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
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
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
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*);
#include<bencode.h>
-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; }
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; }
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);
}
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;
+}
#include<torrent.h>
-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);
#include<torrent.h>
-#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;
+}
#include<torrent.h>
-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;i<p->files.roots->size;i++) {
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;i<pieces;i++) {
- file_p = (struct file*)p->files.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);
}
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; }
$(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 = \