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 * EV_READ, since we *do* want to learn about any close events.) */
373 bufferevent_setcb(evcon->bufev,
379 bufferevent_enable(evcon->bufev, EV_READ|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 bufferevent_setcb(evcon->bufev, NULL, NULL, NULL, NULL);
1314 /* XXXX This is not actually an optimal fix. Instead we ought to have
1315 an API for "stop connecting", or use bufferevent_setfd to turn off
1316 connecting. But for Libevent 2.0, this seems like a minimal change
1317 least likely to disrupt the rest of the bufferevent and http code.
1319 Why is this here? If the fd is set in the bufferevent, and the
1320 bufferevent is connecting, then you can't actually stop the
1321 bufferevent from trying to connect with bufferevent_disable(). The
1322 connect will never trigger, since we close the fd, but the timeout
1323 might. That caused an assertion failure in evhttp_connection_fail_.
1325 bufferevent_disable_hard_(evcon->bufev, EV_READ|EV_WRITE);
1327 if (evcon->fd == -1)
1328 evcon->fd = bufferevent_getfd(evcon->bufev);
1330 if (evcon->fd != -1) {
1331 /* inform interested parties about connection close */
1332 if (evhttp_connected(evcon) && evcon->closecb != NULL)
1333 (*evcon->closecb)(evcon, evcon->closecb_arg);
1335 shutdown(evcon->fd, EVUTIL_SHUT_WR);
1336 evutil_closesocket(evcon->fd);
1339 bufferevent_setfd(evcon->bufev, -1);
1341 /* we need to clean up any buffered data */
1342 tmp = bufferevent_get_output(evcon->bufev);
1343 err = evbuffer_drain(tmp, -1);
1344 EVUTIL_ASSERT(!err && "drain output");
1345 tmp = bufferevent_get_input(evcon->bufev);
1346 err = evbuffer_drain(tmp, -1);
1347 EVUTIL_ASSERT(!err && "drain input");
1349 evcon->flags &= ~EVHTTP_CON_READING_ERROR;
1351 evcon->state = EVCON_DISCONNECTED;
1355 evhttp_connection_start_detectclose(struct evhttp_connection *evcon)
1357 evcon->flags |= EVHTTP_CON_CLOSEDETECT;
1359 bufferevent_enable(evcon->bufev, EV_READ);
1363 evhttp_connection_stop_detectclose(struct evhttp_connection *evcon)
1365 evcon->flags &= ~EVHTTP_CON_CLOSEDETECT;
1367 bufferevent_disable(evcon->bufev, EV_READ);
1371 evhttp_connection_retry(evutil_socket_t fd, short what, void *arg)
1373 struct evhttp_connection *evcon = arg;
1375 evcon->state = EVCON_DISCONNECTED;
1376 evhttp_connection_connect_(evcon);
1380 evhttp_connection_cb_cleanup(struct evhttp_connection *evcon)
1382 struct evcon_requestq requests;
1384 evhttp_connection_reset_(evcon);
1385 if (evcon->retry_max < 0 || evcon->retry_cnt < evcon->retry_max) {
1386 struct timeval tv_retry = evcon->initial_retry_timeout;
1388 evtimer_assign(&evcon->retry_ev, evcon->base, evhttp_connection_retry, evcon);
1389 /* XXXX handle failure from evhttp_add_event */
1390 for (i=0; i < evcon->retry_cnt; ++i) {
1391 tv_retry.tv_usec *= 2;
1392 if (tv_retry.tv_usec > 1000000) {
1393 tv_retry.tv_usec -= 1000000;
1394 tv_retry.tv_sec += 1;
1396 tv_retry.tv_sec *= 2;
1397 if (tv_retry.tv_sec > 3600) {
1398 tv_retry.tv_sec = 3600;
1399 tv_retry.tv_usec = 0;
1402 event_add(&evcon->retry_ev, &tv_retry);
1408 * User callback can do evhttp_make_request() on the same
1409 * evcon so new request will be added to evcon->requests. To
1410 * avoid freeing it prematurely we iterate over the copy of
1413 TAILQ_INIT(&requests);
1414 while (TAILQ_FIRST(&evcon->requests) != NULL) {
1415 struct evhttp_request *request = TAILQ_FIRST(&evcon->requests);
1416 TAILQ_REMOVE(&evcon->requests, request, next);
1417 TAILQ_INSERT_TAIL(&requests, request, next);
1420 /* for now, we just signal all requests by executing their callbacks */
1421 while (TAILQ_FIRST(&requests) != NULL) {
1422 struct evhttp_request *request = TAILQ_FIRST(&requests);
1423 TAILQ_REMOVE(&requests, request, next);
1424 request->evcon = NULL;
1426 /* we might want to set an error here */
1427 request->cb(request, request->cb_arg);
1428 evhttp_request_free_auto(request);
1433 evhttp_connection_read_on_write_error(struct evhttp_connection *evcon,
1434 struct evhttp_request *req)
1436 struct evbuffer *buf;
1438 /** Second time, we can't read anything */
1439 if (evcon->flags & EVHTTP_CON_READING_ERROR) {
1440 evcon->flags &= ~EVHTTP_CON_READING_ERROR;
1441 evhttp_connection_fail_(evcon, EVREQ_HTTP_EOF);
1445 req->kind = EVHTTP_RESPONSE;
1447 buf = bufferevent_get_output(evcon->bufev);
1448 evbuffer_unfreeze(buf, 1);
1449 evbuffer_drain(buf, evbuffer_get_length(buf));
1450 evbuffer_freeze(buf, 1);
1452 evhttp_start_read_(evcon);
1453 evcon->flags |= EVHTTP_CON_READING_ERROR;
1457 evhttp_error_cb(struct bufferevent *bufev, short what, void *arg)
1459 struct evhttp_connection *evcon = arg;
1460 struct evhttp_request *req = TAILQ_FIRST(&evcon->requests);
1462 if (evcon->fd == -1)
1463 evcon->fd = bufferevent_getfd(bufev);
1465 switch (evcon->state) {
1466 case EVCON_CONNECTING:
1467 if (what & BEV_EVENT_TIMEOUT) {
1468 event_debug(("%s: connection timeout for \"%s:%d\" on "
1470 __func__, evcon->address, evcon->port,
1471 EV_SOCK_ARG(evcon->fd)));
1472 evhttp_connection_cb_cleanup(evcon);
1477 case EVCON_READING_BODY:
1478 if (!req->chunked && req->ntoread < 0
1479 && what == (BEV_EVENT_READING|BEV_EVENT_EOF)) {
1480 /* EOF on read can be benign */
1481 evhttp_connection_done(evcon);
1486 case EVCON_DISCONNECTED:
1488 case EVCON_READING_FIRSTLINE:
1489 case EVCON_READING_HEADERS:
1490 case EVCON_READING_TRAILER:
1496 /* when we are in close detect mode, a read error means that
1497 * the other side closed their connection.
1499 if (evcon->flags & EVHTTP_CON_CLOSEDETECT) {
1500 evcon->flags &= ~EVHTTP_CON_CLOSEDETECT;
1501 EVUTIL_ASSERT(evcon->http_server == NULL);
1502 /* For connections from the client, we just
1503 * reset the connection so that it becomes
1506 EVUTIL_ASSERT(evcon->state == EVCON_IDLE);
1507 evhttp_connection_reset_(evcon);
1510 * If we have no more requests that need completion
1511 * and we want to auto-free the connection when all
1512 * requests have been completed.
1514 if (TAILQ_FIRST(&evcon->requests) == NULL
1515 && (evcon->flags & EVHTTP_CON_OUTGOING)
1516 && (evcon->flags & EVHTTP_CON_AUTOFREE)) {
1517 evhttp_connection_free(evcon);
1522 if (what & BEV_EVENT_TIMEOUT) {
1523 evhttp_connection_fail_(evcon, EVREQ_HTTP_TIMEOUT);
1524 } else if (what & (BEV_EVENT_EOF|BEV_EVENT_ERROR)) {
1525 if (what & BEV_EVENT_WRITING &&
1526 evcon->flags & EVHTTP_CON_READ_ON_WRITE_ERROR) {
1527 evhttp_connection_read_on_write_error(evcon, req);
1531 evhttp_connection_fail_(evcon, EVREQ_HTTP_EOF);
1532 } else if (what == BEV_EVENT_CONNECTED) {
1534 evhttp_connection_fail_(evcon, EVREQ_HTTP_BUFFER_ERROR);
1539 * Event callback for asynchronous connection attempt.
1542 evhttp_connection_cb(struct bufferevent *bufev, short what, void *arg)
1544 struct evhttp_connection *evcon = arg;
1546 ev_socklen_t errsz = sizeof(error);
1548 if (evcon->fd == -1)
1549 evcon->fd = bufferevent_getfd(bufev);
1551 if (!(what & BEV_EVENT_CONNECTED)) {
1552 /* some operating systems return ECONNREFUSED immediately
1553 * when connecting to a local address. the cleanup is going
1554 * to reschedule this function call.
1557 if (errno == ECONNREFUSED)
1560 evhttp_error_cb(bufev, what, arg);
1564 if (evcon->fd == -1) {
1565 event_debug(("%s: bufferevent_getfd returned -1",
1570 /* Check if the connection completed */
1571 if (getsockopt(evcon->fd, SOL_SOCKET, SO_ERROR, (void*)&error,
1573 event_debug(("%s: getsockopt for \"%s:%d\" on "EV_SOCK_FMT,
1574 __func__, evcon->address, evcon->port,
1575 EV_SOCK_ARG(evcon->fd)));
1580 event_debug(("%s: connect failed for \"%s:%d\" on "
1582 __func__, evcon->address, evcon->port,
1583 EV_SOCK_ARG(evcon->fd),
1584 evutil_socket_error_to_string(error)));
1588 /* We are connected to the server now */
1589 event_debug(("%s: connected to \"%s:%d\" on "EV_SOCK_FMT"\n",
1590 __func__, evcon->address, evcon->port,
1591 EV_SOCK_ARG(evcon->fd)));
1593 /* Reset the retry count as we were successful in connecting */
1594 evcon->retry_cnt = 0;
1595 evcon->state = EVCON_IDLE;
1597 /* reset the bufferevent cbs */
1598 bufferevent_setcb(evcon->bufev,
1604 if (!evutil_timerisset(&evcon->timeout)) {
1605 const struct timeval read_tv = { HTTP_READ_TIMEOUT, 0 };
1606 const struct timeval write_tv = { HTTP_WRITE_TIMEOUT, 0 };
1607 bufferevent_set_timeouts(evcon->bufev, &read_tv, &write_tv);
1609 bufferevent_set_timeouts(evcon->bufev, &evcon->timeout, &evcon->timeout);
1612 /* try to start requests that have queued up on this connection */
1613 evhttp_request_dispatch(evcon);
1617 evhttp_connection_cb_cleanup(evcon);
1621 * Check if we got a valid response code.
1625 evhttp_valid_response_code(int code)
1634 evhttp_parse_http_version(const char *version, struct evhttp_request *req)
1638 int n = sscanf(version, "HTTP/%d.%d%c", &major, &minor, &ch);
1639 if (n != 2 || major > 1) {
1640 event_debug(("%s: bad version %s on message %p from %s",
1641 __func__, version, req, req->remote_host));
1649 /* Parses the status line of a web server */
1652 evhttp_parse_response_line(struct evhttp_request *req, char *line)
1656 const char *readable = "";
1658 protocol = strsep(&line, " ");
1661 number = strsep(&line, " ");
1665 if (evhttp_parse_http_version(protocol, req) < 0)
1668 req->response_code = atoi(number);
1669 if (!evhttp_valid_response_code(req->response_code)) {
1670 event_debug(("%s: bad response code \"%s\"",
1675 if (req->response_code_line != NULL)
1676 mm_free(req->response_code_line);
1677 if ((req->response_code_line = mm_strdup(readable)) == NULL) {
1678 event_warn("%s: strdup", __func__);
1685 /* Parse the first line of a HTTP request */
1688 evhttp_parse_request_line(struct evhttp_request *req, char *line)
1693 const char *hostname;
1696 enum evhttp_cmd_type type;
1698 /* Parse the request line */
1699 method = strsep(&line, " ");
1702 uri = strsep(&line, " ");
1705 version = strsep(&line, " ");
1709 method_len = (uri - method) - 1;
1710 type = EVHTTP_REQ_UNKNOWN_;
1713 switch (method_len) {
1715 /* The length of the method string is 3, meaning it can only be one of two methods: GET or PUT */
1717 /* Since both GET and PUT share the same character 'T' at the end,
1718 * if the string doesn't have 'T', we can immediately determine this
1719 * is an invalid HTTP method */
1721 if (method[2] != 'T') {
1727 /* This first byte is 'G', so make sure the next byte is
1728 * 'E', if it isn't then this isn't a valid method */
1730 if (method[1] == 'E') {
1731 type = EVHTTP_REQ_GET;
1736 /* First byte is P, check second byte for 'U', if not,
1737 * we know it's an invalid method */
1738 if (method[1] == 'U') {
1739 type = EVHTTP_REQ_PUT;
1747 /* The method length is 4 bytes, leaving only the methods "POST" and "HEAD" */
1750 if (method[3] == 'T' && method[2] == 'S' && method[1] == 'O') {
1751 type = EVHTTP_REQ_POST;
1755 if (method[3] == 'D' && method[2] == 'A' && method[1] == 'E') {
1756 type = EVHTTP_REQ_HEAD;
1764 /* Method length is 5 bytes, which can only encompass PATCH and TRACE */
1767 if (method[4] == 'H' && method[3] == 'C' && method[2] == 'T' && method[1] == 'A') {
1768 type = EVHTTP_REQ_PATCH;
1772 if (method[4] == 'E' && method[3] == 'C' && method[2] == 'A' && method[1] == 'R') {
1773 type = EVHTTP_REQ_TRACE;
1782 /* Method length is 6, only valid method 6 bytes in length is DELEte */
1784 /* If the first byte isn't 'D' then it's invalid */
1785 if (*method != 'D') {
1789 if (method[5] == 'E' && method[4] == 'T' && method[3] == 'E' && method[2] == 'L' && method[1] == 'E') {
1790 type = EVHTTP_REQ_DELETE;
1795 /* Method length is 7, only valid methods are "OPTIONS" and "CONNECT" */
1798 if (method[6] == 'S' && method[5] == 'N' && method[4] == 'O' &&
1799 method[3] == 'I' && method[2] == 'T' && method[1] == 'P') {
1800 type = EVHTTP_REQ_OPTIONS;
1805 if (method[6] == 'T' && method[5] == 'C' && method[4] == 'E' &&
1806 method[3] == 'N' && method[2] == 'N' && method[1] == 'O') {
1807 type = EVHTTP_REQ_CONNECT;
1817 if ((int)type == EVHTTP_REQ_UNKNOWN_) {
1818 event_debug(("%s: bad method %s on request %p from %s",
1819 __func__, method, req, req->remote_host));
1820 /* No error yet; we'll give a better error later when
1821 * we see that req->type is unsupported. */
1826 if (evhttp_parse_http_version(version, req) < 0)
1829 if ((req->uri = mm_strdup(uri)) == NULL) {
1830 event_debug(("%s: mm_strdup", __func__));
1834 if ((req->uri_elems = evhttp_uri_parse_with_flags(req->uri,
1835 EVHTTP_URI_NONCONFORMANT)) == NULL) {
1839 /* If we have an absolute-URI, check to see if it is an http request
1840 for a known vhost or server alias. If we don't know about this
1841 host, we consider it a proxy request. */
1842 scheme = evhttp_uri_get_scheme(req->uri_elems);
1843 hostname = evhttp_uri_get_host(req->uri_elems);
1844 if (scheme && (!evutil_ascii_strcasecmp(scheme, "http") ||
1845 !evutil_ascii_strcasecmp(scheme, "https")) &&
1847 !evhttp_find_vhost(req->evcon->http_server, NULL, hostname))
1848 req->flags |= EVHTTP_PROXY_REQUEST;
1854 evhttp_find_header(const struct evkeyvalq *headers, const char *key)
1856 struct evkeyval *header;
1858 TAILQ_FOREACH(header, headers, next) {
1859 if (evutil_ascii_strcasecmp(header->key, key) == 0)
1860 return (header->value);
1867 evhttp_clear_headers(struct evkeyvalq *headers)
1869 struct evkeyval *header;
1871 for (header = TAILQ_FIRST(headers);
1873 header = TAILQ_FIRST(headers)) {
1874 TAILQ_REMOVE(headers, header, next);
1875 mm_free(header->key);
1876 mm_free(header->value);
1882 * Returns 0, if the header was successfully removed.
1883 * Returns -1, if the header could not be found.
1887 evhttp_remove_header(struct evkeyvalq *headers, const char *key)
1889 struct evkeyval *header;
1891 TAILQ_FOREACH(header, headers, next) {
1892 if (evutil_ascii_strcasecmp(header->key, key) == 0)
1899 /* Free and remove the header that we found */
1900 TAILQ_REMOVE(headers, header, next);
1901 mm_free(header->key);
1902 mm_free(header->value);
1909 evhttp_header_is_valid_value(const char *value)
1911 const char *p = value;
1913 while ((p = strpbrk(p, "\r\n")) != NULL) {
1914 /* we really expect only one new line */
1915 p += strspn(p, "\r\n");
1916 /* we expect a space or tab for continuation */
1917 if (*p != ' ' && *p != '\t')
1924 evhttp_add_header(struct evkeyvalq *headers,
1925 const char *key, const char *value)
1927 event_debug(("%s: key: %s val: %s\n", __func__, key, value));
1929 if (strchr(key, '\r') != NULL || strchr(key, '\n') != NULL) {
1930 /* drop illegal headers */
1931 event_debug(("%s: dropping illegal header key\n", __func__));
1935 if (!evhttp_header_is_valid_value(value)) {
1936 event_debug(("%s: dropping illegal header value\n", __func__));
1940 return (evhttp_add_header_internal(headers, key, value));
1944 evhttp_add_header_internal(struct evkeyvalq *headers,
1945 const char *key, const char *value)
1947 struct evkeyval *header = mm_calloc(1, sizeof(struct evkeyval));
1948 if (header == NULL) {
1949 event_warn("%s: calloc", __func__);
1952 if ((header->key = mm_strdup(key)) == NULL) {
1954 event_warn("%s: strdup", __func__);
1957 if ((header->value = mm_strdup(value)) == NULL) {
1958 mm_free(header->key);
1960 event_warn("%s: strdup", __func__);
1964 TAILQ_INSERT_TAIL(headers, header, next);
1970 * Parses header lines from a request or a response into the specified
1971 * request object given an event buffer.
1974 * DATA_CORRUPTED on error
1975 * MORE_DATA_EXPECTED when we need to read more headers
1976 * ALL_DATA_READ when all headers have been read.
1979 enum message_read_status
1980 evhttp_parse_firstline_(struct evhttp_request *req, struct evbuffer *buffer)
1983 enum message_read_status status = ALL_DATA_READ;
1987 line = evbuffer_readln(buffer, &line_length, EVBUFFER_EOL_CRLF);
1989 if (req->evcon != NULL &&
1990 evbuffer_get_length(buffer) > req->evcon->max_headers_size)
1991 return (DATA_TOO_LONG);
1993 return (MORE_DATA_EXPECTED);
1996 if (req->evcon != NULL &&
1997 line_length > req->evcon->max_headers_size) {
1999 return (DATA_TOO_LONG);
2002 req->headers_size = line_length;
2004 switch (req->kind) {
2005 case EVHTTP_REQUEST:
2006 if (evhttp_parse_request_line(req, line) == -1)
2007 status = DATA_CORRUPTED;
2009 case EVHTTP_RESPONSE:
2010 if (evhttp_parse_response_line(req, line) == -1)
2011 status = DATA_CORRUPTED;
2014 status = DATA_CORRUPTED;
2022 evhttp_append_to_last_header(struct evkeyvalq *headers, char *line)
2024 struct evkeyval *header = TAILQ_LAST(headers, evkeyvalq);
2026 size_t old_len, line_len;
2031 old_len = strlen(header->value);
2033 /* Strip space from start and end of line. */
2034 while (*line == ' ' || *line == '\t')
2036 evutil_rtrim_lws_(line);
2038 line_len = strlen(line);
2040 newval = mm_realloc(header->value, old_len + line_len + 2);
2044 newval[old_len] = ' ';
2045 memcpy(newval + old_len + 1, line, line_len + 1);
2046 header->value = newval;
2051 enum message_read_status
2052 evhttp_parse_headers_(struct evhttp_request *req, struct evbuffer* buffer)
2054 enum message_read_status errcode = DATA_CORRUPTED;
2056 enum message_read_status status = MORE_DATA_EXPECTED;
2058 struct evkeyvalq* headers = req->input_headers;
2060 while ((line = evbuffer_readln(buffer, &line_length, EVBUFFER_EOL_CRLF))
2062 char *skey, *svalue;
2064 req->headers_size += line_length;
2066 if (req->evcon != NULL &&
2067 req->headers_size > req->evcon->max_headers_size) {
2068 errcode = DATA_TOO_LONG;
2072 if (*line == '\0') { /* Last header - Done */
2073 status = ALL_DATA_READ;
2078 /* Check if this is a continuation line */
2079 if (*line == ' ' || *line == '\t') {
2080 if (evhttp_append_to_last_header(headers, line) == -1)
2086 /* Processing of header lines */
2088 skey = strsep(&svalue, ":");
2092 svalue += strspn(svalue, " ");
2093 evutil_rtrim_lws_(svalue);
2095 if (evhttp_add_header(headers, skey, svalue) == -1)
2101 if (status == MORE_DATA_EXPECTED) {
2102 if (req->evcon != NULL &&
2103 req->headers_size + evbuffer_get_length(buffer) > req->evcon->max_headers_size)
2104 return (DATA_TOO_LONG);
2115 evhttp_get_body_length(struct evhttp_request *req)
2117 struct evkeyvalq *headers = req->input_headers;
2118 const char *content_length;
2119 const char *connection;
2121 content_length = evhttp_find_header(headers, "Content-Length");
2122 connection = evhttp_find_header(headers, "Connection");
2124 if (content_length == NULL && connection == NULL)
2126 else if (content_length == NULL &&
2127 evutil_ascii_strcasecmp(connection, "Close") != 0) {
2128 /* Bad combination, we don't know when it will end */
2129 event_warnx("%s: we got no content length, but the "
2130 "server wants to keep the connection open: %s.",
2131 __func__, connection);
2133 } else if (content_length == NULL) {
2137 ev_int64_t ntoread = evutil_strtoll(content_length, &endp, 10);
2138 if (*content_length == '\0' || *endp != '\0' || ntoread < 0) {
2139 event_debug(("%s: illegal content length: %s",
2140 __func__, content_length));
2143 req->ntoread = ntoread;
2146 event_debug(("%s: bytes to read: "EV_I64_FMT" (in buffer "EV_SIZE_FMT")\n",
2147 __func__, EV_I64_ARG(req->ntoread),
2148 EV_SIZE_ARG(evbuffer_get_length(bufferevent_get_input(req->evcon->bufev)))));
2154 evhttp_method_may_have_body(enum evhttp_cmd_type type)
2157 case EVHTTP_REQ_POST:
2158 case EVHTTP_REQ_PUT:
2159 case EVHTTP_REQ_PATCH:
2161 case EVHTTP_REQ_TRACE:
2163 /* XXX May any of the below methods have a body? */
2164 case EVHTTP_REQ_GET:
2165 case EVHTTP_REQ_HEAD:
2166 case EVHTTP_REQ_DELETE:
2167 case EVHTTP_REQ_OPTIONS:
2168 case EVHTTP_REQ_CONNECT:
2176 evhttp_get_body(struct evhttp_connection *evcon, struct evhttp_request *req)
2178 const char *xfer_enc;
2180 /* If this is a request without a body, then we are done */
2181 if (req->kind == EVHTTP_REQUEST &&
2182 !evhttp_method_may_have_body(req->type)) {
2183 evhttp_connection_done(evcon);
2186 evcon->state = EVCON_READING_BODY;
2187 xfer_enc = evhttp_find_header(req->input_headers, "Transfer-Encoding");
2188 if (xfer_enc != NULL && evutil_ascii_strcasecmp(xfer_enc, "chunked") == 0) {
2192 if (evhttp_get_body_length(req) == -1) {
2193 evhttp_connection_fail_(evcon, EVREQ_HTTP_INVALID_HEADER);
2196 if (req->kind == EVHTTP_REQUEST && req->ntoread < 1) {
2197 /* An incoming request with no content-length and no
2198 * transfer-encoding has no body. */
2199 evhttp_connection_done(evcon);
2204 /* Should we send a 100 Continue status line? */
2205 switch (evhttp_have_expect(req, 1)) {
2207 /* XXX It would be nice to do some sanity
2208 checking here. Does the resource exist?
2209 Should the resource accept post requests? If
2210 no, we should respond with an error. For
2211 now, just optimistically tell the client to
2212 send their message body. */
2213 if (req->ntoread > 0) {
2214 /* ntoread is ev_int64_t, max_body_size is ev_uint64_t */
2215 if ((req->evcon->max_body_size <= EV_INT64_MAX) &&
2216 (ev_uint64_t)req->ntoread > req->evcon->max_body_size) {
2217 evhttp_lingering_fail(evcon, req);
2221 if (!evbuffer_get_length(bufferevent_get_input(evcon->bufev)))
2222 evhttp_send_continue(evcon, req);
2225 evhttp_send_error(req, HTTP_EXPECTATIONFAILED, NULL);
2230 evhttp_read_body(evcon, req);
2231 /* note the request may have been freed in evhttp_read_body */
2235 evhttp_read_firstline(struct evhttp_connection *evcon,
2236 struct evhttp_request *req)
2238 enum message_read_status res;
2240 res = evhttp_parse_firstline_(req, bufferevent_get_input(evcon->bufev));
2241 if (res == DATA_CORRUPTED || res == DATA_TOO_LONG) {
2242 /* Error while reading, terminate */
2243 event_debug(("%s: bad header lines on "EV_SOCK_FMT"\n",
2244 __func__, EV_SOCK_ARG(evcon->fd)));
2245 evhttp_connection_fail_(evcon, EVREQ_HTTP_INVALID_HEADER);
2247 } else if (res == MORE_DATA_EXPECTED) {
2248 /* Need more header lines */
2252 evcon->state = EVCON_READING_HEADERS;
2253 evhttp_read_header(evcon, req);
2257 evhttp_read_header(struct evhttp_connection *evcon,
2258 struct evhttp_request *req)
2260 enum message_read_status res;
2261 evutil_socket_t fd = evcon->fd;
2263 res = evhttp_parse_headers_(req, bufferevent_get_input(evcon->bufev));
2264 if (res == DATA_CORRUPTED || res == DATA_TOO_LONG) {
2265 /* Error while reading, terminate */
2266 event_debug(("%s: bad header lines on "EV_SOCK_FMT"\n",
2267 __func__, EV_SOCK_ARG(fd)));
2268 evhttp_connection_fail_(evcon, EVREQ_HTTP_INVALID_HEADER);
2270 } else if (res == MORE_DATA_EXPECTED) {
2271 /* Need more header lines */
2275 /* Callback can shut down connection with negative return value */
2276 if (req->header_cb != NULL) {
2277 if ((*req->header_cb)(req, req->cb_arg) < 0) {
2278 evhttp_connection_fail_(evcon, EVREQ_HTTP_EOF);
2283 /* Done reading headers, do the real work */
2284 switch (req->kind) {
2285 case EVHTTP_REQUEST:
2286 event_debug(("%s: checking for post data on "EV_SOCK_FMT"\n",
2287 __func__, EV_SOCK_ARG(fd)));
2288 evhttp_get_body(evcon, req);
2289 /* note the request may have been freed in evhttp_get_body */
2292 case EVHTTP_RESPONSE:
2293 /* Start over if we got a 100 Continue response. */
2294 if (req->response_code == 100) {
2295 struct evbuffer *output = bufferevent_get_output(evcon->bufev);
2296 evbuffer_add_buffer(output, req->output_buffer);
2297 evhttp_start_write_(evcon);
2300 if (!evhttp_response_needs_body(req)) {
2301 event_debug(("%s: skipping body for code %d\n",
2302 __func__, req->response_code));
2303 evhttp_connection_done(evcon);
2305 event_debug(("%s: start of read body for %s on "
2307 __func__, req->remote_host, EV_SOCK_ARG(fd)));
2308 evhttp_get_body(evcon, req);
2309 /* note the request may have been freed in
2310 * evhttp_get_body */
2315 event_warnx("%s: bad header on "EV_SOCK_FMT, __func__,
2317 evhttp_connection_fail_(evcon, EVREQ_HTTP_INVALID_HEADER);
2320 /* request may have been freed above */
2324 * Creates a TCP connection to the specified port and executes a callback
2325 * when finished. Failure or success is indicate by the passed connection
2328 * Although this interface accepts a hostname, it is intended to take
2329 * only numeric hostnames so that non-blocking DNS resolution can
2333 struct evhttp_connection *
2334 evhttp_connection_new(const char *address, ev_uint16_t port)
2336 return (evhttp_connection_base_new(NULL, NULL, address, port));
2339 struct evhttp_connection *
2340 evhttp_connection_base_bufferevent_new(struct event_base *base, struct evdns_base *dnsbase, struct bufferevent* bev,
2341 const char *address, ev_uint16_t port)
2343 struct evhttp_connection *evcon = NULL;
2345 event_debug(("Attempting connection to %s:%d\n", address, port));
2347 if ((evcon = mm_calloc(1, sizeof(struct evhttp_connection))) == NULL) {
2348 event_warn("%s: calloc failed", __func__);
2355 evcon->max_headers_size = EV_SIZE_MAX;
2356 evcon->max_body_size = EV_SIZE_MAX;
2358 evutil_timerclear(&evcon->timeout);
2359 evcon->retry_cnt = evcon->retry_max = 0;
2361 if ((evcon->address = mm_strdup(address)) == NULL) {
2362 event_warn("%s: strdup failed", __func__);
2367 if (!(bev = bufferevent_socket_new(base, -1, 0))) {
2368 event_warn("%s: bufferevent_socket_new failed", __func__);
2373 bufferevent_setcb(bev, evhttp_read_cb, evhttp_write_cb, evhttp_error_cb, evcon);
2376 evcon->state = EVCON_DISCONNECTED;
2377 TAILQ_INIT(&evcon->requests);
2379 evcon->initial_retry_timeout.tv_sec = 2;
2380 evcon->initial_retry_timeout.tv_usec = 0;
2384 if (bufferevent_get_base(bev) != base)
2385 bufferevent_base_set(base, evcon->bufev);
2388 event_deferred_cb_init_(
2389 &evcon->read_more_deferred_cb,
2390 bufferevent_get_priority(bev),
2391 evhttp_deferred_read_cb, evcon);
2393 evcon->dns_base = dnsbase;
2394 evcon->ai_family = AF_UNSPEC;
2400 evhttp_connection_free(evcon);
2404 struct bufferevent* evhttp_connection_get_bufferevent(struct evhttp_connection *evcon)
2406 return evcon->bufev;
2410 evhttp_connection_get_server(struct evhttp_connection *evcon)
2412 return evcon->http_server;
2415 struct evhttp_connection *
2416 evhttp_connection_base_new(struct event_base *base, struct evdns_base *dnsbase,
2417 const char *address, ev_uint16_t port)
2419 return evhttp_connection_base_bufferevent_new(base, dnsbase, NULL, address, port);
2422 void evhttp_connection_set_family(struct evhttp_connection *evcon,
2425 evcon->ai_family = family;
2428 int evhttp_connection_set_flags(struct evhttp_connection *evcon,
2431 int avail_flags = 0;
2432 avail_flags |= EVHTTP_CON_REUSE_CONNECTED_ADDR;
2433 avail_flags |= EVHTTP_CON_READ_ON_WRITE_ERROR;
2435 if (flags & ~avail_flags || flags > EVHTTP_CON_PUBLIC_FLAGS_END)
2437 evcon->flags &= ~avail_flags;
2439 evcon->flags |= flags;
2445 evhttp_connection_set_base(struct evhttp_connection *evcon,
2446 struct event_base *base)
2448 EVUTIL_ASSERT(evcon->base == NULL);
2449 EVUTIL_ASSERT(evcon->state == EVCON_DISCONNECTED);
2451 bufferevent_base_set(base, evcon->bufev);
2455 evhttp_connection_set_timeout(struct evhttp_connection *evcon,
2456 int timeout_in_secs)
2458 if (timeout_in_secs == -1)
2459 evhttp_connection_set_timeout_tv(evcon, NULL);
2462 tv.tv_sec = timeout_in_secs;
2464 evhttp_connection_set_timeout_tv(evcon, &tv);
2469 evhttp_connection_set_timeout_tv(struct evhttp_connection *evcon,
2470 const struct timeval* tv)
2473 evcon->timeout = *tv;
2474 bufferevent_set_timeouts(evcon->bufev, &evcon->timeout, &evcon->timeout);
2476 const struct timeval read_tv = { HTTP_READ_TIMEOUT, 0 };
2477 const struct timeval write_tv = { HTTP_WRITE_TIMEOUT, 0 };
2478 evutil_timerclear(&evcon->timeout);
2479 bufferevent_set_timeouts(evcon->bufev, &read_tv, &write_tv);
2484 evhttp_connection_set_initial_retry_tv(struct evhttp_connection *evcon,
2485 const struct timeval *tv)
2488 evcon->initial_retry_timeout = *tv;
2490 evutil_timerclear(&evcon->initial_retry_timeout);
2491 evcon->initial_retry_timeout.tv_sec = 2;
2496 evhttp_connection_set_retries(struct evhttp_connection *evcon,
2499 evcon->retry_max = retry_max;
2503 evhttp_connection_set_closecb(struct evhttp_connection *evcon,
2504 void (*cb)(struct evhttp_connection *, void *), void *cbarg)
2506 evcon->closecb = cb;
2507 evcon->closecb_arg = cbarg;
2511 evhttp_connection_get_peer(struct evhttp_connection *evcon,
2512 char **address, ev_uint16_t *port)
2514 *address = evcon->address;
2515 *port = evcon->port;
2518 const struct sockaddr*
2519 evhttp_connection_get_addr(struct evhttp_connection *evcon)
2521 return bufferevent_socket_get_conn_address_(evcon->bufev);
2525 evhttp_connection_connect_(struct evhttp_connection *evcon)
2527 int old_state = evcon->state;
2528 const char *address = evcon->address;
2529 const struct sockaddr *sa = evhttp_connection_get_addr(evcon);
2532 if (evcon->state == EVCON_CONNECTING)
2535 evhttp_connection_reset_(evcon);
2537 EVUTIL_ASSERT(!(evcon->flags & EVHTTP_CON_INCOMING));
2538 evcon->flags |= EVHTTP_CON_OUTGOING;
2540 if (evcon->bind_address || evcon->bind_port) {
2541 evcon->fd = bind_socket(
2542 evcon->bind_address, evcon->bind_port, 0 /*reuse*/);
2543 if (evcon->fd == -1) {
2544 event_debug(("%s: failed to bind to \"%s\"",
2545 __func__, evcon->bind_address));
2549 bufferevent_setfd(evcon->bufev, evcon->fd);
2551 bufferevent_setfd(evcon->bufev, -1);
2554 /* Set up a callback for successful connection setup */
2555 bufferevent_setcb(evcon->bufev,
2556 NULL /* evhttp_read_cb */,
2557 NULL /* evhttp_write_cb */,
2558 evhttp_connection_cb,
2560 if (!evutil_timerisset(&evcon->timeout)) {
2561 const struct timeval conn_tv = { HTTP_CONNECT_TIMEOUT, 0 };
2562 bufferevent_set_timeouts(evcon->bufev, &conn_tv, &conn_tv);
2564 bufferevent_set_timeouts(evcon->bufev, &evcon->timeout, &evcon->timeout);
2566 /* make sure that we get a write callback */
2567 bufferevent_enable(evcon->bufev, EV_WRITE);
2569 evcon->state = EVCON_CONNECTING;
2571 if (evcon->flags & EVHTTP_CON_REUSE_CONNECTED_ADDR &&
2573 (sa->sa_family == AF_INET || sa->sa_family == AF_INET6)) {
2574 int socklen = sizeof(struct sockaddr_in);
2575 if (sa->sa_family == AF_INET6) {
2576 socklen = sizeof(struct sockaddr_in6);
2578 ret = bufferevent_socket_connect(evcon->bufev, sa, socklen);
2580 ret = bufferevent_socket_connect_hostname(evcon->bufev,
2581 evcon->dns_base, evcon->ai_family, address, evcon->port);
2585 evcon->state = old_state;
2586 event_sock_warn(evcon->fd, "%s: connection to \"%s\" failed",
2587 __func__, evcon->address);
2588 /* some operating systems return ECONNREFUSED immediately
2589 * when connecting to a local address. the cleanup is going
2590 * to reschedule this function call.
2592 evhttp_connection_cb_cleanup(evcon);
2600 * Starts an HTTP request on the provided evhttp_connection object.
2601 * If the connection object is not connected to the web server already,
2602 * this will start the connection.
2606 evhttp_make_request(struct evhttp_connection *evcon,
2607 struct evhttp_request *req,
2608 enum evhttp_cmd_type type, const char *uri)
2610 /* We are making a request */
2611 req->kind = EVHTTP_REQUEST;
2613 if (req->uri != NULL)
2615 if ((req->uri = mm_strdup(uri)) == NULL) {
2616 event_warn("%s: strdup", __func__);
2617 evhttp_request_free_auto(req);
2621 /* Set the protocol version if it is not supplied */
2622 if (!req->major && !req->minor) {
2627 EVUTIL_ASSERT(req->evcon == NULL);
2629 EVUTIL_ASSERT(!(req->flags & EVHTTP_REQ_OWN_CONNECTION));
2631 TAILQ_INSERT_TAIL(&evcon->requests, req, next);
2633 /* If the connection object is not connected; make it so */
2634 if (!evhttp_connected(evcon)) {
2635 int res = evhttp_connection_connect_(evcon);
2636 /* evhttp_connection_fail_(), which is called through
2637 * evhttp_connection_connect_(), assumes that req lies in
2638 * evcon->requests. Thus, enqueue the request in advance and
2639 * remove it in the error case. */
2641 TAILQ_REMOVE(&evcon->requests, req, next);
2647 * If it's connected already and we are the first in the queue,
2648 * then we can dispatch this request immediately. Otherwise, it
2649 * will be dispatched once the pending requests are completed.
2651 if (TAILQ_FIRST(&evcon->requests) == req)
2652 evhttp_request_dispatch(evcon);
2658 evhttp_cancel_request(struct evhttp_request *req)
2660 struct evhttp_connection *evcon = req->evcon;
2661 if (evcon != NULL) {
2662 /* We need to remove it from the connection */
2663 if (TAILQ_FIRST(&evcon->requests) == req) {
2664 /* it's currently being worked on, so reset
2667 evhttp_connection_fail_(evcon,
2668 EVREQ_HTTP_REQUEST_CANCEL);
2670 /* connection fail freed the request */
2673 /* otherwise, we can just remove it from the
2676 TAILQ_REMOVE(&evcon->requests, req, next);
2680 evhttp_request_free_auto(req);
2684 * Reads data from file descriptor into request structure
2685 * Request structure needs to be set up correctly.
2689 evhttp_start_read_(struct evhttp_connection *evcon)
2691 bufferevent_disable(evcon->bufev, EV_WRITE);
2692 bufferevent_enable(evcon->bufev, EV_READ);
2694 evcon->state = EVCON_READING_FIRSTLINE;
2695 /* Reset the bufferevent callbacks */
2696 bufferevent_setcb(evcon->bufev,
2702 /* If there's still data pending, process it next time through the
2703 * loop. Don't do it now; that could get recusive. */
2704 if (evbuffer_get_length(bufferevent_get_input(evcon->bufev))) {
2705 event_deferred_cb_schedule_(get_deferred_queue(evcon),
2706 &evcon->read_more_deferred_cb);
2711 evhttp_start_write_(struct evhttp_connection *evcon)
2713 bufferevent_disable(evcon->bufev, EV_WRITE);
2714 bufferevent_enable(evcon->bufev, EV_READ);
2716 evcon->state = EVCON_WRITING;
2717 evhttp_write_buffer(evcon, evhttp_write_connectioncb, NULL);
2721 evhttp_send_done(struct evhttp_connection *evcon, void *arg)
2724 struct evhttp_request *req = TAILQ_FIRST(&evcon->requests);
2725 TAILQ_REMOVE(&evcon->requests, req, next);
2727 if (req->on_complete_cb != NULL) {
2728 req->on_complete_cb(req, req->on_complete_cb_arg);
2732 (REQ_VERSION_BEFORE(req, 1, 1) &&
2733 !evhttp_is_connection_keepalive(req->input_headers)) ||
2734 evhttp_is_request_connection_close(req);
2736 EVUTIL_ASSERT(req->flags & EVHTTP_REQ_OWN_CONNECTION);
2737 evhttp_request_free(req);
2740 evhttp_connection_free(evcon);
2744 /* we have a persistent connection; try to accept another request. */
2745 if (evhttp_associate_new_request_with_connection(evcon) == -1) {
2746 evhttp_connection_free(evcon);
2751 * Returns an error page.
2755 evhttp_send_error(struct evhttp_request *req, int error, const char *reason)
2758 #define ERR_FORMAT "<HTML><HEAD>\n" \
2759 "<TITLE>%d %s</TITLE>\n" \
2764 struct evbuffer *buf = evbuffer_new();
2766 /* if we cannot allocate memory; we just drop the connection */
2767 evhttp_connection_free(req->evcon);
2770 if (reason == NULL) {
2771 reason = evhttp_response_phrase_internal(error);
2774 evhttp_response_code_(req, error, reason);
2776 evbuffer_add_printf(buf, ERR_FORMAT, error, reason, reason);
2778 evhttp_send_page_(req, buf);
2784 /* Requires that headers and response code are already set up */
2787 evhttp_send(struct evhttp_request *req, struct evbuffer *databuf)
2789 struct evhttp_connection *evcon = req->evcon;
2791 if (evcon == NULL) {
2792 evhttp_request_free(req);
2796 EVUTIL_ASSERT(TAILQ_FIRST(&evcon->requests) == req);
2798 /* we expect no more calls form the user on this request */
2801 /* xxx: not sure if we really should expose the data buffer this way */
2802 if (databuf != NULL)
2803 evbuffer_add_buffer(req->output_buffer, databuf);
2805 /* Adds headers to the response */
2806 evhttp_make_header(evcon, req);
2808 evhttp_write_buffer(evcon, evhttp_send_done, NULL);
2812 evhttp_send_reply(struct evhttp_request *req, int code, const char *reason,
2813 struct evbuffer *databuf)
2815 evhttp_response_code_(req, code, reason);
2817 evhttp_send(req, databuf);
2821 evhttp_send_reply_start(struct evhttp_request *req, int code,
2824 evhttp_response_code_(req, code, reason);
2825 if (evhttp_find_header(req->output_headers, "Content-Length") == NULL &&
2826 REQ_VERSION_ATLEAST(req, 1, 1) &&
2827 evhttp_response_needs_body(req)) {
2829 * prefer HTTP/1.1 chunked encoding to closing the connection;
2830 * note RFC 2616 section 4.4 forbids it with Content-Length:
2831 * and it's not necessary then anyway.
2833 evhttp_add_header(req->output_headers, "Transfer-Encoding",
2839 evhttp_make_header(req->evcon, req);
2840 evhttp_write_buffer(req->evcon, NULL, NULL);
2844 evhttp_send_reply_chunk_with_cb(struct evhttp_request *req, struct evbuffer *databuf,
2845 void (*cb)(struct evhttp_connection *, void *), void *arg)
2847 struct evhttp_connection *evcon = req->evcon;
2848 struct evbuffer *output;
2853 output = bufferevent_get_output(evcon->bufev);
2855 if (evbuffer_get_length(databuf) == 0)
2857 if (!evhttp_response_needs_body(req))
2860 evbuffer_add_printf(output, "%x\r\n",
2861 (unsigned)evbuffer_get_length(databuf));
2863 evbuffer_add_buffer(output, databuf);
2865 evbuffer_add(output, "\r\n", 2);
2867 evhttp_write_buffer(evcon, cb, arg);
2871 evhttp_send_reply_chunk(struct evhttp_request *req, struct evbuffer *databuf)
2873 evhttp_send_reply_chunk_with_cb(req, databuf, NULL, NULL);
2876 evhttp_send_reply_end(struct evhttp_request *req)
2878 struct evhttp_connection *evcon = req->evcon;
2879 struct evbuffer *output;
2881 if (evcon == NULL) {
2882 evhttp_request_free(req);
2886 output = bufferevent_get_output(evcon->bufev);
2888 /* we expect no more calls form the user on this request */
2892 evbuffer_add(output, "0\r\n\r\n", 5);
2893 evhttp_write_buffer(req->evcon, evhttp_send_done, NULL);
2895 } else if (evbuffer_get_length(output) == 0) {
2896 /* let the connection know that we are done with the request */
2897 evhttp_send_done(evcon, NULL);
2899 /* make the callback execute after all data has been written */
2900 evcon->cb = evhttp_send_done;
2901 evcon->cb_arg = NULL;
2905 static const char *informational_phrases[] = {
2906 /* 100 */ "Continue",
2907 /* 101 */ "Switching Protocols"
2910 static const char *success_phrases[] = {
2912 /* 201 */ "Created",
2913 /* 202 */ "Accepted",
2914 /* 203 */ "Non-Authoritative Information",
2915 /* 204 */ "No Content",
2916 /* 205 */ "Reset Content",
2917 /* 206 */ "Partial Content"
2920 static const char *redirection_phrases[] = {
2921 /* 300 */ "Multiple Choices",
2922 /* 301 */ "Moved Permanently",
2924 /* 303 */ "See Other",
2925 /* 304 */ "Not Modified",
2926 /* 305 */ "Use Proxy",
2927 /* 307 */ "Temporary Redirect"
2930 static const char *client_error_phrases[] = {
2931 /* 400 */ "Bad Request",
2932 /* 401 */ "Unauthorized",
2933 /* 402 */ "Payment Required",
2934 /* 403 */ "Forbidden",
2935 /* 404 */ "Not Found",
2936 /* 405 */ "Method Not Allowed",
2937 /* 406 */ "Not Acceptable",
2938 /* 407 */ "Proxy Authentication Required",
2939 /* 408 */ "Request Time-out",
2940 /* 409 */ "Conflict",
2942 /* 411 */ "Length Required",
2943 /* 412 */ "Precondition Failed",
2944 /* 413 */ "Request Entity Too Large",
2945 /* 414 */ "Request-URI Too Large",
2946 /* 415 */ "Unsupported Media Type",
2947 /* 416 */ "Requested range not satisfiable",
2948 /* 417 */ "Expectation Failed"
2951 static const char *server_error_phrases[] = {
2952 /* 500 */ "Internal Server Error",
2953 /* 501 */ "Not Implemented",
2954 /* 502 */ "Bad Gateway",
2955 /* 503 */ "Service Unavailable",
2956 /* 504 */ "Gateway Time-out",
2957 /* 505 */ "HTTP Version not supported"
2960 struct response_class {
2962 size_t num_responses;
2963 const char **responses;
2967 #define MEMBERSOF(x) (sizeof(x)/sizeof(x[0]))
2970 static const struct response_class response_classes[] = {
2971 /* 1xx */ { "Informational", MEMBERSOF(informational_phrases), informational_phrases },
2972 /* 2xx */ { "Success", MEMBERSOF(success_phrases), success_phrases },
2973 /* 3xx */ { "Redirection", MEMBERSOF(redirection_phrases), redirection_phrases },
2974 /* 4xx */ { "Client Error", MEMBERSOF(client_error_phrases), client_error_phrases },
2975 /* 5xx */ { "Server Error", MEMBERSOF(server_error_phrases), server_error_phrases }
2979 evhttp_response_phrase_internal(int code)
2981 int klass = code / 100 - 1;
2982 int subcode = code % 100;
2984 /* Unknown class - can't do any better here */
2985 if (klass < 0 || klass >= (int) MEMBERSOF(response_classes))
2986 return "Unknown Status Class";
2988 /* Unknown sub-code, return class name at least */
2989 if (subcode >= (int) response_classes[klass].num_responses)
2990 return response_classes[klass].name;
2992 return response_classes[klass].responses[subcode];
2996 evhttp_response_code_(struct evhttp_request *req, int code, const char *reason)
2998 req->kind = EVHTTP_RESPONSE;
2999 req->response_code = code;
3000 if (req->response_code_line != NULL)
3001 mm_free(req->response_code_line);
3003 reason = evhttp_response_phrase_internal(code);
3004 req->response_code_line = mm_strdup(reason);
3005 if (req->response_code_line == NULL) {
3006 event_warn("%s: strdup", __func__);
3007 /* XXX what else can we do? */
3012 evhttp_send_page_(struct evhttp_request *req, struct evbuffer *databuf)
3014 if (!req->major || !req->minor) {
3019 if (req->kind != EVHTTP_RESPONSE)
3020 evhttp_response_code_(req, 200, "OK");
3022 evhttp_clear_headers(req->output_headers);
3023 evhttp_add_header(req->output_headers, "Content-Type", "text/html");
3024 evhttp_add_header(req->output_headers, "Connection", "close");
3026 evhttp_send(req, databuf);
3029 static const char uri_chars[256] = {
3031 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3032 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3033 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0,
3034 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,
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, 0, 1,
3038 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3039 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 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,
3043 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3044 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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,
3048 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3049 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3052 #define CHAR_IS_UNRESERVED(c) \
3053 (uri_chars[(unsigned char)(c)])
3056 * Helper functions to encode/decode a string for inclusion in a URI.
3057 * The returned string must be freed by the caller.
3060 evhttp_uriencode(const char *uri, ev_ssize_t len, int space_as_plus)
3062 struct evbuffer *buf = evbuffer_new();
3063 const char *p, *end;
3072 if (uri + len < uri) {
3078 size_t slen = strlen(uri);
3080 if (slen >= EV_SSIZE_MAX) {
3081 /* we don't want to mix signed and unsigned */
3085 if (uri + slen < uri) {
3092 for (p = uri; p < end; p++) {
3093 if (CHAR_IS_UNRESERVED(*p)) {
3094 evbuffer_add(buf, p, 1);
3095 } else if (*p == ' ' && space_as_plus) {
3096 evbuffer_add(buf, "+", 1);
3098 evbuffer_add_printf(buf, "%%%02X", (unsigned char)(*p));
3102 evbuffer_add(buf, "", 1); /* NUL-terminator. */
3103 result = mm_malloc(evbuffer_get_length(buf));
3106 evbuffer_remove(buf, result, evbuffer_get_length(buf));
3114 evhttp_encode_uri(const char *str)
3116 return evhttp_uriencode(str, -1, 0);
3120 * @param decode_plus_ctl: if 1, we decode plus into space. If 0, we don't.
3121 * If -1, when true we transform plus to space only after we've seen
3122 * a ?. -1 is deprecated.
3123 * @return the number of bytes written to 'ret'.
3126 evhttp_decode_uri_internal(
3127 const char *uri, size_t length, char *ret, int decode_plus_ctl)
3131 int decode_plus = (decode_plus_ctl == 1) ? 1: 0;
3134 for (i = j = 0; i < length; i++) {
3137 if (decode_plus_ctl < 0)
3139 } else if (c == '+' && decode_plus) {
3141 } else if ((i + 2) < length && c == '%' &&
3142 EVUTIL_ISXDIGIT_(uri[i+1]) && EVUTIL_ISXDIGIT_(uri[i+2])) {
3147 c = (char)strtol(tmp, NULL, 16);
3159 evhttp_decode_uri(const char *uri)
3163 if ((ret = mm_malloc(strlen(uri) + 1)) == NULL) {
3164 event_warn("%s: malloc(%lu)", __func__,
3165 (unsigned long)(strlen(uri) + 1));
3169 evhttp_decode_uri_internal(uri, strlen(uri),
3170 ret, -1 /*always_decode_plus*/);
3176 evhttp_uridecode(const char *uri, int decode_plus, size_t *size_out)
3181 if ((ret = mm_malloc(strlen(uri) + 1)) == NULL) {
3182 event_warn("%s: malloc(%lu)", __func__,
3183 (unsigned long)(strlen(uri) + 1));
3187 n = evhttp_decode_uri_internal(uri, strlen(uri),
3188 ret, !!decode_plus/*always_decode_plus*/);
3191 EVUTIL_ASSERT(n >= 0);
3192 *size_out = (size_t)n;
3199 * Helper function to parse out arguments in a query.
3200 * The arguments are separated by key and value.
3204 evhttp_parse_query_impl(const char *str, struct evkeyvalq *headers,
3210 const char *query_part;
3212 struct evhttp_uri *uri=NULL;
3214 TAILQ_INIT(headers);
3217 uri = evhttp_uri_parse(str);
3220 query_part = evhttp_uri_get_query(uri);
3225 /* No arguments - we are done */
3226 if (!query_part || !strlen(query_part)) {
3231 if ((line = mm_strdup(query_part)) == NULL) {
3232 event_warn("%s: strdup", __func__);
3236 p = argument = line;
3237 while (p != NULL && *p != '\0') {
3238 char *key, *value, *decoded_value;
3239 argument = strsep(&p, "&");
3242 key = strsep(&value, "=");
3243 if (value == NULL || *key == '\0') {
3247 if ((decoded_value = mm_malloc(strlen(value) + 1)) == NULL) {
3248 event_warn("%s: mm_malloc", __func__);
3251 evhttp_decode_uri_internal(value, strlen(value),
3252 decoded_value, 1 /*always_decode_plus*/);
3253 event_debug(("Query Param: %s -> %s\n", key, decoded_value));
3254 evhttp_add_header_internal(headers, key, decoded_value);
3255 mm_free(decoded_value);
3261 evhttp_clear_headers(headers);
3266 evhttp_uri_free(uri);
3271 evhttp_parse_query(const char *uri, struct evkeyvalq *headers)
3273 return evhttp_parse_query_impl(uri, headers, 1);
3276 evhttp_parse_query_str(const char *uri, struct evkeyvalq *headers)
3278 return evhttp_parse_query_impl(uri, headers, 0);
3281 static struct evhttp_cb *
3282 evhttp_dispatch_callback(struct httpcbq *callbacks, struct evhttp_request *req)
3284 struct evhttp_cb *cb;
3289 /* Test for different URLs */
3290 path = evhttp_uri_get_path(req->uri_elems);
3291 offset = strlen(path);
3292 if ((translated = mm_malloc(offset + 1)) == NULL)
3294 evhttp_decode_uri_internal(path, offset, translated,
3295 0 /* decode_plus */);
3297 TAILQ_FOREACH(cb, callbacks, next) {
3298 if (!strcmp(cb->what, translated)) {
3299 mm_free(translated);
3304 mm_free(translated);
3310 prefix_suffix_match(const char *pattern, const char *name, int ignorecase)
3315 switch (c = *pattern++) {
3317 return *name == '\0';
3320 while (*name != '\0') {
3321 if (prefix_suffix_match(pattern, name,
3330 EVUTIL_TOLOWER_(c) != EVUTIL_TOLOWER_(*name))
3340 Search the vhost hierarchy beginning with http for a server alias
3341 matching hostname. If a match is found, and outhttp is non-null,
3342 outhttp is set to the matching http object and 1 is returned.
3346 evhttp_find_alias(struct evhttp *http, struct evhttp **outhttp,
3347 const char *hostname)
3349 struct evhttp_server_alias *alias;
3350 struct evhttp *vhost;
3352 TAILQ_FOREACH(alias, &http->aliases, next) {
3353 /* XXX Do we need to handle IP addresses? */
3354 if (!evutil_ascii_strcasecmp(alias->alias, hostname)) {
3361 /* XXX It might be good to avoid recursion here, but I don't
3362 see a way to do that w/o a list. */
3363 TAILQ_FOREACH(vhost, &http->virtualhosts, next_vhost) {
3364 if (evhttp_find_alias(vhost, outhttp, hostname))
3372 Attempts to find the best http object to handle a request for a hostname.
3373 All aliases for the root http object and vhosts are searched for an exact
3374 match. Then, the vhost hierarchy is traversed again for a matching
3377 If an alias or vhost is matched, 1 is returned, and outhttp, if non-null,
3378 is set with the best matching http object. If there are no matches, the
3379 root http object is stored in outhttp and 0 is returned.
3383 evhttp_find_vhost(struct evhttp *http, struct evhttp **outhttp,
3384 const char *hostname)
3386 struct evhttp *vhost;
3387 struct evhttp *oldhttp;
3388 int match_found = 0;
3390 if (evhttp_find_alias(http, outhttp, hostname))
3395 TAILQ_FOREACH(vhost, &http->virtualhosts, next_vhost) {
3396 if (prefix_suffix_match(vhost->vhost_pattern,
3397 hostname, 1 /* ignorecase */)) {
3403 } while (oldhttp != http);
3412 evhttp_handle_request(struct evhttp_request *req, void *arg)
3414 struct evhttp *http = arg;
3415 struct evhttp_cb *cb = NULL;
3416 const char *hostname;
3418 /* we have a new request on which the user needs to take action */
3421 if (req->type == 0 || req->uri == NULL) {
3422 evhttp_send_error(req, req->response_code, NULL);
3426 if ((http->allowed_methods & req->type) == 0) {
3427 event_debug(("Rejecting disallowed method %x (allowed: %x)\n",
3428 (unsigned)req->type, (unsigned)http->allowed_methods));
3429 evhttp_send_error(req, HTTP_NOTIMPLEMENTED, NULL);
3433 /* handle potential virtual hosts */
3434 hostname = evhttp_request_get_host(req);
3435 if (hostname != NULL) {
3436 evhttp_find_vhost(http, &http, hostname);
3439 if ((cb = evhttp_dispatch_callback(&http->callbacks, req)) != NULL) {
3440 bufferevent_disable(req->evcon->bufev, EV_READ);
3442 (*cb->cb)(req, cb->cbarg);
3446 /* Generic call back */
3448 (*http->gencb)(req, http->gencbarg);
3451 /* We need to send a 404 here */
3452 #define ERR_FORMAT "<html><head>" \
3453 "<title>404 Not Found</title>" \
3455 "<h1>Not Found</h1>" \
3456 "<p>The requested URL %s was not found on this server.</p>"\
3460 struct evbuffer *buf;
3462 if ((escaped_html = evhttp_htmlescape(req->uri)) == NULL) {
3463 evhttp_connection_free(req->evcon);
3467 if ((buf = evbuffer_new()) == NULL) {
3468 mm_free(escaped_html);
3469 evhttp_connection_free(req->evcon);
3473 evhttp_response_code_(req, HTTP_NOTFOUND, "Not Found");
3475 evbuffer_add_printf(buf, ERR_FORMAT, escaped_html);
3477 mm_free(escaped_html);
3479 evhttp_send_page_(req, buf);
3486 /* Listener callback when a connection arrives at a server. */
3488 accept_socket_cb(struct evconnlistener *listener, evutil_socket_t nfd, struct sockaddr *peer_sa, int peer_socklen, void *arg)
3490 struct evhttp *http = arg;
3492 evhttp_get_request(http, nfd, peer_sa, peer_socklen);
3496 evhttp_bind_socket(struct evhttp *http, const char *address, ev_uint16_t port)
3498 struct evhttp_bound_socket *bound =
3499 evhttp_bind_socket_with_handle(http, address, port);
3505 struct evhttp_bound_socket *
3506 evhttp_bind_socket_with_handle(struct evhttp *http, const char *address, ev_uint16_t port)
3509 struct evhttp_bound_socket *bound;
3511 if ((fd = bind_socket(address, port, 1 /*reuse*/)) == -1)
3514 if (listen(fd, 128) == -1) {
3515 event_sock_warn(fd, "%s: listen", __func__);
3516 evutil_closesocket(fd);
3520 bound = evhttp_accept_socket_with_handle(http, fd);
3522 if (bound != NULL) {
3523 event_debug(("Bound to port %d - Awaiting connections ... ",
3532 evhttp_accept_socket(struct evhttp *http, evutil_socket_t fd)
3534 struct evhttp_bound_socket *bound =
3535 evhttp_accept_socket_with_handle(http, fd);
3542 evhttp_foreach_bound_socket(struct evhttp *http,
3543 evhttp_bound_socket_foreach_fn *function,
3546 struct evhttp_bound_socket *bound;
3548 TAILQ_FOREACH(bound, &http->sockets, next)
3549 function(bound, argument);
3552 struct evhttp_bound_socket *
3553 evhttp_accept_socket_with_handle(struct evhttp *http, evutil_socket_t fd)
3555 struct evhttp_bound_socket *bound;
3556 struct evconnlistener *listener;
3558 LEV_OPT_REUSEABLE|LEV_OPT_CLOSE_ON_EXEC|LEV_OPT_CLOSE_ON_FREE;
3560 listener = evconnlistener_new(http->base, NULL, NULL,
3562 0, /* Backlog is '0' because we already said 'listen' */
3567 bound = evhttp_bind_listener(http, listener);
3569 evconnlistener_free(listener);
3575 struct evhttp_bound_socket *
3576 evhttp_bind_listener(struct evhttp *http, struct evconnlistener *listener)
3578 struct evhttp_bound_socket *bound;
3580 bound = mm_malloc(sizeof(struct evhttp_bound_socket));
3584 bound->listener = listener;
3585 TAILQ_INSERT_TAIL(&http->sockets, bound, next);
3587 evconnlistener_set_cb(listener, accept_socket_cb, http);
3592 evhttp_bound_socket_get_fd(struct evhttp_bound_socket *bound)
3594 return evconnlistener_get_fd(bound->listener);
3597 struct evconnlistener *
3598 evhttp_bound_socket_get_listener(struct evhttp_bound_socket *bound)
3600 return bound->listener;
3604 evhttp_del_accept_socket(struct evhttp *http, struct evhttp_bound_socket *bound)
3606 TAILQ_REMOVE(&http->sockets, bound, next);
3607 evconnlistener_free(bound->listener);
3611 static struct evhttp*
3612 evhttp_new_object(void)
3614 struct evhttp *http = NULL;
3616 if ((http = mm_calloc(1, sizeof(struct evhttp))) == NULL) {
3617 event_warn("%s: calloc", __func__);
3621 evutil_timerclear(&http->timeout);
3622 evhttp_set_max_headers_size(http, EV_SIZE_MAX);
3623 evhttp_set_max_body_size(http, EV_SIZE_MAX);
3624 evhttp_set_default_content_type(http, "text/html; charset=ISO-8859-1");
3625 evhttp_set_allowed_methods(http,
3632 TAILQ_INIT(&http->sockets);
3633 TAILQ_INIT(&http->callbacks);
3634 TAILQ_INIT(&http->connections);
3635 TAILQ_INIT(&http->virtualhosts);
3636 TAILQ_INIT(&http->aliases);
3642 evhttp_new(struct event_base *base)
3644 struct evhttp *http = NULL;
3646 http = evhttp_new_object();
3655 * Start a web server on the specified address and port.
3659 evhttp_start(const char *address, ev_uint16_t port)
3661 struct evhttp *http = NULL;
3663 http = evhttp_new_object();
3666 if (evhttp_bind_socket(http, address, port) == -1) {
3675 evhttp_free(struct evhttp* http)
3677 struct evhttp_cb *http_cb;
3678 struct evhttp_connection *evcon;
3679 struct evhttp_bound_socket *bound;
3680 struct evhttp* vhost;
3681 struct evhttp_server_alias *alias;
3683 /* Remove the accepting part */
3684 while ((bound = TAILQ_FIRST(&http->sockets)) != NULL) {
3685 TAILQ_REMOVE(&http->sockets, bound, next);
3687 evconnlistener_free(bound->listener);
3692 while ((evcon = TAILQ_FIRST(&http->connections)) != NULL) {
3693 /* evhttp_connection_free removes the connection */
3694 evhttp_connection_free(evcon);
3697 while ((http_cb = TAILQ_FIRST(&http->callbacks)) != NULL) {
3698 TAILQ_REMOVE(&http->callbacks, http_cb, next);
3699 mm_free(http_cb->what);
3703 while ((vhost = TAILQ_FIRST(&http->virtualhosts)) != NULL) {
3704 TAILQ_REMOVE(&http->virtualhosts, vhost, next_vhost);
3709 if (http->vhost_pattern != NULL)
3710 mm_free(http->vhost_pattern);
3712 while ((alias = TAILQ_FIRST(&http->aliases)) != NULL) {
3713 TAILQ_REMOVE(&http->aliases, alias, next);
3714 mm_free(alias->alias);
3722 evhttp_add_virtual_host(struct evhttp* http, const char *pattern,
3723 struct evhttp* vhost)
3725 /* a vhost can only be a vhost once and should not have bound sockets */
3726 if (vhost->vhost_pattern != NULL ||
3727 TAILQ_FIRST(&vhost->sockets) != NULL)
3730 vhost->vhost_pattern = mm_strdup(pattern);
3731 if (vhost->vhost_pattern == NULL)
3734 TAILQ_INSERT_TAIL(&http->virtualhosts, vhost, next_vhost);
3740 evhttp_remove_virtual_host(struct evhttp* http, struct evhttp* vhost)
3742 if (vhost->vhost_pattern == NULL)
3745 TAILQ_REMOVE(&http->virtualhosts, vhost, next_vhost);
3747 mm_free(vhost->vhost_pattern);
3748 vhost->vhost_pattern = NULL;
3754 evhttp_add_server_alias(struct evhttp *http, const char *alias)
3756 struct evhttp_server_alias *evalias;
3758 evalias = mm_calloc(1, sizeof(*evalias));
3762 evalias->alias = mm_strdup(alias);
3763 if (!evalias->alias) {
3768 TAILQ_INSERT_TAIL(&http->aliases, evalias, next);
3774 evhttp_remove_server_alias(struct evhttp *http, const char *alias)
3776 struct evhttp_server_alias *evalias;
3778 TAILQ_FOREACH(evalias, &http->aliases, next) {
3779 if (evutil_ascii_strcasecmp(evalias->alias, alias) == 0) {
3780 TAILQ_REMOVE(&http->aliases, evalias, next);
3781 mm_free(evalias->alias);
3791 evhttp_set_timeout(struct evhttp* http, int timeout_in_secs)
3793 if (timeout_in_secs == -1) {
3794 evhttp_set_timeout_tv(http, NULL);
3797 tv.tv_sec = timeout_in_secs;
3799 evhttp_set_timeout_tv(http, &tv);
3804 evhttp_set_timeout_tv(struct evhttp* http, const struct timeval* tv)
3807 http->timeout = *tv;
3809 evutil_timerclear(&http->timeout);
3813 int evhttp_set_flags(struct evhttp *http, int flags)
3815 int avail_flags = 0;
3816 avail_flags |= EVHTTP_SERVER_LINGERING_CLOSE;
3818 if (flags & ~avail_flags)
3820 http->flags &= ~avail_flags;
3822 http->flags |= flags;
3828 evhttp_set_max_headers_size(struct evhttp* http, ev_ssize_t max_headers_size)
3830 if (max_headers_size < 0)
3831 http->default_max_headers_size = EV_SIZE_MAX;
3833 http->default_max_headers_size = max_headers_size;
3837 evhttp_set_max_body_size(struct evhttp* http, ev_ssize_t max_body_size)
3839 if (max_body_size < 0)
3840 http->default_max_body_size = EV_UINT64_MAX;
3842 http->default_max_body_size = max_body_size;
3846 evhttp_set_default_content_type(struct evhttp *http,
3847 const char *content_type) {
3848 http->default_content_type = content_type;
3852 evhttp_set_allowed_methods(struct evhttp* http, ev_uint16_t methods)
3854 http->allowed_methods = methods;
3858 evhttp_set_cb(struct evhttp *http, const char *uri,
3859 void (*cb)(struct evhttp_request *, void *), void *cbarg)
3861 struct evhttp_cb *http_cb;
3863 TAILQ_FOREACH(http_cb, &http->callbacks, next) {
3864 if (strcmp(http_cb->what, uri) == 0)
3868 if ((http_cb = mm_calloc(1, sizeof(struct evhttp_cb))) == NULL) {
3869 event_warn("%s: calloc", __func__);
3873 http_cb->what = mm_strdup(uri);
3874 if (http_cb->what == NULL) {
3875 event_warn("%s: strdup", __func__);
3880 http_cb->cbarg = cbarg;
3882 TAILQ_INSERT_TAIL(&http->callbacks, http_cb, next);
3888 evhttp_del_cb(struct evhttp *http, const char *uri)
3890 struct evhttp_cb *http_cb;
3892 TAILQ_FOREACH(http_cb, &http->callbacks, next) {
3893 if (strcmp(http_cb->what, uri) == 0)
3896 if (http_cb == NULL)
3899 TAILQ_REMOVE(&http->callbacks, http_cb, next);
3900 mm_free(http_cb->what);
3907 evhttp_set_gencb(struct evhttp *http,
3908 void (*cb)(struct evhttp_request *, void *), void *cbarg)
3911 http->gencbarg = cbarg;
3915 evhttp_set_bevcb(struct evhttp *http,
3916 struct bufferevent* (*cb)(struct event_base *, void *), void *cbarg)
3919 http->bevcbarg = cbarg;
3923 * Request related functions
3926 struct evhttp_request *
3927 evhttp_request_new(void (*cb)(struct evhttp_request *, void *), void *arg)
3929 struct evhttp_request *req = NULL;
3931 /* Allocate request structure */
3932 if ((req = mm_calloc(1, sizeof(struct evhttp_request))) == NULL) {
3933 event_warn("%s: calloc", __func__);
3937 req->headers_size = 0;
3940 req->kind = EVHTTP_RESPONSE;
3941 req->input_headers = mm_calloc(1, sizeof(struct evkeyvalq));
3942 if (req->input_headers == NULL) {
3943 event_warn("%s: calloc", __func__);
3946 TAILQ_INIT(req->input_headers);
3948 req->output_headers = mm_calloc(1, sizeof(struct evkeyvalq));
3949 if (req->output_headers == NULL) {
3950 event_warn("%s: calloc", __func__);
3953 TAILQ_INIT(req->output_headers);
3955 if ((req->input_buffer = evbuffer_new()) == NULL) {
3956 event_warn("%s: evbuffer_new", __func__);
3960 if ((req->output_buffer = evbuffer_new()) == NULL) {
3961 event_warn("%s: evbuffer_new", __func__);
3972 evhttp_request_free(req);
3977 evhttp_request_free(struct evhttp_request *req)
3979 if ((req->flags & EVHTTP_REQ_DEFER_FREE) != 0) {
3980 req->flags |= EVHTTP_REQ_NEEDS_FREE;
3984 if (req->remote_host != NULL)
3985 mm_free(req->remote_host);
3986 if (req->uri != NULL)
3988 if (req->uri_elems != NULL)
3989 evhttp_uri_free(req->uri_elems);
3990 if (req->response_code_line != NULL)
3991 mm_free(req->response_code_line);
3992 if (req->host_cache != NULL)
3993 mm_free(req->host_cache);
3995 evhttp_clear_headers(req->input_headers);
3996 mm_free(req->input_headers);
3998 evhttp_clear_headers(req->output_headers);
3999 mm_free(req->output_headers);
4001 if (req->input_buffer != NULL)
4002 evbuffer_free(req->input_buffer);
4004 if (req->output_buffer != NULL)
4005 evbuffer_free(req->output_buffer);
4011 evhttp_request_own(struct evhttp_request *req)
4013 req->flags |= EVHTTP_USER_OWNED;
4017 evhttp_request_is_owned(struct evhttp_request *req)
4019 return (req->flags & EVHTTP_USER_OWNED) != 0;
4022 struct evhttp_connection *
4023 evhttp_request_get_connection(struct evhttp_request *req)
4029 evhttp_connection_get_base(struct evhttp_connection *conn)
4035 evhttp_request_set_chunked_cb(struct evhttp_request *req,
4036 void (*cb)(struct evhttp_request *, void *))
4042 evhttp_request_set_header_cb(struct evhttp_request *req,
4043 int (*cb)(struct evhttp_request *, void *))
4045 req->header_cb = cb;
4049 evhttp_request_set_error_cb(struct evhttp_request *req,
4050 void (*cb)(enum evhttp_request_error, void *))
4056 evhttp_request_set_on_complete_cb(struct evhttp_request *req,
4057 void (*cb)(struct evhttp_request *, void *), void *cb_arg)
4059 req->on_complete_cb = cb;
4060 req->on_complete_cb_arg = cb_arg;
4064 * Allows for inspection of the request URI
4068 evhttp_request_get_uri(const struct evhttp_request *req) {
4069 if (req->uri == NULL)
4070 event_debug(("%s: request %p has no uri\n", __func__, req));
4074 const struct evhttp_uri *
4075 evhttp_request_get_evhttp_uri(const struct evhttp_request *req) {
4076 if (req->uri_elems == NULL)
4077 event_debug(("%s: request %p has no uri elems\n",
4079 return (req->uri_elems);
4083 evhttp_request_get_host(struct evhttp_request *req)
4085 const char *host = NULL;
4087 if (req->host_cache)
4088 return req->host_cache;
4091 host = evhttp_uri_get_host(req->uri_elems);
4092 if (!host && req->input_headers) {
4096 host = evhttp_find_header(req->input_headers, "Host");
4097 /* The Host: header may include a port. Remove it here
4098 to be consistent with uri_elems case above. */
4100 p = host + strlen(host) - 1;
4101 while (p > host && EVUTIL_ISDIGIT_(*p))
4103 if (p > host && *p == ':') {
4105 req->host_cache = mm_malloc(len + 1);
4106 if (!req->host_cache) {
4107 event_warn("%s: malloc", __func__);
4110 memcpy(req->host_cache, host, len);
4111 req->host_cache[len] = '\0';
4112 host = req->host_cache;
4120 enum evhttp_cmd_type
4121 evhttp_request_get_command(const struct evhttp_request *req) {
4126 evhttp_request_get_response_code(const struct evhttp_request *req)
4128 return req->response_code;
4132 evhttp_request_get_response_code_line(const struct evhttp_request *req)
4134 return req->response_code_line;
4137 /** Returns the input headers */
4138 struct evkeyvalq *evhttp_request_get_input_headers(struct evhttp_request *req)
4140 return (req->input_headers);
4143 /** Returns the output headers */
4144 struct evkeyvalq *evhttp_request_get_output_headers(struct evhttp_request *req)
4146 return (req->output_headers);
4149 /** Returns the input buffer */
4150 struct evbuffer *evhttp_request_get_input_buffer(struct evhttp_request *req)
4152 return (req->input_buffer);
4155 /** Returns the output buffer */
4156 struct evbuffer *evhttp_request_get_output_buffer(struct evhttp_request *req)
4158 return (req->output_buffer);
4163 * Takes a file descriptor to read a request from.
4164 * The callback is executed once the whole request has been read.
4167 static struct evhttp_connection*
4168 evhttp_get_request_connection(
4169 struct evhttp* http,
4170 evutil_socket_t fd, struct sockaddr *sa, ev_socklen_t salen)
4172 struct evhttp_connection *evcon;
4173 char *hostname = NULL, *portname = NULL;
4174 struct bufferevent* bev = NULL;
4176 name_from_addr(sa, salen, &hostname, &portname);
4177 if (hostname == NULL || portname == NULL) {
4178 if (hostname) mm_free(hostname);
4179 if (portname) mm_free(portname);
4183 event_debug(("%s: new request from %s:%s on "EV_SOCK_FMT"\n",
4184 __func__, hostname, portname, EV_SOCK_ARG(fd)));
4186 /* we need a connection object to put the http request on */
4187 if (http->bevcb != NULL) {
4188 bev = (*http->bevcb)(http->base, http->bevcbarg);
4190 evcon = evhttp_connection_base_bufferevent_new(
4191 http->base, NULL, bev, hostname, atoi(portname));
4197 evcon->max_headers_size = http->default_max_headers_size;
4198 evcon->max_body_size = http->default_max_body_size;
4199 if (http->flags & EVHTTP_SERVER_LINGERING_CLOSE)
4200 evcon->flags |= EVHTTP_CON_LINGERING_CLOSE;
4202 evcon->flags |= EVHTTP_CON_INCOMING;
4203 evcon->state = EVCON_READING_FIRSTLINE;
4207 bufferevent_enable(evcon->bufev, EV_READ);
4208 bufferevent_disable(evcon->bufev, EV_WRITE);
4209 bufferevent_setfd(evcon->bufev, fd);
4215 evhttp_associate_new_request_with_connection(struct evhttp_connection *evcon)
4217 struct evhttp *http = evcon->http_server;
4218 struct evhttp_request *req;
4219 if ((req = evhttp_request_new(evhttp_handle_request, http)) == NULL)
4222 if ((req->remote_host = mm_strdup(evcon->address)) == NULL) {
4223 event_warn("%s: strdup", __func__);
4224 evhttp_request_free(req);
4227 req->remote_port = evcon->port;
4229 req->evcon = evcon; /* the request ends up owning the connection */
4230 req->flags |= EVHTTP_REQ_OWN_CONNECTION;
4232 /* We did not present the request to the user user yet, so treat it as
4233 * if the user was done with the request. This allows us to free the
4234 * request on a persistent connection if the client drops it without
4235 * sending a request.
4239 TAILQ_INSERT_TAIL(&evcon->requests, req, next);
4241 req->kind = EVHTTP_REQUEST;
4244 evhttp_start_read_(evcon);
4250 evhttp_get_request(struct evhttp *http, evutil_socket_t fd,
4251 struct sockaddr *sa, ev_socklen_t salen)
4253 struct evhttp_connection *evcon;
4255 evcon = evhttp_get_request_connection(http, fd, sa, salen);
4256 if (evcon == NULL) {
4257 event_sock_warn(fd, "%s: cannot get connection on "EV_SOCK_FMT,
4258 __func__, EV_SOCK_ARG(fd));
4259 evutil_closesocket(fd);
4263 /* the timeout can be used by the server to close idle connections */
4264 if (evutil_timerisset(&http->timeout))
4265 evhttp_connection_set_timeout_tv(evcon, &http->timeout);
4268 * if we want to accept more than one request on a connection,
4269 * we need to know which http server it belongs to.
4271 evcon->http_server = http;
4272 TAILQ_INSERT_TAIL(&http->connections, evcon, next);
4274 if (evhttp_associate_new_request_with_connection(evcon) == -1)
4275 evhttp_connection_free(evcon);
4280 * Network helper functions that we do not want to export to the rest of
4285 name_from_addr(struct sockaddr *sa, ev_socklen_t salen,
4286 char **phost, char **pport)
4288 char ntop[NI_MAXHOST];
4289 char strport[NI_MAXSERV];
4292 #ifdef EVENT__HAVE_GETNAMEINFO
4293 ni_result = getnameinfo(sa, salen,
4294 ntop, sizeof(ntop), strport, sizeof(strport),
4295 NI_NUMERICHOST|NI_NUMERICSERV);
4297 if (ni_result != 0) {
4299 /* Windows doesn't have an EAI_SYSTEM. */
4300 if (ni_result == EAI_SYSTEM)
4301 event_err(1, "getnameinfo failed");
4304 event_errx(1, "getnameinfo failed: %s", gai_strerror(ni_result));
4308 ni_result = fake_getnameinfo(sa, salen,
4309 ntop, sizeof(ntop), strport, sizeof(strport),
4310 NI_NUMERICHOST|NI_NUMERICSERV);
4315 *phost = mm_strdup(ntop);
4316 *pport = mm_strdup(strport);
4319 /* Create a non-blocking socket and bind it */
4320 /* todo: rename this function */
4321 static evutil_socket_t
4322 bind_socket_ai(struct evutil_addrinfo *ai, int reuse)
4329 /* Create listen socket */
4330 fd = evutil_socket_(ai ? ai->ai_family : AF_INET,
4331 SOCK_STREAM|EVUTIL_SOCK_NONBLOCK|EVUTIL_SOCK_CLOEXEC, 0);
4333 event_sock_warn(-1, "socket");
4337 if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (void *)&on, sizeof(on))<0)
4340 if (evutil_make_listen_socket_reuseable(fd) < 0)
4345 r = bind(fd, ai->ai_addr, (ev_socklen_t)ai->ai_addrlen);
4353 serrno = EVUTIL_SOCKET_ERROR();
4354 evutil_closesocket(fd);
4355 EVUTIL_SET_SOCKET_ERROR(serrno);
4359 static struct evutil_addrinfo *
4360 make_addrinfo(const char *address, ev_uint16_t port)
4362 struct evutil_addrinfo *ai = NULL;
4364 struct evutil_addrinfo hints;
4365 char strport[NI_MAXSERV];
4368 memset(&hints, 0, sizeof(hints));
4369 hints.ai_family = AF_UNSPEC;
4370 hints.ai_socktype = SOCK_STREAM;
4371 /* turn NULL hostname into INADDR_ANY, and skip looking up any address
4372 * types we don't have an interface to connect to. */
4373 hints.ai_flags = EVUTIL_AI_PASSIVE|EVUTIL_AI_ADDRCONFIG;
4374 evutil_snprintf(strport, sizeof(strport), "%d", port);
4375 if ((ai_result = evutil_getaddrinfo(address, strport, &hints, &ai))
4377 if (ai_result == EVUTIL_EAI_SYSTEM)
4378 event_warn("getaddrinfo");
4380 event_warnx("getaddrinfo: %s",
4381 evutil_gai_strerror(ai_result));
4388 static evutil_socket_t
4389 bind_socket(const char *address, ev_uint16_t port, int reuse)
4392 struct evutil_addrinfo *aitop = NULL;
4394 /* just create an unbound socket */
4395 if (address == NULL && port == 0)
4396 return bind_socket_ai(NULL, 0);
4398 aitop = make_addrinfo(address, port);
4403 fd = bind_socket_ai(aitop, reuse);
4405 evutil_freeaddrinfo(aitop);
4412 char *scheme; /* scheme; e.g http, ftp etc */
4413 char *userinfo; /* userinfo (typically username:pass), or NULL */
4414 char *host; /* hostname, IP address, or NULL */
4415 int port; /* port, or zero */
4416 char *path; /* path, or "". */
4417 char *query; /* query, or NULL */
4418 char *fragment; /* fragment or NULL */
4422 evhttp_uri_new(void)
4424 struct evhttp_uri *uri = mm_calloc(sizeof(struct evhttp_uri), 1);
4431 evhttp_uri_set_flags(struct evhttp_uri *uri, unsigned flags)
4436 /* Return true if the string starting at s and ending immediately before eos
4437 * is a valid URI scheme according to RFC3986
4440 scheme_ok(const char *s, const char *eos)
4442 /* scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." ) */
4443 EVUTIL_ASSERT(eos >= s);
4446 if (!EVUTIL_ISALPHA_(*s))
4449 if (! EVUTIL_ISALNUM_(*s) &&
4450 *s != '+' && *s != '-' && *s != '.')
4456 #define SUBDELIMS "!$&'()*+,;="
4458 /* Return true iff [s..eos) is a valid userinfo */
4460 userinfo_ok(const char *s, const char *eos)
4463 if (CHAR_IS_UNRESERVED(*s) ||
4464 strchr(SUBDELIMS, *s) ||
4467 else if (*s == '%' && s+2 < eos &&
4468 EVUTIL_ISXDIGIT_(s[1]) &&
4469 EVUTIL_ISXDIGIT_(s[2]))
4478 regname_ok(const char *s, const char *eos)
4480 while (s && s<eos) {
4481 if (CHAR_IS_UNRESERVED(*s) ||
4482 strchr(SUBDELIMS, *s))
4484 else if (*s == '%' &&
4485 EVUTIL_ISXDIGIT_(s[1]) &&
4486 EVUTIL_ISXDIGIT_(s[2]))
4495 parse_port(const char *s, const char *eos)
4499 if (! EVUTIL_ISDIGIT_(*s))
4501 portnum = (portnum * 10) + (*s - '0');
4504 if (portnum > 65535)
4511 /* returns 0 for bad, 1 for ipv6, 2 for IPvFuture */
4513 bracket_addr_ok(const char *s, const char *eos)
4515 if (s + 3 > eos || *s != '[' || *(eos-1) != ']')
4518 /* IPvFuture, or junk.
4519 "v" 1*HEXDIG "." 1*( unreserved / sub-delims / ":" )
4521 s += 2; /* skip [v */
4523 if (!EVUTIL_ISXDIGIT_(*s)) /*require at least one*/
4525 while (s < eos && *s != '.') {
4526 if (EVUTIL_ISXDIGIT_(*s))
4535 if (CHAR_IS_UNRESERVED(*s) ||
4536 strchr(SUBDELIMS, *s) ||
4546 ev_ssize_t n_chars = eos-s-2;
4547 struct in6_addr in6;
4548 if (n_chars >= 64) /* way too long */
4550 memcpy(buf, s+1, n_chars);
4552 return (evutil_inet_pton(AF_INET6,buf,&in6)==1) ? 1 : 0;
4557 parse_authority(struct evhttp_uri *uri, char *s, char *eos)
4562 uri->host = mm_strdup("");
4563 if (uri->host == NULL) {
4564 event_warn("%s: strdup", __func__);
4570 /* Optionally, we start with "userinfo@" */
4572 cp = strchr(s, '@');
4573 if (cp && cp < eos) {
4574 if (! userinfo_ok(s,cp))
4577 uri->userinfo = mm_strdup(s);
4578 if (uri->userinfo == NULL) {
4579 event_warn("%s: strdup", __func__);
4585 /* Optionally, we end with ":port" */
4586 for (port=eos-1; port >= cp && EVUTIL_ISDIGIT_(*port); --port)
4588 if (port >= cp && *port == ':') {
4589 if (port+1 == eos) /* Leave port unspecified; the RFC allows a
4592 else if ((uri->port = parse_port(port+1, eos))<0)
4596 /* Now, cp..eos holds the "host" port, which can be an IPv4Address,
4597 * an IP-Literal, or a reg-name */
4598 EVUTIL_ASSERT(eos >= cp);
4599 if (*cp == '[' && eos >= cp+2 && *(eos-1) == ']') {
4600 /* IPv6address, IP-Literal, or junk. */
4601 if (! bracket_addr_ok(cp, eos))
4604 /* Make sure the host part is ok. */
4605 if (! regname_ok(cp,eos)) /* Match IPv4Address or reg-name */
4608 uri->host = mm_malloc(eos-cp+1);
4609 if (uri->host == NULL) {
4610 event_warn("%s: malloc", __func__);
4613 memcpy(uri->host, cp, eos-cp);
4614 uri->host[eos-cp] = '\0';
4620 end_of_authority(char *cp)
4623 if (*cp == '?' || *cp == '#' || *cp == '/')
4636 /* Return the character after the longest prefix of 'cp' that matches...
4637 * *pchar / "/" if allow_qchars is false, or
4638 * *(pchar / "/" / "?") if allow_qchars is true.
4641 end_of_path(char *cp, enum uri_part part, unsigned flags)
4643 if (flags & EVHTTP_URI_NONCONFORMANT) {
4644 /* If NONCONFORMANT:
4645 * Path is everything up to a # or ? or nul.
4646 * Query is everything up a # or nul
4647 * Fragment is everything up to a nul.
4651 while (*cp && *cp != '#' && *cp != '?')
4655 while (*cp && *cp != '#')
4666 if (CHAR_IS_UNRESERVED(*cp) ||
4667 strchr(SUBDELIMS, *cp) ||
4668 *cp == ':' || *cp == '@' || *cp == '/')
4670 else if (*cp == '%' && EVUTIL_ISXDIGIT_(cp[1]) &&
4671 EVUTIL_ISXDIGIT_(cp[2]))
4673 else if (*cp == '?' && part != PART_PATH)
4682 path_matches_noscheme(const char *cp)
4687 else if (*cp == '/')
4695 evhttp_uri_parse(const char *source_uri)
4697 return evhttp_uri_parse_with_flags(source_uri, 0);
4701 evhttp_uri_parse_with_flags(const char *source_uri, unsigned flags)
4703 char *readbuf = NULL, *readp = NULL, *token = NULL, *query = NULL;
4704 char *path = NULL, *fragment = NULL;
4705 int got_authority = 0;
4707 struct evhttp_uri *uri = mm_calloc(1, sizeof(struct evhttp_uri));
4709 event_warn("%s: calloc", __func__);
4715 readbuf = mm_strdup(source_uri);
4716 if (readbuf == NULL) {
4717 event_warn("%s: strdup", __func__);
4724 /* We try to follow RFC3986 here as much as we can, and match
4727 URI = scheme ":" hier-part [ "?" query ] [ "#" fragment ]
4729 relative-ref = relative-part [ "?" query ] [ "#" fragment ]
4733 token = strchr(readp, ':');
4734 if (token && scheme_ok(readp,token)) {
4736 uri->scheme = mm_strdup(readp);
4737 if (uri->scheme == NULL) {
4738 event_warn("%s: strdup", __func__);
4741 readp = token+1; /* eat : */
4744 /* 2. Optionally, "//" then an 'authority' part. */
4745 if (readp[0]=='/' && readp[1] == '/') {
4749 path = end_of_authority(readp);
4750 if (parse_authority(uri, authority, path) < 0)
4756 /* 3. Query: path-abempty, path-absolute, path-rootless, or path-empty
4759 readp = end_of_path(path, PART_PATH, flags);
4762 if (*readp == '?') {
4766 readp = end_of_path(readp, PART_QUERY, flags);
4769 if (*readp == '#') {
4773 readp = end_of_path(readp, PART_FRAGMENT, flags);
4775 if (*readp != '\0') {
4779 /* These next two cases may be unreachable; I'm leaving them
4780 * in to be defensive. */
4781 /* If you didn't get an authority, the path can't begin with "//" */
4782 if (!got_authority && path[0]=='/' && path[1]=='/')
4784 /* If you did get an authority, the path must begin with "/" or be
4786 if (got_authority && path[0] != '/' && path[0] != '\0')
4788 /* (End of maybe-unreachable cases) */
4790 /* If there was no scheme, the first part of the path (if any) must
4791 * have no colon in it. */
4792 if (! uri->scheme && !path_matches_noscheme(path))
4795 EVUTIL_ASSERT(path);
4796 uri->path = mm_strdup(path);
4797 if (uri->path == NULL) {
4798 event_warn("%s: strdup", __func__);
4803 uri->query = mm_strdup(query);
4804 if (uri->query == NULL) {
4805 event_warn("%s: strdup", __func__);
4810 uri->fragment = mm_strdup(fragment);
4811 if (uri->fragment == NULL) {
4812 event_warn("%s: strdup", __func__);
4822 evhttp_uri_free(uri);
4829 evhttp_uri_free(struct evhttp_uri *uri)
4831 #define URI_FREE_STR_(f) \
4836 URI_FREE_STR_(scheme);
4837 URI_FREE_STR_(userinfo);
4838 URI_FREE_STR_(host);
4839 URI_FREE_STR_(path);
4840 URI_FREE_STR_(query);
4841 URI_FREE_STR_(fragment);
4844 #undef URI_FREE_STR_
4848 evhttp_uri_join(struct evhttp_uri *uri, char *buf, size_t limit)
4850 struct evbuffer *tmp = 0;
4851 size_t joined_size = 0;
4852 char *output = NULL;
4854 #define URI_ADD_(f) evbuffer_add(tmp, uri->f, strlen(uri->f))
4856 if (!uri || !buf || !limit)
4859 tmp = evbuffer_new();
4865 evbuffer_add(tmp, ":", 1);
4868 evbuffer_add(tmp, "//", 2);
4870 evbuffer_add_printf(tmp,"%s@", uri->userinfo);
4873 evbuffer_add_printf(tmp,":%d", uri->port);
4875 if (uri->path && uri->path[0] != '/' && uri->path[0] != '\0')
4883 evbuffer_add(tmp, "?", 1);
4887 if (uri->fragment) {
4888 evbuffer_add(tmp, "#", 1);
4892 evbuffer_add(tmp, "\0", 1); /* NUL */
4894 joined_size = evbuffer_get_length(tmp);
4896 if (joined_size > limit) {
4897 /* It doesn't fit. */
4901 evbuffer_remove(tmp, buf, joined_size);
4912 evhttp_uri_get_scheme(const struct evhttp_uri *uri)
4917 evhttp_uri_get_userinfo(const struct evhttp_uri *uri)
4919 return uri->userinfo;
4922 evhttp_uri_get_host(const struct evhttp_uri *uri)
4927 evhttp_uri_get_port(const struct evhttp_uri *uri)
4932 evhttp_uri_get_path(const struct evhttp_uri *uri)
4937 evhttp_uri_get_query(const struct evhttp_uri *uri)
4942 evhttp_uri_get_fragment(const struct evhttp_uri *uri)
4944 return uri->fragment;
4947 #define URI_SET_STR_(f) do { \
4951 if ((uri->f = mm_strdup(f)) == NULL) { \
4952 event_warn("%s: strdup()", __func__); \
4961 evhttp_uri_set_scheme(struct evhttp_uri *uri, const char *scheme)
4963 if (scheme && !scheme_ok(scheme, scheme+strlen(scheme)))
4966 URI_SET_STR_(scheme);
4970 evhttp_uri_set_userinfo(struct evhttp_uri *uri, const char *userinfo)
4972 if (userinfo && !userinfo_ok(userinfo, userinfo+strlen(userinfo)))
4974 URI_SET_STR_(userinfo);
4978 evhttp_uri_set_host(struct evhttp_uri *uri, const char *host)
4981 if (host[0] == '[') {
4982 if (! bracket_addr_ok(host, host+strlen(host)))
4985 if (! regname_ok(host, host+strlen(host)))
4994 evhttp_uri_set_port(struct evhttp_uri *uri, int port)
5001 #define end_of_cpath(cp,p,f) \
5002 ((const char*)(end_of_path(((char*)(cp)), (p), (f))))
5005 evhttp_uri_set_path(struct evhttp_uri *uri, const char *path)
5007 if (path && end_of_cpath(path, PART_PATH, uri->flags) != path+strlen(path))
5014 evhttp_uri_set_query(struct evhttp_uri *uri, const char *query)
5016 if (query && end_of_cpath(query, PART_QUERY, uri->flags) != query+strlen(query))
5018 URI_SET_STR_(query);
5022 evhttp_uri_set_fragment(struct evhttp_uri *uri, const char *fragment)
5024 if (fragment && end_of_cpath(fragment, PART_FRAGMENT, uri->flags) != fragment+strlen(fragment))
5026 URI_SET_STR_(fragment);