예제 #1
0
파일: http_tr_if.c 프로젝트: Koushien/btpd
static void
parse_reply(struct torrent *tp, struct tr_response *res, const char *content,
            size_t size)
{
    const char *buf;
    size_t len;
    const char *peers;
    const char *v6key[] = {"peers6", "peers_ipv6"};

    if (benc_validate(content, size) != 0)
        goto bad_data;

    if ((buf = benc_dget_any(content, "failure reason")) != NULL) {
        if (!benc_isstr(buf))
            goto bad_data;
        res->type = TR_RES_FAIL;
        res->mi_failure = buf;
        return;
    }

    buf = benc_dget_any(content, "interval");
    if (buf != NULL && benc_isint(buf))
        res->interval = benc_int(buf, NULL);

    if ((peers = benc_dget_any(content, "peers")) == NULL)
        goto after_peers;

    if (benc_islst(peers)) {
        for (peers = benc_first(peers);
                peers != NULL && net_npeers < net_max_peers;
                peers = benc_next(peers))
            maybe_connect_to(tp, peers);
    } else if (benc_isstr(peers)) {
        if (net_ipv4) {
            peers = benc_dget_mem(content, "peers", &len);
            for (size_t i = 0; i < len && net_npeers < net_max_peers; i += 6)
                peer_create_out_compact(tp->net, AF_INET, peers + i);
        }
    } else
        goto bad_data;

after_peers:
    if (!net_ipv6)
        goto after_peers6;
    for (int k = 0; k < 2; k++) {
        peers = benc_dget_any(content, v6key[k]);
        if (peers != NULL && benc_isstr(peers)) {
            peers = benc_dget_mem(content, v6key[k], &len);
            for (size_t i = 0; i < len && net_npeers < net_max_peers; i += 18)
                peer_create_out_compact(tp->net, AF_INET6, peers + i);
        }
    }
after_peers6:
    res->type = TR_RES_OK;
    return;

bad_data:
    res->type = TR_RES_BAD;
}
예제 #2
0
파일: metainfo.c 프로젝트: AchillesA/btpd
int
mi_test(const char *p, size_t size)
{
    const char *info;
    const char *alst;
    const char *pieces;
    const char *files;
    const char *fdct;
    const char *name;
    size_t slen, npieces;
    off_t length = 0, piece_length;

    if (benc_validate(p, size) != 0 || !benc_isdct(p))
        return 0;

    if ((alst = benc_dget_any(p, "announce-list")) != NULL) {
        if (!benc_islst(alst))
            return 0;
        if (!mi_test_announce_list(alst))
            return 0;
    } else if (benc_dget_mem(p, "announce", NULL) == NULL)
        return 0;

    if ((info = benc_dget_dct(p, "info")) == NULL)
        return 0;
    if ((name = benc_dget_mem(info, "name", &slen)) != NULL)
        if (!mi_test_path(name, slen))
            return 0;
    if ((piece_length = benc_dget_int(info, "piece length")) <= 0)
        return 0;
    if ((pieces = benc_dget_mem(info, "pieces", &slen)) == NULL ||
            slen % 20 != 0)
        return 0;
    npieces = slen / 20;
    if ((length = benc_dget_int(info, "length")) != 0) {
        if (length < 0 || benc_dget_any(info, "files") != NULL)
            return 0;
    } else {
        if ((files = benc_dget_lst(info, "files")) == NULL)
            return 0;
        if (!mi_test_files(files))
            return 0;
        fdct = benc_first(files);
        while (fdct != NULL) {
            length += benc_dget_int(fdct, "length");
            fdct = benc_next(fdct);
        }
    }
    if (length < (npieces - 1) * piece_length ||
            length > npieces * piece_length)
        return 0;
    return 1;
}
예제 #3
0
파일: metainfo.c 프로젝트: AchillesA/btpd
size_t
mi_npieces(const char *p)
{
    size_t plen;
    benc_dget_mem(benc_dget_dct(p, "info"), "pieces", &plen);
    return plen / 20;
}
예제 #4
0
파일: http_tr_if.c 프로젝트: Koushien/btpd
static void
maybe_connect_to(struct torrent *tp, const char *pinfo)
{
    const char *pid;
    char *ip;
    int port;
    size_t len;

    if ((pid = benc_dget_mem(pinfo, "peer id", &len)) == NULL || len != 20)
        return;

    if (bcmp(btpd_get_peer_id(), pid, 20) == 0)
        return;

    if (net_torrent_has_peer(tp->net, pid))
        return;

    if ((ip = benc_dget_str(pinfo, "ip", NULL)) == NULL)
        return;

    port = benc_dget_int(pinfo, "port");
    peer_create_out(tp->net, pid, ip, port);

    if (ip != NULL)
        free(ip);
}
예제 #5
0
파일: cli_if.c 프로젝트: Koushien/btpd
static int
cmd_add(struct cli *cli, int argc, const char *args)
{
    if (argc != 1 || !benc_isdct(args))
        return IPC_COMMERR;

    struct tlib *tl;
    size_t mi_size = 0, csize = 0;
    const char *mi, *cp;
    char content[PATH_MAX];
    uint8_t hash[20];

    if ((mi = benc_dget_mem(args, "torrent", &mi_size)) == NULL)
        return IPC_COMMERR;

    if (!mi_test(mi, mi_size))
        return write_code_buffer(cli, IPC_EBADT);

    if ((cp = benc_dget_mem(args, "content", &csize)) == NULL ||
            csize >= PATH_MAX || csize == 0)
        return write_code_buffer(cli, IPC_EBADCDIR);

    if (cp[0] != '/')
        return write_code_buffer(cli, IPC_EBADCDIR);
    bcopy(cp, content, csize);
    content[csize] = '\0';

    tl = tlib_by_hash(mi_info_hash(mi, hash));
    if (tl != NULL && !torrent_haunting(tl))
        return write_code_buffer(cli, IPC_ETENTEXIST);
    if (tl != NULL) {
        tl = tlib_readd(tl, hash, mi, mi_size, content,
            benc_dget_str(args, "name", NULL),
            benc_dget_str(args, "label", NULL));
    } else {
        tl = tlib_add(hash, mi, mi_size, content,
            benc_dget_str(args, "name", NULL),
            benc_dget_str(args, "label", NULL));
    }
    return write_add_buffer(cli, tl->num);
}
예제 #6
0
파일: add.c 프로젝트: AchillesA/btpd
void
cmd_add(int argc, char **argv)
{
    int ch, topdir = 0, start = 1, nfile, nloaded = 0;
    size_t dirlen = 0, labellen = 0;
    char *dir = NULL, *name = NULL, *glabel = NULL, *label;

    while ((ch = getopt_long(argc, argv, "NTd:l:n:", add_opts, NULL)) != -1) {
        switch (ch) {
        case 'N':
            start = 0;
            break;
        case 'T':
            topdir = 1;
            break;
        case 'd':
            dir = optarg;
            if ((dirlen = strlen(dir)) == 0)
                diemsg("bad option value for -d.\n");
            break;
        case 'l':
            glabel = optarg;
            if ((labellen = strlen(dir)) == 0)
                diemsg("bad option value for -l.\n");
            break;
        case 'n':
            name = optarg;
            break;
        default:
            usage_add();
        }
    }
    argc -= optind;
    argv += optind;

    if (argc < 1 || dir == NULL)
        usage_add();

    btpd_connect();
    char *mi;
    size_t mi_size;
    enum ipc_err code;
    char dpath[PATH_MAX];
    struct iobuf iob;

    for (nfile = 0; nfile < argc; nfile++) {
       if ((mi = mi_load(argv[nfile], &mi_size)) == NULL) {
           fprintf(stderr, "error loading '%s' (%s).\n", argv[nfile], strerror(errno));
           continue;
       }
       iob = iobuf_init(PATH_MAX);
       iobuf_write(&iob, dir, dirlen);
       if (topdir && !mi_simple(mi)) {
           size_t tdlen;
           const char *td =
               benc_dget_mem(benc_dget_dct(mi, "info"), "name", &tdlen);
           iobuf_swrite(&iob, "/");
           iobuf_write(&iob, td, tdlen);
       }
       iobuf_swrite(&iob, "\0");
       if ((errno = make_abs_path(iob.buf, dpath)) != 0) {
           fprintf(stderr, "make_abs_path '%s' failed (%s).\n", dpath, strerror(errno));
           iobuf_free(&iob);
           continue;
       }
       if(NULL == glabel)
          label = benc_dget_str(mi, "announce", NULL);
       else
          label = glabel;
       code = btpd_add(ipc, mi, mi_size, dpath, name, label);
       if ((code == IPC_OK) && start) {
           struct ipc_torrent tspec;
           tspec.by_hash = 1;
           mi_info_hash(mi, tspec.u.hash);
           code = btpd_start(ipc, &tspec);
       }
       if (code != IPC_OK) {
           fprintf(stderr, "command failed for '%s' (%s).\n", argv[nfile], ipc_strerror(code));
       } else {
           nloaded++;
       }
       iobuf_free(&iob);
    }

    if (nloaded != nfile) {
       diemsg("error loaded %d of %d files.\n", nloaded, nfile);
    }
}