2 * Copyright (c) 2002-2007 Niels Provos <provos@citi.umich.edu>
3 * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. The name of the author may not be used to endorse or promote products
14 * derived from this software without specific prior written permission.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 #include "event2/event-config.h"
29 #include "evconfig-private.h"
31 #define member_size(type, member) sizeof(((type *)0)->member)
33 #ifdef EVENT__HAVE_SYS_PARAM_H
34 #include <sys/param.h>
36 #ifdef EVENT__HAVE_SYS_TYPES_H
37 #include <sys/types.h>
40 #ifdef HAVE_SYS_IOCCOM_H
41 #include <sys/ioccom.h>
43 #ifdef EVENT__HAVE_SYS_RESOURCE_H
44 #include <sys/resource.h>
46 #ifdef EVENT__HAVE_SYS_TIME_H
49 #ifdef EVENT__HAVE_SYS_WAIT_H
54 #include <sys/socket.h>
61 #ifdef EVENT__HAVE_SYS_UN_H
64 #ifdef EVENT__HAVE_AFUNIX_H
68 #include <sys/queue.h>
70 #ifdef EVENT__HAVE_NETINET_IN_H
71 #include <netinet/in.h>
73 #ifdef EVENT__HAVE_ARPA_INET_H
74 #include <arpa/inet.h>
76 #ifdef EVENT__HAVE_NETDB_H
92 #ifdef EVENT__HAVE_UNISTD_H
95 #ifdef EVENT__HAVE_FCNTL_H
99 #undef timeout_pending
100 #undef timeout_initialized
102 #include "strlcpy-internal.h"
103 #include "event2/http.h"
104 #include "event2/event.h"
105 #include "event2/buffer.h"
106 #include "event2/bufferevent.h"
107 #include "event2/http_struct.h"
108 #include "event2/http_compat.h"
109 #include "event2/util.h"
110 #include "event2/ws.h"
111 #include "event2/listener.h"
112 #include "log-internal.h"
113 #include "util-internal.h"
114 #include "http-internal.h"
115 #include "mm-internal.h"
116 #include "bufferevent-internal.h"
118 #ifndef EVENT__HAVE_GETNAMEINFO
119 #define NI_MAXSERV 32
120 #define NI_MAXHOST 1025
122 #ifndef NI_NUMERICHOST
123 #define NI_NUMERICHOST 1
126 #ifndef NI_NUMERICSERV
127 #define NI_NUMERICSERV 2
131 fake_getnameinfo(const struct sockaddr *sa, size_t salen, char *host,
132 size_t hostlen, char *serv, size_t servlen, int flags)
134 struct sockaddr_in *sin = (struct sockaddr_in *)sa;
138 evutil_snprintf(tmpserv, sizeof(tmpserv),
139 "%d", ntohs(sin->sin_port));
140 if (strlcpy(serv, tmpserv, servlen) >= servlen)
145 if (flags & NI_NUMERICHOST) {
146 if (strlcpy(host, inet_ntoa(sin->sin_addr),
153 hp = gethostbyaddr((char *)&sin->sin_addr,
154 sizeof(struct in_addr), AF_INET);
158 if (strlcpy(host, hp->h_name, hostlen) >= hostlen)
169 #define REQ_VERSION_BEFORE(req, major_v, minor_v) \
170 ((req)->major < (major_v) || \
171 ((req)->major == (major_v) && (req)->minor < (minor_v)))
173 #define REQ_VERSION_ATLEAST(req, major_v, minor_v) \
174 ((req)->major > (major_v) || \
175 ((req)->major == (major_v) && (req)->minor >= (minor_v)))
178 #define MIN(a,b) (((a)<(b))?(a):(b))
183 static evutil_socket_t create_bind_socket_nonblock(struct evutil_addrinfo *, int reuse);
184 static evutil_socket_t bind_socket(const char *, ev_uint16_t, int reuse);
185 static void name_from_addr(struct sockaddr *, ev_socklen_t, char **, char **);
186 static struct evhttp_uri *evhttp_uri_parse_authority(char *source_uri, unsigned flags);
187 static int evhttp_associate_new_request_with_connection(
188 struct evhttp_connection *evcon);
189 static void evhttp_connection_start_detectclose(
190 struct evhttp_connection *evcon);
191 static void evhttp_connection_stop_detectclose(
192 struct evhttp_connection *evcon);
193 static void evhttp_request_dispatch(struct evhttp_connection* evcon);
194 static void evhttp_read_firstline(struct evhttp_connection *evcon,
195 struct evhttp_request *req);
196 static void evhttp_read_header(struct evhttp_connection *evcon,
197 struct evhttp_request *req);
198 static int evhttp_add_header_internal(struct evkeyvalq *headers,
199 const char *key, const char *value);
200 static const char *evhttp_response_phrase_internal(int code);
201 static void evhttp_get_request(struct evhttp *, evutil_socket_t, struct sockaddr *, ev_socklen_t, struct bufferevent *bev);
202 static void evhttp_write_buffer(struct evhttp_connection *,
203 void (*)(struct evhttp_connection *, void *), void *);
204 static void evhttp_make_header(struct evhttp_connection *, struct evhttp_request *);
205 static int evhttp_method_may_have_body_(struct evhttp_connection *, enum evhttp_cmd_type);
207 /* callbacks for bufferevent */
208 static void evhttp_read_cb(struct bufferevent *, void *);
209 static void evhttp_write_cb(struct bufferevent *, void *);
210 static void evhttp_error_cb(struct bufferevent *bufev, short what, void *arg);
211 static int evhttp_find_vhost(struct evhttp *http, struct evhttp **outhttp, const char *hostname);
212 static const char *evhttp_method_(struct evhttp_connection *evcon,
213 enum evhttp_cmd_type type, ev_uint16_t *flags);
215 #ifndef EVENT__HAVE_STRSEP
216 /* strsep replacement for platforms that lack it. Only works if
217 * del is one character long. */
219 strsep(char **s, const char *del)
222 EVUTIL_ASSERT(strlen(del) == 1);
226 d = strstr(tok, del);
237 html_replace(const char ch, const char **escaped)
263 * Replaces <, >, ", ' and & with <, >, ",
264 * ' and & correspondingly.
266 * The returned string needs to be freed by the caller.
270 evhttp_htmlescape(const char *html)
273 size_t new_size = 0, old_size = 0;
274 char *escaped_html, *p;
279 old_size = strlen(html);
280 for (i = 0; i < old_size; ++i) {
281 const char *replaced = NULL;
282 const size_t replace_size = html_replace(html[i], &replaced);
283 if (replace_size > EV_SIZE_MAX - new_size) {
284 event_warn("%s: html_replace overflow", __func__);
287 new_size += replace_size;
290 if (new_size == EV_SIZE_MAX)
292 p = escaped_html = mm_malloc(new_size + 1);
293 if (escaped_html == NULL) {
294 event_warn("%s: malloc(%lu)", __func__,
295 (unsigned long)(new_size + 1));
298 for (i = 0; i < old_size; ++i) {
299 const char *replaced = &html[i];
300 const size_t len = html_replace(html[i], &replaced);
301 memcpy(p, replaced, len);
307 return (escaped_html);
310 /** Given an evhttp_cmd_type, returns a constant string containing the
311 * equivalent HTTP command, or NULL if the evhttp_cmd_type is
314 evhttp_method_(struct evhttp_connection *evcon,
315 enum evhttp_cmd_type type, ev_uint16_t *flags)
317 struct evhttp_ext_method ext_method;
318 const char *method = NULL;
319 ev_uint16_t tmp_flags = EVHTTP_METHOD_HAS_BODY;
325 case EVHTTP_REQ_POST:
328 case EVHTTP_REQ_HEAD:
330 tmp_flags &= ~EVHTTP_METHOD_HAS_BODY;
335 case EVHTTP_REQ_DELETE:
338 case EVHTTP_REQ_OPTIONS:
341 case EVHTTP_REQ_TRACE:
343 tmp_flags &= ~EVHTTP_METHOD_HAS_BODY;
345 case EVHTTP_REQ_CONNECT:
348 case EVHTTP_REQ_PATCH:
351 case EVHTTP_REQ_PROPFIND:
354 case EVHTTP_REQ_PROPPATCH:
355 method = "PROPPATCH";
357 case EVHTTP_REQ_MKCOL:
360 case EVHTTP_REQ_LOCK:
363 case EVHTTP_REQ_UNLOCK:
366 case EVHTTP_REQ_COPY:
369 case EVHTTP_REQ_MOVE:
373 /* setup the structure to allow for the cmp.
375 * if the cmp function is set, it has the ability to
376 * modify method and flags. Other fields will be
379 * NOTE: the flags returned are OR'd with the current
383 ext_method.method = NULL;
384 ext_method.type = type;
385 ext_method.flags = tmp_flags;
387 if (evcon->ext_method_cmp != NULL &&
388 evcon->ext_method_cmp(&ext_method) == 0) {
390 if (ext_method.type != type) {
391 event_debug(("%s: callback modified type from %u to %u, not allowed",
392 __func__, type, ext_method.type));
396 method = ext_method.method;
397 tmp_flags |= ext_method.flags;
403 event_debug(("%s: type=%04x => '%s' flags=%04x",
404 __func__, (int)type, method, tmp_flags));
412 * Determines if a response should have a body.
413 * Follows the rules in RFC 2616 section 4.3.
414 * @return 1 if the response MUST have a body; 0 if the response MUST NOT have
418 evhttp_response_needs_body(struct evhttp_request *req)
420 return (req->response_code != HTTP_NOCONTENT &&
421 req->response_code != HTTP_NOTMODIFIED &&
422 (req->response_code < 100 || req->response_code >= 200) &&
423 req->type != EVHTTP_REQ_CONNECT &&
424 req->type != EVHTTP_REQ_HEAD);
427 /** Helper: called after we've added some data to an evcon's bufferevent's
428 * output buffer. Sets the evconn's writing-is-done callback, and puts
429 * the bufferevent into writing mode.
432 evhttp_write_buffer(struct evhttp_connection *evcon,
433 void (*cb)(struct evhttp_connection *, void *), void *arg)
435 event_debug(("%s: preparing to write buffer\n", __func__));
441 /* Disable the read callback: we don't actually care about data;
442 * we only care about close detection. (We don't disable reading --
443 * EV_READ, since we *do* want to learn about any close events.) */
444 bufferevent_setcb(evcon->bufev,
450 bufferevent_enable(evcon->bufev, EV_READ|EV_WRITE);
454 evhttp_send_continue_done(struct evhttp_connection *evcon, void *arg)
456 bufferevent_disable(evcon->bufev, EV_WRITE);
460 evhttp_send_continue(struct evhttp_connection *evcon,
461 struct evhttp_request *req)
463 bufferevent_enable(evcon->bufev, EV_WRITE);
464 evbuffer_add_printf(bufferevent_get_output(evcon->bufev),
465 "HTTP/%d.%d 100 Continue\r\n\r\n",
466 req->major, req->minor);
467 evcon->cb = evhttp_send_continue_done;
468 evcon->cb_arg = NULL;
469 bufferevent_setcb(evcon->bufev,
476 /** Helper: returns true iff evconn is in any connected state. */
478 evhttp_connected(struct evhttp_connection *evcon)
480 switch (evcon->state) {
481 case EVCON_DISCONNECTED:
482 case EVCON_CONNECTING:
485 case EVCON_READING_FIRSTLINE:
486 case EVCON_READING_HEADERS:
487 case EVCON_READING_BODY:
488 case EVCON_READING_TRAILER:
495 /* Create the headers needed for an outgoing HTTP request, adds them to
496 * the request's header list, and writes the request line to the
497 * connection's output buffer.
500 evhttp_make_header_request(struct evhttp_connection *evcon,
501 struct evhttp_request *req)
504 /* NOTE: some version of GCC reports a warning that flags may be uninitialized, hence assignment */
505 ev_uint16_t flags = 0;
507 evhttp_remove_header(req->output_headers, "Proxy-Connection");
509 /* Generate request line */
510 if (!(method = evhttp_method_(evcon, req->type, &flags))) {
514 evbuffer_add_printf(bufferevent_get_output(evcon->bufev),
515 "%s %s HTTP/%d.%d\r\n",
516 method, req->uri, req->major, req->minor);
518 /* Add the content length on a request if missing
519 * Always add it for POST and PUT requests as clients expect it */
520 if ((flags & EVHTTP_METHOD_HAS_BODY) &&
521 (evbuffer_get_length(req->output_buffer) > 0 ||
522 req->type == EVHTTP_REQ_POST || req->type == EVHTTP_REQ_PUT) &&
523 evhttp_find_header(req->output_headers, "Content-Length") == NULL) {
525 evutil_snprintf(size, sizeof(size), EV_SIZE_FMT,
526 EV_SIZE_ARG(evbuffer_get_length(req->output_buffer)));
527 evhttp_add_header(req->output_headers, "Content-Length", size);
531 /** Return true if the list of headers in 'headers', intepreted with respect
532 * to flags, means that we should send a "connection: close" when the request
535 evhttp_is_connection_close(int flags, struct evkeyvalq* headers)
537 if (flags & EVHTTP_PROXY_REQUEST) {
538 /* proxy connection */
539 const char *connection = evhttp_find_header(headers, "Proxy-Connection");
540 return (connection == NULL || evutil_ascii_strcasecmp(connection, "keep-alive") != 0);
542 const char *connection = evhttp_find_header(headers, "Connection");
543 return (connection != NULL && evutil_ascii_strcasecmp(connection, "close") == 0);
547 evhttp_is_request_connection_close(struct evhttp_request *req)
549 if (req->type == EVHTTP_REQ_CONNECT)
553 evhttp_is_connection_close(req->flags, req->input_headers) ||
554 evhttp_is_connection_close(req->flags, req->output_headers);
557 /* Return true iff 'headers' contains 'Connection: keep-alive' */
559 evhttp_is_connection_keepalive(struct evkeyvalq* headers)
561 const char *connection = evhttp_find_header(headers, "Connection");
562 return (connection != NULL
563 && evutil_ascii_strncasecmp(connection, "keep-alive", 10) == 0);
566 /* Add a correct "Date" header to headers, unless it already has one. */
568 evhttp_maybe_add_date_header(struct evkeyvalq *headers)
570 if (evhttp_find_header(headers, "Date") == NULL) {
572 if ((signed)sizeof(date) > evutil_date_rfc1123(date, sizeof(date), NULL)) {
573 evhttp_add_header(headers, "Date", date);
578 /* Add a "Content-Length" header with value 'content_length' to headers,
579 * unless it already has a content-length or transfer-encoding header. */
581 evhttp_maybe_add_content_length_header(struct evkeyvalq *headers,
582 size_t content_length)
584 if (evhttp_find_header(headers, "Transfer-Encoding") == NULL &&
585 evhttp_find_header(headers, "Content-Length") == NULL) {
587 evutil_snprintf(len, sizeof(len), EV_SIZE_FMT,
588 EV_SIZE_ARG(content_length));
589 evhttp_add_header(headers, "Content-Length", len);
594 * Create the headers needed for an HTTP reply in req->output_headers,
595 * and write the first HTTP response for req line to evcon.
598 evhttp_make_header_response(struct evhttp_connection *evcon,
599 struct evhttp_request *req)
601 int is_keepalive = evhttp_is_connection_keepalive(req->input_headers);
602 evbuffer_add_printf(bufferevent_get_output(evcon->bufev),
603 "HTTP/%d.%d %d %s\r\n",
604 req->major, req->minor, req->response_code,
605 req->response_code_line);
607 if (req->major == 1) {
609 evhttp_maybe_add_date_header(req->output_headers);
612 * if the protocol is 1.0; and the connection was keep-alive
613 * we need to add a keep-alive header, too.
615 if (req->minor == 0 && is_keepalive)
616 evhttp_add_header(req->output_headers,
617 "Connection", "keep-alive");
619 if ((req->minor >= 1 || is_keepalive) &&
620 evhttp_response_needs_body(req)) {
622 * we need to add the content length if the
623 * user did not give it, this is required for
624 * persistent connections to work.
626 evhttp_maybe_add_content_length_header(
628 evbuffer_get_length(req->output_buffer));
632 /* Potentially add headers for unidentified content. */
633 if (evhttp_response_needs_body(req)) {
634 if (evhttp_find_header(req->output_headers,
635 "Content-Type") == NULL
636 && evcon->http_server->default_content_type) {
637 evhttp_add_header(req->output_headers,
639 evcon->http_server->default_content_type);
643 /* if the request asked for a close, we send a close, too */
644 if (evhttp_is_connection_close(req->flags, req->input_headers)) {
645 evhttp_remove_header(req->output_headers, "Connection");
646 if (!(req->flags & EVHTTP_PROXY_REQUEST))
647 evhttp_add_header(req->output_headers, "Connection", "close");
648 evhttp_remove_header(req->output_headers, "Proxy-Connection");
652 enum expect { NO, CONTINUE, OTHER };
653 static enum expect evhttp_have_expect(struct evhttp_request *req, int input)
656 struct evkeyvalq *h = input ? req->input_headers : req->output_headers;
658 if (!(req->kind == EVHTTP_REQUEST) || !REQ_VERSION_ATLEAST(req, 1, 1))
661 expect = evhttp_find_header(h, "Expect");
665 return !evutil_ascii_strcasecmp(expect, "100-continue") ? CONTINUE : OTHER;
669 /** Generate all headers appropriate for sending the http request in req (or
670 * the response, if we're sending a response), and write them to evcon's
671 * bufferevent. Also writes all data from req->output_buffer */
673 evhttp_make_header(struct evhttp_connection *evcon, struct evhttp_request *req)
675 struct evkeyval *header;
676 struct evbuffer *output = bufferevent_get_output(evcon->bufev);
679 * Depending if this is a HTTP request or response, we might need to
680 * add some new headers or remove existing headers.
682 if (req->kind == EVHTTP_REQUEST) {
683 evhttp_make_header_request(evcon, req);
685 evhttp_make_header_response(evcon, req);
688 TAILQ_FOREACH(header, req->output_headers, next) {
689 evbuffer_add_printf(output, "%s: %s\r\n",
690 header->key, header->value);
692 evbuffer_add(output, "\r\n", 2);
694 if (evhttp_have_expect(req, 0) != CONTINUE &&
695 evbuffer_get_length(req->output_buffer)) {
697 * For a request, we add the POST data, for a reply, this
698 * is the regular data.
700 evbuffer_add_buffer(output, req->output_buffer);
705 evhttp_connection_set_max_headers_size(struct evhttp_connection *evcon,
706 ev_ssize_t new_max_headers_size)
708 if (new_max_headers_size<0)
709 evcon->max_headers_size = EV_SIZE_MAX;
711 evcon->max_headers_size = new_max_headers_size;
714 evhttp_connection_set_max_body_size(struct evhttp_connection* evcon,
715 ev_ssize_t new_max_body_size)
717 if (new_max_body_size<0)
718 evcon->max_body_size = EV_UINT64_MAX;
720 evcon->max_body_size = new_max_body_size;
724 evhttp_connection_incoming_fail(struct evhttp_request *req,
725 enum evhttp_request_error error)
728 case EVREQ_HTTP_DATA_TOO_LONG:
729 req->response_code = HTTP_ENTITYTOOLARGE;
732 req->response_code = HTTP_BADREQUEST;
736 case EVREQ_HTTP_TIMEOUT:
739 * these are cases in which we probably should just
740 * close the connection and not send a reply. this
741 * case may happen when a browser keeps a persistent
742 * connection open and we timeout on the read. when
743 * the request is still being used for sending, we
744 * need to disassociate it from the connection here.
746 if (!req->userdone) {
747 /* remove it so that it will not be freed */
748 TAILQ_REMOVE(&req->evcon->requests, req, next);
749 /* indicate that this request no longer has a
755 case EVREQ_HTTP_INVALID_HEADER:
756 case EVREQ_HTTP_BUFFER_ERROR:
757 case EVREQ_HTTP_REQUEST_CANCEL:
758 case EVREQ_HTTP_DATA_TOO_LONG:
759 default: /* xxx: probably should just error on default */
760 /* the callback looks at the uri to determine errors */
765 if (req->uri_elems) {
766 evhttp_uri_free(req->uri_elems);
767 req->uri_elems = NULL;
771 * the callback needs to send a reply, once the reply has
772 * been send, the connection should get freed.
774 (*req->cb)(req, req->cb_arg);
780 /* Free connection ownership of which can be acquired by user using
781 * evhttp_request_own(). */
783 evhttp_request_free_auto(struct evhttp_request *req)
785 if (!(req->flags & EVHTTP_USER_OWNED))
786 evhttp_request_free(req);
790 evhttp_request_free_(struct evhttp_connection *evcon, struct evhttp_request *req)
792 TAILQ_REMOVE(&evcon->requests, req, next);
793 evhttp_request_free_auto(req);
797 evhttp_set_timeout_tv_(struct timeval *tv, const struct timeval *timeout, int def)
799 if (timeout == NULL && def != -1) {
808 evutil_timerclear(tv);
812 evhttp_set_timeout_(struct timeval *tv, int timeout, int def)
819 evutil_timerclear(tv);
821 struct timeval timeout_tv;
822 timeout_tv.tv_sec = timeout;
823 timeout_tv.tv_usec = 0;
828 /* Called when evcon has experienced a (non-recoverable? -NM) error, as
829 * given in error. If it's an outgoing connection, reset the connection,
830 * retry any pending requests, and inform the user. If it's incoming,
831 * delegates to evhttp_connection_incoming_fail(). */
833 evhttp_connection_fail_(struct evhttp_connection *evcon,
834 enum evhttp_request_error error)
836 const int errsave = EVUTIL_SOCKET_ERROR();
837 struct evhttp_request* req = TAILQ_FIRST(&evcon->requests);
838 void (*cb)(struct evhttp_request *, void *);
840 void (*error_cb)(enum evhttp_request_error, void *);
842 EVUTIL_ASSERT(req != NULL);
844 bufferevent_disable(evcon->bufev, EV_READ|EV_WRITE);
846 if (evcon->flags & EVHTTP_CON_INCOMING) {
848 * for incoming requests, there are two different
849 * failure cases. it's either a network level error
850 * or an http layer error. for problems on the network
851 * layer like timeouts we just drop the connections.
852 * For HTTP problems, we might have to send back a
853 * reply before the connection can be freed.
855 if (evhttp_connection_incoming_fail(req, error) == -1)
856 evhttp_connection_free(evcon);
860 error_cb = req->error_cb;
861 error_cb_arg = req->cb_arg;
862 /* when the request was canceled, the callback is not executed */
863 if (error != EVREQ_HTTP_REQUEST_CANCEL) {
864 /* save the callback for later; the cb might free our object */
866 cb_arg = req->cb_arg;
872 /* do not fail all requests; the next request is going to get
873 * send over a new connection. when a user cancels a request,
874 * all other pending requests should be processed as normal
876 evhttp_request_free_(evcon, req);
878 /* reset the connection */
879 evhttp_connection_reset_(evcon, 1);
881 /* We are trying the next request that was queued on us */
882 if (TAILQ_FIRST(&evcon->requests) != NULL)
883 evhttp_connection_connect_(evcon);
885 if ((evcon->flags & EVHTTP_CON_OUTGOING) &&
886 (evcon->flags & EVHTTP_CON_AUTOFREE)) {
887 evhttp_connection_free(evcon);
890 /* The call to evhttp_connection_reset_ overwrote errno.
891 * Let's restore the original errno, so that the user's
892 * callback can have a better idea of what the error was.
894 EVUTIL_SET_SOCKET_ERROR(errsave);
896 /* inform the user */
897 if (error_cb != NULL)
898 error_cb(error, error_cb_arg);
903 /* Bufferevent callback: invoked when any data has been written from an
904 * http connection's bufferevent */
906 evhttp_write_cb(struct bufferevent *bufev, void *arg)
908 struct evhttp_connection *evcon = arg;
910 /* Activate our call back */
911 if (evcon->cb != NULL)
912 (*evcon->cb)(evcon, evcon->cb_arg);
916 * Advance the connection state.
917 * - If this is an outgoing connection, we've just processed the response;
918 * idle or close the connection.
919 * - If this is an incoming connection, we've just processed the request;
923 evhttp_connection_done(struct evhttp_connection *evcon)
925 struct evhttp_request *req = TAILQ_FIRST(&evcon->requests);
926 int con_outgoing = evcon->flags & EVHTTP_CON_OUTGOING;
930 /* idle or close the connection */
931 int need_close = evhttp_is_request_connection_close(req);
932 TAILQ_REMOVE(&evcon->requests, req, next);
935 evcon->state = EVCON_IDLE;
937 /* check if we got asked to close the connection */
939 evhttp_connection_reset_(evcon, 1);
941 if (TAILQ_FIRST(&evcon->requests) != NULL) {
943 * We have more requests; reset the connection
944 * and deal with the next request.
946 if (!evhttp_connected(evcon))
947 evhttp_connection_connect_(evcon);
949 evhttp_request_dispatch(evcon);
950 } else if (!need_close) {
952 * The connection is going to be persistent, but we
953 * need to detect if the other side closes it.
955 evhttp_connection_start_detectclose(evcon);
956 } else if ((evcon->flags & EVHTTP_CON_AUTOFREE)) {
958 * If we have no more requests that need completion
959 * and we're not waiting for the connection to close
965 * incoming connection - we need to leave the request on the
966 * connection so that we can reply to it.
968 evcon->state = EVCON_WRITING;
971 /* notify the user of the request */
972 (*req->cb)(req, req->cb_arg);
974 /* if this was an outgoing request, we own and it's done. so free it. */
976 evhttp_request_free_auto(req);
979 /* If this was the last request of an outgoing connection and we're
980 * not waiting to receive a connection close event and we want to
981 * automatically free the connection. We check to ensure our request
982 * list is empty one last time just in case our callback added a
985 if (free_evcon && TAILQ_FIRST(&evcon->requests) == NULL) {
986 evhttp_connection_free(evcon);
991 * Handles reading from a chunked request.
992 * return ALL_DATA_READ:
993 * all data has been read
994 * return MORE_DATA_EXPECTED:
995 * more data is expected
996 * return DATA_CORRUPTED:
998 * return REQUEST_CANCELED:
999 * request was canceled by the user calling evhttp_cancel_request
1000 * return DATA_TOO_LONG:
1001 * ran over the maximum limit
1004 static enum message_read_status
1005 evhttp_handle_chunked_read(struct evhttp_request *req, struct evbuffer *buf)
1007 if (req == NULL || buf == NULL) {
1008 return DATA_CORRUPTED;
1014 if ((buflen = evbuffer_get_length(buf)) == 0) {
1018 /* evbuffer_get_length returns size_t, but len variable is ssize_t,
1019 * check for overflow conditions */
1020 if (buflen > EV_SSIZE_MAX) {
1021 return DATA_CORRUPTED;
1024 if (req->ntoread < 0) {
1025 /* Read chunk size */
1027 char *p = evbuffer_readln(buf, NULL, EVBUFFER_EOL_CRLF);
1032 /* the last chunk is on a new line? */
1033 if (strlen(p) == 0) {
1037 ntoread = evutil_strtoll(p, &endp, 16);
1038 error = (*p == '\0' ||
1039 (*endp != '\0' && *endp != ' ') ||
1043 /* could not get chunk size */
1044 return (DATA_CORRUPTED);
1047 /* ntoread is signed int64, body_size is unsigned size_t, check for under/overflow conditions */
1048 if ((ev_uint64_t)ntoread > EV_SIZE_MAX - req->body_size) {
1049 return DATA_CORRUPTED;
1052 if (req->body_size + (size_t)ntoread > req->evcon->max_body_size) {
1053 /* failed body length test */
1054 event_debug(("Request body is too long"));
1055 return (DATA_TOO_LONG);
1058 req->body_size += (size_t)ntoread;
1059 req->ntoread = ntoread;
1060 if (req->ntoread == 0) {
1062 return (ALL_DATA_READ);
1067 /* req->ntoread is signed int64, len is ssize_t, based on arch,
1068 * ssize_t could only be 32b, check for these conditions */
1069 if (req->ntoread > EV_SSIZE_MAX) {
1070 return DATA_CORRUPTED;
1073 /* don't have enough to complete a chunk; wait for more */
1074 if (req->ntoread > 0 && buflen < (ev_uint64_t)req->ntoread)
1075 return (MORE_DATA_EXPECTED);
1077 /* Completed chunk */
1078 evbuffer_remove_buffer(buf, req->input_buffer, (size_t)req->ntoread);
1080 if (req->chunk_cb != NULL) {
1081 req->flags |= EVHTTP_REQ_DEFER_FREE;
1082 (*req->chunk_cb)(req, req->cb_arg);
1083 evbuffer_drain(req->input_buffer,
1084 evbuffer_get_length(req->input_buffer));
1085 req->flags &= ~EVHTTP_REQ_DEFER_FREE;
1086 if ((req->flags & EVHTTP_REQ_NEEDS_FREE) != 0) {
1087 return (REQUEST_CANCELED);
1092 return (MORE_DATA_EXPECTED);
1096 evhttp_read_trailer(struct evhttp_connection *evcon, struct evhttp_request *req)
1098 struct evbuffer *buf = bufferevent_get_input(evcon->bufev);
1100 switch (evhttp_parse_headers_(req, buf)) {
1101 case DATA_CORRUPTED:
1103 evhttp_connection_fail_(evcon, EVREQ_HTTP_DATA_TOO_LONG);
1106 bufferevent_disable(evcon->bufev, EV_READ);
1107 evhttp_connection_done(evcon);
1109 case MORE_DATA_EXPECTED:
1110 case REQUEST_CANCELED: /* ??? */
1117 evhttp_lingering_close(struct evhttp_connection *evcon,
1118 struct evhttp_request *req)
1120 struct evbuffer *buf = bufferevent_get_input(evcon->bufev);
1122 size_t n = evbuffer_get_length(buf);
1123 if (n > (size_t) req->ntoread)
1124 n = (size_t) req->ntoread;
1126 req->body_size += n;
1128 event_debug(("Request body is too long, left " EV_I64_FMT,
1129 EV_I64_ARG(req->ntoread)));
1131 evbuffer_drain(buf, n);
1133 evhttp_connection_fail_(evcon, EVREQ_HTTP_DATA_TOO_LONG);
1136 evhttp_lingering_fail(struct evhttp_connection *evcon,
1137 struct evhttp_request *req)
1139 if (evcon->flags & EVHTTP_CON_LINGERING_CLOSE)
1140 evhttp_lingering_close(evcon, req);
1142 evhttp_connection_fail_(evcon, EVREQ_HTTP_DATA_TOO_LONG);
1146 evhttp_read_body(struct evhttp_connection *evcon, struct evhttp_request *req)
1148 struct evbuffer *buf = bufferevent_get_input(evcon->bufev);
1151 switch (evhttp_handle_chunked_read(req, buf)) {
1153 /* finished last chunk */
1154 evcon->state = EVCON_READING_TRAILER;
1155 evhttp_read_trailer(evcon, req);
1157 case DATA_CORRUPTED:
1159 /* corrupted data */
1160 evhttp_connection_fail_(evcon,
1161 EVREQ_HTTP_DATA_TOO_LONG);
1163 case REQUEST_CANCELED:
1164 /* request canceled */
1165 evhttp_request_free_auto(req);
1167 case MORE_DATA_EXPECTED:
1171 } else if (req->ntoread < 0) {
1172 /* Read until connection close. */
1173 if ((size_t)(req->body_size + evbuffer_get_length(buf)) < req->body_size) {
1174 evhttp_connection_fail_(evcon, EVREQ_HTTP_INVALID_HEADER);
1178 req->body_size += evbuffer_get_length(buf);
1179 evbuffer_add_buffer(req->input_buffer, buf);
1180 } else if (req->chunk_cb != NULL || evbuffer_get_length(buf) >= (size_t)req->ntoread) {
1181 /* XXX: the above get_length comparison has to be fixed for overflow conditions! */
1182 /* We've postponed moving the data until now, but we're
1183 * about to use it. */
1184 size_t n = evbuffer_get_length(buf);
1186 if (n > (size_t) req->ntoread)
1187 n = (size_t) req->ntoread;
1189 req->body_size += n;
1190 evbuffer_remove_buffer(buf, req->input_buffer, n);
1193 if (req->body_size > req->evcon->max_body_size ||
1194 (!req->chunked && req->ntoread >= 0 &&
1195 (size_t)req->ntoread > req->evcon->max_body_size)) {
1196 /* XXX: The above casted comparison must checked for overflow */
1197 /* failed body length test */
1199 evhttp_lingering_fail(evcon, req);
1203 if (evbuffer_get_length(req->input_buffer) > 0 && req->chunk_cb != NULL) {
1204 req->flags |= EVHTTP_REQ_DEFER_FREE;
1205 (*req->chunk_cb)(req, req->cb_arg);
1206 req->flags &= ~EVHTTP_REQ_DEFER_FREE;
1207 evbuffer_drain(req->input_buffer,
1208 evbuffer_get_length(req->input_buffer));
1209 if ((req->flags & EVHTTP_REQ_NEEDS_FREE) != 0) {
1210 evhttp_request_free_auto(req);
1215 if (!req->ntoread) {
1216 bufferevent_disable(evcon->bufev, EV_READ);
1217 /* Completed content length */
1218 evhttp_connection_done(evcon);
1223 #define get_deferred_queue(evcon) \
1227 * Gets called when more data becomes available
1231 evhttp_read_cb(struct bufferevent *bufev, void *arg)
1233 struct evhttp_connection *evcon = arg;
1234 struct evhttp_request *req = TAILQ_FIRST(&evcon->requests);
1236 /* Cancel if it's pending. */
1237 event_deferred_cb_cancel_(get_deferred_queue(evcon),
1238 &evcon->read_more_deferred_cb);
1240 switch (evcon->state) {
1241 case EVCON_READING_FIRSTLINE:
1242 evhttp_read_firstline(evcon, req);
1243 /* note the request may have been freed in
1244 * evhttp_read_body */
1246 case EVCON_READING_HEADERS:
1247 evhttp_read_header(evcon, req);
1248 /* note the request may have been freed in
1249 * evhttp_read_body */
1251 case EVCON_READING_BODY:
1252 evhttp_read_body(evcon, req);
1253 /* note the request may have been freed in
1254 * evhttp_read_body */
1256 case EVCON_READING_TRAILER:
1257 evhttp_read_trailer(evcon, req);
1262 struct evbuffer *input;
1265 input = bufferevent_get_input(evcon->bufev);
1266 total_len = evbuffer_get_length(input);
1267 event_debug(("%s: read "EV_SIZE_FMT
1268 " bytes in EVCON_IDLE state,"
1269 " resetting connection",
1270 __func__, EV_SIZE_ARG(total_len)));
1273 evhttp_connection_reset_(evcon, 1);
1276 case EVCON_DISCONNECTED:
1277 case EVCON_CONNECTING:
1280 event_errx(1, "%s: illegal connection state %d",
1281 __func__, evcon->state);
1286 evhttp_deferred_read_cb(struct event_callback *cb, void *data)
1288 struct evhttp_connection *evcon = data;
1289 struct bufferevent *bev = evcon->bufev;
1291 (bev->readcb)(evcon->bufev, evcon);
1295 evhttp_write_connectioncb(struct evhttp_connection *evcon, void *arg)
1297 /* This is after writing the request to the server */
1298 struct evhttp_request *req = TAILQ_FIRST(&evcon->requests);
1299 struct evbuffer *output = bufferevent_get_output(evcon->bufev);
1300 EVUTIL_ASSERT(req != NULL);
1302 EVUTIL_ASSERT(evcon->state == EVCON_WRITING);
1304 /* We need to wait until we've written all of our output data before we can
1306 if (evbuffer_get_length(output) > 0)
1309 /* We are done writing our header and are now expecting the response */
1310 req->kind = EVHTTP_RESPONSE;
1312 evhttp_start_read_(evcon);
1316 * Clean up a connection object
1320 evhttp_connection_free(struct evhttp_connection *evcon)
1322 struct evhttp_request *req;
1324 /* notify interested parties that this connection is going down */
1325 if (evhttp_connected(evcon) && evcon->closecb != NULL)
1326 (*evcon->closecb)(evcon, evcon->closecb_arg);
1328 /* remove all requests that might be queued on this
1329 * connection. for server connections, this should be empty.
1330 * because it gets dequeued either in evhttp_connection_done or
1331 * evhttp_connection_fail_.
1333 while ((req = TAILQ_FIRST(&evcon->requests)) != NULL) {
1334 evhttp_request_free_(evcon, req);
1337 if (evcon->http_server != NULL) {
1338 struct evhttp *http = evcon->http_server;
1339 TAILQ_REMOVE(&http->connections, evcon, next);
1340 http->connection_cnt--;
1343 if (event_initialized(&evcon->retry_ev)) {
1344 event_del(&evcon->retry_ev);
1345 event_debug_unassign(&evcon->retry_ev);
1348 event_deferred_cb_cancel_(get_deferred_queue(evcon),
1349 &evcon->read_more_deferred_cb);
1351 if (evcon->bufev != NULL) {
1352 bufferevent_free(evcon->bufev);
1355 if (evcon->bind_address != NULL)
1356 mm_free(evcon->bind_address);
1358 if (evcon->address != NULL)
1359 mm_free(evcon->address);
1362 if (evcon->unixsocket != NULL)
1363 mm_free(evcon->unixsocket);
1370 evhttp_connection_free_on_completion(struct evhttp_connection *evcon) {
1371 evcon->flags |= EVHTTP_CON_AUTOFREE;
1375 evhttp_connection_set_local_address(struct evhttp_connection *evcon,
1376 const char *address)
1378 EVUTIL_ASSERT(evcon->state == EVCON_DISCONNECTED);
1379 if (evcon->bind_address)
1380 mm_free(evcon->bind_address);
1381 if ((evcon->bind_address = mm_strdup(address)) == NULL)
1382 event_warn("%s: strdup", __func__);
1386 evhttp_connection_set_local_port(struct evhttp_connection *evcon,
1389 EVUTIL_ASSERT(evcon->state == EVCON_DISCONNECTED);
1390 evcon->bind_port = port;
1394 evhttp_request_dispatch(struct evhttp_connection* evcon)
1396 struct evhttp_request *req = TAILQ_FIRST(&evcon->requests);
1398 /* this should not usually happy but it's possible */
1402 EVUTIL_ASSERT(req->kind == EVHTTP_REQUEST);
1404 /* delete possible close detection events */
1405 evhttp_connection_stop_detectclose(evcon);
1407 /* we assume that the connection is connected already */
1408 EVUTIL_ASSERT(evcon->state == EVCON_IDLE);
1410 evcon->state = EVCON_WRITING;
1412 /* Create the header from the store arguments */
1413 evhttp_make_header(evcon, req);
1415 evhttp_write_buffer(evcon, evhttp_write_connectioncb, NULL);
1418 /** Hard-reset our connection state
1422 * - clears out buffers
1426 evhttp_connection_reset_hard_(struct evhttp_connection *evcon)
1428 struct evbuffer *tmp;
1431 /* XXXX This is not actually an optimal fix. Instead we ought to have
1432 an API for "stop connecting", or use bufferevent_replacefd to turn off
1433 connecting. But for Libevent 2.0, this seems like a minimal change
1434 least likely to disrupt the rest of the bufferevent and http code.
1436 Why is this here? If the fd is set in the bufferevent, and the
1437 bufferevent is connecting, then you can't actually stop the
1438 bufferevent from trying to connect with bufferevent_disable(). The
1439 connect will never trigger, since we close the fd, but the timeout
1440 might. That caused an assertion failure in evhttp_connection_fail_.
1442 bufferevent_disable_hard_(evcon->bufev, EV_READ|EV_WRITE);
1444 /* inform interested parties about connection close */
1445 if (evhttp_connected(evcon) && evcon->closecb != NULL)
1446 (*evcon->closecb)(evcon, evcon->closecb_arg);
1448 /** FIXME: manipulating with fd is unwanted */
1449 err = bufferevent_replacefd(evcon->bufev, -1);
1450 EVUTIL_ASSERT(!err && "setfd");
1452 /* we need to clean up any buffered data */
1453 tmp = bufferevent_get_output(evcon->bufev);
1454 err = evbuffer_drain(tmp, -1);
1455 EVUTIL_ASSERT(!err && "drain output");
1456 tmp = bufferevent_get_input(evcon->bufev);
1457 err = evbuffer_drain(tmp, -1);
1458 EVUTIL_ASSERT(!err && "drain input");
1461 /** Reset our connection state
1464 * - disables reading/writing
1465 * - puts us in DISCONNECTED state
1467 * @param hard - hard reset will (@see evhttp_connection_reset_hard_())
1470 evhttp_connection_reset_(struct evhttp_connection *evcon, int hard)
1472 bufferevent_setcb(evcon->bufev, NULL, NULL, NULL, NULL);
1475 evhttp_connection_reset_hard_(evcon);
1478 evcon->flags &= ~EVHTTP_CON_READING_ERROR;
1479 evcon->state = EVCON_DISCONNECTED;
1483 evhttp_connection_start_detectclose(struct evhttp_connection *evcon)
1485 evcon->flags |= EVHTTP_CON_CLOSEDETECT;
1486 bufferevent_enable(evcon->bufev, EV_READ);
1490 evhttp_connection_stop_detectclose(struct evhttp_connection *evcon)
1492 evcon->flags &= ~EVHTTP_CON_CLOSEDETECT;
1493 bufferevent_disable(evcon->bufev, EV_READ);
1497 evhttp_connection_retry(evutil_socket_t fd, short what, void *arg)
1499 struct evhttp_connection *evcon = arg;
1501 evcon->state = EVCON_DISCONNECTED;
1502 evhttp_connection_connect_(evcon);
1506 evhttp_connection_cb_cleanup(struct evhttp_connection *evcon)
1508 struct evcon_requestq requests;
1509 EVUTIL_ASSERT(evcon->flags & EVHTTP_CON_OUTGOING);
1511 evhttp_connection_reset_(evcon, 1);
1513 if (evcon->retry_max < 0 || evcon->retry_cnt < evcon->retry_max) {
1514 struct timeval tv_retry = evcon->initial_retry_timeout;
1516 evtimer_assign(&evcon->retry_ev, evcon->base, evhttp_connection_retry, evcon);
1517 /* XXXX handle failure from evhttp_add_event */
1518 for (i=0; i < evcon->retry_cnt; ++i) {
1519 tv_retry.tv_usec *= 2;
1520 if (tv_retry.tv_usec > 1000000) {
1521 tv_retry.tv_usec -= 1000000;
1522 tv_retry.tv_sec += 1;
1524 tv_retry.tv_sec *= 2;
1525 if (tv_retry.tv_sec > 3600) {
1526 tv_retry.tv_sec = 3600;
1527 tv_retry.tv_usec = 0;
1530 event_add(&evcon->retry_ev, &tv_retry);
1536 * User callback can do evhttp_make_request() on the same
1537 * evcon so new request will be added to evcon->requests. To
1538 * avoid freeing it prematurely we iterate over the copy of
1541 TAILQ_INIT(&requests);
1542 while (TAILQ_FIRST(&evcon->requests) != NULL) {
1543 struct evhttp_request *request = TAILQ_FIRST(&evcon->requests);
1544 TAILQ_REMOVE(&evcon->requests, request, next);
1545 TAILQ_INSERT_TAIL(&requests, request, next);
1548 /* for now, we just signal all requests by executing their callbacks */
1549 while (TAILQ_FIRST(&requests) != NULL) {
1550 struct evhttp_request *request = TAILQ_FIRST(&requests);
1551 TAILQ_REMOVE(&requests, request, next);
1552 request->evcon = NULL;
1554 /* we might want to set an error here */
1555 request->cb(request, request->cb_arg);
1556 evhttp_request_free_auto(request);
1559 if (TAILQ_FIRST(&evcon->requests) == NULL
1560 && (evcon->flags & EVHTTP_CON_AUTOFREE)) {
1561 evhttp_connection_free(evcon);
1567 evhttp_connection_read_on_write_error(struct evhttp_connection *evcon,
1568 struct evhttp_request *req)
1570 struct evbuffer *buf;
1572 /** Second time, we can't read anything */
1573 if (evcon->flags & EVHTTP_CON_READING_ERROR) {
1574 evcon->flags &= ~EVHTTP_CON_READING_ERROR;
1575 evhttp_connection_fail_(evcon, EVREQ_HTTP_EOF);
1579 req->kind = EVHTTP_RESPONSE;
1581 buf = bufferevent_get_output(evcon->bufev);
1582 evbuffer_unfreeze(buf, 1);
1583 evbuffer_drain(buf, evbuffer_get_length(buf));
1584 evbuffer_freeze(buf, 1);
1586 evhttp_start_read_(evcon);
1587 evcon->flags |= EVHTTP_CON_READING_ERROR;
1591 evhttp_error_cb(struct bufferevent *bufev, short what, void *arg)
1593 struct evhttp_connection *evcon = arg;
1594 struct evhttp_request *req = TAILQ_FIRST(&evcon->requests);
1596 switch (evcon->state) {
1597 case EVCON_CONNECTING:
1598 if (what & BEV_EVENT_TIMEOUT) {
1599 event_debug(("%s: connection timeout for \"%s:%d\" on "
1601 __func__, evcon->address, evcon->port,
1602 EV_SOCK_ARG(bufferevent_getfd(bufev))));
1603 evhttp_connection_cb_cleanup(evcon);
1608 case EVCON_READING_BODY:
1609 if (!req->chunked && req->ntoread < 0
1610 && what == (BEV_EVENT_READING|BEV_EVENT_EOF)) {
1611 /* EOF on read can be benign */
1612 evhttp_connection_done(evcon);
1617 case EVCON_DISCONNECTED:
1619 case EVCON_READING_FIRSTLINE:
1620 case EVCON_READING_HEADERS:
1621 case EVCON_READING_TRAILER:
1627 /* when we are in close detect mode, a read error means that
1628 * the other side closed their connection.
1630 if (evcon->flags & EVHTTP_CON_CLOSEDETECT) {
1631 evcon->flags &= ~EVHTTP_CON_CLOSEDETECT;
1632 EVUTIL_ASSERT(evcon->http_server == NULL);
1633 /* For connections from the client, we just
1634 * reset the connection so that it becomes
1637 EVUTIL_ASSERT(evcon->state == EVCON_IDLE);
1638 evhttp_connection_reset_(evcon, 1);
1641 * If we have no more requests that need completion
1642 * and we want to auto-free the connection when all
1643 * requests have been completed.
1645 if (TAILQ_FIRST(&evcon->requests) == NULL
1646 && (evcon->flags & EVHTTP_CON_OUTGOING)
1647 && (evcon->flags & EVHTTP_CON_AUTOFREE)) {
1648 evhttp_connection_free(evcon);
1653 if (what & BEV_EVENT_TIMEOUT) {
1654 evhttp_connection_fail_(evcon, EVREQ_HTTP_TIMEOUT);
1655 } else if (what & (BEV_EVENT_EOF|BEV_EVENT_ERROR)) {
1656 if (what & BEV_EVENT_WRITING &&
1657 evcon->flags & EVHTTP_CON_READ_ON_WRITE_ERROR) {
1658 evhttp_connection_read_on_write_error(evcon, req);
1662 if (what & BEV_EVENT_READING &&
1663 evcon->flags & EVHTTP_CON_READ_ON_WRITE_ERROR &&
1664 evbuffer_get_length(bufferevent_get_input(bufev))) {
1665 event_deferred_cb_schedule_(get_deferred_queue(evcon),
1666 &evcon->read_more_deferred_cb);
1670 evhttp_connection_fail_(evcon, EVREQ_HTTP_EOF);
1671 } else if (what == BEV_EVENT_CONNECTED) {
1673 evhttp_connection_fail_(evcon, EVREQ_HTTP_BUFFER_ERROR);
1678 * Event callback for asynchronous connection attempt.
1681 evhttp_connection_cb(struct bufferevent *bufev, short what, void *arg)
1683 struct evhttp_connection *evcon = arg;
1685 if (!(what & BEV_EVENT_CONNECTED)) {
1686 /* some operating systems return ECONNREFUSED immediately
1687 * when connecting to a local address. the cleanup is going
1688 * to reschedule this function call.
1691 if (errno == ECONNREFUSED)
1694 evhttp_error_cb(bufev, what, arg);
1698 /* We are connected to the server now */
1699 event_debug(("%s: connected to \"%s:%d\" on "EV_SOCK_FMT"\n",
1700 __func__, evcon->address, evcon->port,
1701 EV_SOCK_ARG(bufferevent_getfd(bufev))));
1703 /* Reset the retry count as we were successful in connecting */
1704 evcon->retry_cnt = 0;
1705 evcon->state = EVCON_IDLE;
1707 /* reset the bufferevent cbs */
1708 bufferevent_setcb(evcon->bufev,
1714 bufferevent_set_timeouts(evcon->bufev,
1715 &evcon->timeout_read, &evcon->timeout_write);
1717 /* try to start requests that have queued up on this connection */
1718 evhttp_request_dispatch(evcon);
1722 evhttp_connection_cb_cleanup(evcon);
1726 * Check if we got a valid response code.
1730 evhttp_valid_response_code(int code)
1739 evhttp_parse_http_version(const char *version, struct evhttp_request *req)
1743 int n = sscanf(version, "HTTP/%d.%d%c", &major, &minor, &ch);
1744 if (n != 2 || major > 1) {
1745 event_debug(("%s: bad version %s on message %p from %s",
1746 __func__, version, (void *)req, req->remote_host));
1754 /* Parses the status line of a web server */
1757 evhttp_parse_response_line(struct evhttp_request *req, char *line)
1761 const char *readable = "";
1763 protocol = strsep(&line, " ");
1766 number = strsep(&line, " ");
1770 if (evhttp_parse_http_version(protocol, req) < 0)
1773 req->response_code = atoi(number);
1774 if (!evhttp_valid_response_code(req->response_code)) {
1775 event_debug(("%s: bad response code \"%s\"",
1780 if (req->response_code_line != NULL)
1781 mm_free(req->response_code_line);
1782 if ((req->response_code_line = mm_strdup(readable)) == NULL) {
1783 event_warn("%s: strdup", __func__);
1790 /* Parse the first line of a HTTP request */
1793 evhttp_parse_request_line(struct evhttp_request *req, char *line, size_t len)
1795 char *eos = line + len;
1799 const char *hostname;
1802 enum evhttp_cmd_type type = 0;
1804 while (eos > line && *(eos-1) == ' ') {
1809 if (len < strlen("GET / HTTP/1.0"))
1812 /* Parse the request line */
1813 method = strsep(&line, " ");
1817 version = strrchr(uri, ' ');
1818 if (!version || uri == version)
1823 method_len = (uri - method) - 1;
1826 switch (method_len) {
1828 /* The length of the method string is 3, meaning it can only be one of two methods: GET or PUT */
1830 /* Since both GET and PUT share the same character 'T' at the end,
1831 * if the string doesn't have 'T', we can immediately determine this
1832 * is an invalid HTTP method */
1834 if (method[2] != 'T') {
1840 /* This first byte is 'G', so make sure the next byte is
1841 * 'E', if it isn't then this isn't a valid method */
1843 if (method[1] == 'E') {
1844 type = EVHTTP_REQ_GET;
1849 /* First byte is P, check second byte for 'U', if not,
1850 * we know it's an invalid method */
1851 if (method[1] == 'U') {
1852 type = EVHTTP_REQ_PUT;
1860 /* The method length is 4 bytes, leaving only the methods POST, HEAD, LOCK, COPY and MOVE */
1863 if (method[3] == 'T' && method[2] == 'S' && method[1] == 'O') {
1864 type = EVHTTP_REQ_POST;
1868 if (method[3] == 'D' && method[2] == 'A' && method[1] == 'E') {
1869 type = EVHTTP_REQ_HEAD;
1873 if (method[3] == 'K' && method[2] == 'C' && method[1] == 'O') {
1874 type = EVHTTP_REQ_LOCK;
1878 if (method[3] == 'Y' && method[2] == 'P' && method[1] == 'O') {
1879 type = EVHTTP_REQ_COPY;
1883 if (method[3] == 'E' && method[2] == 'V' && method[1] == 'O') {
1884 type = EVHTTP_REQ_MOVE;
1892 /* Method length is 5 bytes, which can only encompass PATCH, TRACE and MKCOL */
1895 if (method[4] == 'H' && method[3] == 'C' && method[2] == 'T' && method[1] == 'A') {
1896 type = EVHTTP_REQ_PATCH;
1900 if (method[4] == 'E' && method[3] == 'C' && method[2] == 'A' && method[1] == 'R') {
1901 type = EVHTTP_REQ_TRACE;
1906 if (method[4] == 'L' && method[3] == 'O' && method[2] == 'C' && method[1] == 'K') {
1907 type = EVHTTP_REQ_MKCOL;
1915 /* Method length is 6, only valid methods 6 bytes in length is DELETE and UNLOCK */
1918 if (method[5] == 'E' && method[4] == 'T' && method[3] == 'E' &&
1919 method[2] == 'L' && method[1] == 'E') {
1920 type = EVHTTP_REQ_DELETE;
1924 if (method[5] == 'K' && method[4] == 'C' && method[3] == 'O' &&
1925 method[2] == 'L' && method[1] == 'N') {
1926 type = EVHTTP_REQ_UNLOCK;
1934 /* Method length is 7, only valid methods are "OPTIONS" and "CONNECT" */
1937 if (method[6] == 'S' && method[5] == 'N' && method[4] == 'O' &&
1938 method[3] == 'I' && method[2] == 'T' && method[1] == 'P') {
1939 type = EVHTTP_REQ_OPTIONS;
1944 if (method[6] == 'T' && method[5] == 'C' && method[4] == 'E' &&
1945 method[3] == 'N' && method[2] == 'N' && method[1] == 'O') {
1946 type = EVHTTP_REQ_CONNECT;
1955 /* Method length is 8, only valid method 8 bytes in length is PROPFIND */
1957 /* If the first byte isn't 'P' then it's invalid */
1958 if (*method != 'P') {
1962 if (method[7] == 'D' && method[6] == 'N' && method[5] == 'I' &&
1963 method[4] == 'F' && method[3] == 'P' && method[2] == 'O' &&
1965 type = EVHTTP_REQ_PROPFIND;
1970 /* Method length is 9, only valid method 9 bytes in length is PROPPATCH */
1972 /* If the first byte isn't 'P' then it's invalid */
1973 if (*method != 'P') {
1977 if (method[8] == 'H' && method[7] == 'C' && method[6] == 'T' &&
1978 method[5] == 'A' && method[4] == 'P' && method[3] == 'P' &&
1979 method[2] == 'O' && method[1] == 'R') {
1980 type = EVHTTP_REQ_PROPPATCH;
1987 /* check extended methods, we only care about the
1988 * type set by the cmp function if the cmp function
1989 * returns a 0 value.
1991 struct evhttp_ext_method ext_method;
1993 ext_method.method = method;
1994 ext_method.type = 0;
1995 ext_method.flags = 0;
1997 if (req->evcon->ext_method_cmp &&
1998 req->evcon->ext_method_cmp(&ext_method) == 0) {
1999 /* make sure the other fields in ext_method are
2000 * not changed by the callback.
2002 if (strcmp(ext_method.method, method) != 0) {
2003 event_warn("%s: modifying the 'method' field of ext_method_cmp's "
2004 "parameter is not allowed", __func__);
2007 if (ext_method.flags != 0) {
2008 event_warn("%s: modifying the 'flags' field of ext_method_cmp's "
2009 "parameter is not allowed", __func__);
2012 type = ext_method.type;
2017 event_debug(("%s: bad method %s on request %p from %s",
2018 __func__, method, (void *)req, req->remote_host));
2019 /* No error yet; we'll give a better error later when
2020 * we see that req->type is unsupported. */
2025 if (evhttp_parse_http_version(version, req) < 0)
2028 if ((req->uri = mm_strdup(uri)) == NULL) {
2029 event_debug(("%s: mm_strdup", __func__));
2033 if (type == EVHTTP_REQ_CONNECT) {
2034 if ((req->uri_elems = evhttp_uri_parse_authority(req->uri, 0)) == NULL) {
2038 if ((req->uri_elems = evhttp_uri_parse_with_flags(req->uri,
2039 EVHTTP_URI_NONCONFORMANT)) == NULL) {
2044 /* If we have an absolute-URI, check to see if it is an http request
2045 for a known vhost or server alias. If we don't know about this
2046 host, we consider it a proxy request. */
2047 scheme = evhttp_uri_get_scheme(req->uri_elems);
2048 hostname = evhttp_uri_get_host(req->uri_elems);
2049 if (scheme && (!evutil_ascii_strcasecmp(scheme, "http") ||
2050 !evutil_ascii_strcasecmp(scheme, "https")) &&
2052 !evhttp_find_vhost(req->evcon->http_server, NULL, hostname))
2053 req->flags |= EVHTTP_PROXY_REQUEST;
2059 evhttp_find_header(const struct evkeyvalq *headers, const char *key)
2061 struct evkeyval *header;
2063 TAILQ_FOREACH(header, headers, next) {
2064 if (evutil_ascii_strcasecmp(header->key, key) == 0)
2065 return (header->value);
2072 evhttp_clear_headers(struct evkeyvalq *headers)
2074 struct evkeyval *header;
2076 for (header = TAILQ_FIRST(headers);
2078 header = TAILQ_FIRST(headers)) {
2079 TAILQ_REMOVE(headers, header, next);
2080 mm_free(header->key);
2081 mm_free(header->value);
2087 * Returns 0, if the header was successfully removed.
2088 * Returns -1, if the header could not be found.
2092 evhttp_remove_header(struct evkeyvalq *headers, const char *key)
2094 struct evkeyval *header;
2096 TAILQ_FOREACH(header, headers, next) {
2097 if (evutil_ascii_strcasecmp(header->key, key) == 0)
2104 /* Free and remove the header that we found */
2105 TAILQ_REMOVE(headers, header, next);
2106 mm_free(header->key);
2107 mm_free(header->value);
2114 evhttp_header_is_valid_value(const char *value)
2116 const char *p = value;
2118 while ((p = strpbrk(p, "\r\n")) != NULL) {
2119 /* we really expect only one new line */
2120 p += strspn(p, "\r\n");
2121 /* we expect a space or tab for continuation */
2122 if (*p != ' ' && *p != '\t')
2129 evhttp_add_header(struct evkeyvalq *headers,
2130 const char *key, const char *value)
2132 event_debug(("%s: key: %s val: %s\n", __func__, key, value));
2134 if (strchr(key, '\r') != NULL || strchr(key, '\n') != NULL) {
2135 /* drop illegal headers */
2136 event_debug(("%s: dropping illegal header key\n", __func__));
2140 if (!evhttp_header_is_valid_value(value)) {
2141 event_debug(("%s: dropping illegal header value\n", __func__));
2145 return (evhttp_add_header_internal(headers, key, value));
2149 evhttp_add_header_internal(struct evkeyvalq *headers,
2150 const char *key, const char *value)
2152 struct evkeyval *header = mm_calloc(1, sizeof(struct evkeyval));
2153 if (header == NULL) {
2154 event_warn("%s: calloc", __func__);
2157 if ((header->key = mm_strdup(key)) == NULL) {
2159 event_warn("%s: strdup", __func__);
2162 if ((header->value = mm_strdup(value)) == NULL) {
2163 mm_free(header->key);
2165 event_warn("%s: strdup", __func__);
2169 TAILQ_INSERT_TAIL(headers, header, next);
2175 * Parses header lines from a request or a response into the specified
2176 * request object given an event buffer.
2179 * DATA_CORRUPTED on error
2180 * MORE_DATA_EXPECTED when we need to read more headers
2181 * ALL_DATA_READ when all headers have been read.
2184 enum message_read_status
2185 evhttp_parse_firstline_(struct evhttp_request *req, struct evbuffer *buffer)
2188 enum message_read_status status = ALL_DATA_READ;
2192 line = evbuffer_readln(buffer, &len, EVBUFFER_EOL_CRLF);
2194 if (req->evcon != NULL &&
2195 evbuffer_get_length(buffer) > req->evcon->max_headers_size)
2196 return (DATA_TOO_LONG);
2198 return (MORE_DATA_EXPECTED);
2201 if (req->evcon != NULL && len > req->evcon->max_headers_size) {
2203 return (DATA_TOO_LONG);
2206 req->headers_size = len;
2208 switch (req->kind) {
2209 case EVHTTP_REQUEST:
2210 if (evhttp_parse_request_line(req, line, len) == -1)
2211 status = DATA_CORRUPTED;
2213 case EVHTTP_RESPONSE:
2214 if (evhttp_parse_response_line(req, line) == -1)
2215 status = DATA_CORRUPTED;
2218 status = DATA_CORRUPTED;
2226 evhttp_append_to_last_header(struct evkeyvalq *headers, char *line)
2228 struct evkeyval *header = TAILQ_LAST(headers, evkeyvalq);
2230 size_t old_len, line_len;
2235 old_len = strlen(header->value);
2237 /* Strip space from start and end of line. */
2238 while (*line == ' ' || *line == '\t')
2240 evutil_rtrim_lws_(line);
2242 line_len = strlen(line);
2244 newval = mm_realloc(header->value, old_len + line_len + 2);
2248 newval[old_len] = ' ';
2249 memcpy(newval + old_len + 1, line, line_len + 1);
2250 header->value = newval;
2255 enum message_read_status
2256 evhttp_parse_headers_(struct evhttp_request *req, struct evbuffer* buffer)
2258 enum message_read_status errcode = DATA_CORRUPTED;
2260 enum message_read_status status = MORE_DATA_EXPECTED;
2262 struct evkeyvalq* headers = req->input_headers;
2264 while ((line = evbuffer_readln(buffer, &len, EVBUFFER_EOL_CRLF))
2266 char *skey, *svalue;
2268 req->headers_size += len;
2270 if (req->evcon != NULL &&
2271 req->headers_size > req->evcon->max_headers_size) {
2272 errcode = DATA_TOO_LONG;
2276 if (*line == '\0') { /* Last header - Done */
2277 status = ALL_DATA_READ;
2282 /* Check if this is a continuation line */
2283 if (*line == ' ' || *line == '\t') {
2284 if (evhttp_append_to_last_header(headers, line) == -1)
2290 /* Processing of header lines */
2292 skey = strsep(&svalue, ":");
2296 svalue += strspn(svalue, " ");
2297 evutil_rtrim_lws_(svalue);
2299 if (evhttp_add_header(headers, skey, svalue) == -1)
2305 if (status == MORE_DATA_EXPECTED) {
2306 if (req->evcon != NULL &&
2307 req->headers_size + evbuffer_get_length(buffer) > req->evcon->max_headers_size)
2308 return (DATA_TOO_LONG);
2319 evhttp_get_body_length(struct evhttp_request *req)
2321 struct evkeyvalq *headers = req->input_headers;
2322 const char *content_length;
2323 const char *connection;
2325 content_length = evhttp_find_header(headers, "Content-Length");
2326 connection = evhttp_find_header(headers, "Connection");
2328 if (content_length == NULL && connection == NULL)
2330 else if (content_length == NULL &&
2331 evutil_ascii_strcasecmp(connection, "Close") != 0) {
2333 } else if (content_length == NULL) {
2337 ev_int64_t ntoread = evutil_strtoll(content_length, &endp, 10);
2338 if (*content_length == '\0' || *endp != '\0' || ntoread < 0) {
2339 event_debug(("%s: illegal content length: %s",
2340 __func__, content_length));
2343 req->ntoread = ntoread;
2346 event_debug(("%s: bytes to read: "EV_I64_FMT" (in buffer "EV_SIZE_FMT")\n",
2347 __func__, EV_I64_ARG(req->ntoread),
2348 EV_SIZE_ARG(evbuffer_get_length(bufferevent_get_input(req->evcon->bufev)))));
2354 evhttp_method_may_have_body_(struct evhttp_connection *evcon, enum evhttp_cmd_type type)
2356 /* NOTE: some version of GCC reports a warning that flags may be uninitialized, hence assignment */
2357 ev_uint16_t flags = 0;
2358 evhttp_method_(evcon, type, &flags);
2359 return (flags & EVHTTP_METHOD_HAS_BODY) ? 1 : 0;
2363 evhttp_get_body(struct evhttp_connection *evcon, struct evhttp_request *req)
2365 const char *xfer_enc;
2367 /* If this is a request without a body, then we are done */
2368 if (req->kind == EVHTTP_REQUEST &&
2369 !evhttp_method_may_have_body_(evcon, req->type)) {
2370 evhttp_connection_done(evcon);
2373 evcon->state = EVCON_READING_BODY;
2374 xfer_enc = evhttp_find_header(req->input_headers, "Transfer-Encoding");
2375 if (xfer_enc != NULL && evutil_ascii_strcasecmp(xfer_enc, "chunked") == 0) {
2379 if (evhttp_get_body_length(req) == -1) {
2380 evhttp_connection_fail_(evcon, EVREQ_HTTP_INVALID_HEADER);
2383 if (req->kind == EVHTTP_REQUEST && req->ntoread < 1) {
2384 /* An incoming request with no content-length and no
2385 * transfer-encoding has no body. */
2386 evhttp_connection_done(evcon);
2391 /* Should we send a 100 Continue status line? */
2392 switch (evhttp_have_expect(req, 1)) {
2394 /* XXX It would be nice to do some sanity
2395 checking here. Does the resource exist?
2396 Should the resource accept post requests? If
2397 no, we should respond with an error. For
2398 now, just optimistically tell the client to
2399 send their message body. */
2400 if (req->ntoread > 0) {
2401 /* ntoread is ev_int64_t, max_body_size is ev_uint64_t */
2402 if ((req->evcon->max_body_size <= EV_INT64_MAX) &&
2403 (ev_uint64_t)req->ntoread > req->evcon->max_body_size) {
2404 evhttp_lingering_fail(evcon, req);
2408 if (!evbuffer_get_length(bufferevent_get_input(evcon->bufev)))
2409 evhttp_send_continue(evcon, req);
2412 evhttp_send_error(req, HTTP_EXPECTATIONFAILED, NULL);
2417 evhttp_read_body(evcon, req);
2418 /* note the request may have been freed in evhttp_read_body */
2422 evhttp_read_firstline(struct evhttp_connection *evcon,
2423 struct evhttp_request *req)
2425 enum message_read_status res;
2427 res = evhttp_parse_firstline_(req, bufferevent_get_input(evcon->bufev));
2428 if (res == DATA_CORRUPTED || res == DATA_TOO_LONG) {
2429 /* Error while reading, terminate */
2430 event_debug(("%s: bad header lines on "EV_SOCK_FMT"\n",
2431 __func__, EV_SOCK_ARG(bufferevent_getfd(evcon->bufev))));
2432 evhttp_connection_fail_(evcon, EVREQ_HTTP_INVALID_HEADER);
2434 } else if (res == MORE_DATA_EXPECTED) {
2435 /* Need more header lines */
2439 evcon->state = EVCON_READING_HEADERS;
2440 evhttp_read_header(evcon, req);
2444 evhttp_read_header(struct evhttp_connection *evcon,
2445 struct evhttp_request *req)
2447 enum message_read_status res;
2448 evutil_socket_t fd = bufferevent_getfd(evcon->bufev);
2450 res = evhttp_parse_headers_(req, bufferevent_get_input(evcon->bufev));
2451 if (res == DATA_CORRUPTED || res == DATA_TOO_LONG) {
2452 /* Error while reading, terminate */
2453 event_debug(("%s: bad header lines on "EV_SOCK_FMT"\n",
2454 __func__, EV_SOCK_ARG(fd)));
2455 evhttp_connection_fail_(evcon, EVREQ_HTTP_INVALID_HEADER);
2457 } else if (res == MORE_DATA_EXPECTED) {
2458 /* Need more header lines */
2462 /* Callback can shut down connection with negative return value */
2463 if (req->header_cb != NULL) {
2464 if ((*req->header_cb)(req, req->cb_arg) < 0) {
2465 evhttp_connection_fail_(evcon, EVREQ_HTTP_EOF);
2470 /* Done reading headers, do the real work */
2471 switch (req->kind) {
2472 case EVHTTP_REQUEST:
2473 event_debug(("%s: checking for post data on "EV_SOCK_FMT"\n",
2474 __func__, EV_SOCK_ARG(fd)));
2475 evhttp_get_body(evcon, req);
2476 /* note the request may have been freed in evhttp_get_body */
2479 case EVHTTP_RESPONSE:
2480 /* Start over if we got a 100 Continue response. */
2481 if (req->response_code == 100) {
2482 struct evbuffer *output = bufferevent_get_output(evcon->bufev);
2483 evbuffer_add_buffer(output, req->output_buffer);
2484 evhttp_start_write_(evcon);
2487 if (!evhttp_response_needs_body(req)) {
2488 event_debug(("%s: skipping body for code %d\n",
2489 __func__, req->response_code));
2490 evhttp_connection_done(evcon);
2492 event_debug(("%s: start of read body for %s on "
2494 __func__, req->remote_host, EV_SOCK_ARG(fd)));
2495 evhttp_get_body(evcon, req);
2496 /* note the request may have been freed in
2497 * evhttp_get_body */
2502 event_warnx("%s: bad header on "EV_SOCK_FMT, __func__,
2504 evhttp_connection_fail_(evcon, EVREQ_HTTP_INVALID_HEADER);
2507 /* request may have been freed above */
2511 * Creates a TCP connection to the specified port and executes a callback
2512 * when finished. Failure or success is indicate by the passed connection
2515 * Although this interface accepts a hostname, it is intended to take
2516 * only numeric hostnames so that non-blocking DNS resolution can
2520 struct evhttp_connection *
2521 evhttp_connection_new(const char *address, ev_uint16_t port)
2523 return (evhttp_connection_base_new(NULL, NULL, address, port));
2526 static struct evhttp_connection *
2527 evhttp_connection_new_(struct event_base *base, struct bufferevent* bev)
2529 struct evhttp_connection *evcon;
2531 if ((evcon = mm_calloc(1, sizeof(struct evhttp_connection))) == NULL) {
2532 event_warn("%s: calloc failed", __func__);
2536 evcon->max_headers_size = EV_SIZE_MAX;
2537 evcon->max_body_size = EV_SIZE_MAX;
2539 evcon->timeout_connect.tv_sec = HTTP_CONNECT_TIMEOUT;
2540 evcon->timeout_read.tv_sec = HTTP_READ_TIMEOUT;
2541 evcon->timeout_write.tv_sec = HTTP_WRITE_TIMEOUT;
2542 evcon->initial_retry_timeout.tv_sec = HTTP_INITIAL_RETRY_TIMEOUT;
2544 evcon->retry_cnt = evcon->retry_max = 0;
2547 if (!(bev = bufferevent_socket_new(base, -1, BEV_OPT_CLOSE_ON_FREE))) {
2548 event_warn("%s: bufferevent_socket_new failed", __func__);
2553 bufferevent_setcb(bev, evhttp_read_cb, evhttp_write_cb, evhttp_error_cb, evcon);
2556 evcon->state = EVCON_DISCONNECTED;
2557 TAILQ_INIT(&evcon->requests);
2561 if (bufferevent_get_base(bev) != base)
2562 bufferevent_base_set(base, evcon->bufev);
2565 event_deferred_cb_init_(
2566 &evcon->read_more_deferred_cb,
2567 bufferevent_get_priority(bev),
2568 evhttp_deferred_read_cb, evcon);
2570 evcon->ai_family = AF_UNSPEC;
2576 evhttp_connection_free(evcon);
2581 struct evhttp_connection *
2582 evhttp_connection_base_bufferevent_unix_new(struct event_base *base, struct bufferevent* bev, const char *unixsocket)
2584 struct evhttp_connection *evcon;
2586 if (strlen(unixsocket) >= member_size(struct sockaddr_un, sun_path)) {
2587 event_warn("%s: unix socket too long", __func__);
2591 evcon = evhttp_connection_new_(base, bev);
2595 if ((evcon->unixsocket = mm_strdup(unixsocket)) == NULL) {
2596 event_warn("%s: strdup failed", __func__);
2600 evcon->ai_family = AF_UNIX;
2605 evhttp_connection_free(evcon);
2610 struct evhttp_connection *
2611 evhttp_connection_base_bufferevent_new(struct event_base *base, struct evdns_base *dnsbase, struct bufferevent* bev,
2612 const char *address, unsigned short port)
2614 struct evhttp_connection *evcon;
2616 event_debug(("Attempting connection to %s:%d\n", address, port));
2618 evcon = evhttp_connection_new_(base, bev);
2622 if ((evcon->address = mm_strdup(address)) == NULL) {
2623 event_warn("%s: strdup failed", __func__);
2627 evcon->dns_base = dnsbase;
2632 evhttp_connection_free(evcon);
2637 struct bufferevent* evhttp_connection_get_bufferevent(struct evhttp_connection *evcon)
2639 return evcon->bufev;
2643 evhttp_connection_get_server(struct evhttp_connection *evcon)
2645 return evcon->http_server;
2648 struct evhttp_connection *
2649 evhttp_connection_base_new(struct event_base *base, struct evdns_base *dnsbase,
2650 const char *address, ev_uint16_t port)
2652 return evhttp_connection_base_bufferevent_new(base, dnsbase, NULL, address, port);
2655 void evhttp_connection_set_family(struct evhttp_connection *evcon,
2658 evcon->ai_family = family;
2661 int evhttp_connection_set_flags(struct evhttp_connection *evcon,
2664 int avail_flags = 0;
2665 avail_flags |= EVHTTP_CON_REUSE_CONNECTED_ADDR;
2666 avail_flags |= EVHTTP_CON_READ_ON_WRITE_ERROR;
2668 if (flags & ~avail_flags || flags > EVHTTP_CON_PUBLIC_FLAGS_END)
2670 evcon->flags &= ~avail_flags;
2672 evcon->flags |= flags;
2678 evhttp_connection_set_ext_method_cmp(struct evhttp_connection *evcon,
2679 evhttp_ext_method_cb cmp)
2681 evcon->ext_method_cmp = cmp;
2685 evhttp_connection_set_base(struct evhttp_connection *evcon,
2686 struct event_base *base)
2688 EVUTIL_ASSERT(evcon->base == NULL);
2689 EVUTIL_ASSERT(evcon->state == EVCON_DISCONNECTED);
2691 bufferevent_base_set(base, evcon->bufev);
2695 evhttp_connection_set_timeout(struct evhttp_connection *evcon,
2698 if (timeout != -1) {
2699 evcon->flags |= EVHTTP_CON_TIMEOUT_ADJUSTED;
2701 evcon->flags &= ~EVHTTP_CON_TIMEOUT_ADJUSTED;
2703 evhttp_set_timeout_(&evcon->timeout_read, timeout, HTTP_READ_TIMEOUT);
2704 evhttp_set_timeout_(&evcon->timeout_write, timeout, HTTP_WRITE_TIMEOUT);
2705 bufferevent_set_timeouts(evcon->bufev,
2706 &evcon->timeout_read, &evcon->timeout_write);
2709 evhttp_connection_set_timeout_tv(struct evhttp_connection *evcon,
2710 const struct timeval* tv)
2713 evcon->flags |= EVHTTP_CON_TIMEOUT_ADJUSTED;
2715 evcon->flags &= ~EVHTTP_CON_TIMEOUT_ADJUSTED;
2717 evhttp_set_timeout_tv_(&evcon->timeout_read, tv, HTTP_READ_TIMEOUT);
2718 evhttp_set_timeout_tv_(&evcon->timeout_write, tv, HTTP_WRITE_TIMEOUT);
2719 bufferevent_set_timeouts(evcon->bufev,
2720 &evcon->timeout_read, &evcon->timeout_write);
2722 void evhttp_connection_set_connect_timeout_tv(struct evhttp_connection *evcon,
2723 const struct timeval *tv)
2725 evcon->flags |= EVHTTP_CON_TIMEOUT_ADJUSTED;
2726 evhttp_set_timeout_tv_(&evcon->timeout_connect, tv, -1);
2727 if (evcon->state == EVCON_CONNECTING)
2728 bufferevent_set_timeouts(evcon->bufev,
2729 &evcon->timeout_connect, &evcon->timeout_connect);
2731 void evhttp_connection_set_read_timeout_tv(struct evhttp_connection *evcon,
2732 const struct timeval *tv)
2734 evcon->flags |= EVHTTP_CON_TIMEOUT_ADJUSTED;
2735 evhttp_set_timeout_tv_(&evcon->timeout_read, tv, -1);
2736 if (evcon->state != EVCON_CONNECTING)
2737 bufferevent_set_timeouts(evcon->bufev,
2738 &evcon->timeout_read, &evcon->timeout_write);
2740 void evhttp_connection_set_write_timeout_tv(struct evhttp_connection *evcon,
2741 const struct timeval *tv)
2743 evcon->flags |= EVHTTP_CON_TIMEOUT_ADJUSTED;
2744 evhttp_set_timeout_tv_(&evcon->timeout_write, tv, -1);
2745 if (evcon->state != EVCON_CONNECTING)
2746 bufferevent_set_timeouts(evcon->bufev,
2747 &evcon->timeout_read, &evcon->timeout_write);
2751 evhttp_connection_set_initial_retry_tv(struct evhttp_connection *evcon,
2752 const struct timeval *tv)
2755 evcon->initial_retry_timeout = *tv;
2757 evutil_timerclear(&evcon->initial_retry_timeout);
2758 evcon->initial_retry_timeout.tv_sec = 2;
2763 evhttp_connection_set_retries(struct evhttp_connection *evcon,
2766 evcon->retry_max = retry_max;
2770 evhttp_connection_set_closecb(struct evhttp_connection *evcon,
2771 void (*cb)(struct evhttp_connection *, void *), void *cbarg)
2773 evcon->closecb = cb;
2774 evcon->closecb_arg = cbarg;
2778 evhttp_connection_get_peer(struct evhttp_connection *evcon,
2779 const char **address, ev_uint16_t *port)
2781 *address = evcon->address;
2782 *port = evcon->port;
2785 const struct sockaddr*
2786 evhttp_connection_get_addr(struct evhttp_connection *evcon)
2788 return bufferevent_socket_get_conn_address_(evcon->bufev);
2792 evhttp_connection_connect_(struct evhttp_connection *evcon)
2794 int old_state = evcon->state;
2795 const char *address = evcon->address;
2796 const struct sockaddr *sa = evhttp_connection_get_addr(evcon);
2799 if (evcon->state == EVCON_CONNECTING)
2802 /* Do not do hard reset, since this will reset the fd, but someone may
2803 * change some options for it (i.e. setsockopt(), #875)
2805 * However don't think that this options will be preserved for all
2806 * connection lifetime, they will be reseted in the following cases:
2807 * - evhttp_connection_set_local_address()
2808 * - evhttp_connection_set_local_port()
2809 * - evhttp_connection_set_retries()
2811 evhttp_connection_reset_(evcon, 0);
2813 EVUTIL_ASSERT(!(evcon->flags & EVHTTP_CON_INCOMING));
2814 evcon->flags |= EVHTTP_CON_OUTGOING;
2816 if (evcon->bind_address || evcon->bind_port) {
2817 int fd = bind_socket(evcon->bind_address, evcon->bind_port,
2820 event_debug(("%s: failed to bind to \"%s\"",
2821 __func__, evcon->bind_address));
2825 if (bufferevent_replacefd(evcon->bufev, fd))
2829 /* Set up a callback for successful connection setup */
2830 bufferevent_setcb(evcon->bufev,
2831 NULL /* evhttp_read_cb */,
2832 NULL /* evhttp_write_cb */,
2833 evhttp_connection_cb,
2835 bufferevent_set_timeouts(evcon->bufev,
2836 &evcon->timeout_connect, &evcon->timeout_connect);
2837 /* make sure that we get a write callback */
2838 if (bufferevent_enable(evcon->bufev, EV_WRITE))
2841 evcon->state = EVCON_CONNECTING;
2843 if (evcon->flags & EVHTTP_CON_REUSE_CONNECTED_ADDR &&
2845 (sa->sa_family == AF_INET || sa->sa_family == AF_INET6)) {
2846 int socklen = sizeof(struct sockaddr_in);
2847 if (sa->sa_family == AF_INET6) {
2848 socklen = sizeof(struct sockaddr_in6);
2850 ret = bufferevent_socket_connect(evcon->bufev, sa, socklen);
2853 else if (evcon->unixsocket) {
2854 struct sockaddr_un sockaddr;
2855 sockaddr.sun_family = AF_UNIX;
2856 strcpy(sockaddr.sun_path, evcon->unixsocket);
2857 ret = bufferevent_socket_connect(evcon->bufev, (const struct sockaddr*)&sockaddr, sizeof(sockaddr));
2861 ret = bufferevent_socket_connect_hostname(evcon->bufev,
2862 evcon->dns_base, evcon->ai_family, address, evcon->port);
2866 evcon->state = old_state;
2867 event_sock_warn(bufferevent_getfd(evcon->bufev), "%s: connection to \"%s\" failed",
2868 __func__, evcon->address);
2869 /* some operating systems return ECONNREFUSED immediately
2870 * when connecting to a local address. the cleanup is going
2871 * to reschedule this function call.
2873 evhttp_connection_cb_cleanup(evcon);
2881 * Starts an HTTP request on the provided evhttp_connection object.
2882 * If the connection object is not connected to the web server already,
2883 * this will start the connection.
2887 evhttp_make_request(struct evhttp_connection *evcon,
2888 struct evhttp_request *req,
2889 enum evhttp_cmd_type type, const char *uri)
2891 /* We are making a request */
2892 req->kind = EVHTTP_REQUEST;
2894 if (req->uri != NULL)
2896 if ((req->uri = mm_strdup(uri)) == NULL) {
2897 event_warn("%s: strdup", __func__);
2898 evhttp_request_free_auto(req);
2902 /* Set the protocol version if it is not supplied */
2903 if (!req->major && !req->minor) {
2908 EVUTIL_ASSERT(req->evcon == NULL);
2910 EVUTIL_ASSERT(!(req->flags & EVHTTP_REQ_OWN_CONNECTION));
2912 TAILQ_INSERT_TAIL(&evcon->requests, req, next);
2914 /* We do not want to conflict with retry_ev */
2915 if (evcon->retry_cnt)
2918 /* If the connection object is not connected; make it so */
2919 if (!evhttp_connected(evcon)) {
2920 int res = evhttp_connection_connect_(evcon);
2921 /* evhttp_connection_fail_(), which is called through
2922 * evhttp_connection_connect_(), assumes that req lies in
2923 * evcon->requests. Thus, enqueue the request in advance and
2924 * remove it in the error case. */
2926 TAILQ_REMOVE(&evcon->requests, req, next);
2932 * If it's connected already and we are the first in the queue,
2933 * then we can dispatch this request immediately. Otherwise, it
2934 * will be dispatched once the pending requests are completed.
2936 if (TAILQ_FIRST(&evcon->requests) == req)
2937 evhttp_request_dispatch(evcon);
2943 evhttp_cancel_request(struct evhttp_request *req)
2945 struct evhttp_connection *evcon = req->evcon;
2946 if (evcon != NULL) {
2947 /* We need to remove it from the connection */
2948 if (TAILQ_FIRST(&evcon->requests) == req) {
2949 /* it's currently being worked on, so reset
2952 evhttp_connection_fail_(evcon,
2953 EVREQ_HTTP_REQUEST_CANCEL);
2955 /* connection fail freed the request */
2958 /* otherwise, we can just remove it from the
2961 TAILQ_REMOVE(&evcon->requests, req, next);
2965 evhttp_request_free_auto(req);
2969 * Reads data from file descriptor into request structure
2970 * Request structure needs to be set up correctly.
2974 evhttp_start_read_(struct evhttp_connection *evcon)
2976 bufferevent_disable(evcon->bufev, EV_WRITE);
2977 bufferevent_enable(evcon->bufev, EV_READ);
2979 evcon->state = EVCON_READING_FIRSTLINE;
2980 /* Reset the bufferevent callbacks */
2981 bufferevent_setcb(evcon->bufev,
2987 /* If there's still data pending, process it next time through the
2988 * loop. Don't do it now; that could get recusive. */
2989 if (evbuffer_get_length(bufferevent_get_input(evcon->bufev))) {
2990 event_deferred_cb_schedule_(get_deferred_queue(evcon),
2991 &evcon->read_more_deferred_cb);
2996 evhttp_start_write_(struct evhttp_connection *evcon)
2998 bufferevent_disable(evcon->bufev, EV_WRITE);
2999 bufferevent_enable(evcon->bufev, EV_READ);
3001 evcon->state = EVCON_WRITING;
3002 evhttp_write_buffer(evcon, evhttp_write_connectioncb, NULL);
3006 evhttp_send_done(struct evhttp_connection *evcon, void *arg)
3009 struct evhttp_request *req = TAILQ_FIRST(&evcon->requests);
3010 TAILQ_REMOVE(&evcon->requests, req, next);
3012 if (req->on_complete_cb != NULL) {
3013 req->on_complete_cb(req, req->on_complete_cb_arg);
3017 (REQ_VERSION_BEFORE(req, 1, 1) &&
3018 !evhttp_is_connection_keepalive(req->input_headers)) ||
3019 evhttp_is_request_connection_close(req);
3021 EVUTIL_ASSERT(req->flags & EVHTTP_REQ_OWN_CONNECTION);
3022 evhttp_request_free(req);
3025 evhttp_connection_free(evcon);
3029 /* we have a persistent connection; try to accept another request. */
3030 if (evhttp_associate_new_request_with_connection(evcon) == -1) {
3031 evhttp_connection_free(evcon);
3036 * Returns an error page.
3039 evhttp_send_error(struct evhttp_request *req, int error, const char *reason)
3041 #define ERR_FORMAT "<html><head>" \
3042 "<title>%d %s</title>" \
3044 "<h1>%d %s</h1>%s" \
3047 struct evbuffer *buf = evbuffer_new();
3048 struct evhttp *http = req->evcon->http_server;
3051 /* if we cannot allocate memory; we just drop the connection */
3052 evhttp_connection_free(req->evcon);
3056 evhttp_response_code_(req, error, reason);
3058 /* Output error using callback for connection's evhttp, if available */
3059 if ((http->errorcb == NULL) ||
3060 ((*http->errorcb)(req, buf, error, reason, http->errorcbarg) < 0))
3062 const char *heading = evhttp_response_phrase_internal(error);
3064 evbuffer_drain(buf, evbuffer_get_length(buf));
3065 evbuffer_add_printf(buf, ERR_FORMAT,
3066 error, heading, error, heading,
3067 (reason ? reason : ""));
3070 evhttp_send_page_(req, buf);
3076 evhttp_send_notfound(struct evhttp_request *req, const char *url)
3078 #define REASON_FORMAT "<p>The requested URL %s was not found on this server.</p>"
3079 char *escaped_url = NULL;
3080 char *reason = NULL;
3083 url = (url != NULL ? url : req->uri);
3085 escaped_url = evhttp_htmlescape(url);
3087 if (escaped_url != NULL) {
3088 reason_len = strlen(REASON_FORMAT)+strlen(escaped_url)+1;
3089 reason = mm_malloc(reason_len);
3092 if ((escaped_url != NULL) && (reason != NULL))
3093 evutil_snprintf(reason, reason_len, REASON_FORMAT, escaped_url);
3095 evhttp_send_error(req, HTTP_NOTFOUND, reason);
3099 if (escaped_url != NULL)
3100 mm_free(escaped_url);
3101 #undef REASON_FORMAT
3105 /* Requires that headers and response code are already set up */
3108 evhttp_send(struct evhttp_request *req, struct evbuffer *databuf)
3110 struct evhttp_connection *evcon = req->evcon;
3112 if (evcon == NULL) {
3113 evhttp_request_free(req);
3117 EVUTIL_ASSERT(TAILQ_FIRST(&evcon->requests) == req);
3119 /* we expect no more calls form the user on this request */
3122 /* xxx: not sure if we really should expose the data buffer this way */
3123 if (databuf != NULL)
3124 evbuffer_add_buffer(req->output_buffer, databuf);
3126 /* Adds headers to the response */
3127 evhttp_make_header(evcon, req);
3129 evhttp_write_buffer(evcon, evhttp_send_done, NULL);
3133 evhttp_send_reply(struct evhttp_request *req, int code, const char *reason,
3134 struct evbuffer *databuf)
3136 evhttp_response_code_(req, code, reason);
3138 evhttp_send(req, databuf);
3142 evhttp_send_reply_start(struct evhttp_request *req, int code,
3145 evhttp_response_code_(req, code, reason);
3147 if (req->evcon == NULL)
3150 if (evhttp_find_header(req->output_headers, "Content-Length") == NULL &&
3151 REQ_VERSION_ATLEAST(req, 1, 1) &&
3152 evhttp_response_needs_body(req)) {
3154 * prefer HTTP/1.1 chunked encoding to closing the connection;
3155 * note RFC 2616 section 4.4 forbids it with Content-Length:
3156 * and it's not necessary then anyway.
3158 evhttp_add_header(req->output_headers, "Transfer-Encoding",
3164 evhttp_make_header(req->evcon, req);
3165 evhttp_write_buffer(req->evcon, NULL, NULL);
3169 evhttp_send_reply_chunk_with_cb(struct evhttp_request *req, struct evbuffer *databuf,
3170 void (*cb)(struct evhttp_connection *, void *), void *arg)
3172 struct evhttp_connection *evcon = req->evcon;
3173 struct evbuffer *output;
3178 output = bufferevent_get_output(evcon->bufev);
3180 if (evbuffer_get_length(databuf) == 0)
3182 if (!evhttp_response_needs_body(req))
3185 evbuffer_add_printf(output, "%x\r\n",
3186 (unsigned)evbuffer_get_length(databuf));
3188 evbuffer_add_buffer(output, databuf);
3190 evbuffer_add(output, "\r\n", 2);
3192 evhttp_write_buffer(evcon, cb, arg);
3195 struct bufferevent *
3196 evhttp_start_ws_(struct evhttp_request *req)
3198 struct evhttp_connection *evcon = req->evcon;
3199 struct bufferevent *bufev;
3201 evhttp_response_code_(req, HTTP_SWITCH_PROTOCOLS, "Switching Protocols");
3203 if (req->evcon == NULL)
3206 evhttp_make_header(req->evcon, req);
3207 evhttp_write_buffer(req->evcon, NULL, NULL);
3209 TAILQ_REMOVE(&evcon->requests, req, next);
3211 bufev = evcon->bufev;
3212 evcon->bufev = NULL;
3213 evcon->closecb = NULL;
3215 evhttp_request_free(req);
3216 evhttp_connection_free(evcon);
3221 evhttp_send_reply_chunk(struct evhttp_request *req, struct evbuffer *databuf)
3223 evhttp_send_reply_chunk_with_cb(req, databuf, NULL, NULL);
3226 evhttp_send_reply_end(struct evhttp_request *req)
3228 struct evhttp_connection *evcon = req->evcon;
3229 struct evbuffer *output;
3231 if (evcon == NULL) {
3232 evhttp_request_free(req);
3236 output = bufferevent_get_output(evcon->bufev);
3238 /* we expect no more calls form the user on this request */
3242 evbuffer_add(output, "0\r\n\r\n", 5);
3243 evhttp_write_buffer(req->evcon, evhttp_send_done, NULL);
3245 } else if (evbuffer_get_length(output) == 0) {
3246 /* let the connection know that we are done with the request */
3247 evhttp_send_done(evcon, NULL);
3249 /* make the callback execute after all data has been written */
3250 evcon->cb = evhttp_send_done;
3251 evcon->cb_arg = NULL;
3255 static const char *informational_phrases[] = {
3256 /* 100 */ "Continue",
3257 /* 101 */ "Switching Protocols"
3260 static const char *success_phrases[] = {
3262 /* 201 */ "Created",
3263 /* 202 */ "Accepted",
3264 /* 203 */ "Non-Authoritative Information",
3265 /* 204 */ "No Content",
3266 /* 205 */ "Reset Content",
3267 /* 206 */ "Partial Content"
3270 static const char *redirection_phrases[] = {
3271 /* 300 */ "Multiple Choices",
3272 /* 301 */ "Moved Permanently",
3274 /* 303 */ "See Other",
3275 /* 304 */ "Not Modified",
3276 /* 305 */ "Use Proxy",
3277 /* 307 */ "Temporary Redirect"
3280 static const char *client_error_phrases[] = {
3281 /* 400 */ "Bad Request",
3282 /* 401 */ "Unauthorized",
3283 /* 402 */ "Payment Required",
3284 /* 403 */ "Forbidden",
3285 /* 404 */ "Not Found",
3286 /* 405 */ "Method Not Allowed",
3287 /* 406 */ "Not Acceptable",
3288 /* 407 */ "Proxy Authentication Required",
3289 /* 408 */ "Request Time-out",
3290 /* 409 */ "Conflict",
3292 /* 411 */ "Length Required",
3293 /* 412 */ "Precondition Failed",
3294 /* 413 */ "Request Entity Too Large",
3295 /* 414 */ "Request-URI Too Large",
3296 /* 415 */ "Unsupported Media Type",
3297 /* 416 */ "Requested range not satisfiable",
3298 /* 417 */ "Expectation Failed"
3301 static const char *server_error_phrases[] = {
3302 /* 500 */ "Internal Server Error",
3303 /* 501 */ "Not Implemented",
3304 /* 502 */ "Bad Gateway",
3305 /* 503 */ "Service Unavailable",
3306 /* 504 */ "Gateway Time-out",
3307 /* 505 */ "HTTP Version not supported"
3310 struct response_class {
3312 size_t num_responses;
3313 const char **responses;
3317 #define MEMBERSOF(x) (sizeof(x)/sizeof(x[0]))
3320 static const struct response_class response_classes[] = {
3321 /* 1xx */ { "Informational", MEMBERSOF(informational_phrases), informational_phrases },
3322 /* 2xx */ { "Success", MEMBERSOF(success_phrases), success_phrases },
3323 /* 3xx */ { "Redirection", MEMBERSOF(redirection_phrases), redirection_phrases },
3324 /* 4xx */ { "Client Error", MEMBERSOF(client_error_phrases), client_error_phrases },
3325 /* 5xx */ { "Server Error", MEMBERSOF(server_error_phrases), server_error_phrases }
3329 evhttp_response_phrase_internal(int code)
3331 int klass = code / 100 - 1;
3332 int subcode = code % 100;
3334 /* Unknown class - can't do any better here */
3335 if (klass < 0 || klass >= (int) MEMBERSOF(response_classes))
3336 return "Unknown Status Class";
3338 /* Unknown sub-code, return class name at least */
3339 if (subcode >= (int) response_classes[klass].num_responses)
3340 return response_classes[klass].name;
3342 return response_classes[klass].responses[subcode];
3346 evhttp_response_code_(struct evhttp_request *req, int code, const char *reason)
3348 req->kind = EVHTTP_RESPONSE;
3349 req->response_code = code;
3350 if (req->response_code_line != NULL)
3351 mm_free(req->response_code_line);
3353 reason = evhttp_response_phrase_internal(code);
3354 req->response_code_line = mm_strdup(reason);
3355 if (req->response_code_line == NULL) {
3356 event_warn("%s: strdup", __func__);
3357 /* XXX what else can we do? */
3362 evhttp_send_page_(struct evhttp_request *req, struct evbuffer *databuf)
3364 if (!req->major || !req->minor) {
3369 if (req->kind != EVHTTP_RESPONSE)
3370 evhttp_response_code_(req, 200, "OK");
3372 evhttp_clear_headers(req->output_headers);
3373 evhttp_add_header(req->output_headers, "Content-Type", "text/html");
3374 evhttp_add_header(req->output_headers, "Connection", "close");
3376 evhttp_send(req, databuf);
3379 static const char uri_chars[256] = {
3381 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3382 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3383 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0,
3384 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,
3386 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3387 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1,
3388 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3389 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0,
3391 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3392 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3393 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3394 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3396 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3397 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3398 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3399 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3402 #define CHAR_IS_UNRESERVED(c) \
3403 (uri_chars[(unsigned char)(c)])
3406 * Helper functions to encode/decode a string for inclusion in a URI.
3407 * The returned string must be freed by the caller.
3410 evhttp_uriencode(const char *uri, ev_ssize_t len, int space_as_plus)
3412 struct evbuffer *buf = evbuffer_new();
3413 const char *p, *end;
3414 char *result = NULL;
3421 if (uri + len < uri) {
3427 size_t slen = strlen(uri);
3429 if (slen >= EV_SSIZE_MAX) {
3430 /* we don't want to mix signed and unsigned */
3434 if (uri + slen < uri) {
3441 for (p = uri; p < end; p++) {
3442 if (CHAR_IS_UNRESERVED(*p)) {
3443 evbuffer_add(buf, p, 1);
3444 } else if (*p == ' ' && space_as_plus) {
3445 evbuffer_add(buf, "+", 1);
3447 evbuffer_add_printf(buf, "%%%02X", (unsigned char)(*p));
3451 evbuffer_add(buf, "", 1); /* NUL-terminator. */
3452 result = mm_malloc(evbuffer_get_length(buf));
3455 evbuffer_remove(buf, result, evbuffer_get_length(buf));
3464 evhttp_encode_uri(const char *str)
3466 return evhttp_uriencode(str, -1, 0);
3470 * @param decode_plus_ctl: if 1, we decode plus into space. If 0, we don't.
3471 * If -1, when true we transform plus to space only after we've seen
3472 * a ?. -1 is deprecated.
3473 * @return the number of bytes written to 'ret'.
3476 evhttp_decode_uri_internal(
3477 const char *uri, size_t length, char *ret, int decode_plus_ctl)
3481 int decode_plus = (decode_plus_ctl == 1) ? 1: 0;
3484 for (i = j = 0; i < length; i++) {
3487 if (decode_plus_ctl < 0)
3489 } else if (c == '+' && decode_plus) {
3491 } else if ((i + 2) < length && c == '%' &&
3492 EVUTIL_ISXDIGIT_(uri[i+1]) && EVUTIL_ISXDIGIT_(uri[i+2])) {
3497 c = (char)strtol(tmp, NULL, 16);
3509 evhttp_decode_uri(const char *uri)
3513 if ((ret = mm_malloc(strlen(uri) + 1)) == NULL) {
3514 event_warn("%s: malloc(%lu)", __func__,
3515 (unsigned long)(strlen(uri) + 1));
3519 evhttp_decode_uri_internal(uri, strlen(uri),
3520 ret, -1 /*always_decode_plus*/);
3526 evhttp_uridecode(const char *uri, int decode_plus, size_t *size_out)
3531 if ((ret = mm_malloc(strlen(uri) + 1)) == NULL) {
3532 event_warn("%s: malloc(%lu)", __func__,
3533 (unsigned long)(strlen(uri) + 1));
3537 n = evhttp_decode_uri_internal(uri, strlen(uri),
3538 ret, !!decode_plus/*always_decode_plus*/);
3541 EVUTIL_ASSERT(n >= 0);
3542 *size_out = (size_t)n;
3549 * Helper function to parse out arguments in a query.
3550 * The arguments are separated by key and value.
3554 evhttp_parse_query_impl(const char *str, struct evkeyvalq *headers,
3555 int is_whole_uri, unsigned flags)
3559 const char *query_part;
3561 struct evhttp_uri *uri=NULL;
3563 TAILQ_INIT(headers);
3566 uri = evhttp_uri_parse(str);
3569 query_part = evhttp_uri_get_query(uri);
3574 /* No arguments - we are done */
3575 if (!query_part || !strlen(query_part)) {
3580 if ((line = mm_strdup(query_part)) == NULL) {
3581 event_warn("%s: strdup", __func__);
3586 while (p != NULL && *p != '\0') {
3587 char *key, *value, *decoded_value;
3590 value = strsep(&p, "&");
3591 key = strsep(&value, "=");
3592 if (flags & EVHTTP_URI_QUERY_NONCONFORMANT) {
3598 if (value == NULL || *key == '\0')
3602 if ((decoded_value = mm_malloc(strlen(value) + 1)) == NULL) {
3603 event_warn("%s: mm_malloc", __func__);
3606 evhttp_decode_uri_internal(value, strlen(value),
3607 decoded_value, 1 /*always_decode_plus*/);
3608 event_debug(("Query Param: %s -> %s\n", key, decoded_value));
3609 if (flags & EVHTTP_URI_QUERY_LAST_VAL)
3610 evhttp_remove_header(headers, key);
3611 err = evhttp_add_header_internal(headers, key, decoded_value);
3612 mm_free(decoded_value);
3620 evhttp_clear_headers(headers);
3625 evhttp_uri_free(uri);
3630 evhttp_parse_query(const char *uri, struct evkeyvalq *headers)
3632 return evhttp_parse_query_impl(uri, headers, 1, 0);
3635 evhttp_parse_query_str(const char *uri, struct evkeyvalq *headers)
3637 return evhttp_parse_query_impl(uri, headers, 0, 0);
3640 evhttp_parse_query_str_flags(const char *uri, struct evkeyvalq *headers, unsigned flags)
3642 return evhttp_parse_query_impl(uri, headers, 0, flags);
3645 static struct evhttp_cb *
3646 evhttp_dispatch_callback(struct httpcbq *callbacks, struct evhttp_request *req)
3648 struct evhttp_cb *cb;
3653 /* Test for different URLs */
3654 path = evhttp_uri_get_path(req->uri_elems);
3655 offset = strlen(path);
3656 if ((translated = mm_malloc(offset + 1)) == NULL)
3658 evhttp_decode_uri_internal(path, offset, translated,
3659 0 /* decode_plus */);
3661 TAILQ_FOREACH(cb, callbacks, next) {
3662 if (!strcmp(cb->what, translated)) {
3663 mm_free(translated);
3668 mm_free(translated);
3674 prefix_suffix_match(const char *pattern, const char *name, int ignorecase)
3679 switch (c = *pattern++) {
3681 return *name == '\0';
3684 while (*name != '\0') {
3685 if (prefix_suffix_match(pattern, name,
3694 EVUTIL_TOLOWER_(c) != EVUTIL_TOLOWER_(*name))
3704 Search the vhost hierarchy beginning with http for a server alias
3705 matching hostname. If a match is found, and outhttp is non-null,
3706 outhttp is set to the matching http object and 1 is returned.
3710 evhttp_find_alias(struct evhttp *http, struct evhttp **outhttp,
3711 const char *hostname)
3713 struct evhttp_server_alias *alias;
3714 struct evhttp *vhost;
3716 TAILQ_FOREACH(alias, &http->aliases, next) {
3717 /* XXX Do we need to handle IP addresses? */
3718 if (!evutil_ascii_strcasecmp(alias->alias, hostname)) {
3725 /* XXX It might be good to avoid recursion here, but I don't
3726 see a way to do that w/o a list. */
3727 TAILQ_FOREACH(vhost, &http->virtualhosts, next_vhost) {
3728 if (evhttp_find_alias(vhost, outhttp, hostname))
3736 Attempts to find the best http object to handle a request for a hostname.
3737 All aliases for the root http object and vhosts are searched for an exact
3738 match. Then, the vhost hierarchy is traversed again for a matching
3741 If an alias or vhost is matched, 1 is returned, and outhttp, if non-null,
3742 is set with the best matching http object. If there are no matches, the
3743 root http object is stored in outhttp and 0 is returned.
3747 evhttp_find_vhost(struct evhttp *http, struct evhttp **outhttp,
3748 const char *hostname)
3750 struct evhttp *vhost;
3751 struct evhttp *oldhttp;
3752 int match_found = 0;
3754 if (evhttp_find_alias(http, outhttp, hostname))
3759 TAILQ_FOREACH(vhost, &http->virtualhosts, next_vhost) {
3760 if (prefix_suffix_match(vhost->vhost_pattern,
3761 hostname, 1 /* ignorecase */)) {
3767 } while (oldhttp != http);
3776 evhttp_handle_request(struct evhttp_request *req, void *arg)
3778 struct evhttp *http = arg;
3779 struct evhttp_cb *cb = NULL;
3780 const char *hostname;
3782 /* we have a new request on which the user needs to take action */
3785 bufferevent_disable(req->evcon->bufev, EV_READ);
3787 if (req->uri == NULL) {
3788 evhttp_send_error(req, req->response_code, NULL);
3792 if ((http->allowed_methods & req->type) == 0) {
3793 event_debug(("Rejecting disallowed method %x (allowed: %x)\n",
3794 (unsigned)req->type, (unsigned)http->allowed_methods));
3795 evhttp_send_error(req, HTTP_NOTIMPLEMENTED, NULL);
3799 /* handle potential virtual hosts */
3800 hostname = evhttp_request_get_host(req);
3801 if (hostname != NULL) {
3802 evhttp_find_vhost(http, &http, hostname);
3805 if ((cb = evhttp_dispatch_callback(&http->callbacks, req)) != NULL) {
3806 (*cb->cb)(req, cb->cbarg);
3810 /* Generic call back */
3812 (*http->gencb)(req, http->gencbarg);
3815 evhttp_send_notfound(req, NULL);
3818 /* Listener callback when a connection arrives at a server. */
3820 accept_socket_cb(struct evconnlistener *listener, evutil_socket_t nfd, struct sockaddr *peer_sa, int peer_socklen, void *arg)
3822 struct evhttp_bound_socket *bound = arg;
3824 struct evhttp *http = bound->http;
3826 struct bufferevent *bev = NULL;
3828 bev = bound->bevcb(http->base, bound->bevcbarg);
3830 evhttp_get_request(http, nfd, peer_sa, peer_socklen, bev);
3834 evhttp_bind_socket(struct evhttp *http, const char *address, ev_uint16_t port)
3836 struct evhttp_bound_socket *bound =
3837 evhttp_bind_socket_with_handle(http, address, port);
3843 struct evhttp_bound_socket *
3844 evhttp_bind_socket_with_handle(struct evhttp *http, const char *address, ev_uint16_t port)
3847 struct evhttp_bound_socket *bound;
3850 if ((fd = bind_socket(address, port, 1 /*reuse*/)) == -1)
3853 if (listen(fd, 128) == -1) {
3854 serrno = EVUTIL_SOCKET_ERROR();
3855 event_sock_warn(fd, "%s: listen", __func__);
3856 evutil_closesocket(fd);
3857 EVUTIL_SET_SOCKET_ERROR(serrno);
3861 bound = evhttp_accept_socket_with_handle(http, fd);
3863 if (bound != NULL) {
3864 event_debug(("Bound to port %d - Awaiting connections ... ",
3873 evhttp_accept_socket(struct evhttp *http, evutil_socket_t fd)
3875 struct evhttp_bound_socket *bound =
3876 evhttp_accept_socket_with_handle(http, fd);
3883 evhttp_foreach_bound_socket(struct evhttp *http,
3884 evhttp_bound_socket_foreach_fn *function,
3887 struct evhttp_bound_socket *bound;
3889 TAILQ_FOREACH(bound, &http->sockets, next)
3890 function(bound, argument);
3893 struct evhttp_bound_socket *
3894 evhttp_accept_socket_with_handle(struct evhttp *http, evutil_socket_t fd)
3896 struct evhttp_bound_socket *bound;
3897 struct evconnlistener *listener;
3899 LEV_OPT_REUSEABLE|LEV_OPT_CLOSE_ON_EXEC|LEV_OPT_CLOSE_ON_FREE;
3901 listener = evconnlistener_new(http->base, NULL, NULL,
3903 0, /* Backlog is '0' because we already said 'listen' */
3908 bound = evhttp_bind_listener(http, listener);
3910 evconnlistener_free(listener);
3916 struct evhttp_bound_socket *
3917 evhttp_bind_listener(struct evhttp *http, struct evconnlistener *listener)
3919 struct evhttp_bound_socket *bound;
3921 bound = mm_malloc(sizeof(struct evhttp_bound_socket));
3925 bound->listener = listener;
3926 bound->bevcb = NULL;
3928 TAILQ_INSERT_TAIL(&http->sockets, bound, next);
3930 evconnlistener_set_cb(listener, accept_socket_cb, bound);
3935 evhttp_bound_socket_get_fd(struct evhttp_bound_socket *bound)
3937 return evconnlistener_get_fd(bound->listener);
3940 struct evconnlistener *
3941 evhttp_bound_socket_get_listener(struct evhttp_bound_socket *bound)
3943 return bound->listener;
3947 evhttp_bound_set_bevcb(struct evhttp_bound_socket *bound,
3948 struct bufferevent* (*cb)(struct event_base *, void *), void *cbarg)
3951 bound->bevcbarg = cbarg;
3955 evhttp_del_accept_socket(struct evhttp *http, struct evhttp_bound_socket *bound)
3957 TAILQ_REMOVE(&http->sockets, bound, next);
3958 evconnlistener_free(bound->listener);
3962 static struct evhttp*
3963 evhttp_new_object(void)
3965 struct evhttp *http = NULL;
3967 if ((http = mm_calloc(1, sizeof(struct evhttp))) == NULL) {
3968 event_warn("%s: calloc", __func__);
3972 evutil_timerclear(&http->timeout_read);
3973 evutil_timerclear(&http->timeout_write);
3975 evhttp_set_max_headers_size(http, EV_SIZE_MAX);
3976 evhttp_set_max_body_size(http, EV_SIZE_MAX);
3977 evhttp_set_default_content_type(http, "text/html; charset=ISO-8859-1");
3978 evhttp_set_allowed_methods(http,
3985 TAILQ_INIT(&http->sockets);
3986 TAILQ_INIT(&http->callbacks);
3987 TAILQ_INIT(&http->connections);
3988 TAILQ_INIT(&http->ws_sessions);
3989 TAILQ_INIT(&http->virtualhosts);
3990 TAILQ_INIT(&http->aliases);
3996 evhttp_new(struct event_base *base)
3998 struct evhttp *http = NULL;
4000 http = evhttp_new_object();
4009 * Start a web server on the specified address and port.
4013 evhttp_start(const char *address, ev_uint16_t port)
4015 struct evhttp *http = NULL;
4017 http = evhttp_new_object();
4020 if (evhttp_bind_socket(http, address, port) == -1) {
4029 evhttp_free(struct evhttp* http)
4031 struct evhttp_cb *http_cb;
4032 struct evhttp_connection *evcon;
4033 struct evws_connection *evws;
4034 struct evhttp_bound_socket *bound;
4035 struct evhttp* vhost;
4036 struct evhttp_server_alias *alias;
4038 /* Remove the accepting part */
4039 while ((bound = TAILQ_FIRST(&http->sockets)) != NULL) {
4040 TAILQ_REMOVE(&http->sockets, bound, next);
4042 evconnlistener_free(bound->listener);
4047 while ((evcon = TAILQ_FIRST(&http->connections)) != NULL) {
4048 /* evhttp_connection_free removes the connection */
4049 evhttp_connection_free(evcon);
4052 while ((evws = TAILQ_FIRST(&http->ws_sessions)) != NULL) {
4053 evws_connection_free(evws);
4056 while ((http_cb = TAILQ_FIRST(&http->callbacks)) != NULL) {
4057 TAILQ_REMOVE(&http->callbacks, http_cb, next);
4058 mm_free(http_cb->what);
4062 while ((vhost = TAILQ_FIRST(&http->virtualhosts)) != NULL) {
4063 TAILQ_REMOVE(&http->virtualhosts, vhost, next_vhost);
4068 if (http->vhost_pattern != NULL)
4069 mm_free(http->vhost_pattern);
4071 while ((alias = TAILQ_FIRST(&http->aliases)) != NULL) {
4072 TAILQ_REMOVE(&http->aliases, alias, next);
4073 mm_free(alias->alias);
4081 evhttp_add_virtual_host(struct evhttp* http, const char *pattern,
4082 struct evhttp* vhost)
4084 /* a vhost can only be a vhost once and should not have bound sockets */
4085 if (vhost->vhost_pattern != NULL ||
4086 TAILQ_FIRST(&vhost->sockets) != NULL)
4089 vhost->vhost_pattern = mm_strdup(pattern);
4090 if (vhost->vhost_pattern == NULL)
4093 TAILQ_INSERT_TAIL(&http->virtualhosts, vhost, next_vhost);
4099 evhttp_remove_virtual_host(struct evhttp* http, struct evhttp* vhost)
4101 if (vhost->vhost_pattern == NULL)
4104 TAILQ_REMOVE(&http->virtualhosts, vhost, next_vhost);
4106 mm_free(vhost->vhost_pattern);
4107 vhost->vhost_pattern = NULL;
4113 evhttp_add_server_alias(struct evhttp *http, const char *alias)
4115 struct evhttp_server_alias *evalias;
4117 evalias = mm_calloc(1, sizeof(*evalias));
4121 evalias->alias = mm_strdup(alias);
4122 if (!evalias->alias) {
4127 TAILQ_INSERT_TAIL(&http->aliases, evalias, next);
4133 evhttp_remove_server_alias(struct evhttp *http, const char *alias)
4135 struct evhttp_server_alias *evalias;
4137 TAILQ_FOREACH(evalias, &http->aliases, next) {
4138 if (evutil_ascii_strcasecmp(evalias->alias, alias) == 0) {
4139 TAILQ_REMOVE(&http->aliases, evalias, next);
4140 mm_free(evalias->alias);
4150 evhttp_set_timeout(struct evhttp* http, int timeout)
4152 evhttp_set_timeout_(&http->timeout_read, timeout, -1);
4153 evhttp_set_timeout_(&http->timeout_write, timeout, -1);
4156 evhttp_set_timeout_tv(struct evhttp* http, const struct timeval* tv)
4158 evhttp_set_timeout_tv_(&http->timeout_read, tv, -1);
4159 evhttp_set_timeout_tv_(&http->timeout_write, tv, -1);
4162 evhttp_set_read_timeout_tv(struct evhttp* http, const struct timeval* tv)
4164 evhttp_set_timeout_tv_(&http->timeout_read, tv, -1);
4167 evhttp_set_write_timeout_tv(struct evhttp* http, const struct timeval* tv)
4169 evhttp_set_timeout_tv_(&http->timeout_write, tv, -1);
4172 int evhttp_set_flags(struct evhttp *http, int flags)
4174 int avail_flags = 0;
4175 avail_flags |= EVHTTP_SERVER_LINGERING_CLOSE;
4177 if (flags & ~avail_flags)
4179 http->flags &= ~avail_flags;
4181 http->flags |= flags;
4187 evhttp_set_max_headers_size(struct evhttp* http, ev_ssize_t max_headers_size)
4189 if (max_headers_size < 0)
4190 http->default_max_headers_size = EV_SIZE_MAX;
4192 http->default_max_headers_size = max_headers_size;
4196 evhttp_set_max_body_size(struct evhttp* http, ev_ssize_t max_body_size)
4198 if (max_body_size < 0)
4199 http->default_max_body_size = EV_UINT64_MAX;
4201 http->default_max_body_size = max_body_size;
4205 evhttp_set_max_connections(struct evhttp* http, int max_connections)
4207 if (max_connections < 0)
4208 http->connection_max = 0;
4210 http->connection_max = max_connections;
4214 evhttp_get_connection_count(struct evhttp* http)
4216 return http->connection_cnt;
4220 evhttp_set_default_content_type(struct evhttp *http,
4221 const char *content_type) {
4222 http->default_content_type = content_type;
4226 evhttp_set_allowed_methods(struct evhttp* http, ev_uint32_t methods)
4228 http->allowed_methods = methods;
4232 evhttp_set_ext_method_cmp(struct evhttp *http, evhttp_ext_method_cb cmp)
4234 http->ext_method_cmp = cmp;
4238 evhttp_set_cb(struct evhttp *http, const char *uri,
4239 void (*cb)(struct evhttp_request *, void *), void *cbarg)
4241 struct evhttp_cb *http_cb;
4243 TAILQ_FOREACH(http_cb, &http->callbacks, next) {
4244 if (strcmp(http_cb->what, uri) == 0)
4248 if ((http_cb = mm_calloc(1, sizeof(struct evhttp_cb))) == NULL) {
4249 event_warn("%s: calloc", __func__);
4253 http_cb->what = mm_strdup(uri);
4254 if (http_cb->what == NULL) {
4255 event_warn("%s: strdup", __func__);
4260 http_cb->cbarg = cbarg;
4262 TAILQ_INSERT_TAIL(&http->callbacks, http_cb, next);
4268 evhttp_del_cb(struct evhttp *http, const char *uri)
4270 struct evhttp_cb *http_cb;
4272 TAILQ_FOREACH(http_cb, &http->callbacks, next) {
4273 if (strcmp(http_cb->what, uri) == 0)
4276 if (http_cb == NULL)
4279 TAILQ_REMOVE(&http->callbacks, http_cb, next);
4280 mm_free(http_cb->what);
4287 evhttp_set_gencb(struct evhttp *http,
4288 void (*cb)(struct evhttp_request *, void *), void *cbarg)
4291 http->gencbarg = cbarg;
4295 evhttp_set_bevcb(struct evhttp *http,
4296 struct bufferevent* (*cb)(struct event_base *, void *), void *cbarg)
4299 http->bevcbarg = cbarg;
4303 evhttp_set_newreqcb(struct evhttp *http,
4304 int (*cb)(struct evhttp_request *, void *), void *cbarg)
4306 http->newreqcb = cb;
4307 http->newreqcbarg = cbarg;
4310 evhttp_set_errorcb(struct evhttp *http,
4311 int (*cb)(struct evhttp_request *, struct evbuffer *, int, const char *, void *),
4315 http->errorcbarg = cbarg;
4319 * Request related functions
4322 struct evhttp_request *
4323 evhttp_request_new(void (*cb)(struct evhttp_request *, void *), void *arg)
4325 struct evhttp_request *req = NULL;
4327 /* Allocate request structure */
4328 if ((req = mm_calloc(1, sizeof(struct evhttp_request))) == NULL) {
4329 event_warn("%s: calloc", __func__);
4333 req->headers_size = 0;
4336 req->kind = EVHTTP_RESPONSE;
4337 req->input_headers = mm_calloc(1, sizeof(struct evkeyvalq));
4338 if (req->input_headers == NULL) {
4339 event_warn("%s: calloc", __func__);
4342 TAILQ_INIT(req->input_headers);
4344 req->output_headers = mm_calloc(1, sizeof(struct evkeyvalq));
4345 if (req->output_headers == NULL) {
4346 event_warn("%s: calloc", __func__);
4349 TAILQ_INIT(req->output_headers);
4351 if ((req->input_buffer = evbuffer_new()) == NULL) {
4352 event_warn("%s: evbuffer_new", __func__);
4356 if ((req->output_buffer = evbuffer_new()) == NULL) {
4357 event_warn("%s: evbuffer_new", __func__);
4368 evhttp_request_free(req);
4373 evhttp_request_free(struct evhttp_request *req)
4375 if ((req->flags & EVHTTP_REQ_DEFER_FREE) != 0) {
4376 req->flags |= EVHTTP_REQ_NEEDS_FREE;
4380 if (req->remote_host != NULL)
4381 mm_free(req->remote_host);
4382 if (req->uri != NULL)
4384 if (req->uri_elems != NULL)
4385 evhttp_uri_free(req->uri_elems);
4386 if (req->response_code_line != NULL)
4387 mm_free(req->response_code_line);
4388 if (req->host_cache != NULL)
4389 mm_free(req->host_cache);
4391 evhttp_clear_headers(req->input_headers);
4392 mm_free(req->input_headers);
4394 evhttp_clear_headers(req->output_headers);
4395 mm_free(req->output_headers);
4397 if (req->input_buffer != NULL)
4398 evbuffer_free(req->input_buffer);
4400 if (req->output_buffer != NULL)
4401 evbuffer_free(req->output_buffer);
4407 evhttp_request_own(struct evhttp_request *req)
4409 req->flags |= EVHTTP_USER_OWNED;
4413 evhttp_request_is_owned(struct evhttp_request *req)
4415 return (req->flags & EVHTTP_USER_OWNED) != 0;
4418 struct evhttp_connection *
4419 evhttp_request_get_connection(struct evhttp_request *req)
4425 evhttp_connection_get_base(struct evhttp_connection *conn)
4431 evhttp_request_set_chunked_cb(struct evhttp_request *req,
4432 void (*cb)(struct evhttp_request *, void *))
4438 evhttp_request_set_header_cb(struct evhttp_request *req,
4439 int (*cb)(struct evhttp_request *, void *))
4441 req->header_cb = cb;
4445 evhttp_request_set_error_cb(struct evhttp_request *req,
4446 void (*cb)(enum evhttp_request_error, void *))
4452 evhttp_request_set_on_complete_cb(struct evhttp_request *req,
4453 void (*cb)(struct evhttp_request *, void *), void *cb_arg)
4455 req->on_complete_cb = cb;
4456 req->on_complete_cb_arg = cb_arg;
4460 * Allows for inspection of the request URI
4464 evhttp_request_get_uri(const struct evhttp_request *req) {
4465 if (req->uri == NULL)
4466 event_debug(("%s: request %p has no uri\n", __func__, (void *)req));
4470 const struct evhttp_uri *
4471 evhttp_request_get_evhttp_uri(const struct evhttp_request *req) {
4472 if (req->uri_elems == NULL)
4473 event_debug(("%s: request %p has no uri elems\n",
4474 __func__, (void *)req));
4475 return (req->uri_elems);
4479 evhttp_request_get_host(struct evhttp_request *req)
4481 const char *host = NULL;
4483 if (req->host_cache)
4484 return req->host_cache;
4487 host = evhttp_uri_get_host(req->uri_elems);
4488 if (!host && req->input_headers) {
4492 host = evhttp_find_header(req->input_headers, "Host");
4493 /* The Host: header may include a port. Remove it here
4494 to be consistent with uri_elems case above. */
4496 p = host + strlen(host) - 1;
4497 while (p > host && EVUTIL_ISDIGIT_(*p))
4499 if (p > host && *p == ':') {
4501 req->host_cache = mm_malloc(len + 1);
4502 if (!req->host_cache) {
4503 event_warn("%s: malloc", __func__);
4506 memcpy(req->host_cache, host, len);
4507 req->host_cache[len] = '\0';
4508 host = req->host_cache;
4516 enum evhttp_cmd_type
4517 evhttp_request_get_command(const struct evhttp_request *req) {
4522 evhttp_request_get_response_code(const struct evhttp_request *req)
4524 return req->response_code;
4528 evhttp_request_get_response_code_line(const struct evhttp_request *req)
4530 return req->response_code_line;
4533 /** Returns the input headers */
4534 struct evkeyvalq *evhttp_request_get_input_headers(struct evhttp_request *req)
4536 return (req->input_headers);
4539 /** Returns the output headers */
4540 struct evkeyvalq *evhttp_request_get_output_headers(struct evhttp_request *req)
4542 return (req->output_headers);
4545 /** Returns the input buffer */
4546 struct evbuffer *evhttp_request_get_input_buffer(struct evhttp_request *req)
4548 return (req->input_buffer);
4551 /** Returns the output buffer */
4552 struct evbuffer *evhttp_request_get_output_buffer(struct evhttp_request *req)
4554 return (req->output_buffer);
4559 * Takes a file descriptor to read a request from.
4560 * The callback is executed once the whole request has been read.
4563 static struct evhttp_connection*
4564 evhttp_get_request_connection(
4565 struct evhttp* http,
4566 evutil_socket_t fd, struct sockaddr *sa, ev_socklen_t salen,
4567 struct bufferevent* bev)
4569 struct evhttp_connection *evcon;
4571 #ifdef EVENT__HAVE_STRUCT_SOCKADDR_UN
4572 if (sa->sa_family == AF_UNIX) {
4573 struct sockaddr_un *sa_un = (struct sockaddr_un *)sa;
4574 sa_un->sun_path[0] = '\0';
4579 if (sa->sa_family == AF_UNIX) {
4580 struct sockaddr_un *sockaddr = (struct sockaddr_un *)sa;
4582 event_debug(("%s: new request from unix socket on "
4583 EV_SOCK_FMT"\n", __func__, EV_SOCK_ARG(fd)));
4585 /* we need a connection object to put the http request on */
4586 if (!bev && http->bevcb != NULL) {
4587 bev = (*http->bevcb)(http->base, http->bevcbarg);
4590 evcon = evhttp_connection_base_bufferevent_unix_new(http->base,
4591 bev, sockaddr->sun_path);
4596 char *hostname = NULL, *portname = NULL;
4598 name_from_addr(sa, salen, &hostname, &portname);
4599 if (hostname == NULL || portname == NULL) {
4600 if (hostname) mm_free(hostname);
4601 if (portname) mm_free(portname);
4605 event_debug(("%s: new request from %s:%s on "EV_SOCK_FMT"\n",
4606 __func__, hostname, portname, EV_SOCK_ARG(fd)));
4608 /* we need a connection object to put the http request on */
4609 if (!bev && http->bevcb != NULL) {
4610 bev = (*http->bevcb)(http->base, http->bevcbarg);
4612 evcon = evhttp_connection_base_bufferevent_new(
4613 http->base, NULL, bev, hostname, atoi(portname));
4620 evcon->max_headers_size = http->default_max_headers_size;
4621 evcon->max_body_size = http->default_max_body_size;
4622 if (http->flags & EVHTTP_SERVER_LINGERING_CLOSE)
4623 evcon->flags |= EVHTTP_CON_LINGERING_CLOSE;
4625 evcon->flags |= EVHTTP_CON_INCOMING;
4626 evcon->state = EVCON_READING_FIRSTLINE;
4628 if (bufferevent_replacefd(evcon->bufev, fd))
4630 if (bufferevent_enable(evcon->bufev, EV_READ))
4632 if (bufferevent_disable(evcon->bufev, EV_WRITE))
4634 bufferevent_socket_set_conn_address_(evcon->bufev, sa, salen);
4639 evhttp_connection_free(evcon);
4644 evhttp_associate_new_request_with_connection(struct evhttp_connection *evcon)
4646 struct evhttp *http = evcon->http_server;
4647 struct evhttp_request *req;
4648 if ((req = evhttp_request_new(evhttp_handle_request, http)) == NULL)
4651 if (evcon->address != NULL) {
4652 if ((req->remote_host = mm_strdup(evcon->address)) == NULL) {
4653 event_warn("%s: strdup", __func__);
4654 evhttp_request_free(req);
4658 req->remote_port = evcon->port;
4660 req->evcon = evcon; /* the request ends up owning the connection */
4661 req->flags |= EVHTTP_REQ_OWN_CONNECTION;
4663 /* We did not present the request to the user yet, so treat it
4664 * as if the user was done with the request. This allows us
4665 * to free the request on a persistent connection if the
4666 * client drops it without sending a request.
4669 req->kind = EVHTTP_REQUEST;
4671 if (http->newreqcb && http->newreqcb(req, http->newreqcbarg) == -1) {
4672 evhttp_request_free(req);
4676 TAILQ_INSERT_TAIL(&evcon->requests, req, next);
4678 evhttp_start_read_(evcon);
4684 evhttp_get_request(struct evhttp *http, evutil_socket_t fd,
4685 struct sockaddr *sa, ev_socklen_t salen,
4686 struct bufferevent *bev)
4688 struct evhttp_connection *evcon;
4690 evcon = evhttp_get_request_connection(http, fd, sa, salen, bev);
4691 if (evcon == NULL) {
4692 event_sock_warn(fd, "%s: cannot get connection on "EV_SOCK_FMT,
4693 __func__, EV_SOCK_ARG(fd));
4694 evutil_closesocket(fd);
4698 /* the timeout can be used by the server to close idle connections */
4699 if (evutil_timerisset(&http->timeout_read))
4700 evhttp_connection_set_read_timeout_tv(evcon, &http->timeout_read);
4701 if (evutil_timerisset(&http->timeout_write))
4702 evhttp_connection_set_write_timeout_tv(evcon, &http->timeout_write);
4705 * if we want to accept more than one request on a connection,
4706 * we need to know which http server it belongs to.
4708 evcon->http_server = http;
4709 evcon->ext_method_cmp = http->ext_method_cmp;
4710 TAILQ_INSERT_TAIL(&http->connections, evcon, next);
4711 http->connection_cnt++;
4713 /* send "service unavailable" if we've reached the connection limit */
4714 if (http->connection_max && http->connection_max < http->connection_cnt) {
4715 struct evhttp_request *req;
4717 if ((req = evhttp_request_new(evhttp_handle_request, http)) == NULL) {
4718 evhttp_connection_free(evcon);
4722 req->evcon = evcon; /* the request owns the connection */
4723 req->flags |= EVHTTP_REQ_OWN_CONNECTION;
4724 req->kind = EVHTTP_REQUEST;
4725 /* note, req->remote_host not needed since we don't read */
4727 TAILQ_INSERT_TAIL(&evcon->requests, req, next);
4729 /* send error to client */
4730 evcon->state = EVCON_WRITING;
4731 bufferevent_enable(evcon->bufev, EV_READ); /* enable close events */
4732 evhttp_send_error(req, HTTP_SERVUNAVAIL, NULL);
4734 } else if (evhttp_associate_new_request_with_connection(evcon) == -1)
4735 evhttp_connection_free(evcon);
4740 * Network helper functions that we do not want to export to the rest of
4745 name_from_addr(struct sockaddr *sa, ev_socklen_t salen,
4746 char **phost, char **pport)
4748 char ntop[NI_MAXHOST];
4749 char strport[NI_MAXSERV];
4752 #ifdef EVENT__HAVE_GETNAMEINFO
4753 ni_result = getnameinfo(sa, salen,
4754 ntop, sizeof(ntop), strport, sizeof(strport),
4755 NI_NUMERICHOST|NI_NUMERICSERV);
4757 if (ni_result != 0) {
4759 /* Windows doesn't have an EAI_SYSTEM. */
4760 if (ni_result == EAI_SYSTEM)
4761 event_err(1, "getnameinfo failed");
4764 event_errx(1, "getnameinfo failed: %s", gai_strerror(ni_result));
4768 ni_result = fake_getnameinfo(sa, salen,
4769 ntop, sizeof(ntop), strport, sizeof(strport),
4770 NI_NUMERICHOST|NI_NUMERICSERV);
4775 *phost = mm_strdup(ntop);
4776 *pport = mm_strdup(strport);
4779 /* Create a non-blocking socket and bind it */
4780 static evutil_socket_t
4781 create_bind_socket_nonblock(struct evutil_addrinfo *ai, int reuse)
4788 /* Create listen socket */
4789 fd = evutil_socket_(ai ? ai->ai_family : AF_INET,
4790 SOCK_STREAM|EVUTIL_SOCK_NONBLOCK|EVUTIL_SOCK_CLOEXEC, 0);
4792 event_sock_warn(-1, "socket");
4796 if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (void *)&on, sizeof(on))<0)
4799 if (evutil_make_listen_socket_reuseable(fd) < 0)
4804 r = bind(fd, ai->ai_addr, (ev_socklen_t)ai->ai_addrlen);
4812 serrno = EVUTIL_SOCKET_ERROR();
4813 evutil_closesocket(fd);
4814 EVUTIL_SET_SOCKET_ERROR(serrno);
4818 static struct evutil_addrinfo *
4819 make_addrinfo(const char *address, ev_uint16_t port)
4821 struct evutil_addrinfo *ai = NULL;
4823 struct evutil_addrinfo hints;
4824 char strport[NI_MAXSERV];
4827 memset(&hints, 0, sizeof(hints));
4828 hints.ai_family = AF_UNSPEC;
4829 hints.ai_socktype = SOCK_STREAM;
4830 /* turn NULL hostname into INADDR_ANY, and skip looking up any address
4831 * types we don't have an interface to connect to. */
4832 hints.ai_flags = EVUTIL_AI_PASSIVE|EVUTIL_AI_ADDRCONFIG;
4833 evutil_snprintf(strport, sizeof(strport), "%d", port);
4834 if ((ai_result = evutil_getaddrinfo(address, strport, &hints, &ai))
4836 if (ai_result == EVUTIL_EAI_SYSTEM)
4837 event_warn("getaddrinfo");
4839 event_warnx("getaddrinfo: %s",
4840 evutil_gai_strerror(ai_result));
4847 static evutil_socket_t
4848 bind_socket(const char *address, ev_uint16_t port, int reuse)
4851 struct evutil_addrinfo *aitop = NULL;
4853 /* just create an unbound socket */
4854 if (address == NULL && port == 0)
4855 return create_bind_socket_nonblock(NULL, 0);
4857 aitop = make_addrinfo(address, port);
4862 fd = create_bind_socket_nonblock(aitop, reuse);
4864 evutil_freeaddrinfo(aitop);
4871 char *scheme; /* scheme; e.g http, ftp etc */
4872 char *userinfo; /* userinfo (typically username:pass), or NULL */
4873 char *host; /* hostname, IP address, or NULL */
4874 int port; /* port, or zero */
4876 char *unixsocket; /* unix domain socket or NULL */
4878 char *path; /* path, or "". */
4879 char *query; /* query, or NULL */
4880 char *fragment; /* fragment or NULL */
4884 evhttp_uri_new(void)
4886 struct evhttp_uri *uri = mm_calloc(sizeof(struct evhttp_uri), 1);
4893 evhttp_uri_set_flags(struct evhttp_uri *uri, unsigned flags)
4898 /* Return true if the string starting at s and ending immediately before eos
4899 * is a valid URI scheme according to RFC3986
4902 scheme_ok(const char *s, const char *eos)
4904 /* scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." ) */
4905 EVUTIL_ASSERT(eos >= s);
4908 if (!EVUTIL_ISALPHA_(*s))
4911 if (! EVUTIL_ISALNUM_(*s) &&
4912 *s != '+' && *s != '-' && *s != '.')
4918 #define SUBDELIMS "!$&'()*+,;="
4920 /* Return true iff [s..eos) is a valid userinfo */
4922 userinfo_ok(const char *s, const char *eos)
4925 if (CHAR_IS_UNRESERVED(*s) ||
4926 strchr(SUBDELIMS, *s) ||
4929 else if (*s == '%' && s+2 < eos &&
4930 EVUTIL_ISXDIGIT_(s[1]) &&
4931 EVUTIL_ISXDIGIT_(s[2]))
4940 regname_ok(const char *s, const char *eos)
4942 while (s && s<eos) {
4943 if (CHAR_IS_UNRESERVED(*s) ||
4944 strchr(SUBDELIMS, *s))
4946 else if (*s == '%' &&
4947 EVUTIL_ISXDIGIT_(s[1]) &&
4948 EVUTIL_ISXDIGIT_(s[2]))
4957 parse_port(const char *s, const char *eos)
4961 if (! EVUTIL_ISDIGIT_(*s))
4963 portnum = (portnum * 10) + (*s - '0');
4966 if (portnum > 65535)
4973 /* returns 0 for bad, 1 for ipv6, 2 for IPvFuture */
4975 bracket_addr_ok(const char *s, const char *eos)
4977 if (s + 3 > eos || *s != '[' || *(eos-1) != ']')
4980 /* IPvFuture, or junk.
4981 "v" 1*HEXDIG "." 1*( unreserved / sub-delims / ":" )
4983 s += 2; /* skip [v */
4985 if (!EVUTIL_ISXDIGIT_(*s)) /*require at least one*/
4987 while (s < eos && *s != '.') {
4988 if (EVUTIL_ISXDIGIT_(*s))
4997 if (CHAR_IS_UNRESERVED(*s) ||
4998 strchr(SUBDELIMS, *s) ||
5008 ev_ssize_t n_chars = eos-s-2;
5009 struct in6_addr in6;
5010 if (n_chars >= 64) /* way too long */
5012 memcpy(buf, s+1, n_chars);
5014 return (evutil_inet_pton(AF_INET6,buf,&in6)==1) ? 1 : 0;
5019 parse_authority(struct evhttp_uri *uri, char *s, char *eos, unsigned *flags)
5026 uri->host = mm_strdup("");
5027 if (uri->host == NULL) {
5028 event_warn("%s: strdup", __func__);
5034 /* Optionally, we start with "userinfo@" */
5036 cp = strchr(s, '@');
5037 if (cp && cp < eos) {
5038 if (! userinfo_ok(s,cp))
5041 uri->userinfo = mm_strdup(s);
5042 if (uri->userinfo == NULL) {
5043 event_warn("%s: strdup", __func__);
5051 if (*flags & EVHTTP_URI_UNIX_SOCKET && !strncmp(cp, "unix:", 5)) {
5052 char *e = strchr(cp + 5, ':');
5055 uri->unixsocket = mm_strdup(cp + 5);
5063 /* Optionally, we end with ":port" */
5064 for (port=eos-1; port >= cp && EVUTIL_ISDIGIT_(*port); --port)
5066 if (port >= cp && *port == ':') {
5067 if (port+1 == eos) /* Leave port unspecified; the RFC allows a
5070 else if ((uri->port = parse_port(port+1, eos))<0)
5074 /* Now, cp..eos holds the "host" port, which can be an IPv4Address,
5075 * an IP-Literal, or a reg-name */
5076 EVUTIL_ASSERT(eos >= cp);
5078 if (*cp == '[' && eos >= cp+2 && *(eos-1) == ']') {
5079 /* IPv6address, IP-Literal, or junk. */
5080 if (! bracket_addr_ok(cp, eos))
5082 if (*flags & EVHTTP_URI_HOST_STRIP_BRACKETS)
5085 /* Make sure the host part is ok. */
5086 if (! regname_ok(cp,eos)) /* Match IPv4Address or reg-name */
5090 uri->host = mm_malloc(len+1);
5091 if (uri->host == NULL) {
5092 event_warn("%s: malloc", __func__);
5095 if (*cp == '[' && *flags & EVHTTP_URI_HOST_STRIP_BRACKETS) {
5096 memcpy(uri->host, cp+1, len);
5097 *flags |= _EVHTTP_URI_HOST_HAS_BRACKETS;
5099 memcpy(uri->host, cp, len);
5101 uri->host[len] = '\0';
5107 end_of_authority(char *cp)
5110 if (*cp == '?' || *cp == '#' || *cp == '/')
5123 /* Return the character after the longest prefix of 'cp' that matches...
5124 * *pchar / "/" if allow_qchars is false, or
5125 * *(pchar / "/" / "?") if allow_qchars is true.
5128 end_of_path(char *cp, enum uri_part part, unsigned flags)
5130 if (flags & EVHTTP_URI_NONCONFORMANT) {
5131 /* If NONCONFORMANT:
5132 * Path is everything up to a # or ? or nul.
5133 * Query is everything up a # or nul
5134 * Fragment is everything up to a nul.
5138 while (*cp && *cp != '#' && *cp != '?')
5142 while (*cp && *cp != '#')
5153 if (CHAR_IS_UNRESERVED(*cp) ||
5154 strchr(SUBDELIMS, *cp) ||
5155 *cp == ':' || *cp == '@' || *cp == '/')
5157 else if (*cp == '%' && EVUTIL_ISXDIGIT_(cp[1]) &&
5158 EVUTIL_ISXDIGIT_(cp[2]))
5160 else if (*cp == '?' && part != PART_PATH)
5169 path_matches_noscheme(const char *cp)
5174 else if (*cp == '/')
5182 evhttp_uri_parse(const char *source_uri)
5184 return evhttp_uri_parse_with_flags(source_uri, 0);
5188 evhttp_uri_parse_with_flags(const char *source_uri, unsigned flags)
5190 char *readbuf = NULL, *readp = NULL, *token = NULL, *query = NULL;
5191 char *path = NULL, *fragment = NULL;
5192 int got_authority = 0;
5194 struct evhttp_uri *uri = mm_calloc(1, sizeof(struct evhttp_uri));
5196 event_warn("%s: calloc", __func__);
5202 readbuf = mm_strdup(source_uri);
5203 if (readbuf == NULL) {
5204 event_warn("%s: strdup", __func__);
5211 /* We try to follow RFC3986 here as much as we can, and match
5214 URI = scheme ":" hier-part [ "?" query ] [ "#" fragment ]
5216 relative-ref = relative-part [ "?" query ] [ "#" fragment ]
5220 token = strchr(readp, ':');
5221 if (token && scheme_ok(readp,token)) {
5223 uri->scheme = mm_strdup(readp);
5224 if (uri->scheme == NULL) {
5225 event_warn("%s: strdup", __func__);
5228 readp = token+1; /* eat : */
5231 /* 2. Optionally, "//" then an 'authority' part. */
5232 if (readp[0]=='/' && readp[1] == '/') {
5236 path = end_of_authority(readp);
5237 if (parse_authority(uri, authority, path, &uri->flags) < 0)
5243 /* 3. Query: path-abempty, path-absolute, path-rootless, or path-empty
5246 readp = end_of_path(path, PART_PATH, flags);
5249 if (*readp == '?') {
5253 readp = end_of_path(readp, PART_QUERY, flags);
5256 if (*readp == '#') {
5260 readp = end_of_path(readp, PART_FRAGMENT, flags);
5262 if (*readp != '\0') {
5266 /* These next two cases may be unreachable; I'm leaving them
5267 * in to be defensive. */
5268 /* If you didn't get an authority, the path can't begin with "//" */
5269 if (!got_authority && path[0]=='/' && path[1]=='/')
5271 /* If you did get an authority, the path must begin with "/" or be
5273 if (got_authority && path[0] != '/' && path[0] != '\0')
5275 /* (End of maybe-unreachable cases) */
5277 /* If there was no scheme, the first part of the path (if any) must
5278 * have no colon in it. */
5279 if (! uri->scheme && !path_matches_noscheme(path))
5282 EVUTIL_ASSERT(path);
5283 uri->path = mm_strdup(path);
5284 if (uri->path == NULL) {
5285 event_warn("%s: strdup", __func__);
5290 uri->query = mm_strdup(query);
5291 if (uri->query == NULL) {
5292 event_warn("%s: strdup", __func__);
5297 uri->fragment = mm_strdup(fragment);
5298 if (uri->fragment == NULL) {
5299 event_warn("%s: strdup", __func__);
5309 evhttp_uri_free(uri);
5315 static struct evhttp_uri *
5316 evhttp_uri_parse_authority(char *source_uri, unsigned flags)
5318 struct evhttp_uri *uri = mm_calloc(1, sizeof(struct evhttp_uri));
5322 event_warn("%s: calloc", __func__);
5328 end = end_of_authority(source_uri);
5329 if (parse_authority(uri, source_uri, end, &uri->flags) < 0)
5332 uri->path = mm_strdup("");
5333 if (uri->path == NULL) {
5334 event_warn("%s: strdup", __func__);
5341 evhttp_uri_free(uri);
5346 evhttp_uri_free(struct evhttp_uri *uri)
5348 #define URI_FREE_STR_(f) \
5353 URI_FREE_STR_(scheme);
5354 URI_FREE_STR_(userinfo);
5355 URI_FREE_STR_(host);
5357 URI_FREE_STR_(unixsocket);
5359 URI_FREE_STR_(path);
5360 URI_FREE_STR_(query);
5361 URI_FREE_STR_(fragment);
5364 #undef URI_FREE_STR_
5368 evhttp_uri_join(struct evhttp_uri *uri, char *buf, size_t limit)
5370 struct evbuffer *tmp = 0;
5371 size_t joined_size = 0;
5372 char *output = NULL;
5374 #define URI_ADD_(f) evbuffer_add(tmp, uri->f, strlen(uri->f))
5376 if (!uri || !buf || !limit)
5379 tmp = evbuffer_new();
5385 evbuffer_add(tmp, ":", 1);
5388 if (uri->unixsocket) {
5389 evbuffer_add(tmp, "//", 2);
5391 evbuffer_add_printf(tmp, "%s@", uri->userinfo);
5392 evbuffer_add_printf(tmp, "unix:%s:", uri->unixsocket);
5397 evbuffer_add(tmp, "//", 2);
5399 evbuffer_add_printf(tmp,"%s@", uri->userinfo);
5400 if (uri->flags & _EVHTTP_URI_HOST_HAS_BRACKETS) {
5401 evbuffer_add(tmp, "[", 1);
5403 evbuffer_add(tmp, "]", 1);
5408 evbuffer_add_printf(tmp,":%d", uri->port);
5410 if (uri->path && uri->path[0] != '/' && uri->path[0] != '\0')
5418 evbuffer_add(tmp, "?", 1);
5422 if (uri->fragment) {
5423 evbuffer_add(tmp, "#", 1);
5427 evbuffer_add(tmp, "\0", 1); /* NUL */
5429 joined_size = evbuffer_get_length(tmp);
5431 if (joined_size > limit) {
5432 /* It doesn't fit. */
5436 evbuffer_remove(tmp, buf, joined_size);
5447 evhttp_uri_get_scheme(const struct evhttp_uri *uri)
5452 evhttp_uri_get_userinfo(const struct evhttp_uri *uri)
5454 return uri->userinfo;
5457 evhttp_uri_get_host(const struct evhttp_uri *uri)
5463 evhttp_uri_get_unixsocket(const struct evhttp_uri *uri)
5465 return uri->unixsocket;
5469 evhttp_uri_get_port(const struct evhttp_uri *uri)
5474 evhttp_uri_get_path(const struct evhttp_uri *uri)
5479 evhttp_uri_get_query(const struct evhttp_uri *uri)
5484 evhttp_uri_get_fragment(const struct evhttp_uri *uri)
5486 return uri->fragment;
5489 #define URI_SET_STR_(f) do { \
5493 if ((uri->f = mm_strdup(f)) == NULL) { \
5494 event_warn("%s: strdup()", __func__); \
5503 evhttp_uri_set_scheme(struct evhttp_uri *uri, const char *scheme)
5505 if (scheme && !scheme_ok(scheme, scheme+strlen(scheme)))
5508 URI_SET_STR_(scheme);
5512 evhttp_uri_set_userinfo(struct evhttp_uri *uri, const char *userinfo)
5514 if (userinfo && !userinfo_ok(userinfo, userinfo+strlen(userinfo)))
5516 URI_SET_STR_(userinfo);
5520 evhttp_uri_set_host(struct evhttp_uri *uri, const char *host)
5527 if (host[0] == '[') {
5528 if (! bracket_addr_ok(host, host+len))
5531 if (! regname_ok(host, host+len))
5536 if (host && host[0] == '[' && uri->flags & EVHTTP_URI_HOST_STRIP_BRACKETS) {
5540 new_host = mm_realloc(uri->host, len+1);
5545 memcpy(new_host, host+1, len);
5546 new_host[len] = '\0';
5547 uri->host = new_host;
5549 uri->flags |= _EVHTTP_URI_HOST_HAS_BRACKETS;
5552 uri->flags &= ~_EVHTTP_URI_HOST_HAS_BRACKETS;
5559 evhttp_uri_set_unixsocket(struct evhttp_uri *uri, const char *unixsocket)
5561 URI_SET_STR_(unixsocket);
5566 evhttp_uri_set_port(struct evhttp_uri *uri, int port)
5573 #define end_of_cpath(cp,p,f) \
5574 ((const char*)(end_of_path(((char*)(cp)), (p), (f))))
5577 evhttp_uri_set_path(struct evhttp_uri *uri, const char *path)
5579 if (path && end_of_cpath(path, PART_PATH, uri->flags) != path+strlen(path))
5586 evhttp_uri_set_query(struct evhttp_uri *uri, const char *query)
5588 if (query && end_of_cpath(query, PART_QUERY, uri->flags) != query+strlen(query))
5590 URI_SET_STR_(query);
5594 evhttp_uri_set_fragment(struct evhttp_uri *uri, const char *fragment)
5596 if (fragment && end_of_cpath(fragment, PART_FRAGMENT, uri->flags) != fragment+strlen(fragment))
5598 URI_SET_STR_(fragment);