char *bitcoind_RPC(char **retstrp,char *debugstr,char *url,char *userpass,char *command,char *params) { static int didinit,count,count2; static double elapsedsum,elapsedsum2; extern int32_t USE_JAY; 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 } if ( USE_JAY != 0 && (strncmp(url,"http://127.0.0.1:7876/nxt",strlen("http://127.0.0.1:7876/nxt")) == 0 || strncmp(url,"https://127.0.0.1:7876/nxt",strlen("https://127.0.0.1:7876/nxt")) == 0) ) { if ( (databuf= Jay_NXTrequest(command,params)) != 0 ) return(databuf); } 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 *)accumulate); // 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 >= 2 ) { printf("Maximum number of retries exceeded!\n"); free(s.ptr); return(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<<numretries)); goto try_again; } else { if ( command != 0 && specialcase == 0 ) { count++; elapsedsum += (OS_milliseconds() - starttime); if ( (count % 10000) == 0) printf("%d: ave %9.6f | elapsed %.3f millis | bitcoind_RPC.(%s) url.(%s)\n",count,elapsedsum/count,(OS_milliseconds() - starttime),command,url); if ( retstrp != 0 ) { *retstrp = s.ptr; return(s.ptr); } return(post_process_bitcoind_RPC(debugstr,command,s.ptr,params)); } else { if ( 0 && specialcase != 0 ) fprintf(stderr,"<<<<<<<<<<< bitcoind_RPC: BTCD.(%s) -> (%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); }
char *bitcoind_RPC(char *debugstr,int32_t numretries,char *url,char *userpass,char *command,char *params) { static int32_t count,didinit; static double elapsedsum,elapsedsum2,laststart; char *retstr,*bracket0,*bracket1,*databuf=0,len_hdr[10240]; CURL *curl_handle; CURLcode res; long len; int32_t delay = MAGIC_BITCOINC_RPCDELAY; double starttime; struct curl_slist *headers = NULL; struct upload_buffer upload_data; struct MemoryStruct chunk; double milliseconds(); //static pthread_mutex_t mutex; //pthread_mutex_lock(&mutex); if ( didinit == 0 ) { didinit = 1; curl_global_init(CURL_GLOBAL_ALL); //init the curl session } //printf("start bitcoind_RPC %s\n",command!=0?command:""); starttime = milliseconds(); if ( 1 && laststart+1 > starttime ) // horrible hack for bitcoind "Couldn't connect to server" { usleep(2000); starttime = milliseconds(); } laststart = starttime; if ( params == 0 ) params = ""; retry: chunk.memory = malloc(1); // will be grown as needed by the realloc above chunk.size = 0; // no data at this point curl_handle = curl_easy_init(); curl_easy_setopt(curl_handle,CURLOPT_CONNECTTIMEOUT,2); // chanc3r: limit any *real* timeouts to 2s curl_easy_setopt(curl_handle,CURLOPT_FRESH_CONNECT,1); // chanc3r: force a new connection for each request - i'm curl_easy_setopt(curl_handle,CURLOPT_SSL_VERIFYHOST,0); curl_easy_setopt(curl_handle,CURLOPT_SSL_VERIFYPEER,0); curl_easy_setopt(curl_handle,CURLOPT_URL,url); curl_easy_setopt(curl_handle, CURLOPT_NOSIGNAL, 1); // supposed to fix "Alarm clock" and long jump crash curl_easy_setopt(curl_handle,CURLOPT_WRITEFUNCTION,WriteMemoryCallback); // send all data to this function curl_easy_setopt(curl_handle,CURLOPT_WRITEDATA,(void *)&chunk); // we pass our 'chunk' struct to the callback function curl_easy_setopt(curl_handle,CURLOPT_USERAGENT,"libcurl-agent/1.0"); // some servers don't like requests that are made without a user-agent field, so we provide one if ( userpass != 0 ) curl_easy_setopt(curl_handle,CURLOPT_USERPWD,userpass); if ( command != 0 ) { curl_easy_setopt(curl_handle,CURLOPT_READFUNCTION,upload_data_cb); curl_easy_setopt(curl_handle,CURLOPT_READDATA,&upload_data); curl_easy_setopt(curl_handle,CURLOPT_POST,1); len = strlen(params); if ( len > 0 && params[0] == '[' && params[len-1] == ']' ) bracket0 = bracket1 = ""; else bracket0 = "[", bracket1 = "]"; databuf = malloc(4096 + strlen(command) + strlen(params)); sprintf(databuf,"{\"id\":\"jl777\",\"method\":\"%s\",\"params\":%s%s%s}",command,bracket0,params,bracket1); // printf(">>>>(%s)<<<<< args.(%s)\n",databuf,params); upload_data.buf = (unsigned char *)databuf; upload_data.len = strlen(databuf); sprintf(len_hdr, "Content-Length: %lu",(unsigned long)upload_data.len); headers = curl_slist_append(NULL,"Expect:"); headers = curl_slist_append(headers,"Content-type: application/json"); headers = curl_slist_append(headers,len_hdr); curl_easy_setopt(curl_handle,CURLOPT_HTTPHEADER,headers); } res = curl_easy_perform(curl_handle); if ( headers != 0 ) curl_slist_free_all(headers); if ( databuf != 0 ) free(databuf), databuf = 0; if ( res != CURLE_OK ) { fprintf(stderr, "curl_easy_perform() failed: %s %s.(%s %s %s %s)\n",curl_easy_strerror(res),debugstr,url,userpass,command,params); if ( command != 0 && params != 0 ) sleep(delay); else sleep(1); //delay *= 3; if ( numretries-- > 0 ) { free(chunk.memory); curl_easy_cleanup(curl_handle); //curl_global_cleanup(); //curl_global_init(CURL_GLOBAL_ALL); //init the curl session goto retry; } } else { // printf("%lu bytes retrieved [%s]\n", (int64_t )chunk.size,chunk.memory); } elapsedsum += (milliseconds() - starttime); curl_easy_cleanup(curl_handle); retstr = malloc(strlen(chunk.memory)+1); strcpy(retstr,chunk.memory); free(chunk.memory); count++; elapsedsum2 += (milliseconds() - starttime); #ifndef __APPLE__ if ( elapsedsum2/count > 1000 && (milliseconds() - starttime) > 1000 ) fprintf(stderr,"%d: %9.6f %9.6f | elapsed %.3f millis | bitcoind_RPC.(%s)\n",count,elapsedsum/count,elapsedsum2/count,(milliseconds() - starttime),url); #endif // pthread_mutex_unlock(&mutex); return(post_process_bitcoind_RPC(debugstr,command,params,retstr)); }