torrentd

simple torrent daemon
git clone git@git.2f30.org/torrentd.git
Log | Files | Refs | LICENSE

commit 1b95d93ca2bc0cd467e48f69c983cd421e53dc23
parent bd3979b9d7b029d898e9718d19fa855bf191c5c4
Author: sin <sin@2f30.org>
Date:   Fri, 18 Dec 2015 15:04:29 +0000

Add {load,unload}torrent()

Diffstat:
Msbtd.h | 16++++++++++++++++
Mtorrent.c | 81+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 97 insertions(+), 0 deletions(-)

diff --git a/sbtd.h b/sbtd.h @@ -25,6 +25,18 @@ struct ben { struct ben *next; }; +struct torrent { + char *buf; + size_t buflen; + struct ben *ben; + struct ben *info; + char *announce; + uint8_t infohash[20]; + long long length; + long long piecelen; + long long npieces; +}; + /* ben.c */ char *bdecode(char *, char *, struct ben **); void bencode(char **, size_t *, struct ben *); @@ -35,6 +47,10 @@ struct ben *dlookstr(struct ben *, char *); void bfree(struct ben *); void bprint(struct ben *, int); +/* torrent.c */ +struct torrent *loadtorrent(char *); +void unloadtorrent(struct torrent *); + /* util.c */ void *emalloc(size_t); void *ecalloc(size_t, size_t); diff --git a/torrent.c b/torrent.c @@ -13,3 +13,84 @@ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include <err.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> + +#include "sbtd.h" +#include "sha1.h" + +static void +calcinfohash(struct torrent *t) +{ + char *buf; + size_t n; + + bencode(&buf, &n, t->info); + sha1sum((unsigned char *)buf, n, t->infohash); + free(buf); +} + +struct torrent * +loadtorrent(char *f) +{ + struct torrent *t; + + t = emalloc(sizeof(*t)); + if (readfile(f, &t->buf, &t->buflen) < 0) { + warnx("failed to read %s", f); + goto err0; + } + if (!bdecode(t->buf, t->buf + t->buflen, &t->ben)) { + warnx("failed to decode %s", f); + goto err1; + } + + t->info = dlookstr(t->ben, "info"); + if (!t->info) { + warnx("no info dictionary in %s", f); + goto err2; + } + + if (!dlookstr(t->ben, "announce")) { + warnx("no announce field in %s", f); + goto err2; + } + t->announce = bstr2str(dlookstr(t->ben, "announce")); + + if (!dlookstr(t->info, "length")) { + warnx("no length field in %s", f); + goto err2; + } + t->length = dlookstr(t->info, "length")->i; + + if (!dlookstr(t->info, "piece length")) { + warnx("no piece length field in %s", f); + goto err2; + } + t->piecelen = dlookstr(t->info, "piece length")->i; + + t->npieces = (t->length + t->piecelen - 1) / t->piecelen; + + calcinfohash(t); + return t; +err2: + bfree(t->ben); +err1: + free(t->buf); +err0: + free(t); + return NULL; +} + +void +unloadtorrent(struct torrent *t) +{ + if (!t) + return; + bfree(t->ben); + free(t->buf); + free(t); +}