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.

449 lines
18 KiB

9 years ago
/******************************************************************************
9 years ago
* Copyright © 2014-2016 The SuperNET Developers. *
9 years ago
* *
* 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. *
* *
******************************************************************************/
/**
* - we need to include WinSock2.h header to correctly use windows structure
* as the application is still using 32bit structure from mingw so, we need to
* add the include based on checking
* @author - fadedreamz@gmail.com
* @remarks - #if (defined(_M_X64) || defined(__amd64__)) && defined(WIN32)
* is equivalent to #if defined(_M_X64) as _M_X64 is defined for MSVC only
*/
#if defined(_M_X64)
#define WIN32_LEAN_AND_MEAN
#include <WinSock2.h>
#endif
9 years ago
#include "iguana777.h"
#include "exchanges777.h"
9 years ago
struct iguana_accept { struct queueitem DL; char ipaddr[64]; uint32_t ipbits; int32_t sock; uint16_t port; };
int32_t iguana_acceptspoll(uint8_t *buf,int32_t bufsize,struct iguana_accept *accepts,int32_t num,int32_t timeout)
{
/**
* This solution is for win64
* 2^11*sizeof(struct fd) for win64 bit gives a very big number
* for that reason it cannot allocate memory from stack
* so the solution is to allocate memory from heap, instead of stack
* @author - fadedreamz@gmail.com
*/
#if defined(_M_X64)
struct pollfd * fds;
int32_t i, j, n, r, nonz, flag; struct iguana_accept *ptr;
if (num == 0)
return(0);;
fds = (struct pollfd *) malloc(sizeof(struct pollfd) * IGUANA_MAXPEERS);
if (NULL == fds)
return -1;
memset(fds, 0, sizeof(struct pollfd) * IGUANA_MAXPEERS);
#else
9 years ago
struct pollfd fds[IGUANA_MAXPEERS]; int32_t i,j,n,r,nonz,flag; struct iguana_accept *ptr;
if ( num == 0 )
return(0);;
memset(fds,0,sizeof(fds));
#endif
9 years ago
flag = 0;
r = (rand() % num);
for (j=n=nonz=0; j<num&&j<sizeof(fds)/sizeof(*fds)-1; j++)
{
i = (j + r) % num;
ptr = &accepts[i];
fds[i].fd = -1;
if ( ptr->sock >= 0 )
{
fds[i].fd = ptr->sock;
fds[i].events = (POLLIN | POLLOUT);
nonz++;
}
}
if ( nonz != 0 && poll(fds,num,timeout) > 0 )
{
for (j=0; j<num; j++)
{
i = (j + r) % num;
ptr = &accepts[i];
if ( ptr->sock < 0 )
continue;
if ( (fds[i].revents & POLLIN) != 0 )
{
//return(iguana_recvmsg(ptr->ipaddr,ptr->sock,buf,bufsize));
}
if ( (fds[i].revents & POLLOUT) != 0 )
{
//if ( iguana_pollsendQ(coin,addr) == 0 )
// flag += iguana_poll(coin,addr);
//else flag++;
}
}
}
/**
* graceful memory release, because we allocated memory on heap,
* so we are releasing it here
* @author - fadedreamz@gmail.com
*/
#if defined(_M_X64)
free(fds);
#endif
9 years ago
return(0);
}
void iguana_acceptloop(void *args)
{
9 years ago
struct iguana_peer *addr; struct iguana_info *coin = args;
9 years ago
struct pollfd pfd; int32_t sock; struct iguana_accept *ptr; uint16_t port = coin->chain->portp2p;
9 years ago
socklen_t clilen; struct sockaddr_in cli_addr; char ipaddr[64]; uint32_t i,ipbits,flag;
9 years ago
if ( coin->peers == 0 )
return;
9 years ago
while ( (coin->bindsock= iguana_socket(1,"0.0.0.0",port)) < 0 )
9 years ago
{
9 years ago
if ( coin->peers->localaddr != 0 )
9 years ago
{
printf("another daemon running, no need to have iguana accept connections\n");
return;
}
9 years ago
//if ( port != IGUANA_RPCPORT )
// return;
9 years ago
sleep(5);
9 years ago
}
9 years ago
printf(">>>>>>>>>>>>>>>> iguana_bindloop 127.0.0.1:%d bind sock.%d\n",port,coin->bindsock);
9 years ago
printf("START ACCEPTING\n");
9 years ago
while ( coin->bindsock >= 0 )
9 years ago
{
9 years ago
memset(&pfd,0,sizeof(pfd));
9 years ago
pfd.fd = coin->bindsock;
9 years ago
pfd.events = POLLIN;
9 years ago
if ( poll(&pfd,1,100) <= 0 )
continue;
9 years ago
clilen = sizeof(cli_addr);
9 years ago
//printf("ACCEPT (%s:%d) on sock.%d\n","127.0.0.1",coin->chain->portp2p,coin->bindsock);
9 years ago
sock = accept(coin->bindsock,(struct sockaddr *)&cli_addr,&clilen);
9 years ago
if ( sock < 0 )
{
9 years ago
printf("ERROR on accept bindsock.%d errno.%d (%s)\n",coin->bindsock,errno,strerror(errno));
9 years ago
continue;
}
memcpy(&ipbits,&cli_addr.sin_addr.s_addr,sizeof(ipbits));
expand_ipbits(ipaddr,ipbits);
8 years ago
//printf("incoming %s (%s:%u)\n",coin->symbol,ipaddr,cli_addr.sin_port);
9 years ago
for (i=flag=0; i<IGUANA_MAXPEERS; i++)
9 years ago
{
8 years ago
addr = &coin->peers->active[i];
if ( addr->ipbits == (uint32_t)ipbits && addr->usock >= 0 )
9 years ago
{
//printf("found existing %s peer.(%s) in slot[%d]\n",coin->symbol,ipaddr,i);
8 years ago
close(addr->usock);
addr->dead = 0;
addr->usock = sock;
addr->A.port = cli_addr.sin_port;
addr->ready = (uint32_t)time(NULL);
9 years ago
flag = 1;
8 years ago
iguana_send_version(coin,addr,coin->myservices);
9 years ago
//instantdex_peerhas_clear(coin,&coin->peers->active[i]);
9 years ago
//iguana_iAkill(coin,&coin->peers->active[i],0);
9 years ago
//sleep(1);
9 years ago
break;
9 years ago
}
}
9 years ago
if ( flag != 0 )
9 years ago
continue;
8 years ago
printf("%s NEWSOCK.%d for %x (%s)\n",coin->symbol,sock,ipbits,ipaddr);
9 years ago
/*if ( (uint32_t)ipbits == myinfo->myaddr.myipbits )
{
}*/
9 years ago
if ( (addr= iguana_peerslot(coin,ipbits,1)) == 0 )
9 years ago
{
ptr = mycalloc('a',1,sizeof(*ptr));
strcpy(ptr->ipaddr,ipaddr);
ptr->ipbits = ipbits;
ptr->sock = sock;
9 years ago
ptr->port = cli_addr.sin_port;
printf("queue PENDING ACCEPTS\n");
8 years ago
queue_enqueue("acceptQ",&coin->acceptQ,&ptr->DL);
9 years ago
}
else
{
8 years ago
printf("LAUNCH %s DEDICATED THREAD for %s:%u\n",coin->symbol,ipaddr,cli_addr.sin_port);
9 years ago
addr->usock = sock;
9 years ago
addr->dead = 0;
9 years ago
addr->A.port = cli_addr.sin_port;
9 years ago
strcpy(addr->symbol,coin->symbol);
iguana_launch(coin,"accept",iguana_dedicatedglue,addr,IGUANA_CONNTHREAD);
//iguana_dedicatedloop(coin,addr);
9 years ago
}
}
}
int32_t iguana_pendingaccept(struct iguana_info *coin)
{
struct iguana_accept *ptr; char ipaddr[64]; struct iguana_peer *addr;
8 years ago
if ( (ptr= queue_dequeue(&coin->acceptQ)) != 0 )
{
9 years ago
if ( (addr= iguana_peerslot(coin,ptr->ipbits,0)) != 0 )
{
expand_ipbits(ipaddr,ptr->ipbits);
8 years ago
printf("iguana_pendingaccept %s LAUNCH DEDICATED THREAD for %s\n",coin->symbol,ipaddr);
addr->usock = ptr->sock;
strcpy(addr->symbol,coin->symbol);
iguana_launch(coin,"accept",iguana_dedicatedglue,addr,IGUANA_CONNTHREAD);
myfree(ptr,sizeof(*ptr));
return(1);
8 years ago
} else queue_enqueue("requeue_acceptQ",&coin->acceptQ,&ptr->DL);
}
return(0);
}
9 years ago
9 years ago
/*int32_t iguana_acceptport(struct iguana_info *coin,uint16_t port)
{
if ( OS_thread_create(malloc(sizeof(pthread_t)),NULL,(void *)iguana_acceptloop,(void *)coin) != 0 )
{
printf("error launching accept thread for port.%u\n",port);
return(-1);
}
return(0);
}*/
9 years ago
9 years ago
void iguana_msgrequestQ(struct iguana_info *coin,struct iguana_peer *addr,int32_t type,bits256 hash2)
{
struct iguana_peermsgrequest *msg;
msg = calloc(1,sizeof(*msg));
msg->addr = addr;
msg->hash2 = hash2;
msg->type = type;
8 years ago
queue_enqueue("msgrequest",&coin->msgrequestQ,&msg->DL);
9 years ago
}
9 years ago
int32_t iguana_process_msgrequestQ(struct supernet_info *myinfo,struct iguana_info *coin)
9 years ago
{
9 years ago
struct iguana_peermsgrequest *msg; int32_t height,len,flag = 0; bits256 checktxid; struct iguana_txid *tx,T; struct iguana_peer *addr;
8 years ago
if ( (msg= queue_dequeue(&coin->msgrequestQ)) != 0 )
9 years ago
{
flag = 1;
if ( msg->addr != 0 )
{
9 years ago
//char str[65]; printf("send type.%d %s -> (%s)\n",msg->type,bits256_str(str,msg->hash2),msg->addr->ipaddr);
9 years ago
if ( msg->type == MSG_BLOCK )
{
if ( coin->FULLNODE > 0 || coin->VALIDATENODE > 0 )
9 years ago
{
8 years ago
if ( (addr= msg->addr) != 0 && (len= iguana_peerblockrequest(myinfo,coin,coin->blockspace,(int32_t)(coin->blockspacesize - sizeof(struct iguana_msghdr)),0,msg->hash2,0)) > 0 )
9 years ago
{
9 years ago
//char str[65]; printf("msg Sendlen.%d block %s to %s\n",len,bits256_str(str,msg->hash2),addr->ipaddr);
9 years ago
iguana_queue_send(addr,0,coin->blockspace,"block",len);
9 years ago
}
}
}
else if ( msg->type == MSG_TX )
{
if ( coin->FULLNODE > 0 || coin->VALIDATENODE > 0 )
9 years ago
{
if ( (tx= iguana_txidfind(coin,&height,&T,msg->hash2,coin->bundlescount-1)) != 0 )
{
if ( (len= iguana_ramtxbytes(coin,&coin->blockspace[sizeof(struct iguana_msghdr)],coin->blockspacesize,&checktxid,tx,height,0,0,0)) > 0 )
9 years ago
{
char str[65],str2[65];
if ( bits256_cmp(msg->hash2,checktxid) == 0 )
9 years ago
iguana_queue_send(msg->addr,0,coin->blockspace,"block",len);
9 years ago
else printf("checktxid mismatch (%s) != (%s)\n",bits256_str(str,msg->hash2),bits256_str(str2,checktxid));
}
}
}
}
else if ( msg->type == MSG_FILTERED_BLOCK )
{
}
else if ( msg->type == MSG_BUNDLE_HEADERS )
{
}
else if ( msg->type == MSG_BUNDLE )
{
}
9 years ago
/*else if ( msg->type == MSG_QUOTE )
{
if ( (len= instantdex_quoterequest(myinfo,coin,&coin->blockspace[sizeof(struct iguana_msghdr)],coin->blockspacesize,msg->addr,msg->hash2)) > 0 )
9 years ago
{
9 years ago
//iguana_sethdr((void *)coin->blockspace,coin->chain->netmagic,"quote",&coin->blockspace[sizeof(struct iguana_msghdr)],len);
//iguana_msgparser(coin,msg->addr,0,0,0,(void *)coin->blockspace,&coin->blockspace[sizeof(struct iguana_msghdr)],len);
9 years ago
iguana_queue_send(msg->addr,0,coin->blockspace,"quote",len);
9 years ago
}
9 years ago
}*/
9 years ago
}
free(msg);
}
return(flag);
}
9 years ago
int32_t iguana_peerdatarequest(struct iguana_info *coin,struct iguana_peer *addr,uint8_t *data,int32_t recvlen)
9 years ago
{
int32_t i,type,len = 0; uint64_t x; bits256 hash2;
9 years ago
len += iguana_rwvarint(0,data,&x);
9 years ago
//for (i=0; i<10; i++)
// printf("%02x ",data[i]);
//printf("x.%d recvlen.%d\n",(int32_t)x,recvlen);
9 years ago
if ( x < IGUANA_MAXINV )
{
for (i=0; i<x; i++)
{
9 years ago
len += iguana_rwnum(0,&data[len],sizeof(uint32_t),&type);
len += iguana_rwbignum(0,&data[len],sizeof(bits256),hash2.bytes);
9 years ago
iguana_msgrequestQ(coin,addr,type,hash2);
}
}
return(len);
}
9 years ago
int32_t iguana_inv2packet(uint8_t *serialized,int32_t maxsize,int32_t type,bits256 *hashes,int32_t n)
{
int32_t i,len = sizeof(struct iguana_msghdr); uint64_t x = n;
memset(serialized,0,len);
len += iguana_rwvarint(1,&serialized[len],&x);
//for (i=0; i<10; i++)
// printf("%02x ",data[i]);
//printf("x.%d recvlen.%d\n",(int32_t)x,recvlen);
if ( x < IGUANA_MAXINV )
{
for (i=0; i<x; i++)
{
len += iguana_rwnum(1,&serialized[len],sizeof(uint32_t),&type);
len += iguana_rwbignum(1,&serialized[len],sizeof(bits256),hashes[i].bytes);
}
}
if ( len > maxsize )
return(-1);
9 years ago
return(len - sizeof(struct iguana_msghdr));
9 years ago
}
8 years ago
int32_t iguana_headerget(struct supernet_info *myinfo,struct iguana_info *coin,uint8_t *serialized,int32_t maxsize,struct iguana_block *block)
{
bits256 checkhash2; struct iguana_msgzblock zmsgB; int32_t len = 0;
iguana_blockunconv(coin->chain->zcash,coin->chain->auxpow,&zmsgB,(void *)block,1);
if ( (len= iguana_rwblock(myinfo,coin->symbol,coin->chain->zcash,coin->chain->auxpow,coin->chain->hashalgo,1,&checkhash2,&serialized[sizeof(struct iguana_msghdr)],&zmsgB,(int32_t)(maxsize-sizeof(struct iguana_msghdr)))) < 0 )
return(-1);
if ( bits256_cmp(checkhash2,block->RO.hash2) != 0 )
{
char str[65],str2[65];
printf("iguana_peerhdrrequest blockhash.%d error (%s) vs (%s)\n",block->height,bits256_str(str,checkhash2),bits256_str(str2,block->RO.hash2));
return(-1);
}
return(len);
}
9 years ago
int32_t iguana_peerhdrrequest(struct supernet_info *myinfo,struct iguana_info *coin,uint8_t *serialized,int32_t maxsize,struct iguana_peer *addr,bits256 hash2)
9 years ago
{
8 years ago
int32_t len=0,i,flag=0,height,n,hdrsi,bundlei,bundlesize,retval=-1; struct iguana_block *block; struct iguana_bundle *bp; struct iguana_outpoint outpt;
if ( coin->RTheight > 0 && iguana_RTunspentindfind(myinfo,coin,&outpt,0,0,0,0,&height,hash2,0,coin->bundlescount-1,0) == 0 )
9 years ago
{
9 years ago
bundlesize = coin->chain->bundlesize;
hdrsi = (height / bundlesize);
bundlei = height - (hdrsi * bundlesize);
if ( hdrsi >= 0 && hdrsi < bundlesize && bundlei >= 0 && bundlei < bundlesize && (bp= coin->bundles[hdrsi]) != 0 )
9 years ago
{
9 years ago
for (i=0; i<coin->chain->bundlesize; i++)
9 years ago
{
9 years ago
if ( (block= bp->blocks[i]) != 0 )
9 years ago
{
8 years ago
if ( (n= iguana_headerget(myinfo,coin,&serialized[len],maxsize-len,block)) < 0 )
9 years ago
{
printf("%s error getting header ht.%d\n",coin->symbol,block->height);
continue;
9 years ago
}
len += n;
9 years ago
} else printf("cant find block at ht.%d\n",height+i);
}
9 years ago
}
8 years ago
if ( 0 && flag != 0 && strcmp("BTCD",coin->symbol) != 0 )
9 years ago
retval = iguana_queue_send(addr,0,serialized,"headers",len);
9 years ago
//printf("hdrs request retval.%d len.%d\n",retval,len);
9 years ago
} //else printf("couldnt find header\n");
9 years ago
return(retval);
}
9 years ago
int32_t iguana_peergetrequest(struct supernet_info *myinfo,struct iguana_info *coin,struct iguana_peer *addr,uint8_t *data,int32_t recvlen,int32_t getblock)
9 years ago
{
9 years ago
int32_t i,reqvers,len,n,flag = 0; bits256 hash2;
8 years ago
if ( coin->RTheight <= 0 )
return(0);
9 years ago
if ( getblock != 0 )
addr->msgcounts.getblocks++;
else addr->msgcounts.getheaders++;
len = iguana_rwnum(0,&data[0],sizeof(uint32_t),&reqvers);
len += iguana_rwvarint32(0,&data[len],(uint32_t *)&n);
9 years ago
for (i=0; i<n&&len<=recvlen-sizeof(bits256)*2; i++)
9 years ago
{
9 years ago
len += iguana_rwbignum(0,&data[len],sizeof(bits256),hash2.bytes);
if ( bits256_nonz(hash2) == 0 )
break;
if ( flag == 0 )
9 years ago
{
8 years ago
if ( getblock != 0 && iguana_peerblockrequest(myinfo,coin,addr->blockspace,IGUANA_MAXPACKETSIZE,addr,hash2,0) > 0 )
9 years ago
flag = 1;
9 years ago
else if ( getblock == 0 && iguana_peerhdrrequest(myinfo,coin,addr->blockspace,IGUANA_MAXPACKETSIZE,addr,hash2) > 0 )
9 years ago
flag = 1;
9 years ago
}
}
9 years ago
len += iguana_rwbignum(0,&data[len],sizeof(bits256),hash2.bytes);
9 years ago
//for (i=0; i<69; i++)
// printf("%02x ",data[i]);
//printf("version.%d num blocks.%d recvlen.%d len.%d\n",reqvers,n,recvlen,len);
9 years ago
return(len);
}
int32_t iguana_peeraddrrequest(struct iguana_info *coin,struct iguana_peer *addr,uint8_t *space,int32_t spacesize)
{
9 years ago
int32_t i,iter,n,max,sendlen; uint64_t x; struct iguana_peer *tmpaddr,tmp; char ipaddr[65];
9 years ago
if ( coin->peers == 0 )
return(0);
9 years ago
sendlen = 0;
max = (IGUANA_MINPEERS + IGUANA_MAXPEERS) / 2;
9 years ago
if ( max > coin->peers->numranked )
max = coin->peers->numranked;
9 years ago
x = 0;
9 years ago
sendlen = iguana_rwvarint(1,&space[sendlen],&x);
9 years ago
for (iter=0; iter<2; iter++)
{
for (i=n=0; i<max; i++)
{
9 years ago
if ( (tmpaddr= coin->peers->ranked[i]) != 0 && ((iter == 0 && tmpaddr->supernet != 0) || (iter == 1 && tmpaddr->supernet == 0)) && tmpaddr->ipbits != 0 )
9 years ago
{
9 years ago
tmp = *tmpaddr;
iguana_rwnum(1,&tmp.A.ip[12],sizeof(uint32_t),&tmp.ipbits);
expand_ipbits(ipaddr,tmp.ipbits);
if ( tmp.A.port == 0 )
{
((uint8_t *)&tmp.A.port)[0] = ((uint8_t *)&coin->chain->portp2p)[1];
((uint8_t *)&tmp.A.port)[1] = ((uint8_t *)&coin->chain->portp2p)[0];
}
9 years ago
//printf("(%s:%02x%02x).%04x ",ipaddr,((uint8_t *)&tmp.A.port)[0],((uint8_t *)&tmp.A.port)[1],(int32_t)tmp.protover);
9 years ago
sendlen += iguana_rwaddr(1,&space[sendlen],&tmp.A,CADDR_TIME_VERSION);
9 years ago
x++;
9 years ago
if ( x == 0xf8 )
break;
9 years ago
}
}
}
9 years ago
iguana_rwvarint(1,space,&x);
9 years ago
//for (i=0; i<sendlen; i++)
// printf("%02x",space[i]);
9 years ago
//printf(" %p addrrequest: sendlen.%d x.%d\n",space,sendlen,(int32_t)x);
9 years ago
if ( x == 0 )
return(-1);
9 years ago
return(sendlen);
}