From a8dde80c255a8c3c13e7bb0ba0a58f362c1ed725 Mon Sep 17 00:00:00 2001 From: alex Date: Sun, 20 Mar 2022 19:37:25 -0700 Subject: [PATCH] ... --- inc/peer.h | 1 + inc/session.h | 1 + src/net/handler.c | 77 ++++++++++++++++++++++++++++---------------- src/net/loop.c | 5 ++- src/net/queue.c | 10 +++--- src/net/send.c | 25 ++++++++++++++ src/net/wait.c | 7 +++- src/peer/handshake.c | 48 ++++++++++++--------------- 8 files changed, 114 insertions(+), 60 deletions(-) create mode 100644 src/net/send.c diff --git a/inc/peer.h b/inc/peer.h index 8f0bbda..7c73326 100644 --- a/inc/peer.h +++ b/inc/peer.h @@ -5,6 +5,7 @@ #define PEER_PEER_ID_SIZE 20 struct peer { + unsigned int handshake : 1; unsigned int choked : 1; unsigned int interested: 1; diff --git a/inc/session.h b/inc/session.h index ebc3066..70109da 100644 --- a/inc/session.h +++ b/inc/session.h @@ -20,6 +20,7 @@ struct session { extern struct session session; void session_clean(); +struct torrent *session_find_torrent(uint8_t*,size_t); int session_init(); int session_torrent_add(struct torrent*); diff --git a/src/net/handler.c b/src/net/handler.c index 4569d02..10f1ca2 100644 --- a/src/net/handler.c +++ b/src/net/handler.c @@ -1,38 +1,53 @@ #include -void net_handler(int epoll_fd, int sock, struct peer *peer_info) { - struct epoll_event ev; +static ssize_t net_expected_length(int); +static void send_remaining(int,struct peer*); + +static ssize_t net_expected_length(int sock) { unsigned char buf[4]; ssize_t i; - unsigned int len; - - if(NULL==peer_info) { - if(peer_handshake(sock,peer_info)<0) { goto close; } - return; - } - + i = recv(sock,buf,4,MSG_PEEK); if(-1==i) { if(!((errno==EAGAIN)||(errno==EWOULDBLOCK))) { perror("recv"); - return; + return -1; } - goto epoll; - } + // returning 0 here won't affect anything, + // will be treated as a keep alive (although + // message is still coming in, but since MSG_PEEK + // flag is used no data will have been consumed) + // and sock will be returned to epoll + return 0; + } + /* * message should at least have 4 bytes (length prefix of * the following message) */ - if(i<4) { goto epoll; } + if(i<4) { return 0; } - len = 0; - for(size_t i=0;i<4;i++) { - len <<= 1; - len += buf[i]; + i = 0; + for(size_t j=0;j<4;j++) { + i <<= 1; + i += buf[j]; } - if(0==len) { return; } // message of length 0 == keep-alive + return i; +} + +void net_handler(int epoll_fd, int sock, struct peer *peer_info) { + struct epoll_event ev; + ssize_t i; + unsigned int len; + + if(info->out!=NULL) { goto remaining; } + + if(!info->handshake) { goto handshake; } + + if((i = net_expected_length(sock))<0) { goto close; } + if(0==i) { goto queue; } // message of length 0 == keep-alive switch(buf[4]) { case PEER_MESSAGE_CHOKE: @@ -65,18 +80,26 @@ void net_handler(int epoll_fd, int sock, struct peer *peer_info) { break; } + return; +remaining: + if(send_remaining(sock,peer_info)<0) { goto close; } + goto queue; +handshake: + if(peer_handshake(sock,peer_info)<0) { goto close; } + goto queue; +queue: + if(net_queue(sock,info,NULL,0)<0) { goto close; } return; close: - if(peer_info!=NULL) { peer_free(peer_info); } + peer_free(peer_info); close(sock); return; -epoll: - ev.events = EPOLLIN | EPOLLET; - ev.data.ptr = peer_info; - ev.data.fd = sock; +} - if(-1==epoll_ctl(epoll_fd,EPOLL_CTL_ADD,sock,&ev)) { - perror("epoll_ctl"); - return; - } +static int send_remaining(int sock, struct peer *info) { + if(net_send(sock,peer_info->out,peer_info->out_size)<0) { return -1; } + + free(info->out); + info->out = NULL; + return 1; } diff --git a/src/net/loop.c b/src/net/loop.c index ee45b53..f204049 100644 --- a/src/net/loop.c +++ b/src/net/loop.c @@ -32,9 +32,12 @@ static void net_await_epoll_event(struct net_info *info) { setnonblocking(conn_sock); ev.events = EPOLLIN | EPOLLET; - ev.data.ptr = NULL; ev.data.fd = conn_sock; + if(peer_init((struct peer*)&(ev.data.ptr))<0) { + return; + } + if(-1==epoll_ctl(info->epoll_fd,EPOLL_CTL_ADD,conn_sock,&ev)) { perror("epoll_ctl"); return; diff --git a/src/net/queue.c b/src/net/queue.c index a46a5e9..ba47dfd 100644 --- a/src/net/queue.c +++ b/src/net/queue.c @@ -3,12 +3,14 @@ int net_queue(int sock, struct peer *info, void *p, size_t size) { struct epoll_event ev; - info->data = malloc(size); - if(NULL==info->data) { return -1; } + if((p!=NULL)&&(size>0)) { + info->data = malloc(size); + if(NULL==info->data) { return -1; } - memcpy(info->data,p,size); + memcpy(info->data,p,size); + } - ev.events = EPOLLOUT; + ev.events = EPOLLIN | EPOLLOUT | EPOLLET; ev.data.ptr = info; ev.data.fd = sock; diff --git a/src/net/send.c b/src/net/send.c new file mode 100644 index 0000000..468154f --- /dev/null +++ b/src/net/send.c @@ -0,0 +1,25 @@ +#include + +int net_send(int sock, struct peer *info, void *p, size_t size) { + ssize_t i; + + i = send(sock,p,size,0); + if(iout = malloc(size-i); + if(NULL==info->out) { + perror("malloc"); + return -1; + } + + memcpy(info->out,p,size); + info->out_size = size; + return 0; + } + + return 1; +} diff --git a/src/net/wait.c b/src/net/wait.c index af59bcc..9979ca8 100644 --- a/src/net/wait.c +++ b/src/net/wait.c @@ -1,5 +1,10 @@ #include -int net_wait(int sock, struct peer *info, size_t size) { +int net_wait(int sock, struct peer *info, void *p, size_t size) { return -1; + /*if(-1==i) { + if(!((errno==EAGAIN)||(errno==EWOULDBLOCK))) { + perror("recv"); + return -1; + }*/ } diff --git a/src/peer/handshake.c b/src/peer/handshake.c index 1bb7e8b..8f79351 100644 --- a/src/peer/handshake.c +++ b/src/peer/handshake.c @@ -7,16 +7,14 @@ static int peer_handshake_receive(int); -int peer_handshake(int sock) { - struct peer *info; +int peer_handshake(int sock, struct peer *info) { char header[HEADER_LENGTH] = HANDSHAKE_STRING; - ssize_t i; + int i; if(sock<0) { return -1; } - if(peer_init(&info)<0) { return -1; } - if(peer_handshake_receive(sock)<0) { return -1; } + if(!info->handshake) { return 0; } // copy infohash to buffer memcpy( @@ -30,36 +28,32 @@ int peer_handshake(int sock) { info->peer_id, PEER_PEER_ID_SIZE); - // send header - i = send(sock,header,HEADER_LENGTH,0); - if(iinfohash, + &(header[HANDSHAKE_STRING_LENGTH]), + PEER_INFOHASH_SIZE); + memcpy( + info->peer_id, + &(header[HANDSHAKE_STRING_LENGTH+PEER_INFOHASH_SIZE]), + PEER_INFOHASH_SIZE); + + p = session_find_torrent(info->infohash,PEER_INFOHASH_SIZE); + if(NULL==p) { return -1; } + + return 1; wait: - if(net_wait(sock,info, + if(net_wait(sock,info,header,i)<0) { return -1; } + return 0; } -- 2.30.2