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.
436 lines
18 KiB
436 lines
18 KiB
/******************************************************************************
|
|
* Copyright © 2014-2016 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. *
|
|
* *
|
|
******************************************************************************/
|
|
|
|
#include "pangea777.h"
|
|
|
|
struct pangeanet777_id *pangeanet777_find(struct pangeanet777_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 pangeanet777_lastcontact(struct pangeanet777_server *srv,bits256 senderpub)
|
|
{
|
|
struct pangeanet777_id *ptr;
|
|
if ( (ptr= pangeanet777_find(srv,senderpub)) != 0 )
|
|
ptr->lastcontact = (uint32_t)time(NULL);
|
|
}
|
|
|
|
void pangeanet777_processmsg(uint64_t *destbitsp,bits256 *senderpubp,queue_t *Q,bits256 mypriv,bits256 mypub,uint8_t *msg,int32_t origlen,int32_t pmflag)
|
|
{
|
|
char *jsonstr = 0; bits256 sig; uint32_t timestamp; int32_t len; uint64_t senderbits; 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= SuperNET_decrypt(senderpubp,&senderbits,×tamp,mypriv,mypub,&ptr[sizeof(struct queueitem)],len*4,msg,len)) > 1 && len < len*4 )
|
|
{
|
|
senderbits = timestamp = len = 0;
|
|
jsonstr = (char *)&ptr[sizeof(struct queueitem)];
|
|
if ( (json= cJSON_Parse(jsonstr)) != 0 )
|
|
{
|
|
//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);
|
|
}
|
|
|
|
int32_t pangeanet777_idle(union pangeanet777 *hn)
|
|
{
|
|
int32_t len=0,slot,n = 0; bits256 senderpub,mypriv,mypub; uint64_t destbits; uint8_t *msg=0;
|
|
//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 )
|
|
{
|
|
SuperNET_copybits(1,msg,(void *)&destbits,sizeof(uint64_t));
|
|
//printf("client got pub len.%d\n",len);
|
|
if ( destbits == 0 || destbits == hn->client->H.nxt64bits )
|
|
pangeanet777_processmsg(&destbits,&senderpub,&hn->client->H.Q,mypriv,mypub,msg,len,0), 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());
|
|
//f ( (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);
|
|
SuperNET_copybits(1,msg,(void *)&destbits,sizeof(uint64_t));
|
|
if ( destbits == 0 || destbits == hn->server->H.nxt64bits )
|
|
{
|
|
pangeanet777_processmsg(&destbits,&senderpub,&hn->server->H.Q,mypriv,mypub,msg,len,1);
|
|
pangeanet777_lastcontact(hn->server,senderpub);
|
|
}
|
|
printf("pangeanet777_idle: do the send here\n");
|
|
//pangeanet777_send(hn->server->pubsock,msg,len);
|
|
//nn_freemsg(msg);
|
|
}
|
|
}
|
|
if ( hn->server->H.pollfunc != 0 )
|
|
(*hn->server->H.pollfunc)(hn);
|
|
}
|
|
return(n);
|
|
}
|
|
|
|
int32_t pangeanet777_replace(struct pangeanet777_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 )
|
|
{
|
|
printf("pangeanet777_replace deal with getting new socket here\n");
|
|
//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 pangeanet777_register(struct pangeanet777_server *srv,bits256 clientpub,int32_t slot)
|
|
{
|
|
int32_t i,n; struct pangeanet777_id *ptr;
|
|
if ( slot < 0 )
|
|
{
|
|
if ( (ptr= pangeanet777_find(srv,clientpub)) != 0 )
|
|
{
|
|
slot = (int32_t)(((long)ptr - (long)srv->clients) / sizeof(*srv->clients));
|
|
//printf("pangea_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("pangea_register: cant register anymore num.%d vs max.%d\n",srv->num,srv->max);
|
|
return(-1);
|
|
}
|
|
if ( (ptr= pangeanet777_find(srv,clientpub)) != 0 )
|
|
{
|
|
printf("pangea_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("pangea_register: cant register slot.%d vs num.%d vs max.%d\n",slot,srv->num,srv->max);
|
|
return(-1);
|
|
}
|
|
pangeanet777_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 pangeanet777_client *pangeanet777_client(bits256 privkey,bits256 pubkey,char *srvendpoint,int32_t slot)
|
|
{
|
|
char endbuf[128],endbuf2[128]; uint16_t port; struct pangeanet777_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);
|
|
printf("pangeanet777_client: deal with creating connections here\n");
|
|
//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 pangeanet777_freeclient(struct pangeanet777_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 pangeanet777_freeserver(struct pangeanet777_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 pangeanet777_server *pangeanet777_server(bits256 srvprivkey,bits256 srvpubkey,char *transport,char *ipaddr,uint16_t port,int32_t maxclients)
|
|
{
|
|
struct pangeanet777_server *srv; int32_t i; struct pangeanet777_endpoint *ep; char buf[128];
|
|
srv = calloc(1,sizeof(*srv) + maxclients*sizeof(struct pangeanet777_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);
|
|
printf("pangeanet777_server: create socket here\n");
|
|
//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 *pangeanet777_idler(union pangeanet777 *ptr)
|
|
{
|
|
while ( ptr->client->H.done == 0 )
|
|
{
|
|
if ( pangeanet777_idle(ptr) == 0 )
|
|
usleep(1000);
|
|
}
|
|
//printf("pangea_idler ind.%d done\n",ptr->client->H.slot);
|
|
sleep(1);
|
|
free(ptr);
|
|
return(0);
|
|
}
|
|
|
|
int32_t SuperNET_sendmsg(struct supernet_info *myinfo,struct iguana_info *coin,struct iguana_peer *addr,bits256 destpub,bits256 mypriv,bits256 mypub,uint8_t *msg,int32_t len,uint8_t *data,int32_t delaymillis);
|
|
|
|
#define pangeanet777_broadcast(mypriv,mypub,msg,len) SuperNET_sendmsg(myinfo,coin,addr,zeropoint,mypriv,mypub,msg,len,space,0)
|
|
#define pangeanet777_blindcast(msg,len) SuperNET_sendmsg(myinfo,coin,addr,zeropoint,zeropoint,zeropoint,msg,len,space,0)
|
|
#define pangeanet777_signedPM(destpub,mypriv,mypub,msg,len) SuperNET_sendmsg(myinfo,coin,addr,destpub,mypriv,mypub,msg,len,space,0)
|
|
#define pangeanet777_blindPM(destpub,msg,len) SuperNET_sendmsg(myinfo,coin,addr,destpub,zeropoint,zeropoint,msg,len,space,0)
|
|
void pangeanet777_msg(uint64_t destbits,bits256 destpub,union pangeanet777 *src,int32_t blindflag,char *jsonstr,int32_t len)
|
|
{
|
|
/*static bits256 zeropoint;
|
|
struct supernet_info *myinfo = SuperNET_MYINFO(0); uint8_t *space;
|
|
struct iguana_peer *addr = 0; struct iguana_info *coin = iguana_coinfind("BTCD");
|
|
if ( destbits == 0 )
|
|
{
|
|
//printf(">>>>>>>>> blind.%d broadcast from %llu, len.%d\n",blindflag,(long long)src->client->H.nxt64bits,len);
|
|
space = calloc(1,IGUANA_MAXPACKETSIZE);
|
|
if ( blindflag != 0 )
|
|
pangeanet777_blindcast((uint8_t *)jsonstr,len);
|
|
else pangeanet777_broadcast(src->client->H.privkey,src->client->H.pubkey,(uint8_t *)jsonstr,len);
|
|
free(space);
|
|
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);
|
|
space = calloc(1,IGUANA_MAXPACKETSIZE);
|
|
if ( blindflag != 0 )
|
|
pangeanet777_blindPM(destpub,(uint8_t *)jsonstr,len);
|
|
else pangeanet777_signedPM(destpub,src->client->H.privkey,src->client->H.pubkey,(uint8_t *)jsonstr,len);
|
|
free(space);
|
|
}
|
|
else queue_enqueue("loopback",&src->client->H.Q,queueitem(jsonstr),1);*/
|
|
}
|
|
|
|
int32_t pangea_search(struct pangea_info *sp,uint64_t nxt64bits)
|
|
{
|
|
int32_t i;
|
|
for (i=0; i<sp->numactive; i++)
|
|
if ( sp->active[i] == nxt64bits )
|
|
return(i);
|
|
for (i=0; i<sp->numactive; i++)
|
|
PNACL_message("%llu ",(long long)sp->active[i]);
|
|
PNACL_message("active[]\n");
|
|
for (i=0; i<sp->numaddrs; i++)
|
|
PNACL_message("%llu ",(long long)sp->addrs[i]);
|
|
PNACL_message("addrs[]\n");
|
|
PNACL_message("pangea_search: slot.%d ind.%d cant find %llu in active[%d]\n",sp->myslot,sp->myind,(long long)nxt64bits,sp->numactive);
|
|
return(-1);
|
|
}
|
|
|
|
int32_t pangea_tableaddr(struct cards777_pubdata *dp,uint64_t destbits)
|
|
{
|
|
int32_t i; struct pangea_info *sp;
|
|
if ( dp != 0 && (sp= dp->table) != 0 )
|
|
{
|
|
for (i=0; i<sp->numaddrs; i++)
|
|
if ( sp->addrs[i] == destbits )
|
|
return(i);
|
|
}
|
|
return(-1);
|
|
}
|
|
|
|
int32_t pangea_addplayer(struct cards777_pubdata *dp,struct pangea_info *sp,bits256 clientpub)
|
|
{
|
|
int32_t i,n,openslot = -1; uint64_t nxt64bits = acct777_nxt64bits(clientpub);
|
|
for (i=n=0; i<sp->numaddrs; i++)
|
|
{
|
|
if ( sp->addrs[i] == nxt64bits )
|
|
{
|
|
PNACL_message("pangea_addplayer: player %llu already in addrs[%d]\n",(long long)nxt64bits,i);
|
|
return(-1);
|
|
}
|
|
if ( sp->balances[i] <= 0 )
|
|
openslot = i;
|
|
}
|
|
if ( openslot < 0 || sp->numactive >= sp->numaddrs-1 )
|
|
{
|
|
PNACL_message("pangea_addplayer: no room to add %llu\n",(long long)nxt64bits);
|
|
return(-1);
|
|
}
|
|
dp->readymask &= ~(1 << openslot);
|
|
sp->addrs[openslot] = nxt64bits;
|
|
sp->playerpubs[openslot] = clientpub;
|
|
sp->active[sp->numactive++] = nxt64bits;
|
|
if ( sp->myslot == 0 )
|
|
{
|
|
uint64_t isbot[CARDS777_MAXPLAYERS]; char *retbuf = malloc(65536);
|
|
if ( retbuf != 0 )
|
|
{
|
|
pangeanet777_replace(sp->tp->hn.server,clientpub,openslot);
|
|
for (i=0; i<sp->numactive; i++)
|
|
isbot[i] = sp->isbot[i];
|
|
pangea_create_newtable(retbuf,sp,dp,isbot);
|
|
pangeanet777_msg(nxt64bits,clientpub,&sp->tp->hn,0,retbuf,(int32_t)strlen(retbuf)+1);
|
|
free(retbuf);
|
|
}
|
|
}
|
|
pangea_neworder(dp,sp,0,0);
|
|
return(n);
|
|
}
|
|
|
|
bits256 pangea_destpub(uint64_t destbits)
|
|
{
|
|
int32_t i,haspubkey; bits256 destpub; char destNXT[64];
|
|
memset(destpub.bytes,0,sizeof(destpub));
|
|
for (i=0; i<sizeof(TABLES)/sizeof(*TABLES); i++)
|
|
if ( TABLES[i] != 0 && TABLES[i]->tp->nxt64bits == destbits )
|
|
{
|
|
destpub = TABLES[i]->tp->hn.client->H.pubkey;
|
|
break;
|
|
}
|
|
if ( i == sizeof(TABLES)/sizeof(*TABLES) )
|
|
{
|
|
expand_nxt64bits(destNXT,destbits);
|
|
destpub = issue_getpubkey(&haspubkey,destNXT);
|
|
}
|
|
return(destpub);
|
|
}
|
|
|
|
struct pangea_info *pangea_find(uint64_t tableid,int32_t threadid)
|
|
{
|
|
int32_t i;
|
|
for (i=0; i<sizeof(TABLES)/sizeof(*TABLES); i++)
|
|
if ( TABLES[i] != 0 && tableid == TABLES[i]->tableid && (threadid < 0 || TABLES[i]->tp->threadid == threadid) )
|
|
return(TABLES[i]);
|
|
return(0);
|
|
}
|
|
|
|
struct pangea_info *pangea_find64(uint64_t tableid,uint64_t nxt64bits)
|
|
{
|
|
int32_t i,j;
|
|
for (i=0; i<sizeof(TABLES)/sizeof(*TABLES); i++)
|
|
{
|
|
if ( TABLES[i] != 0 && (tableid == 0 || tableid == TABLES[i]->tableid) && TABLES[i]->tp != 0 )
|
|
{
|
|
for (j=0; j<TABLES[i]->numaddrs; j++)
|
|
{
|
|
if ( TABLES[i]->addrs[j] == nxt64bits )
|
|
return(TABLES[i]);
|
|
}
|
|
}
|
|
}
|
|
return(0);
|
|
}
|
|
|
|
void pangea_free(struct pangea_info *sp)
|
|
{
|
|
int32_t i;
|
|
for (i=0; i<sizeof(TABLES)/sizeof(*TABLES); i++)
|
|
if ( TABLES[i] == sp )
|
|
{
|
|
TABLES[i] = 0;
|
|
break;
|
|
}
|
|
PNACL_message("PANGEA PURGE %llu\n",(long long)sp->tableid);
|
|
free(sp);
|
|
}
|
|
|
|
|