]> infiniteadaptability.org Git - seeder/commitdiff
...
authoralex <[email protected]>
Tue, 29 Mar 2022 00:07:18 +0000 (17:07 -0700)
committeralex <[email protected]>
Tue, 29 Mar 2022 00:07:18 +0000 (17:07 -0700)
18 files changed:
Makefile.am
inc/net.h
inc/peer.h
src/net/expected.c [new file with mode: 0644]
src/net/handler.c
src/peer/bitfield.c
src/peer/cancel.c
src/peer/choke.c
src/peer/hash.c
src/peer/hashes.c [new file with mode: 0644]
src/peer/have.c
src/peer/interest.c
src/peer/keepalive.c [new file with mode: 0644]
src/peer/piece.c [new file with mode: 0644]
src/peer/reject.c [new file with mode: 0644]
src/peer/request.c
test/unit/Makefile.am
test/unit/net.tests.c

index 5c01a311cb5152bc1766785bc8d9b50cbb1bf00f..4d513e6949ef6e1b64b877a031749914348b9875 100644 (file)
@@ -34,6 +34,7 @@ seederd_SOURCES = \
        src/main.c \
        src/meta.c \
        src/net/cache.c \
+       src/net/expected.c \
        src/net/handler.c \
        src/net/listen.c \
        src/net/loop.c \
@@ -55,9 +56,20 @@ seederd_SOURCES = \
        src/opt/set.c \
        src/opt/watch.c \
        src/opt/worker.c \
+       src/peer/bitfield.c \
+       src/peer/cancel.c \
+       src/peer/choke.c \
        src/peer/free.c \
        src/peer/handshake.c \
+       src/peer/hash.c \
+       src/peer/hashes.c \
+       src/peer/have.c \
        src/peer/init.c \
+       src/peer/interest.c \
+       src/peer/keepalive.c \
+       src/peer/piece.c \
+       src/peer/reject.c \
+       src/peer/request.c \
        src/pqueue.c \
        src/rss/entry.c \
        src/rss/footer.c \
index 9cd57dec8e78ba7dd4f9fa7e2c9381bacffa113c..d69828faf60877f4b19cb75ee00ad198602908d1 100644 (file)
--- a/inc/net.h
+++ b/inc/net.h
@@ -1,9 +1,6 @@
 #ifndef __NET_H_
 #define __NET_H_
 
-#include<opt.h>
-#include<peer.h>
-
 #include<errno.h>
 #include<fcntl.h>
 #include<netdb.h>
@@ -15,6 +12,9 @@
 #include<sys/socket.h>
 #include<unistd.h>
 
+#include<opt.h>
+#include<peer.h>
+
 struct net_info {
        int tcp_socket;
        int udp_socket;
@@ -37,6 +37,7 @@ struct net_info {
 }
 
 int net_cache(void**,size_t*,void*,size_t);
+ssize_t net_expected(int,enum peer_message*);
 void net_handler(int,int,struct peer*);
 int net_listen_sock();
 void net_loop();
index df2a21fde68325335bd709dccfe94c97f4e86a21..ccc9ee48bcc3949d3ec129b75167a6be1828cc66 100644 (file)
@@ -26,6 +26,7 @@ struct peer {
 };
 
 enum peer_message {
+       PEER_MESSAGE_KEEPALIVE = -1,
        PEER_MESSAGE_CHOKE = 0,
        PEER_MESSAGE_UNCHOKE = 1,
        PEER_MESSAGE_INTERESTED = 2,
@@ -44,8 +45,22 @@ enum peer_message {
 #include<net.h>
 #include<session.h>
 
+int peer_bitfield(int,struct peer*);
+int peer_cancel(int,struct peer*);
+int peer_choke(int,struct peer*);
 void peer_free(struct peer*);
 int peer_handshake(int,struct peer*);
+int peer_hash_reject(int,struct peer*);
+int peer_hash_request(int,struct peer*);
+int peer_hashes(int,struct peer*);
+int peer_have(int,struct peer*);
 int peer_init(struct peer**);
+int peer_interested(int,struct peer*);
+int peer_keepalive(int,struct peer*);
+int peer_not_interested(int,struct peer*);
+int peer_piece(int,struct peer*);
+int peer_reject(int,struct peer*);
+int peer_request(int,struct peer*);
+int peer_unchoke(int,struct peer*);
 
 #endif
diff --git a/src/net/expected.c b/src/net/expected.c
new file mode 100644 (file)
index 0000000..87c5518
--- /dev/null
@@ -0,0 +1,39 @@
+#include<net.h>
+
+ssize_t net_expected(int sock, enum peer_message *type) {
+       unsigned char buf[4];
+       ssize_t i;
+
+       (*type) = PEER_MESSAGE_KEEPALIVE;
+       
+       i = recv(sock,buf,5,MSG_PEEK);
+       if(-1==i) {
+               if(!((errno==EAGAIN)||(errno==EWOULDBLOCK))) {
+                       perror("recv");
+                       return -1;
+               }
+
+               // 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) { return 0; }
+
+       if(i==5) { (*type) = (uint8_t)buf[4]; }
+
+       i = 0;
+       for(size_t j=0;j<4;j++) {
+               i <<= 8;
+               i += buf[j];
+       }
+
+       return i;
+}
index 15c98cab0fef4fe671848a785fbf3b631cb3d004..71c25fe580c8c770a696273e22bdd9bdfb4170e4 100644 (file)
@@ -1,85 +1,71 @@
 #include<net.h>
 
-static uint32_t net_expected_length(int);
 static int send_remaining(int,struct peer*);
 
-static uint32_t net_expected_length(int sock) {
-       unsigned char buf[4];
-       uint32_t len;
-       ssize_t i;
-       
-       i = recv(sock,buf,4,MSG_PEEK);
-       if(-1==i) {
-               if(!((errno==EAGAIN)||(errno==EWOULDBLOCK))) {
-                       perror("recv");
-                       return -1;
-               }
-
-               // 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) { return 0; }
-
-       len = 0;
-       for(size_t j=0;j<4;j++) {
-               len <<= 1;
-               len += buf[j];
-       }
-
-       return i;
-}
 
 void net_handler(int epoll_fd, int sock, struct peer *info) {
+       enum peer_message type;
        uint32_t i;
 
+       if(epoll_fd<0) { return; }
+       if(sock<0) { return; }
+       if(NULL==info) { goto close; }
+
        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
+       if((i = net_expected(sock,&type))<0) { goto close; }
 
-       switch(0) {
+       switch(type) {
+               /* these are ordered based on enum peer_message */
+               case PEER_MESSAGE_KEEPALIVE:
+                       if(peer_keepalive(sock,info)<0) { goto close; }
+                       break;
                case PEER_MESSAGE_CHOKE:
+                       if(peer_choke(sock,info)<0) { goto close; }
                        break;
                case PEER_MESSAGE_UNCHOKE:
+                       if(peer_unchoke(sock,info)<0) { goto close; }
                        break;
                case PEER_MESSAGE_INTERESTED:
+                       if(peer_interested(sock,info)<0) { goto close; }
                        break;
                case PEER_MESSAGE_NOT_INTERESTED:
+                       if(peer_not_interested(sock,info)<0) { goto close; }
                        break;
                case PEER_MESSAGE_HAVE:
+                       if(peer_have(sock,info)<0) { goto close; }
                        break;
                case PEER_MESSAGE_BITFIELD:
+                       if(peer_bitfield(sock,info)<0) { goto close; }
                        break;
                case PEER_MESSAGE_REQUEST:
+                       if(peer_request(sock,info)<0) { goto close; }
                        break;
                case PEER_MESSAGE_PIECE:
+                       if(peer_piece(sock,info)<0) { goto close; }
                        break;
                case PEER_MESSAGE_CANCEL:
+                       if(peer_cancel(sock,info)<0) { goto close; }
                        break;
                case PEER_MESSAGE_REJECT:
+                       if(peer_reject(sock,info)<0) { goto close; }
                        break;
                case PEER_MESSAGE_HASH_REQUEST:
+                       if(peer_hash_request(sock,info)<0) { goto close; }
                        break;
                case PEER_MESSAGE_HASHES:
+                       if(peer_hashes(sock,info)<0) { goto close; }
                        break;
                case PEER_MESSAGE_HASH_REJECT:
+                       if(peer_hash_reject(sock,info)<0) { goto close; }
                        break;
                default:
-                       break;
+                       goto close;
        }
 
-       return;
+       goto queue;
 remaining:
        if(send_remaining(sock,info)<0) { goto close; }
        goto queue;
index 9947ff88a2969b3f274bfa73d49a125c9f07b2a7..3df3b547054dcf14b3fb2855d9538cbef28629a1 100644 (file)
@@ -1,5 +1,5 @@
 #include<peer.h>
 
-int peer_bitfield(int sock) {
+int peer_bitfield(int sock, struct peer *info) {
        return -1;
 }
index 07da8b991cfa58f2e884aa8da1f6fe42cda03495..bbb3f4aeb3b3ec063be83991b3a7e7d6b468a379 100644 (file)
@@ -1,5 +1,5 @@
 #include<peer.h>
 
-int peer_cancel() {
+int peer_cancel(int sock, struct peer *info) {
        return -1;
 }
index 99d8423e846283d3c09c6478a18f562026240b71..cded0a38393a26d8144e653c7f098a9633f6076f 100644 (file)
@@ -1,9 +1,9 @@
 #include<peer.h>
 
-int peer_choke(int sock) {
+int peer_choke(int sock, struct peer *info) {
        return -1;
 }
 
-int peer_unchoke(int sock) {
+int peer_unchoke(int sock, struct peer *info) {
        return -1;
 }
index 4f1e067764eb15c79dad6aeb4889ac19e243c24e..fe8d77ee6ebfb3922f92d872d03e999947b41a72 100644 (file)
@@ -1,9 +1,9 @@
 #include<peer.h>
 
-int peer_hash_request() {
+int peer_hash_request(int sock, struct peer *info) {
        return -1;
 }
 
-int peer_hash_reject() {
+int peer_hash_reject(int sock, struct peer *info) {
        return -1;
 }
diff --git a/src/peer/hashes.c b/src/peer/hashes.c
new file mode 100644 (file)
index 0000000..323a625
--- /dev/null
@@ -0,0 +1,5 @@
+#include<peer.h>
+
+int peer_hashes(int sock, struct peer *info) {
+       return -1;
+}
index 28c14b2ccbdb0c0595170a9364fcb7d31318c462..e27f81886ec476ae01a169a68ee73ea051fcf144 100644 (file)
@@ -1,5 +1,5 @@
 #include<peer.h>
 
-int peer_have(int sock) {
+int peer_have(int sock, struct peer *info) {
        return -1;
 }
index 651704d9592c97ee1d5c3c176446a1286ce369a2..e9033c705b450d6ae46d1e2c3dc3dc30beac8e11 100644 (file)
@@ -1,9 +1,9 @@
 #include<peer.h>
 
-int peer_interested(int sock) {
+int peer_interested(int sock, struct peer *info) {
        return -1;
 }
 
-int peer_not_interested(int sock) {
+int peer_not_interested(int sock, struct peer *info) {
        return -1;
 }
diff --git a/src/peer/keepalive.c b/src/peer/keepalive.c
new file mode 100644 (file)
index 0000000..922e979
--- /dev/null
@@ -0,0 +1,5 @@
+#include<peer.h>
+
+int peer_keepalive(int sock, struct peer *info) {
+       return -1;
+}
diff --git a/src/peer/piece.c b/src/peer/piece.c
new file mode 100644 (file)
index 0000000..92d60ad
--- /dev/null
@@ -0,0 +1,5 @@
+#include<peer.h>
+
+int peer_piece(int sock, struct peer *info) {
+       return -1;
+}
diff --git a/src/peer/reject.c b/src/peer/reject.c
new file mode 100644 (file)
index 0000000..f3e0153
--- /dev/null
@@ -0,0 +1,5 @@
+#include<peer.h>
+
+int peer_reject(int sock, struct peer *info) {
+       return -1;
+}
index 371f9885246ad53a226e42156f52fa20e73c0579..1a42c804bd2ad3e24f432ed6d4352440d74b6867 100644 (file)
@@ -1,5 +1,5 @@
 #include<peer.h>
 
-int peer_request() {
+int peer_request(int sock, struct peer *info) {
        return -1;
 }
index ea1d39f4b2a41d2ca73b6bfaef2501397826485b..fe93e83baa01e92f51ff4e441cae193c4aebd723 100644 (file)
@@ -120,6 +120,8 @@ net_tests_SOURCES = \
        $(common_SOURCES) \
        net.tests.c \
        $(top_srcdir)/src/net/cache.c \
+       $(top_srcdir)/src/net/expected.c \
+       $(top_srcdir)/src/net/handler.c \
        $(top_srcdir)/src/net/queue.c \
        $(top_srcdir)/src/net/send.c \
        $(top_srcdir)/src/net/wait.c \
index eeb6014b0065a698891e780b7ada8d27ed72e8a4..766c20eb1ae0b159684f24f98fb5a9e4a0cb88d2 100644 (file)
@@ -5,10 +5,32 @@
 int main();
 static void setup_sockets();
 static void net_cache_basic_test();
+static void net_expected_basic_test();
+static void net_handler_basic_test();
+static void net_handler_invalid_message_test();
 static void net_queue_basic_test();
 static void net_send_basic_test();
 static void net_wait_basic_test();
 
+/* dummy functions (and array) used to test net_handler */
+int message_count[25];
+int peer_bitfield(int sock,struct peer *info) { message_count[PEER_MESSAGE_BITFIELD+1]++; return 0; }
+int peer_cancel(int sock,struct peer *info) { message_count[PEER_MESSAGE_CANCEL+1]++; return 0; }
+int peer_choke(int sock,struct peer *info) { message_count[PEER_MESSAGE_CHOKE+1]++; return 0; }
+int peer_handshake(int sock,struct peer *info) { return 0; }
+int peer_hash_reject(int sock,struct peer *info) { message_count[PEER_MESSAGE_HASH_REJECT+1]++; return 0; }
+int peer_hash_request(int sock,struct peer *info) { message_count[PEER_MESSAGE_HASH_REQUEST+1]++; return 0; }
+int peer_hashes(int sock,struct peer *info) { message_count[PEER_MESSAGE_HASHES+1]++; return 0; }
+int peer_have(int sock,struct peer *info) { message_count[PEER_MESSAGE_HAVE+1]++; return 0; }
+int peer_interested(int sock,struct peer *info) { message_count[PEER_MESSAGE_INTERESTED+1]++; return 0; }
+int peer_keepalive(int sock,struct peer *info) { message_count[PEER_MESSAGE_KEEPALIVE+1]++; return 0; }
+int peer_not_interested(int sock,struct peer *info) { message_count[PEER_MESSAGE_NOT_INTERESTED+1]++; return 0; }
+int peer_piece(int sock,struct peer *info) { message_count[PEER_MESSAGE_PIECE+1]++; return 0; }
+int peer_reject(int sock,struct peer *info) { message_count[PEER_MESSAGE_REJECT+1]++; return 0; }
+int peer_request(int sock,struct peer *info) { message_count[PEER_MESSAGE_REQUEST+1]++; return 0; }
+int peer_unchoke(int sock,struct peer *info) { message_count[PEER_MESSAGE_UNCHOKE+1]++; return 0; }
+/* end dummy functions */
+
 static int read_sock;
 static int write_sock;
 
@@ -16,6 +38,9 @@ int main() {
        setup_env();
 
        net_cache_basic_test();
+       net_expected_basic_test();
+       net_handler_basic_test();
+       net_handler_invalid_message_test();
        net_queue_basic_test();
        net_send_basic_test();
        net_wait_basic_test();
@@ -68,6 +93,161 @@ static void net_cache_basic_test() {
        free(p1);
 }
 
+static void net_expected_basic_test() {
+       struct peer *info;
+       enum peer_message type;
+       unsigned char buf[10];
+
+       assert(1==peer_init(&info));
+
+       setup_sockets();
+
+       /* verify messages with <4 bytes returns keepalive */
+       unsigned char expected1[4] = "\x00\x00\x00\x00";
+       assert(3==write(write_sock,expected1,3));
+
+       assert(0==net_expected(read_sock,&type));
+       assert(PEER_MESSAGE_KEEPALIVE==type);
+       assert(3==read(read_sock,buf,sizeof(buf)));
+
+       /* verify keepalive returns as expected */
+       assert(4==write(write_sock,expected1,4));
+
+       assert(0==net_expected(read_sock,&type));
+       assert(PEER_MESSAGE_KEEPALIVE==type);
+       assert(4==read(read_sock,buf,sizeof(buf)));
+
+       unsigned char expected2[5] = "\x00\x00\x01\x00";
+       expected2[4] = PEER_MESSAGE_CHOKE;
+       assert(5==write(write_sock,expected2,5));
+
+       assert(256==net_expected(read_sock,&type));
+       assert(PEER_MESSAGE_CHOKE==type);
+       assert(5==read(read_sock,buf,sizeof(buf)));
+
+       unsigned char expected3[5] = "\x00\x10\x01\x00";
+       expected3[4] = PEER_MESSAGE_HASHES;
+       assert(5==write(write_sock,expected3,5));
+
+       assert(1048832==net_expected(read_sock,&type));
+       assert(PEER_MESSAGE_HASHES==type);
+       assert(5==read(read_sock,buf,sizeof(buf)));
+
+       unsigned char expected4[5] = "\xf0\x10\x01\x00";
+       expected4[4] = PEER_MESSAGE_UNCHOKE;
+       assert(5==write(write_sock,expected4,5));
+
+       assert(4027580672==net_expected(read_sock,&type));
+       assert(PEER_MESSAGE_UNCHOKE==type);
+       assert(5==read(read_sock,buf,sizeof(buf)));
+
+       peer_free(info);
+       close(read_sock);
+       close(write_sock);
+}
+
+/* Parameters:
+ * unsigned char *message
+ * enum peer_message type
+ */
+#define NET_HANDLER_HELPER(message,type) { \
+       assert(sizeof(message)==write(write_sock,message,sizeof(message))); \
+\
+       net_handler(epoll_fd,read_sock,info); \
+       assert(0==epoll_ctl(epoll_fd,EPOLL_CTL_DEL,read_sock,NULL)); \
+       assert(sizeof(message)==read(read_sock,buf,sizeof(buf))); \
+\
+       assert(1==message_count[type+1]); \
+}
+
+static void net_handler_invalid_message_test() {
+       struct peer *info;
+       int epoll_fd;
+       
+       assert(1==peer_init(&info));
+       info->handshake = 1;
+
+       epoll_fd = epoll_create1(0);
+       assert(epoll_fd!=-1);
+       
+       setup_sockets();
+       
+       memset(message_count, 0, sizeof(message_count));
+
+       unsigned char invalid_message_type[5] = "\x00\x00\x00\x01\xff";
+       assert(5==write(write_sock,invalid_message_type,5));
+       net_handler(epoll_fd,read_sock,info);
+
+       for(size_t i=0;i<25;i++) {
+               assert(0==message_count[i]);
+       }
+
+       close(epoll_fd);
+}
+
+static void net_handler_basic_test() {
+       struct peer *info;
+       unsigned char buf[10];
+       int epoll_fd;
+
+       memset(message_count, 0, sizeof(message_count));
+
+       assert(1==peer_init(&info));
+       info->handshake = 1;
+
+       epoll_fd = epoll_create1(0);
+       assert(epoll_fd!=-1);
+
+       setup_sockets();
+
+       /* all peer_message enums indexes are +1 in message_count */
+       unsigned char keepalive_message[4] = "\x00\x00\x00\x00";
+       NET_HANDLER_HELPER(keepalive_message,PEER_MESSAGE_KEEPALIVE);
+
+       unsigned char choke_message[5] = "\x00\x00\x00\x01\x00";
+       NET_HANDLER_HELPER(choke_message,PEER_MESSAGE_CHOKE);
+
+       unsigned char unchoke_message[5] = "\x00\x00\x00\x01\x01";
+       NET_HANDLER_HELPER(unchoke_message,PEER_MESSAGE_UNCHOKE);
+
+       unsigned char interested_message[5] = "\x00\x00\x00\x01\x02";
+       NET_HANDLER_HELPER(interested_message,PEER_MESSAGE_INTERESTED);
+
+       unsigned char not_interested_message[5] = "\x00\x00\x00\x01\x03";
+       NET_HANDLER_HELPER(not_interested_message,PEER_MESSAGE_NOT_INTERESTED);
+
+       unsigned char have_message[5] = "\x00\x00\x00\x01\x04";
+       NET_HANDLER_HELPER(have_message,PEER_MESSAGE_HAVE);
+
+       unsigned char bitfield_message[5] = "\x00\x00\x00\x01\x05";
+       NET_HANDLER_HELPER(bitfield_message,PEER_MESSAGE_BITFIELD);
+
+       unsigned char request_message[5] = "\x00\x00\x00\x01\x06";
+       NET_HANDLER_HELPER(request_message,PEER_MESSAGE_REQUEST);
+
+       unsigned char piece_message[5] = "\x00\x00\x00\x01\x07";
+       NET_HANDLER_HELPER(piece_message,PEER_MESSAGE_PIECE);
+
+       unsigned char cancel_message[5] = "\x00\x00\x00\x01\x08";
+       NET_HANDLER_HELPER(cancel_message,PEER_MESSAGE_CANCEL);
+
+       unsigned char reject_message[5] = "\x00\x00\x00\x01\x10";
+       NET_HANDLER_HELPER(reject_message,PEER_MESSAGE_REJECT);
+
+       unsigned char hash_request_message[5] = "\x00\x00\x00\x01\x15";
+       NET_HANDLER_HELPER(hash_request_message,PEER_MESSAGE_HASH_REQUEST);
+
+       unsigned char hashes_message[5] = "\x00\x00\x00\x01\x16";
+       NET_HANDLER_HELPER(hashes_message,PEER_MESSAGE_HASHES);
+
+       unsigned char hash_reject_message[5] = "\x00\x00\x00\x01\x17";
+       NET_HANDLER_HELPER(hash_reject_message,PEER_MESSAGE_HASH_REJECT);
+
+       peer_free(info);
+       close(read_sock);
+       close(write_sock);
+}
+
 static void net_queue_basic_test() {
        int epoll_fd;
        int sock;