#include<torrent.h>
-#define BUF_SIZE 1024
-
static int torrent_add_file(struct torrent*,struct file*);
+static int torrent_file_announce(FILE*,struct torrent*);
static char *torrent_file_path(unsigned char*,size_t);
+static int torrent_file_piece_layers(FILE*,struct torrent*);
+static int torrent_file_write_end(FILE*);
+static int torrent_file_write_info(FILE*,uint8_t*,size_t);
+static int torrent_file_write_piece_layers(FILE*,struct torrent*);
+static int torrent_file_write_start(FILE*);
int torrent_add(struct torrent *p, struct file *f) {
const char *path;
char *path;
ssize_t i;
- if((i = torrent_file_info(torrent_p,&info))<0) { return -1; }
+ info = NULL;
+ fp = NULL;
+ path = NULL;
- if(hash(info,i,infohash,crypto_hash_sha256_BYTES)<0) { return -1; }
+ if((i = torrent_file_info(torrent_p,&info))<0) { goto clean; }
- path = torrent_file_path(infohash);
- if(NULL==path) { return -1; }
+ if(hash(info,i,infohash,crypto_hash_sha256_BYTES)<0) { goto clean; }
+
+ path = torrent_file_path(infohash,crypto_hash_sha256_BYTES);
+ if(NULL==path) { goto clean; }
fp = fopen(path,"w");
- if(NULL==fp) {
- free(path);
- return -1;
- }
-
- if((i = bencode_dict_start(buf,BUF_SIZE))<0) { goto clean; }
+ if(NULL==fp) { goto clean; }
- if(torrent_file_announce(p)<0) { goto clean; }
+ if(torrent_file_write_start(fp)<0) { goto clean; }
+ if(torrent_file_announce(fp,torrent_p)<0) { goto clean; }
- if((i = bencode_string("info",4,buf,BUF_SIZE))<0) { goto clean; }
+ if(torrent_file_write_info(fp,info,i)<0) { goto clean; }
+ free(info);
+ info = NULL;
- if((i = bencode_string("piece layers",12,buf,BUF_SIZE))<0) { goto clean; }
- if(torrent_file_piece_layers(torrent_p)<0) { goto clean; }
+ if(torrent_file_write_piece_layers(fp,torrent_p)<0) { goto clean; }
+ if(torrent_file_write_end(fp)<0) { goto clean; }
- if((i = bencode_dict_end(buf,BUF_SIZE))<0) { goto clean; }
+ fclose(fp);
+ free(path);
return 1;
clean:
- fclose(fp);
+ if(info!=NULL) { free(info); }
+ if(fp!=NULL) { fclose(fp); }
remove(path);
- free(path);
+ if(path!=NULL) { free(path); }
return -1;
}
-static int torrent_file_announce(struct torrent *p) {
- if((i = bencode_string("announce",8,buf,BUF_SIZE))<0) { goto clean; }
- if((i = bencode_string("http://example.com/announce",28,buf,BUF_SIZE))<0) { goto clean; }
+static int torrent_file_announce(FILE *fp, struct torrent *p) {
+ uint8_t buf[28];
+ ssize_t i;
+
+ uint8_t announce_string[] = "announce";
+ if((i = bencode_string(announce_string,sizeof(announce_string),buf,28))<0) { return -1; }
+ if(i!=fwrite(buf,sizeof(uint8_t),i,fp)) { return -1; }
+
+ uint8_t announce_sample_string[] = "http://example.com/announce";
+ if((i = bencode_string(announce_sample_string,sizeof(announce_sample_string),buf,28))<0) { return -1; }
+ if(i!=fwrite(buf,sizeof(uint8_t),i,fp)) { return -1; }
+
return 1;
}
+#define INITIAL_TORRENT_INFO_SIZE 100
+
ssize_t torrent_file_info(struct torrent *torrent_p, uint8_t **buf) {
uint8_t *p;
ssize_t i, len;
if((i = bencode_dict_start(p,buf_len))<0) { goto clean; }
len += i;
- if((i = bencode_string("file tree",9,&(p[len]),buf_len-len))<0) { goto clean; }
+ uint8_t file_tree_string[] = "file tree";
+ if((i = bencode_string(file_tree_string,sizeof(file_tree_string),&(p[len]),buf_len-len))<0) { goto clean; }
len += i;
- if((i = tree_bencode(p->file_tree,&(p[len]),buf_len-len))<0) { goto clean; }
+ if((i = tree_bencode(torrent_p->tree,&(p[len]),buf_len-len))<0) { goto clean; }
len += i;
- if((i = bencode_string("meta version",12,&(p[len]),buf_len-len))<0) { goto clean; }
+ uint8_t meta_version_string[] = "meta version";
+ if((i = bencode_string(meta_version_string,sizeof(meta_version_string),&(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;
- if((i = bencode_string("name",4,&(p[len]),buf_len-len))<0) { goto clean; }
+ uint8_t name_string[] = "name";
+ if((i = bencode_string(name_string,sizeof(name_string),&(p[len]),buf_len-len))<0) { goto clean; }
len += i;
- if((i = bencode_string(p->name,strlen(p->name),&(p[len]),buf_len-len))<0) { goto clean; }
+ if((i = bencode_string((const uint8_t*)torrent_p->name,strlen(torrent_p->name),&(p[len]),buf_len-len))<0) { goto clean; }
len += i;
- if((i = bencode_string("piece length",12,&(p[len]),buf_len-len))<0) { goto clean; }
+ 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(torrent_p->piece_length,&(p[len]),buf_len-len))<0) { goto clean; }
+ if((i = bencode_int(global_options.piece_length,&(p[len]),buf_len-len))<0) { goto clean; }
len += i;
*buf = malloc(len);
return -1;
}
+#define TORRENT_FILE_EXTENSION ".torrent"
+
static char *torrent_file_path(unsigned char *infohash, size_t len) {
+ char *path, *p;
+ char hex[(crypto_hash_sha256_BYTES<<1)+1];
+
+ if(len!=crypto_hash_sha256_BYTES) { return NULL; }
+
// this always returns hex, unnecessary to return
sodium_bin2hex(hex,(crypto_hash_sha256_BYTES<<1)+1,infohash,crypto_hash_sha256_BYTES);
- return NULL;
+
+ p = concat(PREFIX,hex);
+ if(NULL==p) { return NULL; }
+
+ path = malloc(strlen(p)+strlen(".torrent")+1);
+ if(NULL==path) {
+ free(p);
+ return NULL;
+ }
+
+ if(sprintf("%s" TORRENT_FILE_EXTENSION,p)<0) {
+ free(p);
+ free(path);
+ return NULL;
+ }
+
+ free(p);
+
+ return path;
}
-static int torrent_file_piece_layers(struct torrent *p) {
+static int torrent_file_piece_layers(FILE *fp, struct torrent *p) {
return -1;
}
+static int torrent_file_write_end(FILE *fp) {
+ uint8_t c;
+ ssize_t i;
+
+ if((i = bencode_dict_end(&c,1))<0) { return -1; }
+ if(i!=fwrite(&c,sizeof(uint8_t),i,fp)) { return -1; }
+
+ return 1;
+}
+
+static int torrent_file_write_info(FILE *fp, uint8_t *info, size_t info_len) {
+ uint8_t info_string[] = "info";
+ uint8_t buf[6];
+ ssize_t i;
+
+ if((i = bencode_string(info_string,sizeof(info_string),buf,6))<0) { return -1; }
+ if(i!=fwrite(buf,sizeof(uint8_t),i,fp)) { return -1; }
+
+ if(info_len!=fwrite(info,sizeof(uint8_t),info_len,fp)) { return -1; }
+
+ return 1;
+}
+
+static int torrent_file_write_piece_layers(FILE *fp, struct torrent *p) {
+ uint8_t piece_layers_string[] = "piece layers";
+ uint8_t buf[15];
+ ssize_t i;
+
+ if((i = bencode_string(piece_layers_string,sizeof(piece_layers_string),buf,15))<0) { return -1; }
+ if(i!=fwrite(buf,sizeof(uint8_t),i,fp)) { return -1; }
+
+ if(torrent_file_piece_layers(fp,p)<0) { return -1; }
+
+ return 1;
+}
+
+static int torrent_file_write_start(FILE *fp) {
+ uint8_t c;
+ ssize_t i;
+
+ if((i = bencode_dict_start(&c,1))<0) { return -1; }
+ if(i!=fwrite(&c,sizeof(uint8_t),i,fp)) { return -1; }
+
+ return 1;
+}
+
+
void torrent_free(struct torrent *p) {
if(NULL==p) { return; }