2 * Copyright (c) 2002-2007 Niels Provos <provos@citi.umich.edu>
3 * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. The name of the author may not be used to endorse or promote products
14 * derived from this software without specific prior written permission.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 #include "event2/event-config.h"
29 #include "evconfig-private.h"
31 #ifdef EVENT__HAVE_SYS_PARAM_H
32 #include <sys/param.h>
34 #ifdef EVENT__HAVE_SYS_TYPES_H
35 #include <sys/types.h>
38 #ifdef HAVE_SYS_IOCCOM_H
39 #include <sys/ioccom.h>
41 #ifdef EVENT__HAVE_SYS_RESOURCE_H
42 #include <sys/resource.h>
44 #ifdef EVENT__HAVE_SYS_TIME_H
47 #ifdef EVENT__HAVE_SYS_WAIT_H
52 #include <sys/socket.h>
59 #include <sys/queue.h>
61 #ifdef EVENT__HAVE_NETINET_IN_H
62 #include <netinet/in.h>
64 #ifdef EVENT__HAVE_ARPA_INET_H
65 #include <arpa/inet.h>
67 #ifdef EVENT__HAVE_NETDB_H
83 #ifdef EVENT__HAVE_UNISTD_H
86 #ifdef EVENT__HAVE_FCNTL_H
90 #undef timeout_pending
91 #undef timeout_initialized
93 #include "strlcpy-internal.h"
94 #include "event2/http.h"
95 #include "event2/event.h"
96 #include "event2/buffer.h"
97 #include "event2/bufferevent.h"
98 #include "event2/http_struct.h"
99 #include "event2/http_compat.h"
100 #include "event2/util.h"
101 #include "event2/listener.h"
102 #include "log-internal.h"
103 #include "util-internal.h"
104 #include "http-internal.h"
105 #include "mm-internal.h"
106 #include "bufferevent-internal.h"
108 #ifndef EVENT__HAVE_GETNAMEINFO
109 #define NI_MAXSERV 32
110 #define NI_MAXHOST 1025
112 #ifndef NI_NUMERICHOST
113 #define NI_NUMERICHOST 1
116 #ifndef NI_NUMERICSERV
117 #define NI_NUMERICSERV 2
121 fake_getnameinfo(const struct sockaddr *sa, size_t salen, char *host,
122 size_t hostlen, char *serv, size_t servlen, int flags)
124 struct sockaddr_in *sin = (struct sockaddr_in *)sa;
128 evutil_snprintf(tmpserv, sizeof(tmpserv),
129 "%d", ntohs(sin->sin_port));
130 if (strlcpy(serv, tmpserv, servlen) >= servlen)
135 if (flags & NI_NUMERICHOST) {
136 if (strlcpy(host, inet_ntoa(sin->sin_addr),
143 hp = gethostbyaddr((char *)&sin->sin_addr,
144 sizeof(struct in_addr), AF_INET);
148 if (strlcpy(host, hp->h_name, hostlen) >= hostlen)
159 #define REQ_VERSION_BEFORE(req, major_v, minor_v) \
160 ((req)->major < (major_v) || \
161 ((req)->major == (major_v) && (req)->minor < (minor_v)))
163 #define REQ_VERSION_ATLEAST(req, major_v, minor_v) \
164 ((req)->major > (major_v) || \
165 ((req)->major == (major_v) && (req)->minor >= (minor_v)))
168 #define MIN(a,b) (((a)<(b))?(a):(b))
173 static evutil_socket_t bind_socket_ai(struct evutil_addrinfo *, int reuse);
174 static evutil_socket_t bind_socket(const char *, ev_uint16_t, int reuse);
175 static void name_from_addr(struct sockaddr *, ev_socklen_t, char **, char **);
176 static int evhttp_associate_new_request_with_connection(
177 struct evhttp_connection *evcon);
178 static void evhttp_connection_start_detectclose(
179 struct evhttp_connection *evcon);
180 static void evhttp_connection_stop_detectclose(
181 struct evhttp_connection *evcon);
182 static void evhttp_request_dispatch(struct evhttp_connection* evcon);
183 static void evhttp_read_firstline(struct evhttp_connection *evcon,
184 struct evhttp_request *req);
185 static void evhttp_read_header(struct evhttp_connection *evcon,
186 struct evhttp_request *req);
187 static int evhttp_add_header_internal(struct evkeyvalq *headers,
188 const char *key, const char *value);
189 static const char *evhttp_response_phrase_internal(int code);
190 static void evhttp_get_request(struct evhttp *, evutil_socket_t, struct sockaddr *, ev_socklen_t);
191 static void evhttp_write_buffer(struct evhttp_connection *,
192 void (*)(struct evhttp_connection *, void *), void *);
193 static void evhttp_make_header(struct evhttp_connection *, struct evhttp_request *);
195 /* callbacks for bufferevent */
196 static void evhttp_read_cb(struct bufferevent *, void *);
197 static void evhttp_write_cb(struct bufferevent *, void *);
198 static void evhttp_error_cb(struct bufferevent *bufev, short what, void *arg);
199 static int evhttp_find_vhost(struct evhttp *http, struct evhttp **outhttp,
200 const char *hostname);
202 #ifndef EVENT__HAVE_STRSEP
203 /* strsep replacement for platforms that lack it. Only works if
204 * del is one character long. */
206 strsep(char **s, const char *del)
209 EVUTIL_ASSERT(strlen(del) == 1);
213 d = strstr(tok, del);
224 html_replace(const char ch, const char **escaped)
250 * Replaces <, >, ", ' and & with <, >, ",
251 * ' and & correspondingly.
253 * The returned string needs to be freed by the caller.
257 evhttp_htmlescape(const char *html)
260 size_t new_size = 0, old_size = 0;
261 char *escaped_html, *p;
266 old_size = strlen(html);
267 for (i = 0; i < old_size; ++i) {
268 const char *replaced = NULL;
269 const size_t replace_size = html_replace(html[i], &replaced);
270 if (replace_size > EV_SIZE_MAX - new_size) {
271 event_warn("%s: html_replace overflow", __func__);
274 new_size += replace_size;
277 if (new_size == EV_SIZE_MAX)
279 p = escaped_html = mm_malloc(new_size + 1);
280 if (escaped_html == NULL) {
281 event_warn("%s: malloc(%lu)", __func__,
282 (unsigned long)(new_size + 1));
285 for (i = 0; i < old_size; ++i) {
286 const char *replaced = &html[i];
287 const size_t len = html_replace(html[i], &replaced);
288 memcpy(p, replaced, len);
294 return (escaped_html);
297 /** Given an evhttp_cmd_type, returns a constant string containing the
298 * equivalent HTTP command, or NULL if the evhttp_command_type is
301 evhttp_method(enum evhttp_cmd_type type)
309 case EVHTTP_REQ_POST:
312 case EVHTTP_REQ_HEAD:
318 case EVHTTP_REQ_DELETE:
321 case EVHTTP_REQ_OPTIONS:
324 case EVHTTP_REQ_TRACE:
327 case EVHTTP_REQ_CONNECT:
330 case EVHTTP_REQ_PATCH:
342 * Determines if a response should have a body.
343 * Follows the rules in RFC 2616 section 4.3.
344 * @return 1 if the response MUST have a body; 0 if the response MUST NOT have
348 evhttp_response_needs_body(struct evhttp_request *req)
350 return (req->response_code != HTTP_NOCONTENT &&
351 req->response_code != HTTP_NOTMODIFIED &&
352 (req->response_code < 100 || req->response_code >= 200) &&
353 req->type != EVHTTP_REQ_HEAD);
356 /** Helper: called after we've added some data to an evcon's bufferevent's
357 * output buffer. Sets the evconn's writing-is-done callback, and puts
358 * the bufferevent into writing mode.
361 evhttp_write_buffer(struct evhttp_connection *evcon,
362 void (*cb)(struct evhttp_connection *, void *), void *arg)
364 event_debug(("%s: preparing to write buffer\n", __func__));
370 /* Disable the read callback: we don't actually care about data;
371 * we only care about close detection. (We don't disable reading,
372 * since we *do* want to learn about any close events.) */
373 bufferevent_setcb(evcon->bufev,
379 bufferevent_enable(evcon->bufev, EV_WRITE);
383 evhttp_send_continue_done(struct evhttp_connection *evcon, void *arg)
385 bufferevent_disable(evcon->bufev, EV_WRITE);
389 evhttp_send_continue(struct evhttp_connection *evcon,
390 struct evhttp_request *req)
392 bufferevent_enable(evcon->bufev, EV_WRITE);
393 evbuffer_add_printf(bufferevent_get_output(evcon->bufev),
394 "HTTP/%d.%d 100 Continue\r\n\r\n",
395 req->major, req->minor);
396 evcon->cb = evhttp_send_continue_done;
397 evcon->cb_arg = NULL;
398 bufferevent_setcb(evcon->bufev,
405 /** Helper: returns true iff evconn is in any connected state. */
407 evhttp_connected(struct evhttp_connection *evcon)
409 switch (evcon->state) {
410 case EVCON_DISCONNECTED:
411 case EVCON_CONNECTING:
414 case EVCON_READING_FIRSTLINE:
415 case EVCON_READING_HEADERS:
416 case EVCON_READING_BODY:
417 case EVCON_READING_TRAILER:
424 /* Create the headers needed for an outgoing HTTP request, adds them to
425 * the request's header list, and writes the request line to the
426 * connection's output buffer.
429 evhttp_make_header_request(struct evhttp_connection *evcon,
430 struct evhttp_request *req)
434 evhttp_remove_header(req->output_headers, "Proxy-Connection");
436 /* Generate request line */
437 if (!(method = evhttp_method(req->type))) {
441 evbuffer_add_printf(bufferevent_get_output(evcon->bufev),
442 "%s %s HTTP/%d.%d\r\n",
443 method, req->uri, req->major, req->minor);
445 /* Add the content length on a post or put request if missing */
446 if ((req->type == EVHTTP_REQ_POST || req->type == EVHTTP_REQ_PUT) &&
447 evhttp_find_header(req->output_headers, "Content-Length") == NULL){
449 evutil_snprintf(size, sizeof(size), EV_SIZE_FMT,
450 EV_SIZE_ARG(evbuffer_get_length(req->output_buffer)));
451 evhttp_add_header(req->output_headers, "Content-Length", size);
455 /** Return true if the list of headers in 'headers', intepreted with respect
456 * to flags, means that we should send a "connection: close" when the request
459 evhttp_is_connection_close(int flags, struct evkeyvalq* headers)
461 if (flags & EVHTTP_PROXY_REQUEST) {
462 /* proxy connection */
463 const char *connection = evhttp_find_header(headers, "Proxy-Connection");
464 return (connection == NULL || evutil_ascii_strcasecmp(connection, "keep-alive") != 0);
466 const char *connection = evhttp_find_header(headers, "Connection");
467 return (connection != NULL && evutil_ascii_strcasecmp(connection, "close") == 0);
471 evhttp_is_request_connection_close(struct evhttp_request *req)
474 evhttp_is_connection_close(req->flags, req->input_headers) ||
475 evhttp_is_connection_close(req->flags, req->output_headers);
478 /* Return true iff 'headers' contains 'Connection: keep-alive' */
480 evhttp_is_connection_keepalive(struct evkeyvalq* headers)
482 const char *connection = evhttp_find_header(headers, "Connection");
483 return (connection != NULL
484 && evutil_ascii_strncasecmp(connection, "keep-alive", 10) == 0);
487 /* Add a correct "Date" header to headers, unless it already has one. */
489 evhttp_maybe_add_date_header(struct evkeyvalq *headers)
491 if (evhttp_find_header(headers, "Date") == NULL) {
493 if (sizeof(date) - evutil_date_rfc1123(date, sizeof(date), NULL) > 0) {
494 evhttp_add_header(headers, "Date", date);
499 /* Add a "Content-Length" header with value 'content_length' to headers,
500 * unless it already has a content-length or transfer-encoding header. */
502 evhttp_maybe_add_content_length_header(struct evkeyvalq *headers,
503 size_t content_length)
505 if (evhttp_find_header(headers, "Transfer-Encoding") == NULL &&
506 evhttp_find_header(headers, "Content-Length") == NULL) {
508 evutil_snprintf(len, sizeof(len), EV_SIZE_FMT,
509 EV_SIZE_ARG(content_length));
510 evhttp_add_header(headers, "Content-Length", len);
515 * Create the headers needed for an HTTP reply in req->output_headers,
516 * and write the first HTTP response for req line to evcon.
519 evhttp_make_header_response(struct evhttp_connection *evcon,
520 struct evhttp_request *req)
522 int is_keepalive = evhttp_is_connection_keepalive(req->input_headers);
523 evbuffer_add_printf(bufferevent_get_output(evcon->bufev),
524 "HTTP/%d.%d %d %s\r\n",
525 req->major, req->minor, req->response_code,
526 req->response_code_line);
528 if (req->major == 1) {
530 evhttp_maybe_add_date_header(req->output_headers);
533 * if the protocol is 1.0; and the connection was keep-alive
534 * we need to add a keep-alive header, too.
536 if (req->minor == 0 && is_keepalive)
537 evhttp_add_header(req->output_headers,
538 "Connection", "keep-alive");
540 if ((req->minor >= 1 || is_keepalive) &&
541 evhttp_response_needs_body(req)) {
543 * we need to add the content length if the
544 * user did not give it, this is required for
545 * persistent connections to work.
547 evhttp_maybe_add_content_length_header(
549 evbuffer_get_length(req->output_buffer));
553 /* Potentially add headers for unidentified content. */
554 if (evhttp_response_needs_body(req)) {
555 if (evhttp_find_header(req->output_headers,
556 "Content-Type") == NULL
557 && evcon->http_server->default_content_type) {
558 evhttp_add_header(req->output_headers,
560 evcon->http_server->default_content_type);
564 /* if the request asked for a close, we send a close, too */
565 if (evhttp_is_connection_close(req->flags, req->input_headers)) {
566 evhttp_remove_header(req->output_headers, "Connection");
567 if (!(req->flags & EVHTTP_PROXY_REQUEST))
568 evhttp_add_header(req->output_headers, "Connection", "close");
569 evhttp_remove_header(req->output_headers, "Proxy-Connection");
573 enum expect { NO, CONTINUE, OTHER };
574 static enum expect evhttp_have_expect(struct evhttp_request *req, int input)
577 struct evkeyvalq *h = input ? req->input_headers : req->output_headers;
579 if (!(req->kind == EVHTTP_REQUEST) || !REQ_VERSION_ATLEAST(req, 1, 1))
582 expect = evhttp_find_header(h, "Expect");
586 return !evutil_ascii_strcasecmp(expect, "100-continue") ? CONTINUE : OTHER;
590 /** Generate all headers appropriate for sending the http request in req (or
591 * the response, if we're sending a response), and write them to evcon's
592 * bufferevent. Also writes all data from req->output_buffer */
594 evhttp_make_header(struct evhttp_connection *evcon, struct evhttp_request *req)
596 struct evkeyval *header;
597 struct evbuffer *output = bufferevent_get_output(evcon->bufev);
600 * Depending if this is a HTTP request or response, we might need to
601 * add some new headers or remove existing headers.
603 if (req->kind == EVHTTP_REQUEST) {
604 evhttp_make_header_request(evcon, req);
606 evhttp_make_header_response(evcon, req);
609 TAILQ_FOREACH(header, req->output_headers, next) {
610 evbuffer_add_printf(output, "%s: %s\r\n",
611 header->key, header->value);
613 evbuffer_add(output, "\r\n", 2);
615 if (evhttp_have_expect(req, 0) != CONTINUE &&
616 evbuffer_get_length(req->output_buffer)) {
618 * For a request, we add the POST data, for a reply, this
619 * is the regular data.
621 evbuffer_add_buffer(output, req->output_buffer);
626 evhttp_connection_set_max_headers_size(struct evhttp_connection *evcon,
627 ev_ssize_t new_max_headers_size)
629 if (new_max_headers_size<0)
630 evcon->max_headers_size = EV_SIZE_MAX;
632 evcon->max_headers_size = new_max_headers_size;
635 evhttp_connection_set_max_body_size(struct evhttp_connection* evcon,
636 ev_ssize_t new_max_body_size)
638 if (new_max_body_size<0)
639 evcon->max_body_size = EV_UINT64_MAX;
641 evcon->max_body_size = new_max_body_size;
645 evhttp_connection_incoming_fail(struct evhttp_request *req,
646 enum evhttp_request_error error)
649 case EVREQ_HTTP_DATA_TOO_LONG:
650 req->response_code = HTTP_ENTITYTOOLARGE;
653 req->response_code = HTTP_BADREQUEST;
657 case EVREQ_HTTP_TIMEOUT:
660 * these are cases in which we probably should just
661 * close the connection and not send a reply. this
662 * case may happen when a browser keeps a persistent
663 * connection open and we timeout on the read. when
664 * the request is still being used for sending, we
665 * need to disassociated it from the connection here.
667 if (!req->userdone) {
668 /* remove it so that it will not be freed */
669 TAILQ_REMOVE(&req->evcon->requests, req, next);
670 /* indicate that this request no longer has a
676 case EVREQ_HTTP_INVALID_HEADER:
677 case EVREQ_HTTP_BUFFER_ERROR:
678 case EVREQ_HTTP_REQUEST_CANCEL:
679 case EVREQ_HTTP_DATA_TOO_LONG:
680 default: /* xxx: probably should just error on default */
681 /* the callback looks at the uri to determine errors */
686 if (req->uri_elems) {
687 evhttp_uri_free(req->uri_elems);
688 req->uri_elems = NULL;
692 * the callback needs to send a reply, once the reply has
693 * been send, the connection should get freed.
695 (*req->cb)(req, req->cb_arg);
701 /* Free connection ownership of which can be acquired by user using
702 * evhttp_request_own(). */
704 evhttp_request_free_auto(struct evhttp_request *req)
706 if (!(req->flags & EVHTTP_USER_OWNED))
707 evhttp_request_free(req);
711 evhttp_request_free_(struct evhttp_connection *evcon, struct evhttp_request *req)
713 TAILQ_REMOVE(&evcon->requests, req, next);
714 evhttp_request_free_auto(req);
717 /* Called when evcon has experienced a (non-recoverable? -NM) error, as
718 * given in error. If it's an outgoing connection, reset the connection,
719 * retry any pending requests, and inform the user. If it's incoming,
720 * delegates to evhttp_connection_incoming_fail(). */
722 evhttp_connection_fail_(struct evhttp_connection *evcon,
723 enum evhttp_request_error error)
725 const int errsave = EVUTIL_SOCKET_ERROR();
726 struct evhttp_request* req = TAILQ_FIRST(&evcon->requests);
727 void (*cb)(struct evhttp_request *, void *);
729 void (*error_cb)(enum evhttp_request_error, void *);
731 EVUTIL_ASSERT(req != NULL);
733 bufferevent_disable(evcon->bufev, EV_READ|EV_WRITE);
735 if (evcon->flags & EVHTTP_CON_INCOMING) {
737 * for incoming requests, there are two different
738 * failure cases. it's either a network level error
739 * or an http layer error. for problems on the network
740 * layer like timeouts we just drop the connections.
741 * For HTTP problems, we might have to send back a
742 * reply before the connection can be freed.
744 if (evhttp_connection_incoming_fail(req, error) == -1)
745 evhttp_connection_free(evcon);
749 error_cb = req->error_cb;
750 error_cb_arg = req->cb_arg;
751 /* when the request was canceled, the callback is not executed */
752 if (error != EVREQ_HTTP_REQUEST_CANCEL) {
753 /* save the callback for later; the cb might free our object */
755 cb_arg = req->cb_arg;
761 /* do not fail all requests; the next request is going to get
762 * send over a new connection. when a user cancels a request,
763 * all other pending requests should be processed as normal
765 evhttp_request_free_(evcon, req);
767 /* reset the connection */
768 evhttp_connection_reset_(evcon);
770 /* We are trying the next request that was queued on us */
771 if (TAILQ_FIRST(&evcon->requests) != NULL)
772 evhttp_connection_connect_(evcon);
774 /* The call to evhttp_connection_reset_ overwrote errno.
775 * Let's restore the original errno, so that the user's
776 * callback can have a better idea of what the error was.
778 EVUTIL_SET_SOCKET_ERROR(errsave);
780 /* inform the user */
781 if (error_cb != NULL)
782 error_cb(error, error_cb_arg);
787 /* Bufferevent callback: invoked when any data has been written from an
788 * http connection's bufferevent */
790 evhttp_write_cb(struct bufferevent *bufev, void *arg)
792 struct evhttp_connection *evcon = arg;
794 /* Activate our call back */
795 if (evcon->cb != NULL)
796 (*evcon->cb)(evcon, evcon->cb_arg);
800 * Advance the connection state.
801 * - If this is an outgoing connection, we've just processed the response;
802 * idle or close the connection.
803 * - If this is an incoming connection, we've just processed the request;
807 evhttp_connection_done(struct evhttp_connection *evcon)
809 struct evhttp_request *req = TAILQ_FIRST(&evcon->requests);
810 int con_outgoing = evcon->flags & EVHTTP_CON_OUTGOING;
814 /* idle or close the connection */
815 int need_close = evhttp_is_request_connection_close(req);
816 TAILQ_REMOVE(&evcon->requests, req, next);
819 evcon->state = EVCON_IDLE;
821 /* check if we got asked to close the connection */
823 evhttp_connection_reset_(evcon);
825 if (TAILQ_FIRST(&evcon->requests) != NULL) {
827 * We have more requests; reset the connection
828 * and deal with the next request.
830 if (!evhttp_connected(evcon))
831 evhttp_connection_connect_(evcon);
833 evhttp_request_dispatch(evcon);
834 } else if (!need_close) {
836 * The connection is going to be persistent, but we
837 * need to detect if the other side closes it.
839 evhttp_connection_start_detectclose(evcon);
840 } else if ((evcon->flags & EVHTTP_CON_AUTOFREE)) {
842 * If we have no more requests that need completion
843 * and we're not waiting for the connection to close
849 * incoming connection - we need to leave the request on the
850 * connection so that we can reply to it.
852 evcon->state = EVCON_WRITING;
855 /* notify the user of the request */
856 (*req->cb)(req, req->cb_arg);
858 /* if this was an outgoing request, we own and it's done. so free it. */
860 evhttp_request_free_auto(req);
863 /* If this was the last request of an outgoing connection and we're
864 * not waiting to receive a connection close event and we want to
865 * automatically free the connection. We check to ensure our request
866 * list is empty one last time just in case our callback added a
869 if (free_evcon && TAILQ_FIRST(&evcon->requests) == NULL) {
870 evhttp_connection_free(evcon);
875 * Handles reading from a chunked request.
876 * return ALL_DATA_READ:
877 * all data has been read
878 * return MORE_DATA_EXPECTED:
879 * more data is expected
880 * return DATA_CORRUPTED:
882 * return REQUEST_CANCELED:
883 * request was canceled by the user calling evhttp_cancel_request
884 * return DATA_TOO_LONG:
885 * ran over the maximum limit
888 static enum message_read_status
889 evhttp_handle_chunked_read(struct evhttp_request *req, struct evbuffer *buf)
891 if (req == NULL || buf == NULL) {
892 return DATA_CORRUPTED;
898 if ((buflen = evbuffer_get_length(buf)) == 0) {
902 /* evbuffer_get_length returns size_t, but len variable is ssize_t,
903 * check for overflow conditions */
904 if (buflen > EV_SSIZE_MAX) {
905 return DATA_CORRUPTED;
908 if (req->ntoread < 0) {
909 /* Read chunk size */
911 char *p = evbuffer_readln(buf, NULL, EVBUFFER_EOL_CRLF);
916 /* the last chunk is on a new line? */
917 if (strlen(p) == 0) {
921 ntoread = evutil_strtoll(p, &endp, 16);
922 error = (*p == '\0' ||
923 (*endp != '\0' && *endp != ' ') ||
927 /* could not get chunk size */
928 return (DATA_CORRUPTED);
931 /* ntoread is signed int64, body_size is unsigned size_t, check for under/overflow conditions */
932 if ((ev_uint64_t)ntoread > EV_SIZE_MAX - req->body_size) {
933 return DATA_CORRUPTED;
936 if (req->body_size + (size_t)ntoread > req->evcon->max_body_size) {
937 /* failed body length test */
938 event_debug(("Request body is too long"));
939 return (DATA_TOO_LONG);
942 req->body_size += (size_t)ntoread;
943 req->ntoread = ntoread;
944 if (req->ntoread == 0) {
946 return (ALL_DATA_READ);
951 /* req->ntoread is signed int64, len is ssize_t, based on arch,
952 * ssize_t could only be 32b, check for these conditions */
953 if (req->ntoread > EV_SSIZE_MAX) {
954 return DATA_CORRUPTED;
957 /* don't have enough to complete a chunk; wait for more */
958 if (req->ntoread > 0 && buflen < (ev_uint64_t)req->ntoread)
959 return (MORE_DATA_EXPECTED);
961 /* Completed chunk */
962 evbuffer_remove_buffer(buf, req->input_buffer, (size_t)req->ntoread);
964 if (req->chunk_cb != NULL) {
965 req->flags |= EVHTTP_REQ_DEFER_FREE;
966 (*req->chunk_cb)(req, req->cb_arg);
967 evbuffer_drain(req->input_buffer,
968 evbuffer_get_length(req->input_buffer));
969 req->flags &= ~EVHTTP_REQ_DEFER_FREE;
970 if ((req->flags & EVHTTP_REQ_NEEDS_FREE) != 0) {
971 return (REQUEST_CANCELED);
976 return (MORE_DATA_EXPECTED);
980 evhttp_read_trailer(struct evhttp_connection *evcon, struct evhttp_request *req)
982 struct evbuffer *buf = bufferevent_get_input(evcon->bufev);
984 switch (evhttp_parse_headers_(req, buf)) {
987 evhttp_connection_fail_(evcon, EVREQ_HTTP_DATA_TOO_LONG);
990 bufferevent_disable(evcon->bufev, EV_READ);
991 evhttp_connection_done(evcon);
993 case MORE_DATA_EXPECTED:
994 case REQUEST_CANCELED: /* ??? */
1001 evhttp_lingering_close(struct evhttp_connection *evcon,
1002 struct evhttp_request *req)
1004 struct evbuffer *buf = bufferevent_get_input(evcon->bufev);
1006 size_t n = evbuffer_get_length(buf);
1007 if (n > (size_t) req->ntoread)
1008 n = (size_t) req->ntoread;
1010 req->body_size += n;
1012 event_debug(("Request body is too long, left " EV_I64_FMT,
1013 EV_I64_ARG(req->ntoread)));
1015 evbuffer_drain(buf, n);
1017 evhttp_connection_fail_(evcon, EVREQ_HTTP_DATA_TOO_LONG);
1020 evhttp_lingering_fail(struct evhttp_connection *evcon,
1021 struct evhttp_request *req)
1023 if (evcon->flags & EVHTTP_CON_LINGERING_CLOSE)
1024 evhttp_lingering_close(evcon, req);
1026 evhttp_connection_fail_(evcon, EVREQ_HTTP_DATA_TOO_LONG);
1030 evhttp_read_body(struct evhttp_connection *evcon, struct evhttp_request *req)
1032 struct evbuffer *buf = bufferevent_get_input(evcon->bufev);
1035 switch (evhttp_handle_chunked_read(req, buf)) {
1037 /* finished last chunk */
1038 evcon->state = EVCON_READING_TRAILER;
1039 evhttp_read_trailer(evcon, req);
1041 case DATA_CORRUPTED:
1043 /* corrupted data */
1044 evhttp_connection_fail_(evcon,
1045 EVREQ_HTTP_DATA_TOO_LONG);
1047 case REQUEST_CANCELED:
1048 /* request canceled */
1049 evhttp_request_free_auto(req);
1051 case MORE_DATA_EXPECTED:
1055 } else if (req->ntoread < 0) {
1056 /* Read until connection close. */
1057 if ((size_t)(req->body_size + evbuffer_get_length(buf)) < req->body_size) {
1058 evhttp_connection_fail_(evcon, EVREQ_HTTP_INVALID_HEADER);
1062 req->body_size += evbuffer_get_length(buf);
1063 evbuffer_add_buffer(req->input_buffer, buf);
1064 } else if (req->chunk_cb != NULL || evbuffer_get_length(buf) >= (size_t)req->ntoread) {
1065 /* XXX: the above get_length comparison has to be fixed for overflow conditions! */
1066 /* We've postponed moving the data until now, but we're
1067 * about to use it. */
1068 size_t n = evbuffer_get_length(buf);
1070 if (n > (size_t) req->ntoread)
1071 n = (size_t) req->ntoread;
1073 req->body_size += n;
1074 evbuffer_remove_buffer(buf, req->input_buffer, n);
1077 if (req->body_size > req->evcon->max_body_size ||
1078 (!req->chunked && req->ntoread >= 0 &&
1079 (size_t)req->ntoread > req->evcon->max_body_size)) {
1080 /* XXX: The above casted comparison must checked for overflow */
1081 /* failed body length test */
1083 evhttp_lingering_fail(evcon, req);
1087 if (evbuffer_get_length(req->input_buffer) > 0 && req->chunk_cb != NULL) {
1088 req->flags |= EVHTTP_REQ_DEFER_FREE;
1089 (*req->chunk_cb)(req, req->cb_arg);
1090 req->flags &= ~EVHTTP_REQ_DEFER_FREE;
1091 evbuffer_drain(req->input_buffer,
1092 evbuffer_get_length(req->input_buffer));
1093 if ((req->flags & EVHTTP_REQ_NEEDS_FREE) != 0) {
1094 evhttp_request_free_auto(req);
1099 if (!req->ntoread) {
1100 bufferevent_disable(evcon->bufev, EV_READ);
1101 /* Completed content length */
1102 evhttp_connection_done(evcon);
1107 #define get_deferred_queue(evcon) \
1111 * Gets called when more data becomes available
1115 evhttp_read_cb(struct bufferevent *bufev, void *arg)
1117 struct evhttp_connection *evcon = arg;
1118 struct evhttp_request *req = TAILQ_FIRST(&evcon->requests);
1120 /* Cancel if it's pending. */
1121 event_deferred_cb_cancel_(get_deferred_queue(evcon),
1122 &evcon->read_more_deferred_cb);
1124 switch (evcon->state) {
1125 case EVCON_READING_FIRSTLINE:
1126 evhttp_read_firstline(evcon, req);
1127 /* note the request may have been freed in
1128 * evhttp_read_body */
1130 case EVCON_READING_HEADERS:
1131 evhttp_read_header(evcon, req);
1132 /* note the request may have been freed in
1133 * evhttp_read_body */
1135 case EVCON_READING_BODY:
1136 evhttp_read_body(evcon, req);
1137 /* note the request may have been freed in
1138 * evhttp_read_body */
1140 case EVCON_READING_TRAILER:
1141 evhttp_read_trailer(evcon, req);
1146 struct evbuffer *input;
1149 input = bufferevent_get_input(evcon->bufev);
1150 total_len = evbuffer_get_length(input);
1151 event_debug(("%s: read "EV_SIZE_FMT
1152 " bytes in EVCON_IDLE state,"
1153 " resetting connection",
1154 __func__, EV_SIZE_ARG(total_len)));
1157 evhttp_connection_reset_(evcon);
1160 case EVCON_DISCONNECTED:
1161 case EVCON_CONNECTING:
1164 event_errx(1, "%s: illegal connection state %d",
1165 __func__, evcon->state);
1170 evhttp_deferred_read_cb(struct event_callback *cb, void *data)
1172 struct evhttp_connection *evcon = data;
1173 evhttp_read_cb(evcon->bufev, evcon);
1177 evhttp_write_connectioncb(struct evhttp_connection *evcon, void *arg)
1179 /* This is after writing the request to the server */
1180 struct evhttp_request *req = TAILQ_FIRST(&evcon->requests);
1181 struct evbuffer *output = bufferevent_get_output(evcon->bufev);
1182 EVUTIL_ASSERT(req != NULL);
1184 EVUTIL_ASSERT(evcon->state == EVCON_WRITING);
1186 /* We need to wait until we've written all of our output data before we can
1188 if (evbuffer_get_length(output) > 0)
1191 /* We are done writing our header and are now expecting the response */
1192 req->kind = EVHTTP_RESPONSE;
1194 evhttp_start_read_(evcon);
1198 * Clean up a connection object
1202 evhttp_connection_free(struct evhttp_connection *evcon)
1204 struct evhttp_request *req;
1206 /* notify interested parties that this connection is going down */
1207 if (evcon->fd != -1) {
1208 if (evhttp_connected(evcon) && evcon->closecb != NULL)
1209 (*evcon->closecb)(evcon, evcon->closecb_arg);
1212 /* remove all requests that might be queued on this
1213 * connection. for server connections, this should be empty.
1214 * because it gets dequeued either in evhttp_connection_done or
1215 * evhttp_connection_fail_.
1217 while ((req = TAILQ_FIRST(&evcon->requests)) != NULL) {
1218 evhttp_request_free_(evcon, req);
1221 if (evcon->http_server != NULL) {
1222 struct evhttp *http = evcon->http_server;
1223 TAILQ_REMOVE(&http->connections, evcon, next);
1226 if (event_initialized(&evcon->retry_ev)) {
1227 event_del(&evcon->retry_ev);
1228 event_debug_unassign(&evcon->retry_ev);
1231 if (evcon->bufev != NULL)
1232 bufferevent_free(evcon->bufev);
1234 event_deferred_cb_cancel_(get_deferred_queue(evcon),
1235 &evcon->read_more_deferred_cb);
1237 if (evcon->fd == -1)
1238 evcon->fd = bufferevent_getfd(evcon->bufev);
1240 if (evcon->fd != -1) {
1241 bufferevent_disable(evcon->bufev, EV_READ|EV_WRITE);
1242 shutdown(evcon->fd, EVUTIL_SHUT_WR);
1243 if (!(bufferevent_get_options_(evcon->bufev) & BEV_OPT_CLOSE_ON_FREE)) {
1244 evutil_closesocket(evcon->fd);
1248 if (evcon->bind_address != NULL)
1249 mm_free(evcon->bind_address);
1251 if (evcon->address != NULL)
1252 mm_free(evcon->address);
1258 evhttp_connection_free_on_completion(struct evhttp_connection *evcon) {
1259 evcon->flags |= EVHTTP_CON_AUTOFREE;
1263 evhttp_connection_set_local_address(struct evhttp_connection *evcon,
1264 const char *address)
1266 EVUTIL_ASSERT(evcon->state == EVCON_DISCONNECTED);
1267 if (evcon->bind_address)
1268 mm_free(evcon->bind_address);
1269 if ((evcon->bind_address = mm_strdup(address)) == NULL)
1270 event_warn("%s: strdup", __func__);
1274 evhttp_connection_set_local_port(struct evhttp_connection *evcon,
1277 EVUTIL_ASSERT(evcon->state == EVCON_DISCONNECTED);
1278 evcon->bind_port = port;
1282 evhttp_request_dispatch(struct evhttp_connection* evcon)
1284 struct evhttp_request *req = TAILQ_FIRST(&evcon->requests);
1286 /* this should not usually happy but it's possible */
1290 /* delete possible close detection events */
1291 evhttp_connection_stop_detectclose(evcon);
1293 /* we assume that the connection is connected already */
1294 EVUTIL_ASSERT(evcon->state == EVCON_IDLE);
1296 evcon->state = EVCON_WRITING;
1298 /* Create the header from the store arguments */
1299 evhttp_make_header(evcon, req);
1301 evhttp_write_buffer(evcon, evhttp_write_connectioncb, NULL);
1304 /* Reset our connection state: disables reading/writing, closes our fd (if
1305 * any), clears out buffers, and puts us in state DISCONNECTED. */
1307 evhttp_connection_reset_(struct evhttp_connection *evcon)
1309 struct evbuffer *tmp;
1312 /* XXXX This is not actually an optimal fix. Instead we ought to have
1313 an API for "stop connecting", or use bufferevent_setfd to turn off
1314 connecting. But for Libevent 2.0, this seems like a minimal change
1315 least likely to disrupt the rest of the bufferevent and http code.
1317 Why is this here? If the fd is set in the bufferevent, and the
1318 bufferevent is connecting, then you can't actually stop the
1319 bufferevent from trying to connect with bufferevent_disable(). The
1320 connect will never trigger, since we close the fd, but the timeout
1321 might. That caused an assertion failure in evhttp_connection_fail_.
1323 bufferevent_disable_hard_(evcon->bufev, EV_READ|EV_WRITE);
1325 if (evcon->fd == -1)
1326 evcon->fd = bufferevent_getfd(evcon->bufev);
1328 if (evcon->fd != -1) {
1329 /* inform interested parties about connection close */
1330 if (evhttp_connected(evcon) && evcon->closecb != NULL)
1331 (*evcon->closecb)(evcon, evcon->closecb_arg);
1333 shutdown(evcon->fd, EVUTIL_SHUT_WR);
1334 evutil_closesocket(evcon->fd);
1337 bufferevent_setfd(evcon->bufev, -1);
1339 /* we need to clean up any buffered data */
1340 tmp = bufferevent_get_output(evcon->bufev);
1341 err = evbuffer_drain(tmp, -1);
1342 EVUTIL_ASSERT(!err && "drain output");
1343 tmp = bufferevent_get_input(evcon->bufev);
1344 err = evbuffer_drain(tmp, -1);
1345 EVUTIL_ASSERT(!err && "drain input");
1347 evcon->flags &= ~EVHTTP_CON_READING_ERROR;
1349 evcon->state = EVCON_DISCONNECTED;
1353 evhttp_connection_start_detectclose(struct evhttp_connection *evcon)
1355 evcon->flags |= EVHTTP_CON_CLOSEDETECT;
1357 bufferevent_enable(evcon->bufev, EV_READ);
1361 evhttp_connection_stop_detectclose(struct evhttp_connection *evcon)
1363 evcon->flags &= ~EVHTTP_CON_CLOSEDETECT;
1365 bufferevent_disable(evcon->bufev, EV_READ);
1369 evhttp_connection_retry(evutil_socket_t fd, short what, void *arg)
1371 struct evhttp_connection *evcon = arg;
1373 evcon->state = EVCON_DISCONNECTED;
1374 evhttp_connection_connect_(evcon);
1378 evhttp_connection_cb_cleanup(struct evhttp_connection *evcon)
1380 struct evcon_requestq requests;
1382 evhttp_connection_reset_(evcon);
1383 if (evcon->retry_max < 0 || evcon->retry_cnt < evcon->retry_max) {
1384 struct timeval tv_retry = evcon->initial_retry_timeout;
1386 evtimer_assign(&evcon->retry_ev, evcon->base, evhttp_connection_retry, evcon);
1387 /* XXXX handle failure from evhttp_add_event */
1388 for (i=0; i < evcon->retry_cnt; ++i) {
1389 tv_retry.tv_usec *= 2;
1390 if (tv_retry.tv_usec > 1000000) {
1391 tv_retry.tv_usec -= 1000000;
1392 tv_retry.tv_sec += 1;
1394 tv_retry.tv_sec *= 2;
1395 if (tv_retry.tv_sec > 3600) {
1396 tv_retry.tv_sec = 3600;
1397 tv_retry.tv_usec = 0;
1400 event_add(&evcon->retry_ev, &tv_retry);
1406 * User callback can do evhttp_make_request() on the same
1407 * evcon so new request will be added to evcon->requests. To
1408 * avoid freeing it prematurely we iterate over the copy of
1411 TAILQ_INIT(&requests);
1412 while (TAILQ_FIRST(&evcon->requests) != NULL) {
1413 struct evhttp_request *request = TAILQ_FIRST(&evcon->requests);
1414 TAILQ_REMOVE(&evcon->requests, request, next);
1415 TAILQ_INSERT_TAIL(&requests, request, next);
1418 /* for now, we just signal all requests by executing their callbacks */
1419 while (TAILQ_FIRST(&requests) != NULL) {
1420 struct evhttp_request *request = TAILQ_FIRST(&requests);
1421 TAILQ_REMOVE(&requests, request, next);
1422 request->evcon = NULL;
1424 /* we might want to set an error here */
1425 request->cb(request, request->cb_arg);
1426 evhttp_request_free_auto(request);
1431 evhttp_connection_read_on_write_error(struct evhttp_connection *evcon,
1432 struct evhttp_request *req)
1434 struct evbuffer *buf;
1436 /** Second time, we can't read anything */
1437 if (evcon->flags & EVHTTP_CON_READING_ERROR) {
1438 evcon->flags &= ~EVHTTP_CON_READING_ERROR;
1439 evhttp_connection_fail_(evcon, EVREQ_HTTP_EOF);
1443 req->kind = EVHTTP_RESPONSE;
1445 buf = bufferevent_get_output(evcon->bufev);
1446 evbuffer_unfreeze(buf, 1);
1447 evbuffer_drain(buf, evbuffer_get_length(buf));
1448 evbuffer_freeze(buf, 1);
1450 evhttp_start_read_(evcon);
1451 evcon->flags |= EVHTTP_CON_READING_ERROR;
1455 evhttp_error_cb(struct bufferevent *bufev, short what, void *arg)
1457 struct evhttp_connection *evcon = arg;
1458 struct evhttp_request *req = TAILQ_FIRST(&evcon->requests);
1460 if (evcon->fd == -1)
1461 evcon->fd = bufferevent_getfd(bufev);
1463 switch (evcon->state) {
1464 case EVCON_CONNECTING:
1465 if (what & BEV_EVENT_TIMEOUT) {
1466 event_debug(("%s: connection timeout for \"%s:%d\" on "
1468 __func__, evcon->address, evcon->port,
1469 EV_SOCK_ARG(evcon->fd)));
1470 evhttp_connection_cb_cleanup(evcon);
1475 case EVCON_READING_BODY:
1476 if (!req->chunked && req->ntoread < 0
1477 && what == (BEV_EVENT_READING|BEV_EVENT_EOF)) {
1478 /* EOF on read can be benign */
1479 evhttp_connection_done(evcon);
1484 case EVCON_DISCONNECTED:
1486 case EVCON_READING_FIRSTLINE:
1487 case EVCON_READING_HEADERS:
1488 case EVCON_READING_TRAILER:
1494 /* when we are in close detect mode, a read error means that
1495 * the other side closed their connection.
1497 if (evcon->flags & EVHTTP_CON_CLOSEDETECT) {
1498 evcon->flags &= ~EVHTTP_CON_CLOSEDETECT;
1499 EVUTIL_ASSERT(evcon->http_server == NULL);
1500 /* For connections from the client, we just
1501 * reset the connection so that it becomes
1504 EVUTIL_ASSERT(evcon->state == EVCON_IDLE);
1505 evhttp_connection_reset_(evcon);
1508 * If we have no more requests that need completion
1509 * and we want to auto-free the connection when all
1510 * requests have been completed.
1512 if (TAILQ_FIRST(&evcon->requests) == NULL
1513 && (evcon->flags & EVHTTP_CON_OUTGOING)
1514 && (evcon->flags & EVHTTP_CON_AUTOFREE)) {
1515 evhttp_connection_free(evcon);
1520 if (what & BEV_EVENT_TIMEOUT) {
1521 evhttp_connection_fail_(evcon, EVREQ_HTTP_TIMEOUT);
1522 } else if (what & (BEV_EVENT_EOF|BEV_EVENT_ERROR)) {
1523 if (what & BEV_EVENT_WRITING &&
1524 evcon->flags & EVHTTP_CON_READ_ON_WRITE_ERROR) {
1525 evhttp_connection_read_on_write_error(evcon, req);
1529 evhttp_connection_fail_(evcon, EVREQ_HTTP_EOF);
1530 } else if (what == BEV_EVENT_CONNECTED) {
1532 evhttp_connection_fail_(evcon, EVREQ_HTTP_BUFFER_ERROR);
1537 * Event callback for asynchronous connection attempt.
1540 evhttp_connection_cb(struct bufferevent *bufev, short what, void *arg)
1542 struct evhttp_connection *evcon = arg;
1544 ev_socklen_t errsz = sizeof(error);
1546 if (evcon->fd == -1)
1547 evcon->fd = bufferevent_getfd(bufev);
1549 if (!(what & BEV_EVENT_CONNECTED)) {
1550 /* some operating systems return ECONNREFUSED immediately
1551 * when connecting to a local address. the cleanup is going
1552 * to reschedule this function call.
1555 if (errno == ECONNREFUSED)
1558 evhttp_error_cb(bufev, what, arg);
1562 if (evcon->fd == -1) {
1563 event_debug(("%s: bufferevent_getfd returned -1",
1568 /* Check if the connection completed */
1569 if (getsockopt(evcon->fd, SOL_SOCKET, SO_ERROR, (void*)&error,
1571 event_debug(("%s: getsockopt for \"%s:%d\" on "EV_SOCK_FMT,
1572 __func__, evcon->address, evcon->port,
1573 EV_SOCK_ARG(evcon->fd)));
1578 event_debug(("%s: connect failed for \"%s:%d\" on "
1580 __func__, evcon->address, evcon->port,
1581 EV_SOCK_ARG(evcon->fd),
1582 evutil_socket_error_to_string(error)));
1586 /* We are connected to the server now */
1587 event_debug(("%s: connected to \"%s:%d\" on "EV_SOCK_FMT"\n",
1588 __func__, evcon->address, evcon->port,
1589 EV_SOCK_ARG(evcon->fd)));
1591 /* Reset the retry count as we were successful in connecting */
1592 evcon->retry_cnt = 0;
1593 evcon->state = EVCON_IDLE;
1595 /* reset the bufferevent cbs */
1596 bufferevent_setcb(evcon->bufev,
1602 if (!evutil_timerisset(&evcon->timeout)) {
1603 const struct timeval read_tv = { HTTP_READ_TIMEOUT, 0 };
1604 const struct timeval write_tv = { HTTP_WRITE_TIMEOUT, 0 };
1605 bufferevent_set_timeouts(evcon->bufev, &read_tv, &write_tv);
1607 bufferevent_set_timeouts(evcon->bufev, &evcon->timeout, &evcon->timeout);
1610 /* try to start requests that have queued up on this connection */
1611 evhttp_request_dispatch(evcon);
1615 evhttp_connection_cb_cleanup(evcon);
1619 * Check if we got a valid response code.
1623 evhttp_valid_response_code(int code)
1632 evhttp_parse_http_version(const char *version, struct evhttp_request *req)
1636 int n = sscanf(version, "HTTP/%d.%d%c", &major, &minor, &ch);
1637 if (n != 2 || major > 1) {
1638 event_debug(("%s: bad version %s on message %p from %s",
1639 __func__, version, req, req->remote_host));
1647 /* Parses the status line of a web server */
1650 evhttp_parse_response_line(struct evhttp_request *req, char *line)
1654 const char *readable = "";
1656 protocol = strsep(&line, " ");
1659 number = strsep(&line, " ");
1663 if (evhttp_parse_http_version(protocol, req) < 0)
1666 req->response_code = atoi(number);
1667 if (!evhttp_valid_response_code(req->response_code)) {
1668 event_debug(("%s: bad response code \"%s\"",
1673 if (req->response_code_line != NULL)
1674 mm_free(req->response_code_line);
1675 if ((req->response_code_line = mm_strdup(readable)) == NULL) {
1676 event_warn("%s: strdup", __func__);
1683 /* Parse the first line of a HTTP request */
1686 evhttp_parse_request_line(struct evhttp_request *req, char *line)
1691 const char *hostname;
1694 enum evhttp_cmd_type type;
1696 /* Parse the request line */
1697 method = strsep(&line, " ");
1700 uri = strsep(&line, " ");
1703 version = strsep(&line, " ");
1707 method_len = (uri - method) - 1;
1708 type = EVHTTP_REQ_UNKNOWN_;
1711 switch (method_len) {
1713 /* The length of the method string is 3, meaning it can only be one of two methods: GET or PUT */
1715 /* Since both GET and PUT share the same character 'T' at the end,
1716 * if the string doesn't have 'T', we can immediately determine this
1717 * is an invalid HTTP method */
1719 if (method[2] != 'T') {
1725 /* This first byte is 'G', so make sure the next byte is
1726 * 'E', if it isn't then this isn't a valid method */
1728 if (method[1] == 'E') {
1729 type = EVHTTP_REQ_GET;
1734 /* First byte is P, check second byte for 'U', if not,
1735 * we know it's an invalid method */
1736 if (method[1] == 'U') {
1737 type = EVHTTP_REQ_PUT;
1745 /* The method length is 4 bytes, leaving only the methods "POST" and "HEAD" */
1748 if (method[3] == 'T' && method[2] == 'S' && method[1] == 'O') {
1749 type = EVHTTP_REQ_POST;
1753 if (method[3] == 'D' && method[2] == 'A' && method[1] == 'E') {
1754 type = EVHTTP_REQ_HEAD;
1762 /* Method length is 5 bytes, which can only encompass PATCH and TRACE */
1765 if (method[4] == 'H' && method[3] == 'C' && method[2] == 'T' && method[1] == 'A') {
1766 type = EVHTTP_REQ_PATCH;
1770 if (method[4] == 'E' && method[3] == 'C' && method[2] == 'A' && method[1] == 'R') {
1771 type = EVHTTP_REQ_TRACE;
1780 /* Method length is 6, only valid method 6 bytes in length is DELEte */
1782 /* If the first byte isn't 'D' then it's invalid */
1783 if (*method != 'D') {
1787 if (method[5] == 'E' && method[4] == 'T' && method[3] == 'E' && method[2] == 'L' && method[1] == 'E') {
1788 type = EVHTTP_REQ_DELETE;
1793 /* Method length is 7, only valid methods are "OPTIONS" and "CONNECT" */
1796 if (method[6] == 'S' && method[5] == 'N' && method[4] == 'O' &&
1797 method[3] == 'I' && method[2] == 'T' && method[1] == 'P') {
1798 type = EVHTTP_REQ_OPTIONS;
1803 if (method[6] == 'T' && method[5] == 'C' && method[4] == 'E' &&
1804 method[3] == 'N' && method[2] == 'N' && method[1] == 'O') {
1805 type = EVHTTP_REQ_CONNECT;
1815 if ((int)type == EVHTTP_REQ_UNKNOWN_) {
1816 event_debug(("%s: bad method %s on request %p from %s",
1817 __func__, method, req, req->remote_host));
1818 /* No error yet; we'll give a better error later when
1819 * we see that req->type is unsupported. */
1824 if (evhttp_parse_http_version(version, req) < 0)
1827 if ((req->uri = mm_strdup(uri)) == NULL) {
1828 event_debug(("%s: mm_strdup", __func__));
1832 if ((req->uri_elems = evhttp_uri_parse_with_flags(req->uri,
1833 EVHTTP_URI_NONCONFORMANT)) == NULL) {
1837 /* If we have an absolute-URI, check to see if it is an http request
1838 for a known vhost or server alias. If we don't know about this
1839 host, we consider it a proxy request. */
1840 scheme = evhttp_uri_get_scheme(req->uri_elems);
1841 hostname = evhttp_uri_get_host(req->uri_elems);
1842 if (scheme && (!evutil_ascii_strcasecmp(scheme, "http") ||
1843 !evutil_ascii_strcasecmp(scheme, "https")) &&
1845 !evhttp_find_vhost(req->evcon->http_server, NULL, hostname))
1846 req->flags |= EVHTTP_PROXY_REQUEST;
1852 evhttp_find_header(const struct evkeyvalq *headers, const char *key)
1854 struct evkeyval *header;
1856 TAILQ_FOREACH(header, headers, next) {
1857 if (evutil_ascii_strcasecmp(header->key, key) == 0)
1858 return (header->value);
1865 evhttp_clear_headers(struct evkeyvalq *headers)
1867 struct evkeyval *header;
1869 for (header = TAILQ_FIRST(headers);
1871 header = TAILQ_FIRST(headers)) {
1872 TAILQ_REMOVE(headers, header, next);
1873 mm_free(header->key);
1874 mm_free(header->value);
1880 * Returns 0, if the header was successfully removed.
1881 * Returns -1, if the header could not be found.
1885 evhttp_remove_header(struct evkeyvalq *headers, const char *key)
1887 struct evkeyval *header;
1889 TAILQ_FOREACH(header, headers, next) {
1890 if (evutil_ascii_strcasecmp(header->key, key) == 0)
1897 /* Free and remove the header that we found */
1898 TAILQ_REMOVE(headers, header, next);
1899 mm_free(header->key);
1900 mm_free(header->value);
1907 evhttp_header_is_valid_value(const char *value)
1909 const char *p = value;
1911 while ((p = strpbrk(p, "\r\n")) != NULL) {
1912 /* we really expect only one new line */
1913 p += strspn(p, "\r\n");
1914 /* we expect a space or tab for continuation */
1915 if (*p != ' ' && *p != '\t')
1922 evhttp_add_header(struct evkeyvalq *headers,
1923 const char *key, const char *value)
1925 event_debug(("%s: key: %s val: %s\n", __func__, key, value));
1927 if (strchr(key, '\r') != NULL || strchr(key, '\n') != NULL) {
1928 /* drop illegal headers */
1929 event_debug(("%s: dropping illegal header key\n", __func__));
1933 if (!evhttp_header_is_valid_value(value)) {
1934 event_debug(("%s: dropping illegal header value\n", __func__));
1938 return (evhttp_add_header_internal(headers, key, value));
1942 evhttp_add_header_internal(struct evkeyvalq *headers,
1943 const char *key, const char *value)
1945 struct evkeyval *header = mm_calloc(1, sizeof(struct evkeyval));
1946 if (header == NULL) {
1947 event_warn("%s: calloc", __func__);
1950 if ((header->key = mm_strdup(key)) == NULL) {
1952 event_warn("%s: strdup", __func__);
1955 if ((header->value = mm_strdup(value)) == NULL) {
1956 mm_free(header->key);
1958 event_warn("%s: strdup", __func__);
1962 TAILQ_INSERT_TAIL(headers, header, next);
1968 * Parses header lines from a request or a response into the specified
1969 * request object given an event buffer.
1972 * DATA_CORRUPTED on error
1973 * MORE_DATA_EXPECTED when we need to read more headers
1974 * ALL_DATA_READ when all headers have been read.
1977 enum message_read_status
1978 evhttp_parse_firstline_(struct evhttp_request *req, struct evbuffer *buffer)
1981 enum message_read_status status = ALL_DATA_READ;
1985 line = evbuffer_readln(buffer, &line_length, EVBUFFER_EOL_CRLF);
1987 if (req->evcon != NULL &&
1988 evbuffer_get_length(buffer) > req->evcon->max_headers_size)
1989 return (DATA_TOO_LONG);
1991 return (MORE_DATA_EXPECTED);
1994 if (req->evcon != NULL &&
1995 line_length > req->evcon->max_headers_size) {
1997 return (DATA_TOO_LONG);
2000 req->headers_size = line_length;
2002 switch (req->kind) {
2003 case EVHTTP_REQUEST:
2004 if (evhttp_parse_request_line(req, line) == -1)
2005 status = DATA_CORRUPTED;
2007 case EVHTTP_RESPONSE:
2008 if (evhttp_parse_response_line(req, line) == -1)
2009 status = DATA_CORRUPTED;
2012 status = DATA_CORRUPTED;
2020 evhttp_append_to_last_header(struct evkeyvalq *headers, char *line)
2022 struct evkeyval *header = TAILQ_LAST(headers, evkeyvalq);
2024 size_t old_len, line_len;
2029 old_len = strlen(header->value);
2031 /* Strip space from start and end of line. */
2032 while (*line == ' ' || *line == '\t')
2034 evutil_rtrim_lws_(line);
2036 line_len = strlen(line);
2038 newval = mm_realloc(header->value, old_len + line_len + 2);
2042 newval[old_len] = ' ';
2043 memcpy(newval + old_len + 1, line, line_len + 1);
2044 header->value = newval;
2049 enum message_read_status
2050 evhttp_parse_headers_(struct evhttp_request *req, struct evbuffer* buffer)
2052 enum message_read_status errcode = DATA_CORRUPTED;
2054 enum message_read_status status = MORE_DATA_EXPECTED;
2056 struct evkeyvalq* headers = req->input_headers;
2058 while ((line = evbuffer_readln(buffer, &line_length, EVBUFFER_EOL_CRLF))
2060 char *skey, *svalue;
2062 req->headers_size += line_length;
2064 if (req->evcon != NULL &&
2065 req->headers_size > req->evcon->max_headers_size) {
2066 errcode = DATA_TOO_LONG;
2070 if (*line == '\0') { /* Last header - Done */
2071 status = ALL_DATA_READ;
2076 /* Check if this is a continuation line */
2077 if (*line == ' ' || *line == '\t') {
2078 if (evhttp_append_to_last_header(headers, line) == -1)
2084 /* Processing of header lines */
2086 skey = strsep(&svalue, ":");
2090 svalue += strspn(svalue, " ");
2091 evutil_rtrim_lws_(svalue);
2093 if (evhttp_add_header(headers, skey, svalue) == -1)
2099 if (status == MORE_DATA_EXPECTED) {
2100 if (req->evcon != NULL &&
2101 req->headers_size + evbuffer_get_length(buffer) > req->evcon->max_headers_size)
2102 return (DATA_TOO_LONG);
2113 evhttp_get_body_length(struct evhttp_request *req)
2115 struct evkeyvalq *headers = req->input_headers;
2116 const char *content_length;
2117 const char *connection;
2119 content_length = evhttp_find_header(headers, "Content-Length");
2120 connection = evhttp_find_header(headers, "Connection");
2122 if (content_length == NULL && connection == NULL)
2124 else if (content_length == NULL &&
2125 evutil_ascii_strcasecmp(connection, "Close") != 0) {
2126 /* Bad combination, we don't know when it will end */
2127 event_warnx("%s: we got no content length, but the "
2128 "server wants to keep the connection open: %s.",
2129 __func__, connection);
2131 } else if (content_length == NULL) {
2135 ev_int64_t ntoread = evutil_strtoll(content_length, &endp, 10);
2136 if (*content_length == '\0' || *endp != '\0' || ntoread < 0) {
2137 event_debug(("%s: illegal content length: %s",
2138 __func__, content_length));
2141 req->ntoread = ntoread;
2144 event_debug(("%s: bytes to read: "EV_I64_FMT" (in buffer "EV_SIZE_FMT")\n",
2145 __func__, EV_I64_ARG(req->ntoread),
2146 EV_SIZE_ARG(evbuffer_get_length(bufferevent_get_input(req->evcon->bufev)))));
2152 evhttp_method_may_have_body(enum evhttp_cmd_type type)
2155 case EVHTTP_REQ_POST:
2156 case EVHTTP_REQ_PUT:
2157 case EVHTTP_REQ_PATCH:
2159 case EVHTTP_REQ_TRACE:
2161 /* XXX May any of the below methods have a body? */
2162 case EVHTTP_REQ_GET:
2163 case EVHTTP_REQ_HEAD:
2164 case EVHTTP_REQ_DELETE:
2165 case EVHTTP_REQ_OPTIONS:
2166 case EVHTTP_REQ_CONNECT:
2174 evhttp_get_body(struct evhttp_connection *evcon, struct evhttp_request *req)
2176 const char *xfer_enc;
2178 /* If this is a request without a body, then we are done */
2179 if (req->kind == EVHTTP_REQUEST &&
2180 !evhttp_method_may_have_body(req->type)) {
2181 evhttp_connection_done(evcon);
2184 evcon->state = EVCON_READING_BODY;
2185 xfer_enc = evhttp_find_header(req->input_headers, "Transfer-Encoding");
2186 if (xfer_enc != NULL && evutil_ascii_strcasecmp(xfer_enc, "chunked") == 0) {
2190 if (evhttp_get_body_length(req) == -1) {
2191 evhttp_connection_fail_(evcon, EVREQ_HTTP_INVALID_HEADER);
2194 if (req->kind == EVHTTP_REQUEST && req->ntoread < 1) {
2195 /* An incoming request with no content-length and no
2196 * transfer-encoding has no body. */
2197 evhttp_connection_done(evcon);
2202 /* Should we send a 100 Continue status line? */
2203 switch (evhttp_have_expect(req, 1)) {
2205 /* XXX It would be nice to do some sanity
2206 checking here. Does the resource exist?
2207 Should the resource accept post requests? If
2208 no, we should respond with an error. For
2209 now, just optimistically tell the client to
2210 send their message body. */
2211 if (req->ntoread > 0) {
2212 /* ntoread is ev_int64_t, max_body_size is ev_uint64_t */
2213 if ((req->evcon->max_body_size <= EV_INT64_MAX) &&
2214 (ev_uint64_t)req->ntoread > req->evcon->max_body_size) {
2215 evhttp_lingering_fail(evcon, req);
2219 if (!evbuffer_get_length(bufferevent_get_input(evcon->bufev)))
2220 evhttp_send_continue(evcon, req);
2223 evhttp_send_error(req, HTTP_EXPECTATIONFAILED, NULL);
2228 evhttp_read_body(evcon, req);
2229 /* note the request may have been freed in evhttp_read_body */
2233 evhttp_read_firstline(struct evhttp_connection *evcon,
2234 struct evhttp_request *req)
2236 enum message_read_status res;
2238 res = evhttp_parse_firstline_(req, bufferevent_get_input(evcon->bufev));
2239 if (res == DATA_CORRUPTED || res == DATA_TOO_LONG) {
2240 /* Error while reading, terminate */
2241 event_debug(("%s: bad header lines on "EV_SOCK_FMT"\n",
2242 __func__, EV_SOCK_ARG(evcon->fd)));
2243 evhttp_connection_fail_(evcon, EVREQ_HTTP_INVALID_HEADER);
2245 } else if (res == MORE_DATA_EXPECTED) {
2246 /* Need more header lines */
2250 evcon->state = EVCON_READING_HEADERS;
2251 evhttp_read_header(evcon, req);
2255 evhttp_read_header(struct evhttp_connection *evcon,
2256 struct evhttp_request *req)
2258 enum message_read_status res;
2259 evutil_socket_t fd = evcon->fd;
2261 res = evhttp_parse_headers_(req, bufferevent_get_input(evcon->bufev));
2262 if (res == DATA_CORRUPTED || res == DATA_TOO_LONG) {
2263 /* Error while reading, terminate */
2264 event_debug(("%s: bad header lines on "EV_SOCK_FMT"\n",
2265 __func__, EV_SOCK_ARG(fd)));
2266 evhttp_connection_fail_(evcon, EVREQ_HTTP_INVALID_HEADER);
2268 } else if (res == MORE_DATA_EXPECTED) {
2269 /* Need more header lines */
2273 /* Callback can shut down connection with negative return value */
2274 if (req->header_cb != NULL) {
2275 if ((*req->header_cb)(req, req->cb_arg) < 0) {
2276 evhttp_connection_fail_(evcon, EVREQ_HTTP_EOF);
2281 /* Done reading headers, do the real work */
2282 switch (req->kind) {
2283 case EVHTTP_REQUEST:
2284 event_debug(("%s: checking for post data on "EV_SOCK_FMT"\n",
2285 __func__, EV_SOCK_ARG(fd)));
2286 evhttp_get_body(evcon, req);
2287 /* note the request may have been freed in evhttp_get_body */
2290 case EVHTTP_RESPONSE:
2291 /* Start over if we got a 100 Continue response. */
2292 if (req->response_code == 100) {
2293 struct evbuffer *output = bufferevent_get_output(evcon->bufev);
2294 evbuffer_add_buffer(output, req->output_buffer);
2295 evhttp_start_write_(evcon);
2298 if (!evhttp_response_needs_body(req)) {
2299 event_debug(("%s: skipping body for code %d\n",
2300 __func__, req->response_code));
2301 evhttp_connection_done(evcon);
2303 event_debug(("%s: start of read body for %s on "
2305 __func__, req->remote_host, EV_SOCK_ARG(fd)));
2306 evhttp_get_body(evcon, req);
2307 /* note the request may have been freed in
2308 * evhttp_get_body */
2313 event_warnx("%s: bad header on "EV_SOCK_FMT, __func__,
2315 evhttp_connection_fail_(evcon, EVREQ_HTTP_INVALID_HEADER);
2318 /* request may have been freed above */
2322 * Creates a TCP connection to the specified port and executes a callback
2323 * when finished. Failure or success is indicate by the passed connection
2326 * Although this interface accepts a hostname, it is intended to take
2327 * only numeric hostnames so that non-blocking DNS resolution can
2331 struct evhttp_connection *
2332 evhttp_connection_new(const char *address, ev_uint16_t port)
2334 return (evhttp_connection_base_new(NULL, NULL, address, port));
2337 struct evhttp_connection *
2338 evhttp_connection_base_bufferevent_new(struct event_base *base, struct evdns_base *dnsbase, struct bufferevent* bev,
2339 const char *address, ev_uint16_t port)
2341 struct evhttp_connection *evcon = NULL;
2343 event_debug(("Attempting connection to %s:%d\n", address, port));
2345 if ((evcon = mm_calloc(1, sizeof(struct evhttp_connection))) == NULL) {
2346 event_warn("%s: calloc failed", __func__);
2353 evcon->max_headers_size = EV_SIZE_MAX;
2354 evcon->max_body_size = EV_SIZE_MAX;
2356 evutil_timerclear(&evcon->timeout);
2357 evcon->retry_cnt = evcon->retry_max = 0;
2359 if ((evcon->address = mm_strdup(address)) == NULL) {
2360 event_warn("%s: strdup failed", __func__);
2365 if (!(bev = bufferevent_socket_new(base, -1, 0))) {
2366 event_warn("%s: bufferevent_socket_new failed", __func__);
2371 bufferevent_setcb(bev, evhttp_read_cb, evhttp_write_cb, evhttp_error_cb, evcon);
2374 evcon->state = EVCON_DISCONNECTED;
2375 TAILQ_INIT(&evcon->requests);
2377 evcon->initial_retry_timeout.tv_sec = 2;
2378 evcon->initial_retry_timeout.tv_usec = 0;
2382 if (bufferevent_get_base(bev) != base)
2383 bufferevent_base_set(base, evcon->bufev);
2386 event_deferred_cb_init_(
2387 &evcon->read_more_deferred_cb,
2388 bufferevent_get_priority(bev),
2389 evhttp_deferred_read_cb, evcon);
2391 evcon->dns_base = dnsbase;
2392 evcon->ai_family = AF_UNSPEC;
2398 evhttp_connection_free(evcon);
2402 struct bufferevent* evhttp_connection_get_bufferevent(struct evhttp_connection *evcon)
2404 return evcon->bufev;
2408 evhttp_connection_get_server(struct evhttp_connection *evcon)
2410 return evcon->http_server;
2413 struct evhttp_connection *
2414 evhttp_connection_base_new(struct event_base *base, struct evdns_base *dnsbase,
2415 const char *address, ev_uint16_t port)
2417 return evhttp_connection_base_bufferevent_new(base, dnsbase, NULL, address, port);
2420 void evhttp_connection_set_family(struct evhttp_connection *evcon,
2423 evcon->ai_family = family;
2426 int evhttp_connection_set_flags(struct evhttp_connection *evcon,
2429 int avail_flags = 0;
2430 avail_flags |= EVHTTP_CON_REUSE_CONNECTED_ADDR;
2431 avail_flags |= EVHTTP_CON_READ_ON_WRITE_ERROR;
2433 if (flags & ~avail_flags || flags > EVHTTP_CON_PUBLIC_FLAGS_END)
2435 evcon->flags &= ~avail_flags;
2437 evcon->flags |= flags;
2443 evhttp_connection_set_base(struct evhttp_connection *evcon,
2444 struct event_base *base)
2446 EVUTIL_ASSERT(evcon->base == NULL);
2447 EVUTIL_ASSERT(evcon->state == EVCON_DISCONNECTED);
2449 bufferevent_base_set(base, evcon->bufev);
2453 evhttp_connection_set_timeout(struct evhttp_connection *evcon,
2454 int timeout_in_secs)
2456 if (timeout_in_secs == -1)
2457 evhttp_connection_set_timeout_tv(evcon, NULL);
2460 tv.tv_sec = timeout_in_secs;
2462 evhttp_connection_set_timeout_tv(evcon, &tv);
2467 evhttp_connection_set_timeout_tv(struct evhttp_connection *evcon,
2468 const struct timeval* tv)
2471 evcon->timeout = *tv;
2472 bufferevent_set_timeouts(evcon->bufev, &evcon->timeout, &evcon->timeout);
2474 const struct timeval read_tv = { HTTP_READ_TIMEOUT, 0 };
2475 const struct timeval write_tv = { HTTP_WRITE_TIMEOUT, 0 };
2476 evutil_timerclear(&evcon->timeout);
2477 bufferevent_set_timeouts(evcon->bufev, &read_tv, &write_tv);
2482 evhttp_connection_set_initial_retry_tv(struct evhttp_connection *evcon,
2483 const struct timeval *tv)
2486 evcon->initial_retry_timeout = *tv;
2488 evutil_timerclear(&evcon->initial_retry_timeout);
2489 evcon->initial_retry_timeout.tv_sec = 2;
2494 evhttp_connection_set_retries(struct evhttp_connection *evcon,
2497 evcon->retry_max = retry_max;
2501 evhttp_connection_set_closecb(struct evhttp_connection *evcon,
2502 void (*cb)(struct evhttp_connection *, void *), void *cbarg)
2504 evcon->closecb = cb;
2505 evcon->closecb_arg = cbarg;
2509 evhttp_connection_get_peer(struct evhttp_connection *evcon,
2510 char **address, ev_uint16_t *port)
2512 *address = evcon->address;
2513 *port = evcon->port;
2516 const struct sockaddr*
2517 evhttp_connection_get_addr(struct evhttp_connection *evcon)
2519 return bufferevent_socket_get_conn_address_(evcon->bufev);
2523 evhttp_connection_connect_(struct evhttp_connection *evcon)
2525 int old_state = evcon->state;
2526 const char *address = evcon->address;
2527 const struct sockaddr *sa = evhttp_connection_get_addr(evcon);
2530 if (evcon->state == EVCON_CONNECTING)
2533 evhttp_connection_reset_(evcon);
2535 EVUTIL_ASSERT(!(evcon->flags & EVHTTP_CON_INCOMING));
2536 evcon->flags |= EVHTTP_CON_OUTGOING;
2538 if (evcon->bind_address || evcon->bind_port) {
2539 evcon->fd = bind_socket(
2540 evcon->bind_address, evcon->bind_port, 0 /*reuse*/);
2541 if (evcon->fd == -1) {
2542 event_debug(("%s: failed to bind to \"%s\"",
2543 __func__, evcon->bind_address));
2547 bufferevent_setfd(evcon->bufev, evcon->fd);
2549 bufferevent_setfd(evcon->bufev, -1);
2552 /* Set up a callback for successful connection setup */
2553 bufferevent_setcb(evcon->bufev,
2554 NULL /* evhttp_read_cb */,
2555 NULL /* evhttp_write_cb */,
2556 evhttp_connection_cb,
2558 if (!evutil_timerisset(&evcon->timeout)) {
2559 const struct timeval conn_tv = { HTTP_CONNECT_TIMEOUT, 0 };
2560 bufferevent_set_timeouts(evcon->bufev, &conn_tv, &conn_tv);
2562 bufferevent_set_timeouts(evcon->bufev, &evcon->timeout, &evcon->timeout);
2564 /* make sure that we get a write callback */
2565 bufferevent_enable(evcon->bufev, EV_WRITE);
2567 evcon->state = EVCON_CONNECTING;
2569 if (evcon->flags & EVHTTP_CON_REUSE_CONNECTED_ADDR &&
2571 (sa->sa_family == AF_INET || sa->sa_family == AF_INET6)) {
2572 int socklen = sizeof(struct sockaddr_in);
2573 if (sa->sa_family == AF_INET6) {
2574 socklen = sizeof(struct sockaddr_in6);
2576 ret = bufferevent_socket_connect(evcon->bufev, sa, socklen);
2578 ret = bufferevent_socket_connect_hostname(evcon->bufev,
2579 evcon->dns_base, evcon->ai_family, address, evcon->port);
2583 evcon->state = old_state;
2584 event_sock_warn(evcon->fd, "%s: connection to \"%s\" failed",
2585 __func__, evcon->address);
2586 /* some operating systems return ECONNREFUSED immediately
2587 * when connecting to a local address. the cleanup is going
2588 * to reschedule this function call.
2590 evhttp_connection_cb_cleanup(evcon);
2598 * Starts an HTTP request on the provided evhttp_connection object.
2599 * If the connection object is not connected to the web server already,
2600 * this will start the connection.
2604 evhttp_make_request(struct evhttp_connection *evcon,
2605 struct evhttp_request *req,
2606 enum evhttp_cmd_type type, const char *uri)
2608 /* We are making a request */
2609 req->kind = EVHTTP_REQUEST;
2611 if (req->uri != NULL)
2613 if ((req->uri = mm_strdup(uri)) == NULL) {
2614 event_warn("%s: strdup", __func__);
2615 evhttp_request_free_auto(req);
2619 /* Set the protocol version if it is not supplied */
2620 if (!req->major && !req->minor) {
2625 EVUTIL_ASSERT(req->evcon == NULL);
2627 EVUTIL_ASSERT(!(req->flags & EVHTTP_REQ_OWN_CONNECTION));
2629 TAILQ_INSERT_TAIL(&evcon->requests, req, next);
2631 /* If the connection object is not connected; make it so */
2632 if (!evhttp_connected(evcon)) {
2633 int res = evhttp_connection_connect_(evcon);
2634 /* evhttp_connection_fail_(), which is called through
2635 * evhttp_connection_connect_(), assumes that req lies in
2636 * evcon->requests. Thus, enqueue the request in advance and
2637 * remove it in the error case. */
2639 TAILQ_REMOVE(&evcon->requests, req, next);
2645 * If it's connected already and we are the first in the queue,
2646 * then we can dispatch this request immediately. Otherwise, it
2647 * will be dispatched once the pending requests are completed.
2649 if (TAILQ_FIRST(&evcon->requests) == req)
2650 evhttp_request_dispatch(evcon);
2656 evhttp_cancel_request(struct evhttp_request *req)
2658 struct evhttp_connection *evcon = req->evcon;
2659 if (evcon != NULL) {
2660 /* We need to remove it from the connection */
2661 if (TAILQ_FIRST(&evcon->requests) == req) {
2662 /* it's currently being worked on, so reset
2665 evhttp_connection_fail_(evcon,
2666 EVREQ_HTTP_REQUEST_CANCEL);
2668 /* connection fail freed the request */
2671 /* otherwise, we can just remove it from the
2674 TAILQ_REMOVE(&evcon->requests, req, next);
2678 evhttp_request_free_auto(req);
2682 * Reads data from file descriptor into request structure
2683 * Request structure needs to be set up correctly.
2687 evhttp_start_read_(struct evhttp_connection *evcon)
2689 bufferevent_disable(evcon->bufev, EV_WRITE);
2690 bufferevent_enable(evcon->bufev, EV_READ);
2692 evcon->state = EVCON_READING_FIRSTLINE;
2693 /* Reset the bufferevent callbacks */
2694 bufferevent_setcb(evcon->bufev,
2700 /* If there's still data pending, process it next time through the
2701 * loop. Don't do it now; that could get recusive. */
2702 if (evbuffer_get_length(bufferevent_get_input(evcon->bufev))) {
2703 event_deferred_cb_schedule_(get_deferred_queue(evcon),
2704 &evcon->read_more_deferred_cb);
2709 evhttp_start_write_(struct evhttp_connection *evcon)
2711 bufferevent_disable(evcon->bufev, EV_WRITE);
2712 bufferevent_enable(evcon->bufev, EV_READ);
2714 evcon->state = EVCON_WRITING;
2715 evhttp_write_buffer(evcon, evhttp_write_connectioncb, NULL);
2719 evhttp_send_done(struct evhttp_connection *evcon, void *arg)
2722 struct evhttp_request *req = TAILQ_FIRST(&evcon->requests);
2723 TAILQ_REMOVE(&evcon->requests, req, next);
2725 if (req->on_complete_cb != NULL) {
2726 req->on_complete_cb(req, req->on_complete_cb_arg);
2730 (REQ_VERSION_BEFORE(req, 1, 1) &&
2731 !evhttp_is_connection_keepalive(req->input_headers)) ||
2732 evhttp_is_request_connection_close(req);
2734 EVUTIL_ASSERT(req->flags & EVHTTP_REQ_OWN_CONNECTION);
2735 evhttp_request_free(req);
2738 evhttp_connection_free(evcon);
2742 /* we have a persistent connection; try to accept another request. */
2743 if (evhttp_associate_new_request_with_connection(evcon) == -1) {
2744 evhttp_connection_free(evcon);
2749 * Returns an error page.
2753 evhttp_send_error(struct evhttp_request *req, int error, const char *reason)
2756 #define ERR_FORMAT "<HTML><HEAD>\n" \
2757 "<TITLE>%d %s</TITLE>\n" \
2762 struct evbuffer *buf = evbuffer_new();
2764 /* if we cannot allocate memory; we just drop the connection */
2765 evhttp_connection_free(req->evcon);
2768 if (reason == NULL) {
2769 reason = evhttp_response_phrase_internal(error);
2772 evhttp_response_code_(req, error, reason);
2774 evbuffer_add_printf(buf, ERR_FORMAT, error, reason, reason);
2776 evhttp_send_page_(req, buf);
2782 /* Requires that headers and response code are already set up */
2785 evhttp_send(struct evhttp_request *req, struct evbuffer *databuf)
2787 struct evhttp_connection *evcon = req->evcon;
2789 if (evcon == NULL) {
2790 evhttp_request_free(req);
2794 EVUTIL_ASSERT(TAILQ_FIRST(&evcon->requests) == req);
2796 /* we expect no more calls form the user on this request */
2799 /* xxx: not sure if we really should expose the data buffer this way */
2800 if (databuf != NULL)
2801 evbuffer_add_buffer(req->output_buffer, databuf);
2803 /* Adds headers to the response */
2804 evhttp_make_header(evcon, req);
2806 evhttp_write_buffer(evcon, evhttp_send_done, NULL);
2810 evhttp_send_reply(struct evhttp_request *req, int code, const char *reason,
2811 struct evbuffer *databuf)
2813 evhttp_response_code_(req, code, reason);
2815 evhttp_send(req, databuf);
2819 evhttp_send_reply_start(struct evhttp_request *req, int code,
2822 evhttp_response_code_(req, code, reason);
2823 if (evhttp_find_header(req->output_headers, "Content-Length") == NULL &&
2824 REQ_VERSION_ATLEAST(req, 1, 1) &&
2825 evhttp_response_needs_body(req)) {
2827 * prefer HTTP/1.1 chunked encoding to closing the connection;
2828 * note RFC 2616 section 4.4 forbids it with Content-Length:
2829 * and it's not necessary then anyway.
2831 evhttp_add_header(req->output_headers, "Transfer-Encoding",
2837 evhttp_make_header(req->evcon, req);
2838 evhttp_write_buffer(req->evcon, NULL, NULL);
2842 evhttp_send_reply_chunk_with_cb(struct evhttp_request *req, struct evbuffer *databuf,
2843 void (*cb)(struct evhttp_connection *, void *), void *arg)
2845 struct evhttp_connection *evcon = req->evcon;
2846 struct evbuffer *output;
2851 output = bufferevent_get_output(evcon->bufev);
2853 if (evbuffer_get_length(databuf) == 0)
2855 if (!evhttp_response_needs_body(req))
2858 evbuffer_add_printf(output, "%x\r\n",
2859 (unsigned)evbuffer_get_length(databuf));
2861 evbuffer_add_buffer(output, databuf);
2863 evbuffer_add(output, "\r\n", 2);
2865 evhttp_write_buffer(evcon, cb, arg);
2869 evhttp_send_reply_chunk(struct evhttp_request *req, struct evbuffer *databuf)
2871 evhttp_send_reply_chunk_with_cb(req, databuf, NULL, NULL);
2874 evhttp_send_reply_end(struct evhttp_request *req)
2876 struct evhttp_connection *evcon = req->evcon;
2877 struct evbuffer *output;
2879 if (evcon == NULL) {
2880 evhttp_request_free(req);
2884 output = bufferevent_get_output(evcon->bufev);
2886 /* we expect no more calls form the user on this request */
2890 evbuffer_add(output, "0\r\n\r\n", 5);
2891 evhttp_write_buffer(req->evcon, evhttp_send_done, NULL);
2893 } else if (evbuffer_get_length(output) == 0) {
2894 /* let the connection know that we are done with the request */
2895 evhttp_send_done(evcon, NULL);
2897 /* make the callback execute after all data has been written */
2898 evcon->cb = evhttp_send_done;
2899 evcon->cb_arg = NULL;
2903 static const char *informational_phrases[] = {
2904 /* 100 */ "Continue",
2905 /* 101 */ "Switching Protocols"
2908 static const char *success_phrases[] = {
2910 /* 201 */ "Created",
2911 /* 202 */ "Accepted",
2912 /* 203 */ "Non-Authoritative Information",
2913 /* 204 */ "No Content",
2914 /* 205 */ "Reset Content",
2915 /* 206 */ "Partial Content"
2918 static const char *redirection_phrases[] = {
2919 /* 300 */ "Multiple Choices",
2920 /* 301 */ "Moved Permanently",
2922 /* 303 */ "See Other",
2923 /* 304 */ "Not Modified",
2924 /* 305 */ "Use Proxy",
2925 /* 307 */ "Temporary Redirect"
2928 static const char *client_error_phrases[] = {
2929 /* 400 */ "Bad Request",
2930 /* 401 */ "Unauthorized",
2931 /* 402 */ "Payment Required",
2932 /* 403 */ "Forbidden",
2933 /* 404 */ "Not Found",
2934 /* 405 */ "Method Not Allowed",
2935 /* 406 */ "Not Acceptable",
2936 /* 407 */ "Proxy Authentication Required",
2937 /* 408 */ "Request Time-out",
2938 /* 409 */ "Conflict",
2940 /* 411 */ "Length Required",
2941 /* 412 */ "Precondition Failed",
2942 /* 413 */ "Request Entity Too Large",
2943 /* 414 */ "Request-URI Too Large",
2944 /* 415 */ "Unsupported Media Type",
2945 /* 416 */ "Requested range not satisfiable",
2946 /* 417 */ "Expectation Failed"
2949 static const char *server_error_phrases[] = {
2950 /* 500 */ "Internal Server Error",
2951 /* 501 */ "Not Implemented",
2952 /* 502 */ "Bad Gateway",
2953 /* 503 */ "Service Unavailable",
2954 /* 504 */ "Gateway Time-out",
2955 /* 505 */ "HTTP Version not supported"
2958 struct response_class {
2960 size_t num_responses;
2961 const char **responses;
2965 #define MEMBERSOF(x) (sizeof(x)/sizeof(x[0]))
2968 static const struct response_class response_classes[] = {
2969 /* 1xx */ { "Informational", MEMBERSOF(informational_phrases), informational_phrases },
2970 /* 2xx */ { "Success", MEMBERSOF(success_phrases), success_phrases },
2971 /* 3xx */ { "Redirection", MEMBERSOF(redirection_phrases), redirection_phrases },
2972 /* 4xx */ { "Client Error", MEMBERSOF(client_error_phrases), client_error_phrases },
2973 /* 5xx */ { "Server Error", MEMBERSOF(server_error_phrases), server_error_phrases }
2977 evhttp_response_phrase_internal(int code)
2979 int klass = code / 100 - 1;
2980 int subcode = code % 100;
2982 /* Unknown class - can't do any better here */
2983 if (klass < 0 || klass >= (int) MEMBERSOF(response_classes))
2984 return "Unknown Status Class";
2986 /* Unknown sub-code, return class name at least */
2987 if (subcode >= (int) response_classes[klass].num_responses)
2988 return response_classes[klass].name;
2990 return response_classes[klass].responses[subcode];
2994 evhttp_response_code_(struct evhttp_request *req, int code, const char *reason)
2996 req->kind = EVHTTP_RESPONSE;
2997 req->response_code = code;
2998 if (req->response_code_line != NULL)
2999 mm_free(req->response_code_line);
3001 reason = evhttp_response_phrase_internal(code);
3002 req->response_code_line = mm_strdup(reason);
3003 if (req->response_code_line == NULL) {
3004 event_warn("%s: strdup", __func__);
3005 /* XXX what else can we do? */
3010 evhttp_send_page_(struct evhttp_request *req, struct evbuffer *databuf)
3012 if (!req->major || !req->minor) {
3017 if (req->kind != EVHTTP_RESPONSE)
3018 evhttp_response_code_(req, 200, "OK");
3020 evhttp_clear_headers(req->output_headers);
3021 evhttp_add_header(req->output_headers, "Content-Type", "text/html");
3022 evhttp_add_header(req->output_headers, "Connection", "close");
3024 evhttp_send(req, databuf);
3027 static const char uri_chars[256] = {
3029 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3030 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3031 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0,
3032 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,
3034 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3035 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1,
3036 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3037 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0,
3039 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3040 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3041 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3042 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, 0, 0, 0,
3045 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3046 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3047 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3050 #define CHAR_IS_UNRESERVED(c) \
3051 (uri_chars[(unsigned char)(c)])
3054 * Helper functions to encode/decode a string for inclusion in a URI.
3055 * The returned string must be freed by the caller.
3058 evhttp_uriencode(const char *uri, ev_ssize_t len, int space_as_plus)
3060 struct evbuffer *buf = evbuffer_new();
3061 const char *p, *end;
3070 if (uri + len < uri) {
3076 size_t slen = strlen(uri);
3078 if (slen >= EV_SSIZE_MAX) {
3079 /* we don't want to mix signed and unsigned */
3083 if (uri + slen < uri) {
3090 for (p = uri; p < end; p++) {
3091 if (CHAR_IS_UNRESERVED(*p)) {
3092 evbuffer_add(buf, p, 1);
3093 } else if (*p == ' ' && space_as_plus) {
3094 evbuffer_add(buf, "+", 1);
3096 evbuffer_add_printf(buf, "%%%02X", (unsigned char)(*p));
3100 evbuffer_add(buf, "", 1); /* NUL-terminator. */
3101 result = mm_malloc(evbuffer_get_length(buf));
3104 evbuffer_remove(buf, result, evbuffer_get_length(buf));
3112 evhttp_encode_uri(const char *str)
3114 return evhttp_uriencode(str, -1, 0);
3118 * @param decode_plus_ctl: if 1, we decode plus into space. If 0, we don't.
3119 * If -1, when true we transform plus to space only after we've seen
3120 * a ?. -1 is deprecated.
3121 * @return the number of bytes written to 'ret'.
3124 evhttp_decode_uri_internal(
3125 const char *uri, size_t length, char *ret, int decode_plus_ctl)
3129 int decode_plus = (decode_plus_ctl == 1) ? 1: 0;
3132 for (i = j = 0; i < length; i++) {
3135 if (decode_plus_ctl < 0)
3137 } else if (c == '+' && decode_plus) {
3139 } else if ((i + 2) < length && c == '%' &&
3140 EVUTIL_ISXDIGIT_(uri[i+1]) && EVUTIL_ISXDIGIT_(uri[i+2])) {
3145 c = (char)strtol(tmp, NULL, 16);
3157 evhttp_decode_uri(const char *uri)
3161 if ((ret = mm_malloc(strlen(uri) + 1)) == NULL) {
3162 event_warn("%s: malloc(%lu)", __func__,
3163 (unsigned long)(strlen(uri) + 1));
3167 evhttp_decode_uri_internal(uri, strlen(uri),
3168 ret, -1 /*always_decode_plus*/);
3174 evhttp_uridecode(const char *uri, int decode_plus, size_t *size_out)
3179 if ((ret = mm_malloc(strlen(uri) + 1)) == NULL) {
3180 event_warn("%s: malloc(%lu)", __func__,
3181 (unsigned long)(strlen(uri) + 1));
3185 n = evhttp_decode_uri_internal(uri, strlen(uri),
3186 ret, !!decode_plus/*always_decode_plus*/);
3189 EVUTIL_ASSERT(n >= 0);
3190 *size_out = (size_t)n;
3197 * Helper function to parse out arguments in a query.
3198 * The arguments are separated by key and value.
3202 evhttp_parse_query_impl(const char *str, struct evkeyvalq *headers,
3208 const char *query_part;
3210 struct evhttp_uri *uri=NULL;
3212 TAILQ_INIT(headers);
3215 uri = evhttp_uri_parse(str);
3218 query_part = evhttp_uri_get_query(uri);
3223 /* No arguments - we are done */
3224 if (!query_part || !strlen(query_part)) {
3229 if ((line = mm_strdup(query_part)) == NULL) {
3230 event_warn("%s: strdup", __func__);
3234 p = argument = line;
3235 while (p != NULL && *p != '\0') {
3236 char *key, *value, *decoded_value;
3237 argument = strsep(&p, "&");
3240 key = strsep(&value, "=");
3241 if (value == NULL || *key == '\0') {
3245 if ((decoded_value = mm_malloc(strlen(value) + 1)) == NULL) {
3246 event_warn("%s: mm_malloc", __func__);
3249 evhttp_decode_uri_internal(value, strlen(value),
3250 decoded_value, 1 /*always_decode_plus*/);
3251 event_debug(("Query Param: %s -> %s\n", key, decoded_value));
3252 evhttp_add_header_internal(headers, key, decoded_value);
3253 mm_free(decoded_value);
3259 evhttp_clear_headers(headers);
3264 evhttp_uri_free(uri);
3269 evhttp_parse_query(const char *uri, struct evkeyvalq *headers)
3271 return evhttp_parse_query_impl(uri, headers, 1);
3274 evhttp_parse_query_str(const char *uri, struct evkeyvalq *headers)
3276 return evhttp_parse_query_impl(uri, headers, 0);
3279 static struct evhttp_cb *
3280 evhttp_dispatch_callback(struct httpcbq *callbacks, struct evhttp_request *req)
3282 struct evhttp_cb *cb;
3287 /* Test for different URLs */
3288 path = evhttp_uri_get_path(req->uri_elems);
3289 offset = strlen(path);
3290 if ((translated = mm_malloc(offset + 1)) == NULL)
3292 evhttp_decode_uri_internal(path, offset, translated,
3293 0 /* decode_plus */);
3295 TAILQ_FOREACH(cb, callbacks, next) {
3296 if (!strcmp(cb->what, translated)) {
3297 mm_free(translated);
3302 mm_free(translated);
3308 prefix_suffix_match(const char *pattern, const char *name, int ignorecase)
3313 switch (c = *pattern++) {
3315 return *name == '\0';
3318 while (*name != '\0') {
3319 if (prefix_suffix_match(pattern, name,
3328 EVUTIL_TOLOWER_(c) != EVUTIL_TOLOWER_(*name))
3338 Search the vhost hierarchy beginning with http for a server alias
3339 matching hostname. If a match is found, and outhttp is non-null,
3340 outhttp is set to the matching http object and 1 is returned.
3344 evhttp_find_alias(struct evhttp *http, struct evhttp **outhttp,
3345 const char *hostname)
3347 struct evhttp_server_alias *alias;
3348 struct evhttp *vhost;
3350 TAILQ_FOREACH(alias, &http->aliases, next) {
3351 /* XXX Do we need to handle IP addresses? */
3352 if (!evutil_ascii_strcasecmp(alias->alias, hostname)) {
3359 /* XXX It might be good to avoid recursion here, but I don't
3360 see a way to do that w/o a list. */
3361 TAILQ_FOREACH(vhost, &http->virtualhosts, next_vhost) {
3362 if (evhttp_find_alias(vhost, outhttp, hostname))
3370 Attempts to find the best http object to handle a request for a hostname.
3371 All aliases for the root http object and vhosts are searched for an exact
3372 match. Then, the vhost hierarchy is traversed again for a matching
3375 If an alias or vhost is matched, 1 is returned, and outhttp, if non-null,
3376 is set with the best matching http object. If there are no matches, the
3377 root http object is stored in outhttp and 0 is returned.
3381 evhttp_find_vhost(struct evhttp *http, struct evhttp **outhttp,
3382 const char *hostname)
3384 struct evhttp *vhost;
3385 struct evhttp *oldhttp;
3386 int match_found = 0;
3388 if (evhttp_find_alias(http, outhttp, hostname))
3393 TAILQ_FOREACH(vhost, &http->virtualhosts, next_vhost) {
3394 if (prefix_suffix_match(vhost->vhost_pattern,
3395 hostname, 1 /* ignorecase */)) {
3401 } while (oldhttp != http);
3410 evhttp_handle_request(struct evhttp_request *req, void *arg)
3412 struct evhttp *http = arg;
3413 struct evhttp_cb *cb = NULL;
3414 const char *hostname;
3416 /* we have a new request on which the user needs to take action */
3419 if (req->type == 0 || req->uri == NULL) {
3420 evhttp_send_error(req, req->response_code, NULL);
3424 if ((http->allowed_methods & req->type) == 0) {
3425 event_debug(("Rejecting disallowed method %x (allowed: %x)\n",
3426 (unsigned)req->type, (unsigned)http->allowed_methods));
3427 evhttp_send_error(req, HTTP_NOTIMPLEMENTED, NULL);
3431 /* handle potential virtual hosts */
3432 hostname = evhttp_request_get_host(req);
3433 if (hostname != NULL) {
3434 evhttp_find_vhost(http, &http, hostname);
3437 if ((cb = evhttp_dispatch_callback(&http->callbacks, req)) != NULL) {
3438 (*cb->cb)(req, cb->cbarg);
3442 /* Generic call back */
3444 (*http->gencb)(req, http->gencbarg);
3447 /* We need to send a 404 here */
3448 #define ERR_FORMAT "<html><head>" \
3449 "<title>404 Not Found</title>" \
3451 "<h1>Not Found</h1>" \
3452 "<p>The requested URL %s was not found on this server.</p>"\
3456 struct evbuffer *buf;
3458 if ((escaped_html = evhttp_htmlescape(req->uri)) == NULL) {
3459 evhttp_connection_free(req->evcon);
3463 if ((buf = evbuffer_new()) == NULL) {
3464 mm_free(escaped_html);
3465 evhttp_connection_free(req->evcon);
3469 evhttp_response_code_(req, HTTP_NOTFOUND, "Not Found");
3471 evbuffer_add_printf(buf, ERR_FORMAT, escaped_html);
3473 mm_free(escaped_html);
3475 evhttp_send_page_(req, buf);
3482 /* Listener callback when a connection arrives at a server. */
3484 accept_socket_cb(struct evconnlistener *listener, evutil_socket_t nfd, struct sockaddr *peer_sa, int peer_socklen, void *arg)
3486 struct evhttp *http = arg;
3488 evhttp_get_request(http, nfd, peer_sa, peer_socklen);
3492 evhttp_bind_socket(struct evhttp *http, const char *address, ev_uint16_t port)
3494 struct evhttp_bound_socket *bound =
3495 evhttp_bind_socket_with_handle(http, address, port);
3501 struct evhttp_bound_socket *
3502 evhttp_bind_socket_with_handle(struct evhttp *http, const char *address, ev_uint16_t port)
3505 struct evhttp_bound_socket *bound;
3507 if ((fd = bind_socket(address, port, 1 /*reuse*/)) == -1)
3510 if (listen(fd, 128) == -1) {
3511 event_sock_warn(fd, "%s: listen", __func__);
3512 evutil_closesocket(fd);
3516 bound = evhttp_accept_socket_with_handle(http, fd);
3518 if (bound != NULL) {
3519 event_debug(("Bound to port %d - Awaiting connections ... ",
3528 evhttp_accept_socket(struct evhttp *http, evutil_socket_t fd)
3530 struct evhttp_bound_socket *bound =
3531 evhttp_accept_socket_with_handle(http, fd);
3538 evhttp_foreach_bound_socket(struct evhttp *http,
3539 evhttp_bound_socket_foreach_fn *function,
3542 struct evhttp_bound_socket *bound;
3544 TAILQ_FOREACH(bound, &http->sockets, next)
3545 function(bound, argument);
3548 struct evhttp_bound_socket *
3549 evhttp_accept_socket_with_handle(struct evhttp *http, evutil_socket_t fd)
3551 struct evhttp_bound_socket *bound;
3552 struct evconnlistener *listener;
3554 LEV_OPT_REUSEABLE|LEV_OPT_CLOSE_ON_EXEC|LEV_OPT_CLOSE_ON_FREE;
3556 listener = evconnlistener_new(http->base, NULL, NULL,
3558 0, /* Backlog is '0' because we already said 'listen' */
3563 bound = evhttp_bind_listener(http, listener);
3565 evconnlistener_free(listener);
3571 struct evhttp_bound_socket *
3572 evhttp_bind_listener(struct evhttp *http, struct evconnlistener *listener)
3574 struct evhttp_bound_socket *bound;
3576 bound = mm_malloc(sizeof(struct evhttp_bound_socket));
3580 bound->listener = listener;
3581 TAILQ_INSERT_TAIL(&http->sockets, bound, next);
3583 evconnlistener_set_cb(listener, accept_socket_cb, http);
3588 evhttp_bound_socket_get_fd(struct evhttp_bound_socket *bound)
3590 return evconnlistener_get_fd(bound->listener);
3593 struct evconnlistener *
3594 evhttp_bound_socket_get_listener(struct evhttp_bound_socket *bound)
3596 return bound->listener;
3600 evhttp_del_accept_socket(struct evhttp *http, struct evhttp_bound_socket *bound)
3602 TAILQ_REMOVE(&http->sockets, bound, next);
3603 evconnlistener_free(bound->listener);
3607 static struct evhttp*
3608 evhttp_new_object(void)
3610 struct evhttp *http = NULL;
3612 if ((http = mm_calloc(1, sizeof(struct evhttp))) == NULL) {
3613 event_warn("%s: calloc", __func__);
3617 evutil_timerclear(&http->timeout);
3618 evhttp_set_max_headers_size(http, EV_SIZE_MAX);
3619 evhttp_set_max_body_size(http, EV_SIZE_MAX);
3620 evhttp_set_default_content_type(http, "text/html; charset=ISO-8859-1");
3621 evhttp_set_allowed_methods(http,
3628 TAILQ_INIT(&http->sockets);
3629 TAILQ_INIT(&http->callbacks);
3630 TAILQ_INIT(&http->connections);
3631 TAILQ_INIT(&http->virtualhosts);
3632 TAILQ_INIT(&http->aliases);
3638 evhttp_new(struct event_base *base)
3640 struct evhttp *http = NULL;
3642 http = evhttp_new_object();
3651 * Start a web server on the specified address and port.
3655 evhttp_start(const char *address, ev_uint16_t port)
3657 struct evhttp *http = NULL;
3659 http = evhttp_new_object();
3662 if (evhttp_bind_socket(http, address, port) == -1) {
3671 evhttp_free(struct evhttp* http)
3673 struct evhttp_cb *http_cb;
3674 struct evhttp_connection *evcon;
3675 struct evhttp_bound_socket *bound;
3676 struct evhttp* vhost;
3677 struct evhttp_server_alias *alias;
3679 /* Remove the accepting part */
3680 while ((bound = TAILQ_FIRST(&http->sockets)) != NULL) {
3681 TAILQ_REMOVE(&http->sockets, bound, next);
3683 evconnlistener_free(bound->listener);
3688 while ((evcon = TAILQ_FIRST(&http->connections)) != NULL) {
3689 /* evhttp_connection_free removes the connection */
3690 evhttp_connection_free(evcon);
3693 while ((http_cb = TAILQ_FIRST(&http->callbacks)) != NULL) {
3694 TAILQ_REMOVE(&http->callbacks, http_cb, next);
3695 mm_free(http_cb->what);
3699 while ((vhost = TAILQ_FIRST(&http->virtualhosts)) != NULL) {
3700 TAILQ_REMOVE(&http->virtualhosts, vhost, next_vhost);
3705 if (http->vhost_pattern != NULL)
3706 mm_free(http->vhost_pattern);
3708 while ((alias = TAILQ_FIRST(&http->aliases)) != NULL) {
3709 TAILQ_REMOVE(&http->aliases, alias, next);
3710 mm_free(alias->alias);
3718 evhttp_add_virtual_host(struct evhttp* http, const char *pattern,
3719 struct evhttp* vhost)
3721 /* a vhost can only be a vhost once and should not have bound sockets */
3722 if (vhost->vhost_pattern != NULL ||
3723 TAILQ_FIRST(&vhost->sockets) != NULL)
3726 vhost->vhost_pattern = mm_strdup(pattern);
3727 if (vhost->vhost_pattern == NULL)
3730 TAILQ_INSERT_TAIL(&http->virtualhosts, vhost, next_vhost);
3736 evhttp_remove_virtual_host(struct evhttp* http, struct evhttp* vhost)
3738 if (vhost->vhost_pattern == NULL)
3741 TAILQ_REMOVE(&http->virtualhosts, vhost, next_vhost);
3743 mm_free(vhost->vhost_pattern);
3744 vhost->vhost_pattern = NULL;
3750 evhttp_add_server_alias(struct evhttp *http, const char *alias)
3752 struct evhttp_server_alias *evalias;
3754 evalias = mm_calloc(1, sizeof(*evalias));
3758 evalias->alias = mm_strdup(alias);
3759 if (!evalias->alias) {
3764 TAILQ_INSERT_TAIL(&http->aliases, evalias, next);
3770 evhttp_remove_server_alias(struct evhttp *http, const char *alias)
3772 struct evhttp_server_alias *evalias;
3774 TAILQ_FOREACH(evalias, &http->aliases, next) {
3775 if (evutil_ascii_strcasecmp(evalias->alias, alias) == 0) {
3776 TAILQ_REMOVE(&http->aliases, evalias, next);
3777 mm_free(evalias->alias);
3787 evhttp_set_timeout(struct evhttp* http, int timeout_in_secs)
3789 if (timeout_in_secs == -1) {
3790 evhttp_set_timeout_tv(http, NULL);
3793 tv.tv_sec = timeout_in_secs;
3795 evhttp_set_timeout_tv(http, &tv);
3800 evhttp_set_timeout_tv(struct evhttp* http, const struct timeval* tv)
3803 http->timeout = *tv;
3805 evutil_timerclear(&http->timeout);
3809 int evhttp_set_flags(struct evhttp *http, int flags)
3811 int avail_flags = 0;
3812 avail_flags |= EVHTTP_SERVER_LINGERING_CLOSE;
3814 if (flags & ~avail_flags)
3816 http->flags &= ~avail_flags;
3818 http->flags |= flags;
3824 evhttp_set_max_headers_size(struct evhttp* http, ev_ssize_t max_headers_size)
3826 if (max_headers_size < 0)
3827 http->default_max_headers_size = EV_SIZE_MAX;
3829 http->default_max_headers_size = max_headers_size;
3833 evhttp_set_max_body_size(struct evhttp* http, ev_ssize_t max_body_size)
3835 if (max_body_size < 0)
3836 http->default_max_body_size = EV_UINT64_MAX;
3838 http->default_max_body_size = max_body_size;
3842 evhttp_set_default_content_type(struct evhttp *http,
3843 const char *content_type) {
3844 http->default_content_type = content_type;
3848 evhttp_set_allowed_methods(struct evhttp* http, ev_uint16_t methods)
3850 http->allowed_methods = methods;
3854 evhttp_set_cb(struct evhttp *http, const char *uri,
3855 void (*cb)(struct evhttp_request *, void *), void *cbarg)
3857 struct evhttp_cb *http_cb;
3859 TAILQ_FOREACH(http_cb, &http->callbacks, next) {
3860 if (strcmp(http_cb->what, uri) == 0)
3864 if ((http_cb = mm_calloc(1, sizeof(struct evhttp_cb))) == NULL) {
3865 event_warn("%s: calloc", __func__);
3869 http_cb->what = mm_strdup(uri);
3870 if (http_cb->what == NULL) {
3871 event_warn("%s: strdup", __func__);
3876 http_cb->cbarg = cbarg;
3878 TAILQ_INSERT_TAIL(&http->callbacks, http_cb, next);
3884 evhttp_del_cb(struct evhttp *http, const char *uri)
3886 struct evhttp_cb *http_cb;
3888 TAILQ_FOREACH(http_cb, &http->callbacks, next) {
3889 if (strcmp(http_cb->what, uri) == 0)
3892 if (http_cb == NULL)
3895 TAILQ_REMOVE(&http->callbacks, http_cb, next);
3896 mm_free(http_cb->what);
3903 evhttp_set_gencb(struct evhttp *http,
3904 void (*cb)(struct evhttp_request *, void *), void *cbarg)
3907 http->gencbarg = cbarg;
3911 evhttp_set_bevcb(struct evhttp *http,
3912 struct bufferevent* (*cb)(struct event_base *, void *), void *cbarg)
3915 http->bevcbarg = cbarg;
3919 * Request related functions
3922 struct evhttp_request *
3923 evhttp_request_new(void (*cb)(struct evhttp_request *, void *), void *arg)
3925 struct evhttp_request *req = NULL;
3927 /* Allocate request structure */
3928 if ((req = mm_calloc(1, sizeof(struct evhttp_request))) == NULL) {
3929 event_warn("%s: calloc", __func__);
3933 req->headers_size = 0;
3936 req->kind = EVHTTP_RESPONSE;
3937 req->input_headers = mm_calloc(1, sizeof(struct evkeyvalq));
3938 if (req->input_headers == NULL) {
3939 event_warn("%s: calloc", __func__);
3942 TAILQ_INIT(req->input_headers);
3944 req->output_headers = mm_calloc(1, sizeof(struct evkeyvalq));
3945 if (req->output_headers == NULL) {
3946 event_warn("%s: calloc", __func__);
3949 TAILQ_INIT(req->output_headers);
3951 if ((req->input_buffer = evbuffer_new()) == NULL) {
3952 event_warn("%s: evbuffer_new", __func__);
3956 if ((req->output_buffer = evbuffer_new()) == NULL) {
3957 event_warn("%s: evbuffer_new", __func__);
3968 evhttp_request_free(req);
3973 evhttp_request_free(struct evhttp_request *req)
3975 if ((req->flags & EVHTTP_REQ_DEFER_FREE) != 0) {
3976 req->flags |= EVHTTP_REQ_NEEDS_FREE;
3980 if (req->remote_host != NULL)
3981 mm_free(req->remote_host);
3982 if (req->uri != NULL)
3984 if (req->uri_elems != NULL)
3985 evhttp_uri_free(req->uri_elems);
3986 if (req->response_code_line != NULL)
3987 mm_free(req->response_code_line);
3988 if (req->host_cache != NULL)
3989 mm_free(req->host_cache);
3991 evhttp_clear_headers(req->input_headers);
3992 mm_free(req->input_headers);
3994 evhttp_clear_headers(req->output_headers);
3995 mm_free(req->output_headers);
3997 if (req->input_buffer != NULL)
3998 evbuffer_free(req->input_buffer);
4000 if (req->output_buffer != NULL)
4001 evbuffer_free(req->output_buffer);
4007 evhttp_request_own(struct evhttp_request *req)
4009 req->flags |= EVHTTP_USER_OWNED;
4013 evhttp_request_is_owned(struct evhttp_request *req)
4015 return (req->flags & EVHTTP_USER_OWNED) != 0;
4018 struct evhttp_connection *
4019 evhttp_request_get_connection(struct evhttp_request *req)
4025 evhttp_connection_get_base(struct evhttp_connection *conn)
4031 evhttp_request_set_chunked_cb(struct evhttp_request *req,
4032 void (*cb)(struct evhttp_request *, void *))
4038 evhttp_request_set_header_cb(struct evhttp_request *req,
4039 int (*cb)(struct evhttp_request *, void *))
4041 req->header_cb = cb;
4045 evhttp_request_set_error_cb(struct evhttp_request *req,
4046 void (*cb)(enum evhttp_request_error, void *))
4052 evhttp_request_set_on_complete_cb(struct evhttp_request *req,
4053 void (*cb)(struct evhttp_request *, void *), void *cb_arg)
4055 req->on_complete_cb = cb;
4056 req->on_complete_cb_arg = cb_arg;
4060 * Allows for inspection of the request URI
4064 evhttp_request_get_uri(const struct evhttp_request *req) {
4065 if (req->uri == NULL)
4066 event_debug(("%s: request %p has no uri\n", __func__, req));
4070 const struct evhttp_uri *
4071 evhttp_request_get_evhttp_uri(const struct evhttp_request *req) {
4072 if (req->uri_elems == NULL)
4073 event_debug(("%s: request %p has no uri elems\n",
4075 return (req->uri_elems);
4079 evhttp_request_get_host(struct evhttp_request *req)
4081 const char *host = NULL;
4083 if (req->host_cache)
4084 return req->host_cache;
4087 host = evhttp_uri_get_host(req->uri_elems);
4088 if (!host && req->input_headers) {
4092 host = evhttp_find_header(req->input_headers, "Host");
4093 /* The Host: header may include a port. Remove it here
4094 to be consistent with uri_elems case above. */
4096 p = host + strlen(host) - 1;
4097 while (p > host && EVUTIL_ISDIGIT_(*p))
4099 if (p > host && *p == ':') {
4101 req->host_cache = mm_malloc(len + 1);
4102 if (!req->host_cache) {
4103 event_warn("%s: malloc", __func__);
4106 memcpy(req->host_cache, host, len);
4107 req->host_cache[len] = '\0';
4108 host = req->host_cache;
4116 enum evhttp_cmd_type
4117 evhttp_request_get_command(const struct evhttp_request *req) {
4122 evhttp_request_get_response_code(const struct evhttp_request *req)
4124 return req->response_code;
4128 evhttp_request_get_response_code_line(const struct evhttp_request *req)
4130 return req->response_code_line;
4133 /** Returns the input headers */
4134 struct evkeyvalq *evhttp_request_get_input_headers(struct evhttp_request *req)
4136 return (req->input_headers);
4139 /** Returns the output headers */
4140 struct evkeyvalq *evhttp_request_get_output_headers(struct evhttp_request *req)
4142 return (req->output_headers);
4145 /** Returns the input buffer */
4146 struct evbuffer *evhttp_request_get_input_buffer(struct evhttp_request *req)
4148 return (req->input_buffer);
4151 /** Returns the output buffer */
4152 struct evbuffer *evhttp_request_get_output_buffer(struct evhttp_request *req)
4154 return (req->output_buffer);
4159 * Takes a file descriptor to read a request from.
4160 * The callback is executed once the whole request has been read.
4163 static struct evhttp_connection*
4164 evhttp_get_request_connection(
4165 struct evhttp* http,
4166 evutil_socket_t fd, struct sockaddr *sa, ev_socklen_t salen)
4168 struct evhttp_connection *evcon;
4169 char *hostname = NULL, *portname = NULL;
4170 struct bufferevent* bev = NULL;
4172 name_from_addr(sa, salen, &hostname, &portname);
4173 if (hostname == NULL || portname == NULL) {
4174 if (hostname) mm_free(hostname);
4175 if (portname) mm_free(portname);
4179 event_debug(("%s: new request from %s:%s on "EV_SOCK_FMT"\n",
4180 __func__, hostname, portname, EV_SOCK_ARG(fd)));
4182 /* we need a connection object to put the http request on */
4183 if (http->bevcb != NULL) {
4184 bev = (*http->bevcb)(http->base, http->bevcbarg);
4186 evcon = evhttp_connection_base_bufferevent_new(
4187 http->base, NULL, bev, hostname, atoi(portname));
4193 evcon->max_headers_size = http->default_max_headers_size;
4194 evcon->max_body_size = http->default_max_body_size;
4195 if (http->flags & EVHTTP_SERVER_LINGERING_CLOSE)
4196 evcon->flags |= EVHTTP_CON_LINGERING_CLOSE;
4198 evcon->flags |= EVHTTP_CON_INCOMING;
4199 evcon->state = EVCON_READING_FIRSTLINE;
4203 bufferevent_enable(evcon->bufev, EV_READ);
4204 bufferevent_disable(evcon->bufev, EV_WRITE);
4205 bufferevent_setfd(evcon->bufev, fd);
4211 evhttp_associate_new_request_with_connection(struct evhttp_connection *evcon)
4213 struct evhttp *http = evcon->http_server;
4214 struct evhttp_request *req;
4215 if ((req = evhttp_request_new(evhttp_handle_request, http)) == NULL)
4218 if ((req->remote_host = mm_strdup(evcon->address)) == NULL) {
4219 event_warn("%s: strdup", __func__);
4220 evhttp_request_free(req);
4223 req->remote_port = evcon->port;
4225 req->evcon = evcon; /* the request ends up owning the connection */
4226 req->flags |= EVHTTP_REQ_OWN_CONNECTION;
4228 /* We did not present the request to the user user yet, so treat it as
4229 * if the user was done with the request. This allows us to free the
4230 * request on a persistent connection if the client drops it without
4231 * sending a request.
4235 TAILQ_INSERT_TAIL(&evcon->requests, req, next);
4237 req->kind = EVHTTP_REQUEST;
4240 evhttp_start_read_(evcon);
4246 evhttp_get_request(struct evhttp *http, evutil_socket_t fd,
4247 struct sockaddr *sa, ev_socklen_t salen)
4249 struct evhttp_connection *evcon;
4251 evcon = evhttp_get_request_connection(http, fd, sa, salen);
4252 if (evcon == NULL) {
4253 event_sock_warn(fd, "%s: cannot get connection on "EV_SOCK_FMT,
4254 __func__, EV_SOCK_ARG(fd));
4255 evutil_closesocket(fd);
4259 /* the timeout can be used by the server to close idle connections */
4260 if (evutil_timerisset(&http->timeout))
4261 evhttp_connection_set_timeout_tv(evcon, &http->timeout);
4264 * if we want to accept more than one request on a connection,
4265 * we need to know which http server it belongs to.
4267 evcon->http_server = http;
4268 TAILQ_INSERT_TAIL(&http->connections, evcon, next);
4270 if (evhttp_associate_new_request_with_connection(evcon) == -1)
4271 evhttp_connection_free(evcon);
4276 * Network helper functions that we do not want to export to the rest of
4281 name_from_addr(struct sockaddr *sa, ev_socklen_t salen,
4282 char **phost, char **pport)
4284 char ntop[NI_MAXHOST];
4285 char strport[NI_MAXSERV];
4288 #ifdef EVENT__HAVE_GETNAMEINFO
4289 ni_result = getnameinfo(sa, salen,
4290 ntop, sizeof(ntop), strport, sizeof(strport),
4291 NI_NUMERICHOST|NI_NUMERICSERV);
4293 if (ni_result != 0) {
4295 /* Windows doesn't have an EAI_SYSTEM. */
4296 if (ni_result == EAI_SYSTEM)
4297 event_err(1, "getnameinfo failed");
4300 event_errx(1, "getnameinfo failed: %s", gai_strerror(ni_result));
4304 ni_result = fake_getnameinfo(sa, salen,
4305 ntop, sizeof(ntop), strport, sizeof(strport),
4306 NI_NUMERICHOST|NI_NUMERICSERV);
4311 *phost = mm_strdup(ntop);
4312 *pport = mm_strdup(strport);
4315 /* Create a non-blocking socket and bind it */
4316 /* todo: rename this function */
4317 static evutil_socket_t
4318 bind_socket_ai(struct evutil_addrinfo *ai, int reuse)
4325 /* Create listen socket */
4326 fd = evutil_socket_(ai ? ai->ai_family : AF_INET,
4327 SOCK_STREAM|EVUTIL_SOCK_NONBLOCK|EVUTIL_SOCK_CLOEXEC, 0);
4329 event_sock_warn(-1, "socket");
4333 if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (void *)&on, sizeof(on))<0)
4336 if (evutil_make_listen_socket_reuseable(fd) < 0)
4341 r = bind(fd, ai->ai_addr, (ev_socklen_t)ai->ai_addrlen);
4349 serrno = EVUTIL_SOCKET_ERROR();
4350 evutil_closesocket(fd);
4351 EVUTIL_SET_SOCKET_ERROR(serrno);
4355 static struct evutil_addrinfo *
4356 make_addrinfo(const char *address, ev_uint16_t port)
4358 struct evutil_addrinfo *ai = NULL;
4360 struct evutil_addrinfo hints;
4361 char strport[NI_MAXSERV];
4364 memset(&hints, 0, sizeof(hints));
4365 hints.ai_family = AF_UNSPEC;
4366 hints.ai_socktype = SOCK_STREAM;
4367 /* turn NULL hostname into INADDR_ANY, and skip looking up any address
4368 * types we don't have an interface to connect to. */
4369 hints.ai_flags = EVUTIL_AI_PASSIVE|EVUTIL_AI_ADDRCONFIG;
4370 evutil_snprintf(strport, sizeof(strport), "%d", port);
4371 if ((ai_result = evutil_getaddrinfo(address, strport, &hints, &ai))
4373 if (ai_result == EVUTIL_EAI_SYSTEM)
4374 event_warn("getaddrinfo");
4376 event_warnx("getaddrinfo: %s",
4377 evutil_gai_strerror(ai_result));
4384 static evutil_socket_t
4385 bind_socket(const char *address, ev_uint16_t port, int reuse)
4388 struct evutil_addrinfo *aitop = NULL;
4390 /* just create an unbound socket */
4391 if (address == NULL && port == 0)
4392 return bind_socket_ai(NULL, 0);
4394 aitop = make_addrinfo(address, port);
4399 fd = bind_socket_ai(aitop, reuse);
4401 evutil_freeaddrinfo(aitop);
4408 char *scheme; /* scheme; e.g http, ftp etc */
4409 char *userinfo; /* userinfo (typically username:pass), or NULL */
4410 char *host; /* hostname, IP address, or NULL */
4411 int port; /* port, or zero */
4412 char *path; /* path, or "". */
4413 char *query; /* query, or NULL */
4414 char *fragment; /* fragment or NULL */
4418 evhttp_uri_new(void)
4420 struct evhttp_uri *uri = mm_calloc(sizeof(struct evhttp_uri), 1);
4427 evhttp_uri_set_flags(struct evhttp_uri *uri, unsigned flags)
4432 /* Return true if the string starting at s and ending immediately before eos
4433 * is a valid URI scheme according to RFC3986
4436 scheme_ok(const char *s, const char *eos)
4438 /* scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." ) */
4439 EVUTIL_ASSERT(eos >= s);
4442 if (!EVUTIL_ISALPHA_(*s))
4445 if (! EVUTIL_ISALNUM_(*s) &&
4446 *s != '+' && *s != '-' && *s != '.')
4452 #define SUBDELIMS "!$&'()*+,;="
4454 /* Return true iff [s..eos) is a valid userinfo */
4456 userinfo_ok(const char *s, const char *eos)
4459 if (CHAR_IS_UNRESERVED(*s) ||
4460 strchr(SUBDELIMS, *s) ||
4463 else if (*s == '%' && s+2 < eos &&
4464 EVUTIL_ISXDIGIT_(s[1]) &&
4465 EVUTIL_ISXDIGIT_(s[2]))
4474 regname_ok(const char *s, const char *eos)
4476 while (s && s<eos) {
4477 if (CHAR_IS_UNRESERVED(*s) ||
4478 strchr(SUBDELIMS, *s))
4480 else if (*s == '%' &&
4481 EVUTIL_ISXDIGIT_(s[1]) &&
4482 EVUTIL_ISXDIGIT_(s[2]))
4491 parse_port(const char *s, const char *eos)
4495 if (! EVUTIL_ISDIGIT_(*s))
4497 portnum = (portnum * 10) + (*s - '0');
4500 if (portnum > 65535)
4507 /* returns 0 for bad, 1 for ipv6, 2 for IPvFuture */
4509 bracket_addr_ok(const char *s, const char *eos)
4511 if (s + 3 > eos || *s != '[' || *(eos-1) != ']')
4514 /* IPvFuture, or junk.
4515 "v" 1*HEXDIG "." 1*( unreserved / sub-delims / ":" )
4517 s += 2; /* skip [v */
4519 if (!EVUTIL_ISXDIGIT_(*s)) /*require at least one*/
4521 while (s < eos && *s != '.') {
4522 if (EVUTIL_ISXDIGIT_(*s))
4531 if (CHAR_IS_UNRESERVED(*s) ||
4532 strchr(SUBDELIMS, *s) ||
4542 ev_ssize_t n_chars = eos-s-2;
4543 struct in6_addr in6;
4544 if (n_chars >= 64) /* way too long */
4546 memcpy(buf, s+1, n_chars);
4548 return (evutil_inet_pton(AF_INET6,buf,&in6)==1) ? 1 : 0;
4553 parse_authority(struct evhttp_uri *uri, char *s, char *eos)
4558 uri->host = mm_strdup("");
4559 if (uri->host == NULL) {
4560 event_warn("%s: strdup", __func__);
4566 /* Optionally, we start with "userinfo@" */
4568 cp = strchr(s, '@');
4569 if (cp && cp < eos) {
4570 if (! userinfo_ok(s,cp))
4573 uri->userinfo = mm_strdup(s);
4574 if (uri->userinfo == NULL) {
4575 event_warn("%s: strdup", __func__);
4581 /* Optionally, we end with ":port" */
4582 for (port=eos-1; port >= cp && EVUTIL_ISDIGIT_(*port); --port)
4584 if (port >= cp && *port == ':') {
4585 if (port+1 == eos) /* Leave port unspecified; the RFC allows a
4588 else if ((uri->port = parse_port(port+1, eos))<0)
4592 /* Now, cp..eos holds the "host" port, which can be an IPv4Address,
4593 * an IP-Literal, or a reg-name */
4594 EVUTIL_ASSERT(eos >= cp);
4595 if (*cp == '[' && eos >= cp+2 && *(eos-1) == ']') {
4596 /* IPv6address, IP-Literal, or junk. */
4597 if (! bracket_addr_ok(cp, eos))
4600 /* Make sure the host part is ok. */
4601 if (! regname_ok(cp,eos)) /* Match IPv4Address or reg-name */
4604 uri->host = mm_malloc(eos-cp+1);
4605 if (uri->host == NULL) {
4606 event_warn("%s: malloc", __func__);
4609 memcpy(uri->host, cp, eos-cp);
4610 uri->host[eos-cp] = '\0';
4616 end_of_authority(char *cp)
4619 if (*cp == '?' || *cp == '#' || *cp == '/')
4632 /* Return the character after the longest prefix of 'cp' that matches...
4633 * *pchar / "/" if allow_qchars is false, or
4634 * *(pchar / "/" / "?") if allow_qchars is true.
4637 end_of_path(char *cp, enum uri_part part, unsigned flags)
4639 if (flags & EVHTTP_URI_NONCONFORMANT) {
4640 /* If NONCONFORMANT:
4641 * Path is everything up to a # or ? or nul.
4642 * Query is everything up a # or nul
4643 * Fragment is everything up to a nul.
4647 while (*cp && *cp != '#' && *cp != '?')
4651 while (*cp && *cp != '#')
4662 if (CHAR_IS_UNRESERVED(*cp) ||
4663 strchr(SUBDELIMS, *cp) ||
4664 *cp == ':' || *cp == '@' || *cp == '/')
4666 else if (*cp == '%' && EVUTIL_ISXDIGIT_(cp[1]) &&
4667 EVUTIL_ISXDIGIT_(cp[2]))
4669 else if (*cp == '?' && part != PART_PATH)
4678 path_matches_noscheme(const char *cp)
4683 else if (*cp == '/')
4691 evhttp_uri_parse(const char *source_uri)
4693 return evhttp_uri_parse_with_flags(source_uri, 0);
4697 evhttp_uri_parse_with_flags(const char *source_uri, unsigned flags)
4699 char *readbuf = NULL, *readp = NULL, *token = NULL, *query = NULL;
4700 char *path = NULL, *fragment = NULL;
4701 int got_authority = 0;
4703 struct evhttp_uri *uri = mm_calloc(1, sizeof(struct evhttp_uri));
4705 event_warn("%s: calloc", __func__);
4711 readbuf = mm_strdup(source_uri);
4712 if (readbuf == NULL) {
4713 event_warn("%s: strdup", __func__);
4720 /* We try to follow RFC3986 here as much as we can, and match
4723 URI = scheme ":" hier-part [ "?" query ] [ "#" fragment ]
4725 relative-ref = relative-part [ "?" query ] [ "#" fragment ]
4729 token = strchr(readp, ':');
4730 if (token && scheme_ok(readp,token)) {
4732 uri->scheme = mm_strdup(readp);
4733 if (uri->scheme == NULL) {
4734 event_warn("%s: strdup", __func__);
4737 readp = token+1; /* eat : */
4740 /* 2. Optionally, "//" then an 'authority' part. */
4741 if (readp[0]=='/' && readp[1] == '/') {
4745 path = end_of_authority(readp);
4746 if (parse_authority(uri, authority, path) < 0)
4752 /* 3. Query: path-abempty, path-absolute, path-rootless, or path-empty
4755 readp = end_of_path(path, PART_PATH, flags);
4758 if (*readp == '?') {
4762 readp = end_of_path(readp, PART_QUERY, flags);
4765 if (*readp == '#') {
4769 readp = end_of_path(readp, PART_FRAGMENT, flags);
4771 if (*readp != '\0') {
4775 /* These next two cases may be unreachable; I'm leaving them
4776 * in to be defensive. */
4777 /* If you didn't get an authority, the path can't begin with "//" */
4778 if (!got_authority && path[0]=='/' && path[1]=='/')
4780 /* If you did get an authority, the path must begin with "/" or be
4782 if (got_authority && path[0] != '/' && path[0] != '\0')
4784 /* (End of maybe-unreachable cases) */
4786 /* If there was no scheme, the first part of the path (if any) must
4787 * have no colon in it. */
4788 if (! uri->scheme && !path_matches_noscheme(path))
4791 EVUTIL_ASSERT(path);
4792 uri->path = mm_strdup(path);
4793 if (uri->path == NULL) {
4794 event_warn("%s: strdup", __func__);
4799 uri->query = mm_strdup(query);
4800 if (uri->query == NULL) {
4801 event_warn("%s: strdup", __func__);
4806 uri->fragment = mm_strdup(fragment);
4807 if (uri->fragment == NULL) {
4808 event_warn("%s: strdup", __func__);
4818 evhttp_uri_free(uri);
4825 evhttp_uri_free(struct evhttp_uri *uri)
4827 #define URI_FREE_STR_(f) \
4832 URI_FREE_STR_(scheme);
4833 URI_FREE_STR_(userinfo);
4834 URI_FREE_STR_(host);
4835 URI_FREE_STR_(path);
4836 URI_FREE_STR_(query);
4837 URI_FREE_STR_(fragment);
4840 #undef URI_FREE_STR_
4844 evhttp_uri_join(struct evhttp_uri *uri, char *buf, size_t limit)
4846 struct evbuffer *tmp = 0;
4847 size_t joined_size = 0;
4848 char *output = NULL;
4850 #define URI_ADD_(f) evbuffer_add(tmp, uri->f, strlen(uri->f))
4852 if (!uri || !buf || !limit)
4855 tmp = evbuffer_new();
4861 evbuffer_add(tmp, ":", 1);
4864 evbuffer_add(tmp, "//", 2);
4866 evbuffer_add_printf(tmp,"%s@", uri->userinfo);
4869 evbuffer_add_printf(tmp,":%d", uri->port);
4871 if (uri->path && uri->path[0] != '/' && uri->path[0] != '\0')
4879 evbuffer_add(tmp, "?", 1);
4883 if (uri->fragment) {
4884 evbuffer_add(tmp, "#", 1);
4888 evbuffer_add(tmp, "\0", 1); /* NUL */
4890 joined_size = evbuffer_get_length(tmp);
4892 if (joined_size > limit) {
4893 /* It doesn't fit. */
4897 evbuffer_remove(tmp, buf, joined_size);
4908 evhttp_uri_get_scheme(const struct evhttp_uri *uri)
4913 evhttp_uri_get_userinfo(const struct evhttp_uri *uri)
4915 return uri->userinfo;
4918 evhttp_uri_get_host(const struct evhttp_uri *uri)
4923 evhttp_uri_get_port(const struct evhttp_uri *uri)
4928 evhttp_uri_get_path(const struct evhttp_uri *uri)
4933 evhttp_uri_get_query(const struct evhttp_uri *uri)
4938 evhttp_uri_get_fragment(const struct evhttp_uri *uri)
4940 return uri->fragment;
4943 #define URI_SET_STR_(f) do { \
4947 if ((uri->f = mm_strdup(f)) == NULL) { \
4948 event_warn("%s: strdup()", __func__); \
4957 evhttp_uri_set_scheme(struct evhttp_uri *uri, const char *scheme)
4959 if (scheme && !scheme_ok(scheme, scheme+strlen(scheme)))
4962 URI_SET_STR_(scheme);
4966 evhttp_uri_set_userinfo(struct evhttp_uri *uri, const char *userinfo)
4968 if (userinfo && !userinfo_ok(userinfo, userinfo+strlen(userinfo)))
4970 URI_SET_STR_(userinfo);
4974 evhttp_uri_set_host(struct evhttp_uri *uri, const char *host)
4977 if (host[0] == '[') {
4978 if (! bracket_addr_ok(host, host+strlen(host)))
4981 if (! regname_ok(host, host+strlen(host)))
4990 evhttp_uri_set_port(struct evhttp_uri *uri, int port)
4997 #define end_of_cpath(cp,p,f) \
4998 ((const char*)(end_of_path(((char*)(cp)), (p), (f))))
5001 evhttp_uri_set_path(struct evhttp_uri *uri, const char *path)
5003 if (path && end_of_cpath(path, PART_PATH, uri->flags) != path+strlen(path))
5010 evhttp_uri_set_query(struct evhttp_uri *uri, const char *query)
5012 if (query && end_of_cpath(query, PART_QUERY, uri->flags) != query+strlen(query))
5014 URI_SET_STR_(query);
5018 evhttp_uri_set_fragment(struct evhttp_uri *uri, const char *fragment)
5020 if (fragment && end_of_cpath(fragment, PART_FRAGMENT, uri->flags) != fragment+strlen(fragment))
5022 URI_SET_STR_(fragment);