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 #ifdef EVENT__HAVE_SYS_PARAM_H
32 #include <sys/param.h>
34 #ifdef EVENT__HAVE_SYS_TYPES_H
35 #include <sys/types.h>
38 #ifdef HAVE_SYS_IOCCOM_H
39 #include <sys/ioccom.h>
41 #ifdef EVENT__HAVE_SYS_RESOURCE_H
42 #include <sys/resource.h>
44 #ifdef EVENT__HAVE_SYS_TIME_H
47 #ifdef EVENT__HAVE_SYS_WAIT_H
52 #include <sys/socket.h>
59 #include <sys/queue.h>
61 #ifdef EVENT__HAVE_NETINET_IN_H
62 #include <netinet/in.h>
64 #ifdef EVENT__HAVE_ARPA_INET_H
65 #include <arpa/inet.h>
67 #ifdef EVENT__HAVE_NETDB_H
83 #ifdef EVENT__HAVE_UNISTD_H
86 #ifdef EVENT__HAVE_FCNTL_H
90 #undef timeout_pending
91 #undef timeout_initialized
93 #include "strlcpy-internal.h"
94 #include "event2/http.h"
95 #include "event2/event.h"
96 #include "event2/buffer.h"
97 #include "event2/bufferevent.h"
98 #include "event2/http_struct.h"
99 #include "event2/http_compat.h"
100 #include "event2/util.h"
101 #include "event2/listener.h"
102 #include "log-internal.h"
103 #include "util-internal.h"
104 #include "http-internal.h"
105 #include "mm-internal.h"
106 #include "bufferevent-internal.h"
108 #ifndef EVENT__HAVE_GETNAMEINFO
109 #define NI_MAXSERV 32
110 #define NI_MAXHOST 1025
112 #ifndef NI_NUMERICHOST
113 #define NI_NUMERICHOST 1
116 #ifndef NI_NUMERICSERV
117 #define NI_NUMERICSERV 2
121 fake_getnameinfo(const struct sockaddr *sa, size_t salen, char *host,
122 size_t hostlen, char *serv, size_t servlen, int flags)
124 struct sockaddr_in *sin = (struct sockaddr_in *)sa;
128 evutil_snprintf(tmpserv, sizeof(tmpserv),
129 "%d", ntohs(sin->sin_port));
130 if (strlcpy(serv, tmpserv, servlen) >= servlen)
135 if (flags & NI_NUMERICHOST) {
136 if (strlcpy(host, inet_ntoa(sin->sin_addr),
143 hp = gethostbyaddr((char *)&sin->sin_addr,
144 sizeof(struct in_addr), AF_INET);
148 if (strlcpy(host, hp->h_name, hostlen) >= hostlen)
159 #define REQ_VERSION_BEFORE(req, major_v, minor_v) \
160 ((req)->major < (major_v) || \
161 ((req)->major == (major_v) && (req)->minor < (minor_v)))
163 #define REQ_VERSION_ATLEAST(req, major_v, minor_v) \
164 ((req)->major > (major_v) || \
165 ((req)->major == (major_v) && (req)->minor >= (minor_v)))
168 #define MIN(a,b) (((a)<(b))?(a):(b))
173 static evutil_socket_t bind_socket_ai(struct evutil_addrinfo *, int reuse);
174 static evutil_socket_t bind_socket(const char *, ev_uint16_t, int reuse);
175 static void name_from_addr(struct sockaddr *, ev_socklen_t, char **, char **);
176 static struct evhttp_uri *evhttp_uri_parse_authority(char *source_uri);
177 static int evhttp_associate_new_request_with_connection(
178 struct evhttp_connection *evcon);
179 static void evhttp_connection_start_detectclose(
180 struct evhttp_connection *evcon);
181 static void evhttp_connection_stop_detectclose(
182 struct evhttp_connection *evcon);
183 static void evhttp_request_dispatch(struct evhttp_connection* evcon);
184 static void evhttp_read_firstline(struct evhttp_connection *evcon,
185 struct evhttp_request *req);
186 static void evhttp_read_header(struct evhttp_connection *evcon,
187 struct evhttp_request *req);
188 static int evhttp_add_header_internal(struct evkeyvalq *headers,
189 const char *key, const char *value);
190 static const char *evhttp_response_phrase_internal(int code);
191 static void evhttp_get_request(struct evhttp *, evutil_socket_t, struct sockaddr *, ev_socklen_t);
192 static void evhttp_write_buffer(struct evhttp_connection *,
193 void (*)(struct evhttp_connection *, void *), void *);
194 static void evhttp_make_header(struct evhttp_connection *, struct evhttp_request *);
196 /* callbacks for bufferevent */
197 static void evhttp_read_cb(struct bufferevent *, void *);
198 static void evhttp_write_cb(struct bufferevent *, void *);
199 static void evhttp_error_cb(struct bufferevent *bufev, short what, void *arg);
200 static int evhttp_find_vhost(struct evhttp *http, struct evhttp **outhttp,
201 const char *hostname);
203 #ifndef EVENT__HAVE_STRSEP
204 /* strsep replacement for platforms that lack it. Only works if
205 * del is one character long. */
207 strsep(char **s, const char *del)
210 EVUTIL_ASSERT(strlen(del) == 1);
214 d = strstr(tok, del);
225 html_replace(const char ch, const char **escaped)
251 * Replaces <, >, ", ' and & with <, >, ",
252 * ' and & correspondingly.
254 * The returned string needs to be freed by the caller.
258 evhttp_htmlescape(const char *html)
261 size_t new_size = 0, old_size = 0;
262 char *escaped_html, *p;
267 old_size = strlen(html);
268 for (i = 0; i < old_size; ++i) {
269 const char *replaced = NULL;
270 const size_t replace_size = html_replace(html[i], &replaced);
271 if (replace_size > EV_SIZE_MAX - new_size) {
272 event_warn("%s: html_replace overflow", __func__);
275 new_size += replace_size;
278 if (new_size == EV_SIZE_MAX)
280 p = escaped_html = mm_malloc(new_size + 1);
281 if (escaped_html == NULL) {
282 event_warn("%s: malloc(%lu)", __func__,
283 (unsigned long)(new_size + 1));
286 for (i = 0; i < old_size; ++i) {
287 const char *replaced = &html[i];
288 const size_t len = html_replace(html[i], &replaced);
289 memcpy(p, replaced, len);
295 return (escaped_html);
298 /** Given an evhttp_cmd_type, returns a constant string containing the
299 * equivalent HTTP command, or NULL if the evhttp_command_type is
302 evhttp_method(enum evhttp_cmd_type type)
310 case EVHTTP_REQ_POST:
313 case EVHTTP_REQ_HEAD:
319 case EVHTTP_REQ_DELETE:
322 case EVHTTP_REQ_OPTIONS:
325 case EVHTTP_REQ_TRACE:
328 case EVHTTP_REQ_CONNECT:
331 case EVHTTP_REQ_PATCH:
343 * Determines if a response should have a body.
344 * Follows the rules in RFC 2616 section 4.3.
345 * @return 1 if the response MUST have a body; 0 if the response MUST NOT have
349 evhttp_response_needs_body(struct evhttp_request *req)
351 return (req->response_code != HTTP_NOCONTENT &&
352 req->response_code != HTTP_NOTMODIFIED &&
353 (req->response_code < 100 || req->response_code >= 200) &&
354 req->type != EVHTTP_REQ_HEAD);
357 /** Helper: called after we've added some data to an evcon's bufferevent's
358 * output buffer. Sets the evconn's writing-is-done callback, and puts
359 * the bufferevent into writing mode.
362 evhttp_write_buffer(struct evhttp_connection *evcon,
363 void (*cb)(struct evhttp_connection *, void *), void *arg)
365 event_debug(("%s: preparing to write buffer\n", __func__));
371 /* Disable the read callback: we don't actually care about data;
372 * we only care about close detection. (We don't disable reading --
373 * EV_READ, since we *do* want to learn about any close events.) */
374 bufferevent_setcb(evcon->bufev,
380 bufferevent_enable(evcon->bufev, EV_READ|EV_WRITE);
384 evhttp_send_continue_done(struct evhttp_connection *evcon, void *arg)
386 bufferevent_disable(evcon->bufev, EV_WRITE);
390 evhttp_send_continue(struct evhttp_connection *evcon,
391 struct evhttp_request *req)
393 bufferevent_enable(evcon->bufev, EV_WRITE);
394 evbuffer_add_printf(bufferevent_get_output(evcon->bufev),
395 "HTTP/%d.%d 100 Continue\r\n\r\n",
396 req->major, req->minor);
397 evcon->cb = evhttp_send_continue_done;
398 evcon->cb_arg = NULL;
399 bufferevent_setcb(evcon->bufev,
406 /** Helper: returns true iff evconn is in any connected state. */
408 evhttp_connected(struct evhttp_connection *evcon)
410 switch (evcon->state) {
411 case EVCON_DISCONNECTED:
412 case EVCON_CONNECTING:
415 case EVCON_READING_FIRSTLINE:
416 case EVCON_READING_HEADERS:
417 case EVCON_READING_BODY:
418 case EVCON_READING_TRAILER:
425 /* Create the headers needed for an outgoing HTTP request, adds them to
426 * the request's header list, and writes the request line to the
427 * connection's output buffer.
430 evhttp_make_header_request(struct evhttp_connection *evcon,
431 struct evhttp_request *req)
435 evhttp_remove_header(req->output_headers, "Proxy-Connection");
437 /* Generate request line */
438 if (!(method = evhttp_method(req->type))) {
442 evbuffer_add_printf(bufferevent_get_output(evcon->bufev),
443 "%s %s HTTP/%d.%d\r\n",
444 method, req->uri, req->major, req->minor);
446 /* Add the content length on a post or put request if missing */
447 if ((req->type == EVHTTP_REQ_POST || req->type == EVHTTP_REQ_PUT) &&
448 evhttp_find_header(req->output_headers, "Content-Length") == NULL){
450 evutil_snprintf(size, sizeof(size), EV_SIZE_FMT,
451 EV_SIZE_ARG(evbuffer_get_length(req->output_buffer)));
452 evhttp_add_header(req->output_headers, "Content-Length", size);
456 /** Return true if the list of headers in 'headers', intepreted with respect
457 * to flags, means that we should send a "connection: close" when the request
460 evhttp_is_connection_close(int flags, struct evkeyvalq* headers)
462 if (flags & EVHTTP_PROXY_REQUEST) {
463 /* proxy connection */
464 const char *connection = evhttp_find_header(headers, "Proxy-Connection");
465 return (connection == NULL || evutil_ascii_strcasecmp(connection, "keep-alive") != 0);
467 const char *connection = evhttp_find_header(headers, "Connection");
468 return (connection != NULL && evutil_ascii_strcasecmp(connection, "close") == 0);
472 evhttp_is_request_connection_close(struct evhttp_request *req)
475 evhttp_is_connection_close(req->flags, req->input_headers) ||
476 evhttp_is_connection_close(req->flags, req->output_headers);
479 /* Return true iff 'headers' contains 'Connection: keep-alive' */
481 evhttp_is_connection_keepalive(struct evkeyvalq* headers)
483 const char *connection = evhttp_find_header(headers, "Connection");
484 return (connection != NULL
485 && evutil_ascii_strncasecmp(connection, "keep-alive", 10) == 0);
488 /* Add a correct "Date" header to headers, unless it already has one. */
490 evhttp_maybe_add_date_header(struct evkeyvalq *headers)
492 if (evhttp_find_header(headers, "Date") == NULL) {
494 if (sizeof(date) - evutil_date_rfc1123(date, sizeof(date), NULL) > 0) {
495 evhttp_add_header(headers, "Date", date);
500 /* Add a "Content-Length" header with value 'content_length' to headers,
501 * unless it already has a content-length or transfer-encoding header. */
503 evhttp_maybe_add_content_length_header(struct evkeyvalq *headers,
504 size_t content_length)
506 if (evhttp_find_header(headers, "Transfer-Encoding") == NULL &&
507 evhttp_find_header(headers, "Content-Length") == NULL) {
509 evutil_snprintf(len, sizeof(len), EV_SIZE_FMT,
510 EV_SIZE_ARG(content_length));
511 evhttp_add_header(headers, "Content-Length", len);
516 * Create the headers needed for an HTTP reply in req->output_headers,
517 * and write the first HTTP response for req line to evcon.
520 evhttp_make_header_response(struct evhttp_connection *evcon,
521 struct evhttp_request *req)
523 int is_keepalive = evhttp_is_connection_keepalive(req->input_headers);
524 evbuffer_add_printf(bufferevent_get_output(evcon->bufev),
525 "HTTP/%d.%d %d %s\r\n",
526 req->major, req->minor, req->response_code,
527 req->response_code_line);
529 if (req->major == 1) {
531 evhttp_maybe_add_date_header(req->output_headers);
534 * if the protocol is 1.0; and the connection was keep-alive
535 * we need to add a keep-alive header, too.
537 if (req->minor == 0 && is_keepalive)
538 evhttp_add_header(req->output_headers,
539 "Connection", "keep-alive");
541 if ((req->minor >= 1 || is_keepalive) &&
542 evhttp_response_needs_body(req)) {
544 * we need to add the content length if the
545 * user did not give it, this is required for
546 * persistent connections to work.
548 evhttp_maybe_add_content_length_header(
550 evbuffer_get_length(req->output_buffer));
554 /* Potentially add headers for unidentified content. */
555 if (evhttp_response_needs_body(req)) {
556 if (evhttp_find_header(req->output_headers,
557 "Content-Type") == NULL
558 && evcon->http_server->default_content_type) {
559 evhttp_add_header(req->output_headers,
561 evcon->http_server->default_content_type);
565 /* if the request asked for a close, we send a close, too */
566 if (evhttp_is_connection_close(req->flags, req->input_headers)) {
567 evhttp_remove_header(req->output_headers, "Connection");
568 if (!(req->flags & EVHTTP_PROXY_REQUEST))
569 evhttp_add_header(req->output_headers, "Connection", "close");
570 evhttp_remove_header(req->output_headers, "Proxy-Connection");
574 enum expect { NO, CONTINUE, OTHER };
575 static enum expect evhttp_have_expect(struct evhttp_request *req, int input)
578 struct evkeyvalq *h = input ? req->input_headers : req->output_headers;
580 if (!(req->kind == EVHTTP_REQUEST) || !REQ_VERSION_ATLEAST(req, 1, 1))
583 expect = evhttp_find_header(h, "Expect");
587 return !evutil_ascii_strcasecmp(expect, "100-continue") ? CONTINUE : OTHER;
591 /** Generate all headers appropriate for sending the http request in req (or
592 * the response, if we're sending a response), and write them to evcon's
593 * bufferevent. Also writes all data from req->output_buffer */
595 evhttp_make_header(struct evhttp_connection *evcon, struct evhttp_request *req)
597 struct evkeyval *header;
598 struct evbuffer *output = bufferevent_get_output(evcon->bufev);
601 * Depending if this is a HTTP request or response, we might need to
602 * add some new headers or remove existing headers.
604 if (req->kind == EVHTTP_REQUEST) {
605 evhttp_make_header_request(evcon, req);
607 evhttp_make_header_response(evcon, req);
610 TAILQ_FOREACH(header, req->output_headers, next) {
611 evbuffer_add_printf(output, "%s: %s\r\n",
612 header->key, header->value);
614 evbuffer_add(output, "\r\n", 2);
616 if (evhttp_have_expect(req, 0) != CONTINUE &&
617 evbuffer_get_length(req->output_buffer)) {
619 * For a request, we add the POST data, for a reply, this
620 * is the regular data.
622 evbuffer_add_buffer(output, req->output_buffer);
627 evhttp_connection_set_max_headers_size(struct evhttp_connection *evcon,
628 ev_ssize_t new_max_headers_size)
630 if (new_max_headers_size<0)
631 evcon->max_headers_size = EV_SIZE_MAX;
633 evcon->max_headers_size = new_max_headers_size;
636 evhttp_connection_set_max_body_size(struct evhttp_connection* evcon,
637 ev_ssize_t new_max_body_size)
639 if (new_max_body_size<0)
640 evcon->max_body_size = EV_UINT64_MAX;
642 evcon->max_body_size = new_max_body_size;
646 evhttp_connection_incoming_fail(struct evhttp_request *req,
647 enum evhttp_request_error error)
650 case EVREQ_HTTP_DATA_TOO_LONG:
651 req->response_code = HTTP_ENTITYTOOLARGE;
654 req->response_code = HTTP_BADREQUEST;
658 case EVREQ_HTTP_TIMEOUT:
661 * these are cases in which we probably should just
662 * close the connection and not send a reply. this
663 * case may happen when a browser keeps a persistent
664 * connection open and we timeout on the read. when
665 * the request is still being used for sending, we
666 * need to disassociated it from the connection here.
668 if (!req->userdone) {
669 /* remove it so that it will not be freed */
670 TAILQ_REMOVE(&req->evcon->requests, req, next);
671 /* indicate that this request no longer has a
677 case EVREQ_HTTP_INVALID_HEADER:
678 case EVREQ_HTTP_BUFFER_ERROR:
679 case EVREQ_HTTP_REQUEST_CANCEL:
680 case EVREQ_HTTP_DATA_TOO_LONG:
681 default: /* xxx: probably should just error on default */
682 /* the callback looks at the uri to determine errors */
687 if (req->uri_elems) {
688 evhttp_uri_free(req->uri_elems);
689 req->uri_elems = NULL;
693 * the callback needs to send a reply, once the reply has
694 * been send, the connection should get freed.
696 (*req->cb)(req, req->cb_arg);
702 /* Free connection ownership of which can be acquired by user using
703 * evhttp_request_own(). */
705 evhttp_request_free_auto(struct evhttp_request *req)
707 if (!(req->flags & EVHTTP_USER_OWNED))
708 evhttp_request_free(req);
712 evhttp_request_free_(struct evhttp_connection *evcon, struct evhttp_request *req)
714 TAILQ_REMOVE(&evcon->requests, req, next);
715 evhttp_request_free_auto(req);
718 /* Called when evcon has experienced a (non-recoverable? -NM) error, as
719 * given in error. If it's an outgoing connection, reset the connection,
720 * retry any pending requests, and inform the user. If it's incoming,
721 * delegates to evhttp_connection_incoming_fail(). */
723 evhttp_connection_fail_(struct evhttp_connection *evcon,
724 enum evhttp_request_error error)
726 const int errsave = EVUTIL_SOCKET_ERROR();
727 struct evhttp_request* req = TAILQ_FIRST(&evcon->requests);
728 void (*cb)(struct evhttp_request *, void *);
730 void (*error_cb)(enum evhttp_request_error, void *);
732 EVUTIL_ASSERT(req != NULL);
734 bufferevent_disable(evcon->bufev, EV_READ|EV_WRITE);
736 if (evcon->flags & EVHTTP_CON_INCOMING) {
738 * for incoming requests, there are two different
739 * failure cases. it's either a network level error
740 * or an http layer error. for problems on the network
741 * layer like timeouts we just drop the connections.
742 * For HTTP problems, we might have to send back a
743 * reply before the connection can be freed.
745 if (evhttp_connection_incoming_fail(req, error) == -1)
746 evhttp_connection_free(evcon);
750 error_cb = req->error_cb;
751 error_cb_arg = req->cb_arg;
752 /* when the request was canceled, the callback is not executed */
753 if (error != EVREQ_HTTP_REQUEST_CANCEL) {
754 /* save the callback for later; the cb might free our object */
756 cb_arg = req->cb_arg;
762 /* do not fail all requests; the next request is going to get
763 * send over a new connection. when a user cancels a request,
764 * all other pending requests should be processed as normal
766 evhttp_request_free_(evcon, req);
768 /* reset the connection */
769 evhttp_connection_reset_(evcon);
771 /* We are trying the next request that was queued on us */
772 if (TAILQ_FIRST(&evcon->requests) != NULL)
773 evhttp_connection_connect_(evcon);
775 /* The call to evhttp_connection_reset_ overwrote errno.
776 * Let's restore the original errno, so that the user's
777 * callback can have a better idea of what the error was.
779 EVUTIL_SET_SOCKET_ERROR(errsave);
781 /* inform the user */
782 if (error_cb != NULL)
783 error_cb(error, error_cb_arg);
788 /* Bufferevent callback: invoked when any data has been written from an
789 * http connection's bufferevent */
791 evhttp_write_cb(struct bufferevent *bufev, void *arg)
793 struct evhttp_connection *evcon = arg;
795 /* Activate our call back */
796 if (evcon->cb != NULL)
797 (*evcon->cb)(evcon, evcon->cb_arg);
801 * Advance the connection state.
802 * - If this is an outgoing connection, we've just processed the response;
803 * idle or close the connection.
804 * - If this is an incoming connection, we've just processed the request;
808 evhttp_connection_done(struct evhttp_connection *evcon)
810 struct evhttp_request *req = TAILQ_FIRST(&evcon->requests);
811 int con_outgoing = evcon->flags & EVHTTP_CON_OUTGOING;
815 /* idle or close the connection */
816 int need_close = evhttp_is_request_connection_close(req);
817 TAILQ_REMOVE(&evcon->requests, req, next);
820 evcon->state = EVCON_IDLE;
822 /* check if we got asked to close the connection */
824 evhttp_connection_reset_(evcon);
826 if (TAILQ_FIRST(&evcon->requests) != NULL) {
828 * We have more requests; reset the connection
829 * and deal with the next request.
831 if (!evhttp_connected(evcon))
832 evhttp_connection_connect_(evcon);
834 evhttp_request_dispatch(evcon);
835 } else if (!need_close) {
837 * The connection is going to be persistent, but we
838 * need to detect if the other side closes it.
840 evhttp_connection_start_detectclose(evcon);
841 } else if ((evcon->flags & EVHTTP_CON_AUTOFREE)) {
843 * If we have no more requests that need completion
844 * and we're not waiting for the connection to close
850 * incoming connection - we need to leave the request on the
851 * connection so that we can reply to it.
853 evcon->state = EVCON_WRITING;
856 /* notify the user of the request */
857 (*req->cb)(req, req->cb_arg);
859 /* if this was an outgoing request, we own and it's done. so free it. */
861 evhttp_request_free_auto(req);
864 /* If this was the last request of an outgoing connection and we're
865 * not waiting to receive a connection close event and we want to
866 * automatically free the connection. We check to ensure our request
867 * list is empty one last time just in case our callback added a
870 if (free_evcon && TAILQ_FIRST(&evcon->requests) == NULL) {
871 evhttp_connection_free(evcon);
876 * Handles reading from a chunked request.
877 * return ALL_DATA_READ:
878 * all data has been read
879 * return MORE_DATA_EXPECTED:
880 * more data is expected
881 * return DATA_CORRUPTED:
883 * return REQUEST_CANCELED:
884 * request was canceled by the user calling evhttp_cancel_request
885 * return DATA_TOO_LONG:
886 * ran over the maximum limit
889 static enum message_read_status
890 evhttp_handle_chunked_read(struct evhttp_request *req, struct evbuffer *buf)
892 if (req == NULL || buf == NULL) {
893 return DATA_CORRUPTED;
899 if ((buflen = evbuffer_get_length(buf)) == 0) {
903 /* evbuffer_get_length returns size_t, but len variable is ssize_t,
904 * check for overflow conditions */
905 if (buflen > EV_SSIZE_MAX) {
906 return DATA_CORRUPTED;
909 if (req->ntoread < 0) {
910 /* Read chunk size */
912 char *p = evbuffer_readln(buf, NULL, EVBUFFER_EOL_CRLF);
917 /* the last chunk is on a new line? */
918 if (strlen(p) == 0) {
922 ntoread = evutil_strtoll(p, &endp, 16);
923 error = (*p == '\0' ||
924 (*endp != '\0' && *endp != ' ') ||
928 /* could not get chunk size */
929 return (DATA_CORRUPTED);
932 /* ntoread is signed int64, body_size is unsigned size_t, check for under/overflow conditions */
933 if ((ev_uint64_t)ntoread > EV_SIZE_MAX - req->body_size) {
934 return DATA_CORRUPTED;
937 if (req->body_size + (size_t)ntoread > req->evcon->max_body_size) {
938 /* failed body length test */
939 event_debug(("Request body is too long"));
940 return (DATA_TOO_LONG);
943 req->body_size += (size_t)ntoread;
944 req->ntoread = ntoread;
945 if (req->ntoread == 0) {
947 return (ALL_DATA_READ);
952 /* req->ntoread is signed int64, len is ssize_t, based on arch,
953 * ssize_t could only be 32b, check for these conditions */
954 if (req->ntoread > EV_SSIZE_MAX) {
955 return DATA_CORRUPTED;
958 /* don't have enough to complete a chunk; wait for more */
959 if (req->ntoread > 0 && buflen < (ev_uint64_t)req->ntoread)
960 return (MORE_DATA_EXPECTED);
962 /* Completed chunk */
963 evbuffer_remove_buffer(buf, req->input_buffer, (size_t)req->ntoread);
965 if (req->chunk_cb != NULL) {
966 req->flags |= EVHTTP_REQ_DEFER_FREE;
967 (*req->chunk_cb)(req, req->cb_arg);
968 evbuffer_drain(req->input_buffer,
969 evbuffer_get_length(req->input_buffer));
970 req->flags &= ~EVHTTP_REQ_DEFER_FREE;
971 if ((req->flags & EVHTTP_REQ_NEEDS_FREE) != 0) {
972 return (REQUEST_CANCELED);
977 return (MORE_DATA_EXPECTED);
981 evhttp_read_trailer(struct evhttp_connection *evcon, struct evhttp_request *req)
983 struct evbuffer *buf = bufferevent_get_input(evcon->bufev);
985 switch (evhttp_parse_headers_(req, buf)) {
988 evhttp_connection_fail_(evcon, EVREQ_HTTP_DATA_TOO_LONG);
991 bufferevent_disable(evcon->bufev, EV_READ);
992 evhttp_connection_done(evcon);
994 case MORE_DATA_EXPECTED:
995 case REQUEST_CANCELED: /* ??? */
1002 evhttp_lingering_close(struct evhttp_connection *evcon,
1003 struct evhttp_request *req)
1005 struct evbuffer *buf = bufferevent_get_input(evcon->bufev);
1007 size_t n = evbuffer_get_length(buf);
1008 if (n > (size_t) req->ntoread)
1009 n = (size_t) req->ntoread;
1011 req->body_size += n;
1013 event_debug(("Request body is too long, left " EV_I64_FMT,
1014 EV_I64_ARG(req->ntoread)));
1016 evbuffer_drain(buf, n);
1018 evhttp_connection_fail_(evcon, EVREQ_HTTP_DATA_TOO_LONG);
1021 evhttp_lingering_fail(struct evhttp_connection *evcon,
1022 struct evhttp_request *req)
1024 if (evcon->flags & EVHTTP_CON_LINGERING_CLOSE)
1025 evhttp_lingering_close(evcon, req);
1027 evhttp_connection_fail_(evcon, EVREQ_HTTP_DATA_TOO_LONG);
1031 evhttp_read_body(struct evhttp_connection *evcon, struct evhttp_request *req)
1033 struct evbuffer *buf = bufferevent_get_input(evcon->bufev);
1036 switch (evhttp_handle_chunked_read(req, buf)) {
1038 /* finished last chunk */
1039 evcon->state = EVCON_READING_TRAILER;
1040 evhttp_read_trailer(evcon, req);
1042 case DATA_CORRUPTED:
1044 /* corrupted data */
1045 evhttp_connection_fail_(evcon,
1046 EVREQ_HTTP_DATA_TOO_LONG);
1048 case REQUEST_CANCELED:
1049 /* request canceled */
1050 evhttp_request_free_auto(req);
1052 case MORE_DATA_EXPECTED:
1056 } else if (req->ntoread < 0) {
1057 /* Read until connection close. */
1058 if ((size_t)(req->body_size + evbuffer_get_length(buf)) < req->body_size) {
1059 evhttp_connection_fail_(evcon, EVREQ_HTTP_INVALID_HEADER);
1063 req->body_size += evbuffer_get_length(buf);
1064 evbuffer_add_buffer(req->input_buffer, buf);
1065 } else if (req->chunk_cb != NULL || evbuffer_get_length(buf) >= (size_t)req->ntoread) {
1066 /* XXX: the above get_length comparison has to be fixed for overflow conditions! */
1067 /* We've postponed moving the data until now, but we're
1068 * about to use it. */
1069 size_t n = evbuffer_get_length(buf);
1071 if (n > (size_t) req->ntoread)
1072 n = (size_t) req->ntoread;
1074 req->body_size += n;
1075 evbuffer_remove_buffer(buf, req->input_buffer, n);
1078 if (req->body_size > req->evcon->max_body_size ||
1079 (!req->chunked && req->ntoread >= 0 &&
1080 (size_t)req->ntoread > req->evcon->max_body_size)) {
1081 /* XXX: The above casted comparison must checked for overflow */
1082 /* failed body length test */
1084 evhttp_lingering_fail(evcon, req);
1088 if (evbuffer_get_length(req->input_buffer) > 0 && req->chunk_cb != NULL) {
1089 req->flags |= EVHTTP_REQ_DEFER_FREE;
1090 (*req->chunk_cb)(req, req->cb_arg);
1091 req->flags &= ~EVHTTP_REQ_DEFER_FREE;
1092 evbuffer_drain(req->input_buffer,
1093 evbuffer_get_length(req->input_buffer));
1094 if ((req->flags & EVHTTP_REQ_NEEDS_FREE) != 0) {
1095 evhttp_request_free_auto(req);
1100 if (!req->ntoread) {
1101 bufferevent_disable(evcon->bufev, EV_READ);
1102 /* Completed content length */
1103 evhttp_connection_done(evcon);
1108 #define get_deferred_queue(evcon) \
1112 * Gets called when more data becomes available
1116 evhttp_read_cb(struct bufferevent *bufev, void *arg)
1118 struct evhttp_connection *evcon = arg;
1119 struct evhttp_request *req = TAILQ_FIRST(&evcon->requests);
1121 /* Cancel if it's pending. */
1122 event_deferred_cb_cancel_(get_deferred_queue(evcon),
1123 &evcon->read_more_deferred_cb);
1125 switch (evcon->state) {
1126 case EVCON_READING_FIRSTLINE:
1127 evhttp_read_firstline(evcon, req);
1128 /* note the request may have been freed in
1129 * evhttp_read_body */
1131 case EVCON_READING_HEADERS:
1132 evhttp_read_header(evcon, req);
1133 /* note the request may have been freed in
1134 * evhttp_read_body */
1136 case EVCON_READING_BODY:
1137 evhttp_read_body(evcon, req);
1138 /* note the request may have been freed in
1139 * evhttp_read_body */
1141 case EVCON_READING_TRAILER:
1142 evhttp_read_trailer(evcon, req);
1147 struct evbuffer *input;
1150 input = bufferevent_get_input(evcon->bufev);
1151 total_len = evbuffer_get_length(input);
1152 event_debug(("%s: read "EV_SIZE_FMT
1153 " bytes in EVCON_IDLE state,"
1154 " resetting connection",
1155 __func__, EV_SIZE_ARG(total_len)));
1158 evhttp_connection_reset_(evcon);
1161 case EVCON_DISCONNECTED:
1162 case EVCON_CONNECTING:
1165 event_errx(1, "%s: illegal connection state %d",
1166 __func__, evcon->state);
1171 evhttp_deferred_read_cb(struct event_callback *cb, void *data)
1173 struct evhttp_connection *evcon = data;
1174 evhttp_read_cb(evcon->bufev, evcon);
1178 evhttp_write_connectioncb(struct evhttp_connection *evcon, void *arg)
1180 /* This is after writing the request to the server */
1181 struct evhttp_request *req = TAILQ_FIRST(&evcon->requests);
1182 struct evbuffer *output = bufferevent_get_output(evcon->bufev);
1183 EVUTIL_ASSERT(req != NULL);
1185 EVUTIL_ASSERT(evcon->state == EVCON_WRITING);
1187 /* We need to wait until we've written all of our output data before we can
1189 if (evbuffer_get_length(output) > 0)
1192 /* We are done writing our header and are now expecting the response */
1193 req->kind = EVHTTP_RESPONSE;
1195 evhttp_start_read_(evcon);
1199 * Clean up a connection object
1203 evhttp_connection_free(struct evhttp_connection *evcon)
1205 struct evhttp_request *req;
1207 /* notify interested parties that this connection is going down */
1208 if (evcon->fd != -1) {
1209 if (evhttp_connected(evcon) && evcon->closecb != NULL)
1210 (*evcon->closecb)(evcon, evcon->closecb_arg);
1213 /* remove all requests that might be queued on this
1214 * connection. for server connections, this should be empty.
1215 * because it gets dequeued either in evhttp_connection_done or
1216 * evhttp_connection_fail_.
1218 while ((req = TAILQ_FIRST(&evcon->requests)) != NULL) {
1219 evhttp_request_free_(evcon, req);
1222 if (evcon->http_server != NULL) {
1223 struct evhttp *http = evcon->http_server;
1224 TAILQ_REMOVE(&http->connections, evcon, next);
1227 if (event_initialized(&evcon->retry_ev)) {
1228 event_del(&evcon->retry_ev);
1229 event_debug_unassign(&evcon->retry_ev);
1232 if (evcon->bufev != NULL)
1233 bufferevent_free(evcon->bufev);
1235 event_deferred_cb_cancel_(get_deferred_queue(evcon),
1236 &evcon->read_more_deferred_cb);
1238 if (evcon->fd == -1)
1239 evcon->fd = bufferevent_getfd(evcon->bufev);
1241 if (evcon->fd != -1) {
1242 bufferevent_disable(evcon->bufev, EV_READ|EV_WRITE);
1243 shutdown(evcon->fd, EVUTIL_SHUT_WR);
1244 if (!(bufferevent_get_options_(evcon->bufev) & BEV_OPT_CLOSE_ON_FREE)) {
1245 evutil_closesocket(evcon->fd);
1249 if (evcon->bind_address != NULL)
1250 mm_free(evcon->bind_address);
1252 if (evcon->address != NULL)
1253 mm_free(evcon->address);
1259 evhttp_connection_free_on_completion(struct evhttp_connection *evcon) {
1260 evcon->flags |= EVHTTP_CON_AUTOFREE;
1264 evhttp_connection_set_local_address(struct evhttp_connection *evcon,
1265 const char *address)
1267 EVUTIL_ASSERT(evcon->state == EVCON_DISCONNECTED);
1268 if (evcon->bind_address)
1269 mm_free(evcon->bind_address);
1270 if ((evcon->bind_address = mm_strdup(address)) == NULL)
1271 event_warn("%s: strdup", __func__);
1275 evhttp_connection_set_local_port(struct evhttp_connection *evcon,
1278 EVUTIL_ASSERT(evcon->state == EVCON_DISCONNECTED);
1279 evcon->bind_port = port;
1283 evhttp_request_dispatch(struct evhttp_connection* evcon)
1285 struct evhttp_request *req = TAILQ_FIRST(&evcon->requests);
1287 /* this should not usually happy but it's possible */
1291 /* delete possible close detection events */
1292 evhttp_connection_stop_detectclose(evcon);
1294 /* we assume that the connection is connected already */
1295 EVUTIL_ASSERT(evcon->state == EVCON_IDLE);
1297 evcon->state = EVCON_WRITING;
1299 /* Create the header from the store arguments */
1300 evhttp_make_header(evcon, req);
1302 evhttp_write_buffer(evcon, evhttp_write_connectioncb, NULL);
1305 /* Reset our connection state: disables reading/writing, closes our fd (if
1306 * any), clears out buffers, and puts us in state DISCONNECTED. */
1308 evhttp_connection_reset_(struct evhttp_connection *evcon)
1310 struct evbuffer *tmp;
1313 bufferevent_setcb(evcon->bufev, NULL, NULL, NULL, NULL);
1315 /* XXXX This is not actually an optimal fix. Instead we ought to have
1316 an API for "stop connecting", or use bufferevent_setfd to turn off
1317 connecting. But for Libevent 2.0, this seems like a minimal change
1318 least likely to disrupt the rest of the bufferevent and http code.
1320 Why is this here? If the fd is set in the bufferevent, and the
1321 bufferevent is connecting, then you can't actually stop the
1322 bufferevent from trying to connect with bufferevent_disable(). The
1323 connect will never trigger, since we close the fd, but the timeout
1324 might. That caused an assertion failure in evhttp_connection_fail_.
1326 bufferevent_disable_hard_(evcon->bufev, EV_READ|EV_WRITE);
1328 if (evcon->fd == -1)
1329 evcon->fd = bufferevent_getfd(evcon->bufev);
1331 if (evcon->fd != -1) {
1332 /* inform interested parties about connection close */
1333 if (evhttp_connected(evcon) && evcon->closecb != NULL)
1334 (*evcon->closecb)(evcon, evcon->closecb_arg);
1336 shutdown(evcon->fd, EVUTIL_SHUT_WR);
1337 evutil_closesocket(evcon->fd);
1340 bufferevent_setfd(evcon->bufev, -1);
1342 /* we need to clean up any buffered data */
1343 tmp = bufferevent_get_output(evcon->bufev);
1344 err = evbuffer_drain(tmp, -1);
1345 EVUTIL_ASSERT(!err && "drain output");
1346 tmp = bufferevent_get_input(evcon->bufev);
1347 err = evbuffer_drain(tmp, -1);
1348 EVUTIL_ASSERT(!err && "drain input");
1350 evcon->flags &= ~EVHTTP_CON_READING_ERROR;
1352 evcon->state = EVCON_DISCONNECTED;
1356 evhttp_connection_start_detectclose(struct evhttp_connection *evcon)
1358 evcon->flags |= EVHTTP_CON_CLOSEDETECT;
1360 bufferevent_enable(evcon->bufev, EV_READ);
1364 evhttp_connection_stop_detectclose(struct evhttp_connection *evcon)
1366 evcon->flags &= ~EVHTTP_CON_CLOSEDETECT;
1368 bufferevent_disable(evcon->bufev, EV_READ);
1372 evhttp_connection_retry(evutil_socket_t fd, short what, void *arg)
1374 struct evhttp_connection *evcon = arg;
1376 evcon->state = EVCON_DISCONNECTED;
1377 evhttp_connection_connect_(evcon);
1381 evhttp_connection_cb_cleanup(struct evhttp_connection *evcon)
1383 struct evcon_requestq requests;
1385 evhttp_connection_reset_(evcon);
1386 if (evcon->retry_max < 0 || evcon->retry_cnt < evcon->retry_max) {
1387 struct timeval tv_retry = evcon->initial_retry_timeout;
1389 evtimer_assign(&evcon->retry_ev, evcon->base, evhttp_connection_retry, evcon);
1390 /* XXXX handle failure from evhttp_add_event */
1391 for (i=0; i < evcon->retry_cnt; ++i) {
1392 tv_retry.tv_usec *= 2;
1393 if (tv_retry.tv_usec > 1000000) {
1394 tv_retry.tv_usec -= 1000000;
1395 tv_retry.tv_sec += 1;
1397 tv_retry.tv_sec *= 2;
1398 if (tv_retry.tv_sec > 3600) {
1399 tv_retry.tv_sec = 3600;
1400 tv_retry.tv_usec = 0;
1403 event_add(&evcon->retry_ev, &tv_retry);
1409 * User callback can do evhttp_make_request() on the same
1410 * evcon so new request will be added to evcon->requests. To
1411 * avoid freeing it prematurely we iterate over the copy of
1414 TAILQ_INIT(&requests);
1415 while (TAILQ_FIRST(&evcon->requests) != NULL) {
1416 struct evhttp_request *request = TAILQ_FIRST(&evcon->requests);
1417 TAILQ_REMOVE(&evcon->requests, request, next);
1418 TAILQ_INSERT_TAIL(&requests, request, next);
1421 /* for now, we just signal all requests by executing their callbacks */
1422 while (TAILQ_FIRST(&requests) != NULL) {
1423 struct evhttp_request *request = TAILQ_FIRST(&requests);
1424 TAILQ_REMOVE(&requests, request, next);
1425 request->evcon = NULL;
1427 /* we might want to set an error here */
1428 request->cb(request, request->cb_arg);
1429 evhttp_request_free_auto(request);
1434 evhttp_connection_read_on_write_error(struct evhttp_connection *evcon,
1435 struct evhttp_request *req)
1437 struct evbuffer *buf;
1439 /** Second time, we can't read anything */
1440 if (evcon->flags & EVHTTP_CON_READING_ERROR) {
1441 evcon->flags &= ~EVHTTP_CON_READING_ERROR;
1442 evhttp_connection_fail_(evcon, EVREQ_HTTP_EOF);
1446 req->kind = EVHTTP_RESPONSE;
1448 buf = bufferevent_get_output(evcon->bufev);
1449 evbuffer_unfreeze(buf, 1);
1450 evbuffer_drain(buf, evbuffer_get_length(buf));
1451 evbuffer_freeze(buf, 1);
1453 evhttp_start_read_(evcon);
1454 evcon->flags |= EVHTTP_CON_READING_ERROR;
1458 evhttp_error_cb(struct bufferevent *bufev, short what, void *arg)
1460 struct evhttp_connection *evcon = arg;
1461 struct evhttp_request *req = TAILQ_FIRST(&evcon->requests);
1463 if (evcon->fd == -1)
1464 evcon->fd = bufferevent_getfd(bufev);
1466 switch (evcon->state) {
1467 case EVCON_CONNECTING:
1468 if (what & BEV_EVENT_TIMEOUT) {
1469 event_debug(("%s: connection timeout for \"%s:%d\" on "
1471 __func__, evcon->address, evcon->port,
1472 EV_SOCK_ARG(evcon->fd)));
1473 evhttp_connection_cb_cleanup(evcon);
1478 case EVCON_READING_BODY:
1479 if (!req->chunked && req->ntoread < 0
1480 && what == (BEV_EVENT_READING|BEV_EVENT_EOF)) {
1481 /* EOF on read can be benign */
1482 evhttp_connection_done(evcon);
1487 case EVCON_DISCONNECTED:
1489 case EVCON_READING_FIRSTLINE:
1490 case EVCON_READING_HEADERS:
1491 case EVCON_READING_TRAILER:
1497 /* when we are in close detect mode, a read error means that
1498 * the other side closed their connection.
1500 if (evcon->flags & EVHTTP_CON_CLOSEDETECT) {
1501 evcon->flags &= ~EVHTTP_CON_CLOSEDETECT;
1502 EVUTIL_ASSERT(evcon->http_server == NULL);
1503 /* For connections from the client, we just
1504 * reset the connection so that it becomes
1507 EVUTIL_ASSERT(evcon->state == EVCON_IDLE);
1508 evhttp_connection_reset_(evcon);
1511 * If we have no more requests that need completion
1512 * and we want to auto-free the connection when all
1513 * requests have been completed.
1515 if (TAILQ_FIRST(&evcon->requests) == NULL
1516 && (evcon->flags & EVHTTP_CON_OUTGOING)
1517 && (evcon->flags & EVHTTP_CON_AUTOFREE)) {
1518 evhttp_connection_free(evcon);
1523 if (what & BEV_EVENT_TIMEOUT) {
1524 evhttp_connection_fail_(evcon, EVREQ_HTTP_TIMEOUT);
1525 } else if (what & (BEV_EVENT_EOF|BEV_EVENT_ERROR)) {
1526 if (what & BEV_EVENT_WRITING &&
1527 evcon->flags & EVHTTP_CON_READ_ON_WRITE_ERROR) {
1528 evhttp_connection_read_on_write_error(evcon, req);
1532 evhttp_connection_fail_(evcon, EVREQ_HTTP_EOF);
1533 } else if (what == BEV_EVENT_CONNECTED) {
1535 evhttp_connection_fail_(evcon, EVREQ_HTTP_BUFFER_ERROR);
1540 * Event callback for asynchronous connection attempt.
1543 evhttp_connection_cb(struct bufferevent *bufev, short what, void *arg)
1545 struct evhttp_connection *evcon = arg;
1547 ev_socklen_t errsz = sizeof(error);
1549 if (evcon->fd == -1)
1550 evcon->fd = bufferevent_getfd(bufev);
1552 if (!(what & BEV_EVENT_CONNECTED)) {
1553 /* some operating systems return ECONNREFUSED immediately
1554 * when connecting to a local address. the cleanup is going
1555 * to reschedule this function call.
1558 if (errno == ECONNREFUSED)
1561 evhttp_error_cb(bufev, what, arg);
1565 if (evcon->fd == -1) {
1566 event_debug(("%s: bufferevent_getfd returned -1",
1571 /* Check if the connection completed */
1572 if (getsockopt(evcon->fd, SOL_SOCKET, SO_ERROR, (void*)&error,
1574 event_debug(("%s: getsockopt for \"%s:%d\" on "EV_SOCK_FMT,
1575 __func__, evcon->address, evcon->port,
1576 EV_SOCK_ARG(evcon->fd)));
1581 event_debug(("%s: connect failed for \"%s:%d\" on "
1583 __func__, evcon->address, evcon->port,
1584 EV_SOCK_ARG(evcon->fd),
1585 evutil_socket_error_to_string(error)));
1589 /* We are connected to the server now */
1590 event_debug(("%s: connected to \"%s:%d\" on "EV_SOCK_FMT"\n",
1591 __func__, evcon->address, evcon->port,
1592 EV_SOCK_ARG(evcon->fd)));
1594 /* Reset the retry count as we were successful in connecting */
1595 evcon->retry_cnt = 0;
1596 evcon->state = EVCON_IDLE;
1598 /* reset the bufferevent cbs */
1599 bufferevent_setcb(evcon->bufev,
1605 if (!evutil_timerisset(&evcon->timeout)) {
1606 const struct timeval read_tv = { HTTP_READ_TIMEOUT, 0 };
1607 const struct timeval write_tv = { HTTP_WRITE_TIMEOUT, 0 };
1608 bufferevent_set_timeouts(evcon->bufev, &read_tv, &write_tv);
1610 bufferevent_set_timeouts(evcon->bufev, &evcon->timeout, &evcon->timeout);
1613 /* try to start requests that have queued up on this connection */
1614 evhttp_request_dispatch(evcon);
1618 evhttp_connection_cb_cleanup(evcon);
1622 * Check if we got a valid response code.
1626 evhttp_valid_response_code(int code)
1635 evhttp_parse_http_version(const char *version, struct evhttp_request *req)
1639 int n = sscanf(version, "HTTP/%d.%d%c", &major, &minor, &ch);
1640 if (n != 2 || major > 1) {
1641 event_debug(("%s: bad version %s on message %p from %s",
1642 __func__, version, req, req->remote_host));
1650 /* Parses the status line of a web server */
1653 evhttp_parse_response_line(struct evhttp_request *req, char *line)
1657 const char *readable = "";
1659 protocol = strsep(&line, " ");
1662 number = strsep(&line, " ");
1666 if (evhttp_parse_http_version(protocol, req) < 0)
1669 req->response_code = atoi(number);
1670 if (!evhttp_valid_response_code(req->response_code)) {
1671 event_debug(("%s: bad response code \"%s\"",
1676 if (req->response_code_line != NULL)
1677 mm_free(req->response_code_line);
1678 if ((req->response_code_line = mm_strdup(readable)) == NULL) {
1679 event_warn("%s: strdup", __func__);
1686 /* Parse the first line of a HTTP request */
1689 evhttp_parse_request_line(struct evhttp_request *req, char *line)
1694 const char *hostname;
1697 enum evhttp_cmd_type type;
1699 /* Parse the request line */
1700 method = strsep(&line, " ");
1703 uri = strsep(&line, " ");
1706 version = strsep(&line, " ");
1710 method_len = (uri - method) - 1;
1711 type = EVHTTP_REQ_UNKNOWN_;
1714 switch (method_len) {
1716 /* The length of the method string is 3, meaning it can only be one of two methods: GET or PUT */
1718 /* Since both GET and PUT share the same character 'T' at the end,
1719 * if the string doesn't have 'T', we can immediately determine this
1720 * is an invalid HTTP method */
1722 if (method[2] != 'T') {
1728 /* This first byte is 'G', so make sure the next byte is
1729 * 'E', if it isn't then this isn't a valid method */
1731 if (method[1] == 'E') {
1732 type = EVHTTP_REQ_GET;
1737 /* First byte is P, check second byte for 'U', if not,
1738 * we know it's an invalid method */
1739 if (method[1] == 'U') {
1740 type = EVHTTP_REQ_PUT;
1748 /* The method length is 4 bytes, leaving only the methods "POST" and "HEAD" */
1751 if (method[3] == 'T' && method[2] == 'S' && method[1] == 'O') {
1752 type = EVHTTP_REQ_POST;
1756 if (method[3] == 'D' && method[2] == 'A' && method[1] == 'E') {
1757 type = EVHTTP_REQ_HEAD;
1765 /* Method length is 5 bytes, which can only encompass PATCH and TRACE */
1768 if (method[4] == 'H' && method[3] == 'C' && method[2] == 'T' && method[1] == 'A') {
1769 type = EVHTTP_REQ_PATCH;
1773 if (method[4] == 'E' && method[3] == 'C' && method[2] == 'A' && method[1] == 'R') {
1774 type = EVHTTP_REQ_TRACE;
1783 /* Method length is 6, only valid method 6 bytes in length is DELEte */
1785 /* If the first byte isn't 'D' then it's invalid */
1786 if (*method != 'D') {
1790 if (method[5] == 'E' && method[4] == 'T' && method[3] == 'E' && method[2] == 'L' && method[1] == 'E') {
1791 type = EVHTTP_REQ_DELETE;
1796 /* Method length is 7, only valid methods are "OPTIONS" and "CONNECT" */
1799 if (method[6] == 'S' && method[5] == 'N' && method[4] == 'O' &&
1800 method[3] == 'I' && method[2] == 'T' && method[1] == 'P') {
1801 type = EVHTTP_REQ_OPTIONS;
1806 if (method[6] == 'T' && method[5] == 'C' && method[4] == 'E' &&
1807 method[3] == 'N' && method[2] == 'N' && method[1] == 'O') {
1808 type = EVHTTP_REQ_CONNECT;
1818 if ((int)type == EVHTTP_REQ_UNKNOWN_) {
1819 event_debug(("%s: bad method %s on request %p from %s",
1820 __func__, method, req, req->remote_host));
1821 /* No error yet; we'll give a better error later when
1822 * we see that req->type is unsupported. */
1827 if (evhttp_parse_http_version(version, req) < 0)
1830 if ((req->uri = mm_strdup(uri)) == NULL) {
1831 event_debug(("%s: mm_strdup", __func__));
1835 if (type == EVHTTP_REQ_CONNECT) {
1836 if ((req->uri_elems = evhttp_uri_parse_authority(req->uri)) == NULL) {
1840 if ((req->uri_elems = evhttp_uri_parse_with_flags(req->uri,
1841 EVHTTP_URI_NONCONFORMANT)) == NULL) {
1846 /* If we have an absolute-URI, check to see if it is an http request
1847 for a known vhost or server alias. If we don't know about this
1848 host, we consider it a proxy request. */
1849 scheme = evhttp_uri_get_scheme(req->uri_elems);
1850 hostname = evhttp_uri_get_host(req->uri_elems);
1851 if (scheme && (!evutil_ascii_strcasecmp(scheme, "http") ||
1852 !evutil_ascii_strcasecmp(scheme, "https")) &&
1854 !evhttp_find_vhost(req->evcon->http_server, NULL, hostname))
1855 req->flags |= EVHTTP_PROXY_REQUEST;
1861 evhttp_find_header(const struct evkeyvalq *headers, const char *key)
1863 struct evkeyval *header;
1865 TAILQ_FOREACH(header, headers, next) {
1866 if (evutil_ascii_strcasecmp(header->key, key) == 0)
1867 return (header->value);
1874 evhttp_clear_headers(struct evkeyvalq *headers)
1876 struct evkeyval *header;
1878 for (header = TAILQ_FIRST(headers);
1880 header = TAILQ_FIRST(headers)) {
1881 TAILQ_REMOVE(headers, header, next);
1882 mm_free(header->key);
1883 mm_free(header->value);
1889 * Returns 0, if the header was successfully removed.
1890 * Returns -1, if the header could not be found.
1894 evhttp_remove_header(struct evkeyvalq *headers, const char *key)
1896 struct evkeyval *header;
1898 TAILQ_FOREACH(header, headers, next) {
1899 if (evutil_ascii_strcasecmp(header->key, key) == 0)
1906 /* Free and remove the header that we found */
1907 TAILQ_REMOVE(headers, header, next);
1908 mm_free(header->key);
1909 mm_free(header->value);
1916 evhttp_header_is_valid_value(const char *value)
1918 const char *p = value;
1920 while ((p = strpbrk(p, "\r\n")) != NULL) {
1921 /* we really expect only one new line */
1922 p += strspn(p, "\r\n");
1923 /* we expect a space or tab for continuation */
1924 if (*p != ' ' && *p != '\t')
1931 evhttp_add_header(struct evkeyvalq *headers,
1932 const char *key, const char *value)
1934 event_debug(("%s: key: %s val: %s\n", __func__, key, value));
1936 if (strchr(key, '\r') != NULL || strchr(key, '\n') != NULL) {
1937 /* drop illegal headers */
1938 event_debug(("%s: dropping illegal header key\n", __func__));
1942 if (!evhttp_header_is_valid_value(value)) {
1943 event_debug(("%s: dropping illegal header value\n", __func__));
1947 return (evhttp_add_header_internal(headers, key, value));
1951 evhttp_add_header_internal(struct evkeyvalq *headers,
1952 const char *key, const char *value)
1954 struct evkeyval *header = mm_calloc(1, sizeof(struct evkeyval));
1955 if (header == NULL) {
1956 event_warn("%s: calloc", __func__);
1959 if ((header->key = mm_strdup(key)) == NULL) {
1961 event_warn("%s: strdup", __func__);
1964 if ((header->value = mm_strdup(value)) == NULL) {
1965 mm_free(header->key);
1967 event_warn("%s: strdup", __func__);
1971 TAILQ_INSERT_TAIL(headers, header, next);
1977 * Parses header lines from a request or a response into the specified
1978 * request object given an event buffer.
1981 * DATA_CORRUPTED on error
1982 * MORE_DATA_EXPECTED when we need to read more headers
1983 * ALL_DATA_READ when all headers have been read.
1986 enum message_read_status
1987 evhttp_parse_firstline_(struct evhttp_request *req, struct evbuffer *buffer)
1990 enum message_read_status status = ALL_DATA_READ;
1994 line = evbuffer_readln(buffer, &line_length, EVBUFFER_EOL_CRLF);
1996 if (req->evcon != NULL &&
1997 evbuffer_get_length(buffer) > req->evcon->max_headers_size)
1998 return (DATA_TOO_LONG);
2000 return (MORE_DATA_EXPECTED);
2003 if (req->evcon != NULL &&
2004 line_length > req->evcon->max_headers_size) {
2006 return (DATA_TOO_LONG);
2009 req->headers_size = line_length;
2011 switch (req->kind) {
2012 case EVHTTP_REQUEST:
2013 if (evhttp_parse_request_line(req, line) == -1)
2014 status = DATA_CORRUPTED;
2016 case EVHTTP_RESPONSE:
2017 if (evhttp_parse_response_line(req, line) == -1)
2018 status = DATA_CORRUPTED;
2021 status = DATA_CORRUPTED;
2029 evhttp_append_to_last_header(struct evkeyvalq *headers, char *line)
2031 struct evkeyval *header = TAILQ_LAST(headers, evkeyvalq);
2033 size_t old_len, line_len;
2038 old_len = strlen(header->value);
2040 /* Strip space from start and end of line. */
2041 while (*line == ' ' || *line == '\t')
2043 evutil_rtrim_lws_(line);
2045 line_len = strlen(line);
2047 newval = mm_realloc(header->value, old_len + line_len + 2);
2051 newval[old_len] = ' ';
2052 memcpy(newval + old_len + 1, line, line_len + 1);
2053 header->value = newval;
2058 enum message_read_status
2059 evhttp_parse_headers_(struct evhttp_request *req, struct evbuffer* buffer)
2061 enum message_read_status errcode = DATA_CORRUPTED;
2063 enum message_read_status status = MORE_DATA_EXPECTED;
2065 struct evkeyvalq* headers = req->input_headers;
2067 while ((line = evbuffer_readln(buffer, &line_length, EVBUFFER_EOL_CRLF))
2069 char *skey, *svalue;
2071 req->headers_size += line_length;
2073 if (req->evcon != NULL &&
2074 req->headers_size > req->evcon->max_headers_size) {
2075 errcode = DATA_TOO_LONG;
2079 if (*line == '\0') { /* Last header - Done */
2080 status = ALL_DATA_READ;
2085 /* Check if this is a continuation line */
2086 if (*line == ' ' || *line == '\t') {
2087 if (evhttp_append_to_last_header(headers, line) == -1)
2093 /* Processing of header lines */
2095 skey = strsep(&svalue, ":");
2099 svalue += strspn(svalue, " ");
2100 evutil_rtrim_lws_(svalue);
2102 if (evhttp_add_header(headers, skey, svalue) == -1)
2108 if (status == MORE_DATA_EXPECTED) {
2109 if (req->evcon != NULL &&
2110 req->headers_size + evbuffer_get_length(buffer) > req->evcon->max_headers_size)
2111 return (DATA_TOO_LONG);
2122 evhttp_get_body_length(struct evhttp_request *req)
2124 struct evkeyvalq *headers = req->input_headers;
2125 const char *content_length;
2126 const char *connection;
2128 content_length = evhttp_find_header(headers, "Content-Length");
2129 connection = evhttp_find_header(headers, "Connection");
2131 if (content_length == NULL && connection == NULL)
2133 else if (content_length == NULL &&
2134 evutil_ascii_strcasecmp(connection, "Close") != 0) {
2136 } else if (content_length == NULL) {
2140 ev_int64_t ntoread = evutil_strtoll(content_length, &endp, 10);
2141 if (*content_length == '\0' || *endp != '\0' || ntoread < 0) {
2142 event_debug(("%s: illegal content length: %s",
2143 __func__, content_length));
2146 req->ntoread = ntoread;
2149 event_debug(("%s: bytes to read: "EV_I64_FMT" (in buffer "EV_SIZE_FMT")\n",
2150 __func__, EV_I64_ARG(req->ntoread),
2151 EV_SIZE_ARG(evbuffer_get_length(bufferevent_get_input(req->evcon->bufev)))));
2157 evhttp_method_may_have_body(enum evhttp_cmd_type type)
2160 case EVHTTP_REQ_POST:
2161 case EVHTTP_REQ_PUT:
2162 case EVHTTP_REQ_PATCH:
2164 case EVHTTP_REQ_GET:
2165 case EVHTTP_REQ_DELETE:
2166 case EVHTTP_REQ_OPTIONS:
2167 case EVHTTP_REQ_CONNECT:
2170 case EVHTTP_REQ_TRACE:
2171 case EVHTTP_REQ_HEAD:
2178 evhttp_get_body(struct evhttp_connection *evcon, struct evhttp_request *req)
2180 const char *xfer_enc;
2182 /* If this is a request without a body, then we are done */
2183 if (req->kind == EVHTTP_REQUEST &&
2184 !evhttp_method_may_have_body(req->type)) {
2185 evhttp_connection_done(evcon);
2188 evcon->state = EVCON_READING_BODY;
2189 xfer_enc = evhttp_find_header(req->input_headers, "Transfer-Encoding");
2190 if (xfer_enc != NULL && evutil_ascii_strcasecmp(xfer_enc, "chunked") == 0) {
2194 if (evhttp_get_body_length(req) == -1) {
2195 evhttp_connection_fail_(evcon, EVREQ_HTTP_INVALID_HEADER);
2198 if (req->kind == EVHTTP_REQUEST && req->ntoread < 1) {
2199 /* An incoming request with no content-length and no
2200 * transfer-encoding has no body. */
2201 evhttp_connection_done(evcon);
2206 /* Should we send a 100 Continue status line? */
2207 switch (evhttp_have_expect(req, 1)) {
2209 /* XXX It would be nice to do some sanity
2210 checking here. Does the resource exist?
2211 Should the resource accept post requests? If
2212 no, we should respond with an error. For
2213 now, just optimistically tell the client to
2214 send their message body. */
2215 if (req->ntoread > 0) {
2216 /* ntoread is ev_int64_t, max_body_size is ev_uint64_t */
2217 if ((req->evcon->max_body_size <= EV_INT64_MAX) &&
2218 (ev_uint64_t)req->ntoread > req->evcon->max_body_size) {
2219 evhttp_lingering_fail(evcon, req);
2223 if (!evbuffer_get_length(bufferevent_get_input(evcon->bufev)))
2224 evhttp_send_continue(evcon, req);
2227 evhttp_send_error(req, HTTP_EXPECTATIONFAILED, NULL);
2232 evhttp_read_body(evcon, req);
2233 /* note the request may have been freed in evhttp_read_body */
2237 evhttp_read_firstline(struct evhttp_connection *evcon,
2238 struct evhttp_request *req)
2240 enum message_read_status res;
2242 res = evhttp_parse_firstline_(req, bufferevent_get_input(evcon->bufev));
2243 if (res == DATA_CORRUPTED || res == DATA_TOO_LONG) {
2244 /* Error while reading, terminate */
2245 event_debug(("%s: bad header lines on "EV_SOCK_FMT"\n",
2246 __func__, EV_SOCK_ARG(evcon->fd)));
2247 evhttp_connection_fail_(evcon, EVREQ_HTTP_INVALID_HEADER);
2249 } else if (res == MORE_DATA_EXPECTED) {
2250 /* Need more header lines */
2254 evcon->state = EVCON_READING_HEADERS;
2255 evhttp_read_header(evcon, req);
2259 evhttp_read_header(struct evhttp_connection *evcon,
2260 struct evhttp_request *req)
2262 enum message_read_status res;
2263 evutil_socket_t fd = evcon->fd;
2265 res = evhttp_parse_headers_(req, bufferevent_get_input(evcon->bufev));
2266 if (res == DATA_CORRUPTED || res == DATA_TOO_LONG) {
2267 /* Error while reading, terminate */
2268 event_debug(("%s: bad header lines on "EV_SOCK_FMT"\n",
2269 __func__, EV_SOCK_ARG(fd)));
2270 evhttp_connection_fail_(evcon, EVREQ_HTTP_INVALID_HEADER);
2272 } else if (res == MORE_DATA_EXPECTED) {
2273 /* Need more header lines */
2277 /* Callback can shut down connection with negative return value */
2278 if (req->header_cb != NULL) {
2279 if ((*req->header_cb)(req, req->cb_arg) < 0) {
2280 evhttp_connection_fail_(evcon, EVREQ_HTTP_EOF);
2285 /* Done reading headers, do the real work */
2286 switch (req->kind) {
2287 case EVHTTP_REQUEST:
2288 event_debug(("%s: checking for post data on "EV_SOCK_FMT"\n",
2289 __func__, EV_SOCK_ARG(fd)));
2290 evhttp_get_body(evcon, req);
2291 /* note the request may have been freed in evhttp_get_body */
2294 case EVHTTP_RESPONSE:
2295 /* Start over if we got a 100 Continue response. */
2296 if (req->response_code == 100) {
2297 struct evbuffer *output = bufferevent_get_output(evcon->bufev);
2298 evbuffer_add_buffer(output, req->output_buffer);
2299 evhttp_start_write_(evcon);
2302 if (!evhttp_response_needs_body(req)) {
2303 event_debug(("%s: skipping body for code %d\n",
2304 __func__, req->response_code));
2305 evhttp_connection_done(evcon);
2307 event_debug(("%s: start of read body for %s on "
2309 __func__, req->remote_host, EV_SOCK_ARG(fd)));
2310 evhttp_get_body(evcon, req);
2311 /* note the request may have been freed in
2312 * evhttp_get_body */
2317 event_warnx("%s: bad header on "EV_SOCK_FMT, __func__,
2319 evhttp_connection_fail_(evcon, EVREQ_HTTP_INVALID_HEADER);
2322 /* request may have been freed above */
2326 * Creates a TCP connection to the specified port and executes a callback
2327 * when finished. Failure or success is indicate by the passed connection
2330 * Although this interface accepts a hostname, it is intended to take
2331 * only numeric hostnames so that non-blocking DNS resolution can
2335 struct evhttp_connection *
2336 evhttp_connection_new(const char *address, ev_uint16_t port)
2338 return (evhttp_connection_base_new(NULL, NULL, address, port));
2341 struct evhttp_connection *
2342 evhttp_connection_base_bufferevent_new(struct event_base *base, struct evdns_base *dnsbase, struct bufferevent* bev,
2343 const char *address, ev_uint16_t port)
2345 struct evhttp_connection *evcon = NULL;
2347 event_debug(("Attempting connection to %s:%d\n", address, port));
2349 if ((evcon = mm_calloc(1, sizeof(struct evhttp_connection))) == NULL) {
2350 event_warn("%s: calloc failed", __func__);
2357 evcon->max_headers_size = EV_SIZE_MAX;
2358 evcon->max_body_size = EV_SIZE_MAX;
2360 evutil_timerclear(&evcon->timeout);
2361 evcon->retry_cnt = evcon->retry_max = 0;
2363 if ((evcon->address = mm_strdup(address)) == NULL) {
2364 event_warn("%s: strdup failed", __func__);
2369 if (!(bev = bufferevent_socket_new(base, -1, 0))) {
2370 event_warn("%s: bufferevent_socket_new failed", __func__);
2375 bufferevent_setcb(bev, evhttp_read_cb, evhttp_write_cb, evhttp_error_cb, evcon);
2378 evcon->state = EVCON_DISCONNECTED;
2379 TAILQ_INIT(&evcon->requests);
2381 evcon->initial_retry_timeout.tv_sec = 2;
2382 evcon->initial_retry_timeout.tv_usec = 0;
2386 if (bufferevent_get_base(bev) != base)
2387 bufferevent_base_set(base, evcon->bufev);
2390 event_deferred_cb_init_(
2391 &evcon->read_more_deferred_cb,
2392 bufferevent_get_priority(bev),
2393 evhttp_deferred_read_cb, evcon);
2395 evcon->dns_base = dnsbase;
2396 evcon->ai_family = AF_UNSPEC;
2402 evhttp_connection_free(evcon);
2406 struct bufferevent* evhttp_connection_get_bufferevent(struct evhttp_connection *evcon)
2408 return evcon->bufev;
2412 evhttp_connection_get_server(struct evhttp_connection *evcon)
2414 return evcon->http_server;
2417 struct evhttp_connection *
2418 evhttp_connection_base_new(struct event_base *base, struct evdns_base *dnsbase,
2419 const char *address, ev_uint16_t port)
2421 return evhttp_connection_base_bufferevent_new(base, dnsbase, NULL, address, port);
2424 void evhttp_connection_set_family(struct evhttp_connection *evcon,
2427 evcon->ai_family = family;
2430 int evhttp_connection_set_flags(struct evhttp_connection *evcon,
2433 int avail_flags = 0;
2434 avail_flags |= EVHTTP_CON_REUSE_CONNECTED_ADDR;
2435 avail_flags |= EVHTTP_CON_READ_ON_WRITE_ERROR;
2437 if (flags & ~avail_flags || flags > EVHTTP_CON_PUBLIC_FLAGS_END)
2439 evcon->flags &= ~avail_flags;
2441 evcon->flags |= flags;
2447 evhttp_connection_set_base(struct evhttp_connection *evcon,
2448 struct event_base *base)
2450 EVUTIL_ASSERT(evcon->base == NULL);
2451 EVUTIL_ASSERT(evcon->state == EVCON_DISCONNECTED);
2453 bufferevent_base_set(base, evcon->bufev);
2457 evhttp_connection_set_timeout(struct evhttp_connection *evcon,
2458 int timeout_in_secs)
2460 if (timeout_in_secs == -1)
2461 evhttp_connection_set_timeout_tv(evcon, NULL);
2464 tv.tv_sec = timeout_in_secs;
2466 evhttp_connection_set_timeout_tv(evcon, &tv);
2471 evhttp_connection_set_timeout_tv(struct evhttp_connection *evcon,
2472 const struct timeval* tv)
2475 evcon->timeout = *tv;
2476 bufferevent_set_timeouts(evcon->bufev, &evcon->timeout, &evcon->timeout);
2478 const struct timeval read_tv = { HTTP_READ_TIMEOUT, 0 };
2479 const struct timeval write_tv = { HTTP_WRITE_TIMEOUT, 0 };
2480 evutil_timerclear(&evcon->timeout);
2481 bufferevent_set_timeouts(evcon->bufev, &read_tv, &write_tv);
2486 evhttp_connection_set_initial_retry_tv(struct evhttp_connection *evcon,
2487 const struct timeval *tv)
2490 evcon->initial_retry_timeout = *tv;
2492 evutil_timerclear(&evcon->initial_retry_timeout);
2493 evcon->initial_retry_timeout.tv_sec = 2;
2498 evhttp_connection_set_retries(struct evhttp_connection *evcon,
2501 evcon->retry_max = retry_max;
2505 evhttp_connection_set_closecb(struct evhttp_connection *evcon,
2506 void (*cb)(struct evhttp_connection *, void *), void *cbarg)
2508 evcon->closecb = cb;
2509 evcon->closecb_arg = cbarg;
2513 evhttp_connection_get_peer(struct evhttp_connection *evcon,
2514 char **address, ev_uint16_t *port)
2516 *address = evcon->address;
2517 *port = evcon->port;
2520 const struct sockaddr*
2521 evhttp_connection_get_addr(struct evhttp_connection *evcon)
2523 return bufferevent_socket_get_conn_address_(evcon->bufev);
2527 evhttp_connection_connect_(struct evhttp_connection *evcon)
2529 int old_state = evcon->state;
2530 const char *address = evcon->address;
2531 const struct sockaddr *sa = evhttp_connection_get_addr(evcon);
2534 if (evcon->state == EVCON_CONNECTING)
2537 evhttp_connection_reset_(evcon);
2539 EVUTIL_ASSERT(!(evcon->flags & EVHTTP_CON_INCOMING));
2540 evcon->flags |= EVHTTP_CON_OUTGOING;
2542 if (evcon->bind_address || evcon->bind_port) {
2543 evcon->fd = bind_socket(
2544 evcon->bind_address, evcon->bind_port, 0 /*reuse*/);
2545 if (evcon->fd == -1) {
2546 event_debug(("%s: failed to bind to \"%s\"",
2547 __func__, evcon->bind_address));
2551 bufferevent_setfd(evcon->bufev, evcon->fd);
2553 bufferevent_setfd(evcon->bufev, -1);
2556 /* Set up a callback for successful connection setup */
2557 bufferevent_setcb(evcon->bufev,
2558 NULL /* evhttp_read_cb */,
2559 NULL /* evhttp_write_cb */,
2560 evhttp_connection_cb,
2562 if (!evutil_timerisset(&evcon->timeout)) {
2563 const struct timeval conn_tv = { HTTP_CONNECT_TIMEOUT, 0 };
2564 bufferevent_set_timeouts(evcon->bufev, &conn_tv, &conn_tv);
2566 bufferevent_set_timeouts(evcon->bufev, &evcon->timeout, &evcon->timeout);
2568 /* make sure that we get a write callback */
2569 bufferevent_enable(evcon->bufev, EV_WRITE);
2571 evcon->state = EVCON_CONNECTING;
2573 if (evcon->flags & EVHTTP_CON_REUSE_CONNECTED_ADDR &&
2575 (sa->sa_family == AF_INET || sa->sa_family == AF_INET6)) {
2576 int socklen = sizeof(struct sockaddr_in);
2577 if (sa->sa_family == AF_INET6) {
2578 socklen = sizeof(struct sockaddr_in6);
2580 ret = bufferevent_socket_connect(evcon->bufev, sa, socklen);
2582 ret = bufferevent_socket_connect_hostname(evcon->bufev,
2583 evcon->dns_base, evcon->ai_family, address, evcon->port);
2587 evcon->state = old_state;
2588 event_sock_warn(evcon->fd, "%s: connection to \"%s\" failed",
2589 __func__, evcon->address);
2590 /* some operating systems return ECONNREFUSED immediately
2591 * when connecting to a local address. the cleanup is going
2592 * to reschedule this function call.
2594 evhttp_connection_cb_cleanup(evcon);
2602 * Starts an HTTP request on the provided evhttp_connection object.
2603 * If the connection object is not connected to the web server already,
2604 * this will start the connection.
2608 evhttp_make_request(struct evhttp_connection *evcon,
2609 struct evhttp_request *req,
2610 enum evhttp_cmd_type type, const char *uri)
2612 /* We are making a request */
2613 req->kind = EVHTTP_REQUEST;
2615 if (req->uri != NULL)
2617 if ((req->uri = mm_strdup(uri)) == NULL) {
2618 event_warn("%s: strdup", __func__);
2619 evhttp_request_free_auto(req);
2623 /* Set the protocol version if it is not supplied */
2624 if (!req->major && !req->minor) {
2629 EVUTIL_ASSERT(req->evcon == NULL);
2631 EVUTIL_ASSERT(!(req->flags & EVHTTP_REQ_OWN_CONNECTION));
2633 TAILQ_INSERT_TAIL(&evcon->requests, req, next);
2635 /* If the connection object is not connected; make it so */
2636 if (!evhttp_connected(evcon)) {
2637 int res = evhttp_connection_connect_(evcon);
2638 /* evhttp_connection_fail_(), which is called through
2639 * evhttp_connection_connect_(), assumes that req lies in
2640 * evcon->requests. Thus, enqueue the request in advance and
2641 * remove it in the error case. */
2643 TAILQ_REMOVE(&evcon->requests, req, next);
2649 * If it's connected already and we are the first in the queue,
2650 * then we can dispatch this request immediately. Otherwise, it
2651 * will be dispatched once the pending requests are completed.
2653 if (TAILQ_FIRST(&evcon->requests) == req)
2654 evhttp_request_dispatch(evcon);
2660 evhttp_cancel_request(struct evhttp_request *req)
2662 struct evhttp_connection *evcon = req->evcon;
2663 if (evcon != NULL) {
2664 /* We need to remove it from the connection */
2665 if (TAILQ_FIRST(&evcon->requests) == req) {
2666 /* it's currently being worked on, so reset
2669 evhttp_connection_fail_(evcon,
2670 EVREQ_HTTP_REQUEST_CANCEL);
2672 /* connection fail freed the request */
2675 /* otherwise, we can just remove it from the
2678 TAILQ_REMOVE(&evcon->requests, req, next);
2682 evhttp_request_free_auto(req);
2686 * Reads data from file descriptor into request structure
2687 * Request structure needs to be set up correctly.
2691 evhttp_start_read_(struct evhttp_connection *evcon)
2693 bufferevent_disable(evcon->bufev, EV_WRITE);
2694 bufferevent_enable(evcon->bufev, EV_READ);
2696 evcon->state = EVCON_READING_FIRSTLINE;
2697 /* Reset the bufferevent callbacks */
2698 bufferevent_setcb(evcon->bufev,
2704 /* If there's still data pending, process it next time through the
2705 * loop. Don't do it now; that could get recusive. */
2706 if (evbuffer_get_length(bufferevent_get_input(evcon->bufev))) {
2707 event_deferred_cb_schedule_(get_deferred_queue(evcon),
2708 &evcon->read_more_deferred_cb);
2713 evhttp_start_write_(struct evhttp_connection *evcon)
2715 bufferevent_disable(evcon->bufev, EV_WRITE);
2716 bufferevent_enable(evcon->bufev, EV_READ);
2718 evcon->state = EVCON_WRITING;
2719 evhttp_write_buffer(evcon, evhttp_write_connectioncb, NULL);
2723 evhttp_send_done(struct evhttp_connection *evcon, void *arg)
2726 struct evhttp_request *req = TAILQ_FIRST(&evcon->requests);
2727 TAILQ_REMOVE(&evcon->requests, req, next);
2729 if (req->on_complete_cb != NULL) {
2730 req->on_complete_cb(req, req->on_complete_cb_arg);
2734 (REQ_VERSION_BEFORE(req, 1, 1) &&
2735 !evhttp_is_connection_keepalive(req->input_headers)) ||
2736 evhttp_is_request_connection_close(req);
2738 EVUTIL_ASSERT(req->flags & EVHTTP_REQ_OWN_CONNECTION);
2739 evhttp_request_free(req);
2742 evhttp_connection_free(evcon);
2746 /* we have a persistent connection; try to accept another request. */
2747 if (evhttp_associate_new_request_with_connection(evcon) == -1) {
2748 evhttp_connection_free(evcon);
2753 * Returns an error page.
2757 evhttp_send_error(struct evhttp_request *req, int error, const char *reason)
2760 #define ERR_FORMAT "<HTML><HEAD>\n" \
2761 "<TITLE>%d %s</TITLE>\n" \
2766 struct evbuffer *buf = evbuffer_new();
2768 /* if we cannot allocate memory; we just drop the connection */
2769 evhttp_connection_free(req->evcon);
2772 if (reason == NULL) {
2773 reason = evhttp_response_phrase_internal(error);
2776 evhttp_response_code_(req, error, reason);
2778 evbuffer_add_printf(buf, ERR_FORMAT, error, reason, reason);
2780 evhttp_send_page_(req, buf);
2786 /* Requires that headers and response code are already set up */
2789 evhttp_send(struct evhttp_request *req, struct evbuffer *databuf)
2791 struct evhttp_connection *evcon = req->evcon;
2793 if (evcon == NULL) {
2794 evhttp_request_free(req);
2798 EVUTIL_ASSERT(TAILQ_FIRST(&evcon->requests) == req);
2800 /* we expect no more calls form the user on this request */
2803 /* xxx: not sure if we really should expose the data buffer this way */
2804 if (databuf != NULL)
2805 evbuffer_add_buffer(req->output_buffer, databuf);
2807 /* Adds headers to the response */
2808 evhttp_make_header(evcon, req);
2810 evhttp_write_buffer(evcon, evhttp_send_done, NULL);
2814 evhttp_send_reply(struct evhttp_request *req, int code, const char *reason,
2815 struct evbuffer *databuf)
2817 evhttp_response_code_(req, code, reason);
2819 evhttp_send(req, databuf);
2823 evhttp_send_reply_start(struct evhttp_request *req, int code,
2826 evhttp_response_code_(req, code, reason);
2828 if (req->evcon == NULL)
2831 if (evhttp_find_header(req->output_headers, "Content-Length") == NULL &&
2832 REQ_VERSION_ATLEAST(req, 1, 1) &&
2833 evhttp_response_needs_body(req)) {
2835 * prefer HTTP/1.1 chunked encoding to closing the connection;
2836 * note RFC 2616 section 4.4 forbids it with Content-Length:
2837 * and it's not necessary then anyway.
2839 evhttp_add_header(req->output_headers, "Transfer-Encoding",
2845 evhttp_make_header(req->evcon, req);
2846 evhttp_write_buffer(req->evcon, NULL, NULL);
2850 evhttp_send_reply_chunk_with_cb(struct evhttp_request *req, struct evbuffer *databuf,
2851 void (*cb)(struct evhttp_connection *, void *), void *arg)
2853 struct evhttp_connection *evcon = req->evcon;
2854 struct evbuffer *output;
2859 output = bufferevent_get_output(evcon->bufev);
2861 if (evbuffer_get_length(databuf) == 0)
2863 if (!evhttp_response_needs_body(req))
2866 evbuffer_add_printf(output, "%x\r\n",
2867 (unsigned)evbuffer_get_length(databuf));
2869 evbuffer_add_buffer(output, databuf);
2871 evbuffer_add(output, "\r\n", 2);
2873 evhttp_write_buffer(evcon, cb, arg);
2877 evhttp_send_reply_chunk(struct evhttp_request *req, struct evbuffer *databuf)
2879 evhttp_send_reply_chunk_with_cb(req, databuf, NULL, NULL);
2882 evhttp_send_reply_end(struct evhttp_request *req)
2884 struct evhttp_connection *evcon = req->evcon;
2885 struct evbuffer *output;
2887 if (evcon == NULL) {
2888 evhttp_request_free(req);
2892 output = bufferevent_get_output(evcon->bufev);
2894 /* we expect no more calls form the user on this request */
2898 evbuffer_add(output, "0\r\n\r\n", 5);
2899 evhttp_write_buffer(req->evcon, evhttp_send_done, NULL);
2901 } else if (evbuffer_get_length(output) == 0) {
2902 /* let the connection know that we are done with the request */
2903 evhttp_send_done(evcon, NULL);
2905 /* make the callback execute after all data has been written */
2906 evcon->cb = evhttp_send_done;
2907 evcon->cb_arg = NULL;
2911 static const char *informational_phrases[] = {
2912 /* 100 */ "Continue",
2913 /* 101 */ "Switching Protocols"
2916 static const char *success_phrases[] = {
2918 /* 201 */ "Created",
2919 /* 202 */ "Accepted",
2920 /* 203 */ "Non-Authoritative Information",
2921 /* 204 */ "No Content",
2922 /* 205 */ "Reset Content",
2923 /* 206 */ "Partial Content"
2926 static const char *redirection_phrases[] = {
2927 /* 300 */ "Multiple Choices",
2928 /* 301 */ "Moved Permanently",
2930 /* 303 */ "See Other",
2931 /* 304 */ "Not Modified",
2932 /* 305 */ "Use Proxy",
2933 /* 307 */ "Temporary Redirect"
2936 static const char *client_error_phrases[] = {
2937 /* 400 */ "Bad Request",
2938 /* 401 */ "Unauthorized",
2939 /* 402 */ "Payment Required",
2940 /* 403 */ "Forbidden",
2941 /* 404 */ "Not Found",
2942 /* 405 */ "Method Not Allowed",
2943 /* 406 */ "Not Acceptable",
2944 /* 407 */ "Proxy Authentication Required",
2945 /* 408 */ "Request Time-out",
2946 /* 409 */ "Conflict",
2948 /* 411 */ "Length Required",
2949 /* 412 */ "Precondition Failed",
2950 /* 413 */ "Request Entity Too Large",
2951 /* 414 */ "Request-URI Too Large",
2952 /* 415 */ "Unsupported Media Type",
2953 /* 416 */ "Requested range not satisfiable",
2954 /* 417 */ "Expectation Failed"
2957 static const char *server_error_phrases[] = {
2958 /* 500 */ "Internal Server Error",
2959 /* 501 */ "Not Implemented",
2960 /* 502 */ "Bad Gateway",
2961 /* 503 */ "Service Unavailable",
2962 /* 504 */ "Gateway Time-out",
2963 /* 505 */ "HTTP Version not supported"
2966 struct response_class {
2968 size_t num_responses;
2969 const char **responses;
2973 #define MEMBERSOF(x) (sizeof(x)/sizeof(x[0]))
2976 static const struct response_class response_classes[] = {
2977 /* 1xx */ { "Informational", MEMBERSOF(informational_phrases), informational_phrases },
2978 /* 2xx */ { "Success", MEMBERSOF(success_phrases), success_phrases },
2979 /* 3xx */ { "Redirection", MEMBERSOF(redirection_phrases), redirection_phrases },
2980 /* 4xx */ { "Client Error", MEMBERSOF(client_error_phrases), client_error_phrases },
2981 /* 5xx */ { "Server Error", MEMBERSOF(server_error_phrases), server_error_phrases }
2985 evhttp_response_phrase_internal(int code)
2987 int klass = code / 100 - 1;
2988 int subcode = code % 100;
2990 /* Unknown class - can't do any better here */
2991 if (klass < 0 || klass >= (int) MEMBERSOF(response_classes))
2992 return "Unknown Status Class";
2994 /* Unknown sub-code, return class name at least */
2995 if (subcode >= (int) response_classes[klass].num_responses)
2996 return response_classes[klass].name;
2998 return response_classes[klass].responses[subcode];
3002 evhttp_response_code_(struct evhttp_request *req, int code, const char *reason)
3004 req->kind = EVHTTP_RESPONSE;
3005 req->response_code = code;
3006 if (req->response_code_line != NULL)
3007 mm_free(req->response_code_line);
3009 reason = evhttp_response_phrase_internal(code);
3010 req->response_code_line = mm_strdup(reason);
3011 if (req->response_code_line == NULL) {
3012 event_warn("%s: strdup", __func__);
3013 /* XXX what else can we do? */
3018 evhttp_send_page_(struct evhttp_request *req, struct evbuffer *databuf)
3020 if (!req->major || !req->minor) {
3025 if (req->kind != EVHTTP_RESPONSE)
3026 evhttp_response_code_(req, 200, "OK");
3028 evhttp_clear_headers(req->output_headers);
3029 evhttp_add_header(req->output_headers, "Content-Type", "text/html");
3030 evhttp_add_header(req->output_headers, "Connection", "close");
3032 evhttp_send(req, databuf);
3035 static const char uri_chars[256] = {
3037 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3038 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3039 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0,
3040 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,
3042 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3043 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1,
3044 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3045 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0,
3047 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3048 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3049 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3050 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3052 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3053 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3054 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3055 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3058 #define CHAR_IS_UNRESERVED(c) \
3059 (uri_chars[(unsigned char)(c)])
3062 * Helper functions to encode/decode a string for inclusion in a URI.
3063 * The returned string must be freed by the caller.
3066 evhttp_uriencode(const char *uri, ev_ssize_t len, int space_as_plus)
3068 struct evbuffer *buf = evbuffer_new();
3069 const char *p, *end;
3070 char *result = NULL;
3077 if (uri + len < uri) {
3083 size_t slen = strlen(uri);
3085 if (slen >= EV_SSIZE_MAX) {
3086 /* we don't want to mix signed and unsigned */
3090 if (uri + slen < uri) {
3097 for (p = uri; p < end; p++) {
3098 if (CHAR_IS_UNRESERVED(*p)) {
3099 evbuffer_add(buf, p, 1);
3100 } else if (*p == ' ' && space_as_plus) {
3101 evbuffer_add(buf, "+", 1);
3103 evbuffer_add_printf(buf, "%%%02X", (unsigned char)(*p));
3107 evbuffer_add(buf, "", 1); /* NUL-terminator. */
3108 result = mm_malloc(evbuffer_get_length(buf));
3111 evbuffer_remove(buf, result, evbuffer_get_length(buf));
3120 evhttp_encode_uri(const char *str)
3122 return evhttp_uriencode(str, -1, 0);
3126 * @param decode_plus_ctl: if 1, we decode plus into space. If 0, we don't.
3127 * If -1, when true we transform plus to space only after we've seen
3128 * a ?. -1 is deprecated.
3129 * @return the number of bytes written to 'ret'.
3132 evhttp_decode_uri_internal(
3133 const char *uri, size_t length, char *ret, int decode_plus_ctl)
3137 int decode_plus = (decode_plus_ctl == 1) ? 1: 0;
3140 for (i = j = 0; i < length; i++) {
3143 if (decode_plus_ctl < 0)
3145 } else if (c == '+' && decode_plus) {
3147 } else if ((i + 2) < length && c == '%' &&
3148 EVUTIL_ISXDIGIT_(uri[i+1]) && EVUTIL_ISXDIGIT_(uri[i+2])) {
3153 c = (char)strtol(tmp, NULL, 16);
3165 evhttp_decode_uri(const char *uri)
3169 if ((ret = mm_malloc(strlen(uri) + 1)) == NULL) {
3170 event_warn("%s: malloc(%lu)", __func__,
3171 (unsigned long)(strlen(uri) + 1));
3175 evhttp_decode_uri_internal(uri, strlen(uri),
3176 ret, -1 /*always_decode_plus*/);
3182 evhttp_uridecode(const char *uri, int decode_plus, size_t *size_out)
3187 if ((ret = mm_malloc(strlen(uri) + 1)) == NULL) {
3188 event_warn("%s: malloc(%lu)", __func__,
3189 (unsigned long)(strlen(uri) + 1));
3193 n = evhttp_decode_uri_internal(uri, strlen(uri),
3194 ret, !!decode_plus/*always_decode_plus*/);
3197 EVUTIL_ASSERT(n >= 0);
3198 *size_out = (size_t)n;
3205 * Helper function to parse out arguments in a query.
3206 * The arguments are separated by key and value.
3210 evhttp_parse_query_impl(const char *str, struct evkeyvalq *headers,
3216 const char *query_part;
3218 struct evhttp_uri *uri=NULL;
3220 TAILQ_INIT(headers);
3223 uri = evhttp_uri_parse(str);
3226 query_part = evhttp_uri_get_query(uri);
3231 /* No arguments - we are done */
3232 if (!query_part || !strlen(query_part)) {
3237 if ((line = mm_strdup(query_part)) == NULL) {
3238 event_warn("%s: strdup", __func__);
3242 p = argument = line;
3243 while (p != NULL && *p != '\0') {
3244 char *key, *value, *decoded_value;
3245 argument = strsep(&p, "&");
3248 key = strsep(&value, "=");
3249 if (value == NULL || *key == '\0') {
3253 if ((decoded_value = mm_malloc(strlen(value) + 1)) == NULL) {
3254 event_warn("%s: mm_malloc", __func__);
3257 evhttp_decode_uri_internal(value, strlen(value),
3258 decoded_value, 1 /*always_decode_plus*/);
3259 event_debug(("Query Param: %s -> %s\n", key, decoded_value));
3260 evhttp_add_header_internal(headers, key, decoded_value);
3261 mm_free(decoded_value);
3267 evhttp_clear_headers(headers);
3272 evhttp_uri_free(uri);
3277 evhttp_parse_query(const char *uri, struct evkeyvalq *headers)
3279 return evhttp_parse_query_impl(uri, headers, 1);
3282 evhttp_parse_query_str(const char *uri, struct evkeyvalq *headers)
3284 return evhttp_parse_query_impl(uri, headers, 0);
3287 static struct evhttp_cb *
3288 evhttp_dispatch_callback(struct httpcbq *callbacks, struct evhttp_request *req)
3290 struct evhttp_cb *cb;
3295 /* Test for different URLs */
3296 path = evhttp_uri_get_path(req->uri_elems);
3297 offset = strlen(path);
3298 if ((translated = mm_malloc(offset + 1)) == NULL)
3300 evhttp_decode_uri_internal(path, offset, translated,
3301 0 /* decode_plus */);
3303 TAILQ_FOREACH(cb, callbacks, next) {
3304 if (!strcmp(cb->what, translated)) {
3305 mm_free(translated);
3310 mm_free(translated);
3316 prefix_suffix_match(const char *pattern, const char *name, int ignorecase)
3321 switch (c = *pattern++) {
3323 return *name == '\0';
3326 while (*name != '\0') {
3327 if (prefix_suffix_match(pattern, name,
3336 EVUTIL_TOLOWER_(c) != EVUTIL_TOLOWER_(*name))
3346 Search the vhost hierarchy beginning with http for a server alias
3347 matching hostname. If a match is found, and outhttp is non-null,
3348 outhttp is set to the matching http object and 1 is returned.
3352 evhttp_find_alias(struct evhttp *http, struct evhttp **outhttp,
3353 const char *hostname)
3355 struct evhttp_server_alias *alias;
3356 struct evhttp *vhost;
3358 TAILQ_FOREACH(alias, &http->aliases, next) {
3359 /* XXX Do we need to handle IP addresses? */
3360 if (!evutil_ascii_strcasecmp(alias->alias, hostname)) {
3367 /* XXX It might be good to avoid recursion here, but I don't
3368 see a way to do that w/o a list. */
3369 TAILQ_FOREACH(vhost, &http->virtualhosts, next_vhost) {
3370 if (evhttp_find_alias(vhost, outhttp, hostname))
3378 Attempts to find the best http object to handle a request for a hostname.
3379 All aliases for the root http object and vhosts are searched for an exact
3380 match. Then, the vhost hierarchy is traversed again for a matching
3383 If an alias or vhost is matched, 1 is returned, and outhttp, if non-null,
3384 is set with the best matching http object. If there are no matches, the
3385 root http object is stored in outhttp and 0 is returned.
3389 evhttp_find_vhost(struct evhttp *http, struct evhttp **outhttp,
3390 const char *hostname)
3392 struct evhttp *vhost;
3393 struct evhttp *oldhttp;
3394 int match_found = 0;
3396 if (evhttp_find_alias(http, outhttp, hostname))
3401 TAILQ_FOREACH(vhost, &http->virtualhosts, next_vhost) {
3402 if (prefix_suffix_match(vhost->vhost_pattern,
3403 hostname, 1 /* ignorecase */)) {
3409 } while (oldhttp != http);
3418 evhttp_handle_request(struct evhttp_request *req, void *arg)
3420 struct evhttp *http = arg;
3421 struct evhttp_cb *cb = NULL;
3422 const char *hostname;
3424 /* we have a new request on which the user needs to take action */
3427 bufferevent_disable(req->evcon->bufev, EV_READ);
3429 if (req->type == 0 || req->uri == NULL) {
3430 evhttp_send_error(req, req->response_code, NULL);
3434 if ((http->allowed_methods & req->type) == 0) {
3435 event_debug(("Rejecting disallowed method %x (allowed: %x)\n",
3436 (unsigned)req->type, (unsigned)http->allowed_methods));
3437 evhttp_send_error(req, HTTP_NOTIMPLEMENTED, NULL);
3441 /* handle potential virtual hosts */
3442 hostname = evhttp_request_get_host(req);
3443 if (hostname != NULL) {
3444 evhttp_find_vhost(http, &http, hostname);
3447 if ((cb = evhttp_dispatch_callback(&http->callbacks, req)) != NULL) {
3448 (*cb->cb)(req, cb->cbarg);
3452 /* Generic call back */
3454 (*http->gencb)(req, http->gencbarg);
3457 /* We need to send a 404 here */
3458 #define ERR_FORMAT "<html><head>" \
3459 "<title>404 Not Found</title>" \
3461 "<h1>Not Found</h1>" \
3462 "<p>The requested URL %s was not found on this server.</p>"\
3466 struct evbuffer *buf;
3468 if ((escaped_html = evhttp_htmlescape(req->uri)) == NULL) {
3469 evhttp_connection_free(req->evcon);
3473 if ((buf = evbuffer_new()) == NULL) {
3474 mm_free(escaped_html);
3475 evhttp_connection_free(req->evcon);
3479 evhttp_response_code_(req, HTTP_NOTFOUND, "Not Found");
3481 evbuffer_add_printf(buf, ERR_FORMAT, escaped_html);
3483 mm_free(escaped_html);
3485 evhttp_send_page_(req, buf);
3492 /* Listener callback when a connection arrives at a server. */
3494 accept_socket_cb(struct evconnlistener *listener, evutil_socket_t nfd, struct sockaddr *peer_sa, int peer_socklen, void *arg)
3496 struct evhttp *http = arg;
3498 evhttp_get_request(http, nfd, peer_sa, peer_socklen);
3502 evhttp_bind_socket(struct evhttp *http, const char *address, ev_uint16_t port)
3504 struct evhttp_bound_socket *bound =
3505 evhttp_bind_socket_with_handle(http, address, port);
3511 struct evhttp_bound_socket *
3512 evhttp_bind_socket_with_handle(struct evhttp *http, const char *address, ev_uint16_t port)
3515 struct evhttp_bound_socket *bound;
3517 if ((fd = bind_socket(address, port, 1 /*reuse*/)) == -1)
3520 if (listen(fd, 128) == -1) {
3521 event_sock_warn(fd, "%s: listen", __func__);
3522 evutil_closesocket(fd);
3526 bound = evhttp_accept_socket_with_handle(http, fd);
3528 if (bound != NULL) {
3529 event_debug(("Bound to port %d - Awaiting connections ... ",
3538 evhttp_accept_socket(struct evhttp *http, evutil_socket_t fd)
3540 struct evhttp_bound_socket *bound =
3541 evhttp_accept_socket_with_handle(http, fd);
3548 evhttp_foreach_bound_socket(struct evhttp *http,
3549 evhttp_bound_socket_foreach_fn *function,
3552 struct evhttp_bound_socket *bound;
3554 TAILQ_FOREACH(bound, &http->sockets, next)
3555 function(bound, argument);
3558 struct evhttp_bound_socket *
3559 evhttp_accept_socket_with_handle(struct evhttp *http, evutil_socket_t fd)
3561 struct evhttp_bound_socket *bound;
3562 struct evconnlistener *listener;
3564 LEV_OPT_REUSEABLE|LEV_OPT_CLOSE_ON_EXEC|LEV_OPT_CLOSE_ON_FREE;
3566 listener = evconnlistener_new(http->base, NULL, NULL,
3568 0, /* Backlog is '0' because we already said 'listen' */
3573 bound = evhttp_bind_listener(http, listener);
3575 evconnlistener_free(listener);
3581 struct evhttp_bound_socket *
3582 evhttp_bind_listener(struct evhttp *http, struct evconnlistener *listener)
3584 struct evhttp_bound_socket *bound;
3586 bound = mm_malloc(sizeof(struct evhttp_bound_socket));
3590 bound->listener = listener;
3591 TAILQ_INSERT_TAIL(&http->sockets, bound, next);
3593 evconnlistener_set_cb(listener, accept_socket_cb, http);
3598 evhttp_bound_socket_get_fd(struct evhttp_bound_socket *bound)
3600 return evconnlistener_get_fd(bound->listener);
3603 struct evconnlistener *
3604 evhttp_bound_socket_get_listener(struct evhttp_bound_socket *bound)
3606 return bound->listener;
3610 evhttp_del_accept_socket(struct evhttp *http, struct evhttp_bound_socket *bound)
3612 TAILQ_REMOVE(&http->sockets, bound, next);
3613 evconnlistener_free(bound->listener);
3617 static struct evhttp*
3618 evhttp_new_object(void)
3620 struct evhttp *http = NULL;
3622 if ((http = mm_calloc(1, sizeof(struct evhttp))) == NULL) {
3623 event_warn("%s: calloc", __func__);
3627 evutil_timerclear(&http->timeout);
3628 evhttp_set_max_headers_size(http, EV_SIZE_MAX);
3629 evhttp_set_max_body_size(http, EV_SIZE_MAX);
3630 evhttp_set_default_content_type(http, "text/html; charset=ISO-8859-1");
3631 evhttp_set_allowed_methods(http,
3638 TAILQ_INIT(&http->sockets);
3639 TAILQ_INIT(&http->callbacks);
3640 TAILQ_INIT(&http->connections);
3641 TAILQ_INIT(&http->virtualhosts);
3642 TAILQ_INIT(&http->aliases);
3648 evhttp_new(struct event_base *base)
3650 struct evhttp *http = NULL;
3652 http = evhttp_new_object();
3661 * Start a web server on the specified address and port.
3665 evhttp_start(const char *address, ev_uint16_t port)
3667 struct evhttp *http = NULL;
3669 http = evhttp_new_object();
3672 if (evhttp_bind_socket(http, address, port) == -1) {
3681 evhttp_free(struct evhttp* http)
3683 struct evhttp_cb *http_cb;
3684 struct evhttp_connection *evcon;
3685 struct evhttp_bound_socket *bound;
3686 struct evhttp* vhost;
3687 struct evhttp_server_alias *alias;
3689 /* Remove the accepting part */
3690 while ((bound = TAILQ_FIRST(&http->sockets)) != NULL) {
3691 TAILQ_REMOVE(&http->sockets, bound, next);
3693 evconnlistener_free(bound->listener);
3698 while ((evcon = TAILQ_FIRST(&http->connections)) != NULL) {
3699 /* evhttp_connection_free removes the connection */
3700 evhttp_connection_free(evcon);
3703 while ((http_cb = TAILQ_FIRST(&http->callbacks)) != NULL) {
3704 TAILQ_REMOVE(&http->callbacks, http_cb, next);
3705 mm_free(http_cb->what);
3709 while ((vhost = TAILQ_FIRST(&http->virtualhosts)) != NULL) {
3710 TAILQ_REMOVE(&http->virtualhosts, vhost, next_vhost);
3715 if (http->vhost_pattern != NULL)
3716 mm_free(http->vhost_pattern);
3718 while ((alias = TAILQ_FIRST(&http->aliases)) != NULL) {
3719 TAILQ_REMOVE(&http->aliases, alias, next);
3720 mm_free(alias->alias);
3728 evhttp_add_virtual_host(struct evhttp* http, const char *pattern,
3729 struct evhttp* vhost)
3731 /* a vhost can only be a vhost once and should not have bound sockets */
3732 if (vhost->vhost_pattern != NULL ||
3733 TAILQ_FIRST(&vhost->sockets) != NULL)
3736 vhost->vhost_pattern = mm_strdup(pattern);
3737 if (vhost->vhost_pattern == NULL)
3740 TAILQ_INSERT_TAIL(&http->virtualhosts, vhost, next_vhost);
3746 evhttp_remove_virtual_host(struct evhttp* http, struct evhttp* vhost)
3748 if (vhost->vhost_pattern == NULL)
3751 TAILQ_REMOVE(&http->virtualhosts, vhost, next_vhost);
3753 mm_free(vhost->vhost_pattern);
3754 vhost->vhost_pattern = NULL;
3760 evhttp_add_server_alias(struct evhttp *http, const char *alias)
3762 struct evhttp_server_alias *evalias;
3764 evalias = mm_calloc(1, sizeof(*evalias));
3768 evalias->alias = mm_strdup(alias);
3769 if (!evalias->alias) {
3774 TAILQ_INSERT_TAIL(&http->aliases, evalias, next);
3780 evhttp_remove_server_alias(struct evhttp *http, const char *alias)
3782 struct evhttp_server_alias *evalias;
3784 TAILQ_FOREACH(evalias, &http->aliases, next) {
3785 if (evutil_ascii_strcasecmp(evalias->alias, alias) == 0) {
3786 TAILQ_REMOVE(&http->aliases, evalias, next);
3787 mm_free(evalias->alias);
3797 evhttp_set_timeout(struct evhttp* http, int timeout_in_secs)
3799 if (timeout_in_secs == -1) {
3800 evhttp_set_timeout_tv(http, NULL);
3803 tv.tv_sec = timeout_in_secs;
3805 evhttp_set_timeout_tv(http, &tv);
3810 evhttp_set_timeout_tv(struct evhttp* http, const struct timeval* tv)
3813 http->timeout = *tv;
3815 evutil_timerclear(&http->timeout);
3819 int evhttp_set_flags(struct evhttp *http, int flags)
3821 int avail_flags = 0;
3822 avail_flags |= EVHTTP_SERVER_LINGERING_CLOSE;
3824 if (flags & ~avail_flags)
3826 http->flags &= ~avail_flags;
3828 http->flags |= flags;
3834 evhttp_set_max_headers_size(struct evhttp* http, ev_ssize_t max_headers_size)
3836 if (max_headers_size < 0)
3837 http->default_max_headers_size = EV_SIZE_MAX;
3839 http->default_max_headers_size = max_headers_size;
3843 evhttp_set_max_body_size(struct evhttp* http, ev_ssize_t max_body_size)
3845 if (max_body_size < 0)
3846 http->default_max_body_size = EV_UINT64_MAX;
3848 http->default_max_body_size = max_body_size;
3852 evhttp_set_default_content_type(struct evhttp *http,
3853 const char *content_type) {
3854 http->default_content_type = content_type;
3858 evhttp_set_allowed_methods(struct evhttp* http, ev_uint16_t methods)
3860 http->allowed_methods = methods;
3864 evhttp_set_cb(struct evhttp *http, const char *uri,
3865 void (*cb)(struct evhttp_request *, void *), void *cbarg)
3867 struct evhttp_cb *http_cb;
3869 TAILQ_FOREACH(http_cb, &http->callbacks, next) {
3870 if (strcmp(http_cb->what, uri) == 0)
3874 if ((http_cb = mm_calloc(1, sizeof(struct evhttp_cb))) == NULL) {
3875 event_warn("%s: calloc", __func__);
3879 http_cb->what = mm_strdup(uri);
3880 if (http_cb->what == NULL) {
3881 event_warn("%s: strdup", __func__);
3886 http_cb->cbarg = cbarg;
3888 TAILQ_INSERT_TAIL(&http->callbacks, http_cb, next);
3894 evhttp_del_cb(struct evhttp *http, const char *uri)
3896 struct evhttp_cb *http_cb;
3898 TAILQ_FOREACH(http_cb, &http->callbacks, next) {
3899 if (strcmp(http_cb->what, uri) == 0)
3902 if (http_cb == NULL)
3905 TAILQ_REMOVE(&http->callbacks, http_cb, next);
3906 mm_free(http_cb->what);
3913 evhttp_set_gencb(struct evhttp *http,
3914 void (*cb)(struct evhttp_request *, void *), void *cbarg)
3917 http->gencbarg = cbarg;
3921 evhttp_set_bevcb(struct evhttp *http,
3922 struct bufferevent* (*cb)(struct event_base *, void *), void *cbarg)
3925 http->bevcbarg = cbarg;
3929 evhttp_set_newreqcb(struct evhttp *http,
3930 int (*cb)(struct evhttp_request *, void *), void *cbarg)
3932 http->newreqcb = cb;
3933 http->newreqcbarg = cbarg;
3937 * Request related functions
3940 struct evhttp_request *
3941 evhttp_request_new(void (*cb)(struct evhttp_request *, void *), void *arg)
3943 struct evhttp_request *req = NULL;
3945 /* Allocate request structure */
3946 if ((req = mm_calloc(1, sizeof(struct evhttp_request))) == NULL) {
3947 event_warn("%s: calloc", __func__);
3951 req->headers_size = 0;
3954 req->kind = EVHTTP_RESPONSE;
3955 req->input_headers = mm_calloc(1, sizeof(struct evkeyvalq));
3956 if (req->input_headers == NULL) {
3957 event_warn("%s: calloc", __func__);
3960 TAILQ_INIT(req->input_headers);
3962 req->output_headers = mm_calloc(1, sizeof(struct evkeyvalq));
3963 if (req->output_headers == NULL) {
3964 event_warn("%s: calloc", __func__);
3967 TAILQ_INIT(req->output_headers);
3969 if ((req->input_buffer = evbuffer_new()) == NULL) {
3970 event_warn("%s: evbuffer_new", __func__);
3974 if ((req->output_buffer = evbuffer_new()) == NULL) {
3975 event_warn("%s: evbuffer_new", __func__);
3986 evhttp_request_free(req);
3991 evhttp_request_free(struct evhttp_request *req)
3993 if ((req->flags & EVHTTP_REQ_DEFER_FREE) != 0) {
3994 req->flags |= EVHTTP_REQ_NEEDS_FREE;
3998 if (req->remote_host != NULL)
3999 mm_free(req->remote_host);
4000 if (req->uri != NULL)
4002 if (req->uri_elems != NULL)
4003 evhttp_uri_free(req->uri_elems);
4004 if (req->response_code_line != NULL)
4005 mm_free(req->response_code_line);
4006 if (req->host_cache != NULL)
4007 mm_free(req->host_cache);
4009 evhttp_clear_headers(req->input_headers);
4010 mm_free(req->input_headers);
4012 evhttp_clear_headers(req->output_headers);
4013 mm_free(req->output_headers);
4015 if (req->input_buffer != NULL)
4016 evbuffer_free(req->input_buffer);
4018 if (req->output_buffer != NULL)
4019 evbuffer_free(req->output_buffer);
4025 evhttp_request_own(struct evhttp_request *req)
4027 req->flags |= EVHTTP_USER_OWNED;
4031 evhttp_request_is_owned(struct evhttp_request *req)
4033 return (req->flags & EVHTTP_USER_OWNED) != 0;
4036 struct evhttp_connection *
4037 evhttp_request_get_connection(struct evhttp_request *req)
4043 evhttp_connection_get_base(struct evhttp_connection *conn)
4049 evhttp_request_set_chunked_cb(struct evhttp_request *req,
4050 void (*cb)(struct evhttp_request *, void *))
4056 evhttp_request_set_header_cb(struct evhttp_request *req,
4057 int (*cb)(struct evhttp_request *, void *))
4059 req->header_cb = cb;
4063 evhttp_request_set_error_cb(struct evhttp_request *req,
4064 void (*cb)(enum evhttp_request_error, void *))
4070 evhttp_request_set_on_complete_cb(struct evhttp_request *req,
4071 void (*cb)(struct evhttp_request *, void *), void *cb_arg)
4073 req->on_complete_cb = cb;
4074 req->on_complete_cb_arg = cb_arg;
4078 * Allows for inspection of the request URI
4082 evhttp_request_get_uri(const struct evhttp_request *req) {
4083 if (req->uri == NULL)
4084 event_debug(("%s: request %p has no uri\n", __func__, req));
4088 const struct evhttp_uri *
4089 evhttp_request_get_evhttp_uri(const struct evhttp_request *req) {
4090 if (req->uri_elems == NULL)
4091 event_debug(("%s: request %p has no uri elems\n",
4093 return (req->uri_elems);
4097 evhttp_request_get_host(struct evhttp_request *req)
4099 const char *host = NULL;
4101 if (req->host_cache)
4102 return req->host_cache;
4105 host = evhttp_uri_get_host(req->uri_elems);
4106 if (!host && req->input_headers) {
4110 host = evhttp_find_header(req->input_headers, "Host");
4111 /* The Host: header may include a port. Remove it here
4112 to be consistent with uri_elems case above. */
4114 p = host + strlen(host) - 1;
4115 while (p > host && EVUTIL_ISDIGIT_(*p))
4117 if (p > host && *p == ':') {
4119 req->host_cache = mm_malloc(len + 1);
4120 if (!req->host_cache) {
4121 event_warn("%s: malloc", __func__);
4124 memcpy(req->host_cache, host, len);
4125 req->host_cache[len] = '\0';
4126 host = req->host_cache;
4134 enum evhttp_cmd_type
4135 evhttp_request_get_command(const struct evhttp_request *req) {
4140 evhttp_request_get_response_code(const struct evhttp_request *req)
4142 return req->response_code;
4146 evhttp_request_get_response_code_line(const struct evhttp_request *req)
4148 return req->response_code_line;
4151 /** Returns the input headers */
4152 struct evkeyvalq *evhttp_request_get_input_headers(struct evhttp_request *req)
4154 return (req->input_headers);
4157 /** Returns the output headers */
4158 struct evkeyvalq *evhttp_request_get_output_headers(struct evhttp_request *req)
4160 return (req->output_headers);
4163 /** Returns the input buffer */
4164 struct evbuffer *evhttp_request_get_input_buffer(struct evhttp_request *req)
4166 return (req->input_buffer);
4169 /** Returns the output buffer */
4170 struct evbuffer *evhttp_request_get_output_buffer(struct evhttp_request *req)
4172 return (req->output_buffer);
4177 * Takes a file descriptor to read a request from.
4178 * The callback is executed once the whole request has been read.
4181 static struct evhttp_connection*
4182 evhttp_get_request_connection(
4183 struct evhttp* http,
4184 evutil_socket_t fd, struct sockaddr *sa, ev_socklen_t salen)
4186 struct evhttp_connection *evcon;
4187 char *hostname = NULL, *portname = NULL;
4188 struct bufferevent* bev = NULL;
4190 name_from_addr(sa, salen, &hostname, &portname);
4191 if (hostname == NULL || portname == NULL) {
4192 if (hostname) mm_free(hostname);
4193 if (portname) mm_free(portname);
4197 event_debug(("%s: new request from %s:%s on "EV_SOCK_FMT"\n",
4198 __func__, hostname, portname, EV_SOCK_ARG(fd)));
4200 /* we need a connection object to put the http request on */
4201 if (http->bevcb != NULL) {
4202 bev = (*http->bevcb)(http->base, http->bevcbarg);
4204 evcon = evhttp_connection_base_bufferevent_new(
4205 http->base, NULL, bev, hostname, atoi(portname));
4211 evcon->max_headers_size = http->default_max_headers_size;
4212 evcon->max_body_size = http->default_max_body_size;
4213 if (http->flags & EVHTTP_SERVER_LINGERING_CLOSE)
4214 evcon->flags |= EVHTTP_CON_LINGERING_CLOSE;
4216 evcon->flags |= EVHTTP_CON_INCOMING;
4217 evcon->state = EVCON_READING_FIRSTLINE;
4221 bufferevent_enable(evcon->bufev, EV_READ);
4222 bufferevent_disable(evcon->bufev, EV_WRITE);
4223 bufferevent_setfd(evcon->bufev, fd);
4224 bufferevent_socket_set_conn_address_(evcon->bufev, sa, salen);
4230 evhttp_associate_new_request_with_connection(struct evhttp_connection *evcon)
4232 struct evhttp *http = evcon->http_server;
4233 struct evhttp_request *req;
4234 if ((req = evhttp_request_new(evhttp_handle_request, http)) == NULL)
4237 if ((req->remote_host = mm_strdup(evcon->address)) == NULL) {
4238 event_warn("%s: strdup", __func__);
4239 evhttp_request_free(req);
4242 req->remote_port = evcon->port;
4244 req->evcon = evcon; /* the request ends up owning the connection */
4245 req->flags |= EVHTTP_REQ_OWN_CONNECTION;
4247 /* We did not present the request to the user yet, so treat it
4248 * as if the user was done with the request. This allows us
4249 * to free the request on a persistent connection if the
4250 * client drops it without sending a request.
4253 req->kind = EVHTTP_REQUEST;
4255 if (http->newreqcb && http->newreqcb(req, http->newreqcbarg) == -1) {
4256 evhttp_request_free(req);
4260 TAILQ_INSERT_TAIL(&evcon->requests, req, next);
4262 evhttp_start_read_(evcon);
4268 evhttp_get_request(struct evhttp *http, evutil_socket_t fd,
4269 struct sockaddr *sa, ev_socklen_t salen)
4271 struct evhttp_connection *evcon;
4273 evcon = evhttp_get_request_connection(http, fd, sa, salen);
4274 if (evcon == NULL) {
4275 event_sock_warn(fd, "%s: cannot get connection on "EV_SOCK_FMT,
4276 __func__, EV_SOCK_ARG(fd));
4277 evutil_closesocket(fd);
4281 /* the timeout can be used by the server to close idle connections */
4282 if (evutil_timerisset(&http->timeout))
4283 evhttp_connection_set_timeout_tv(evcon, &http->timeout);
4286 * if we want to accept more than one request on a connection,
4287 * we need to know which http server it belongs to.
4289 evcon->http_server = http;
4290 TAILQ_INSERT_TAIL(&http->connections, evcon, next);
4292 if (evhttp_associate_new_request_with_connection(evcon) == -1)
4293 evhttp_connection_free(evcon);
4298 * Network helper functions that we do not want to export to the rest of
4303 name_from_addr(struct sockaddr *sa, ev_socklen_t salen,
4304 char **phost, char **pport)
4306 char ntop[NI_MAXHOST];
4307 char strport[NI_MAXSERV];
4310 #ifdef EVENT__HAVE_GETNAMEINFO
4311 ni_result = getnameinfo(sa, salen,
4312 ntop, sizeof(ntop), strport, sizeof(strport),
4313 NI_NUMERICHOST|NI_NUMERICSERV);
4315 if (ni_result != 0) {
4317 /* Windows doesn't have an EAI_SYSTEM. */
4318 if (ni_result == EAI_SYSTEM)
4319 event_err(1, "getnameinfo failed");
4322 event_errx(1, "getnameinfo failed: %s", gai_strerror(ni_result));
4326 ni_result = fake_getnameinfo(sa, salen,
4327 ntop, sizeof(ntop), strport, sizeof(strport),
4328 NI_NUMERICHOST|NI_NUMERICSERV);
4333 *phost = mm_strdup(ntop);
4334 *pport = mm_strdup(strport);
4337 /* Create a non-blocking socket and bind it */
4338 /* todo: rename this function */
4339 static evutil_socket_t
4340 bind_socket_ai(struct evutil_addrinfo *ai, int reuse)
4347 /* Create listen socket */
4348 fd = evutil_socket_(ai ? ai->ai_family : AF_INET,
4349 SOCK_STREAM|EVUTIL_SOCK_NONBLOCK|EVUTIL_SOCK_CLOEXEC, 0);
4351 event_sock_warn(-1, "socket");
4355 if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (void *)&on, sizeof(on))<0)
4358 if (evutil_make_listen_socket_reuseable(fd) < 0)
4363 r = bind(fd, ai->ai_addr, (ev_socklen_t)ai->ai_addrlen);
4371 serrno = EVUTIL_SOCKET_ERROR();
4372 evutil_closesocket(fd);
4373 EVUTIL_SET_SOCKET_ERROR(serrno);
4377 static struct evutil_addrinfo *
4378 make_addrinfo(const char *address, ev_uint16_t port)
4380 struct evutil_addrinfo *ai = NULL;
4382 struct evutil_addrinfo hints;
4383 char strport[NI_MAXSERV];
4386 memset(&hints, 0, sizeof(hints));
4387 hints.ai_family = AF_UNSPEC;
4388 hints.ai_socktype = SOCK_STREAM;
4389 /* turn NULL hostname into INADDR_ANY, and skip looking up any address
4390 * types we don't have an interface to connect to. */
4391 hints.ai_flags = EVUTIL_AI_PASSIVE|EVUTIL_AI_ADDRCONFIG;
4392 evutil_snprintf(strport, sizeof(strport), "%d", port);
4393 if ((ai_result = evutil_getaddrinfo(address, strport, &hints, &ai))
4395 if (ai_result == EVUTIL_EAI_SYSTEM)
4396 event_warn("getaddrinfo");
4398 event_warnx("getaddrinfo: %s",
4399 evutil_gai_strerror(ai_result));
4406 static evutil_socket_t
4407 bind_socket(const char *address, ev_uint16_t port, int reuse)
4410 struct evutil_addrinfo *aitop = NULL;
4412 /* just create an unbound socket */
4413 if (address == NULL && port == 0)
4414 return bind_socket_ai(NULL, 0);
4416 aitop = make_addrinfo(address, port);
4421 fd = bind_socket_ai(aitop, reuse);
4423 evutil_freeaddrinfo(aitop);
4430 char *scheme; /* scheme; e.g http, ftp etc */
4431 char *userinfo; /* userinfo (typically username:pass), or NULL */
4432 char *host; /* hostname, IP address, or NULL */
4433 int port; /* port, or zero */
4434 char *path; /* path, or "". */
4435 char *query; /* query, or NULL */
4436 char *fragment; /* fragment or NULL */
4440 evhttp_uri_new(void)
4442 struct evhttp_uri *uri = mm_calloc(sizeof(struct evhttp_uri), 1);
4449 evhttp_uri_set_flags(struct evhttp_uri *uri, unsigned flags)
4454 /* Return true if the string starting at s and ending immediately before eos
4455 * is a valid URI scheme according to RFC3986
4458 scheme_ok(const char *s, const char *eos)
4460 /* scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." ) */
4461 EVUTIL_ASSERT(eos >= s);
4464 if (!EVUTIL_ISALPHA_(*s))
4467 if (! EVUTIL_ISALNUM_(*s) &&
4468 *s != '+' && *s != '-' && *s != '.')
4474 #define SUBDELIMS "!$&'()*+,;="
4476 /* Return true iff [s..eos) is a valid userinfo */
4478 userinfo_ok(const char *s, const char *eos)
4481 if (CHAR_IS_UNRESERVED(*s) ||
4482 strchr(SUBDELIMS, *s) ||
4485 else if (*s == '%' && s+2 < eos &&
4486 EVUTIL_ISXDIGIT_(s[1]) &&
4487 EVUTIL_ISXDIGIT_(s[2]))
4496 regname_ok(const char *s, const char *eos)
4498 while (s && s<eos) {
4499 if (CHAR_IS_UNRESERVED(*s) ||
4500 strchr(SUBDELIMS, *s))
4502 else if (*s == '%' &&
4503 EVUTIL_ISXDIGIT_(s[1]) &&
4504 EVUTIL_ISXDIGIT_(s[2]))
4513 parse_port(const char *s, const char *eos)
4517 if (! EVUTIL_ISDIGIT_(*s))
4519 portnum = (portnum * 10) + (*s - '0');
4522 if (portnum > 65535)
4529 /* returns 0 for bad, 1 for ipv6, 2 for IPvFuture */
4531 bracket_addr_ok(const char *s, const char *eos)
4533 if (s + 3 > eos || *s != '[' || *(eos-1) != ']')
4536 /* IPvFuture, or junk.
4537 "v" 1*HEXDIG "." 1*( unreserved / sub-delims / ":" )
4539 s += 2; /* skip [v */
4541 if (!EVUTIL_ISXDIGIT_(*s)) /*require at least one*/
4543 while (s < eos && *s != '.') {
4544 if (EVUTIL_ISXDIGIT_(*s))
4553 if (CHAR_IS_UNRESERVED(*s) ||
4554 strchr(SUBDELIMS, *s) ||
4564 ev_ssize_t n_chars = eos-s-2;
4565 struct in6_addr in6;
4566 if (n_chars >= 64) /* way too long */
4568 memcpy(buf, s+1, n_chars);
4570 return (evutil_inet_pton(AF_INET6,buf,&in6)==1) ? 1 : 0;
4575 parse_authority(struct evhttp_uri *uri, char *s, char *eos)
4580 uri->host = mm_strdup("");
4581 if (uri->host == NULL) {
4582 event_warn("%s: strdup", __func__);
4588 /* Optionally, we start with "userinfo@" */
4590 cp = strchr(s, '@');
4591 if (cp && cp < eos) {
4592 if (! userinfo_ok(s,cp))
4595 uri->userinfo = mm_strdup(s);
4596 if (uri->userinfo == NULL) {
4597 event_warn("%s: strdup", __func__);
4603 /* Optionally, we end with ":port" */
4604 for (port=eos-1; port >= cp && EVUTIL_ISDIGIT_(*port); --port)
4606 if (port >= cp && *port == ':') {
4607 if (port+1 == eos) /* Leave port unspecified; the RFC allows a
4610 else if ((uri->port = parse_port(port+1, eos))<0)
4614 /* Now, cp..eos holds the "host" port, which can be an IPv4Address,
4615 * an IP-Literal, or a reg-name */
4616 EVUTIL_ASSERT(eos >= cp);
4617 if (*cp == '[' && eos >= cp+2 && *(eos-1) == ']') {
4618 /* IPv6address, IP-Literal, or junk. */
4619 if (! bracket_addr_ok(cp, eos))
4622 /* Make sure the host part is ok. */
4623 if (! regname_ok(cp,eos)) /* Match IPv4Address or reg-name */
4626 uri->host = mm_malloc(eos-cp+1);
4627 if (uri->host == NULL) {
4628 event_warn("%s: malloc", __func__);
4631 memcpy(uri->host, cp, eos-cp);
4632 uri->host[eos-cp] = '\0';
4638 end_of_authority(char *cp)
4641 if (*cp == '?' || *cp == '#' || *cp == '/')
4654 /* Return the character after the longest prefix of 'cp' that matches...
4655 * *pchar / "/" if allow_qchars is false, or
4656 * *(pchar / "/" / "?") if allow_qchars is true.
4659 end_of_path(char *cp, enum uri_part part, unsigned flags)
4661 if (flags & EVHTTP_URI_NONCONFORMANT) {
4662 /* If NONCONFORMANT:
4663 * Path is everything up to a # or ? or nul.
4664 * Query is everything up a # or nul
4665 * Fragment is everything up to a nul.
4669 while (*cp && *cp != '#' && *cp != '?')
4673 while (*cp && *cp != '#')
4684 if (CHAR_IS_UNRESERVED(*cp) ||
4685 strchr(SUBDELIMS, *cp) ||
4686 *cp == ':' || *cp == '@' || *cp == '/')
4688 else if (*cp == '%' && EVUTIL_ISXDIGIT_(cp[1]) &&
4689 EVUTIL_ISXDIGIT_(cp[2]))
4691 else if (*cp == '?' && part != PART_PATH)
4700 path_matches_noscheme(const char *cp)
4705 else if (*cp == '/')
4713 evhttp_uri_parse(const char *source_uri)
4715 return evhttp_uri_parse_with_flags(source_uri, 0);
4719 evhttp_uri_parse_with_flags(const char *source_uri, unsigned flags)
4721 char *readbuf = NULL, *readp = NULL, *token = NULL, *query = NULL;
4722 char *path = NULL, *fragment = NULL;
4723 int got_authority = 0;
4725 struct evhttp_uri *uri = mm_calloc(1, sizeof(struct evhttp_uri));
4727 event_warn("%s: calloc", __func__);
4733 readbuf = mm_strdup(source_uri);
4734 if (readbuf == NULL) {
4735 event_warn("%s: strdup", __func__);
4742 /* We try to follow RFC3986 here as much as we can, and match
4745 URI = scheme ":" hier-part [ "?" query ] [ "#" fragment ]
4747 relative-ref = relative-part [ "?" query ] [ "#" fragment ]
4751 token = strchr(readp, ':');
4752 if (token && scheme_ok(readp,token)) {
4754 uri->scheme = mm_strdup(readp);
4755 if (uri->scheme == NULL) {
4756 event_warn("%s: strdup", __func__);
4759 readp = token+1; /* eat : */
4762 /* 2. Optionally, "//" then an 'authority' part. */
4763 if (readp[0]=='/' && readp[1] == '/') {
4767 path = end_of_authority(readp);
4768 if (parse_authority(uri, authority, path) < 0)
4774 /* 3. Query: path-abempty, path-absolute, path-rootless, or path-empty
4777 readp = end_of_path(path, PART_PATH, flags);
4780 if (*readp == '?') {
4784 readp = end_of_path(readp, PART_QUERY, flags);
4787 if (*readp == '#') {
4791 readp = end_of_path(readp, PART_FRAGMENT, flags);
4793 if (*readp != '\0') {
4797 /* These next two cases may be unreachable; I'm leaving them
4798 * in to be defensive. */
4799 /* If you didn't get an authority, the path can't begin with "//" */
4800 if (!got_authority && path[0]=='/' && path[1]=='/')
4802 /* If you did get an authority, the path must begin with "/" or be
4804 if (got_authority && path[0] != '/' && path[0] != '\0')
4806 /* (End of maybe-unreachable cases) */
4808 /* If there was no scheme, the first part of the path (if any) must
4809 * have no colon in it. */
4810 if (! uri->scheme && !path_matches_noscheme(path))
4813 EVUTIL_ASSERT(path);
4814 uri->path = mm_strdup(path);
4815 if (uri->path == NULL) {
4816 event_warn("%s: strdup", __func__);
4821 uri->query = mm_strdup(query);
4822 if (uri->query == NULL) {
4823 event_warn("%s: strdup", __func__);
4828 uri->fragment = mm_strdup(fragment);
4829 if (uri->fragment == NULL) {
4830 event_warn("%s: strdup", __func__);
4840 evhttp_uri_free(uri);
4846 static struct evhttp_uri *
4847 evhttp_uri_parse_authority(char *source_uri)
4849 struct evhttp_uri *uri = mm_calloc(1, sizeof(struct evhttp_uri));
4851 event_warn("%s: calloc", __func__);
4857 char *end = end_of_authority(source_uri);
4858 if (parse_authority(uri, source_uri, end) < 0)
4861 uri->path = mm_strdup("");
4862 if (uri->path == NULL) {
4863 event_warn("%s: strdup", __func__);
4870 evhttp_uri_free(uri);
4875 evhttp_uri_free(struct evhttp_uri *uri)
4877 #define URI_FREE_STR_(f) \
4882 URI_FREE_STR_(scheme);
4883 URI_FREE_STR_(userinfo);
4884 URI_FREE_STR_(host);
4885 URI_FREE_STR_(path);
4886 URI_FREE_STR_(query);
4887 URI_FREE_STR_(fragment);
4890 #undef URI_FREE_STR_
4894 evhttp_uri_join(struct evhttp_uri *uri, char *buf, size_t limit)
4896 struct evbuffer *tmp = 0;
4897 size_t joined_size = 0;
4898 char *output = NULL;
4900 #define URI_ADD_(f) evbuffer_add(tmp, uri->f, strlen(uri->f))
4902 if (!uri || !buf || !limit)
4905 tmp = evbuffer_new();
4911 evbuffer_add(tmp, ":", 1);
4914 evbuffer_add(tmp, "//", 2);
4916 evbuffer_add_printf(tmp,"%s@", uri->userinfo);
4919 evbuffer_add_printf(tmp,":%d", uri->port);
4921 if (uri->path && uri->path[0] != '/' && uri->path[0] != '\0')
4929 evbuffer_add(tmp, "?", 1);
4933 if (uri->fragment) {
4934 evbuffer_add(tmp, "#", 1);
4938 evbuffer_add(tmp, "\0", 1); /* NUL */
4940 joined_size = evbuffer_get_length(tmp);
4942 if (joined_size > limit) {
4943 /* It doesn't fit. */
4947 evbuffer_remove(tmp, buf, joined_size);
4958 evhttp_uri_get_scheme(const struct evhttp_uri *uri)
4963 evhttp_uri_get_userinfo(const struct evhttp_uri *uri)
4965 return uri->userinfo;
4968 evhttp_uri_get_host(const struct evhttp_uri *uri)
4973 evhttp_uri_get_port(const struct evhttp_uri *uri)
4978 evhttp_uri_get_path(const struct evhttp_uri *uri)
4983 evhttp_uri_get_query(const struct evhttp_uri *uri)
4988 evhttp_uri_get_fragment(const struct evhttp_uri *uri)
4990 return uri->fragment;
4993 #define URI_SET_STR_(f) do { \
4997 if ((uri->f = mm_strdup(f)) == NULL) { \
4998 event_warn("%s: strdup()", __func__); \
5007 evhttp_uri_set_scheme(struct evhttp_uri *uri, const char *scheme)
5009 if (scheme && !scheme_ok(scheme, scheme+strlen(scheme)))
5012 URI_SET_STR_(scheme);
5016 evhttp_uri_set_userinfo(struct evhttp_uri *uri, const char *userinfo)
5018 if (userinfo && !userinfo_ok(userinfo, userinfo+strlen(userinfo)))
5020 URI_SET_STR_(userinfo);
5024 evhttp_uri_set_host(struct evhttp_uri *uri, const char *host)
5027 if (host[0] == '[') {
5028 if (! bracket_addr_ok(host, host+strlen(host)))
5031 if (! regname_ok(host, host+strlen(host)))
5040 evhttp_uri_set_port(struct evhttp_uri *uri, int port)
5047 #define end_of_cpath(cp,p,f) \
5048 ((const char*)(end_of_path(((char*)(cp)), (p), (f))))
5051 evhttp_uri_set_path(struct evhttp_uri *uri, const char *path)
5053 if (path && end_of_cpath(path, PART_PATH, uri->flags) != path+strlen(path))
5060 evhttp_uri_set_query(struct evhttp_uri *uri, const char *query)
5062 if (query && end_of_cpath(query, PART_QUERY, uri->flags) != query+strlen(query))
5064 URI_SET_STR_(query);
5068 evhttp_uri_set_fragment(struct evhttp_uri *uri, const char *fragment)
5070 if (fragment && end_of_cpath(fragment, PART_FRAGMENT, uri->flags) != fragment+strlen(fragment))
5072 URI_SET_STR_(fragment);