...
authoralex <[email protected]>
Sat, 4 Dec 2021 01:10:15 +0000 (17:10 -0800)
committeralex <[email protected]>
Sat, 4 Dec 2021 01:10:15 +0000 (17:10 -0800)
inc/bencode.h
inc/file.h
src/bencode/decode.c
src/bencode/encode.c
src/file.c
src/tree.c
test/unit/Makefile.am
test/unit/bencode.tests.c
test/unit/file.tests.c
test/unit/tree.tests.c

index 190613e12aea54bc7c5c729b251d7ab4f6cb7943..e0806759265ade1bc3407247cb2884fe897ff3f2 100644 (file)
@@ -14,12 +14,12 @@ enum bencode_type {
        BENCODE_STRING
 };
 
-ssize_t bdecode_integer(const uint8_t*,size_t,long long int*);
+ssize_t bdecode_int(const uint8_t*,size_t,long long int*);
 ssize_t bdecode_string(const uint8_t*,size_t,uint8_t*,size_t);
 enum bencode_type bdecode_type(const uint8_t*,size_t);
 ssize_t bencode_dict_end(uint8_t*,size_t);
 ssize_t bencode_dict_start(uint8_t*,size_t);
-ssize_t bencode_int(int,uint8_t*,size_t);
+ssize_t bencode_int(long long int,uint8_t*,size_t);
 ssize_t bencode_list_end(uint8_t*,size_t);
 ssize_t bencode_list_start(uint8_t*,size_t);
 ssize_t bencode_string(const uint8_t*,size_t,uint8_t*,size_t);
index bc56fc9d951e4f1aebbc0c2551fd78e3df464ac1..9c4843c35d6b7356137d8b8d80fcb091bfdd1d40 100644 (file)
@@ -8,6 +8,7 @@
 
 #include<sodium.h>
 
+#include<bencode.h>
 #include<block.h>
 #include<fs.h>
 
@@ -19,6 +20,7 @@ struct file {
        size_t size;
 };
 
+ssize_t file_bencode(struct file*,uint8_t*,size_t);
 void file_free(struct file*);
 int file_hash(struct file*,int);
 int file_init(struct file**,const char*);
index 23c7d21af7a8e14078ca9df3d4ed9c26d6f10a0e..8963eee0016e0a8bc30b983435bd731c4f91dbca 100644 (file)
@@ -1,6 +1,6 @@
 #include<bencode.h>
 
-ssize_t bdecode_integer(const uint8_t *buf, size_t buf_len, long long int *output) {
+ssize_t bdecode_int(const uint8_t *buf, size_t buf_len, long long int *output) {
        if(NULL==buf) { return -1; }
        if(buf_len<=0) { return -1; }
        if(NULL==output) { return -1; }
index 01fc8c8ff00912044d965c22aa5f8411af56bf5f..8ba8ffc14d2fd632072d3b4f77773fbfb5d033f1 100644 (file)
@@ -20,7 +20,7 @@ ssize_t bencode_dict_start(uint8_t *output, size_t output_size) {
        return 1;
 }
 
-ssize_t bencode_int(int to_encode, uint8_t *output, size_t output_size) {
+ssize_t bencode_int(long long int to_encode, uint8_t *output, size_t output_size) {
        size_t i;
        int ret;
 
@@ -29,7 +29,7 @@ ssize_t bencode_int(int to_encode, uint8_t *output, size_t output_size) {
        i = size_int(to_encode);
        i += 2;
 
-       if((ret = snprintf((char*)output,output_size,"i%de",to_encode))<0) { return -1; }
+       if((ret = snprintf((char*)output,output_size,"i%llue",to_encode))<0) { return -1; }
        if(ret!=i) { return -1; }
 
        return i;
index 0fcc7a280f609f8f6b74d912745a5a5dab85ca78..1aa03618311afc97dd4b08644c5a076ea360a1ce 100644 (file)
@@ -1,6 +1,55 @@
 #include<file.h>
 
 static int file_piece_layers(struct file *p, int piece_length);
+static int advance(ssize_t,uint8_t**,size_t*);
+
+static int advance(ssize_t i, uint8_t **buf, size_t *len) {
+       if(i<0) { return -1; }
+
+       (*buf) += i;
+       (*len) -= i;
+
+       return 1;
+}
+
+ssize_t file_bencode(struct file *p, uint8_t *buf, size_t len) {
+       ssize_t i;
+       size_t buf_len;
+
+       buf_len = len;
+       
+       i = bencode_dict_start(buf,buf_len);
+       if(advance(i,&buf,&len)<0) { return -1; }
+
+       uint8_t blank_string[] = "";
+       i = bencode_string(blank_string,sizeof(blank_string)-1,buf,len);
+       if(advance(i,&buf,&len)<0) { return -1; }
+
+       i = bencode_dict_start(buf,buf_len);
+       if(advance(i,&buf,&len)<0) { return -1; }
+
+       uint8_t length_string[] = "length";
+       i = bencode_string(length_string,sizeof(length_string)-1,buf,len);
+       if(advance(i,&buf,&len)<0) { return -1; }
+
+       i = bencode_int(p->size,buf,len);
+       if(advance(i,&buf,&len)<0) { return -1; }
+
+       uint8_t pieces_root_string[] = "pieces root";
+       i = bencode_string(pieces_root_string,sizeof(pieces_root_string)-1,buf,len);
+       if(advance(i,&buf,&len)<0) { return -1; }
+
+       i = bencode_string((uint8_t*)p->root,crypto_hash_sha256_BYTES,buf,len);
+       if(advance(i,&buf,&len)<0) { return -1; }
+
+       i = bencode_dict_end(buf,buf_len);
+       if(advance(i,&buf,&len)<0) { return -1; }
+
+       i = bencode_dict_end(buf,buf_len);
+       if(advance(i,&buf,&len)<0) { return -1; }
+
+       return buf_len-len;
+}
 
 void file_free(struct file *p) {
        if(NULL==p) { return; }
index 1b3207affc83652e39887d5ad2996c1818c93a20..10322aa7abecfb7c0e7c1f6136598cce744d6921 100644 (file)
@@ -1,9 +1,19 @@
 #include<tree.h>
 
+static int advance(ssize_t,uint8_t**,size_t*);
 static struct tree* tree_add_directory(struct tree*,const char*);
 static int tree_add_file(struct tree*,struct file*);
 static int tree_entry_init_directory(struct tree_entry**,const char*);
 
+static int advance(ssize_t i, uint8_t **buf, size_t *len) {
+       if(i<0) { return -1; }
+
+       (*buf) += i;
+       (*len) -= i;
+
+       return 1;
+}
+
 int tree_add(struct tree *root, const char *path, struct file *to_add) {
        char *str, *p, *prev;
        struct tree *tree;
@@ -110,32 +120,42 @@ static int tree_add_file(struct tree *root, struct file *to_add) {
        return 1;
 }
 
-ssize_t tree_bencode(struct tree *tree, uint8_t *buf, size_t buf_len) {
+ssize_t tree_bencode(struct tree *tree, uint8_t *buf, size_t len) {
        struct tree_entry *p;
        ssize_t i;
+       size_t buf_len;
+
+       buf_len = len;
+       
+       i = bencode_dict_start(buf,len);
+       if(advance(i,&buf,&len)<0) { return -1; }
 
        p = tree->entries;
        while(p!=NULL) {
-               i = bencode_string((const uint8_t*)p->name,strlen(p->name),buf,buf_len);
-               if(i<0) { return -1; }
-
-               buf += i;
-               buf_len -= i;
+               i = bencode_string((const uint8_t*)p->name,strlen(p->name),buf,len);
+               if(advance(i,&buf,&len)<0) { return -1; }
 
                if(p->children!=NULL) {
-                       // write directory
-                       // recurse into subdirectory
+                       i = tree_bencode(p->children,buf,len);
                } else {
-                       // write file
+                       i = file_bencode(p->file,buf,len);
                }
+               if(advance(i,&buf,&len)<0) { return -1; }
+
+               p = p->next;
        }
+       
+       i = bencode_dict_end(buf,len);
+       if(advance(i,&buf,&len)<0) { return -1; }
 
-       return -1;
+       return buf_len - len;
 }
 
 void tree_entry_free(struct tree_entry *p) {
        if(NULL==p) { return; }
        
+       free(p->name);
+
        if(NULL!=p->file) { file_free(p->file); }
        if(NULL!=p->children) { tree_free(p->children); }
 
index a1ae89d483330cad5ceab00ec4a22bd45a988db7..c8e471e0b77e2565172c682813270e48bd77207a 100644 (file)
@@ -37,6 +37,7 @@ block_tests_SOURCES = \
 file_tests_SOURCES = \
        $(common_SOURCES) \
        file.tests.c \
+       $(top_srcdir)/src/bencode/encode.c \
        $(top_srcdir)/src/block.c \
        $(top_srcdir)/src/file.c \
        $(top_srcdir)/src/hash.c
index 25a4320748b73ad0555e5b4eaae0a1435d1c7ee8..72adc766f876d51f5aaddef3311838650ad18d92 100644 (file)
@@ -32,18 +32,18 @@ static void bdecode_integer_basic_test() {
        uint8_t str4[] = "i10928390128301e";
        long long int i;
 
-       assert(bdecode_integer(NULL,sizeof(str1)-1,&i)==-1);
-       assert(bdecode_integer(str1,0,&i)==-1);
-       assert(bdecode_integer(str1,sizeof(str1)-1,NULL)==-1);
-       assert(bdecode_integer(str1,sizeof(str1)-1,&i)==4);
+       assert(bdecode_int(NULL,sizeof(str1)-1,&i)==-1);
+       assert(bdecode_int(str1,0,&i)==-1);
+       assert(bdecode_int(str1,sizeof(str1)-1,NULL)==-1);
+       assert(bdecode_int(str1,sizeof(str1)-1,&i)==4);
        assert(i==10);
 
-       assert(bdecode_integer(str2,sizeof(str2)-1,&i)==3);
+       assert(bdecode_int(str2,sizeof(str2)-1,&i)==3);
        assert(i==0);
 
-       assert(bdecode_integer(str3,sizeof(str3)-1,&i)==-1);
+       assert(bdecode_int(str3,sizeof(str3)-1,&i)==-1);
 
-       assert(bdecode_integer(str4,sizeof(str4)-1,&i)==16);
+       assert(bdecode_int(str4,sizeof(str4)-1,&i)==16);
        assert(i==10928390128301);
 }
 
index 8f1daba1baf8cfee1281935c86e2c8d68d0b6b6b..14e51e9b29a05e80cb0e3bfc577e78e7e30e34b0 100644 (file)
@@ -4,6 +4,7 @@
 
 int main();
 static void extend_file(const char*);
+static void file_bencode_basic_test();
 static void file_hash_basic_test();
 static void file_hash_large_file_test();
 static void file_hash_large_piece_test();
@@ -14,6 +15,7 @@ int main() {
        setup_env();
 
        file_init_basic_test();
+       file_bencode_basic_test();
        file_hash_basic_test();
        file_hash_large_file_test();
        file_hash_large_piece_test();
@@ -39,6 +41,22 @@ static void extend_file(const char *file) {
        fclose(fp);
 }
 
+static void file_bencode_basic_test() {
+       struct file *p;
+       uint8_t buf[100];
+       uint8_t expected[] = "d0:d6:lengthi1024e11:pieces root32:00000000000000000000000000000000ee";
+
+       assert(file_init(&p,TEST_FILE_1)==1);
+       memset(p->root,48,crypto_hash_sha256_BYTES);
+       p->size = 1024;
+
+       assert(69==file_bencode(p,buf,100));
+
+       assert(memcmp(buf,expected,69)==0);
+
+       file_free(p);
+}
+
 static void file_hash_basic_test() {
        struct file *p;
        unsigned char expected1[crypto_hash_sha256_BYTES] = {174,73,190,37,189,244,236,113,18,122,255,20,5,229,77,151,187,72,27,75,203,32,25,154,81,249,19,29,118,7,228,229};
index 6034844588d88effcba75b7ff12afa6ca70d4100..30a4786f937b0885cabed22d323a1be182861d16 100644 (file)
@@ -4,8 +4,6 @@
 
 int main();
 static char *create_random_path();
-static int tree_deep_equals(struct tree*,struct tree*);
-static int tree_entry_equals(struct tree_entry*,struct tree_entry*);
 static void tree_add_basic_test();
 static void tree_add_extended_test();
 static void tree_bencode_basic_test();
@@ -24,6 +22,31 @@ int main() {
        return EXIT_SUCCESS;
 }
 
+static char *create_random_path() {
+       char *str;
+       int len, index;
+
+       char valid[] = " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~";
+
+       str = malloc(100);
+       assert(str!=NULL);
+
+       // make sure string is at least 1 character long (not including '\0'
+       len = rand()%98;
+       len+=2;
+
+       index = 0;
+       while(len>1) {
+               str[index] = valid[rand()%(sizeof(valid)-1)];
+               index++;
+               len--;
+       }
+
+       str[index] = '\0';
+
+       return str;
+}
+
 static void tree_add_basic_test() {
        struct tree *tree;
        struct tree_entry *p;
@@ -125,68 +148,6 @@ static void tree_add_basic_test() {
        tree_free(tree);
 }
 
-static int tree_deep_equals(struct tree *a, struct tree *b) {
-       if(a==NULL&&b==NULL) { return 1; }
-       if((a!=NULL&&b==NULL)||(a==NULL&&b!=NULL)) { return -1; }
-
-       {
-               struct tree_entry *p1, *p2;
-               p1 = a->entries;
-               p2 = b->entries;
-               while(p1!=NULL) {
-                       if(p2==NULL) { return -1; }
-                       if(tree_entry_equals(p1,p2)<0) { return -1; }
-
-                       p1 = p1->next;
-                       p2 = p2->next;
-               }
-       }
-
-       return 1;
-}
-
-static int tree_entry_equals(struct tree_entry *a, struct tree_entry *b) {
-       if((a->name!=NULL&&b->name==NULL)||(a->name==NULL&&b->name!=NULL)) { return -1; }
-       if(a->name!=NULL) {
-               if(strcmp(a->name,b->name)!=0) { return -1; }
-       }
-
-       if(tree_deep_equals(a->children,b->children)<0) { return -1; }
-
-       if((a->file!=NULL&&b->file==NULL)||(a->file==NULL&&b->file!=NULL)) { return -1; }
-       if(a->file!=NULL) {
-               if(strcmp(a->file->name,b->file->name)!=0) { return -1; }
-               if(strcmp(a->file->path,b->file->path)!=0) { return -1; }
-       }
-
-       return 1;
-}
-
-static char *create_random_path() {
-       char *str;
-       int len, index;
-
-       char valid[] = " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~";
-
-       str = malloc(100);
-       assert(str!=NULL);
-
-       // make sure string is at least 1 character long (not including '\0'
-       len = rand()%98;
-       len+=2;
-
-       index = 0;
-       while(len>1) {
-               str[index] = valid[rand()%(sizeof(valid)-1)];
-               index++;
-               len--;
-       }
-
-       str[index] = '\0';
-
-       return str;
-}
-
 static void tree_add_extended_test() {
        struct tree *tree;
        struct file *file;
@@ -206,18 +167,23 @@ static void tree_add_extended_test() {
 static void tree_bencode_basic_test() {
        struct tree *root;
        struct file *file;
-       uint8_t buf[100];
+       uint8_t buf[120];
        char fileA_path[] = "dir1/dir2/fileA.txt";
-       uint8_t expected[] = "d4:dir1d4:dir2d9:fileA.txtd0:d5:lengthi102411:pieces root32:00000000000000000000000000000000eeeee";
+       uint8_t expected[] = "d4:dir1d4:dir2d9:fileA.txtd0:d6:lengthi1024e11:pieces root32:00000000000000000000000000000000eeeee";
 
        assert(1==tree_init(&root));
 
        assert(1==file_init(&file,fileA_path));
        memset(file->root,48,crypto_hash_sha256_BYTES);
+       file->size = 1024;
+
+       assert(1==tree_add(root,file->path,file));
+
+       assert(98==tree_bencode(root,buf,120));
 
-       assert(45==tree_bencode(root,buf,100));
+       assert(memcmp(buf,expected,98)==0);
 
-       assert(memcmp(buf,expected,45)==0);
+       tree_free(root);
 }
 
 static void tree_init_basic_test() {