|
|
@ -23,52 +23,291 @@ |
|
|
|
#include "../pnacl_main.h" |
|
|
|
#include "SuperNET.h" |
|
|
|
|
|
|
|
#ifndef MSG_NOSIGNAL |
|
|
|
#define MSG_NOSIGNAL 0x4000 // Do not generate SIGPIPE
|
|
|
|
#endif |
|
|
|
|
|
|
|
// ALL globals must be here!
|
|
|
|
int32_t PULLsock; |
|
|
|
|
|
|
|
|
|
|
|
int32_t badass_servers(char servers[][MAX_SERVERNAME],int32_t max,int32_t port) |
|
|
|
{ |
|
|
|
int32_t n = 0; |
|
|
|
strcpy(servers[n++],"89.248.160.237"); |
|
|
|
strcpy(servers[n++],"89.248.160.238"); |
|
|
|
strcpy(servers[n++],"89.248.160.239"); |
|
|
|
strcpy(servers[n++],"89.248.160.240"); |
|
|
|
strcpy(servers[n++],"89.248.160.241"); |
|
|
|
strcpy(servers[n++],"89.248.160.242"); |
|
|
|
//strcpy(servers[n++],"89.248.160.243");
|
|
|
|
//strcpy(servers[n++],"89.248.160.244");
|
|
|
|
//strcpy(servers[n++],"89.248.160.245");
|
|
|
|
return(n); |
|
|
|
|
|
|
|
int32_t nn_typelist[] = { NN_REP, NN_REQ, NN_RESPONDENT, NN_SURVEYOR, NN_PUB, NN_SUB, NN_PULL, NN_PUSH, NN_BUS, NN_PAIR }; |
|
|
|
char *nn_transports[] = { "tcp", "ws", "ipc", "inproc", "tcpmux", "", "", "" }; |
|
|
|
|
|
|
|
void expand_epbits(char *endpoint,struct endpoint epbits) |
|
|
|
{ |
|
|
|
char ipaddr[64]; |
|
|
|
if ( epbits.ipbits != 0 ) |
|
|
|
expand_ipbits(ipaddr,epbits.ipbits); |
|
|
|
else strcpy(ipaddr,"*"); |
|
|
|
sprintf(endpoint,"%s://%s:%d",nn_transports[epbits.transport],ipaddr,epbits.port); |
|
|
|
} |
|
|
|
|
|
|
|
int32_t crackfoo_servers(char servers[][MAX_SERVERNAME],int32_t max,int32_t port) |
|
|
|
struct endpoint calc_epbits(char *transport,uint32_t ipbits,uint16_t port,int32_t type) |
|
|
|
{ |
|
|
|
int32_t n = 0; |
|
|
|
/*strcpy(servers[n++],"192.99.151.160");
|
|
|
|
strcpy(servers[n++],"167.114.96.223"); |
|
|
|
strcpy(servers[n++],"167.114.113.197"); |
|
|
|
strcpy(servers[n++],"5.9.105.170"); |
|
|
|
strcpy(servers[n++],"136.243.5.70"); |
|
|
|
strcpy(servers[n++],"5.9.155.145");*/ |
|
|
|
if ( 1 ) |
|
|
|
int32_t i; struct endpoint epbits; |
|
|
|
memset(&epbits,0,sizeof(epbits)); |
|
|
|
for (i=0; i<(int32_t)(sizeof(nn_transports)/sizeof(*nn_transports)); i++) |
|
|
|
if ( strcmp(transport,nn_transports[i]) == 0 ) |
|
|
|
{ |
|
|
|
epbits.ipbits = ipbits; |
|
|
|
epbits.port = port; |
|
|
|
epbits.transport = i; |
|
|
|
epbits.nn = type; |
|
|
|
break; |
|
|
|
} |
|
|
|
return(epbits); |
|
|
|
} |
|
|
|
|
|
|
|
int32_t ismyaddress(struct supernet_info *myinfo,char *server) |
|
|
|
{ |
|
|
|
uint32_t ipbits; int32_t i,tlen; char str[64]; |
|
|
|
for (i=0; i<sizeof(nn_transports)/sizeof(*nn_transports); i++) |
|
|
|
{ |
|
|
|
if ( nn_transports[i] == 0 ) |
|
|
|
break; |
|
|
|
sprintf(str,"%s://",nn_transports[i]); |
|
|
|
tlen = (int32_t)strlen(str); |
|
|
|
if ( strncmp(server,str,tlen) == 0 ) |
|
|
|
{ |
|
|
|
server += tlen; |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
if ( (ipbits= is_ipaddr(server)) != 0 ) |
|
|
|
{ |
|
|
|
if ( strcmp(server,myinfo->ipaddr) == 0 || myinfo->ipbits == ipbits ) |
|
|
|
{ |
|
|
|
printf("(%s) MATCHES me (%s)\n",server,myinfo->ipaddr); |
|
|
|
return(1); |
|
|
|
} |
|
|
|
} |
|
|
|
else if ( myinfo->my64bits == ipbits ) |
|
|
|
return(1); |
|
|
|
//printf("(%s) is not me (%s)\n",server,myipaddr);
|
|
|
|
return(0); |
|
|
|
} |
|
|
|
|
|
|
|
char *nn_typestr(int32_t type) |
|
|
|
{ |
|
|
|
switch ( type ) |
|
|
|
{ |
|
|
|
// Messages that need a response from the set of peers: SURVEY
|
|
|
|
case NN_SURVEYOR: return("NN_SURVEYOR"); break; |
|
|
|
case NN_RESPONDENT: return("NN_RESPONDENT"); break; |
|
|
|
// Messages that need a response, but only from one peer: REQ/REP
|
|
|
|
case NN_REQ: return("NN_REQ"); break; |
|
|
|
case NN_REP: return("NN_REP"); break; |
|
|
|
// One-way messages to one peer: PUSH/PULL
|
|
|
|
case NN_PUSH: return("NN_PUSH"); break; |
|
|
|
case NN_PULL: return("NN_PULL"); break; |
|
|
|
// One-way messages to all: PUB/SUB
|
|
|
|
case NN_PUB: return("NN_PUB"); break; |
|
|
|
case NN_SUB: return("NN_SUB"); break; |
|
|
|
case NN_BUS: return("NN_BUS"); break; |
|
|
|
case NN_PAIR: return("NN_PAIR"); break; |
|
|
|
} |
|
|
|
return("NN_ERROR"); |
|
|
|
} |
|
|
|
|
|
|
|
int32_t nn_oppotype(int32_t type) |
|
|
|
{ |
|
|
|
switch ( type ) |
|
|
|
{ |
|
|
|
// Messages that need a response from the set of peers: SURVEY
|
|
|
|
case NN_SURVEYOR: return(NN_RESPONDENT); break; |
|
|
|
case NN_RESPONDENT: return(NN_SURVEYOR); break; |
|
|
|
// Messages that need a response, but only from one peer: REQ/REP
|
|
|
|
case NN_REQ: return(NN_REP); break; |
|
|
|
case NN_REP: return(NN_REQ); break; |
|
|
|
// One-way messages to one peer: PUSH/PULL
|
|
|
|
case NN_PUSH: return(NN_PULL); break; |
|
|
|
case NN_PULL: return(NN_PUSH); break; |
|
|
|
// One-way messages to all: PUB/SUB
|
|
|
|
case NN_PUB: return(NN_SUB); break; |
|
|
|
case NN_SUB: return(NN_PUB); break; |
|
|
|
case NN_BUS: return(NN_BUS); break; |
|
|
|
case NN_PAIR: return(NN_PAIR); break; |
|
|
|
} |
|
|
|
return(-1); |
|
|
|
} |
|
|
|
|
|
|
|
int32_t nn_portoffset(int32_t type) |
|
|
|
{ |
|
|
|
int32_t i; |
|
|
|
for (i=0; i<(int32_t)(sizeof(nn_typelist)/sizeof(*nn_typelist)); i++) |
|
|
|
if ( nn_typelist[i] == type ) |
|
|
|
return(i + 2); |
|
|
|
return(-1); |
|
|
|
} |
|
|
|
|
|
|
|
int32_t nn_socket_status(int32_t nnsock,int32_t timeoutmillis) |
|
|
|
{ |
|
|
|
struct nn_pollfd pfd; |
|
|
|
int32_t rc; |
|
|
|
pfd.fd = nnsock; |
|
|
|
pfd.events = NN_POLLIN | NN_POLLOUT; |
|
|
|
if ( (rc= nn_poll(&pfd,1,timeoutmillis)) == 0 ) |
|
|
|
return(pfd.revents); |
|
|
|
else return(-1); |
|
|
|
} |
|
|
|
|
|
|
|
int32_t SuperNET_msglen(struct supernet_msghdr *msg) |
|
|
|
{ |
|
|
|
return(msg->serlen[0] + ((int32_t)msg->serlen[1] << 8) + ((int32_t)msg->serlen[2] << 16)); |
|
|
|
} |
|
|
|
|
|
|
|
int32_t SuperNET_msgvalidate(struct supernet_msghdr *msg) |
|
|
|
{ |
|
|
|
int32_t msglen = 0; |
|
|
|
msglen = SuperNET_msglen(msg); |
|
|
|
return(msglen); |
|
|
|
} |
|
|
|
|
|
|
|
char *SuperNET_JSON(struct supernet_info *myinfo,char *jsonstr) |
|
|
|
{ |
|
|
|
return(clonestr("{\"error\":\"SuperNET is just a stub for now\"}")); |
|
|
|
} |
|
|
|
|
|
|
|
int32_t nn_settimeouts(int32_t sock,int32_t sendtimeout,int32_t recvtimeout) |
|
|
|
{ |
|
|
|
int32_t retrymillis,maxmillis; |
|
|
|
if ( (maxmillis= SUPERNET_NETWORKTIMEOUT) == 0 ) |
|
|
|
maxmillis = 3000; |
|
|
|
retrymillis = maxmillis/40; |
|
|
|
if ( nn_setsockopt(sock,NN_SOL_SOCKET,NN_RECONNECT_IVL,&retrymillis,sizeof(retrymillis)) < 0 ) |
|
|
|
fprintf(stderr,"error setting NN_REQ NN_RECONNECT_IVL_MAX socket %s\n",nn_errstr()); |
|
|
|
else if ( nn_setsockopt(sock,NN_SOL_SOCKET,NN_RECONNECT_IVL_MAX,&maxmillis,sizeof(maxmillis)) < 0 ) |
|
|
|
fprintf(stderr,"error setting NN_REQ NN_RECONNECT_IVL_MAX socket %s\n",nn_errstr()); |
|
|
|
else if ( sendtimeout > 0 && nn_setsockopt(sock,NN_SOL_SOCKET,NN_SNDTIMEO,&sendtimeout,sizeof(sendtimeout)) < 0 ) |
|
|
|
fprintf(stderr,"error setting sendtimeout %s\n",nn_errstr()); |
|
|
|
else if ( recvtimeout > 0 && nn_setsockopt(sock,NN_SOL_SOCKET,NN_RCVTIMEO,&recvtimeout,sizeof(recvtimeout)) < 0 ) |
|
|
|
fprintf(stderr,"error setting sendtimeout %s\n",nn_errstr()); |
|
|
|
else return(0); |
|
|
|
return(-1); |
|
|
|
} |
|
|
|
|
|
|
|
int32_t nn_createsocket(struct supernet_info *myinfo,char *endpoint,int32_t bindflag,char *name,int32_t type,uint16_t port,int32_t sendtimeout,int32_t recvtimeout) |
|
|
|
{ |
|
|
|
int32_t sock; |
|
|
|
if ( (sock= nn_socket(AF_SP,type)) < 0 ) |
|
|
|
fprintf(stderr,"error getting socket %s\n",nn_errstr()); |
|
|
|
if ( bindflag != 0 ) |
|
|
|
{ |
|
|
|
if ( endpoint[0] == 0 ) |
|
|
|
expand_epbits(endpoint,calc_epbits(myinfo->transport,0,port,type)); |
|
|
|
if ( nn_bind(sock,endpoint) < 0 ) |
|
|
|
fprintf(stderr,"error binding to relaypoint sock.%d type.%d to (%s) (%s) %s\n",sock,type,name,endpoint,nn_errstr()); |
|
|
|
else fprintf(stderr,"BIND.(%s) <- %s\n",endpoint,name); |
|
|
|
} |
|
|
|
else if ( bindflag == 0 && endpoint != 0 && endpoint[0] != 0 ) |
|
|
|
{ |
|
|
|
if ( nn_connect(sock,endpoint) < 0 ) |
|
|
|
fprintf(stderr,"error connecting to relaypoint sock.%d type.%d to (%s) (%s) %s\n",sock,type,name,endpoint,nn_errstr()); |
|
|
|
else fprintf(stderr,"%s -> CONNECT.(%s)\n",name,endpoint); |
|
|
|
} |
|
|
|
if ( nn_settimeouts(sock,sendtimeout,recvtimeout) < 0 ) |
|
|
|
{ |
|
|
|
fprintf(stderr,"nn_createsocket.(%s) %d\n",name,sock); |
|
|
|
return(-1); |
|
|
|
} |
|
|
|
return(sock); |
|
|
|
} |
|
|
|
|
|
|
|
bits256 SuperNET_OPRETURN(struct supernet_info *myinfo,char *symbol,double fee,uint8_t *buf,int32_t len) |
|
|
|
{ |
|
|
|
bits256 txid; |
|
|
|
return(txid); |
|
|
|
} |
|
|
|
|
|
|
|
/*int32_t SuperNET_OPRETURN(uint8_t *data,char *announce)
|
|
|
|
{ |
|
|
|
static char *protocols[][2] = { {"pangea","GEA"}, {"peggy","PAX"} }; |
|
|
|
int32_t i; |
|
|
|
for (i=0; i<sizeof(protocols)/sizeof(*protocols); i++) |
|
|
|
{ |
|
|
|
if ( strcmp(protocols[i][0],announce) == 0 ) |
|
|
|
{ |
|
|
|
data[0] = SCRIPT_OPRETURN; |
|
|
|
memcpy(&data[1],protocols[i][1],3); |
|
|
|
return(4); |
|
|
|
} |
|
|
|
} |
|
|
|
return(0); |
|
|
|
}*/ |
|
|
|
|
|
|
|
bits256 SuperNET_agentannounce(struct supernet_info *myinfo,struct supernet_agent *agent,cJSON *network) |
|
|
|
{ |
|
|
|
static bits256 zero; |
|
|
|
uint8_t buf[80 + sizeof(struct iguana_msghdr)],*data; |
|
|
|
bits256 pubkey,sig; int32_t i,len=0; uint8_t netmagic[4]; char *sigstr,*announce,*pubkeystr; |
|
|
|
memset(buf,0,sizeof(buf)); |
|
|
|
data = &buf[sizeof(struct iguana_msghdr)]; |
|
|
|
if ( (announce= jstr(network,"announce")) != 0 ) |
|
|
|
{ |
|
|
|
strcpy(servers[n++],"167.114.96.223"); |
|
|
|
strcpy(servers[n++],"167.114.113.25"); |
|
|
|
strcpy(servers[n++],"167.114.113.27"); |
|
|
|
strcpy(servers[n++],"167.114.113.194"); |
|
|
|
strcpy(servers[n++],"167.114.113.197"); |
|
|
|
strcpy(servers[n++],"167.114.113.201"); |
|
|
|
strcpy(servers[n++],"167.114.113.246"); |
|
|
|
strcpy(servers[n++],"167.114.113.249"); |
|
|
|
strcpy(servers[n++],"167.114.113.250"); |
|
|
|
strcpy(servers[n++],"192.99.151.160"); |
|
|
|
strcpy(servers[n++],"167.114.96.222"); |
|
|
|
data[len++] = SCRIPT_OPRETURN; |
|
|
|
data[len++] = 75; |
|
|
|
iguana_rwnum(1,&data[len],sizeof(myinfo->ipbits),&myinfo->ipbits); |
|
|
|
for (i=0; i<7; i++) |
|
|
|
if ( (data[len+i]= announce[i]) == 0 ) |
|
|
|
break; |
|
|
|
len = 13; |
|
|
|
if ( (pubkeystr= jstr(network,"pubkey")) == 0 || strlen(pubkeystr) != sizeof(bits256)*2 ) |
|
|
|
pubkeystr = GENESIS_PUBKEYSTR; |
|
|
|
decode_hex(pubkey.bytes,sizeof(pubkey),pubkeystr); |
|
|
|
len += iguana_rwbignum(1,&data[len],sizeof(pubkey),pubkey.bytes); // 45 bytes
|
|
|
|
if ( (sigstr= jstr(network,"sig")) != 0 && strlen(sigstr) == sizeof(bits256)*2 ) |
|
|
|
{ |
|
|
|
sigstr = GENESIS_PUBKEYSTR; |
|
|
|
len += iguana_rwbignum(1,&data[len],sizeof(sig),sig.bytes); // 77 bytes
|
|
|
|
} |
|
|
|
decode_hex(netmagic,4,"e4c2d8e6"); |
|
|
|
iguana_sethdr((struct iguana_msghdr *)buf,netmagic,"SuperNET",data,len); |
|
|
|
return(SuperNET_OPRETURN(myinfo,"BTCD",.001,buf,len)); |
|
|
|
} |
|
|
|
printf("invalid SuperNET OPRETURN protocol.(%s)\n",announce!=0?announce:""); |
|
|
|
return(zero); |
|
|
|
} |
|
|
|
|
|
|
|
void Supernet_networkadd(struct supernet_info *myinfo,struct supernet_agent *agent,cJSON *network) |
|
|
|
{ |
|
|
|
int32_t sendtimeout=0,recvtimeout=0; |
|
|
|
agent->pubpoint[0] = agent->reppoint[0] = 0; |
|
|
|
if ( (agent->pubport= juint(network,"pubport")) > 1000 ) |
|
|
|
{ |
|
|
|
agent->pubsock = nn_createsocket(myinfo,agent->pubpoint,1,"NN_PUB",NN_PUB,agent->pubport,sendtimeout,recvtimeout); |
|
|
|
SuperNET_agentannounce(myinfo,agent,network); |
|
|
|
} |
|
|
|
else agent->pubport = -1; |
|
|
|
if ( (agent->repport= juint(network,"repport")) > 1000 ) |
|
|
|
agent->repsock = nn_createsocket(myinfo,agent->reppoint,1,"NN_REP",NN_REP,agent->repport,sendtimeout,recvtimeout); |
|
|
|
else agent->repport = -1; |
|
|
|
agent->subsock = nn_createsocket(myinfo,0,0,"NN_SUB",NN_SUB,0,sendtimeout,recvtimeout); |
|
|
|
nn_setsockopt(agent->subsock,NN_SUB,NN_SUB_SUBSCRIBE,"",0); |
|
|
|
agent->reqsock = nn_createsocket(myinfo,0,0,"NN_REQ",NN_REQ,0,sendtimeout,recvtimeout); |
|
|
|
} |
|
|
|
|
|
|
|
int32_t SuperNET_agentcommand(struct supernet_info *myinfo,struct supernet_agent *agent,struct supernet_msghdr *H,uint8_t *buf,int32_t buflen) |
|
|
|
{ |
|
|
|
char *name; cJSON *json; int32_t i; |
|
|
|
if ( strcmp(H->command,"register") == 0 ) |
|
|
|
{ |
|
|
|
if ( (json= cJSON_Parse((char *)buf)) != 0 ) |
|
|
|
{ |
|
|
|
if ( (name= jstr(json,"name")) != 0 ) |
|
|
|
{ |
|
|
|
memset(agent->name,0,sizeof(agent->name)); |
|
|
|
strncpy(agent->name,name,sizeof(agent->name)-1); |
|
|
|
if ( (agent->networks= jarray(&agent->num,json,"networks")) != 0 ) |
|
|
|
{ |
|
|
|
for (i=0; i<agent->num; i++) |
|
|
|
Supernet_networkadd(myinfo,agent,jitem(agent->networks,i)); |
|
|
|
} |
|
|
|
} else free_json(json); |
|
|
|
} |
|
|
|
} |
|
|
|
return(n); |
|
|
|
return(0); |
|
|
|
} |
|
|
|
|
|
|
|
int32_t iguana_socket(int32_t bindflag,char *hostname,uint16_t port) |
|
|
|
int32_t SuperNET_socket(int32_t bindflag,char *hostname,uint16_t port) |
|
|
|
{ |
|
|
|
int32_t opt,sock,result; uint32_t ipbits; char ipaddr[64]; struct timeval timeout; |
|
|
|
struct sockaddr_in saddr; socklen_t addrlen; |
|
|
@ -125,42 +364,6 @@ int32_t iguana_socket(int32_t bindflag,char *hostname,uint16_t port) |
|
|
|
return(sock); |
|
|
|
} |
|
|
|
|
|
|
|
/*void iguana_parsebuf(struct iguana_info *coin,struct iguana_peer *addr,struct iguana_msghdr *H,uint8_t *buf,int32_t len)
|
|
|
|
{ |
|
|
|
struct iguana_msghdr checkH; |
|
|
|
memset(&checkH,0,sizeof(checkH)); |
|
|
|
iguana_sethdr(&checkH,coin->chain->netmagic,H->command,buf,len); |
|
|
|
if ( memcmp(&checkH,H,sizeof(checkH)) == 0 ) |
|
|
|
{ |
|
|
|
//if ( strcmp(addr->ipaddr,"127.0.0.1") == 0 )
|
|
|
|
//printf("%s parse.(%s) len.%d\n",addr->ipaddr,H.command,len);
|
|
|
|
//printf("addr->dead.%u\n",addr->dead);
|
|
|
|
if ( strcmp(H->command,"block") == 0 || strcmp(H->command,"tx") == 0 ) |
|
|
|
{ |
|
|
|
if ( addr->RAWMEM.ptr == 0 ) |
|
|
|
iguana_meminit(&addr->RAWMEM,addr->ipaddr,0,IGUANA_MAXPACKETSIZE,0); |
|
|
|
if ( addr->TXDATA.ptr == 0 ) |
|
|
|
iguana_meminit(&addr->TXDATA,"txdata",0,IGUANA_MAXPACKETSIZE,0); |
|
|
|
if ( addr->HASHMEM.ptr == 0 ) |
|
|
|
iguana_meminit(&addr->HASHMEM,"HASHPTRS",0,256,0);//IGUANA_MAXPACKETSIZE*16,0);
|
|
|
|
//printf("Init %s memory %p %p %p\n",addr->ipaddr,addr->RAWMEM.ptr,addr->TXDATA.ptr,addr->HASHMEM.ptr);
|
|
|
|
} |
|
|
|
if ( iguana_parser(coin,addr,&addr->RAWMEM,&addr->TXDATA,&addr->HASHMEM,H,buf,len) < 0 || addr->dead != 0 ) |
|
|
|
{ |
|
|
|
printf("%p addr->dead.%d or parser break at %u\n",&addr->dead,addr->dead,(uint32_t)time(NULL)); |
|
|
|
addr->dead = (uint32_t)time(NULL); |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
addr->numpackets++; |
|
|
|
addr->totalrecv += len; |
|
|
|
coin->totalrecv += len, coin->totalpackets++; |
|
|
|
//printf("next iter.(%s) numreferrals.%d numpings.%d\n",addr->ipaddr,addr->numreferrals,addr->numpings);
|
|
|
|
} |
|
|
|
} else printf("header error from %s\n",addr->ipaddr); |
|
|
|
}*/ |
|
|
|
|
|
|
|
|
|
|
|
int32_t SuperNET_recv(int32_t sock,uint8_t *recvbuf,int32_t len) |
|
|
|
{ |
|
|
|
int32_t recvlen,remains = len; |
|
|
@ -187,101 +390,206 @@ int32_t SuperNET_recv(int32_t sock,uint8_t *recvbuf,int32_t len) |
|
|
|
return(len); |
|
|
|
} |
|
|
|
|
|
|
|
int32_t SuperNET_recvmsg(char *ipaddr,int32_t sock,uint8_t *_buf,int32_t maxlen) |
|
|
|
int32_t SuperNET_send(struct supernet_info *myinfo,struct supernet_agent *agent,uint8_t *serialized,int32_t len) |
|
|
|
{ |
|
|
|
int32_t numsent,remains,sock; |
|
|
|
if ( agent == 0 ) |
|
|
|
return(-1); |
|
|
|
if ( (sock= agent->sock) < 0 || agent->dead != 0 ) |
|
|
|
{ |
|
|
|
return(-1); |
|
|
|
} |
|
|
|
remains = len; |
|
|
|
while ( remains > 0 ) |
|
|
|
{ |
|
|
|
if ( (numsent= (int32_t)send(sock,serialized,remains,MSG_NOSIGNAL)) < 0 ) |
|
|
|
{ |
|
|
|
printf("send errno.%d %s\n",errno,strerror(errno)); |
|
|
|
if ( errno != EAGAIN && errno != EWOULDBLOCK ) |
|
|
|
{ |
|
|
|
printf("bad errno.%d %s zombify.%p\n",errno,strerror(errno),agent->name); |
|
|
|
agent->dead = (uint32_t)time(NULL); |
|
|
|
return(-errno); |
|
|
|
} //else usleep(*sleeptimep), *sleeptimep *= 1.1;
|
|
|
|
} |
|
|
|
else if ( remains > 0 ) |
|
|
|
{ |
|
|
|
remains -= numsent; |
|
|
|
serialized += numsent; |
|
|
|
if ( remains > 0 ) |
|
|
|
printf("SuperNET sent.%d remains.%d of len.%d\n",numsent,remains,len); |
|
|
|
} |
|
|
|
} |
|
|
|
agent->totalsent += len; |
|
|
|
//printf(" sent.%d bytes to %s\n",len,addr->ipaddr);// getchar();
|
|
|
|
return(len); |
|
|
|
} |
|
|
|
|
|
|
|
int32_t SuperNET_msgrecv(struct supernet_info *myinfo,struct supernet_agent *agent,uint8_t *_buf,int32_t maxlen) |
|
|
|
{ |
|
|
|
int32_t len,recvlen; void *buf = _buf; struct iguana_msghdr H; |
|
|
|
printf("got.(%s) from %s | sock.%d\n",H.command,ipaddr,sock); |
|
|
|
int32_t len,recvlen; void *buf = _buf; struct supernet_msghdr H; |
|
|
|
printf("got.(%s) from %s | sock.%d\n",H.command,agent->ipaddr,agent->sock); |
|
|
|
memset(&H,0,sizeof(H)); |
|
|
|
if ( (recvlen= (int32_t)SuperNET_recv(sock,(uint8_t *)&H,sizeof(H))) == sizeof(H) ) |
|
|
|
if ( (recvlen= (int32_t)SuperNET_recv(agent->sock,(uint8_t *)&H,sizeof(H))) == sizeof(H) ) |
|
|
|
{ |
|
|
|
//printf("%p got.(%s) recvlen.%d from %s | usock.%d ready.%u dead.%u\n",addr,H.command,recvlen,addr->ipaddr,addr->usock,addr->ready,addr->dead);
|
|
|
|
if ( (len= iguana_validatehdr(&H)) >= 0 ) |
|
|
|
agent->totalrecv += recvlen; |
|
|
|
if ( (len= SuperNET_msgvalidate(&H)) >= 0 ) |
|
|
|
{ |
|
|
|
recvlen = 0; |
|
|
|
if ( len > 0 ) |
|
|
|
{ |
|
|
|
if ( len > IGUANA_MAXPACKETSIZE ) |
|
|
|
{ |
|
|
|
printf("buffer %d too small for %d\n",IGUANA_MAXPACKETSIZE,len); |
|
|
|
return(-1);; |
|
|
|
} |
|
|
|
if ( len > maxlen ) |
|
|
|
buf = calloc(1,len); |
|
|
|
if ( (recvlen= SuperNET_recv(sock,buf,len)) < 0 ) |
|
|
|
if ( (recvlen= SuperNET_recv(agent->sock,buf,len)) < 0 ) |
|
|
|
{ |
|
|
|
printf("recv error on (%s) len.%d errno.%d (%s)\n",H.command,len,-recvlen,strerror(-recvlen)); |
|
|
|
if ( buf != _buf ) |
|
|
|
free(buf); |
|
|
|
//addr->dead = (uint32_t)time(NULL);
|
|
|
|
agent->dead = (uint32_t)time(NULL); |
|
|
|
return(recvlen); |
|
|
|
} |
|
|
|
} else agent->totalrecv += recvlen; |
|
|
|
} |
|
|
|
//iguana_parsebuf(coin,addr,&H,buf,len);
|
|
|
|
printf("PROCESS.%c NNRECV(%s) recvlen.%d\n",H.type,H.command,recvlen); |
|
|
|
if ( H.type == 'C' ) |
|
|
|
SuperNET_agentcommand(myinfo,agent,&H,buf,recvlen); |
|
|
|
else if ( agent->recvfunc != 0 ) |
|
|
|
(*agent->recvfunc)(myinfo,agent,&H,buf,recvlen); |
|
|
|
if ( buf != _buf ) |
|
|
|
free(buf); |
|
|
|
return(recvlen); |
|
|
|
} |
|
|
|
printf("invalid header received from (%s)\n",ipaddr); |
|
|
|
printf("invalid header received from (%s)\n",agent->ipaddr); |
|
|
|
} |
|
|
|
printf("%s recv error on hdr errno.%d (%s)\n",ipaddr,-recvlen,strerror(-recvlen)); |
|
|
|
printf("%s recv error on hdr errno.%d (%s)\n",agent->ipaddr,-recvlen,strerror(-recvlen)); |
|
|
|
return(-1); |
|
|
|
} |
|
|
|
|
|
|
|
struct supernet_accept { struct queueitem DL; char ipaddr[64]; uint32_t ipbits; int32_t sock; uint16_t port; } Accepts[SUPERNET_MAXPEERS]; |
|
|
|
queue_t AcceptQ; |
|
|
|
int32_t SuperNET_msgsend(struct supernet_info *myinfo,struct supernet_agent *agent,struct supernet_msghdr *msg) |
|
|
|
{ |
|
|
|
return(SuperNET_send(myinfo,agent,(uint8_t *)msg,SuperNET_msglen(msg) + sizeof(*msg))); |
|
|
|
} |
|
|
|
|
|
|
|
int32_t SuperNET_nnsend(struct supernet_info *myinfo,struct supernet_endpoint *ptr,int32_t ind,struct supernet_msghdr *msg) |
|
|
|
{ |
|
|
|
return(nn_send(ptr->eps[ind].nnsock,(uint8_t *)msg,SuperNET_msglen(msg) + sizeof(*msg),0)); |
|
|
|
} |
|
|
|
|
|
|
|
struct supernet_msghdr *SuperNET_msgpending(struct supernet_info *myinfo,struct supernet_agent *agent) |
|
|
|
{ |
|
|
|
return(queue_dequeue(&agent->recvQ,0)); |
|
|
|
} |
|
|
|
|
|
|
|
struct supernet_msghdr *SuperNET_nnpending(struct supernet_info *myinfo,struct supernet_endpoint *ptr,int32_t ind) |
|
|
|
{ |
|
|
|
return(queue_dequeue(&ptr->eps[ind].nnrecvQ,0)); |
|
|
|
} |
|
|
|
|
|
|
|
int32_t SuperNET_nnrecv(struct supernet_info *myinfo,struct supernet_endpoint *ptr,int32_t ind) |
|
|
|
{ |
|
|
|
void *msg; int32_t nnlen; |
|
|
|
if ( (nnlen= nn_recv(ptr->eps[ind].nnsock,&msg,NN_MSG,0)) > 0 ) |
|
|
|
{ |
|
|
|
printf("PROCESS NNRECV(%s)\n",msg); |
|
|
|
if ( ptr->nnrecvfunc != 0 ) |
|
|
|
(*ptr->nnrecvfunc)(myinfo,ptr,ind,msg,nnlen); |
|
|
|
nn_freemsg(msg); |
|
|
|
} |
|
|
|
return(nnlen); |
|
|
|
} |
|
|
|
|
|
|
|
int32_t Supernet_poll(uint8_t *buf,int32_t bufsize,struct supernet_accept *accepts,int32_t num,int32_t timeout) |
|
|
|
int32_t Supernet_poll(struct supernet_info *myinfo,uint8_t *buf,int32_t bufsize,struct supernet_agent *agents,int32_t num,int32_t timeout) |
|
|
|
{ |
|
|
|
struct pollfd fds[SUPERNET_MAXPEERS]; int32_t i,j,n,r,nonz,flag; struct supernet_accept *ptr; |
|
|
|
struct pollfd fds[SUPERNET_MAXAGENTS]; int32_t i,nonz,flag; struct supernet_msghdr *msg; struct supernet_agent *agent; |
|
|
|
if ( num == 0 ) |
|
|
|
return(0);; |
|
|
|
memset(fds,0,sizeof(fds)); |
|
|
|
flag = 0; |
|
|
|
r = (rand() % num); |
|
|
|
for (j=n=nonz=0; j<num&&j<sizeof(fds)/sizeof(*fds)-1; j++) |
|
|
|
for (i=nonz=0; i<num; i++) |
|
|
|
{ |
|
|
|
i = (j + r) % num; |
|
|
|
ptr = &accepts[i]; |
|
|
|
agent = &agents[i]; |
|
|
|
fds[i].fd = -1; |
|
|
|
if ( ptr->sock >= 0 ) |
|
|
|
if ( agent->sock >= 0 ) |
|
|
|
{ |
|
|
|
fds[i].fd = ptr->sock; |
|
|
|
fds[i].fd = agent->sock; |
|
|
|
fds[i].events = (POLLIN | POLLOUT); |
|
|
|
nonz++; |
|
|
|
} |
|
|
|
} |
|
|
|
if ( nonz != 0 && poll(fds,num,timeout) > 0 ) |
|
|
|
{ |
|
|
|
for (j=0; j<num; j++) |
|
|
|
for (i=0; i<num; i++) |
|
|
|
{ |
|
|
|
i = (j + r) % num; |
|
|
|
ptr = &accepts[i]; |
|
|
|
if ( ptr->sock < 0 ) |
|
|
|
agent = &agents[i]; |
|
|
|
if ( agent->sock < 0 ) |
|
|
|
continue; |
|
|
|
if ( (fds[i].revents & POLLIN) != 0 ) |
|
|
|
if ( (fds[i].revents & POLLIN) != 0 && SuperNET_msgrecv(myinfo,agent,buf,bufsize) >= 0 ) |
|
|
|
flag++; |
|
|
|
if ( (fds[i].revents & POLLOUT) != 0 ) |
|
|
|
{ |
|
|
|
return(SuperNET_recvmsg(ptr->ipaddr,ptr->sock,buf,bufsize)); |
|
|
|
if ( (msg= SuperNET_msgpending(myinfo,agent)) != 0 && SuperNET_msgsend(myinfo,agent,msg) > 0 ) |
|
|
|
flag++; |
|
|
|
} |
|
|
|
if ( (fds[i].revents & POLLOUT) != 0 ) |
|
|
|
} |
|
|
|
} |
|
|
|
return(flag); |
|
|
|
} |
|
|
|
|
|
|
|
int32_t Supernet_nnpoll(struct supernet_info *myinfo,uint8_t *buf,int32_t bufsize,struct supernet_endpoint **eps,int32_t num,int32_t timeout) |
|
|
|
{ |
|
|
|
struct nn_pollfd fds[1024]; int32_t i,j,n,k,r,starti,nonz,flag; struct supernet_msghdr *msg; struct supernet_endpoint *ptr; |
|
|
|
if ( num == 0 ) |
|
|
|
return(0); |
|
|
|
memset(fds,0,sizeof(fds)); |
|
|
|
flag = 0; |
|
|
|
r = rand(); |
|
|
|
for (j=k=nonz=n=0; j<num; j++) |
|
|
|
{ |
|
|
|
i = (j + r) % num; |
|
|
|
ptr = eps[i]; |
|
|
|
starti = n; |
|
|
|
for (k=0; k<ptr->num; k++,n++) |
|
|
|
{ |
|
|
|
fds[n].fd = -1; |
|
|
|
if ( ptr->eps[k].nnsock >= 0 ) |
|
|
|
{ |
|
|
|
//if ( iguana_pollsendQ(coin,addr) == 0 )
|
|
|
|
// flag += iguana_poll(coin,addr);
|
|
|
|
//else flag++;
|
|
|
|
fds[n].fd = ptr->eps[k].nnsock; |
|
|
|
fds[n].events = (POLLIN | POLLOUT); |
|
|
|
nonz++; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
return(0); |
|
|
|
if ( nonz != 0 && nn_poll(fds,num,timeout) > 0 ) |
|
|
|
{ |
|
|
|
for (j=k=0; j<num; j++) |
|
|
|
{ |
|
|
|
i = (j + r) % num; |
|
|
|
ptr = eps[i]; |
|
|
|
starti = n; |
|
|
|
for (k=0; k<ptr->num; k++,n++) |
|
|
|
{ |
|
|
|
if ( (fds[i].revents & POLLIN) != 0 && SuperNET_nnrecv(myinfo,ptr,n - starti) >= 0 ) |
|
|
|
flag++; |
|
|
|
if ( (fds[i].revents & POLLOUT) != 0 ) |
|
|
|
{ |
|
|
|
if ( (msg= SuperNET_nnpending(myinfo,ptr,n - starti)) != 0 && SuperNET_nnsend(myinfo,ptr,n - starti,msg) > 0 ) |
|
|
|
flag++; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
return(flag); |
|
|
|
} |
|
|
|
|
|
|
|
void SuperNET_acceptloop(void *args) |
|
|
|
{ |
|
|
|
int32_t bindsock,sock; struct supernet_accept *ptr; struct supernet_info *myinfo = args; |
|
|
|
socklen_t clilen; struct sockaddr_in cli_addr; char ipaddr[64]; uint32_t ipbits; |
|
|
|
bindsock = iguana_socket(1,"127.0.0.1",myinfo->portp2p); |
|
|
|
printf("iguana_bindloop 127.0.0.1:%d bind sock.%d\n",myinfo->portp2p,bindsock); |
|
|
|
int32_t bindsock,sock; struct supernet_agent *agent; struct supernet_info *myinfo = args; |
|
|
|
socklen_t clilen; uint16_t agentport; struct sockaddr_in cli_addr; char ipaddr[64]; uint32_t ipbits; |
|
|
|
bindsock = SuperNET_socket(1,"127.0.0.1",myinfo->acceptport); |
|
|
|
printf("SuperNET_acceptloop 127.0.0.1:%d bind sock.%d\n",myinfo->acceptport,bindsock); |
|
|
|
while ( bindsock >= 0 ) |
|
|
|
{ |
|
|
|
clilen = sizeof(cli_addr); |
|
|
|
printf("ACCEPT (%s:%d) on sock.%d\n","127.0.0.1",myinfo->portp2p,bindsock); |
|
|
|
printf("ACCEPT (%s:%d) on sock.%d\n","127.0.0.1",myinfo->acceptport,bindsock); |
|
|
|
sock = accept(bindsock,(struct sockaddr *)&cli_addr,&clilen); |
|
|
|
if ( sock < 0 ) |
|
|
|
{ |
|
|
@ -289,14 +597,16 @@ void SuperNET_acceptloop(void *args) |
|
|
|
continue; |
|
|
|
} |
|
|
|
memcpy(&ipbits,&cli_addr.sin_addr.s_addr,sizeof(ipbits)); |
|
|
|
agentport = cli_addr.sin_port; |
|
|
|
expand_ipbits(ipaddr,ipbits); |
|
|
|
printf("NEWSOCK.%d for %x (%s)\n",sock,ipbits,ipaddr); |
|
|
|
ptr = calloc(1,sizeof(*ptr)); |
|
|
|
strcpy(ptr->ipaddr,ipaddr); |
|
|
|
ptr->ipbits = ipbits; |
|
|
|
ptr->sock = sock; |
|
|
|
ptr->port = myinfo->portp2p; |
|
|
|
queue_enqueue("acceptQ",&AcceptQ,&ptr->DL,0); |
|
|
|
printf("NEWSOCK.%d for %x (%s:%u)\n",sock,ipbits,ipaddr,agentport); |
|
|
|
agent = calloc(1,sizeof(*agent)); |
|
|
|
strcpy(agent->ipaddr,ipaddr); |
|
|
|
sprintf(agent->name,"%s:%d",ipaddr,agentport); |
|
|
|
agent->ipbits = ipbits; |
|
|
|
agent->sock = sock; |
|
|
|
agent->port = myinfo->acceptport; |
|
|
|
queue_enqueue("acceptQ",&myinfo->acceptQ,&agent->DL,0); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
@ -305,7 +615,7 @@ int32_t SuperNET_acceptport(struct supernet_info *myinfo,uint16_t port) |
|
|
|
struct supernet_info *ptr; |
|
|
|
ptr = calloc(1,sizeof(*myinfo)); |
|
|
|
*ptr = *myinfo; |
|
|
|
ptr->portp2p = port; |
|
|
|
ptr->acceptport = port; |
|
|
|
if ( OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)SuperNET_acceptloop,(void *)ptr) != 0 ) |
|
|
|
{ |
|
|
|
printf("error launching accept thread for port.%u\n",port); |
|
|
@ -314,20 +624,42 @@ int32_t SuperNET_acceptport(struct supernet_info *myinfo,uint16_t port) |
|
|
|
return(0); |
|
|
|
} |
|
|
|
|
|
|
|
void SuperNET_loop(struct supernet_info *myinfo) |
|
|
|
{ |
|
|
|
struct supernet_agent *ptr; char *buf; int32_t bufsize = 65536 * 32; |
|
|
|
buf = calloc(1,bufsize); |
|
|
|
while ( myinfo->dead == 0 ) |
|
|
|
{ |
|
|
|
if ( (ptr= queue_dequeue(&myinfo->acceptQ,0)) != 0 ) |
|
|
|
{ |
|
|
|
if ( myinfo->numagents < sizeof(myinfo->agents)/sizeof(*myinfo->agents)-1 ) |
|
|
|
{ |
|
|
|
myinfo->agents[myinfo->numagents++] = *ptr; |
|
|
|
free(ptr); |
|
|
|
} |
|
|
|
printf("SuperNET.[%d] got new socket %d for %s:%d\n",myinfo->numagents,ptr->sock,ptr->ipaddr,ptr->port); |
|
|
|
} |
|
|
|
else if ( Supernet_poll(myinfo,(uint8_t *)buf,bufsize,myinfo->agents,myinfo->numagents,myinfo->POLLTIMEOUT) <= 0 ) |
|
|
|
usleep(10000); |
|
|
|
} |
|
|
|
free(buf); |
|
|
|
} |
|
|
|
|
|
|
|
void SuperNET_main(void *arg) |
|
|
|
{ |
|
|
|
struct supernet_info MYINFO; struct supernet_accept *ptr; char buf[8192]; |
|
|
|
cJSON *json,*array; uint16_t port; int32_t i,n = 0; |
|
|
|
struct supernet_info MYINFO; cJSON *json,*array; uint16_t port; int32_t i,n = 0; |
|
|
|
memset(&MYINFO,0,sizeof(MYINFO)); |
|
|
|
if ( 0 ) |
|
|
|
if ( 1 ) |
|
|
|
{ |
|
|
|
strcpy(MYINFO.transport,"tcp"); |
|
|
|
strcpy(MYINFO.ipaddr,"127.0.0.1"); |
|
|
|
MYINFO.port = SUPERNET_PORT; MYINFO.serviceport = SUPERNET_PORT - 2; |
|
|
|
SuperNET_init(&MYINFO,arg); |
|
|
|
MYINFO.acceptport = SUPERNET_PORT; MYINFO.serviceport = SUPERNET_PORT - 2; |
|
|
|
// SuperNET_init(&MYINFO,arg); parse supernet.conf
|
|
|
|
if ( MYINFO.POLLTIMEOUT == 0 ) |
|
|
|
MYINFO.POLLTIMEOUT = SUPERNET_POLLTIMEOUT; |
|
|
|
} |
|
|
|
if ( arg == 0 || (json= cJSON_Parse(arg)) == 0 ) |
|
|
|
SuperNET_acceptport(&MYINFO,14631); |
|
|
|
SuperNET_acceptport(&MYINFO,MYINFO.port); |
|
|
|
else |
|
|
|
{ |
|
|
|
if ( (array= jarray(&n,json,"accept")) != 0 ) |
|
|
@ -339,22 +671,8 @@ void SuperNET_main(void *arg) |
|
|
|
free_json(json); |
|
|
|
} |
|
|
|
sleep(3); |
|
|
|
printf("start SuperNET_loop\n"); |
|
|
|
while ( MYINFO.dead == 0 ) |
|
|
|
{ |
|
|
|
//if ( busdata_poll(&MYINFO) == 0 && MYINFO.APISLEEP > 0 )
|
|
|
|
// usleep(MYINFO.APISLEEP * 1000);
|
|
|
|
if ( (ptr= queue_dequeue(&AcceptQ,0)) != 0 ) |
|
|
|
{ |
|
|
|
if ( n < sizeof(Accepts)/sizeof(*Accepts)-1 ) |
|
|
|
{ |
|
|
|
Accepts[n++] = *ptr; |
|
|
|
free(ptr); |
|
|
|
} |
|
|
|
PostMessage("SuperNET.[%d] got new socket %d for %s:%d\n",n,ptr->sock,ptr->ipaddr,ptr->port); |
|
|
|
} |
|
|
|
if ( n > 0 ) |
|
|
|
Supernet_poll(buf,sizeof(buf),Accepts,n,7); |
|
|
|
sleep(1); |
|
|
|
} |
|
|
|
printf("start SuperNET_loop on port.%u\n",MYINFO.port); |
|
|
|
for (i=0; i<sizeof(MYINFO.agents)/sizeof(*MYINFO.agents); i++) |
|
|
|
MYINFO.agents[i].sock = -1; |
|
|
|
SuperNET_loop(&MYINFO); |
|
|
|
} |
|
|
|