void block_free(struct block*);
int block_init(struct block**);
size_t block_length(struct block*);
-int block_merkle_layer(struct block*);
+int block_merkle_layer(struct block*,struct block**);
int block_merkle_root(struct block*);
int block_pad(struct block*);
const static unsigned char zerod[crypto_hash_sha256_BYTES] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
-int block_merkle_layer(struct block *root) {
- struct block *p, *to_free;
+int block_merkle_layer(struct block *root, struct block **next_layer) {
+ struct block *p, *tail;
crypto_hash_sha256_state state;
-
+ int i;
+
if(NULL==root) { return -1; }
+ if(NULL==next_layer) { return -1; }
+
+ tail = root;
+ while(tail->next!=NULL) {
+ tail = tail->next;
+ }
p = root;
+ i = 0;
while(p!=NULL) {
if((NULL==p->next)&&(p==root)) { break; }
if(hash_init(&state)<0) { return -1; }
if(hash_update(&state,zerod,crypto_hash_sha256_BYTES)<0) { return -1; }
}
- if(hash_final(&state,p->hash,crypto_hash_sha256_BYTES)<0) { return -1; }
-
- to_free = p->next;
- if(p->next!=NULL) {
- p->next = p->next->next;
- } else {
- p->next = NULL;
- }
-
- if(to_free!=NULL) {
- to_free->next = NULL;
- block_free(to_free);
- }
-
+ if(block_init(&(tail->next))<0) { return -1; }
+ tail = tail->next;
+
+ if(hash_final(&state,tail->hash,crypto_hash_sha256_BYTES)<0) { return -1; }
+
+ // set index, marking as padding if both leaves are padding
+ tail->index = ((p->index<0)||(p->next->index<0))?-1:i;
+
+ if(NULL==(*next_layer)) { (*next_layer) = tail; }
+
p = p->next;
+ i++;
}
return 1;
if(NULL==root) { return -1; }
end = NULL;
- while(root->next!=NULL) {
- end = block_merkle_layer(root,end);
- if(NULL==end) { return -1; }
- }
+ do {
+ if(block_merkle_layer(root,&end)<0) { return -1; }
+ } while(end->index>0);
return 1;
}
#include<file.h>
-static int file_piece_layers(struct file *p, int piece_length);
+static int file_merkle_root(struct file*);
+static int file_piece_layers(struct file*,int);
static int advance(ssize_t,uint8_t**,size_t*);
static int advance(ssize_t i, uint8_t **buf, size_t *len) {
fclose(fp);
- if(block_length(p)>1) {
+ if(p->next!=NULL) { // i.e. more than 1 block
if(block_pad(p)<0) { goto clean; }
}
- if(block_merkle_root(p)<0) { goto clean; }
if(file_piece_layers(file_p,piece_length)<0) { return -1; }
+ if(file_merkle_root(file_p)<0) { goto clean; }
return 1;
clean:
return -1;
}
+static int file_merkle_root(struct file *file_p) {
+ return -1;
+}
+
static int file_piece_layers(struct file *file_p, int piece_length) {
- struct block *p, *last;
- size_t blocks;
+ struct block *p;
int ratio;
ratio = piece_length / BLOCK_SIZE;
- blocks = 0;
- p = file_p->piece_layers;
- last = p;
- while(p->next!=NULL) {
- p = p->next;
- blocks++;
- if(blocks%ratio==0) {
- last = p;
- }
- }
-
- for(int i=1;i<ratio;i<<=1) {
- if(block_pad(last)<0) { return -1; }
- }
-
+ p = file_p->blocks;
while(ratio>1) {
- if(block_merkle_layer(file_p->piece_layers)<0) { return -1; }
+ if(block_merkle_layer(p,&(file_p->piece_layers))<0) { return -1; }
+ p = file_p->piece_layers;
ratio>>=1;
}
ssize_t i;
uint8_t buf[PIECE_LAYER_BENCODED_LENGTH];
- if((i = bencode_string(file_p->root,crypto_hash_sha256_BYTES,buf,PIECE_LAYER_BENCODED_LENGTH))<0) { return -1; }
+ if((i = bencode_string(file_p->root->hash,crypto_hash_sha256_BYTES,buf,PIECE_LAYER_BENCODED_LENGTH))<0) { return -1; }
if(fwrite(buf,sizeof(uint8_t),i,fp)!=i) { return -1; }
blocks = block_length(file_p->piece_layers);
file_p = (struct file*)p->files.roots->map[i];
if(file_p!=NULL) {
if(file_p->size>p->piece_length) {
- hashes[index] = file_p->root;
+ hashes[index] = file_p->root->hash;
index++;
}
}