summaryrefslogtreecommitdiff
path: root/ot_http.c
diff options
context:
space:
mode:
Diffstat (limited to 'ot_http.c')
-rw-r--r--ot_http.c63
1 files changed, 42 insertions, 21 deletions
diff --git a/ot_http.c b/ot_http.c
index d4c7363..bb6ff24 100644
--- a/ot_http.c
+++ b/ot_http.c
@@ -6,6 +6,7 @@
6/* System */ 6/* System */
7#define _GNU_SOURCE 7#define _GNU_SOURCE
8#include <arpa/inet.h> 8#include <arpa/inet.h>
9#include <errno.h>
9#include <pthread.h> 10#include <pthread.h>
10#include <stdio.h> 11#include <stdio.h>
11#include <stdlib.h> 12#include <stdlib.h>
@@ -38,9 +39,25 @@ ssize_t g_stats_path_len;
38 39
39enum { SUCCESS_HTTP_HEADER_LENGTH = 80, SUCCESS_HTTP_SIZE_OFF = 17 }; 40enum { SUCCESS_HTTP_HEADER_LENGTH = 80, SUCCESS_HTTP_SIZE_OFF = 17 };
40 41
41/* Give up a connection: the one place that knows everything hanging off it. 42int http_adopt(const int64_t sock, struct http_data *cookie) {
42 The slot is released before anything is freed, so that a late event or the 43 struct http_data *heap = malloc(sizeof(*heap));
43 expiry sweep finds a closed descriptor rather than a freed cookie. */ 44
45 if (!heap)
46 return -1;
47
48 *heap = *cookie;
49 heap->flag &= ~STRUCT_HTTP_FLAG_ONSTACK;
50 fdstate_set_cookie((int)sock, heap);
51
52 if (event_add((int)sock, heap->interest, fdstate_generation((int)sock)) == -1) {
53 fdstate_set_cookie((int)sock, cookie);
54 free(heap);
55 return -1;
56 }
57 return 0;
58}
59
60/* Give up a connection: the one place that knows everything hanging off it. */
44void http_close(const int64_t sock) { 61void http_close(const int64_t sock) {
45 struct http_data *cookie = fdstate_cookie(sock); 62 struct http_data *cookie = fdstate_cookie(sock);
46 63
@@ -53,7 +70,8 @@ void http_close(const int64_t sock) {
53 buf_reset(&cookie->request); 70 buf_reset(&cookie->request);
54 if (cookie->flag & (STRUCT_HTTP_FLAG_WAITINGFORTASK | STRUCT_HTTP_FLAG_CHUNKED_IN_TRANSFER)) 71 if (cookie->flag & (STRUCT_HTTP_FLAG_WAITINGFORTASK | STRUCT_HTTP_FLAG_CHUNKED_IN_TRANSFER))
55 mutex_workqueue_canceltask(sock); 72 mutex_workqueue_canceltask(sock);
56 free(cookie); 73 if (!(cookie->flag & STRUCT_HTTP_FLAG_ONSTACK))
74 free(cookie);
57 } 75 }
58 76
59 event_close((int)sock); 77 event_close((int)sock);
@@ -85,6 +103,12 @@ static void http_senddata(const int64_t sock, struct ot_workstruct *ws) {
85 buf_reset(&cookie->request); 103 buf_reset(&cookie->request);
86 104
87 written_size = write(sock, ws->reply, ws->reply_size); 105 written_size = write(sock, ws->reply, ws->reply_size);
106 /* A send buffer with no room in it is not a failure: nothing went out, so
107 the whole reply goes into the batch below and leaves when the socket
108 drains. Only a real error ends the connection here. */
109 if (written_size < 0 && (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR))
110 written_size = 0;
111
88 if ((written_size < 0) || ((written_size == ws->reply_size) && !ws->keep_alive)) { 112 if ((written_size < 0) || ((written_size == ws->reply_size) && !ws->keep_alive)) {
89 http_close(sock); 113 http_close(sock);
90 return; 114 return;
@@ -111,11 +135,9 @@ static void http_senddata(const int64_t sock, struct ot_workstruct *ws) {
111 batch_add(cookie->batch, outbuf, ws->reply_size - written_size); 135 batch_add(cookie->batch, outbuf, ws->reply_size - written_size);
112 136
113 /* writeable short data sockets just have a tcp timeout */ 137 /* writeable short data sockets just have a tcp timeout */
114 if (!ws->keep_alive) { 138 if (!ws->keep_alive)
115 fdstate_set_expiry(sock, 0); 139 fdstate_set_expiry(sock, 0);
116 http_interest_drop(sock, cookie, EVENT_IN); 140 http_interest_set(sock, cookie, EVENT_OUT);
117 }
118 http_interest_add(sock, cookie, EVENT_OUT);
119 } 141 }
120} 142}
121 143
@@ -128,21 +150,20 @@ static void http_senddata(const int64_t sock, struct ot_workstruct *ws) {
128#define HTTPERROR_403_IP return http_issue_error(sock, ws, CODE_HTTPERROR_403_IP) 150#define HTTPERROR_403_IP return http_issue_error(sock, ws, CODE_HTTPERROR_403_IP)
129#define HTTPERROR_404 return http_issue_error(sock, ws, CODE_HTTPERROR_404) 151#define HTTPERROR_404 return http_issue_error(sock, ws, CODE_HTTPERROR_404)
130#define HTTPERROR_500 return http_issue_error(sock, ws, CODE_HTTPERROR_500) 152#define HTTPERROR_500 return http_issue_error(sock, ws, CODE_HTTPERROR_500)
131static void http_interest(const int64_t sock, struct http_data *cookie, int what) { 153/* A connection is either being read or being written, never both, so what it
154 waits for is set outright rather than added to and taken away again. The
155 event layer only hears about it when the answer changes. */
156void http_interest_set(const int64_t sock, struct http_data *cookie, int what) {
132 if (cookie->interest == what) 157 if (cookie->interest == what)
133 return; 158 return;
134 cookie->interest = what; 159 cookie->interest = what;
160 /* Still on a stack, so not in the event loop yet: whoever adopts this
161 connection registers whatever it asked for last */
162 if (cookie->flag & STRUCT_HTTP_FLAG_ONSTACK)
163 return;
135 event_modify((int)sock, what, fdstate_generation((int)sock)); 164 event_modify((int)sock, what, fdstate_generation((int)sock));
136} 165}
137 166
138void http_interest_add(const int64_t sock, struct http_data *cookie, int what) {
139 http_interest(sock, cookie, cookie->interest | what);
140}
141
142void http_interest_drop(const int64_t sock, struct http_data *cookie, int what) {
143 http_interest(sock, cookie, cookie->interest & ~what);
144}
145
146ssize_t http_issue_error(const int64_t sock, struct ot_workstruct *ws, int code) { 167ssize_t http_issue_error(const int64_t sock, struct ot_workstruct *ws, int code) {
147 const char *error_code[] = {"302 Found", "400 Invalid Request", "400 Invalid Request", "400 Invalid Request", "402 Payment Required", 168 const char *error_code[] = {"302 Found", "400 Invalid Request", "400 Invalid Request", "400 Invalid Request", "402 Payment Required",
148 "403 Not Modest", "403 Access Denied", "404 Not Found", "500 Internal Server Error"}; 169 "403 Not Modest", "403 Access Denied", "404 Not Found", "500 Internal Server Error"};
@@ -187,7 +208,7 @@ ssize_t http_sendiovecdata(const int64_t sock, struct ot_workstruct *ws, size_t
187 208
188 /* If we came here, wait for the answer is over */ 209 /* If we came here, wait for the answer is over */
189 if (cookie->flag & STRUCT_HTTP_FLAG_WAITINGFORTASK) { 210 if (cookie->flag & STRUCT_HTTP_FLAG_WAITINGFORTASK) {
190 http_interest_drop(sock, cookie, EVENT_IN); 211 http_interest_set(sock, cookie, 0);
191 cookie->flag &= ~STRUCT_HTTP_FLAG_WAITINGFORTASK; 212 cookie->flag &= ~STRUCT_HTTP_FLAG_WAITINGFORTASK;
192 } 213 }
193 214
@@ -238,7 +259,7 @@ ssize_t http_sendiovecdata(const int64_t sock, struct ot_workstruct *ws, size_t
238 } 259 }
239 260
240 fdstate_set_expiry(sock, time_future_seconds(OT_CLIENT_TIMEOUT_SEND)); 261 fdstate_set_expiry(sock, time_future_seconds(OT_CLIENT_TIMEOUT_SEND));
241 http_interest_add(sock, cookie, EVENT_OUT); 262 http_interest_set(sock, cookie, EVENT_OUT);
242 return 0; 263 return 0;
243} 264}
244 265
@@ -333,7 +354,7 @@ static ssize_t http_handle_stats(const int64_t sock, struct ot_workstruct *ws, c
333 /* Clients waiting for us should not easily timeout */ 354 /* Clients waiting for us should not easily timeout */
334 fdstate_set_expiry(sock, 0); 355 fdstate_set_expiry(sock, 0);
335 fullscrape_deliver(sock, format); 356 fullscrape_deliver(sock, format);
336 http_interest_drop(sock, cookie, EVENT_IN); 357 http_interest_set(sock, cookie, 0);
337 return ws->reply_size = -2; 358 return ws->reply_size = -2;
338 } 359 }
339#endif 360#endif
@@ -428,7 +449,7 @@ static ssize_t http_handle_fullscrape(const int64_t sock, struct ot_workstruct *
428 /* Clients waiting for us should not easily timeout */ 449 /* Clients waiting for us should not easily timeout */
429 fdstate_set_expiry(sock, 0); 450 fdstate_set_expiry(sock, 0);
430 fullscrape_deliver(sock, format); 451 fullscrape_deliver(sock, format);
431 http_interest_drop(sock, cookie, EVENT_IN); 452 http_interest_set(sock, cookie, 0);
432 return ws->reply_size = -2; 453 return ws->reply_size = -2;
433} 454}
434#endif 455#endif