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;
1208 /* notify interested parties that this connection is going down */
1209 if (evcon->fd != -1) {
1210 if (evhttp_connected(evcon) && evcon->closecb != NULL)
1211 (*evcon->closecb)(evcon, evcon->closecb_arg);
1214 /* remove all requests that might be queued on this
1215 * connection. for server connections, this should be empty.
1216 * because it gets dequeued either in evhttp_connection_done or
1217 * evhttp_connection_fail_.
1219 while ((req = TAILQ_FIRST(&evcon->requests)) != NULL) {
1220 evhttp_request_free_(evcon, req);
1223 if (evcon->http_server != NULL) {
1224 struct evhttp *http = evcon->http_server;
1225 TAILQ_REMOVE(&http->connections, evcon, next);
1228 if (event_initialized(&evcon->retry_ev)) {
1229 event_del(&evcon->retry_ev);
1230 event_debug_unassign(&evcon->retry_ev);
1233 event_deferred_cb_cancel_(get_deferred_queue(evcon),
1234 &evcon->read_more_deferred_cb);
1236 if (evcon->bufev != NULL) {
1238 !(bufferevent_get_options_(evcon->bufev) & BEV_OPT_CLOSE_ON_FREE);
1239 if (evcon->fd == -1)
1240 evcon->fd = bufferevent_getfd(evcon->bufev);
1242 bufferevent_free(evcon->bufev);
1245 if (evcon->fd != -1) {
1246 shutdown(evcon->fd, EVUTIL_SHUT_WR);
1248 evutil_closesocket(evcon->fd);
1251 if (evcon->bind_address != NULL)
1252 mm_free(evcon->bind_address);
1254 if (evcon->address != NULL)
1255 mm_free(evcon->address);
1261 evhttp_connection_free_on_completion(struct evhttp_connection *evcon) {
1262 evcon->flags |= EVHTTP_CON_AUTOFREE;
1266 evhttp_connection_set_local_address(struct evhttp_connection *evcon,
1267 const char *address)
1269 EVUTIL_ASSERT(evcon->state == EVCON_DISCONNECTED);
1270 if (evcon->bind_address)
1271 mm_free(evcon->bind_address);
1272 if ((evcon->bind_address = mm_strdup(address)) == NULL)
1273 event_warn("%s: strdup", __func__);
1277 evhttp_connection_set_local_port(struct evhttp_connection *evcon,
1280 EVUTIL_ASSERT(evcon->state == EVCON_DISCONNECTED);
1281 evcon->bind_port = port;
1285 evhttp_request_dispatch(struct evhttp_connection* evcon)
1287 struct evhttp_request *req = TAILQ_FIRST(&evcon->requests);
1289 /* this should not usually happy but it's possible */
1293 EVUTIL_ASSERT(req->kind == EVHTTP_REQUEST);
1295 /* delete possible close detection events */
1296 evhttp_connection_stop_detectclose(evcon);
1298 /* we assume that the connection is connected already */
1299 EVUTIL_ASSERT(evcon->state == EVCON_IDLE);
1301 evcon->state = EVCON_WRITING;
1303 /* Create the header from the store arguments */
1304 evhttp_make_header(evcon, req);
1306 evhttp_write_buffer(evcon, evhttp_write_connectioncb, NULL);
1309 /* Reset our connection state: disables reading/writing, closes our fd (if
1310 * any), clears out buffers, and puts us in state DISCONNECTED. */
1312 evhttp_connection_reset_(struct evhttp_connection *evcon)
1314 struct evbuffer *tmp;
1317 bufferevent_setcb(evcon->bufev, NULL, NULL, NULL, NULL);
1319 /* XXXX This is not actually an optimal fix. Instead we ought to have
1320 an API for "stop connecting", or use bufferevent_setfd to turn off
1321 connecting. But for Libevent 2.0, this seems like a minimal change
1322 least likely to disrupt the rest of the bufferevent and http code.
1324 Why is this here? If the fd is set in the bufferevent, and the
1325 bufferevent is connecting, then you can't actually stop the
1326 bufferevent from trying to connect with bufferevent_disable(). The
1327 connect will never trigger, since we close the fd, but the timeout
1328 might. That caused an assertion failure in evhttp_connection_fail_.
1330 bufferevent_disable_hard_(evcon->bufev, EV_READ|EV_WRITE);
1332 if (evcon->fd == -1)
1333 evcon->fd = bufferevent_getfd(evcon->bufev);
1335 if (evcon->fd != -1) {
1336 /* inform interested parties about connection close */
1337 if (evhttp_connected(evcon) && evcon->closecb != NULL)
1338 (*evcon->closecb)(evcon, evcon->closecb_arg);
1340 shutdown(evcon->fd, EVUTIL_SHUT_WR);
1341 evutil_closesocket(evcon->fd);
1344 err = bufferevent_setfd(evcon->bufev, -1);
1345 EVUTIL_ASSERT(!err && "setfd");
1347 /* we need to clean up any buffered data */
1348 tmp = bufferevent_get_output(evcon->bufev);
1349 err = evbuffer_drain(tmp, -1);
1350 EVUTIL_ASSERT(!err && "drain output");
1351 tmp = bufferevent_get_input(evcon->bufev);
1352 err = evbuffer_drain(tmp, -1);
1353 EVUTIL_ASSERT(!err && "drain input");
1355 evcon->flags &= ~EVHTTP_CON_READING_ERROR;
1357 evcon->state = EVCON_DISCONNECTED;
1361 evhttp_connection_start_detectclose(struct evhttp_connection *evcon)
1363 evcon->flags |= EVHTTP_CON_CLOSEDETECT;
1364 bufferevent_enable(evcon->bufev, EV_READ);
1368 evhttp_connection_stop_detectclose(struct evhttp_connection *evcon)
1370 evcon->flags &= ~EVHTTP_CON_CLOSEDETECT;
1371 bufferevent_disable(evcon->bufev, EV_READ);
1375 evhttp_connection_retry(evutil_socket_t fd, short what, void *arg)
1377 struct evhttp_connection *evcon = arg;
1379 evcon->state = EVCON_DISCONNECTED;
1380 evhttp_connection_connect_(evcon);
1384 evhttp_connection_cb_cleanup(struct evhttp_connection *evcon)
1386 struct evcon_requestq requests;
1388 evhttp_connection_reset_(evcon);
1389 if (evcon->retry_max < 0 || evcon->retry_cnt < evcon->retry_max) {
1390 struct timeval tv_retry = evcon->initial_retry_timeout;
1392 evtimer_assign(&evcon->retry_ev, evcon->base, evhttp_connection_retry, evcon);
1393 /* XXXX handle failure from evhttp_add_event */
1394 for (i=0; i < evcon->retry_cnt; ++i) {
1395 tv_retry.tv_usec *= 2;
1396 if (tv_retry.tv_usec > 1000000) {
1397 tv_retry.tv_usec -= 1000000;
1398 tv_retry.tv_sec += 1;
1400 tv_retry.tv_sec *= 2;
1401 if (tv_retry.tv_sec > 3600) {
1402 tv_retry.tv_sec = 3600;
1403 tv_retry.tv_usec = 0;
1406 event_add(&evcon->retry_ev, &tv_retry);
1412 * User callback can do evhttp_make_request() on the same
1413 * evcon so new request will be added to evcon->requests. To
1414 * avoid freeing it prematurely we iterate over the copy of
1417 TAILQ_INIT(&requests);
1418 while (TAILQ_FIRST(&evcon->requests) != NULL) {
1419 struct evhttp_request *request = TAILQ_FIRST(&evcon->requests);
1420 TAILQ_REMOVE(&evcon->requests, request, next);
1421 TAILQ_INSERT_TAIL(&requests, request, next);
1424 /* for now, we just signal all requests by executing their callbacks */
1425 while (TAILQ_FIRST(&requests) != NULL) {
1426 struct evhttp_request *request = TAILQ_FIRST(&requests);
1427 TAILQ_REMOVE(&requests, request, next);
1428 request->evcon = NULL;
1430 /* we might want to set an error here */
1431 request->cb(request, request->cb_arg);
1432 evhttp_request_free_auto(request);
1437 evhttp_connection_read_on_write_error(struct evhttp_connection *evcon,
1438 struct evhttp_request *req)
1440 struct evbuffer *buf;
1442 /** Second time, we can't read anything */
1443 if (evcon->flags & EVHTTP_CON_READING_ERROR) {
1444 evcon->flags &= ~EVHTTP_CON_READING_ERROR;
1445 evhttp_connection_fail_(evcon, EVREQ_HTTP_EOF);
1449 req->kind = EVHTTP_RESPONSE;
1451 buf = bufferevent_get_output(evcon->bufev);
1452 evbuffer_unfreeze(buf, 1);
1453 evbuffer_drain(buf, evbuffer_get_length(buf));
1454 evbuffer_freeze(buf, 1);
1456 evhttp_start_read_(evcon);
1457 evcon->flags |= EVHTTP_CON_READING_ERROR;
1461 evhttp_error_cb(struct bufferevent *bufev, short what, void *arg)
1463 struct evhttp_connection *evcon = arg;
1464 struct evhttp_request *req = TAILQ_FIRST(&evcon->requests);
1466 if (evcon->fd == -1)
1467 evcon->fd = bufferevent_getfd(bufev);
1469 switch (evcon->state) {
1470 case EVCON_CONNECTING:
1471 if (what & BEV_EVENT_TIMEOUT) {
1472 event_debug(("%s: connection timeout for \"%s:%d\" on "
1474 __func__, evcon->address, evcon->port,
1475 EV_SOCK_ARG(evcon->fd)));
1476 evhttp_connection_cb_cleanup(evcon);
1481 case EVCON_READING_BODY:
1482 if (!req->chunked && req->ntoread < 0
1483 && what == (BEV_EVENT_READING|BEV_EVENT_EOF)) {
1484 /* EOF on read can be benign */
1485 evhttp_connection_done(evcon);
1490 case EVCON_DISCONNECTED:
1492 case EVCON_READING_FIRSTLINE:
1493 case EVCON_READING_HEADERS:
1494 case EVCON_READING_TRAILER:
1500 /* when we are in close detect mode, a read error means that
1501 * the other side closed their connection.
1503 if (evcon->flags & EVHTTP_CON_CLOSEDETECT) {
1504 evcon->flags &= ~EVHTTP_CON_CLOSEDETECT;
1505 EVUTIL_ASSERT(evcon->http_server == NULL);
1506 /* For connections from the client, we just
1507 * reset the connection so that it becomes
1510 EVUTIL_ASSERT(evcon->state == EVCON_IDLE);
1511 evhttp_connection_reset_(evcon);
1514 * If we have no more requests that need completion
1515 * and we want to auto-free the connection when all
1516 * requests have been completed.
1518 if (TAILQ_FIRST(&evcon->requests) == NULL
1519 && (evcon->flags & EVHTTP_CON_OUTGOING)
1520 && (evcon->flags & EVHTTP_CON_AUTOFREE)) {
1521 evhttp_connection_free(evcon);
1526 if (what & BEV_EVENT_TIMEOUT) {
1527 evhttp_connection_fail_(evcon, EVREQ_HTTP_TIMEOUT);
1528 } else if (what & (BEV_EVENT_EOF|BEV_EVENT_ERROR)) {
1529 if (what & BEV_EVENT_WRITING &&
1530 evcon->flags & EVHTTP_CON_READ_ON_WRITE_ERROR) {
1531 evhttp_connection_read_on_write_error(evcon, req);
1535 evhttp_connection_fail_(evcon, EVREQ_HTTP_EOF);
1536 } else if (what == BEV_EVENT_CONNECTED) {
1538 evhttp_connection_fail_(evcon, EVREQ_HTTP_BUFFER_ERROR);
1543 * Event callback for asynchronous connection attempt.
1546 evhttp_connection_cb(struct bufferevent *bufev, short what, void *arg)
1548 struct evhttp_connection *evcon = arg;
1550 ev_socklen_t errsz = sizeof(error);
1552 if (evcon->fd == -1)
1553 evcon->fd = bufferevent_getfd(bufev);
1555 if (!(what & BEV_EVENT_CONNECTED)) {
1556 /* some operating systems return ECONNREFUSED immediately
1557 * when connecting to a local address. the cleanup is going
1558 * to reschedule this function call.
1561 if (errno == ECONNREFUSED)
1564 evhttp_error_cb(bufev, what, arg);
1568 if (evcon->fd == -1) {
1569 event_debug(("%s: bufferevent_getfd returned -1",
1574 /* Check if the connection completed */
1575 if (getsockopt(evcon->fd, SOL_SOCKET, SO_ERROR, (void*)&error,
1577 event_debug(("%s: getsockopt for \"%s:%d\" on "EV_SOCK_FMT,
1578 __func__, evcon->address, evcon->port,
1579 EV_SOCK_ARG(evcon->fd)));
1584 event_debug(("%s: connect failed for \"%s:%d\" on "
1586 __func__, evcon->address, evcon->port,
1587 EV_SOCK_ARG(evcon->fd),
1588 evutil_socket_error_to_string(error)));
1592 /* We are connected to the server now */
1593 event_debug(("%s: connected to \"%s:%d\" on "EV_SOCK_FMT"\n",
1594 __func__, evcon->address, evcon->port,
1595 EV_SOCK_ARG(evcon->fd)));
1597 /* Reset the retry count as we were successful in connecting */
1598 evcon->retry_cnt = 0;
1599 evcon->state = EVCON_IDLE;
1601 /* reset the bufferevent cbs */
1602 bufferevent_setcb(evcon->bufev,
1608 if (!evutil_timerisset(&evcon->timeout)) {
1609 const struct timeval read_tv = { HTTP_READ_TIMEOUT, 0 };
1610 const struct timeval write_tv = { HTTP_WRITE_TIMEOUT, 0 };
1611 bufferevent_set_timeouts(evcon->bufev, &read_tv, &write_tv);
1613 bufferevent_set_timeouts(evcon->bufev, &evcon->timeout, &evcon->timeout);
1616 /* try to start requests that have queued up on this connection */
1617 evhttp_request_dispatch(evcon);
1621 evhttp_connection_cb_cleanup(evcon);
1625 * Check if we got a valid response code.
1629 evhttp_valid_response_code(int code)
1638 evhttp_parse_http_version(const char *version, struct evhttp_request *req)
1642 int n = sscanf(version, "HTTP/%d.%d%c", &major, &minor, &ch);
1643 if (n != 2 || major > 1) {
1644 event_debug(("%s: bad version %s on message %p from %s",
1645 __func__, version, req, req->remote_host));
1653 /* Parses the status line of a web server */
1656 evhttp_parse_response_line(struct evhttp_request *req, char *line)
1660 const char *readable = "";
1662 protocol = strsep(&line, " ");
1665 number = strsep(&line, " ");
1669 if (evhttp_parse_http_version(protocol, req) < 0)
1672 req->response_code = atoi(number);
1673 if (!evhttp_valid_response_code(req->response_code)) {
1674 event_debug(("%s: bad response code \"%s\"",
1679 if (req->response_code_line != NULL)
1680 mm_free(req->response_code_line);
1681 if ((req->response_code_line = mm_strdup(readable)) == NULL) {
1682 event_warn("%s: strdup", __func__);
1689 /* Parse the first line of a HTTP request */
1692 evhttp_parse_request_line(struct evhttp_request *req, char *line, size_t len)
1694 char *eos = line + len;
1698 const char *hostname;
1701 enum evhttp_cmd_type type;
1703 while (eos > line && *(eos-1) == ' ') {
1708 if (len < strlen("GET / HTTP/1.0"))
1711 /* Parse the request line */
1712 method = strsep(&line, " ");
1716 version = strrchr(uri, ' ');
1717 if (!version || uri == version)
1722 method_len = (uri - method) - 1;
1723 type = EVHTTP_REQ_UNKNOWN_;
1726 switch (method_len) {
1728 /* The length of the method string is 3, meaning it can only be one of two methods: GET or PUT */
1730 /* Since both GET and PUT share the same character 'T' at the end,
1731 * if the string doesn't have 'T', we can immediately determine this
1732 * is an invalid HTTP method */
1734 if (method[2] != 'T') {
1740 /* This first byte is 'G', so make sure the next byte is
1741 * 'E', if it isn't then this isn't a valid method */
1743 if (method[1] == 'E') {
1744 type = EVHTTP_REQ_GET;
1749 /* First byte is P, check second byte for 'U', if not,
1750 * we know it's an invalid method */
1751 if (method[1] == 'U') {
1752 type = EVHTTP_REQ_PUT;
1760 /* The method length is 4 bytes, leaving only the methods "POST" and "HEAD" */
1763 if (method[3] == 'T' && method[2] == 'S' && method[1] == 'O') {
1764 type = EVHTTP_REQ_POST;
1768 if (method[3] == 'D' && method[2] == 'A' && method[1] == 'E') {
1769 type = EVHTTP_REQ_HEAD;
1777 /* Method length is 5 bytes, which can only encompass PATCH and TRACE */
1780 if (method[4] == 'H' && method[3] == 'C' && method[2] == 'T' && method[1] == 'A') {
1781 type = EVHTTP_REQ_PATCH;
1785 if (method[4] == 'E' && method[3] == 'C' && method[2] == 'A' && method[1] == 'R') {
1786 type = EVHTTP_REQ_TRACE;
1795 /* Method length is 6, only valid method 6 bytes in length is DELEte */
1797 /* If the first byte isn't 'D' then it's invalid */
1798 if (*method != 'D') {
1802 if (method[5] == 'E' && method[4] == 'T' && method[3] == 'E' && method[2] == 'L' && method[1] == 'E') {
1803 type = EVHTTP_REQ_DELETE;
1808 /* Method length is 7, only valid methods are "OPTIONS" and "CONNECT" */
1811 if (method[6] == 'S' && method[5] == 'N' && method[4] == 'O' &&
1812 method[3] == 'I' && method[2] == 'T' && method[1] == 'P') {
1813 type = EVHTTP_REQ_OPTIONS;
1818 if (method[6] == 'T' && method[5] == 'C' && method[4] == 'E' &&
1819 method[3] == 'N' && method[2] == 'N' && method[1] == 'O') {
1820 type = EVHTTP_REQ_CONNECT;
1830 if ((int)type == EVHTTP_REQ_UNKNOWN_) {
1831 event_debug(("%s: bad method %s on request %p from %s",
1832 __func__, method, req, req->remote_host));
1833 /* No error yet; we'll give a better error later when
1834 * we see that req->type is unsupported. */
1839 if (evhttp_parse_http_version(version, req) < 0)
1842 if ((req->uri = mm_strdup(uri)) == NULL) {
1843 event_debug(("%s: mm_strdup", __func__));
1847 if (type == EVHTTP_REQ_CONNECT) {
1848 if ((req->uri_elems = evhttp_uri_parse_authority(req->uri)) == NULL) {
1852 if ((req->uri_elems = evhttp_uri_parse_with_flags(req->uri,
1853 EVHTTP_URI_NONCONFORMANT)) == NULL) {
1858 /* If we have an absolute-URI, check to see if it is an http request
1859 for a known vhost or server alias. If we don't know about this
1860 host, we consider it a proxy request. */
1861 scheme = evhttp_uri_get_scheme(req->uri_elems);
1862 hostname = evhttp_uri_get_host(req->uri_elems);
1863 if (scheme && (!evutil_ascii_strcasecmp(scheme, "http") ||
1864 !evutil_ascii_strcasecmp(scheme, "https")) &&
1866 !evhttp_find_vhost(req->evcon->http_server, NULL, hostname))
1867 req->flags |= EVHTTP_PROXY_REQUEST;
1873 evhttp_find_header(const struct evkeyvalq *headers, const char *key)
1875 struct evkeyval *header;
1877 TAILQ_FOREACH(header, headers, next) {
1878 if (evutil_ascii_strcasecmp(header->key, key) == 0)
1879 return (header->value);
1886 evhttp_clear_headers(struct evkeyvalq *headers)
1888 struct evkeyval *header;
1890 for (header = TAILQ_FIRST(headers);
1892 header = TAILQ_FIRST(headers)) {
1893 TAILQ_REMOVE(headers, header, next);
1894 mm_free(header->key);
1895 mm_free(header->value);
1901 * Returns 0, if the header was successfully removed.
1902 * Returns -1, if the header could not be found.
1906 evhttp_remove_header(struct evkeyvalq *headers, const char *key)
1908 struct evkeyval *header;
1910 TAILQ_FOREACH(header, headers, next) {
1911 if (evutil_ascii_strcasecmp(header->key, key) == 0)
1918 /* Free and remove the header that we found */
1919 TAILQ_REMOVE(headers, header, next);
1920 mm_free(header->key);
1921 mm_free(header->value);
1928 evhttp_header_is_valid_value(const char *value)
1930 const char *p = value;
1932 while ((p = strpbrk(p, "\r\n")) != NULL) {
1933 /* we really expect only one new line */
1934 p += strspn(p, "\r\n");
1935 /* we expect a space or tab for continuation */
1936 if (*p != ' ' && *p != '\t')
1943 evhttp_add_header(struct evkeyvalq *headers,
1944 const char *key, const char *value)
1946 event_debug(("%s: key: %s val: %s\n", __func__, key, value));
1948 if (strchr(key, '\r') != NULL || strchr(key, '\n') != NULL) {
1949 /* drop illegal headers */
1950 event_debug(("%s: dropping illegal header key\n", __func__));
1954 if (!evhttp_header_is_valid_value(value)) {
1955 event_debug(("%s: dropping illegal header value\n", __func__));
1959 return (evhttp_add_header_internal(headers, key, value));
1963 evhttp_add_header_internal(struct evkeyvalq *headers,
1964 const char *key, const char *value)
1966 struct evkeyval *header = mm_calloc(1, sizeof(struct evkeyval));
1967 if (header == NULL) {
1968 event_warn("%s: calloc", __func__);
1971 if ((header->key = mm_strdup(key)) == NULL) {
1973 event_warn("%s: strdup", __func__);
1976 if ((header->value = mm_strdup(value)) == NULL) {
1977 mm_free(header->key);
1979 event_warn("%s: strdup", __func__);
1983 TAILQ_INSERT_TAIL(headers, header, next);
1989 * Parses header lines from a request or a response into the specified
1990 * request object given an event buffer.
1993 * DATA_CORRUPTED on error
1994 * MORE_DATA_EXPECTED when we need to read more headers
1995 * ALL_DATA_READ when all headers have been read.
1998 enum message_read_status
1999 evhttp_parse_firstline_(struct evhttp_request *req, struct evbuffer *buffer)
2002 enum message_read_status status = ALL_DATA_READ;
2006 line = evbuffer_readln(buffer, &len, EVBUFFER_EOL_CRLF);
2008 if (req->evcon != NULL &&
2009 evbuffer_get_length(buffer) > req->evcon->max_headers_size)
2010 return (DATA_TOO_LONG);
2012 return (MORE_DATA_EXPECTED);
2015 if (req->evcon != NULL && len > req->evcon->max_headers_size) {
2017 return (DATA_TOO_LONG);
2020 req->headers_size = len;
2022 switch (req->kind) {
2023 case EVHTTP_REQUEST:
2024 if (evhttp_parse_request_line(req, line, len) == -1)
2025 status = DATA_CORRUPTED;
2027 case EVHTTP_RESPONSE:
2028 if (evhttp_parse_response_line(req, line) == -1)
2029 status = DATA_CORRUPTED;
2032 status = DATA_CORRUPTED;
2040 evhttp_append_to_last_header(struct evkeyvalq *headers, char *line)
2042 struct evkeyval *header = TAILQ_LAST(headers, evkeyvalq);
2044 size_t old_len, line_len;
2049 old_len = strlen(header->value);
2051 /* Strip space from start and end of line. */
2052 while (*line == ' ' || *line == '\t')
2054 evutil_rtrim_lws_(line);
2056 line_len = strlen(line);
2058 newval = mm_realloc(header->value, old_len + line_len + 2);
2062 newval[old_len] = ' ';
2063 memcpy(newval + old_len + 1, line, line_len + 1);
2064 header->value = newval;
2069 enum message_read_status
2070 evhttp_parse_headers_(struct evhttp_request *req, struct evbuffer* buffer)
2072 enum message_read_status errcode = DATA_CORRUPTED;
2074 enum message_read_status status = MORE_DATA_EXPECTED;
2076 struct evkeyvalq* headers = req->input_headers;
2078 while ((line = evbuffer_readln(buffer, &len, EVBUFFER_EOL_CRLF))
2080 char *skey, *svalue;
2082 req->headers_size += len;
2084 if (req->evcon != NULL &&
2085 req->headers_size > req->evcon->max_headers_size) {
2086 errcode = DATA_TOO_LONG;
2090 if (*line == '\0') { /* Last header - Done */
2091 status = ALL_DATA_READ;
2096 /* Check if this is a continuation line */
2097 if (*line == ' ' || *line == '\t') {
2098 if (evhttp_append_to_last_header(headers, line) == -1)
2104 /* Processing of header lines */
2106 skey = strsep(&svalue, ":");
2110 svalue += strspn(svalue, " ");
2111 evutil_rtrim_lws_(svalue);
2113 if (evhttp_add_header(headers, skey, svalue) == -1)
2119 if (status == MORE_DATA_EXPECTED) {
2120 if (req->evcon != NULL &&
2121 req->headers_size + evbuffer_get_length(buffer) > req->evcon->max_headers_size)
2122 return (DATA_TOO_LONG);
2133 evhttp_get_body_length(struct evhttp_request *req)
2135 struct evkeyvalq *headers = req->input_headers;
2136 const char *content_length;
2137 const char *connection;
2139 content_length = evhttp_find_header(headers, "Content-Length");
2140 connection = evhttp_find_header(headers, "Connection");
2142 if (content_length == NULL && connection == NULL)
2144 else if (content_length == NULL &&
2145 evutil_ascii_strcasecmp(connection, "Close") != 0) {
2147 } else if (content_length == NULL) {
2151 ev_int64_t ntoread = evutil_strtoll(content_length, &endp, 10);
2152 if (*content_length == '\0' || *endp != '\0' || ntoread < 0) {
2153 event_debug(("%s: illegal content length: %s",
2154 __func__, content_length));
2157 req->ntoread = ntoread;
2160 event_debug(("%s: bytes to read: "EV_I64_FMT" (in buffer "EV_SIZE_FMT")\n",
2161 __func__, EV_I64_ARG(req->ntoread),
2162 EV_SIZE_ARG(evbuffer_get_length(bufferevent_get_input(req->evcon->bufev)))));
2168 evhttp_method_may_have_body(enum evhttp_cmd_type type)
2171 case EVHTTP_REQ_POST:
2172 case EVHTTP_REQ_PUT:
2173 case EVHTTP_REQ_PATCH:
2175 case EVHTTP_REQ_GET:
2176 case EVHTTP_REQ_DELETE:
2177 case EVHTTP_REQ_OPTIONS:
2178 case EVHTTP_REQ_CONNECT:
2181 case EVHTTP_REQ_TRACE:
2182 case EVHTTP_REQ_HEAD:
2189 evhttp_get_body(struct evhttp_connection *evcon, struct evhttp_request *req)
2191 const char *xfer_enc;
2193 /* If this is a request without a body, then we are done */
2194 if (req->kind == EVHTTP_REQUEST &&
2195 !evhttp_method_may_have_body(req->type)) {
2196 evhttp_connection_done(evcon);
2199 evcon->state = EVCON_READING_BODY;
2200 xfer_enc = evhttp_find_header(req->input_headers, "Transfer-Encoding");
2201 if (xfer_enc != NULL && evutil_ascii_strcasecmp(xfer_enc, "chunked") == 0) {
2205 if (evhttp_get_body_length(req) == -1) {
2206 evhttp_connection_fail_(evcon, EVREQ_HTTP_INVALID_HEADER);
2209 if (req->kind == EVHTTP_REQUEST && req->ntoread < 1) {
2210 /* An incoming request with no content-length and no
2211 * transfer-encoding has no body. */
2212 evhttp_connection_done(evcon);
2217 /* Should we send a 100 Continue status line? */
2218 switch (evhttp_have_expect(req, 1)) {
2220 /* XXX It would be nice to do some sanity
2221 checking here. Does the resource exist?
2222 Should the resource accept post requests? If
2223 no, we should respond with an error. For
2224 now, just optimistically tell the client to
2225 send their message body. */
2226 if (req->ntoread > 0) {
2227 /* ntoread is ev_int64_t, max_body_size is ev_uint64_t */
2228 if ((req->evcon->max_body_size <= EV_INT64_MAX) &&
2229 (ev_uint64_t)req->ntoread > req->evcon->max_body_size) {
2230 evhttp_lingering_fail(evcon, req);
2234 if (!evbuffer_get_length(bufferevent_get_input(evcon->bufev)))
2235 evhttp_send_continue(evcon, req);
2238 evhttp_send_error(req, HTTP_EXPECTATIONFAILED, NULL);
2243 evhttp_read_body(evcon, req);
2244 /* note the request may have been freed in evhttp_read_body */
2248 evhttp_read_firstline(struct evhttp_connection *evcon,
2249 struct evhttp_request *req)
2251 enum message_read_status res;
2253 res = evhttp_parse_firstline_(req, bufferevent_get_input(evcon->bufev));
2254 if (res == DATA_CORRUPTED || res == DATA_TOO_LONG) {
2255 /* Error while reading, terminate */
2256 event_debug(("%s: bad header lines on "EV_SOCK_FMT"\n",
2257 __func__, EV_SOCK_ARG(evcon->fd)));
2258 evhttp_connection_fail_(evcon, EVREQ_HTTP_INVALID_HEADER);
2260 } else if (res == MORE_DATA_EXPECTED) {
2261 /* Need more header lines */
2265 evcon->state = EVCON_READING_HEADERS;
2266 evhttp_read_header(evcon, req);
2270 evhttp_read_header(struct evhttp_connection *evcon,
2271 struct evhttp_request *req)
2273 enum message_read_status res;
2274 evutil_socket_t fd = evcon->fd;
2276 res = evhttp_parse_headers_(req, bufferevent_get_input(evcon->bufev));
2277 if (res == DATA_CORRUPTED || res == DATA_TOO_LONG) {
2278 /* Error while reading, terminate */
2279 event_debug(("%s: bad header lines on "EV_SOCK_FMT"\n",
2280 __func__, EV_SOCK_ARG(fd)));
2281 evhttp_connection_fail_(evcon, EVREQ_HTTP_INVALID_HEADER);
2283 } else if (res == MORE_DATA_EXPECTED) {
2284 /* Need more header lines */
2288 /* Callback can shut down connection with negative return value */
2289 if (req->header_cb != NULL) {
2290 if ((*req->header_cb)(req, req->cb_arg) < 0) {
2291 evhttp_connection_fail_(evcon, EVREQ_HTTP_EOF);
2296 /* Done reading headers, do the real work */
2297 switch (req->kind) {
2298 case EVHTTP_REQUEST:
2299 event_debug(("%s: checking for post data on "EV_SOCK_FMT"\n",
2300 __func__, EV_SOCK_ARG(fd)));
2301 evhttp_get_body(evcon, req);
2302 /* note the request may have been freed in evhttp_get_body */
2305 case EVHTTP_RESPONSE:
2306 /* Start over if we got a 100 Continue response. */
2307 if (req->response_code == 100) {
2308 struct evbuffer *output = bufferevent_get_output(evcon->bufev);
2309 evbuffer_add_buffer(output, req->output_buffer);
2310 evhttp_start_write_(evcon);
2313 if (!evhttp_response_needs_body(req)) {
2314 event_debug(("%s: skipping body for code %d\n",
2315 __func__, req->response_code));
2316 evhttp_connection_done(evcon);
2318 event_debug(("%s: start of read body for %s on "
2320 __func__, req->remote_host, EV_SOCK_ARG(fd)));
2321 evhttp_get_body(evcon, req);
2322 /* note the request may have been freed in
2323 * evhttp_get_body */
2328 event_warnx("%s: bad header on "EV_SOCK_FMT, __func__,
2330 evhttp_connection_fail_(evcon, EVREQ_HTTP_INVALID_HEADER);
2333 /* request may have been freed above */
2337 * Creates a TCP connection to the specified port and executes a callback
2338 * when finished. Failure or success is indicate by the passed connection
2341 * Although this interface accepts a hostname, it is intended to take
2342 * only numeric hostnames so that non-blocking DNS resolution can
2346 struct evhttp_connection *
2347 evhttp_connection_new(const char *address, ev_uint16_t port)
2349 return (evhttp_connection_base_new(NULL, NULL, address, port));
2352 struct evhttp_connection *
2353 evhttp_connection_base_bufferevent_new(struct event_base *base, struct evdns_base *dnsbase, struct bufferevent* bev,
2354 const char *address, ev_uint16_t port)
2356 struct evhttp_connection *evcon = NULL;
2358 event_debug(("Attempting connection to %s:%d\n", address, port));
2360 if ((evcon = mm_calloc(1, sizeof(struct evhttp_connection))) == NULL) {
2361 event_warn("%s: calloc failed", __func__);
2368 evcon->max_headers_size = EV_SIZE_MAX;
2369 evcon->max_body_size = EV_SIZE_MAX;
2371 evutil_timerclear(&evcon->timeout);
2372 evcon->retry_cnt = evcon->retry_max = 0;
2374 if ((evcon->address = mm_strdup(address)) == NULL) {
2375 event_warn("%s: strdup failed", __func__);
2380 if (!(bev = bufferevent_socket_new(base, -1, 0))) {
2381 event_warn("%s: bufferevent_socket_new failed", __func__);
2386 bufferevent_setcb(bev, evhttp_read_cb, evhttp_write_cb, evhttp_error_cb, evcon);
2389 evcon->state = EVCON_DISCONNECTED;
2390 TAILQ_INIT(&evcon->requests);
2392 evcon->initial_retry_timeout.tv_sec = 2;
2393 evcon->initial_retry_timeout.tv_usec = 0;
2397 if (bufferevent_get_base(bev) != base)
2398 bufferevent_base_set(base, evcon->bufev);
2401 event_deferred_cb_init_(
2402 &evcon->read_more_deferred_cb,
2403 bufferevent_get_priority(bev),
2404 evhttp_deferred_read_cb, evcon);
2406 evcon->dns_base = dnsbase;
2407 evcon->ai_family = AF_UNSPEC;
2413 evhttp_connection_free(evcon);
2417 struct bufferevent* evhttp_connection_get_bufferevent(struct evhttp_connection *evcon)
2419 return evcon->bufev;
2423 evhttp_connection_get_server(struct evhttp_connection *evcon)
2425 return evcon->http_server;
2428 struct evhttp_connection *
2429 evhttp_connection_base_new(struct event_base *base, struct evdns_base *dnsbase,
2430 const char *address, ev_uint16_t port)
2432 return evhttp_connection_base_bufferevent_new(base, dnsbase, NULL, address, port);
2435 void evhttp_connection_set_family(struct evhttp_connection *evcon,
2438 evcon->ai_family = family;
2441 int evhttp_connection_set_flags(struct evhttp_connection *evcon,
2444 int avail_flags = 0;
2445 avail_flags |= EVHTTP_CON_REUSE_CONNECTED_ADDR;
2446 avail_flags |= EVHTTP_CON_READ_ON_WRITE_ERROR;
2448 if (flags & ~avail_flags || flags > EVHTTP_CON_PUBLIC_FLAGS_END)
2450 evcon->flags &= ~avail_flags;
2452 evcon->flags |= flags;
2458 evhttp_connection_set_base(struct evhttp_connection *evcon,
2459 struct event_base *base)
2461 EVUTIL_ASSERT(evcon->base == NULL);
2462 EVUTIL_ASSERT(evcon->state == EVCON_DISCONNECTED);
2464 bufferevent_base_set(base, evcon->bufev);
2468 evhttp_connection_set_timeout(struct evhttp_connection *evcon,
2469 int timeout_in_secs)
2471 if (timeout_in_secs == -1)
2472 evhttp_connection_set_timeout_tv(evcon, NULL);
2475 tv.tv_sec = timeout_in_secs;
2477 evhttp_connection_set_timeout_tv(evcon, &tv);
2482 evhttp_connection_set_timeout_tv(struct evhttp_connection *evcon,
2483 const struct timeval* tv)
2486 evcon->timeout = *tv;
2487 bufferevent_set_timeouts(evcon->bufev, &evcon->timeout, &evcon->timeout);
2489 const struct timeval read_tv = { HTTP_READ_TIMEOUT, 0 };
2490 const struct timeval write_tv = { HTTP_WRITE_TIMEOUT, 0 };
2491 evutil_timerclear(&evcon->timeout);
2492 bufferevent_set_timeouts(evcon->bufev, &read_tv, &write_tv);
2497 evhttp_connection_set_initial_retry_tv(struct evhttp_connection *evcon,
2498 const struct timeval *tv)
2501 evcon->initial_retry_timeout = *tv;
2503 evutil_timerclear(&evcon->initial_retry_timeout);
2504 evcon->initial_retry_timeout.tv_sec = 2;
2509 evhttp_connection_set_retries(struct evhttp_connection *evcon,
2512 evcon->retry_max = retry_max;
2516 evhttp_connection_set_closecb(struct evhttp_connection *evcon,
2517 void (*cb)(struct evhttp_connection *, void *), void *cbarg)
2519 evcon->closecb = cb;
2520 evcon->closecb_arg = cbarg;
2524 evhttp_connection_get_peer(struct evhttp_connection *evcon,
2525 char **address, ev_uint16_t *port)
2527 *address = evcon->address;
2528 *port = evcon->port;
2531 const struct sockaddr*
2532 evhttp_connection_get_addr(struct evhttp_connection *evcon)
2534 return bufferevent_socket_get_conn_address_(evcon->bufev);
2538 evhttp_connection_connect_(struct evhttp_connection *evcon)
2540 int old_state = evcon->state;
2541 const char *address = evcon->address;
2542 const struct sockaddr *sa = evhttp_connection_get_addr(evcon);
2545 if (evcon->state == EVCON_CONNECTING)
2548 evhttp_connection_reset_(evcon);
2550 EVUTIL_ASSERT(!(evcon->flags & EVHTTP_CON_INCOMING));
2551 evcon->flags |= EVHTTP_CON_OUTGOING;
2553 if (evcon->bind_address || evcon->bind_port) {
2554 evcon->fd = bind_socket(
2555 evcon->bind_address, evcon->bind_port, 0 /*reuse*/);
2556 if (evcon->fd == -1) {
2557 event_debug(("%s: failed to bind to \"%s\"",
2558 __func__, evcon->bind_address));
2562 if (bufferevent_setfd(evcon->bufev, evcon->fd))
2565 if (bufferevent_setfd(evcon->bufev, -1))
2569 /* Set up a callback for successful connection setup */
2570 bufferevent_setcb(evcon->bufev,
2571 NULL /* evhttp_read_cb */,
2572 NULL /* evhttp_write_cb */,
2573 evhttp_connection_cb,
2575 if (!evutil_timerisset(&evcon->timeout)) {
2576 const struct timeval conn_tv = { HTTP_CONNECT_TIMEOUT, 0 };
2577 bufferevent_set_timeouts(evcon->bufev, &conn_tv, &conn_tv);
2579 bufferevent_set_timeouts(evcon->bufev, &evcon->timeout, &evcon->timeout);
2581 /* make sure that we get a write callback */
2582 if (bufferevent_enable(evcon->bufev, EV_WRITE))
2585 evcon->state = EVCON_CONNECTING;
2587 if (evcon->flags & EVHTTP_CON_REUSE_CONNECTED_ADDR &&
2589 (sa->sa_family == AF_INET || sa->sa_family == AF_INET6)) {
2590 int socklen = sizeof(struct sockaddr_in);
2591 if (sa->sa_family == AF_INET6) {
2592 socklen = sizeof(struct sockaddr_in6);
2594 ret = bufferevent_socket_connect(evcon->bufev, sa, socklen);
2596 ret = bufferevent_socket_connect_hostname(evcon->bufev,
2597 evcon->dns_base, evcon->ai_family, address, evcon->port);
2601 evcon->state = old_state;
2602 event_sock_warn(evcon->fd, "%s: connection to \"%s\" failed",
2603 __func__, evcon->address);
2604 /* some operating systems return ECONNREFUSED immediately
2605 * when connecting to a local address. the cleanup is going
2606 * to reschedule this function call.
2608 evhttp_connection_cb_cleanup(evcon);
2616 * Starts an HTTP request on the provided evhttp_connection object.
2617 * If the connection object is not connected to the web server already,
2618 * this will start the connection.
2622 evhttp_make_request(struct evhttp_connection *evcon,
2623 struct evhttp_request *req,
2624 enum evhttp_cmd_type type, const char *uri)
2626 /* We are making a request */
2627 req->kind = EVHTTP_REQUEST;
2629 if (req->uri != NULL)
2631 if ((req->uri = mm_strdup(uri)) == NULL) {
2632 event_warn("%s: strdup", __func__);
2633 evhttp_request_free_auto(req);
2637 /* Set the protocol version if it is not supplied */
2638 if (!req->major && !req->minor) {
2643 EVUTIL_ASSERT(req->evcon == NULL);
2645 EVUTIL_ASSERT(!(req->flags & EVHTTP_REQ_OWN_CONNECTION));
2647 TAILQ_INSERT_TAIL(&evcon->requests, req, next);
2649 /* We do not want to conflict with retry_ev */
2650 if (evcon->retry_cnt)
2653 /* If the connection object is not connected; make it so */
2654 if (!evhttp_connected(evcon)) {
2655 int res = evhttp_connection_connect_(evcon);
2656 /* evhttp_connection_fail_(), which is called through
2657 * evhttp_connection_connect_(), assumes that req lies in
2658 * evcon->requests. Thus, enqueue the request in advance and
2659 * remove it in the error case. */
2661 TAILQ_REMOVE(&evcon->requests, req, next);
2667 * If it's connected already and we are the first in the queue,
2668 * then we can dispatch this request immediately. Otherwise, it
2669 * will be dispatched once the pending requests are completed.
2671 if (TAILQ_FIRST(&evcon->requests) == req)
2672 evhttp_request_dispatch(evcon);
2678 evhttp_cancel_request(struct evhttp_request *req)
2680 struct evhttp_connection *evcon = req->evcon;
2681 if (evcon != NULL) {
2682 /* We need to remove it from the connection */
2683 if (TAILQ_FIRST(&evcon->requests) == req) {
2684 /* it's currently being worked on, so reset
2687 evhttp_connection_fail_(evcon,
2688 EVREQ_HTTP_REQUEST_CANCEL);
2690 /* connection fail freed the request */
2693 /* otherwise, we can just remove it from the
2696 TAILQ_REMOVE(&evcon->requests, req, next);
2700 evhttp_request_free_auto(req);
2704 * Reads data from file descriptor into request structure
2705 * Request structure needs to be set up correctly.
2709 evhttp_start_read_(struct evhttp_connection *evcon)
2711 bufferevent_disable(evcon->bufev, EV_WRITE);
2712 bufferevent_enable(evcon->bufev, EV_READ);
2714 evcon->state = EVCON_READING_FIRSTLINE;
2715 /* Reset the bufferevent callbacks */
2716 bufferevent_setcb(evcon->bufev,
2722 /* If there's still data pending, process it next time through the
2723 * loop. Don't do it now; that could get recusive. */
2724 if (evbuffer_get_length(bufferevent_get_input(evcon->bufev))) {
2725 event_deferred_cb_schedule_(get_deferred_queue(evcon),
2726 &evcon->read_more_deferred_cb);
2731 evhttp_start_write_(struct evhttp_connection *evcon)
2733 bufferevent_disable(evcon->bufev, EV_WRITE);
2734 bufferevent_enable(evcon->bufev, EV_READ);
2736 evcon->state = EVCON_WRITING;
2737 evhttp_write_buffer(evcon, evhttp_write_connectioncb, NULL);
2741 evhttp_send_done(struct evhttp_connection *evcon, void *arg)
2744 struct evhttp_request *req = TAILQ_FIRST(&evcon->requests);
2745 TAILQ_REMOVE(&evcon->requests, req, next);
2747 if (req->on_complete_cb != NULL) {
2748 req->on_complete_cb(req, req->on_complete_cb_arg);
2752 (REQ_VERSION_BEFORE(req, 1, 1) &&
2753 !evhttp_is_connection_keepalive(req->input_headers)) ||
2754 evhttp_is_request_connection_close(req);
2756 EVUTIL_ASSERT(req->flags & EVHTTP_REQ_OWN_CONNECTION);
2757 evhttp_request_free(req);
2760 evhttp_connection_free(evcon);
2764 /* we have a persistent connection; try to accept another request. */
2765 if (evhttp_associate_new_request_with_connection(evcon) == -1) {
2766 evhttp_connection_free(evcon);
2771 * Returns an error page.
2775 evhttp_send_error(struct evhttp_request *req, int error, const char *reason)
2778 #define ERR_FORMAT "<HTML><HEAD>\n" \
2779 "<TITLE>%d %s</TITLE>\n" \
2784 struct evbuffer *buf = evbuffer_new();
2786 /* if we cannot allocate memory; we just drop the connection */
2787 evhttp_connection_free(req->evcon);
2790 if (reason == NULL) {
2791 reason = evhttp_response_phrase_internal(error);
2794 evhttp_response_code_(req, error, reason);
2796 evbuffer_add_printf(buf, ERR_FORMAT, error, reason, reason);
2798 evhttp_send_page_(req, buf);
2804 /* Requires that headers and response code are already set up */
2807 evhttp_send(struct evhttp_request *req, struct evbuffer *databuf)
2809 struct evhttp_connection *evcon = req->evcon;
2811 if (evcon == NULL) {
2812 evhttp_request_free(req);
2816 EVUTIL_ASSERT(TAILQ_FIRST(&evcon->requests) == req);
2818 /* we expect no more calls form the user on this request */
2821 /* xxx: not sure if we really should expose the data buffer this way */
2822 if (databuf != NULL)
2823 evbuffer_add_buffer(req->output_buffer, databuf);
2825 /* Adds headers to the response */
2826 evhttp_make_header(evcon, req);
2828 evhttp_write_buffer(evcon, evhttp_send_done, NULL);
2832 evhttp_send_reply(struct evhttp_request *req, int code, const char *reason,
2833 struct evbuffer *databuf)
2835 evhttp_response_code_(req, code, reason);
2837 evhttp_send(req, databuf);
2841 evhttp_send_reply_start(struct evhttp_request *req, int code,
2844 evhttp_response_code_(req, code, reason);
2846 if (req->evcon == NULL)
2849 if (evhttp_find_header(req->output_headers, "Content-Length") == NULL &&
2850 REQ_VERSION_ATLEAST(req, 1, 1) &&
2851 evhttp_response_needs_body(req)) {
2853 * prefer HTTP/1.1 chunked encoding to closing the connection;
2854 * note RFC 2616 section 4.4 forbids it with Content-Length:
2855 * and it's not necessary then anyway.
2857 evhttp_add_header(req->output_headers, "Transfer-Encoding",
2863 evhttp_make_header(req->evcon, req);
2864 evhttp_write_buffer(req->evcon, NULL, NULL);
2868 evhttp_send_reply_chunk_with_cb(struct evhttp_request *req, struct evbuffer *databuf,
2869 void (*cb)(struct evhttp_connection *, void *), void *arg)
2871 struct evhttp_connection *evcon = req->evcon;
2872 struct evbuffer *output;
2877 output = bufferevent_get_output(evcon->bufev);
2879 if (evbuffer_get_length(databuf) == 0)
2881 if (!evhttp_response_needs_body(req))
2884 evbuffer_add_printf(output, "%x\r\n",
2885 (unsigned)evbuffer_get_length(databuf));
2887 evbuffer_add_buffer(output, databuf);
2889 evbuffer_add(output, "\r\n", 2);
2891 evhttp_write_buffer(evcon, cb, arg);
2895 evhttp_send_reply_chunk(struct evhttp_request *req, struct evbuffer *databuf)
2897 evhttp_send_reply_chunk_with_cb(req, databuf, NULL, NULL);
2900 evhttp_send_reply_end(struct evhttp_request *req)
2902 struct evhttp_connection *evcon = req->evcon;
2903 struct evbuffer *output;
2905 if (evcon == NULL) {
2906 evhttp_request_free(req);
2910 output = bufferevent_get_output(evcon->bufev);
2912 /* we expect no more calls form the user on this request */
2916 evbuffer_add(output, "0\r\n\r\n", 5);
2917 evhttp_write_buffer(req->evcon, evhttp_send_done, NULL);
2919 } else if (evbuffer_get_length(output) == 0) {
2920 /* let the connection know that we are done with the request */
2921 evhttp_send_done(evcon, NULL);
2923 /* make the callback execute after all data has been written */
2924 evcon->cb = evhttp_send_done;
2925 evcon->cb_arg = NULL;
2929 static const char *informational_phrases[] = {
2930 /* 100 */ "Continue",
2931 /* 101 */ "Switching Protocols"
2934 static const char *success_phrases[] = {
2936 /* 201 */ "Created",
2937 /* 202 */ "Accepted",
2938 /* 203 */ "Non-Authoritative Information",
2939 /* 204 */ "No Content",
2940 /* 205 */ "Reset Content",
2941 /* 206 */ "Partial Content"
2944 static const char *redirection_phrases[] = {
2945 /* 300 */ "Multiple Choices",
2946 /* 301 */ "Moved Permanently",
2948 /* 303 */ "See Other",
2949 /* 304 */ "Not Modified",
2950 /* 305 */ "Use Proxy",
2951 /* 307 */ "Temporary Redirect"
2954 static const char *client_error_phrases[] = {
2955 /* 400 */ "Bad Request",
2956 /* 401 */ "Unauthorized",
2957 /* 402 */ "Payment Required",
2958 /* 403 */ "Forbidden",
2959 /* 404 */ "Not Found",
2960 /* 405 */ "Method Not Allowed",
2961 /* 406 */ "Not Acceptable",
2962 /* 407 */ "Proxy Authentication Required",
2963 /* 408 */ "Request Time-out",
2964 /* 409 */ "Conflict",
2966 /* 411 */ "Length Required",
2967 /* 412 */ "Precondition Failed",
2968 /* 413 */ "Request Entity Too Large",
2969 /* 414 */ "Request-URI Too Large",
2970 /* 415 */ "Unsupported Media Type",
2971 /* 416 */ "Requested range not satisfiable",
2972 /* 417 */ "Expectation Failed"
2975 static const char *server_error_phrases[] = {
2976 /* 500 */ "Internal Server Error",
2977 /* 501 */ "Not Implemented",
2978 /* 502 */ "Bad Gateway",
2979 /* 503 */ "Service Unavailable",
2980 /* 504 */ "Gateway Time-out",
2981 /* 505 */ "HTTP Version not supported"
2984 struct response_class {
2986 size_t num_responses;
2987 const char **responses;
2991 #define MEMBERSOF(x) (sizeof(x)/sizeof(x[0]))
2994 static const struct response_class response_classes[] = {
2995 /* 1xx */ { "Informational", MEMBERSOF(informational_phrases), informational_phrases },
2996 /* 2xx */ { "Success", MEMBERSOF(success_phrases), success_phrases },
2997 /* 3xx */ { "Redirection", MEMBERSOF(redirection_phrases), redirection_phrases },
2998 /* 4xx */ { "Client Error", MEMBERSOF(client_error_phrases), client_error_phrases },
2999 /* 5xx */ { "Server Error", MEMBERSOF(server_error_phrases), server_error_phrases }
3003 evhttp_response_phrase_internal(int code)
3005 int klass = code / 100 - 1;
3006 int subcode = code % 100;
3008 /* Unknown class - can't do any better here */
3009 if (klass < 0 || klass >= (int) MEMBERSOF(response_classes))
3010 return "Unknown Status Class";
3012 /* Unknown sub-code, return class name at least */
3013 if (subcode >= (int) response_classes[klass].num_responses)
3014 return response_classes[klass].name;
3016 return response_classes[klass].responses[subcode];
3020 evhttp_response_code_(struct evhttp_request *req, int code, const char *reason)
3022 req->kind = EVHTTP_RESPONSE;
3023 req->response_code = code;
3024 if (req->response_code_line != NULL)
3025 mm_free(req->response_code_line);
3027 reason = evhttp_response_phrase_internal(code);
3028 req->response_code_line = mm_strdup(reason);
3029 if (req->response_code_line == NULL) {
3030 event_warn("%s: strdup", __func__);
3031 /* XXX what else can we do? */
3036 evhttp_send_page_(struct evhttp_request *req, struct evbuffer *databuf)
3038 if (!req->major || !req->minor) {
3043 if (req->kind != EVHTTP_RESPONSE)
3044 evhttp_response_code_(req, 200, "OK");
3046 evhttp_clear_headers(req->output_headers);
3047 evhttp_add_header(req->output_headers, "Content-Type", "text/html");
3048 evhttp_add_header(req->output_headers, "Connection", "close");
3050 evhttp_send(req, databuf);
3053 static const char uri_chars[256] = {
3055 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3056 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3057 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0,
3058 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,
3060 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3061 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1,
3062 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3063 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0,
3065 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3066 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3067 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3068 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3070 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3071 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3072 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3073 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3076 #define CHAR_IS_UNRESERVED(c) \
3077 (uri_chars[(unsigned char)(c)])
3080 * Helper functions to encode/decode a string for inclusion in a URI.
3081 * The returned string must be freed by the caller.
3084 evhttp_uriencode(const char *uri, ev_ssize_t len, int space_as_plus)
3086 struct evbuffer *buf = evbuffer_new();
3087 const char *p, *end;
3088 char *result = NULL;
3095 if (uri + len < uri) {
3101 size_t slen = strlen(uri);
3103 if (slen >= EV_SSIZE_MAX) {
3104 /* we don't want to mix signed and unsigned */
3108 if (uri + slen < uri) {
3115 for (p = uri; p < end; p++) {
3116 if (CHAR_IS_UNRESERVED(*p)) {
3117 evbuffer_add(buf, p, 1);
3118 } else if (*p == ' ' && space_as_plus) {
3119 evbuffer_add(buf, "+", 1);
3121 evbuffer_add_printf(buf, "%%%02X", (unsigned char)(*p));
3125 evbuffer_add(buf, "", 1); /* NUL-terminator. */
3126 result = mm_malloc(evbuffer_get_length(buf));
3129 evbuffer_remove(buf, result, evbuffer_get_length(buf));
3138 evhttp_encode_uri(const char *str)
3140 return evhttp_uriencode(str, -1, 0);
3144 * @param decode_plus_ctl: if 1, we decode plus into space. If 0, we don't.
3145 * If -1, when true we transform plus to space only after we've seen
3146 * a ?. -1 is deprecated.
3147 * @return the number of bytes written to 'ret'.
3150 evhttp_decode_uri_internal(
3151 const char *uri, size_t length, char *ret, int decode_plus_ctl)
3155 int decode_plus = (decode_plus_ctl == 1) ? 1: 0;
3158 for (i = j = 0; i < length; i++) {
3161 if (decode_plus_ctl < 0)
3163 } else if (c == '+' && decode_plus) {
3165 } else if ((i + 2) < length && c == '%' &&
3166 EVUTIL_ISXDIGIT_(uri[i+1]) && EVUTIL_ISXDIGIT_(uri[i+2])) {
3171 c = (char)strtol(tmp, NULL, 16);
3183 evhttp_decode_uri(const char *uri)
3187 if ((ret = mm_malloc(strlen(uri) + 1)) == NULL) {
3188 event_warn("%s: malloc(%lu)", __func__,
3189 (unsigned long)(strlen(uri) + 1));
3193 evhttp_decode_uri_internal(uri, strlen(uri),
3194 ret, -1 /*always_decode_plus*/);
3200 evhttp_uridecode(const char *uri, int decode_plus, size_t *size_out)
3205 if ((ret = mm_malloc(strlen(uri) + 1)) == NULL) {
3206 event_warn("%s: malloc(%lu)", __func__,
3207 (unsigned long)(strlen(uri) + 1));
3211 n = evhttp_decode_uri_internal(uri, strlen(uri),
3212 ret, !!decode_plus/*always_decode_plus*/);
3215 EVUTIL_ASSERT(n >= 0);
3216 *size_out = (size_t)n;
3223 * Helper function to parse out arguments in a query.
3224 * The arguments are separated by key and value.
3228 evhttp_parse_query_impl(const char *str, struct evkeyvalq *headers,
3229 int is_whole_uri, unsigned flags)
3234 const char *query_part;
3236 struct evhttp_uri *uri=NULL;
3238 TAILQ_INIT(headers);
3241 uri = evhttp_uri_parse(str);
3244 query_part = evhttp_uri_get_query(uri);
3249 /* No arguments - we are done */
3250 if (!query_part || !strlen(query_part)) {
3255 if ((line = mm_strdup(query_part)) == NULL) {
3256 event_warn("%s: strdup", __func__);
3260 p = argument = line;
3261 while (p != NULL && *p != '\0') {
3262 char *key, *value, *decoded_value;
3263 argument = strsep(&p, "&");
3266 key = strsep(&value, "=");
3267 if (flags & EVHTTP_URI_QUERY_NONCONFORMANT) {
3273 if (value == NULL || *key == '\0')
3277 if ((decoded_value = mm_malloc(strlen(value) + 1)) == NULL) {
3278 event_warn("%s: mm_malloc", __func__);
3281 evhttp_decode_uri_internal(value, strlen(value),
3282 decoded_value, 1 /*always_decode_plus*/);
3283 event_debug(("Query Param: %s -> %s\n", key, decoded_value));
3284 if (flags & EVHTTP_URI_QUERY_LAST_VAL)
3285 evhttp_remove_header(headers, key);
3286 evhttp_add_header_internal(headers, key, decoded_value);
3287 mm_free(decoded_value);
3293 evhttp_clear_headers(headers);
3298 evhttp_uri_free(uri);
3303 evhttp_parse_query(const char *uri, struct evkeyvalq *headers)
3305 return evhttp_parse_query_impl(uri, headers, 1, 0);
3308 evhttp_parse_query_str(const char *uri, struct evkeyvalq *headers)
3310 return evhttp_parse_query_impl(uri, headers, 0, 0);
3313 evhttp_parse_query_str_flags(const char *uri, struct evkeyvalq *headers, unsigned flags)
3315 return evhttp_parse_query_impl(uri, headers, 0, flags);
3318 static struct evhttp_cb *
3319 evhttp_dispatch_callback(struct httpcbq *callbacks, struct evhttp_request *req)
3321 struct evhttp_cb *cb;
3326 /* Test for different URLs */
3327 path = evhttp_uri_get_path(req->uri_elems);
3328 offset = strlen(path);
3329 if ((translated = mm_malloc(offset + 1)) == NULL)
3331 evhttp_decode_uri_internal(path, offset, translated,
3332 0 /* decode_plus */);
3334 TAILQ_FOREACH(cb, callbacks, next) {
3335 if (!strcmp(cb->what, translated)) {
3336 mm_free(translated);
3341 mm_free(translated);
3347 prefix_suffix_match(const char *pattern, const char *name, int ignorecase)
3352 switch (c = *pattern++) {
3354 return *name == '\0';
3357 while (*name != '\0') {
3358 if (prefix_suffix_match(pattern, name,
3367 EVUTIL_TOLOWER_(c) != EVUTIL_TOLOWER_(*name))
3377 Search the vhost hierarchy beginning with http for a server alias
3378 matching hostname. If a match is found, and outhttp is non-null,
3379 outhttp is set to the matching http object and 1 is returned.
3383 evhttp_find_alias(struct evhttp *http, struct evhttp **outhttp,
3384 const char *hostname)
3386 struct evhttp_server_alias *alias;
3387 struct evhttp *vhost;
3389 TAILQ_FOREACH(alias, &http->aliases, next) {
3390 /* XXX Do we need to handle IP addresses? */
3391 if (!evutil_ascii_strcasecmp(alias->alias, hostname)) {
3398 /* XXX It might be good to avoid recursion here, but I don't
3399 see a way to do that w/o a list. */
3400 TAILQ_FOREACH(vhost, &http->virtualhosts, next_vhost) {
3401 if (evhttp_find_alias(vhost, outhttp, hostname))
3409 Attempts to find the best http object to handle a request for a hostname.
3410 All aliases for the root http object and vhosts are searched for an exact
3411 match. Then, the vhost hierarchy is traversed again for a matching
3414 If an alias or vhost is matched, 1 is returned, and outhttp, if non-null,
3415 is set with the best matching http object. If there are no matches, the
3416 root http object is stored in outhttp and 0 is returned.
3420 evhttp_find_vhost(struct evhttp *http, struct evhttp **outhttp,
3421 const char *hostname)
3423 struct evhttp *vhost;
3424 struct evhttp *oldhttp;
3425 int match_found = 0;
3427 if (evhttp_find_alias(http, outhttp, hostname))
3432 TAILQ_FOREACH(vhost, &http->virtualhosts, next_vhost) {
3433 if (prefix_suffix_match(vhost->vhost_pattern,
3434 hostname, 1 /* ignorecase */)) {
3440 } while (oldhttp != http);
3449 evhttp_handle_request(struct evhttp_request *req, void *arg)
3451 struct evhttp *http = arg;
3452 struct evhttp_cb *cb = NULL;
3453 const char *hostname;
3455 /* we have a new request on which the user needs to take action */
3458 bufferevent_disable(req->evcon->bufev, EV_READ);
3460 if (req->type == 0 || req->uri == NULL) {
3461 evhttp_send_error(req, req->response_code, NULL);
3465 if ((http->allowed_methods & req->type) == 0) {
3466 event_debug(("Rejecting disallowed method %x (allowed: %x)\n",
3467 (unsigned)req->type, (unsigned)http->allowed_methods));
3468 evhttp_send_error(req, HTTP_NOTIMPLEMENTED, NULL);
3472 /* handle potential virtual hosts */
3473 hostname = evhttp_request_get_host(req);
3474 if (hostname != NULL) {
3475 evhttp_find_vhost(http, &http, hostname);
3478 if ((cb = evhttp_dispatch_callback(&http->callbacks, req)) != NULL) {
3479 (*cb->cb)(req, cb->cbarg);
3483 /* Generic call back */
3485 (*http->gencb)(req, http->gencbarg);
3488 /* We need to send a 404 here */
3489 #define ERR_FORMAT "<html><head>" \
3490 "<title>404 Not Found</title>" \
3492 "<h1>Not Found</h1>" \
3493 "<p>The requested URL %s was not found on this server.</p>"\
3497 struct evbuffer *buf;
3499 if ((escaped_html = evhttp_htmlescape(req->uri)) == NULL) {
3500 evhttp_connection_free(req->evcon);
3504 if ((buf = evbuffer_new()) == NULL) {
3505 mm_free(escaped_html);
3506 evhttp_connection_free(req->evcon);
3510 evhttp_response_code_(req, HTTP_NOTFOUND, "Not Found");
3512 evbuffer_add_printf(buf, ERR_FORMAT, escaped_html);
3514 mm_free(escaped_html);
3516 evhttp_send_page_(req, buf);
3523 /* Listener callback when a connection arrives at a server. */
3525 accept_socket_cb(struct evconnlistener *listener, evutil_socket_t nfd, struct sockaddr *peer_sa, int peer_socklen, void *arg)
3527 struct evhttp *http = arg;
3529 evhttp_get_request(http, nfd, peer_sa, peer_socklen);
3533 evhttp_bind_socket(struct evhttp *http, const char *address, ev_uint16_t port)
3535 struct evhttp_bound_socket *bound =
3536 evhttp_bind_socket_with_handle(http, address, port);
3542 struct evhttp_bound_socket *
3543 evhttp_bind_socket_with_handle(struct evhttp *http, const char *address, ev_uint16_t port)
3546 struct evhttp_bound_socket *bound;
3549 if ((fd = bind_socket(address, port, 1 /*reuse*/)) == -1)
3552 if (listen(fd, 128) == -1) {
3553 serrno = EVUTIL_SOCKET_ERROR();
3554 event_sock_warn(fd, "%s: listen", __func__);
3555 evutil_closesocket(fd);
3556 EVUTIL_SET_SOCKET_ERROR(serrno);
3560 bound = evhttp_accept_socket_with_handle(http, fd);
3562 if (bound != NULL) {
3563 event_debug(("Bound to port %d - Awaiting connections ... ",
3572 evhttp_accept_socket(struct evhttp *http, evutil_socket_t fd)
3574 struct evhttp_bound_socket *bound =
3575 evhttp_accept_socket_with_handle(http, fd);
3582 evhttp_foreach_bound_socket(struct evhttp *http,
3583 evhttp_bound_socket_foreach_fn *function,
3586 struct evhttp_bound_socket *bound;
3588 TAILQ_FOREACH(bound, &http->sockets, next)
3589 function(bound, argument);
3592 struct evhttp_bound_socket *
3593 evhttp_accept_socket_with_handle(struct evhttp *http, evutil_socket_t fd)
3595 struct evhttp_bound_socket *bound;
3596 struct evconnlistener *listener;
3598 LEV_OPT_REUSEABLE|LEV_OPT_CLOSE_ON_EXEC|LEV_OPT_CLOSE_ON_FREE;
3600 listener = evconnlistener_new(http->base, NULL, NULL,
3602 0, /* Backlog is '0' because we already said 'listen' */
3607 bound = evhttp_bind_listener(http, listener);
3609 evconnlistener_free(listener);
3615 struct evhttp_bound_socket *
3616 evhttp_bind_listener(struct evhttp *http, struct evconnlistener *listener)
3618 struct evhttp_bound_socket *bound;
3620 bound = mm_malloc(sizeof(struct evhttp_bound_socket));
3624 bound->listener = listener;
3625 TAILQ_INSERT_TAIL(&http->sockets, bound, next);
3627 evconnlistener_set_cb(listener, accept_socket_cb, http);
3632 evhttp_bound_socket_get_fd(struct evhttp_bound_socket *bound)
3634 return evconnlistener_get_fd(bound->listener);
3637 struct evconnlistener *
3638 evhttp_bound_socket_get_listener(struct evhttp_bound_socket *bound)
3640 return bound->listener;
3644 evhttp_del_accept_socket(struct evhttp *http, struct evhttp_bound_socket *bound)
3646 TAILQ_REMOVE(&http->sockets, bound, next);
3647 evconnlistener_free(bound->listener);
3651 static struct evhttp*
3652 evhttp_new_object(void)
3654 struct evhttp *http = NULL;
3656 if ((http = mm_calloc(1, sizeof(struct evhttp))) == NULL) {
3657 event_warn("%s: calloc", __func__);
3661 evutil_timerclear(&http->timeout);
3662 evhttp_set_max_headers_size(http, EV_SIZE_MAX);
3663 evhttp_set_max_body_size(http, EV_SIZE_MAX);
3664 evhttp_set_default_content_type(http, "text/html; charset=ISO-8859-1");
3665 evhttp_set_allowed_methods(http,
3672 TAILQ_INIT(&http->sockets);
3673 TAILQ_INIT(&http->callbacks);
3674 TAILQ_INIT(&http->connections);
3675 TAILQ_INIT(&http->virtualhosts);
3676 TAILQ_INIT(&http->aliases);
3682 evhttp_new(struct event_base *base)
3684 struct evhttp *http = NULL;
3686 http = evhttp_new_object();
3695 * Start a web server on the specified address and port.
3699 evhttp_start(const char *address, ev_uint16_t port)
3701 struct evhttp *http = NULL;
3703 http = evhttp_new_object();
3706 if (evhttp_bind_socket(http, address, port) == -1) {
3715 evhttp_free(struct evhttp* http)
3717 struct evhttp_cb *http_cb;
3718 struct evhttp_connection *evcon;
3719 struct evhttp_bound_socket *bound;
3720 struct evhttp* vhost;
3721 struct evhttp_server_alias *alias;
3723 /* Remove the accepting part */
3724 while ((bound = TAILQ_FIRST(&http->sockets)) != NULL) {
3725 TAILQ_REMOVE(&http->sockets, bound, next);
3727 evconnlistener_free(bound->listener);
3732 while ((evcon = TAILQ_FIRST(&http->connections)) != NULL) {
3733 /* evhttp_connection_free removes the connection */
3734 evhttp_connection_free(evcon);
3737 while ((http_cb = TAILQ_FIRST(&http->callbacks)) != NULL) {
3738 TAILQ_REMOVE(&http->callbacks, http_cb, next);
3739 mm_free(http_cb->what);
3743 while ((vhost = TAILQ_FIRST(&http->virtualhosts)) != NULL) {
3744 TAILQ_REMOVE(&http->virtualhosts, vhost, next_vhost);
3749 if (http->vhost_pattern != NULL)
3750 mm_free(http->vhost_pattern);
3752 while ((alias = TAILQ_FIRST(&http->aliases)) != NULL) {
3753 TAILQ_REMOVE(&http->aliases, alias, next);
3754 mm_free(alias->alias);
3762 evhttp_add_virtual_host(struct evhttp* http, const char *pattern,
3763 struct evhttp* vhost)
3765 /* a vhost can only be a vhost once and should not have bound sockets */
3766 if (vhost->vhost_pattern != NULL ||
3767 TAILQ_FIRST(&vhost->sockets) != NULL)
3770 vhost->vhost_pattern = mm_strdup(pattern);
3771 if (vhost->vhost_pattern == NULL)
3774 TAILQ_INSERT_TAIL(&http->virtualhosts, vhost, next_vhost);
3780 evhttp_remove_virtual_host(struct evhttp* http, struct evhttp* vhost)
3782 if (vhost->vhost_pattern == NULL)
3785 TAILQ_REMOVE(&http->virtualhosts, vhost, next_vhost);
3787 mm_free(vhost->vhost_pattern);
3788 vhost->vhost_pattern = NULL;
3794 evhttp_add_server_alias(struct evhttp *http, const char *alias)
3796 struct evhttp_server_alias *evalias;
3798 evalias = mm_calloc(1, sizeof(*evalias));
3802 evalias->alias = mm_strdup(alias);
3803 if (!evalias->alias) {
3808 TAILQ_INSERT_TAIL(&http->aliases, evalias, next);
3814 evhttp_remove_server_alias(struct evhttp *http, const char *alias)
3816 struct evhttp_server_alias *evalias;
3818 TAILQ_FOREACH(evalias, &http->aliases, next) {
3819 if (evutil_ascii_strcasecmp(evalias->alias, alias) == 0) {
3820 TAILQ_REMOVE(&http->aliases, evalias, next);
3821 mm_free(evalias->alias);
3831 evhttp_set_timeout(struct evhttp* http, int timeout_in_secs)
3833 if (timeout_in_secs == -1) {
3834 evhttp_set_timeout_tv(http, NULL);
3837 tv.tv_sec = timeout_in_secs;
3839 evhttp_set_timeout_tv(http, &tv);
3844 evhttp_set_timeout_tv(struct evhttp* http, const struct timeval* tv)
3847 http->timeout = *tv;
3849 evutil_timerclear(&http->timeout);
3853 int evhttp_set_flags(struct evhttp *http, int flags)
3855 int avail_flags = 0;
3856 avail_flags |= EVHTTP_SERVER_LINGERING_CLOSE;
3858 if (flags & ~avail_flags)
3860 http->flags &= ~avail_flags;
3862 http->flags |= flags;
3868 evhttp_set_max_headers_size(struct evhttp* http, ev_ssize_t max_headers_size)
3870 if (max_headers_size < 0)
3871 http->default_max_headers_size = EV_SIZE_MAX;
3873 http->default_max_headers_size = max_headers_size;
3877 evhttp_set_max_body_size(struct evhttp* http, ev_ssize_t max_body_size)
3879 if (max_body_size < 0)
3880 http->default_max_body_size = EV_UINT64_MAX;
3882 http->default_max_body_size = max_body_size;
3886 evhttp_set_default_content_type(struct evhttp *http,
3887 const char *content_type) {
3888 http->default_content_type = content_type;
3892 evhttp_set_allowed_methods(struct evhttp* http, ev_uint16_t methods)
3894 http->allowed_methods = methods;
3898 evhttp_set_cb(struct evhttp *http, const char *uri,
3899 void (*cb)(struct evhttp_request *, void *), void *cbarg)
3901 struct evhttp_cb *http_cb;
3903 TAILQ_FOREACH(http_cb, &http->callbacks, next) {
3904 if (strcmp(http_cb->what, uri) == 0)
3908 if ((http_cb = mm_calloc(1, sizeof(struct evhttp_cb))) == NULL) {
3909 event_warn("%s: calloc", __func__);
3913 http_cb->what = mm_strdup(uri);
3914 if (http_cb->what == NULL) {
3915 event_warn("%s: strdup", __func__);
3920 http_cb->cbarg = cbarg;
3922 TAILQ_INSERT_TAIL(&http->callbacks, http_cb, next);
3928 evhttp_del_cb(struct evhttp *http, const char *uri)
3930 struct evhttp_cb *http_cb;
3932 TAILQ_FOREACH(http_cb, &http->callbacks, next) {
3933 if (strcmp(http_cb->what, uri) == 0)
3936 if (http_cb == NULL)
3939 TAILQ_REMOVE(&http->callbacks, http_cb, next);
3940 mm_free(http_cb->what);
3947 evhttp_set_gencb(struct evhttp *http,
3948 void (*cb)(struct evhttp_request *, void *), void *cbarg)
3951 http->gencbarg = cbarg;
3955 evhttp_set_bevcb(struct evhttp *http,
3956 struct bufferevent* (*cb)(struct event_base *, void *), void *cbarg)
3959 http->bevcbarg = cbarg;
3963 evhttp_set_newreqcb(struct evhttp *http,
3964 int (*cb)(struct evhttp_request *, void *), void *cbarg)
3966 http->newreqcb = cb;
3967 http->newreqcbarg = cbarg;
3971 * Request related functions
3974 struct evhttp_request *
3975 evhttp_request_new(void (*cb)(struct evhttp_request *, void *), void *arg)
3977 struct evhttp_request *req = NULL;
3979 /* Allocate request structure */
3980 if ((req = mm_calloc(1, sizeof(struct evhttp_request))) == NULL) {
3981 event_warn("%s: calloc", __func__);
3985 req->headers_size = 0;
3988 req->kind = EVHTTP_RESPONSE;
3989 req->input_headers = mm_calloc(1, sizeof(struct evkeyvalq));
3990 if (req->input_headers == NULL) {
3991 event_warn("%s: calloc", __func__);
3994 TAILQ_INIT(req->input_headers);
3996 req->output_headers = mm_calloc(1, sizeof(struct evkeyvalq));
3997 if (req->output_headers == NULL) {
3998 event_warn("%s: calloc", __func__);
4001 TAILQ_INIT(req->output_headers);
4003 if ((req->input_buffer = evbuffer_new()) == NULL) {
4004 event_warn("%s: evbuffer_new", __func__);
4008 if ((req->output_buffer = evbuffer_new()) == NULL) {
4009 event_warn("%s: evbuffer_new", __func__);
4020 evhttp_request_free(req);
4025 evhttp_request_free(struct evhttp_request *req)
4027 if ((req->flags & EVHTTP_REQ_DEFER_FREE) != 0) {
4028 req->flags |= EVHTTP_REQ_NEEDS_FREE;
4032 if (req->remote_host != NULL)
4033 mm_free(req->remote_host);
4034 if (req->uri != NULL)
4036 if (req->uri_elems != NULL)
4037 evhttp_uri_free(req->uri_elems);
4038 if (req->response_code_line != NULL)
4039 mm_free(req->response_code_line);
4040 if (req->host_cache != NULL)
4041 mm_free(req->host_cache);
4043 evhttp_clear_headers(req->input_headers);
4044 mm_free(req->input_headers);
4046 evhttp_clear_headers(req->output_headers);
4047 mm_free(req->output_headers);
4049 if (req->input_buffer != NULL)
4050 evbuffer_free(req->input_buffer);
4052 if (req->output_buffer != NULL)
4053 evbuffer_free(req->output_buffer);
4059 evhttp_request_own(struct evhttp_request *req)
4061 req->flags |= EVHTTP_USER_OWNED;
4065 evhttp_request_is_owned(struct evhttp_request *req)
4067 return (req->flags & EVHTTP_USER_OWNED) != 0;
4070 struct evhttp_connection *
4071 evhttp_request_get_connection(struct evhttp_request *req)
4077 evhttp_connection_get_base(struct evhttp_connection *conn)
4083 evhttp_request_set_chunked_cb(struct evhttp_request *req,
4084 void (*cb)(struct evhttp_request *, void *))
4090 evhttp_request_set_header_cb(struct evhttp_request *req,
4091 int (*cb)(struct evhttp_request *, void *))
4093 req->header_cb = cb;
4097 evhttp_request_set_error_cb(struct evhttp_request *req,
4098 void (*cb)(enum evhttp_request_error, void *))
4104 evhttp_request_set_on_complete_cb(struct evhttp_request *req,
4105 void (*cb)(struct evhttp_request *, void *), void *cb_arg)
4107 req->on_complete_cb = cb;
4108 req->on_complete_cb_arg = cb_arg;
4112 * Allows for inspection of the request URI
4116 evhttp_request_get_uri(const struct evhttp_request *req) {
4117 if (req->uri == NULL)
4118 event_debug(("%s: request %p has no uri\n", __func__, req));
4122 const struct evhttp_uri *
4123 evhttp_request_get_evhttp_uri(const struct evhttp_request *req) {
4124 if (req->uri_elems == NULL)
4125 event_debug(("%s: request %p has no uri elems\n",
4127 return (req->uri_elems);
4131 evhttp_request_get_host(struct evhttp_request *req)
4133 const char *host = NULL;
4135 if (req->host_cache)
4136 return req->host_cache;
4139 host = evhttp_uri_get_host(req->uri_elems);
4140 if (!host && req->input_headers) {
4144 host = evhttp_find_header(req->input_headers, "Host");
4145 /* The Host: header may include a port. Remove it here
4146 to be consistent with uri_elems case above. */
4148 p = host + strlen(host) - 1;
4149 while (p > host && EVUTIL_ISDIGIT_(*p))
4151 if (p > host && *p == ':') {
4153 req->host_cache = mm_malloc(len + 1);
4154 if (!req->host_cache) {
4155 event_warn("%s: malloc", __func__);
4158 memcpy(req->host_cache, host, len);
4159 req->host_cache[len] = '\0';
4160 host = req->host_cache;
4168 enum evhttp_cmd_type
4169 evhttp_request_get_command(const struct evhttp_request *req) {
4174 evhttp_request_get_response_code(const struct evhttp_request *req)
4176 return req->response_code;
4180 evhttp_request_get_response_code_line(const struct evhttp_request *req)
4182 return req->response_code_line;
4185 /** Returns the input headers */
4186 struct evkeyvalq *evhttp_request_get_input_headers(struct evhttp_request *req)
4188 return (req->input_headers);
4191 /** Returns the output headers */
4192 struct evkeyvalq *evhttp_request_get_output_headers(struct evhttp_request *req)
4194 return (req->output_headers);
4197 /** Returns the input buffer */
4198 struct evbuffer *evhttp_request_get_input_buffer(struct evhttp_request *req)
4200 return (req->input_buffer);
4203 /** Returns the output buffer */
4204 struct evbuffer *evhttp_request_get_output_buffer(struct evhttp_request *req)
4206 return (req->output_buffer);
4211 * Takes a file descriptor to read a request from.
4212 * The callback is executed once the whole request has been read.
4215 static struct evhttp_connection*
4216 evhttp_get_request_connection(
4217 struct evhttp* http,
4218 evutil_socket_t fd, struct sockaddr *sa, ev_socklen_t salen)
4220 struct evhttp_connection *evcon;
4221 char *hostname = NULL, *portname = NULL;
4222 struct bufferevent* bev = NULL;
4224 name_from_addr(sa, salen, &hostname, &portname);
4225 if (hostname == NULL || portname == NULL) {
4226 if (hostname) mm_free(hostname);
4227 if (portname) mm_free(portname);
4231 event_debug(("%s: new request from %s:%s on "EV_SOCK_FMT"\n",
4232 __func__, hostname, portname, EV_SOCK_ARG(fd)));
4234 /* we need a connection object to put the http request on */
4235 if (http->bevcb != NULL) {
4236 bev = (*http->bevcb)(http->base, http->bevcbarg);
4238 evcon = evhttp_connection_base_bufferevent_new(
4239 http->base, NULL, bev, hostname, atoi(portname));
4245 evcon->max_headers_size = http->default_max_headers_size;
4246 evcon->max_body_size = http->default_max_body_size;
4247 if (http->flags & EVHTTP_SERVER_LINGERING_CLOSE)
4248 evcon->flags |= EVHTTP_CON_LINGERING_CLOSE;
4250 evcon->flags |= EVHTTP_CON_INCOMING;
4251 evcon->state = EVCON_READING_FIRSTLINE;
4255 if (bufferevent_setfd(evcon->bufev, fd))
4257 if (bufferevent_enable(evcon->bufev, EV_READ))
4259 if (bufferevent_disable(evcon->bufev, EV_WRITE))
4261 bufferevent_socket_set_conn_address_(evcon->bufev, sa, salen);
4266 evhttp_connection_free(evcon);
4271 evhttp_associate_new_request_with_connection(struct evhttp_connection *evcon)
4273 struct evhttp *http = evcon->http_server;
4274 struct evhttp_request *req;
4275 if ((req = evhttp_request_new(evhttp_handle_request, http)) == NULL)
4278 if ((req->remote_host = mm_strdup(evcon->address)) == NULL) {
4279 event_warn("%s: strdup", __func__);
4280 evhttp_request_free(req);
4283 req->remote_port = evcon->port;
4285 req->evcon = evcon; /* the request ends up owning the connection */
4286 req->flags |= EVHTTP_REQ_OWN_CONNECTION;
4288 /* We did not present the request to the user yet, so treat it
4289 * as if the user was done with the request. This allows us
4290 * to free the request on a persistent connection if the
4291 * client drops it without sending a request.
4294 req->kind = EVHTTP_REQUEST;
4296 if (http->newreqcb && http->newreqcb(req, http->newreqcbarg) == -1) {
4297 evhttp_request_free(req);
4301 TAILQ_INSERT_TAIL(&evcon->requests, req, next);
4303 evhttp_start_read_(evcon);
4309 evhttp_get_request(struct evhttp *http, evutil_socket_t fd,
4310 struct sockaddr *sa, ev_socklen_t salen)
4312 struct evhttp_connection *evcon;
4314 evcon = evhttp_get_request_connection(http, fd, sa, salen);
4315 if (evcon == NULL) {
4316 event_sock_warn(fd, "%s: cannot get connection on "EV_SOCK_FMT,
4317 __func__, EV_SOCK_ARG(fd));
4318 evutil_closesocket(fd);
4322 /* the timeout can be used by the server to close idle connections */
4323 if (evutil_timerisset(&http->timeout))
4324 evhttp_connection_set_timeout_tv(evcon, &http->timeout);
4327 * if we want to accept more than one request on a connection,
4328 * we need to know which http server it belongs to.
4330 evcon->http_server = http;
4331 TAILQ_INSERT_TAIL(&http->connections, evcon, next);
4333 if (evhttp_associate_new_request_with_connection(evcon) == -1)
4334 evhttp_connection_free(evcon);
4339 * Network helper functions that we do not want to export to the rest of
4344 name_from_addr(struct sockaddr *sa, ev_socklen_t salen,
4345 char **phost, char **pport)
4347 char ntop[NI_MAXHOST];
4348 char strport[NI_MAXSERV];
4351 #ifdef EVENT__HAVE_GETNAMEINFO
4352 ni_result = getnameinfo(sa, salen,
4353 ntop, sizeof(ntop), strport, sizeof(strport),
4354 NI_NUMERICHOST|NI_NUMERICSERV);
4356 if (ni_result != 0) {
4358 /* Windows doesn't have an EAI_SYSTEM. */
4359 if (ni_result == EAI_SYSTEM)
4360 event_err(1, "getnameinfo failed");
4363 event_errx(1, "getnameinfo failed: %s", gai_strerror(ni_result));
4367 ni_result = fake_getnameinfo(sa, salen,
4368 ntop, sizeof(ntop), strport, sizeof(strport),
4369 NI_NUMERICHOST|NI_NUMERICSERV);
4374 *phost = mm_strdup(ntop);
4375 *pport = mm_strdup(strport);
4378 /* Create a non-blocking socket and bind it */
4379 /* todo: rename this function */
4380 static evutil_socket_t
4381 bind_socket_ai(struct evutil_addrinfo *ai, int reuse)
4388 /* Create listen socket */
4389 fd = evutil_socket_(ai ? ai->ai_family : AF_INET,
4390 SOCK_STREAM|EVUTIL_SOCK_NONBLOCK|EVUTIL_SOCK_CLOEXEC, 0);
4392 event_sock_warn(-1, "socket");
4396 if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (void *)&on, sizeof(on))<0)
4399 if (evutil_make_listen_socket_reuseable(fd) < 0)
4404 r = bind(fd, ai->ai_addr, (ev_socklen_t)ai->ai_addrlen);
4412 serrno = EVUTIL_SOCKET_ERROR();
4413 evutil_closesocket(fd);
4414 EVUTIL_SET_SOCKET_ERROR(serrno);
4418 static struct evutil_addrinfo *
4419 make_addrinfo(const char *address, ev_uint16_t port)
4421 struct evutil_addrinfo *ai = NULL;
4423 struct evutil_addrinfo hints;
4424 char strport[NI_MAXSERV];
4427 memset(&hints, 0, sizeof(hints));
4428 hints.ai_family = AF_UNSPEC;
4429 hints.ai_socktype = SOCK_STREAM;
4430 /* turn NULL hostname into INADDR_ANY, and skip looking up any address
4431 * types we don't have an interface to connect to. */
4432 hints.ai_flags = EVUTIL_AI_PASSIVE|EVUTIL_AI_ADDRCONFIG;
4433 evutil_snprintf(strport, sizeof(strport), "%d", port);
4434 if ((ai_result = evutil_getaddrinfo(address, strport, &hints, &ai))
4436 if (ai_result == EVUTIL_EAI_SYSTEM)
4437 event_warn("getaddrinfo");
4439 event_warnx("getaddrinfo: %s",
4440 evutil_gai_strerror(ai_result));
4447 static evutil_socket_t
4448 bind_socket(const char *address, ev_uint16_t port, int reuse)
4451 struct evutil_addrinfo *aitop = NULL;
4453 /* just create an unbound socket */
4454 if (address == NULL && port == 0)
4455 return bind_socket_ai(NULL, 0);
4457 aitop = make_addrinfo(address, port);
4462 fd = bind_socket_ai(aitop, reuse);
4464 evutil_freeaddrinfo(aitop);
4471 char *scheme; /* scheme; e.g http, ftp etc */
4472 char *userinfo; /* userinfo (typically username:pass), or NULL */
4473 char *host; /* hostname, IP address, or NULL */
4474 int port; /* port, or zero */
4475 char *path; /* path, or "". */
4476 char *query; /* query, or NULL */
4477 char *fragment; /* fragment or NULL */
4481 evhttp_uri_new(void)
4483 struct evhttp_uri *uri = mm_calloc(sizeof(struct evhttp_uri), 1);
4490 evhttp_uri_set_flags(struct evhttp_uri *uri, unsigned flags)
4495 /* Return true if the string starting at s and ending immediately before eos
4496 * is a valid URI scheme according to RFC3986
4499 scheme_ok(const char *s, const char *eos)
4501 /* scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." ) */
4502 EVUTIL_ASSERT(eos >= s);
4505 if (!EVUTIL_ISALPHA_(*s))
4508 if (! EVUTIL_ISALNUM_(*s) &&
4509 *s != '+' && *s != '-' && *s != '.')
4515 #define SUBDELIMS "!$&'()*+,;="
4517 /* Return true iff [s..eos) is a valid userinfo */
4519 userinfo_ok(const char *s, const char *eos)
4522 if (CHAR_IS_UNRESERVED(*s) ||
4523 strchr(SUBDELIMS, *s) ||
4526 else if (*s == '%' && s+2 < eos &&
4527 EVUTIL_ISXDIGIT_(s[1]) &&
4528 EVUTIL_ISXDIGIT_(s[2]))
4537 regname_ok(const char *s, const char *eos)
4539 while (s && s<eos) {
4540 if (CHAR_IS_UNRESERVED(*s) ||
4541 strchr(SUBDELIMS, *s))
4543 else if (*s == '%' &&
4544 EVUTIL_ISXDIGIT_(s[1]) &&
4545 EVUTIL_ISXDIGIT_(s[2]))
4554 parse_port(const char *s, const char *eos)
4558 if (! EVUTIL_ISDIGIT_(*s))
4560 portnum = (portnum * 10) + (*s - '0');
4563 if (portnum > 65535)
4570 /* returns 0 for bad, 1 for ipv6, 2 for IPvFuture */
4572 bracket_addr_ok(const char *s, const char *eos)
4574 if (s + 3 > eos || *s != '[' || *(eos-1) != ']')
4577 /* IPvFuture, or junk.
4578 "v" 1*HEXDIG "." 1*( unreserved / sub-delims / ":" )
4580 s += 2; /* skip [v */
4582 if (!EVUTIL_ISXDIGIT_(*s)) /*require at least one*/
4584 while (s < eos && *s != '.') {
4585 if (EVUTIL_ISXDIGIT_(*s))
4594 if (CHAR_IS_UNRESERVED(*s) ||
4595 strchr(SUBDELIMS, *s) ||
4605 ev_ssize_t n_chars = eos-s-2;
4606 struct in6_addr in6;
4607 if (n_chars >= 64) /* way too long */
4609 memcpy(buf, s+1, n_chars);
4611 return (evutil_inet_pton(AF_INET6,buf,&in6)==1) ? 1 : 0;
4616 parse_authority(struct evhttp_uri *uri, char *s, char *eos)
4621 uri->host = mm_strdup("");
4622 if (uri->host == NULL) {
4623 event_warn("%s: strdup", __func__);
4629 /* Optionally, we start with "userinfo@" */
4631 cp = strchr(s, '@');
4632 if (cp && cp < eos) {
4633 if (! userinfo_ok(s,cp))
4636 uri->userinfo = mm_strdup(s);
4637 if (uri->userinfo == NULL) {
4638 event_warn("%s: strdup", __func__);
4644 /* Optionally, we end with ":port" */
4645 for (port=eos-1; port >= cp && EVUTIL_ISDIGIT_(*port); --port)
4647 if (port >= cp && *port == ':') {
4648 if (port+1 == eos) /* Leave port unspecified; the RFC allows a
4651 else if ((uri->port = parse_port(port+1, eos))<0)
4655 /* Now, cp..eos holds the "host" port, which can be an IPv4Address,
4656 * an IP-Literal, or a reg-name */
4657 EVUTIL_ASSERT(eos >= cp);
4658 if (*cp == '[' && eos >= cp+2 && *(eos-1) == ']') {
4659 /* IPv6address, IP-Literal, or junk. */
4660 if (! bracket_addr_ok(cp, eos))
4663 /* Make sure the host part is ok. */
4664 if (! regname_ok(cp,eos)) /* Match IPv4Address or reg-name */
4667 uri->host = mm_malloc(eos-cp+1);
4668 if (uri->host == NULL) {
4669 event_warn("%s: malloc", __func__);
4672 memcpy(uri->host, cp, eos-cp);
4673 uri->host[eos-cp] = '\0';
4679 end_of_authority(char *cp)
4682 if (*cp == '?' || *cp == '#' || *cp == '/')
4695 /* Return the character after the longest prefix of 'cp' that matches...
4696 * *pchar / "/" if allow_qchars is false, or
4697 * *(pchar / "/" / "?") if allow_qchars is true.
4700 end_of_path(char *cp, enum uri_part part, unsigned flags)
4702 if (flags & EVHTTP_URI_NONCONFORMANT) {
4703 /* If NONCONFORMANT:
4704 * Path is everything up to a # or ? or nul.
4705 * Query is everything up a # or nul
4706 * Fragment is everything up to a nul.
4710 while (*cp && *cp != '#' && *cp != '?')
4714 while (*cp && *cp != '#')
4725 if (CHAR_IS_UNRESERVED(*cp) ||
4726 strchr(SUBDELIMS, *cp) ||
4727 *cp == ':' || *cp == '@' || *cp == '/')
4729 else if (*cp == '%' && EVUTIL_ISXDIGIT_(cp[1]) &&
4730 EVUTIL_ISXDIGIT_(cp[2]))
4732 else if (*cp == '?' && part != PART_PATH)
4741 path_matches_noscheme(const char *cp)
4746 else if (*cp == '/')
4754 evhttp_uri_parse(const char *source_uri)
4756 return evhttp_uri_parse_with_flags(source_uri, 0);
4760 evhttp_uri_parse_with_flags(const char *source_uri, unsigned flags)
4762 char *readbuf = NULL, *readp = NULL, *token = NULL, *query = NULL;
4763 char *path = NULL, *fragment = NULL;
4764 int got_authority = 0;
4766 struct evhttp_uri *uri = mm_calloc(1, sizeof(struct evhttp_uri));
4768 event_warn("%s: calloc", __func__);
4774 readbuf = mm_strdup(source_uri);
4775 if (readbuf == NULL) {
4776 event_warn("%s: strdup", __func__);
4783 /* We try to follow RFC3986 here as much as we can, and match
4786 URI = scheme ":" hier-part [ "?" query ] [ "#" fragment ]
4788 relative-ref = relative-part [ "?" query ] [ "#" fragment ]
4792 token = strchr(readp, ':');
4793 if (token && scheme_ok(readp,token)) {
4795 uri->scheme = mm_strdup(readp);
4796 if (uri->scheme == NULL) {
4797 event_warn("%s: strdup", __func__);
4800 readp = token+1; /* eat : */
4803 /* 2. Optionally, "//" then an 'authority' part. */
4804 if (readp[0]=='/' && readp[1] == '/') {
4808 path = end_of_authority(readp);
4809 if (parse_authority(uri, authority, path) < 0)
4815 /* 3. Query: path-abempty, path-absolute, path-rootless, or path-empty
4818 readp = end_of_path(path, PART_PATH, flags);
4821 if (*readp == '?') {
4825 readp = end_of_path(readp, PART_QUERY, flags);
4828 if (*readp == '#') {
4832 readp = end_of_path(readp, PART_FRAGMENT, flags);
4834 if (*readp != '\0') {
4838 /* These next two cases may be unreachable; I'm leaving them
4839 * in to be defensive. */
4840 /* If you didn't get an authority, the path can't begin with "//" */
4841 if (!got_authority && path[0]=='/' && path[1]=='/')
4843 /* If you did get an authority, the path must begin with "/" or be
4845 if (got_authority && path[0] != '/' && path[0] != '\0')
4847 /* (End of maybe-unreachable cases) */
4849 /* If there was no scheme, the first part of the path (if any) must
4850 * have no colon in it. */
4851 if (! uri->scheme && !path_matches_noscheme(path))
4854 EVUTIL_ASSERT(path);
4855 uri->path = mm_strdup(path);
4856 if (uri->path == NULL) {
4857 event_warn("%s: strdup", __func__);
4862 uri->query = mm_strdup(query);
4863 if (uri->query == NULL) {
4864 event_warn("%s: strdup", __func__);
4869 uri->fragment = mm_strdup(fragment);
4870 if (uri->fragment == NULL) {
4871 event_warn("%s: strdup", __func__);
4881 evhttp_uri_free(uri);
4887 static struct evhttp_uri *
4888 evhttp_uri_parse_authority(char *source_uri)
4890 struct evhttp_uri *uri = mm_calloc(1, sizeof(struct evhttp_uri));
4894 event_warn("%s: calloc", __func__);
4900 end = end_of_authority(source_uri);
4901 if (parse_authority(uri, source_uri, end) < 0)
4904 uri->path = mm_strdup("");
4905 if (uri->path == NULL) {
4906 event_warn("%s: strdup", __func__);
4913 evhttp_uri_free(uri);
4918 evhttp_uri_free(struct evhttp_uri *uri)
4920 #define URI_FREE_STR_(f) \
4925 URI_FREE_STR_(scheme);
4926 URI_FREE_STR_(userinfo);
4927 URI_FREE_STR_(host);
4928 URI_FREE_STR_(path);
4929 URI_FREE_STR_(query);
4930 URI_FREE_STR_(fragment);
4933 #undef URI_FREE_STR_
4937 evhttp_uri_join(struct evhttp_uri *uri, char *buf, size_t limit)
4939 struct evbuffer *tmp = 0;
4940 size_t joined_size = 0;
4941 char *output = NULL;
4943 #define URI_ADD_(f) evbuffer_add(tmp, uri->f, strlen(uri->f))
4945 if (!uri || !buf || !limit)
4948 tmp = evbuffer_new();
4954 evbuffer_add(tmp, ":", 1);
4957 evbuffer_add(tmp, "//", 2);
4959 evbuffer_add_printf(tmp,"%s@", uri->userinfo);
4962 evbuffer_add_printf(tmp,":%d", uri->port);
4964 if (uri->path && uri->path[0] != '/' && uri->path[0] != '\0')
4972 evbuffer_add(tmp, "?", 1);
4976 if (uri->fragment) {
4977 evbuffer_add(tmp, "#", 1);
4981 evbuffer_add(tmp, "\0", 1); /* NUL */
4983 joined_size = evbuffer_get_length(tmp);
4985 if (joined_size > limit) {
4986 /* It doesn't fit. */
4990 evbuffer_remove(tmp, buf, joined_size);
5001 evhttp_uri_get_scheme(const struct evhttp_uri *uri)
5006 evhttp_uri_get_userinfo(const struct evhttp_uri *uri)
5008 return uri->userinfo;
5011 evhttp_uri_get_host(const struct evhttp_uri *uri)
5016 evhttp_uri_get_port(const struct evhttp_uri *uri)
5021 evhttp_uri_get_path(const struct evhttp_uri *uri)
5026 evhttp_uri_get_query(const struct evhttp_uri *uri)
5031 evhttp_uri_get_fragment(const struct evhttp_uri *uri)
5033 return uri->fragment;
5036 #define URI_SET_STR_(f) do { \
5040 if ((uri->f = mm_strdup(f)) == NULL) { \
5041 event_warn("%s: strdup()", __func__); \
5050 evhttp_uri_set_scheme(struct evhttp_uri *uri, const char *scheme)
5052 if (scheme && !scheme_ok(scheme, scheme+strlen(scheme)))
5055 URI_SET_STR_(scheme);
5059 evhttp_uri_set_userinfo(struct evhttp_uri *uri, const char *userinfo)
5061 if (userinfo && !userinfo_ok(userinfo, userinfo+strlen(userinfo)))
5063 URI_SET_STR_(userinfo);
5067 evhttp_uri_set_host(struct evhttp_uri *uri, const char *host)
5070 if (host[0] == '[') {
5071 if (! bracket_addr_ok(host, host+strlen(host)))
5074 if (! regname_ok(host, host+strlen(host)))
5083 evhttp_uri_set_port(struct evhttp_uri *uri, int port)
5090 #define end_of_cpath(cp,p,f) \
5091 ((const char*)(end_of_path(((char*)(cp)), (p), (f))))
5094 evhttp_uri_set_path(struct evhttp_uri *uri, const char *path)
5096 if (path && end_of_cpath(path, PART_PATH, uri->flags) != path+strlen(path))
5103 evhttp_uri_set_query(struct evhttp_uri *uri, const char *query)
5105 if (query && end_of_cpath(query, PART_QUERY, uri->flags) != query+strlen(query))
5107 URI_SET_STR_(query);
5111 evhttp_uri_set_fragment(struct evhttp_uri *uri, const char *fragment)
5113 if (fragment && end_of_cpath(fragment, PART_FRAGMENT, uri->flags) != fragment+strlen(fragment))
5115 URI_SET_STR_(fragment);