summaryrefslogtreecommitdiff
path: root/ot_http.c
diff options
context:
space:
mode:
Diffstat (limited to 'ot_http.c')
-rw-r--r--ot_http.c85
1 files changed, 24 insertions, 61 deletions
diff --git a/ot_http.c b/ot_http.c
index 46ca5a9..331a457 100644
--- a/ot_http.c
+++ b/ot_http.c
@@ -15,7 +15,7 @@
15#include <unistd.h> 15#include <unistd.h>
16 16
17/* Libowfat */ 17/* Libowfat */
18#include "iob.h" 18#include "io.h"
19 19
20/* Opentracker */ 20/* Opentracker */
21#include "ot_accesslist.h" 21#include "ot_accesslist.h"
@@ -26,20 +26,14 @@
26#include "ot_mutex.h" 26#include "ot_mutex.h"
27#include "ot_scan.h" 27#include "ot_scan.h"
28#include "ot_stats.h" 28#include "ot_stats.h"
29#include "ot_timeout.h"
29#include "scan_urlencoded_query.h" 30#include "scan_urlencoded_query.h"
30#include "trackerlogic.h" 31#include "trackerlogic.h"
31 32
32#ifdef WANT_NO_AUTO_FREE
33#define OT_IOB_INIT(B) (bzero(B, sizeof(io_batch)), 0)
34#else
35#define OT_IOB_INIT(B) iob_init_autofree(B, 0)
36#endif
37
38#define OT_MAXMULTISCRAPE_COUNT 64 33#define OT_MAXMULTISCRAPE_COUNT 64
39#define OT_BATCH_LIMIT (1024 * 1024 * 16) 34extern const char *g_redirecturl;
40extern char *g_redirecturl;
41 35
42char *g_stats_path; 36const char *g_stats_path;
43ssize_t g_stats_path_len; 37ssize_t g_stats_path_len;
44 38
45enum { SUCCESS_HTTP_HEADER_LENGTH = 80, SUCCESS_HTTP_SIZE_OFF = 17 }; 39enum { SUCCESS_HTTP_HEADER_LENGTH = 80, SUCCESS_HTTP_SIZE_OFF = 17 };
@@ -79,7 +73,6 @@ static void http_senddata(const int64_t sock, struct ot_workstruct *ws) {
79 73
80 if (written_size < ws->reply_size) { 74 if (written_size < ws->reply_size) {
81 char *outbuf; 75 char *outbuf;
82 tai6464 t;
83 76
84 if (!(outbuf = malloc(ws->reply_size - written_size))) { 77 if (!(outbuf = malloc(ws->reply_size - written_size))) {
85 buf_reset(&cookie->request); 78 buf_reset(&cookie->request);
@@ -90,25 +83,21 @@ static void http_senddata(const int64_t sock, struct ot_workstruct *ws) {
90 83
91 memcpy(outbuf, ws->reply + written_size, ws->reply_size - written_size); 84 memcpy(outbuf, ws->reply + written_size, ws->reply_size - written_size);
92 if (!cookie->batch) { 85 if (!cookie->batch) {
93 cookie->batch = malloc(sizeof(io_batch)); 86 cookie->batch = calloc(1, sizeof(ot_batch));
94 if (!cookie->batch || OT_IOB_INIT(cookie->batch) == -1) { 87 if (!cookie->batch) {
95 free(cookie->batch);
96 free(outbuf); 88 free(outbuf);
97 buf_reset(&cookie->request); 89 buf_reset(&cookie->request);
98 free(cookie); 90 free(cookie);
99 io_close(sock); 91 io_close(sock);
100 return; 92 return;
101 } 93 }
102
103 cookie->batches = 1;
104 } 94 }
105 95
106 iob_addbuf_free(cookie->batch, outbuf, ws->reply_size - written_size); 96 batch_add(cookie->batch, outbuf, ws->reply_size - written_size);
107 97
108 /* writeable short data sockets just have a tcp timeout */ 98 /* writeable short data sockets just have a tcp timeout */
109 if (!ws->keep_alive) { 99 if (!ws->keep_alive) {
110 taia_uint(&t, 0); 100 timeout_never(sock);
111 io_timeout(sock, t);
112 io_dontwantread(sock); 101 io_dontwantread(sock);
113 } 102 }
114 io_wantwrite(sock); 103 io_wantwrite(sock);
@@ -125,9 +114,9 @@ static void http_senddata(const int64_t sock, struct ot_workstruct *ws) {
125#define HTTPERROR_404 return http_issue_error(sock, ws, CODE_HTTPERROR_404) 114#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) 115#define HTTPERROR_500 return http_issue_error(sock, ws, CODE_HTTPERROR_500)
127ssize_t http_issue_error(const int64_t sock, struct ot_workstruct *ws, int code) { 116ssize_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", 117 const 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"}; 118 "403 Not Modest", "403 Access Denied", "404 Not Found", "500 Internal Server Error"};
130 char *title = error_code[code]; 119 const char *title = error_code[code];
131 120
132 ws->reply = ws->outbuf; 121 ws->reply = ws->outbuf;
133 if (code == CODE_HTTPERROR_302) 122 if (code == CODE_HTTPERROR_302)
@@ -146,11 +135,9 @@ ssize_t http_issue_error(const int64_t sock, struct ot_workstruct *ws, int code)
146 135
147ssize_t http_sendiovecdata(const int64_t sock, struct ot_workstruct *ws, size_t iovec_entries, struct iovec *iovector, int is_partial) { 136ssize_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); 137 struct http_data *cookie = io_getcookie(sock);
149 io_batch *current;
150 char *header; 138 char *header;
151 const char *encoding = ""; 139 const char *encoding = "";
152 size_t i, header_size, size = iovec_length(&iovec_entries, (const struct iovec **)&iovector); 140 size_t header_size, size = iovec_length(&iovec_entries, (const struct iovec **)&iovector);
153 tai6464 t;
154 141
155 /* No cookie? Bad socket. Leave. */ 142 /* No cookie? Bad socket. Leave. */
156 if (!cookie) { 143 if (!cookie) {
@@ -199,46 +186,28 @@ ssize_t http_sendiovecdata(const int64_t sock, struct ot_workstruct *ws, size_t
199 } 186 }
200 187
201 if (!cookie->batch) { 188 if (!cookie->batch) {
202 cookie->batch = malloc(sizeof(io_batch)); 189 cookie->batch = calloc(1, sizeof(ot_batch));
203 if (!cookie->batch || OT_IOB_INIT(cookie->batch) == -1) { 190 if (!cookie->batch) {
204 free(cookie->batch);
205 free(header); 191 free(header);
206 iovec_free(&iovec_entries, &iovector); 192 iovec_free(&iovec_entries, &iovector);
207 HTTPERROR_500; 193 HTTPERROR_500;
208 } 194 }
209 cookie->batches = 1;
210 } 195 }
211 current = cookie->batch + cookie->batches - 1;
212 iob_addbuf_free(current, header, header_size);
213 196
214 /* Split huge iovectors into separate io_batches */ 197 batch_add(cookie->batch, header, header_size);
215 for (i = 0; i < (size_t)iovec_entries; ++i) { 198 batch_add_vector(cookie->batch, iovector, iovec_entries);
216 /* If the current batch's limit is reached, try to reallocate a new batch to work on */
217 if (current->bytesleft > OT_BATCH_LIMIT) {
218 io_batch *new_batch = realloc(cookie->batch, (cookie->batches + 1) * sizeof(io_batch));
219 if (new_batch) {
220 cookie->batch = new_batch;
221 if (OT_IOB_INIT(current) != -1)
222 current = cookie->batch + cookie->batches++;
223 }
224 }
225 iob_addbuf_free(current, iovector[i].iov_base, iovector[i].iov_len);
226 }
227 free(iovector); 199 free(iovector);
200
228 if (cookie->flag & STRUCT_HTTP_FLAG_CHUNKED_IN_TRANSFER) 201 if (cookie->flag & STRUCT_HTTP_FLAG_CHUNKED_IN_TRANSFER)
229 iob_addbuf(current, "\r\n", 2); 202 batch_add_copy(cookie->batch, "\r\n", 2);
230 } 203 }
231 204
232 if ((cookie->flag & STRUCT_HTTP_FLAG_CHUNKED_IN_TRANSFER) && cookie->batch && !is_partial) { 205 if ((cookie->flag & STRUCT_HTTP_FLAG_CHUNKED_IN_TRANSFER) && cookie->batch && !is_partial) {
233 current = cookie->batch + cookie->batches - 1; 206 batch_add_copy(cookie->batch, "0\r\n\r\n", 5);
234 iob_addbuf(current, "0\r\n\r\n", 5);
235 cookie->flag &= ~STRUCT_HTTP_FLAG_CHUNKED_IN_TRANSFER; 207 cookie->flag &= ~STRUCT_HTTP_FLAG_CHUNKED_IN_TRANSFER;
236 } 208 }
237 209
238 /* writeable sockets timeout after 10 minutes */ 210 timeout_in(sock, OT_CLIENT_TIMEOUT_SEND);
239 taia_now(&t);
240 taia_addsec(&t, &t, OT_CLIENT_TIMEOUT_SEND);
241 io_timeout(sock, t);
242 io_wantwrite(sock); 211 io_wantwrite(sock);
243 return 0; 212 return 0;
244} 213}
@@ -317,7 +286,6 @@ static ssize_t http_handle_stats(const int64_t sock, struct ot_workstruct *ws, c
317 } 286 }
318 287
319 if (mode == TASK_STATS_TPB) { 288 if (mode == TASK_STATS_TPB) {
320 tai6464 t;
321#ifdef WANT_COMPRESSION_GZIP 289#ifdef WANT_COMPRESSION_GZIP
322 ws->request[ws->request_size - 1] = 0; 290 ws->request[ws->request_size - 1] = 0;
323#ifndef WANT_COMPRESSION_GZIP_ALWAYS 291#ifndef WANT_COMPRESSION_GZIP_ALWAYS
@@ -333,8 +301,7 @@ static ssize_t http_handle_stats(const int64_t sock, struct ot_workstruct *ws, c
333 cookie->flag |= STRUCT_HTTP_FLAG_WAITINGFORTASK | STRUCT_HTTP_FLAG_CHUNKED; 301 cookie->flag |= STRUCT_HTTP_FLAG_WAITINGFORTASK | STRUCT_HTTP_FLAG_CHUNKED;
334 302
335 /* Clients waiting for us should not easily timeout */ 303 /* Clients waiting for us should not easily timeout */
336 taia_uint(&t, 0); 304 timeout_never(sock);
337 io_timeout(sock, t);
338 fullscrape_deliver(sock, format); 305 fullscrape_deliver(sock, format);
339 io_dontwantread(sock); 306 io_dontwantread(sock);
340 return ws->reply_size = -2; 307 return ws->reply_size = -2;
@@ -343,13 +310,11 @@ static ssize_t http_handle_stats(const int64_t sock, struct ot_workstruct *ws, c
343 310
344 /* default format for now */ 311 /* default format for now */
345 if ((mode & TASK_CLASS_MASK) == TASK_STATS) { 312 if ((mode & TASK_CLASS_MASK) == TASK_STATS) {
346 tai6464 t;
347 313
348 cookie->flag |= STRUCT_HTTP_FLAG_WAITINGFORTASK; 314 cookie->flag |= STRUCT_HTTP_FLAG_WAITINGFORTASK;
349 315
350 /* Complex stats also include expensive memory debugging tools */ 316 /* Complex stats also include expensive memory debugging tools */
351 taia_uint(&t, 0); 317 timeout_never(sock);
352 io_timeout(sock, t);
353 stats_deliver(sock, mode); 318 stats_deliver(sock, mode);
354 return ws->reply_size = -2; 319 return ws->reply_size = -2;
355 } 320 }
@@ -371,7 +336,6 @@ typedef struct {
371static ssize_t http_handle_fullscrape(const int64_t sock, struct ot_workstruct *ws) { 336static ssize_t http_handle_fullscrape(const int64_t sock, struct ot_workstruct *ws) {
372 struct http_data *cookie = io_getcookie(sock); 337 struct http_data *cookie = io_getcookie(sock);
373 int format = 0; 338 int format = 0;
374 tai6464 t;
375 339
376#ifdef WANT_MODEST_FULLSCRAPES 340#ifdef WANT_MODEST_FULLSCRAPES
377 { 341 {
@@ -430,9 +394,8 @@ static ssize_t http_handle_fullscrape(const int64_t sock, struct ot_workstruct *
430 /* Pass this task to the worker thread */ 394 /* Pass this task to the worker thread */
431 cookie->flag |= STRUCT_HTTP_FLAG_WAITINGFORTASK | STRUCT_HTTP_FLAG_CHUNKED; 395 cookie->flag |= STRUCT_HTTP_FLAG_WAITINGFORTASK | STRUCT_HTTP_FLAG_CHUNKED;
432 /* Clients waiting for us should not easily timeout */ 396 /* Clients waiting for us should not easily timeout */
433 taia_uint(&t, 0); 397 timeout_never(sock);
434 io_timeout(sock, t); 398 fullscrape_deliver(sock, format);
435 fullscrape_deliver(sock, TASK_FULLSCRAPE | format);
436 io_dontwantread(sock); 399 io_dontwantread(sock);
437 return ws->reply_size = -2; 400 return ws->reply_size = -2;
438} 401}
@@ -491,7 +454,7 @@ unsigned long long numwants[201];
491#endif 454#endif
492 455
493#if defined(WANT_KEEPALIVE) || defined(WANT_IP_FROM_PROXY) 456#if defined(WANT_KEEPALIVE) || defined(WANT_IP_FROM_PROXY)
494static char *http_header(char *data, size_t byte_count, char *header) { 457static char *http_header(char *data, size_t byte_count, const char *header) {
495 size_t i; 458 size_t i;
496 long sl = strlen(header); 459 long sl = strlen(header);
497 for (i = 0; i + sl + 2 < byte_count; ++i) { 460 for (i = 0; i + sl + 2 < byte_count; ++i) {