uint8_t piece_length_string[] = "piece length";
if((i = bencode_string(piece_length_string,sizeof(piece_length_string),&(p[len]),buf_len-len))<0) { goto clean; }
len += i;
- if((i = bencode_int(global_options.piece_length,&(p[len]),buf_len-len))<0) { goto clean; }
+ if((i = bencode_int(torrent_p->piece_length,&(p[len]),buf_len-len))<0) { goto clean; }
len += i;
*buf = malloc(len);
return -1;
}
+#define TORRENT_FILE_DIRECTORY "/torrents"
#define TORRENT_FILE_EXTENSION ".torrent"
static char *torrent_file_path(unsigned char *infohash, size_t len) {
// this always returns hex, unnecessary to return
sodium_bin2hex(hex,(crypto_hash_sha256_BYTES<<1)+1,infohash,crypto_hash_sha256_BYTES);
- p = concat(PREFIX,hex);
+ p = concat(PREFIX TORRENT_FILE_DIRECTORY,hex);
if(NULL==p) { return NULL; }
path = malloc(strlen(p)+strlen(".torrent")+1);
#define TORRENT_FILES_HASHMAP_INITIAL_SIZE 8
-int torrent_init(struct torrent **torrent_p, const char *root, const char *name) {
+int torrent_init(struct torrent **torrent_p, const char *root, const char *name, unsigned long long piece_length) {
if(NULL==torrent_p) { return -1; }
if(NULL==root) { return -1; }
if(NULL==name) { return -1; }
+ if((piece_length<16384)||(!(piece_length&&!(piece_length&(piece_length-1))))) { return -1; }
+
*(torrent_p) = malloc(sizeof(struct torrent));
if(NULL==(*torrent_p)) {
perror("malloc");
(*torrent_p)->name = strdup(name);
if(NULL==(*torrent_p)->name) { goto clean; }
+ (*torrent_p)->piece_length = piece_length;
+
if(tree_init(&((*torrent_p)->tree))<0) { goto clean; }
if(hashmap_init(&((*torrent_p)->files),TORRENT_FILES_HASHMAP_INITIAL_SIZE)<0) { goto clean; }
assert(file_init(&file3,TEST_FILE_3)==1);
assert(file_init(&file4,TEST_FILE_4)==1);
- assert(torrent_init(&torrent,TEST_DIRECTORY,TEST_DIRECTORY)==1);
+ assert(torrent_init(&torrent,TEST_DIRECTORY,TEST_DIRECTORY,16384)==1);
assert(torrent_add(torrent,file1)==1);
assert(torrent_add(torrent,file2)==1);
assert(torrent_add(torrent,file3)==1);
assert(torrent_add(torrent,file4)==1);
- assert(NULL==torrent->tree->directories);
- assert(torrent->tree->files->file==file3);
- assert(torrent->tree->files->next->file==file4);
- assert(torrent->tree->files->next->next->file==file1);
- assert(torrent->tree->files->next->next->next->file==file2);
+ assert(torrent->tree->entries->file==file3);
+ assert(torrent->tree->entries->next->file==file4);
+ assert(torrent->tree->entries->next->next->file==file1);
+ assert(torrent->tree->entries->next->next->next->file==file2);
torrent_free(torrent);
static void torrent_init_basic_test() {
struct torrent *torrent;
- assert(torrent_init(&torrent,NULL,NULL)<0);
- assert(torrent_init(&torrent,"src",NULL)<0);
+ assert(torrent_init(&torrent,NULL,NULL,0)<0);
+ assert(torrent_init(&torrent,"src",NULL,0)<0);
+ assert(torrent_init(&torrent,"src","src",1000)<0);
- assert(torrent_init(&torrent,"src","src")==1);
+ assert(torrent_init(&torrent,"src","src",16384)==1);
torrent_free(torrent);
}
int main();
static char *create_random_path();
-static int tree_deep_equals(struct tree *a, struct tree *b);
+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();
}
static void tree_add_basic_test() {
- struct tree *tree, *root, *test, *test2, *hello, *nope, *helloo;
- struct tree_entry *entry1, *entry2, *entry3, *entry4;
+ struct tree *tree;
+ struct tree_entry *p;
struct file *file1, *file2, *file3, *file4;
- assert(1==tree_init(&tree,NULL));
-
- assert(1==tree_init(&root,NULL));
- assert(1==tree_init(&test,"test"));
- assert(1==tree_init(&test2,"test2"));
- assert(1==tree_init(&hello,"hello"));
- assert(1==tree_init(&nope,"nope"));
- assert(1==tree_init(&helloo,"helloo"));
+ assert(1==tree_init(&tree));
assert(1==file_init(&file1,"test/file1"));
assert(1==file_init(&file2,"test/hello/file2"));
assert(1==file_init(&file3,"test2/nope/helloo/file3"));
assert(1==file_init(&file4,"test/file4"));
- assert(1==tree_entry_init(&entry1,file1));
- assert(1==tree_entry_init(&entry2,file2));
- assert(1==tree_entry_init(&entry3,file3));
- assert(1==tree_entry_init(&entry4,file4));
-
/*
* Tree:
* test(d)
* file3(f)
*/
- root->directories = test;
- test->next = test2;
- test->files = entry1;
- entry1->next = entry4;
- test->directories = hello;
- hello->files = entry2;
- test2->directories = nope;
- nope->directories = helloo;
- helloo->files = entry3;
-
assert(-1==tree_add(NULL,NULL,NULL));
assert(-1==tree_add(tree,NULL,NULL));
assert(-1==tree_add(tree,"test path",NULL));
assert(1==tree_add(tree,file3->path,file3));
assert(1==tree_add(tree,file4->path,file4));
- assert(NULL==tree->name);
- assert(NULL==tree->files);
-
- assert(tree_deep_equals(tree,root)==1);
- assert(tree_deep_equals(tree->directories,test)==1);
- assert(tree_deep_equals(tree->directories->next,test2)==1);
- assert(tree_deep_equals(tree->directories->directories,hello)==1);
- assert(tree_deep_equals(tree->directories->next->directories,nope)==1);
- assert(tree_deep_equals(tree->directories->next->directories->directories,helloo)==1);
+ // test/
+ p = tree->entries;
+ assert(strcmp(p->name,"test")==0);
+ assert(p->children!=NULL);
+ assert(p->file==NULL);
+ assert(p->next!=NULL);
+
+ // test/file1
+ p = tree->entries->children->entries;
+ assert(strcmp(p->name,"file1")==0);
+ assert(p->children==NULL);
+ assert(p->file==file1);
+ assert(p->next!=NULL);
+
+ // test/file4
+ p = tree->entries->children->entries->next;
+ assert(strcmp(p->name,"file4")==0);
+ assert(p->children==NULL);
+ assert(p->file==file4);
+ assert(p->next!=NULL);
+
+ // test/hello/
+ p = tree->entries->children->entries->next->next;
+ assert(strcmp(p->name,"hello")==0);
+ assert(p->children!=NULL);
+ assert(p->file==NULL);
+ assert(p->next==NULL);
+
+ // test/hello/file2
+ p = tree->entries->children->entries->next->next->children->entries;
+ assert(strcmp(p->name,"file2")==0);
+ assert(p->children==NULL);
+ assert(p->file==file2);
+ assert(p->next==NULL);
+
+ // test2/
+ p = tree->entries->next;
+ assert(strcmp(p->name,"test2")==0);
+ assert(p->children!=NULL);
+ assert(p->file==NULL);
+ assert(p->next==NULL);
+
+ // test2/nope/
+ p = tree->entries->next->children->entries;
+ assert(strcmp(p->name,"nope")==0);
+ assert(p->children!=NULL);
+ assert(p->file==NULL);
+ assert(p->next==NULL);
+
+ // test2/nope/helloo/
+ p = tree->entries->next->children->entries->children->entries;
+ assert(strcmp(p->name,"helloo")==0);
+ assert(p->children!=NULL);
+ assert(p->file==NULL);
+ assert(p->next==NULL);
+
+ // test2/nope/helloo/file3
+ p = tree->entries->next->children->entries->children->entries->children->entries;
+ assert(strcmp(p->name,"file3")==0);
+ assert(p->children==NULL);
+ assert(p->file==file3);
+ assert(p->next==NULL);
tree_free(tree);
-
- // remove pointers to already free'd entries
- entry1->file = NULL;
- entry2->file = NULL;
- entry3->file = NULL;
- entry4->file = NULL;
-
- tree_free(root);
}
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; }
- 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; }
- }
{
struct tree_entry *p1, *p2;
- p1 = a->files;
- p2 = b->files;
+ p1 = a->entries;
+ p2 = b->entries;
while(p1!=NULL) {
if(p2==NULL) { return -1; }
- if(strcmp(p1->file->name,p2->file->name)!=0) { return -1; }
- if(strcmp(p1->file->path,p2->file->path)!=0) { return -1; }
+ if(tree_entry_equals(p1,p2)<0) { return -1; }
p1 = p1->next;
p2 = p2->next;
}
}
- if(tree_deep_equals(a->directories,b->directories)<0) { return -1; }
- if(tree_deep_equals(a->next,b->next)<0) { return -1; }
+ 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;
}
struct tree *tree;
struct file *file;
- assert(1==tree_init(&tree,NULL));
+ assert(1==tree_init(&tree));
for(int i=0;i<100;i++) {
char *path = create_random_path();
char fileA_path[] = "dir1/dir2/fileA.txt";
uint8_t expected[] = "d4:dir1d4:dir2d9:fileA.txtd0:d5:lengthi102411:pieces root32:00000000000000000000000000000000eeeee";
- assert(1==tree_init(&root,NULL));
+ assert(1==tree_init(&root));
assert(1==file_init(&file,fileA_path));
memset(file->root,48,crypto_hash_sha256_BYTES);
static void tree_init_basic_test() {
struct tree *p;
- char str[] = "this is a test string";
-
- assert(-1==tree_init(NULL,NULL));
- assert(1==tree_init(&p,NULL));
-
- assert(NULL==p->name);
- assert(NULL==p->files);
- assert(NULL==p->directories);
- assert(NULL==p->next);
+ assert(-1==tree_init(NULL));
+ assert(1==tree_init(&p));
- tree_free(p);
-
- assert(1==tree_init(&p,str));
+ assert(NULL==p->entries);
+ assert(-1==p->watch_fd);
- assert(strcmp(p->name,str)==0);
- assert(NULL==p->files);
- assert(NULL==p->directories);
- assert(NULL==p->next);
-
tree_free(p);
}