8 #include <event2/util.h>
9 #include <event2/event.h>
10 #include <event2/bufferevent.h>
11 #include <event2/buffer.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};
38 enum http_state state
;
39 enum http_version vers
;
42 enum http_te output_te
;
46 int tunnel_read_paused
;
47 int msg_complete_on_eof
;
52 const struct http_cbs
*cbs
;
54 ev_int64_t body_length
;
55 ev_int64_t data_remaining
;
57 struct header_list
*headers
;
58 struct event_base
*base
;
59 struct bufferevent
*bev
;
60 struct bufferevent
*tunnel_bev
;
61 struct evbuffer
*inbuf_processed
;
65 method_from_string(enum http_method
*m
, const char *method
)
67 if (!evutil_ascii_strcasecmp(method
, "GET"))
69 else if (!evutil_ascii_strcasecmp(method
, "HEAD"))
71 else if (!evutil_ascii_strcasecmp(method
, "POST"))
73 else if (!evutil_ascii_strcasecmp(method
, "PUT"))
75 else if (!evutil_ascii_strcasecmp(method
, "CONNECT"))
78 log_warn("method_from_string: unknown method, '%s'", method
);
86 http_method_to_string(enum http_method m
)
101 log_fatal("http_method_to_string: unknown method %d", m
);
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
);
115 /* XXX this only understands 1.0 and 1.1 */
117 if (!strcmp(vers
, "1.0"))
119 else if (!strcmp(vers
, "1.1"))
122 log_warn("version_from_string: unknown http-version, '%s'",
131 http_version_to_string(enum http_version v
)
142 log_fatal("http_version_to_string: unknown version %d", v
);
147 http_conn_error_to_string(enum http_conn_error err
)
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";
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
);
192 bufferevent_set_timeouts(conn
->bev
, &idle_client_timeout
, NULL
);
196 end_message(struct http_conn
*conn
, enum http_conn_error err
)
199 mem_free(conn
->firstline
);
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
);
214 if (err
!= ERROR_NONE
)
215 EVENT1(conn
, on_error
, err
);
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
;
228 struct url
*u
= NULL
;
231 assert(conn
->type
== HTTP_CLIENT
);
236 ntokens
= tokenize(conn
->firstline
, " ", 4, &tokens
);
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)
248 if (m
== METH_CONNECT
)
249 u
= url_connect_tokenize(url
->token
);
251 u
= url_tokenize(url
->token
);
255 req
= mem_calloc(1, sizeof(*req
));
260 req
->headers
= conn
->headers
;
264 token_list_clear(&tokens
);
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
;
279 assert(conn
->type
== HTTP_SERVER
);
284 ntokens
= tokenize(conn
->firstline
, " ", 2, &tokens
);
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)
296 resp
= mem_calloc(1, sizeof(*resp
));
299 resp
->reason
= reason
->token
;
300 reason
->token
= NULL
; /* so token_list_clear will skip this */
301 resp
->headers
= conn
->headers
;
304 token_list_clear(&tokens
);
309 /* return -1 failure, 0 incomplete, 1 ok */
311 parse_chunk_len(struct http_conn
*conn
)
313 struct evbuffer
*inbuf
= bufferevent_get_input(conn
->bev
);
317 while ((line
= evbuffer_readln(inbuf
, NULL
, EVBUFFER_EOL_CRLF
))) {
323 len
= get_int(line
, 16);
326 log_warn("parse_chunk_len: invalid chunk len");
330 conn
->data_remaining
= len
;
338 read_chunk(struct http_conn
*conn
)
340 struct evbuffer
*inbuf
= bufferevent_get_input(conn
->bev
);
345 while ((len
= evbuffer_get_length(inbuf
)) > 0) {
346 if (conn
->data_remaining
< 0) {
347 ret
= parse_chunk_len(conn
);
351 ERROR_CHUNK_PARSE_FAILED
);
354 } else if (conn
->data_remaining
== 0) {
355 line
= evbuffer_readln(inbuf
, NULL
, EVBUFFER_EOL_CRLF
);
357 /* XXX doesn't handle trailers */
359 end_message(conn
, ERROR_NONE
);
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
,
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;
379 read_body(struct http_conn
*conn
)
381 struct evbuffer
*inbuf
= bufferevent_get_input(conn
->bev
);
384 assert(conn
->has_body
);
386 if (conn
->te
== TE_CHUNKED
) {
391 len
= evbuffer_get_length(inbuf
);
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
,
399 EVENT1(conn
, on_read_body
, conn
->inbuf_processed
);
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
;
420 conn
->te
= TE_IDENTITY
;
422 conn
->msg_complete_on_eof
= 0;
423 conn
->data_remaining
= -1;
424 conn
->body_length
= -1;
425 conn
->expect_continue
= 0;
428 if (conn
->type
== HTTP_CLIENT
) {
431 if (req
->meth
== METH_POST
||
432 req
->meth
== METH_PUT
)
434 else if (req
->meth
== METH_CONNECT
)
437 val
= headers_find(conn
->headers
, "Expect");
441 cont
= !evutil_ascii_strcasecmp(val
, "100-continue");
443 if (cont
== 0 || !conn
->has_body
)
444 return ERROR_CLIENT_EXPECTATION_FAILED
;
446 if (cont
&& req
->vers
!= HTTP_11
) {
448 log_info("http: ignoring expect continue from "
450 headers_remove(conn
->headers
, "Expect");
453 conn
->expect_continue
= cont
;
455 } else { /* server */
457 if ((resp
->code
>= 100 && resp
->code
< 200) ||
458 resp
->code
== 204 || resp
->code
== 205 ||
464 if (conn
->has_body
) {
465 val
= headers_find(conn
->headers
, "transfer-encoding");
467 if (!evutil_ascii_strcasecmp(val
, "chunked"))
468 conn
->te
= TE_CHUNKED
;
472 if (conn
->te
!= TE_CHUNKED
) {
473 val
= headers_find(conn
->headers
, "content-length");
476 iv
= get_int(val
, 10);
478 log_warn("http: mangled "
480 headers_remove(conn
->headers
,
483 conn
->body_length
= iv
;
485 if (conn
->body_length
== 0)
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
);
501 if (!tunnel
&& !conn
->msg_complete_on_eof
&& vers
== HTTP_11
)
504 if (conn
->vers
!= HTTP_UNKNOWN
&& conn
->vers
!= vers
) {
505 log_warn("http_conn: http version changed!");
511 val
= headers_find(conn
->headers
, "connection");
513 if (!evutil_ascii_strcasecmp(val
, "close"))
518 conn
->persistent
= persistent
;
524 read_headers(struct http_conn
*conn
)
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
)) {
536 end_message(conn
, ERROR_HEADER_PARSE_FAILED
);
540 /* case 1: finished, fall thru */
543 assert(conn
->firstline
);
545 if (conn
->type
== HTTP_CLIENT
) {
546 req
= build_request(conn
);
550 resp
= build_response(conn
);
555 mem_free(conn
->firstline
);
556 conn
->firstline
= NULL
;
559 assert(!req
&& !resp
);
560 end_message(conn
, ERROR_HEADER_PARSE_FAILED
);
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 */
572 EVENT1(conn
, on_client_request
, req
);
574 if (resp
->code
== 100) {
575 http_response_free(resp
);
576 EVENT0(conn
, on_server_continuation
);
578 server_continuation
= 1;
580 EVENT1(conn
, on_server_response
, resp
);
583 if (!server_continuation
&&
584 conn
->state
!= HTTP_STATE_TUNNEL_CONNECTING
) {
586 end_message(conn
, ERROR_NONE
);
588 conn
->state
= HTTP_STATE_READ_BODY
;
591 http_request_free(req
);
592 http_response_free(resp
);
593 end_message(conn
, err
);
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)
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;
616 log_debug("tunnel: throttling server read");
617 conn
->tunnel_read_paused
= 1;
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);
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
);
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
);
655 tunnel_transfer_data(conn
, conn
->bev
, bev
);
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
;
670 log_debug("tunnel: server closed conn...");
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
);
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
);
691 log_fatal("tunnel: errorcb called in invalid state!");
696 tunnel_connectcb(struct bufferevent
*bev
, int ok
, void *_conn
)
698 struct http_conn
*conn
= _conn
;
700 assert(conn
->state
== HTTP_STATE_TUNNEL_CONNECTING
);
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
));
715 bufferevent_setcb(conn
->tunnel_bev
, NULL
, NULL
,
717 EVENT1(conn
, on_error
, ERROR_TUNNEL_CONNECT_FAILED
);
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
));
730 conn
->state
= HTTP_STATE_MANGLED
;
732 if (what
& BEV_EVENT_WRITING
) {
733 end_message(conn
, ERROR_WRITE_FAILED
);
738 case HTTP_STATE_IDLE
:
739 end_message(conn
, ERROR_IDLE_CONN_TIMEDOUT
);
741 case HTTP_STATE_READ_FIRSTLINE
:
742 case HTTP_STATE_READ_HEADERS
:
743 end_message(conn
, ERROR_INCOMPLETE_HEADERS
);
745 case HTTP_STATE_READ_BODY
:
746 if ((what
& BEV_EVENT_EOF
) && conn
->msg_complete_on_eof
)
747 end_message(conn
, ERROR_NONE
);
749 end_message(conn
, ERROR_INCOMPLETE_BODY
);
752 log_fatal("http_conn: errorcb called in invalid state");
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
);
766 case HTTP_STATE_READ_FIRSTLINE
:
767 assert(conn
->firstline
== NULL
);
768 conn
->firstline
= evbuffer_readln(inbuf
, NULL
,
771 conn
->state
= HTTP_STATE_READ_HEADERS
;
773 case HTTP_STATE_READ_HEADERS
:
776 case HTTP_STATE_READ_BODY
:
780 log_fatal("http_conn: read cb called in invalid state");
785 process_inbuf(struct http_conn
*conn
)
787 struct evbuffer
*inbuf
= bufferevent_get_input(conn
->bev
);
788 enum http_state state_before
;
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
);
799 http_readcb(struct bufferevent
*bev
, void *_conn
)
801 process_inbuf(_conn
);
805 http_writecb(struct bufferevent
*bev
, void *_conn
)
807 struct http_conn
*conn
= _conn
;
808 struct evbuffer
*outbuf
= bufferevent_get_output(bev
);
811 bufferevent_setwatermark(bev
, EV_WRITE
, 0, 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
);
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
,
831 EVENT0(conn
, on_connect
);
833 conn
->state
= HTTP_STATE_MANGLED
;
834 EVENT1(conn
, on_error
, ERROR_CONNECT_FAILED
);
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
));
850 conn
->bev
= bufferevent_socket_new(base
, sock
,
851 BEV_OPT_CLOSE_ON_FREE
);
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
,
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
);
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
);
891 http_conn_free(struct http_conn
*conn
)
897 http_conn_stop_reading(conn
);
898 bufferevent_disable(conn
->bev
, EV_WRITE
);
899 bufferevent_setcb(conn
->bev
, NULL
, NULL
, NULL
, NULL
);
901 event_base_once(conn
->base
, -1, EV_TIMEOUT
, deferred_free
, conn
, NULL
);
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");
914 outbuf
= bufferevent_get_output(conn
->bev
);
916 evbuffer_add_printf(outbuf
, "%s %s %s\r\n",
917 http_method_to_string(req
->meth
),
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
;
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");
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
),
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);
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
;
1016 http_conn_set_current_message_bodyless(struct http_conn
*conn
)
1018 assert(conn
->type
== HTTP_SERVER
);
1023 http_conn_get_current_message_body_encoding(struct http_conn
*conn
)
1029 http_conn_get_current_message_body_length(struct http_conn
*conn
)
1031 return conn
->body_length
;
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
;
1047 http_conn_disable_persistence(struct http_conn
*conn
)
1049 conn
->persistent
= 0;
1053 http_conn_stop_reading(struct http_conn
*conn
)
1055 bufferevent_disable(conn
->bev
, EV_READ
);
1056 conn
->read_paused
= 1;
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
);
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
);
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
);
1092 http_conn_send_error(struct http_conn
*conn
, int code
, const char *fmt
, ...)
1096 struct evbuffer
*msg
;
1097 struct http_response resp
;
1098 struct header_list headers
;
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
;
1112 evutil_vsnprintf(reason
, sizeof(reason
), fmt
, ap
);
1115 conn
->output_te
= TE_IDENTITY
;
1116 resp
.vers
= HTTP_11
;
1118 resp
.reason
= reason
;
1120 evbuffer_add_printf(msg
,
1123 "<title>%d %s</title>\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
);
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
);
1165 http_request_free(struct http_request
*req
)
1171 headers_clear(req
->headers
);
1176 http_response_free(struct http_response
*resp
)
1181 headers_clear(resp
->headers
);
1182 mem_free(resp
->headers
);
1183 mem_free(resp
->reason
);
1188 #include <netinet/in.h>
1190 #include <event2/dns.h>
1191 #include <event2/listener.h>
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
;
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
);
1211 http_conn_write_request(conn
, &req
);
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
);
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
),
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
);
1237 http_conn_send_error(conn
, 401);
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
),
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
);
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
);
1265 proxy_msg_complete(struct http_conn
*conn
, void *arg
)
1267 fprintf(stderr
, "\n...MSG COMPLETE...\n");
1271 proxy_write_more(struct http_conn
*conn
, void *arg
)
1276 proxy_flush(struct http_conn
*conn
, void *arg
)
1278 fprintf(stderr
, "\n....FLUSHED...\n");
1281 static struct http_cbs test_proxy_cbs
= {
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
;
1310 base
= event_base_new();
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
);
1324 url
= url_tokenize(argv
[1]);
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
);