static void cli_read_cb(int sd, short type, void *arg) { struct cli *cli = arg; uint32_t cmdlen; uint8_t *msg = NULL; if (read_fully(sd, &cmdlen, sizeof(cmdlen)) != 0) goto error; msg = btpd_malloc(cmdlen); if (read_fully(sd, msg, cmdlen) != 0) goto error; if (!(benc_validate(msg, cmdlen) == 0 && benc_islst(msg) && benc_first(msg) != NULL && benc_isstr(benc_first(msg)))) goto error; if (cmd_dispatch(cli, msg) != 0) goto error; free(msg); return; error: btpd_ev_del(&cli->read); close(cli->sd); free(cli); if (msg != NULL) free(msg); }
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; }
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; }