summaryrefslogtreecommitdiff
path: root/ot_http.c
diff options
context:
space:
mode:
authorDirk Engling <erdgeist@erdgeist.org>2026-10-26 22:32:52 +0100
committerDirk Engling <erdgeist@erdgeist.org>2026-10-26 22:32:52 +0100
commit1f9494979268b62ed4b4588fb7d9e790c0e12100 (patch)
treeed4f78369fe610b5c9188cb4159a23370d50a799 /ot_http.c
parent6d5485b97cd46f81512e9198ac7c59c7ba1d9247 (diff)
replace all calls to sprintf with a format helper that advances a cursor. Also convert the meta-formatter (i.e. results printer) to this scheme
Diffstat (limited to 'ot_http.c')
-rw-r--r--ot_http.c40
1 files changed, 29 insertions, 11 deletions
diff --git a/ot_http.c b/ot_http.c
index e1798dc..36819c7 100644
--- a/ot_http.c
+++ b/ot_http.c
@@ -24,6 +24,7 @@
24#include "ot_scan.h" 24#include "ot_scan.h"
25#include "ot_event.h" 25#include "ot_event.h"
26#include "ot_fdstate.h" 26#include "ot_fdstate.h"
27#include "ot_fmt.h"
27#include "ot_stats.h" 28#include "ot_stats.h"
28#include "ot_urlencoded.h" 29#include "ot_urlencoded.h"
29#include "trackerlogic.h" 30#include "trackerlogic.h"
@@ -257,6 +258,7 @@ static ssize_t http_handle_stats(const int64_t sock, struct ot_workstruct *ws, c
257 {"txtp", TASK_FULLSCRAPE_TPB_ASCII_PLUS}, {NULL, -3}}; 258 {"txtp", TASK_FULLSCRAPE_TPB_ASCII_PLUS}, {NULL, -3}};
258 259
259 struct http_data *cookie = fdstate_cookie(sock); 260 struct http_data *cookie = fdstate_cookie(sock);
261 char *reply;
260 int mode = TASK_STATS_PEERS, scanon = 1, format = 0; 262 int mode = TASK_STATS_PEERS, scanon = 1, format = 0;
261 263
262 /* A socket without one is a dead socket, which is what http_sendiovecdata 264 /* A socket without one is a dead socket, which is what http_sendiovecdata
@@ -333,7 +335,9 @@ static ssize_t http_handle_stats(const int64_t sock, struct ot_workstruct *ws, c
333 } 335 }
334 336
335 /* Simple stats can be answerred immediately */ 337 /* Simple stats can be answerred immediately */
336 return ws->reply_size = return_stats_for_tracker(ws->reply, mode, 0); 338 reply = ws->reply;
339 return_stats_for_tracker(&reply, ws->outbuf + G_OUTBUF_SIZE, mode, 0);
340 return ws->reply_size = reply - ws->reply;
337} 341}
338 342
339#ifdef WANT_MODEST_FULLSCRAPES 343#ifdef WANT_MODEST_FULLSCRAPES
@@ -417,9 +421,10 @@ static ssize_t http_handle_fullscrape(const int64_t sock, struct ot_workstruct *
417static ssize_t http_handle_scrape(const int64_t sock, struct ot_workstruct *ws, char *read_ptr) { 421static ssize_t http_handle_scrape(const int64_t sock, struct ot_workstruct *ws, char *read_ptr) {
418 static const ot_keywords keywords_scrape[] = {{"info_hash", 1}, {NULL, -3}}; 422 static const ot_keywords keywords_scrape[] = {{"info_hash", 1}, {NULL, -3}};
419 423
420 ot_hash *multiscrape_buf = (ot_hash *)ws->request; 424 ot_hash *multiscrape_buf = (ot_hash *)ws->request;
421 int scanon = 1; 425 char *reply = ws->reply;
422 size_t numwant = 0; 426 int scanon = 1;
427 size_t numwant = 0;
423 428
424 /* This is to hack around stupid clients that send "scrape ?info_hash" */ 429 /* This is to hack around stupid clients that send "scrape ?info_hash" */
425 if (read_ptr[-1] != '?') { 430 if (read_ptr[-1] != '?') {
@@ -457,7 +462,8 @@ static ssize_t http_handle_scrape(const int64_t sock, struct ot_workstruct *ws,
457 numwant = OT_MAXMULTISCRAPE_COUNT; 462 numwant = OT_MAXMULTISCRAPE_COUNT;
458 463
459 /* Enough for http header + whole scrape string */ 464 /* Enough for http header + whole scrape string */
460 ws->reply_size = return_tcp_scrape_for_torrent((const ot_hash *)multiscrape_buf, numwant, ws->reply); 465 return_tcp_scrape_for_torrent((const ot_hash *)multiscrape_buf, numwant, &reply, ws->outbuf + G_OUTBUF_SIZE);
466 ws->reply_size = reply - ws->reply;
461 stats_issue_event(EVENT_SCRAPE, FLAG_TCP, ws->reply_size); 467 stats_issue_event(EVENT_SCRAPE, FLAG_TCP, ws->reply_size);
462 return ws->reply_size; 468 return ws->reply_size;
463} 469}
@@ -493,6 +499,16 @@ static ot_keywords keywords_announce[] = {{"port", 1}, {"left", 2}, {"event",
493#endif 499#endif
494 {"peer_id", 9}, {NULL, -3}}; 500 {"peer_id", 9}, {NULL, -3}};
495static ot_keywords keywords_announce_event[] = {{"completed", 1}, {"stopped", 2}, {NULL, -3}}; 501static ot_keywords keywords_announce_event[] = {{"completed", 1}, {"stopped", 2}, {NULL, -3}};
502
503/* For the replies that are one fixed string and nothing else, where the only
504 thing the caller wants back is how long it turned out */
505static ssize_t reply_literal(struct ot_workstruct *ws, const char *text) {
506 char *reply = ws->reply;
507
508 fmt_bytes(&reply, ws->outbuf + G_OUTBUF_SIZE, text, strlen(text));
509 return reply - ws->reply;
510}
511
496static ssize_t http_handle_announce(const int64_t sock, struct ot_workstruct *ws, char *read_ptr) { 512static ssize_t http_handle_announce(const int64_t sock, struct ot_workstruct *ws, char *read_ptr) {
497 size_t numwant; 513 size_t numwant;
498 int64_t tmp; 514 int64_t tmp;
@@ -621,7 +637,7 @@ static ssize_t http_handle_announce(const int64_t sock, struct ot_workstruct
621 HTTPERROR_400_PARAM; 637 HTTPERROR_400_PARAM;
622 if (*tmp_buf == '-') { 638 if (*tmp_buf == '-') {
623 loglist_reset(); 639 loglist_reset();
624 return ws->reply_size = sprintf(ws->reply, "Successfully removed.\n"); 640 return ws->reply_size = reply_literal(ws, "Successfully removed.\n");
625 } 641 }
626 parsed = ip_parse(tmp_buf, net.address); 642 parsed = ip_parse(tmp_buf, net.address);
627 if (!parsed) 643 if (!parsed)
@@ -638,7 +654,7 @@ static ssize_t http_handle_announce(const int64_t sock, struct ot_workstruct
638 } 654 }
639 net.bits = bits; 655 net.bits = bits;
640 loglist_add_network(&net); 656 loglist_add_network(&net);
641 return ws->reply_size = sprintf(ws->reply, "Successfully added.\n"); 657 return ws->reply_size = reply_literal(ws, "Successfully added.\n");
642 //} 658 //}
643 } break; 659 } break;
644#endif 660#endif
@@ -661,7 +677,7 @@ static ssize_t http_handle_announce(const int64_t sock, struct ot_workstruct
661 677
662 /* Scanned whole query string */ 678 /* Scanned whole query string */
663 if (!ws->hash) 679 if (!ws->hash)
664 return ws->reply_size = sprintf(ws->reply, "d14:failure reason80:Your client forgot to send your torrent's info_hash. Please upgrade your client.e"); 680 return ws->reply_size = reply_literal(ws, "d14:failure reason80:Your client forgot to send your torrent's info_hash. Please upgrade your client.e");
665 681
666 if (OT_PEERFLAG(&ws->peer) & PEER_FLAG_STOPPED) 682 if (OT_PEERFLAG(&ws->peer) & PEER_FLAG_STOPPED)
667 ws->reply_size = remove_peer_from_torrent(FLAG_TCP, ws); 683 ws->reply_size = remove_peer_from_torrent(FLAG_TCP, ws);
@@ -772,9 +788,11 @@ ssize_t http_handle_request(const int64_t sock, struct ot_workstruct *ws) {
772 reply_off = SUCCESS_HTTP_SIZE_OFF - snprintf(ws->outbuf, 0, "%zd", ws->reply_size); 788 reply_off = SUCCESS_HTTP_SIZE_OFF - snprintf(ws->outbuf, 0, "%zd", ws->reply_size);
773 ws->reply = ws->outbuf + reply_off; 789 ws->reply = ws->outbuf + reply_off;
774 790
775 /* 2. Now we sprintf our header so that sprintf writes its terminating '\0' exactly one byte before content starts. Complete 791 /* 2. Now we write the header so that its terminating '\0' lands exactly one byte before the content starts. The bound is the
776 packet size is increased by size of header plus one byte '\n', we will copy over '\0' in next step */ 792 space step 1 reserved, so the '\0' falls where step 3 expects it. Complete packet size is increased by size of header plus
777 ws->reply_size += 1 + sprintf(ws->reply, "HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\nContent-Length: %zd\r\n\r", ws->reply_size); 793 one byte '\n', we will copy over '\0' in next step */
794 ws->reply_size += 1 + snprintf(ws->reply, (size_t)(SUCCESS_HTTP_HEADER_LENGTH - reply_off),
795 "HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\nContent-Length: %zd\r\n\r", ws->reply_size);
778 796
779 /* 3. Finally we join both blocks neatly */ 797 /* 3. Finally we join both blocks neatly */
780 ws->outbuf[SUCCESS_HTTP_HEADER_LENGTH - 1] = '\n'; 798 ws->outbuf[SUCCESS_HTTP_HEADER_LENGTH - 1] = '\n';