summaryrefslogtreecommitdiff
path: root/opentracker.c
diff options
context:
space:
mode:
Diffstat (limited to 'opentracker.c')
-rw-r--r--opentracker.c128
1 files changed, 5 insertions, 123 deletions
diff --git a/opentracker.c b/opentracker.c
index 27b2570..2eaf988 100644
--- a/opentracker.c
+++ b/opentracker.c
@@ -35,6 +35,7 @@
35#include "ot_fdstate.h" 35#include "ot_fdstate.h"
36#include "ot_socket.h" 36#include "ot_socket.h"
37#include "ot_stats.h" 37#include "ot_stats.h"
38#include "ot_tcp.h"
38#include "ot_udp.h" 39#include "ot_udp.h"
39#include "trackerlogic.h" 40#include "trackerlogic.h"
40 41
@@ -96,126 +97,6 @@ static void install_signal_handlers(void) {
96} 97}
97 98
98 99
99static ssize_t header_complete(char *request, ssize_t byte_count) {
100 ssize_t i = 0, state = 0;
101
102 for (i = 1; i < byte_count; i += 2)
103 if (request[i] <= 13) {
104 i--;
105 for (state = 0; i < byte_count; ++i) {
106 char c = request[i];
107 if (c == '\r' || c == '\n')
108 state = (state >> 2) | ((c << 6) & 0xc0);
109 else
110 break;
111 if (state >= 0xa0 || state == 0x99)
112 return i + 1;
113 }
114 }
115 return 0;
116}
117
118static void handle_read(const int64_t sock, struct ot_workstruct *ws) {
119 struct http_data *cookie = fdstate_cookie(sock);
120 ssize_t byte_count = read((int)sock, ws->inbuf, G_INBUF_SIZE);
121
122 if (byte_count == 0 || (byte_count == -1 && errno != EAGAIN && errno != EWOULDBLOCK && errno != EINTR)) {
123 http_close(sock);
124 return;
125 }
126
127 if (byte_count == -1)
128 return;
129
130 ws->request = NULL;
131 ws->request_size = 0;
132 ws->header_size = 0;
133 ws->keep_alive = 0;
134
135 /* If we get the whole request in one packet, handle it without copying */
136 if (!cookie->request.data) {
137 if ((ws->header_size = header_complete(ws->inbuf, byte_count))) {
138 ws->request = ws->inbuf;
139 ws->request_size = byte_count;
140 http_handle_request(sock, ws);
141 } else if (buf_cat(&cookie->request, ws->inbuf, (size_t)byte_count))
142 http_close(sock);
143 return;
144 }
145
146 if (buf_cat(&cookie->request, ws->inbuf, (size_t)byte_count) || cookie->request.size > G_INBUF_SIZE) {
147 http_issue_error(sock, ws, CODE_HTTPERROR_500);
148 return;
149 }
150
151 while ((ws->header_size = header_complete(cookie->request.data, (ssize_t)cookie->request.size))) {
152 ws->request = cookie->request.data;
153 ws->request_size = (ssize_t)cookie->request.size;
154 http_handle_request(sock, ws);
155#ifdef WANT_KEEPALIVE
156 if (!ws->keep_alive)
157#endif
158 return;
159 }
160}
161
162static void handle_write(const int64_t sock) {
163 struct http_data *cookie = fdstate_cookie(sock);
164 int chunked = 0;
165 int keep_alive = 0;
166
167 if (cookie) {
168 chunked = (cookie->flag & STRUCT_HTTP_FLAG_CHUNKED_IN_TRANSFER) != 0;
169 keep_alive = (cookie->flag & STRUCT_HTTP_FLAG_KEEPALIVE) != 0;
170
171 if (cookie->batch) {
172 if (batch_send(sock, cookie->batch) == BATCH_FAILED) {
173 http_close(sock);
174 return;
175 }
176 if (batch_pending(cookie->batch))
177 return;
178 }
179 }
180
181 /* In a chunked transfer, wait for the next piece once everything queued has gone out */
182 if (chunked)
183 http_interest_set(sock, cookie, 0);
184 else if (keep_alive) {
185 /* The reply is out and the client asked to keep the connection, so go
186 back to waiting for the next request */
187 http_interest_set(sock, cookie, EVENT_IN);
188 fdstate_set_expiry(sock, time_future_seconds(OT_CLIENT_TIMEOUT));
189 } else
190 http_close(sock);
191}
192
193static void handle_accept(const int64_t serversocket, struct ot_workstruct *ws) {
194 struct http_data *cookie;
195 int64_t sock;
196 ot_ip6 ip;
197 uint16_t port;
198
199 while ((sock = socket_accept(serversocket, ip, &port)) != -1) {
200
201 if (!(cookie = (struct http_data *)calloc(1, sizeof(struct http_data)))) {
202 close((int)sock);
203 continue;
204 }
205 memcpy(cookie->ip, ip, sizeof(ot_ip6));
206 cookie->interest = EVENT_IN;
207
208 if (event_add((int)sock, EVENT_IN, fdstate_open(sock, cookie, time_future_seconds(OT_CLIENT_TIMEOUT))) == -1) {
209 fdstate_close(sock);
210 free(cookie);
211 close((int)sock);
212 continue;
213 }
214
215 stats_issue_event(ws, EVENT_ACCEPT, FLAG_TCP, (uintptr_t)ip);
216 }
217}
218
219/* How many ready descriptors one wait hands back at a time */ 100/* How many ready descriptors one wait hands back at a time */
220#define OT_EVENT_BATCH 512 101#define OT_EVENT_BATCH 512
221 102
@@ -261,7 +142,7 @@ static void *server_mainloop(void *args) {
261 cookie = fdstate_cookie((int)sock); 142 cookie = fdstate_cookie((int)sock);
262 143
263 if ((intptr_t)cookie == FLAG_TCP) 144 if ((intptr_t)cookie == FLAG_TCP)
264 handle_accept(sock, &ws); 145 tcp_accept(sock, &ws);
265 else if ((intptr_t)cookie == FLAG_UDP) 146 else if ((intptr_t)cookie == FLAG_UDP)
266 handle_udp6(sock, &ws); 147 handle_udp6(sock, &ws);
267 else if ((intptr_t)cookie == FLAG_SELFPIPE) 148 else if ((intptr_t)cookie == FLAG_SELFPIPE)
@@ -269,10 +150,10 @@ static void *server_mainloop(void *args) {
269 ; 150 ;
270 else { 151 else {
271 if (ready[i].what & EVENT_IN) 152 if (ready[i].what & EVENT_IN)
272 handle_read(sock, &ws); 153 tcp_read(sock, &ws);
273 /* The read may have closed it, so look again before writing */ 154 /* The read may have closed it, so look again before writing */
274 if ((ready[i].what & EVENT_OUT) && fdstate_generation((int)sock) == ready[i].generation) 155 if ((ready[i].what & EVENT_OUT) && fdstate_generation((int)sock) == ready[i].generation)
275 handle_write(sock); 156 tcp_write(sock);
276 } 157 }
277 } 158 }
278 159
@@ -339,6 +220,7 @@ static void listen_bind_one(ot_listen *entry) {
339 if (entry->proto == FLAG_TCP) { 220 if (entry->proto == FLAG_TCP) {
340 if ((entry->sock = socket_tcp_listen(entry->ip, entry->port, sharing)) == -1) 221 if ((entry->sock = socket_tcp_listen(entry->ip, entry->port, sharing)) == -1)
341 panic("socket_tcp_listen"); 222 panic("socket_tcp_listen");
223 socket_defer_accept((int)entry->sock);
342 } else { 224 } else {
343 if ((entry->sock = socket_udp_bind(entry->ip, entry->port, sharing)) == -1) 225 if ((entry->sock = socket_udp_bind(entry->ip, entry->port, sharing)) == -1)
344 panic("socket_udp_bind"); 226 panic("socket_udp_bind");