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_GET:
2162 case EVHTTP_REQ_DELETE:
2163 case EVHTTP_REQ_OPTIONS:
2164 case EVHTTP_REQ_CONNECT:
2167 case EVHTTP_REQ_TRACE:
2168 case EVHTTP_REQ_HEAD:
2175 evhttp_get_body(struct evhttp_connection *evcon, struct evhttp_request *req)
2177 const char *xfer_enc;
2179 /* If this is a request without a body, then we are done */
2180 if (req->kind == EVHTTP_REQUEST &&
2181 !evhttp_method_may_have_body(req->type)) {
2182 evhttp_connection_done(evcon);
2185 evcon->state = EVCON_READING_BODY;
2186 xfer_enc = evhttp_find_header(req->input_headers, "Transfer-Encoding");
2187 if (xfer_enc != NULL && evutil_ascii_strcasecmp(xfer_enc, "chunked") == 0) {
2191 if (evhttp_get_body_length(req) == -1) {
2192 evhttp_connection_fail_(evcon, EVREQ_HTTP_INVALID_HEADER);
2195 if (req->kind == EVHTTP_REQUEST && req->ntoread < 1) {
2196 /* An incoming request with no content-length and no
2197 * transfer-encoding has no body. */
2198 evhttp_connection_done(evcon);
2203 /* Should we send a 100 Continue status line? */
2204 switch (evhttp_have_expect(req, 1)) {
2206 /* XXX It would be nice to do some sanity
2207 checking here. Does the resource exist?
2208 Should the resource accept post requests? If
2209 no, we should respond with an error. For
2210 now, just optimistically tell the client to
2211 send their message body. */
2212 if (req->ntoread > 0) {
2213 /* ntoread is ev_int64_t, max_body_size is ev_uint64_t */
2214 if ((req->evcon->max_body_size <= EV_INT64_MAX) &&
2215 (ev_uint64_t)req->ntoread > req->evcon->max_body_size) {
2216 evhttp_lingering_fail(evcon, req);
2220 if (!evbuffer_get_length(bufferevent_get_input(evcon->bufev)))
2221 evhttp_send_continue(evcon, req);
2224 evhttp_send_error(req, HTTP_EXPECTATIONFAILED, NULL);
2229 evhttp_read_body(evcon, req);
2230 /* note the request may have been freed in evhttp_read_body */
2234 evhttp_read_firstline(struct evhttp_connection *evcon,
2235 struct evhttp_request *req)
2237 enum message_read_status res;
2239 res = evhttp_parse_firstline_(req, bufferevent_get_input(evcon->bufev));
2240 if (res == DATA_CORRUPTED || res == DATA_TOO_LONG) {
2241 /* Error while reading, terminate */
2242 event_debug(("%s: bad header lines on "EV_SOCK_FMT"\n",
2243 __func__, EV_SOCK_ARG(evcon->fd)));
2244 evhttp_connection_fail_(evcon, EVREQ_HTTP_INVALID_HEADER);
2246 } else if (res == MORE_DATA_EXPECTED) {
2247 /* Need more header lines */
2251 evcon->state = EVCON_READING_HEADERS;
2252 evhttp_read_header(evcon, req);
2256 evhttp_read_header(struct evhttp_connection *evcon,
2257 struct evhttp_request *req)
2259 enum message_read_status res;
2260 evutil_socket_t fd = evcon->fd;
2262 res = evhttp_parse_headers_(req, bufferevent_get_input(evcon->bufev));
2263 if (res == DATA_CORRUPTED || res == DATA_TOO_LONG) {
2264 /* Error while reading, terminate */
2265 event_debug(("%s: bad header lines on "EV_SOCK_FMT"\n",
2266 __func__, EV_SOCK_ARG(fd)));
2267 evhttp_connection_fail_(evcon, EVREQ_HTTP_INVALID_HEADER);
2269 } else if (res == MORE_DATA_EXPECTED) {
2270 /* Need more header lines */
2274 /* Callback can shut down connection with negative return value */
2275 if (req->header_cb != NULL) {
2276 if ((*req->header_cb)(req, req->cb_arg) < 0) {
2277 evhttp_connection_fail_(evcon, EVREQ_HTTP_EOF);
2282 /* Done reading headers, do the real work */
2283 switch (req->kind) {
2284 case EVHTTP_REQUEST:
2285 event_debug(("%s: checking for post data on "EV_SOCK_FMT"\n",
2286 __func__, EV_SOCK_ARG(fd)));
2287 evhttp_get_body(evcon, req);
2288 /* note the request may have been freed in evhttp_get_body */
2291 case EVHTTP_RESPONSE:
2292 /* Start over if we got a 100 Continue response. */
2293 if (req->response_code == 100) {
2294 struct evbuffer *output = bufferevent_get_output(evcon->bufev);
2295 evbuffer_add_buffer(output, req->output_buffer);
2296 evhttp_start_write_(evcon);
2299 if (!evhttp_response_needs_body(req)) {
2300 event_debug(("%s: skipping body for code %d\n",
2301 __func__, req->response_code));
2302 evhttp_connection_done(evcon);
2304 event_debug(("%s: start of read body for %s on "
2306 __func__, req->remote_host, EV_SOCK_ARG(fd)));
2307 evhttp_get_body(evcon, req);
2308 /* note the request may have been freed in
2309 * evhttp_get_body */
2314 event_warnx("%s: bad header on "EV_SOCK_FMT, __func__,
2316 evhttp_connection_fail_(evcon, EVREQ_HTTP_INVALID_HEADER);
2319 /* request may have been freed above */
2323 * Creates a TCP connection to the specified port and executes a callback
2324 * when finished. Failure or success is indicate by the passed connection
2327 * Although this interface accepts a hostname, it is intended to take
2328 * only numeric hostnames so that non-blocking DNS resolution can
2332 struct evhttp_connection *
2333 evhttp_connection_new(const char *address, ev_uint16_t port)
2335 return (evhttp_connection_base_new(NULL, NULL, address, port));
2338 struct evhttp_connection *
2339 evhttp_connection_base_bufferevent_new(struct event_base *base, struct evdns_base *dnsbase, struct bufferevent* bev,
2340 const char *address, ev_uint16_t port)
2342 struct evhttp_connection *evcon = NULL;
2344 event_debug(("Attempting connection to %s:%d\n", address, port));
2346 if ((evcon = mm_calloc(1, sizeof(struct evhttp_connection))) == NULL) {
2347 event_warn("%s: calloc failed", __func__);
2354 evcon->max_headers_size = EV_SIZE_MAX;
2355 evcon->max_body_size = EV_SIZE_MAX;
2357 evutil_timerclear(&evcon->timeout);
2358 evcon->retry_cnt = evcon->retry_max = 0;
2360 if ((evcon->address = mm_strdup(address)) == NULL) {
2361 event_warn("%s: strdup failed", __func__);
2366 if (!(bev = bufferevent_socket_new(base, -1, 0))) {
2367 event_warn("%s: bufferevent_socket_new failed", __func__);
2372 bufferevent_setcb(bev, evhttp_read_cb, evhttp_write_cb, evhttp_error_cb, evcon);
2375 evcon->state = EVCON_DISCONNECTED;
2376 TAILQ_INIT(&evcon->requests);
2378 evcon->initial_retry_timeout.tv_sec = 2;
2379 evcon->initial_retry_timeout.tv_usec = 0;
2383 if (bufferevent_get_base(bev) != base)
2384 bufferevent_base_set(base, evcon->bufev);
2387 event_deferred_cb_init_(
2388 &evcon->read_more_deferred_cb,
2389 bufferevent_get_priority(bev),
2390 evhttp_deferred_read_cb, evcon);
2392 evcon->dns_base = dnsbase;
2393 evcon->ai_family = AF_UNSPEC;
2399 evhttp_connection_free(evcon);
2403 struct bufferevent* evhttp_connection_get_bufferevent(struct evhttp_connection *evcon)
2405 return evcon->bufev;
2409 evhttp_connection_get_server(struct evhttp_connection *evcon)
2411 return evcon->http_server;
2414 struct evhttp_connection *
2415 evhttp_connection_base_new(struct event_base *base, struct evdns_base *dnsbase,
2416 const char *address, ev_uint16_t port)
2418 return evhttp_connection_base_bufferevent_new(base, dnsbase, NULL, address, port);
2421 void evhttp_connection_set_family(struct evhttp_connection *evcon,
2424 evcon->ai_family = family;
2427 int evhttp_connection_set_flags(struct evhttp_connection *evcon,
2430 int avail_flags = 0;
2431 avail_flags |= EVHTTP_CON_REUSE_CONNECTED_ADDR;
2432 avail_flags |= EVHTTP_CON_READ_ON_WRITE_ERROR;
2434 if (flags & ~avail_flags || flags > EVHTTP_CON_PUBLIC_FLAGS_END)
2436 evcon->flags &= ~avail_flags;
2438 evcon->flags |= flags;
2444 evhttp_connection_set_base(struct evhttp_connection *evcon,
2445 struct event_base *base)
2447 EVUTIL_ASSERT(evcon->base == NULL);
2448 EVUTIL_ASSERT(evcon->state == EVCON_DISCONNECTED);
2450 bufferevent_base_set(base, evcon->bufev);
2454 evhttp_connection_set_timeout(struct evhttp_connection *evcon,
2455 int timeout_in_secs)
2457 if (timeout_in_secs == -1)
2458 evhttp_connection_set_timeout_tv(evcon, NULL);
2461 tv.tv_sec = timeout_in_secs;
2463 evhttp_connection_set_timeout_tv(evcon, &tv);
2468 evhttp_connection_set_timeout_tv(struct evhttp_connection *evcon,
2469 const struct timeval* tv)
2472 evcon->timeout = *tv;
2473 bufferevent_set_timeouts(evcon->bufev, &evcon->timeout, &evcon->timeout);
2475 const struct timeval read_tv = { HTTP_READ_TIMEOUT, 0 };
2476 const struct timeval write_tv = { HTTP_WRITE_TIMEOUT, 0 };
2477 evutil_timerclear(&evcon->timeout);
2478 bufferevent_set_timeouts(evcon->bufev, &read_tv, &write_tv);
2483 evhttp_connection_set_initial_retry_tv(struct evhttp_connection *evcon,
2484 const struct timeval *tv)
2487 evcon->initial_retry_timeout = *tv;
2489 evutil_timerclear(&evcon->initial_retry_timeout);
2490 evcon->initial_retry_timeout.tv_sec = 2;
2495 evhttp_connection_set_retries(struct evhttp_connection *evcon,
2498 evcon->retry_max = retry_max;
2502 evhttp_connection_set_closecb(struct evhttp_connection *evcon,
2503 void (*cb)(struct evhttp_connection *, void *), void *cbarg)
2505 evcon->closecb = cb;
2506 evcon->closecb_arg = cbarg;
2510 evhttp_connection_get_peer(struct evhttp_connection *evcon,
2511 char **address, ev_uint16_t *port)
2513 *address = evcon->address;
2514 *port = evcon->port;
2517 const struct sockaddr*
2518 evhttp_connection_get_addr(struct evhttp_connection *evcon)
2520 return bufferevent_socket_get_conn_address_(evcon->bufev);
2524 evhttp_connection_connect_(struct evhttp_connection *evcon)
2526 int old_state = evcon->state;
2527 const char *address = evcon->address;
2528 const struct sockaddr *sa = evhttp_connection_get_addr(evcon);
2531 if (evcon->state == EVCON_CONNECTING)
2534 evhttp_connection_reset_(evcon);
2536 EVUTIL_ASSERT(!(evcon->flags & EVHTTP_CON_INCOMING));
2537 evcon->flags |= EVHTTP_CON_OUTGOING;
2539 if (evcon->bind_address || evcon->bind_port) {
2540 evcon->fd = bind_socket(
2541 evcon->bind_address, evcon->bind_port, 0 /*reuse*/);
2542 if (evcon->fd == -1) {
2543 event_debug(("%s: failed to bind to \"%s\"",
2544 __func__, evcon->bind_address));
2548 bufferevent_setfd(evcon->bufev, evcon->fd);
2550 bufferevent_setfd(evcon->bufev, -1);
2553 /* Set up a callback for successful connection setup */
2554 bufferevent_setcb(evcon->bufev,
2555 NULL /* evhttp_read_cb */,
2556 NULL /* evhttp_write_cb */,
2557 evhttp_connection_cb,
2559 if (!evutil_timerisset(&evcon->timeout)) {
2560 const struct timeval conn_tv = { HTTP_CONNECT_TIMEOUT, 0 };
2561 bufferevent_set_timeouts(evcon->bufev, &conn_tv, &conn_tv);
2563 bufferevent_set_timeouts(evcon->bufev, &evcon->timeout, &evcon->timeout);
2565 /* make sure that we get a write callback */
2566 bufferevent_enable(evcon->bufev, EV_WRITE);
2568 evcon->state = EVCON_CONNECTING;
2570 if (evcon->flags & EVHTTP_CON_REUSE_CONNECTED_ADDR &&
2572 (sa->sa_family == AF_INET || sa->sa_family == AF_INET6)) {
2573 int socklen = sizeof(struct sockaddr_in);
2574 if (sa->sa_family == AF_INET6) {
2575 socklen = sizeof(struct sockaddr_in6);
2577 ret = bufferevent_socket_connect(evcon->bufev, sa, socklen);
2579 ret = bufferevent_socket_connect_hostname(evcon->bufev,
2580 evcon->dns_base, evcon->ai_family, address, evcon->port);
2584 evcon->state = old_state;
2585 event_sock_warn(evcon->fd, "%s: connection to \"%s\" failed",
2586 __func__, evcon->address);
2587 /* some operating systems return ECONNREFUSED immediately
2588 * when connecting to a local address. the cleanup is going
2589 * to reschedule this function call.
2591 evhttp_connection_cb_cleanup(evcon);
2599 * Starts an HTTP request on the provided evhttp_connection object.
2600 * If the connection object is not connected to the web server already,
2601 * this will start the connection.
2605 evhttp_make_request(struct evhttp_connection *evcon,
2606 struct evhttp_request *req,
2607 enum evhttp_cmd_type type, const char *uri)
2609 /* We are making a request */
2610 req->kind = EVHTTP_REQUEST;
2612 if (req->uri != NULL)
2614 if ((req->uri = mm_strdup(uri)) == NULL) {
2615 event_warn("%s: strdup", __func__);
2616 evhttp_request_free_auto(req);
2620 /* Set the protocol version if it is not supplied */
2621 if (!req->major && !req->minor) {
2626 EVUTIL_ASSERT(req->evcon == NULL);
2628 EVUTIL_ASSERT(!(req->flags & EVHTTP_REQ_OWN_CONNECTION));
2630 TAILQ_INSERT_TAIL(&evcon->requests, req, next);
2632 /* If the connection object is not connected; make it so */
2633 if (!evhttp_connected(evcon)) {
2634 int res = evhttp_connection_connect_(evcon);
2635 /* evhttp_connection_fail_(), which is called through
2636 * evhttp_connection_connect_(), assumes that req lies in
2637 * evcon->requests. Thus, enqueue the request in advance and
2638 * remove it in the error case. */
2640 TAILQ_REMOVE(&evcon->requests, req, next);
2646 * If it's connected already and we are the first in the queue,
2647 * then we can dispatch this request immediately. Otherwise, it
2648 * will be dispatched once the pending requests are completed.
2650 if (TAILQ_FIRST(&evcon->requests) == req)
2651 evhttp_request_dispatch(evcon);
2657 evhttp_cancel_request(struct evhttp_request *req)
2659 struct evhttp_connection *evcon = req->evcon;
2660 if (evcon != NULL) {
2661 /* We need to remove it from the connection */
2662 if (TAILQ_FIRST(&evcon->requests) == req) {
2663 /* it's currently being worked on, so reset
2666 evhttp_connection_fail_(evcon,
2667 EVREQ_HTTP_REQUEST_CANCEL);
2669 /* connection fail freed the request */
2672 /* otherwise, we can just remove it from the
2675 TAILQ_REMOVE(&evcon->requests, req, next);
2679 evhttp_request_free_auto(req);
2683 * Reads data from file descriptor into request structure
2684 * Request structure needs to be set up correctly.
2688 evhttp_start_read_(struct evhttp_connection *evcon)
2690 bufferevent_disable(evcon->bufev, EV_WRITE);
2691 bufferevent_enable(evcon->bufev, EV_READ);
2693 evcon->state = EVCON_READING_FIRSTLINE;
2694 /* Reset the bufferevent callbacks */
2695 bufferevent_setcb(evcon->bufev,
2701 /* If there's still data pending, process it next time through the
2702 * loop. Don't do it now; that could get recusive. */
2703 if (evbuffer_get_length(bufferevent_get_input(evcon->bufev))) {
2704 event_deferred_cb_schedule_(get_deferred_queue(evcon),
2705 &evcon->read_more_deferred_cb);
2710 evhttp_start_write_(struct evhttp_connection *evcon)
2712 bufferevent_disable(evcon->bufev, EV_WRITE);
2713 bufferevent_enable(evcon->bufev, EV_READ);
2715 evcon->state = EVCON_WRITING;
2716 evhttp_write_buffer(evcon, evhttp_write_connectioncb, NULL);
2720 evhttp_send_done(struct evhttp_connection *evcon, void *arg)
2723 struct evhttp_request *req = TAILQ_FIRST(&evcon->requests);
2724 TAILQ_REMOVE(&evcon->requests, req, next);
2726 if (req->on_complete_cb != NULL) {
2727 req->on_complete_cb(req, req->on_complete_cb_arg);
2731 (REQ_VERSION_BEFORE(req, 1, 1) &&
2732 !evhttp_is_connection_keepalive(req->input_headers)) ||
2733 evhttp_is_request_connection_close(req);
2735 EVUTIL_ASSERT(req->flags & EVHTTP_REQ_OWN_CONNECTION);
2736 evhttp_request_free(req);
2739 evhttp_connection_free(evcon);
2743 /* we have a persistent connection; try to accept another request. */
2744 if (evhttp_associate_new_request_with_connection(evcon) == -1) {
2745 evhttp_connection_free(evcon);
2750 * Returns an error page.
2754 evhttp_send_error(struct evhttp_request *req, int error, const char *reason)
2757 #define ERR_FORMAT "<HTML><HEAD>\n" \
2758 "<TITLE>%d %s</TITLE>\n" \
2763 struct evbuffer *buf = evbuffer_new();
2765 /* if we cannot allocate memory; we just drop the connection */
2766 evhttp_connection_free(req->evcon);
2769 if (reason == NULL) {
2770 reason = evhttp_response_phrase_internal(error);
2773 evhttp_response_code_(req, error, reason);
2775 evbuffer_add_printf(buf, ERR_FORMAT, error, reason, reason);
2777 evhttp_send_page_(req, buf);
2783 /* Requires that headers and response code are already set up */
2786 evhttp_send(struct evhttp_request *req, struct evbuffer *databuf)
2788 struct evhttp_connection *evcon = req->evcon;
2790 if (evcon == NULL) {
2791 evhttp_request_free(req);
2795 EVUTIL_ASSERT(TAILQ_FIRST(&evcon->requests) == req);
2797 /* we expect no more calls form the user on this request */
2800 /* xxx: not sure if we really should expose the data buffer this way */
2801 if (databuf != NULL)
2802 evbuffer_add_buffer(req->output_buffer, databuf);
2804 /* Adds headers to the response */
2805 evhttp_make_header(evcon, req);
2807 evhttp_write_buffer(evcon, evhttp_send_done, NULL);
2811 evhttp_send_reply(struct evhttp_request *req, int code, const char *reason,
2812 struct evbuffer *databuf)
2814 evhttp_response_code_(req, code, reason);
2816 evhttp_send(req, databuf);
2820 evhttp_send_reply_start(struct evhttp_request *req, int code,
2823 evhttp_response_code_(req, code, reason);
2825 if (req->evcon == NULL)
2828 if (evhttp_find_header(req->output_headers, "Content-Length") == NULL &&
2829 REQ_VERSION_ATLEAST(req, 1, 1) &&
2830 evhttp_response_needs_body(req)) {
2832 * prefer HTTP/1.1 chunked encoding to closing the connection;
2833 * note RFC 2616 section 4.4 forbids it with Content-Length:
2834 * and it's not necessary then anyway.
2836 evhttp_add_header(req->output_headers, "Transfer-Encoding",
2842 evhttp_make_header(req->evcon, req);
2843 evhttp_write_buffer(req->evcon, NULL, NULL);
2847 evhttp_send_reply_chunk_with_cb(struct evhttp_request *req, struct evbuffer *databuf,
2848 void (*cb)(struct evhttp_connection *, void *), void *arg)
2850 struct evhttp_connection *evcon = req->evcon;
2851 struct evbuffer *output;
2856 output = bufferevent_get_output(evcon->bufev);
2858 if (evbuffer_get_length(databuf) == 0)
2860 if (!evhttp_response_needs_body(req))
2863 evbuffer_add_printf(output, "%x\r\n",
2864 (unsigned)evbuffer_get_length(databuf));
2866 evbuffer_add_buffer(output, databuf);
2868 evbuffer_add(output, "\r\n", 2);
2870 evhttp_write_buffer(evcon, cb, arg);
2874 evhttp_send_reply_chunk(struct evhttp_request *req, struct evbuffer *databuf)
2876 evhttp_send_reply_chunk_with_cb(req, databuf, NULL, NULL);
2879 evhttp_send_reply_end(struct evhttp_request *req)
2881 struct evhttp_connection *evcon = req->evcon;
2882 struct evbuffer *output;
2884 if (evcon == NULL) {
2885 evhttp_request_free(req);
2889 output = bufferevent_get_output(evcon->bufev);
2891 /* we expect no more calls form the user on this request */
2895 evbuffer_add(output, "0\r\n\r\n", 5);
2896 evhttp_write_buffer(req->evcon, evhttp_send_done, NULL);
2898 } else if (evbuffer_get_length(output) == 0) {
2899 /* let the connection know that we are done with the request */
2900 evhttp_send_done(evcon, NULL);
2902 /* make the callback execute after all data has been written */
2903 evcon->cb = evhttp_send_done;
2904 evcon->cb_arg = NULL;
2908 static const char *informational_phrases[] = {
2909 /* 100 */ "Continue",
2910 /* 101 */ "Switching Protocols"
2913 static const char *success_phrases[] = {
2915 /* 201 */ "Created",
2916 /* 202 */ "Accepted",
2917 /* 203 */ "Non-Authoritative Information",
2918 /* 204 */ "No Content",
2919 /* 205 */ "Reset Content",
2920 /* 206 */ "Partial Content"
2923 static const char *redirection_phrases[] = {
2924 /* 300 */ "Multiple Choices",
2925 /* 301 */ "Moved Permanently",
2927 /* 303 */ "See Other",
2928 /* 304 */ "Not Modified",
2929 /* 305 */ "Use Proxy",
2930 /* 307 */ "Temporary Redirect"
2933 static const char *client_error_phrases[] = {
2934 /* 400 */ "Bad Request",
2935 /* 401 */ "Unauthorized",
2936 /* 402 */ "Payment Required",
2937 /* 403 */ "Forbidden",
2938 /* 404 */ "Not Found",
2939 /* 405 */ "Method Not Allowed",
2940 /* 406 */ "Not Acceptable",
2941 /* 407 */ "Proxy Authentication Required",
2942 /* 408 */ "Request Time-out",
2943 /* 409 */ "Conflict",
2945 /* 411 */ "Length Required",
2946 /* 412 */ "Precondition Failed",
2947 /* 413 */ "Request Entity Too Large",
2948 /* 414 */ "Request-URI Too Large",
2949 /* 415 */ "Unsupported Media Type",
2950 /* 416 */ "Requested range not satisfiable",
2951 /* 417 */ "Expectation Failed"
2954 static const char *server_error_phrases[] = {
2955 /* 500 */ "Internal Server Error",
2956 /* 501 */ "Not Implemented",
2957 /* 502 */ "Bad Gateway",
2958 /* 503 */ "Service Unavailable",
2959 /* 504 */ "Gateway Time-out",
2960 /* 505 */ "HTTP Version not supported"
2963 struct response_class {
2965 size_t num_responses;
2966 const char **responses;
2970 #define MEMBERSOF(x) (sizeof(x)/sizeof(x[0]))
2973 static const struct response_class response_classes[] = {
2974 /* 1xx */ { "Informational", MEMBERSOF(informational_phrases), informational_phrases },
2975 /* 2xx */ { "Success", MEMBERSOF(success_phrases), success_phrases },
2976 /* 3xx */ { "Redirection", MEMBERSOF(redirection_phrases), redirection_phrases },
2977 /* 4xx */ { "Client Error", MEMBERSOF(client_error_phrases), client_error_phrases },
2978 /* 5xx */ { "Server Error", MEMBERSOF(server_error_phrases), server_error_phrases }
2982 evhttp_response_phrase_internal(int code)
2984 int klass = code / 100 - 1;
2985 int subcode = code % 100;
2987 /* Unknown class - can't do any better here */
2988 if (klass < 0 || klass >= (int) MEMBERSOF(response_classes))
2989 return "Unknown Status Class";
2991 /* Unknown sub-code, return class name at least */
2992 if (subcode >= (int) response_classes[klass].num_responses)
2993 return response_classes[klass].name;
2995 return response_classes[klass].responses[subcode];
2999 evhttp_response_code_(struct evhttp_request *req, int code, const char *reason)
3001 req->kind = EVHTTP_RESPONSE;
3002 req->response_code = code;
3003 if (req->response_code_line != NULL)
3004 mm_free(req->response_code_line);
3006 reason = evhttp_response_phrase_internal(code);
3007 req->response_code_line = mm_strdup(reason);
3008 if (req->response_code_line == NULL) {
3009 event_warn("%s: strdup", __func__);
3010 /* XXX what else can we do? */
3015 evhttp_send_page_(struct evhttp_request *req, struct evbuffer *databuf)
3017 if (!req->major || !req->minor) {
3022 if (req->kind != EVHTTP_RESPONSE)
3023 evhttp_response_code_(req, 200, "OK");
3025 evhttp_clear_headers(req->output_headers);
3026 evhttp_add_header(req->output_headers, "Content-Type", "text/html");
3027 evhttp_add_header(req->output_headers, "Connection", "close");
3029 evhttp_send(req, databuf);
3032 static const char uri_chars[256] = {
3034 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3035 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3036 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0,
3037 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,
3039 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3040 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1,
3041 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3042 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0,
3044 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3045 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3046 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3047 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3049 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3050 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3051 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3052 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3055 #define CHAR_IS_UNRESERVED(c) \
3056 (uri_chars[(unsigned char)(c)])
3059 * Helper functions to encode/decode a string for inclusion in a URI.
3060 * The returned string must be freed by the caller.
3063 evhttp_uriencode(const char *uri, ev_ssize_t len, int space_as_plus)
3065 struct evbuffer *buf = evbuffer_new();
3066 const char *p, *end;
3075 if (uri + len < uri) {
3081 size_t slen = strlen(uri);
3083 if (slen >= EV_SSIZE_MAX) {
3084 /* we don't want to mix signed and unsigned */
3088 if (uri + slen < uri) {
3095 for (p = uri; p < end; p++) {
3096 if (CHAR_IS_UNRESERVED(*p)) {
3097 evbuffer_add(buf, p, 1);
3098 } else if (*p == ' ' && space_as_plus) {
3099 evbuffer_add(buf, "+", 1);
3101 evbuffer_add_printf(buf, "%%%02X", (unsigned char)(*p));
3105 evbuffer_add(buf, "", 1); /* NUL-terminator. */
3106 result = mm_malloc(evbuffer_get_length(buf));
3109 evbuffer_remove(buf, result, evbuffer_get_length(buf));
3117 evhttp_encode_uri(const char *str)
3119 return evhttp_uriencode(str, -1, 0);
3123 * @param decode_plus_ctl: if 1, we decode plus into space. If 0, we don't.
3124 * If -1, when true we transform plus to space only after we've seen
3125 * a ?. -1 is deprecated.
3126 * @return the number of bytes written to 'ret'.
3129 evhttp_decode_uri_internal(
3130 const char *uri, size_t length, char *ret, int decode_plus_ctl)
3134 int decode_plus = (decode_plus_ctl == 1) ? 1: 0;
3137 for (i = j = 0; i < length; i++) {
3140 if (decode_plus_ctl < 0)
3142 } else if (c == '+' && decode_plus) {
3144 } else if ((i + 2) < length && c == '%' &&
3145 EVUTIL_ISXDIGIT_(uri[i+1]) && EVUTIL_ISXDIGIT_(uri[i+2])) {
3150 c = (char)strtol(tmp, NULL, 16);
3162 evhttp_decode_uri(const char *uri)
3166 if ((ret = mm_malloc(strlen(uri) + 1)) == NULL) {
3167 event_warn("%s: malloc(%lu)", __func__,
3168 (unsigned long)(strlen(uri) + 1));
3172 evhttp_decode_uri_internal(uri, strlen(uri),
3173 ret, -1 /*always_decode_plus*/);
3179 evhttp_uridecode(const char *uri, int decode_plus, size_t *size_out)
3184 if ((ret = mm_malloc(strlen(uri) + 1)) == NULL) {
3185 event_warn("%s: malloc(%lu)", __func__,
3186 (unsigned long)(strlen(uri) + 1));
3190 n = evhttp_decode_uri_internal(uri, strlen(uri),
3191 ret, !!decode_plus/*always_decode_plus*/);
3194 EVUTIL_ASSERT(n >= 0);
3195 *size_out = (size_t)n;
3202 * Helper function to parse out arguments in a query.
3203 * The arguments are separated by key and value.
3207 evhttp_parse_query_impl(const char *str, struct evkeyvalq *headers,
3213 const char *query_part;
3215 struct evhttp_uri *uri=NULL;
3217 TAILQ_INIT(headers);
3220 uri = evhttp_uri_parse(str);
3223 query_part = evhttp_uri_get_query(uri);
3228 /* No arguments - we are done */
3229 if (!query_part || !strlen(query_part)) {
3234 if ((line = mm_strdup(query_part)) == NULL) {
3235 event_warn("%s: strdup", __func__);
3239 p = argument = line;
3240 while (p != NULL && *p != '\0') {
3241 char *key, *value, *decoded_value;
3242 argument = strsep(&p, "&");
3245 key = strsep(&value, "=");
3246 if (value == NULL || *key == '\0') {
3250 if ((decoded_value = mm_malloc(strlen(value) + 1)) == NULL) {
3251 event_warn("%s: mm_malloc", __func__);
3254 evhttp_decode_uri_internal(value, strlen(value),
3255 decoded_value, 1 /*always_decode_plus*/);
3256 event_debug(("Query Param: %s -> %s\n", key, decoded_value));
3257 evhttp_add_header_internal(headers, key, decoded_value);
3258 mm_free(decoded_value);
3264 evhttp_clear_headers(headers);
3269 evhttp_uri_free(uri);
3274 evhttp_parse_query(const char *uri, struct evkeyvalq *headers)
3276 return evhttp_parse_query_impl(uri, headers, 1);
3279 evhttp_parse_query_str(const char *uri, struct evkeyvalq *headers)
3281 return evhttp_parse_query_impl(uri, headers, 0);
3284 static struct evhttp_cb *
3285 evhttp_dispatch_callback(struct httpcbq *callbacks, struct evhttp_request *req)
3287 struct evhttp_cb *cb;
3292 /* Test for different URLs */
3293 path = evhttp_uri_get_path(req->uri_elems);
3294 offset = strlen(path);
3295 if ((translated = mm_malloc(offset + 1)) == NULL)
3297 evhttp_decode_uri_internal(path, offset, translated,
3298 0 /* decode_plus */);
3300 TAILQ_FOREACH(cb, callbacks, next) {
3301 if (!strcmp(cb->what, translated)) {
3302 mm_free(translated);
3307 mm_free(translated);
3313 prefix_suffix_match(const char *pattern, const char *name, int ignorecase)
3318 switch (c = *pattern++) {
3320 return *name == '\0';
3323 while (*name != '\0') {
3324 if (prefix_suffix_match(pattern, name,
3333 EVUTIL_TOLOWER_(c) != EVUTIL_TOLOWER_(*name))
3343 Search the vhost hierarchy beginning with http for a server alias
3344 matching hostname. If a match is found, and outhttp is non-null,
3345 outhttp is set to the matching http object and 1 is returned.
3349 evhttp_find_alias(struct evhttp *http, struct evhttp **outhttp,
3350 const char *hostname)
3352 struct evhttp_server_alias *alias;
3353 struct evhttp *vhost;
3355 TAILQ_FOREACH(alias, &http->aliases, next) {
3356 /* XXX Do we need to handle IP addresses? */
3357 if (!evutil_ascii_strcasecmp(alias->alias, hostname)) {
3364 /* XXX It might be good to avoid recursion here, but I don't
3365 see a way to do that w/o a list. */
3366 TAILQ_FOREACH(vhost, &http->virtualhosts, next_vhost) {
3367 if (evhttp_find_alias(vhost, outhttp, hostname))
3375 Attempts to find the best http object to handle a request for a hostname.
3376 All aliases for the root http object and vhosts are searched for an exact
3377 match. Then, the vhost hierarchy is traversed again for a matching
3380 If an alias or vhost is matched, 1 is returned, and outhttp, if non-null,
3381 is set with the best matching http object. If there are no matches, the
3382 root http object is stored in outhttp and 0 is returned.
3386 evhttp_find_vhost(struct evhttp *http, struct evhttp **outhttp,
3387 const char *hostname)
3389 struct evhttp *vhost;
3390 struct evhttp *oldhttp;
3391 int match_found = 0;
3393 if (evhttp_find_alias(http, outhttp, hostname))
3398 TAILQ_FOREACH(vhost, &http->virtualhosts, next_vhost) {
3399 if (prefix_suffix_match(vhost->vhost_pattern,
3400 hostname, 1 /* ignorecase */)) {
3406 } while (oldhttp != http);
3415 evhttp_handle_request(struct evhttp_request *req, void *arg)
3417 struct evhttp *http = arg;
3418 struct evhttp_cb *cb = NULL;
3419 const char *hostname;
3421 /* we have a new request on which the user needs to take action */
3424 bufferevent_disable(req->evcon->bufev, EV_READ);
3426 if (req->type == 0 || req->uri == NULL) {
3427 evhttp_send_error(req, req->response_code, NULL);
3431 if ((http->allowed_methods & req->type) == 0) {
3432 event_debug(("Rejecting disallowed method %x (allowed: %x)\n",
3433 (unsigned)req->type, (unsigned)http->allowed_methods));
3434 evhttp_send_error(req, HTTP_NOTIMPLEMENTED, NULL);
3438 /* handle potential virtual hosts */
3439 hostname = evhttp_request_get_host(req);
3440 if (hostname != NULL) {
3441 evhttp_find_vhost(http, &http, hostname);
3444 if ((cb = evhttp_dispatch_callback(&http->callbacks, req)) != NULL) {
3445 (*cb->cb)(req, cb->cbarg);
3449 /* Generic call back */
3451 (*http->gencb)(req, http->gencbarg);
3454 /* We need to send a 404 here */
3455 #define ERR_FORMAT "<html><head>" \
3456 "<title>404 Not Found</title>" \
3458 "<h1>Not Found</h1>" \
3459 "<p>The requested URL %s was not found on this server.</p>"\
3463 struct evbuffer *buf;
3465 if ((escaped_html = evhttp_htmlescape(req->uri)) == NULL) {
3466 evhttp_connection_free(req->evcon);
3470 if ((buf = evbuffer_new()) == NULL) {
3471 mm_free(escaped_html);
3472 evhttp_connection_free(req->evcon);
3476 evhttp_response_code_(req, HTTP_NOTFOUND, "Not Found");
3478 evbuffer_add_printf(buf, ERR_FORMAT, escaped_html);
3480 mm_free(escaped_html);
3482 evhttp_send_page_(req, buf);
3489 /* Listener callback when a connection arrives at a server. */
3491 accept_socket_cb(struct evconnlistener *listener, evutil_socket_t nfd, struct sockaddr *peer_sa, int peer_socklen, void *arg)
3493 struct evhttp *http = arg;
3495 evhttp_get_request(http, nfd, peer_sa, peer_socklen);
3499 evhttp_bind_socket(struct evhttp *http, const char *address, ev_uint16_t port)
3501 struct evhttp_bound_socket *bound =
3502 evhttp_bind_socket_with_handle(http, address, port);
3508 struct evhttp_bound_socket *
3509 evhttp_bind_socket_with_handle(struct evhttp *http, const char *address, ev_uint16_t port)
3512 struct evhttp_bound_socket *bound;
3514 if ((fd = bind_socket(address, port, 1 /*reuse*/)) == -1)
3517 if (listen(fd, 128) == -1) {
3518 event_sock_warn(fd, "%s: listen", __func__);
3519 evutil_closesocket(fd);
3523 bound = evhttp_accept_socket_with_handle(http, fd);
3525 if (bound != NULL) {
3526 event_debug(("Bound to port %d - Awaiting connections ... ",
3535 evhttp_accept_socket(struct evhttp *http, evutil_socket_t fd)
3537 struct evhttp_bound_socket *bound =
3538 evhttp_accept_socket_with_handle(http, fd);
3545 evhttp_foreach_bound_socket(struct evhttp *http,
3546 evhttp_bound_socket_foreach_fn *function,
3549 struct evhttp_bound_socket *bound;
3551 TAILQ_FOREACH(bound, &http->sockets, next)
3552 function(bound, argument);
3555 struct evhttp_bound_socket *
3556 evhttp_accept_socket_with_handle(struct evhttp *http, evutil_socket_t fd)
3558 struct evhttp_bound_socket *bound;
3559 struct evconnlistener *listener;
3561 LEV_OPT_REUSEABLE|LEV_OPT_CLOSE_ON_EXEC|LEV_OPT_CLOSE_ON_FREE;
3563 listener = evconnlistener_new(http->base, NULL, NULL,
3565 0, /* Backlog is '0' because we already said 'listen' */
3570 bound = evhttp_bind_listener(http, listener);
3572 evconnlistener_free(listener);
3578 struct evhttp_bound_socket *
3579 evhttp_bind_listener(struct evhttp *http, struct evconnlistener *listener)
3581 struct evhttp_bound_socket *bound;
3583 bound = mm_malloc(sizeof(struct evhttp_bound_socket));
3587 bound->listener = listener;
3588 TAILQ_INSERT_TAIL(&http->sockets, bound, next);
3590 evconnlistener_set_cb(listener, accept_socket_cb, http);
3595 evhttp_bound_socket_get_fd(struct evhttp_bound_socket *bound)
3597 return evconnlistener_get_fd(bound->listener);
3600 struct evconnlistener *
3601 evhttp_bound_socket_get_listener(struct evhttp_bound_socket *bound)
3603 return bound->listener;
3607 evhttp_del_accept_socket(struct evhttp *http, struct evhttp_bound_socket *bound)
3609 TAILQ_REMOVE(&http->sockets, bound, next);
3610 evconnlistener_free(bound->listener);
3614 static struct evhttp*
3615 evhttp_new_object(void)
3617 struct evhttp *http = NULL;
3619 if ((http = mm_calloc(1, sizeof(struct evhttp))) == NULL) {
3620 event_warn("%s: calloc", __func__);
3624 evutil_timerclear(&http->timeout);
3625 evhttp_set_max_headers_size(http, EV_SIZE_MAX);
3626 evhttp_set_max_body_size(http, EV_SIZE_MAX);
3627 evhttp_set_default_content_type(http, "text/html; charset=ISO-8859-1");
3628 evhttp_set_allowed_methods(http,
3635 TAILQ_INIT(&http->sockets);
3636 TAILQ_INIT(&http->callbacks);
3637 TAILQ_INIT(&http->connections);
3638 TAILQ_INIT(&http->virtualhosts);
3639 TAILQ_INIT(&http->aliases);
3645 evhttp_new(struct event_base *base)
3647 struct evhttp *http = NULL;
3649 http = evhttp_new_object();
3658 * Start a web server on the specified address and port.
3662 evhttp_start(const char *address, ev_uint16_t port)
3664 struct evhttp *http = NULL;
3666 http = evhttp_new_object();
3669 if (evhttp_bind_socket(http, address, port) == -1) {
3678 evhttp_free(struct evhttp* http)
3680 struct evhttp_cb *http_cb;
3681 struct evhttp_connection *evcon;
3682 struct evhttp_bound_socket *bound;
3683 struct evhttp* vhost;
3684 struct evhttp_server_alias *alias;
3686 /* Remove the accepting part */
3687 while ((bound = TAILQ_FIRST(&http->sockets)) != NULL) {
3688 TAILQ_REMOVE(&http->sockets, bound, next);
3690 evconnlistener_free(bound->listener);
3695 while ((evcon = TAILQ_FIRST(&http->connections)) != NULL) {
3696 /* evhttp_connection_free removes the connection */
3697 evhttp_connection_free(evcon);
3700 while ((http_cb = TAILQ_FIRST(&http->callbacks)) != NULL) {
3701 TAILQ_REMOVE(&http->callbacks, http_cb, next);
3702 mm_free(http_cb->what);
3706 while ((vhost = TAILQ_FIRST(&http->virtualhosts)) != NULL) {
3707 TAILQ_REMOVE(&http->virtualhosts, vhost, next_vhost);
3712 if (http->vhost_pattern != NULL)
3713 mm_free(http->vhost_pattern);
3715 while ((alias = TAILQ_FIRST(&http->aliases)) != NULL) {
3716 TAILQ_REMOVE(&http->aliases, alias, next);
3717 mm_free(alias->alias);
3725 evhttp_add_virtual_host(struct evhttp* http, const char *pattern,
3726 struct evhttp* vhost)
3728 /* a vhost can only be a vhost once and should not have bound sockets */
3729 if (vhost->vhost_pattern != NULL ||
3730 TAILQ_FIRST(&vhost->sockets) != NULL)
3733 vhost->vhost_pattern = mm_strdup(pattern);
3734 if (vhost->vhost_pattern == NULL)
3737 TAILQ_INSERT_TAIL(&http->virtualhosts, vhost, next_vhost);
3743 evhttp_remove_virtual_host(struct evhttp* http, struct evhttp* vhost)
3745 if (vhost->vhost_pattern == NULL)
3748 TAILQ_REMOVE(&http->virtualhosts, vhost, next_vhost);
3750 mm_free(vhost->vhost_pattern);
3751 vhost->vhost_pattern = NULL;
3757 evhttp_add_server_alias(struct evhttp *http, const char *alias)
3759 struct evhttp_server_alias *evalias;
3761 evalias = mm_calloc(1, sizeof(*evalias));
3765 evalias->alias = mm_strdup(alias);
3766 if (!evalias->alias) {
3771 TAILQ_INSERT_TAIL(&http->aliases, evalias, next);
3777 evhttp_remove_server_alias(struct evhttp *http, const char *alias)
3779 struct evhttp_server_alias *evalias;
3781 TAILQ_FOREACH(evalias, &http->aliases, next) {
3782 if (evutil_ascii_strcasecmp(evalias->alias, alias) == 0) {
3783 TAILQ_REMOVE(&http->aliases, evalias, next);
3784 mm_free(evalias->alias);
3794 evhttp_set_timeout(struct evhttp* http, int timeout_in_secs)
3796 if (timeout_in_secs == -1) {
3797 evhttp_set_timeout_tv(http, NULL);
3800 tv.tv_sec = timeout_in_secs;
3802 evhttp_set_timeout_tv(http, &tv);
3807 evhttp_set_timeout_tv(struct evhttp* http, const struct timeval* tv)
3810 http->timeout = *tv;
3812 evutil_timerclear(&http->timeout);
3816 int evhttp_set_flags(struct evhttp *http, int flags)
3818 int avail_flags = 0;
3819 avail_flags |= EVHTTP_SERVER_LINGERING_CLOSE;
3821 if (flags & ~avail_flags)
3823 http->flags &= ~avail_flags;
3825 http->flags |= flags;
3831 evhttp_set_max_headers_size(struct evhttp* http, ev_ssize_t max_headers_size)
3833 if (max_headers_size < 0)
3834 http->default_max_headers_size = EV_SIZE_MAX;
3836 http->default_max_headers_size = max_headers_size;
3840 evhttp_set_max_body_size(struct evhttp* http, ev_ssize_t max_body_size)
3842 if (max_body_size < 0)
3843 http->default_max_body_size = EV_UINT64_MAX;
3845 http->default_max_body_size = max_body_size;
3849 evhttp_set_default_content_type(struct evhttp *http,
3850 const char *content_type) {
3851 http->default_content_type = content_type;
3855 evhttp_set_allowed_methods(struct evhttp* http, ev_uint16_t methods)
3857 http->allowed_methods = methods;
3861 evhttp_set_cb(struct evhttp *http, const char *uri,
3862 void (*cb)(struct evhttp_request *, void *), void *cbarg)
3864 struct evhttp_cb *http_cb;
3866 TAILQ_FOREACH(http_cb, &http->callbacks, next) {
3867 if (strcmp(http_cb->what, uri) == 0)
3871 if ((http_cb = mm_calloc(1, sizeof(struct evhttp_cb))) == NULL) {
3872 event_warn("%s: calloc", __func__);
3876 http_cb->what = mm_strdup(uri);
3877 if (http_cb->what == NULL) {
3878 event_warn("%s: strdup", __func__);
3883 http_cb->cbarg = cbarg;
3885 TAILQ_INSERT_TAIL(&http->callbacks, http_cb, next);
3891 evhttp_del_cb(struct evhttp *http, const char *uri)
3893 struct evhttp_cb *http_cb;
3895 TAILQ_FOREACH(http_cb, &http->callbacks, next) {
3896 if (strcmp(http_cb->what, uri) == 0)
3899 if (http_cb == NULL)
3902 TAILQ_REMOVE(&http->callbacks, http_cb, next);
3903 mm_free(http_cb->what);
3910 evhttp_set_gencb(struct evhttp *http,
3911 void (*cb)(struct evhttp_request *, void *), void *cbarg)
3914 http->gencbarg = cbarg;
3918 evhttp_set_bevcb(struct evhttp *http,
3919 struct bufferevent* (*cb)(struct event_base *, void *), void *cbarg)
3922 http->bevcbarg = cbarg;
3926 * Request related functions
3929 struct evhttp_request *
3930 evhttp_request_new(void (*cb)(struct evhttp_request *, void *), void *arg)
3932 struct evhttp_request *req = NULL;
3934 /* Allocate request structure */
3935 if ((req = mm_calloc(1, sizeof(struct evhttp_request))) == NULL) {
3936 event_warn("%s: calloc", __func__);
3940 req->headers_size = 0;
3943 req->kind = EVHTTP_RESPONSE;
3944 req->input_headers = mm_calloc(1, sizeof(struct evkeyvalq));
3945 if (req->input_headers == NULL) {
3946 event_warn("%s: calloc", __func__);
3949 TAILQ_INIT(req->input_headers);
3951 req->output_headers = mm_calloc(1, sizeof(struct evkeyvalq));
3952 if (req->output_headers == NULL) {
3953 event_warn("%s: calloc", __func__);
3956 TAILQ_INIT(req->output_headers);
3958 if ((req->input_buffer = evbuffer_new()) == NULL) {
3959 event_warn("%s: evbuffer_new", __func__);
3963 if ((req->output_buffer = evbuffer_new()) == NULL) {
3964 event_warn("%s: evbuffer_new", __func__);
3975 evhttp_request_free(req);
3980 evhttp_request_free(struct evhttp_request *req)
3982 if ((req->flags & EVHTTP_REQ_DEFER_FREE) != 0) {
3983 req->flags |= EVHTTP_REQ_NEEDS_FREE;
3987 if (req->remote_host != NULL)
3988 mm_free(req->remote_host);
3989 if (req->uri != NULL)
3991 if (req->uri_elems != NULL)
3992 evhttp_uri_free(req->uri_elems);
3993 if (req->response_code_line != NULL)
3994 mm_free(req->response_code_line);
3995 if (req->host_cache != NULL)
3996 mm_free(req->host_cache);
3998 evhttp_clear_headers(req->input_headers);
3999 mm_free(req->input_headers);
4001 evhttp_clear_headers(req->output_headers);
4002 mm_free(req->output_headers);
4004 if (req->input_buffer != NULL)
4005 evbuffer_free(req->input_buffer);
4007 if (req->output_buffer != NULL)
4008 evbuffer_free(req->output_buffer);
4014 evhttp_request_own(struct evhttp_request *req)
4016 req->flags |= EVHTTP_USER_OWNED;
4020 evhttp_request_is_owned(struct evhttp_request *req)
4022 return (req->flags & EVHTTP_USER_OWNED) != 0;
4025 struct evhttp_connection *
4026 evhttp_request_get_connection(struct evhttp_request *req)
4032 evhttp_connection_get_base(struct evhttp_connection *conn)
4038 evhttp_request_set_chunked_cb(struct evhttp_request *req,
4039 void (*cb)(struct evhttp_request *, void *))
4045 evhttp_request_set_header_cb(struct evhttp_request *req,
4046 int (*cb)(struct evhttp_request *, void *))
4048 req->header_cb = cb;
4052 evhttp_request_set_error_cb(struct evhttp_request *req,
4053 void (*cb)(enum evhttp_request_error, void *))
4059 evhttp_request_set_on_complete_cb(struct evhttp_request *req,
4060 void (*cb)(struct evhttp_request *, void *), void *cb_arg)
4062 req->on_complete_cb = cb;
4063 req->on_complete_cb_arg = cb_arg;
4067 * Allows for inspection of the request URI
4071 evhttp_request_get_uri(const struct evhttp_request *req) {
4072 if (req->uri == NULL)
4073 event_debug(("%s: request %p has no uri\n", __func__, req));
4077 const struct evhttp_uri *
4078 evhttp_request_get_evhttp_uri(const struct evhttp_request *req) {
4079 if (req->uri_elems == NULL)
4080 event_debug(("%s: request %p has no uri elems\n",
4082 return (req->uri_elems);
4086 evhttp_request_get_host(struct evhttp_request *req)
4088 const char *host = NULL;
4090 if (req->host_cache)
4091 return req->host_cache;
4094 host = evhttp_uri_get_host(req->uri_elems);
4095 if (!host && req->input_headers) {
4099 host = evhttp_find_header(req->input_headers, "Host");
4100 /* The Host: header may include a port. Remove it here
4101 to be consistent with uri_elems case above. */
4103 p = host + strlen(host) - 1;
4104 while (p > host && EVUTIL_ISDIGIT_(*p))
4106 if (p > host && *p == ':') {
4108 req->host_cache = mm_malloc(len + 1);
4109 if (!req->host_cache) {
4110 event_warn("%s: malloc", __func__);
4113 memcpy(req->host_cache, host, len);
4114 req->host_cache[len] = '\0';
4115 host = req->host_cache;
4123 enum evhttp_cmd_type
4124 evhttp_request_get_command(const struct evhttp_request *req) {
4129 evhttp_request_get_response_code(const struct evhttp_request *req)
4131 return req->response_code;
4135 evhttp_request_get_response_code_line(const struct evhttp_request *req)
4137 return req->response_code_line;
4140 /** Returns the input headers */
4141 struct evkeyvalq *evhttp_request_get_input_headers(struct evhttp_request *req)
4143 return (req->input_headers);
4146 /** Returns the output headers */
4147 struct evkeyvalq *evhttp_request_get_output_headers(struct evhttp_request *req)
4149 return (req->output_headers);
4152 /** Returns the input buffer */
4153 struct evbuffer *evhttp_request_get_input_buffer(struct evhttp_request *req)
4155 return (req->input_buffer);
4158 /** Returns the output buffer */
4159 struct evbuffer *evhttp_request_get_output_buffer(struct evhttp_request *req)
4161 return (req->output_buffer);
4166 * Takes a file descriptor to read a request from.
4167 * The callback is executed once the whole request has been read.
4170 static struct evhttp_connection*
4171 evhttp_get_request_connection(
4172 struct evhttp* http,
4173 evutil_socket_t fd, struct sockaddr *sa, ev_socklen_t salen)
4175 struct evhttp_connection *evcon;
4176 char *hostname = NULL, *portname = NULL;
4177 struct bufferevent* bev = NULL;
4179 name_from_addr(sa, salen, &hostname, &portname);
4180 if (hostname == NULL || portname == NULL) {
4181 if (hostname) mm_free(hostname);
4182 if (portname) mm_free(portname);
4186 event_debug(("%s: new request from %s:%s on "EV_SOCK_FMT"\n",
4187 __func__, hostname, portname, EV_SOCK_ARG(fd)));
4189 /* we need a connection object to put the http request on */
4190 if (http->bevcb != NULL) {
4191 bev = (*http->bevcb)(http->base, http->bevcbarg);
4193 evcon = evhttp_connection_base_bufferevent_new(
4194 http->base, NULL, bev, hostname, atoi(portname));
4200 evcon->max_headers_size = http->default_max_headers_size;
4201 evcon->max_body_size = http->default_max_body_size;
4202 if (http->flags & EVHTTP_SERVER_LINGERING_CLOSE)
4203 evcon->flags |= EVHTTP_CON_LINGERING_CLOSE;
4205 evcon->flags |= EVHTTP_CON_INCOMING;
4206 evcon->state = EVCON_READING_FIRSTLINE;
4210 bufferevent_enable(evcon->bufev, EV_READ);
4211 bufferevent_disable(evcon->bufev, EV_WRITE);
4212 bufferevent_setfd(evcon->bufev, fd);
4218 evhttp_associate_new_request_with_connection(struct evhttp_connection *evcon)
4220 struct evhttp *http = evcon->http_server;
4221 struct evhttp_request *req;
4222 if ((req = evhttp_request_new(evhttp_handle_request, http)) == NULL)
4225 if ((req->remote_host = mm_strdup(evcon->address)) == NULL) {
4226 event_warn("%s: strdup", __func__);
4227 evhttp_request_free(req);
4230 req->remote_port = evcon->port;
4232 req->evcon = evcon; /* the request ends up owning the connection */
4233 req->flags |= EVHTTP_REQ_OWN_CONNECTION;
4235 /* We did not present the request to the user user yet, so treat it as
4236 * if the user was done with the request. This allows us to free the
4237 * request on a persistent connection if the client drops it without
4238 * sending a request.
4242 TAILQ_INSERT_TAIL(&evcon->requests, req, next);
4244 req->kind = EVHTTP_REQUEST;
4247 evhttp_start_read_(evcon);
4253 evhttp_get_request(struct evhttp *http, evutil_socket_t fd,
4254 struct sockaddr *sa, ev_socklen_t salen)
4256 struct evhttp_connection *evcon;
4258 evcon = evhttp_get_request_connection(http, fd, sa, salen);
4259 if (evcon == NULL) {
4260 event_sock_warn(fd, "%s: cannot get connection on "EV_SOCK_FMT,
4261 __func__, EV_SOCK_ARG(fd));
4262 evutil_closesocket(fd);
4266 /* the timeout can be used by the server to close idle connections */
4267 if (evutil_timerisset(&http->timeout))
4268 evhttp_connection_set_timeout_tv(evcon, &http->timeout);
4271 * if we want to accept more than one request on a connection,
4272 * we need to know which http server it belongs to.
4274 evcon->http_server = http;
4275 TAILQ_INSERT_TAIL(&http->connections, evcon, next);
4277 if (evhttp_associate_new_request_with_connection(evcon) == -1)
4278 evhttp_connection_free(evcon);
4283 * Network helper functions that we do not want to export to the rest of
4288 name_from_addr(struct sockaddr *sa, ev_socklen_t salen,
4289 char **phost, char **pport)
4291 char ntop[NI_MAXHOST];
4292 char strport[NI_MAXSERV];
4295 #ifdef EVENT__HAVE_GETNAMEINFO
4296 ni_result = getnameinfo(sa, salen,
4297 ntop, sizeof(ntop), strport, sizeof(strport),
4298 NI_NUMERICHOST|NI_NUMERICSERV);
4300 if (ni_result != 0) {
4302 /* Windows doesn't have an EAI_SYSTEM. */
4303 if (ni_result == EAI_SYSTEM)
4304 event_err(1, "getnameinfo failed");
4307 event_errx(1, "getnameinfo failed: %s", gai_strerror(ni_result));
4311 ni_result = fake_getnameinfo(sa, salen,
4312 ntop, sizeof(ntop), strport, sizeof(strport),
4313 NI_NUMERICHOST|NI_NUMERICSERV);
4318 *phost = mm_strdup(ntop);
4319 *pport = mm_strdup(strport);
4322 /* Create a non-blocking socket and bind it */
4323 /* todo: rename this function */
4324 static evutil_socket_t
4325 bind_socket_ai(struct evutil_addrinfo *ai, int reuse)
4332 /* Create listen socket */
4333 fd = evutil_socket_(ai ? ai->ai_family : AF_INET,
4334 SOCK_STREAM|EVUTIL_SOCK_NONBLOCK|EVUTIL_SOCK_CLOEXEC, 0);
4336 event_sock_warn(-1, "socket");
4340 if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (void *)&on, sizeof(on))<0)
4343 if (evutil_make_listen_socket_reuseable(fd) < 0)
4348 r = bind(fd, ai->ai_addr, (ev_socklen_t)ai->ai_addrlen);
4356 serrno = EVUTIL_SOCKET_ERROR();
4357 evutil_closesocket(fd);
4358 EVUTIL_SET_SOCKET_ERROR(serrno);
4362 static struct evutil_addrinfo *
4363 make_addrinfo(const char *address, ev_uint16_t port)
4365 struct evutil_addrinfo *ai = NULL;
4367 struct evutil_addrinfo hints;
4368 char strport[NI_MAXSERV];
4371 memset(&hints, 0, sizeof(hints));
4372 hints.ai_family = AF_UNSPEC;
4373 hints.ai_socktype = SOCK_STREAM;
4374 /* turn NULL hostname into INADDR_ANY, and skip looking up any address
4375 * types we don't have an interface to connect to. */
4376 hints.ai_flags = EVUTIL_AI_PASSIVE|EVUTIL_AI_ADDRCONFIG;
4377 evutil_snprintf(strport, sizeof(strport), "%d", port);
4378 if ((ai_result = evutil_getaddrinfo(address, strport, &hints, &ai))
4380 if (ai_result == EVUTIL_EAI_SYSTEM)
4381 event_warn("getaddrinfo");
4383 event_warnx("getaddrinfo: %s",
4384 evutil_gai_strerror(ai_result));
4391 static evutil_socket_t
4392 bind_socket(const char *address, ev_uint16_t port, int reuse)
4395 struct evutil_addrinfo *aitop = NULL;
4397 /* just create an unbound socket */
4398 if (address == NULL && port == 0)
4399 return bind_socket_ai(NULL, 0);
4401 aitop = make_addrinfo(address, port);
4406 fd = bind_socket_ai(aitop, reuse);
4408 evutil_freeaddrinfo(aitop);
4415 char *scheme; /* scheme; e.g http, ftp etc */
4416 char *userinfo; /* userinfo (typically username:pass), or NULL */
4417 char *host; /* hostname, IP address, or NULL */
4418 int port; /* port, or zero */
4419 char *path; /* path, or "". */
4420 char *query; /* query, or NULL */
4421 char *fragment; /* fragment or NULL */
4425 evhttp_uri_new(void)
4427 struct evhttp_uri *uri = mm_calloc(sizeof(struct evhttp_uri), 1);
4434 evhttp_uri_set_flags(struct evhttp_uri *uri, unsigned flags)
4439 /* Return true if the string starting at s and ending immediately before eos
4440 * is a valid URI scheme according to RFC3986
4443 scheme_ok(const char *s, const char *eos)
4445 /* scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." ) */
4446 EVUTIL_ASSERT(eos >= s);
4449 if (!EVUTIL_ISALPHA_(*s))
4452 if (! EVUTIL_ISALNUM_(*s) &&
4453 *s != '+' && *s != '-' && *s != '.')
4459 #define SUBDELIMS "!$&'()*+,;="
4461 /* Return true iff [s..eos) is a valid userinfo */
4463 userinfo_ok(const char *s, const char *eos)
4466 if (CHAR_IS_UNRESERVED(*s) ||
4467 strchr(SUBDELIMS, *s) ||
4470 else if (*s == '%' && s+2 < eos &&
4471 EVUTIL_ISXDIGIT_(s[1]) &&
4472 EVUTIL_ISXDIGIT_(s[2]))
4481 regname_ok(const char *s, const char *eos)
4483 while (s && s<eos) {
4484 if (CHAR_IS_UNRESERVED(*s) ||
4485 strchr(SUBDELIMS, *s))
4487 else if (*s == '%' &&
4488 EVUTIL_ISXDIGIT_(s[1]) &&
4489 EVUTIL_ISXDIGIT_(s[2]))
4498 parse_port(const char *s, const char *eos)
4502 if (! EVUTIL_ISDIGIT_(*s))
4504 portnum = (portnum * 10) + (*s - '0');
4507 if (portnum > 65535)
4514 /* returns 0 for bad, 1 for ipv6, 2 for IPvFuture */
4516 bracket_addr_ok(const char *s, const char *eos)
4518 if (s + 3 > eos || *s != '[' || *(eos-1) != ']')
4521 /* IPvFuture, or junk.
4522 "v" 1*HEXDIG "." 1*( unreserved / sub-delims / ":" )
4524 s += 2; /* skip [v */
4526 if (!EVUTIL_ISXDIGIT_(*s)) /*require at least one*/
4528 while (s < eos && *s != '.') {
4529 if (EVUTIL_ISXDIGIT_(*s))
4538 if (CHAR_IS_UNRESERVED(*s) ||
4539 strchr(SUBDELIMS, *s) ||
4549 ev_ssize_t n_chars = eos-s-2;
4550 struct in6_addr in6;
4551 if (n_chars >= 64) /* way too long */
4553 memcpy(buf, s+1, n_chars);
4555 return (evutil_inet_pton(AF_INET6,buf,&in6)==1) ? 1 : 0;
4560 parse_authority(struct evhttp_uri *uri, char *s, char *eos)
4565 uri->host = mm_strdup("");
4566 if (uri->host == NULL) {
4567 event_warn("%s: strdup", __func__);
4573 /* Optionally, we start with "userinfo@" */
4575 cp = strchr(s, '@');
4576 if (cp && cp < eos) {
4577 if (! userinfo_ok(s,cp))
4580 uri->userinfo = mm_strdup(s);
4581 if (uri->userinfo == NULL) {
4582 event_warn("%s: strdup", __func__);
4588 /* Optionally, we end with ":port" */
4589 for (port=eos-1; port >= cp && EVUTIL_ISDIGIT_(*port); --port)
4591 if (port >= cp && *port == ':') {
4592 if (port+1 == eos) /* Leave port unspecified; the RFC allows a
4595 else if ((uri->port = parse_port(port+1, eos))<0)
4599 /* Now, cp..eos holds the "host" port, which can be an IPv4Address,
4600 * an IP-Literal, or a reg-name */
4601 EVUTIL_ASSERT(eos >= cp);
4602 if (*cp == '[' && eos >= cp+2 && *(eos-1) == ']') {
4603 /* IPv6address, IP-Literal, or junk. */
4604 if (! bracket_addr_ok(cp, eos))
4607 /* Make sure the host part is ok. */
4608 if (! regname_ok(cp,eos)) /* Match IPv4Address or reg-name */
4611 uri->host = mm_malloc(eos-cp+1);
4612 if (uri->host == NULL) {
4613 event_warn("%s: malloc", __func__);
4616 memcpy(uri->host, cp, eos-cp);
4617 uri->host[eos-cp] = '\0';
4623 end_of_authority(char *cp)
4626 if (*cp == '?' || *cp == '#' || *cp == '/')
4639 /* Return the character after the longest prefix of 'cp' that matches...
4640 * *pchar / "/" if allow_qchars is false, or
4641 * *(pchar / "/" / "?") if allow_qchars is true.
4644 end_of_path(char *cp, enum uri_part part, unsigned flags)
4646 if (flags & EVHTTP_URI_NONCONFORMANT) {
4647 /* If NONCONFORMANT:
4648 * Path is everything up to a # or ? or nul.
4649 * Query is everything up a # or nul
4650 * Fragment is everything up to a nul.
4654 while (*cp && *cp != '#' && *cp != '?')
4658 while (*cp && *cp != '#')
4669 if (CHAR_IS_UNRESERVED(*cp) ||
4670 strchr(SUBDELIMS, *cp) ||
4671 *cp == ':' || *cp == '@' || *cp == '/')
4673 else if (*cp == '%' && EVUTIL_ISXDIGIT_(cp[1]) &&
4674 EVUTIL_ISXDIGIT_(cp[2]))
4676 else if (*cp == '?' && part != PART_PATH)
4685 path_matches_noscheme(const char *cp)
4690 else if (*cp == '/')
4698 evhttp_uri_parse(const char *source_uri)
4700 return evhttp_uri_parse_with_flags(source_uri, 0);
4704 evhttp_uri_parse_with_flags(const char *source_uri, unsigned flags)
4706 char *readbuf = NULL, *readp = NULL, *token = NULL, *query = NULL;
4707 char *path = NULL, *fragment = NULL;
4708 int got_authority = 0;
4710 struct evhttp_uri *uri = mm_calloc(1, sizeof(struct evhttp_uri));
4712 event_warn("%s: calloc", __func__);
4718 readbuf = mm_strdup(source_uri);
4719 if (readbuf == NULL) {
4720 event_warn("%s: strdup", __func__);
4727 /* We try to follow RFC3986 here as much as we can, and match
4730 URI = scheme ":" hier-part [ "?" query ] [ "#" fragment ]
4732 relative-ref = relative-part [ "?" query ] [ "#" fragment ]
4736 token = strchr(readp, ':');
4737 if (token && scheme_ok(readp,token)) {
4739 uri->scheme = mm_strdup(readp);
4740 if (uri->scheme == NULL) {
4741 event_warn("%s: strdup", __func__);
4744 readp = token+1; /* eat : */
4747 /* 2. Optionally, "//" then an 'authority' part. */
4748 if (readp[0]=='/' && readp[1] == '/') {
4752 path = end_of_authority(readp);
4753 if (parse_authority(uri, authority, path) < 0)
4759 /* 3. Query: path-abempty, path-absolute, path-rootless, or path-empty
4762 readp = end_of_path(path, PART_PATH, flags);
4765 if (*readp == '?') {
4769 readp = end_of_path(readp, PART_QUERY, flags);
4772 if (*readp == '#') {
4776 readp = end_of_path(readp, PART_FRAGMENT, flags);
4778 if (*readp != '\0') {
4782 /* These next two cases may be unreachable; I'm leaving them
4783 * in to be defensive. */
4784 /* If you didn't get an authority, the path can't begin with "//" */
4785 if (!got_authority && path[0]=='/' && path[1]=='/')
4787 /* If you did get an authority, the path must begin with "/" or be
4789 if (got_authority && path[0] != '/' && path[0] != '\0')
4791 /* (End of maybe-unreachable cases) */
4793 /* If there was no scheme, the first part of the path (if any) must
4794 * have no colon in it. */
4795 if (! uri->scheme && !path_matches_noscheme(path))
4798 EVUTIL_ASSERT(path);
4799 uri->path = mm_strdup(path);
4800 if (uri->path == NULL) {
4801 event_warn("%s: strdup", __func__);
4806 uri->query = mm_strdup(query);
4807 if (uri->query == NULL) {
4808 event_warn("%s: strdup", __func__);
4813 uri->fragment = mm_strdup(fragment);
4814 if (uri->fragment == NULL) {
4815 event_warn("%s: strdup", __func__);
4825 evhttp_uri_free(uri);
4832 evhttp_uri_free(struct evhttp_uri *uri)
4834 #define URI_FREE_STR_(f) \
4839 URI_FREE_STR_(scheme);
4840 URI_FREE_STR_(userinfo);
4841 URI_FREE_STR_(host);
4842 URI_FREE_STR_(path);
4843 URI_FREE_STR_(query);
4844 URI_FREE_STR_(fragment);
4847 #undef URI_FREE_STR_
4851 evhttp_uri_join(struct evhttp_uri *uri, char *buf, size_t limit)
4853 struct evbuffer *tmp = 0;
4854 size_t joined_size = 0;
4855 char *output = NULL;
4857 #define URI_ADD_(f) evbuffer_add(tmp, uri->f, strlen(uri->f))
4859 if (!uri || !buf || !limit)
4862 tmp = evbuffer_new();
4868 evbuffer_add(tmp, ":", 1);
4871 evbuffer_add(tmp, "//", 2);
4873 evbuffer_add_printf(tmp,"%s@", uri->userinfo);
4876 evbuffer_add_printf(tmp,":%d", uri->port);
4878 if (uri->path && uri->path[0] != '/' && uri->path[0] != '\0')
4886 evbuffer_add(tmp, "?", 1);
4890 if (uri->fragment) {
4891 evbuffer_add(tmp, "#", 1);
4895 evbuffer_add(tmp, "\0", 1); /* NUL */
4897 joined_size = evbuffer_get_length(tmp);
4899 if (joined_size > limit) {
4900 /* It doesn't fit. */
4904 evbuffer_remove(tmp, buf, joined_size);
4915 evhttp_uri_get_scheme(const struct evhttp_uri *uri)
4920 evhttp_uri_get_userinfo(const struct evhttp_uri *uri)
4922 return uri->userinfo;
4925 evhttp_uri_get_host(const struct evhttp_uri *uri)
4930 evhttp_uri_get_port(const struct evhttp_uri *uri)
4935 evhttp_uri_get_path(const struct evhttp_uri *uri)
4940 evhttp_uri_get_query(const struct evhttp_uri *uri)
4945 evhttp_uri_get_fragment(const struct evhttp_uri *uri)
4947 return uri->fragment;
4950 #define URI_SET_STR_(f) do { \
4954 if ((uri->f = mm_strdup(f)) == NULL) { \
4955 event_warn("%s: strdup()", __func__); \
4964 evhttp_uri_set_scheme(struct evhttp_uri *uri, const char *scheme)
4966 if (scheme && !scheme_ok(scheme, scheme+strlen(scheme)))
4969 URI_SET_STR_(scheme);
4973 evhttp_uri_set_userinfo(struct evhttp_uri *uri, const char *userinfo)
4975 if (userinfo && !userinfo_ok(userinfo, userinfo+strlen(userinfo)))
4977 URI_SET_STR_(userinfo);
4981 evhttp_uri_set_host(struct evhttp_uri *uri, const char *host)
4984 if (host[0] == '[') {
4985 if (! bracket_addr_ok(host, host+strlen(host)))
4988 if (! regname_ok(host, host+strlen(host)))
4997 evhttp_uri_set_port(struct evhttp_uri *uri, int port)
5004 #define end_of_cpath(cp,p,f) \
5005 ((const char*)(end_of_path(((char*)(cp)), (p), (f))))
5008 evhttp_uri_set_path(struct evhttp_uri *uri, const char *path)
5010 if (path && end_of_cpath(path, PART_PATH, uri->flags) != path+strlen(path))
5017 evhttp_uri_set_query(struct evhttp_uri *uri, const char *query)
5019 if (query && end_of_cpath(query, PART_QUERY, uri->flags) != query+strlen(query))
5021 URI_SET_STR_(query);
5025 evhttp_uri_set_fragment(struct evhttp_uri *uri, const char *fragment)
5027 if (fragment && end_of_cpath(fragment, PART_FRAGMENT, uri->flags) != fragment+strlen(fragment))
5029 URI_SET_STR_(fragment);