diff options
Diffstat (limited to 'ot_http.c')
| -rw-r--r-- | ot_http.c | 40 |
1 files changed, 30 insertions, 10 deletions
| @@ -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_vector.h" | ||
| 27 | #include "ot_fmt.h" | 28 | #include "ot_fmt.h" |
| 28 | #include "ot_stats.h" | 29 | #include "ot_stats.h" |
| 29 | #include "ot_urlencoded.h" | 30 | #include "ot_urlencoded.h" |
| @@ -233,7 +234,6 @@ static ssize_t http_handle_stats(const int64_t sock, struct ot_workstruct *ws, c | |||
| 233 | {"scrp", TASK_STATS_SCRAPE}, | 234 | {"scrp", TASK_STATS_SCRAPE}, |
| 234 | {"udp4", TASK_STATS_UDP}, | 235 | {"udp4", TASK_STATS_UDP}, |
| 235 | {"tcp4", TASK_STATS_TCP}, | 236 | {"tcp4", TASK_STATS_TCP}, |
| 236 | {"busy", TASK_STATS_BUSY_NETWORKS}, | ||
| 237 | {"torr", TASK_STATS_TORRENTS}, | 237 | {"torr", TASK_STATS_TORRENTS}, |
| 238 | {"fscr", TASK_STATS_FULLSCRAPE}, | 238 | {"fscr", TASK_STATS_FULLSCRAPE}, |
| 239 | {"s24s", TASK_STATS_SLASH24S}, | 239 | {"s24s", TASK_STATS_SLASH24S}, |
| @@ -418,13 +418,15 @@ static ssize_t http_handle_fullscrape(const int64_t sock, struct ot_workstruct * | |||
| 418 | } | 418 | } |
| 419 | #endif | 419 | #endif |
| 420 | 420 | ||
| 421 | static int compare_hash(const void *left, const void *right) { return memcmp(left, right, sizeof(ot_hash)); } | ||
| 422 | |||
| 421 | static ssize_t http_handle_scrape(const int64_t sock, struct ot_workstruct *ws, char *read_ptr) { | 423 | static ssize_t http_handle_scrape(const int64_t sock, struct ot_workstruct *ws, char *read_ptr) { |
| 422 | static const ot_keywords keywords_scrape[] = {{"info_hash", 1}, {NULL, -3}}; | 424 | static const ot_keywords keywords_scrape[] = {{"info_hash", 1}, {NULL, -3}}; |
| 423 | 425 | ||
| 424 | ot_hash *multiscrape_buf = (ot_hash *)ws->request; | 426 | ot_hash *multiscrape_buf = (ot_hash *)ws->request; |
| 425 | char *reply = ws->reply; | 427 | char *reply = ws->reply; |
| 426 | int scanon = 1; | 428 | int scanon = 1; |
| 427 | size_t numwant = 0; | 429 | size_t i, unique, numwant = 0; |
| 428 | 430 | ||
| 429 | /* This is to hack around stupid clients that send "scrape ?info_hash" */ | 431 | /* This is to hack around stupid clients that send "scrape ?info_hash" */ |
| 430 | if (read_ptr[-1] != '?') { | 432 | if (read_ptr[-1] != '?') { |
| @@ -461,6 +463,14 @@ static ssize_t http_handle_scrape(const int64_t sock, struct ot_workstruct *ws, | |||
| 461 | if (numwant > OT_MAXMULTISCRAPE_COUNT) | 463 | if (numwant > OT_MAXMULTISCRAPE_COUNT) |
| 462 | numwant = OT_MAXMULTISCRAPE_COUNT; | 464 | numwant = OT_MAXMULTISCRAPE_COUNT; |
| 463 | 465 | ||
| 466 | /* A bencoded dictionary has its keys in order and names each one once, so | ||
| 467 | the answer cannot just follow the order the client asked in */ | ||
| 468 | qsort(multiscrape_buf, numwant, sizeof(ot_hash), compare_hash); | ||
| 469 | for (i = unique = 1; i < numwant; ++i) | ||
| 470 | if (memcmp(multiscrape_buf[i], multiscrape_buf[unique - 1], sizeof(ot_hash))) | ||
| 471 | memcpy(multiscrape_buf[unique++], multiscrape_buf[i], sizeof(ot_hash)); | ||
| 472 | numwant = unique; | ||
| 473 | |||
| 464 | /* Enough for http header + whole scrape string */ | 474 | /* Enough for http header + whole scrape string */ |
| 465 | return_tcp_scrape_for_torrent((const ot_hash *)multiscrape_buf, numwant, &reply, ws->outbuf + G_OUTBUF_SIZE); | 475 | return_tcp_scrape_for_torrent((const ot_hash *)multiscrape_buf, numwant, &reply, ws->outbuf + G_OUTBUF_SIZE); |
| 466 | ws->reply_size = reply - ws->reply; | 476 | ws->reply_size = reply - ws->reply; |
| @@ -727,6 +737,24 @@ ssize_t http_handle_request(const int64_t sock, struct ot_workstruct *ws) { | |||
| 727 | /* Tell subroutines where to put reply data */ | 737 | /* Tell subroutines where to put reply data */ |
| 728 | ws->reply = ws->outbuf + SUCCESS_HTTP_HEADER_LENGTH; | 738 | ws->reply = ws->outbuf + SUCCESS_HTTP_HEADER_LENGTH; |
| 729 | 739 | ||
| 740 | /* Find out if the client wants to keep this connection alive, before any | ||
| 741 | subroutine gets to answer: an error reply finishes with the connection | ||
| 742 | on its way out, and ws outlives the connection it was serving */ | ||
| 743 | ws->keep_alive = 0; | ||
| 744 | #ifdef WANT_KEEPALIVE | ||
| 745 | if ((write_ptr = http_header(ws->request, ws->header_size, "connection")) && (*write_ptr == 'K' || *write_ptr == 'k')) | ||
| 746 | ws->keep_alive = 1; | ||
| 747 | #endif | ||
| 748 | { | ||
| 749 | struct http_data *connection = fdstate_cookie(sock); | ||
| 750 | if (connection) { | ||
| 751 | if (ws->keep_alive) | ||
| 752 | connection->flag |= STRUCT_HTTP_FLAG_KEEPALIVE; | ||
| 753 | else | ||
| 754 | connection->flag &= ~STRUCT_HTTP_FLAG_KEEPALIVE; | ||
| 755 | } | ||
| 756 | } | ||
| 757 | |||
| 730 | /* This one implicitely tests strlen < 5, too -- remember, it is \n terminated */ | 758 | /* This one implicitely tests strlen < 5, too -- remember, it is \n terminated */ |
| 731 | if (memcmp(read_ptr, "GET /", 5)) | 759 | if (memcmp(read_ptr, "GET /", 5)) |
| 732 | HTTPERROR_400; | 760 | HTTPERROR_400; |
| @@ -763,14 +791,6 @@ ssize_t http_handle_request(const int64_t sock, struct ot_workstruct *ws) { | |||
| 763 | else | 791 | else |
| 764 | HTTPERROR_404; | 792 | HTTPERROR_404; |
| 765 | 793 | ||
| 766 | /* Find out if the client wants to keep this connection alive */ | ||
| 767 | ws->keep_alive = 0; | ||
| 768 | #ifdef WANT_KEEPALIVE | ||
| 769 | read_ptr = http_header(ws->request, ws->header_size, "connection"); | ||
| 770 | if (read_ptr && (*read_ptr == 'K' || *read_ptr == 'k')) | ||
| 771 | ws->keep_alive = 1; | ||
| 772 | #endif | ||
| 773 | |||
| 774 | /* If routines handled sending themselves, just return */ | 794 | /* If routines handled sending themselves, just return */ |
| 775 | if (ws->reply_size == -2) | 795 | if (ws->reply_size == -2) |
| 776 | return 0; | 796 | return 0; |
