From f0f44772f2ac7176069d05fcf1f49083bdf8e52a Mon Sep 17 00:00:00 2001 From: alex Date: Fri, 3 Dec 2021 17:10:15 -0800 Subject: [PATCH] ... --- inc/bencode.h | 4 +- inc/file.h | 2 + src/bencode/decode.c | 2 +- src/bencode/encode.c | 4 +- src/file.c | 49 ++++++++++++++++++ src/tree.c | 40 +++++++++++---- test/unit/Makefile.am | 1 + test/unit/bencode.tests.c | 14 +++--- test/unit/file.tests.c | 18 +++++++ test/unit/tree.tests.c | 102 +++++++++++++------------------------- 10 files changed, 146 insertions(+), 90 deletions(-) diff --git a/inc/bencode.h b/inc/bencode.h index 190613e..e080675 100644 --- a/inc/bencode.h +++ b/inc/bencode.h @@ -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); diff --git a/inc/file.h b/inc/file.h index bc56fc9..9c4843c 100644 --- a/inc/file.h +++ b/inc/file.h @@ -8,6 +8,7 @@ #include +#include #include #include @@ -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*); diff --git a/src/bencode/decode.c b/src/bencode/decode.c index 23c7d21..8963eee 100644 --- a/src/bencode/decode.c +++ b/src/bencode/decode.c @@ -1,6 +1,6 @@ #include -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; } diff --git a/src/bencode/encode.c b/src/bencode/encode.c index 01fc8c8..8ba8ffc 100644 --- a/src/bencode/encode.c +++ b/src/bencode/encode.c @@ -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; diff --git a/src/file.c b/src/file.c index 0fcc7a2..1aa0361 100644 --- a/src/file.c +++ b/src/file.c @@ -1,6 +1,55 @@ #include 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; } diff --git a/src/tree.c b/src/tree.c index 1b3207a..10322aa 100644 --- a/src/tree.c +++ b/src/tree.c @@ -1,9 +1,19 @@ #include +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); } diff --git a/test/unit/Makefile.am b/test/unit/Makefile.am index a1ae89d..c8e471e 100644 --- a/test/unit/Makefile.am +++ b/test/unit/Makefile.am @@ -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 diff --git a/test/unit/bencode.tests.c b/test/unit/bencode.tests.c index 25a4320..72adc76 100644 --- a/test/unit/bencode.tests.c +++ b/test/unit/bencode.tests.c @@ -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); } diff --git a/test/unit/file.tests.c b/test/unit/file.tests.c index 8f1daba..14e51e9 100644 --- a/test/unit/file.tests.c +++ b/test/unit/file.tests.c @@ -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}; diff --git a/test/unit/tree.tests.c b/test/unit/tree.tests.c index 6034844..30a4786 100644 --- a/test/unit/tree.tests.c +++ b/test/unit/tree.tests.c @@ -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() { -- 2.30.2