From 9bf9aceb131647b845a23480b326637987f95cde Mon Sep 17 00:00:00 2001 From: alex Date: Tue, 14 Dec 2021 21:41:31 -0800 Subject: [PATCH] ... --- Makefile.am | 1 + inc/bencode.h | 2 ++ inc/torrent.h | 1 - inc/tree.h | 1 + src/bencode/encode.c | 35 ++++++++++++++---------- src/torrent/file.c | 1 - src/torrent/info.c | 40 +++++++++++++++++----------- src/torrent/piece.c | 62 ++++++++++++++++++++++++++----------------- src/tree.c | 4 +++ test/unit/Makefile.am | 1 + 10 files changed, 92 insertions(+), 56 deletions(-) diff --git a/Makefile.am b/Makefile.am index 483ce40..746c99b 100644 --- a/Makefile.am +++ b/Makefile.am @@ -46,6 +46,7 @@ seederd_SOURCES = \ src/torrent/info.c \ src/torrent/init.c \ src/torrent/magnet.c \ + src/torrent/piece.c \ src/tree.c \ src/usage.c \ src/watch.c diff --git a/inc/bencode.h b/inc/bencode.h index e080675..0d4ecff 100644 --- a/inc/bencode.h +++ b/inc/bencode.h @@ -22,6 +22,8 @@ ssize_t bencode_dict_start(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_size(size_t,uint8_t*,size_t); +size_t bencode_size_int(int); ssize_t bencode_string(const uint8_t*,size_t,uint8_t*,size_t); #endif diff --git a/inc/torrent.h b/inc/torrent.h index 24c67ab..939e038 100644 --- a/inc/torrent.h +++ b/inc/torrent.h @@ -37,6 +37,5 @@ int torrent_file_piece_layers(FILE*,struct torrent*); void torrent_free(struct torrent*); int torrent_init(struct torrent**,const char*,const char*,unsigned long long); char *torrent_magnet(struct torrent*); -int torrent_bencode_piece_layers(); #endif diff --git a/inc/tree.h b/inc/tree.h index b2893bb..f315945 100644 --- a/inc/tree.h +++ b/inc/tree.h @@ -22,6 +22,7 @@ struct tree { int tree_add(struct tree*,const char*,struct file*); ssize_t tree_bencode(struct tree*,uint8_t*,size_t); +size_t tree_bencode_length(struct tree*); void tree_entry_free(struct tree_entry*); int tree_entry_init(struct tree_entry**, struct file*); void tree_free(struct tree*); diff --git a/src/bencode/encode.c b/src/bencode/encode.c index 536532a..c7dc994 100644 --- a/src/bencode/encode.c +++ b/src/bencode/encode.c @@ -1,7 +1,5 @@ #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; } @@ -26,7 +24,7 @@ ssize_t bencode_int(long long int to_encode, uint8_t *output, size_t output_size if(NULL==output) { return -1; } - i = size_int(to_encode); + i = bencode_size_int(to_encode); i += 2; if((ret = snprintf((char*)output,output_size,"i%llue",to_encode))<0) { return -1; } @@ -53,26 +51,20 @@ ssize_t bencode_list_start(uint8_t *output, size_t output_size) { return 1; } -ssize_t bencode_string(const uint8_t *str, size_t len, uint8_t *output, size_t output_size) { +ssize_t bencode_size(size_t len, uint8_t *output, size_t output_size) { size_t i; - - if(NULL==str) { return -1; } - if(NULL==output) { return -1; } - i = size_int(len); + i = bencode_size_int(len); i++; // account for ':' - if(i+len>output_size) { return -1; } + if(i>output_size) { return -1; } // snprintf requires space for '\0' otherwise will truncate if(snprintf((char*)output,i+1,"%lu:",len)!=i) { return -1; } - memcpy(&(output[i]),str,len); - - return i+len; + return i; } - -static size_t size_int(int i) { +size_t bencode_size_int(int i) { size_t j = (i<0)?1:0; i = abs(i); @@ -84,3 +76,18 @@ static size_t size_int(int i) { } return j; } + +ssize_t bencode_string(const uint8_t *str, size_t len, uint8_t *output, size_t output_size) { + size_t i; + + if(NULL==str) { return -1; } + if(NULL==output) { return -1; } + + if((i = bencode_size(len,output,output_size))<0) { return -1; } + + if(i+len>output_size) { return -1; } + + memcpy(&(output[i]),str,len); + + return i+len; +} diff --git a/src/torrent/file.c b/src/torrent/file.c index c0ed145..dc1e0a7 100644 --- a/src/torrent/file.c +++ b/src/torrent/file.c @@ -1,6 +1,5 @@ #include -static int piece_layer_sort(const void*,const void*); static int torrent_file_announce(FILE*,struct torrent*); static int torrent_file_write_end(FILE*); static int torrent_file_write_info(FILE*,uint8_t*,size_t); diff --git a/src/torrent/info.c b/src/torrent/info.c index 99347e7..71f8474 100644 --- a/src/torrent/info.c +++ b/src/torrent/info.c @@ -1,54 +1,64 @@ #include -#define INITIAL_TORRENT_INFO_SIZE 16384 +static size_t torrent_file_info_length(struct tree *tree); + +static uint8_t file_tree_string[] = "file tree"; +static uint8_t meta_version_string[] = "meta version"; +static uint8_t name_string[] = "name"; +static uint8_t piece_length_string[] = "piece length"; ssize_t torrent_file_info(struct torrent *torrent_p, uint8_t **buf) { uint8_t *p; - ssize_t i, len; - size_t buf_len; + ssize_t i, len, buf_len; if(NULL==buf) { return -1; } - p = malloc(INITIAL_TORRENT_INFO_SIZE); + buf_len = torrent_file_info_length(torrent_p->tree); + p = malloc(sizeof(uint8_t)*buf_len); if(NULL==p) { return -1; } len = 0; - buf_len = INITIAL_TORRENT_INFO_SIZE; if((i = bencode_dict_start(p,buf_len))<0) { goto clean; } len += i; - uint8_t file_tree_string[] = "file tree"; if((i = bencode_string(file_tree_string,sizeof(file_tree_string)-1,&(p[len]),buf_len-len))<0) { goto clean; } len += i; if((i = tree_bencode(torrent_p->tree,&(p[len]),buf_len-len))<0) { goto clean; } len += i; - uint8_t meta_version_string[] = "meta version"; if((i = bencode_string(meta_version_string,sizeof(meta_version_string)-1,&(p[len]),buf_len-len))<0) { goto clean; } len += i; if((i = bencode_int(2,&(p[len]),buf_len-len))<0) { goto clean; } len += i; - uint8_t name_string[] = "name"; if((i = bencode_string(name_string,sizeof(name_string)-1,&(p[len]),buf_len-len))<0) { goto clean; } len += i; if((i = bencode_string((const uint8_t*)torrent_p->name,strlen(torrent_p->name),&(p[len]),buf_len-len))<0) { goto clean; } len += i; - uint8_t piece_length_string[] = "piece length"; if((i = bencode_string(piece_length_string,sizeof(piece_length_string)-1,&(p[len]),buf_len-len))<0) { goto clean; } len += i; if((i = bencode_int(torrent_p->piece_length,&(p[len]),buf_len-len))<0) { goto clean; } len += i; - *buf = malloc(len); - if(NULL==(*buf)) { goto clean; } - - memcpy(*buf,p,len); - free(p); - return len; clean: free(p); return -1; } + +static size_t torrent_file_info_length(struct tree *tree) { + size_t i; + + i = 0; + + // string length = sizeof()-1, +1 for ':' included + i += sizeof(file_tree_string)+bencode_size_int(sizeof(file_tree_string)); + i += sizeof(meta_version_string)+bencode_size_int(sizeof(file_tree_string)); + i += sizeof(name_string)+bencode_size_int(sizeof(file_tree_string)); + i += sizeof(piece_length_string)+bencode_size_int(sizeof(file_tree_string)); + + i += tree_bencode_length(tree); + + return i; +} diff --git a/src/torrent/piece.c b/src/torrent/piece.c index 94725f7..07f6ed1 100644 --- a/src/torrent/piece.c +++ b/src/torrent/piece.c @@ -1,37 +1,38 @@ #include -ssize_t torrent_bencode_piece_layers(struct torrent *torrent_p, unsigned char *hash) { - struct file *file_p; +static int piece_layer_sort(const void*, const void*); +static int torrent_bencode_piece_layers(FILE*,struct file*); + +#define PIECE_LAYER_BENCODED_LENGTH 2+1+32+2+1+32 + +static int torrent_bencode_piece_layers(FILE *fp, struct file *file_p) { struct block *p; - size_t buf_len, len; + size_t blocks; ssize_t i; - uint8_t *buf; - - file_p = hashmap_find(torrent_p->files.roots,hash,crypto_hash_sha256_BYTES) - if(NULL==file_p) { return -1; } - - // more lenght + uint8_t buf[PIECE_LAYER_BENCODED_LENGTH]; - buf = malloc(sizeof(uint8_t)*len); - if(NULL==buf) { return -1; } + if((i = bencode_string(file_p->root,crypto_hash_sha256_BYTES,buf,PIECE_LAYER_BENCODED_LENGTH))<0) { return -1; } + if(fwrite(buf,sizeof(uint8_t),i,fp)!=i) { return -1; } - buf_len = len; + blocks = block_length(file_p->piece_layers); + if((i = bencode_size(blocks*crypto_hash_sha256_BYTES,buf,PIECE_LAYER_BENCODED_LENGTH))<0) { return -1; } - if((i = bencode_string(file_p->root,crypto_hash_sha256_BYTES,buf,len))<0) { goto clean; } - buf += i; - len -= i; + if(fwrite(buf,sizeof(uint8_t),i,fp)!=i) { return -1; } p = file_p->piece_layers; - while( + while(p!=NULL) { + if(fwrite(p->hash,sizeof(uint8_t),crypto_hash_sha256_BYTES,fp)!=crypto_hash_sha256_BYTES) { return -1; } - return -1; + p = p->next; + } + + return 1; } int torrent_file_piece_layers(FILE *fp, struct torrent *p) { unsigned char **hashes; size_t index, pieces; struct file *file_p; - struct block **piece_layers, *block_p; pieces = 0; for(size_t i=0;ifiles.roots->size;i++) { @@ -54,19 +55,30 @@ int torrent_file_piece_layers(FILE *fp, struct torrent *p) { qsort(hashes,pieces,sizeof(unsigned char*),&piece_layer_sort); - // NOT DONE + // hashes[0] should never be NULL + if(NULL==hashes[0]) { return -1; } + + file_p = hashmap_find(p->files.roots,hashes[0],crypto_hash_sha256_BYTES); + if(NULL==file_p) { return -1; } + for(size_t i=0;ifiles.roots->map[i]; + file_p = hashmap_find(p->files.roots,hash,crypto_hash_sha256_BYTES); + if(NULL==file_p) { break; } // sorting guarantees all NULLs at end + + if(torrent_bencode_piece_layers(fp,file_p)<0) { goto clean; } + } + + free(hashes); return 1; -//clean: -// free(piece_layers); -// return -1; +clean: + free(hashes); + return -1; } static int piece_layer_sort(const void *p1, const void *p2) { - if(NULL==a) { return 1; } - if(NULL==b) { return -1; } + if(NULL==p1) { return 1; } + if(NULL==p2) { return -1; } return memcmp(p1,p2,crypto_hash_sha256_BYTES); } diff --git a/src/tree.c b/src/tree.c index 10322aa..6503b08 100644 --- a/src/tree.c +++ b/src/tree.c @@ -151,6 +151,10 @@ ssize_t tree_bencode(struct tree *tree, uint8_t *buf, size_t len) { return buf_len - len; } +size_t tree_bencode_length(struct tree *p) { + return 0; +} + void tree_entry_free(struct tree_entry *p) { if(NULL==p) { return; } diff --git a/test/unit/Makefile.am b/test/unit/Makefile.am index a542789..82ec0ae 100644 --- a/test/unit/Makefile.am +++ b/test/unit/Makefile.am @@ -77,6 +77,7 @@ torrent_tests_SOURCES = \ $(top_srcdir)/src/torrent/info.c \ $(top_srcdir)/src/torrent/init.c \ $(top_srcdir)/src/torrent/magnet.c \ + $(top_srcdir)/src/torrent/piece.c \ $(top_srcdir)/src/tree.c tree_tests_SOURCES = \ -- 2.39.5