struct mi_announce * mi_announce(const char *p) { int ti, ui; const char *alst, *ulst, *url; struct mi_announce *res; if ((res = calloc(1, sizeof(*res))) == NULL) return NULL; if ((alst = benc_dget_lst(p, "announce-list")) != NULL) { res->ntiers = benc_nelems(alst); if ((res->tiers = calloc(res->ntiers, sizeof(*res->tiers))) == NULL) goto error; ti = 0; ulst = benc_first(alst); while (ulst != NULL) { res->tiers[ti].nurls = benc_nelems(ulst); res->tiers[ti].urls = calloc(res->tiers[ti].nurls, sizeof(*res->tiers[ti].urls)); if (res->tiers[ti].urls == NULL) goto error; ui = 0; url = benc_first(ulst); while (url != NULL) { if ((res->tiers[ti].urls[ui] = benc_str(url, NULL, NULL)) == NULL) goto error; ui++; url = benc_next(url); } ti++; ulst = benc_next(ulst); } } else { res->ntiers = 1; if ((res->tiers = calloc(1, sizeof(*res->tiers))) == NULL) goto error; res->tiers[0].nurls = 1; if ((res->tiers[0].urls = calloc(1, sizeof(*res->tiers[0].urls))) == NULL) goto error; if ((res->tiers[0].urls[0] = benc_dget_str(p, "announce", NULL)) == NULL) goto error; } mi_shuffle_announce(res); return res; error: if (res != NULL) mi_free_announce(res); return NULL; }
struct mi_file * mi_files(const char *p) { struct mi_file *fi; const char *info = benc_dget_dct(p, "info"); const char *files = benc_dget_lst(info, "files"); if (files != NULL) { int i = 0; unsigned nfiles = benc_nelems(files); const char *fdct = benc_first(files); if ((fi = calloc(nfiles, sizeof(*fi))) == NULL) return NULL; for (fdct = benc_first(files); fdct != NULL; fdct = benc_next(fdct)) { fi[i].length = benc_dget_int(fdct, "length"); fi[i].path = mi_filepath(benc_dget_lst(fdct, "path")); if (fi[i].path == NULL) { mi_free_files(nfiles, fi); return NULL; } i++; } } else { if ((fi = calloc(1, sizeof(*fi))) == NULL) return NULL; fi[0].length = benc_dget_int(info, "length"); fi[0].path = benc_dget_str(info, "name", NULL); if (fi[0].path == NULL) { free(fi); return NULL; } } return fi; }
size_t mi_nfiles(const char *p) { const char *files = benc_dget_lst(benc_dget_dct(p, "info"), "files"); if (files != NULL) return benc_nelems(files); else return 1; }
static int cmd_dispatch(struct cli *cli, const char *buf) { size_t cmdlen; const char *cmd; const char *args; cmd = benc_mem(benc_first(buf), &cmdlen, &args); for (int i = 0; i < ARRAY_COUNT(cmd_table); i++) { if ((cmdlen == cmd_table[i].nlen && strncmp(cmd_table[i].name, cmd, cmdlen) == 0)) { return cmd_table[i].fun(cli, benc_nelems(buf) - 1, args); } } return ENOENT; }
static int cmd_tget(struct cli *cli, int argc, const char *args) { if (argc != 1 || !benc_isdct(args)) return IPC_COMMERR; size_t nkeys; const char *keys, *p; enum ipc_tval *opts; struct iobuf iob; if ((keys = benc_dget_lst(args, "keys")) == NULL) return IPC_COMMERR; nkeys = benc_nelems(keys); opts = btpd_calloc(nkeys, sizeof(*opts)); p = benc_first(keys); for (int i = 0; i < nkeys; i++) opts[i] = benc_int(p, &p); iob = iobuf_init(1 << 15); iobuf_swrite(&iob, "d4:codei0e6:resultl"); p = benc_dget_any(args, "from"); if (benc_isint(p)) { enum ipc_twc from = benc_int(p, NULL); struct htbl_iter it; struct tlib *tl; for (tl = tlib_iter_first(&it); tl != NULL; tl = tlib_iter_next(&it)) { if (!torrent_haunting(tl) && ( from == IPC_TWC_ALL || (!torrent_active(tl) && from == IPC_TWC_INACTIVE) || (torrent_active(tl) && from == IPC_TWC_ACTIVE))) { iobuf_swrite(&iob, "l"); for (int k = 0; k < nkeys; k++) write_ans(&iob, tl, opts[k]); iobuf_swrite(&iob, "e"); } } } else if (benc_islst(p)) { for (p = benc_first(p); p != NULL; p = benc_next(p)) { struct tlib *tl = NULL; if (benc_isint(p)) tl = tlib_by_num(benc_int(p, NULL)); else if (benc_isstr(p) && benc_strlen(p) == 20) tl = tlib_by_hash(benc_mem(p, NULL, NULL)); else { iobuf_free(&iob); free(opts); return IPC_COMMERR; } if (tl != NULL && !torrent_haunting(tl)) { iobuf_swrite(&iob, "l"); for (int i = 0; i < nkeys; i++) write_ans(&iob, tl, opts[i]); iobuf_swrite(&iob, "e"); } else iobuf_print(&iob, "i%de", IPC_ENOTENT); } } iobuf_swrite(&iob, "ee"); free(opts); return write_buffer(cli, &iob); }