SOCKS, better logging
[shim.git] / httpconn.c
blob63d20af9cfc3671f9ec2b1047701e47c62a0c478
2 #include <sys/queue.h>
3 #include <assert.h>
4 #include <stdarg.h>
5 #include <stdlib.h>
6 #include <string.h>
8 #include <event2/util.h>
9 #include <event2/event.h>
10 #include <event2/bufferevent.h>
11 #include <event2/buffer.h>
13 #include "httpconn.h"
14 #include "conn.h"
15 #include "headers.h"
16 #include "util.h"
17 #include "log.h"
19 #define EVENT0(conn, slot) \
20 (conn)->cbs->slot((conn), (conn)->cbarg)
21 #define EVENT1(conn, slot, a) \
22 (conn)->cbs->slot((conn), (a), (conn)->cbarg)
23 #define EVENT2(conn, slot, a, b) \
24 (conn)->cbs->slot((conn), (a), (b), (conn)->cbarg)
25 #define EVENT3(conn, slot, a, b, c) \
26 (conn)->cbs->slot((conn), (a), (b), (c), (conn)->cbarg)
27 #define EVENT4(conn, slot, a, b, c, d) \
28 (conn)->cbs->slot((conn), (a), (b), (c), (d), (conn)->cbarg)
30 /* max amount of data we can have backlogged on outbuf before choaking */
31 static size_t max_write_backlog = 50 * 1024;
33 /* the number of seconds to keep an idle connections hanging around */
34 static struct timeval idle_client_timeout = {120, 0};
35 static struct timeval idle_server_timeout = {120, 0};
37 struct http_conn {
38 enum http_state state;
39 enum http_version vers;
40 enum http_te te;
41 enum http_type type;
42 enum http_te output_te;
43 int choked;
44 int has_body;
45 int read_paused;
46 int tunnel_read_paused;
47 int msg_complete_on_eof;
48 int persistent;
49 int expect_continue;
50 int will_flush;
51 int will_free;
52 const struct http_cbs *cbs;
53 void *cbarg;
54 ev_int64_t body_length;
55 ev_int64_t data_remaining;
56 char *firstline;
57 struct header_list *headers;
58 struct event_base *base;
59 struct bufferevent *bev;
60 struct bufferevent *tunnel_bev;
61 struct evbuffer *inbuf_processed;
64 static int
65 method_from_string(enum http_method *m, const char *method)
67 if (!evutil_ascii_strcasecmp(method, "GET"))
68 *m = METH_GET;
69 else if (!evutil_ascii_strcasecmp(method, "HEAD"))
70 *m = METH_HEAD;
71 else if (!evutil_ascii_strcasecmp(method, "POST"))
72 *m = METH_POST;
73 else if (!evutil_ascii_strcasecmp(method, "PUT"))
74 *m = METH_PUT;
75 else if (!evutil_ascii_strcasecmp(method, "CONNECT"))
76 *m = METH_CONNECT;
77 else {
78 log_warn("method_from_string: unknown method, '%s'", method);
79 return -1;
82 return 0;
85 const char *
86 http_method_to_string(enum http_method m)
88 switch (m) {
89 case METH_GET:
90 return "GET";
91 case METH_HEAD:
92 return "HEAD";
93 case METH_POST:
94 return "POST";
95 case METH_PUT:
96 return "PUT";
97 case METH_CONNECT:
98 return "CONNECT";
101 log_fatal("http_method_to_string: unknown method %d", m);
102 return "???";
105 static int
106 version_from_string(enum http_version *v, const char *vers)
108 if (evutil_ascii_strncasecmp(vers, "HTTP/", 5)) {
109 log_warn("version_from_string: bad http-version, '%s'", vers);
110 return -1;
113 vers += 5;
115 /* XXX this only understands 1.0 and 1.1 */
117 if (!strcmp(vers, "1.0"))
118 *v = HTTP_10;
119 else if (!strcmp(vers, "1.1"))
120 *v = HTTP_11;
121 else {
122 log_warn("version_from_string: unknown http-version, '%s'",
123 vers);
124 return -1;
127 return 0;
130 const char *
131 http_version_to_string(enum http_version v)
133 switch (v) {
134 case HTTP_UNKNOWN:
135 return "HTTP/??";
136 case HTTP_10:
137 return "HTTP/1.0";
138 case HTTP_11:
139 return "HTTP/1.1";
142 log_fatal("http_version_to_string: unknown version %d", v);
143 return "???";
146 const char *
147 http_conn_error_to_string(enum http_conn_error err)
149 switch (err) {
150 case ERROR_NONE:
151 return "No error";
152 case ERROR_CONNECT_FAILED:
153 return "Connection failed";
154 case ERROR_IDLE_CONN_TIMEDOUT:
155 return "Idle connection timed out";
156 case ERROR_CLIENT_EXPECTATION_FAILED:
157 return "Can't statisfy client's expectation";
158 case ERROR_CLIENT_POST_WITHOUT_LENGTH:
159 return "Client post with unknown length";
160 case ERROR_INCOMPLETE_HEADERS:
161 return "Connection terminated while reading headers";
162 case ERROR_INCOMPLETE_BODY:
163 return "Connection terminated prematurely while reading body";
164 case ERROR_HEADER_PARSE_FAILED:
165 return "Invalid client request";
166 case ERROR_CHUNK_PARSE_FAILED:
167 return "Invalid chunked data";
168 case ERROR_WRITE_FAILED:
169 return "Write failed";
170 case ERROR_TUNNEL_CONNECT_FAILED:
171 return "Tunnel connection failed";
172 case ERROR_TUNNEL_CLOSED:
173 return "Tunnel closed";
176 return "???";
179 static void
180 begin_message(struct http_conn *conn)
182 assert(conn->headers == NULL && conn->firstline == NULL);
183 conn->headers = mem_calloc(1, sizeof(*conn->headers));
184 TAILQ_INIT(conn->headers);
185 conn->state = HTTP_STATE_IDLE;
186 if (!conn->read_paused)
187 bufferevent_enable(conn->bev, EV_READ);
188 // XXX we should have a separate function to tell that server is idle.
189 if (conn->type == HTTP_SERVER)
190 bufferevent_set_timeouts(conn->bev, &idle_server_timeout, NULL);
191 else
192 bufferevent_set_timeouts(conn->bev, &idle_client_timeout, NULL);
195 static void
196 end_message(struct http_conn *conn, enum http_conn_error err)
198 if (conn->firstline)
199 mem_free(conn->firstline);
200 if (conn->headers) {
201 headers_clear(conn->headers);
202 mem_free(conn->headers);
205 conn->firstline = NULL;
206 conn->headers = NULL;
208 if (err != ERROR_NONE || !conn->persistent) {
209 conn->state = HTTP_STATE_MANGLED;
210 http_conn_stop_reading(conn);
211 } else
212 begin_message(conn);
214 if (err != ERROR_NONE)
215 EVENT1(conn, on_error, err);
216 else
217 EVENT0(conn, on_msg_complete);
220 static struct http_request *
221 build_request(struct http_conn *conn)
223 struct http_request *req;
224 struct token_list tokens;
225 struct token *method, *url, *vers;
226 enum http_method m;
227 enum http_version v;
228 struct url *u = NULL;
229 size_t ntokens;
231 assert(conn->type == HTTP_CLIENT);
233 TAILQ_INIT(&tokens);
234 req = NULL;
236 ntokens = tokenize(conn->firstline, " ", 4, &tokens);
237 if (ntokens != 3)
238 goto out;
240 method = TAILQ_FIRST(&tokens);
241 url = TAILQ_NEXT(method, next);
242 vers = TAILQ_NEXT(url, next);
244 if (method_from_string(&m, method->token) < 0 ||
245 version_from_string(&v, vers->token) < 0)
246 goto out;
248 if (m == METH_CONNECT)
249 u = url_connect_tokenize(url->token);
250 else
251 u = url_tokenize(url->token);
252 if (!u)
253 goto out;
255 req = mem_calloc(1, sizeof(*req));
256 req->meth = m;
257 req->vers = v;
258 req->url = u;
259 u = NULL;
260 req->headers = conn->headers;
262 out:
263 url_free(u);
264 token_list_clear(&tokens);
266 return req;
269 static struct http_response *
270 build_response(struct http_conn *conn)
272 struct http_response *resp;
273 struct token_list tokens;
274 struct token *vers, *code, *reason;
275 enum http_version v;
276 int c;
277 size_t ntokens;
279 assert(conn->type == HTTP_SERVER);
281 TAILQ_INIT(&tokens);
282 resp = NULL;
284 ntokens = tokenize(conn->firstline, " ", 2, &tokens);
285 if (ntokens != 3)
286 goto out;
288 vers = TAILQ_FIRST(&tokens);
289 code = TAILQ_NEXT(vers, next);
290 reason = TAILQ_NEXT(code, next);
291 c = atoi(code->token);
293 if (version_from_string(&v, vers->token) < 0 || c < 100 || c > 999)
294 goto out;
296 resp = mem_calloc(1, sizeof(*resp));
297 resp->vers = v;
298 resp->code = c;
299 resp->reason = reason->token;
300 reason->token = NULL; /* so token_list_clear will skip this */
301 resp->headers = conn->headers;
303 out:
304 token_list_clear(&tokens);
306 return resp;
309 /* return -1 failure, 0 incomplete, 1 ok */
310 static int
311 parse_chunk_len(struct http_conn *conn)
313 struct evbuffer *inbuf = bufferevent_get_input(conn->bev);
314 char *line;
315 ev_int64_t len;
317 while ((line = evbuffer_readln(inbuf, NULL, EVBUFFER_EOL_CRLF))) {
318 if (*line == '\0') {
319 mem_free(line);
320 continue;
323 len = get_int(line, 16);
324 mem_free(line);
325 if (len < 0) {
326 log_warn("parse_chunk_len: invalid chunk len");
327 return -1;
330 conn->data_remaining = len;
331 return 1;
334 return 0;
337 static void
338 read_chunk(struct http_conn *conn)
340 struct evbuffer *inbuf = bufferevent_get_input(conn->bev);
341 size_t len;
342 char *line;
343 int ret;
345 while ((len = evbuffer_get_length(inbuf)) > 0) {
346 if (conn->data_remaining < 0) {
347 ret = parse_chunk_len(conn);
348 if (ret <= 0) {
349 if (ret < 0)
350 end_message(conn,
351 ERROR_CHUNK_PARSE_FAILED);
352 return;
354 } else if (conn->data_remaining == 0) {
355 line = evbuffer_readln(inbuf, NULL, EVBUFFER_EOL_CRLF);
356 if (line) {
357 /* XXX doesn't handle trailers */
358 mem_free(line);
359 end_message(conn, ERROR_NONE);
361 return;
362 } else {
363 /* XXX should mind potential overflow */
364 if (len >= (size_t)conn->data_remaining)
365 len = (size_t)conn->data_remaining;
367 evbuffer_remove_buffer(inbuf, conn->inbuf_processed,
368 len);
369 EVENT1(conn, on_read_body, conn->inbuf_processed);
370 conn->data_remaining -= len;
372 if (conn->data_remaining == 0)
373 conn->data_remaining = -1;
378 static void
379 read_body(struct http_conn *conn)
381 struct evbuffer *inbuf = bufferevent_get_input(conn->bev);
382 size_t len;
384 assert(conn->has_body);
386 if (conn->te == TE_CHUNKED) {
387 read_chunk(conn);
388 return;
391 len = evbuffer_get_length(inbuf);
392 if (len) {
393 /* XXX should mind potential overflow */
394 if (conn->data_remaining >= 0 &&
395 len > (size_t)conn->data_remaining) {
396 len = (size_t)conn->data_remaining;
397 evbuffer_remove_buffer(inbuf, conn->inbuf_processed,
398 len);
399 EVENT1(conn, on_read_body, conn->inbuf_processed);
400 } else {
401 evbuffer_add_buffer(conn->inbuf_processed, inbuf);
402 EVENT1(conn, on_read_body, conn->inbuf_processed);
405 conn->data_remaining -= len;
406 if (conn->data_remaining == 0)
407 end_message(conn, ERROR_NONE);
411 static enum http_conn_error
412 check_headers(struct http_conn *conn, struct http_request *req,
413 struct http_response *resp)
415 enum http_version vers;
416 int persistent;
417 int tunnel;
418 char *val;
420 conn->te = TE_IDENTITY;
421 conn->has_body = 1;
422 conn->msg_complete_on_eof = 0;
423 conn->data_remaining = -1;
424 conn->body_length = -1;
425 conn->expect_continue = 0;
426 tunnel = 0;
428 if (conn->type == HTTP_CLIENT) {
429 vers = req->vers;
430 conn->has_body = 0;
431 if (req->meth == METH_POST ||
432 req->meth == METH_PUT)
433 conn->has_body = 1;
434 else if (req->meth == METH_CONNECT)
435 tunnel = 1;
437 val = headers_find(conn->headers, "Expect");
438 if (val) {
439 int cont;
441 cont = !evutil_ascii_strcasecmp(val, "100-continue");
442 mem_free(val);
443 if (cont == 0 || !conn->has_body)
444 return ERROR_CLIENT_EXPECTATION_FAILED;
446 if (cont && req->vers != HTTP_11) {
447 cont = 0;
448 log_info("http: ignoring expect continue from "
449 "old client");
450 headers_remove(conn->headers, "Expect");
453 conn->expect_continue = cont;
455 } else { /* server */
456 vers = resp->vers;
457 if ((resp->code >= 100 && resp->code < 200) ||
458 resp->code == 204 || resp->code == 205 ||
459 resp->code == 304)
460 conn->has_body = 0;
463 /* check headers */
464 if (conn->has_body) {
465 val = headers_find(conn->headers, "transfer-encoding");
466 if (val) {
467 if (!evutil_ascii_strcasecmp(val, "chunked"))
468 conn->te = TE_CHUNKED;
469 mem_free(val);
472 if (conn->te != TE_CHUNKED) {
473 val = headers_find(conn->headers, "content-length");
474 if (val) {
475 ev_int64_t iv;
476 iv = get_int(val, 10);
477 if (iv < 0) {
478 log_warn("http: mangled "
479 "Content-Length");
480 headers_remove(conn->headers,
481 "content-length");
482 } else
483 conn->body_length = iv;
484 mem_free(val);
485 if (conn->body_length == 0)
486 conn->has_body = 0;
487 } else {
488 conn->msg_complete_on_eof = 1;
492 if (conn->type == HTTP_CLIENT && conn->body_length < 0 &&
493 conn->te != TE_CHUNKED)
494 return ERROR_CLIENT_POST_WITHOUT_LENGTH;
496 conn->data_remaining = conn->body_length;
498 assert(vers != HTTP_UNKNOWN);
500 persistent = 0;
501 if (!tunnel && !conn->msg_complete_on_eof && vers == HTTP_11)
502 persistent = 1;
504 if (conn->vers != HTTP_UNKNOWN && conn->vers != vers) {
505 log_warn("http_conn: http version changed!");
506 persistent = 0;
508 conn->vers = vers;
510 if (persistent) {
511 val = headers_find(conn->headers, "connection");
512 if (val) {
513 if (!evutil_ascii_strcasecmp(val, "close"))
514 persistent = 0;
515 mem_free(val);
518 conn->persistent = persistent;
520 return ERROR_NONE;
523 static void
524 read_headers(struct http_conn *conn)
526 int failed = 0;
527 struct evbuffer *inbuf = bufferevent_get_input(conn->bev);
528 struct http_request *req = NULL;
529 struct http_response *resp = NULL;
530 enum http_conn_error err;
532 assert(conn->state == HTTP_STATE_READ_HEADERS);
534 switch (headers_load(conn->headers, inbuf)) {
535 case -1:
536 end_message(conn, ERROR_HEADER_PARSE_FAILED);
537 return;
538 case 0:
539 return;
540 /* case 1: finished, fall thru */
543 assert(conn->firstline);
545 if (conn->type == HTTP_CLIENT) {
546 req = build_request(conn);
547 if (!req)
548 failed = 1;
549 } else {
550 resp = build_response(conn);
551 if (!resp)
552 failed = 1;
555 mem_free(conn->firstline);
556 conn->firstline = NULL;
558 if (failed) {
559 assert(!req && !resp);
560 end_message(conn, ERROR_HEADER_PARSE_FAILED);
561 return;
564 err = check_headers(conn, req, resp);
565 conn->headers = NULL;
567 if (err == ERROR_NONE) {
568 int server_continuation = 0;
570 /* ownership of req or resp is now passed on */
571 if (req)
572 EVENT1(conn, on_client_request, req);
573 if (resp) {
574 if (resp->code == 100) {
575 http_response_free(resp);
576 EVENT0(conn, on_server_continuation);
577 begin_message(conn);
578 server_continuation = 1;
579 } else
580 EVENT1(conn, on_server_response, resp);
583 if (!server_continuation &&
584 conn->state != HTTP_STATE_TUNNEL_CONNECTING) {
585 if (!conn->has_body)
586 end_message(conn, ERROR_NONE);
587 else
588 conn->state = HTTP_STATE_READ_BODY;
590 } else {
591 http_request_free(req);
592 http_response_free(resp);
593 end_message(conn, err);
597 static void
598 tunnel_transfer_data(struct http_conn *conn, struct bufferevent *to,
599 struct bufferevent *from)
601 struct evbuffer *frombuf = bufferevent_get_input(from);
602 struct evbuffer *tobuf = bufferevent_get_output(to);
604 if (evbuffer_get_length(frombuf) == 0)
605 return;
607 evbuffer_add_buffer(tobuf, frombuf);
608 if (evbuffer_get_length(tobuf) > max_write_backlog) {
609 bufferevent_setwatermark(to, EV_WRITE,
610 max_write_backlog / 2, 0);
611 bufferevent_disable(from, EV_READ);
612 if (from == conn->bev) {
613 log_debug("tunnel: throttling client read");
614 conn->read_paused = 1;
615 } else {
616 log_debug("tunnel: throttling server read");
617 conn->tunnel_read_paused = 1;
622 static void
623 tunnel_writecb(struct bufferevent *bev, void *_conn)
625 struct http_conn *conn = _conn;
627 if (conn->state == HTTP_STATE_TUNNEL_OPEN) {
628 if (conn->tunnel_read_paused && bev == conn->bev) {
629 log_debug("tunnel: unthrottling server read");
630 conn->tunnel_read_paused = 0;
631 bufferevent_enable(conn->tunnel_bev, EV_READ);
632 bufferevent_setwatermark(bev, EV_WRITE, 0, 0);
633 } else if (conn->read_paused && bev == conn->tunnel_bev) {
634 log_debug("tunnel: unthrottling client read");
635 conn->read_paused = 0;
636 bufferevent_enable(conn->bev, EV_READ);
637 bufferevent_setwatermark(bev, EV_WRITE, 0, 0);
639 } else {
640 log_debug("tunnel: flushed!");
641 bufferevent_setcb(conn->bev, NULL, NULL, NULL, NULL);
642 bufferevent_setcb(conn->tunnel_bev, NULL, NULL, NULL, NULL);
643 EVENT1(conn, on_error, ERROR_TUNNEL_CLOSED);
647 static void
648 tunnel_readcb(struct bufferevent *bev, void *_conn)
650 struct http_conn *conn = _conn;
652 if (bev == conn->bev)
653 tunnel_transfer_data(conn, conn->tunnel_bev, bev);
654 else
655 tunnel_transfer_data(conn, conn->bev, bev);
658 static void
659 tunnel_errorcb(struct bufferevent *bev, short what, void *_conn)
661 struct http_conn *conn = _conn;
662 struct evbuffer *buf;
664 switch (conn->state) {
665 case HTTP_STATE_TUNNEL_OPEN:
666 if (bev == conn->bev) {
667 log_debug("tunnel: client closed conn...");
668 bev = conn->tunnel_bev;
669 } else {
670 log_debug("tunnel: server closed conn...");
671 bev = conn->bev;
673 buf = bufferevent_get_output(bev);
674 if (evbuffer_get_length(buf)) {
675 conn->state = HTTP_STATE_TUNNEL_FLUSHING;
676 log_debug("tunnel: flushing %lu bytes...",
677 (unsigned long)evbuffer_get_length(buf));
678 bufferevent_disable(bev, EV_READ);
679 bufferevent_setcb(bev, NULL, tunnel_writecb,
680 tunnel_errorcb, conn);
681 break;
683 /* nothing left to write.. lets just fall thru... */
684 case HTTP_STATE_TUNNEL_FLUSHING:
685 /* an error happend while flushing, lets just give up. */
686 bufferevent_setcb(conn->bev, NULL, NULL, NULL, NULL);
687 bufferevent_setcb(conn->tunnel_bev, NULL, NULL, NULL, NULL);
688 EVENT1(conn, on_error, ERROR_TUNNEL_CLOSED);
689 break;
690 default:
691 log_fatal("tunnel: errorcb called in invalid state!");
695 static void
696 tunnel_connectcb(struct bufferevent *bev, int ok, void *_conn)
698 struct http_conn *conn = _conn;
700 assert(conn->state == HTTP_STATE_TUNNEL_CONNECTING);
702 if (ok) {
703 conn->state = HTTP_STATE_TUNNEL_OPEN;
704 bufferevent_setcb(conn->tunnel_bev, tunnel_readcb,
705 tunnel_writecb, tunnel_errorcb, conn);
706 bufferevent_enable(conn->bev, EV_READ);
707 bufferevent_enable(conn->tunnel_bev, EV_READ);
708 conn->read_paused = 0;
709 conn->tunnel_read_paused = 0;
710 tunnel_transfer_data(conn, conn->tunnel_bev, conn->bev);
711 evbuffer_add_printf(bufferevent_get_output(conn->bev),
712 "%s 200 Connection established\r\n\r\n",
713 http_version_to_string(conn->vers));
714 } else {
715 bufferevent_setcb(conn->tunnel_bev, NULL, NULL,
716 NULL, NULL);
717 EVENT1(conn, on_error, ERROR_TUNNEL_CONNECT_FAILED);
721 static void
722 http_errorcb(struct bufferevent *bev, short what, void *_conn)
724 enum http_state state;
725 struct http_conn *conn = _conn;
727 assert(!(what & BEV_EVENT_CONNECTED));
729 state = conn->state;
730 conn->state = HTTP_STATE_MANGLED;
732 if (what & BEV_EVENT_WRITING) {
733 end_message(conn, ERROR_WRITE_FAILED);
734 return;
737 switch (state) {
738 case HTTP_STATE_IDLE:
739 end_message(conn, ERROR_IDLE_CONN_TIMEDOUT);
740 break;
741 case HTTP_STATE_READ_FIRSTLINE:
742 case HTTP_STATE_READ_HEADERS:
743 end_message(conn, ERROR_INCOMPLETE_HEADERS);
744 break;
745 case HTTP_STATE_READ_BODY:
746 if ((what & BEV_EVENT_EOF) && conn->msg_complete_on_eof)
747 end_message(conn, ERROR_NONE);
748 else
749 end_message(conn, ERROR_INCOMPLETE_BODY);
750 break;
751 default:
752 log_fatal("http_conn: errorcb called in invalid state");
756 static void
757 process_one_step(struct http_conn *conn)
759 struct evbuffer *inbuf = bufferevent_get_input(conn->bev);
761 switch (conn->state) {
762 case HTTP_STATE_IDLE:
763 conn->state = HTTP_STATE_READ_FIRSTLINE;
764 bufferevent_set_timeouts(conn->bev, NULL, NULL);
765 /* fallthru... */
766 case HTTP_STATE_READ_FIRSTLINE:
767 assert(conn->firstline == NULL);
768 conn->firstline = evbuffer_readln(inbuf, NULL,
769 EVBUFFER_EOL_CRLF);
770 if (conn->firstline)
771 conn->state = HTTP_STATE_READ_HEADERS;
772 break;
773 case HTTP_STATE_READ_HEADERS:
774 read_headers(conn);
775 break;
776 case HTTP_STATE_READ_BODY:
777 read_body(conn);
778 break;
779 default:
780 log_fatal("http_conn: read cb called in invalid state");
784 static void
785 process_inbuf(struct http_conn *conn)
787 struct evbuffer *inbuf = bufferevent_get_input(conn->bev);
788 enum http_state state_before;
790 do {
791 state_before = conn->state;
792 process_one_step(conn);
793 } while (!conn->read_paused &&
794 evbuffer_get_length(inbuf) > 0 &&
795 state_before != conn->state);
798 static void
799 http_readcb(struct bufferevent *bev, void *_conn)
801 process_inbuf(_conn);
804 static void
805 http_writecb(struct bufferevent *bev, void *_conn)
807 struct http_conn *conn = _conn;
808 struct evbuffer *outbuf = bufferevent_get_output(bev);
810 if (conn->choked) {
811 bufferevent_setwatermark(bev, EV_WRITE, 0, 0);
812 conn->choked = 0;
813 EVENT0(conn, on_write_more);
814 } else if (evbuffer_get_length(outbuf) == 0) {
815 if (!conn->will_flush)
816 EVENT0(conn, on_flush);
820 static void
821 http_connectcb(struct bufferevent *bev, int ok, void *_conn)
823 struct http_conn *conn = _conn;
825 assert(conn->state == HTTP_STATE_CONNECTING);
826 bufferevent_setcb(conn->bev, http_readcb, http_writecb,
827 http_errorcb, conn);
829 if (ok) {
830 begin_message(conn);
831 EVENT0(conn, on_connect);
832 } else {
833 conn->state = HTTP_STATE_MANGLED;
834 EVENT1(conn, on_error, ERROR_CONNECT_FAILED);
839 struct http_conn *
840 http_conn_new(struct event_base *base, evutil_socket_t sock,
841 enum http_type type, const struct http_cbs *cbs, void *cbarg)
843 struct http_conn *conn;
845 conn = mem_calloc(1, sizeof(*conn));
846 conn->base = base;
847 conn->type = type;
848 conn->cbs = cbs;
849 conn->cbarg = cbarg;
850 conn->bev = bufferevent_socket_new(base, sock,
851 BEV_OPT_CLOSE_ON_FREE);
852 if (!conn->bev)
853 log_fatal("http_conn: failed to create bufferevent");
855 conn->inbuf_processed = evbuffer_new();
856 if (!conn->inbuf_processed)
857 log_fatal("http_conn: failed to create evbuffer");
859 if (type != HTTP_SERVER)
860 bufferevent_setcb(conn->bev, http_readcb, http_writecb,
861 http_errorcb, conn);
863 if (sock >= 0)
864 begin_message(conn);
866 return conn;
870 http_conn_connect(struct http_conn *conn, struct evdns_base *dns,
871 int family, const char *host, int port)
873 assert(conn->type == HTTP_SERVER);
874 conn->state = HTTP_STATE_CONNECTING;
875 return conn_connect_bufferevent(conn->bev, dns, family, host, port,
876 http_connectcb, conn);
879 static void
880 deferred_free(evutil_socket_t s, short what, void *arg)
882 struct http_conn *conn = arg;
883 bufferevent_free(conn->bev);
884 if (conn->tunnel_bev)
885 bufferevent_free(conn->tunnel_bev);
886 evbuffer_free(conn->inbuf_processed);
887 mem_free(conn);
890 void
891 http_conn_free(struct http_conn *conn)
893 if (conn->will_free)
894 return;
896 conn->will_free = 1;
897 http_conn_stop_reading(conn);
898 bufferevent_disable(conn->bev, EV_WRITE);
899 bufferevent_setcb(conn->bev, NULL, NULL, NULL, NULL);
900 conn->cbs = NULL;
901 event_base_once(conn->base, -1, EV_TIMEOUT, deferred_free, conn, NULL);
904 void
905 http_conn_write_request(struct http_conn *conn, struct http_request *req)
907 struct evbuffer *outbuf;
909 assert(conn->type == HTTP_SERVER);
911 headers_remove(req->headers, "connection");
912 req->vers = HTTP_11;
914 outbuf = bufferevent_get_output(conn->bev);
916 evbuffer_add_printf(outbuf, "%s %s %s\r\n",
917 http_method_to_string(req->meth),
918 req->url->path,
919 http_version_to_string(req->vers));
921 headers_dump(req->headers, outbuf);
925 http_conn_expect_continue(struct http_conn *conn)
927 return conn->expect_continue;
930 void
931 http_conn_write_continue(struct http_conn *conn)
933 struct evbuffer *outbuf;
935 if (conn->expect_continue) {
936 outbuf = bufferevent_get_output(conn->bev);
937 conn->expect_continue = 0;
938 assert(conn->vers == HTTP_11);
939 evbuffer_add_printf(outbuf, "HTTP/1.1 100 Continue\r\n\r\n");
943 void
944 http_conn_write_response(struct http_conn *conn, struct http_response *resp)
946 struct evbuffer *outbuf;
948 assert(conn->type == HTTP_CLIENT);
949 assert(conn->vers != HTTP_UNKNOWN);
951 headers_remove(resp->headers, "connection");
952 headers_remove(resp->headers, "transfer-encoding");
953 resp->vers = conn->vers;
955 if (conn->vers == HTTP_10 || !conn->persistent) {
956 if (conn->vers == HTTP_10)
957 conn->output_te = TE_IDENTITY;
958 headers_add_key_val(resp->headers, "Connection", "close");
960 if (conn->output_te == TE_CHUNKED) {
961 headers_add_key_val(resp->headers,
962 "Transfer-Encoding", "chunked");
965 outbuf = bufferevent_get_output(conn->bev);
967 evbuffer_add_printf(outbuf, "%s %d %s\r\n",
968 http_version_to_string(conn->vers),
969 resp->code,
970 resp->reason);
972 headers_dump(resp->headers, outbuf);
976 http_conn_write_buf(struct http_conn *conn, struct evbuffer *buf)
978 struct evbuffer *outbuf;
980 outbuf = bufferevent_get_output(conn->bev);
982 if (conn->output_te == TE_CHUNKED)
983 evbuffer_add_printf(outbuf, "%x\r\n",
984 (unsigned)evbuffer_get_length(buf));
985 evbuffer_add_buffer(outbuf, buf);
986 if (conn->output_te == TE_CHUNKED)
987 evbuffer_add(outbuf, "\r\n", 2);
989 /* have we choked? */
990 if (evbuffer_get_length(outbuf) > max_write_backlog) {
991 bufferevent_setwatermark(conn->bev, EV_WRITE,
992 max_write_backlog / 2, 0);
993 conn->choked = 1;
994 return 0;
997 return 1;
1000 void
1001 http_conn_write_finished(struct http_conn *conn)
1003 if (conn->output_te == TE_CHUNKED)
1004 bufferevent_write(conn->bev, "0\r\n\r\n", 5);
1005 conn->output_te = TE_IDENTITY;
1010 http_conn_current_message_has_body(struct http_conn *conn)
1012 return conn->has_body;
1015 void
1016 http_conn_set_current_message_bodyless(struct http_conn *conn)
1018 assert(conn->type == HTTP_SERVER);
1019 conn->has_body = 0;
1022 enum http_te
1023 http_conn_get_current_message_body_encoding(struct http_conn *conn)
1025 return conn->te;
1028 ev_int64_t
1029 http_conn_get_current_message_body_length(struct http_conn *conn)
1031 return conn->body_length;
1034 void
1035 http_conn_set_output_encoding(struct http_conn *conn, enum http_te te)
1037 conn->output_te = te;
1041 http_conn_is_persistent(struct http_conn *conn)
1043 return conn->persistent;
1046 void
1047 http_conn_disable_persistence(struct http_conn *conn)
1049 conn->persistent = 0;
1052 void
1053 http_conn_stop_reading(struct http_conn *conn)
1055 bufferevent_disable(conn->bev, EV_READ);
1056 conn->read_paused = 1;
1059 void
1060 http_conn_start_reading(struct http_conn *conn)
1062 struct evbuffer *inbuf = bufferevent_get_input(conn->bev);
1064 bufferevent_enable(conn->bev, EV_READ);
1065 conn->read_paused = 0;
1066 // XXX this might cause recursion
1067 if (evbuffer_get_length(inbuf) > 0)
1068 process_inbuf(conn);
1071 static void
1072 deferred_flush(evutil_socket_t fd, short what, void *_conn)
1074 struct http_conn *conn = _conn;
1075 struct evbuffer *outbuf = bufferevent_get_output(conn->bev);
1077 if (evbuffer_get_length(outbuf) == 0) {
1078 conn->will_flush = 0;
1079 EVENT0(conn, on_flush);
1083 void
1084 http_conn_flush(struct http_conn *conn)
1086 assert(!conn->will_free);
1087 conn->will_flush = 1;
1088 event_base_once(conn->base, -1, EV_TIMEOUT, deferred_flush, conn, NULL);
1091 void
1092 http_conn_send_error(struct http_conn *conn, int code, const char *fmt, ...)
1094 char length[64];
1095 char reason[256];
1096 struct evbuffer *msg;
1097 struct http_response resp;
1098 struct header_list headers;
1099 va_list ap;
1101 assert(conn->type == HTTP_CLIENT);
1103 TAILQ_INIT(&headers);
1104 msg = evbuffer_new();
1105 resp.headers = &headers;
1107 if (conn->vers == HTTP_UNKNOWN)
1108 conn->vers = HTTP_11;
1111 va_start(ap, fmt);
1112 evutil_vsnprintf(reason, sizeof(reason), fmt, ap);
1113 va_end(ap);
1115 conn->output_te = TE_IDENTITY;
1116 resp.vers = HTTP_11;
1117 resp.code = code;
1118 resp.reason = reason;
1120 evbuffer_add_printf(msg,
1121 "<html>\n"
1122 "<head>\n"
1123 "<title>%d %s</title>\n"
1124 "</head>\n"
1125 "<body>\n"
1126 "<h1>%d %s</h1>\n"
1127 "</body>\n"
1128 "</html>\n",
1129 code, resp.reason, code, resp.reason);
1131 evutil_snprintf(length, sizeof(length), "%u",
1132 (unsigned)evbuffer_get_length(msg));
1133 headers_add_key_val(&headers, "Content-Type", "text/html");
1134 headers_add_key_val(&headers, "Content-Length", length);
1135 headers_add_key_val(&headers, "Expires", "0");
1136 headers_add_key_val(&headers, "Cache-Control", "no-cache");
1137 headers_add_key_val(&headers, "Pragma", "no-cache");
1139 http_conn_write_response(conn, &resp);
1140 http_conn_write_buf(conn, msg);
1141 headers_clear(&headers);
1142 evbuffer_free(msg);
1146 http_conn_start_tunnel(struct http_conn *conn, struct evdns_base *dns,
1147 int family, const char *host, int port)
1149 assert(conn->type == HTTP_CLIENT);
1150 assert(conn->tunnel_bev == NULL);
1152 http_conn_stop_reading(conn);
1153 conn->tunnel_bev = bufferevent_socket_new(conn->base, -1,
1154 BEV_OPT_CLOSE_ON_FREE);
1155 bufferevent_setcb(conn->bev, tunnel_readcb,
1156 tunnel_writecb, tunnel_errorcb, conn);
1157 log_info("tunnel: attempting connection to %s:%d",
1158 log_scrub(host), port);
1159 conn->state = HTTP_STATE_TUNNEL_CONNECTING;
1160 return conn_connect_bufferevent(conn->tunnel_bev, dns, family,
1161 host, port, tunnel_connectcb, conn);
1164 void
1165 http_request_free(struct http_request *req)
1167 if (!req)
1168 return;
1170 url_free(req->url);
1171 headers_clear(req->headers);
1172 mem_free(req);
1175 void
1176 http_response_free(struct http_response *resp)
1178 if (!resp)
1179 return;
1181 headers_clear(resp->headers);
1182 mem_free(resp->headers);
1183 mem_free(resp->reason);
1184 mem_free(resp);
1187 #ifdef TEST_HTTP
1188 #include <netinet/in.h>
1189 #include <stdio.h>
1190 #include <event2/dns.h>
1191 #include <event2/listener.h>
1193 static void
1194 proxy_connected(struct http_conn *conn, void *arg)
1196 struct http_request req;
1197 struct header_list headers;
1198 struct evbuffer *buf;
1200 TAILQ_INIT(&headers);
1201 req.meth = METH_GET;
1202 req.url = arg;
1203 req.vers = HTTP_11;
1204 req.headers = &headers;
1206 buf = evbuffer_new();
1207 evbuffer_add_printf(buf, "Host: %s\r\n\r\n", req.url->host);
1208 headers_load(&headers, buf);
1209 evbuffer_free(buf);
1211 http_conn_write_request(conn, &req);
1214 static void
1215 proxy_error(struct http_conn *conn, enum http_conn_error err, void *arg)
1217 fprintf(stderr, "error %d\n", err);
1218 http_conn_free(conn);
1221 static void
1222 proxy_request(struct http_conn *conn, struct http_request *req, void *arg)
1224 struct evbuffer *buf;
1226 fprintf(stderr, "request: %s %s %s\n",
1227 http_method_to_string(req->meth),
1228 req->url->path,
1229 http_version_to_string(req->vers));
1231 buf = evbuffer_new();
1232 headers_dump(req->headers, buf);
1233 fwrite(evbuffer_pullup(buf, evbuffer_get_length(buf)), evbuffer_get_length(buf), 1, stderr);
1234 evbuffer_free(buf);
1237 http_conn_send_error(conn, 401);
1240 static void
1241 proxy_response(struct http_conn *conn, struct http_response *resp, void *arg)
1243 struct evbuffer *buf;
1245 fprintf(stderr, "response: %s, %d, %s\n",
1246 http_version_to_string(resp->vers),
1247 resp->code,
1248 resp->reason);
1250 buf = evbuffer_new();
1251 headers_dump(resp->headers, buf);
1252 fwrite(evbuffer_pullup(buf, evbuffer_get_length(buf)), evbuffer_get_length(buf), 1, stderr);
1253 evbuffer_free(buf);
1256 static void
1257 proxy_read_body(struct http_conn *conn, struct evbuffer *buf, void *arg)
1259 size_t len = evbuffer_get_length(buf);
1260 fwrite(evbuffer_pullup(buf, len), len, 1, stderr);
1261 evbuffer_drain(buf, len);
1264 static void
1265 proxy_msg_complete(struct http_conn *conn, void *arg)
1267 fprintf(stderr, "\n...MSG COMPLETE...\n");
1270 static void
1271 proxy_write_more(struct http_conn *conn, void *arg)
1275 static void
1276 proxy_flush(struct http_conn *conn, void *arg)
1278 fprintf(stderr, "\n....FLUSHED...\n");
1281 static struct http_cbs test_proxy_cbs = {
1282 proxy_connected,
1283 proxy_error,
1284 proxy_request,
1285 proxy_response,
1286 proxy_read_body,
1287 proxy_msg_complete,
1288 proxy_write_more,
1289 proxy_flush
1293 static void
1294 clientcb(struct evconnlistener *ecs, evutil_socket_t s,
1295 struct sockaddr *addr, int len, void *arg)
1297 struct http_conn *client;
1299 client = http_conn_new(evconnlistener_get_base(ecs), s, HTTP_CLIENT, &test_proxy_cbs, arg);
1303 main(int argc, char **argv)
1305 struct event_base *base;
1306 struct evdns_base *dns;
1307 struct http_conn *http;
1308 struct url *url;
1310 base = event_base_new();
1312 if (argc < 2) {
1313 struct evconnlistener *ecs;
1314 struct sockaddr_in sin;
1315 memset(&sin, 0, sizeof(sin));
1316 sin.sin_family=AF_INET;
1317 sin.sin_port = htons(8080);
1318 ecs = evconnlistener_new_bind(base, clientcb, NULL, 0,
1319 LEV_OPT_REUSEABLE, &sin, sizeof(sin));
1320 event_base_dispatch(base);
1321 return 0;
1324 url = url_tokenize(argv[1]);
1325 if (!url)
1326 return 0;
1328 if (url->port < 0)
1329 url->port = 80;
1331 dns = evdns_base_new(base, 1);
1333 http = http_conn_new(base, -1, HTTP_SERVER, &test_proxy_cbs, url);
1334 http_conn_connect(http, dns, AF_UNSPEC, url->host, url->port);
1336 event_base_dispatch(base);
1338 return 0;
1341 #endif