From: alex Date: Wed, 27 Oct 2021 21:18:38 +0000 (-0700) Subject: ... X-Git-Url: http://git.infiniteadaptability.org/?a=commitdiff_plain;h=794fc57be8497f19f9d4a831fc85fe3cc4986db4;p=seeder ... --- diff --git a/Makefile.am b/Makefile.am index 0b37448..90c8c4e 100644 --- a/Makefile.am +++ b/Makefile.am @@ -13,6 +13,8 @@ bin_PROGRAMS = seederd seederd_SOURCES = \ src/add.c \ + src/bencode/decode.c \ + src/bencode/encode.c \ src/default.c \ src/file.c \ src/hash.c \ @@ -44,6 +46,7 @@ seederd_SOURCES = \ seederd_SOURCES += \ inc/add.h \ + inc/bencode.h \ inc/default.h \ inc/file.h \ inc/hash.h \ diff --git a/inc/bencode.h b/inc/bencode.h new file mode 100644 index 0000000..190613e --- /dev/null +++ b/inc/bencode.h @@ -0,0 +1,27 @@ +#ifndef __BENCODE_H_ +#define __BENCODE_H_ + +#include +#include +#include +#include +#include + +enum bencode_type { + BENCODE_DICTIONARY, + BENCODE_INTEGER, + BENCODE_LIST, + BENCODE_STRING +}; + +ssize_t bdecode_integer(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_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); + +#endif diff --git a/src/bencode/decode.c b/src/bencode/decode.c new file mode 100644 index 0000000..23c7d21 --- /dev/null +++ b/src/bencode/decode.c @@ -0,0 +1,67 @@ +#include + +ssize_t bdecode_integer(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; } + + const uint8_t *p = NULL; + for(size_t i=0;i3)) { return -1; } + if(buf[i]=='e') { + p = &(buf[i]); + } + } + + if(NULL==p) { return -1; } + + ssize_t len = p - (buf+1); + uint8_t *num_string = (uint8_t*) strndup((const char*)&(buf[1]),len); + *output = atoll((char *)num_string); + free(num_string); + + len += 2; + + return len; +} + +ssize_t bdecode_string(const uint8_t *buf, size_t buf_len, uint8_t *output, size_t output_size) { + if(NULL==buf) { return -1; } + if(buf_len<=0) { return -1; } + if(NULL==output) { return -1; } + + const uint8_t *p = NULL; + for(size_t i=0;ioutput_size)) { return -1; } + + p++; + memcpy(output,p,str_len); + + return len; +} + +enum bencode_type bdecode_type(const uint8_t *buf, size_t len) { + switch(buf[0]) { + case 'i': + return BENCODE_INTEGER; + case 'l': + return BENCODE_LIST; + case 'd': + return BENCODE_DICTIONARY; + default: + return BENCODE_STRING; + } +} diff --git a/src/bencode/encode.c b/src/bencode/encode.c new file mode 100644 index 0000000..b21c6b8 --- /dev/null +++ b/src/bencode/encode.c @@ -0,0 +1,85 @@ +#include + +static size_t size_int(int i); + +ssize_t bencode_dict_end(uint8_t *output, size_t output_size) { + if(NULL==output) { return -1; } + if(output_size<=1) { return -1; } + + output[0] = 'e'; + + return 1; +} + +ssize_t bencode_dict_start(uint8_t *output, size_t output_size) { + if(NULL==output) { return -1; } + if(output_size<=1) { return -1; } + + output[0] = 'd'; + + return 1; +} + +ssize_t bencode_int(int to_encode, uint8_t *output, size_t output_size) { + size_t i; + int ret; + + if(NULL==output) { return -1; } + + i = size_int(to_encode); + i += 2; + + if((ret = snprintf((char*)output,output_size,"i%de",to_encode))<0) { return -1; } + if(ret!=i) { return -1; } + + return i; +} + +ssize_t bencode_list_end(uint8_t *output, size_t output_size) { + if(NULL==output) { return -1; } + if(output_size<=1) { return -1; } + + output[0] = 'e'; + + return 1; +} + +ssize_t bencode_list_start(uint8_t *output, size_t output_size) { + if(NULL==output) { return -1; } + if(output_size<=1) { return -1; } + + output[0] = 'l'; + + return 1; +} + +ssize_t bencode_string(const uint8_t *str, size_t len, uint8_t *output, size_t output_size) { + size_t i; + int ret; + + if(NULL==str) { return -1; } + if(len<=0) { return -1; } + if(NULL==output) { return -1; } + if(len>output_size) { return -1; } + + i = size_int(len); + i++; + i += len; + + if((ret = snprintf((char*)output,output_size,"%lu:%s",len,(const char*)str))<0) { return -1; } + + if(ret!=i) { return -1; } + + return i; +} + + +static size_t size_int(int i) { + i = abs(i); + size_t j = 0; + while(i>0) { + i /= 10; + j++; + } + return j; +} diff --git a/test/unit/Makefile.am b/test/unit/Makefile.am index 41d1d2d..77aa90a 100644 --- a/test/unit/Makefile.am +++ b/test/unit/Makefile.am @@ -12,7 +12,7 @@ AM_CPPFLAGS += \ -DNDEBUG endif -check_PROGRAMS = file.tests hash.tests hashmap.tests torrent.tests tree.tests util.filter.tests +check_PROGRAMS = bencode.tests file.tests hash.tests hashmap.tests torrent.tests tree.tests util.filter.tests TESTS = $(check_PROGRAMS) if ENABLE_MEMCHECK @@ -22,6 +22,12 @@ endif common_SOURCES = test_utils.c +bencode_tests_SOURCES = \ + $(common_SOURCES) \ + bencode.tests.c \ + $(top_srcdir)/src/bencode/decode.c \ + $(top_srcdir)/src/bencode/encode.c + file_tests_SOURCES = \ $(common_SOURCES) \ file.tests.c \ diff --git a/test/unit/bencode.tests.c b/test/unit/bencode.tests.c new file mode 100644 index 0000000..08e1cad --- /dev/null +++ b/test/unit/bencode.tests.c @@ -0,0 +1,150 @@ +#include + +#include + +int main(); +static void bdecode_integer_basic_test(); +static void bdecode_string_basic_test(); +static void bdecode_type_basic_test(); +static void bencode_dict_basic_test(); +static void bencode_list_basic_test(); +static void bencode_string_basic_test(); + +int main() { + setup_env(); + + bdecode_integer_basic_test(); + bdecode_string_basic_test(); + bdecode_type_basic_test(); + bencode_dict_basic_test(); + bencode_list_basic_test(); + bencode_string_basic_test(); + + clean_env(); + + return EXIT_SUCCESS; +} + +static void bdecode_integer_basic_test() { + uint8_t str1[] = "i10e"; + uint8_t str2[] = "i0e"; + uint8_t str3[] = "i0023423e"; + 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(i==10); + + assert(bdecode_integer(str2,sizeof(str2)-1,&i)==3); + assert(i==0); + + assert(bdecode_integer(str3,sizeof(str3)-1,&i)==-1); + + assert(bdecode_integer(str4,sizeof(str4)-1,&i)==16); + assert(i==10928390128301); +} + +static void bdecode_string_basic_test() { + uint8_t buf[1024]; + uint8_t str1[] = "4:spam"; + + assert(bdecode_string(NULL,sizeof(str1)-1,buf,1024)==-1); + assert(bdecode_string(str1,0,buf,1024)==-1); + assert(bdecode_string(str1,sizeof(str1)-1,NULL,1024)==-1); + assert(bdecode_string(str1,sizeof(str1)-1,buf,0)==-1); + assert(bdecode_string(str1,sizeof(str1)-1,buf,3)==-1); + assert(bdecode_string(str1,sizeof(str1)-1,buf,4)==4); + assert(bdecode_string(str1,sizeof(str1)-1,buf,1024)==4); +} + +static void bdecode_type_basic_test() { + uint8_t str1[] = "4:spam"; + uint8_t str2[] = "i12093e"; + uint8_t str3[] = "l4:spam4:eggse"; + uint8_t str4[] = "d3:cow3:moo4:spam4:eggse"; + + assert(BENCODE_STRING==bdecode_type(str1,sizeof(str1)-1)); + assert(BENCODE_INTEGER==bdecode_type(str2,sizeof(str2)-1)); + assert(BENCODE_LIST==bdecode_type(str3,sizeof(str3)-1)); + assert(BENCODE_DICTIONARY==bdecode_type(str4,sizeof(str4)-1)); +} + +static void bencode_dict_basic_test() { + uint8_t buf[1024]; + uint8_t *p; + + memset(buf,0,1024); + + p = buf; + assert(bencode_dict_start(NULL,1024)==-1); + assert(bencode_dict_start(p,0)==-1); + assert(bencode_dict_start(p,1024)==1); + p++; + + uint8_t str1[] = "cow"; + assert(bencode_string(str1,3,p,1023)==5); + p += 5; + + uint8_t str2[] = "moo"; + assert(bencode_string(str2,3,p,1018)==5); + p += 5; + + uint8_t str3[] = "spam"; + assert(bencode_string(str3,4,p,1013)==6); + p += 6; + + uint8_t str4[] = "eggs"; + assert(bencode_string(str4,4,p,1007)==6); + p += 6; + + assert(bencode_dict_end(NULL,1001)==-1); + assert(bencode_dict_end(p,0)==-1); + assert(bencode_dict_end(p,1001)==1); + + assert(memcmp(buf,"d3:cow3:moo4:spam4:eggse",24)==0); +} + +static void bencode_list_basic_test() { + uint8_t buf[1024]; + uint8_t *p; + + memset(buf,0,1024); + + p = buf; + assert(bencode_list_start(NULL,1024)==-1); + assert(bencode_list_start(p,0)==-1); + assert(bencode_list_start(p,1024)==1); + p++; + + uint8_t str1[] = "spam"; + assert(bencode_string(str1,4,p,1023)==6); + p += 6; + + uint8_t str2[] = "eggs"; + assert(bencode_string(str2,4,p,1017)==6); + p += 6; + + assert(bencode_list_end(NULL,1011)==-1); + assert(bencode_list_end(p,0)==-1); + assert(bencode_list_end(p,1011)==1); + + assert(memcmp(buf,"l4:spam4:eggse",14)==0); +} + +static void bencode_string_basic_test() { + uint8_t buf[1024]; + + memset(buf,0,1024); + + uint8_t str1[] = "testlkajslfkdjasdfl test string"; + assert(bencode_string(NULL,31,buf,1024)==-1); + assert(bencode_string(str1,0,buf,1024)==-1); + assert(bencode_string(str1,31,NULL,1024)==-1); + assert(bencode_string(str1,31,buf,0)==-1); + assert(bencode_string(str1,31,buf,1024)==34); + + assert(memcmp("31:testlkajslfkdjasdfl test string",buf,34)==0); +} diff --git a/test/unit/torrent.tests.c b/test/unit/torrent.tests.c index da41854..70140a4 100644 --- a/test/unit/torrent.tests.c +++ b/test/unit/torrent.tests.c @@ -33,11 +33,11 @@ static void torrent_add_basic_test() { assert(torrent_add(torrent,file3)==1); assert(torrent_add(torrent,file4)==1); - assert(strcmp(torrent->file_tree->directories->name,TEST_DIRECTORY)==0); - assert(torrent->file_tree->directories->files->file==file3); - assert(torrent->file_tree->directories->files->next->file==file4); - assert(torrent->file_tree->directories->files->next->next->file==file1); - assert(torrent->file_tree->directories->files->next->next->next->file==file2); + assert(strcmp(torrent->tree->directories->name,TEST_DIRECTORY)==0); + assert(torrent->tree->directories->files->file==file3); + assert(torrent->tree->directories->files->next->file==file4); + assert(torrent->tree->directories->files->next->next->file==file1); + assert(torrent->tree->directories->files->next->next->next->file==file2); torrent_free(torrent);