7 #include <event2/util.h>
8 #include <event2/event.h>
9 #include <event2/bufferevent.h>
10 #include <event2/buffer.h>
17 #define METHOD0(conn, slot) \
18 (conn)->cbs->slot((conn), (conn)->cbarg)
19 #define METHOD1(conn, slot, a) \
20 (conn)->cbs->slot((conn), (a), (conn)->cbarg)
21 #define METHOD2(conn, slot, a, b) \
22 (conn)->cbs->slot((conn), (a), (b), (conn)->cbarg)
23 #define METHOD3(conn, slot, a, b, c) \
24 (conn)->cbs->slot((conn), (a), (b), (c), (conn)->cbarg)
25 #define METHOD4(conn, slot, a, b, c, d) \
26 (conn)->cbs->slot((conn), (a), (b), (c), (d), (conn)->cbarg)
28 /* max amount of data we can have backlogged on outbuf before choaking */
29 static size_t max_write_backlog
= 50 * 1024;
31 /* the number of seconds to keep an idle connections hanging around */
32 static int idle_client_timeout
= 120;
33 static int idle_server_timeout
= 120;
36 enum http_state state
;
37 enum http_version vers
;
43 int msg_complete_on_eof
;
45 const struct http_cbs
*cbs
;
47 ev_int64_t data_remaining
;
49 struct header_list
*headers
;
50 struct bufferevent
*bev
;
51 struct evbuffer
*inbuf_processed
;
55 method_from_string(enum http_method
*m
, const char *method
)
57 if (!evutil_ascii_strcasecmp(method
, "GET"))
59 else if (!evutil_ascii_strcasecmp(method
, "HEAD"))
61 else if (!evutil_ascii_strcasecmp(method
, "POST"))
63 else if (!evutil_ascii_strcasecmp(method
, "PUT"))
65 else if (!evutil_ascii_strcasecmp(method
, "CONNECT"))
68 log_warn("method_from_string: unknown method, '%s'", method
);
76 method_to_string(enum http_method m
)
91 log_fatal("method_to_string: unknown method %d", m
);
96 version_from_string(enum http_version
*v
, const char *vers
)
98 if (evutil_ascii_strncasecmp(vers
, "HTTP/", 5)) {
99 log_warn("version_from_string: bad http-version, '%s'", vers
);
105 /* XXX this only understands 1.0 and 1.1 */
107 if (!strcmp(vers
, "1.0"))
109 else if (!strcmp(vers
, "1.1"))
112 log_warn("version_from_string: unknown http-version, '%s'",
121 version_to_string(enum http_version v
)
132 log_fatal("version_to_string: unknown version %d", v
);
137 error_code_to_reason_string(int code
)
141 return "Bad Request";
143 return "Unauthorized";
149 return "Method Not Allowed";
151 return "Not Acceptable";
153 return "Proxy Authentication Required";
155 return "Request Timeout";
161 return "Length Required";
163 return "Precondition Failed";
165 return "Request Entity Too Large";
167 return "Request-URI Too Long";
169 return "Unsupported Media Type";
171 return "Requested Range Not Satisfiable";
173 return "Expectation Failed";
175 return "There are too many connections from your internet address";
177 return "Internal Server Error";
179 return "Not Implemented";
181 return "Bad Gateway";
183 return "Service Unavailable";
185 return "Gateway Timeout";
187 return "HTTP Version Not Supported";
189 return "User access denied";
196 begin_message(struct http_conn
*conn
)
199 assert(conn
->headers
== NULL
&& conn
->firstline
== NULL
);
200 assert(!conn
->read_paused
);
201 conn
->headers
= mem_calloc(1, sizeof(*conn
->headers
));
202 TAILQ_INIT(conn
->headers
);
203 conn
->state
= HTTP_STATE_IDLE
;
204 bufferevent_enable(conn
->bev
, EV_WRITE
| EV_READ
);
208 end_message(struct http_conn
*conn
, enum http_conn_error err
)
211 mem_free(conn
->firstline
);
213 headers_clear(conn
->headers
);
215 if (err
!= ERROR_NONE
|| !conn
->persistent
) {
216 conn
->state
= HTTP_STATE_MANGLED
;
217 bufferevent_disable(conn
->bev
, EV_WRITE
| EV_READ
);
221 if (err
!= ERROR_NONE
)
222 METHOD1(conn
, on_error
, err
);
224 METHOD0(conn
, on_msg_complete
);
227 static struct http_request
*
228 build_request(struct http_conn
*conn
)
230 struct http_request
*req
;
231 struct token_list tokens
;
232 struct token
*method
, *url
, *vers
;
235 struct url
*u
= NULL
;
238 assert(conn
->type
== HTTP_CLIENT
);
243 ntokens
= tokenize(conn
->firstline
, " ", 4, &tokens
);
247 method
= TAILQ_FIRST(&tokens
);
248 url
= TAILQ_NEXT(method
, next
);
249 vers
= TAILQ_NEXT(url
, next
);
250 u
= url_tokenize(url
->token
);
252 if (!u
|| method_from_string(&m
, method
->token
) < 0 ||
253 version_from_string(&v
, vers
->token
) < 0)
256 req
= mem_calloc(1, sizeof(*req
));
261 req
->headers
= conn
->headers
;
265 token_list_clear(&tokens
);
270 static struct http_response
*
271 build_response(struct http_conn
*conn
)
273 struct http_response
*resp
;
274 struct token_list tokens
;
275 struct token
*vers
, *code
, *reason
;
280 assert(conn
->type
== HTTP_SERVER
);
285 ntokens
= tokenize(conn
->firstline
, " ", 2, &tokens
);
289 vers
= TAILQ_FIRST(&tokens
);
290 code
= TAILQ_NEXT(vers
, next
);
291 reason
= TAILQ_NEXT(code
, next
);
292 c
= atoi(code
->token
);
294 if (version_from_string(&v
, vers
->token
) < 0 || c
< 100 || c
> 999)
297 resp
= mem_calloc(1, sizeof(*resp
));
300 resp
->reason
= reason
->token
;
301 reason
->token
= NULL
; /* so token_list_clear will skip this */
302 resp
->headers
= conn
->headers
;
305 token_list_clear(&tokens
);
310 /* return -1 failure, 0 incomplete, 1 ok */
312 parse_chunk_len(struct http_conn
*conn
)
314 struct evbuffer
*inbuf
= bufferevent_get_input(conn
->bev
);
318 while ((line
= evbuffer_readln(inbuf
, NULL
, EVBUFFER_EOL_CRLF
))) {
324 len
= get_int(line
, 16);
327 log_warn("parse_chunk_len: invalid chunk len");
331 conn
->data_remaining
= len
;
339 read_chunk(struct http_conn
*conn
)
341 struct evbuffer
*inbuf
= bufferevent_get_input(conn
->bev
);
342 size_t len
= evbuffer_get_length(inbuf
);
345 if (conn
->data_remaining
< 0) {
346 if (parse_chunk_len(conn
) < 0)
347 end_message(conn
, ERROR_CHUNK_PARSE_FAILED
);
348 } else if (conn
->data_remaining
== 0) {
349 line
= evbuffer_readln(inbuf
, NULL
, EVBUFFER_EOL_CRLF
);
351 /* XXX doesn't handle trailers */
353 log_warn("http_conn: garbage after last chunk");
355 end_message(conn
, ERROR_NONE
);
359 /* XXX should mind potential overflow */
360 if (len
>= (size_t)conn
->data_remaining
)
361 len
= (size_t)conn
->data_remaining
;
363 evbuffer_remove_buffer(inbuf
, conn
->inbuf_processed
, len
);
364 METHOD1(conn
, on_read_body
, conn
->inbuf_processed
);
365 conn
->data_remaining
-= len
;
367 if (conn
->data_remaining
== 0)
368 conn
->data_remaining
= -1;
373 read_body(struct http_conn
*conn
)
375 struct evbuffer
*inbuf
= bufferevent_get_input(conn
->bev
);
378 assert(conn
->has_body
);
380 if (conn
->te
== TE_CHUNKED
) {
385 len
= evbuffer_get_length(inbuf
);
387 /* XXX should mind potential overflow */
388 if (conn
->data_remaining
>= 0 &&
389 len
> (size_t)conn
->data_remaining
) {
390 len
= (size_t)conn
->data_remaining
;
391 evbuffer_remove_buffer(inbuf
, conn
->inbuf_processed
, len
);
392 METHOD1(conn
, on_read_body
, conn
->inbuf_processed
);
394 evbuffer_add_buffer(conn
->inbuf_processed
, inbuf
);
395 METHOD1(conn
, on_read_body
, conn
->inbuf_processed
);
398 conn
->data_remaining
-= len
;
399 if (conn
->data_remaining
== 0)
400 end_message(conn
, ERROR_NONE
);
405 check_headers(struct http_conn
*conn
, struct http_request
*req
,
406 struct http_response
*resp
)
408 enum http_version vers
;
412 conn
->te
= TE_IDENTITY
;
414 conn
->msg_complete_on_eof
= 0;
415 conn
->data_remaining
= -1;
417 if (conn
->type
== HTTP_CLIENT
) {
420 if (req
->meth
== METH_POST
||
421 req
->meth
== METH_PUT
)
423 } else { /* server */
425 if ((resp
->code
>= 100 && resp
->code
< 200) ||
426 resp
->code
== 204 || resp
->code
== 205 ||
432 if (conn
->has_body
) {
433 val
= headers_find(conn
->headers
, "transfer-encoding");
435 if (!evutil_ascii_strcasecmp(val
, "chunked"))
436 conn
->te
= TE_CHUNKED
;
440 if (conn
->te
!= TE_CHUNKED
) {
441 val
= headers_find(conn
->headers
, "content-length");
444 iv
= get_int(val
, 10);
446 log_warn("http_conn: mangled Content-Length");
448 conn
->data_remaining
= iv
;
450 if (conn
->data_remaining
== 0)
453 conn
->msg_complete_on_eof
= 1;
457 if (conn
->type
== HTTP_CLIENT
&& conn
->data_remaining
< 0 &&
458 conn
->te
!= TE_CHUNKED
) {
459 METHOD1(conn
, on_error
,
460 ERROR_CLIENT_POST_WITHOUT_LENGTH
);
465 assert(vers
!= HTTP_UNKNOWN
);
468 if (!conn
->msg_complete_on_eof
&& vers
== HTTP_11
)
471 if (conn
->vers
!= HTTP_UNKNOWN
&& conn
->vers
!= vers
) {
472 log_warn("http_conn: http version changed!");
478 val
= headers_find(conn
->headers
, "connection");
480 if (evutil_ascii_strcasecmp(val
, "close"))
485 conn
->persistent
= persistent
;
494 read_headers(struct http_conn
*conn
)
497 struct evbuffer
*inbuf
= bufferevent_get_input(conn
->bev
);
498 struct http_request
*req
= NULL
;
499 struct http_response
*resp
= NULL
;
501 assert(conn
->state
== HTTP_STATE_READ_HEADERS
);
503 switch (headers_load(conn
->headers
, inbuf
)) {
505 end_message(conn
, ERROR_HEADER_PARSE_FAILED
);
509 /* case 1: finished, fall thru */
512 assert(conn
->firstline
);
514 if (conn
->type
== HTTP_CLIENT
) {
515 req
= build_request(conn
);
519 resp
= build_response(conn
);
524 mem_free(conn
->firstline
);
525 conn
->firstline
= NULL
;
528 assert(!req
&& !resp
);
529 end_message(conn
, ERROR_HEADER_PARSE_FAILED
);
533 check_headers(conn
, req
, resp
);
534 conn
->headers
= NULL
;
536 /* ownership of req or resp is now passed on */
538 METHOD1(conn
, on_client_request
, req
);
540 METHOD1(conn
, on_server_response
, resp
);
543 end_message(conn
, ERROR_NONE
);
545 conn
->state
= HTTP_STATE_READ_BODY
;
549 http_errorcb(struct bufferevent
*bev
, short what
, void *_conn
)
551 enum http_state state
;
552 struct http_conn
*conn
= _conn
;
554 if (conn
->state
== HTTP_STATE_CONNECTING
) {
555 if (what
& BEV_EVENT_CONNECTED
) {
557 METHOD0(conn
, on_connect
);
559 conn
->state
= HTTP_STATE_MANGLED
;
560 METHOD1(conn
, on_error
, ERROR_CONNECT_FAILED
);
565 assert(!(what
& BEV_EVENT_CONNECTED
));
568 conn
->state
= HTTP_STATE_MANGLED
;
570 if (what
& BEV_EVENT_WRITING
) {
571 end_message(conn
, ERROR_WRITE_FAILED
);
576 case HTTP_STATE_IDLE
:
577 end_message(conn
, ERROR_IDLE_CONN_TIMEDOUT
);
579 case HTTP_STATE_READ_FIRSTLINE
:
580 case HTTP_STATE_READ_HEADERS
:
581 end_message(conn
, ERROR_INCOMPLETE_HEADERS
);
583 case HTTP_STATE_READ_BODY
:
584 if ((what
& BEV_EVENT_EOF
) && conn
->msg_complete_on_eof
)
585 end_message(conn
, ERROR_NONE
);
587 end_message(conn
, ERROR_INCOMPLETE_BODY
);
590 log_fatal("http_conn: errorcb called in invalid state");
595 process_one_message(struct http_conn
*conn
)
597 struct evbuffer
*inbuf
= bufferevent_get_input(conn
->bev
);
599 switch (conn
->state
) {
600 case HTTP_STATE_IDLE
:
601 conn
->state
= HTTP_STATE_READ_FIRSTLINE
;
602 // XXX should remove idle timeout at this point?
604 case HTTP_STATE_READ_FIRSTLINE
:
605 assert(conn
->firstline
== NULL
);
606 conn
->firstline
= evbuffer_readln(inbuf
, NULL
, EVBUFFER_EOL_CRLF
);
608 conn
->state
= HTTP_STATE_READ_HEADERS
;
610 case HTTP_STATE_READ_HEADERS
:
613 case HTTP_STATE_READ_BODY
:
617 log_fatal("http_conn: read cb called in invalid state");
622 process_inbuf(struct http_conn
*conn
)
624 struct evbuffer
*inbuf
= bufferevent_get_input(conn
->bev
);
627 process_one_message(conn
);
628 } while (!conn
->read_paused
&&
629 evbuffer_get_length(inbuf
) > 0);
633 http_readcb(struct bufferevent
*bev
, void *_conn
)
635 process_inbuf(_conn
);
639 http_writecb(struct bufferevent
*bev
, void *_conn
)
641 struct http_conn
*conn
= _conn
;
642 struct evbuffer
*outbuf
= bufferevent_get_output(bev
);
644 if (conn
->is_choaked
) {
645 bufferevent_setwatermark(bev
, EV_WRITE
, 0, 0);
646 conn
->is_choaked
= 0;
647 METHOD0(conn
, on_write_more
);
648 } else if (evbuffer_get_length(outbuf
) == 0)
649 METHOD0(conn
, on_flush
);
653 http_conn_new(struct event_base
*base
, evutil_socket_t sock
,
654 enum http_type type
, const struct http_cbs
*cbs
, void *cbarg
)
656 struct http_conn
*conn
;
658 conn
= mem_calloc(1, sizeof(*conn
));
662 conn
->bev
= bufferevent_socket_new(base
, sock
,
663 BEV_OPT_CLOSE_ON_FREE
);
665 log_fatal("http_conn: failed to create bufferevent");
667 conn
->inbuf_processed
= evbuffer_new();
668 if (!conn
->inbuf_processed
)
669 log_fatal("http_conn: failed to create evbuffer");
671 bufferevent_setcb(conn
->bev
, http_readcb
, http_writecb
,
681 http_conn_connect(struct http_conn
*conn
, struct evdns_base
*dns
,
682 int family
, const char *host
, int port
)
685 conn
->state
= HTTP_STATE_CONNECTING
;
686 return bufferevent_socket_connect_hostname(conn
->bev
, dns
, family
,
691 http_conn_free(struct http_conn
*conn
)
693 bufferevent_free(conn
->bev
);
694 evbuffer_free(conn
->inbuf_processed
);
699 http_conn_write_request(struct http_conn
*conn
, struct http_request
*req
)
701 struct evbuffer
*outbuf
;
703 assert(conn
->type
== HTTP_SERVER
);
705 headers_remove(req
->headers
, "connection");
707 conn
->output_te
= req
->te
;
710 outbuf
= bufferevent_get_output(conn
->bev
);
712 evbuffer_add_printf(outbuf
, "%s %s %s\r\n",
713 method_to_string(req
->meth
),
715 version_to_string(req
->vers
));
717 headers_dump(req
->headers
, outbuf
);
721 http_conn_write_response(struct http_conn
*conn
, struct http_response
*resp
)
723 struct evbuffer
*outbuf
;
725 assert(conn
->type
== HTTP_CLIENT
);
726 assert(conn
->vers
!= HTTP_UNKNOWN
);
728 headers_remove(req
->headers
, "connection");
729 resp
->vers
= conn
->vers
;
731 conn
->output_te
= resp
->te
;
732 if (conn
->vers
== HTTP_10
) {
733 conn
->output_te
= TE_IDENTITY
;
734 headers_remove(req
->headers
, "transfer-encoding");
735 headers_add_key_val(req
->headers
, "Connection", "close");
738 outbuf
= bufferevent_get_output(conn
->bev
);
740 evbuffer_add_printf(outbuf
, "%s %d %s\r\n",
741 version_to_string(conn
->vers
),
745 headers_dump(resp
->headers
, outbuf
);
749 http_conn_write_buf(struct http_conn
*conn
, struct evbuffer
*buf
)
751 struct evbuffer
*outbuf
;
753 outbuf
= bufferevent_get_output(conn
->bev
);
755 if (conn
->output_te
== TE_CHUNKED
)
756 evbuffer_add_printf("%x\r\n",
757 (unsigned)evbuffer_get_length(outbuf
));
758 evbuffer_add_buffer(outbuf
, buf
);
759 if (conn
->output_te
== TE_CHUNKED
)
760 evbuffer_add(outbuf
, "\r\n", 2);
762 /* have we choaked? */
763 if (evbuffer_get_length(outbuf
) > max_write_backlog
) {
764 bufferevent_setwatermark(conn
->bev
, EV_WRITE
,
765 max_write_backlog
/ 2, 0);
766 conn
->is_choaked
= 1;
774 http_conn_write_finished(struct http_conn
*conn
)
776 if (conn
->output_te
== TE_CHUNKED
)
777 bufferevent_write(conn
->bev
, "0\r\n\r\n", 5);
778 conn
->output_te
= TE_IDENTITY
;
783 http_conn_current_message_has_body(struct http_conn
*conn
)
785 return conn
->has_body
;
789 http_conn_set_current_message_bodyless(struct http_conn
*conn
)
791 assert(conn
->type
== HTTP_SERVER
);
796 http_conn_is_persistent(struct http_conn
*conn
)
798 return conn
->persistent
;
802 http_conn_stop_reading(struct http_conn
*conn
)
804 bufferevent_disable(conn
->bev
, EV_READ
);
805 conn
->read_paused
= 1;
809 http_conn_start_reading(struct http_conn
*conn
)
811 struct evbuffer
*inbuf
= bufferevent_get_input(conn
->bev
);
813 bufferevent_enable(conn
->bev
, EV_READ
);
814 conn
->read_paused
= 0;
815 // XXX this might cause recursion
816 if (evbuffer_get_length(inbuf
) > 0)
821 http_conn_flush(struct http_conn
*conn
)
823 struct evbuffer
*outbuf
= bufferevent_get_outbuf(conn
->bev
);
825 // XXX this might cause recursion
826 if (evbuffer_get_length(outbuf
) == 0)
827 METHOD0(conn
, on_flush
);
830 // XXX this should support more descriptive messages
832 http_conn_send_error(struct http_conn
*conn
, int code
)
835 struct evbuffer
*msg
;
836 struct http_response resp
;
837 struct header_list headers
;
839 assert(conn
->type
== HTTP_CLIENT
);
842 msg
= evbuffer_new();
843 resp
.headers
= &headers
;
845 resp
.te
= TE_IDENTITY
;
848 resp
.reason
= code_to_reason_string(code
);
853 "<title>%s</title>\n"
859 resp
.reason
, code
, resp
.reason
);
861 evutil_snprintf(length
, sizeof(length
), "%u",
862 (unsigned)evbuffer_get_length(msg
));
863 headers_add_key_val(&headers
, "Content-Type", "text/html");
864 headers_add_key_val(&headers
, "Content-Length", length
);
866 http_conn_write_response(conn
, &resp
);
867 http_conn_write_buf(conn
, msg
);
868 headers_clear(&headers
);
873 http_request_free(struct http_request
*req
)
876 headers_clear(req
->headers
);
881 http_response_free(struct http_response
*resp
)
883 headers_clear(resp
->headers
);
884 mem_free(resp
->headers
);
885 mem_free(resp
->reason
);
890 #include <netinet/in.h>
892 #include <event2/dns.h>
895 proxy_connected(struct http_conn
*conn
, void *arg
)
897 struct http_request req
;
898 struct header_list headers
;
899 struct evbuffer
*buf
;
901 TAILQ_INIT(&headers
);
905 req
.headers
= &headers
;
907 buf
= evbuffer_new();
908 evbuffer_add_printf(buf
, "Host: %s\r\n\r\n", req
.url
->host
);
909 headers_load(&headers
, buf
);
912 http_conn_write_request(conn
, &req
);
916 proxy_error(struct http_conn
*conn
, enum http_conn_error err
, void *arg
)
918 fprintf(stderr
, "error %d\n", err
);
919 http_conn_free(conn
);
923 proxy_response(struct http_conn
*conn
, struct http_response
*resp
, void *arg
)
925 struct evbuffer
*buf
;
927 fprintf(stderr
, "response: %s, %d, %s\n",
928 version_to_string(resp
->vers
),
932 buf
= evbuffer_new();
933 headers_dump(resp
->headers
, buf
);
934 fwrite(evbuffer_pullup(buf
, evbuffer_get_length(buf
)), evbuffer_get_length(buf
), 1, stderr
);
939 proxy_read_body(struct http_conn
*conn
, struct evbuffer
*buf
, void *arg
)
941 size_t len
= evbuffer_get_length(buf
);
942 fwrite(evbuffer_pullup(buf
, len
), len
, 1, stderr
);
943 evbuffer_drain(buf
, len
);
947 proxy_msg_complete(struct http_conn
*conn
, void *arg
)
949 fprintf(stderr
, "\n...MSG COMPLETE...\n");
953 proxy_write_more(struct http_conn
*conn
, void *arg
)
957 static struct http_cbs test_proxy_cbs
= {
968 main(int argc
, char **argv
)
970 struct event_base
*base
;
971 struct evdns_base
*dns
;
972 struct http_conn
*http
;
975 url
= url_tokenize(argv
[1]);
982 base
= event_base_new();
983 dns
= evdns_base_new(base
, 1);
985 http
= http_conn_new(base
, -1, HTTP_SERVER
, &test_proxy_cbs
, url
);
986 http_conn_connect(http
, dns
, AF_UNSPEC
, url
->host
, url
->port
);
988 event_base_dispatch(base
);