struct iguana_peer *iguana_choosepeer(struct iguana_info *coin) { int32_t i,j,r,iter; struct iguana_peer *addr; r = rand(); portable_mutex_lock(&coin->peers_mutex); if ( coin->MAXPEERS == 0 ) coin->MAXPEERS = IGUANA_MAXPEERS; if ( coin->peers.numranked > 0 ) { for (j=0; j<coin->peers.numranked; j++) { i = (j + r) % coin->MAXPEERS; if ( (addr= coin->peers.ranked[i]) != 0 && addr->pendblocks < IGUANA_MAXPENDING && addr->dead == 0 && addr->usock >= 0 ) { portable_mutex_unlock(&coin->peers_mutex); return(addr); } } } portable_mutex_unlock(&coin->peers_mutex); for (iter=0; iter<2; iter++) { for (i=0; i<coin->MAXPEERS; i++) { addr = &coin->peers.active[(i + r) % coin->MAXPEERS]; if ( addr->dead == 0 && addr->usock >= 0 && (iter == 1 || addr->pendblocks < IGUANA_MAXPENDING) ) return(addr); } } return(0); }
int32_t queue_size(queue_t *queue) { int32_t count = 0; struct queueitem *tmp; lock_queue(queue); DL_COUNT(queue->list,tmp,count); portable_mutex_unlock(&queue->mutex); return count; }
void queue_enqueue(char *name,queue_t *queue,struct queueitem *item) { if ( queue->list == 0 && name != 0 && name[0] != 0 ) safecopy(queue->name,name,sizeof(queue->name)); if ( item == 0 ) { printf("FATAL type error: queueing empty value\n"), getchar(); return; } lock_queue(queue); DL_APPEND(queue->list,item); portable_mutex_unlock(&queue->mutex); //printf("name.(%s) append.%p list.%p\n",name,item,queue->list); }
struct basilisk_swap *basilisk_request_started(struct supernet_info *myinfo,uint32_t requestid) { int32_t i; struct basilisk_swap *active = 0; portable_mutex_lock(&myinfo->DEX_swapmutex); for (i=0; i<myinfo->numswaps; i++) if ( myinfo->swaps[i]->req.requestid == requestid ) { //printf("REQUEST STARTED.[%d] <- req.%u\n",i,requestid); active = myinfo->swaps[i]; break; } portable_mutex_unlock(&myinfo->DEX_swapmutex); return(active); }
void *queue_dequeue(queue_t *queue,int32_t offsetflag) { struct queueitem *item = 0; lock_queue(queue); if ( queue->list != 0 ) { item = queue->list; DL_DELETE(queue->list,item); //printf("name.(%s) dequeue.%p list.%p\n",queue->name,item,queue->list); } portable_mutex_unlock(&queue->mutex); if ( item != 0 && offsetflag != 0 ) return((void *)((long)item + sizeof(struct queueitem))); else return(item); }
void *iguana_kvconnectiterator(struct iguana_info *coin,struct iguanakv *kv,struct iguana_kvitem *item,uint64_t args,void *key,void *value,int32_t valuesize) { struct iguana_iAddr *iA = value; char ipaddr[64]; int32_t i; struct iguana_peer *addr = 0; if ( iA->ipbits != 0 && iguana_numthreads(1 << IGUANA_CONNTHREAD) < IGUANA_MAXCONNTHREADS && iA->status != IGUANA_PEER_READY && iA->status != IGUANA_PEER_CONNECTING ) { //printf("%x\n",iA->ipbits); expand_ipbits(ipaddr,iA->ipbits); portable_mutex_lock(&coin->peers_mutex); for (i=0; i<coin->MAXPEERS; i++) { addr = &coin->peers.active[i]; if ( addr->pending != 0 || addr->ipbits == iA->ipbits || strcmp(ipaddr,addr->ipaddr) == 0 ) { portable_mutex_unlock(&coin->peers_mutex); return(0); } if ( addr->ipbits == 0 ) { iguana_initpeer(coin,addr,iA->ipbits); break; } } portable_mutex_unlock(&coin->peers_mutex); if ( addr != 0 ) { //printf("status.%d addr.%p possible peer.(%s) (%s).%x %u threads %d %d %d %d\n",iA->status,addr,ipaddr,addr->ipaddr,addr->ipbits,addr->pending,iguana_numthreads(0),iguana_numthreads(1),iguana_numthreads(2),iguana_numthreads(3)); iA->status = IGUANA_PEER_CONNECTING; if ( iguana_rwiAddrind(coin,1,iA,item->hh.itemind) > 0 ) { //printf("iguana_startconnection.(%s) status.%d\n",ipaddr,IGUANA_PEER_CONNECTING); iguana_launch("connection",iguana_startconnection,addr,IGUANA_CONNTHREAD); } } else printf("no open peer slots left\n"); } return(0); }
int32_t iguana_scriptdata(struct iguana_info *coin, uint8_t *scriptspace, long fileptr[2], char *fname, uint64_t scriptpos, int32_t scriptlen) #endif { FILE *fp; long err; int32_t retval = scriptlen; #ifndef __PNACL__ if ( scriptpos < 0xffffffff ) { if ( fileptr[0] == 0 ) #if defined(_M_X64) fileptr[0] = (uint64_t)OS_mapfile(fname,&fileptr[1],0); #else fileptr[0] = (long)OS_mapfile(fname, &fileptr[1], 0); #endif if ( fileptr[0] != 0 ) { if ( (scriptpos + scriptlen) <= fileptr[1] ) { memcpy(scriptspace,(void *)(fileptr[0] + (uint32_t)scriptpos),scriptlen); return(retval); } else if ( 0 ) { printf("munmap (%s)\n",fname); munmap((void *)fileptr[0],fileptr[1]); fileptr[0] = fileptr[1] = 0; } } } #else static portable_mutex_t mutex; portable_mutex_lock(&mutex); #endif if ( (fp= fopen(fname,"rb")) != 0 ) { fseek(fp,scriptpos,SEEK_SET); if ( (err= fread(scriptspace,1,scriptlen,fp)) != scriptlen ) { retval = -1; printf("%s script[%d] offset.%llu err.%ld\n",fname,scriptlen,(long long)scriptpos,err); } //else printf("%s script[%d] offset.%llu read.%ld\n",fname,scriptlen,(long long)scriptpos,err); fclose(fp); } else retval = -1; #ifdef __PNACL__ portable_mutex_unlock(&mutex); #endif return(retval); }
char *basilisk_respond_getmessage(struct supernet_info *myinfo,uint8_t *key,int32_t keylen) { cJSON *retjson,*msgjson; struct basilisk_message *msg; char *ptr = 0,strbuf[32768]; retjson = cJSON_CreateObject(); portable_mutex_lock(&myinfo->messagemutex); HASH_FIND(hh,myinfo->messagetable,key,keylen,msg); if ( msg != 0 ) { msgjson = cJSON_CreateObject(); if ( basilisk_addhexstr(&ptr,msgjson,strbuf,sizeof(strbuf),msg->data,msg->datalen) != 0 ) { jadd(retjson,"message",msgjson); jaddstr(retjson,"result","success"); printf("havemessage len.%d\n",msg->datalen); } else jaddstr(retjson,"error","couldnt add message"); } else jaddstr(retjson,"error","no message"); portable_mutex_unlock(&myinfo->messagemutex); return(jprint(retjson,1)); }
char *basilisk_respond_addmessage(struct supernet_info *myinfo,uint8_t *key,int32_t keylen,uint8_t *data,int32_t datalen,int32_t sendping) { struct basilisk_message *msg; if ( keylen == sizeof(bits256)+sizeof(uint32_t)*2 ) { msg = calloc(1,sizeof(*msg) + datalen); msg->expiration = (uint32_t)time(NULL) + INSTANTDEX_LOCKTIME*2; msg->keylen = keylen; memcpy(msg->key,key,keylen); msg->datalen = datalen; memcpy(msg->data,data,datalen); portable_mutex_lock(&myinfo->messagemutex); HASH_ADD_KEYPTR(hh,myinfo->messagetable,msg->key,msg->keylen,msg); portable_mutex_unlock(&myinfo->messagemutex); if ( sendping != 0 ) { queue_enqueue("basilisk_message",&myinfo->msgQ,&msg->DL,0); return(clonestr("{\"result\":\"message added to hashtable\"}")); } else return(0); } else return(0); }
void *OS_portable_tmpalloc(char *dirname,char *name,struct OS_memspace *mem,long origsize) { #ifdef __PNACL return(OS_nonportable_tmpalloc(dirname,name,mem,origsize)); #else char fname[1024]; void *ptr; long size; if ( mem->threadsafe != 0 ) portable_mutex_lock(&mem->mutex); if ( origsize != 0 && (mem->M.fileptr == 0 || (mem->used + origsize) > mem->totalsize) ) { //coin->TMPallocated += origsize; memset(&mem->M,0,sizeof(mem->M)); sprintf(fname,"tmp/%s/%s.%d",dirname,name,mem->counter), OS_compatible_path(fname); mem->counter++; if ( mem->totalsize == 0 ) { mem->totalsize = (1024 * 1024 * 16); } //if ( coin->R.RSPACE.size == 0 ) // coin->R.RSPACE.size = mem->size; if ( mem->totalsize > origsize ) size = mem->totalsize; else size = origsize; fprintf(stderr,"filealloc.(%s) -> ",fname); if ( OS_filealloc(&mem->M,fname,mem,size) == 0 ) { printf("couldnt map tmpfile %s\n",fname); return(0); } fprintf(stderr,"created\n"); } ptr = iguana_memalloc(mem,origsize,1); if ( mem->threadsafe != 0 ) portable_mutex_unlock(&mem->mutex); return(ptr); #endif }
int32_t PLUGNAME(_process_json)(char *forwarder,char *sender,int32_t valid,struct plugin_info *plugin,uint64_t tag,char *retbuf,int32_t maxlen,char *jsonstr,cJSON *json,int32_t initflag,char *tokenstr) { char *resultstr,*methodstr,*retstr = 0; retbuf[0] = 0; if ( Debuglevel > 2 ) fprintf(stderr,"<<<<<<<<<<<< INSIDE PLUGIN! process %s (%s)\n",plugin->name,jsonstr); if ( initflag > 0 ) { // configure settings plugin->allowremote = 1; portable_mutex_init(&plugin->mutex); init_InstantDEX(calc_nxt64bits(SUPERNET.NXTADDR),0); update_NXT_assettrades(); INSTANTDEX.readyflag = 1; strcpy(retbuf,"{\"result\":\"InstantDEX init\"}"); } else { if ( plugin_result(retbuf,json,tag) > 0 ) return((int32_t)strlen(retbuf)); resultstr = cJSON_str(cJSON_GetObjectItem(json,"result")); if ( (methodstr= cJSON_str(cJSON_GetObjectItem(json,"method"))) == 0 ) methodstr = cJSON_str(cJSON_GetObjectItem(json,"requestType")); retbuf[0] = 0; if ( methodstr == 0 || methodstr[0] == 0 ) { printf("(%s) has not method\n",jsonstr); return(0); } portable_mutex_lock(&plugin->mutex); if ( resultstr != 0 && strcmp(resultstr,"registered") == 0 ) { plugin->registered = 1; strcpy(retbuf,"{\"result\":\"activated\"}"); } else if ( strcmp(methodstr,"msigaddr") == 0 ) { char *devMGW_command(char *jsonstr,cJSON *json); if ( SUPERNET.gatewayid >= 0 ) { if ( (retstr= devMGW_command(jsonstr,json)) != 0 ) { //should_forward(sender,retstr); } } //else retstr = nn_loadbalanced((uint8_t *)jsonstr,(int32_t)strlen(jsonstr)+1); } else if ( strcmp(methodstr,"LSUM") == 0 ) { sprintf(retbuf,"{\"result\":\"%s\",\"amount\":%d}",(rand() & 1) ? "BUY" : "SELL",(rand() % 100) * 100000); retstr = clonestr(retbuf); } else if ( SUPERNET.iamrelay == 0 ) { retstr = InstantDEX_parser(forwarder,sender,valid,jsonstr,json); //printf("InstantDEX_parser return.(%s)\n",retstr); } else retstr = clonestr("{\"result\":\"relays only relay\"}"); if ( retstr != 0 ) { if ( strlen(retstr) >= maxlen-1 ) retstr[maxlen-1] = 0; strcpy(retbuf,retstr); free(retstr); } //else sprintf(retbuf,"{\"error\":\"method %s not found\"}",methodstr); portable_mutex_unlock(&plugin->mutex); } return((int32_t)strlen(retbuf) + retbuf[0]!=0); }
char *InstantDEX(char *jsonstr,char *remoteaddr,int32_t localaccess) { char *prices777_allorderbooks(); char *InstantDEX_openorders(); char *InstantDEX_tradehistory(int32_t firsti,int32_t endi); char *InstantDEX_cancelorder(char *activenxt,char *secret,uint64_t sequenceid,uint64_t quoteid); struct destbuf exchangestr,method,gui,name,base,rel; double balance; char *retstr = 0,key[512],retbuf[1024],*activenxt,*secret,*coinstr; struct InstantDEX_quote iQ; struct exchange_info *exchange; cJSON *json; uint64_t assetbits,sequenceid; uint32_t maxdepth; int32_t invert=0,keysize,allfields; struct prices777 *prices; //printf("INSTANTDEX.(%s)\n",jsonstr); if ( INSTANTDEX.readyflag == 0 ) return(0); if ( jsonstr != 0 && (json= cJSON_Parse(jsonstr)) != 0 ) { // test: asset/asset, asset/external, external/external, autofill and automatch // peggy integration bidask_parse(&exchangestr,&name,&base,&rel,&gui,&iQ,json); if ( iQ.s.offerNXT == 0 ) iQ.s.offerNXT = SUPERNET.my64bits; //printf("isask.%d base.(%s) rel.(%s)\n",iQ.s.isask,base.buf,rel.buf); copy_cJSON(&method,jobj(json,"method")); if ( (sequenceid= j64bits(json,"orderid")) == 0 ) sequenceid = j64bits(json,"sequenceid"); allfields = juint(json,"allfields"); if ( (maxdepth= juint(json,"maxdepth")) <= 0 ) maxdepth = MAX_DEPTH; if ( exchangestr.buf[0] == 0 ) { if ( iQ.s.baseid != 0 && iQ.s.relid != 0 ) strcpy(exchangestr.buf,"nxtae"); else strcpy(exchangestr.buf,"basket"); } assetbits = InstantDEX_name(key,&keysize,exchangestr.buf,name.buf,base.buf,&iQ.s.baseid,rel.buf,&iQ.s.relid); //printf("2nd isask.%d base.(%s) rel.(%s)\n",iQ.s.isask,base.buf,rel.buf); exchange = exchange_find(exchangestr.buf); secret = jstr(json,"secret"), activenxt = jstr(json,"activenxt"); if ( secret == 0 ) { secret = SUPERNET.NXTACCTSECRET; activenxt = SUPERNET.NXTADDR; } if ( strcmp(method.buf,"allorderbooks") == 0 ) retstr = prices777_allorderbooks(); /*else if ( strcmp(method.buf,"coinshuffle") == 0 ) { if ( strcmp(exchangestr.buf,"shuffle") == 0 ) retstr = InstantDEX_coinshuffle(base.buf,&iQ,json); else retstr = clonestr("{\"error\":\"coinshuffle must use shuffle exchange\"}"); }*/ else if ( strcmp(method.buf,"openorders") == 0 ) retstr = InstantDEX_openorders(SUPERNET.NXTADDR,juint(json,"allorders")); else if ( strcmp(method.buf,"allexchanges") == 0 ) retstr = jprint(exchanges_json(),1); else if ( strcmp(method.buf,"cancelorder") == 0 ) retstr = InstantDEX_cancelorder(jstr(json,"activenxt"),jstr(json,"secret"),sequenceid,iQ.s.quoteid); else if ( strcmp(method.buf,"orderstatus") == 0 ) retstr = InstantDEX_orderstatus(sequenceid,iQ.s.quoteid); else if ( strcmp(method.buf,"tradehistory") == 0 ) retstr = InstantDEX_tradehistory(juint(json,"firsti"),juint(json,"endi")); else if ( strcmp(method.buf,"lottostats") == 0 ) retstr = jprint(InstantDEX_lottostats(),1); else if ( strcmp(method.buf,"balance") == 0 ) { if ( exchange != 0 && exchange->trade != 0 ) { if ( (coinstr= jstr(json,"base")) != 0 ) { if ( exchange->coinbalance != 0 ) { if ( exchange->balancejson == 0 ) { (*exchange->trade)(&retstr,exchange,0,0,0,0,0); if ( retstr != 0 ) { exchange->balancejson = cJSON_Parse(retstr); free(retstr); } } return((*exchange->coinbalance)(exchange,&balance,coinstr)); } else retstr = clonestr("{\"error\":\"coinbalance missing\"}"); } else (*exchange->trade)(&retstr,exchange,0,0,0,0,0); } else retstr = clonestr("{\"error\":\"cant find exchange\"}"); printf("%s ptr%.p trade.%p\n",exchangestr.buf,exchange,exchange!=0?exchange->trade:0); } else if ( strcmp(method.buf,"tradesequence") == 0 ) { //printf("call tradesequence.(%s)\n",jsonstr); retstr = InstantDEX_tradesequence(activenxt,secret,json); } else if ( strcmp(method.buf,"makebasket") == 0 ) { if ( (prices= prices777_makebasket(0,json,1,"basket",0,0)) != 0 ) retstr = clonestr("{\"result\":\"basket made\"}"); else retstr = clonestr("{\"error\":\"couldnt make basket\"}"); } else if ( strcmp(method.buf,"peggyrates") == 0 ) { if ( SUPERNET.peggy != 0 ) retstr = peggyrates(juint(json,"timestamp")); else retstr = clonestr("{\"error\":\"peggy disabled\"}"); } else if ( strcmp(method.buf,"LSUM") == 0 ) { sprintf(retbuf,"{\"result\":\"%s\",\"amount\":%d}",(rand() & 1) ? "BUY" : "SELL",(rand() % 100) * 100000); retstr = clonestr(retbuf); } else if ( strcmp(method.buf,"placebid") == 0 || strcmp(method.buf,"placeask") == 0 ) return(InstantDEX_placebidask(0,sequenceid,exchangestr.buf,name.buf,base.buf,rel.buf,&iQ,jstr(json,"extra"),secret,activenxt,json)); else if ( strcmp(exchangestr.buf,"active") == 0 && strcmp(method.buf,"orderbook") == 0 ) retstr = prices777_activebooks(name.buf,base.buf,rel.buf,iQ.s.baseid,iQ.s.relid,maxdepth,allfields,strcmp(exchangestr.buf,"active") == 0 || juint(json,"tradeable")); else if ( (prices= prices777_find(&invert,iQ.s.baseid,iQ.s.relid,exchangestr.buf)) == 0 ) { if ( (prices= prices777_poll(exchangestr.buf,name.buf,base.buf,iQ.s.baseid,rel.buf,iQ.s.relid)) != 0 ) { if ( prices777_equiv(prices->baseid) == prices777_equiv(iQ.s.baseid) && prices777_equiv(prices->relid) == prices777_equiv(iQ.s.relid) ) invert = 0; else if ( prices777_equiv(prices->baseid) == prices777_equiv(iQ.s.relid) && prices777_equiv(prices->relid) == prices777_equiv(iQ.s.baseid) ) invert = 1; else invert = 0, printf("baserel not matching (%s %s) %llu %llu vs (%s %s) %llu %llu\n",prices->base,prices->rel,(long long)prices->baseid,(long long)prices->relid,base.buf,rel.buf,(long long)iQ.s.baseid,(long long)iQ.s.relid); } } if ( retstr == 0 && prices != 0 ) { if ( strcmp(method.buf,"disable") == 0 ) { if ( prices != 0 ) { if ( strcmp(prices->exchange,"unconf") == 0 ) return(clonestr("{\"error\":\"cannot disable unconf\"}")); prices->disabled = 1; return(clonestr("{\"result\":\"success\"}")); } else return(clonestr("{\"error\":\"no prices to disable\"}")); } else if ( strcmp(method.buf,"enable") == 0 ) { if ( prices != 0 ) { prices->disabled = 0; return(clonestr("{\"result\":\"success\"}")); } else return(clonestr("{\"error\":\"no prices to enable\"}")); } else if ( strcmp(method.buf,"orderbook") == 0 ) { if ( maxdepth < MAX_DEPTH ) return(prices777_orderbook_jsonstr(invert,SUPERNET.my64bits,prices,&prices->O,maxdepth,allfields)); else if ( (retstr= prices->orderbook_jsonstrs[invert][allfields]) == 0 ) { retstr = prices777_orderbook_jsonstr(invert,SUPERNET.my64bits,prices,&prices->O,MAX_DEPTH,allfields); portable_mutex_lock(&prices->mutex); if ( prices->orderbook_jsonstrs[invert][allfields] != 0 ) free(prices->orderbook_jsonstrs[invert][allfields]); prices->orderbook_jsonstrs[invert][allfields] = retstr; portable_mutex_unlock(&prices->mutex); if ( retstr == 0 ) retstr = clonestr("{}"); } if ( retstr != 0 ) retstr = clonestr(retstr); } } //if ( Debuglevel > 2 ) printf("(%s) %p exchange.(%s) base.(%s) %llu rel.(%s) %llu | name.(%s) %llu\n",retstr!=0?retstr:"",prices,exchangestr.buf,base.buf,(long long)iQ.s.baseid,rel.buf,(long long)iQ.s.relid,name.buf,(long long)assetbits); } return(retstr); }