...
authoralex <[email protected]>
Thu, 23 Dec 2021 20:43:50 +0000 (12:43 -0800)
committeralex <[email protected]>
Thu, 23 Dec 2021 20:43:50 +0000 (12:43 -0800)
src/bencode/encode.c
src/torrent/info.c
src/torrent/magnet.c
src/torrent/piece.c
test/unit/test_utils.h
test/unit/torrent.tests.c

index 6da200049986f91e8bb41f8c7634be9cc4706f86..ef1ccd1d83623f5f475e2fdc73985959de7ec157 100644 (file)
@@ -2,7 +2,7 @@
 
 ssize_t bencode_dict_end(uint8_t *output, size_t output_size) {
        if(NULL==output) { return -1; }
-       if(output_size<=1) { return -1; }
+       if(output_size<1) { return -1; }
 
        output[0] = 'e';
 
@@ -11,7 +11,7 @@ ssize_t bencode_dict_end(uint8_t *output, size_t output_size) {
 
 ssize_t bencode_dict_start(uint8_t *output, size_t output_size) {
        if(NULL==output) { return -1; }
-       if(output_size<=1) { return -1; }
+       if(output_size<1) { return -1; }
 
        output[0] = 'd';
 
index 71f84743be05b5bdf8824b9f4bfd31fbf5e43176..28d63f657dec71baee1a829f157bb8cf9f50b5be 100644 (file)
@@ -1,9 +1,12 @@
 #include<torrent.h>
 
-static size_t torrent_file_info_length(struct tree *tree);
+static size_t torrent_file_info_length(struct torrent*);
 
 static uint8_t file_tree_string[] = "file tree";
 static uint8_t meta_version_string[] = "meta version";
+
+#define TORRENT_FILE_META_VERSION 2
+
 static uint8_t name_string[] = "name";
 static uint8_t piece_length_string[] = "piece length";
 
@@ -13,7 +16,7 @@ ssize_t torrent_file_info(struct torrent *torrent_p, uint8_t **buf) {
 
        if(NULL==buf) { return -1; }
 
-       buf_len = torrent_file_info_length(torrent_p->tree);
+       buf_len = torrent_file_info_length(torrent_p);
        p = malloc(sizeof(uint8_t)*buf_len);
        if(NULL==p) { return -1; }
 
@@ -28,7 +31,7 @@ ssize_t torrent_file_info(struct torrent *torrent_p, uint8_t **buf) {
        
        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; }
+       if((i = bencode_int(TORRENT_FILE_META_VERSION,&(p[len]),buf_len-len))<0) { goto clean; }
        len += i;
 
        if((i = bencode_string(name_string,sizeof(name_string)-1,&(p[len]),buf_len-len))<0) { goto clean; }
@@ -41,24 +44,35 @@ ssize_t torrent_file_info(struct torrent *torrent_p, uint8_t **buf) {
        if((i = bencode_int(torrent_p->piece_length,&(p[len]),buf_len-len))<0) { goto clean; }
        len += i;
 
+       if((i = bencode_dict_end(&(p[len]),buf_len-len))<0) { goto clean; }
+       len += i;
+
+       (*buf) = p;
+
        return len;
 clean:
        free(p);
        return -1;
 }
 
-static size_t torrent_file_info_length(struct tree *tree) {
-       size_t i;
+static size_t torrent_file_info_length(struct torrent *p) {
+       size_t i, len;
 
-       i = 0;
+       i = 2; // opening '{' (d) and ending '}' (e)
 
        // 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(p->tree);
+
+       i += sizeof(meta_version_string)+bencode_size_int(sizeof(meta_version_string));
+       i += bencode_size_int(TORRENT_FILE_META_VERSION)+2; // i[INT]e
+
+       len = strlen(p->name);
+       i += sizeof(name_string)+bencode_size_int(sizeof(name_string));
+       i += bencode_size_int(len)+len;
 
-       i += tree_bencode_length(tree);
+       i += sizeof(piece_length_string)+bencode_size_int(sizeof(piece_length_string));
+       i += bencode_size_int(p->piece_length)+2; // i[INT]e
 
        return i;
 }
index 2a27ab607ffac2e67b36f83ffe3c3a33a934d0ca..f0eff3499cc7462b2cf7cbbf3a6131f91f752ab3 100644 (file)
@@ -14,7 +14,6 @@ char *torrent_magnet(struct torrent *torrent_p) {
        info = NULL;
        if((i = torrent_file_info(torrent_p,&info))<0) { goto clean; }
 
-
        if(hash(info,i,infohash,crypto_hash_sha256_BYTES)<0) { goto clean; }
        free(info);
        info = NULL;
index 07f6ed1ef5c3d011d5cc5976ceb82ae986792133..5443b1c7b0216b9ca4699617d918a4a10cc4e5e8 100644 (file)
@@ -41,29 +41,22 @@ int torrent_file_piece_layers(FILE *fp, struct torrent *p) {
        }
 
        hashes = malloc(sizeof(unsigned char*));
-       if(NULL==hashes) {
-               return -1;
-       }
+       if(NULL==hashes) { return -1; }
 
        index = 0;
        for(size_t i=0;i<p->files.roots->size;i++) {
                file_p = (struct file*)p->files.roots->map[i];
                if(file_p!=NULL) {
                        hashes[index] = file_p->root;
+                       index++;
                }
        }
 
        qsort(hashes,pieces,sizeof(unsigned char*),&piece_layer_sort);
 
-       // 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;i<pieces;i++) {
-               file_p = hashmap_find(p->files.roots,hash,crypto_hash_sha256_BYTES);
-               if(NULL==file_p) { break; } // sorting guarantees all NULLs at end
+               file_p = hashmap_find(p->files.roots,hashes[i],crypto_hash_sha256_BYTES);
+               if(NULL==file_p) { goto clean; }
 
                if(torrent_bencode_piece_layers(fp,file_p)<0) { goto clean; }
        }
@@ -80,5 +73,5 @@ static int piece_layer_sort(const void *p1, const void *p2) {
        if(NULL==p1) { return 1; }
        if(NULL==p2) { return -1; }
 
-       return memcmp(p1,p2,crypto_hash_sha256_BYTES);
+       return memcmp(*(unsigned char**)p1,*(unsigned char**)p2,crypto_hash_sha256_BYTES);
 }
index 02932cc3b703998a96566df4b4ccd7ed218b957f..44b407ee61867dea101378969ef420ba06429063 100644 (file)
@@ -20,6 +20,7 @@
 #define TEST_FILE_4 PREFIX "/.test.meta"
 #define TEST_FILE_4_CONTENTS ";alsikdjf;lkasdjflk\n;asjdflk\n;ajsdklfjl;aksdfjla;kj"
 #define TEST_FILE_5 PREFIX "/random.test"
+#define TEST_FILE_6 PREFIX "/file.torrent"
 
 void clean_env();
 void reset_env();
index 8b8300eb726b8401e7852fa8c7666e96b7baf407..9c598486e233c0db7f46b56ba6cfbea21aefdfc6 100644 (file)
@@ -6,6 +6,7 @@ int main();
 static void torrent_add_basic_test();
 static void torrent_file_info_basic_test();
 static void torrent_file_path_basic_test();
+static void torrent_file_piece_layers_basic_test();
 static void torrent_init_basic_test();
 static void torrent_magnet_basic_test();
 static void torrent_setup_example(struct torrent**);
@@ -15,6 +16,7 @@ int main() {
 
        torrent_init_basic_test();
        torrent_add_basic_test();
+       torrent_file_piece_layers_basic_test();
        torrent_magnet_basic_test();
        torrent_file_info_basic_test();
        torrent_file_path_basic_test();
@@ -83,10 +85,10 @@ static void torrent_file_info_basic_test() {
        assert(-1==torrent_file_info(NULL,NULL));
        assert(-1==torrent_file_info(torrent,NULL));
 
-       assert(212==torrent_file_info(torrent,&buf));
+       assert(213==torrent_file_info(torrent,&buf));
 
-       uint8_t expected[] = "d9:file treed4:testd0:d6:lengthi0e11:pieces root32:" "\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01" "ee5:test2d0:d6:lengthi0e11:pieces root32:" "\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02" "eee12:meta versioni2e4:name5:.test12:piece lengthi16384e";
-       assert(memcmp(buf,expected,212)==0);
+       uint8_t expected[] = "d9:file treed4:testd0:d6:lengthi0e11:pieces root32:" "\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01" "ee5:test2d0:d6:lengthi0e11:pieces root32:" "\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02" "eee12:meta versioni2e4:name5:.test12:piece lengthi16384ee";
+       assert(memcmp(buf,expected,213)==0);
 
        free(buf);
 
@@ -115,6 +117,54 @@ static void torrent_file_path_basic_test() {
        free(p);
 }
 
+static void hash_torrent_file(unsigned char *hash, size_t hash_len) {
+       uint8_t buf[16384];
+       crypto_hash_sha256_state st;
+       FILE *fp;
+       size_t i;
+
+       assert(hash_len==crypto_hash_sha256_BYTES);
+
+       fp = fopen(TEST_FILE_6,"w");
+       assert(fp!=NULL);
+
+       assert(1==hash_init(&st));
+
+       while(feof(fp)!=0) {
+               i = fread(buf,sizeof(uint8_t),16384,fp);
+               if(i>0) {
+                       assert(1==hash_update(&st,buf,i));
+               }
+       }
+
+       assert(0==fclose(fp));
+
+       assert(hash_final(&st,hash,crypto_hash_sha256_BYTES)==1);
+}
+
+static void torrent_file_piece_layers_basic_test() {
+       struct torrent *torrent;
+       FILE *fp;
+       unsigned char hash[crypto_hash_sha256_BYTES];
+       unsigned char expected[crypto_hash_sha256_BYTES] = {227,176,196,66,152,252,28,20,154,251,244,200,153,111,185,36,39,174,65,228,100,155,147,76,164,149,153,27,120,82,184,85};
+
+       fp = fopen(TEST_FILE_6,"w");
+       assert(fp!=NULL);
+
+       torrent_setup_example(&torrent);
+       assert(torrent_file_piece_layers(fp,torrent)==1);
+
+       assert(0==fclose(fp));
+
+       hash_torrent_file(hash,crypto_hash_sha256_BYTES);
+
+       assert(memcmp(hash,expected,crypto_hash_sha256_BYTES)==0);
+
+       torrent_free(torrent);
+
+       reset_env();
+}
+
 static void torrent_init_basic_test() {
        struct torrent *torrent;
 
@@ -130,13 +180,14 @@ static void torrent_init_basic_test() {
 static void torrent_magnet_basic_test() {
        struct torrent *torrent;
        char *p;
+       char expected[] = "magnet:?xt=urn:btmh:59b2020fe4275cac5c3b8ac32bdc79010c95cf0bac2fd91ced8dd071f8ef91ca&dn=" TEST_DIRECTORY;
 
        torrent_setup_example(&torrent);
        
        p = torrent_magnet(torrent);
        assert(p!=NULL);
 
-       assert(strcmp(p,"magnet:?xt=urn:btmh:d2cb0c8d48b492e0407e2b24ae6b9c2e542d9addf08d71eef8db7008944def9e&dn=" TEST_DIRECTORY)==0);
+       assert(strcmp(p,expected)==0);
 
        free(p);
        torrent_free(torrent);