]> infiniteadaptability.org Git - seeder/commitdiff
...
authoralex <[email protected]>
Mon, 21 Mar 2022 02:37:25 +0000 (19:37 -0700)
committeralex <[email protected]>
Mon, 21 Mar 2022 02:37:25 +0000 (19:37 -0700)
inc/peer.h
inc/session.h
src/net/handler.c
src/net/loop.c
src/net/queue.c
src/net/send.c [new file with mode: 0644]
src/net/wait.c
src/peer/handshake.c

index 8f0bbda980a95c854840d84d96c30584353c09e2..7c73326e91997f33e0ffd0534242f71804be543e 100644 (file)
@@ -5,6 +5,7 @@
 #define PEER_PEER_ID_SIZE 20
 
 struct peer {
+       unsigned int handshake : 1;
        unsigned int choked : 1;
        unsigned int interested: 1;
 
index ebc3066880d9b7e981d5c162a71e92d00ffa90c7..70109da0ce388e626dee3c9b3836803f6ad40a36 100644 (file)
@@ -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*);
 
index 4569d02a36c4c1eb756ef514e34301dd77aa2c29..10f1ca281260d0719a9c37b086addef093989e3e 100644 (file)
@@ -1,38 +1,53 @@
 #include<net.h>
 
-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;
 }
index ee45b5332f4ab7a055595c55f653b7f73900d608..f20404918d9ee39b48cc17022908f064743188fc 100644 (file)
@@ -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;
index a46a5e917407d08dea4ecdd488934002de2c62df..ba47dfda0524b3a5b21939a1c1445181432fdafb 100644 (file)
@@ -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 (file)
index 0000000..468154f
--- /dev/null
@@ -0,0 +1,25 @@
+#include<net.h>
+
+int net_send(int sock, struct peer *info, void *p, size_t size) {
+       ssize_t i;
+
+       i = send(sock,p,size,0);
+       if(i<size) {
+               if(i<0) {
+                       perror("send");
+                       return -1;
+               }
+
+               info->out = malloc(size-i);
+               if(NULL==info->out) {
+                       perror("malloc");
+                       return -1;
+               }
+
+               memcpy(info->out,p,size);
+               info->out_size = size;
+               return 0;
+       }
+
+       return 1;
+}
index af59bcca842734b9c6a3b78cb232e4cff9f3c59b..9979ca81eb45c269a4bfd34e56fa2e96600840dc 100644 (file)
@@ -1,5 +1,10 @@
 #include<net.h>
 
-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;
+               }*/
 }
index 1bb7e8b760dcf0088d2f64e98a2dab1fbbbe52b3..8f79351e038389400ff07831b5e731aff3751b00 100644 (file)
@@ -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(i<HEADER_LENGTH) {
-               if(i<0) {
-                       perror("send");
-                       return -1;
-               }
-               goto epoll;
-       }
+       if(net_send(sock,info,header,HEADER_LENGTH)<0) { return -1; }
 
        return 1;
-epoll:
-       if(net_queue(sock,info,&(header[i]),HEADER_LENGTH-i)<0) { return -1; }
-       return 0;
 }
 
 static int peer_handshake_receive(int sock, struct peer *info) {
        char header[HEADER_LENGTH];
+       struct torrent *p;
        ssize_t i;
 
-       i = recv(sock,header,HEADER_LENGTH);
-       if(-1==i) {
-               if(!((errno==EAGAIN)||(errno==EWOULDBLOCK))) {
-                       perror("recv");
-                       return;
-               }
-               goto wait;
-       }
+       if(net_wait(sock,info,header,HEADER_LENGTH)<0) { return -1; }
 
-       return -1;
+       memcpy(
+               info->infohash,
+               &(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;
 }