diff options
Diffstat (limited to 'ot_http.c')
| -rw-r--r-- | ot_http.c | 41 |
1 files changed, 27 insertions, 14 deletions
| @@ -44,7 +44,7 @@ ssize_t g_stats_path_len; | |||
| 44 | 44 | ||
| 45 | enum { SUCCESS_HTTP_HEADER_LENGTH = 80, SUCCESS_HTTP_SIZE_OFF = 17 }; | 45 | enum { SUCCESS_HTTP_HEADER_LENGTH = 80, SUCCESS_HTTP_SIZE_OFF = 17 }; |
| 46 | 46 | ||
| 47 | static void http_senddata(const int64 sock, struct ot_workstruct *ws) { | 47 | static void http_senddata(const int64_t sock, struct ot_workstruct *ws) { |
| 48 | struct http_data *cookie = io_getcookie(sock); | 48 | struct http_data *cookie = io_getcookie(sock); |
| 49 | ssize_t written_size; | 49 | ssize_t written_size; |
| 50 | 50 | ||
| @@ -124,7 +124,7 @@ static void http_senddata(const int64 sock, struct ot_workstruct *ws) { | |||
| 124 | #define HTTPERROR_403_IP return http_issue_error(sock, ws, CODE_HTTPERROR_403_IP) | 124 | #define HTTPERROR_403_IP return http_issue_error(sock, ws, CODE_HTTPERROR_403_IP) |
| 125 | #define HTTPERROR_404 return http_issue_error(sock, ws, CODE_HTTPERROR_404) | 125 | #define HTTPERROR_404 return http_issue_error(sock, ws, CODE_HTTPERROR_404) |
| 126 | #define HTTPERROR_500 return http_issue_error(sock, ws, CODE_HTTPERROR_500) | 126 | #define HTTPERROR_500 return http_issue_error(sock, ws, CODE_HTTPERROR_500) |
| 127 | ssize_t http_issue_error(const int64 sock, struct ot_workstruct *ws, int code) { | 127 | ssize_t http_issue_error(const int64_t sock, struct ot_workstruct *ws, int code) { |
| 128 | char *error_code[] = {"302 Found", "400 Invalid Request", "400 Invalid Request", "400 Invalid Request", "402 Payment Required", | 128 | char *error_code[] = {"302 Found", "400 Invalid Request", "400 Invalid Request", "400 Invalid Request", "402 Payment Required", |
| 129 | "403 Not Modest", "403 Access Denied", "404 Not Found", "500 Internal Server Error"}; | 129 | "403 Not Modest", "403 Access Denied", "404 Not Found", "500 Internal Server Error"}; |
| 130 | char *title = error_code[code]; | 130 | char *title = error_code[code]; |
| @@ -144,7 +144,7 @@ ssize_t http_issue_error(const int64 sock, struct ot_workstruct *ws, int code) { | |||
| 144 | return ws->reply_size = -2; | 144 | return ws->reply_size = -2; |
| 145 | } | 145 | } |
| 146 | 146 | ||
| 147 | ssize_t http_sendiovecdata(const int64 sock, struct ot_workstruct *ws, size_t iovec_entries, struct iovec *iovector, int is_partial) { | 147 | ssize_t http_sendiovecdata(const int64_t sock, struct ot_workstruct *ws, size_t iovec_entries, struct iovec *iovector, int is_partial) { |
| 148 | struct http_data *cookie = io_getcookie(sock); | 148 | struct http_data *cookie = io_getcookie(sock); |
| 149 | io_batch *current; | 149 | io_batch *current; |
| 150 | char *header; | 150 | char *header; |
| @@ -158,6 +158,13 @@ ssize_t http_sendiovecdata(const int64 sock, struct ot_workstruct *ws, size_t io | |||
| 158 | HTTPERROR_500; | 158 | HTTPERROR_500; |
| 159 | } | 159 | } |
| 160 | 160 | ||
| 161 | /* Descriptor numbers get recycled, so a result can only belong to this | ||
| 162 | connection if this connection is in fact waiting for one. */ | ||
| 163 | if (!(cookie->flag & (STRUCT_HTTP_FLAG_WAITINGFORTASK | STRUCT_HTTP_FLAG_CHUNKED_IN_TRANSFER))) { | ||
| 164 | iovec_free(&iovec_entries, &iovector); | ||
| 165 | return 0; | ||
| 166 | } | ||
| 167 | |||
| 161 | /* If this socket collected request in a buffer, free it now */ | 168 | /* If this socket collected request in a buffer, free it now */ |
| 162 | buf_reset(&cookie->request); | 169 | buf_reset(&cookie->request); |
| 163 | 170 | ||
| @@ -236,7 +243,7 @@ ssize_t http_sendiovecdata(const int64 sock, struct ot_workstruct *ws, size_t io | |||
| 236 | return 0; | 243 | return 0; |
| 237 | } | 244 | } |
| 238 | 245 | ||
| 239 | static ssize_t http_handle_stats(const int64 sock, struct ot_workstruct *ws, char *read_ptr) { | 246 | static ssize_t http_handle_stats(const int64_t sock, struct ot_workstruct *ws, char *read_ptr) { |
| 240 | static const ot_keywords keywords_main[] = {{"mode", 1}, {"format", 2}, {"info_hash", 3}, {NULL, -3}}; | 247 | static const ot_keywords keywords_main[] = {{"mode", 1}, {"format", 2}, {"info_hash", 3}, {NULL, -3}}; |
| 241 | static const ot_keywords keywords_mode[] = {{"peer", TASK_STATS_PEERS}, | 248 | static const ot_keywords keywords_mode[] = {{"peer", TASK_STATS_PEERS}, |
| 242 | {"conn", TASK_STATS_CONNS}, | 249 | {"conn", TASK_STATS_CONNS}, |
| @@ -267,12 +274,16 @@ static ssize_t http_handle_stats(const int64 sock, struct ot_workstruct *ws, cha | |||
| 267 | {"url", TASK_FULLSCRAPE_TPB_URLENCODED}, {"txt", TASK_FULLSCRAPE_TPB_ASCII}, | 274 | {"url", TASK_FULLSCRAPE_TPB_URLENCODED}, {"txt", TASK_FULLSCRAPE_TPB_ASCII}, |
| 268 | {"txtp", TASK_FULLSCRAPE_TPB_ASCII_PLUS}, {NULL, -3}}; | 275 | {"txtp", TASK_FULLSCRAPE_TPB_ASCII_PLUS}, {NULL, -3}}; |
| 269 | 276 | ||
| 270 | int mode = TASK_STATS_PEERS, scanon = 1, format = 0; | ||
| 271 | |||
| 272 | #ifdef WANT_RESTRICT_STATS | ||
| 273 | struct http_data *cookie = io_getcookie(sock); | 277 | struct http_data *cookie = io_getcookie(sock); |
| 278 | int mode = TASK_STATS_PEERS, scanon = 1, format = 0; | ||
| 274 | 279 | ||
| 275 | if (!cookie || !accesslist_is_blessed(cookie->ip, OT_PERMISSION_MAY_STAT)) | 280 | /* A socket without one is a dead socket, which is what http_sendiovecdata |
| 281 | already answers 500 to. */ | ||
| 282 | if (!cookie) | ||
| 283 | HTTPERROR_500; | ||
| 284 | |||
| 285 | #ifdef WANT_RESTRICT_STATS | ||
| 286 | if (!accesslist_is_blessed(cookie->ip, OT_PERMISSION_MAY_STAT)) | ||
| 276 | HTTPERROR_403_IP; | 287 | HTTPERROR_403_IP; |
| 277 | #endif | 288 | #endif |
| 278 | 289 | ||
| @@ -306,8 +317,7 @@ static ssize_t http_handle_stats(const int64 sock, struct ot_workstruct *ws, cha | |||
| 306 | } | 317 | } |
| 307 | 318 | ||
| 308 | if (mode == TASK_STATS_TPB) { | 319 | if (mode == TASK_STATS_TPB) { |
| 309 | struct http_data *cookie = io_getcookie(sock); | 320 | tai6464 t; |
| 310 | tai6464 t; | ||
| 311 | #ifdef WANT_COMPRESSION_GZIP | 321 | #ifdef WANT_COMPRESSION_GZIP |
| 312 | ws->request[ws->request_size - 1] = 0; | 322 | ws->request[ws->request_size - 1] = 0; |
| 313 | #ifndef WANT_COMPRESSION_GZIP_ALWAYS | 323 | #ifndef WANT_COMPRESSION_GZIP_ALWAYS |
| @@ -334,6 +344,9 @@ static ssize_t http_handle_stats(const int64 sock, struct ot_workstruct *ws, cha | |||
| 334 | /* default format for now */ | 344 | /* default format for now */ |
| 335 | if ((mode & TASK_CLASS_MASK) == TASK_STATS) { | 345 | if ((mode & TASK_CLASS_MASK) == TASK_STATS) { |
| 336 | tai6464 t; | 346 | tai6464 t; |
| 347 | |||
| 348 | cookie->flag |= STRUCT_HTTP_FLAG_WAITINGFORTASK; | ||
| 349 | |||
| 337 | /* Complex stats also include expensive memory debugging tools */ | 350 | /* Complex stats also include expensive memory debugging tools */ |
| 338 | taia_uint(&t, 0); | 351 | taia_uint(&t, 0); |
| 339 | io_timeout(sock, t); | 352 | io_timeout(sock, t); |
| @@ -355,7 +368,7 @@ typedef struct { | |||
| 355 | #endif | 368 | #endif |
| 356 | 369 | ||
| 357 | #ifdef WANT_FULLSCRAPE | 370 | #ifdef WANT_FULLSCRAPE |
| 358 | static ssize_t http_handle_fullscrape(const int64 sock, struct ot_workstruct *ws) { | 371 | static ssize_t http_handle_fullscrape(const int64_t sock, struct ot_workstruct *ws) { |
| 359 | struct http_data *cookie = io_getcookie(sock); | 372 | struct http_data *cookie = io_getcookie(sock); |
| 360 | int format = 0; | 373 | int format = 0; |
| 361 | tai6464 t; | 374 | tai6464 t; |
| @@ -425,7 +438,7 @@ static ssize_t http_handle_fullscrape(const int64 sock, struct ot_workstruct *ws | |||
| 425 | } | 438 | } |
| 426 | #endif | 439 | #endif |
| 427 | 440 | ||
| 428 | static ssize_t http_handle_scrape(const int64 sock, struct ot_workstruct *ws, char *read_ptr) { | 441 | static ssize_t http_handle_scrape(const int64_t sock, struct ot_workstruct *ws, char *read_ptr) { |
| 429 | static const ot_keywords keywords_scrape[] = {{"info_hash", 1}, {NULL, -3}}; | 442 | static const ot_keywords keywords_scrape[] = {{"info_hash", 1}, {NULL, -3}}; |
| 430 | 443 | ||
| 431 | ot_hash *multiscrape_buf = (ot_hash *)ws->request; | 444 | ot_hash *multiscrape_buf = (ot_hash *)ws->request; |
| @@ -504,7 +517,7 @@ static ot_keywords keywords_announce[] = {{"port", 1}, {"left", 2}, {"event", | |||
| 504 | #endif | 517 | #endif |
| 505 | {"peer_id", 9}, {NULL, -3}}; | 518 | {"peer_id", 9}, {NULL, -3}}; |
| 506 | static ot_keywords keywords_announce_event[] = {{"completed", 1}, {"stopped", 2}, {NULL, -3}}; | 519 | static ot_keywords keywords_announce_event[] = {{"completed", 1}, {"stopped", 2}, {NULL, -3}}; |
| 507 | static ssize_t http_handle_announce(const int64 sock, struct ot_workstruct *ws, char *read_ptr) { | 520 | static ssize_t http_handle_announce(const int64_t sock, struct ot_workstruct *ws, char *read_ptr) { |
| 508 | size_t numwant; | 521 | size_t numwant; |
| 509 | int tmp, scanon; | 522 | int tmp, scanon; |
| 510 | unsigned short port = 0; | 523 | unsigned short port = 0; |
| @@ -682,7 +695,7 @@ static ssize_t http_handle_announce(const int64 sock, struct ot_workstruct * | |||
| 682 | return ws->reply_size; | 695 | return ws->reply_size; |
| 683 | } | 696 | } |
| 684 | 697 | ||
| 685 | ssize_t http_handle_request(const int64 sock, struct ot_workstruct *ws) { | 698 | ssize_t http_handle_request(const int64_t sock, struct ot_workstruct *ws) { |
| 686 | ssize_t reply_off, len; | 699 | ssize_t reply_off, len; |
| 687 | char *read_ptr = ws->request, *write_ptr; | 700 | char *read_ptr = ws->request, *write_ptr; |
| 688 | 701 | ||
