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
84 #ifdef EVENT__HAVE_UNISTD_H
87 #ifdef EVENT__HAVE_FCNTL_H
91 #undef timeout_pending
92 #undef timeout_initialized
94 #include "strlcpy-internal.h"
95 #include "event2/http.h"
96 #include "event2/event.h"
97 #include "event2/buffer.h"
98 #include "event2/bufferevent.h"
99 #include "event2/http_struct.h"
100 #include "event2/http_compat.h"
101 #include "event2/util.h"
102 #include "event2/listener.h"
103 #include "log-internal.h"
104 #include "util-internal.h"
105 #include "http-internal.h"
106 #include "mm-internal.h"
107 #include "bufferevent-internal.h"
109 #ifndef EVENT__HAVE_GETNAMEINFO
110 #define NI_MAXSERV 32
111 #define NI_MAXHOST 1025
113 #ifndef NI_NUMERICHOST
114 #define NI_NUMERICHOST 1
117 #ifndef NI_NUMERICSERV
118 #define NI_NUMERICSERV 2
122 fake_getnameinfo(const struct sockaddr *sa, size_t salen, char *host,
123 size_t hostlen, char *serv, size_t servlen, int flags)
125 struct sockaddr_in *sin = (struct sockaddr_in *)sa;
129 evutil_snprintf(tmpserv, sizeof(tmpserv),
130 "%d", ntohs(sin->sin_port));
131 if (strlcpy(serv, tmpserv, servlen) >= servlen)
136 if (flags & NI_NUMERICHOST) {
137 if (strlcpy(host, inet_ntoa(sin->sin_addr),
144 hp = gethostbyaddr((char *)&sin->sin_addr,
145 sizeof(struct in_addr), AF_INET);
149 if (strlcpy(host, hp->h_name, hostlen) >= hostlen)
160 #define REQ_VERSION_BEFORE(req, major_v, minor_v) \
161 ((req)->major < (major_v) || \
162 ((req)->major == (major_v) && (req)->minor < (minor_v)))
164 #define REQ_VERSION_ATLEAST(req, major_v, minor_v) \
165 ((req)->major > (major_v) || \
166 ((req)->major == (major_v) && (req)->minor >= (minor_v)))
169 #define MIN(a,b) (((a)<(b))?(a):(b))
174 static evutil_socket_t bind_socket_ai(struct evutil_addrinfo *, int reuse);
175 static evutil_socket_t bind_socket(const char *, ev_uint16_t, int reuse);
176 static void name_from_addr(struct sockaddr *, ev_socklen_t, char **, char **);
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 * since we *do* want to learn about any close events.) */
374 bufferevent_setcb(evcon->bufev,
380 bufferevent_enable(evcon->bufev, 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) {
498 time_t t = time(NULL);
505 if (strftime(date, sizeof(date),
506 "%a, %d %b %Y %H:%M:%S GMT", cur_p) != 0) {
507 evhttp_add_header(headers, "Date", date);
512 /* Add a "Content-Length" header with value 'content_length' to headers,
513 * unless it already has a content-length or transfer-encoding header. */
515 evhttp_maybe_add_content_length_header(struct evkeyvalq *headers,
516 size_t content_length)
518 if (evhttp_find_header(headers, "Transfer-Encoding") == NULL &&
519 evhttp_find_header(headers, "Content-Length") == NULL) {
521 evutil_snprintf(len, sizeof(len), EV_SIZE_FMT,
522 EV_SIZE_ARG(content_length));
523 evhttp_add_header(headers, "Content-Length", len);
528 * Create the headers needed for an HTTP reply in req->output_headers,
529 * and write the first HTTP response for req line to evcon.
532 evhttp_make_header_response(struct evhttp_connection *evcon,
533 struct evhttp_request *req)
535 int is_keepalive = evhttp_is_connection_keepalive(req->input_headers);
536 evbuffer_add_printf(bufferevent_get_output(evcon->bufev),
537 "HTTP/%d.%d %d %s\r\n",
538 req->major, req->minor, req->response_code,
539 req->response_code_line);
541 if (req->major == 1) {
543 evhttp_maybe_add_date_header(req->output_headers);
546 * if the protocol is 1.0; and the connection was keep-alive
547 * we need to add a keep-alive header, too.
549 if (req->minor == 0 && is_keepalive)
550 evhttp_add_header(req->output_headers,
551 "Connection", "keep-alive");
553 if ((req->minor >= 1 || is_keepalive) &&
554 evhttp_response_needs_body(req)) {
556 * we need to add the content length if the
557 * user did not give it, this is required for
558 * persistent connections to work.
560 evhttp_maybe_add_content_length_header(
562 evbuffer_get_length(req->output_buffer));
566 /* Potentially add headers for unidentified content. */
567 if (evhttp_response_needs_body(req)) {
568 if (evhttp_find_header(req->output_headers,
569 "Content-Type") == NULL
570 && evcon->http_server->default_content_type) {
571 evhttp_add_header(req->output_headers,
573 evcon->http_server->default_content_type);
577 /* if the request asked for a close, we send a close, too */
578 if (evhttp_is_connection_close(req->flags, req->input_headers)) {
579 evhttp_remove_header(req->output_headers, "Connection");
580 if (!(req->flags & EVHTTP_PROXY_REQUEST))
581 evhttp_add_header(req->output_headers, "Connection", "close");
582 evhttp_remove_header(req->output_headers, "Proxy-Connection");
586 enum expect { NO, CONTINUE, OTHER };
587 static enum expect evhttp_have_expect(struct evhttp_request *req, int input)
590 struct evkeyvalq *h = input ? req->input_headers : req->output_headers;
592 if (!(req->kind == EVHTTP_REQUEST) || !REQ_VERSION_ATLEAST(req, 1, 1))
595 expect = evhttp_find_header(h, "Expect");
599 return !evutil_ascii_strcasecmp(expect, "100-continue") ? CONTINUE : OTHER;
603 /** Generate all headers appropriate for sending the http request in req (or
604 * the response, if we're sending a response), and write them to evcon's
605 * bufferevent. Also writes all data from req->output_buffer */
607 evhttp_make_header(struct evhttp_connection *evcon, struct evhttp_request *req)
609 struct evkeyval *header;
610 struct evbuffer *output = bufferevent_get_output(evcon->bufev);
613 * Depending if this is a HTTP request or response, we might need to
614 * add some new headers or remove existing headers.
616 if (req->kind == EVHTTP_REQUEST) {
617 evhttp_make_header_request(evcon, req);
619 evhttp_make_header_response(evcon, req);
622 TAILQ_FOREACH(header, req->output_headers, next) {
623 evbuffer_add_printf(output, "%s: %s\r\n",
624 header->key, header->value);
626 evbuffer_add(output, "\r\n", 2);
628 if (evhttp_have_expect(req, 0) != CONTINUE &&
629 evbuffer_get_length(req->output_buffer)) {
631 * For a request, we add the POST data, for a reply, this
632 * is the regular data.
634 evbuffer_add_buffer(output, req->output_buffer);
639 evhttp_connection_set_max_headers_size(struct evhttp_connection *evcon,
640 ev_ssize_t new_max_headers_size)
642 if (new_max_headers_size<0)
643 evcon->max_headers_size = EV_SIZE_MAX;
645 evcon->max_headers_size = new_max_headers_size;
648 evhttp_connection_set_max_body_size(struct evhttp_connection* evcon,
649 ev_ssize_t new_max_body_size)
651 if (new_max_body_size<0)
652 evcon->max_body_size = EV_UINT64_MAX;
654 evcon->max_body_size = new_max_body_size;
658 evhttp_connection_incoming_fail(struct evhttp_request *req,
659 enum evhttp_request_error error)
662 case EVREQ_HTTP_DATA_TOO_LONG:
663 req->response_code = HTTP_ENTITYTOOLARGE;
666 req->response_code = HTTP_BADREQUEST;
670 case EVREQ_HTTP_TIMEOUT:
673 * these are cases in which we probably should just
674 * close the connection and not send a reply. this
675 * case may happen when a browser keeps a persistent
676 * connection open and we timeout on the read. when
677 * the request is still being used for sending, we
678 * need to disassociated it from the connection here.
680 if (!req->userdone) {
681 /* remove it so that it will not be freed */
682 TAILQ_REMOVE(&req->evcon->requests, req, next);
683 /* indicate that this request no longer has a
689 case EVREQ_HTTP_INVALID_HEADER:
690 case EVREQ_HTTP_BUFFER_ERROR:
691 case EVREQ_HTTP_REQUEST_CANCEL:
692 case EVREQ_HTTP_DATA_TOO_LONG:
693 default: /* xxx: probably should just error on default */
694 /* the callback looks at the uri to determine errors */
699 if (req->uri_elems) {
700 evhttp_uri_free(req->uri_elems);
701 req->uri_elems = NULL;
705 * the callback needs to send a reply, once the reply has
706 * been send, the connection should get freed.
708 (*req->cb)(req, req->cb_arg);
714 /* Free connection ownership of which can be acquired by user using
715 * evhttp_request_own(). */
717 evhttp_request_free_auto(struct evhttp_request *req)
719 if (!(req->flags & EVHTTP_USER_OWNED))
720 evhttp_request_free(req);
724 evhttp_request_free_(struct evhttp_connection *evcon, struct evhttp_request *req)
726 TAILQ_REMOVE(&evcon->requests, req, next);
727 evhttp_request_free_auto(req);
730 /* Called when evcon has experienced a (non-recoverable? -NM) error, as
731 * given in error. If it's an outgoing connection, reset the connection,
732 * retry any pending requests, and inform the user. If it's incoming,
733 * delegates to evhttp_connection_incoming_fail(). */
735 evhttp_connection_fail_(struct evhttp_connection *evcon,
736 enum evhttp_request_error error)
738 const int errsave = EVUTIL_SOCKET_ERROR();
739 struct evhttp_request* req = TAILQ_FIRST(&evcon->requests);
740 void (*cb)(struct evhttp_request *, void *);
742 void (*error_cb)(enum evhttp_request_error, void *);
744 EVUTIL_ASSERT(req != NULL);
746 bufferevent_disable(evcon->bufev, EV_READ|EV_WRITE);
748 if (evcon->flags & EVHTTP_CON_INCOMING) {
750 * for incoming requests, there are two different
751 * failure cases. it's either a network level error
752 * or an http layer error. for problems on the network
753 * layer like timeouts we just drop the connections.
754 * For HTTP problems, we might have to send back a
755 * reply before the connection can be freed.
757 if (evhttp_connection_incoming_fail(req, error) == -1)
758 evhttp_connection_free(evcon);
762 error_cb = req->error_cb;
763 error_cb_arg = req->cb_arg;
764 /* when the request was canceled, the callback is not executed */
765 if (error != EVREQ_HTTP_REQUEST_CANCEL) {
766 /* save the callback for later; the cb might free our object */
768 cb_arg = req->cb_arg;
774 /* do not fail all requests; the next request is going to get
775 * send over a new connection. when a user cancels a request,
776 * all other pending requests should be processed as normal
778 evhttp_request_free_(evcon, req);
780 /* reset the connection */
781 evhttp_connection_reset_(evcon);
783 /* We are trying the next request that was queued on us */
784 if (TAILQ_FIRST(&evcon->requests) != NULL)
785 evhttp_connection_connect_(evcon);
787 /* The call to evhttp_connection_reset_ overwrote errno.
788 * Let's restore the original errno, so that the user's
789 * callback can have a better idea of what the error was.
791 EVUTIL_SET_SOCKET_ERROR(errsave);
793 /* inform the user */
794 if (error_cb != NULL)
795 error_cb(error, error_cb_arg);
800 /* Bufferevent callback: invoked when any data has been written from an
801 * http connection's bufferevent */
803 evhttp_write_cb(struct bufferevent *bufev, void *arg)
805 struct evhttp_connection *evcon = arg;
807 /* Activate our call back */
808 if (evcon->cb != NULL)
809 (*evcon->cb)(evcon, evcon->cb_arg);
813 * Advance the connection state.
814 * - If this is an outgoing connection, we've just processed the response;
815 * idle or close the connection.
816 * - If this is an incoming connection, we've just processed the request;
820 evhttp_connection_done(struct evhttp_connection *evcon)
822 struct evhttp_request *req = TAILQ_FIRST(&evcon->requests);
823 int con_outgoing = evcon->flags & EVHTTP_CON_OUTGOING;
827 /* idle or close the connection */
828 int need_close = evhttp_is_request_connection_close(req);
829 TAILQ_REMOVE(&evcon->requests, req, next);
832 evcon->state = EVCON_IDLE;
834 /* check if we got asked to close the connection */
836 evhttp_connection_reset_(evcon);
838 if (TAILQ_FIRST(&evcon->requests) != NULL) {
840 * We have more requests; reset the connection
841 * and deal with the next request.
843 if (!evhttp_connected(evcon))
844 evhttp_connection_connect_(evcon);
846 evhttp_request_dispatch(evcon);
847 } else if (!need_close) {
849 * The connection is going to be persistent, but we
850 * need to detect if the other side closes it.
852 evhttp_connection_start_detectclose(evcon);
853 } else if ((evcon->flags & EVHTTP_CON_AUTOFREE)) {
855 * If we have no more requests that need completion
856 * and we're not waiting for the connection to close
862 * incoming connection - we need to leave the request on the
863 * connection so that we can reply to it.
865 evcon->state = EVCON_WRITING;
868 /* notify the user of the request */
869 (*req->cb)(req, req->cb_arg);
871 /* if this was an outgoing request, we own and it's done. so free it. */
873 evhttp_request_free_auto(req);
876 /* If this was the last request of an outgoing connection and we're
877 * not waiting to receive a connection close event and we want to
878 * automatically free the connection. We check to ensure our request
879 * list is empty one last time just in case our callback added a
882 if (free_evcon && TAILQ_FIRST(&evcon->requests) == NULL) {
883 evhttp_connection_free(evcon);
888 * Handles reading from a chunked request.
889 * return ALL_DATA_READ:
890 * all data has been read
891 * return MORE_DATA_EXPECTED:
892 * more data is expected
893 * return DATA_CORRUPTED:
895 * return REQUEST_CANCELED:
896 * request was canceled by the user calling evhttp_cancel_request
897 * return DATA_TOO_LONG:
898 * ran over the maximum limit
901 static enum message_read_status
902 evhttp_handle_chunked_read(struct evhttp_request *req, struct evbuffer *buf)
904 if (req == NULL || buf == NULL) {
905 return DATA_CORRUPTED;
911 if ((buflen = evbuffer_get_length(buf)) == 0) {
915 /* evbuffer_get_length returns size_t, but len variable is ssize_t,
916 * check for overflow conditions */
917 if (buflen > EV_SSIZE_MAX) {
918 return DATA_CORRUPTED;
921 if (req->ntoread < 0) {
922 /* Read chunk size */
924 char *p = evbuffer_readln(buf, NULL, EVBUFFER_EOL_CRLF);
929 /* the last chunk is on a new line? */
930 if (strlen(p) == 0) {
934 ntoread = evutil_strtoll(p, &endp, 16);
935 error = (*p == '\0' ||
936 (*endp != '\0' && *endp != ' ') ||
940 /* could not get chunk size */
941 return (DATA_CORRUPTED);
944 /* ntoread is signed int64, body_size is unsigned size_t, check for under/overflow conditions */
945 if ((ev_uint64_t)ntoread > EV_SIZE_MAX - req->body_size) {
946 return DATA_CORRUPTED;
949 if (req->body_size + (size_t)ntoread > req->evcon->max_body_size) {
950 /* failed body length test */
951 event_debug(("Request body is too long"));
952 return (DATA_TOO_LONG);
955 req->body_size += (size_t)ntoread;
956 req->ntoread = ntoread;
957 if (req->ntoread == 0) {
959 return (ALL_DATA_READ);
964 /* req->ntoread is signed int64, len is ssize_t, based on arch,
965 * ssize_t could only be 32b, check for these conditions */
966 if (req->ntoread > EV_SSIZE_MAX) {
967 return DATA_CORRUPTED;
970 /* don't have enough to complete a chunk; wait for more */
971 if (req->ntoread > 0 && buflen < (ev_uint64_t)req->ntoread)
972 return (MORE_DATA_EXPECTED);
974 /* Completed chunk */
975 evbuffer_remove_buffer(buf, req->input_buffer, (size_t)req->ntoread);
977 if (req->chunk_cb != NULL) {
978 req->flags |= EVHTTP_REQ_DEFER_FREE;
979 (*req->chunk_cb)(req, req->cb_arg);
980 evbuffer_drain(req->input_buffer,
981 evbuffer_get_length(req->input_buffer));
982 req->flags &= ~EVHTTP_REQ_DEFER_FREE;
983 if ((req->flags & EVHTTP_REQ_NEEDS_FREE) != 0) {
984 return (REQUEST_CANCELED);
989 return (MORE_DATA_EXPECTED);
993 evhttp_read_trailer(struct evhttp_connection *evcon, struct evhttp_request *req)
995 struct evbuffer *buf = bufferevent_get_input(evcon->bufev);
997 switch (evhttp_parse_headers_(req, buf)) {
1000 evhttp_connection_fail_(evcon, EVREQ_HTTP_DATA_TOO_LONG);
1003 bufferevent_disable(evcon->bufev, EV_READ);
1004 evhttp_connection_done(evcon);
1006 case MORE_DATA_EXPECTED:
1007 case REQUEST_CANCELED: /* ??? */
1014 evhttp_lingering_close(struct evhttp_connection *evcon,
1015 struct evhttp_request *req)
1017 struct evbuffer *buf = bufferevent_get_input(evcon->bufev);
1019 size_t n = evbuffer_get_length(buf);
1020 if (n > (size_t) req->ntoread)
1021 n = (size_t) req->ntoread;
1023 req->body_size += n;
1025 event_debug(("Request body is too long, left " EV_SIZE_FMT,
1026 EV_SIZE_ARG(req->ntoread)));
1028 evbuffer_drain(buf, n);
1030 evhttp_connection_fail_(evcon, EVREQ_HTTP_DATA_TOO_LONG);
1033 evhttp_lingering_fail(struct evhttp_connection *evcon,
1034 struct evhttp_request *req)
1036 if (evcon->flags & EVHTTP_CON_LINGERING_CLOSE)
1037 evhttp_lingering_close(evcon, req);
1039 evhttp_connection_fail_(evcon, EVREQ_HTTP_DATA_TOO_LONG);
1043 evhttp_read_body(struct evhttp_connection *evcon, struct evhttp_request *req)
1045 struct evbuffer *buf = bufferevent_get_input(evcon->bufev);
1048 switch (evhttp_handle_chunked_read(req, buf)) {
1050 /* finished last chunk */
1051 evcon->state = EVCON_READING_TRAILER;
1052 evhttp_read_trailer(evcon, req);
1054 case DATA_CORRUPTED:
1056 /* corrupted data */
1057 evhttp_connection_fail_(evcon,
1058 EVREQ_HTTP_DATA_TOO_LONG);
1060 case REQUEST_CANCELED:
1061 /* request canceled */
1062 evhttp_request_free_auto(req);
1064 case MORE_DATA_EXPECTED:
1068 } else if (req->ntoread < 0) {
1069 /* Read until connection close. */
1070 if ((size_t)(req->body_size + evbuffer_get_length(buf)) < req->body_size) {
1071 evhttp_connection_fail_(evcon, EVREQ_HTTP_INVALID_HEADER);
1075 req->body_size += evbuffer_get_length(buf);
1076 evbuffer_add_buffer(req->input_buffer, buf);
1077 } else if (req->chunk_cb != NULL || evbuffer_get_length(buf) >= (size_t)req->ntoread) {
1078 /* XXX: the above get_length comparison has to be fixed for overflow conditions! */
1079 /* We've postponed moving the data until now, but we're
1080 * about to use it. */
1081 size_t n = evbuffer_get_length(buf);
1083 if (n > (size_t) req->ntoread)
1084 n = (size_t) req->ntoread;
1086 req->body_size += n;
1087 evbuffer_remove_buffer(buf, req->input_buffer, n);
1090 if (req->body_size > req->evcon->max_body_size ||
1091 (!req->chunked && req->ntoread >= 0 &&
1092 (size_t)req->ntoread > req->evcon->max_body_size)) {
1093 /* XXX: The above casted comparison must checked for overflow */
1094 /* failed body length test */
1096 evhttp_lingering_fail(evcon, req);
1100 if (evbuffer_get_length(req->input_buffer) > 0 && req->chunk_cb != NULL) {
1101 req->flags |= EVHTTP_REQ_DEFER_FREE;
1102 (*req->chunk_cb)(req, req->cb_arg);
1103 req->flags &= ~EVHTTP_REQ_DEFER_FREE;
1104 evbuffer_drain(req->input_buffer,
1105 evbuffer_get_length(req->input_buffer));
1106 if ((req->flags & EVHTTP_REQ_NEEDS_FREE) != 0) {
1107 evhttp_request_free_auto(req);
1112 if (!req->ntoread) {
1113 bufferevent_disable(evcon->bufev, EV_READ);
1114 /* Completed content length */
1115 evhttp_connection_done(evcon);
1120 #define get_deferred_queue(evcon) \
1124 * Gets called when more data becomes available
1128 evhttp_read_cb(struct bufferevent *bufev, void *arg)
1130 struct evhttp_connection *evcon = arg;
1131 struct evhttp_request *req = TAILQ_FIRST(&evcon->requests);
1133 /* Cancel if it's pending. */
1134 event_deferred_cb_cancel_(get_deferred_queue(evcon),
1135 &evcon->read_more_deferred_cb);
1137 switch (evcon->state) {
1138 case EVCON_READING_FIRSTLINE:
1139 evhttp_read_firstline(evcon, req);
1140 /* note the request may have been freed in
1141 * evhttp_read_body */
1143 case EVCON_READING_HEADERS:
1144 evhttp_read_header(evcon, req);
1145 /* note the request may have been freed in
1146 * evhttp_read_body */
1148 case EVCON_READING_BODY:
1149 evhttp_read_body(evcon, req);
1150 /* note the request may have been freed in
1151 * evhttp_read_body */
1153 case EVCON_READING_TRAILER:
1154 evhttp_read_trailer(evcon, req);
1159 struct evbuffer *input;
1162 input = bufferevent_get_input(evcon->bufev);
1163 total_len = evbuffer_get_length(input);
1164 event_debug(("%s: read "EV_SIZE_FMT
1165 " bytes in EVCON_IDLE state,"
1166 " resetting connection",
1167 __func__, EV_SIZE_ARG(total_len)));
1170 evhttp_connection_reset_(evcon);
1173 case EVCON_DISCONNECTED:
1174 case EVCON_CONNECTING:
1177 event_errx(1, "%s: illegal connection state %d",
1178 __func__, evcon->state);
1183 evhttp_deferred_read_cb(struct event_callback *cb, void *data)
1185 struct evhttp_connection *evcon = data;
1186 evhttp_read_cb(evcon->bufev, evcon);
1190 evhttp_write_connectioncb(struct evhttp_connection *evcon, void *arg)
1192 /* This is after writing the request to the server */
1193 struct evhttp_request *req = TAILQ_FIRST(&evcon->requests);
1194 struct evbuffer *output = bufferevent_get_output(evcon->bufev);
1195 EVUTIL_ASSERT(req != NULL);
1197 EVUTIL_ASSERT(evcon->state == EVCON_WRITING);
1199 /* We need to wait until we've written all of our output data before we can
1201 if (evbuffer_get_length(output) > 0)
1204 /* We are done writing our header and are now expecting the response */
1205 req->kind = EVHTTP_RESPONSE;
1207 evhttp_start_read_(evcon);
1211 * Clean up a connection object
1215 evhttp_connection_free(struct evhttp_connection *evcon)
1217 struct evhttp_request *req;
1219 /* notify interested parties that this connection is going down */
1220 if (evcon->fd != -1) {
1221 if (evhttp_connected(evcon) && evcon->closecb != NULL)
1222 (*evcon->closecb)(evcon, evcon->closecb_arg);
1225 /* remove all requests that might be queued on this
1226 * connection. for server connections, this should be empty.
1227 * because it gets dequeued either in evhttp_connection_done or
1228 * evhttp_connection_fail_.
1230 while ((req = TAILQ_FIRST(&evcon->requests)) != NULL) {
1231 evhttp_request_free_(evcon, req);
1234 if (evcon->http_server != NULL) {
1235 struct evhttp *http = evcon->http_server;
1236 TAILQ_REMOVE(&http->connections, evcon, next);
1239 if (event_initialized(&evcon->retry_ev)) {
1240 event_del(&evcon->retry_ev);
1241 event_debug_unassign(&evcon->retry_ev);
1244 if (evcon->bufev != NULL)
1245 bufferevent_free(evcon->bufev);
1247 event_deferred_cb_cancel_(get_deferred_queue(evcon),
1248 &evcon->read_more_deferred_cb);
1250 if (evcon->fd == -1)
1251 evcon->fd = bufferevent_getfd(evcon->bufev);
1253 if (evcon->fd != -1) {
1254 bufferevent_disable(evcon->bufev, EV_READ|EV_WRITE);
1255 shutdown(evcon->fd, EVUTIL_SHUT_WR);
1256 if (!(bufferevent_get_options_(evcon->bufev) & BEV_OPT_CLOSE_ON_FREE)) {
1257 evutil_closesocket(evcon->fd);
1261 if (evcon->bind_address != NULL)
1262 mm_free(evcon->bind_address);
1264 if (evcon->address != NULL)
1265 mm_free(evcon->address);
1271 evhttp_connection_free_on_completion(struct evhttp_connection *evcon) {
1272 evcon->flags |= EVHTTP_CON_AUTOFREE;
1276 evhttp_connection_set_local_address(struct evhttp_connection *evcon,
1277 const char *address)
1279 EVUTIL_ASSERT(evcon->state == EVCON_DISCONNECTED);
1280 if (evcon->bind_address)
1281 mm_free(evcon->bind_address);
1282 if ((evcon->bind_address = mm_strdup(address)) == NULL)
1283 event_warn("%s: strdup", __func__);
1287 evhttp_connection_set_local_port(struct evhttp_connection *evcon,
1290 EVUTIL_ASSERT(evcon->state == EVCON_DISCONNECTED);
1291 evcon->bind_port = port;
1295 evhttp_request_dispatch(struct evhttp_connection* evcon)
1297 struct evhttp_request *req = TAILQ_FIRST(&evcon->requests);
1299 /* this should not usually happy but it's possible */
1303 /* delete possible close detection events */
1304 evhttp_connection_stop_detectclose(evcon);
1306 /* we assume that the connection is connected already */
1307 EVUTIL_ASSERT(evcon->state == EVCON_IDLE);
1309 evcon->state = EVCON_WRITING;
1311 /* Create the header from the store arguments */
1312 evhttp_make_header(evcon, req);
1314 evhttp_write_buffer(evcon, evhttp_write_connectioncb, NULL);
1317 /* Reset our connection state: disables reading/writing, closes our fd (if
1318 * any), clears out buffers, and puts us in state DISCONNECTED. */
1320 evhttp_connection_reset_(struct evhttp_connection *evcon)
1322 struct evbuffer *tmp;
1325 /* XXXX This is not actually an optimal fix. Instead we ought to have
1326 an API for "stop connecting", or use bufferevent_setfd to turn off
1327 connecting. But for Libevent 2.0, this seems like a minimal change
1328 least likely to disrupt the rest of the bufferevent and http code.
1330 Why is this here? If the fd is set in the bufferevent, and the
1331 bufferevent is connecting, then you can't actually stop the
1332 bufferevent from trying to connect with bufferevent_disable(). The
1333 connect will never trigger, since we close the fd, but the timeout
1334 might. That caused an assertion failure in evhttp_connection_fail_.
1336 bufferevent_disable_hard_(evcon->bufev, EV_READ|EV_WRITE);
1338 if (evcon->fd == -1)
1339 evcon->fd = bufferevent_getfd(evcon->bufev);
1341 if (evcon->fd != -1) {
1342 /* inform interested parties about connection close */
1343 if (evhttp_connected(evcon) && evcon->closecb != NULL)
1344 (*evcon->closecb)(evcon, evcon->closecb_arg);
1346 shutdown(evcon->fd, EVUTIL_SHUT_WR);
1347 evutil_closesocket(evcon->fd);
1350 bufferevent_setfd(evcon->bufev, -1);
1352 /* we need to clean up any buffered data */
1353 tmp = bufferevent_get_output(evcon->bufev);
1354 err = evbuffer_drain(tmp, -1);
1355 EVUTIL_ASSERT(!err && "drain output");
1356 tmp = bufferevent_get_input(evcon->bufev);
1357 err = evbuffer_drain(tmp, -1);
1358 EVUTIL_ASSERT(!err && "drain input");
1360 evcon->flags &= ~EVHTTP_CON_READING_ERROR;
1362 evcon->state = EVCON_DISCONNECTED;
1366 evhttp_connection_start_detectclose(struct evhttp_connection *evcon)
1368 evcon->flags |= EVHTTP_CON_CLOSEDETECT;
1370 bufferevent_enable(evcon->bufev, EV_READ);
1374 evhttp_connection_stop_detectclose(struct evhttp_connection *evcon)
1376 evcon->flags &= ~EVHTTP_CON_CLOSEDETECT;
1378 bufferevent_disable(evcon->bufev, EV_READ);
1382 evhttp_connection_retry(evutil_socket_t fd, short what, void *arg)
1384 struct evhttp_connection *evcon = arg;
1386 evcon->state = EVCON_DISCONNECTED;
1387 evhttp_connection_connect_(evcon);
1391 evhttp_connection_cb_cleanup(struct evhttp_connection *evcon)
1393 struct evcon_requestq requests;
1395 evhttp_connection_reset_(evcon);
1396 if (evcon->retry_max < 0 || evcon->retry_cnt < evcon->retry_max) {
1397 struct timeval tv_retry = evcon->initial_retry_timeout;
1399 evtimer_assign(&evcon->retry_ev, evcon->base, evhttp_connection_retry, evcon);
1400 /* XXXX handle failure from evhttp_add_event */
1401 for (i=0; i < evcon->retry_cnt; ++i) {
1402 tv_retry.tv_usec *= 2;
1403 if (tv_retry.tv_usec > 1000000) {
1404 tv_retry.tv_usec -= 1000000;
1405 tv_retry.tv_sec += 1;
1407 tv_retry.tv_sec *= 2;
1408 if (tv_retry.tv_sec > 3600) {
1409 tv_retry.tv_sec = 3600;
1410 tv_retry.tv_usec = 0;
1413 event_add(&evcon->retry_ev, &tv_retry);
1419 * User callback can do evhttp_make_request() on the same
1420 * evcon so new request will be added to evcon->requests. To
1421 * avoid freeing it prematurely we iterate over the copy of
1424 TAILQ_INIT(&requests);
1425 while (TAILQ_FIRST(&evcon->requests) != NULL) {
1426 struct evhttp_request *request = TAILQ_FIRST(&evcon->requests);
1427 TAILQ_REMOVE(&evcon->requests, request, next);
1428 TAILQ_INSERT_TAIL(&requests, request, next);
1431 /* for now, we just signal all requests by executing their callbacks */
1432 while (TAILQ_FIRST(&requests) != NULL) {
1433 struct evhttp_request *request = TAILQ_FIRST(&requests);
1434 TAILQ_REMOVE(&requests, request, next);
1435 request->evcon = NULL;
1437 /* we might want to set an error here */
1438 request->cb(request, request->cb_arg);
1439 evhttp_request_free_auto(request);
1444 evhttp_connection_read_on_write_error(struct evhttp_connection *evcon,
1445 struct evhttp_request *req)
1447 struct evbuffer *buf;
1449 /** Second time, we can't read anything */
1450 if (evcon->flags & EVHTTP_CON_READING_ERROR) {
1451 evcon->flags &= ~EVHTTP_CON_READING_ERROR;
1452 evhttp_connection_fail_(evcon, EVREQ_HTTP_EOF);
1456 req->kind = EVHTTP_RESPONSE;
1458 buf = bufferevent_get_output(evcon->bufev);
1459 evbuffer_unfreeze(buf, 1);
1460 evbuffer_drain(buf, evbuffer_get_length(buf));
1461 evbuffer_freeze(buf, 1);
1463 evhttp_start_read_(evcon);
1464 evcon->flags |= EVHTTP_CON_READING_ERROR;
1468 evhttp_error_cb(struct bufferevent *bufev, short what, void *arg)
1470 struct evhttp_connection *evcon = arg;
1471 struct evhttp_request *req = TAILQ_FIRST(&evcon->requests);
1473 if (evcon->fd == -1)
1474 evcon->fd = bufferevent_getfd(bufev);
1476 switch (evcon->state) {
1477 case EVCON_CONNECTING:
1478 if (what & BEV_EVENT_TIMEOUT) {
1479 event_debug(("%s: connection timeout for \"%s:%d\" on "
1481 __func__, evcon->address, evcon->port,
1482 EV_SOCK_ARG(evcon->fd)));
1483 evhttp_connection_cb_cleanup(evcon);
1488 case EVCON_READING_BODY:
1489 if (!req->chunked && req->ntoread < 0
1490 && what == (BEV_EVENT_READING|BEV_EVENT_EOF)) {
1491 /* EOF on read can be benign */
1492 evhttp_connection_done(evcon);
1497 case EVCON_DISCONNECTED:
1499 case EVCON_READING_FIRSTLINE:
1500 case EVCON_READING_HEADERS:
1501 case EVCON_READING_TRAILER:
1507 /* when we are in close detect mode, a read error means that
1508 * the other side closed their connection.
1510 if (evcon->flags & EVHTTP_CON_CLOSEDETECT) {
1511 evcon->flags &= ~EVHTTP_CON_CLOSEDETECT;
1512 EVUTIL_ASSERT(evcon->http_server == NULL);
1513 /* For connections from the client, we just
1514 * reset the connection so that it becomes
1517 EVUTIL_ASSERT(evcon->state == EVCON_IDLE);
1518 evhttp_connection_reset_(evcon);
1521 * If we have no more requests that need completion
1522 * and we want to auto-free the connection when all
1523 * requests have been completed.
1525 if (TAILQ_FIRST(&evcon->requests) == NULL
1526 && (evcon->flags & EVHTTP_CON_OUTGOING)
1527 && (evcon->flags & EVHTTP_CON_AUTOFREE)) {
1528 evhttp_connection_free(evcon);
1533 if (what & BEV_EVENT_TIMEOUT) {
1534 evhttp_connection_fail_(evcon, EVREQ_HTTP_TIMEOUT);
1535 } else if (what & (BEV_EVENT_EOF|BEV_EVENT_ERROR)) {
1536 if (what & BEV_EVENT_WRITING &&
1537 evcon->flags & EVHTTP_CON_READ_ON_WRITE_ERROR) {
1538 evhttp_connection_read_on_write_error(evcon, req);
1542 evhttp_connection_fail_(evcon, EVREQ_HTTP_EOF);
1543 } else if (what == BEV_EVENT_CONNECTED) {
1545 evhttp_connection_fail_(evcon, EVREQ_HTTP_BUFFER_ERROR);
1550 * Event callback for asynchronous connection attempt.
1553 evhttp_connection_cb(struct bufferevent *bufev, short what, void *arg)
1555 struct evhttp_connection *evcon = arg;
1557 ev_socklen_t errsz = sizeof(error);
1559 if (evcon->fd == -1)
1560 evcon->fd = bufferevent_getfd(bufev);
1562 if (!(what & BEV_EVENT_CONNECTED)) {
1563 /* some operating systems return ECONNREFUSED immediately
1564 * when connecting to a local address. the cleanup is going
1565 * to reschedule this function call.
1568 if (errno == ECONNREFUSED)
1571 evhttp_error_cb(bufev, what, arg);
1575 if (evcon->fd == -1) {
1576 event_debug(("%s: bufferevent_getfd returned -1",
1581 /* Check if the connection completed */
1582 if (getsockopt(evcon->fd, SOL_SOCKET, SO_ERROR, (void*)&error,
1584 event_debug(("%s: getsockopt for \"%s:%d\" on "EV_SOCK_FMT,
1585 __func__, evcon->address, evcon->port,
1586 EV_SOCK_ARG(evcon->fd)));
1591 event_debug(("%s: connect failed for \"%s:%d\" on "
1593 __func__, evcon->address, evcon->port,
1594 EV_SOCK_ARG(evcon->fd),
1595 evutil_socket_error_to_string(error)));
1599 /* We are connected to the server now */
1600 event_debug(("%s: connected to \"%s:%d\" on "EV_SOCK_FMT"\n",
1601 __func__, evcon->address, evcon->port,
1602 EV_SOCK_ARG(evcon->fd)));
1604 /* Reset the retry count as we were successful in connecting */
1605 evcon->retry_cnt = 0;
1606 evcon->state = EVCON_IDLE;
1608 /* reset the bufferevent cbs */
1609 bufferevent_setcb(evcon->bufev,
1615 if (!evutil_timerisset(&evcon->timeout)) {
1616 const struct timeval read_tv = { HTTP_READ_TIMEOUT, 0 };
1617 const struct timeval write_tv = { HTTP_WRITE_TIMEOUT, 0 };
1618 bufferevent_set_timeouts(evcon->bufev, &read_tv, &write_tv);
1620 bufferevent_set_timeouts(evcon->bufev, &evcon->timeout, &evcon->timeout);
1623 /* try to start requests that have queued up on this connection */
1624 evhttp_request_dispatch(evcon);
1628 evhttp_connection_cb_cleanup(evcon);
1632 * Check if we got a valid response code.
1636 evhttp_valid_response_code(int code)
1645 evhttp_parse_http_version(const char *version, struct evhttp_request *req)
1649 int n = sscanf(version, "HTTP/%d.%d%c", &major, &minor, &ch);
1650 if (n != 2 || major > 1) {
1651 event_debug(("%s: bad version %s on message %p from %s",
1652 __func__, version, req, req->remote_host));
1660 /* Parses the status line of a web server */
1663 evhttp_parse_response_line(struct evhttp_request *req, char *line)
1667 const char *readable = "";
1669 protocol = strsep(&line, " ");
1672 number = strsep(&line, " ");
1676 if (evhttp_parse_http_version(protocol, req) < 0)
1679 req->response_code = atoi(number);
1680 if (!evhttp_valid_response_code(req->response_code)) {
1681 event_debug(("%s: bad response code \"%s\"",
1686 if (req->response_code_line != NULL)
1687 mm_free(req->response_code_line);
1688 if ((req->response_code_line = mm_strdup(readable)) == NULL) {
1689 event_warn("%s: strdup", __func__);
1696 /* Parse the first line of a HTTP request */
1699 evhttp_parse_request_line(struct evhttp_request *req, char *line)
1704 const char *hostname;
1707 enum evhttp_cmd_type type;
1709 /* Parse the request line */
1710 method = strsep(&line, " ");
1713 uri = strsep(&line, " ");
1716 version = strsep(&line, " ");
1720 method_len = (uri - method) - 1;
1721 type = EVHTTP_REQ_UNKNOWN_;
1724 switch (method_len) {
1726 /* The length of the method string is 3, meaning it can only be one of two methods: GET or PUT */
1728 /* Since both GET and PUT share the same character 'T' at the end,
1729 * if the string doesn't have 'T', we can immediately determine this
1730 * is an invalid HTTP method */
1732 if (method[2] != 'T') {
1738 /* This first byte is 'G', so make sure the next byte is
1739 * 'E', if it isn't then this isn't a valid method */
1741 if (method[1] == 'E') {
1742 type = EVHTTP_REQ_GET;
1747 /* First byte is P, check second byte for 'U', if not,
1748 * we know it's an invalid method */
1749 if (method[1] == 'U') {
1750 type = EVHTTP_REQ_PUT;
1758 /* The method length is 4 bytes, leaving only the methods "POST" and "HEAD" */
1761 if (method[3] == 'T' && method[2] == 'S' && method[1] == 'O') {
1762 type = EVHTTP_REQ_POST;
1766 if (method[3] == 'D' && method[2] == 'A' && method[1] == 'E') {
1767 type = EVHTTP_REQ_HEAD;
1775 /* Method length is 5 bytes, which can only encompass PATCH and TRACE */
1778 if (method[4] == 'H' && method[3] == 'C' && method[2] == 'T' && method[1] == 'A') {
1779 type = EVHTTP_REQ_PATCH;
1783 if (method[4] == 'E' && method[3] == 'C' && method[2] == 'A' && method[1] == 'R') {
1784 type = EVHTTP_REQ_TRACE;
1793 /* Method length is 6, only valid method 6 bytes in length is DELEte */
1795 /* If the first byte isn't 'D' then it's invalid */
1796 if (*method != 'D') {
1800 if (method[5] == 'E' && method[4] == 'T' && method[3] == 'E' && method[2] == 'L' && method[1] == 'E') {
1801 type = EVHTTP_REQ_DELETE;
1806 /* Method length is 7, only valid methods are "OPTIONS" and "CONNECT" */
1809 if (method[6] == 'S' && method[5] == 'N' && method[4] == 'O' &&
1810 method[3] == 'I' && method[2] == 'T' && method[1] == 'P') {
1811 type = EVHTTP_REQ_OPTIONS;
1816 if (method[6] == 'T' && method[5] == 'C' && method[4] == 'E' &&
1817 method[3] == 'N' && method[2] == 'N' && method[1] == 'O') {
1818 type = EVHTTP_REQ_CONNECT;
1828 if ((int)type == EVHTTP_REQ_UNKNOWN_) {
1829 event_debug(("%s: bad method %s on request %p from %s",
1830 __func__, method, req, req->remote_host));
1831 /* No error yet; we'll give a better error later when
1832 * we see that req->type is unsupported. */
1837 if (evhttp_parse_http_version(version, req) < 0)
1840 if ((req->uri = mm_strdup(uri)) == NULL) {
1841 event_debug(("%s: mm_strdup", __func__));
1845 if ((req->uri_elems = evhttp_uri_parse_with_flags(req->uri,
1846 EVHTTP_URI_NONCONFORMANT)) == NULL) {
1850 /* If we have an absolute-URI, check to see if it is an http request
1851 for a known vhost or server alias. If we don't know about this
1852 host, we consider it a proxy request. */
1853 scheme = evhttp_uri_get_scheme(req->uri_elems);
1854 hostname = evhttp_uri_get_host(req->uri_elems);
1855 if (scheme && (!evutil_ascii_strcasecmp(scheme, "http") ||
1856 !evutil_ascii_strcasecmp(scheme, "https")) &&
1858 !evhttp_find_vhost(req->evcon->http_server, NULL, hostname))
1859 req->flags |= EVHTTP_PROXY_REQUEST;
1865 evhttp_find_header(const struct evkeyvalq *headers, const char *key)
1867 struct evkeyval *header;
1869 TAILQ_FOREACH(header, headers, next) {
1870 if (evutil_ascii_strcasecmp(header->key, key) == 0)
1871 return (header->value);
1878 evhttp_clear_headers(struct evkeyvalq *headers)
1880 struct evkeyval *header;
1882 for (header = TAILQ_FIRST(headers);
1884 header = TAILQ_FIRST(headers)) {
1885 TAILQ_REMOVE(headers, header, next);
1886 mm_free(header->key);
1887 mm_free(header->value);
1893 * Returns 0, if the header was successfully removed.
1894 * Returns -1, if the header could not be found.
1898 evhttp_remove_header(struct evkeyvalq *headers, const char *key)
1900 struct evkeyval *header;
1902 TAILQ_FOREACH(header, headers, next) {
1903 if (evutil_ascii_strcasecmp(header->key, key) == 0)
1910 /* Free and remove the header that we found */
1911 TAILQ_REMOVE(headers, header, next);
1912 mm_free(header->key);
1913 mm_free(header->value);
1920 evhttp_header_is_valid_value(const char *value)
1922 const char *p = value;
1924 while ((p = strpbrk(p, "\r\n")) != NULL) {
1925 /* we really expect only one new line */
1926 p += strspn(p, "\r\n");
1927 /* we expect a space or tab for continuation */
1928 if (*p != ' ' && *p != '\t')
1935 evhttp_add_header(struct evkeyvalq *headers,
1936 const char *key, const char *value)
1938 event_debug(("%s: key: %s val: %s\n", __func__, key, value));
1940 if (strchr(key, '\r') != NULL || strchr(key, '\n') != NULL) {
1941 /* drop illegal headers */
1942 event_debug(("%s: dropping illegal header key\n", __func__));
1946 if (!evhttp_header_is_valid_value(value)) {
1947 event_debug(("%s: dropping illegal header value\n", __func__));
1951 return (evhttp_add_header_internal(headers, key, value));
1955 evhttp_add_header_internal(struct evkeyvalq *headers,
1956 const char *key, const char *value)
1958 struct evkeyval *header = mm_calloc(1, sizeof(struct evkeyval));
1959 if (header == NULL) {
1960 event_warn("%s: calloc", __func__);
1963 if ((header->key = mm_strdup(key)) == NULL) {
1965 event_warn("%s: strdup", __func__);
1968 if ((header->value = mm_strdup(value)) == NULL) {
1969 mm_free(header->key);
1971 event_warn("%s: strdup", __func__);
1975 TAILQ_INSERT_TAIL(headers, header, next);
1981 * Parses header lines from a request or a response into the specified
1982 * request object given an event buffer.
1985 * DATA_CORRUPTED on error
1986 * MORE_DATA_EXPECTED when we need to read more headers
1987 * ALL_DATA_READ when all headers have been read.
1990 enum message_read_status
1991 evhttp_parse_firstline_(struct evhttp_request *req, struct evbuffer *buffer)
1994 enum message_read_status status = ALL_DATA_READ;
1998 line = evbuffer_readln(buffer, &line_length, EVBUFFER_EOL_CRLF);
2000 if (req->evcon != NULL &&
2001 evbuffer_get_length(buffer) > req->evcon->max_headers_size)
2002 return (DATA_TOO_LONG);
2004 return (MORE_DATA_EXPECTED);
2007 if (req->evcon != NULL &&
2008 line_length > req->evcon->max_headers_size) {
2010 return (DATA_TOO_LONG);
2013 req->headers_size = line_length;
2015 switch (req->kind) {
2016 case EVHTTP_REQUEST:
2017 if (evhttp_parse_request_line(req, line) == -1)
2018 status = DATA_CORRUPTED;
2020 case EVHTTP_RESPONSE:
2021 if (evhttp_parse_response_line(req, line) == -1)
2022 status = DATA_CORRUPTED;
2025 status = DATA_CORRUPTED;
2033 evhttp_append_to_last_header(struct evkeyvalq *headers, char *line)
2035 struct evkeyval *header = TAILQ_LAST(headers, evkeyvalq);
2037 size_t old_len, line_len;
2042 old_len = strlen(header->value);
2044 /* Strip space from start and end of line. */
2045 while (*line == ' ' || *line == '\t')
2047 evutil_rtrim_lws_(line);
2049 line_len = strlen(line);
2051 newval = mm_realloc(header->value, old_len + line_len + 2);
2055 newval[old_len] = ' ';
2056 memcpy(newval + old_len + 1, line, line_len + 1);
2057 header->value = newval;
2062 enum message_read_status
2063 evhttp_parse_headers_(struct evhttp_request *req, struct evbuffer* buffer)
2065 enum message_read_status errcode = DATA_CORRUPTED;
2067 enum message_read_status status = MORE_DATA_EXPECTED;
2069 struct evkeyvalq* headers = req->input_headers;
2071 while ((line = evbuffer_readln(buffer, &line_length, EVBUFFER_EOL_CRLF))
2073 char *skey, *svalue;
2075 req->headers_size += line_length;
2077 if (req->evcon != NULL &&
2078 req->headers_size > req->evcon->max_headers_size) {
2079 errcode = DATA_TOO_LONG;
2083 if (*line == '\0') { /* Last header - Done */
2084 status = ALL_DATA_READ;
2089 /* Check if this is a continuation line */
2090 if (*line == ' ' || *line == '\t') {
2091 if (evhttp_append_to_last_header(headers, line) == -1)
2097 /* Processing of header lines */
2099 skey = strsep(&svalue, ":");
2103 svalue += strspn(svalue, " ");
2104 evutil_rtrim_lws_(svalue);
2106 if (evhttp_add_header(headers, skey, svalue) == -1)
2112 if (status == MORE_DATA_EXPECTED) {
2113 if (req->evcon != NULL &&
2114 req->headers_size + evbuffer_get_length(buffer) > req->evcon->max_headers_size)
2115 return (DATA_TOO_LONG);
2126 evhttp_get_body_length(struct evhttp_request *req)
2128 struct evkeyvalq *headers = req->input_headers;
2129 const char *content_length;
2130 const char *connection;
2132 content_length = evhttp_find_header(headers, "Content-Length");
2133 connection = evhttp_find_header(headers, "Connection");
2135 if (content_length == NULL && connection == NULL)
2137 else if (content_length == NULL &&
2138 evutil_ascii_strcasecmp(connection, "Close") != 0) {
2139 /* Bad combination, we don't know when it will end */
2140 event_warnx("%s: we got no content length, but the "
2141 "server wants to keep the connection open: %s.",
2142 __func__, connection);
2144 } else if (content_length == NULL) {
2148 ev_int64_t ntoread = evutil_strtoll(content_length, &endp, 10);
2149 if (*content_length == '\0' || *endp != '\0' || ntoread < 0) {
2150 event_debug(("%s: illegal content length: %s",
2151 __func__, content_length));
2154 req->ntoread = ntoread;
2157 event_debug(("%s: bytes to read: "EV_I64_FMT" (in buffer "EV_SIZE_FMT")\n",
2158 __func__, EV_I64_ARG(req->ntoread),
2159 EV_SIZE_ARG(evbuffer_get_length(bufferevent_get_input(req->evcon->bufev)))));
2165 evhttp_method_may_have_body(enum evhttp_cmd_type type)
2168 case EVHTTP_REQ_POST:
2169 case EVHTTP_REQ_PUT:
2170 case EVHTTP_REQ_PATCH:
2172 case EVHTTP_REQ_TRACE:
2174 /* XXX May any of the below methods have a body? */
2175 case EVHTTP_REQ_GET:
2176 case EVHTTP_REQ_HEAD:
2177 case EVHTTP_REQ_DELETE:
2178 case EVHTTP_REQ_OPTIONS:
2179 case EVHTTP_REQ_CONNECT:
2187 evhttp_get_body(struct evhttp_connection *evcon, struct evhttp_request *req)
2189 const char *xfer_enc;
2191 /* If this is a request without a body, then we are done */
2192 if (req->kind == EVHTTP_REQUEST &&
2193 !evhttp_method_may_have_body(req->type)) {
2194 evhttp_connection_done(evcon);
2197 evcon->state = EVCON_READING_BODY;
2198 xfer_enc = evhttp_find_header(req->input_headers, "Transfer-Encoding");
2199 if (xfer_enc != NULL && evutil_ascii_strcasecmp(xfer_enc, "chunked") == 0) {
2203 if (evhttp_get_body_length(req) == -1) {
2204 evhttp_connection_fail_(evcon, EVREQ_HTTP_INVALID_HEADER);
2207 if (req->kind == EVHTTP_REQUEST && req->ntoread < 1) {
2208 /* An incoming request with no content-length and no
2209 * transfer-encoding has no body. */
2210 evhttp_connection_done(evcon);
2215 /* Should we send a 100 Continue status line? */
2216 switch (evhttp_have_expect(req, 1)) {
2218 /* XXX It would be nice to do some sanity
2219 checking here. Does the resource exist?
2220 Should the resource accept post requests? If
2221 no, we should respond with an error. For
2222 now, just optimistically tell the client to
2223 send their message body. */
2224 if (req->ntoread > 0) {
2225 /* ntoread is ev_int64_t, max_body_size is ev_uint64_t */
2226 if ((req->evcon->max_body_size <= EV_INT64_MAX) &&
2227 (ev_uint64_t)req->ntoread > req->evcon->max_body_size) {
2228 evhttp_lingering_fail(evcon, req);
2232 if (!evbuffer_get_length(bufferevent_get_input(evcon->bufev)))
2233 evhttp_send_continue(evcon, req);
2236 evhttp_send_error(req, HTTP_EXPECTATIONFAILED, NULL);
2241 evhttp_read_body(evcon, req);
2242 /* note the request may have been freed in evhttp_read_body */
2246 evhttp_read_firstline(struct evhttp_connection *evcon,
2247 struct evhttp_request *req)
2249 enum message_read_status res;
2251 res = evhttp_parse_firstline_(req, bufferevent_get_input(evcon->bufev));
2252 if (res == DATA_CORRUPTED || res == DATA_TOO_LONG) {
2253 /* Error while reading, terminate */
2254 event_debug(("%s: bad header lines on "EV_SOCK_FMT"\n",
2255 __func__, EV_SOCK_ARG(evcon->fd)));
2256 evhttp_connection_fail_(evcon, EVREQ_HTTP_INVALID_HEADER);
2258 } else if (res == MORE_DATA_EXPECTED) {
2259 /* Need more header lines */
2263 evcon->state = EVCON_READING_HEADERS;
2264 evhttp_read_header(evcon, req);
2268 evhttp_read_header(struct evhttp_connection *evcon,
2269 struct evhttp_request *req)
2271 enum message_read_status res;
2272 evutil_socket_t fd = evcon->fd;
2274 res = evhttp_parse_headers_(req, bufferevent_get_input(evcon->bufev));
2275 if (res == DATA_CORRUPTED || res == DATA_TOO_LONG) {
2276 /* Error while reading, terminate */
2277 event_debug(("%s: bad header lines on "EV_SOCK_FMT"\n",
2278 __func__, EV_SOCK_ARG(fd)));
2279 evhttp_connection_fail_(evcon, EVREQ_HTTP_INVALID_HEADER);
2281 } else if (res == MORE_DATA_EXPECTED) {
2282 /* Need more header lines */
2286 /* Callback can shut down connection with negative return value */
2287 if (req->header_cb != NULL) {
2288 if ((*req->header_cb)(req, req->cb_arg) < 0) {
2289 evhttp_connection_fail_(evcon, EVREQ_HTTP_EOF);
2294 /* Done reading headers, do the real work */
2295 switch (req->kind) {
2296 case EVHTTP_REQUEST:
2297 event_debug(("%s: checking for post data on "EV_SOCK_FMT"\n",
2298 __func__, EV_SOCK_ARG(fd)));
2299 evhttp_get_body(evcon, req);
2300 /* note the request may have been freed in evhttp_get_body */
2303 case EVHTTP_RESPONSE:
2304 /* Start over if we got a 100 Continue response. */
2305 if (req->response_code == 100) {
2306 struct evbuffer *output = bufferevent_get_output(evcon->bufev);
2307 evbuffer_add_buffer(output, req->output_buffer);
2308 evhttp_start_write_(evcon);
2311 if (!evhttp_response_needs_body(req)) {
2312 event_debug(("%s: skipping body for code %d\n",
2313 __func__, req->response_code));
2314 evhttp_connection_done(evcon);
2316 event_debug(("%s: start of read body for %s on "
2318 __func__, req->remote_host, EV_SOCK_ARG(fd)));
2319 evhttp_get_body(evcon, req);
2320 /* note the request may have been freed in
2321 * evhttp_get_body */
2326 event_warnx("%s: bad header on "EV_SOCK_FMT, __func__,
2328 evhttp_connection_fail_(evcon, EVREQ_HTTP_INVALID_HEADER);
2331 /* request may have been freed above */
2335 * Creates a TCP connection to the specified port and executes a callback
2336 * when finished. Failure or success is indicate by the passed connection
2339 * Although this interface accepts a hostname, it is intended to take
2340 * only numeric hostnames so that non-blocking DNS resolution can
2344 struct evhttp_connection *
2345 evhttp_connection_new(const char *address, unsigned short port)
2347 return (evhttp_connection_base_new(NULL, NULL, address, port));
2350 struct evhttp_connection *
2351 evhttp_connection_base_bufferevent_new(struct event_base *base, struct evdns_base *dnsbase, struct bufferevent* bev,
2352 const char *address, unsigned short port)
2354 struct evhttp_connection *evcon = NULL;
2356 event_debug(("Attempting connection to %s:%d\n", address, port));
2358 if ((evcon = mm_calloc(1, sizeof(struct evhttp_connection))) == NULL) {
2359 event_warn("%s: calloc failed", __func__);
2366 evcon->max_headers_size = EV_SIZE_MAX;
2367 evcon->max_body_size = EV_SIZE_MAX;
2369 evutil_timerclear(&evcon->timeout);
2370 evcon->retry_cnt = evcon->retry_max = 0;
2372 if ((evcon->address = mm_strdup(address)) == NULL) {
2373 event_warn("%s: strdup failed", __func__);
2378 if (!(bev = bufferevent_socket_new(base, -1, 0))) {
2379 event_warn("%s: bufferevent_socket_new failed", __func__);
2384 bufferevent_setcb(bev, evhttp_read_cb, evhttp_write_cb, evhttp_error_cb, evcon);
2387 evcon->state = EVCON_DISCONNECTED;
2388 TAILQ_INIT(&evcon->requests);
2390 evcon->initial_retry_timeout.tv_sec = 2;
2391 evcon->initial_retry_timeout.tv_usec = 0;
2395 if (bufferevent_get_base(bev) != base)
2396 bufferevent_base_set(base, evcon->bufev);
2399 event_deferred_cb_init_(
2400 &evcon->read_more_deferred_cb,
2401 bufferevent_get_priority(bev),
2402 evhttp_deferred_read_cb, evcon);
2404 evcon->dns_base = dnsbase;
2405 evcon->ai_family = AF_UNSPEC;
2411 evhttp_connection_free(evcon);
2415 struct bufferevent* evhttp_connection_get_bufferevent(struct evhttp_connection *evcon)
2417 return evcon->bufev;
2421 evhttp_connection_get_server(struct evhttp_connection *evcon)
2423 return evcon->http_server;
2426 struct evhttp_connection *
2427 evhttp_connection_base_new(struct event_base *base, struct evdns_base *dnsbase,
2428 const char *address, unsigned short port)
2430 return evhttp_connection_base_bufferevent_new(base, dnsbase, NULL, address, port);
2433 void evhttp_connection_set_family(struct evhttp_connection *evcon,
2436 evcon->ai_family = family;
2439 int evhttp_connection_set_flags(struct evhttp_connection *evcon,
2442 int avail_flags = 0;
2443 avail_flags |= EVHTTP_CON_REUSE_CONNECTED_ADDR;
2444 avail_flags |= EVHTTP_CON_READ_ON_WRITE_ERROR;
2446 if (flags & ~avail_flags || flags > EVHTTP_CON_PUBLIC_FLAGS_END)
2448 evcon->flags &= ~avail_flags;
2450 evcon->flags |= flags;
2456 evhttp_connection_set_base(struct evhttp_connection *evcon,
2457 struct event_base *base)
2459 EVUTIL_ASSERT(evcon->base == NULL);
2460 EVUTIL_ASSERT(evcon->state == EVCON_DISCONNECTED);
2462 bufferevent_base_set(base, evcon->bufev);
2466 evhttp_connection_set_timeout(struct evhttp_connection *evcon,
2467 int timeout_in_secs)
2469 if (timeout_in_secs == -1)
2470 evhttp_connection_set_timeout_tv(evcon, NULL);
2473 tv.tv_sec = timeout_in_secs;
2475 evhttp_connection_set_timeout_tv(evcon, &tv);
2480 evhttp_connection_set_timeout_tv(struct evhttp_connection *evcon,
2481 const struct timeval* tv)
2484 evcon->timeout = *tv;
2485 bufferevent_set_timeouts(evcon->bufev, &evcon->timeout, &evcon->timeout);
2487 const struct timeval read_tv = { HTTP_READ_TIMEOUT, 0 };
2488 const struct timeval write_tv = { HTTP_WRITE_TIMEOUT, 0 };
2489 evutil_timerclear(&evcon->timeout);
2490 bufferevent_set_timeouts(evcon->bufev, &read_tv, &write_tv);
2495 evhttp_connection_set_initial_retry_tv(struct evhttp_connection *evcon,
2496 const struct timeval *tv)
2499 evcon->initial_retry_timeout = *tv;
2501 evutil_timerclear(&evcon->initial_retry_timeout);
2502 evcon->initial_retry_timeout.tv_sec = 2;
2507 evhttp_connection_set_retries(struct evhttp_connection *evcon,
2510 evcon->retry_max = retry_max;
2514 evhttp_connection_set_closecb(struct evhttp_connection *evcon,
2515 void (*cb)(struct evhttp_connection *, void *), void *cbarg)
2517 evcon->closecb = cb;
2518 evcon->closecb_arg = cbarg;
2522 evhttp_connection_get_peer(struct evhttp_connection *evcon,
2523 char **address, ev_uint16_t *port)
2525 *address = evcon->address;
2526 *port = evcon->port;
2529 const struct sockaddr*
2530 evhttp_connection_get_addr(struct evhttp_connection *evcon)
2532 return bufferevent_socket_get_conn_address_(evcon->bufev);
2536 evhttp_connection_connect_(struct evhttp_connection *evcon)
2538 int old_state = evcon->state;
2539 const char *address = evcon->address;
2540 const struct sockaddr *sa = evhttp_connection_get_addr(evcon);
2543 if (evcon->state == EVCON_CONNECTING)
2546 evhttp_connection_reset_(evcon);
2548 EVUTIL_ASSERT(!(evcon->flags & EVHTTP_CON_INCOMING));
2549 evcon->flags |= EVHTTP_CON_OUTGOING;
2551 if (evcon->bind_address || evcon->bind_port) {
2552 evcon->fd = bind_socket(
2553 evcon->bind_address, evcon->bind_port, 0 /*reuse*/);
2554 if (evcon->fd == -1) {
2555 event_debug(("%s: failed to bind to \"%s\"",
2556 __func__, evcon->bind_address));
2560 bufferevent_setfd(evcon->bufev, evcon->fd);
2562 bufferevent_setfd(evcon->bufev, -1);
2565 /* Set up a callback for successful connection setup */
2566 bufferevent_setcb(evcon->bufev,
2567 NULL /* evhttp_read_cb */,
2568 NULL /* evhttp_write_cb */,
2569 evhttp_connection_cb,
2571 if (!evutil_timerisset(&evcon->timeout)) {
2572 const struct timeval conn_tv = { HTTP_CONNECT_TIMEOUT, 0 };
2573 bufferevent_set_timeouts(evcon->bufev, &conn_tv, &conn_tv);
2575 bufferevent_set_timeouts(evcon->bufev, &evcon->timeout, &evcon->timeout);
2577 /* make sure that we get a write callback */
2578 bufferevent_enable(evcon->bufev, EV_WRITE);
2580 evcon->state = EVCON_CONNECTING;
2582 if (evcon->flags & EVHTTP_CON_REUSE_CONNECTED_ADDR &&
2584 (sa->sa_family == AF_INET || sa->sa_family == AF_INET6)) {
2585 int socklen = sizeof(struct sockaddr_in);
2586 if (sa->sa_family == AF_INET6) {
2587 socklen = sizeof(struct sockaddr_in6);
2589 ret = bufferevent_socket_connect(evcon->bufev, sa, socklen);
2591 ret = bufferevent_socket_connect_hostname(evcon->bufev,
2592 evcon->dns_base, evcon->ai_family, address, evcon->port);
2596 evcon->state = old_state;
2597 event_sock_warn(evcon->fd, "%s: connection to \"%s\" failed",
2598 __func__, evcon->address);
2599 /* some operating systems return ECONNREFUSED immediately
2600 * when connecting to a local address. the cleanup is going
2601 * to reschedule this function call.
2603 evhttp_connection_cb_cleanup(evcon);
2611 * Starts an HTTP request on the provided evhttp_connection object.
2612 * If the connection object is not connected to the web server already,
2613 * this will start the connection.
2617 evhttp_make_request(struct evhttp_connection *evcon,
2618 struct evhttp_request *req,
2619 enum evhttp_cmd_type type, const char *uri)
2621 /* We are making a request */
2622 req->kind = EVHTTP_REQUEST;
2624 if (req->uri != NULL)
2626 if ((req->uri = mm_strdup(uri)) == NULL) {
2627 event_warn("%s: strdup", __func__);
2628 evhttp_request_free_auto(req);
2632 /* Set the protocol version if it is not supplied */
2633 if (!req->major && !req->minor) {
2638 EVUTIL_ASSERT(req->evcon == NULL);
2640 EVUTIL_ASSERT(!(req->flags & EVHTTP_REQ_OWN_CONNECTION));
2642 TAILQ_INSERT_TAIL(&evcon->requests, req, next);
2644 /* If the connection object is not connected; make it so */
2645 if (!evhttp_connected(evcon)) {
2646 int res = evhttp_connection_connect_(evcon);
2647 /* evhttp_connection_fail_(), which is called through
2648 * evhttp_connection_connect_(), assumes that req lies in
2649 * evcon->requests. Thus, enqueue the request in advance and
2650 * remove it in the error case. */
2652 TAILQ_REMOVE(&evcon->requests, req, next);
2658 * If it's connected already and we are the first in the queue,
2659 * then we can dispatch this request immediately. Otherwise, it
2660 * will be dispatched once the pending requests are completed.
2662 if (TAILQ_FIRST(&evcon->requests) == req)
2663 evhttp_request_dispatch(evcon);
2669 evhttp_cancel_request(struct evhttp_request *req)
2671 struct evhttp_connection *evcon = req->evcon;
2672 if (evcon != NULL) {
2673 /* We need to remove it from the connection */
2674 if (TAILQ_FIRST(&evcon->requests) == req) {
2675 /* it's currently being worked on, so reset
2678 evhttp_connection_fail_(evcon,
2679 EVREQ_HTTP_REQUEST_CANCEL);
2681 /* connection fail freed the request */
2684 /* otherwise, we can just remove it from the
2687 TAILQ_REMOVE(&evcon->requests, req, next);
2691 evhttp_request_free_auto(req);
2695 * Reads data from file descriptor into request structure
2696 * Request structure needs to be set up correctly.
2700 evhttp_start_read_(struct evhttp_connection *evcon)
2702 bufferevent_disable(evcon->bufev, EV_WRITE);
2703 bufferevent_enable(evcon->bufev, EV_READ);
2705 evcon->state = EVCON_READING_FIRSTLINE;
2706 /* Reset the bufferevent callbacks */
2707 bufferevent_setcb(evcon->bufev,
2713 /* If there's still data pending, process it next time through the
2714 * loop. Don't do it now; that could get recusive. */
2715 if (evbuffer_get_length(bufferevent_get_input(evcon->bufev))) {
2716 event_deferred_cb_schedule_(get_deferred_queue(evcon),
2717 &evcon->read_more_deferred_cb);
2722 evhttp_start_write_(struct evhttp_connection *evcon)
2724 bufferevent_disable(evcon->bufev, EV_WRITE);
2725 bufferevent_enable(evcon->bufev, EV_READ);
2727 evcon->state = EVCON_WRITING;
2728 evhttp_write_buffer(evcon, evhttp_write_connectioncb, NULL);
2732 evhttp_send_done(struct evhttp_connection *evcon, void *arg)
2735 struct evhttp_request *req = TAILQ_FIRST(&evcon->requests);
2736 TAILQ_REMOVE(&evcon->requests, req, next);
2738 if (req->on_complete_cb != NULL) {
2739 req->on_complete_cb(req, req->on_complete_cb_arg);
2743 (REQ_VERSION_BEFORE(req, 1, 1) &&
2744 !evhttp_is_connection_keepalive(req->input_headers)) ||
2745 evhttp_is_request_connection_close(req);
2747 EVUTIL_ASSERT(req->flags & EVHTTP_REQ_OWN_CONNECTION);
2748 evhttp_request_free(req);
2751 evhttp_connection_free(evcon);
2755 /* we have a persistent connection; try to accept another request. */
2756 if (evhttp_associate_new_request_with_connection(evcon) == -1) {
2757 evhttp_connection_free(evcon);
2762 * Returns an error page.
2766 evhttp_send_error(struct evhttp_request *req, int error, const char *reason)
2769 #define ERR_FORMAT "<HTML><HEAD>\n" \
2770 "<TITLE>%d %s</TITLE>\n" \
2775 struct evbuffer *buf = evbuffer_new();
2777 /* if we cannot allocate memory; we just drop the connection */
2778 evhttp_connection_free(req->evcon);
2781 if (reason == NULL) {
2782 reason = evhttp_response_phrase_internal(error);
2785 evhttp_response_code_(req, error, reason);
2787 evbuffer_add_printf(buf, ERR_FORMAT, error, reason, reason);
2789 evhttp_send_page_(req, buf);
2795 /* Requires that headers and response code are already set up */
2798 evhttp_send(struct evhttp_request *req, struct evbuffer *databuf)
2800 struct evhttp_connection *evcon = req->evcon;
2802 if (evcon == NULL) {
2803 evhttp_request_free(req);
2807 EVUTIL_ASSERT(TAILQ_FIRST(&evcon->requests) == req);
2809 /* we expect no more calls form the user on this request */
2812 /* xxx: not sure if we really should expose the data buffer this way */
2813 if (databuf != NULL)
2814 evbuffer_add_buffer(req->output_buffer, databuf);
2816 /* Adds headers to the response */
2817 evhttp_make_header(evcon, req);
2819 evhttp_write_buffer(evcon, evhttp_send_done, NULL);
2823 evhttp_send_reply(struct evhttp_request *req, int code, const char *reason,
2824 struct evbuffer *databuf)
2826 evhttp_response_code_(req, code, reason);
2828 evhttp_send(req, databuf);
2832 evhttp_send_reply_start(struct evhttp_request *req, int code,
2835 evhttp_response_code_(req, code, reason);
2836 if (evhttp_find_header(req->output_headers, "Content-Length") == NULL &&
2837 REQ_VERSION_ATLEAST(req, 1, 1) &&
2838 evhttp_response_needs_body(req)) {
2840 * prefer HTTP/1.1 chunked encoding to closing the connection;
2841 * note RFC 2616 section 4.4 forbids it with Content-Length:
2842 * and it's not necessary then anyway.
2844 evhttp_add_header(req->output_headers, "Transfer-Encoding",
2850 evhttp_make_header(req->evcon, req);
2851 evhttp_write_buffer(req->evcon, NULL, NULL);
2855 evhttp_send_reply_chunk_with_cb(struct evhttp_request *req, struct evbuffer *databuf,
2856 void (*cb)(struct evhttp_connection *, void *), void *arg)
2858 struct evhttp_connection *evcon = req->evcon;
2859 struct evbuffer *output;
2864 output = bufferevent_get_output(evcon->bufev);
2866 if (evbuffer_get_length(databuf) == 0)
2868 if (!evhttp_response_needs_body(req))
2871 evbuffer_add_printf(output, "%x\r\n",
2872 (unsigned)evbuffer_get_length(databuf));
2874 evbuffer_add_buffer(output, databuf);
2876 evbuffer_add(output, "\r\n", 2);
2878 evhttp_write_buffer(evcon, cb, arg);
2882 evhttp_send_reply_chunk(struct evhttp_request *req, struct evbuffer *databuf)
2884 evhttp_send_reply_chunk_with_cb(req, databuf, NULL, NULL);
2887 evhttp_send_reply_end(struct evhttp_request *req)
2889 struct evhttp_connection *evcon = req->evcon;
2890 struct evbuffer *output;
2892 if (evcon == NULL) {
2893 evhttp_request_free(req);
2897 output = bufferevent_get_output(evcon->bufev);
2899 /* we expect no more calls form the user on this request */
2903 evbuffer_add(output, "0\r\n\r\n", 5);
2904 evhttp_write_buffer(req->evcon, evhttp_send_done, NULL);
2906 } else if (evbuffer_get_length(output) == 0) {
2907 /* let the connection know that we are done with the request */
2908 evhttp_send_done(evcon, NULL);
2910 /* make the callback execute after all data has been written */
2911 evcon->cb = evhttp_send_done;
2912 evcon->cb_arg = NULL;
2916 static const char *informational_phrases[] = {
2917 /* 100 */ "Continue",
2918 /* 101 */ "Switching Protocols"
2921 static const char *success_phrases[] = {
2923 /* 201 */ "Created",
2924 /* 202 */ "Accepted",
2925 /* 203 */ "Non-Authoritative Information",
2926 /* 204 */ "No Content",
2927 /* 205 */ "Reset Content",
2928 /* 206 */ "Partial Content"
2931 static const char *redirection_phrases[] = {
2932 /* 300 */ "Multiple Choices",
2933 /* 301 */ "Moved Permanently",
2935 /* 303 */ "See Other",
2936 /* 304 */ "Not Modified",
2937 /* 305 */ "Use Proxy",
2938 /* 307 */ "Temporary Redirect"
2941 static const char *client_error_phrases[] = {
2942 /* 400 */ "Bad Request",
2943 /* 401 */ "Unauthorized",
2944 /* 402 */ "Payment Required",
2945 /* 403 */ "Forbidden",
2946 /* 404 */ "Not Found",
2947 /* 405 */ "Method Not Allowed",
2948 /* 406 */ "Not Acceptable",
2949 /* 407 */ "Proxy Authentication Required",
2950 /* 408 */ "Request Time-out",
2951 /* 409 */ "Conflict",
2953 /* 411 */ "Length Required",
2954 /* 412 */ "Precondition Failed",
2955 /* 413 */ "Request Entity Too Large",
2956 /* 414 */ "Request-URI Too Large",
2957 /* 415 */ "Unsupported Media Type",
2958 /* 416 */ "Requested range not satisfiable",
2959 /* 417 */ "Expectation Failed"
2962 static const char *server_error_phrases[] = {
2963 /* 500 */ "Internal Server Error",
2964 /* 501 */ "Not Implemented",
2965 /* 502 */ "Bad Gateway",
2966 /* 503 */ "Service Unavailable",
2967 /* 504 */ "Gateway Time-out",
2968 /* 505 */ "HTTP Version not supported"
2971 struct response_class {
2973 size_t num_responses;
2974 const char **responses;
2978 #define MEMBERSOF(x) (sizeof(x)/sizeof(x[0]))
2981 static const struct response_class response_classes[] = {
2982 /* 1xx */ { "Informational", MEMBERSOF(informational_phrases), informational_phrases },
2983 /* 2xx */ { "Success", MEMBERSOF(success_phrases), success_phrases },
2984 /* 3xx */ { "Redirection", MEMBERSOF(redirection_phrases), redirection_phrases },
2985 /* 4xx */ { "Client Error", MEMBERSOF(client_error_phrases), client_error_phrases },
2986 /* 5xx */ { "Server Error", MEMBERSOF(server_error_phrases), server_error_phrases }
2990 evhttp_response_phrase_internal(int code)
2992 int klass = code / 100 - 1;
2993 int subcode = code % 100;
2995 /* Unknown class - can't do any better here */
2996 if (klass < 0 || klass >= (int) MEMBERSOF(response_classes))
2997 return "Unknown Status Class";
2999 /* Unknown sub-code, return class name at least */
3000 if (subcode >= (int) response_classes[klass].num_responses)
3001 return response_classes[klass].name;
3003 return response_classes[klass].responses[subcode];
3007 evhttp_response_code_(struct evhttp_request *req, int code, const char *reason)
3009 req->kind = EVHTTP_RESPONSE;
3010 req->response_code = code;
3011 if (req->response_code_line != NULL)
3012 mm_free(req->response_code_line);
3014 reason = evhttp_response_phrase_internal(code);
3015 req->response_code_line = mm_strdup(reason);
3016 if (req->response_code_line == NULL) {
3017 event_warn("%s: strdup", __func__);
3018 /* XXX what else can we do? */
3023 evhttp_send_page_(struct evhttp_request *req, struct evbuffer *databuf)
3025 if (!req->major || !req->minor) {
3030 if (req->kind != EVHTTP_RESPONSE)
3031 evhttp_response_code_(req, 200, "OK");
3033 evhttp_clear_headers(req->output_headers);
3034 evhttp_add_header(req->output_headers, "Content-Type", "text/html");
3035 evhttp_add_header(req->output_headers, "Connection", "close");
3037 evhttp_send(req, databuf);
3040 static const char uri_chars[256] = {
3042 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3043 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3044 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0,
3045 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,
3047 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3048 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1,
3049 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3050 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0,
3052 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3053 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3054 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3055 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3057 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3058 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3059 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3060 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3063 #define CHAR_IS_UNRESERVED(c) \
3064 (uri_chars[(unsigned char)(c)])
3067 * Helper functions to encode/decode a string for inclusion in a URI.
3068 * The returned string must be freed by the caller.
3071 evhttp_uriencode(const char *uri, ev_ssize_t len, int space_as_plus)
3073 struct evbuffer *buf = evbuffer_new();
3074 const char *p, *end;
3076 ev_ssize_t c_len = len;
3083 if (len >= 0 && uri + len < uri) {
3084 if (uri + len < uri) {
3090 size_t slen = strlen(uri);
3092 if (slen >= EV_SSIZE_MAX) {
3093 /* we don't want to mix signed and unsigned */
3097 if (uri + slen < uri) {
3104 for (p = uri; p < end; p++) {
3105 if (CHAR_IS_UNRESERVED(*p)) {
3106 evbuffer_add(buf, p, 1);
3107 } else if (*p == ' ' && space_as_plus) {
3108 evbuffer_add(buf, "+", 1);
3110 evbuffer_add_printf(buf, "%%%02X", (unsigned char)(*p));
3114 evbuffer_add(buf, "", 1); /* NUL-terminator. */
3115 result = mm_malloc(evbuffer_get_length(buf));
3118 evbuffer_remove(buf, result, evbuffer_get_length(buf));
3126 evhttp_encode_uri(const char *str)
3128 return evhttp_uriencode(str, -1, 0);
3132 * @param decode_plus_ctl: if 1, we decode plus into space. If 0, we don't.
3133 * If -1, when true we transform plus to space only after we've seen
3134 * a ?. -1 is deprecated.
3135 * @return the number of bytes written to 'ret'.
3138 evhttp_decode_uri_internal(
3139 const char *uri, size_t length, char *ret, int decode_plus_ctl)
3143 int decode_plus = (decode_plus_ctl == 1) ? 1: 0;
3146 for (i = j = 0; i < length; i++) {
3149 if (decode_plus_ctl < 0)
3151 } else if (c == '+' && decode_plus) {
3153 } else if ((i + 2) < length && c == '%' &&
3154 EVUTIL_ISXDIGIT_(uri[i+1]) && EVUTIL_ISXDIGIT_(uri[i+2])) {
3159 c = (char)strtol(tmp, NULL, 16);
3171 evhttp_decode_uri(const char *uri)
3175 if ((ret = mm_malloc(strlen(uri) + 1)) == NULL) {
3176 event_warn("%s: malloc(%lu)", __func__,
3177 (unsigned long)(strlen(uri) + 1));
3181 evhttp_decode_uri_internal(uri, strlen(uri),
3182 ret, -1 /*always_decode_plus*/);
3188 evhttp_uridecode(const char *uri, int decode_plus, size_t *size_out)
3193 if ((ret = mm_malloc(strlen(uri) + 1)) == NULL) {
3194 event_warn("%s: malloc(%lu)", __func__,
3195 (unsigned long)(strlen(uri) + 1));
3199 n = evhttp_decode_uri_internal(uri, strlen(uri),
3200 ret, !!decode_plus/*always_decode_plus*/);
3203 EVUTIL_ASSERT(n >= 0);
3204 *size_out = (size_t)n;
3211 * Helper function to parse out arguments in a query.
3212 * The arguments are separated by key and value.
3216 evhttp_parse_query_impl(const char *str, struct evkeyvalq *headers,
3222 const char *query_part;
3224 struct evhttp_uri *uri=NULL;
3226 TAILQ_INIT(headers);
3229 uri = evhttp_uri_parse(str);
3232 query_part = evhttp_uri_get_query(uri);
3237 /* No arguments - we are done */
3238 if (!query_part || !strlen(query_part)) {
3243 if ((line = mm_strdup(query_part)) == NULL) {
3244 event_warn("%s: strdup", __func__);
3248 p = argument = line;
3249 while (p != NULL && *p != '\0') {
3250 char *key, *value, *decoded_value;
3251 argument = strsep(&p, "&");
3254 key = strsep(&value, "=");
3255 if (value == NULL || *key == '\0') {
3259 if ((decoded_value = mm_malloc(strlen(value) + 1)) == NULL) {
3260 event_warn("%s: mm_malloc", __func__);
3263 evhttp_decode_uri_internal(value, strlen(value),
3264 decoded_value, 1 /*always_decode_plus*/);
3265 event_debug(("Query Param: %s -> %s\n", key, decoded_value));
3266 evhttp_add_header_internal(headers, key, decoded_value);
3267 mm_free(decoded_value);
3273 evhttp_clear_headers(headers);
3278 evhttp_uri_free(uri);
3283 evhttp_parse_query(const char *uri, struct evkeyvalq *headers)
3285 return evhttp_parse_query_impl(uri, headers, 1);
3288 evhttp_parse_query_str(const char *uri, struct evkeyvalq *headers)
3290 return evhttp_parse_query_impl(uri, headers, 0);
3293 static struct evhttp_cb *
3294 evhttp_dispatch_callback(struct httpcbq *callbacks, struct evhttp_request *req)
3296 struct evhttp_cb *cb;
3301 /* Test for different URLs */
3302 path = evhttp_uri_get_path(req->uri_elems);
3303 offset = strlen(path);
3304 if ((translated = mm_malloc(offset + 1)) == NULL)
3306 evhttp_decode_uri_internal(path, offset, translated,
3307 0 /* decode_plus */);
3309 TAILQ_FOREACH(cb, callbacks, next) {
3310 if (!strcmp(cb->what, translated)) {
3311 mm_free(translated);
3316 mm_free(translated);
3322 prefix_suffix_match(const char *pattern, const char *name, int ignorecase)
3327 switch (c = *pattern++) {
3329 return *name == '\0';
3332 while (*name != '\0') {
3333 if (prefix_suffix_match(pattern, name,
3342 EVUTIL_TOLOWER_(c) != EVUTIL_TOLOWER_(*name))
3352 Search the vhost hierarchy beginning with http for a server alias
3353 matching hostname. If a match is found, and outhttp is non-null,
3354 outhttp is set to the matching http object and 1 is returned.
3358 evhttp_find_alias(struct evhttp *http, struct evhttp **outhttp,
3359 const char *hostname)
3361 struct evhttp_server_alias *alias;
3362 struct evhttp *vhost;
3364 TAILQ_FOREACH(alias, &http->aliases, next) {
3365 /* XXX Do we need to handle IP addresses? */
3366 if (!evutil_ascii_strcasecmp(alias->alias, hostname)) {
3373 /* XXX It might be good to avoid recursion here, but I don't
3374 see a way to do that w/o a list. */
3375 TAILQ_FOREACH(vhost, &http->virtualhosts, next_vhost) {
3376 if (evhttp_find_alias(vhost, outhttp, hostname))
3384 Attempts to find the best http object to handle a request for a hostname.
3385 All aliases for the root http object and vhosts are searched for an exact
3386 match. Then, the vhost hierarchy is traversed again for a matching
3389 If an alias or vhost is matched, 1 is returned, and outhttp, if non-null,
3390 is set with the best matching http object. If there are no matches, the
3391 root http object is stored in outhttp and 0 is returned.
3395 evhttp_find_vhost(struct evhttp *http, struct evhttp **outhttp,
3396 const char *hostname)
3398 struct evhttp *vhost;
3399 struct evhttp *oldhttp;
3400 int match_found = 0;
3402 if (evhttp_find_alias(http, outhttp, hostname))
3407 TAILQ_FOREACH(vhost, &http->virtualhosts, next_vhost) {
3408 if (prefix_suffix_match(vhost->vhost_pattern,
3409 hostname, 1 /* ignorecase */)) {
3415 } while (oldhttp != http);
3424 evhttp_handle_request(struct evhttp_request *req, void *arg)
3426 struct evhttp *http = arg;
3427 struct evhttp_cb *cb = NULL;
3428 const char *hostname;
3430 /* we have a new request on which the user needs to take action */
3433 if (req->type == 0 || req->uri == NULL) {
3434 evhttp_send_error(req, req->response_code, NULL);
3438 if ((http->allowed_methods & req->type) == 0) {
3439 event_debug(("Rejecting disallowed method %x (allowed: %x)\n",
3440 (unsigned)req->type, (unsigned)http->allowed_methods));
3441 evhttp_send_error(req, HTTP_NOTIMPLEMENTED, NULL);
3445 /* handle potential virtual hosts */
3446 hostname = evhttp_request_get_host(req);
3447 if (hostname != NULL) {
3448 evhttp_find_vhost(http, &http, hostname);
3451 if ((cb = evhttp_dispatch_callback(&http->callbacks, req)) != NULL) {
3452 (*cb->cb)(req, cb->cbarg);
3456 /* Generic call back */
3458 (*http->gencb)(req, http->gencbarg);
3461 /* We need to send a 404 here */
3462 #define ERR_FORMAT "<html><head>" \
3463 "<title>404 Not Found</title>" \
3465 "<h1>Not Found</h1>" \
3466 "<p>The requested URL %s was not found on this server.</p>"\
3470 struct evbuffer *buf;
3472 if ((escaped_html = evhttp_htmlescape(req->uri)) == NULL) {
3473 evhttp_connection_free(req->evcon);
3477 if ((buf = evbuffer_new()) == NULL) {
3478 mm_free(escaped_html);
3479 evhttp_connection_free(req->evcon);
3483 evhttp_response_code_(req, HTTP_NOTFOUND, "Not Found");
3485 evbuffer_add_printf(buf, ERR_FORMAT, escaped_html);
3487 mm_free(escaped_html);
3489 evhttp_send_page_(req, buf);
3496 /* Listener callback when a connection arrives at a server. */
3498 accept_socket_cb(struct evconnlistener *listener, evutil_socket_t nfd, struct sockaddr *peer_sa, int peer_socklen, void *arg)
3500 struct evhttp *http = arg;
3502 evhttp_get_request(http, nfd, peer_sa, peer_socklen);
3506 evhttp_bind_socket(struct evhttp *http, const char *address, ev_uint16_t port)
3508 struct evhttp_bound_socket *bound =
3509 evhttp_bind_socket_with_handle(http, address, port);
3515 struct evhttp_bound_socket *
3516 evhttp_bind_socket_with_handle(struct evhttp *http, const char *address, ev_uint16_t port)
3519 struct evhttp_bound_socket *bound;
3521 if ((fd = bind_socket(address, port, 1 /*reuse*/)) == -1)
3524 if (listen(fd, 128) == -1) {
3525 event_sock_warn(fd, "%s: listen", __func__);
3526 evutil_closesocket(fd);
3530 bound = evhttp_accept_socket_with_handle(http, fd);
3532 if (bound != NULL) {
3533 event_debug(("Bound to port %d - Awaiting connections ... ",
3542 evhttp_accept_socket(struct evhttp *http, evutil_socket_t fd)
3544 struct evhttp_bound_socket *bound =
3545 evhttp_accept_socket_with_handle(http, fd);
3552 evhttp_foreach_bound_socket(struct evhttp *http,
3553 evhttp_bound_socket_foreach_fn *function,
3556 struct evhttp_bound_socket *bound;
3558 TAILQ_FOREACH(bound, &http->sockets, next)
3559 function(bound, argument);
3562 struct evhttp_bound_socket *
3563 evhttp_accept_socket_with_handle(struct evhttp *http, evutil_socket_t fd)
3565 struct evhttp_bound_socket *bound;
3566 struct evconnlistener *listener;
3568 LEV_OPT_REUSEABLE|LEV_OPT_CLOSE_ON_EXEC|LEV_OPT_CLOSE_ON_FREE;
3570 listener = evconnlistener_new(http->base, NULL, NULL,
3572 0, /* Backlog is '0' because we already said 'listen' */
3577 bound = evhttp_bind_listener(http, listener);
3579 evconnlistener_free(listener);
3585 struct evhttp_bound_socket *
3586 evhttp_bind_listener(struct evhttp *http, struct evconnlistener *listener)
3588 struct evhttp_bound_socket *bound;
3590 bound = mm_malloc(sizeof(struct evhttp_bound_socket));
3594 bound->listener = listener;
3595 TAILQ_INSERT_TAIL(&http->sockets, bound, next);
3597 evconnlistener_set_cb(listener, accept_socket_cb, http);
3602 evhttp_bound_socket_get_fd(struct evhttp_bound_socket *bound)
3604 return evconnlistener_get_fd(bound->listener);
3607 struct evconnlistener *
3608 evhttp_bound_socket_get_listener(struct evhttp_bound_socket *bound)
3610 return bound->listener;
3614 evhttp_del_accept_socket(struct evhttp *http, struct evhttp_bound_socket *bound)
3616 TAILQ_REMOVE(&http->sockets, bound, next);
3617 evconnlistener_free(bound->listener);
3621 static struct evhttp*
3622 evhttp_new_object(void)
3624 struct evhttp *http = NULL;
3626 if ((http = mm_calloc(1, sizeof(struct evhttp))) == NULL) {
3627 event_warn("%s: calloc", __func__);
3631 evutil_timerclear(&http->timeout);
3632 evhttp_set_max_headers_size(http, EV_SIZE_MAX);
3633 evhttp_set_max_body_size(http, EV_SIZE_MAX);
3634 evhttp_set_default_content_type(http, "text/html; charset=ISO-8859-1");
3635 evhttp_set_allowed_methods(http,
3642 TAILQ_INIT(&http->sockets);
3643 TAILQ_INIT(&http->callbacks);
3644 TAILQ_INIT(&http->connections);
3645 TAILQ_INIT(&http->virtualhosts);
3646 TAILQ_INIT(&http->aliases);
3652 evhttp_new(struct event_base *base)
3654 struct evhttp *http = NULL;
3656 http = evhttp_new_object();
3665 * Start a web server on the specified address and port.
3669 evhttp_start(const char *address, unsigned short port)
3671 struct evhttp *http = NULL;
3673 http = evhttp_new_object();
3676 if (evhttp_bind_socket(http, address, port) == -1) {
3685 evhttp_free(struct evhttp* http)
3687 struct evhttp_cb *http_cb;
3688 struct evhttp_connection *evcon;
3689 struct evhttp_bound_socket *bound;
3690 struct evhttp* vhost;
3691 struct evhttp_server_alias *alias;
3693 /* Remove the accepting part */
3694 while ((bound = TAILQ_FIRST(&http->sockets)) != NULL) {
3695 TAILQ_REMOVE(&http->sockets, bound, next);
3697 evconnlistener_free(bound->listener);
3702 while ((evcon = TAILQ_FIRST(&http->connections)) != NULL) {
3703 /* evhttp_connection_free removes the connection */
3704 evhttp_connection_free(evcon);
3707 while ((http_cb = TAILQ_FIRST(&http->callbacks)) != NULL) {
3708 TAILQ_REMOVE(&http->callbacks, http_cb, next);
3709 mm_free(http_cb->what);
3713 while ((vhost = TAILQ_FIRST(&http->virtualhosts)) != NULL) {
3714 TAILQ_REMOVE(&http->virtualhosts, vhost, next_vhost);
3719 if (http->vhost_pattern != NULL)
3720 mm_free(http->vhost_pattern);
3722 while ((alias = TAILQ_FIRST(&http->aliases)) != NULL) {
3723 TAILQ_REMOVE(&http->aliases, alias, next);
3724 mm_free(alias->alias);
3732 evhttp_add_virtual_host(struct evhttp* http, const char *pattern,
3733 struct evhttp* vhost)
3735 /* a vhost can only be a vhost once and should not have bound sockets */
3736 if (vhost->vhost_pattern != NULL ||
3737 TAILQ_FIRST(&vhost->sockets) != NULL)
3740 vhost->vhost_pattern = mm_strdup(pattern);
3741 if (vhost->vhost_pattern == NULL)
3744 TAILQ_INSERT_TAIL(&http->virtualhosts, vhost, next_vhost);
3750 evhttp_remove_virtual_host(struct evhttp* http, struct evhttp* vhost)
3752 if (vhost->vhost_pattern == NULL)
3755 TAILQ_REMOVE(&http->virtualhosts, vhost, next_vhost);
3757 mm_free(vhost->vhost_pattern);
3758 vhost->vhost_pattern = NULL;
3764 evhttp_add_server_alias(struct evhttp *http, const char *alias)
3766 struct evhttp_server_alias *evalias;
3768 evalias = mm_calloc(1, sizeof(*evalias));
3772 evalias->alias = mm_strdup(alias);
3773 if (!evalias->alias) {
3778 TAILQ_INSERT_TAIL(&http->aliases, evalias, next);
3784 evhttp_remove_server_alias(struct evhttp *http, const char *alias)
3786 struct evhttp_server_alias *evalias;
3788 TAILQ_FOREACH(evalias, &http->aliases, next) {
3789 if (evutil_ascii_strcasecmp(evalias->alias, alias) == 0) {
3790 TAILQ_REMOVE(&http->aliases, evalias, next);
3791 mm_free(evalias->alias);
3801 evhttp_set_timeout(struct evhttp* http, int timeout_in_secs)
3803 if (timeout_in_secs == -1) {
3804 evhttp_set_timeout_tv(http, NULL);
3807 tv.tv_sec = timeout_in_secs;
3809 evhttp_set_timeout_tv(http, &tv);
3814 evhttp_set_timeout_tv(struct evhttp* http, const struct timeval* tv)
3817 http->timeout = *tv;
3819 evutil_timerclear(&http->timeout);
3823 int evhttp_set_flags(struct evhttp *http, int flags)
3825 int avail_flags = 0;
3826 avail_flags |= EVHTTP_SERVER_LINGERING_CLOSE;
3828 if (flags & ~avail_flags)
3830 http->flags &= ~avail_flags;
3832 http->flags |= flags;
3838 evhttp_set_max_headers_size(struct evhttp* http, ev_ssize_t max_headers_size)
3840 if (max_headers_size < 0)
3841 http->default_max_headers_size = EV_SIZE_MAX;
3843 http->default_max_headers_size = max_headers_size;
3847 evhttp_set_max_body_size(struct evhttp* http, ev_ssize_t max_body_size)
3849 if (max_body_size < 0)
3850 http->default_max_body_size = EV_UINT64_MAX;
3852 http->default_max_body_size = max_body_size;
3856 evhttp_set_default_content_type(struct evhttp *http,
3857 const char *content_type) {
3858 http->default_content_type = content_type;
3862 evhttp_set_allowed_methods(struct evhttp* http, ev_uint16_t methods)
3864 http->allowed_methods = methods;
3868 evhttp_set_cb(struct evhttp *http, const char *uri,
3869 void (*cb)(struct evhttp_request *, void *), void *cbarg)
3871 struct evhttp_cb *http_cb;
3873 TAILQ_FOREACH(http_cb, &http->callbacks, next) {
3874 if (strcmp(http_cb->what, uri) == 0)
3878 if ((http_cb = mm_calloc(1, sizeof(struct evhttp_cb))) == NULL) {
3879 event_warn("%s: calloc", __func__);
3883 http_cb->what = mm_strdup(uri);
3884 if (http_cb->what == NULL) {
3885 event_warn("%s: strdup", __func__);
3890 http_cb->cbarg = cbarg;
3892 TAILQ_INSERT_TAIL(&http->callbacks, http_cb, next);
3898 evhttp_del_cb(struct evhttp *http, const char *uri)
3900 struct evhttp_cb *http_cb;
3902 TAILQ_FOREACH(http_cb, &http->callbacks, next) {
3903 if (strcmp(http_cb->what, uri) == 0)
3906 if (http_cb == NULL)
3909 TAILQ_REMOVE(&http->callbacks, http_cb, next);
3910 mm_free(http_cb->what);
3917 evhttp_set_gencb(struct evhttp *http,
3918 void (*cb)(struct evhttp_request *, void *), void *cbarg)
3921 http->gencbarg = cbarg;
3925 evhttp_set_bevcb(struct evhttp *http,
3926 struct bufferevent* (*cb)(struct event_base *, void *), void *cbarg)
3929 http->bevcbarg = cbarg;
3933 * Request related functions
3936 struct evhttp_request *
3937 evhttp_request_new(void (*cb)(struct evhttp_request *, void *), void *arg)
3939 struct evhttp_request *req = NULL;
3941 /* Allocate request structure */
3942 if ((req = mm_calloc(1, sizeof(struct evhttp_request))) == NULL) {
3943 event_warn("%s: calloc", __func__);
3947 req->headers_size = 0;
3950 req->kind = EVHTTP_RESPONSE;
3951 req->input_headers = mm_calloc(1, sizeof(struct evkeyvalq));
3952 if (req->input_headers == NULL) {
3953 event_warn("%s: calloc", __func__);
3956 TAILQ_INIT(req->input_headers);
3958 req->output_headers = mm_calloc(1, sizeof(struct evkeyvalq));
3959 if (req->output_headers == NULL) {
3960 event_warn("%s: calloc", __func__);
3963 TAILQ_INIT(req->output_headers);
3965 if ((req->input_buffer = evbuffer_new()) == NULL) {
3966 event_warn("%s: evbuffer_new", __func__);
3970 if ((req->output_buffer = evbuffer_new()) == NULL) {
3971 event_warn("%s: evbuffer_new", __func__);
3982 evhttp_request_free(req);
3987 evhttp_request_free(struct evhttp_request *req)
3989 if ((req->flags & EVHTTP_REQ_DEFER_FREE) != 0) {
3990 req->flags |= EVHTTP_REQ_NEEDS_FREE;
3994 if (req->remote_host != NULL)
3995 mm_free(req->remote_host);
3996 if (req->uri != NULL)
3998 if (req->uri_elems != NULL)
3999 evhttp_uri_free(req->uri_elems);
4000 if (req->response_code_line != NULL)
4001 mm_free(req->response_code_line);
4002 if (req->host_cache != NULL)
4003 mm_free(req->host_cache);
4005 evhttp_clear_headers(req->input_headers);
4006 mm_free(req->input_headers);
4008 evhttp_clear_headers(req->output_headers);
4009 mm_free(req->output_headers);
4011 if (req->input_buffer != NULL)
4012 evbuffer_free(req->input_buffer);
4014 if (req->output_buffer != NULL)
4015 evbuffer_free(req->output_buffer);
4021 evhttp_request_own(struct evhttp_request *req)
4023 req->flags |= EVHTTP_USER_OWNED;
4027 evhttp_request_is_owned(struct evhttp_request *req)
4029 return (req->flags & EVHTTP_USER_OWNED) != 0;
4032 struct evhttp_connection *
4033 evhttp_request_get_connection(struct evhttp_request *req)
4039 evhttp_connection_get_base(struct evhttp_connection *conn)
4045 evhttp_request_set_chunked_cb(struct evhttp_request *req,
4046 void (*cb)(struct evhttp_request *, void *))
4052 evhttp_request_set_header_cb(struct evhttp_request *req,
4053 int (*cb)(struct evhttp_request *, void *))
4055 req->header_cb = cb;
4059 evhttp_request_set_error_cb(struct evhttp_request *req,
4060 void (*cb)(enum evhttp_request_error, void *))
4066 evhttp_request_set_on_complete_cb(struct evhttp_request *req,
4067 void (*cb)(struct evhttp_request *, void *), void *cb_arg)
4069 req->on_complete_cb = cb;
4070 req->on_complete_cb_arg = cb_arg;
4074 * Allows for inspection of the request URI
4078 evhttp_request_get_uri(const struct evhttp_request *req) {
4079 if (req->uri == NULL)
4080 event_debug(("%s: request %p has no uri\n", __func__, req));
4084 const struct evhttp_uri *
4085 evhttp_request_get_evhttp_uri(const struct evhttp_request *req) {
4086 if (req->uri_elems == NULL)
4087 event_debug(("%s: request %p has no uri elems\n",
4089 return (req->uri_elems);
4093 evhttp_request_get_host(struct evhttp_request *req)
4095 const char *host = NULL;
4097 if (req->host_cache)
4098 return req->host_cache;
4101 host = evhttp_uri_get_host(req->uri_elems);
4102 if (!host && req->input_headers) {
4106 host = evhttp_find_header(req->input_headers, "Host");
4107 /* The Host: header may include a port. Remove it here
4108 to be consistent with uri_elems case above. */
4110 p = host + strlen(host) - 1;
4111 while (p > host && EVUTIL_ISDIGIT_(*p))
4113 if (p > host && *p == ':') {
4115 req->host_cache = mm_malloc(len + 1);
4116 if (!req->host_cache) {
4117 event_warn("%s: malloc", __func__);
4120 memcpy(req->host_cache, host, len);
4121 req->host_cache[len] = '\0';
4122 host = req->host_cache;
4130 enum evhttp_cmd_type
4131 evhttp_request_get_command(const struct evhttp_request *req) {
4136 evhttp_request_get_response_code(const struct evhttp_request *req)
4138 return req->response_code;
4142 evhttp_request_get_response_code_line(const struct evhttp_request *req)
4144 return req->response_code_line;
4147 /** Returns the input headers */
4148 struct evkeyvalq *evhttp_request_get_input_headers(struct evhttp_request *req)
4150 return (req->input_headers);
4153 /** Returns the output headers */
4154 struct evkeyvalq *evhttp_request_get_output_headers(struct evhttp_request *req)
4156 return (req->output_headers);
4159 /** Returns the input buffer */
4160 struct evbuffer *evhttp_request_get_input_buffer(struct evhttp_request *req)
4162 return (req->input_buffer);
4165 /** Returns the output buffer */
4166 struct evbuffer *evhttp_request_get_output_buffer(struct evhttp_request *req)
4168 return (req->output_buffer);
4173 * Takes a file descriptor to read a request from.
4174 * The callback is executed once the whole request has been read.
4177 static struct evhttp_connection*
4178 evhttp_get_request_connection(
4179 struct evhttp* http,
4180 evutil_socket_t fd, struct sockaddr *sa, ev_socklen_t salen)
4182 struct evhttp_connection *evcon;
4183 char *hostname = NULL, *portname = NULL;
4184 struct bufferevent* bev = NULL;
4186 name_from_addr(sa, salen, &hostname, &portname);
4187 if (hostname == NULL || portname == NULL) {
4188 if (hostname) mm_free(hostname);
4189 if (portname) mm_free(portname);
4193 event_debug(("%s: new request from %s:%s on "EV_SOCK_FMT"\n",
4194 __func__, hostname, portname, EV_SOCK_ARG(fd)));
4196 /* we need a connection object to put the http request on */
4197 if (http->bevcb != NULL) {
4198 bev = (*http->bevcb)(http->base, http->bevcbarg);
4200 evcon = evhttp_connection_base_bufferevent_new(
4201 http->base, NULL, bev, hostname, atoi(portname));
4207 evcon->max_headers_size = http->default_max_headers_size;
4208 evcon->max_body_size = http->default_max_body_size;
4209 if (http->flags & EVHTTP_SERVER_LINGERING_CLOSE)
4210 evcon->flags |= EVHTTP_CON_LINGERING_CLOSE;
4212 evcon->flags |= EVHTTP_CON_INCOMING;
4213 evcon->state = EVCON_READING_FIRSTLINE;
4217 bufferevent_enable(evcon->bufev, EV_READ);
4218 bufferevent_disable(evcon->bufev, EV_WRITE);
4219 bufferevent_setfd(evcon->bufev, fd);
4225 evhttp_associate_new_request_with_connection(struct evhttp_connection *evcon)
4227 struct evhttp *http = evcon->http_server;
4228 struct evhttp_request *req;
4229 if ((req = evhttp_request_new(evhttp_handle_request, http)) == NULL)
4232 if ((req->remote_host = mm_strdup(evcon->address)) == NULL) {
4233 event_warn("%s: strdup", __func__);
4234 evhttp_request_free(req);
4237 req->remote_port = evcon->port;
4239 req->evcon = evcon; /* the request ends up owning the connection */
4240 req->flags |= EVHTTP_REQ_OWN_CONNECTION;
4242 /* We did not present the request to the user user yet, so treat it as
4243 * if the user was done with the request. This allows us to free the
4244 * request on a persistent connection if the client drops it without
4245 * sending a request.
4249 TAILQ_INSERT_TAIL(&evcon->requests, req, next);
4251 req->kind = EVHTTP_REQUEST;
4254 evhttp_start_read_(evcon);
4260 evhttp_get_request(struct evhttp *http, evutil_socket_t fd,
4261 struct sockaddr *sa, ev_socklen_t salen)
4263 struct evhttp_connection *evcon;
4265 evcon = evhttp_get_request_connection(http, fd, sa, salen);
4266 if (evcon == NULL) {
4267 event_sock_warn(fd, "%s: cannot get connection on "EV_SOCK_FMT,
4268 __func__, EV_SOCK_ARG(fd));
4269 evutil_closesocket(fd);
4273 /* the timeout can be used by the server to close idle connections */
4274 if (evutil_timerisset(&http->timeout))
4275 evhttp_connection_set_timeout_tv(evcon, &http->timeout);
4278 * if we want to accept more than one request on a connection,
4279 * we need to know which http server it belongs to.
4281 evcon->http_server = http;
4282 TAILQ_INSERT_TAIL(&http->connections, evcon, next);
4284 if (evhttp_associate_new_request_with_connection(evcon) == -1)
4285 evhttp_connection_free(evcon);
4290 * Network helper functions that we do not want to export to the rest of
4295 name_from_addr(struct sockaddr *sa, ev_socklen_t salen,
4296 char **phost, char **pport)
4298 char ntop[NI_MAXHOST];
4299 char strport[NI_MAXSERV];
4302 #ifdef EVENT__HAVE_GETNAMEINFO
4303 ni_result = getnameinfo(sa, salen,
4304 ntop, sizeof(ntop), strport, sizeof(strport),
4305 NI_NUMERICHOST|NI_NUMERICSERV);
4307 if (ni_result != 0) {
4309 /* Windows doesn't have an EAI_SYSTEM. */
4310 if (ni_result == EAI_SYSTEM)
4311 event_err(1, "getnameinfo failed");
4314 event_errx(1, "getnameinfo failed: %s", gai_strerror(ni_result));
4318 ni_result = fake_getnameinfo(sa, salen,
4319 ntop, sizeof(ntop), strport, sizeof(strport),
4320 NI_NUMERICHOST|NI_NUMERICSERV);
4325 *phost = mm_strdup(ntop);
4326 *pport = mm_strdup(strport);
4329 /* Create a non-blocking socket and bind it */
4330 /* todo: rename this function */
4331 static evutil_socket_t
4332 bind_socket_ai(struct evutil_addrinfo *ai, int reuse)
4339 /* Create listen socket */
4340 fd = evutil_socket_(ai ? ai->ai_family : AF_INET,
4341 SOCK_STREAM|EVUTIL_SOCK_NONBLOCK|EVUTIL_SOCK_CLOEXEC, 0);
4343 event_sock_warn(-1, "socket");
4347 if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (void *)&on, sizeof(on))<0)
4350 if (evutil_make_listen_socket_reuseable(fd) < 0)
4355 r = bind(fd, ai->ai_addr, (ev_socklen_t)ai->ai_addrlen);
4363 serrno = EVUTIL_SOCKET_ERROR();
4364 evutil_closesocket(fd);
4365 EVUTIL_SET_SOCKET_ERROR(serrno);
4369 static struct evutil_addrinfo *
4370 make_addrinfo(const char *address, ev_uint16_t port)
4372 struct evutil_addrinfo *ai = NULL;
4374 struct evutil_addrinfo hints;
4375 char strport[NI_MAXSERV];
4378 memset(&hints, 0, sizeof(hints));
4379 hints.ai_family = AF_UNSPEC;
4380 hints.ai_socktype = SOCK_STREAM;
4381 /* turn NULL hostname into INADDR_ANY, and skip looking up any address
4382 * types we don't have an interface to connect to. */
4383 hints.ai_flags = EVUTIL_AI_PASSIVE|EVUTIL_AI_ADDRCONFIG;
4384 evutil_snprintf(strport, sizeof(strport), "%d", port);
4385 if ((ai_result = evutil_getaddrinfo(address, strport, &hints, &ai))
4387 if (ai_result == EVUTIL_EAI_SYSTEM)
4388 event_warn("getaddrinfo");
4390 event_warnx("getaddrinfo: %s",
4391 evutil_gai_strerror(ai_result));
4398 static evutil_socket_t
4399 bind_socket(const char *address, ev_uint16_t port, int reuse)
4402 struct evutil_addrinfo *aitop = NULL;
4404 /* just create an unbound socket */
4405 if (address == NULL && port == 0)
4406 return bind_socket_ai(NULL, 0);
4408 aitop = make_addrinfo(address, port);
4413 fd = bind_socket_ai(aitop, reuse);
4415 evutil_freeaddrinfo(aitop);
4422 char *scheme; /* scheme; e.g http, ftp etc */
4423 char *userinfo; /* userinfo (typically username:pass), or NULL */
4424 char *host; /* hostname, IP address, or NULL */
4425 int port; /* port, or zero */
4426 char *path; /* path, or "". */
4427 char *query; /* query, or NULL */
4428 char *fragment; /* fragment or NULL */
4432 evhttp_uri_new(void)
4434 struct evhttp_uri *uri = mm_calloc(sizeof(struct evhttp_uri), 1);
4441 evhttp_uri_set_flags(struct evhttp_uri *uri, unsigned flags)
4446 /* Return true if the string starting at s and ending immediately before eos
4447 * is a valid URI scheme according to RFC3986
4450 scheme_ok(const char *s, const char *eos)
4452 /* scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." ) */
4453 EVUTIL_ASSERT(eos >= s);
4456 if (!EVUTIL_ISALPHA_(*s))
4459 if (! EVUTIL_ISALNUM_(*s) &&
4460 *s != '+' && *s != '-' && *s != '.')
4466 #define SUBDELIMS "!$&'()*+,;="
4468 /* Return true iff [s..eos) is a valid userinfo */
4470 userinfo_ok(const char *s, const char *eos)
4473 if (CHAR_IS_UNRESERVED(*s) ||
4474 strchr(SUBDELIMS, *s) ||
4477 else if (*s == '%' && s+2 < eos &&
4478 EVUTIL_ISXDIGIT_(s[1]) &&
4479 EVUTIL_ISXDIGIT_(s[2]))
4488 regname_ok(const char *s, const char *eos)
4490 while (s && s<eos) {
4491 if (CHAR_IS_UNRESERVED(*s) ||
4492 strchr(SUBDELIMS, *s))
4494 else if (*s == '%' &&
4495 EVUTIL_ISXDIGIT_(s[1]) &&
4496 EVUTIL_ISXDIGIT_(s[2]))
4505 parse_port(const char *s, const char *eos)
4509 if (! EVUTIL_ISDIGIT_(*s))
4511 portnum = (portnum * 10) + (*s - '0');
4514 if (portnum > 65535)
4521 /* returns 0 for bad, 1 for ipv6, 2 for IPvFuture */
4523 bracket_addr_ok(const char *s, const char *eos)
4525 if (s + 3 > eos || *s != '[' || *(eos-1) != ']')
4528 /* IPvFuture, or junk.
4529 "v" 1*HEXDIG "." 1*( unreserved / sub-delims / ":" )
4531 s += 2; /* skip [v */
4533 if (!EVUTIL_ISXDIGIT_(*s)) /*require at least one*/
4535 while (s < eos && *s != '.') {
4536 if (EVUTIL_ISXDIGIT_(*s))
4545 if (CHAR_IS_UNRESERVED(*s) ||
4546 strchr(SUBDELIMS, *s) ||
4556 ev_ssize_t n_chars = eos-s-2;
4557 struct in6_addr in6;
4558 if (n_chars >= 64) /* way too long */
4560 memcpy(buf, s+1, n_chars);
4562 return (evutil_inet_pton(AF_INET6,buf,&in6)==1) ? 1 : 0;
4567 parse_authority(struct evhttp_uri *uri, char *s, char *eos)
4572 uri->host = mm_strdup("");
4573 if (uri->host == NULL) {
4574 event_warn("%s: strdup", __func__);
4580 /* Optionally, we start with "userinfo@" */
4582 cp = strchr(s, '@');
4583 if (cp && cp < eos) {
4584 if (! userinfo_ok(s,cp))
4587 uri->userinfo = mm_strdup(s);
4588 if (uri->userinfo == NULL) {
4589 event_warn("%s: strdup", __func__);
4595 /* Optionally, we end with ":port" */
4596 for (port=eos-1; port >= cp && EVUTIL_ISDIGIT_(*port); --port)
4598 if (port >= cp && *port == ':') {
4599 if (port+1 == eos) /* Leave port unspecified; the RFC allows a
4602 else if ((uri->port = parse_port(port+1, eos))<0)
4606 /* Now, cp..eos holds the "host" port, which can be an IPv4Address,
4607 * an IP-Literal, or a reg-name */
4608 EVUTIL_ASSERT(eos >= cp);
4609 if (*cp == '[' && eos >= cp+2 && *(eos-1) == ']') {
4610 /* IPv6address, IP-Literal, or junk. */
4611 if (! bracket_addr_ok(cp, eos))
4614 /* Make sure the host part is ok. */
4615 if (! regname_ok(cp,eos)) /* Match IPv4Address or reg-name */
4618 uri->host = mm_malloc(eos-cp+1);
4619 if (uri->host == NULL) {
4620 event_warn("%s: malloc", __func__);
4623 memcpy(uri->host, cp, eos-cp);
4624 uri->host[eos-cp] = '\0';
4630 end_of_authority(char *cp)
4633 if (*cp == '?' || *cp == '#' || *cp == '/')
4646 /* Return the character after the longest prefix of 'cp' that matches...
4647 * *pchar / "/" if allow_qchars is false, or
4648 * *(pchar / "/" / "?") if allow_qchars is true.
4651 end_of_path(char *cp, enum uri_part part, unsigned flags)
4653 if (flags & EVHTTP_URI_NONCONFORMANT) {
4654 /* If NONCONFORMANT:
4655 * Path is everything up to a # or ? or nul.
4656 * Query is everything up a # or nul
4657 * Fragment is everything up to a nul.
4661 while (*cp && *cp != '#' && *cp != '?')
4665 while (*cp && *cp != '#')
4676 if (CHAR_IS_UNRESERVED(*cp) ||
4677 strchr(SUBDELIMS, *cp) ||
4678 *cp == ':' || *cp == '@' || *cp == '/')
4680 else if (*cp == '%' && EVUTIL_ISXDIGIT_(cp[1]) &&
4681 EVUTIL_ISXDIGIT_(cp[2]))
4683 else if (*cp == '?' && part != PART_PATH)
4692 path_matches_noscheme(const char *cp)
4697 else if (*cp == '/')
4705 evhttp_uri_parse(const char *source_uri)
4707 return evhttp_uri_parse_with_flags(source_uri, 0);
4711 evhttp_uri_parse_with_flags(const char *source_uri, unsigned flags)
4713 char *readbuf = NULL, *readp = NULL, *token = NULL, *query = NULL;
4714 char *path = NULL, *fragment = NULL;
4715 int got_authority = 0;
4717 struct evhttp_uri *uri = mm_calloc(1, sizeof(struct evhttp_uri));
4719 event_warn("%s: calloc", __func__);
4725 readbuf = mm_strdup(source_uri);
4726 if (readbuf == NULL) {
4727 event_warn("%s: strdup", __func__);
4734 /* We try to follow RFC3986 here as much as we can, and match
4737 URI = scheme ":" hier-part [ "?" query ] [ "#" fragment ]
4739 relative-ref = relative-part [ "?" query ] [ "#" fragment ]
4743 token = strchr(readp, ':');
4744 if (token && scheme_ok(readp,token)) {
4746 uri->scheme = mm_strdup(readp);
4747 if (uri->scheme == NULL) {
4748 event_warn("%s: strdup", __func__);
4751 readp = token+1; /* eat : */
4754 /* 2. Optionally, "//" then an 'authority' part. */
4755 if (readp[0]=='/' && readp[1] == '/') {
4759 path = end_of_authority(readp);
4760 if (parse_authority(uri, authority, path) < 0)
4766 /* 3. Query: path-abempty, path-absolute, path-rootless, or path-empty
4769 readp = end_of_path(path, PART_PATH, flags);
4772 if (*readp == '?') {
4776 readp = end_of_path(readp, PART_QUERY, flags);
4779 if (*readp == '#') {
4783 readp = end_of_path(readp, PART_FRAGMENT, flags);
4785 if (*readp != '\0') {
4789 /* These next two cases may be unreachable; I'm leaving them
4790 * in to be defensive. */
4791 /* If you didn't get an authority, the path can't begin with "//" */
4792 if (!got_authority && path[0]=='/' && path[1]=='/')
4794 /* If you did get an authority, the path must begin with "/" or be
4796 if (got_authority && path[0] != '/' && path[0] != '\0')
4798 /* (End of maybe-unreachable cases) */
4800 /* If there was no scheme, the first part of the path (if any) must
4801 * have no colon in it. */
4802 if (! uri->scheme && !path_matches_noscheme(path))
4805 EVUTIL_ASSERT(path);
4806 uri->path = mm_strdup(path);
4807 if (uri->path == NULL) {
4808 event_warn("%s: strdup", __func__);
4813 uri->query = mm_strdup(query);
4814 if (uri->query == NULL) {
4815 event_warn("%s: strdup", __func__);
4820 uri->fragment = mm_strdup(fragment);
4821 if (uri->fragment == NULL) {
4822 event_warn("%s: strdup", __func__);
4832 evhttp_uri_free(uri);
4839 evhttp_uri_free(struct evhttp_uri *uri)
4841 #define URI_FREE_STR_(f) \
4846 URI_FREE_STR_(scheme);
4847 URI_FREE_STR_(userinfo);
4848 URI_FREE_STR_(host);
4849 URI_FREE_STR_(path);
4850 URI_FREE_STR_(query);
4851 URI_FREE_STR_(fragment);
4854 #undef URI_FREE_STR_
4858 evhttp_uri_join(struct evhttp_uri *uri, char *buf, size_t limit)
4860 struct evbuffer *tmp = 0;
4861 size_t joined_size = 0;
4862 char *output = NULL;
4864 #define URI_ADD_(f) evbuffer_add(tmp, uri->f, strlen(uri->f))
4866 if (!uri || !buf || !limit)
4869 tmp = evbuffer_new();
4875 evbuffer_add(tmp, ":", 1);
4878 evbuffer_add(tmp, "//", 2);
4880 evbuffer_add_printf(tmp,"%s@", uri->userinfo);
4883 evbuffer_add_printf(tmp,":%d", uri->port);
4885 if (uri->path && uri->path[0] != '/' && uri->path[0] != '\0')
4893 evbuffer_add(tmp, "?", 1);
4897 if (uri->fragment) {
4898 evbuffer_add(tmp, "#", 1);
4902 evbuffer_add(tmp, "\0", 1); /* NUL */
4904 joined_size = evbuffer_get_length(tmp);
4906 if (joined_size > limit) {
4907 /* It doesn't fit. */
4911 evbuffer_remove(tmp, buf, joined_size);
4922 evhttp_uri_get_scheme(const struct evhttp_uri *uri)
4927 evhttp_uri_get_userinfo(const struct evhttp_uri *uri)
4929 return uri->userinfo;
4932 evhttp_uri_get_host(const struct evhttp_uri *uri)
4937 evhttp_uri_get_port(const struct evhttp_uri *uri)
4942 evhttp_uri_get_path(const struct evhttp_uri *uri)
4947 evhttp_uri_get_query(const struct evhttp_uri *uri)
4952 evhttp_uri_get_fragment(const struct evhttp_uri *uri)
4954 return uri->fragment;
4957 #define URI_SET_STR_(f) do { \
4961 if ((uri->f = mm_strdup(f)) == NULL) { \
4962 event_warn("%s: strdup()", __func__); \
4971 evhttp_uri_set_scheme(struct evhttp_uri *uri, const char *scheme)
4973 if (scheme && !scheme_ok(scheme, scheme+strlen(scheme)))
4976 URI_SET_STR_(scheme);
4980 evhttp_uri_set_userinfo(struct evhttp_uri *uri, const char *userinfo)
4982 if (userinfo && !userinfo_ok(userinfo, userinfo+strlen(userinfo)))
4984 URI_SET_STR_(userinfo);
4988 evhttp_uri_set_host(struct evhttp_uri *uri, const char *host)
4991 if (host[0] == '[') {
4992 if (! bracket_addr_ok(host, host+strlen(host)))
4995 if (! regname_ok(host, host+strlen(host)))
5004 evhttp_uri_set_port(struct evhttp_uri *uri, int port)
5011 #define end_of_cpath(cp,p,f) \
5012 ((const char*)(end_of_path(((char*)(cp)), (p), (f))))
5015 evhttp_uri_set_path(struct evhttp_uri *uri, const char *path)
5017 if (path && end_of_cpath(path, PART_PATH, uri->flags) != path+strlen(path))
5024 evhttp_uri_set_query(struct evhttp_uri *uri, const char *query)
5026 if (query && end_of_cpath(query, PART_QUERY, uri->flags) != query+strlen(query))
5028 URI_SET_STR_(query);
5032 evhttp_uri_set_fragment(struct evhttp_uri *uri, const char *fragment)
5034 if (fragment && end_of_cpath(fragment, PART_FRAGMENT, uri->flags) != fragment+strlen(fragment))
5036 URI_SET_STR_(fragment);