From db3a0b9bb51ba59051173b0f81f1d088a5176d95 Mon Sep 17 00:00:00 2001 From: Dirk Engling Date: Tue, 27 Oct 2026 03:07:41 +0100 Subject: Sort info_hashes in a scrape so that the reply forms a valid bencoded dict --- ot_http.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) (limited to 'ot_http.c') diff --git a/ot_http.c b/ot_http.c index 14952b5..2216453 100644 --- a/ot_http.c +++ b/ot_http.c @@ -24,6 +24,7 @@ #include "ot_scan.h" #include "ot_event.h" #include "ot_fdstate.h" +#include "ot_vector.h" #include "ot_fmt.h" #include "ot_stats.h" #include "ot_urlencoded.h" @@ -233,7 +234,6 @@ static ssize_t http_handle_stats(const int64_t sock, struct ot_workstruct *ws, c {"scrp", TASK_STATS_SCRAPE}, {"udp4", TASK_STATS_UDP}, {"tcp4", TASK_STATS_TCP}, - {"busy", TASK_STATS_BUSY_NETWORKS}, {"torr", TASK_STATS_TORRENTS}, {"fscr", TASK_STATS_FULLSCRAPE}, {"s24s", TASK_STATS_SLASH24S}, @@ -418,13 +418,15 @@ static ssize_t http_handle_fullscrape(const int64_t sock, struct ot_workstruct * } #endif +static int compare_hash(const void *left, const void *right) { return memcmp(left, right, sizeof(ot_hash)); } + static ssize_t http_handle_scrape(const int64_t sock, struct ot_workstruct *ws, char *read_ptr) { static const ot_keywords keywords_scrape[] = {{"info_hash", 1}, {NULL, -3}}; ot_hash *multiscrape_buf = (ot_hash *)ws->request; char *reply = ws->reply; int scanon = 1; - size_t numwant = 0; + size_t i, unique, numwant = 0; /* This is to hack around stupid clients that send "scrape ?info_hash" */ if (read_ptr[-1] != '?') { @@ -461,6 +463,14 @@ static ssize_t http_handle_scrape(const int64_t sock, struct ot_workstruct *ws, if (numwant > OT_MAXMULTISCRAPE_COUNT) numwant = OT_MAXMULTISCRAPE_COUNT; + /* A bencoded dictionary has its keys in order and names each one once, so + the answer cannot just follow the order the client asked in */ + qsort(multiscrape_buf, numwant, sizeof(ot_hash), compare_hash); + for (i = unique = 1; i < numwant; ++i) + if (memcmp(multiscrape_buf[i], multiscrape_buf[unique - 1], sizeof(ot_hash))) + memcpy(multiscrape_buf[unique++], multiscrape_buf[i], sizeof(ot_hash)); + numwant = unique; + /* Enough for http header + whole scrape string */ return_tcp_scrape_for_torrent((const ot_hash *)multiscrape_buf, numwant, &reply, ws->outbuf + G_OUTBUF_SIZE); ws->reply_size = reply - ws->reply; -- cgit v1.3