diff options
| author | me_desk <me_desk@fb96df88-216d-11de-830c-f3023f12d8ac> | 2012-06-17 21:15:12 +0000 |
|---|---|---|
| committer | me_desk <me_desk@fb96df88-216d-11de-830c-f3023f12d8ac> | 2012-06-17 21:15:12 +0000 |
| commit | 8df9466ada46e4b07990b9cb7e8b1cd61b96844a (patch) | |
| tree | 2cb652e5839bed672133ffa90e7ad477f55cfb6b /PICA_node.c | |
| download | pica-pica-8df9466ada46e4b07990b9cb7e8b1cd61b96844a.tar.gz pica-pica-8df9466ada46e4b07990b9cb7e8b1cd61b96844a.zip | |
todo list update
git-svn-id: svn://localhost/project_picapica/trunk@128 fb96df88-216d-11de-830c-f3023f12d8ac
Diffstat (limited to 'PICA_node.c')
| -rwxr-xr-x | PICA_node.c | 2266 |
1 files changed, 2266 insertions, 0 deletions
diff --git a/PICA_node.c b/PICA_node.c new file mode 100755 index 0000000..72c30cc --- /dev/null +++ b/PICA_node.c @@ -0,0 +1,2266 @@ +//Программа является узлом сети +// +#include <stdio.h> +#include <stdlib.h> +#include <limits.h> +#include <string.h> +#include <time.h> +#include <sys/time.h> + +#include "PICA_node.h" +#include "PICA_proto.h" +#include "PICA_msgproc.h" +#include "PICA_nodeaddrlist.h" +#include "PICA_common.h" +#include "PICA_nodejoinskynet.h" + +#ifdef NO_RAND_DEV +#include "PICA_rand_seed.h" +#endif + +#define MAX_NEWCONNS 64 + +#define NEWCONN_TIMEOUT 10 //sec +#define JOINSKYNET_TIMEOUT 15 +#define SELECT_TIMEOUT 1 + +clock_t TMO_CCLINK_WAITACTIVE=15;//CONF //таймаут ожидания перехода соединения в активное состояние + +char *my_addr;//TEMP CONF FIXME собственный ip-адрес узла, на котором он ожидает соединения + +SOCKET listen_comm_sck;//* + +SSL_CTX* ctx; +struct newconn newconns[MAX_NEWCONNS]; +unsigned int newconns_pos=0; + + +struct client *client_tree_root;//корень дерева клиентов +struct client *client_list_head;//указатель на первый элемент списка клиентов или 0, если список пуст +struct client *client_list_end;//указатель на последний элемент списка клиентов или 0, если список пуст + +struct cclink *cclink_list_head; +struct cclink *cclink_list_end; + +unsigned int cclink_list_count; + +struct nodelink *nodelink_list_head; +struct nodelink *nodelink_list_end; +unsigned int nodelink_list_count; + +struct PICA_nodeaddr *nodeaddr_list_head; +struct PICA_nodeaddr *nodeaddr_list_end; +unsigned int nodeaddr_list_count; + + +char msg_VERDIFFER[4]={PICA_PROTO_VERDIFFER,PICA_PROTO_VERDIFFER,PICA_PROTO_VER_HIGH,PICA_PROTO_VER_LOW}; +const unsigned int msg_VERDIFFER_len=4; + +unsigned int procmsg_INITREQ(unsigned char* buf,unsigned int size,void* ptr); +unsigned int procmsg_CONNID(unsigned char* buf,unsigned int size,void* ptr); +unsigned int procmsg_NODECONNREQ(unsigned char* buf,unsigned int size,void* ptr); + +unsigned int procmsg_CONNREQOUTG(unsigned char* buf,unsigned int size,void* ptr); +unsigned int procmsg_CONNALLOW(unsigned char* buf,unsigned int size,void* ptr); +unsigned int procmsg_CONNDENY(unsigned char* buf,unsigned int size,void* ptr); +unsigned int procmsg_NODERESP(unsigned char* buf,unsigned int size,void* ptr); +unsigned int procmsg_NEWNODE(unsigned char* buf,unsigned int size,void* ptr); +unsigned int procmsg_NODELISTREQ(unsigned char* buf,unsigned int size,void* ptr); +unsigned int procmsg_NODELIST(unsigned char* buf,unsigned int size,void* ptr); +unsigned int procmsg_N2NFOUND(unsigned char* buf,unsigned int size,void* ptr); +unsigned int procmsg_SEARCH(unsigned char* buf,unsigned int size,void* ptr); +unsigned int procmsg_N2NCONNREQOUTG(unsigned char* buf,unsigned int size,void* ptr); +unsigned int procmsg_N2NALLOW(unsigned char* buf,unsigned int size,void* ptr); +unsigned int procmsg_N2NNOTFOUND(unsigned char* buf,unsigned int size,void* ptr); +unsigned int procmsg_N2NMSG(unsigned char* buf,unsigned int size,void* ptr); + +struct cclink* cclink_list_add(struct client *clr,struct client *cle); +struct cclink* cclink_list_search(unsigned int caller_id, unsigned int callee_id); +struct cclink* cclink_list_findwaitsearch(unsigned int callee_id); +void cclink_list_addlocal(struct client *clr,struct client *cle); +void cclink_list_delete(struct cclink *l); +void cclink_list_addn2nclr(struct client *clr,unsigned int callee_id); +void cclink_setwaitconn(struct cclink *ccl); +void cclink_list_addn2ncle(unsigned int caller_id, struct nodelink *caller_node, struct client *cle); +void cclink_activate(struct cclink *ccl,SOCKET s); +void cclink_attach_remotecle_node(struct cclink *ccl, struct nodelink *callee_node); + +struct client* client_tree_search(unsigned int id);// +struct client *client_list_addnew(struct newconn *nc); +struct PICA_proto_msg* client_wbuf_push(struct client *c,unsigned int msgid,unsigned int size); + +struct PICA_proto_msg* nodelink_wbuf_push(struct nodelink *nl,unsigned int msgid,unsigned int size); +int nodelink_rbuf_grow(struct nodelink *nl); +int nodelink_attach_nodeaddr(struct nodelink *nl, unsigned int addr_type, void* nodeaddr, unsigned int nodeaddr_size); +struct nodelink *nodelink_list_addnew(struct newconn *nc); +void nodelink_list_delete(struct nodelink *n); + +void newconn_close(struct newconn* nc); +void newconn_free(struct newconn* nc); +struct newconn* newconn_add(struct newconn *ncs,int *pos); + +//описание формата сообщений, которые могут приходить _ОТ_ клиентов по управляющему защищенному соединению +#define MSGINFO_MSGSNUM(arr) (sizeof(arr)/sizeof(struct PICA_msginfo)) + +struct PICA_msginfo _msginfo_comm[]={ +{PICA_PROTO_CONNREQOUTG, PICA_MSG_FIXED_SIZE, PICA_PROTO_CONNREQOUTG_SIZE, procmsg_CONNREQOUTG}, +{PICA_PROTO_CONNALLOW, PICA_MSG_FIXED_SIZE, PICA_PROTO_CONNALLOW_SIZE, procmsg_CONNALLOW}, +{PICA_PROTO_CONNDENY, PICA_MSG_FIXED_SIZE, PICA_PROTO_CONNDENY_SIZE, procmsg_CONNDENY}, +{PICA_PROTO_CLNODELISTREQ, PICA_MSG_FIXED_SIZE, PICA_PROTO_CLNODELISTREQ_SIZE, procmsg_NODELISTREQ} +};//---!!! PING!!! + +struct PICA_msginfo _msginfo_node[]={ +{PICA_PROTO_INITRESPOK,PICA_MSG_FIXED_SIZE,PICA_PROTO_INITRESPOK_SIZE,procmsg_NODERESP}, +{PICA_PROTO_VERDIFFER ,PICA_MSG_FIXED_SIZE,PICA_PROTO_VERDIFFER_SIZE,procmsg_NODERESP}, +{PICA_PROTO_NEWNODE_IPV4 ,PICA_MSG_FIXED_SIZE,PICA_PROTO_NEWNODE_IPV4_SIZE,procmsg_NEWNODE}, +{PICA_PROTO_NODELISTREQ,PICA_MSG_FIXED_SIZE,PICA_PROTO_NODELISTREQ_SIZE,procmsg_NODELISTREQ}, +{PICA_PROTO_NODELIST,PICA_MSG_VAR_SIZE,PICA_MSG_VARSIZE_INT16,procmsg_NODELIST}, + +{PICA_PROTO_SEARCH,PICA_MSG_FIXED_SIZE,PICA_PROTO_SEARCH_SIZE,procmsg_SEARCH}, +{PICA_PROTO_N2NFOUND,PICA_MSG_FIXED_SIZE,PICA_PROTO_N2NFOUND_SIZE,procmsg_N2NFOUND}, +{PICA_PROTO_N2NFOUNDCACHE,PICA_MSG_VAR_SIZE,PICA_MSG_VARSIZE_INT16,procmsg_N2NFOUND}, +{PICA_PROTO_N2NCONNREQOUTG,PICA_MSG_FIXED_SIZE,PICA_PROTO_N2NCONNREQOUTG_SIZE,procmsg_N2NCONNREQOUTG}, +{PICA_PROTO_N2NALLOW,PICA_MSG_FIXED_SIZE,PICA_PROTO_N2NALLOW_SIZE,procmsg_N2NALLOW}, +{PICA_PROTO_N2NNOTFOUND,PICA_MSG_FIXED_SIZE,PICA_PROTO_N2NNOTFOUND_SIZE,procmsg_N2NNOTFOUND}, +{PICA_PROTO_N2NMSG,PICA_MSG_VAR_SIZE,PICA_MSG_VARSIZE_INT16,procmsg_N2NMSG} +}; + +struct PICA_msginfo _msginfo_newconn[]={ +{PICA_PROTO_INITREQ,PICA_MSG_FIXED_SIZE,PICA_PROTO_INITREQ_SIZE,procmsg_INITREQ}, +{PICA_PROTO_CONNID,PICA_MSG_FIXED_SIZE,PICA_PROTO_CONNID_SIZE,procmsg_CONNID}, +{PICA_PROTO_NODECONNREQ,PICA_MSG_FIXED_SIZE,PICA_PROTO_NODECONNREQ_SIZE,procmsg_NODECONNREQ} +}; + + + +unsigned int procmsg_INITREQ(unsigned char* buf,unsigned int size,void* ptr) +{ +struct newconn *nc=(struct newconn*)ptr; +struct PICA_proto_msg *mp; + +if (buf[2]==PICA_PROTO_VER_HIGH && buf[3]==PICA_PROTO_VER_LOW) + { + struct client *c; + c=client_list_addnew(nc); + if (!c) + return 0; + + newconn_free(nc); + + if (mp=client_wbuf_push(c,PICA_PROTO_INITRESPOK,PICA_PROTO_INITRESPOK_SIZE)) + { + mp->tail[0]='O'; + mp->tail[1]='K'; + } + + c->state=PICA_CLSTATE_SENDINGRESP; + printf("got PICA_PROTO_INITREQ from client\n");//debug + }///////---------<<<<<<<<<<< new client +else + { + //// PICA_PROTO_VERDIFFER + send(nc->sck,msg_VERDIFFER,msg_VERDIFFER_len,0); + return 0; + } + +return 1; +} + +unsigned int procmsg_CONNID(unsigned char* buf,unsigned int size,void* ptr) +{ +struct PICA_proto_msg *mp; +struct newconn *nc=(struct newconn*)ptr; +unsigned int caller_id,callee_id; +struct cclink *link; + +puts("received CONNID");//debug + +caller_id=*((unsigned int*)(buf+2)); +callee_id=*((unsigned int*)(buf+6)); + +printf("CONNID: caller_id=%u callee_id=%u\n",caller_id,callee_id);//debug + +link=cclink_list_search(caller_id,callee_id); + +if (!link) + return 0; + +puts("\ncclink found");//debug + +printf("link->state = %i\n", link->state);//debug + +if (link->state!=PICA_CCLINK_LOCAL_WAITCONNCLE && link->state!=PICA_CCLINK_LOCAL_WAITCONNCLR + && link->state!=PICA_CCLINK_N2NCLR_WAITCONNCLR && link->state!=PICA_CCLINK_N2NCLE_WAITCONNCLE) + return 0; + +{ +struct client *c; +//проверка IP адреса. +//IP адрес должен совпадать с адресом клиента в управляющем соединении + +if (link->state==PICA_CCLINK_LOCAL_WAITCONNCLE || link->state==PICA_CCLINK_N2NCLE_WAITCONNCLE) + c = link->p2; +else if (link->state==PICA_CCLINK_LOCAL_WAITCONNCLR || link->state==PICA_CCLINK_N2NCLR_WAITCONNCLR) + c = link->p1; + +if (nc->addr.sin_addr.s_addr!=c->addr.sin_addr.s_addr) + { + puts("IP check failed");//debug + return 0; + } +} + +if (link->state==PICA_CCLINK_LOCAL_WAITCONNCLE) + { + if(mp=client_wbuf_push(link->p1,PICA_PROTO_FOUND,PICA_PROTO_FOUND_SIZE)) + { + *((unsigned int*)mp->tail)=callee_id; + } + else + { + puts("unable to send FOUND to caller");//debug + cclink_list_delete(link); + return 0; + } + } + +if (link->state==PICA_CCLINK_N2NCLE_WAITCONNCLE) + { + if(mp=nodelink_wbuf_push(link->caller_node,PICA_PROTO_N2NALLOW,PICA_PROTO_N2NALLOW_SIZE)) + { + *((unsigned int*)mp->tail)=caller_id; + *((unsigned int*)(mp->tail+4))=callee_id; + } + else + { + puts("unable to send N2NALLOW to caller node");//debug + cclink_list_delete(link); + return 0; + } + } + +cclink_activate(link,nc->sck); +newconn_free(nc); +return 1; +} + +unsigned int procmsg_NODECONNREQ(unsigned char* buf,unsigned int size,void* ptr) +{ +struct newconn *nc=(struct newconn*)ptr; +struct PICA_proto_msg *mp; + +if (buf[2]==PICA_PROTO_VER_HIGH && + buf[3]==PICA_PROTO_VER_LOW) + { + ////-прием входящего подключения + //-------------------------- + struct nodelink *nl; + nl=nodelink_list_addnew(nc); + newconn_free(nc); + if (!nl) + return 0; + + if (mp=nodelink_wbuf_push(nl,PICA_PROTO_INITRESPOK,PICA_PROTO_INITRESPOK_SIZE)) + { + mp->tail[0]='O'; + mp->tail[1]='K'; + } + } +else + { + //// PICA_PROTO_VERDIFFER + send(nc->sck,msg_VERDIFFER,msg_VERDIFFER_len,0); + return 0; + } + +return 1; +} + + +void mapfunc_sendsearchreq(struct nodelink *p,unsigned int id) +{ +struct PICA_proto_msg *mp; + +mp=nodelink_wbuf_push(p,PICA_PROTO_SEARCH,PICA_PROTO_SEARCH_SIZE); + +if (mp) + *((unsigned int*)mp->tail) = id; + +} + +int nodelink_send_searchreq(unsigned int id) +{ +if (!nodelink_list_count) + return 0; + +LISTMAP(nodelink,nodelink,mapfunc_sendsearchreq,id); + +return 1; +} + +unsigned int procmsg_CONNREQOUTG(unsigned char* buf,unsigned int size,void* ptr) +{ +struct client *i,*o;//i - указатель на вызывающего клиента, o - вызываемого(если найден) +unsigned int callee_id; +struct PICA_proto_msg *mp; + +puts("procmsg_CONNREQOUTGOING");//debug + +i=(struct client *)ptr; + +callee_id=*(unsigned int*)(buf+2); + +if (o=client_tree_search(callee_id)) + { + #warning "duplicated connections" // сделать проверку на наличие уже имеющегося соединения между клиентами + // и если оно есть, то разрывать его, либо... ???? надо подумать + + #warning "self" // а еще - если клиент вызывает сам себя? + + //отправить o _CONNREQINC + if (mp=client_wbuf_push(o,PICA_PROTO_CONNREQINC,PICA_PROTO_CONNREQINC_SIZE)) + { + *((unsigned int*)mp->tail)=i->id; + cclink_list_addlocal(i,o); + return 1; + } + + return 1;//сообщение отправить не удалось, но все равно возвращаем 1 + } + +if (cclink_list_findwaitsearch(callee_id)/*search request for this id is already in progress*/ + || nodelink_send_searchreq(callee_id) /*make new search*/) + { + cclink_list_addn2nclr(i,callee_id); + return 1; + } + +//отправить i _NOTFOUND +if (mp=client_wbuf_push(i,PICA_PROTO_NOTFOUND,PICA_PROTO_NOTFOUND_SIZE)) + { + *((unsigned int*)mp->tail)=callee_id; + puts("sending NOTFOUND... put to senq q...");//debug + } + +return 1; +} + +unsigned int procmsg_CONNALLOW(unsigned char* buf,unsigned int size,void* ptr) +{ +struct client *caller,*callee; +struct cclink *link; +unsigned int caller_id; + +puts("procmsg_CONNALLOW");//debug + +callee=(struct client *)ptr; +caller_id=*(unsigned int*)(buf+2); + +puts("procmsg_CONNALLOW_");//debug +printf("ptr=%X\n",ptr);//debug + +puts("procmsg_CONNALLOW__");//debug + + +link=cclink_list_search(caller_id,callee->id); + +if (!link) + return 0; + +if (link->state!=PICA_CCLINK_LOCAL_WAITREP && + link->state!=PICA_CCLINK_N2NCLE_WAITREP) + return 0; + +cclink_setwaitconn(link); + +puts("procmsg_CONNALLOW - return 1");//debug +return 1; +} + +unsigned int procmsg_CONNDENY(unsigned char* buf,unsigned int size,void* ptr) +{ +struct client *caller,*callee; +struct cclink *link; +unsigned int caller_id; +struct PICA_proto_msg *mp; + +puts("procmsg_procmsg_CONNDENY");//debug + +callee=(struct client *)ptr; +caller_id=*(unsigned int*)(buf+2); + +link=cclink_list_search(caller_id,callee->id); + +if (!link) + return 0; + +caller = link -> p1;//check for NULL if not LOCAL + +if (link->state!=PICA_CCLINK_LOCAL_WAITREP && + link->state!=PICA_CCLINK_N2NCLE_WAITREP) + { + cclink_list_delete(link); + return 0; + } + +if (link->state==PICA_CCLINK_LOCAL_WAITREP) + { + //отправить caller _NOTFOUND + if (mp=client_wbuf_push(caller,PICA_PROTO_NOTFOUND,PICA_PROTO_NOTFOUND_SIZE)) + { + *((unsigned int*)mp->tail)=callee->id; + } + } +else if (link->state==PICA_CCLINK_N2NCLE_WAITREP) + { + //отправить caller N2NNOTFOUND + if (mp=nodelink_wbuf_push(link->caller_node,PICA_PROTO_N2NNOTFOUND,PICA_PROTO_N2NNOTFOUND_SIZE)) + { + *((unsigned int*)mp->tail)=caller_id; + *( ((unsigned int*)mp->tail)+1)=callee->id; + } + } + +cclink_list_delete(link); + +return 1; +} + +unsigned int procmsg_NODERESP(unsigned char* buf,unsigned int size,void* ptr) +{ +switch(buf[0]) + { + case PICA_PROTO_INITRESPOK: + if (buf[2]!='O' || buf[3]!='K') + return 0; + + *((int*)ptr)=0; + break; + case PICA_PROTO_VERDIFFER: + ((char*)ptr)[0]=buf[2]; + ((char*)ptr)[1]=buf[3]; + break; + } + +return 1; +} + +unsigned int procmsg_NEWNODE(unsigned char* buf,unsigned int size,void* ptr) +{ +struct nodelink *n=(struct nodelink *)ptr; + +switch (buf[0]) + { + case PICA_PROTO_NEWNODE_IPV4: + printf("NEWNODE_IPV4: ip %.16s port %hu\n",inet_ntoa(*(struct in_addr*)(buf+2)),ntohs(*(uint16_t*)(buf+6)));//debug + { + struct PICA_nodeaddr_ipv4 na_ipv4; + + na_ipv4.magick=PICA_PROTO_NEWNODE_IPV4; + na_ipv4.addr=*(in_addr_t*)(buf+2); + na_ipv4.port=*(in_port_t*)(buf+6); + //int nodelink_attach_nodeaddr(struct nodelink *nl, unsigned int addr_type, void* nodeaddr, unsigned int nodeaddr_size) + nodelink_attach_nodeaddr(n,na_ipv4.magick,&na_ipv4,sizeof(struct PICA_nodeaddr_ipv4)); + } + break; + case PICA_PROTO_NEWNODE_IPV6: + #warning "TO DO" + break; + case PICA_PROTO_NEWNODE_DNS: + #warning "TODO" + break; + } + + + +return 1; +} + +unsigned int procmsg_NODELISTREQ(unsigned char* buf,unsigned int size,void* ptr) +{ +struct PICA_proto_msg *mp; +struct nodelink *nlp; +unsigned int nl_size=0; +struct nodelink *n=0; +struct client *c=0; + +switch(buf[0]) + { + case PICA_PROTO_CLNODELISTREQ: + c = (struct client *)ptr; + break; + case PICA_PROTO_NODELISTREQ: + n = (struct nodelink *)ptr; + break; + } + +unsigned char *nl_buf=malloc(65536); + +if (!nl_buf) + return 0;//ERR + +puts("NODELISTREQ");//debug + +{//TEMP FIXME CONF +//собственный адрес узла +nl_buf[nl_size]=PICA_PROTO_NEWNODE_IPV4; +*((in_addr_t*)(nl_buf+nl_size+1))=inet_addr(my_addr); +*((uint16_t*)(nl_buf+nl_size+5))=htons(PICA_COMM_PORT); +nl_size+=PICA_PROTO_NODELIST_ITEM_IPV4_SIZE; +} + +nlp=nodelink_list_head; +while(nlp && nl_size < 65532)//MAP + { + switch(nlp->addr_type) + { + case PICA_PROTO_NEWNODE_IPV4: + if ( PICA_PROTO_NODELISTREQ == buf[0] && + ((struct PICA_nodeaddr_ipv4*)nlp->node_addr)->addr==((struct PICA_nodeaddr_ipv4*)n->node_addr)->addr && + ((struct PICA_nodeaddr_ipv4*)nlp->node_addr)->port==((struct PICA_nodeaddr_ipv4*)n->node_addr)->port ) + break;//exclude requester's address + + nl_buf[nl_size]=PICA_PROTO_NEWNODE_IPV4; + *((in_addr_t*)(nl_buf+nl_size+1)) = ((struct PICA_nodeaddr_ipv4*)nlp->node_addr)->addr; + *((uint16_t*)(nl_buf+nl_size+5)) = ((struct PICA_nodeaddr_ipv4*)nlp->node_addr)->port; + nl_size += PICA_PROTO_NODELIST_ITEM_IPV4_SIZE;//CONF + break; + } +//#warning "set limit on list size, <65532 bytes!!!" + nlp = nlp->next; + } + +switch(buf[0]) + { + case PICA_PROTO_CLNODELISTREQ: + mp = client_wbuf_push( c, PICA_PROTO_CLNODELIST, nl_size+4); + break; + case PICA_PROTO_NODELISTREQ: + mp = nodelink_wbuf_push( n, PICA_PROTO_NODELIST, nl_size+4); + break; + } + +if (mp) + { + *((uint16_t*)mp->tail)=nl_size; + memcpy(mp->tail+2,nl_buf,nl_size); + } + +free(nl_buf); +return 1; +} + +unsigned int procmsg_NODELIST(unsigned char* buf,unsigned int size,void* ptr) +{ +struct PICA_nodeaddr_ipv4 na_ipv4; + +struct nodelink *n=(struct nodelink *)ptr; +unsigned int listsize=size-2-PICA_MSG_VARSIZE_INT16; +unsigned int listleft=listsize; + +puts("NODELIST");//debug +printf("NODELIST_SIZE:%u\n",listsize); + +while(listleft) + { +#warning "strict error checking!!! -- listleft overflow, unknown list items, check listleft >= possible item size" + if (listleft==listsize) //first entry, sender node's address + { + switch(buf[size-listleft]) + { + case PICA_PROTO_NEWNODE_IPV4: + na_ipv4.magick=PICA_PROTO_NEWNODE_IPV4; + na_ipv4.addr=*(in_addr_t*)(buf+size-listleft+1); + na_ipv4.port=*(in_port_t*)(buf+size-listleft+5); + nodelink_attach_nodeaddr(n,na_ipv4.magick,&na_ipv4,sizeof(struct PICA_nodeaddr_ipv4)); + + listleft-=PICA_PROTO_NODELIST_ITEM_IPV4_SIZE; + break; + } + continue; + } + else + { + char addr[256]; + struct newconn nc; + struct nodelink *nlp; + + memset(addr,0,256); + memset(&nc,0,sizeof(struct newconn)); + + switch(buf[size-listleft]) + { + case PICA_PROTO_NEWNODE_IPV4: + na_ipv4.magick=PICA_PROTO_NEWNODE_IPV4; + na_ipv4.addr=*(in_addr_t*)(buf+size-listleft+1); + na_ipv4.port=*(in_port_t*)(buf+size-listleft+5); + + sprintf(addr,"%.16s",inet_ntoa(*(struct in_addr*)&na_ipv4.addr)); + if (try_connect_to_node(addr,ntohs(na_ipv4.port),&nc)) + if (try_get_reply(&nc)) + { + nlp=nodelink_list_addnew(&nc); + send_newnode(nlp,my_addr); + nodelink_attach_nodeaddr(nlp,na_ipv4.magick,&na_ipv4,sizeof(struct PICA_nodeaddr_ipv4)); + printf("LINKED NODE:%s\n",inet_ntoa(*(struct in_addr*)&na_ipv4.addr));//debug + } + + listleft-=PICA_PROTO_NODELIST_ITEM_IPV4_SIZE; + break; + } + } + } + +return 1; +} + +unsigned int procmsg_N2NFOUND(unsigned char* buf,unsigned int size,void* ptr) +{ +struct cclink *cc; +struct nodelink *n=(struct nodelink *)ptr; +unsigned int callee_id=*(unsigned int*)(buf+2); +struct PICA_proto_msg *mp; + +while(cc=cclink_list_findwaitsearch(callee_id)) + { + cclink_attach_remotecle_node(cc,n); + if(mp=nodelink_wbuf_push(n,PICA_PROTO_N2NCONNREQOUTG,PICA_PROTO_N2NCONNREQOUTG_SIZE)) + { + *((unsigned int*)mp->tail) = cc->caller_id; + *((unsigned int*)(mp->tail+4)) = callee_id; + } + } +return 1; +} + +unsigned int procmsg_SEARCH(unsigned char* buf,unsigned int size,void* ptr) +{ +struct nodelink *n=(struct nodelink *)ptr; +unsigned int callee_id=*(unsigned int*)(buf+2); +struct PICA_proto_msg *mp; +struct client *callee; + +if (callee=client_tree_search(callee_id)) + { + if(mp=nodelink_wbuf_push(n,PICA_PROTO_N2NFOUND,PICA_PROTO_N2NFOUND_SIZE)) + { + *((unsigned int*)mp->tail) = callee_id; + } + } +return 1; +} + +unsigned int procmsg_N2NCONNREQOUTG(unsigned char* buf,unsigned int size,void* ptr) +{ +struct nodelink *n=(struct nodelink *)ptr; +unsigned int caller_id,callee_id; +struct PICA_proto_msg *mp; +struct client *callee; + +caller_id=*(unsigned int*)(buf+2); +callee_id=*(unsigned int*)(buf+6); + +if (callee=client_tree_search(callee_id)) + { + if (mp=client_wbuf_push(callee,PICA_PROTO_CONNREQINC,PICA_PROTO_CONNREQINC_SIZE)) + { + *((unsigned int*)mp->tail)=caller_id; + cclink_list_addn2ncle(caller_id, n, callee); + } + } +else + { + if(mp=nodelink_wbuf_push(n,PICA_PROTO_N2NNOTFOUND,PICA_PROTO_N2NNOTFOUND_SIZE)) + { + *((unsigned int*)mp->tail) = caller_id; + *((unsigned int*)(mp->tail+4)) = callee_id; + } + } +return 1; +} + +unsigned int procmsg_N2NALLOW(unsigned char* buf,unsigned int size,void* ptr) +{ +struct nodelink *n=(struct nodelink *)ptr; +unsigned int caller_id,callee_id; +struct PICA_proto_msg *mp; +struct cclink *cc; + +caller_id=*(unsigned int*)(buf+2); +callee_id=*(unsigned int*)(buf+6); + +cc=cclink_list_search(caller_id,callee_id); + +if (cc) + { + if (mp=client_wbuf_push(cc->p1,PICA_PROTO_FOUND,PICA_PROTO_FOUND_SIZE)) + { + *((unsigned int*)mp->tail)=callee_id; + + cclink_setwaitconn(cc); + } + } +return 1; +} + +unsigned int procmsg_N2NNOTFOUND(unsigned char* buf,unsigned int size,void* ptr) +{ +struct nodelink *n=(struct nodelink *)ptr; +unsigned int caller_id,callee_id; +struct PICA_proto_msg *mp; +struct cclink *cc; + +caller_id=*(unsigned int*)(buf+2); +callee_id=*(unsigned int*)(buf+6); + +cc=cclink_list_search(caller_id,callee_id); + +if (cc) + { + if (mp=client_wbuf_push(cc->p1,PICA_PROTO_NOTFOUND,PICA_PROTO_NOTFOUND_SIZE)) + { + *((unsigned int*)mp->tail)=callee_id; + } + cclink_list_delete(cc); + } + +return 1; +} + +unsigned int procmsg_N2NMSG(unsigned char* buf,unsigned int size,void* ptr) +{ +struct nodelink *n=(struct nodelink *)ptr; +struct PICA_proto_msg *mp; +unsigned int sender_id,receiver_id; +struct cclink *cc; +unsigned int len,datalen; + +len=*(unsigned short*)(buf+2); +sender_id=*(unsigned int*)(buf+4); +receiver_id=*(unsigned int*)(buf+8); + +if (len<8) + return 0; +datalen=len-8; + +cc=cclink_list_search(sender_id,receiver_id); + +if (cc && cc->state==PICA_CCLINK_N2NCLE_ACTIVE) + { + if (datalen + cc->bufpos_p1p2 > cc->buflen_p1p2) + { + cclink_list_delete(cc);//CLOSING CCLINK DUE TO BUFER OVERRUN --------- FIXME FIX FIX FIX + return 1; + } + + memcpy(cc->buf_p1p2 + cc->bufpos_p1p2, buf+12,datalen); + cc->bufpos_p1p2 += datalen; + return 1; + } +/////////////// +cc=cclink_list_search(receiver_id,sender_id); + +if (cc && cc->state==PICA_CCLINK_N2NCLR_ACTIVE) + { + if (datalen + cc->bufpos_p2p1 > cc->buflen_p2p1) + { + cclink_list_delete(cc);//CLOSING CCLINK DUE TO BUFER OVERRUN --------- FIXME FIX FIX FIX + return 1; + } + + memcpy(cc->buf_p2p1 + cc->bufpos_p2p1, buf+12,datalen); + cc->bufpos_p2p1 += datalen; + return 1; + } + +if(mp=nodelink_wbuf_push(n,PICA_PROTO_N2NNOTFOUND,PICA_PROTO_N2NNOTFOUND_SIZE)) + { + *((unsigned int*)mp->tail) = sender_id; + *((unsigned int*)(mp->tail+4)) = receiver_id; + } + +return 1; +} + + +struct cclink* cclink_list_findwaitsearch(unsigned int callee_id) +{ +struct cclink *c; +c = cclink_list_head; +while(c) + { + if (c->callee_id == callee_id && c->state==PICA_CCLINK_N2NCLR_WAITSEARCH) + return c; + c=c->next; + } +return 0; +} + +struct cclink* cclink_list_search(unsigned int caller_id, unsigned int callee_id) +{ +struct cclink *c; +c= cclink_list_head; + +while(c) + { + if (c->caller_id == caller_id && c->callee_id == callee_id) + return c; + c=c->next; + } +return 0; +} + +void cclink_list_delete(struct cclink *l) +{ +//удаление из глобального списка +if (l->prev) + l->prev->next=l->next; +else + cclink_list_head=l->next; + +if (l->next) + l->next->prev=l->prev; +else + cclink_list_end=l->prev; + +if (l->p1) + if (l->sck_p1) + { + SHUTDOWN(l->sck_p1); + CLOSE(l->sck_p1); + } + +if (l->p2) + if (l->sck_p2) + { + SHUTDOWN(l->sck_p2); + CLOSE(l->sck_p2); + } + + +if (l->buf_p1p2) + free(l->buf_p1p2); + +if (l->buf_p2p1) + free(l->buf_p2p1); + +free(l); +cclink_list_count--; +} + + +//clr - caller +//cle - callee +// null value of clr or cle means that corresponding client is on remote node, is not local client +struct cclink* cclink_list_add(struct client *clr,struct client *cle) +{ +struct cclink *l; + +puts("cclink_list_add");//debug + +l=(struct cclink*)calloc(sizeof(struct cclink),1); + +if (!l) + return 0; + +//l->state=PICA_LINKSTATE_WAITREP; + +l->p1=clr; +l->p2=cle; + +//добавление в глобальный список +if (cclink_list_head) + { + cclink_list_end->next=l; + l->prev=cclink_list_end; + cclink_list_end=l; + } +else + { + cclink_list_head=l; + cclink_list_end=l; + } + +//timestamp +l->tmst=time(0); + +cclink_list_count++; + +return l; +} + + +void cclink_list_addlocal(struct client *clr,struct client *cle) +{ +struct cclink *l; + +l=cclink_list_add(clr,cle); + +if (l) + { + l->state=PICA_CCLINK_LOCAL_WAITREP; + l->caller_id = l->p1->id; + l->callee_id = l->p2->id; + } + +} + +void cclink_list_addn2nclr(struct client *clr,unsigned int callee_id) +{ +struct cclink *l; + +l=cclink_list_add(clr,0); + +if (l) + { + l->state=PICA_CCLINK_N2NCLR_WAITSEARCH; + l->caller_id = l->p1->id; + l->callee_id = callee_id; + } +} + +void cclink_attach_remotecle_node(struct cclink *ccl, struct nodelink *callee_node) +{ +if (ccl && ccl->state==PICA_CCLINK_N2NCLR_WAITSEARCH) + { + ccl->state=PICA_CCLINK_N2NCLR_WAITREP; + ccl->callee_node=callee_node; + } +} + +void cclink_list_addn2ncle(unsigned int caller_id, struct nodelink *caller_node, struct client *cle) +{ +struct cclink *l; + +l=cclink_list_add(0,cle); + +if (l) + { + l->state=PICA_CCLINK_N2NCLE_WAITREP; + l->caller_id = caller_id; + l->callee_id = l->p2->id; + l->caller_node = caller_node; + } + +} + +void cclink_setwaitconn(struct cclink *ccl) +{ +switch (ccl->state) + { + case PICA_CCLINK_LOCAL_WAITREP: + ccl->state=PICA_CCLINK_LOCAL_WAITCONNCLE; + // + break; + case PICA_CCLINK_N2NCLR_WAITREP: + ccl->state=PICA_CCLINK_N2NCLR_WAITCONNCLR; + break; + case PICA_CCLINK_N2NCLE_WAITREP: + ccl->state=PICA_CCLINK_N2NCLE_WAITCONNCLE; + break; + default: + ; + } +} + +int cclink_allocbufs(struct cclink *ccl) +{ +ccl->buf_p1p2 = malloc(DEFAULT_BUF_SIZE); +ccl->buf_p2p1 = malloc(DEFAULT_BUF_SIZE); +if (!ccl->buf_p1p2 || !ccl->buf_p2p1) + { + if (ccl->buf_p1p2) + free(ccl->buf_p1p2); + if (ccl->buf_p2p1) + free(ccl->buf_p2p1); + return 0; + } +ccl->buflen_p1p2 = DEFAULT_BUF_SIZE; +ccl->buflen_p2p1 = DEFAULT_BUF_SIZE; +return 1; +} + +void cclink_activate(struct cclink *ccl,SOCKET s) +{ +switch(ccl->state) + { + case PICA_CCLINK_LOCAL_WAITCONNCLE: + ccl->sck_p2 = s; + ccl->state = PICA_CCLINK_LOCAL_WAITCONNCLR; + break; + case PICA_CCLINK_LOCAL_WAITCONNCLR: + ccl->sck_p1 = s; + if (!cclink_allocbufs(ccl)) + { + cclink_list_delete(ccl); + return; + } + ccl->state = PICA_CCLINK_LOCAL_ACTIVE; + puts("caller cclink established");//debug + break; + case PICA_CCLINK_N2NCLR_WAITCONNCLR: + ccl->sck_p1 = s; + if (!cclink_allocbufs(ccl)) + { + cclink_list_delete(ccl); + return; + } + ccl->state = PICA_CCLINK_N2NCLR_ACTIVE; + break; + case PICA_CCLINK_N2NCLE_WAITCONNCLE: + ccl->sck_p2 = s; + if (!cclink_allocbufs(ccl)) + { + cclink_list_delete(ccl); + return; + } + ccl->state = PICA_CCLINK_N2NCLE_ACTIVE; + break; + } +} + + +int PICA_node_init() +{ +struct sockaddr_in sd; + +SSL_load_error_strings(); +SSL_library_init(); + +puts("This product includes software developed by the OpenSSL Project\n\ +for use in the OpenSSL Toolkit (http://www.openssl.org/\n"); +puts("This product includes cryptographic software written by\n\ +Eric Young (eay@cryptsoft.com)\n"); +puts(SSLeay_version(SSLEAY_VERSION)); + + +#ifdef WIN32 +WSADATA wsd; +WSAStartup(MAKEWORD(2,2),&wsd); +#endif + +//CONF -AF_INET6 ???? +listen_comm_sck=socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); +//ERR_CHECK + +memset(&sd,0,sizeof(sd)); + +sd.sin_family=AF_INET; +sd.sin_addr.s_addr=INADDR_ANY;//CONF +sd.sin_port=htons(PICA_COMM_PORT);//CONF + +bind(listen_comm_sck,(struct sockaddr*)&sd,sizeof(sd)); +listen(listen_comm_sck,20); +//ERR_CHECK + +{ +int ret_comm; +unsigned long arg=1; +#ifdef WIN32 +ret_comm=ioctlsocket(listen_comm_sck,FIONBIO,&arg); +// ret_data=ioctlsocket(listen_data_sck,FIONBIO,&arg); +// ret_data=ioctlsocket(listen_node_sck,FIONBIO,&arg); +#else +ret_comm=ioctl(listen_comm_sck,FIONBIO,(int*)&arg); +// ret_data=ioctl(listen_data_sck,FIONBIO,(int*)&arg); +// ret_data=ioctl(listen_node_sck,FIONBIO,(int*)&arg); +#endif +printf("ioctl ret_comm=%i\n",ret_comm);//debug +} + +#ifdef NO_RAND_DEV +PICA_rand_seed(); +#endif + +ctx=SSL_CTX_new(TLSv1_method()); + +if (!ctx) +;//ERR_CHECK + +return 1; +} + +//функция возвращает номер клиента id в бинарном виде, извлекая его из строки, +//которая возвращается функцией X509_NAME_oneline и представляет собой DN из сертификата клиента +int get_id_fromsubjstr(char* DN_str,unsigned int* id) +{ +char* tmp1; +char* tmp2; + +tmp1=strstr(DN_str,"/CN="); + +if (!tmp1) + return 0; + +tmp2=strchr(tmp1,'#'); + +if (!tmp2) + return 0; + +*tmp2=0; + +tmp1+=4; + +if (tmp1==tmp2) + return 0; + +*id=(unsigned int)strtol(tmp1,0,10); + +*tmp2='#'; +return 1; +} + + +void newconn_close(struct newconn* nc) +{ +CLOSE(nc->sck); + + +nc->sck=0; +nc->pos=0; printf("newconn_close: closing connection\n");//debug +} + +//функция ищет свободный элемент в массиве структур newconn и возвращает на него указатель +//В случае, если свободный элемент не найден, возвращается элемент с наиболее поздней отметкой времени, +//при этом соединение закрывается +struct newconn* newconn_add(struct newconn *ncs,int *pos) +{ +time_t min; +int min_pos=0; +if (*pos<MAX_NEWCONNS && !ncs[*pos].sck) + { + goto ret; + } +else + { + *pos=0; + min=ncs->tmst; + while(ncs[*pos].sck && *pos<MAX_NEWCONNS) + { + if (ncs[*pos].tmst<min) + { + min=ncs[*pos].tmst; + min_pos=*pos; + } + (*pos)++; + } + + if ( (*pos)==MAX_NEWCONNS) + { + *pos=min_pos; + SHUTDOWN(ncs[min_pos].sck); + CLOSE(ncs[min_pos].sck); + } + } + +ret: +ncs[*pos].pos=0; +ncs[*pos].tmst=time(0); +return &ncs[(*pos)++]; +} + +void newconn_free(struct newconn* nc) +{ +nc->sck=0; +//nc->pos=0; - pos value is being used in processmsgdatastream +} + +int client_tree_add(struct client *ci) +{ +struct client *i; +if (client_tree_root) + { + i=client_tree_root; + + do + { + if (i->id==ci->id) + return 0; + + if (ci->id < i->id) + { + if (i->left) + i=i->left; + else + { + i->left=ci; + ci->up=i; + return 1; + } + } + else + { + if (i->right) + i=i->right; + else + { + i->right=ci; + ci->up=i; + return 1; + } + } + } + while(1); + } +else + client_tree_root=ci; + +return 1; +} + +struct client* client_tree_search(unsigned int id)//надо бы потестить +{ +struct client* i_ptr; +i_ptr=client_tree_root; + +printf("client_tree_search: searching for %u...\n",id);//debug + +while(i_ptr) + { + if (i_ptr->id==id) + return i_ptr; + + if (id < i_ptr->id) + i_ptr=i_ptr->left; + else + i_ptr=i_ptr->right; + } + +puts("client_tree_search- id not found");//debug +return 0; +} + +void client_tree_print(struct client *c) +{ +if (!c) + { + puts("NULL"); + return; + } + +printf("%p: %u LEFT: %p, RIGHT: %p\n", c, c->id, c->left, c->right); + +if (c->left) + client_tree_print(c->left); + +if (c->right) + client_tree_print(c->right); +} + +//удаление структуры из дерева +void client_tree_remove(struct client* ci) +{ +struct client** p_link;//указывает на left или right в родительском узле + +if (!ci->up) + { + p_link = &client_tree_root; + } +else + { + if (ci==ci->up->left) + p_link=&(ci->up->left); + else + p_link=&(ci->up->right); + } + + +if (!ci->left && !ci->right) + { + *p_link=0; + return; + } + +if (ci->left && !ci->right) + { + ci->left->up=ci->up; + *p_link=ci->left; + return; + } + +if (!ci->left && ci->right) + { + ci->right->up=ci->up; + *p_link=ci->right; + return; + } + + + { + struct client *lm; + lm=ci->right; + while(lm->left) lm=lm->left;//поиск самого левого узла правого поддерева + + if (lm!=ci->right) + { + lm->up->left=lm->right; + lm->right=ci->right; + } + lm->left=ci->left; + lm->up=ci->up; + *p_link=lm; + } +} + +struct client *client_list_addnew(struct newconn *nc) +{ +struct client* ci; + +ci=(struct client *)calloc(1,sizeof(struct client)); + +if (!ci) return 0; + +ci->ssl_comm =SSL_new (ctx); + +if (!ci->ssl_comm) + { + free(ci); + return 0; + } + +if (client_list_end) + { + client_list_end->next=ci; + ci->prev=client_list_end; + client_list_end=ci; + } +else + { + client_list_head=ci; + client_list_end=ci; + } + +ci->sck_comm=nc->sck; +ci->addr=nc->addr; + + +SSL_set_fd(ci->ssl_comm,ci->sck_comm); + +//ci->state=PICA_CLSTATE_SENDINGRESP; + +printf("client_list_addnew: returning %X\n",ci);//debug +return ci; +} + +void client_list_delete(struct client* ci) +{ +printf("client_list_delete: ci=%X\n",ci);//debug + +SSL_free(ci->ssl_comm); +//удаление из списка +if (ci->prev) + ci->prev->next=ci->next; +else + client_list_head=ci->next; + +if (ci->next) + ci->next->prev=ci->prev; +else + client_list_end=ci->prev; + +//удаление из дерева +if (client_tree_search(ci->id) == ci) + { + client_tree_remove(ci); + client_tree_print(client_tree_root);//debug + } + + +CLOSE(ci->sck_comm); + +free(ci); +} + +struct PICA_proto_msg* client_wbuf_push + (struct client *c,unsigned int msgid,unsigned int size) +{ +//Дальнейший вариант - размер буфера w_buf может увеличиться в +//этой функции путем вызова realloc, если размер сообщения превышает половину +//текущего размера буфера +//Если буфер занят меньше, чем на половину, его размер может уменьшаться где-нибудь +//в другом месте, для экономии памяти + if (CL_WBUFSIZE - c->w_pos >= size) + { + struct PICA_proto_msg *mp=(struct PICA_proto_msg *)(c->w_buf + c->w_pos); + mp->head[0]=mp->head[1]=msgid; + c->w_pos+=size; + return mp; + } + else + return 0; +} + +struct nodelink *nodelink_list_addnew(struct newconn *nc) +{ +struct nodelink *nl; + +nl=(struct nodelink*)calloc(1,sizeof(struct nodelink)); + +if (!nl) + return 0; + +if (nodelink_list_end) + { + nodelink_list_end->next=nl; + nl->prev=nodelink_list_end; + nodelink_list_end=nl; + } +else + { + nodelink_list_head=nl; + nodelink_list_end=nl; + } + +nl->sck=nc->sck; +nl->addr=nc->addr; + +nl->r_buf=calloc(1,DEFAULT_BUF_SIZE); +if (!nl->r_buf) + { + free(nl); + return 0; + } +nl->buflen_r=DEFAULT_BUF_SIZE; + +printf("nodelink_list_addnew: returning %X\n",nl);//debug +nodelink_list_count++; +return nl; +} + +void nodelink_list_delete(struct nodelink *n) +{ +if (n->r_buf) + free(n->r_buf); + +if (n->w_buf) + free(n->w_buf); + +if (n->node_addr) + free(n->node_addr); + +CLOSE(n->sck); + +if (n->prev) + n->prev->next=n->next; +else + nodelink_list_head=n->next; + +if (n->next) + n->next->prev=n->prev; +else + nodelink_list_end=n->prev; + +nodelink_list_count--; +free(n); +} + +int nodelink_attach_nodeaddr(struct nodelink *nl, unsigned int addr_type, void* nodeaddr, unsigned int nodeaddr_size) +{ +if (nl && nodeaddr) + { + if (nl->node_addr) + free(nl->node_addr); + + nl->node_addr=malloc(nodeaddr_size); + if (!nl->node_addr) + return 0;//ERR_CHECK + memcpy(nl->node_addr,nodeaddr,nodeaddr_size); + + nl->addr_type=addr_type; + return 1; + } +return 0; +} + +int nodelink_rbuf_grow(struct nodelink *nl) +{ +unsigned char *p; + +puts(__FUNCTION__);//debug + +p=realloc(nl->r_buf,nl->buflen_r + DEFAULT_BUF_SIZE); + +if (!p) + { + puts("out of memory");//debug + return 0; + } +nl->r_buf = p; +nl->buflen_r +=DEFAULT_BUF_SIZE; + +return 1; +} + +struct PICA_proto_msg* nodelink_wbuf_push + (struct nodelink *nl,unsigned int msgid,unsigned int size) +{ +struct PICA_proto_msg *mp; + +if (!nl->w_buf) + { + nl->w_buf=calloc(1,DEFAULT_BUF_SIZE ); + if (!nl->w_buf) + { + puts("out of memory");//debug + return 0; + } + nl->buflen_w=DEFAULT_BUF_SIZE; + } + +if ((nl->buflen_w - nl->w_pos) < size) + { + unsigned char *p; + p=realloc(nl->w_buf,size + nl->w_pos); + + if (p) + { + nl->w_buf=p; + nl->buflen_w=size + nl->w_pos; + } + else + return 0; + } + +mp=(struct PICA_proto_msg *)(nl->w_buf + nl->w_pos); +mp->head[0]=mp->head[1]=msgid; +nl->w_pos+=size; +return mp; +} + + + +// обработка различных таймаутов. Отправка пингов + +void process_timeouts_newconn() +{ +clock_t t; +int i; + +t=time(0); + +for (i=0;i<MAX_NEWCONNS;i++) + { + if (newconns[i].sck) + { + if (newconns[i].tmst<t) + { + if (t-newconns[i].tmst>NEWCONN_TIMEOUT) + { + newconn_close(newconns+i); + puts("closing by timeout(1): ");//debug + } + } + else if ( newconns[i].tmst-t>NEWCONN_TIMEOUT) + { + newconn_close(newconns+i); + puts("closing by timeout(2): ");//debug + } + } + } +} + +void process_timeouts_c2c() +{ +struct cclink *il; + +il=cclink_list_head; + +while(il) + { + switch(il->state) + { + case PICA_CCLINK_LOCAL_ACTIVE: + case PICA_CCLINK_N2NCLR_ACTIVE: + case PICA_CCLINK_N2NCLE_ACTIVE: + + //idle timeout (>=60sec), update timestamp at process_c2c + + break; + default: + if ((time(0)- il->tmst)>TMO_CCLINK_WAITACTIVE) + { + struct cclink *dl; + dl=il; + il=il->next; + cclink_list_delete(dl); + puts("inactive cclink closed by timeout");//debug + continue; + } + } + il=il->next; + } +} + +int process_timeouts() +{ +process_timeouts_newconn(); +process_timeouts_c2c(); +//.. +return 1; +} + +void set_select_fd(SOCKET s, fd_set *readfds, int *nfds) +{ +FD_SET(s,readfds); + +if (s > *nfds) + *nfds=s; + +//printf("set_select_fd([socket %i ])\n",s);//debug +} + +void listen_set_fds(fd_set *readfds,int *nfds) +{ +set_select_fd(listen_comm_sck,readfds,nfds); +} + +void newconn_set_fds(fd_set *readfds,int *nfds) +{ +int i; + +for (i=0;i<MAX_NEWCONNS;i++) + if (newconns[i].sck) + set_select_fd(newconns[i].sck,readfds,nfds); +} + +void c2n_set_fds(fd_set *readfds,int *nfds) +{ +struct client *i_ptr; + +i_ptr=client_list_head; +while(i_ptr) + { + set_select_fd(i_ptr->sck_comm,readfds,nfds); + + i_ptr=i_ptr->next; + } +} + +void c2c_set_fds(fd_set *readfds,int *nfds) +{ +struct cclink *cc; + +cc=cclink_list_head; +while(cc) + { + if ( !cc->jam_p1p2 && (cc->state==PICA_CCLINK_LOCAL_ACTIVE || cc->state==PICA_CCLINK_N2NCLR_ACTIVE) ) + set_select_fd(cc->sck_p1,readfds,nfds); + + if ( !cc->jam_p2p1 && (cc->state==PICA_CCLINK_LOCAL_ACTIVE || cc->state==PICA_CCLINK_N2NCLE_ACTIVE) ) + set_select_fd(cc->sck_p2,readfds,nfds); + + cc=cc->next; + } +} + +void n2n_set_fds(fd_set *readfds,int *nfds) +{ +struct nodelink *nl; +nl=nodelink_list_head; + +while(nl) + { + set_select_fd(nl->sck,readfds,nfds); + nl=nl->next; + } +} + +void process_listen_read(fd_set *readfds) +{ +struct newconn *nc; +SOCKET s; +struct sockaddr_in addr; +int addrsize=sizeof(struct sockaddr_in); +if (FD_ISSET(listen_comm_sck,readfds)) + { + puts("accept");//debug + s=accept(listen_comm_sck,(struct sockaddr*)&addr,&addrsize); + + if (s>0) + { + nc=newconn_add(newconns,&newconns_pos); + + nc->sck=s; + nc->addr=addr; + printf("accepted connection\n");//debug + } + else + { + newconn_free(nc); + + perror("accept:");//debug + printf("accept error!\n");//debug + //ERR_CHECK + } + } + +//IPv6 +} + +void process_newconn_read(fd_set *readfds) +{ +int i,ret; + +for (i=0;i<MAX_NEWCONNS;i++) + if (newconns[i].sck && FD_ISSET(newconns[i].sck,readfds)) + { + ret=recv(newconns[i].sck,newconns[i].buf+newconns[i].pos,NEWCONN_BUFSIZE - newconns[i].pos,0); + + if (ret<=0) + { + perror("process_newconn_read - recv:");//debug + newconn_close(newconns+i); + continue; + } + newconns[i].pos+=ret; + + if(!PICA_processdatastream(newconns[i].buf,&(newconns[i].pos),newconns+i /*arg*/,_msginfo_newconn, MSGINFO_MSGSNUM(_msginfo_newconn) )) + { + puts("processdatastream error\n");//debug + newconn_close(newconns+i); + } + //FD_CLR(newconns[i].sck,readfds); + } +} + + + +void process_c2n_read(fd_set *readfds) +{ +struct client *i_ptr,*kill_ptr; +int ret; + +i_ptr=client_list_head; +kill_ptr=0; + +while (i_ptr) + { + if (FD_ISSET(i_ptr->sck_comm,readfds)) + switch(i_ptr->state) + { + case PICA_CLSTATE_CONNECTED: + ret=SSL_read(i_ptr->ssl_comm,i_ptr->r_buf+i_ptr->r_pos,CL_RBUFSIZE-i_ptr->r_pos); + + if (!ret) + kill_ptr=i_ptr; + + if (ret<0) + switch(SSL_get_error(i_ptr->ssl_comm,ret)) + { + case SSL_ERROR_WANT_WRITE: + case SSL_ERROR_WANT_READ: + break; + default: + kill_ptr=i_ptr; + } + + if (ret>0) + { + i_ptr->r_pos+=ret; + if(!PICA_processdatastream(i_ptr->r_buf,&(i_ptr->r_pos),i_ptr,_msginfo_comm, MSGINFO_MSGSNUM(_msginfo_comm) )) + kill_ptr=i_ptr; + + } + break; + case PICA_CLSTATE_TLSNEGOTIATION: + i_ptr->w_pos=1;//???? + //-------------- <<<<<<<<<<<<<<<<<<<<<<<<---------------------------------------- + break; + }; + + i_ptr=i_ptr->next; + + if (kill_ptr) + { + client_list_delete(kill_ptr); + kill_ptr=0; + } + } + +} + +void process_c2c_read(fd_set *readfds) +{ +int i,ret; +struct cclink *cc,*kill_ptr; + +cc=cclink_list_head; +kill_ptr=0; + +while(cc) + { + if ((cc->state==PICA_CCLINK_LOCAL_ACTIVE || cc->state==PICA_CCLINK_N2NCLR_ACTIVE) + && FD_ISSET(cc->sck_p1,readfds) && !cc->jam_p1p2 ) + { + ret=recv(cc->sck_p1,cc->buf_p1p2 + cc->bufpos_p1p2,cc->buflen_p1p2 - cc->bufpos_p1p2,0); + printf("DATA recv p1p2: ret=%i\n",ret);//debug + if (ret>0) + { + cc->bufpos_p1p2+=ret; + } + else + kill_ptr=cc; + } + + if ((cc->state==PICA_CCLINK_LOCAL_ACTIVE || cc->state==PICA_CCLINK_N2NCLE_ACTIVE) + && FD_ISSET(cc->sck_p2,readfds) && !cc->jam_p2p1 ) + { + ret=recv(cc->sck_p2,cc->buf_p2p1 + cc->bufpos_p2p1,cc->buflen_p2p1 - cc->bufpos_p2p1,0); + printf("DATA recv p2p1: ret=%i\n",ret);//debug + if (ret>0) + { + cc->bufpos_p2p1+=ret; + } + else + kill_ptr=cc; + } + + + cc=cc->next; + + if (kill_ptr) + { + cclink_list_delete(kill_ptr); + kill_ptr=0; + } + } +} + +void process_n2n_read(fd_set *readfds) +{ +int i,ret; +struct nodelink *nl,*kill_ptr; + +nl=nodelink_list_head; +kill_ptr=0; + +while(nl) + { + if (FD_ISSET(nl->sck,readfds)) + { + ret=recv(nl->sck,nl->r_buf+nl->r_pos,nl->buflen_r - nl->r_pos,0); + + if (ret<=0) + { + perror("n2n_read recv:");//debug + kill_ptr=nl; + } + else + { + nl->r_pos+=ret; + + if(!PICA_processdatastream(nl->r_buf,&(nl->r_pos),nl,_msginfo_node, MSGINFO_MSGSNUM(_msginfo_node) )) + kill_ptr=nl; + + if (nl->buflen_r == nl->r_pos) + if (!nodelink_rbuf_grow(nl)) + kill_ptr=nl; + } + } + + nl=nl->next; + + if (kill_ptr) + { + nodelink_list_delete(kill_ptr);puts("process_n2n_read - calling nodelink_list_delete");//debug + kill_ptr=0; + } + } +} + +void process_c2n_write() +{ +struct client *i_ptr,*kill_ptr; +int ret; + +i_ptr=client_list_head; +kill_ptr=0; + +while(i_ptr) + { + //--------- + switch(i_ptr->state) + { + case PICA_CLSTATE_CONNECTED: + if (!i_ptr->w_pos) + break; + + if (!i_ptr->btw_ssl) + i_ptr->btw_ssl=i_ptr->w_pos; + + ret=SSL_write(i_ptr->ssl_comm,i_ptr->w_buf,i_ptr->btw_ssl); + + printf("process_comm: write: ret of SSL_write=%i\n",ret);//debug + + if (ret==i_ptr->btw_ssl) + { + i_ptr->w_pos-=i_ptr->btw_ssl; + i_ptr->btw_ssl=0; + } + + if (!ret) + kill_ptr=i_ptr; + + if (ret<0) + { + ret=SSL_get_error(i_ptr->ssl_comm,ret); + if (ret!=SSL_ERROR_WANT_WRITE && ret!=SSL_ERROR_WANT_READ) + kill_ptr=i_ptr; + } + break; + case PICA_CLSTATE_SENDINGRESP: + ret=send(i_ptr->sck_comm,i_ptr->w_buf,i_ptr->w_pos,0); + printf("process_comm: write: sendingresp w_pos=%u ret=%i\n",i_ptr->w_pos,ret);//debug + if (!ret) + kill_ptr=i_ptr; + + if (ret==SOCKET_ERROR) + ;//ERR_CHECK + + if (ret < i_ptr->w_pos) + memmove(i_ptr->w_buf,i_ptr->w_buf+ret,i_ptr->w_pos - ret); //ring buffer is better (??) + + i_ptr->w_pos-=ret; + + + if (!i_ptr->w_pos) + i_ptr->state=PICA_CLSTATE_TLSNEGOTIATION; + + puts("SENDINGRESP");//debug + break; + case PICA_CLSTATE_TLSNEGOTIATION: + i_ptr->w_pos=0; + ret=SSL_connect(i_ptr->ssl_comm); + + printf("wr SSL_connect=%i\n",ret);//debug + + if (!ret) + kill_ptr=i_ptr; + + if (ret<0) + { + int eret; + eret=SSL_get_error(i_ptr->ssl_comm,ret); + switch(eret) + { + case SSL_ERROR_WANT_WRITE: + i_ptr->w_pos=1; + printf("wr WANT_WRITE\n");//debug + break; + case SSL_ERROR_WANT_READ: + printf("wr WANT_READ\n");//debug + break; + default: + printf("wr SSL_get_error=%i",eret);//debug + kill_ptr=i_ptr; + } + } + if (ret==1) + //проверить сертификат пользователя + { + X509* client_cert; + char* DN_str; + + printf("SSL connection using %s\n", SSL_get_cipher(i_ptr->ssl_comm));//debug + + client_cert=SSL_get_peer_certificate (i_ptr->ssl_comm); + if (!client_cert) + { + //ERR_CHECK //нет сертификата + kill_ptr=i_ptr; + } + //извлечение идентификационного номера из сертификата + DN_str=X509_NAME_oneline(X509_get_subject_name(client_cert), 0, 0); + if (!DN_str) + { + //ERR_CHECK + kill_ptr=i_ptr; + } + ret=get_id_fromsubjstr(DN_str,&i_ptr->id); + if (!ret) + { + //ERR_CHECK //ошибка выделения id + kill_ptr=i_ptr; + } + printf("user id=%u\n",i_ptr->id);//debug + #warning "see comments below" + //сделать проверку названия сети!!!!---------------------------<<<<<<<<<<<<<<<<<<<<<< + + OPENSSL_free(DN_str); + X509_free(client_cert); + //прицепить структуру к дереву + if (client_tree_search(i_ptr->id)) + ret = 0;//id already exists in tree + else + { + ret=client_tree_add(i_ptr); + client_tree_print(client_tree_root);//debug + } + if (!ret) + { + //ERR_CHECK //не уникальный id + kill_ptr=i_ptr; + } + i_ptr->state=PICA_CLSTATE_CONNECTED; + } + break; + } + //--------- + + i_ptr=i_ptr->next; + + if (kill_ptr) + { + client_list_delete(kill_ptr); + kill_ptr=0; + } + } +} + +void process_c2c_write() +{ +int i,ret; +struct cclink *cc,*kill_ptr; + +cc=cclink_list_head; +kill_ptr=0; + +while(cc) + { + if (cc->bufpos_p1p2/* && (cc->state==PICA_CCLINK_LOCAL_ACTIVE || cc->state==PICA_CCLINK_N2NCLE_ACTIVE)*/) + { + if (cc->state==PICA_CCLINK_N2NCLR_ACTIVE)//receiver is on remote node + { + int sendlen; + struct PICA_proto_msg *mp; + + sendlen = (cc->bufpos_p1p2 > PICA_PROTO_N2NMSG_MAXDATASIZE) ? PICA_PROTO_N2NMSG_MAXDATASIZE : cc->bufpos_p1p2; + + if(mp=nodelink_wbuf_push(cc->callee_node,PICA_PROTO_N2NMSG,sendlen+12)) + { + *((unsigned short*)mp->tail) = 8+sendlen; + *((unsigned int*)(mp->tail+2))=cc->caller_id; + *((unsigned int*)(mp->tail+6))=cc->callee_id; + memcpy(mp->tail+10, cc->buf_p1p2, sendlen); + ret=sendlen; + } + else + ret=0; + } + else + ret=send(cc->sck_p2,cc->buf_p1p2,cc->bufpos_p1p2,MSG_NOSIGNAL); + + printf("DATA send p1p2: ret=%i\n",ret);//debug + if (ret>0) + { + if (ret < cc->bufpos_p1p2) + memmove(cc->buf_p1p2,cc->buf_p1p2+ret,cc->bufpos_p1p2-ret);//may be it's better to implement ring buffer here + cc->bufpos_p1p2-=ret; + cc->jam_p1p2=0; + } + + if (ret==0) + { + kill_ptr=cc; + } + if (ret==-1) + { + #ifdef WIN32 + ret=WSAGetLastError(); + if (ret==WSAEWOULDBLOCK || ret==WSAENOBUFS) + cc->jam_p1p2=1; + else + { + kill_ptr=cc; + } + #else + ret=errno; + if (ret==EAGAIN || ret==ENOBUFS) + cc->jam_p1p2=1; + else + { + kill_ptr=cc; + } + #endif + } + + } + if (cc->bufpos_p2p1 /*&& (cc->state==PICA_CCLINK_LOCAL_ACTIVE || cc->state==PICA_CCLINK_N2NCLR_ACTIVE)*/) + { + if (cc->state==PICA_CCLINK_N2NCLE_ACTIVE)//receiver is on remote node + { + int sendlen; + struct PICA_proto_msg *mp; + + sendlen = (cc->bufpos_p2p1 > PICA_PROTO_N2NMSG_MAXDATASIZE) ? PICA_PROTO_N2NMSG_MAXDATASIZE : cc->bufpos_p2p1; + + if(mp=nodelink_wbuf_push(cc->caller_node,PICA_PROTO_N2NMSG,sendlen+12)) + { + *((unsigned short*)mp->tail) = 8+sendlen; + *((unsigned int*)(mp->tail+2))=cc->callee_id; + *((unsigned int*)(mp->tail+6))=cc->caller_id; + memcpy(mp->tail+10, cc->buf_p2p1, sendlen); + ret=sendlen; + } + else + ret=0; + } + else + ret=send(cc->sck_p1,cc->buf_p2p1,cc->bufpos_p2p1,MSG_NOSIGNAL); + + printf("DATA send p2p1: ret=%i\n",ret);//debug + if (ret>0) + { + if (ret < cc->bufpos_p2p1) + memmove(cc->buf_p2p1,cc->buf_p2p1+ret,cc->bufpos_p2p1-ret);//may be it's better to implement ring buffer here + cc->bufpos_p2p1-=ret; + cc->jam_p2p1=0; + } + + if (ret==0) + { + kill_ptr=cc; + } + if (ret==-1) + { + #ifdef WIN32 + ret=WSAGetLastError(); + if (ret==WSAEWOULDBLOCK || ret==WSAENOBUFS) + cc->jam_p2p1=1; + else + { + kill_ptr=cc; + } + #else + ret=errno; + if (ret==EAGAIN || ret==ENOBUFS) + cc->jam_p2p1=1; + else + { + kill_ptr=cc; + } + #endif + + } + + } + + cc=cc->next; + + if (kill_ptr) + { + cclink_list_delete(kill_ptr); + kill_ptr=0; + } + } +} + +void process_n2n_write() +{ +int ret; +struct nodelink *nl,*kill_ptr; + +nl=nodelink_list_head; +kill_ptr=0; + +while(nl) + { + if (nl->w_pos>0) + { + ret=send(nl->sck,nl->w_buf,nl->w_pos,MSG_NOSIGNAL); + + if (ret>0) + { + if (ret < nl->w_pos) + memmove(nl->w_buf,nl->w_buf+ret,nl->w_pos-ret);//may be it's better to implement ring buffer here + nl->w_pos-=ret; + } + if (ret<0) + { + #ifdef WIN32 + ret=WSAGetLastError(); + if (!(ret==WSAEWOULDBLOCK || ret==WSAENOBUFS)) + kill_ptr=nl; + #else + ret=errno; + if (!(ret==EAGAIN || ret==ENOBUFS || ret == EINTR)) + kill_ptr=nl; + #endif + } + if (ret==0) + kill_ptr=nl; + } + + nl=nl->next; + + if (kill_ptr) + { + nodelink_list_delete(kill_ptr);puts("process_n2n_write - calling nodelink_list_delete");//debug + kill_ptr=0; + } + } +} + +int node_loop() +{ +fd_set fds; +struct timeval tv; +int nfds,ret; + +do + { + FD_ZERO(&fds); + tv.tv_sec=SELECT_TIMEOUT; + tv.tv_usec=0; + + listen_set_fds(&fds,&nfds); + newconn_set_fds(&fds,&nfds); + c2n_set_fds(&fds,&nfds); + c2c_set_fds(&fds,&nfds); + n2n_set_fds(&fds,&nfds); + + ret=select(nfds+1,&fds,0,0,&tv); + + if (ret<0) + { + perror("node_loop-select error "); + //ERR_CHECK + return -1; + } + + if (ret>0) + { + process_c2n_read(&fds); + process_c2c_read(&fds); + process_n2n_read(&fds); + process_newconn_read(&fds); + process_listen_read(&fds); + } + + + process_c2n_write(); + process_c2c_write(); + process_n2n_write(); + + process_timeouts(); + } +while(1);////<<<<<<<<<< +return 0; +} + +int main(int argc,char** argv) +{ +printf("PicaPica node started\n");//debug + +if (!PICA_node_init()) + return -1; + +//if (PICA_node_joinskynet("nodelist")<=0)//CONF имя файла + /*return -1*/;//вывести предупреждение, что ни к одному другому узлу подключиться не удалось + +PICA_node_joinskynet("nodes.sqlite",argv[1]);//CONF-CONF имя файла с адресами узлов, свой адрес + +my_addr=argv[1];//TEMP FIXME + +return node_loop(); +} |
