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);
#include<sodium.h>
+#include<bencode.h>
#include<block.h>
#include<fs.h>
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*);
#include<bencode.h>
-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; }
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;
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;
#include<file.h>
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; }
#include<tree.h>
+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;
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); }
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
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);
}
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();
setup_env();
file_init_basic_test();
+ file_bencode_basic_test();
file_hash_basic_test();
file_hash_large_file_test();
file_hash_large_piece_test();
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};
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();
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;
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;
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() {