// Copyright (c) 2016-2024 The Hush developers // Distributed under the GPLv3 software license, see the accompanying // file COPYING or https://www.gnu.org/licenses/gpl-3.0.en.html /****************************************************************************** * Copyright © 2014-2019 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * * holder information and the developer policies on copyright and licensing. * * * * Unless otherwise agreed in a custom licensing agreement, no part of the * * SuperNET software, including this file may be copied, modified, propagated * * or distributed except according to the terms contained in the LICENSE file * * * * Removal or modification of this copyright notice is prohibited. * * * ******************************************************************************/ // requires CHAINNAME and GAMEMAIN() to be #defined #include #include #include #include #include #include #include extern struct games_state globalR; void *gamesiterate(struct games_state *rs); char USERPASS[8192]; uint16_t GAMES_PORT; char Gametxidstr[67]; char *clonestr(char *str); #define MAXSTR 1024 char whoami[MAXSTR]; #define SMALLVAL 0.000000000000001 #define SATOSHIDEN ((uint64_t)100000000L) #define dstr(x) ((double)(x) / SATOSHIDEN) #define HUSH_SMART_CHAIN_MAXLEN 65 char ASSETCHAINS_SYMBOL[HUSH_SMART_CHAIN_MAXLEN],IPADDRESS[100]; #ifndef _BITS256 #define _BITS256 union _bits256 { uint8_t bytes[32]; uint16_t ushorts[16]; uint32_t uints[8]; uint64_t ulongs[4]; uint64_t txid; }; typedef union _bits256 bits256; #endif #ifdef _WIN32 #ifdef _MSC_VER int gettimeofday(struct timeval * tp, struct timezone * tzp) { // Note: some broken versions only have 8 trailing zero's, the correct epoch has 9 trailing zero's static const uint64_t EPOCH = ((uint64_t)116444736000000000ULL); SYSTEMTIME system_time; FILETIME file_time; uint64_t time; GetSystemTime(&system_time); SystemTimeToFileTime(&system_time, &file_time); time = ((uint64_t)file_time.dwLowDateTime); time += ((uint64_t)file_time.dwHighDateTime) << 32; tp->tv_sec = (long)((time - EPOCH) / 10000000L); tp->tv_usec = (long)(system_time.wMilliseconds * 1000); return 0; } #endif // _MSC_VER #endif double OS_milliseconds() { struct timeval tv; double millis; #ifdef __MINGW32__ mingw_gettimeofday(&tv,NULL); #else gettimeofday(&tv,NULL); #endif millis = ((double)tv.tv_sec * 1000. + (double)tv.tv_usec / 1000.); //printf("tv_sec.%ld usec.%d %f\n",tv.tv_sec,tv.tv_usec,millis); return(millis); } int32_t _unhex(char c) { if ( c >= '0' && c <= '9' ) return(c - '0'); else if ( c >= 'a' && c <= 'f' ) return(c - 'a' + 10); else if ( c >= 'A' && c <= 'F' ) return(c - 'A' + 10); return(-1); } int32_t is_hexstr(char *str,int32_t n) { int32_t i; if ( str == 0 || str[0] == 0 ) return(0); for (i=0; str[i]!=0; i++) { if ( n > 0 && i >= n ) break; if ( _unhex(str[i]) < 0 ) break; } if ( n == 0 ) return(i); return(i == n); } int32_t unhex(char c) { int32_t hex; if ( (hex= _unhex(c)) < 0 ) { //printf("unhex: illegal hexchar.(%c)\n",c); } return(hex); } unsigned char _decode_hex(char *hex) { return((unhex(hex[0])<<4) | unhex(hex[1])); } int32_t decode_hex(uint8_t *bytes,int32_t n,char *hex) { int32_t adjust,i = 0; //printf("decode.(%s)\n",hex); if ( is_hexstr(hex,n) <= 0 ) { memset(bytes,0,n); return(n); } if ( hex[n-1] == '\n' || hex[n-1] == '\r' ) hex[--n] = 0; if ( n == 0 || (hex[n*2+1] == 0 && hex[n*2] != 0) ) { if ( n > 0 ) { bytes[0] = unhex(hex[0]); printf("decode_hex n.%d hex[0] (%c) -> %d hex.(%s) [n*2+1: %d] [n*2: %d %c] len.%ld\n",n,hex[0],bytes[0],hex,hex[n*2+1],hex[n*2],hex[n*2],(long)strlen(hex)); } bytes++; hex++; adjust = 1; } else adjust = 0; if ( n > 0 ) { for (i=0; i>4) & 0xf); hexbytes[i*2 + 1] = hexbyte(message[i] & 0xf); //printf("i.%d (%02x) [%c%c]\n",i,message[i],hexbytes[i*2],hexbytes[i*2+1]); } hexbytes[len*2] = 0; //printf("len.%ld\n",len*2+1); return((int32_t)len*2+1); } char *bits256_str(char hexstr[65],bits256 x) { init_hexbytes_noT(hexstr,x.bytes,sizeof(x)); return(hexstr); } long _stripwhite(char *buf,int accept) { int32_t i,j,c; if ( buf == 0 || buf[0] == 0 ) return(0); for (i=j=0; buf[i]!=0; i++) { buf[j] = c = buf[i]; if ( c == accept || (c != ' ' && c != '\n' && c != '\r' && c != '\t' && c != '\b') ) j++; } buf[j] = 0; return(j); } char *parse_conf_line(char *line,char *field) { line += strlen(field); for (; *line!='='&&*line!=0; line++) break; if ( *line == 0 ) return(0); if ( *line == '=' ) line++; while ( line[strlen(line)-1] == '\r' || line[strlen(line)-1] == '\n' || line[strlen(line)-1] == ' ' ) line[strlen(line)-1] = 0; //printf("LINE.(%s)\n",line); _stripwhite(line,0); return(clonestr(line)); } int32_t safecopy(char *dest,char *src,long len) { int32_t i = -1; if ( src != 0 && dest != 0 && src != dest ) { if ( dest != 0 ) memset(dest,0,len); for (i=0; i buflen ) { *allocsizep = filesize; *bufp = buf = (uint8_t *)realloc(buf,(long)*allocsizep+64); } rewind(fp); if ( buf == 0 ) printf("Null buf ???\n"); else { if ( fread(buf,1,(long)filesize,fp) != (unsigned long)filesize ) printf("error reading filesize.%ld\n",(long)filesize); buf[filesize] = 0; } fclose(fp); *lenp = filesize; //printf("loaded.(%s)\n",buf); } //else printf("OS_loadfile couldnt load.(%s)\n",fname); return(buf); } uint8_t *OS_fileptr(long *allocsizep,char *fname) { long filesize = 0; uint8_t *buf = 0; void *retptr; *allocsizep = 0; retptr = OS_loadfile(fname,&buf,&filesize,allocsizep); return((uint8_t *)retptr); } struct MemoryStruct { char *memory; size_t size; }; struct return_string { char *ptr; size_t len; }; // return data from the server #define CURL_GLOBAL_ALL (CURL_GLOBAL_SSL|CURL_GLOBAL_WIN32) #define CURL_GLOBAL_SSL (1<<0) #define CURL_GLOBAL_WIN32 (1<<1) /************************************************************************ * * Initialize the string handler so that it is thread safe * ************************************************************************/ void init_string(struct return_string *s) { s->len = 0; s->ptr = (char *)calloc(1,s->len+1); if ( s->ptr == NULL ) { fprintf(stderr,"init_string malloc() failed\n"); exit(-1); } s->ptr[0] = '\0'; } /************************************************************************ * * Use the "writer" to accumulate text until done * ************************************************************************/ size_t accumulatebytes(void *ptr,size_t size,size_t nmemb,struct return_string *s) { size_t new_len = s->len + size*nmemb; s->ptr = (char *)realloc(s->ptr,new_len+1); if ( s->ptr == NULL ) { fprintf(stderr, "accumulate realloc() failed\n"); exit(-1); } memcpy(s->ptr+s->len,ptr,size*nmemb); s->ptr[new_len] = '\0'; s->len = new_len; return(size * nmemb); } /************************************************************************ * * return the current system time in milliseconds * ************************************************************************/ #define EXTRACT_BITCOIND_RESULT // if defined, ensures error is null and returns the "result" field #ifdef EXTRACT_BITCOIND_RESULT /************************************************************************ * * perform post processing of the results * ************************************************************************/ char *post_process_bitcoind_RPC(char *debugstr,char *command,char *rpcstr,char *params) { long i,j,len; char *retstr = 0; cJSON *json,*result,*error; //printf("<<<<<<<<<<< bitcoind_RPC: %s post_process_bitcoind_RPC.%s.[%s]\n",debugstr,command,rpcstr); if ( command == 0 || rpcstr == 0 || rpcstr[0] == 0 ) { if ( strcmp(command,"signrawtransaction") != 0 ) printf("<<<<<<<<<<< bitcoind_RPC: %s post_process_bitcoind_RPC.%s.[%s]\n",debugstr,command,rpcstr); return(rpcstr); } json = cJSON_Parse(rpcstr); if ( json == 0 ) { printf("<<<<<<<<<<< bitcoind_RPC: %s post_process_bitcoind_RPC.%s can't parse.(%s) params.(%s)\n",debugstr,command,rpcstr,params); free(rpcstr); return(0); } result = cJSON_GetObjectItem(json,"result"); error = cJSON_GetObjectItem(json,"error"); if ( error != 0 && result != 0 ) { if ( (error->type&0xff) == cJSON_NULL && (result->type&0xff) != cJSON_NULL ) { retstr = cJSON_Print(result); len = strlen(retstr); if ( retstr[0] == '"' && retstr[len-1] == '"' ) { for (i=1,j=0; itype&0xff) != cJSON_NULL || (result->type&0xff) != cJSON_NULL ) { if ( strcmp(command,"signrawtransaction") != 0 ) printf("<<<<<<<<<<< bitcoind_RPC: %s post_process_bitcoind_RPC (%s) error.%s\n",debugstr,command,rpcstr); } free(rpcstr); } else retstr = rpcstr; free_json(json); //fprintf(stderr,"<<<<<<<<<<< bitcoind_RPC: postprocess returns.(%s)\n",retstr); return(retstr); } #endif #ifdef _WIN32 #ifdef _MSC_VER #define sleep(x) Sleep(1000*(x)) #endif #endif /************************************************************************ * * perform the query * ************************************************************************/ char *bitcoind_RPC(char **retstrp,char *debugstr,char *url,char *userpass,char *command,char *params) { static int didinit,count,count2; static double elapsedsum,elapsedsum2; struct curl_slist *headers = NULL; struct return_string s; CURLcode res; CURL *curl_handle; char *bracket0,*bracket1,*databuf = 0; long len; int32_t specialcase,numretries; double starttime; if ( didinit == 0 ) { didinit = 1; curl_global_init(CURL_GLOBAL_ALL); //init the curl session } numretries = 0; if ( debugstr != 0 && strcmp(debugstr,"BTCD") == 0 && command != 0 && strcmp(command,"SuperNET") == 0 ) specialcase = 1; else specialcase = 0; if ( url[0] == 0 ) strcpy(url,"http://127.0.0.1:7876/nxt"); if ( specialcase != 0 && 0 ) printf("<<<<<<<<<<< bitcoind_RPC: debug.(%s) url.(%s) command.(%s) params.(%s)\n",debugstr,url,command,params); try_again: if ( retstrp != 0 ) *retstrp = 0; starttime = OS_milliseconds(); curl_handle = curl_easy_init(); init_string(&s); headers = curl_slist_append(0,"Expect:"); curl_easy_setopt(curl_handle,CURLOPT_USERAGENT,"mozilla/4.0");//"Mozilla/4.0 (compatible; )"); curl_easy_setopt(curl_handle,CURLOPT_HTTPHEADER, headers); curl_easy_setopt(curl_handle,CURLOPT_URL, url); curl_easy_setopt(curl_handle,CURLOPT_WRITEFUNCTION, (void *)accumulatebytes); // send all data to this function curl_easy_setopt(curl_handle,CURLOPT_WRITEDATA, &s); // we pass our 's' struct to the callback curl_easy_setopt(curl_handle,CURLOPT_NOSIGNAL, 1L); // supposed to fix "Alarm clock" and long jump crash curl_easy_setopt(curl_handle,CURLOPT_NOPROGRESS, 1L); // no progress callback if ( strncmp(url,"https",5) == 0 ) { curl_easy_setopt(curl_handle,CURLOPT_SSL_VERIFYPEER,0); curl_easy_setopt(curl_handle,CURLOPT_SSL_VERIFYHOST,0); } if ( userpass != 0 ) curl_easy_setopt(curl_handle,CURLOPT_USERPWD, userpass); databuf = 0; if ( params != 0 ) { if ( command != 0 && specialcase == 0 ) { len = strlen(params); if ( len > 0 && params[0] == '[' && params[len-1] == ']' ) { bracket0 = bracket1 = (char *)""; } else { bracket0 = (char *)"["; bracket1 = (char *)"]"; } databuf = (char *)malloc(256 + strlen(command) + strlen(params)); sprintf(databuf,"{\"id\":\"jl777\",\"method\":\"%s\",\"params\":%s%s%s}",command,bracket0,params,bracket1); //printf("url.(%s) userpass.(%s) databuf.(%s)\n",url,userpass,databuf); // } //else if ( specialcase != 0 ) fprintf(stderr,"databuf.(%s)\n",params); curl_easy_setopt(curl_handle,CURLOPT_POST,1L); if ( databuf != 0 ) curl_easy_setopt(curl_handle,CURLOPT_POSTFIELDS,databuf); else curl_easy_setopt(curl_handle,CURLOPT_POSTFIELDS,params); } //laststart = milliseconds(); res = curl_easy_perform(curl_handle); curl_slist_free_all(headers); curl_easy_cleanup(curl_handle); if ( databuf != 0 ) // clean up temporary buffer { free(databuf); databuf = 0; } if ( res != CURLE_OK ) { numretries++; if ( specialcase != 0 ) { printf("<<<<<<<<<<< bitcoind_RPC.(%s): BTCD.%s timeout params.(%s) s.ptr.(%s) err.%d\n",url,command,params,s.ptr,res); free(s.ptr); return(0); } else if ( numretries >= 1 ) { //printf("Maximum number of retries exceeded!\n"); free(s.ptr); return(0); } if ( (rand() % 1000) == 0 ) printf( "curl_easy_perform() failed: %s %s.(%s %s), retries: %d\n",curl_easy_strerror(res),debugstr,url,command,numretries); free(s.ptr); sleep((1< (%s)\n",params,s.ptr); count2++; elapsedsum2 += (OS_milliseconds() - starttime); if ( (count2 % 10000) == 0) printf("%d: ave %9.6f | elapsed %.3f millis | NXT calls.(%s) cmd.(%s)\n",count2,elapsedsum2/count2,(double)(OS_milliseconds() - starttime),url,command); return(s.ptr); } } printf("bitcoind_RPC: impossible case\n"); free(s.ptr); return(0); } static size_t WriteMemoryCallback(void *ptr,size_t size,size_t nmemb,void *data) { size_t realsize = (size * nmemb); struct MemoryStruct *mem = (struct MemoryStruct *)data; mem->memory = (char *)((ptr != 0) ? realloc(mem->memory,mem->size + realsize + 1) : malloc(mem->size + realsize + 1)); if ( mem->memory != 0 ) { if ( ptr != 0 ) memcpy(&(mem->memory[mem->size]),ptr,realsize); mem->size += realsize; mem->memory[mem->size] = 0; } //printf("got %d bytes\n",(int32_t)(size*nmemb)); return(realsize); } char *curl_post(CURL **cHandlep,char *url,char *userpass,char *postfields,char *hdr0,char *hdr1,char *hdr2,char *hdr3) { struct MemoryStruct chunk; CURL *cHandle; long code; struct curl_slist *headers = 0; if ( (cHandle= *cHandlep) == NULL ) *cHandlep = cHandle = curl_easy_init(); else curl_easy_reset(cHandle); //#ifdef DEBUG //curl_easy_setopt(cHandle,CURLOPT_VERBOSE, 1); //#endif curl_easy_setopt(cHandle,CURLOPT_USERAGENT,"mozilla/4.0");//"Mozilla/4.0 (compatible; )"); curl_easy_setopt(cHandle,CURLOPT_SSL_VERIFYPEER,0); //curl_easy_setopt(cHandle,CURLOPT_SSLVERSION,1); curl_easy_setopt(cHandle,CURLOPT_URL,url); curl_easy_setopt(cHandle,CURLOPT_CONNECTTIMEOUT,10); if ( userpass != 0 && userpass[0] != 0 ) curl_easy_setopt(cHandle,CURLOPT_USERPWD,userpass); if ( postfields != 0 && postfields[0] != 0 ) { curl_easy_setopt(cHandle,CURLOPT_POST,1); curl_easy_setopt(cHandle,CURLOPT_POSTFIELDS,postfields); } if ( hdr0 != NULL && hdr0[0] != 0 ) { //printf("HDR0.(%s) HDR1.(%s) HDR2.(%s) HDR3.(%s)\n",hdr0!=0?hdr0:"",hdr1!=0?hdr1:"",hdr2!=0?hdr2:"",hdr3!=0?hdr3:""); headers = curl_slist_append(headers,hdr0); if ( hdr1 != 0 && hdr1[0] != 0 ) headers = curl_slist_append(headers,hdr1); if ( hdr2 != 0 && hdr2[0] != 0 ) headers = curl_slist_append(headers,hdr2); if ( hdr3 != 0 && hdr3[0] != 0 ) headers = curl_slist_append(headers,hdr3); } //headers = curl_slist_append(0,"Expect:"); if ( headers != 0 ) curl_easy_setopt(cHandle,CURLOPT_HTTPHEADER,headers); //res = curl_easy_perform(cHandle); memset(&chunk,0,sizeof(chunk)); curl_easy_setopt(cHandle,CURLOPT_WRITEFUNCTION,WriteMemoryCallback); curl_easy_setopt(cHandle,CURLOPT_WRITEDATA,(void *)&chunk); curl_easy_perform(cHandle); curl_easy_getinfo(cHandle,CURLINFO_RESPONSE_CODE,&code); if ( headers != 0 ) curl_slist_free_all(headers); if ( code != 200 ) printf("(%s) server responded with code %ld (%s)\n",url,code,chunk.memory); return(chunk.memory); } uint16_t _hush_userpass(char *username, char *password, FILE *fp) { char *rpcuser,*rpcpassword,*str,*ipaddress,line[8192]; uint16_t port = 0; rpcuser = rpcpassword = 0; username[0] = password[0] = 0; while ( fgets(line,sizeof(line),fp) != 0 ) { if ( line[0] == '#' ) continue; //printf("line.(%s) %p %p\n",line,strstr(line,(char *)"rpcuser"),strstr(line,(char *)"rpcpassword")); if ( (str= strstr(line,(char *)"rpcuser")) != 0 ) rpcuser = parse_conf_line(str,(char *)"rpcuser"); else if ( (str= strstr(line,(char *)"rpcpassword")) != 0 ) rpcpassword = parse_conf_line(str,(char *)"rpcpassword"); else if ( (str= strstr(line,(char *)"rpcport")) != 0 ) { port = atoi(parse_conf_line(str,(char *)"rpcport")); //fprintf(stderr,"rpcport.%u in file\n",port); } else if ( (str= strstr(line,(char *)"ipaddress")) != 0 ) { ipaddress = parse_conf_line(str,(char *)"ipaddress"); strcpy(IPADDRESS,ipaddress); } } if ( rpcuser != 0 && rpcpassword != 0 ) { strcpy(username,rpcuser); strcpy(password,rpcpassword); } //printf("rpcuser.(%s) rpcpassword.(%s) %u ipaddress.%s\n",rpcuser,rpcpassword,port,ipaddress); if ( rpcuser != 0 ) free(rpcuser); if ( rpcpassword != 0 ) free(rpcpassword); return(port); } uint16_t hush_userpass(char *userpass,char *symbol) { FILE *fp; uint16_t port = 0; char fname[512],username[512],password[512],confname[HUSH_SMART_CHAIN_MAXLEN]; userpass[0] = 0; sprintf(confname,"%s.conf",symbol); //hush_statefname(fname,symbol,confname); if ( (fp= fopen(confname,"rb")) != 0 ) { port = _hush_userpass(username,password,fp); sprintf(userpass,"%s:%s",username,password); if ( strcmp(symbol,ASSETCHAINS_SYMBOL) == 0 ) strcpy(USERPASS,userpass); fclose(fp); } return(port); } #define is_cJSON_True(json) ((json) != 0 && ((json)->type & 0xff) == cJSON_True) char *hush_issuemethod(char *userpass,char *method,char *params,uint16_t port) { //static void *cHandle; char url[512],*retstr=0,*retstr2=0,postdata[8192]; if ( params == 0 || params[0] == 0 ) params = (char *)"[]"; if ( strlen(params) < sizeof(postdata)-128 ) { sprintf(url,(char *)"http://%s:%u",IPADDRESS,port); sprintf(postdata,"{\"method\":\"%s\",\"params\":%s}",method,params); //printf("[%s] (%s) postdata.(%s) params.(%s) USERPASS.(%s)\n",ASSETCHAINS_SYMBOL,url,postdata,params,USERPASS); retstr2 = bitcoind_RPC(&retstr,(char *)"debug",url,userpass,method,params); //retstr = curl_post(&cHandle,url,USERPASS,postdata,0,0,0,0); } return(retstr2); } int32_t games_sendrawtransaction(char *rawtx) { char *params,*retstr,*hexstr; cJSON *retjson,*resobj; int32_t retval = -1; params = (char *)malloc(strlen(rawtx) + 16); sprintf(params,"[\"%s\"]",rawtx); if ( (retstr= hush_issuemethod(USERPASS,(char *)"sendrawtransaction",params,GAMES_PORT)) != 0 ) { if ( 0 ) // causes 4th level crash { static FILE *fp; if ( fp == 0 ) fp = fopen("games.sendlog","wb"); if ( fp != 0 ) { fprintf(fp,"%s\n",retstr); fflush(fp); } } if ( (retjson= cJSON_Parse(retstr)) != 0 ) { if ( (resobj= jobj(retjson,(char *)"result")) != 0 ) { if ( (hexstr= jstr(resobj,0)) != 0 && is_hexstr(hexstr,64) == 64 ) retval = 0; } free_json(retjson); } /* log sendrawtx result in file */ /* FILE *debug_file; debug_file = fopen("tx_debug.log", "a"); fprintf(debug_file, "%s\n", retstr); fflush(debug_file); fclose(debug_file); */ free(retstr); } free(params); return(retval); } int32_t games_progress(struct games_state *rs,int32_t waitflag,uint64_t seed,gamesevent *keystrokes,int32_t num) { char cmd[16384],hexstr[16384],params[32768],*retstr,*errstr,*rawtx; int32_t i,len,retflag = -1; cJSON *retjson,*resobj; if ( rs->guiflag != 0 && Gametxidstr[0] != 0 ) { if ( rs->keystrokeshex != 0 ) { if ( games_sendrawtransaction(rs->keystrokeshex) == 0 ) { if ( waitflag == 0 ) return(0); else if ( 0 ) { while ( games_sendrawtransaction(rs->keystrokeshex) == 0 ) { //fprintf(stderr,"pre-rebroadcast\n"); sleep(10); } } } free(rs->keystrokeshex), rs->keystrokeshex = 0; } memset(hexstr,0,sizeof(hexstr)); for (i=0; ikeystrokeshex != 0 ) free(rs->keystrokeshex); if ( (errstr= jstr(resobj,(char *)"error")) == 0 ) { rs->keystrokeshex = (char *)malloc(strlen(rawtx)+1); strcpy(rs->keystrokeshex,rawtx); retflag = 1; } else fprintf(stderr,"error sending keystrokes tx\n"), sleep(1); //fprintf(stderr,"set keystrokestx <- %s\n",rs->keystrokeshex); } free_json(retjson); } free(retstr); } } return(retflag); } int32_t gamesfname(char *fname,uint64_t seed,int32_t counter) { sprintf(fname,"%s.%llu.%d",GAMENAME,(long long)seed,counter); return(0); } int32_t flushkeystrokes_local(struct games_state *rs,int32_t waitflag) { #ifdef STANDALONE char fname[1024]; FILE *fp; int32_t i,retflag = -1; rs->counter++; gamesfname(fname,rs->origseed,rs->counter); if ( (fp= fopen(fname,"wb")) != 0 ) { if ( fwrite(rs->buffered,sizeof(*rs->buffered),rs->num,fp) == rs->num ) { rs->num = 0; retflag = 0; fclose(fp); gamesfname(fname,rs->origseed,rs->counter+1); if ( (fp= fopen(fname,"wb")) != 0 ) // truncate next file fclose(fp); //fprintf(stderr,"savefile <- %s retflag.%d\n",fname,retflag); //} } else fprintf(stderr,"error writing (%s)\n",fname); } else fprintf(stderr,"error creating (%s)\n",fname); return(retflag); #else return(0); #endif } #ifndef STANDALONE // stubs for inside daemon int32_t games_progress(struct games_state *rs,int32_t waitflag,uint64_t seed,char *keystrokes,int32_t num) { return(0); } int32_t games_setplayerdata(struct games_state *rs,char *gametxidstr) { return(-1); } #endif int32_t flushkeystrokes(struct games_state *rs,int32_t waitflag) { if ( rs->num > 0 ) { if ( games_progress(rs,waitflag,rs->origseed,rs->buffered,rs->num) > 0 ) { flushkeystrokes_local(rs,waitflag); memset(rs->buffered,0,sizeof(rs->buffered)); } } return(0); } void gamesbailout(struct games_state *rs) { flushkeystrokes(rs,1); } #ifdef _WIN32 #ifdef _MSC_VER #define sleep(x) Sleep(1000*(x)) #endif #endif long get_filesize(FILE *fp) { long fsize,fpos = ftell(fp); fseek(fp,0,SEEK_END); fsize = ftell(fp); fseek(fp,fpos,SEEK_SET); return(fsize); } gamesevent *games_keystrokesload(int32_t *numkeysp,uint64_t seed,int32_t counter) { char fname[1024]; gamesevent *keystrokes = 0; FILE *fp; long fsize; int32_t i,num = 0; *numkeysp = 0; while ( 1 ) { gamesfname(fname,seed,counter); //printf("check (%s)\n",fname); if ( (fp= fopen(fname,"rb")) == 0 ) break; if ( (fsize= get_filesize(fp)) <= 0 ) { fclose(fp); //printf("fsize.%ld\n",fsize); break; } if ( (keystrokes= (gamesevent *)realloc(keystrokes,sizeof(*keystrokes)*num+fsize)) == 0 ) { fprintf(stderr,"error reallocating keystrokes\n"); fclose(fp); return(0); } if ( fread(&keystrokes[num],1,fsize,fp) != fsize ) { fprintf(stderr,"error reading keystrokes from (%s)\n",fname); fclose(fp); free(keystrokes); return(0); } fclose(fp); num += (int32_t)(fsize / sizeof(gamesevent)); //for (i=0; i 0 ) { sprintf(fname,"%s.%llu.player",GAMENAME,(long long)seed); if ( (fp=fopen(fname,"rb")) != 0 ) { if ( fread(&P,1,sizeof(P),fp) > 0 ) { //printf("max size player\n"); player = &P; } fclose(fp); } games_replay2(0,seed,keystrokes,num,player,sleeptime); mvaddstr(LINES - 2, 0, (char *)"replay completed"); endwin(); games_exit(); } if ( keystrokes != 0 ) free(keystrokes); return(num); } int32_t games_setplayerdata(struct games_state *rs,char *gametxidstr) { char cmd[32768]; int32_t i,n,retval=-1; char params[1024],*filestr=0,*pname,*statusstr,*datastr,fname[128]; long allocsize; cJSON *retjson,*array,*item,*resultjson; if ( rs->guiflag == 0 ) return(-1); if ( gametxidstr == 0 || *gametxidstr == 0 ) return(retval); if ( 0 ) { sprintf(fname,"%s.gameinfo",gametxidstr); sprintf(cmd,"./hush-cli -ac_name=%s cclib gameinfo 17 \\\"[%%22%s%%22]\\\" > %s",ASSETCHAINS_SYMBOL,gametxidstr,fname); if ( system(cmd) != 0 ) fprintf(stderr,"error issuing (%s)\n",cmd); else filestr = (char *)OS_fileptr(&allocsize,fname); } else { sprintf(params,"[\"gameinfo\",\"17\",\"[%%22%s%%22]\"]",gametxidstr); filestr = hush_issuemethod(USERPASS,(char *)"cclib",params,GAMES_PORT); } if ( filestr != 0 ) { if ( (retjson= cJSON_Parse(filestr)) != 0 && (resultjson= jobj(retjson,(char *)"result")) != 0 ) { //fprintf(stderr,"gameinfo.(%s)\n",jprint(resultjson,0)); if ( (array= jarray(&n,resultjson,(char *)"players")) != 0 ) { for (i=0; iP,(int32_t)strlen(datastr)/2,datastr); fprintf(stderr,"set pname[%s] %s\n",pname==0?"":pname,jprint(item,0)); rs->restoring = 1; } } } } } free_json(retjson); } free(filestr); } return(retval); } #ifdef _WIN32 #ifdef _MSC_VER __inline int msver(void) { switch (_MSC_VER) { case 1500: return 2008; case 1600: return 2010; case 1700: return 2012; case 1800: return 2013; case 1900: return 2015; //case 1910: return 2017; default: return (_MSC_VER / 100); } } static inline bool is_x64(void) { #if defined(__x86_64__) || defined(_WIN64) || defined(__aarch64__) return 1; #elif defined(__amd64__) || defined(__amd64) || defined(_M_X64) || defined(_M_IA64) return 1; #else return 0; #endif } #define BUILD_DATE __DATE__ " " __TIME__ #endif // _WIN32 #endif // _MSC_VER int main(int argc, char **argv) { uint64_t seed; FILE *fp = 0; int32_t i,j,c; char userpass[8192]; #ifdef _WIN32 #ifdef _MSC_VER printf("*** games for Windows [ Build %s ] ***\n", BUILD_DATE); const char* arch = is_x64() ? "64-bits" : "32-bits"; printf(" Built with VC++ %d (%ld) %s\n\n", msver(), _MSC_FULL_VER, arch); #endif #endif for (i=j=0; argv[0][i]!=0&&j