1 #include "netheaders.h"
9 #include <event2/util.h>
10 #include <event2/event.h>
11 #include <event2/bufferevent.h>
12 #include <event2/buffer.h>
20 #define EVENT0(conn, slot) \
21 (conn)->cbs->slot((conn), (conn)->cbarg)
22 #define EVENT1(conn, slot, a) \
23 (conn)->cbs->slot((conn), (a), (conn)->cbarg)
24 #define EVENT2(conn, slot, a, b) \
25 (conn)->cbs->slot((conn), (a), (b), (conn)->cbarg)
26 #define EVENT3(conn, slot, a, b, c) \
27 (conn)->cbs->slot((conn), (a), (b), (c), (conn)->cbarg)
28 #define EVENT4(conn, slot, a, b, c, d) \
29 (conn)->cbs->slot((conn), (a), (b), (c), (d), (conn)->cbarg)
31 /* max amount of data we can have backlogged on outbuf before choaking */
32 static size_t max_write_backlog
= 50 * 1024;
34 /* the number of seconds to keep an idle connections hanging around */
35 static struct timeval idle_client_timeout
= {120, 0};
36 static struct timeval idle_server_timeout
= {120, 0};
39 enum http_state state
;
40 enum http_version vers
;
43 enum http_te output_te
;
47 int tunnel_read_paused
;
48 int msg_complete_on_eof
;
53 const struct http_cbs
*cbs
;
55 ev_int64_t body_length
;
56 ev_int64_t data_remaining
;
58 struct header_list
*headers
;
59 struct event_base
*base
;
60 struct bufferevent
*bev
;
61 struct bufferevent
*tunnel_bev
;
62 struct evbuffer
*inbuf_processed
;
66 method_from_string(enum http_method
*m
, const char *method
)
68 if (!evutil_ascii_strcasecmp(method
, "GET"))
70 else if (!evutil_ascii_strcasecmp(method
, "HEAD"))
72 else if (!evutil_ascii_strcasecmp(method
, "POST"))
74 else if (!evutil_ascii_strcasecmp(method
, "PUT"))
76 else if (!evutil_ascii_strcasecmp(method
, "CONNECT"))
79 log_warn("method_from_string: unknown method, '%s'", method
);
87 http_method_to_string(enum http_method m
)
102 log_fatal("http_method_to_string: unknown method %d", m
);
107 version_from_string(enum http_version
*v
, const char *vers
)
109 if (evutil_ascii_strncasecmp(vers
, "HTTP/", 5)) {
110 log_warn("version_from_string: bad http-version, '%s'", vers
);
116 /* XXX this only understands 1.0 and 1.1 */
118 if (!strcmp(vers
, "1.0"))
120 else if (!strcmp(vers
, "1.1"))
123 log_warn("version_from_string: unknown http-version, '%s'",
132 http_version_to_string(enum http_version v
)
143 log_fatal("http_version_to_string: unknown version %d", v
);
148 http_conn_error_to_string(enum http_conn_error err
)
153 case ERROR_CONNECT_FAILED
:
154 return "Connection failed";
155 case ERROR_IDLE_CONN_TIMEDOUT
:
156 return "Idle connection timed out";
157 case ERROR_CLIENT_EXPECTATION_FAILED
:
158 return "Can't statisfy client's expectation";
159 case ERROR_CLIENT_POST_WITHOUT_LENGTH
:
160 return "Client post with unknown length";
161 case ERROR_INCOMPLETE_HEADERS
:
162 return "Connection terminated while reading headers";
163 case ERROR_INCOMPLETE_BODY
:
164 return "Connection terminated prematurely while reading body";
165 case ERROR_HEADER_PARSE_FAILED
:
166 return "Invalid client request";
167 case ERROR_CHUNK_PARSE_FAILED
:
168 return "Invalid chunked data";
169 case ERROR_WRITE_FAILED
:
170 return "Write failed";
171 case ERROR_TUNNEL_CONNECT_FAILED
:
172 return "Tunnel connection failed";
173 case ERROR_TUNNEL_CLOSED
:
174 return "Tunnel closed";
181 begin_message(struct http_conn
*conn
)
183 assert(conn
->headers
== NULL
&& conn
->firstline
== NULL
);
184 conn
->headers
= mem_calloc(1, sizeof(*conn
->headers
));
185 TAILQ_INIT(conn
->headers
);
186 conn
->state
= HTTP_STATE_IDLE
;
187 if (!conn
->read_paused
)
188 bufferevent_enable(conn
->bev
, EV_READ
);
189 // XXX we should have a separate function to tell that server is idle.
190 if (conn
->type
== HTTP_SERVER
)
191 bufferevent_set_timeouts(conn
->bev
, &idle_server_timeout
, NULL
);
193 bufferevent_set_timeouts(conn
->bev
, &idle_client_timeout
, NULL
);
197 end_message(struct http_conn
*conn
, enum http_conn_error err
)
200 mem_free(conn
->firstline
);
202 headers_clear(conn
->headers
);
203 mem_free(conn
->headers
);
206 conn
->firstline
= NULL
;
207 conn
->headers
= NULL
;
209 if (err
!= ERROR_NONE
|| !conn
->persistent
) {
210 conn
->state
= HTTP_STATE_MANGLED
;
211 http_conn_stop_reading(conn
);
215 if (err
!= ERROR_NONE
)
216 EVENT1(conn
, on_error
, err
);
218 EVENT0(conn
, on_msg_complete
);
221 static struct http_request
*
222 build_request(struct http_conn
*conn
)
224 struct http_request
*req
;
225 struct token_list tokens
;
226 struct token
*method
, *url
, *vers
;
229 struct url
*u
= NULL
;
232 assert(conn
->type
== HTTP_CLIENT
);
237 ntokens
= tokenize(conn
->firstline
, " ", 4, &tokens
);
241 method
= TAILQ_FIRST(&tokens
);
242 url
= TAILQ_NEXT(method
, next
);
243 vers
= TAILQ_NEXT(url
, next
);
245 if (method_from_string(&m
, method
->token
) < 0 ||
246 version_from_string(&v
, vers
->token
) < 0)
249 if (m
== METH_CONNECT
)
250 u
= url_connect_tokenize(url
->token
);
252 u
= url_tokenize(url
->token
);
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
);
346 while ((len
= evbuffer_get_length(inbuf
)) > 0) {
347 if (conn
->data_remaining
< 0) {
348 ret
= parse_chunk_len(conn
);
352 ERROR_CHUNK_PARSE_FAILED
);
355 } else if (conn
->data_remaining
== 0) {
356 line
= evbuffer_readln(inbuf
, NULL
, EVBUFFER_EOL_CRLF
);
358 /* XXX doesn't handle trailers */
360 end_message(conn
, ERROR_NONE
);
364 /* XXX should mind potential overflow */
365 if (len
>= (size_t)conn
->data_remaining
)
366 len
= (size_t)conn
->data_remaining
;
368 evbuffer_remove_buffer(inbuf
, conn
->inbuf_processed
,
370 EVENT1(conn
, on_read_body
, conn
->inbuf_processed
);
371 conn
->data_remaining
-= len
;
373 if (conn
->data_remaining
== 0)
374 conn
->data_remaining
= -1;
380 read_body(struct http_conn
*conn
)
382 struct evbuffer
*inbuf
= bufferevent_get_input(conn
->bev
);
385 assert(conn
->has_body
);
387 if (conn
->te
== TE_CHUNKED
) {
392 len
= evbuffer_get_length(inbuf
);
394 /* XXX should mind potential overflow */
395 if (conn
->data_remaining
>= 0 &&
396 len
> (size_t)conn
->data_remaining
) {
397 len
= (size_t)conn
->data_remaining
;
398 evbuffer_remove_buffer(inbuf
, conn
->inbuf_processed
,
400 EVENT1(conn
, on_read_body
, conn
->inbuf_processed
);
402 evbuffer_add_buffer(conn
->inbuf_processed
, inbuf
);
403 EVENT1(conn
, on_read_body
, conn
->inbuf_processed
);
406 conn
->data_remaining
-= len
;
407 if (conn
->data_remaining
== 0)
408 end_message(conn
, ERROR_NONE
);
412 static enum http_conn_error
413 check_headers(struct http_conn
*conn
, struct http_request
*req
,
414 struct http_response
*resp
)
416 enum http_version vers
;
421 conn
->te
= TE_IDENTITY
;
423 conn
->msg_complete_on_eof
= 0;
424 conn
->data_remaining
= -1;
425 conn
->body_length
= -1;
426 conn
->expect_continue
= 0;
429 if (conn
->type
== HTTP_CLIENT
) {
432 if (req
->meth
== METH_POST
||
433 req
->meth
== METH_PUT
)
435 else if (req
->meth
== METH_CONNECT
)
438 val
= headers_find(conn
->headers
, "Expect");
442 cont
= !evutil_ascii_strcasecmp(val
, "100-continue");
444 if (cont
== 0 || !conn
->has_body
)
445 return ERROR_CLIENT_EXPECTATION_FAILED
;
447 if (cont
&& req
->vers
!= HTTP_11
) {
449 log_info("http: ignoring expect continue from "
451 headers_remove(conn
->headers
, "Expect");
454 conn
->expect_continue
= cont
;
456 } else { /* server */
458 if ((resp
->code
>= 100 && resp
->code
< 200) ||
459 resp
->code
== 204 || resp
->code
== 205 ||
465 if (conn
->has_body
) {
466 val
= headers_find(conn
->headers
, "transfer-encoding");
468 if (!evutil_ascii_strcasecmp(val
, "chunked"))
469 conn
->te
= TE_CHUNKED
;
473 if (conn
->te
!= TE_CHUNKED
) {
474 val
= headers_find(conn
->headers
, "content-length");
477 iv
= get_int(val
, 10);
479 log_warn("http: mangled "
481 headers_remove(conn
->headers
,
484 conn
->body_length
= iv
;
486 if (conn
->body_length
== 0)
489 conn
->msg_complete_on_eof
= 1;
493 if (conn
->type
== HTTP_CLIENT
&& conn
->body_length
< 0 &&
494 conn
->te
!= TE_CHUNKED
)
495 return ERROR_CLIENT_POST_WITHOUT_LENGTH
;
497 conn
->data_remaining
= conn
->body_length
;
499 assert(vers
!= HTTP_UNKNOWN
);
502 if (!tunnel
&& !conn
->msg_complete_on_eof
&& vers
== HTTP_11
)
505 if (conn
->vers
!= HTTP_UNKNOWN
&& conn
->vers
!= vers
) {
506 log_warn("http_conn: http version changed!");
512 val
= headers_find(conn
->headers
, "connection");
514 if (!evutil_ascii_strcasecmp(val
, "close"))
519 conn
->persistent
= persistent
;
525 read_headers(struct http_conn
*conn
)
528 struct evbuffer
*inbuf
= bufferevent_get_input(conn
->bev
);
529 struct http_request
*req
= NULL
;
530 struct http_response
*resp
= NULL
;
531 enum http_conn_error err
;
533 assert(conn
->state
== HTTP_STATE_READ_HEADERS
);
535 switch (headers_load(conn
->headers
, inbuf
)) {
537 end_message(conn
, ERROR_HEADER_PARSE_FAILED
);
541 /* case 1: finished, fall thru */
544 assert(conn
->firstline
);
546 if (conn
->type
== HTTP_CLIENT
) {
547 req
= build_request(conn
);
551 resp
= build_response(conn
);
556 mem_free(conn
->firstline
);
557 conn
->firstline
= NULL
;
560 assert(!req
&& !resp
);
561 end_message(conn
, ERROR_HEADER_PARSE_FAILED
);
565 err
= check_headers(conn
, req
, resp
);
566 conn
->headers
= NULL
;
568 if (err
== ERROR_NONE
) {
569 int server_continuation
= 0;
571 /* ownership of req or resp is now passed on */
573 EVENT1(conn
, on_client_request
, req
);
575 if (resp
->code
== 100) {
576 http_response_free(resp
);
577 EVENT0(conn
, on_server_continuation
);
579 server_continuation
= 1;
581 EVENT1(conn
, on_server_response
, resp
);
584 if (!server_continuation
&&
585 conn
->state
!= HTTP_STATE_TUNNEL_CONNECTING
) {
587 end_message(conn
, ERROR_NONE
);
589 conn
->state
= HTTP_STATE_READ_BODY
;
592 http_request_free(req
);
593 http_response_free(resp
);
594 end_message(conn
, err
);
599 tunnel_transfer_data(struct http_conn
*conn
, struct bufferevent
*to
,
600 struct bufferevent
*from
)
602 struct evbuffer
*frombuf
= bufferevent_get_input(from
);
603 struct evbuffer
*tobuf
= bufferevent_get_output(to
);
605 if (evbuffer_get_length(frombuf
) == 0)
608 evbuffer_add_buffer(tobuf
, frombuf
);
609 if (evbuffer_get_length(tobuf
) > max_write_backlog
) {
610 bufferevent_setwatermark(to
, EV_WRITE
,
611 max_write_backlog
/ 2, 0);
612 bufferevent_disable(from
, EV_READ
);
613 if (from
== conn
->bev
) {
614 log_debug("tunnel: throttling client read");
615 conn
->read_paused
= 1;
617 log_debug("tunnel: throttling server read");
618 conn
->tunnel_read_paused
= 1;
624 tunnel_writecb(struct bufferevent
*bev
, void *_conn
)
626 struct http_conn
*conn
= _conn
;
628 if (conn
->state
== HTTP_STATE_TUNNEL_OPEN
) {
629 if (conn
->tunnel_read_paused
&& bev
== conn
->bev
) {
630 log_debug("tunnel: unthrottling server read");
631 conn
->tunnel_read_paused
= 0;
632 bufferevent_enable(conn
->tunnel_bev
, EV_READ
);
633 bufferevent_setwatermark(bev
, EV_WRITE
, 0, 0);
634 } else if (conn
->read_paused
&& bev
== conn
->tunnel_bev
) {
635 log_debug("tunnel: unthrottling client read");
636 conn
->read_paused
= 0;
637 bufferevent_enable(conn
->bev
, EV_READ
);
638 bufferevent_setwatermark(bev
, EV_WRITE
, 0, 0);
641 log_debug("tunnel: flushed!");
642 bufferevent_setcb(conn
->bev
, NULL
, NULL
, NULL
, NULL
);
643 bufferevent_setcb(conn
->tunnel_bev
, NULL
, NULL
, NULL
, NULL
);
644 EVENT1(conn
, on_error
, ERROR_TUNNEL_CLOSED
);
649 tunnel_readcb(struct bufferevent
*bev
, void *_conn
)
651 struct http_conn
*conn
= _conn
;
653 if (bev
== conn
->bev
)
654 tunnel_transfer_data(conn
, conn
->tunnel_bev
, bev
);
656 tunnel_transfer_data(conn
, conn
->bev
, bev
);
660 tunnel_errorcb(struct bufferevent
*bev
, short what
, void *_conn
)
662 struct http_conn
*conn
= _conn
;
663 struct evbuffer
*buf
;
665 switch (conn
->state
) {
666 case HTTP_STATE_TUNNEL_OPEN
:
667 if (bev
== conn
->bev
) {
668 log_debug("tunnel: client closed conn...");
669 bev
= conn
->tunnel_bev
;
671 log_debug("tunnel: server closed conn...");
674 buf
= bufferevent_get_output(bev
);
675 if (evbuffer_get_length(buf
)) {
676 conn
->state
= HTTP_STATE_TUNNEL_FLUSHING
;
677 log_debug("tunnel: flushing %lu bytes...",
678 (unsigned long)evbuffer_get_length(buf
));
679 bufferevent_disable(bev
, EV_READ
);
680 bufferevent_setcb(bev
, NULL
, tunnel_writecb
,
681 tunnel_errorcb
, conn
);
684 /* nothing left to write.. lets just fall thru... */
685 case HTTP_STATE_TUNNEL_FLUSHING
:
686 /* an error happend while flushing, lets just give up. */
687 bufferevent_setcb(conn
->bev
, NULL
, NULL
, NULL
, NULL
);
688 bufferevent_setcb(conn
->tunnel_bev
, NULL
, NULL
, NULL
, NULL
);
689 EVENT1(conn
, on_error
, ERROR_TUNNEL_CLOSED
);
692 log_fatal("tunnel: errorcb called in invalid state!");
697 tunnel_connectcb(struct bufferevent
*bev
, int ok
, void *_conn
)
699 struct http_conn
*conn
= _conn
;
701 assert(conn
->state
== HTTP_STATE_TUNNEL_CONNECTING
);
704 conn
->state
= HTTP_STATE_TUNNEL_OPEN
;
705 bufferevent_setcb(conn
->tunnel_bev
, tunnel_readcb
,
706 tunnel_writecb
, tunnel_errorcb
, conn
);
707 bufferevent_enable(conn
->bev
, EV_READ
);
708 bufferevent_enable(conn
->tunnel_bev
, EV_READ
);
709 conn
->read_paused
= 0;
710 conn
->tunnel_read_paused
= 0;
711 tunnel_transfer_data(conn
, conn
->tunnel_bev
, conn
->bev
);
712 evbuffer_add_printf(bufferevent_get_output(conn
->bev
),
713 "%s 200 Connection established\r\n\r\n",
714 http_version_to_string(conn
->vers
));
716 bufferevent_setcb(conn
->tunnel_bev
, NULL
, NULL
,
718 EVENT1(conn
, on_error
, ERROR_TUNNEL_CONNECT_FAILED
);
723 http_errorcb(struct bufferevent
*bev
, short what
, void *_conn
)
725 enum http_state state
;
726 struct http_conn
*conn
= _conn
;
728 assert(!(what
& BEV_EVENT_CONNECTED
));
731 conn
->state
= HTTP_STATE_MANGLED
;
733 if (what
& BEV_EVENT_WRITING
) {
734 end_message(conn
, ERROR_WRITE_FAILED
);
739 case HTTP_STATE_IDLE
:
740 end_message(conn
, ERROR_IDLE_CONN_TIMEDOUT
);
742 case HTTP_STATE_READ_FIRSTLINE
:
743 case HTTP_STATE_READ_HEADERS
:
744 end_message(conn
, ERROR_INCOMPLETE_HEADERS
);
746 case HTTP_STATE_READ_BODY
:
747 if ((what
& BEV_EVENT_EOF
) && conn
->msg_complete_on_eof
)
748 end_message(conn
, ERROR_NONE
);
750 end_message(conn
, ERROR_INCOMPLETE_BODY
);
753 log_fatal("http_conn: errorcb called in invalid state");
758 process_one_step(struct http_conn
*conn
)
760 struct evbuffer
*inbuf
= bufferevent_get_input(conn
->bev
);
762 switch (conn
->state
) {
763 case HTTP_STATE_IDLE
:
764 conn
->state
= HTTP_STATE_READ_FIRSTLINE
;
765 bufferevent_set_timeouts(conn
->bev
, NULL
, NULL
);
767 case HTTP_STATE_READ_FIRSTLINE
:
768 assert(conn
->firstline
== NULL
);
769 conn
->firstline
= evbuffer_readln(inbuf
, NULL
,
772 conn
->state
= HTTP_STATE_READ_HEADERS
;
774 case HTTP_STATE_READ_HEADERS
:
777 case HTTP_STATE_READ_BODY
:
781 log_fatal("http_conn: read cb called in invalid state");
786 process_inbuf(struct http_conn
*conn
)
788 struct evbuffer
*inbuf
= bufferevent_get_input(conn
->bev
);
789 enum http_state state_before
;
791 if (evbuffer_get_length(inbuf
) == 0)
795 state_before
= conn
->state
;
796 process_one_step(conn
);
797 } while (!conn
->read_paused
&&
798 evbuffer_get_length(inbuf
) > 0 &&
799 state_before
!= conn
->state
);
803 http_readcb(struct bufferevent
*bev
, void *_conn
)
805 process_inbuf(_conn
);
809 http_writecb(struct bufferevent
*bev
, void *_conn
)
811 struct http_conn
*conn
= _conn
;
812 struct evbuffer
*outbuf
= bufferevent_get_output(bev
);
815 bufferevent_setwatermark(bev
, EV_WRITE
, 0, 0);
817 EVENT0(conn
, on_write_more
);
818 } else if (evbuffer_get_length(outbuf
) == 0) {
819 if (!conn
->will_flush
)
820 EVENT0(conn
, on_flush
);
825 http_connectcb(struct bufferevent
*bev
, int ok
, void *_conn
)
827 struct http_conn
*conn
= _conn
;
829 assert(conn
->state
== HTTP_STATE_CONNECTING
);
830 bufferevent_setcb(conn
->bev
, http_readcb
, http_writecb
,
835 EVENT0(conn
, on_connect
);
837 conn
->state
= HTTP_STATE_MANGLED
;
838 EVENT1(conn
, on_error
, ERROR_CONNECT_FAILED
);
844 http_conn_new(struct event_base
*base
, evutil_socket_t sock
,
845 enum http_type type
, const struct http_cbs
*cbs
, void *cbarg
)
847 struct http_conn
*conn
;
849 conn
= mem_calloc(1, sizeof(*conn
));
854 conn
->bev
= bufferevent_socket_new(base
, sock
,
855 BEV_OPT_CLOSE_ON_FREE
);
857 log_fatal("http_conn: failed to create bufferevent");
859 conn
->inbuf_processed
= evbuffer_new();
860 if (!conn
->inbuf_processed
)
861 log_fatal("http_conn: failed to create evbuffer");
863 if (type
!= HTTP_SERVER
)
864 bufferevent_setcb(conn
->bev
, http_readcb
, http_writecb
,
874 http_conn_connect(struct http_conn
*conn
, struct evdns_base
*dns
,
875 int family
, const char *host
, int port
)
877 assert(conn
->type
== HTTP_SERVER
);
878 conn
->state
= HTTP_STATE_CONNECTING
;
879 return conn_connect_bufferevent(conn
->bev
, dns
, family
, host
, port
,
880 http_connectcb
, conn
);
884 deferred_free(evutil_socket_t s
, short what
, void *arg
)
886 struct http_conn
*conn
= arg
;
887 bufferevent_free(conn
->bev
);
888 if (conn
->tunnel_bev
)
889 bufferevent_free(conn
->tunnel_bev
);
890 evbuffer_free(conn
->inbuf_processed
);
895 http_conn_free(struct http_conn
*conn
)
901 http_conn_stop_reading(conn
);
902 bufferevent_disable(conn
->bev
, EV_WRITE
);
903 bufferevent_setcb(conn
->bev
, NULL
, NULL
, NULL
, NULL
);
905 event_base_once(conn
->base
, -1, EV_TIMEOUT
, deferred_free
, conn
, NULL
);
909 http_conn_write_request(struct http_conn
*conn
, struct http_request
*req
)
911 struct evbuffer
*outbuf
;
913 assert(conn
->type
== HTTP_SERVER
);
915 headers_remove(req
->headers
, "connection");
918 outbuf
= bufferevent_get_output(conn
->bev
);
920 evbuffer_add_printf(outbuf
, "%s %s %s\r\n",
921 http_method_to_string(req
->meth
),
923 http_version_to_string(req
->vers
));
925 headers_dump(req
->headers
, outbuf
);
929 http_conn_expect_continue(struct http_conn
*conn
)
931 return conn
->expect_continue
;
935 http_conn_write_continue(struct http_conn
*conn
)
937 struct evbuffer
*outbuf
;
939 if (conn
->expect_continue
) {
940 log_debug("httpconn: writing continue status");
941 outbuf
= bufferevent_get_output(conn
->bev
);
942 conn
->expect_continue
= 0;
943 assert(conn
->vers
== HTTP_11
);
944 evbuffer_add_printf(outbuf
, "HTTP/1.1 100 Continue\r\n\r\n");
949 http_conn_write_response(struct http_conn
*conn
, struct http_response
*resp
)
951 struct evbuffer
*outbuf
;
953 assert(conn
->type
== HTTP_CLIENT
);
954 assert(conn
->vers
!= HTTP_UNKNOWN
);
956 headers_remove(resp
->headers
, "connection");
957 headers_remove(resp
->headers
, "transfer-encoding");
958 resp
->vers
= conn
->vers
;
960 if (conn
->vers
== HTTP_10
|| !conn
->persistent
) {
961 if (conn
->vers
== HTTP_10
)
962 conn
->output_te
= TE_IDENTITY
;
963 headers_add_key_val(resp
->headers
, "Connection", "close");
965 if (conn
->output_te
== TE_CHUNKED
) {
966 headers_add_key_val(resp
->headers
,
967 "Transfer-Encoding", "chunked");
970 outbuf
= bufferevent_get_output(conn
->bev
);
972 evbuffer_add_printf(outbuf
, "%s %d %s\r\n",
973 http_version_to_string(conn
->vers
),
977 headers_dump(resp
->headers
, outbuf
);
981 http_conn_write_buf(struct http_conn
*conn
, struct evbuffer
*buf
)
983 struct evbuffer
*outbuf
;
985 outbuf
= bufferevent_get_output(conn
->bev
);
987 if (conn
->output_te
== TE_CHUNKED
)
988 evbuffer_add_printf(outbuf
, "%x\r\n",
989 (unsigned)evbuffer_get_length(buf
));
990 evbuffer_add_buffer(outbuf
, buf
);
991 if (conn
->output_te
== TE_CHUNKED
)
992 evbuffer_add(outbuf
, "\r\n", 2);
994 /* have we choked? */
995 if (evbuffer_get_length(outbuf
) > max_write_backlog
) {
996 bufferevent_setwatermark(conn
->bev
, EV_WRITE
,
997 max_write_backlog
/ 2, 0);
1006 http_conn_write_finished(struct http_conn
*conn
)
1008 if (conn
->output_te
== TE_CHUNKED
)
1009 bufferevent_write(conn
->bev
, "0\r\n\r\n", 5);
1010 conn
->output_te
= TE_IDENTITY
;
1015 http_conn_current_message_has_body(struct http_conn
*conn
)
1017 return conn
->has_body
;
1021 http_conn_set_current_message_bodyless(struct http_conn
*conn
)
1023 assert(conn
->type
== HTTP_SERVER
);
1028 http_conn_get_current_message_body_encoding(struct http_conn
*conn
)
1034 http_conn_get_current_message_body_length(struct http_conn
*conn
)
1036 return conn
->body_length
;
1040 http_conn_set_output_encoding(struct http_conn
*conn
, enum http_te te
)
1042 conn
->output_te
= te
;
1046 http_conn_is_persistent(struct http_conn
*conn
)
1048 return conn
->persistent
;
1052 http_conn_disable_persistence(struct http_conn
*conn
)
1054 conn
->persistent
= 0;
1058 http_conn_stop_reading(struct http_conn
*conn
)
1060 bufferevent_disable(conn
->bev
, EV_READ
);
1061 conn
->read_paused
= 1;
1065 deferred_process_inbuf(evutil_socket_t s
, short what
, void *_conn
)
1067 process_inbuf(_conn
);
1071 http_conn_start_reading(struct http_conn
*conn
)
1073 struct evbuffer
*inbuf
= bufferevent_get_input(conn
->bev
);
1075 bufferevent_enable(conn
->bev
, EV_READ
);
1076 conn
->read_paused
= 0;
1077 if (evbuffer_get_length(inbuf
) > 0)
1078 event_base_once(conn
->base
, -1, EV_TIMEOUT
,
1079 deferred_process_inbuf
, conn
, NULL
);
1083 deferred_flush(evutil_socket_t fd
, short what
, void *_conn
)
1085 struct http_conn
*conn
= _conn
;
1086 struct evbuffer
*outbuf
= bufferevent_get_output(conn
->bev
);
1088 if (evbuffer_get_length(outbuf
) == 0) {
1089 conn
->will_flush
= 0;
1090 EVENT0(conn
, on_flush
);
1095 http_conn_flush(struct http_conn
*conn
)
1097 assert(!conn
->will_free
);
1098 conn
->will_flush
= 1;
1099 event_base_once(conn
->base
, -1, EV_TIMEOUT
, deferred_flush
, conn
, NULL
);
1103 http_conn_send_error(struct http_conn
*conn
, int code
, const char *fmt
, ...)
1107 struct evbuffer
*msg
;
1108 struct http_response resp
;
1109 struct header_list headers
;
1112 assert(conn
->type
== HTTP_CLIENT
);
1114 TAILQ_INIT(&headers
);
1115 msg
= evbuffer_new();
1116 resp
.headers
= &headers
;
1118 if (conn
->vers
== HTTP_UNKNOWN
)
1119 conn
->vers
= HTTP_11
;
1123 evutil_vsnprintf(reason
, sizeof(reason
), fmt
, ap
);
1126 conn
->output_te
= TE_IDENTITY
;
1127 resp
.vers
= HTTP_11
;
1129 resp
.reason
= reason
;
1131 evbuffer_add_printf(msg
,
1134 "<title>%d %s</title>\n"
1140 code
, resp
.reason
, resp
.reason
);
1142 evutil_snprintf(length
, sizeof(length
), "%u",
1143 (unsigned)evbuffer_get_length(msg
));
1144 headers_add_key_val(&headers
, "Content-Type", "text/html");
1145 headers_add_key_val(&headers
, "Content-Length", length
);
1146 headers_add_key_val(&headers
, "Expires", "0");
1147 headers_add_key_val(&headers
, "Cache-Control", "no-cache");
1148 headers_add_key_val(&headers
, "Pragma", "no-cache");
1150 http_conn_write_response(conn
, &resp
);
1151 http_conn_write_buf(conn
, msg
);
1152 headers_clear(&headers
);
1157 http_conn_start_tunnel(struct http_conn
*conn
, struct evdns_base
*dns
,
1158 int family
, const char *host
, int port
)
1160 assert(conn
->type
== HTTP_CLIENT
);
1161 assert(conn
->tunnel_bev
== NULL
);
1163 http_conn_stop_reading(conn
);
1164 conn
->tunnel_bev
= bufferevent_socket_new(conn
->base
, -1,
1165 BEV_OPT_CLOSE_ON_FREE
);
1166 bufferevent_setcb(conn
->bev
, tunnel_readcb
,
1167 tunnel_writecb
, tunnel_errorcb
, conn
);
1168 log_info("tunnel: attempting connection to %s:%d",
1169 log_scrub(host
), port
);
1170 conn
->state
= HTTP_STATE_TUNNEL_CONNECTING
;
1171 return conn_connect_bufferevent(conn
->tunnel_bev
, dns
, family
,
1172 host
, port
, tunnel_connectcb
, conn
);
1176 http_request_free(struct http_request
*req
)
1182 headers_clear(req
->headers
);
1187 http_response_free(struct http_response
*resp
)
1192 headers_clear(resp
->headers
);
1193 mem_free(resp
->headers
);
1194 mem_free(resp
->reason
);
1199 #include <netinet/in.h>
1201 #include <event2/dns.h>
1202 #include <event2/listener.h>
1205 proxy_connected(struct http_conn
*conn
, void *arg
)
1207 struct http_request req
;
1208 struct header_list headers
;
1209 struct evbuffer
*buf
;
1211 TAILQ_INIT(&headers
);
1212 req
.meth
= METH_GET
;
1215 req
.headers
= &headers
;
1217 buf
= evbuffer_new();
1218 evbuffer_add_printf(buf
, "Host: %s\r\n\r\n", req
.url
->host
);
1219 headers_load(&headers
, buf
);
1222 http_conn_write_request(conn
, &req
);
1226 proxy_error(struct http_conn
*conn
, enum http_conn_error err
, void *arg
)
1228 fprintf(stderr
, "error %d\n", err
);
1229 http_conn_free(conn
);
1233 proxy_request(struct http_conn
*conn
, struct http_request
*req
, void *arg
)
1235 struct evbuffer
*buf
;
1237 fprintf(stderr
, "request: %s %s %s\n",
1238 http_method_to_string(req
->meth
),
1240 http_version_to_string(req
->vers
));
1242 buf
= evbuffer_new();
1243 headers_dump(req
->headers
, buf
);
1244 fwrite(evbuffer_pullup(buf
, evbuffer_get_length(buf
)), evbuffer_get_length(buf
), 1, stderr
);
1248 http_conn_send_error(conn
, 401);
1252 proxy_response(struct http_conn
*conn
, struct http_response
*resp
, void *arg
)
1254 struct evbuffer
*buf
;
1256 fprintf(stderr
, "response: %s, %d, %s\n",
1257 http_version_to_string(resp
->vers
),
1261 buf
= evbuffer_new();
1262 headers_dump(resp
->headers
, buf
);
1263 fwrite(evbuffer_pullup(buf
, evbuffer_get_length(buf
)), evbuffer_get_length(buf
), 1, stderr
);
1268 proxy_read_body(struct http_conn
*conn
, struct evbuffer
*buf
, void *arg
)
1270 size_t len
= evbuffer_get_length(buf
);
1271 fwrite(evbuffer_pullup(buf
, len
), len
, 1, stderr
);
1272 evbuffer_drain(buf
, len
);
1276 proxy_msg_complete(struct http_conn
*conn
, void *arg
)
1278 fprintf(stderr
, "\n...MSG COMPLETE...\n");
1282 proxy_write_more(struct http_conn
*conn
, void *arg
)
1287 proxy_flush(struct http_conn
*conn
, void *arg
)
1289 fprintf(stderr
, "\n....FLUSHED...\n");
1292 static struct http_cbs test_proxy_cbs
= {
1305 clientcb(struct evconnlistener
*ecs
, evutil_socket_t s
,
1306 struct sockaddr
*addr
, int len
, void *arg
)
1308 struct http_conn
*client
;
1310 client
= http_conn_new(evconnlistener_get_base(ecs
), s
, HTTP_CLIENT
, &test_proxy_cbs
, arg
);
1314 main(int argc
, char **argv
)
1316 struct event_base
*base
;
1317 struct evdns_base
*dns
;
1318 struct http_conn
*http
;
1321 base
= event_base_new();
1324 struct evconnlistener
*ecs
;
1325 struct sockaddr_in sin
;
1326 memset(&sin
, 0, sizeof(sin
));
1327 sin
.sin_family
=AF_INET
;
1328 sin
.sin_port
= htons(8080);
1329 ecs
= evconnlistener_new_bind(base
, clientcb
, NULL
, 0,
1330 LEV_OPT_REUSEABLE
, &sin
, sizeof(sin
));
1331 event_base_dispatch(base
);
1335 url
= url_tokenize(argv
[1]);
1342 dns
= evdns_base_new(base
, 1);
1344 http
= http_conn_new(base
, -1, HTTP_SERVER
, &test_proxy_cbs
, url
);
1345 http_conn_connect(http
, dns
, AF_UNSPEC
, url
->host
, url
->port
);
1347 event_base_dispatch(base
);