libeech

BitTorrent library
git clone git://z3bra.org/libeech.git
Log | Files | Refs | README | LICENSE

commit 2eea005257be3fa89a34c62e77a51956e2605867
parent 97095244b34d1cc1b0678b9dcd84908ae9388cb6
Author: z3bra <contactatz3bradotorg>
Date:   Sun Feb 11 03:28:09 +0100

Read pieces from file and verify their checksum

Diffstat:
libeech.c | 78++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----
libeech.h | 9++++++++-
2 files changed, 82 insertions(+), 5 deletions(-)
diff --git a/libeech.c b/libeech.c @@ -29,6 +29,10 @@ static long torrentsize(struct torrent *); static long torrentfiles(struct torrent *); static int chktorrent(struct be *); +/* helpers to deal with pieces/blocks */ +static long readpiece(struct torrent *, struct data *, long); +static int chkpiece(struct torrent *, struct data *, long); + /* manage a list of peers */ static struct peer * addpeer(struct peer *, char *, int); static struct peer * getpeer(struct peer *, char *, int); @@ -173,6 +177,63 @@ chktorrent(struct be *b) return 0; } +static long +readpiece(struct torrent *t, struct data *p, long n) +{ + int i; + size_t off, fp, sz; + FILE *fh = NULL; + + /* last piece might be truncated, so recalculate it*/ + p->sz = (n == t->npiece - 1) ? t->sz % t->psz : t->psz; + + p->data = malloc(p->sz); + if (!p->data) + return -1; + + /* Calculate file offset for this piece */ + off = t->psz * n; + + /* find file whose piece's offset belongs to */ + fp = i = 0; + while (fp + t->files[i].sz < off && i < t->nfile) + fp += t->files[i++].sz; + + sz = 0; + while (sz < p->sz) { + /* Keep up reading data from next files if needed*/ + if (off + sz >= t->files[i].sz) { + i++; + if (i >= t->nfile) + return -1; + fp += t->files[i].sz; + } + + fh = fopen(t->files[i].path, "r"); + if (!fh) { + free(p->data); + return -1; + } + + if (off + sz - fp) + fseek(fh, off + sz - fp, SEEK_SET); + + sz += fread(p->data, 1, p->sz - sz, fh); + fclose(fh); + } + + return p->sz; +} + +static int +chkpiece(struct torrent *t, struct data *p, long n) +{ + char hash[20]; + sha1(p->data, p->sz, hash); + + return memcmp(t->ph + n*20, hash, 20); +} + static struct peer * addpeer(struct peer *pl, char *host, int port) { @@ -362,6 +423,7 @@ netloop(struct torrent *t, int timeout) int glch_loadtorrent(struct torrent *t, char *b, size_t s) { + long i; struct be v; if (beinit(&t->be, b, s) < 0) @@ -391,11 +453,19 @@ glch_loadtorrent(struct torrent *t, char *b, size_t s) /* pieces related values */ t->psz = bekint(&t->info, "piece length", 12); t->npiece = t->sz / t->psz + !!(t->sz % t->psz); - t->pieces = malloc(t->npiece * 20); - bekstr(&t->be, "pieces", 6, &v); - memcpy(t->pieces, v.off, v.end - v.off); + t->ph = malloc(t->npiece * 20); + bekstr(&t->info, "pieces", 6, &v); + memcpy(t->ph, v.off, v.end - v.off); + t->pieces = malloc(t->npiece * sizeof(*t->pieces)); + + for (i = 0; i < t->npiece; i++) { + readpiece(t, &t->pieces[i], i); + if (!chkpiece(t, &t->pieces[i], i)) { + /* things to do when chksum is valid */ + } + } - return 0; + return 1; } int diff --git a/libeech.h b/libeech.h @@ -19,6 +19,12 @@ enum { ISINTERESTED = 1 << 8, }; +struct data { + long n; + size_t sz; + char *data; +}; + struct peer { int fd; int state; @@ -38,11 +44,12 @@ struct torrent { char id[21]; char ih[20]; char tr[PATH_MAX]; - char *pieces; + char *ph; struct be be; struct be info; struct peer *peers; struct file *files; + struct data *pieces; long npiece; long nfile; long psz;