/****************************************************************************** * Copyright © 2014-2015 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. * * * ******************************************************************************/ #ifdef DEFINES_ONLY #ifndef hostnet777_h #define hostnet777_h #include #include #include #include #include #include "../utils/bits777.c" #include "../utils/ramcoder.c" #define HOSTNET777_MAXTIMEDIFF 10 #define CARDS777_MAXCARDS 52 #define CARDS777_MAXPLAYERS 9 #define CARDS777_FOLD -1 #define CARDS777_START 1 #define CARDS777_ANTE 2 #define CARDS777_SMALLBLIND 3 #define CARDS777_BIGBLIND 4 #define CARDS777_CHECK 5 #define CARDS777_CALL 6 #define CARDS777_BET 7 #define CARDS777_RAISE 8 #define CARDS777_FULLRAISE 9 #define CARDS777_SENTCARDS 10 #define CARDS777_ALLIN 11 #define CARDS777_FACEUP 12 #define CARDS777_WINNINGS 13 #define CARDS777_RAKES 14 #define CARDS777_CHANGES 15 #define CARDS777_SNAPSHOT 16 struct cards777_handinfo { bits256 checkprod,*cardpubs,*final,community256[5],cards[CARDS777_MAXPLAYERS][2]; uint64_t othercardpubs[CARDS777_MAXPLAYERS]; int64_t havemasks[CARDS777_MAXPLAYERS],betsize,hostrake,pangearake,lastraise,bets[CARDS777_MAXPLAYERS],snapshot[CARDS777_MAXPLAYERS+1],won[CARDS777_MAXPLAYERS]; uint32_t starttime,handmask,lastbettor,startdecktime,betstarted,finished,encodestarted; uint32_t cardi,userinput_starttime,handranks[CARDS777_MAXPLAYERS]; int8_t betstatus[CARDS777_MAXPLAYERS],actions[CARDS777_MAXPLAYERS],turnis[CARDS777_MAXPLAYERS]; uint8_t numactions,undergun,community[5],sharenrs[CARDS777_MAXPLAYERS][255],hands[CARDS777_MAXPLAYERS][7]; }; struct hostnet777_mtime { uint32_t starttime; int64_t millistart; double millidiff; }; struct cards777_pubdata { int64_t snapshot[CARDS777_MAXPLAYERS]; uint64_t maxrake,hostrake,bigblind,ante,pangearake,summaries,mismatches; uint32_t button,readymask,numhands,rakemillis,minbuyin,maxbuyin,summarysize; void *table; struct cards777_handinfo hand; char newhand[65536],coinstr[16]; uint8_t M,N,numcards,summary[65536]; bits256 data[]; }; struct cards777_privdata { bits256 holecards[2],*audits,*outcards,*xoverz; //,*reconstructed[CARDS777_MAXPLAYERS],*mofn[CARDS777_MAXPLAYERS][CARDS777_MAXPLAYERS]; uint8_t *myshares[CARDS777_MAXPLAYERS],*allshares,hole[2],cardis[2],automuck,autofold; bits256 data[]; }; struct hostnet777_endpoint { char endpoint[128],transport[16],ipaddr[64]; uint16_t port; }; struct hostnet777_id { bits256 pubkey; uint64_t nxt64bits; void *privdata,*pubdata; int32_t pmsock; uint32_t lastcontact; }; union hostnet777 { struct hostnet777_server *server; struct hostnet777_client *client; }; struct hostnet777_hdr { queue_t Q; bits256 privkey,pubkey; struct hostnet777_mtime mT; void *privdata,*pubdata; uint64_t nxt64bits;//,recvhashes[64]; void (*pollfunc)(union hostnet777 *hn); uint32_t lastping; int32_t slot,done,state,ind; }; struct hostnet777_client { struct hostnet777_hdr H; int32_t subsock; struct hostnet777_id my; uint64_t balance,tableid; }; struct hostnet777_server { struct hostnet777_hdr H; int32_t num,max,pubsock; struct hostnet777_endpoint ep; //queue_t mailboxQ[CARDS777_MAXPLAYERS]; struct hostnet777_id clients[]; }; void hostnet777_msg(uint64_t destbits,bits256 destpub,union hostnet777 *src,int32_t blindflag,char *jsonstr,int32_t len); int32_t cards777_testinit(struct hostnet777_server *srv,int32_t M,struct hostnet777_client **clients,int32_t N,int32_t numcards); bits256 cards777_decode(bits256 *seedp,bits256 *xoverz,int32_t destplayer,bits256 cipher,bits256 *outcards,int32_t numcards,int32_t N); bits256 cards777_cardpriv(bits256 playerpriv,bits256 *cardpubs,int32_t numcards,bits256 cipher); uint8_t *cards777_encode(bits256 *encoded,bits256 *xoverz,uint8_t *allshares,uint8_t *myshares[],uint8_t *sharenrs,int32_t M,bits256 *ciphers,int32_t numcards,int32_t N); bits256 cards777_initdeck(bits256 *cards,bits256 *cardpubs,int32_t numcards,int32_t N,bits256 *playerpubs,bits256 *playerprivs); int32_t init_sharenrs(unsigned char sharenrs[255],unsigned char *orig,int32_t m,int32_t n); uint32_t set_handstr(char *handstr,uint8_t cards[7],int32_t verbose); int32_t hostnet777_idle(union hostnet777 *hn); void msleep(uint32_t milliseconds); struct cards777_privdata *cards777_allocpriv(int32_t numcards,int32_t N); struct cards777_pubdata *cards777_allocpub(int32_t M,int32_t numcards,int32_t N); struct hostnet777_server *hostnet777_server(bits256 srvprivkey,bits256 srvpubkey,char *transport,char *ipaddr,uint16_t port,int32_t maxclients); struct hostnet777_client *hostnet777_client(bits256 privkey,bits256 pubkey,char *srvendpoint,int32_t slot); int32_t hostnet777_register(struct hostnet777_server *srv,bits256 clientpub,int32_t slot); int32_t cards777_checkcard(bits256 *cardprivp,int32_t cardi,int32_t slot,int32_t destplayer,bits256 playerpriv,bits256 *cardpubs,int32_t numcards,bits256 card); int32_t hostnet777_init(union hostnet777 *hn,bits256 *privkeys,int32_t num,int32_t launchflag); int32_t hostnet777_sendmsg(union hostnet777 *ptr,bits256 destpub,bits256 mypriv,bits256 mypub,uint8_t *msg,int32_t len); int64_t hostnet777_convmT(struct hostnet777_mtime *mT,int64_t othermillitime); bits256 cards777_pubkeys(bits256 *pubkeys,int32_t numcards,bits256 cmppubkey); int32_t pangea_tableaddr(struct cards777_pubdata *dp,uint64_t destbits); int32_t hostnet777_copybits(int32_t reverse,uint8_t *dest,uint8_t *src,int32_t len); int32_t cards777_validate(bits256 cardpriv,bits256 final,bits256 *cardpubs,int32_t numcards,bits256 *audit,int32_t numplayers,bits256 playerpub); void *hostnet777_idler(union hostnet777 *ptr); int32_t nn_socket_status(int32_t sock,int32_t timeoutmillis); int32_t nn_createsocket(char *endpoint,int32_t bindflag,char *name,int32_t type,uint16_t port,int32_t sendtimeout,int32_t recvtimeout); void free_queueitem(void *itemptr); struct pangea_info *pangea_find(uint64_t tableid,int32_t threadid); int32_t pangea_ind(struct pangea_info *sp,int32_t slot); int32_t pangea_slot(struct pangea_info *sp,int32_t ind); int32_t hostnet777_replace(struct hostnet777_server *srv,bits256 clientpub,int32_t slot); extern int32_t Debuglevel; #endif #else #ifndef hostnet777_c #define hostnet777_c #ifndef hostnet777_h #define DEFINES_ONLY #include "hostnet777.c" #undef DEFINES_ONLY #endif #include "../includes/tweetnacl.h" #include "../includes/curve25519.h" static const bits256 zeropoint; int64_t hostnet777_convmT(struct hostnet777_mtime *mT,int64_t othermillitime) { int64_t lag,millitime,millis = (uint64_t)milliseconds(); if ( mT->starttime == 0 ) { mT->starttime = (uint32_t)time(NULL); mT->millistart = millis; printf("set millistart.%p %lld\n",mT,(long long)millis); } //printf("%p millis.%lld - millistart.%lld = %lld\n",mT,(long long)millis,(long long)mT->millistart,(long long)(millis - mT->millistart)); millitime = (millis - mT->millistart) + ((long long)mT->starttime * 1000); if ( othermillitime != 0 ) { millitime += mT->millidiff; lag = (othermillitime - millitime); mT->millidiff = (mT->millidiff * .9) + (.1 * lag); } return(millitime); } double hostnet777_updatelag(uint64_t senderbits,int64_t millitime,int64_t now) { printf("updatelag %llu: %lld\n",(long long)senderbits,(long long)(millitime - now)); return(millitime - now); } int32_t hostnet777_send(int32_t sock,void *ptr,int32_t len) { static int32_t numerrs; int32_t j,sendlen = 0; if ( sock >= 0 ) { for (j=0; j<10; j++) { if ( (nn_socket_status(sock,100) & NN_POLLOUT) != 0 ) break; } if ( j == 10 ) { printf("socket.%d not ready\n",sock); return(-1); } for (j=0; j<10; j++) { char *nn_err_strerror(); int32_t nn_err_errno(); if ( (sendlen= nn_send(sock,ptr,len,0)) == len ) break; if ( numerrs++ < 100 ) printf("numerrs.%d retry.%d for sock.%d len.%d vs sendlen.%d (%s) (%s)\n",numerrs,j,sock,len,sendlen,(char *)(len<512?ptr:""),nn_err_strerror(nn_err_errno())); msleep(100); } //printf("hostnet777_send.%d j.%d len.%d sendlen.%d\n",sock,j,len,sendlen); } else printf("hostnet777_send neg socket\n"); return(sendlen); } struct hostnet777_id *hostnet777_find64(struct hostnet777_server *srv,uint64_t senderbits) { int32_t i; if ( srv->num > 0 ) { for (i=0; imax; i++) if ( srv->clients[i].nxt64bits == senderbits ) return(&srv->clients[i]); } return(0); } int32_t hostnet777_sendsock(union hostnet777 *ptr,uint64_t destbits) { int32_t ind; //struct hostnet777_id *client; if ( (ind= ptr->client->H.slot) != 0 ) { //printf("client.%p ind.%d: %d %d\n",ptr->client,ind,ptr->client->pushsock,ptr->client->my.pmsock); //if ( 1 || destbits == 0 ) // return(ptr->client->pushsock); //else return(ptr->client->my.pmsock); } else { //printf("server.%p ind.%d: %d %d\n",ptr->server,ind,ptr->server->pullsock,ptr->server->pubsock); //if ( destbits == 0 ) return(ptr->server->pubsock); /*else if ( (client= hostnet777_find64(ptr->server,destbits)) != 0 ) { //printf("SERVER -> ind.%d: %d %d\n",ind,ptr->server->pubsock,client->pmsock); return(client->pmsock); } else printf("error cant find %llu in server clients\n",(long long)destbits);*/ } return(-1); } struct hostnet777_id *hostnet777_find(struct hostnet777_server *srv,bits256 senderpub) { int32_t i; uint64_t senderbits = acct777_nxt64bits(senderpub); if ( srv->num > 0 ) { for (i=0; imax; i++) if ( srv->clients[i].nxt64bits == senderbits ) return(&srv->clients[i]); } return(0); } void hostnet777_lastcontact(struct hostnet777_server *srv,bits256 senderpub) { struct hostnet777_id *ptr; if ( (ptr= hostnet777_find(srv,senderpub)) != 0 ) ptr->lastcontact = (uint32_t)time(NULL); } int32_t hostnet777_copybits(int32_t reverse,uint8_t *dest,uint8_t *src,int32_t len) { int32_t i; uint8_t *tmp; if ( reverse != 0 ) { tmp = dest; dest = src; src = tmp; } //printf("src.%p dest.%p len.%d\n",src,dest,len); //for (i=0; i> 3); } int32_t hostnet777_serialize(int32_t reverse,bits256 *senderpubp,uint64_t *senderbitsp,bits256 *sigp,uint32_t *timestampp,uint64_t *destbitsp,uint8_t *origbuf) { uint8_t *buf = origbuf; long extra = sizeof(bits256) + sizeof(uint64_t) + sizeof(uint64_t); buf += hostnet777_copybits(reverse,buf,(void *)destbitsp,sizeof(uint64_t)); buf += hostnet777_copybits(reverse,buf,senderpubp->bytes,sizeof(bits256)); buf += hostnet777_copybits(reverse,buf,(void *)senderbitsp,sizeof(uint64_t)); buf += hostnet777_copybits(reverse,buf,(void *)timestampp,sizeof(uint32_t)), extra += sizeof(uint32_t); if ( *senderbitsp != 0 ) buf += hostnet777_copybits(reverse,buf,sigp->bytes,sizeof(bits256)), extra += sizeof(bits256); else memset(sigp,0,sizeof(*sigp)); if ( ((long)buf - (long)origbuf) != extra ) { printf("hostnet777_serialize: extrasize mismatch %ld vs %ld\n",((long)buf - (long)origbuf),extra); } return((int32_t)extra); } uint8_t *hostnet777_encode(int32_t *cipherlenp,void *str,int32_t len,bits256 destpubkey,bits256 myprivkey,bits256 mypubkey,uint64_t senderbits,bits256 sig,uint32_t timestamp) { uint8_t *buf,*nonce,*cipher,*ptr; uint64_t destbits; int32_t totalsize,hdrlen; long extra = crypto_box_NONCEBYTES + crypto_box_ZEROBYTES + sizeof(sig); destbits = (memcmp(destpubkey.bytes,GENESIS_PUBKEY.bytes,sizeof(destpubkey)) != 0) ? acct777_nxt64bits(destpubkey) : 0; totalsize = (int32_t)(len + sizeof(mypubkey) + sizeof(senderbits) + sizeof(destbits) + sizeof(timestamp)); *cipherlenp = 0; if ( (buf= calloc(1,totalsize + extra)) == 0 ) { printf("hostnet777_encode: outof mem for buf[%ld]\n",totalsize+extra); return(0); } if ( (cipher= calloc(1,totalsize + extra)) == 0 ) { printf("hostnet777_encode: outof mem for cipher[%ld]\n",totalsize+extra); free(buf); return(0); } ptr = cipher; hdrlen = hostnet777_serialize(0,&mypubkey,&senderbits,&sig,×tamp,&destbits,cipher); if ( senderbits != 0 ) totalsize += sizeof(sig);//, printf("totalsize.%d extra.%ld add %ld\n",totalsize-len,extra,(long)(sizeof(sig) + sizeof(timestamp))); if ( destbits != 0 && senderbits != 0 ) { totalsize += crypto_box_NONCEBYTES + crypto_box_ZEROBYTES;//, printf("totalsize.%d extra.%ld add %d\n",totalsize-len,extra,crypto_box_NONCEBYTES + crypto_box_ZEROBYTES); nonce = &cipher[hdrlen]; randombytes(nonce,crypto_box_NONCEBYTES); cipher = &nonce[crypto_box_NONCEBYTES]; //printf("len.%d -> %d %d\n",len,len+crypto_box_ZEROBYTES,len + crypto_box_ZEROBYTES + crypto_box_NONCEBYTES); memset(cipher,0,len+crypto_box_ZEROBYTES); memset(buf,0,crypto_box_ZEROBYTES); memcpy(buf+crypto_box_ZEROBYTES,str,len); crypto_box(cipher,buf,len+crypto_box_ZEROBYTES,nonce,destpubkey.bytes,myprivkey.bytes); hdrlen += crypto_box_NONCEBYTES + crypto_box_ZEROBYTES; } else memcpy(&cipher[hdrlen],str,len); if ( totalsize != len+hdrlen ) printf("unexpected totalsize.%d != len.%d + hdrlen.%d %d\n",totalsize,len,hdrlen,len+hdrlen); free(buf); *cipherlenp = totalsize; return(ptr); } int32_t hostnet777_decode(uint64_t *senderbitsp,bits256 *sigp,uint32_t *timestampp,uint64_t *destbitsp,uint8_t *str,uint8_t *cipher,int32_t *lenp,uint8_t *myprivkey) { bits256 srcpubkey; uint8_t *nonce; int i,hdrlen,err=0,len = *lenp; hdrlen = hostnet777_serialize(1,&srcpubkey,senderbitsp,sigp,timestampp,destbitsp,cipher); cipher += hdrlen, len -= hdrlen; if ( *destbitsp != 0 && *senderbitsp != 0 ) { nonce = cipher; cipher += crypto_box_NONCEBYTES, len -= crypto_box_NONCEBYTES; err = crypto_box_open((uint8_t *)str,cipher,len,nonce,srcpubkey.bytes,myprivkey); for (i=0; ibytes,sizeof(mypub)) == 0 ) { if ( destbits != 0 ) printf("hostnet777: got my own msg?\n"); } //printf("decrypt(%d) destbits.%llu my64.%llu mypriv.%llx mypub.%llx senderpub.%llx shared.%llx\n",len,(long long)destbits,(long long)my64bits,(long long)mypriv.txid,(long long)mypub.txid,(long long)senderpubp->txid,(long long)seed.txid); if ( hostnet777_decode(&sendertmp,&sig,timestampp,&desttmp,(void *)buf,src,&len,mypriv.bytes) == 0 ) { if ( (diff= (*timestampp - (uint32_t)time(NULL))) < 0 ) diff = -diff; if ( 0 && diff > HOSTNET777_MAXTIMEDIFF ) printf("diff.%d > %d %u vs %u\n",diff,HOSTNET777_MAXTIMEDIFF,*timestampp,(uint32_t)time(NULL)); else { if ( 1 ) { memset(seed.bytes,0,sizeof(seed)); for (i='0'; i<='9'; i++) SETBIT(seed.bytes,i); for (i='a'; i<='f'; i++) SETBIT(seed.bytes,i); _init_HUFF(hp,len,buf), hp->endpos = (len << 3); newlen = ramcoder_decoder(0,1,dest,maxlen,hp,&seed); } else memcpy(dest,buf,len), newlen = len; //printf("T%d decrypted newlen.%d\n",threadid,newlen); if ( senderbits != 0 && senderpubp->txid != 0 ) { *senderbitsp = senderbits; if ( destbits == 0 ) msgpriv = GENESIS_PRIVKEY; else msgpriv = mypriv; acct777_sign(&checksig,msgpriv,*senderpubp,*timestampp,dest,newlen); if ( memcmp(checksig.sigbits.bytes,&sig,sizeof(checksig.sigbits)) != 0 ) { printf("sender.%llu sig %llx compare error vs %llx using sig->pub from %llu, broadcast.%d\n",(long long)senderbits,(long long)sig.txid,(long long)checksig.sigbits.txid,(long long)senderbits,destbits == 0); //free(buf); //return(0); } //else printf("SIG VERIFIED newlen.%d (%llu -> %llu)\n",newlen,(long long)senderbits,(long long)destbits); } } } else printf("%llu: hostnet777_decrypt skip: decode_cipher error len.%d -> newlen.%d\n",(long long)acct777_nxt64bits(mypub),len,newlen); free(buf); return(newlen); } int32_t hostnet777_hashes(uint64_t *hashes,int32_t n,uint8_t *msg,int32_t len) { int32_t i,firsti = -1; bits256 hash; calc_sha256(0,hash.bytes,msg,len); printf("msg.%p len.%d hash.%llx\n",msg,len,(long long)hash.txid); for (i=0; i= 0 ) hashes[firsti] = hash.txid; else { for (i=n-1; i>0; i--) hashes[i] = hashes[i-1]; hashes[0] = hash.txid; } return(-1); } void hostnet777_processmsg(uint64_t *destbitsp,bits256 *senderpubp,queue_t *Q,bits256 mypriv,bits256 mypub,uint8_t *msg,int32_t origlen,int32_t pmflag,struct hostnet777_mtime *mT) { char *jsonstr = 0; bits256 sig; uint32_t timestamp; int32_t len; uint64_t senderbits,now,millitime; uint8_t *ptr=0; cJSON *json; long extra; extra = sizeof(*senderpubp) + sizeof(*destbitsp) + sizeof(sig) + sizeof(senderbits) + sizeof(timestamp); if ( (len= origlen) > extra ) { //printf("got msglen.%d\n",origlen); if ( (ptr= malloc(len*4 + 8192 + sizeof(struct queueitem) - extra)) == 0 ) { printf("hostnet777_processmsg cant alloc queueitem\n"); return; } if ( (len= hostnet777_decrypt(senderpubp,&senderbits,×tamp,mypriv,mypub,&ptr[sizeof(struct queueitem)],len*4,msg,len)) > 1 && len < len*4 ) { jsonstr = (char *)&ptr[sizeof(struct queueitem)]; if ( (json= cJSON_Parse(jsonstr)) != 0 ) { millitime = j64bits(json,"millitime"); now = hostnet777_convmT(mT,millitime); //printf("now.%lld vs millitime.%lld lag.%lld\n",(long long)now,(long long)millitime,(long long)(millitime - now)); if ( pmflag != 0 && juint(json,"timestamp") != timestamp && juint(json,"timestamp")+1 != timestamp ) printf("msg.(%s) timestamp.%u mismatch | now.%ld\n",jsonstr,timestamp,(long)time(NULL)); else if ( pmflag != 0 && j64bits(json,"sender") != senderbits ) printf("msg.(%ld) sender.%llu mismatch vs json.%llu\n",(long)strlen(jsonstr),(long long)senderbits,(long long)j64bits(json,"sender")); else { //printf("%llu: QUEUE msg.%d\n",(long long)acct777_nxt64bits(mypub),len); //if ( hostnet777_hashes(recvhashes,64,ptr,len) < 0 ) queue_enqueue("host777",Q,(void *)ptr,0); ptr = 0; } free_json(json); } else printf("parse error.(%s)\n",jsonstr); } else printf("decrypt error len.%d origlen.%d\n",len,origlen); } else printf("origlen.%d\n",origlen); if ( ptr != 0 ) free(ptr); } /*void hostnet777_mailboxQ(queue_t *mailboxQ,void *cipher,int32_t cipherlen) { uint16_t *ptr; struct queueitem *item = calloc(1,sizeof(struct queueitem) + cipherlen + sizeof(uint16_t)); ptr = (uint16_t *)((long)item + sizeof(struct queueitem)); ptr[0] = cipherlen; memcpy(&ptr[1],cipher,cipherlen); queue_enqueue("mailboxQ",mailboxQ,item); }*/ #define hostnet777_broadcast(ptr,mypriv,mypub,msg,len) hostnet777_sendmsg(ptr,zeropoint,mypriv,mypub,msg,len) #define hostnet777_blindcast(ptr,msg,len) hostnet777_sendmsg(ptr,zeropoint,zeropoint,zeropoint,msg,len) #define hostnet777_signedPM(ptr,destpub,mypriv,mypub,msg,len) hostnet777_sendmsg(ptr,destpub,mypriv,mypub,msg,len) #define hostnet777_blindPM(ptr,destpub,msg,len) hostnet777_sendmsg(ptr,destpub,zeropoint,zeropoint,msg,len) int32_t hostnet777_sendmsg(union hostnet777 *ptr,bits256 destpub,bits256 mypriv,bits256 mypub,uint8_t *msg,int32_t len) { int32_t cipherlen,datalen,sendsock,i; bits256 seed; uint8_t *data=0,*cipher; uint64_t destbits; struct acct777_sig sig; HUFF H,*hp = &H; if ( destpub.txid != 0 ) destbits = acct777_nxt64bits(destpub); else { destbits = 0; destpub = GENESIS_PUBKEY; } //printf("hostnet777_sendmsg dest.%llu destpub.%llx priv.%llx pub.%llx\n",(long long)destbits,(long long)destpub.txid,(long long)mypriv.txid,(long long)mypub.txid); memset(&sig,0,sizeof(sig)); if ( mypub.txid == 0 || mypriv.txid == 0 ) mypriv = curve25519_keypair(&mypub), sig.timestamp = (uint32_t)time(NULL); else acct777_sign(&sig,mypriv,destpub,(uint32_t)time(NULL),msg,len); if ( (sendsock= hostnet777_sendsock(ptr,mypriv.txid != 0 ? destbits : 0)) < 0 ) { printf("%llu: ind.%d no sendsock for %llx -> %llu\n",(long long)ptr->client->H.nxt64bits,ptr->client->H.slot,(long long)acct777_nxt64bits(mypub),(long long)destbits); return(-1); } if ( 1 ) { memset(seed.bytes,0,sizeof(seed)); data = calloc(1,len*2); _init_HUFF(hp,len*2,data); for (i='0'; i<='9'; i++) SETBIT(seed.bytes,i); for (i='a'; i<='f'; i++) SETBIT(seed.bytes,i); ramcoder_encoder(0,1,msg,len,hp,0,&seed); datalen = hconv_bitlen(hp->bitoffset); } else data = msg, datalen = len; if ( (cipher= hostnet777_encode(&cipherlen,data,datalen,destpub,mypriv,mypub,sig.signer64bits,sig.sigbits,sig.timestamp)) != 0 ) { hostnet777_send(sendsock,cipher,cipherlen); free(cipher); } if ( data != msg ) free(data); return(cipherlen); } int32_t hostnet777_idle(union hostnet777 *hn) { int32_t len,slot,sock,n = 0; bits256 senderpub,mypriv,mypub; uint64_t destbits; uint8_t *msg; long extra = sizeof(bits256)+sizeof(uint64_t); if ( (slot= hn->client->H.slot) != 0 ) { mypriv = hn->client->H.privkey, mypub = hn->client->H.pubkey; if ( (sock= hn->client->subsock) >= 0 && (len= nn_recv(sock,&msg,NN_MSG,0)) > extra ) { hostnet777_copybits(1,msg,(void *)&destbits,sizeof(uint64_t)); //printf("client got pub len.%d\n",len); if ( destbits == 0 || destbits == hn->client->H.nxt64bits ) hostnet777_processmsg(&destbits,&senderpub,&hn->client->H.Q,mypriv,mypub,msg,len,0,&hn->client->H.mT), n++; nn_freemsg(msg); } else if ( hn->client->H.pollfunc != 0 ) (*hn->client->H.pollfunc)(hn); } else { //printf("server idle %.0f\n",milliseconds()); mypriv = hn->server->H.privkey, mypub = hn->server->H.pubkey; for (slot=1; slotserver->num; slot++) { //printf("check ind.%d %.0f\n",ind,milliseconds()); if ( (sock= hn->server->clients[slot].pmsock) >= 0 && (len= nn_recv(sock,&msg,NN_MSG,0)) > extra ) { //printf("server got pm[%d] %d\n",slot,len); hostnet777_copybits(1,msg,(void *)&destbits,sizeof(uint64_t)); if ( destbits == 0 || destbits == hn->server->H.nxt64bits ) { hostnet777_processmsg(&destbits,&senderpub,&hn->server->H.Q,mypriv,mypub,msg,len,1,&hn->server->H.mT); hostnet777_lastcontact(hn->server,senderpub); } hostnet777_send(hn->server->pubsock,msg,len); nn_freemsg(msg); } } if ( hn->server->H.pollfunc != 0 ) (*hn->server->H.pollfunc)(hn); } return(n); } int32_t hostnet777_replace(struct hostnet777_server *srv,bits256 clientpub,int32_t slot) { char endpoint[128],buf[128]; uint64_t nxt64bits = acct777_nxt64bits(clientpub); sprintf(endpoint,"%s://%s:%u",srv->ep.transport,srv->ep.ipaddr,srv->ep.port + slot + 1); //sprintf(buf,"%s://127.0.0.1:%u",srv->ep.transport,srv->ep.port + slot + 1); strcpy(buf,endpoint); if ( srv->clients[slot].pmsock < 0 ) srv->clients[slot].pmsock = nn_createsocket(buf,1,"NN_PULL",NN_PULL,srv->ep.port + slot + 1,10,10); printf("NN_PULL.%d for slot.%d\n",srv->clients[slot].pmsock,slot); srv->clients[slot].pubkey = clientpub; srv->clients[slot].nxt64bits = nxt64bits; srv->clients[slot].lastcontact = (uint32_t)time(NULL); return(srv->clients[slot].pmsock); } int32_t hostnet777_register(struct hostnet777_server *srv,bits256 clientpub,int32_t slot) { int32_t i,n; struct hostnet777_id *ptr; if ( slot < 0 ) { if ( (ptr= hostnet777_find(srv,clientpub)) != 0 ) { slot = (int32_t)(((long)ptr - (long)srv->clients) / sizeof(*srv->clients)); //printf("hostnet777_register: deregister slot.%d\n",slot); if ( ptr->pmsock >= 0 ) nn_shutdown(ptr->pmsock,0); memset(ptr,0,sizeof(*ptr)); ptr->pmsock = -1; srv->num--; return(-1); } for (slot=1; slotmax; slot++) if ( srv->clients[slot].nxt64bits == 0 ) break; } if ( srv->num >= srv->max ) { printf("hostnet777_register: cant register anymore num.%d vs max.%d\n",srv->num,srv->max); return(-1); } if ( (ptr= hostnet777_find(srv,clientpub)) != 0 ) { printf("hostnet777_register: cant register duplicate %llu\n",(long long)acct777_nxt64bits(clientpub)); return((int32_t)(((long)ptr - (long)srv->clients) / sizeof(*srv->clients))); } if ( slot != srv->num ) { printf("hostnet777_register: cant register slot.%d vs num.%d vs max.%d\n",slot,srv->num,srv->max); return(-1); } hostnet777_replace(srv,clientpub,slot); srv->num++; for (i=n=0; imax; i++) if ( srv->clients[i].nxt64bits != 0 ) n++; if ( n != srv->num ) { printf("mismatched nonz nxt64bits n.%d vs %d\n",n,srv->num); srv->num = n; } return(slot); } struct hostnet777_client *hostnet777_client(bits256 privkey,bits256 pubkey,char *srvendpoint,int32_t slot) { char endbuf[128],endbuf2[128]; uint16_t port; struct hostnet777_client *ptr; ptr = calloc(1,sizeof(*ptr)); ptr->H.slot = slot; ptr->H.privkey = privkey, ptr->H.pubkey = ptr->my.pubkey = pubkey; ptr->H.nxt64bits = ptr->my.nxt64bits = acct777_nxt64bits(pubkey); ptr->my.lastcontact = (uint32_t)time(NULL); strcpy(endbuf,srvendpoint); endbuf[strlen(endbuf)-4] = 0; port = atoi(&srvendpoint[strlen(endbuf)]); sprintf(endbuf2,"%s%u",endbuf,port + 1 + slot); ptr->my.pmsock = nn_createsocket(endbuf2,0,"NN_PUSH",NN_PUSH,0,10,100); printf("NN_PUSH %d from (%s) port.%d\n",ptr->my.pmsock,endbuf2,port+1+slot); sprintf(endbuf2,"%s%u",endbuf,port); ptr->subsock = nn_createsocket(endbuf2,0,"NN_SUB",NN_SUB,0,10,100); printf("SUB %d from (%s) port.%d\n",ptr->subsock,endbuf2,port); nn_setsockopt(ptr->subsock,NN_SUB,NN_SUB_SUBSCRIBE,"",0); //sprintf(endbuf2,"%s%u",endbuf,port); //ptr->pushsock = nn_createsocket(endbuf2,0,"NN_PUSH",NN_PUSH,0,10,1); //printf("PUSH %d to (%s)\n",ptr->pushsock,endbuf2); return(ptr); } void hostnet777_freeclient(struct hostnet777_client *client) { client->H.done = 1; if ( client->subsock >= 0 ) nn_shutdown(client->subsock,0); //if ( client->pushsock >= 0 ) // nn_shutdown(client->pushsock,0); if ( client->my.pmsock >= 0 ) nn_shutdown(client->my.pmsock,0); } void hostnet777_freeserver(struct hostnet777_server *srv) { int32_t ind; srv->H.done = 1; //if ( srv->pullsock >= 0 ) // nn_shutdown(srv->pullsock,0); if ( srv->pubsock >= 0 ) nn_shutdown(srv->pubsock,0); for (ind=1; indmax; ind++) { if ( srv->clients[ind].pmsock >= 0 ) nn_shutdown(srv->clients[ind].pmsock,0); } } struct hostnet777_server *hostnet777_server(bits256 srvprivkey,bits256 srvpubkey,char *transport,char *ipaddr,uint16_t port,int32_t maxclients) { struct hostnet777_server *srv; int32_t i; struct hostnet777_endpoint *ep; char buf[128]; srv = calloc(1,sizeof(*srv) + maxclients*sizeof(struct hostnet777_id)); srv->max = maxclients; ep = &srv->ep; if ( (ep->port= port) == 0 ) ep->port = port = 8000 + (rand() % 1000); if ( transport == 0 || transport[0] == 0 ) transport = TEST_TRANSPORT; if ( ipaddr == 0 || ipaddr[0] == 0 ) ipaddr = "127.0.0.1"; strcpy(ep->transport,transport), strcpy(ep->ipaddr,ipaddr); for (i=0; iclients[i].pmsock = -1; srv->H.privkey = srvprivkey; srv->H.pubkey = srv->clients[0].pubkey = srvpubkey; srv->H.nxt64bits = srv->clients[0].nxt64bits = acct777_nxt64bits(srvpubkey); sprintf(ep->endpoint,"%s://%s:%u",transport,ipaddr,port); if ( strcmp(transport,"tcpmux") == 0 ) strcat(ep->endpoint,"/pangea"); //sprintf(buf,"%s://127.0.0.1:%u",transport,port); strcpy(buf,ep->endpoint); srv->pubsock = nn_createsocket(buf,1,"NN_PUB",NN_PUB,port,10,100); printf("PUB.%d to (%s) pangeaport.%d\n",srv->pubsock,ep->endpoint,port); srv->num = 1; return(srv); } void *hostnet777_idler(union hostnet777 *ptr) { while ( ptr->client->H.done == 0 ) { if ( hostnet777_idle(ptr) == 0 ) msleep(1); } //printf("hostnet777_idler ind.%d done\n",ptr->client->H.slot); sleep(1); free(ptr); return(0); } void hostnet777_msg(uint64_t destbits,bits256 destpub,union hostnet777 *src,int32_t blindflag,char *jsonstr,int32_t len) { if ( destbits == 0 ) { //printf(">>>>>>>>> blind.%d broadcast from %llu, len.%d\n",blindflag,(long long)src->client->H.nxt64bits,len); if ( blindflag != 0 ) hostnet777_blindcast(src,(uint8_t *)jsonstr,len); else hostnet777_broadcast(src,src->client->H.privkey,src->client->H.pubkey,(uint8_t *)jsonstr,len); if ( src->server->H.slot == 0 ) queue_enqueue("loopback",&src->client->H.Q,queueitem(jsonstr),1); } else if ( destbits != src->client->H.nxt64bits ) { //printf(">>>>>>>>> blind.%d PM from %llu to %llu\n",blindflag,(long long)src->client->H.nxt64bits,(long long)destbits); if ( blindflag != 0 ) hostnet777_blindPM(src,destpub,(uint8_t *)jsonstr,len); else hostnet777_signedPM(src,destpub,src->client->H.privkey,src->client->H.pubkey,(uint8_t *)jsonstr,len); } else queue_enqueue("loopback",&src->client->H.Q,queueitem(jsonstr),1); } int32_t hostnet777_init(union hostnet777 *hn,bits256 *privkeys,int32_t num,int32_t launchflag) { bits256 pubkey; int32_t slot,threadid; struct hostnet777_server *srv=0; for (threadid=0; threadidH.privkey = privkeys[threadid], srv->H.pubkey = pubkey; if ( launchflag != 0 && portable_thread_create((void *)hostnet777_idler,&hn[0]) == 0 ) printf("error launching server thread\n"); } else { if ( (slot= hostnet777_register(srv,pubkey,-1)) >= 0 ) { if ( (hn[threadid].client= hostnet777_client(privkeys[threadid],pubkey,srv->ep.endpoint,slot)) == 0 ) printf("error creating clients[%d]\n",threadid); else { hn[threadid].client->H.privkey = privkeys[threadid], hn[threadid].client->H.pubkey = pubkey; printf("slot.%d client.%p -> %llu pubkey.%llx\n",slot,hn[threadid].client,(long long)hn[threadid].client->H.nxt64bits,(long long)hn[threadid].client->H.pubkey.txid); if ( launchflag != 0 && portable_thread_create((void *)hostnet777_idler,&hn[threadid]) == 0 ) printf("error launching clients[%d] thread\n",threadid); } } } } return(num); } int32_t hostnet777_block(struct hostnet777_server *srv,uint64_t *senderbitsp,uint32_t *timestampp,union hostnet777 *hn,uint8_t *data,int32_t len,uint8_t *buf,int32_t maxmicro,int32_t blind,int32_t revealed) { static int32_t errs; char *jsonstr,*hexstr,*cmdstr,*handstr,tmp[128]; cJSON *json; void *val; struct cards777_privdata *priv; struct cards777_pubdata *dp; int32_t i,j,cardi,bestj,destplayer,card,senderslot,retval = -1; bits256 cardpriv; uint32_t rank,bestrank; struct pangea_info *sp; *senderbitsp = 0; if ( hn == 0 || hn->client == 0 ) { printf("null hn.%p %p\n",hn,hn!=0?hn->client:0); return(-1); } dp = srv->clients[hn->client->H.slot].pubdata; sp = dp->table; priv = srv->clients[hn->client->H.slot].privdata; for (i=0; iclient->H.Q,1)) != 0 ) { //printf("DEQ.(%s)\n",jsonstr); if ( (json= cJSON_Parse(jsonstr)) != 0 ) { *senderbitsp = j64bits(json,"sender"); *timestampp = juint(json,"timestamp"); if ( (hexstr= jstr(json,"data")) != 0 && strlen(hexstr) == (juint(json,"n")<<1) ) { decode_hex(buf,len,hexstr); if ( memcmp(buf,data,len) == 0 ) { val = hostnet777_find64(srv,*senderbitsp); //printf("blind.%d val.%p\n",blind,val); if ( (blind == 0 && val != 0) || (blind != 0 && val == 0) ) { if ( (cmdstr= jstr(json,"cmd")) != 0 ) { cardi = juint(json,"cardi"); destplayer = juint(json,"dest"); senderslot = juint(json,"myslot"); if ( strcmp(cmdstr,"pubstr") == 0 ) { //printf("player.%d got pubstr\n",hn->client->H.slot); memcpy(dp->hand.cardpubs,buf,len); //if ( (nrs= jstr(json,"sharenrs")) != 0 ) // decode_hex(dp->hand.sharenrs,(int32_t)strlen(nrs)>>1,nrs); memset(dp->hand.handranks,0,sizeof(dp->hand.handranks)); memset(priv->hole,0,sizeof(priv->hole)); memset(priv->holecards,0,sizeof(priv->holecards)); memset(dp->hand.community,0,sizeof(dp->hand.community)); dp->hand.handmask = 0; dp->numhands++; dp->button++; if ( dp->button >= dp->N ) dp->button = 0; exit(1); printf("deprecated\n"); //sp->balances[pangea_slot(dp->button)]--, dp->balances[(pangea_slot(dp->button) + 1) % dp->N] -= 2; } else if ( strcmp(cmdstr,"encode") == 0 ) { if ( Debuglevel > 2 ) printf("player.%d encodes\n",hn->client->H.slot); cards777_encode(priv->outcards,priv->xoverz,priv->allshares,priv->myshares,dp->hand.sharenrs[pangea_ind(dp->table,hn->client->H.slot)],dp->M,(void *)buf,dp->numcards,dp->N); } else if ( strcmp(cmdstr,"final") == 0 ) memcpy(dp->hand.final,buf,sizeof(*dp->hand.final) * dp->N * dp->numcards); else if ( strcmp(cmdstr,"decode") == 0 ) { if ( (card= cards777_checkcard(&cardpriv,cardi,pangea_ind(dp->table,hn->client->H.slot),destplayer,hn->client->H.privkey,dp->hand.cardpubs,dp->numcards,*(bits256 *)buf)) >= 0 ) printf("ERROR: player.%d got card.[%d]\n",hn->client->H.slot,card); printf("deprecated incards, change to audits\n"); //memcpy(&priv->incards[cardi*dp->N + destplayer],buf,sizeof(bits256)); } else if ( strcmp(cmdstr,"card") == 0 ) { if ( (card= cards777_checkcard(&cardpriv,cardi,pangea_ind(dp->table,hn->client->H.slot),destplayer,hn->client->H.privkey,dp->hand.cardpubs,dp->numcards,*(bits256 *)buf)) >= 0 ) { //printf("player.%d got card.[%d]\n",hn->client->H.slot,card); printf("deprecated incards, change to audits\n"); //memcpy(&priv->incards[cardi*dp->N + destplayer],cardpriv.bytes,sizeof(bits256)); } else printf("ERROR player.%d got no card\n",hn->client->H.slot); } else if ( strcmp(cmdstr,"facedown") == 0 ) { //printf("player.%d sees that destplayer.%d got card\n",hn->client->H.slot,destplayer); } else if ( strcmp(cmdstr,"faceup") == 0 ) { if ( revealed < 0 || revealed != buf[1] ) printf(">>>>>>>>>>>>>>> ERROR "); //printf("player.%d was REVEALED.[%d] (%s) cardi.%d\n",hn->client->H.slot,buf[1],hexstr,cardi); dp->hand.community[cardi - 2*dp->N] = buf[1]; } else if ( strcmp(cmdstr,"showdown") == 0 ) { if ( (handstr= jstr(json,"hand")) != 0 ) { rank = set_handstr(tmp,buf,0); if ( strcmp(handstr,tmp) != 0 || rank != juint(json,"rank") ) printf("checkhand.(%s) != (%s) || rank.%u != %u\n",tmp,handstr,rank,juint(json,"rank")); else { //printf("sender.%d (%s) (%d %d)\n",senderslot,handstr,buf[5],buf[6]); dp->hand.handranks[senderslot] = rank; memcpy(dp->hand.hands[senderslot],buf,7); dp->hand.handmask |= (1 << senderslot); if ( dp->hand.handmask == (1 << dp->N)-1 ) { bestj = 0; bestrank = dp->hand.handranks[0]; for (j=1; jN; j++) if ( dp->hand.handranks[j] > bestrank ) { bestrank = dp->hand.handranks[j]; bestj = j; } rank = set_handstr(tmp,dp->hand.hands[bestj],0); if ( rank == bestrank ) { for (j=0; jN; j++) { rank = set_handstr(tmp,dp->hand.hands[j],0); if ( tmp[strlen(tmp)-1] == ' ' ) tmp[strlen(tmp)-1] = 0; printf("%14s|",tmp[0]!=' '?tmp:tmp+1); //printf("(%2d %2d).%d ",dp->hands[j][5],dp->hands[j][6],(int32_t)dp->balances[j]); } rank = set_handstr(tmp,dp->hand.hands[bestj],0); printf("deprecated\n"); /*dp->balances[bestj] += 3; printf("->P%d $%-5lld %s N%d p%d $%d\n",bestj,(long long)dp->balances[bestj],tmp,dp->numhands,hn->client->H.slot,(int32_t)dp->balances[pangea_ind(dp->table,hn->client->H.slot)]);*/ } else printf("bestrank.%u mismatch %u\n",bestrank,rank); } //printf("player.%d got rank %u (%s) from %d\n",hn->client->H.slot,rank,handstr,senderslot); } } } } retval = 0; } } else printf("NXT.%llu data mismatch %08x [%llx] vs [%llx] %08x len.%d (%s)\n",(long long)acct777_nxt64bits(hn->client->H.pubkey),_crc32(0,data,len),*(long long *)data,*(long long *)buf,_crc32(0,buf,len),len,jsonstr); } else printf("NXT.%llu invalid hexstr.%p %ld %d\n",(long long)acct777_nxt64bits(hn->client->H.pubkey),jsonstr,hexstr!=0?(long)strlen(hexstr):0,len); free_json(json); } else printf("NXT.%llu cant parse.(%s)\n",(long long)acct777_nxt64bits(hn->client->H.pubkey),jsonstr); free_queueitem(jsonstr); break; } usleep(1); } if ( i == maxmicro ) printf("NXT.%llu timeout.%d\n",(long long)acct777_nxt64bits(hn->client->H.pubkey),i); else { static uint64_t sum,count,max; sum += (i+1); count++; if ( i > max ) max = i; if ( (count % 10000) == 9999 ) printf("us.%-6d completed | ave %.1f %llu max.%llu errs.%d\n",i,(double)sum/count,(long long)count,(long long)max,errs); } if ( retval != 0 ) errs++; return(retval); } int32_t hostnet777_testresult(struct hostnet777_server *srv,struct hostnet777_client **clients,int32_t numclients,union hostnet777 *src,union hostnet777 *dest,int32_t blind,uint8_t *data,int32_t len,void *buf,int32_t revealed) { uint64_t senderbits; uint32_t timestamp,maxmicro = 100000; int32_t i,n,retval = -1; union hostnet777 hn; if ( dest != 0 && dest->client != 0 ) { //printf("PM call block on %d %llu\n",dest->client->H.slot,(long long)dest->client->H.nxt64bits); if ( hostnet777_block(srv,&senderbits,×tamp,dest,data,len,buf,maxmicro,blind,revealed) == 0 ) retval = 0; } else if ( dest == 0 || dest->client == 0 ) { if ( dest == 0 ) dest = &hn, dest->server = 0; for (i=n=0; iserver = srv; else dest->client = clients[i]; //printf("broadcast call block on %d %llu\n",i,(long long)dest->client->H.nxt64bits); if ( hostnet777_block(srv,&senderbits,×tamp,dest,data,len,buf,maxmicro,blind,revealed) == 0 ) n++;//, printf("verified.%d\n",i); } if ( n == numclients ) retval = 0; } if ( retval != 0 ) { for (i=1; iH.nxt64bits); printf("<<<<<<<<<<<<<<< srv.%llu ERROR.(%s)\n\n",(long long)srv->H.nxt64bits,(char *)buf); }// else printf("<<<<<<<<<<<<<<< PASS\n\n"); return(retval); } int32_t hostnet777_testiter(struct hostnet777_server *srv,struct hostnet777_client **clients,int32_t numclients,int32_t mode,int32_t iter) { int32_t s,d,blindflag,len,n,i,j,k,hexlen,cardi,destplayer,revealed,retval = -1; uint32_t rank; cJSON *json; union hostnet777 src,dest; uint64_t srcbits; char *cmdstr,*hex,pubstr[52*9*64+1],nrs[512],handstr[128]; uint8_t data[32768]; struct cards777_privdata *priv; struct cards777_pubdata *dp; bits256 destpub,card,seed; hex = malloc(sizeof(data) * 3 + 1024); revealed = -1; rank = pubstr[0] = nrs[0] = handstr[0] = 0; if ( mode == 0 ) { cmdstr = "test"; cardi = destplayer = -1; if ( (s= (rand() % numclients)) == 0 ) src.server = srv; else src.client = clients[s]; i = s; srcbits = src.client->H.nxt64bits; if ( (d= (rand() % (numclients+1))) == 0 ) dest.server = srv, destpub = srv->H.pubkey; else if ( d < numclients ) dest.client = clients[d], destpub = clients[d]->H.pubkey; else dest.client = 0; if ( (blindflag = ((rand() & 256) != 0)) != 0 ) srcbits = 0; len = (rand() % (sizeof(data)-10)) + 10; randombytes(data,len); } else { blindflag = 0; cardi = destplayer = -1; if ( (i= iter) < numclients ) { dp = srv->clients[i].pubdata; priv = srv->clients[i].privdata; if ( i < numclients-1 ) { if ( iter == 0 ) { printf("deprecated\n"); exit(1); /*bits256 playerpubs[CARDS777_MAXPLAYERS]; for (i=0; iN; i++) playerpubs[i] = *dp->playerpubs[i]; dp->hand.checkprod = cards777_initdeck(priv->outcards,dp->hand.cardpubs,dp->numcards,dp->N,playerpubs,0);*/ cmdstr = "pubstr"; srcbits = srv->H.nxt64bits; len = dp->numcards*sizeof(bits256); sprintf(hex,"{\"cmd\":\"%s\",\"cardi\":%d,\"dest\":%d,\"sender\":\"%llu\",\"timestamp\":\"%lu\",\"n\":%u,\"data\":\"",cmdstr,cardi,destplayer,(long long)srcbits,(long)time(NULL),len); n = (int32_t)strlen(hex); memcpy(data,dp->hand.cardpubs,len); init_hexbytes_noT(&hex[n],data,len); strcat(hex,"\"}"); hexlen = (int32_t)strlen(hex)+1; dest.client = 0, memset(destpub.bytes,0,sizeof(destpub)); src.server = srv; hostnet777_msg(0,destpub,&src,blindflag,hex,hexlen); hostnet777_testresult(srv,clients,numclients,&src,&dest,blindflag,data,len,hex,revealed); } j = i+1, cmdstr = "encode"; } else j = -1, cmdstr = "final"; len = sizeof(bits256) * dp->N * dp->numcards; memcpy(data,priv->outcards,len); } else { cardi = (iter / numclients) - 1; dp = srv->clients[0].pubdata; destplayer = ((cardi + dp->button) % numclients); if ( cardi < numclients*2 + 5 ) { i = (numclients - 1) - (iter % numclients); if ( i > 1 ) j = i - 1, cmdstr = "decode"; else if ( i == 1 ) j = destplayer, cmdstr = "card"; else //if ( i == 0 ) { j = -1; i = destplayer; if ( cardi < numclients*2 ) cmdstr = "facedown"; else cmdstr = "faceup"; } } else { j = -1; i = (iter % numclients); cmdstr = "showdown"; } dp = srv->clients[i].pubdata; priv = srv->clients[i].privdata; if ( strcmp(cmdstr,"showdown") == 0 ) { len = 7; for (k=0; k<5; k++) data[k] = dp->hand.community[k]; data[k++] = priv->hole[0]; data[k++] = priv->hole[1]; rank = set_handstr(handstr,data,0); } else { card = priv->audits[(cardi*numclients + destplayer) * numclients]; if ( j >= 0 ) card = cards777_decode(&seed,priv->xoverz,destplayer,card,priv->outcards,dp->numcards,numclients); else { if ( strcmp(cmdstr,"facedown") == 0 ) { priv->hole[cardi / numclients] = card.bytes[1]; priv->holecards[cardi / numclients] = card; memset(card.bytes,0,sizeof(card)); } else { revealed = card.bytes[1]; //printf("cmd.%s player.%d %llx (cardi.%d destplayer.%d) card.[%d]\n",cmdstr,i,(long long)card.txid,cardi,destplayer,card.bytes[1]); } } len = sizeof(bits256); memcpy(data,card.bytes,len); } } //printf("iter.%d i.%d cardi.%d destplayer.%d j.%d\n",iter,i,cardi,destplayer,j); if ( i == 0 ) src.server = srv; else src.client = clients[i]; dp = srv->clients[i].pubdata; priv = srv->clients[i].privdata; if ( j < 0 ) dest.client = 0; else if ( j == 0 ) dest.server = srv, destpub = srv->H.pubkey; else dest.client = clients[j], destpub = clients[j]->H.pubkey; srcbits = src.client->H.nxt64bits; } sprintf(hex,"{\"cmd\":\"%s\",\"myslot\":%d,\"hand\":\"%s\",\"rank\":%u,\"cardi\":%d,\"dest\":%d,\"sender\":\"%llu\",\"timestamp\":\"%lu\",\"pubstr\":\"%s\",\"nrs\":\"%s\",\"n\":%u,\"data\":\"",cmdstr,i,handstr,rank,cardi,destplayer,(long long)srcbits,(long)time(NULL),pubstr,nrs,len); n = (int32_t)strlen(hex); init_hexbytes_noT(&hex[n],data,len); //printf("hex.%p n.%d len.%d\n",hex,n,len); strcat(hex,"\"}"); //printf("HEX.[%s]\n",hex); if ( (json= cJSON_Parse(hex)) == 0 ) { printf("error creating json\n"); free(hex); return(-1); } free_json(json); hexlen = (int32_t)strlen(hex)+1; hostnet777_msg(dest.client == 0 ? 0 : dest.client->H.nxt64bits,destpub,&src,blindflag,hex,hexlen); //printf("d.%d %p, s.%d %p len.%d blind.%d | dest.%p src.%p srv.%p | crc %08x\n",d,dest.client,s,src.client,len,blindflag,&dest,&src,srv,_crc32(0,hex,hexlen)); retval = hostnet777_testresult(srv,clients,numclients,&src,&dest,blindflag,data,len,hex,revealed); free(hex); return(retval); } void hostnet777_test(int32_t numclients,int32_t numiters,int32_t mode) { void *portable_thread_create(void *funcp,void *argp); int32_t i,slot,modval,errs = 0; union hostnet777 *hn; struct hostnet777_server *srv; bits256 srvpubkey,srvprivkey,pubkey,privkey; struct hostnet777_client **clients; uint32_t starttime; uint64_t addrs[64]; struct cards777_pubdata *dp; srvprivkey = curve25519_keypair(&srvpubkey); if ( (srv= hostnet777_server(srvprivkey,srvpubkey,0,0,0,numclients)) == 0 ) { printf("cant create hostnet777 server\n"); return; } hn = calloc(1,sizeof(*hn)); hn->server = srv; if ( portable_thread_create((void *)hostnet777_idler,hn) == 0 ) printf("error launching server thread\n"); clients = calloc(numclients+1,sizeof(*clients)); for (i=1; i<=numclients; i++) // generate one error { privkey = curve25519_keypair(&pubkey); if ( (slot= hostnet777_register(srv,pubkey,-1)) >= 0 ) { if ( (clients[i]= hostnet777_client(privkey,pubkey,srv->ep.endpoint,slot)) == 0 ) printf("error creating clients[%d]\n",i); else { hn = calloc(1,sizeof(*hn)); hn->client = clients[i]; clients[i]->H.pubdata = cards777_allocpub((numclients >> 1) + 1,52,numclients); //dp->addrs = addrs; printf("slot.%d client.%p -> hn.%p %llu pubkey.%llx\n",slot,clients[i],hn,(long long)clients[i]->H.nxt64bits,(long long)clients[i]->H.pubkey.txid); if ( portable_thread_create((void *)hostnet777_idler,hn) == 0 ) printf("error launching clients[%d] thread\n",i); } } else { printf("hostnet777_test: error creating client.%d\n",i); break; } //printf("iter.%d server.%p: %d %d\n",i,srv,srv->pullsock,srv->pubsock); //printf("client sendmsg.%d [%p] (%d %d %d)\n",clients[i]->H.slot,clients[i],clients[i]->pushsock,clients[i]->subsock,clients[i]->my.pmsock); } dp = srv->H.pubdata = cards777_allocpub((numclients >> 1) + 1,52,numclients); //dp->addrs = addrs; addrs[0] = srv->H.nxt64bits; for (i=1; iH.nxt64bits; if ( mode != 0 ) cards777_testinit(srv,numclients/2+1,clients,numclients,52); printf("srv.%p %llu M.%d N.%d\n",srv,(long long)srv->H.nxt64bits,numclients/2+1,numclients); if ( i >= numclients ) { starttime = (uint32_t)time(NULL); modval = (numclients + numclients * (numclients*2 + 5 + 1)); for (i=0; iH.pubkey,-1); hostnet777_freeclient(clients[slot]); } } free(clients); hostnet777_freeserver(srv); } #endif #endif