You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1233 lines
56 KiB

/******************************************************************************
* 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 <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <memory.h>
#include <time.h>
#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 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; i<srv->max; 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; i<srv->max; 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<len; i++)
// dest[i] = 0;
memset(dest,0,len);
len <<= 3;
for (i=0; i<len; i++)
if ( GETBIT(src,i) != 0 )
SETBIT(dest,i);
return(len >> 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,&timestamp,&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; i<len-crypto_box_ZEROBYTES; i++)
str[i] = str[i+crypto_box_ZEROBYTES];
*lenp = len - crypto_box_ZEROBYTES;
} else memcpy(str,cipher,len);
return(err);
}
int32_t hostnet777_decrypt(bits256 *senderpubp,uint64_t *senderbitsp,uint32_t *timestampp,bits256 mypriv,bits256 mypub,uint8_t *dest,int32_t maxlen,uint8_t *src,int32_t len)
{
bits256 seed,sig,msgpriv; uint64_t my64bits,destbits,senderbits,sendertmp,desttmp;
uint8_t *buf; int32_t hdrlen,i,diff,newlen = -1; HUFF H,*hp = &H; struct acct777_sig checksig;
*senderbitsp = 0;
my64bits = acct777_nxt64bits(mypub);
if ( (buf = calloc(1,maxlen)) == 0 )
{
printf("hostnet777_decrypt cant allocate maxlen.%d\n",maxlen);
return(-1);
}
hdrlen = hostnet777_serialize(1,senderpubp,&senderbits,&sig,timestampp,&destbits,src);
if ( destbits != 0 && my64bits != destbits && destbits != acct777_nxt64bits(GENESIS_PUBKEY) )
{
free(buf);
printf("hostnet777_decrypt received destination packet.%llu when my64bits.%llu len.%d\n",(long long)destbits,(long long)my64bits,len);
return(-1);
}
if ( memcmp(mypub.bytes,senderpubp->bytes,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<n; i++)
{
if ( hashes[i] == 0 && firsti < 0 )
firsti = i;
if ( hash.txid == hashes[i] )
{
printf("filter duplicate msg %llx\n",(long long)hash.txid);
return(i);
}
}
if ( firsti >= 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,&timestamp,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; slot<hn->server->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; slot<srv->max; 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; i<srv->max; 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; ind<srv->max; 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; i<maxclients; i++)
srv->clients[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; threadid<num; threadid++)
{
pubkey = acct777_pubkey(privkeys[threadid]);
if ( threadid == 0 )
{
if ( (srv= hostnet777_server(privkeys[threadid],pubkey,0,0,0,num)) == 0 )
{
printf("cant create hostnet777 server\n");
return(-1);
}
hn[0].server = srv;
srv->H.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; i<maxmicro; i++)
{
if ( (jsonstr= queue_dequeue(&hn->client->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; j<dp->N; 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; j<dp->N; 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,&timestamp,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; i<numclients; i++)
{
if ( i == 0 )
dest->server = 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,&timestamp,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; i<numclients; i++)
printf("%llu ",(long long)clients[i]->H.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; i<dp->N; 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; i<numclients; i++)
if ( clients[i] != 0 )
addrs[i] = clients[i]->H.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; i<numiters; i++)
errs += hostnet777_testiter(srv,clients,numclients,mode,i % modval);
printf("hostnet777 numerrs %d of %d | %ld seconds, ave %.3f millis\n",errs,numiters,(long)(time(NULL) - starttime),1000. * (double)(time(NULL) - starttime)/numiters);
}
for (slot=1; slot<numclients; slot++)
{
if ( clients[slot] != 0 )
{
hostnet777_register(srv,clients[slot]->H.pubkey,-1);
hostnet777_freeclient(clients[slot]);
}
}
free(clients);
hostnet777_freeserver(srv);
}
#endif
#endif