summaryrefslogtreecommitdiff
path: root/ot_http.c
diff options
context:
space:
mode:
Diffstat (limited to 'ot_http.c')
-rw-r--r--ot_http.c177
1 files changed, 99 insertions, 78 deletions
diff --git a/ot_http.c b/ot_http.c
index 4675efb..36819c7 100644
--- a/ot_http.c
+++ b/ot_http.c
@@ -14,9 +14,6 @@
14#include <sys/types.h> 14#include <sys/types.h>
15#include <unistd.h> 15#include <unistd.h>
16 16
17/* Libowfat */
18#include "io.h"
19
20/* Opentracker */ 17/* Opentracker */
21#include "ot_accesslist.h" 18#include "ot_accesslist.h"
22#include "ot_fullscrape.h" 19#include "ot_fullscrape.h"
@@ -25,8 +22,11 @@
25#include "ot_ip.h" 22#include "ot_ip.h"
26#include "ot_mutex.h" 23#include "ot_mutex.h"
27#include "ot_scan.h" 24#include "ot_scan.h"
25#include "ot_event.h"
26#include "ot_fdstate.h"
27#include "ot_fmt.h"
28#include "ot_stats.h" 28#include "ot_stats.h"
29#include "scan_urlencoded_query.h" 29#include "ot_urlencoded.h"
30#include "trackerlogic.h" 30#include "trackerlogic.h"
31 31
32#define OT_MAXMULTISCRAPE_COUNT 64 32#define OT_MAXMULTISCRAPE_COUNT 64
@@ -38,11 +38,11 @@ ssize_t g_stats_path_len;
38enum { SUCCESS_HTTP_HEADER_LENGTH = 80, SUCCESS_HTTP_SIZE_OFF = 17 }; 38enum { SUCCESS_HTTP_HEADER_LENGTH = 80, SUCCESS_HTTP_SIZE_OFF = 17 };
39 39
40static void http_senddata(const int64_t sock, struct ot_workstruct *ws) { 40static void http_senddata(const int64_t sock, struct ot_workstruct *ws) {
41 struct http_data *cookie = io_getcookie(sock); 41 struct http_data *cookie = fdstate_cookie(sock);
42 ssize_t written_size; 42 ssize_t written_size;
43 43
44 if (!cookie) { 44 if (!cookie) {
45 io_close(sock); 45 event_del((int)sock), close((int)sock);
46 return; 46 return;
47 } 47 }
48 48
@@ -66,18 +66,17 @@ static void http_senddata(const int64_t sock, struct ot_workstruct *ws) {
66 if ((written_size < 0) || ((written_size == ws->reply_size) && !ws->keep_alive)) { 66 if ((written_size < 0) || ((written_size == ws->reply_size) && !ws->keep_alive)) {
67 buf_reset(&cookie->request); 67 buf_reset(&cookie->request);
68 free(cookie); 68 free(cookie);
69 io_close(sock); 69 event_del((int)sock), close((int)sock);
70 return; 70 return;
71 } 71 }
72 72
73 if (written_size < ws->reply_size) { 73 if (written_size < ws->reply_size) {
74 char *outbuf; 74 char *outbuf;
75 tai6464 t;
76 75
77 if (!(outbuf = malloc(ws->reply_size - written_size))) { 76 if (!(outbuf = malloc(ws->reply_size - written_size))) {
78 buf_reset(&cookie->request); 77 buf_reset(&cookie->request);
79 free(cookie); 78 free(cookie);
80 io_close(sock); 79 event_del((int)sock), close((int)sock);
81 return; 80 return;
82 } 81 }
83 82
@@ -88,7 +87,7 @@ static void http_senddata(const int64_t sock, struct ot_workstruct *ws) {
88 free(outbuf); 87 free(outbuf);
89 buf_reset(&cookie->request); 88 buf_reset(&cookie->request);
90 free(cookie); 89 free(cookie);
91 io_close(sock); 90 event_del((int)sock), close((int)sock);
92 return; 91 return;
93 } 92 }
94 } 93 }
@@ -97,11 +96,10 @@ static void http_senddata(const int64_t sock, struct ot_workstruct *ws) {
97 96
98 /* writeable short data sockets just have a tcp timeout */ 97 /* writeable short data sockets just have a tcp timeout */
99 if (!ws->keep_alive) { 98 if (!ws->keep_alive) {
100 taia_uint(&t, 0); 99 fdstate_set_expiry(sock, 0);
101 io_timeout(sock, t); 100 http_interest_drop(sock, cookie, EVENT_IN);
102 io_dontwantread(sock);
103 } 101 }
104 io_wantwrite(sock); 102 http_interest_add(sock, cookie, EVENT_OUT);
105 } 103 }
106} 104}
107 105
@@ -114,6 +112,21 @@ static void http_senddata(const int64_t sock, struct ot_workstruct *ws) {
114#define HTTPERROR_403_IP return http_issue_error(sock, ws, CODE_HTTPERROR_403_IP) 112#define HTTPERROR_403_IP return http_issue_error(sock, ws, CODE_HTTPERROR_403_IP)
115#define HTTPERROR_404 return http_issue_error(sock, ws, CODE_HTTPERROR_404) 113#define HTTPERROR_404 return http_issue_error(sock, ws, CODE_HTTPERROR_404)
116#define HTTPERROR_500 return http_issue_error(sock, ws, CODE_HTTPERROR_500) 114#define HTTPERROR_500 return http_issue_error(sock, ws, CODE_HTTPERROR_500)
115static void http_interest(const int64_t sock, struct http_data *cookie, int what) {
116 if (cookie->interest == what)
117 return;
118 cookie->interest = what;
119 event_modify((int)sock, what, fdstate_generation((int)sock));
120}
121
122void http_interest_add(const int64_t sock, struct http_data *cookie, int what) {
123 http_interest(sock, cookie, cookie->interest | what);
124}
125
126void http_interest_drop(const int64_t sock, struct http_data *cookie, int what) {
127 http_interest(sock, cookie, cookie->interest & ~what);
128}
129
117ssize_t http_issue_error(const int64_t sock, struct ot_workstruct *ws, int code) { 130ssize_t http_issue_error(const int64_t sock, struct ot_workstruct *ws, int code) {
118 const char *error_code[] = {"302 Found", "400 Invalid Request", "400 Invalid Request", "400 Invalid Request", "402 Payment Required", 131 const char *error_code[] = {"302 Found", "400 Invalid Request", "400 Invalid Request", "400 Invalid Request", "402 Payment Required",
119 "403 Not Modest", "403 Access Denied", "404 Not Found", "500 Internal Server Error"}; 132 "403 Not Modest", "403 Access Denied", "404 Not Found", "500 Internal Server Error"};
@@ -135,11 +148,10 @@ ssize_t http_issue_error(const int64_t sock, struct ot_workstruct *ws, int code)
135} 148}
136 149
137ssize_t http_sendiovecdata(const int64_t sock, struct ot_workstruct *ws, size_t iovec_entries, struct iovec *iovector, int is_partial) { 150ssize_t http_sendiovecdata(const int64_t sock, struct ot_workstruct *ws, size_t iovec_entries, struct iovec *iovector, int is_partial) {
138 struct http_data *cookie = io_getcookie(sock); 151 struct http_data *cookie = fdstate_cookie(sock);
139 char *header; 152 char *header;
140 const char *encoding = ""; 153 const char *encoding = "";
141 size_t header_size, size = iovec_length(&iovec_entries, (const struct iovec **)&iovector); 154 size_t header_size, size = iovec_length(&iovec_entries, (const struct iovec **)&iovector);
142 tai6464 t;
143 155
144 /* No cookie? Bad socket. Leave. */ 156 /* No cookie? Bad socket. Leave. */
145 if (!cookie) { 157 if (!cookie) {
@@ -159,7 +171,7 @@ ssize_t http_sendiovecdata(const int64_t sock, struct ot_workstruct *ws, size_t
159 171
160 /* If we came here, wait for the answer is over */ 172 /* If we came here, wait for the answer is over */
161 if (cookie->flag & STRUCT_HTTP_FLAG_WAITINGFORTASK) { 173 if (cookie->flag & STRUCT_HTTP_FLAG_WAITINGFORTASK) {
162 io_dontwantread(sock); 174 http_interest_drop(sock, cookie, EVENT_IN);
163 cookie->flag &= ~STRUCT_HTTP_FLAG_WAITINGFORTASK; 175 cookie->flag &= ~STRUCT_HTTP_FLAG_WAITINGFORTASK;
164 } 176 }
165 177
@@ -209,11 +221,8 @@ ssize_t http_sendiovecdata(const int64_t sock, struct ot_workstruct *ws, size_t
209 cookie->flag &= ~STRUCT_HTTP_FLAG_CHUNKED_IN_TRANSFER; 221 cookie->flag &= ~STRUCT_HTTP_FLAG_CHUNKED_IN_TRANSFER;
210 } 222 }
211 223
212 /* writeable sockets timeout after 10 minutes */ 224 fdstate_set_expiry(sock, g_now_seconds + OT_CLIENT_TIMEOUT_SEND);
213 taia_now(&t); 225 http_interest_add(sock, cookie, EVENT_OUT);
214 taia_addsec(&t, &t, OT_CLIENT_TIMEOUT_SEND);
215 io_timeout(sock, t);
216 io_wantwrite(sock);
217 return 0; 226 return 0;
218} 227}
219 228
@@ -248,7 +257,8 @@ static ssize_t http_handle_stats(const int64_t sock, struct ot_workstruct *ws, c
248 {"url", TASK_FULLSCRAPE_TPB_URLENCODED}, {"txt", TASK_FULLSCRAPE_TPB_ASCII}, 257 {"url", TASK_FULLSCRAPE_TPB_URLENCODED}, {"txt", TASK_FULLSCRAPE_TPB_ASCII},
249 {"txtp", TASK_FULLSCRAPE_TPB_ASCII_PLUS}, {NULL, -3}}; 258 {"txtp", TASK_FULLSCRAPE_TPB_ASCII_PLUS}, {NULL, -3}};
250 259
251 struct http_data *cookie = io_getcookie(sock); 260 struct http_data *cookie = fdstate_cookie(sock);
261 char *reply;
252 int mode = TASK_STATS_PEERS, scanon = 1, format = 0; 262 int mode = TASK_STATS_PEERS, scanon = 1, format = 0;
253 263
254 /* 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
@@ -262,21 +272,21 @@ static ssize_t http_handle_stats(const int64_t sock, struct ot_workstruct *ws, c
262#endif 272#endif
263 273
264 while (scanon) { 274 while (scanon) {
265 switch (scan_find_keywords(keywords_main, &read_ptr, SCAN_SEARCHPATH_PARAM)) { 275 switch (urlencoded_match_keyword(keywords_main, &read_ptr, SCAN_SEARCHPATH_PARAM)) {
266 case -2: 276 case -2:
267 scanon = 0; 277 scanon = 0;
268 break; /* TERMINATOR */ 278 break; /* TERMINATOR */
269 case -1: 279 case -1:
270 HTTPERROR_400_PARAM; /* PARSE ERROR */ 280 HTTPERROR_400_PARAM; /* PARSE ERROR */
271 case -3: 281 case -3:
272 scan_urlencoded_skipvalue(&read_ptr); 282 urlencoded_skip_value(&read_ptr);
273 break; 283 break;
274 case 1: /* matched "mode" */ 284 case 1: /* matched "mode" */
275 if ((mode = scan_find_keywords(keywords_mode, &read_ptr, SCAN_SEARCHPATH_VALUE)) <= 0) 285 if ((mode = urlencoded_match_keyword(keywords_mode, &read_ptr, SCAN_SEARCHPATH_VALUE)) <= 0)
276 HTTPERROR_400_PARAM; 286 HTTPERROR_400_PARAM;
277 break; 287 break;
278 case 2: /* matched "format" */ 288 case 2: /* matched "format" */
279 if ((format = scan_find_keywords(keywords_format, &read_ptr, SCAN_SEARCHPATH_VALUE)) <= 0) 289 if ((format = urlencoded_match_keyword(keywords_format, &read_ptr, SCAN_SEARCHPATH_VALUE)) <= 0)
280 HTTPERROR_400_PARAM; 290 HTTPERROR_400_PARAM;
281 break; 291 break;
282 case 3: 292 case 3:
@@ -291,7 +301,6 @@ static ssize_t http_handle_stats(const int64_t sock, struct ot_workstruct *ws, c
291 } 301 }
292 302
293 if (mode == TASK_STATS_TPB) { 303 if (mode == TASK_STATS_TPB) {
294 tai6464 t;
295#ifdef WANT_COMPRESSION_GZIP 304#ifdef WANT_COMPRESSION_GZIP
296 ws->request[ws->request_size - 1] = 0; 305 ws->request[ws->request_size - 1] = 0;
297#ifndef WANT_COMPRESSION_GZIP_ALWAYS 306#ifndef WANT_COMPRESSION_GZIP_ALWAYS
@@ -307,29 +316,28 @@ static ssize_t http_handle_stats(const int64_t sock, struct ot_workstruct *ws, c
307 cookie->flag |= STRUCT_HTTP_FLAG_WAITINGFORTASK | STRUCT_HTTP_FLAG_CHUNKED; 316 cookie->flag |= STRUCT_HTTP_FLAG_WAITINGFORTASK | STRUCT_HTTP_FLAG_CHUNKED;
308 317
309 /* Clients waiting for us should not easily timeout */ 318 /* Clients waiting for us should not easily timeout */
310 taia_uint(&t, 0); 319 fdstate_set_expiry(sock, 0);
311 io_timeout(sock, t);
312 fullscrape_deliver(sock, format); 320 fullscrape_deliver(sock, format);
313 io_dontwantread(sock); 321 http_interest_drop(sock, cookie, EVENT_IN);
314 return ws->reply_size = -2; 322 return ws->reply_size = -2;
315 } 323 }
316#endif 324#endif
317 325
318 /* default format for now */ 326 /* default format for now */
319 if ((mode & TASK_CLASS_MASK) == TASK_STATS) { 327 if ((mode & TASK_CLASS_MASK) == TASK_STATS) {
320 tai6464 t;
321 328
322 cookie->flag |= STRUCT_HTTP_FLAG_WAITINGFORTASK; 329 cookie->flag |= STRUCT_HTTP_FLAG_WAITINGFORTASK;
323 330
324 /* Complex stats also include expensive memory debugging tools */ 331 /* Complex stats also include expensive memory debugging tools */
325 taia_uint(&t, 0); 332 fdstate_set_expiry(sock, 0);
326 io_timeout(sock, t);
327 stats_deliver(sock, mode); 333 stats_deliver(sock, mode);
328 return ws->reply_size = -2; 334 return ws->reply_size = -2;
329 } 335 }
330 336
331 /* Simple stats can be answerred immediately */ 337 /* Simple stats can be answerred immediately */
332 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;
333} 341}
334 342
335#ifdef WANT_MODEST_FULLSCRAPES 343#ifdef WANT_MODEST_FULLSCRAPES
@@ -343,9 +351,8 @@ typedef struct {
343 351
344#ifdef WANT_FULLSCRAPE 352#ifdef WANT_FULLSCRAPE
345static ssize_t http_handle_fullscrape(const int64_t sock, struct ot_workstruct *ws) { 353static ssize_t http_handle_fullscrape(const int64_t sock, struct ot_workstruct *ws) {
346 struct http_data *cookie = io_getcookie(sock); 354 struct http_data *cookie = fdstate_cookie(sock);
347 int format = 0; 355 int format = 0;
348 tai6464 t;
349 356
350#ifdef WANT_MODEST_FULLSCRAPES 357#ifdef WANT_MODEST_FULLSCRAPES
351 { 358 {
@@ -404,10 +411,9 @@ static ssize_t http_handle_fullscrape(const int64_t sock, struct ot_workstruct *
404 /* Pass this task to the worker thread */ 411 /* Pass this task to the worker thread */
405 cookie->flag |= STRUCT_HTTP_FLAG_WAITINGFORTASK | STRUCT_HTTP_FLAG_CHUNKED; 412 cookie->flag |= STRUCT_HTTP_FLAG_WAITINGFORTASK | STRUCT_HTTP_FLAG_CHUNKED;
406 /* Clients waiting for us should not easily timeout */ 413 /* Clients waiting for us should not easily timeout */
407 taia_uint(&t, 0); 414 fdstate_set_expiry(sock, 0);
408 io_timeout(sock, t);
409 fullscrape_deliver(sock, format); 415 fullscrape_deliver(sock, format);
410 io_dontwantread(sock); 416 http_interest_drop(sock, cookie, EVENT_IN);
411 return ws->reply_size = -2; 417 return ws->reply_size = -2;
412} 418}
413#endif 419#endif
@@ -415,9 +421,10 @@ static ssize_t http_handle_fullscrape(const int64_t sock, struct ot_workstruct *
415static 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) {
416 static const ot_keywords keywords_scrape[] = {{"info_hash", 1}, {NULL, -3}}; 422 static const ot_keywords keywords_scrape[] = {{"info_hash", 1}, {NULL, -3}};
417 423
418 ot_hash *multiscrape_buf = (ot_hash *)ws->request; 424 ot_hash *multiscrape_buf = (ot_hash *)ws->request;
419 int scanon = 1; 425 char *reply = ws->reply;
420 size_t numwant = 0; 426 int scanon = 1;
427 size_t numwant = 0;
421 428
422 /* 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" */
423 if (read_ptr[-1] != '?') { 430 if (read_ptr[-1] != '?') {
@@ -429,18 +436,18 @@ static ssize_t http_handle_scrape(const int64_t sock, struct ot_workstruct *ws,
429 } 436 }
430 437
431 while (scanon) { 438 while (scanon) {
432 switch (scan_find_keywords(keywords_scrape, &read_ptr, SCAN_SEARCHPATH_PARAM)) { 439 switch (urlencoded_match_keyword(keywords_scrape, &read_ptr, SCAN_SEARCHPATH_PARAM)) {
433 case -2: 440 case -2:
434 scanon = 0; 441 scanon = 0;
435 break; /* TERMINATOR */ 442 break; /* TERMINATOR */
436 default: 443 default:
437 HTTPERROR_400_PARAM; /* PARSE ERROR */ 444 HTTPERROR_400_PARAM; /* PARSE ERROR */
438 case -3: 445 case -3:
439 scan_urlencoded_skipvalue(&read_ptr); 446 urlencoded_skip_value(&read_ptr);
440 break; 447 break;
441 case 1: /* matched "info_hash" */ 448 case 1: /* matched "info_hash" */
442 /* ignore this, when we have less than 20 bytes */ 449 /* ignore this, when we have less than 20 bytes */
443 if (scan_urlencoded_query(&read_ptr, (char *)(multiscrape_buf + numwant++), SCAN_SEARCHPATH_VALUE) != (ssize_t)sizeof(ot_hash)) 450 if (urlencoded_parse(&read_ptr, (char *)(multiscrape_buf + numwant++), SCAN_SEARCHPATH_VALUE) != (ssize_t)sizeof(ot_hash))
444 HTTPERROR_400_PARAM; 451 HTTPERROR_400_PARAM;
445 break; 452 break;
446 } 453 }
@@ -455,7 +462,8 @@ static ssize_t http_handle_scrape(const int64_t sock, struct ot_workstruct *ws,
455 numwant = OT_MAXMULTISCRAPE_COUNT; 462 numwant = OT_MAXMULTISCRAPE_COUNT;
456 463
457 /* Enough for http header + whole scrape string */ 464 /* Enough for http header + whole scrape string */
458 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;
459 stats_issue_event(EVENT_SCRAPE, FLAG_TCP, ws->reply_size); 467 stats_issue_event(EVENT_SCRAPE, FLAG_TCP, ws->reply_size);
460 return ws->reply_size; 468 return ws->reply_size;
461} 469}
@@ -491,13 +499,24 @@ static ot_keywords keywords_announce[] = {{"port", 1}, {"left", 2}, {"event",
491#endif 499#endif
492 {"peer_id", 9}, {NULL, -3}}; 500 {"peer_id", 9}, {NULL, -3}};
493static 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
494static 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) {
495 size_t numwant; 513 size_t numwant;
496 int tmp, scanon; 514 int64_t tmp;
515 int scanon;
497 unsigned short port = 0; 516 unsigned short port = 0;
498 char *write_ptr; 517 char *write_ptr;
499 ssize_t len; 518 ssize_t len;
500 struct http_data *cookie = io_getcookie(sock); 519 struct http_data *cookie = fdstate_cookie(sock);
501 520
502 /* This is to hack around stupid clients that send "announce ?info_hash" */ 521 /* This is to hack around stupid clients that send "announce ?info_hash" */
503 if (read_ptr[-1] != '?') { 522 if (read_ptr[-1] != '?') {
@@ -512,7 +531,7 @@ static ssize_t http_handle_announce(const int64_t sock, struct ot_workstruct
512 if (accesslist_is_blessed(cookie->ip, OT_PERMISSION_MAY_PROXY)) { 531 if (accesslist_is_blessed(cookie->ip, OT_PERMISSION_MAY_PROXY)) {
513 ot_ip6 proxied_ip; 532 ot_ip6 proxied_ip;
514 char *fwd = http_header(ws->request, ws->header_size, "x-forwarded-for"); 533 char *fwd = http_header(ws->request, ws->header_size, "x-forwarded-for");
515 if (fwd && ip_scan(fwd, proxied_ip)) { 534 if (fwd && ip_parse(fwd, proxied_ip)) {
516 OT_SETIP(ws->peer, proxied_ip); 535 OT_SETIP(ws->peer, proxied_ip);
517 } else 536 } else
518 OT_SETIP(ws->peer, cookie->ip); 537 OT_SETIP(ws->peer, cookie->ip);
@@ -529,32 +548,32 @@ static ssize_t http_handle_announce(const int64_t sock, struct ot_workstruct
529 scanon = 1; 548 scanon = 1;
530 549
531 while (scanon) { 550 while (scanon) {
532 switch (scan_find_keywords(keywords_announce, &read_ptr, SCAN_SEARCHPATH_PARAM)) { 551 switch (urlencoded_match_keyword(keywords_announce, &read_ptr, SCAN_SEARCHPATH_PARAM)) {
533 case -2: 552 case -2:
534 scanon = 0; 553 scanon = 0;
535 break; /* TERMINATOR */ 554 break; /* TERMINATOR */
536 case -1: 555 case -1:
537 HTTPERROR_400_PARAM; /* PARSE ERROR */ 556 HTTPERROR_400_PARAM; /* PARSE ERROR */
538 case -3: 557 case -3:
539 scan_urlencoded_skipvalue(&read_ptr); 558 urlencoded_skip_value(&read_ptr);
540 break; 559 break;
541 case 1: /* matched "port" */ 560 case 1: /* matched "port" */
542 len = scan_urlencoded_query(&read_ptr, write_ptr = read_ptr, SCAN_SEARCHPATH_VALUE); 561 len = urlencoded_parse(&read_ptr, write_ptr = read_ptr, SCAN_SEARCHPATH_VALUE);
543 if ((len <= 0) || scan_fixed_int(write_ptr, len, &tmp) || (tmp > 0xffff)) 562 if ((len <= 0) || scan_int(write_ptr, len, &tmp) || (tmp > 0xffff))
544 HTTPERROR_400_PARAM; 563 HTTPERROR_400_PARAM;
545 port = htons(tmp); 564 port = htons((uint16_t)tmp);
546 OT_SETPORT(&ws->peer, &port); 565 OT_SETPORT(&ws->peer, &port);
547 break; 566 break;
548 case 2: /* matched "left" */ 567 case 2: /* matched "left" */
549 if ((len = scan_urlencoded_query(&read_ptr, write_ptr = read_ptr, SCAN_SEARCHPATH_VALUE)) <= 0) 568 if ((len = urlencoded_parse(&read_ptr, write_ptr = read_ptr, SCAN_SEARCHPATH_VALUE)) <= 0)
550 HTTPERROR_400_PARAM; 569 HTTPERROR_400_PARAM;
551 if (scan_fixed_int(write_ptr, len, &tmp)) 570 if (scan_int(write_ptr, len, &tmp))
552 tmp = 0; 571 tmp = 0;
553 if (!tmp) 572 if (!tmp)
554 OT_PEERFLAG(&ws->peer) |= PEER_FLAG_SEEDING; 573 OT_PEERFLAG(&ws->peer) |= PEER_FLAG_SEEDING;
555 break; 574 break;
556 case 3: /* matched "event" */ 575 case 3: /* matched "event" */
557 switch (scan_find_keywords(keywords_announce_event, &read_ptr, SCAN_SEARCHPATH_VALUE)) { 576 switch (urlencoded_match_keyword(keywords_announce_event, &read_ptr, SCAN_SEARCHPATH_VALUE)) {
558 case -1: 577 case -1:
559 HTTPERROR_400_PARAM; 578 HTTPERROR_400_PARAM;
560 case 1: /* matched "completed" */ 579 case 1: /* matched "completed" */
@@ -568,18 +587,18 @@ static ssize_t http_handle_announce(const int64_t sock, struct ot_workstruct
568 } 587 }
569 break; 588 break;
570 case 4: /* matched "numwant" */ 589 case 4: /* matched "numwant" */
571 len = scan_urlencoded_query(&read_ptr, write_ptr = read_ptr, SCAN_SEARCHPATH_VALUE); 590 len = urlencoded_parse(&read_ptr, write_ptr = read_ptr, SCAN_SEARCHPATH_VALUE);
572 if ((len <= 0) || scan_fixed_int(write_ptr, len, &tmp)) 591 if ((len <= 0) || scan_int(write_ptr, len, &tmp))
573 HTTPERROR_400_PARAM; 592 HTTPERROR_400_PARAM;
574 if (tmp < 0) 593 if (tmp < 0)
575 tmp = 50; 594 tmp = 50;
576 if (tmp > 200) 595 if (tmp > 200)
577 tmp = 200; 596 tmp = 200;
578 numwant = tmp; 597 numwant = (size_t)tmp;
579 break; 598 break;
580 case 5: /* matched "compact" */ 599 case 5: /* matched "compact" */
581 len = scan_urlencoded_query(&read_ptr, write_ptr = read_ptr, SCAN_SEARCHPATH_VALUE); 600 len = urlencoded_parse(&read_ptr, write_ptr = read_ptr, SCAN_SEARCHPATH_VALUE);
582 if ((len <= 0) || scan_fixed_int(write_ptr, len, &tmp)) 601 if ((len <= 0) || scan_int(write_ptr, len, &tmp))
583 HTTPERROR_400_PARAM; 602 HTTPERROR_400_PARAM;
584 if (!tmp) 603 if (!tmp)
585 HTTPERROR_400_COMPACT; 604 HTTPERROR_400_COMPACT;
@@ -588,7 +607,7 @@ static ssize_t http_handle_announce(const int64_t sock, struct ot_workstruct
588 if (ws->hash) 607 if (ws->hash)
589 HTTPERROR_400_DOUBLEHASH; 608 HTTPERROR_400_DOUBLEHASH;
590 /* ignore this, when we have less than 20 bytes */ 609 /* ignore this, when we have less than 20 bytes */
591 if (scan_urlencoded_query(&read_ptr, write_ptr = read_ptr, SCAN_SEARCHPATH_VALUE) != 20) 610 if (urlencoded_parse(&read_ptr, write_ptr = read_ptr, SCAN_SEARCHPATH_VALUE) != 20)
592 HTTPERROR_400_PARAM; 611 HTTPERROR_400_PARAM;
593 ws->hash = (ot_hash *)write_ptr; 612 ws->hash = (ot_hash *)write_ptr;
594 break; 613 break;
@@ -596,9 +615,9 @@ static ssize_t http_handle_announce(const int64_t sock, struct ot_workstruct
596 case 7: /* matched "ip" */ 615 case 7: /* matched "ip" */
597 { 616 {
598 char *tmp_buf1 = ws->reply, *tmp_buf2 = ws->reply + 16; 617 char *tmp_buf1 = ws->reply, *tmp_buf2 = ws->reply + 16;
599 len = scan_urlencoded_query(&read_ptr, tmp_buf2, SCAN_SEARCHPATH_VALUE); 618 len = urlencoded_parse(&read_ptr, tmp_buf2, SCAN_SEARCHPATH_VALUE);
600 tmp_buf2[len] = 0; 619 tmp_buf2[len] = 0;
601 if ((len <= 0) || !ip_scan(tmp_buf2, tmp_buf1)) 620 if ((len <= 0) || ip_parse(tmp_buf2, tmp_buf1) != (size_t)len)
602 HTTPERROR_400_PARAM; 621 HTTPERROR_400_PARAM;
603 OT_SETIP(&ws->peer, tmp_buf1); 622 OT_SETIP(&ws->peer, tmp_buf1);
604 } break; 623 } break;
@@ -612,21 +631,21 @@ static ssize_t http_handle_announce(const int64_t sock, struct ot_workstruct
612 uint64_t value; 631 uint64_t value;
613 signed short parsed, bits; 632 signed short parsed, bits;
614 633
615 len = scan_urlencoded_query(&read_ptr, tmp_buf, SCAN_SEARCHPATH_VALUE); 634 len = urlencoded_parse(&read_ptr, tmp_buf, SCAN_SEARCHPATH_VALUE);
616 tmp_buf[len] = 0; 635 tmp_buf[len] = 0;
617 if (len <= 0) 636 if (len <= 0)
618 HTTPERROR_400_PARAM; 637 HTTPERROR_400_PARAM;
619 if (*tmp_buf == '-') { 638 if (*tmp_buf == '-') {
620 loglist_reset(); 639 loglist_reset();
621 return ws->reply_size = sprintf(ws->reply, "Successfully removed.\n"); 640 return ws->reply_size = reply_literal(ws, "Successfully removed.\n");
622 } 641 }
623 parsed = ip_scan(tmp_buf, net.address); 642 parsed = ip_parse(tmp_buf, net.address);
624 if (!parsed) 643 if (!parsed)
625 HTTPERROR_400_PARAM; 644 HTTPERROR_400_PARAM;
626 if (tmp_buf[parsed++] != '/') 645 if (tmp_buf[parsed++] != '/')
627 bits = 128; 646 bits = 128;
628 else { 647 else {
629 parsed = scan_udec(tmp_buf + parsed, &value, 128); 648 parsed = scan_uint(tmp_buf + parsed, &value, 128);
630 if (!parsed) 649 if (!parsed)
631 HTTPERROR_400_PARAM; 650 HTTPERROR_400_PARAM;
632 bits = (signed short)value; 651 bits = (signed short)value;
@@ -635,13 +654,13 @@ static ssize_t http_handle_announce(const int64_t sock, struct ot_workstruct
635 } 654 }
636 net.bits = bits; 655 net.bits = bits;
637 loglist_add_network(&net); 656 loglist_add_network(&net);
638 return ws->reply_size = sprintf(ws->reply, "Successfully added.\n"); 657 return ws->reply_size = reply_literal(ws, "Successfully added.\n");
639 //} 658 //}
640 } break; 659 } break;
641#endif 660#endif
642 case 9: /* matched "peer_id" */ 661 case 9: /* matched "peer_id" */
643 /* ignore this, when we have less than 20 bytes */ 662 /* ignore this, when we have less than 20 bytes */
644 if (scan_urlencoded_query(&read_ptr, write_ptr = read_ptr, SCAN_SEARCHPATH_VALUE) != 20) 663 if (urlencoded_parse(&read_ptr, write_ptr = read_ptr, SCAN_SEARCHPATH_VALUE) != 20)
645 HTTPERROR_400_PARAM; 664 HTTPERROR_400_PARAM;
646 ws->peer_id = write_ptr; 665 ws->peer_id = write_ptr;
647 break; 666 break;
@@ -658,7 +677,7 @@ static ssize_t http_handle_announce(const int64_t sock, struct ot_workstruct
658 677
659 /* Scanned whole query string */ 678 /* Scanned whole query string */
660 if (!ws->hash) 679 if (!ws->hash)
661 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");
662 681
663 if (OT_PEERFLAG(&ws->peer) & PEER_FLAG_STOPPED) 682 if (OT_PEERFLAG(&ws->peer) & PEER_FLAG_STOPPED)
664 ws->reply_size = remove_peer_from_torrent(FLAG_TCP, ws); 683 ws->reply_size = remove_peer_from_torrent(FLAG_TCP, ws);
@@ -674,7 +693,7 @@ ssize_t http_handle_request(const int64_t sock, struct ot_workstruct *ws) {
674 char *read_ptr = ws->request, *write_ptr; 693 char *read_ptr = ws->request, *write_ptr;
675 694
676#ifdef WANT_FULLLOG_NETWORKS 695#ifdef WANT_FULLLOG_NETWORKS
677 struct http_data *cookie = io_getcookie(sock); 696 struct http_data *cookie = fdstate_cookie(sock);
678 if (loglist_check_address(cookie->ip)) { 697 if (loglist_check_address(cookie->ip)) {
679 ot_log *log = malloc(sizeof(ot_log)); 698 ot_log *log = malloc(sizeof(ot_log));
680 if (log) { 699 if (log) {
@@ -720,7 +739,7 @@ ssize_t http_handle_request(const int64_t sock, struct ot_workstruct *ws) {
720 In reality we abandoned requiring the url to be correct. This now 739 In reality we abandoned requiring the url to be correct. This now
721 only decodes url encoded characters, we check for announces and 740 only decodes url encoded characters, we check for announces and
722 scrapes by looking for "a*" or "sc" */ 741 scrapes by looking for "a*" or "sc" */
723 len = scan_urlencoded_query(&read_ptr, write_ptr = read_ptr, SCAN_PATH); 742 len = urlencoded_parse(&read_ptr, write_ptr = read_ptr, SCAN_PATH);
724 743
725 /* If parsing returned an error, leave with not found */ 744 /* If parsing returned an error, leave with not found */
726 if (g_redirecturl && (len == -2)) 745 if (g_redirecturl && (len == -2))
@@ -769,9 +788,11 @@ ssize_t http_handle_request(const int64_t sock, struct ot_workstruct *ws) {
769 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);
770 ws->reply = ws->outbuf + reply_off; 789 ws->reply = ws->outbuf + reply_off;
771 790
772 /* 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
773 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
774 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);
775 796
776 /* 3. Finally we join both blocks neatly */ 797 /* 3. Finally we join both blocks neatly */
777 ws->outbuf[SUCCESS_HTTP_HEADER_LENGTH - 1] = '\n'; 798 ws->outbuf[SUCCESS_HTTP_HEADER_LENGTH - 1] = '\n';