Fixed issue with cmake version generation
[libevent.git] / http.c
blob7d7ff07cf26ce8776f4b0fd6a86718423128a109
1 /*
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
7 * are met:
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>
33 #endif
34 #ifdef EVENT__HAVE_SYS_TYPES_H
35 #include <sys/types.h>
36 #endif
38 #ifdef HAVE_SYS_IOCCOM_H
39 #include <sys/ioccom.h>
40 #endif
41 #ifdef EVENT__HAVE_SYS_RESOURCE_H
42 #include <sys/resource.h>
43 #endif
44 #ifdef EVENT__HAVE_SYS_TIME_H
45 #include <sys/time.h>
46 #endif
47 #ifdef EVENT__HAVE_SYS_WAIT_H
48 #include <sys/wait.h>
49 #endif
51 #ifndef _WIN32
52 #include <sys/socket.h>
53 #include <sys/stat.h>
54 #else
55 #include <winsock2.h>
56 #include <ws2tcpip.h>
57 #endif
59 #include <sys/queue.h>
61 #ifdef EVENT__HAVE_NETINET_IN_H
62 #include <netinet/in.h>
63 #endif
64 #ifdef EVENT__HAVE_ARPA_INET_H
65 #include <arpa/inet.h>
66 #endif
67 #ifdef EVENT__HAVE_NETDB_H
68 #include <netdb.h>
69 #endif
71 #ifdef _WIN32
72 #include <winsock2.h>
73 #endif
75 #include <errno.h>
76 #include <stdio.h>
77 #include <stdlib.h>
78 #include <string.h>
79 #ifndef _WIN32
80 #include <syslog.h>
81 #endif
82 #include <signal.h>
83 #include <time.h>
84 #ifdef EVENT__HAVE_UNISTD_H
85 #include <unistd.h>
86 #endif
87 #ifdef EVENT__HAVE_FCNTL_H
88 #include <fcntl.h>
89 #endif
91 #undef timeout_pending
92 #undef timeout_initialized
94 #include "strlcpy-internal.h"
95 #include "event2/http.h"
96 #include "event2/event.h"
97 #include "event2/buffer.h"
98 #include "event2/bufferevent.h"
99 #include "event2/http_struct.h"
100 #include "event2/http_compat.h"
101 #include "event2/util.h"
102 #include "event2/listener.h"
103 #include "log-internal.h"
104 #include "util-internal.h"
105 #include "http-internal.h"
106 #include "mm-internal.h"
107 #include "bufferevent-internal.h"
109 #ifndef EVENT__HAVE_GETNAMEINFO
110 #define NI_MAXSERV 32
111 #define NI_MAXHOST 1025
113 #ifndef NI_NUMERICHOST
114 #define NI_NUMERICHOST 1
115 #endif
117 #ifndef NI_NUMERICSERV
118 #define NI_NUMERICSERV 2
119 #endif
121 static int
122 fake_getnameinfo(const struct sockaddr *sa, size_t salen, char *host,
123 size_t hostlen, char *serv, size_t servlen, int flags)
125 struct sockaddr_in *sin = (struct sockaddr_in *)sa;
127 if (serv != NULL) {
128 char tmpserv[16];
129 evutil_snprintf(tmpserv, sizeof(tmpserv),
130 "%d", ntohs(sin->sin_port));
131 if (strlcpy(serv, tmpserv, servlen) >= servlen)
132 return (-1);
135 if (host != NULL) {
136 if (flags & NI_NUMERICHOST) {
137 if (strlcpy(host, inet_ntoa(sin->sin_addr),
138 hostlen) >= hostlen)
139 return (-1);
140 else
141 return (0);
142 } else {
143 struct hostent *hp;
144 hp = gethostbyaddr((char *)&sin->sin_addr,
145 sizeof(struct in_addr), AF_INET);
146 if (hp == NULL)
147 return (-2);
149 if (strlcpy(host, hp->h_name, hostlen) >= hostlen)
150 return (-1);
151 else
152 return (0);
155 return (0);
158 #endif
160 #define REQ_VERSION_BEFORE(req, major_v, minor_v) \
161 ((req)->major < (major_v) || \
162 ((req)->major == (major_v) && (req)->minor < (minor_v)))
164 #define REQ_VERSION_ATLEAST(req, major_v, minor_v) \
165 ((req)->major > (major_v) || \
166 ((req)->major == (major_v) && (req)->minor >= (minor_v)))
168 #ifndef MIN
169 #define MIN(a,b) (((a)<(b))?(a):(b))
170 #endif
172 extern int debug;
174 static evutil_socket_t bind_socket_ai(struct evutil_addrinfo *, int reuse);
175 static evutil_socket_t bind_socket(const char *, ev_uint16_t, int reuse);
176 static void name_from_addr(struct sockaddr *, ev_socklen_t, char **, char **);
177 static int evhttp_associate_new_request_with_connection(
178 struct evhttp_connection *evcon);
179 static void evhttp_connection_start_detectclose(
180 struct evhttp_connection *evcon);
181 static void evhttp_connection_stop_detectclose(
182 struct evhttp_connection *evcon);
183 static void evhttp_request_dispatch(struct evhttp_connection* evcon);
184 static void evhttp_read_firstline(struct evhttp_connection *evcon,
185 struct evhttp_request *req);
186 static void evhttp_read_header(struct evhttp_connection *evcon,
187 struct evhttp_request *req);
188 static int evhttp_add_header_internal(struct evkeyvalq *headers,
189 const char *key, const char *value);
190 static const char *evhttp_response_phrase_internal(int code);
191 static void evhttp_get_request(struct evhttp *, evutil_socket_t, struct sockaddr *, ev_socklen_t);
192 static void evhttp_write_buffer(struct evhttp_connection *,
193 void (*)(struct evhttp_connection *, void *), void *);
194 static void evhttp_make_header(struct evhttp_connection *, struct evhttp_request *);
196 /* callbacks for bufferevent */
197 static void evhttp_read_cb(struct bufferevent *, void *);
198 static void evhttp_write_cb(struct bufferevent *, void *);
199 static void evhttp_error_cb(struct bufferevent *bufev, short what, void *arg);
200 static int evhttp_find_vhost(struct evhttp *http, struct evhttp **outhttp,
201 const char *hostname);
203 #ifndef EVENT__HAVE_STRSEP
204 /* strsep replacement for platforms that lack it. Only works if
205 * del is one character long. */
206 static char *
207 strsep(char **s, const char *del)
209 char *d, *tok;
210 EVUTIL_ASSERT(strlen(del) == 1);
211 if (!s || !*s)
212 return NULL;
213 tok = *s;
214 d = strstr(tok, del);
215 if (d) {
216 *d = '\0';
217 *s = d + 1;
218 } else
219 *s = NULL;
220 return tok;
222 #endif
224 static size_t
225 html_replace(const char ch, const char **escaped)
227 switch (ch) {
228 case '<':
229 *escaped = "&lt;";
230 return 4;
231 case '>':
232 *escaped = "&gt;";
233 return 4;
234 case '"':
235 *escaped = "&quot;";
236 return 6;
237 case '\'':
238 *escaped = "&#039;";
239 return 6;
240 case '&':
241 *escaped = "&amp;";
242 return 5;
243 default:
244 break;
247 return 1;
251 * Replaces <, >, ", ' and & with &lt;, &gt;, &quot;,
252 * &#039; and &amp; correspondingly.
254 * The returned string needs to be freed by the caller.
257 char *
258 evhttp_htmlescape(const char *html)
260 size_t i;
261 size_t new_size = 0, old_size = 0;
262 char *escaped_html, *p;
264 if (html == NULL)
265 return (NULL);
267 old_size = strlen(html);
268 for (i = 0; i < old_size; ++i) {
269 const char *replaced = NULL;
270 const size_t replace_size = html_replace(html[i], &replaced);
271 if (replace_size > EV_SIZE_MAX - new_size) {
272 event_warn("%s: html_replace overflow", __func__);
273 return (NULL);
275 new_size += replace_size;
278 if (new_size == EV_SIZE_MAX)
279 return (NULL);
280 p = escaped_html = mm_malloc(new_size + 1);
281 if (escaped_html == NULL) {
282 event_warn("%s: malloc(%lu)", __func__,
283 (unsigned long)(new_size + 1));
284 return (NULL);
286 for (i = 0; i < old_size; ++i) {
287 const char *replaced = &html[i];
288 const size_t len = html_replace(html[i], &replaced);
289 memcpy(p, replaced, len);
290 p += len;
293 *p = '\0';
295 return (escaped_html);
298 /** Given an evhttp_cmd_type, returns a constant string containing the
299 * equivalent HTTP command, or NULL if the evhttp_command_type is
300 * unrecognized. */
301 static const char *
302 evhttp_method(enum evhttp_cmd_type type)
304 const char *method;
306 switch (type) {
307 case EVHTTP_REQ_GET:
308 method = "GET";
309 break;
310 case EVHTTP_REQ_POST:
311 method = "POST";
312 break;
313 case EVHTTP_REQ_HEAD:
314 method = "HEAD";
315 break;
316 case EVHTTP_REQ_PUT:
317 method = "PUT";
318 break;
319 case EVHTTP_REQ_DELETE:
320 method = "DELETE";
321 break;
322 case EVHTTP_REQ_OPTIONS:
323 method = "OPTIONS";
324 break;
325 case EVHTTP_REQ_TRACE:
326 method = "TRACE";
327 break;
328 case EVHTTP_REQ_CONNECT:
329 method = "CONNECT";
330 break;
331 case EVHTTP_REQ_PATCH:
332 method = "PATCH";
333 break;
334 default:
335 method = NULL;
336 break;
339 return (method);
343 * Determines if a response should have a body.
344 * Follows the rules in RFC 2616 section 4.3.
345 * @return 1 if the response MUST have a body; 0 if the response MUST NOT have
346 * a body.
348 static int
349 evhttp_response_needs_body(struct evhttp_request *req)
351 return (req->response_code != HTTP_NOCONTENT &&
352 req->response_code != HTTP_NOTMODIFIED &&
353 (req->response_code < 100 || req->response_code >= 200) &&
354 req->type != EVHTTP_REQ_HEAD);
357 /** Helper: called after we've added some data to an evcon's bufferevent's
358 * output buffer. Sets the evconn's writing-is-done callback, and puts
359 * the bufferevent into writing mode.
361 static void
362 evhttp_write_buffer(struct evhttp_connection *evcon,
363 void (*cb)(struct evhttp_connection *, void *), void *arg)
365 event_debug(("%s: preparing to write buffer\n", __func__));
367 /* Set call back */
368 evcon->cb = cb;
369 evcon->cb_arg = arg;
371 /* Disable the read callback: we don't actually care about data;
372 * we only care about close detection. (We don't disable reading,
373 * since we *do* want to learn about any close events.) */
374 bufferevent_setcb(evcon->bufev,
375 NULL, /*read*/
376 evhttp_write_cb,
377 evhttp_error_cb,
378 evcon);
380 bufferevent_enable(evcon->bufev, EV_WRITE);
383 static void
384 evhttp_send_continue_done(struct evhttp_connection *evcon, void *arg)
386 bufferevent_disable(evcon->bufev, EV_WRITE);
389 static void
390 evhttp_send_continue(struct evhttp_connection *evcon,
391 struct evhttp_request *req)
393 bufferevent_enable(evcon->bufev, EV_WRITE);
394 evbuffer_add_printf(bufferevent_get_output(evcon->bufev),
395 "HTTP/%d.%d 100 Continue\r\n\r\n",
396 req->major, req->minor);
397 evcon->cb = evhttp_send_continue_done;
398 evcon->cb_arg = NULL;
399 bufferevent_setcb(evcon->bufev,
400 evhttp_read_cb,
401 evhttp_write_cb,
402 evhttp_error_cb,
403 evcon);
406 /** Helper: returns true iff evconn is in any connected state. */
407 static int
408 evhttp_connected(struct evhttp_connection *evcon)
410 switch (evcon->state) {
411 case EVCON_DISCONNECTED:
412 case EVCON_CONNECTING:
413 return (0);
414 case EVCON_IDLE:
415 case EVCON_READING_FIRSTLINE:
416 case EVCON_READING_HEADERS:
417 case EVCON_READING_BODY:
418 case EVCON_READING_TRAILER:
419 case EVCON_WRITING:
420 default:
421 return (1);
425 /* Create the headers needed for an outgoing HTTP request, adds them to
426 * the request's header list, and writes the request line to the
427 * connection's output buffer.
429 static void
430 evhttp_make_header_request(struct evhttp_connection *evcon,
431 struct evhttp_request *req)
433 const char *method;
435 evhttp_remove_header(req->output_headers, "Proxy-Connection");
437 /* Generate request line */
438 method = evhttp_method(req->type);
439 evbuffer_add_printf(bufferevent_get_output(evcon->bufev),
440 "%s %s HTTP/%d.%d\r\n",
441 method, req->uri, req->major, req->minor);
443 /* Add the content length on a post or put request if missing */
444 if ((req->type == EVHTTP_REQ_POST || req->type == EVHTTP_REQ_PUT) &&
445 evhttp_find_header(req->output_headers, "Content-Length") == NULL){
446 char size[22];
447 evutil_snprintf(size, sizeof(size), EV_SIZE_FMT,
448 EV_SIZE_ARG(evbuffer_get_length(req->output_buffer)));
449 evhttp_add_header(req->output_headers, "Content-Length", size);
453 /** Return true if the list of headers in 'headers', intepreted with respect
454 * to flags, means that we should send a "connection: close" when the request
455 * is done. */
456 static int
457 evhttp_is_connection_close(int flags, struct evkeyvalq* headers)
459 if (flags & EVHTTP_PROXY_REQUEST) {
460 /* proxy connection */
461 const char *connection = evhttp_find_header(headers, "Proxy-Connection");
462 return (connection == NULL || evutil_ascii_strcasecmp(connection, "keep-alive") != 0);
463 } else {
464 const char *connection = evhttp_find_header(headers, "Connection");
465 return (connection != NULL && evutil_ascii_strcasecmp(connection, "close") == 0);
468 static int
469 evhttp_is_request_connection_close(struct evhttp_request *req)
471 return
472 evhttp_is_connection_close(req->flags, req->input_headers) ||
473 evhttp_is_connection_close(req->flags, req->output_headers);
476 /* Return true iff 'headers' contains 'Connection: keep-alive' */
477 static int
478 evhttp_is_connection_keepalive(struct evkeyvalq* headers)
480 const char *connection = evhttp_find_header(headers, "Connection");
481 return (connection != NULL
482 && evutil_ascii_strncasecmp(connection, "keep-alive", 10) == 0);
485 /* Add a correct "Date" header to headers, unless it already has one. */
486 static void
487 evhttp_maybe_add_date_header(struct evkeyvalq *headers)
489 if (evhttp_find_header(headers, "Date") == NULL) {
490 char date[50];
491 #ifndef _WIN32
492 struct tm cur;
493 #endif
494 struct tm *cur_p;
495 time_t t = time(NULL);
496 #ifdef _WIN32
497 cur_p = gmtime(&t);
498 #else
499 gmtime_r(&t, &cur);
500 cur_p = &cur;
501 #endif
502 if (strftime(date, sizeof(date),
503 "%a, %d %b %Y %H:%M:%S GMT", cur_p) != 0) {
504 evhttp_add_header(headers, "Date", date);
509 /* Add a "Content-Length" header with value 'content_length' to headers,
510 * unless it already has a content-length or transfer-encoding header. */
511 static void
512 evhttp_maybe_add_content_length_header(struct evkeyvalq *headers,
513 size_t content_length)
515 if (evhttp_find_header(headers, "Transfer-Encoding") == NULL &&
516 evhttp_find_header(headers, "Content-Length") == NULL) {
517 char len[22];
518 evutil_snprintf(len, sizeof(len), EV_SIZE_FMT,
519 EV_SIZE_ARG(content_length));
520 evhttp_add_header(headers, "Content-Length", len);
525 * Create the headers needed for an HTTP reply in req->output_headers,
526 * and write the first HTTP response for req line to evcon.
528 static void
529 evhttp_make_header_response(struct evhttp_connection *evcon,
530 struct evhttp_request *req)
532 int is_keepalive = evhttp_is_connection_keepalive(req->input_headers);
533 evbuffer_add_printf(bufferevent_get_output(evcon->bufev),
534 "HTTP/%d.%d %d %s\r\n",
535 req->major, req->minor, req->response_code,
536 req->response_code_line);
538 if (req->major == 1) {
539 if (req->minor >= 1)
540 evhttp_maybe_add_date_header(req->output_headers);
543 * if the protocol is 1.0; and the connection was keep-alive
544 * we need to add a keep-alive header, too.
546 if (req->minor == 0 && is_keepalive)
547 evhttp_add_header(req->output_headers,
548 "Connection", "keep-alive");
550 if ((req->minor >= 1 || is_keepalive) &&
551 evhttp_response_needs_body(req)) {
553 * we need to add the content length if the
554 * user did not give it, this is required for
555 * persistent connections to work.
557 evhttp_maybe_add_content_length_header(
558 req->output_headers,
559 evbuffer_get_length(req->output_buffer));
563 /* Potentially add headers for unidentified content. */
564 if (evhttp_response_needs_body(req)) {
565 if (evhttp_find_header(req->output_headers,
566 "Content-Type") == NULL
567 && evcon->http_server->default_content_type) {
568 evhttp_add_header(req->output_headers,
569 "Content-Type",
570 evcon->http_server->default_content_type);
574 /* if the request asked for a close, we send a close, too */
575 if (evhttp_is_connection_close(req->flags, req->input_headers)) {
576 evhttp_remove_header(req->output_headers, "Connection");
577 if (!(req->flags & EVHTTP_PROXY_REQUEST))
578 evhttp_add_header(req->output_headers, "Connection", "close");
579 evhttp_remove_header(req->output_headers, "Proxy-Connection");
583 /** Generate all headers appropriate for sending the http request in req (or
584 * the response, if we're sending a response), and write them to evcon's
585 * bufferevent. Also writes all data from req->output_buffer */
586 static void
587 evhttp_make_header(struct evhttp_connection *evcon, struct evhttp_request *req)
589 struct evkeyval *header;
590 struct evbuffer *output = bufferevent_get_output(evcon->bufev);
593 * Depending if this is a HTTP request or response, we might need to
594 * add some new headers or remove existing headers.
596 if (req->kind == EVHTTP_REQUEST) {
597 evhttp_make_header_request(evcon, req);
598 } else {
599 evhttp_make_header_response(evcon, req);
602 TAILQ_FOREACH(header, req->output_headers, next) {
603 evbuffer_add_printf(output, "%s: %s\r\n",
604 header->key, header->value);
606 evbuffer_add(output, "\r\n", 2);
608 if (evbuffer_get_length(req->output_buffer) > 0) {
610 * For a request, we add the POST data, for a reply, this
611 * is the regular data.
613 /* XXX We might want to support waiting (a limited amount of
614 time) for a continue status line from the server before
615 sending POST/PUT message bodies. */
616 evbuffer_add_buffer(output, req->output_buffer);
620 void
621 evhttp_connection_set_max_headers_size(struct evhttp_connection *evcon,
622 ev_ssize_t new_max_headers_size)
624 if (new_max_headers_size<0)
625 evcon->max_headers_size = EV_SIZE_MAX;
626 else
627 evcon->max_headers_size = new_max_headers_size;
629 void
630 evhttp_connection_set_max_body_size(struct evhttp_connection* evcon,
631 ev_ssize_t new_max_body_size)
633 if (new_max_body_size<0)
634 evcon->max_body_size = EV_UINT64_MAX;
635 else
636 evcon->max_body_size = new_max_body_size;
639 static int
640 evhttp_connection_incoming_fail(struct evhttp_request *req,
641 enum evhttp_request_error error)
643 switch (error) {
644 case EVREQ_HTTP_TIMEOUT:
645 case EVREQ_HTTP_EOF:
647 * these are cases in which we probably should just
648 * close the connection and not send a reply. this
649 * case may happen when a browser keeps a persistent
650 * connection open and we timeout on the read. when
651 * the request is still being used for sending, we
652 * need to disassociated it from the connection here.
654 if (!req->userdone) {
655 /* remove it so that it will not be freed */
656 TAILQ_REMOVE(&req->evcon->requests, req, next);
657 /* indicate that this request no longer has a
658 * connection object
660 req->evcon = NULL;
662 return (-1);
663 case EVREQ_HTTP_INVALID_HEADER:
664 case EVREQ_HTTP_BUFFER_ERROR:
665 case EVREQ_HTTP_REQUEST_CANCEL:
666 case EVREQ_HTTP_DATA_TOO_LONG:
667 default: /* xxx: probably should just error on default */
668 /* the callback looks at the uri to determine errors */
669 if (req->uri) {
670 mm_free(req->uri);
671 req->uri = NULL;
673 if (req->uri_elems) {
674 evhttp_uri_free(req->uri_elems);
675 req->uri_elems = NULL;
679 * the callback needs to send a reply, once the reply has
680 * been send, the connection should get freed.
682 (*req->cb)(req, req->cb_arg);
685 return (0);
688 /* Free connection ownership of which can be acquired by user using
689 * evhttp_request_own(). */
690 static inline void
691 evhttp_request_free_auto(struct evhttp_request *req)
693 if (!(req->flags & EVHTTP_USER_OWNED)) {
694 evhttp_request_free(req);
698 static void
699 evhttp_request_free_(struct evhttp_connection *evcon, struct evhttp_request *req)
701 TAILQ_REMOVE(&evcon->requests, req, next);
702 evhttp_request_free_auto(req);
705 /* Called when evcon has experienced a (non-recoverable? -NM) error, as
706 * given in error. If it's an outgoing connection, reset the connection,
707 * retry any pending requests, and inform the user. If it's incoming,
708 * delegates to evhttp_connection_incoming_fail(). */
709 void
710 evhttp_connection_fail_(struct evhttp_connection *evcon,
711 enum evhttp_request_error error)
713 const int errsave = EVUTIL_SOCKET_ERROR();
714 struct evhttp_request* req = TAILQ_FIRST(&evcon->requests);
715 void (*cb)(struct evhttp_request *, void *);
716 void *cb_arg;
717 void (*error_cb)(enum evhttp_request_error, void *);
718 void *error_cb_arg;
719 EVUTIL_ASSERT(req != NULL);
721 bufferevent_disable(evcon->bufev, EV_READ|EV_WRITE);
723 if (evcon->flags & EVHTTP_CON_INCOMING) {
725 * for incoming requests, there are two different
726 * failure cases. it's either a network level error
727 * or an http layer error. for problems on the network
728 * layer like timeouts we just drop the connections.
729 * For HTTP problems, we might have to send back a
730 * reply before the connection can be freed.
732 if (evhttp_connection_incoming_fail(req, error) == -1)
733 evhttp_connection_free(evcon);
734 return;
737 error_cb = req->error_cb;
738 error_cb_arg = req->cb_arg;
739 /* when the request was canceled, the callback is not executed */
740 if (error != EVREQ_HTTP_REQUEST_CANCEL) {
741 /* save the callback for later; the cb might free our object */
742 cb = req->cb;
743 cb_arg = req->cb_arg;
744 } else {
745 cb = NULL;
746 cb_arg = NULL;
749 /* do not fail all requests; the next request is going to get
750 * send over a new connection. when a user cancels a request,
751 * all other pending requests should be processed as normal
753 evhttp_request_free_(evcon, req);
755 /* reset the connection */
756 evhttp_connection_reset_(evcon);
758 /* We are trying the next request that was queued on us */
759 if (TAILQ_FIRST(&evcon->requests) != NULL)
760 evhttp_connection_connect_(evcon);
762 /* The call to evhttp_connection_reset_ overwrote errno.
763 * Let's restore the original errno, so that the user's
764 * callback can have a better idea of what the error was.
766 EVUTIL_SET_SOCKET_ERROR(errsave);
768 /* inform the user */
769 if (error_cb != NULL)
770 error_cb(error, error_cb_arg);
771 if (cb != NULL)
772 (*cb)(NULL, cb_arg);
775 /* Bufferevent callback: invoked when any data has been written from an
776 * http connection's bufferevent */
777 static void
778 evhttp_write_cb(struct bufferevent *bufev, void *arg)
780 struct evhttp_connection *evcon = arg;
782 /* Activate our call back */
783 if (evcon->cb != NULL)
784 (*evcon->cb)(evcon, evcon->cb_arg);
788 * Advance the connection state.
789 * - If this is an outgoing connection, we've just processed the response;
790 * idle or close the connection.
791 * - If this is an incoming connection, we've just processed the request;
792 * respond.
794 static void
795 evhttp_connection_done(struct evhttp_connection *evcon)
797 struct evhttp_request *req = TAILQ_FIRST(&evcon->requests);
798 int con_outgoing = evcon->flags & EVHTTP_CON_OUTGOING;
799 int free_evcon = 0;
801 if (con_outgoing) {
802 /* idle or close the connection */
803 int need_close = evhttp_is_request_connection_close(req);
804 TAILQ_REMOVE(&evcon->requests, req, next);
805 req->evcon = NULL;
807 evcon->state = EVCON_IDLE;
809 /* check if we got asked to close the connection */
810 if (need_close)
811 evhttp_connection_reset_(evcon);
813 if (TAILQ_FIRST(&evcon->requests) != NULL) {
815 * We have more requests; reset the connection
816 * and deal with the next request.
818 if (!evhttp_connected(evcon))
819 evhttp_connection_connect_(evcon);
820 else
821 evhttp_request_dispatch(evcon);
822 } else if (!need_close) {
824 * The connection is going to be persistent, but we
825 * need to detect if the other side closes it.
827 evhttp_connection_start_detectclose(evcon);
828 } else if ((evcon->flags & EVHTTP_CON_AUTOFREE)) {
830 * If we have no more requests that need completion
831 * and we're not waiting for the connection to close
833 free_evcon = 1;
835 } else {
837 * incoming connection - we need to leave the request on the
838 * connection so that we can reply to it.
840 evcon->state = EVCON_WRITING;
843 /* notify the user of the request */
844 (*req->cb)(req, req->cb_arg);
846 /* if this was an outgoing request, we own and it's done. so free it. */
847 if (con_outgoing) {
848 evhttp_request_free_auto(req);
851 /* If this was the last request of an outgoing connection and we're
852 * not waiting to receive a connection close event and we want to
853 * automatically free the connection. We check to ensure our request
854 * list is empty one last time just in case our callback added a
855 * new request.
857 if (free_evcon && TAILQ_FIRST(&evcon->requests) == NULL) {
858 evhttp_connection_free(evcon);
863 * Handles reading from a chunked request.
864 * return ALL_DATA_READ:
865 * all data has been read
866 * return MORE_DATA_EXPECTED:
867 * more data is expected
868 * return DATA_CORRUPTED:
869 * data is corrupted
870 * return REQUEST_CANCELED:
871 * request was canceled by the user calling evhttp_cancel_request
872 * return DATA_TOO_LONG:
873 * ran over the maximum limit
876 static enum message_read_status
877 evhttp_handle_chunked_read(struct evhttp_request *req, struct evbuffer *buf)
879 if (req == NULL || buf == NULL) {
880 return DATA_CORRUPTED;
883 while (1) {
884 size_t buflen;
886 if ((buflen = evbuffer_get_length(buf)) == 0) {
887 break;
890 /* evbuffer_get_length returns size_t, but len variable is ssize_t,
891 * check for overflow conditions */
892 if (buflen > EV_SSIZE_MAX) {
893 return DATA_CORRUPTED;
896 if (req->ntoread < 0) {
897 /* Read chunk size */
898 ev_int64_t ntoread;
899 char *p = evbuffer_readln(buf, NULL, EVBUFFER_EOL_CRLF);
900 char *endp;
901 int error;
902 if (p == NULL)
903 break;
904 /* the last chunk is on a new line? */
905 if (strlen(p) == 0) {
906 mm_free(p);
907 continue;
909 ntoread = evutil_strtoll(p, &endp, 16);
910 error = (*p == '\0' ||
911 (*endp != '\0' && *endp != ' ') ||
912 ntoread < 0);
913 mm_free(p);
914 if (error) {
915 /* could not get chunk size */
916 return (DATA_CORRUPTED);
919 /* ntoread is signed int64, body_size is unsigned size_t, check for under/overflow conditions */
920 if ((ev_uint64_t)ntoread > EV_SIZE_MAX - req->body_size) {
921 return DATA_CORRUPTED;
924 if (req->body_size + (size_t)ntoread > req->evcon->max_body_size) {
925 /* failed body length test */
926 event_debug(("Request body is too long"));
927 return (DATA_TOO_LONG);
930 req->body_size += (size_t)ntoread;
931 req->ntoread = ntoread;
932 if (req->ntoread == 0) {
933 /* Last chunk */
934 return (ALL_DATA_READ);
936 continue;
939 /* req->ntoread is signed int64, len is ssize_t, based on arch,
940 * ssize_t could only be 32b, check for these conditions */
941 if (req->ntoread > EV_SSIZE_MAX) {
942 return DATA_CORRUPTED;
945 /* don't have enough to complete a chunk; wait for more */
946 if (req->ntoread > 0 && buflen < (ev_uint64_t)req->ntoread)
947 return (MORE_DATA_EXPECTED);
949 /* Completed chunk */
950 evbuffer_remove_buffer(buf, req->input_buffer, (size_t)req->ntoread);
951 req->ntoread = -1;
952 if (req->chunk_cb != NULL) {
953 req->flags |= EVHTTP_REQ_DEFER_FREE;
954 (*req->chunk_cb)(req, req->cb_arg);
955 evbuffer_drain(req->input_buffer,
956 evbuffer_get_length(req->input_buffer));
957 req->flags &= ~EVHTTP_REQ_DEFER_FREE;
958 if ((req->flags & EVHTTP_REQ_NEEDS_FREE) != 0) {
959 return (REQUEST_CANCELED);
964 return (MORE_DATA_EXPECTED);
967 static void
968 evhttp_read_trailer(struct evhttp_connection *evcon, struct evhttp_request *req)
970 struct evbuffer *buf = bufferevent_get_input(evcon->bufev);
972 switch (evhttp_parse_headers_(req, buf)) {
973 case DATA_CORRUPTED:
974 case DATA_TOO_LONG:
975 evhttp_connection_fail_(evcon, EVREQ_HTTP_DATA_TOO_LONG);
976 break;
977 case ALL_DATA_READ:
978 bufferevent_disable(evcon->bufev, EV_READ);
979 evhttp_connection_done(evcon);
980 break;
981 case MORE_DATA_EXPECTED:
982 case REQUEST_CANCELED: /* ??? */
983 default:
984 break;
988 static void
989 evhttp_read_body(struct evhttp_connection *evcon, struct evhttp_request *req)
991 struct evbuffer *buf = bufferevent_get_input(evcon->bufev);
993 if (req->chunked) {
994 switch (evhttp_handle_chunked_read(req, buf)) {
995 case ALL_DATA_READ:
996 /* finished last chunk */
997 evcon->state = EVCON_READING_TRAILER;
998 evhttp_read_trailer(evcon, req);
999 return;
1000 case DATA_CORRUPTED:
1001 case DATA_TOO_LONG:
1002 /* corrupted data */
1003 evhttp_connection_fail_(evcon,
1004 EVREQ_HTTP_DATA_TOO_LONG);
1005 return;
1006 case REQUEST_CANCELED:
1007 /* request canceled */
1008 evhttp_request_free_auto(req);
1009 return;
1010 case MORE_DATA_EXPECTED:
1011 default:
1012 break;
1014 } else if (req->ntoread < 0) {
1015 /* Read until connection close. */
1016 if ((size_t)(req->body_size + evbuffer_get_length(buf)) < req->body_size) {
1017 evhttp_connection_fail_(evcon, EVREQ_HTTP_INVALID_HEADER);
1018 return;
1021 req->body_size += evbuffer_get_length(buf);
1022 evbuffer_add_buffer(req->input_buffer, buf);
1023 } else if (req->chunk_cb != NULL || evbuffer_get_length(buf) >= (size_t)req->ntoread) {
1024 /* XXX: the above get_length comparison has to be fixed for overflow conditions! */
1025 /* We've postponed moving the data until now, but we're
1026 * about to use it. */
1027 size_t n = evbuffer_get_length(buf);
1029 if (n > (size_t) req->ntoread)
1030 n = (size_t) req->ntoread;
1031 req->ntoread -= n;
1032 req->body_size += n;
1033 evbuffer_remove_buffer(buf, req->input_buffer, n);
1036 if (req->body_size > req->evcon->max_body_size ||
1037 (!req->chunked && req->ntoread >= 0 &&
1038 (size_t)req->ntoread > req->evcon->max_body_size)) {
1039 /* XXX: The above casted comparison must checked for overflow */
1040 /* failed body length test */
1041 event_debug(("Request body is too long"));
1042 evhttp_connection_fail_(evcon,
1043 EVREQ_HTTP_DATA_TOO_LONG);
1044 return;
1047 if (evbuffer_get_length(req->input_buffer) > 0 && req->chunk_cb != NULL) {
1048 req->flags |= EVHTTP_REQ_DEFER_FREE;
1049 (*req->chunk_cb)(req, req->cb_arg);
1050 req->flags &= ~EVHTTP_REQ_DEFER_FREE;
1051 evbuffer_drain(req->input_buffer,
1052 evbuffer_get_length(req->input_buffer));
1053 if ((req->flags & EVHTTP_REQ_NEEDS_FREE) != 0) {
1054 evhttp_request_free_auto(req);
1055 return;
1059 if (req->ntoread == 0) {
1060 bufferevent_disable(evcon->bufev, EV_READ);
1061 /* Completed content length */
1062 evhttp_connection_done(evcon);
1063 return;
1067 #define get_deferred_queue(evcon) \
1068 ((evcon)->base)
1071 * Gets called when more data becomes available
1074 static void
1075 evhttp_read_cb(struct bufferevent *bufev, void *arg)
1077 struct evhttp_connection *evcon = arg;
1078 struct evhttp_request *req = TAILQ_FIRST(&evcon->requests);
1080 /* Cancel if it's pending. */
1081 event_deferred_cb_cancel_(get_deferred_queue(evcon),
1082 &evcon->read_more_deferred_cb);
1084 switch (evcon->state) {
1085 case EVCON_READING_FIRSTLINE:
1086 evhttp_read_firstline(evcon, req);
1087 /* note the request may have been freed in
1088 * evhttp_read_body */
1089 break;
1090 case EVCON_READING_HEADERS:
1091 evhttp_read_header(evcon, req);
1092 /* note the request may have been freed in
1093 * evhttp_read_body */
1094 break;
1095 case EVCON_READING_BODY:
1096 evhttp_read_body(evcon, req);
1097 /* note the request may have been freed in
1098 * evhttp_read_body */
1099 break;
1100 case EVCON_READING_TRAILER:
1101 evhttp_read_trailer(evcon, req);
1102 break;
1103 case EVCON_IDLE:
1105 #ifdef USE_DEBUG
1106 struct evbuffer *input;
1107 size_t total_len;
1109 input = bufferevent_get_input(evcon->bufev);
1110 total_len = evbuffer_get_length(input);
1111 event_debug(("%s: read "EV_SIZE_FMT
1112 " bytes in EVCON_IDLE state,"
1113 " resetting connection",
1114 __func__, EV_SIZE_ARG(total_len)));
1115 #endif
1117 evhttp_connection_reset_(evcon);
1119 break;
1120 case EVCON_DISCONNECTED:
1121 case EVCON_CONNECTING:
1122 case EVCON_WRITING:
1123 default:
1124 event_errx(1, "%s: illegal connection state %d",
1125 __func__, evcon->state);
1129 static void
1130 evhttp_deferred_read_cb(struct event_callback *cb, void *data)
1132 struct evhttp_connection *evcon = data;
1133 evhttp_read_cb(evcon->bufev, evcon);
1136 static void
1137 evhttp_write_connectioncb(struct evhttp_connection *evcon, void *arg)
1139 /* This is after writing the request to the server */
1140 struct evhttp_request *req = TAILQ_FIRST(&evcon->requests);
1141 EVUTIL_ASSERT(req != NULL);
1143 EVUTIL_ASSERT(evcon->state == EVCON_WRITING);
1145 /* We need to wait until we've written all of our output data before we can continue */
1146 if (evbuffer_get_length(bufferevent_get_output(evcon->bufev)) > 0) { return; }
1148 /* We are done writing our header and are now expecting the response */
1149 req->kind = EVHTTP_RESPONSE;
1151 evhttp_start_read_(evcon);
1155 * Clean up a connection object
1158 void
1159 evhttp_connection_free(struct evhttp_connection *evcon)
1161 struct evhttp_request *req;
1163 /* notify interested parties that this connection is going down */
1164 if (evcon->fd != -1) {
1165 if (evhttp_connected(evcon) && evcon->closecb != NULL)
1166 (*evcon->closecb)(evcon, evcon->closecb_arg);
1169 /* remove all requests that might be queued on this
1170 * connection. for server connections, this should be empty.
1171 * because it gets dequeued either in evhttp_connection_done or
1172 * evhttp_connection_fail_.
1174 while ((req = TAILQ_FIRST(&evcon->requests)) != NULL) {
1175 evhttp_request_free_(evcon, req);
1178 if (evcon->http_server != NULL) {
1179 struct evhttp *http = evcon->http_server;
1180 TAILQ_REMOVE(&http->connections, evcon, next);
1183 if (event_initialized(&evcon->retry_ev)) {
1184 event_del(&evcon->retry_ev);
1185 event_debug_unassign(&evcon->retry_ev);
1188 if (evcon->bufev != NULL)
1189 bufferevent_free(evcon->bufev);
1191 event_deferred_cb_cancel_(get_deferred_queue(evcon),
1192 &evcon->read_more_deferred_cb);
1194 if (evcon->fd != -1) {
1195 bufferevent_disable(evcon->bufev, EV_READ|EV_WRITE);
1196 shutdown(evcon->fd, EVUTIL_SHUT_WR);
1197 if (!(bufferevent_get_options_(evcon->bufev) & BEV_OPT_CLOSE_ON_FREE)) {
1198 evutil_closesocket(evcon->fd);
1202 if (evcon->bind_address != NULL)
1203 mm_free(evcon->bind_address);
1205 if (evcon->address != NULL)
1206 mm_free(evcon->address);
1208 mm_free(evcon);
1211 void
1212 evhttp_connection_free_on_completion(struct evhttp_connection *evcon) {
1213 evcon->flags |= EVHTTP_CON_AUTOFREE;
1216 void
1217 evhttp_connection_set_local_address(struct evhttp_connection *evcon,
1218 const char *address)
1220 EVUTIL_ASSERT(evcon->state == EVCON_DISCONNECTED);
1221 if (evcon->bind_address)
1222 mm_free(evcon->bind_address);
1223 if ((evcon->bind_address = mm_strdup(address)) == NULL)
1224 event_warn("%s: strdup", __func__);
1227 void
1228 evhttp_connection_set_local_port(struct evhttp_connection *evcon,
1229 ev_uint16_t port)
1231 EVUTIL_ASSERT(evcon->state == EVCON_DISCONNECTED);
1232 evcon->bind_port = port;
1235 static void
1236 evhttp_request_dispatch(struct evhttp_connection* evcon)
1238 struct evhttp_request *req = TAILQ_FIRST(&evcon->requests);
1240 /* this should not usually happy but it's possible */
1241 if (req == NULL)
1242 return;
1244 /* delete possible close detection events */
1245 evhttp_connection_stop_detectclose(evcon);
1247 /* we assume that the connection is connected already */
1248 EVUTIL_ASSERT(evcon->state == EVCON_IDLE);
1250 evcon->state = EVCON_WRITING;
1252 /* Create the header from the store arguments */
1253 evhttp_make_header(evcon, req);
1255 evhttp_write_buffer(evcon, evhttp_write_connectioncb, NULL);
1258 /* Reset our connection state: disables reading/writing, closes our fd (if
1259 * any), clears out buffers, and puts us in state DISCONNECTED. */
1260 void
1261 evhttp_connection_reset_(struct evhttp_connection *evcon)
1263 struct evbuffer *tmp;
1265 /* XXXX This is not actually an optimal fix. Instead we ought to have
1266 an API for "stop connecting", or use bufferevent_setfd to turn off
1267 connecting. But for Libevent 2.0, this seems like a minimal change
1268 least likely to disrupt the rest of the bufferevent and http code.
1270 Why is this here? If the fd is set in the bufferevent, and the
1271 bufferevent is connecting, then you can't actually stop the
1272 bufferevent from trying to connect with bufferevent_disable(). The
1273 connect will never trigger, since we close the fd, but the timeout
1274 might. That caused an assertion failure in evhttp_connection_fail_.
1276 bufferevent_disable_hard_(evcon->bufev, EV_READ|EV_WRITE);
1278 if (evcon->fd != -1) {
1279 /* inform interested parties about connection close */
1280 if (evhttp_connected(evcon) && evcon->closecb != NULL)
1281 (*evcon->closecb)(evcon, evcon->closecb_arg);
1283 shutdown(evcon->fd, EVUTIL_SHUT_WR);
1284 evutil_closesocket(evcon->fd);
1285 bufferevent_setfd(evcon->bufev, -1);
1286 evcon->fd = -1;
1289 /* we need to clean up any buffered data */
1290 tmp = bufferevent_get_output(evcon->bufev);
1291 evbuffer_drain(tmp, evbuffer_get_length(tmp));
1292 tmp = bufferevent_get_input(evcon->bufev);
1293 evbuffer_drain(tmp, evbuffer_get_length(tmp));
1295 evcon->state = EVCON_DISCONNECTED;
1298 static void
1299 evhttp_connection_start_detectclose(struct evhttp_connection *evcon)
1301 evcon->flags |= EVHTTP_CON_CLOSEDETECT;
1303 bufferevent_enable(evcon->bufev, EV_READ);
1306 static void
1307 evhttp_connection_stop_detectclose(struct evhttp_connection *evcon)
1309 evcon->flags &= ~EVHTTP_CON_CLOSEDETECT;
1311 bufferevent_disable(evcon->bufev, EV_READ);
1314 static void
1315 evhttp_connection_retry(evutil_socket_t fd, short what, void *arg)
1317 struct evhttp_connection *evcon = arg;
1319 evcon->state = EVCON_DISCONNECTED;
1320 evhttp_connection_connect_(evcon);
1323 static void
1324 evhttp_connection_cb_cleanup(struct evhttp_connection *evcon)
1326 struct evcon_requestq requests;
1328 evhttp_connection_reset_(evcon);
1329 if (evcon->retry_max < 0 || evcon->retry_cnt < evcon->retry_max) {
1330 struct timeval tv_retry = evcon->initial_retry_timeout;
1331 int i;
1332 evtimer_assign(&evcon->retry_ev, evcon->base, evhttp_connection_retry, evcon);
1333 /* XXXX handle failure from evhttp_add_event */
1334 for (i=0; i < evcon->retry_cnt; ++i) {
1335 tv_retry.tv_usec *= 2;
1336 if (tv_retry.tv_usec > 1000000) {
1337 tv_retry.tv_usec -= 1000000;
1338 tv_retry.tv_sec += 1;
1340 tv_retry.tv_sec *= 2;
1341 if (tv_retry.tv_sec > 3600) {
1342 tv_retry.tv_sec = 3600;
1343 tv_retry.tv_usec = 0;
1346 event_add(&evcon->retry_ev, &tv_retry);
1347 evcon->retry_cnt++;
1348 return;
1352 * User callback can do evhttp_make_request() on the same
1353 * evcon so new request will be added to evcon->requests. To
1354 * avoid freeing it prematurely we iterate over the copy of
1355 * the queue.
1357 TAILQ_INIT(&requests);
1358 while (TAILQ_FIRST(&evcon->requests) != NULL) {
1359 struct evhttp_request *request = TAILQ_FIRST(&evcon->requests);
1360 TAILQ_REMOVE(&evcon->requests, request, next);
1361 TAILQ_INSERT_TAIL(&requests, request, next);
1364 /* for now, we just signal all requests by executing their callbacks */
1365 while (TAILQ_FIRST(&requests) != NULL) {
1366 struct evhttp_request *request = TAILQ_FIRST(&requests);
1367 TAILQ_REMOVE(&requests, request, next);
1368 request->evcon = NULL;
1370 /* we might want to set an error here */
1371 request->cb(request, request->cb_arg);
1372 evhttp_request_free_auto(request);
1376 static void
1377 evhttp_error_cb(struct bufferevent *bufev, short what, void *arg)
1379 struct evhttp_connection *evcon = arg;
1380 struct evhttp_request *req = TAILQ_FIRST(&evcon->requests);
1382 if (evcon->fd == -1)
1383 evcon->fd = bufferevent_getfd(bufev);
1385 switch (evcon->state) {
1386 case EVCON_CONNECTING:
1387 if (what & BEV_EVENT_TIMEOUT) {
1388 event_debug(("%s: connection timeout for \"%s:%d\" on "
1389 EV_SOCK_FMT,
1390 __func__, evcon->address, evcon->port,
1391 EV_SOCK_ARG(evcon->fd)));
1392 evhttp_connection_cb_cleanup(evcon);
1393 return;
1395 break;
1397 case EVCON_READING_BODY:
1398 if (!req->chunked && req->ntoread < 0
1399 && what == (BEV_EVENT_READING|BEV_EVENT_EOF)) {
1400 /* EOF on read can be benign */
1401 evhttp_connection_done(evcon);
1402 return;
1404 break;
1406 case EVCON_DISCONNECTED:
1407 case EVCON_IDLE:
1408 case EVCON_READING_FIRSTLINE:
1409 case EVCON_READING_HEADERS:
1410 case EVCON_READING_TRAILER:
1411 case EVCON_WRITING:
1412 default:
1413 break;
1416 /* when we are in close detect mode, a read error means that
1417 * the other side closed their connection.
1419 if (evcon->flags & EVHTTP_CON_CLOSEDETECT) {
1420 evcon->flags &= ~EVHTTP_CON_CLOSEDETECT;
1421 EVUTIL_ASSERT(evcon->http_server == NULL);
1422 /* For connections from the client, we just
1423 * reset the connection so that it becomes
1424 * disconnected.
1426 EVUTIL_ASSERT(evcon->state == EVCON_IDLE);
1427 evhttp_connection_reset_(evcon);
1430 * If we have no more requests that need completion
1431 * and we want to auto-free the connection when all
1432 * requests have been completed.
1434 if (TAILQ_FIRST(&evcon->requests) == NULL
1435 && (evcon->flags & EVHTTP_CON_OUTGOING)
1436 && (evcon->flags & EVHTTP_CON_AUTOFREE)) {
1437 evhttp_connection_free(evcon);
1439 return;
1442 if (what & BEV_EVENT_TIMEOUT) {
1443 evhttp_connection_fail_(evcon, EVREQ_HTTP_TIMEOUT);
1444 } else if (what & (BEV_EVENT_EOF|BEV_EVENT_ERROR)) {
1445 evhttp_connection_fail_(evcon, EVREQ_HTTP_EOF);
1446 } else if (what == BEV_EVENT_CONNECTED) {
1447 } else {
1448 evhttp_connection_fail_(evcon, EVREQ_HTTP_BUFFER_ERROR);
1453 * Event callback for asynchronous connection attempt.
1455 static void
1456 evhttp_connection_cb(struct bufferevent *bufev, short what, void *arg)
1458 struct evhttp_connection *evcon = arg;
1459 int error;
1460 ev_socklen_t errsz = sizeof(error);
1462 if (evcon->fd == -1)
1463 evcon->fd = bufferevent_getfd(bufev);
1465 if (!(what & BEV_EVENT_CONNECTED)) {
1466 /* some operating systems return ECONNREFUSED immediately
1467 * when connecting to a local address. the cleanup is going
1468 * to reschedule this function call.
1470 #ifndef _WIN32
1471 if (errno == ECONNREFUSED)
1472 goto cleanup;
1473 #endif
1474 evhttp_error_cb(bufev, what, arg);
1475 return;
1478 if (evcon->fd == -1) {
1479 event_debug(("%s: bufferevent_getfd returned -1",
1480 __func__));
1481 goto cleanup;
1484 /* Check if the connection completed */
1485 if (getsockopt(evcon->fd, SOL_SOCKET, SO_ERROR, (void*)&error,
1486 &errsz) == -1) {
1487 event_debug(("%s: getsockopt for \"%s:%d\" on "EV_SOCK_FMT,
1488 __func__, evcon->address, evcon->port,
1489 EV_SOCK_ARG(evcon->fd)));
1490 goto cleanup;
1493 if (error) {
1494 event_debug(("%s: connect failed for \"%s:%d\" on "
1495 EV_SOCK_FMT": %s",
1496 __func__, evcon->address, evcon->port,
1497 EV_SOCK_ARG(evcon->fd),
1498 evutil_socket_error_to_string(error)));
1499 goto cleanup;
1502 /* We are connected to the server now */
1503 event_debug(("%s: connected to \"%s:%d\" on "EV_SOCK_FMT"\n",
1504 __func__, evcon->address, evcon->port,
1505 EV_SOCK_ARG(evcon->fd)));
1507 /* Reset the retry count as we were successful in connecting */
1508 evcon->retry_cnt = 0;
1509 evcon->state = EVCON_IDLE;
1511 /* reset the bufferevent cbs */
1512 bufferevent_setcb(evcon->bufev,
1513 evhttp_read_cb,
1514 evhttp_write_cb,
1515 evhttp_error_cb,
1516 evcon);
1518 if (!evutil_timerisset(&evcon->timeout)) {
1519 const struct timeval read_tv = { HTTP_READ_TIMEOUT, 0 };
1520 const struct timeval write_tv = { HTTP_WRITE_TIMEOUT, 0 };
1521 bufferevent_set_timeouts(evcon->bufev, &read_tv, &write_tv);
1522 } else {
1523 bufferevent_set_timeouts(evcon->bufev, &evcon->timeout, &evcon->timeout);
1526 /* try to start requests that have queued up on this connection */
1527 evhttp_request_dispatch(evcon);
1528 return;
1530 cleanup:
1531 evhttp_connection_cb_cleanup(evcon);
1535 * Check if we got a valid response code.
1538 static int
1539 evhttp_valid_response_code(int code)
1541 if (code == 0)
1542 return (0);
1544 return (1);
1547 static int
1548 evhttp_parse_http_version(const char *version, struct evhttp_request *req)
1550 int major, minor;
1551 char ch;
1552 int n = sscanf(version, "HTTP/%d.%d%c", &major, &minor, &ch);
1553 if (n != 2 || major > 1) {
1554 event_debug(("%s: bad version %s on message %p from %s",
1555 __func__, version, req, req->remote_host));
1556 return (-1);
1558 req->major = major;
1559 req->minor = minor;
1560 return (0);
1563 /* Parses the status line of a web server */
1565 static int
1566 evhttp_parse_response_line(struct evhttp_request *req, char *line)
1568 char *protocol;
1569 char *number;
1570 const char *readable = "";
1572 protocol = strsep(&line, " ");
1573 if (line == NULL)
1574 return (-1);
1575 number = strsep(&line, " ");
1576 if (line != NULL)
1577 readable = line;
1579 if (evhttp_parse_http_version(protocol, req) < 0)
1580 return (-1);
1582 req->response_code = atoi(number);
1583 if (!evhttp_valid_response_code(req->response_code)) {
1584 event_debug(("%s: bad response code \"%s\"",
1585 __func__, number));
1586 return (-1);
1589 if ((req->response_code_line = mm_strdup(readable)) == NULL) {
1590 event_warn("%s: strdup", __func__);
1591 return (-1);
1594 return (0);
1597 /* Parse the first line of a HTTP request */
1599 static int
1600 evhttp_parse_request_line(struct evhttp_request *req, char *line)
1602 char *method;
1603 char *uri;
1604 char *version;
1605 const char *hostname;
1606 const char *scheme;
1607 size_t method_len;
1608 enum evhttp_cmd_type type;
1610 /* Parse the request line */
1611 method = strsep(&line, " ");
1612 if (line == NULL)
1613 return (-1);
1614 uri = strsep(&line, " ");
1615 if (line == NULL)
1616 return (-1);
1617 version = strsep(&line, " ");
1618 if (line != NULL)
1619 return (-1);
1621 method_len = (uri - method) - 1;
1622 type = EVHTTP_REQ_UNKNOWN_;
1624 /* First line */
1625 switch (method_len) {
1626 case 3:
1627 /* The length of the method string is 3, meaning it can only be one of two methods: GET or PUT */
1629 /* Since both GET and PUT share the same character 'T' at the end,
1630 * if the string doesn't have 'T', we can immediately determine this
1631 * is an invalid HTTP method */
1633 if (method[2] != 'T') {
1634 break;
1637 switch (*method) {
1638 case 'G':
1639 /* This first byte is 'G', so make sure the next byte is
1640 * 'E', if it isn't then this isn't a valid method */
1642 if (method[1] == 'E') {
1643 type = EVHTTP_REQ_GET;
1646 break;
1647 case 'P':
1648 /* First byte is P, check second byte for 'U', if not,
1649 * we know it's an invalid method */
1650 if (method[1] == 'U') {
1651 type = EVHTTP_REQ_PUT;
1653 break;
1654 default:
1655 break;
1657 break;
1658 case 4:
1659 /* The method length is 4 bytes, leaving only the methods "POST" and "HEAD" */
1660 switch (*method) {
1661 case 'P':
1662 if (method[3] == 'T' && method[2] == 'S' && method[1] == 'O') {
1663 type = EVHTTP_REQ_POST;
1665 break;
1666 case 'H':
1667 if (method[3] == 'D' && method[2] == 'A' && method[1] == 'E') {
1668 type = EVHTTP_REQ_HEAD;
1670 break;
1671 default:
1672 break;
1674 break;
1675 case 5:
1676 /* Method length is 5 bytes, which can only encompass PATCH and TRACE */
1677 switch (*method) {
1678 case 'P':
1679 if (method[4] == 'H' && method[3] == 'C' && method[2] == 'T' && method[1] == 'A') {
1680 type = EVHTTP_REQ_PATCH;
1682 break;
1683 case 'T':
1684 if (method[4] == 'E' && method[3] == 'C' && method[2] == 'A' && method[1] == 'R') {
1685 type = EVHTTP_REQ_TRACE;
1688 break;
1689 default:
1690 break;
1692 break;
1693 case 6:
1694 /* Method length is 6, only valid method 6 bytes in length is DELEte */
1696 /* If the first byte isn't 'D' then it's invalid */
1697 if (*method != 'D') {
1698 break;
1701 if (method[5] == 'E' && method[4] == 'T' && method[3] == 'E' && method[2] == 'L' && method[1] == 'E') {
1702 type = EVHTTP_REQ_DELETE;
1705 break;
1706 case 7:
1707 /* Method length is 7, only valid methods are "OPTIONS" and "CONNECT" */
1708 switch (*method) {
1709 case 'O':
1710 if (method[6] == 'S' && method[5] == 'N' && method[4] == 'O' &&
1711 method[3] == 'I' && method[2] == 'T' && method[1] == 'P') {
1712 type = EVHTTP_REQ_OPTIONS;
1715 break;
1716 case 'C':
1717 if (method[6] == 'T' && method[5] == 'C' && method[4] == 'E' &&
1718 method[3] == 'N' && method[2] == 'N' && method[1] == 'O') {
1719 type = EVHTTP_REQ_CONNECT;
1722 break;
1723 default:
1724 break;
1726 break;
1727 } /* switch */
1729 if ((int)type == EVHTTP_REQ_UNKNOWN_) {
1730 event_debug(("%s: bad method %s on request %p from %s",
1731 __func__, method, req, req->remote_host));
1732 /* No error yet; we'll give a better error later when
1733 * we see that req->type is unsupported. */
1736 req->type = type;
1738 if (evhttp_parse_http_version(version, req) < 0)
1739 return (-1);
1741 if ((req->uri = mm_strdup(uri)) == NULL) {
1742 event_debug(("%s: mm_strdup", __func__));
1743 return (-1);
1746 if ((req->uri_elems = evhttp_uri_parse_with_flags(req->uri,
1747 EVHTTP_URI_NONCONFORMANT)) == NULL) {
1748 return -1;
1751 /* If we have an absolute-URI, check to see if it is an http request
1752 for a known vhost or server alias. If we don't know about this
1753 host, we consider it a proxy request. */
1754 scheme = evhttp_uri_get_scheme(req->uri_elems);
1755 hostname = evhttp_uri_get_host(req->uri_elems);
1756 if (scheme && (!evutil_ascii_strcasecmp(scheme, "http") ||
1757 !evutil_ascii_strcasecmp(scheme, "https")) &&
1758 hostname &&
1759 !evhttp_find_vhost(req->evcon->http_server, NULL, hostname))
1760 req->flags |= EVHTTP_PROXY_REQUEST;
1762 return (0);
1765 const char *
1766 evhttp_find_header(const struct evkeyvalq *headers, const char *key)
1768 struct evkeyval *header;
1770 TAILQ_FOREACH(header, headers, next) {
1771 if (evutil_ascii_strcasecmp(header->key, key) == 0)
1772 return (header->value);
1775 return (NULL);
1778 void
1779 evhttp_clear_headers(struct evkeyvalq *headers)
1781 struct evkeyval *header;
1783 for (header = TAILQ_FIRST(headers);
1784 header != NULL;
1785 header = TAILQ_FIRST(headers)) {
1786 TAILQ_REMOVE(headers, header, next);
1787 mm_free(header->key);
1788 mm_free(header->value);
1789 mm_free(header);
1794 * Returns 0, if the header was successfully removed.
1795 * Returns -1, if the header could not be found.
1799 evhttp_remove_header(struct evkeyvalq *headers, const char *key)
1801 struct evkeyval *header;
1803 TAILQ_FOREACH(header, headers, next) {
1804 if (evutil_ascii_strcasecmp(header->key, key) == 0)
1805 break;
1808 if (header == NULL)
1809 return (-1);
1811 /* Free and remove the header that we found */
1812 TAILQ_REMOVE(headers, header, next);
1813 mm_free(header->key);
1814 mm_free(header->value);
1815 mm_free(header);
1817 return (0);
1820 static int
1821 evhttp_header_is_valid_value(const char *value)
1823 const char *p = value;
1825 while ((p = strpbrk(p, "\r\n")) != NULL) {
1826 /* we really expect only one new line */
1827 p += strspn(p, "\r\n");
1828 /* we expect a space or tab for continuation */
1829 if (*p != ' ' && *p != '\t')
1830 return (0);
1832 return (1);
1836 evhttp_add_header(struct evkeyvalq *headers,
1837 const char *key, const char *value)
1839 event_debug(("%s: key: %s val: %s\n", __func__, key, value));
1841 if (strchr(key, '\r') != NULL || strchr(key, '\n') != NULL) {
1842 /* drop illegal headers */
1843 event_debug(("%s: dropping illegal header key\n", __func__));
1844 return (-1);
1847 if (!evhttp_header_is_valid_value(value)) {
1848 event_debug(("%s: dropping illegal header value\n", __func__));
1849 return (-1);
1852 return (evhttp_add_header_internal(headers, key, value));
1855 static int
1856 evhttp_add_header_internal(struct evkeyvalq *headers,
1857 const char *key, const char *value)
1859 struct evkeyval *header = mm_calloc(1, sizeof(struct evkeyval));
1860 if (header == NULL) {
1861 event_warn("%s: calloc", __func__);
1862 return (-1);
1864 if ((header->key = mm_strdup(key)) == NULL) {
1865 mm_free(header);
1866 event_warn("%s: strdup", __func__);
1867 return (-1);
1869 if ((header->value = mm_strdup(value)) == NULL) {
1870 mm_free(header->key);
1871 mm_free(header);
1872 event_warn("%s: strdup", __func__);
1873 return (-1);
1876 TAILQ_INSERT_TAIL(headers, header, next);
1878 return (0);
1882 * Parses header lines from a request or a response into the specified
1883 * request object given an event buffer.
1885 * Returns
1886 * DATA_CORRUPTED on error
1887 * MORE_DATA_EXPECTED when we need to read more headers
1888 * ALL_DATA_READ when all headers have been read.
1891 enum message_read_status
1892 evhttp_parse_firstline_(struct evhttp_request *req, struct evbuffer *buffer)
1894 char *line;
1895 enum message_read_status status = ALL_DATA_READ;
1897 size_t line_length;
1898 /* XXX try */
1899 line = evbuffer_readln(buffer, &line_length, EVBUFFER_EOL_CRLF);
1900 if (line == NULL) {
1901 if (req->evcon != NULL &&
1902 evbuffer_get_length(buffer) > req->evcon->max_headers_size)
1903 return (DATA_TOO_LONG);
1904 else
1905 return (MORE_DATA_EXPECTED);
1908 if (req->evcon != NULL &&
1909 line_length > req->evcon->max_headers_size) {
1910 mm_free(line);
1911 return (DATA_TOO_LONG);
1914 req->headers_size = line_length;
1916 switch (req->kind) {
1917 case EVHTTP_REQUEST:
1918 if (evhttp_parse_request_line(req, line) == -1)
1919 status = DATA_CORRUPTED;
1920 break;
1921 case EVHTTP_RESPONSE:
1922 if (evhttp_parse_response_line(req, line) == -1)
1923 status = DATA_CORRUPTED;
1924 break;
1925 default:
1926 status = DATA_CORRUPTED;
1929 mm_free(line);
1930 return (status);
1933 static int
1934 evhttp_append_to_last_header(struct evkeyvalq *headers, char *line)
1936 struct evkeyval *header = TAILQ_LAST(headers, evkeyvalq);
1937 char *newval;
1938 size_t old_len, line_len;
1940 if (header == NULL)
1941 return (-1);
1943 old_len = strlen(header->value);
1945 /* Strip space from start and end of line. */
1946 while (*line == ' ' || *line == '\t')
1947 ++line;
1948 evutil_rtrim_lws_(line);
1950 line_len = strlen(line);
1952 newval = mm_realloc(header->value, old_len + line_len + 2);
1953 if (newval == NULL)
1954 return (-1);
1956 newval[old_len] = ' ';
1957 memcpy(newval + old_len + 1, line, line_len + 1);
1958 header->value = newval;
1960 return (0);
1963 enum message_read_status
1964 evhttp_parse_headers_(struct evhttp_request *req, struct evbuffer* buffer)
1966 enum message_read_status errcode = DATA_CORRUPTED;
1967 char *line;
1968 enum message_read_status status = MORE_DATA_EXPECTED;
1970 struct evkeyvalq* headers = req->input_headers;
1971 size_t line_length;
1972 while ((line = evbuffer_readln(buffer, &line_length, EVBUFFER_EOL_CRLF))
1973 != NULL) {
1974 char *skey, *svalue;
1976 req->headers_size += line_length;
1978 if (req->evcon != NULL &&
1979 req->headers_size > req->evcon->max_headers_size) {
1980 errcode = DATA_TOO_LONG;
1981 goto error;
1984 if (*line == '\0') { /* Last header - Done */
1985 status = ALL_DATA_READ;
1986 mm_free(line);
1987 break;
1990 /* Check if this is a continuation line */
1991 if (*line == ' ' || *line == '\t') {
1992 if (evhttp_append_to_last_header(headers, line) == -1)
1993 goto error;
1994 mm_free(line);
1995 continue;
1998 /* Processing of header lines */
1999 svalue = line;
2000 skey = strsep(&svalue, ":");
2001 if (svalue == NULL)
2002 goto error;
2004 svalue += strspn(svalue, " ");
2005 evutil_rtrim_lws_(svalue);
2007 if (evhttp_add_header(headers, skey, svalue) == -1)
2008 goto error;
2010 mm_free(line);
2013 if (status == MORE_DATA_EXPECTED) {
2014 if (req->evcon != NULL &&
2015 req->headers_size + evbuffer_get_length(buffer) > req->evcon->max_headers_size)
2016 return (DATA_TOO_LONG);
2019 return (status);
2021 error:
2022 mm_free(line);
2023 return (errcode);
2026 static int
2027 evhttp_get_body_length(struct evhttp_request *req)
2029 struct evkeyvalq *headers = req->input_headers;
2030 const char *content_length;
2031 const char *connection;
2033 content_length = evhttp_find_header(headers, "Content-Length");
2034 connection = evhttp_find_header(headers, "Connection");
2036 if (content_length == NULL && connection == NULL)
2037 req->ntoread = -1;
2038 else if (content_length == NULL &&
2039 evutil_ascii_strcasecmp(connection, "Close") != 0) {
2040 /* Bad combination, we don't know when it will end */
2041 event_warnx("%s: we got no content length, but the "
2042 "server wants to keep the connection open: %s.",
2043 __func__, connection);
2044 return (-1);
2045 } else if (content_length == NULL) {
2046 req->ntoread = -1;
2047 } else {
2048 char *endp;
2049 ev_int64_t ntoread = evutil_strtoll(content_length, &endp, 10);
2050 if (*content_length == '\0' || *endp != '\0' || ntoread < 0) {
2051 event_debug(("%s: illegal content length: %s",
2052 __func__, content_length));
2053 return (-1);
2055 req->ntoread = ntoread;
2058 event_debug(("%s: bytes to read: "EV_I64_FMT" (in buffer "EV_SIZE_FMT")\n",
2059 __func__, EV_I64_ARG(req->ntoread),
2060 EV_SIZE_ARG(evbuffer_get_length(bufferevent_get_input(req->evcon->bufev)))));
2062 return (0);
2065 static int
2066 evhttp_method_may_have_body(enum evhttp_cmd_type type)
2068 switch (type) {
2069 case EVHTTP_REQ_POST:
2070 case EVHTTP_REQ_PUT:
2071 case EVHTTP_REQ_PATCH:
2072 return 1;
2073 case EVHTTP_REQ_TRACE:
2074 return 0;
2075 /* XXX May any of the below methods have a body? */
2076 case EVHTTP_REQ_GET:
2077 case EVHTTP_REQ_HEAD:
2078 case EVHTTP_REQ_DELETE:
2079 case EVHTTP_REQ_OPTIONS:
2080 case EVHTTP_REQ_CONNECT:
2081 return 0;
2082 default:
2083 return 0;
2087 static void
2088 evhttp_get_body(struct evhttp_connection *evcon, struct evhttp_request *req)
2090 const char *xfer_enc;
2092 /* If this is a request without a body, then we are done */
2093 if (req->kind == EVHTTP_REQUEST &&
2094 !evhttp_method_may_have_body(req->type)) {
2095 evhttp_connection_done(evcon);
2096 return;
2098 evcon->state = EVCON_READING_BODY;
2099 xfer_enc = evhttp_find_header(req->input_headers, "Transfer-Encoding");
2100 if (xfer_enc != NULL && evutil_ascii_strcasecmp(xfer_enc, "chunked") == 0) {
2101 req->chunked = 1;
2102 req->ntoread = -1;
2103 } else {
2104 if (evhttp_get_body_length(req) == -1) {
2105 evhttp_connection_fail_(evcon,
2106 EVREQ_HTTP_INVALID_HEADER);
2107 return;
2109 if (req->kind == EVHTTP_REQUEST && req->ntoread < 1) {
2110 /* An incoming request with no content-length and no
2111 * transfer-encoding has no body. */
2112 evhttp_connection_done(evcon);
2113 return;
2117 /* Should we send a 100 Continue status line? */
2118 if (req->kind == EVHTTP_REQUEST && REQ_VERSION_ATLEAST(req, 1, 1)) {
2119 const char *expect;
2121 expect = evhttp_find_header(req->input_headers, "Expect");
2122 if (expect) {
2123 if (!evutil_ascii_strcasecmp(expect, "100-continue")) {
2124 /* XXX It would be nice to do some sanity
2125 checking here. Does the resource exist?
2126 Should the resource accept post requests? If
2127 no, we should respond with an error. For
2128 now, just optimistically tell the client to
2129 send their message body. */
2130 if (req->ntoread > 0) {
2131 /* ntoread is ev_int64_t, max_body_size is ev_uint64_t */
2132 if ((req->evcon->max_body_size <= EV_INT64_MAX) && (ev_uint64_t)req->ntoread > req->evcon->max_body_size) {
2133 evhttp_send_error(req, HTTP_ENTITYTOOLARGE, NULL);
2134 return;
2137 if (!evbuffer_get_length(bufferevent_get_input(evcon->bufev)))
2138 evhttp_send_continue(evcon, req);
2139 } else {
2140 evhttp_send_error(req, HTTP_EXPECTATIONFAILED,
2141 NULL);
2142 return;
2147 evhttp_read_body(evcon, req);
2148 /* note the request may have been freed in evhttp_read_body */
2151 static void
2152 evhttp_read_firstline(struct evhttp_connection *evcon,
2153 struct evhttp_request *req)
2155 enum message_read_status res;
2157 res = evhttp_parse_firstline_(req, bufferevent_get_input(evcon->bufev));
2158 if (res == DATA_CORRUPTED || res == DATA_TOO_LONG) {
2159 /* Error while reading, terminate */
2160 event_debug(("%s: bad header lines on "EV_SOCK_FMT"\n",
2161 __func__, EV_SOCK_ARG(evcon->fd)));
2162 evhttp_connection_fail_(evcon, EVREQ_HTTP_INVALID_HEADER);
2163 return;
2164 } else if (res == MORE_DATA_EXPECTED) {
2165 /* Need more header lines */
2166 return;
2169 evcon->state = EVCON_READING_HEADERS;
2170 evhttp_read_header(evcon, req);
2173 static void
2174 evhttp_read_header(struct evhttp_connection *evcon,
2175 struct evhttp_request *req)
2177 enum message_read_status res;
2178 evutil_socket_t fd = evcon->fd;
2180 res = evhttp_parse_headers_(req, bufferevent_get_input(evcon->bufev));
2181 if (res == DATA_CORRUPTED || res == DATA_TOO_LONG) {
2182 /* Error while reading, terminate */
2183 event_debug(("%s: bad header lines on "EV_SOCK_FMT"\n",
2184 __func__, EV_SOCK_ARG(fd)));
2185 evhttp_connection_fail_(evcon, EVREQ_HTTP_INVALID_HEADER);
2186 return;
2187 } else if (res == MORE_DATA_EXPECTED) {
2188 /* Need more header lines */
2189 return;
2192 /* Callback can shut down connection with negative return value */
2193 if (req->header_cb != NULL) {
2194 if ((*req->header_cb)(req, req->cb_arg) < 0) {
2195 evhttp_connection_fail_(evcon, EVREQ_HTTP_EOF);
2196 return;
2200 /* Done reading headers, do the real work */
2201 switch (req->kind) {
2202 case EVHTTP_REQUEST:
2203 event_debug(("%s: checking for post data on "EV_SOCK_FMT"\n",
2204 __func__, EV_SOCK_ARG(fd)));
2205 evhttp_get_body(evcon, req);
2206 /* note the request may have been freed in evhttp_get_body */
2207 break;
2209 case EVHTTP_RESPONSE:
2210 /* Start over if we got a 100 Continue response. */
2211 if (req->response_code == 100) {
2212 evhttp_start_read_(evcon);
2213 return;
2215 if (!evhttp_response_needs_body(req)) {
2216 event_debug(("%s: skipping body for code %d\n",
2217 __func__, req->response_code));
2218 evhttp_connection_done(evcon);
2219 } else {
2220 event_debug(("%s: start of read body for %s on "
2221 EV_SOCK_FMT"\n",
2222 __func__, req->remote_host, EV_SOCK_ARG(fd)));
2223 evhttp_get_body(evcon, req);
2224 /* note the request may have been freed in
2225 * evhttp_get_body */
2227 break;
2229 default:
2230 event_warnx("%s: bad header on "EV_SOCK_FMT, __func__,
2231 EV_SOCK_ARG(fd));
2232 evhttp_connection_fail_(evcon, EVREQ_HTTP_INVALID_HEADER);
2233 break;
2235 /* request may have been freed above */
2239 * Creates a TCP connection to the specified port and executes a callback
2240 * when finished. Failure or success is indicate by the passed connection
2241 * object.
2243 * Although this interface accepts a hostname, it is intended to take
2244 * only numeric hostnames so that non-blocking DNS resolution can
2245 * happen elsewhere.
2248 struct evhttp_connection *
2249 evhttp_connection_new(const char *address, unsigned short port)
2251 return (evhttp_connection_base_new(NULL, NULL, address, port));
2254 struct evhttp_connection *
2255 evhttp_connection_base_bufferevent_new(struct event_base *base, struct evdns_base *dnsbase, struct bufferevent* bev,
2256 const char *address, unsigned short port)
2258 struct evhttp_connection *evcon = NULL;
2260 event_debug(("Attempting connection to %s:%d\n", address, port));
2262 if ((evcon = mm_calloc(1, sizeof(struct evhttp_connection))) == NULL) {
2263 event_warn("%s: calloc failed", __func__);
2264 goto error;
2267 evcon->fd = -1;
2268 evcon->port = port;
2270 evcon->max_headers_size = EV_SIZE_MAX;
2271 evcon->max_body_size = EV_SIZE_MAX;
2273 evutil_timerclear(&evcon->timeout);
2274 evcon->retry_cnt = evcon->retry_max = 0;
2276 if ((evcon->address = mm_strdup(address)) == NULL) {
2277 event_warn("%s: strdup failed", __func__);
2278 goto error;
2281 if (bev == NULL) {
2282 if (!(bev = bufferevent_socket_new(base, -1, 0))) {
2283 event_warn("%s: bufferevent_socket_new failed", __func__);
2284 goto error;
2288 bufferevent_setcb(bev, evhttp_read_cb, evhttp_write_cb, evhttp_error_cb, evcon);
2289 evcon->bufev = bev;
2291 evcon->state = EVCON_DISCONNECTED;
2292 TAILQ_INIT(&evcon->requests);
2294 evcon->initial_retry_timeout.tv_sec = 2;
2295 evcon->initial_retry_timeout.tv_usec = 0;
2297 if (base != NULL) {
2298 evcon->base = base;
2299 if (bufferevent_get_base(bev) != base)
2300 bufferevent_base_set(base, evcon->bufev);
2303 event_deferred_cb_init_(
2304 &evcon->read_more_deferred_cb,
2305 bufferevent_get_priority(bev),
2306 evhttp_deferred_read_cb, evcon);
2308 evcon->dns_base = dnsbase;
2309 evcon->ai_family = AF_UNSPEC;
2311 return (evcon);
2313 error:
2314 if (evcon != NULL)
2315 evhttp_connection_free(evcon);
2316 return (NULL);
2319 struct bufferevent* evhttp_connection_get_bufferevent(struct evhttp_connection *evcon)
2321 return evcon->bufev;
2324 struct evhttp *
2325 evhttp_connection_get_server(struct evhttp_connection *evcon)
2327 return evcon->http_server;
2330 struct evhttp_connection *
2331 evhttp_connection_base_new(struct event_base *base, struct evdns_base *dnsbase,
2332 const char *address, unsigned short port)
2334 return evhttp_connection_base_bufferevent_new(base, dnsbase, NULL, address, port);
2337 void evhttp_connection_set_family(struct evhttp_connection *evcon,
2338 int family)
2340 evcon->ai_family = family;
2343 int evhttp_connection_set_flags(struct evhttp_connection *evcon,
2344 int flags)
2346 if (flags & ~(EVHTTP_CON_REUSE_CONNECTED_ADDR)) {
2347 return 1;
2350 evcon->flags &= ~(EVHTTP_CON_REUSE_CONNECTED_ADDR);
2352 evcon->flags |= EVHTTP_CON_REUSE_CONNECTED_ADDR;
2354 return 0;
2357 void
2358 evhttp_connection_set_base(struct evhttp_connection *evcon,
2359 struct event_base *base)
2361 EVUTIL_ASSERT(evcon->base == NULL);
2362 EVUTIL_ASSERT(evcon->state == EVCON_DISCONNECTED);
2363 evcon->base = base;
2364 bufferevent_base_set(base, evcon->bufev);
2367 void
2368 evhttp_connection_set_timeout(struct evhttp_connection *evcon,
2369 int timeout_in_secs)
2371 if (timeout_in_secs == -1)
2372 evhttp_connection_set_timeout_tv(evcon, NULL);
2373 else {
2374 struct timeval tv;
2375 tv.tv_sec = timeout_in_secs;
2376 tv.tv_usec = 0;
2377 evhttp_connection_set_timeout_tv(evcon, &tv);
2381 void
2382 evhttp_connection_set_timeout_tv(struct evhttp_connection *evcon,
2383 const struct timeval* tv)
2385 if (tv) {
2386 evcon->timeout = *tv;
2387 bufferevent_set_timeouts(evcon->bufev, &evcon->timeout, &evcon->timeout);
2388 } else {
2389 const struct timeval read_tv = { HTTP_READ_TIMEOUT, 0 };
2390 const struct timeval write_tv = { HTTP_WRITE_TIMEOUT, 0 };
2391 evutil_timerclear(&evcon->timeout);
2392 bufferevent_set_timeouts(evcon->bufev, &read_tv, &write_tv);
2396 void
2397 evhttp_connection_set_initial_retry_tv(struct evhttp_connection *evcon,
2398 const struct timeval *tv)
2400 if (tv) {
2401 evcon->initial_retry_timeout = *tv;
2402 } else {
2403 evutil_timerclear(&evcon->initial_retry_timeout);
2404 evcon->initial_retry_timeout.tv_sec = 2;
2408 void
2409 evhttp_connection_set_retries(struct evhttp_connection *evcon,
2410 int retry_max)
2412 evcon->retry_max = retry_max;
2415 void
2416 evhttp_connection_set_closecb(struct evhttp_connection *evcon,
2417 void (*cb)(struct evhttp_connection *, void *), void *cbarg)
2419 evcon->closecb = cb;
2420 evcon->closecb_arg = cbarg;
2423 void
2424 evhttp_connection_get_peer(struct evhttp_connection *evcon,
2425 char **address, ev_uint16_t *port)
2427 *address = evcon->address;
2428 *port = evcon->port;
2431 const struct sockaddr*
2432 evhttp_connection_get_addr(struct evhttp_connection *evcon)
2434 return bufferevent_socket_get_conn_address_(evcon->bufev);
2438 evhttp_connection_connect_(struct evhttp_connection *evcon)
2440 int old_state = evcon->state;
2441 const char *address = evcon->address;
2442 const struct sockaddr *sa = evhttp_connection_get_addr(evcon);
2443 int ret;
2445 if (evcon->state == EVCON_CONNECTING)
2446 return (0);
2448 evhttp_connection_reset_(evcon);
2450 EVUTIL_ASSERT(!(evcon->flags & EVHTTP_CON_INCOMING));
2451 evcon->flags |= EVHTTP_CON_OUTGOING;
2453 if (evcon->bind_address || evcon->bind_port) {
2454 evcon->fd = bind_socket(
2455 evcon->bind_address, evcon->bind_port, 0 /*reuse*/);
2456 if (evcon->fd == -1) {
2457 event_debug(("%s: failed to bind to \"%s\"",
2458 __func__, evcon->bind_address));
2459 return (-1);
2462 bufferevent_setfd(evcon->bufev, evcon->fd);
2463 } else {
2464 bufferevent_setfd(evcon->bufev, -1);
2467 /* Set up a callback for successful connection setup */
2468 bufferevent_setcb(evcon->bufev,
2469 NULL /* evhttp_read_cb */,
2470 NULL /* evhttp_write_cb */,
2471 evhttp_connection_cb,
2472 evcon);
2473 if (!evutil_timerisset(&evcon->timeout)) {
2474 const struct timeval conn_tv = { HTTP_CONNECT_TIMEOUT, 0 };
2475 bufferevent_set_timeouts(evcon->bufev, &conn_tv, &conn_tv);
2476 } else {
2477 bufferevent_set_timeouts(evcon->bufev, &evcon->timeout, &evcon->timeout);
2479 /* make sure that we get a write callback */
2480 bufferevent_enable(evcon->bufev, EV_WRITE);
2482 evcon->state = EVCON_CONNECTING;
2484 if (evcon->flags & EVHTTP_CON_REUSE_CONNECTED_ADDR &&
2485 sa &&
2486 (sa->sa_family == AF_INET || sa->sa_family == AF_INET6)) {
2487 int socklen = sizeof(struct sockaddr_in);
2488 if (sa->sa_family == AF_INET6) {
2489 socklen = sizeof(struct sockaddr_in6);
2491 ret = bufferevent_socket_connect(evcon->bufev, sa, socklen);
2492 } else {
2493 ret = bufferevent_socket_connect_hostname(evcon->bufev,
2494 evcon->dns_base, evcon->ai_family, address, evcon->port);
2497 if (ret < 0) {
2498 evcon->state = old_state;
2499 event_sock_warn(evcon->fd, "%s: connection to \"%s\" failed",
2500 __func__, evcon->address);
2501 /* some operating systems return ECONNREFUSED immediately
2502 * when connecting to a local address. the cleanup is going
2503 * to reschedule this function call.
2505 evhttp_connection_cb_cleanup(evcon);
2506 return (0);
2509 return (0);
2513 * Starts an HTTP request on the provided evhttp_connection object.
2514 * If the connection object is not connected to the web server already,
2515 * this will start the connection.
2519 evhttp_make_request(struct evhttp_connection *evcon,
2520 struct evhttp_request *req,
2521 enum evhttp_cmd_type type, const char *uri)
2523 /* We are making a request */
2524 req->kind = EVHTTP_REQUEST;
2525 req->type = type;
2526 if (req->uri != NULL)
2527 mm_free(req->uri);
2528 if ((req->uri = mm_strdup(uri)) == NULL) {
2529 event_warn("%s: strdup", __func__);
2530 evhttp_request_free_auto(req);
2531 return (-1);
2534 /* Set the protocol version if it is not supplied */
2535 if (!req->major && !req->minor) {
2536 req->major = 1;
2537 req->minor = 1;
2540 EVUTIL_ASSERT(req->evcon == NULL);
2541 req->evcon = evcon;
2542 EVUTIL_ASSERT(!(req->flags & EVHTTP_REQ_OWN_CONNECTION));
2544 TAILQ_INSERT_TAIL(&evcon->requests, req, next);
2546 /* If the connection object is not connected; make it so */
2547 if (!evhttp_connected(evcon)) {
2548 int res = evhttp_connection_connect_(evcon);
2549 /* evhttp_connection_fail_(), which is called through
2550 * evhttp_connection_connect_(), assumes that req lies in
2551 * evcon->requests. Thus, enqueue the request in advance and
2552 * remove it in the error case. */
2553 if (res != 0)
2554 TAILQ_REMOVE(&evcon->requests, req, next);
2556 return res;
2560 * If it's connected already and we are the first in the queue,
2561 * then we can dispatch this request immediately. Otherwise, it
2562 * will be dispatched once the pending requests are completed.
2564 if (TAILQ_FIRST(&evcon->requests) == req)
2565 evhttp_request_dispatch(evcon);
2567 return (0);
2570 void
2571 evhttp_cancel_request(struct evhttp_request *req)
2573 struct evhttp_connection *evcon = req->evcon;
2574 if (evcon != NULL) {
2575 /* We need to remove it from the connection */
2576 if (TAILQ_FIRST(&evcon->requests) == req) {
2577 /* it's currently being worked on, so reset
2578 * the connection.
2580 evhttp_connection_fail_(evcon,
2581 EVREQ_HTTP_REQUEST_CANCEL);
2583 /* connection fail freed the request */
2584 return;
2585 } else {
2586 /* otherwise, we can just remove it from the
2587 * queue
2589 TAILQ_REMOVE(&evcon->requests, req, next);
2593 evhttp_request_free_auto(req);
2597 * Reads data from file descriptor into request structure
2598 * Request structure needs to be set up correctly.
2601 void
2602 evhttp_start_read_(struct evhttp_connection *evcon)
2604 bufferevent_disable(evcon->bufev, EV_WRITE);
2605 bufferevent_enable(evcon->bufev, EV_READ);
2607 evcon->state = EVCON_READING_FIRSTLINE;
2608 /* Reset the bufferevent callbacks */
2609 bufferevent_setcb(evcon->bufev,
2610 evhttp_read_cb,
2611 evhttp_write_cb,
2612 evhttp_error_cb,
2613 evcon);
2615 /* If there's still data pending, process it next time through the
2616 * loop. Don't do it now; that could get recusive. */
2617 if (evbuffer_get_length(bufferevent_get_input(evcon->bufev))) {
2618 event_deferred_cb_schedule_(get_deferred_queue(evcon),
2619 &evcon->read_more_deferred_cb);
2623 static void
2624 evhttp_send_done(struct evhttp_connection *evcon, void *arg)
2626 int need_close;
2627 struct evhttp_request *req = TAILQ_FIRST(&evcon->requests);
2628 TAILQ_REMOVE(&evcon->requests, req, next);
2630 if (req->on_complete_cb != NULL) {
2631 req->on_complete_cb(req, req->on_complete_cb_arg);
2634 need_close =
2635 (REQ_VERSION_BEFORE(req, 1, 1) &&
2636 !evhttp_is_connection_keepalive(req->input_headers)) ||
2637 evhttp_is_request_connection_close(req);
2639 EVUTIL_ASSERT(req->flags & EVHTTP_REQ_OWN_CONNECTION);
2640 evhttp_request_free(req);
2642 if (need_close) {
2643 evhttp_connection_free(evcon);
2644 return;
2647 /* we have a persistent connection; try to accept another request. */
2648 if (evhttp_associate_new_request_with_connection(evcon) == -1) {
2649 evhttp_connection_free(evcon);
2654 * Returns an error page.
2657 void
2658 evhttp_send_error(struct evhttp_request *req, int error, const char *reason)
2661 #define ERR_FORMAT "<HTML><HEAD>\n" \
2662 "<TITLE>%d %s</TITLE>\n" \
2663 "</HEAD><BODY>\n" \
2664 "<H1>%s</H1>\n" \
2665 "</BODY></HTML>\n"
2667 struct evbuffer *buf = evbuffer_new();
2668 if (buf == NULL) {
2669 /* if we cannot allocate memory; we just drop the connection */
2670 evhttp_connection_free(req->evcon);
2671 return;
2673 if (reason == NULL) {
2674 reason = evhttp_response_phrase_internal(error);
2677 evhttp_response_code_(req, error, reason);
2679 evbuffer_add_printf(buf, ERR_FORMAT, error, reason, reason);
2681 evhttp_send_page_(req, buf);
2683 evbuffer_free(buf);
2684 #undef ERR_FORMAT
2687 /* Requires that headers and response code are already set up */
2689 static inline void
2690 evhttp_send(struct evhttp_request *req, struct evbuffer *databuf)
2692 struct evhttp_connection *evcon = req->evcon;
2694 if (evcon == NULL) {
2695 evhttp_request_free(req);
2696 return;
2699 EVUTIL_ASSERT(TAILQ_FIRST(&evcon->requests) == req);
2701 /* we expect no more calls form the user on this request */
2702 req->userdone = 1;
2704 /* xxx: not sure if we really should expose the data buffer this way */
2705 if (databuf != NULL)
2706 evbuffer_add_buffer(req->output_buffer, databuf);
2708 /* Adds headers to the response */
2709 evhttp_make_header(evcon, req);
2711 evhttp_write_buffer(evcon, evhttp_send_done, NULL);
2714 void
2715 evhttp_send_reply(struct evhttp_request *req, int code, const char *reason,
2716 struct evbuffer *databuf)
2718 evhttp_response_code_(req, code, reason);
2720 evhttp_send(req, databuf);
2723 void
2724 evhttp_send_reply_start(struct evhttp_request *req, int code,
2725 const char *reason)
2727 evhttp_response_code_(req, code, reason);
2728 if (evhttp_find_header(req->output_headers, "Content-Length") == NULL &&
2729 REQ_VERSION_ATLEAST(req, 1, 1) &&
2730 evhttp_response_needs_body(req)) {
2732 * prefer HTTP/1.1 chunked encoding to closing the connection;
2733 * note RFC 2616 section 4.4 forbids it with Content-Length:
2734 * and it's not necessary then anyway.
2736 evhttp_add_header(req->output_headers, "Transfer-Encoding",
2737 "chunked");
2738 req->chunked = 1;
2739 } else {
2740 req->chunked = 0;
2742 evhttp_make_header(req->evcon, req);
2743 evhttp_write_buffer(req->evcon, NULL, NULL);
2746 void
2747 evhttp_send_reply_chunk_with_cb(struct evhttp_request *req, struct evbuffer *databuf,
2748 void (*cb)(struct evhttp_connection *, void *), void *arg)
2750 struct evhttp_connection *evcon = req->evcon;
2751 struct evbuffer *output;
2753 if (evcon == NULL)
2754 return;
2756 output = bufferevent_get_output(evcon->bufev);
2758 if (evbuffer_get_length(databuf) == 0)
2759 return;
2760 if (!evhttp_response_needs_body(req))
2761 return;
2762 if (req->chunked) {
2763 evbuffer_add_printf(output, "%x\r\n",
2764 (unsigned)evbuffer_get_length(databuf));
2766 evbuffer_add_buffer(output, databuf);
2767 if (req->chunked) {
2768 evbuffer_add(output, "\r\n", 2);
2770 evhttp_write_buffer(evcon, cb, arg);
2773 void
2774 evhttp_send_reply_chunk(struct evhttp_request *req, struct evbuffer *databuf)
2776 evhttp_send_reply_chunk_with_cb(req, databuf, NULL, NULL);
2778 void
2779 evhttp_send_reply_end(struct evhttp_request *req)
2781 struct evhttp_connection *evcon = req->evcon;
2782 struct evbuffer *output;
2784 if (evcon == NULL) {
2785 evhttp_request_free(req);
2786 return;
2789 output = bufferevent_get_output(evcon->bufev);
2791 /* we expect no more calls form the user on this request */
2792 req->userdone = 1;
2794 if (req->chunked) {
2795 evbuffer_add(output, "0\r\n\r\n", 5);
2796 evhttp_write_buffer(req->evcon, evhttp_send_done, NULL);
2797 req->chunked = 0;
2798 } else if (evbuffer_get_length(output) == 0) {
2799 /* let the connection know that we are done with the request */
2800 evhttp_send_done(evcon, NULL);
2801 } else {
2802 /* make the callback execute after all data has been written */
2803 evcon->cb = evhttp_send_done;
2804 evcon->cb_arg = NULL;
2808 static const char *informational_phrases[] = {
2809 /* 100 */ "Continue",
2810 /* 101 */ "Switching Protocols"
2813 static const char *success_phrases[] = {
2814 /* 200 */ "OK",
2815 /* 201 */ "Created",
2816 /* 202 */ "Accepted",
2817 /* 203 */ "Non-Authoritative Information",
2818 /* 204 */ "No Content",
2819 /* 205 */ "Reset Content",
2820 /* 206 */ "Partial Content"
2823 static const char *redirection_phrases[] = {
2824 /* 300 */ "Multiple Choices",
2825 /* 301 */ "Moved Permanently",
2826 /* 302 */ "Found",
2827 /* 303 */ "See Other",
2828 /* 304 */ "Not Modified",
2829 /* 305 */ "Use Proxy",
2830 /* 307 */ "Temporary Redirect"
2833 static const char *client_error_phrases[] = {
2834 /* 400 */ "Bad Request",
2835 /* 401 */ "Unauthorized",
2836 /* 402 */ "Payment Required",
2837 /* 403 */ "Forbidden",
2838 /* 404 */ "Not Found",
2839 /* 405 */ "Method Not Allowed",
2840 /* 406 */ "Not Acceptable",
2841 /* 407 */ "Proxy Authentication Required",
2842 /* 408 */ "Request Time-out",
2843 /* 409 */ "Conflict",
2844 /* 410 */ "Gone",
2845 /* 411 */ "Length Required",
2846 /* 412 */ "Precondition Failed",
2847 /* 413 */ "Request Entity Too Large",
2848 /* 414 */ "Request-URI Too Large",
2849 /* 415 */ "Unsupported Media Type",
2850 /* 416 */ "Requested range not satisfiable",
2851 /* 417 */ "Expectation Failed"
2854 static const char *server_error_phrases[] = {
2855 /* 500 */ "Internal Server Error",
2856 /* 501 */ "Not Implemented",
2857 /* 502 */ "Bad Gateway",
2858 /* 503 */ "Service Unavailable",
2859 /* 504 */ "Gateway Time-out",
2860 /* 505 */ "HTTP Version not supported"
2863 struct response_class {
2864 const char *name;
2865 size_t num_responses;
2866 const char **responses;
2869 #ifndef MEMBERSOF
2870 #define MEMBERSOF(x) (sizeof(x)/sizeof(x[0]))
2871 #endif
2873 static const struct response_class response_classes[] = {
2874 /* 1xx */ { "Informational", MEMBERSOF(informational_phrases), informational_phrases },
2875 /* 2xx */ { "Success", MEMBERSOF(success_phrases), success_phrases },
2876 /* 3xx */ { "Redirection", MEMBERSOF(redirection_phrases), redirection_phrases },
2877 /* 4xx */ { "Client Error", MEMBERSOF(client_error_phrases), client_error_phrases },
2878 /* 5xx */ { "Server Error", MEMBERSOF(server_error_phrases), server_error_phrases }
2881 static const char *
2882 evhttp_response_phrase_internal(int code)
2884 int klass = code / 100 - 1;
2885 int subcode = code % 100;
2887 /* Unknown class - can't do any better here */
2888 if (klass < 0 || klass >= (int) MEMBERSOF(response_classes))
2889 return "Unknown Status Class";
2891 /* Unknown sub-code, return class name at least */
2892 if (subcode >= (int) response_classes[klass].num_responses)
2893 return response_classes[klass].name;
2895 return response_classes[klass].responses[subcode];
2898 void
2899 evhttp_response_code_(struct evhttp_request *req, int code, const char *reason)
2901 req->kind = EVHTTP_RESPONSE;
2902 req->response_code = code;
2903 if (req->response_code_line != NULL)
2904 mm_free(req->response_code_line);
2905 if (reason == NULL)
2906 reason = evhttp_response_phrase_internal(code);
2907 req->response_code_line = mm_strdup(reason);
2908 if (req->response_code_line == NULL) {
2909 event_warn("%s: strdup", __func__);
2910 /* XXX what else can we do? */
2914 void
2915 evhttp_send_page_(struct evhttp_request *req, struct evbuffer *databuf)
2917 if (!req->major || !req->minor) {
2918 req->major = 1;
2919 req->minor = 1;
2922 if (req->kind != EVHTTP_RESPONSE)
2923 evhttp_response_code_(req, 200, "OK");
2925 evhttp_clear_headers(req->output_headers);
2926 evhttp_add_header(req->output_headers, "Content-Type", "text/html");
2927 evhttp_add_header(req->output_headers, "Connection", "close");
2929 evhttp_send(req, databuf);
2932 static const char uri_chars[256] = {
2933 /* 0 */
2934 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2935 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2936 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0,
2937 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,
2938 /* 64 */
2939 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2940 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1,
2941 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2942 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0,
2943 /* 128 */
2944 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2945 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2946 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2947 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2948 /* 192 */
2949 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2950 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2951 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2952 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2955 #define CHAR_IS_UNRESERVED(c) \
2956 (uri_chars[(unsigned char)(c)])
2959 * Helper functions to encode/decode a string for inclusion in a URI.
2960 * The returned string must be freed by the caller.
2962 char *
2963 evhttp_uriencode(const char *uri, ev_ssize_t len, int space_as_plus)
2965 struct evbuffer *buf = evbuffer_new();
2966 const char *p, *end;
2967 char *result;
2969 if (buf == NULL)
2970 return (NULL);
2972 if (len >= 0)
2973 end = uri+len;
2974 else
2975 end = uri+strlen(uri);
2977 for (p = uri; p < end; p++) {
2978 if (CHAR_IS_UNRESERVED(*p)) {
2979 evbuffer_add(buf, p, 1);
2980 } else if (*p == ' ' && space_as_plus) {
2981 evbuffer_add(buf, "+", 1);
2982 } else {
2983 evbuffer_add_printf(buf, "%%%02X", (unsigned char)(*p));
2986 evbuffer_add(buf, "", 1); /* NUL-terminator. */
2987 result = mm_malloc(evbuffer_get_length(buf));
2988 if (result)
2989 evbuffer_remove(buf, result, evbuffer_get_length(buf));
2990 evbuffer_free(buf);
2992 return (result);
2995 char *
2996 evhttp_encode_uri(const char *str)
2998 return evhttp_uriencode(str, -1, 0);
3002 * @param decode_plus_ctl: if 1, we decode plus into space. If 0, we don't.
3003 * If -1, when true we transform plus to space only after we've seen
3004 * a ?. -1 is deprecated.
3005 * @return the number of bytes written to 'ret'.
3008 evhttp_decode_uri_internal(
3009 const char *uri, size_t length, char *ret, int decode_plus_ctl)
3011 char c;
3012 int j;
3013 int decode_plus = (decode_plus_ctl == 1) ? 1: 0;
3014 unsigned i;
3016 for (i = j = 0; i < length; i++) {
3017 c = uri[i];
3018 if (c == '?') {
3019 if (decode_plus_ctl < 0)
3020 decode_plus = 1;
3021 } else if (c == '+' && decode_plus) {
3022 c = ' ';
3023 } else if ((i + 2) < length && c == '%' &&
3024 EVUTIL_ISXDIGIT_(uri[i+1]) && EVUTIL_ISXDIGIT_(uri[i+2])) {
3025 char tmp[3];
3026 tmp[0] = uri[i+1];
3027 tmp[1] = uri[i+2];
3028 tmp[2] = '\0';
3029 c = (char)strtol(tmp, NULL, 16);
3030 i += 2;
3032 ret[j++] = c;
3034 ret[j] = '\0';
3036 return (j);
3039 /* deprecated */
3040 char *
3041 evhttp_decode_uri(const char *uri)
3043 char *ret;
3045 if ((ret = mm_malloc(strlen(uri) + 1)) == NULL) {
3046 event_warn("%s: malloc(%lu)", __func__,
3047 (unsigned long)(strlen(uri) + 1));
3048 return (NULL);
3051 evhttp_decode_uri_internal(uri, strlen(uri),
3052 ret, -1 /*always_decode_plus*/);
3054 return (ret);
3057 char *
3058 evhttp_uridecode(const char *uri, int decode_plus, size_t *size_out)
3060 char *ret;
3061 int n;
3063 if ((ret = mm_malloc(strlen(uri) + 1)) == NULL) {
3064 event_warn("%s: malloc(%lu)", __func__,
3065 (unsigned long)(strlen(uri) + 1));
3066 return (NULL);
3069 n = evhttp_decode_uri_internal(uri, strlen(uri),
3070 ret, !!decode_plus/*always_decode_plus*/);
3072 if (size_out) {
3073 EVUTIL_ASSERT(n >= 0);
3074 *size_out = (size_t)n;
3077 return (ret);
3081 * Helper function to parse out arguments in a query.
3082 * The arguments are separated by key and value.
3085 static int
3086 evhttp_parse_query_impl(const char *str, struct evkeyvalq *headers,
3087 int is_whole_uri)
3089 char *line=NULL;
3090 char *argument;
3091 char *p;
3092 const char *query_part;
3093 int result = -1;
3094 struct evhttp_uri *uri=NULL;
3096 TAILQ_INIT(headers);
3098 if (is_whole_uri) {
3099 uri = evhttp_uri_parse(str);
3100 if (!uri)
3101 goto error;
3102 query_part = evhttp_uri_get_query(uri);
3103 } else {
3104 query_part = str;
3107 /* No arguments - we are done */
3108 if (!query_part || !strlen(query_part)) {
3109 result = 0;
3110 goto done;
3113 if ((line = mm_strdup(query_part)) == NULL) {
3114 event_warn("%s: strdup", __func__);
3115 goto error;
3118 p = argument = line;
3119 while (p != NULL && *p != '\0') {
3120 char *key, *value, *decoded_value;
3121 argument = strsep(&p, "&");
3123 value = argument;
3124 key = strsep(&value, "=");
3125 if (value == NULL || *key == '\0') {
3126 goto error;
3129 if ((decoded_value = mm_malloc(strlen(value) + 1)) == NULL) {
3130 event_warn("%s: mm_malloc", __func__);
3131 goto error;
3133 evhttp_decode_uri_internal(value, strlen(value),
3134 decoded_value, 1 /*always_decode_plus*/);
3135 event_debug(("Query Param: %s -> %s\n", key, decoded_value));
3136 evhttp_add_header_internal(headers, key, decoded_value);
3137 mm_free(decoded_value);
3140 result = 0;
3141 goto done;
3142 error:
3143 evhttp_clear_headers(headers);
3144 done:
3145 if (line)
3146 mm_free(line);
3147 if (uri)
3148 evhttp_uri_free(uri);
3149 return result;
3153 evhttp_parse_query(const char *uri, struct evkeyvalq *headers)
3155 return evhttp_parse_query_impl(uri, headers, 1);
3158 evhttp_parse_query_str(const char *uri, struct evkeyvalq *headers)
3160 return evhttp_parse_query_impl(uri, headers, 0);
3163 static struct evhttp_cb *
3164 evhttp_dispatch_callback(struct httpcbq *callbacks, struct evhttp_request *req)
3166 struct evhttp_cb *cb;
3167 size_t offset = 0;
3168 char *translated;
3169 const char *path;
3171 /* Test for different URLs */
3172 path = evhttp_uri_get_path(req->uri_elems);
3173 offset = strlen(path);
3174 if ((translated = mm_malloc(offset + 1)) == NULL)
3175 return (NULL);
3176 evhttp_decode_uri_internal(path, offset, translated,
3177 0 /* decode_plus */);
3179 TAILQ_FOREACH(cb, callbacks, next) {
3180 if (!strcmp(cb->what, translated)) {
3181 mm_free(translated);
3182 return (cb);
3186 mm_free(translated);
3187 return (NULL);
3191 static int
3192 prefix_suffix_match(const char *pattern, const char *name, int ignorecase)
3194 char c;
3196 while (1) {
3197 switch (c = *pattern++) {
3198 case '\0':
3199 return *name == '\0';
3201 case '*':
3202 while (*name != '\0') {
3203 if (prefix_suffix_match(pattern, name,
3204 ignorecase))
3205 return (1);
3206 ++name;
3208 return (0);
3209 default:
3210 if (c != *name) {
3211 if (!ignorecase ||
3212 EVUTIL_TOLOWER_(c) != EVUTIL_TOLOWER_(*name))
3213 return (0);
3215 ++name;
3218 /* NOTREACHED */
3222 Search the vhost hierarchy beginning with http for a server alias
3223 matching hostname. If a match is found, and outhttp is non-null,
3224 outhttp is set to the matching http object and 1 is returned.
3227 static int
3228 evhttp_find_alias(struct evhttp *http, struct evhttp **outhttp,
3229 const char *hostname)
3231 struct evhttp_server_alias *alias;
3232 struct evhttp *vhost;
3234 TAILQ_FOREACH(alias, &http->aliases, next) {
3235 /* XXX Do we need to handle IP addresses? */
3236 if (!evutil_ascii_strcasecmp(alias->alias, hostname)) {
3237 if (outhttp)
3238 *outhttp = http;
3239 return 1;
3243 /* XXX It might be good to avoid recursion here, but I don't
3244 see a way to do that w/o a list. */
3245 TAILQ_FOREACH(vhost, &http->virtualhosts, next_vhost) {
3246 if (evhttp_find_alias(vhost, outhttp, hostname))
3247 return 1;
3250 return 0;
3254 Attempts to find the best http object to handle a request for a hostname.
3255 All aliases for the root http object and vhosts are searched for an exact
3256 match. Then, the vhost hierarchy is traversed again for a matching
3257 pattern.
3259 If an alias or vhost is matched, 1 is returned, and outhttp, if non-null,
3260 is set with the best matching http object. If there are no matches, the
3261 root http object is stored in outhttp and 0 is returned.
3264 static int
3265 evhttp_find_vhost(struct evhttp *http, struct evhttp **outhttp,
3266 const char *hostname)
3268 struct evhttp *vhost;
3269 struct evhttp *oldhttp;
3270 int match_found = 0;
3272 if (evhttp_find_alias(http, outhttp, hostname))
3273 return 1;
3275 do {
3276 oldhttp = http;
3277 TAILQ_FOREACH(vhost, &http->virtualhosts, next_vhost) {
3278 if (prefix_suffix_match(vhost->vhost_pattern,
3279 hostname, 1 /* ignorecase */)) {
3280 http = vhost;
3281 match_found = 1;
3282 break;
3285 } while (oldhttp != http);
3287 if (outhttp)
3288 *outhttp = http;
3290 return match_found;
3293 static void
3294 evhttp_handle_request(struct evhttp_request *req, void *arg)
3296 struct evhttp *http = arg;
3297 struct evhttp_cb *cb = NULL;
3298 const char *hostname;
3300 /* we have a new request on which the user needs to take action */
3301 req->userdone = 0;
3303 if (req->type == 0 || req->uri == NULL) {
3304 evhttp_send_error(req, HTTP_BADREQUEST, NULL);
3305 return;
3308 if ((http->allowed_methods & req->type) == 0) {
3309 event_debug(("Rejecting disallowed method %x (allowed: %x)\n",
3310 (unsigned)req->type, (unsigned)http->allowed_methods));
3311 evhttp_send_error(req, HTTP_NOTIMPLEMENTED, NULL);
3312 return;
3315 /* handle potential virtual hosts */
3316 hostname = evhttp_request_get_host(req);
3317 if (hostname != NULL) {
3318 evhttp_find_vhost(http, &http, hostname);
3321 if ((cb = evhttp_dispatch_callback(&http->callbacks, req)) != NULL) {
3322 (*cb->cb)(req, cb->cbarg);
3323 return;
3326 /* Generic call back */
3327 if (http->gencb) {
3328 (*http->gencb)(req, http->gencbarg);
3329 return;
3330 } else {
3331 /* We need to send a 404 here */
3332 #define ERR_FORMAT "<html><head>" \
3333 "<title>404 Not Found</title>" \
3334 "</head><body>" \
3335 "<h1>Not Found</h1>" \
3336 "<p>The requested URL %s was not found on this server.</p>"\
3337 "</body></html>\n"
3339 char *escaped_html;
3340 struct evbuffer *buf;
3342 if ((escaped_html = evhttp_htmlescape(req->uri)) == NULL) {
3343 evhttp_connection_free(req->evcon);
3344 return;
3347 if ((buf = evbuffer_new()) == NULL) {
3348 mm_free(escaped_html);
3349 evhttp_connection_free(req->evcon);
3350 return;
3353 evhttp_response_code_(req, HTTP_NOTFOUND, "Not Found");
3355 evbuffer_add_printf(buf, ERR_FORMAT, escaped_html);
3357 mm_free(escaped_html);
3359 evhttp_send_page_(req, buf);
3361 evbuffer_free(buf);
3362 #undef ERR_FORMAT
3366 /* Listener callback when a connection arrives at a server. */
3367 static void
3368 accept_socket_cb(struct evconnlistener *listener, evutil_socket_t nfd, struct sockaddr *peer_sa, int peer_socklen, void *arg)
3370 struct evhttp *http = arg;
3372 evhttp_get_request(http, nfd, peer_sa, peer_socklen);
3376 evhttp_bind_socket(struct evhttp *http, const char *address, ev_uint16_t port)
3378 struct evhttp_bound_socket *bound =
3379 evhttp_bind_socket_with_handle(http, address, port);
3380 if (bound == NULL)
3381 return (-1);
3382 return (0);
3385 struct evhttp_bound_socket *
3386 evhttp_bind_socket_with_handle(struct evhttp *http, const char *address, ev_uint16_t port)
3388 evutil_socket_t fd;
3389 struct evhttp_bound_socket *bound;
3391 if ((fd = bind_socket(address, port, 1 /*reuse*/)) == -1)
3392 return (NULL);
3394 if (listen(fd, 128) == -1) {
3395 event_sock_warn(fd, "%s: listen", __func__);
3396 evutil_closesocket(fd);
3397 return (NULL);
3400 bound = evhttp_accept_socket_with_handle(http, fd);
3402 if (bound != NULL) {
3403 event_debug(("Bound to port %d - Awaiting connections ... ",
3404 port));
3405 return (bound);
3408 return (NULL);
3412 evhttp_accept_socket(struct evhttp *http, evutil_socket_t fd)
3414 struct evhttp_bound_socket *bound =
3415 evhttp_accept_socket_with_handle(http, fd);
3416 if (bound == NULL)
3417 return (-1);
3418 return (0);
3421 void
3422 evhttp_foreach_bound_socket(struct evhttp *http,
3423 evhttp_bound_socket_foreach_fn *function,
3424 void *argument)
3426 struct evhttp_bound_socket *bound;
3428 TAILQ_FOREACH(bound, &http->sockets, next)
3429 function(bound, argument);
3432 struct evhttp_bound_socket *
3433 evhttp_accept_socket_with_handle(struct evhttp *http, evutil_socket_t fd)
3435 struct evhttp_bound_socket *bound;
3436 struct evconnlistener *listener;
3437 const int flags =
3438 LEV_OPT_REUSEABLE|LEV_OPT_CLOSE_ON_EXEC|LEV_OPT_CLOSE_ON_FREE;
3440 listener = evconnlistener_new(http->base, NULL, NULL,
3441 flags,
3442 0, /* Backlog is '0' because we already said 'listen' */
3443 fd);
3444 if (!listener)
3445 return (NULL);
3447 bound = evhttp_bind_listener(http, listener);
3448 if (!bound) {
3449 evconnlistener_free(listener);
3450 return (NULL);
3452 return (bound);
3455 struct evhttp_bound_socket *
3456 evhttp_bind_listener(struct evhttp *http, struct evconnlistener *listener)
3458 struct evhttp_bound_socket *bound;
3460 bound = mm_malloc(sizeof(struct evhttp_bound_socket));
3461 if (bound == NULL)
3462 return (NULL);
3464 bound->listener = listener;
3465 TAILQ_INSERT_TAIL(&http->sockets, bound, next);
3467 evconnlistener_set_cb(listener, accept_socket_cb, http);
3468 return bound;
3471 evutil_socket_t
3472 evhttp_bound_socket_get_fd(struct evhttp_bound_socket *bound)
3474 return evconnlistener_get_fd(bound->listener);
3477 struct evconnlistener *
3478 evhttp_bound_socket_get_listener(struct evhttp_bound_socket *bound)
3480 return bound->listener;
3483 void
3484 evhttp_del_accept_socket(struct evhttp *http, struct evhttp_bound_socket *bound)
3486 TAILQ_REMOVE(&http->sockets, bound, next);
3487 evconnlistener_free(bound->listener);
3488 mm_free(bound);
3491 static struct evhttp*
3492 evhttp_new_object(void)
3494 struct evhttp *http = NULL;
3496 if ((http = mm_calloc(1, sizeof(struct evhttp))) == NULL) {
3497 event_warn("%s: calloc", __func__);
3498 return (NULL);
3501 evutil_timerclear(&http->timeout);
3502 evhttp_set_max_headers_size(http, EV_SIZE_MAX);
3503 evhttp_set_max_body_size(http, EV_SIZE_MAX);
3504 evhttp_set_default_content_type(http, "text/html; charset=ISO-8859-1");
3505 evhttp_set_allowed_methods(http,
3506 EVHTTP_REQ_GET |
3507 EVHTTP_REQ_POST |
3508 EVHTTP_REQ_HEAD |
3509 EVHTTP_REQ_PUT |
3510 EVHTTP_REQ_DELETE);
3512 TAILQ_INIT(&http->sockets);
3513 TAILQ_INIT(&http->callbacks);
3514 TAILQ_INIT(&http->connections);
3515 TAILQ_INIT(&http->virtualhosts);
3516 TAILQ_INIT(&http->aliases);
3518 return (http);
3521 struct evhttp *
3522 evhttp_new(struct event_base *base)
3524 struct evhttp *http = NULL;
3526 http = evhttp_new_object();
3527 if (http == NULL)
3528 return (NULL);
3529 http->base = base;
3531 return (http);
3535 * Start a web server on the specified address and port.
3538 struct evhttp *
3539 evhttp_start(const char *address, unsigned short port)
3541 struct evhttp *http = NULL;
3543 http = evhttp_new_object();
3544 if (http == NULL)
3545 return (NULL);
3546 if (evhttp_bind_socket(http, address, port) == -1) {
3547 mm_free(http);
3548 return (NULL);
3551 return (http);
3554 void
3555 evhttp_free(struct evhttp* http)
3557 struct evhttp_cb *http_cb;
3558 struct evhttp_connection *evcon;
3559 struct evhttp_bound_socket *bound;
3560 struct evhttp* vhost;
3561 struct evhttp_server_alias *alias;
3563 /* Remove the accepting part */
3564 while ((bound = TAILQ_FIRST(&http->sockets)) != NULL) {
3565 TAILQ_REMOVE(&http->sockets, bound, next);
3567 evconnlistener_free(bound->listener);
3569 mm_free(bound);
3572 while ((evcon = TAILQ_FIRST(&http->connections)) != NULL) {
3573 /* evhttp_connection_free removes the connection */
3574 evhttp_connection_free(evcon);
3577 while ((http_cb = TAILQ_FIRST(&http->callbacks)) != NULL) {
3578 TAILQ_REMOVE(&http->callbacks, http_cb, next);
3579 mm_free(http_cb->what);
3580 mm_free(http_cb);
3583 while ((vhost = TAILQ_FIRST(&http->virtualhosts)) != NULL) {
3584 TAILQ_REMOVE(&http->virtualhosts, vhost, next_vhost);
3586 evhttp_free(vhost);
3589 if (http->vhost_pattern != NULL)
3590 mm_free(http->vhost_pattern);
3592 while ((alias = TAILQ_FIRST(&http->aliases)) != NULL) {
3593 TAILQ_REMOVE(&http->aliases, alias, next);
3594 mm_free(alias->alias);
3595 mm_free(alias);
3598 mm_free(http);
3602 evhttp_add_virtual_host(struct evhttp* http, const char *pattern,
3603 struct evhttp* vhost)
3605 /* a vhost can only be a vhost once and should not have bound sockets */
3606 if (vhost->vhost_pattern != NULL ||
3607 TAILQ_FIRST(&vhost->sockets) != NULL)
3608 return (-1);
3610 vhost->vhost_pattern = mm_strdup(pattern);
3611 if (vhost->vhost_pattern == NULL)
3612 return (-1);
3614 TAILQ_INSERT_TAIL(&http->virtualhosts, vhost, next_vhost);
3616 return (0);
3620 evhttp_remove_virtual_host(struct evhttp* http, struct evhttp* vhost)
3622 if (vhost->vhost_pattern == NULL)
3623 return (-1);
3625 TAILQ_REMOVE(&http->virtualhosts, vhost, next_vhost);
3627 mm_free(vhost->vhost_pattern);
3628 vhost->vhost_pattern = NULL;
3630 return (0);
3634 evhttp_add_server_alias(struct evhttp *http, const char *alias)
3636 struct evhttp_server_alias *evalias;
3638 evalias = mm_calloc(1, sizeof(*evalias));
3639 if (!evalias)
3640 return -1;
3642 evalias->alias = mm_strdup(alias);
3643 if (!evalias->alias) {
3644 mm_free(evalias);
3645 return -1;
3648 TAILQ_INSERT_TAIL(&http->aliases, evalias, next);
3650 return 0;
3654 evhttp_remove_server_alias(struct evhttp *http, const char *alias)
3656 struct evhttp_server_alias *evalias;
3658 TAILQ_FOREACH(evalias, &http->aliases, next) {
3659 if (evutil_ascii_strcasecmp(evalias->alias, alias) == 0) {
3660 TAILQ_REMOVE(&http->aliases, evalias, next);
3661 mm_free(evalias->alias);
3662 mm_free(evalias);
3663 return 0;
3667 return -1;
3670 void
3671 evhttp_set_timeout(struct evhttp* http, int timeout_in_secs)
3673 if (timeout_in_secs == -1) {
3674 evhttp_set_timeout_tv(http, NULL);
3675 } else {
3676 struct timeval tv;
3677 tv.tv_sec = timeout_in_secs;
3678 tv.tv_usec = 0;
3679 evhttp_set_timeout_tv(http, &tv);
3683 void
3684 evhttp_set_timeout_tv(struct evhttp* http, const struct timeval* tv)
3686 if (tv) {
3687 http->timeout = *tv;
3688 } else {
3689 evutil_timerclear(&http->timeout);
3693 void
3694 evhttp_set_max_headers_size(struct evhttp* http, ev_ssize_t max_headers_size)
3696 if (max_headers_size < 0)
3697 http->default_max_headers_size = EV_SIZE_MAX;
3698 else
3699 http->default_max_headers_size = max_headers_size;
3702 void
3703 evhttp_set_max_body_size(struct evhttp* http, ev_ssize_t max_body_size)
3705 if (max_body_size < 0)
3706 http->default_max_body_size = EV_UINT64_MAX;
3707 else
3708 http->default_max_body_size = max_body_size;
3711 void
3712 evhttp_set_default_content_type(struct evhttp *http,
3713 const char *content_type) {
3714 http->default_content_type = content_type;
3717 void
3718 evhttp_set_allowed_methods(struct evhttp* http, ev_uint16_t methods)
3720 http->allowed_methods = methods;
3724 evhttp_set_cb(struct evhttp *http, const char *uri,
3725 void (*cb)(struct evhttp_request *, void *), void *cbarg)
3727 struct evhttp_cb *http_cb;
3729 TAILQ_FOREACH(http_cb, &http->callbacks, next) {
3730 if (strcmp(http_cb->what, uri) == 0)
3731 return (-1);
3734 if ((http_cb = mm_calloc(1, sizeof(struct evhttp_cb))) == NULL) {
3735 event_warn("%s: calloc", __func__);
3736 return (-2);
3739 http_cb->what = mm_strdup(uri);
3740 if (http_cb->what == NULL) {
3741 event_warn("%s: strdup", __func__);
3742 mm_free(http_cb);
3743 return (-3);
3745 http_cb->cb = cb;
3746 http_cb->cbarg = cbarg;
3748 TAILQ_INSERT_TAIL(&http->callbacks, http_cb, next);
3750 return (0);
3754 evhttp_del_cb(struct evhttp *http, const char *uri)
3756 struct evhttp_cb *http_cb;
3758 TAILQ_FOREACH(http_cb, &http->callbacks, next) {
3759 if (strcmp(http_cb->what, uri) == 0)
3760 break;
3762 if (http_cb == NULL)
3763 return (-1);
3765 TAILQ_REMOVE(&http->callbacks, http_cb, next);
3766 mm_free(http_cb->what);
3767 mm_free(http_cb);
3769 return (0);
3772 void
3773 evhttp_set_gencb(struct evhttp *http,
3774 void (*cb)(struct evhttp_request *, void *), void *cbarg)
3776 http->gencb = cb;
3777 http->gencbarg = cbarg;
3780 void
3781 evhttp_set_bevcb(struct evhttp *http,
3782 struct bufferevent* (*cb)(struct event_base *, void *), void *cbarg)
3784 http->bevcb = cb;
3785 http->bevcbarg = cbarg;
3789 * Request related functions
3792 struct evhttp_request *
3793 evhttp_request_new(void (*cb)(struct evhttp_request *, void *), void *arg)
3795 struct evhttp_request *req = NULL;
3797 /* Allocate request structure */
3798 if ((req = mm_calloc(1, sizeof(struct evhttp_request))) == NULL) {
3799 event_warn("%s: calloc", __func__);
3800 goto error;
3803 req->headers_size = 0;
3804 req->body_size = 0;
3806 req->kind = EVHTTP_RESPONSE;
3807 req->input_headers = mm_calloc(1, sizeof(struct evkeyvalq));
3808 if (req->input_headers == NULL) {
3809 event_warn("%s: calloc", __func__);
3810 goto error;
3812 TAILQ_INIT(req->input_headers);
3814 req->output_headers = mm_calloc(1, sizeof(struct evkeyvalq));
3815 if (req->output_headers == NULL) {
3816 event_warn("%s: calloc", __func__);
3817 goto error;
3819 TAILQ_INIT(req->output_headers);
3821 if ((req->input_buffer = evbuffer_new()) == NULL) {
3822 event_warn("%s: evbuffer_new", __func__);
3823 goto error;
3826 if ((req->output_buffer = evbuffer_new()) == NULL) {
3827 event_warn("%s: evbuffer_new", __func__);
3828 goto error;
3831 req->cb = cb;
3832 req->cb_arg = arg;
3834 return (req);
3836 error:
3837 if (req != NULL)
3838 evhttp_request_free(req);
3839 return (NULL);
3842 void
3843 evhttp_request_free(struct evhttp_request *req)
3845 if ((req->flags & EVHTTP_REQ_DEFER_FREE) != 0) {
3846 req->flags |= EVHTTP_REQ_NEEDS_FREE;
3847 return;
3850 if (req->remote_host != NULL)
3851 mm_free(req->remote_host);
3852 if (req->uri != NULL)
3853 mm_free(req->uri);
3854 if (req->uri_elems != NULL)
3855 evhttp_uri_free(req->uri_elems);
3856 if (req->response_code_line != NULL)
3857 mm_free(req->response_code_line);
3858 if (req->host_cache != NULL)
3859 mm_free(req->host_cache);
3861 evhttp_clear_headers(req->input_headers);
3862 mm_free(req->input_headers);
3864 evhttp_clear_headers(req->output_headers);
3865 mm_free(req->output_headers);
3867 if (req->input_buffer != NULL)
3868 evbuffer_free(req->input_buffer);
3870 if (req->output_buffer != NULL)
3871 evbuffer_free(req->output_buffer);
3873 mm_free(req);
3876 void
3877 evhttp_request_own(struct evhttp_request *req)
3879 req->flags |= EVHTTP_USER_OWNED;
3883 evhttp_request_is_owned(struct evhttp_request *req)
3885 return (req->flags & EVHTTP_USER_OWNED) != 0;
3888 struct evhttp_connection *
3889 evhttp_request_get_connection(struct evhttp_request *req)
3891 return req->evcon;
3894 struct event_base *
3895 evhttp_connection_get_base(struct evhttp_connection *conn)
3897 return conn->base;
3900 void
3901 evhttp_request_set_chunked_cb(struct evhttp_request *req,
3902 void (*cb)(struct evhttp_request *, void *))
3904 req->chunk_cb = cb;
3907 void
3908 evhttp_request_set_header_cb(struct evhttp_request *req,
3909 int (*cb)(struct evhttp_request *, void *))
3911 req->header_cb = cb;
3914 void
3915 evhttp_request_set_error_cb(struct evhttp_request *req,
3916 void (*cb)(enum evhttp_request_error, void *))
3918 req->error_cb = cb;
3921 void
3922 evhttp_request_set_on_complete_cb(struct evhttp_request *req,
3923 void (*cb)(struct evhttp_request *, void *), void *cb_arg)
3925 req->on_complete_cb = cb;
3926 req->on_complete_cb_arg = cb_arg;
3930 * Allows for inspection of the request URI
3933 const char *
3934 evhttp_request_get_uri(const struct evhttp_request *req) {
3935 if (req->uri == NULL)
3936 event_debug(("%s: request %p has no uri\n", __func__, req));
3937 return (req->uri);
3940 const struct evhttp_uri *
3941 evhttp_request_get_evhttp_uri(const struct evhttp_request *req) {
3942 if (req->uri_elems == NULL)
3943 event_debug(("%s: request %p has no uri elems\n",
3944 __func__, req));
3945 return (req->uri_elems);
3948 const char *
3949 evhttp_request_get_host(struct evhttp_request *req)
3951 const char *host = NULL;
3953 if (req->host_cache)
3954 return req->host_cache;
3956 if (req->uri_elems)
3957 host = evhttp_uri_get_host(req->uri_elems);
3958 if (!host && req->input_headers) {
3959 const char *p;
3960 size_t len;
3962 host = evhttp_find_header(req->input_headers, "Host");
3963 /* The Host: header may include a port. Remove it here
3964 to be consistent with uri_elems case above. */
3965 if (host) {
3966 p = host + strlen(host) - 1;
3967 while (p > host && EVUTIL_ISDIGIT_(*p))
3968 --p;
3969 if (p > host && *p == ':') {
3970 len = p - host;
3971 req->host_cache = mm_malloc(len + 1);
3972 if (!req->host_cache) {
3973 event_warn("%s: malloc", __func__);
3974 return NULL;
3976 memcpy(req->host_cache, host, len);
3977 req->host_cache[len] = '\0';
3978 host = req->host_cache;
3983 return host;
3986 enum evhttp_cmd_type
3987 evhttp_request_get_command(const struct evhttp_request *req) {
3988 return (req->type);
3992 evhttp_request_get_response_code(const struct evhttp_request *req)
3994 return req->response_code;
3997 const char *
3998 evhttp_request_get_response_code_line(const struct evhttp_request *req)
4000 return req->response_code_line;
4003 /** Returns the input headers */
4004 struct evkeyvalq *evhttp_request_get_input_headers(struct evhttp_request *req)
4006 return (req->input_headers);
4009 /** Returns the output headers */
4010 struct evkeyvalq *evhttp_request_get_output_headers(struct evhttp_request *req)
4012 return (req->output_headers);
4015 /** Returns the input buffer */
4016 struct evbuffer *evhttp_request_get_input_buffer(struct evhttp_request *req)
4018 return (req->input_buffer);
4021 /** Returns the output buffer */
4022 struct evbuffer *evhttp_request_get_output_buffer(struct evhttp_request *req)
4024 return (req->output_buffer);
4029 * Takes a file descriptor to read a request from.
4030 * The callback is executed once the whole request has been read.
4033 static struct evhttp_connection*
4034 evhttp_get_request_connection(
4035 struct evhttp* http,
4036 evutil_socket_t fd, struct sockaddr *sa, ev_socklen_t salen)
4038 struct evhttp_connection *evcon;
4039 char *hostname = NULL, *portname = NULL;
4040 struct bufferevent* bev = NULL;
4042 name_from_addr(sa, salen, &hostname, &portname);
4043 if (hostname == NULL || portname == NULL) {
4044 if (hostname) mm_free(hostname);
4045 if (portname) mm_free(portname);
4046 return (NULL);
4049 event_debug(("%s: new request from %s:%s on "EV_SOCK_FMT"\n",
4050 __func__, hostname, portname, EV_SOCK_ARG(fd)));
4052 /* we need a connection object to put the http request on */
4053 if (http->bevcb != NULL) {
4054 bev = (*http->bevcb)(http->base, http->bevcbarg);
4056 evcon = evhttp_connection_base_bufferevent_new(
4057 http->base, NULL, bev, hostname, atoi(portname));
4058 mm_free(hostname);
4059 mm_free(portname);
4060 if (evcon == NULL)
4061 return (NULL);
4063 evcon->max_headers_size = http->default_max_headers_size;
4064 evcon->max_body_size = http->default_max_body_size;
4066 evcon->flags |= EVHTTP_CON_INCOMING;
4067 evcon->state = EVCON_READING_FIRSTLINE;
4069 evcon->fd = fd;
4071 bufferevent_enable(evcon->bufev, EV_READ);
4072 bufferevent_disable(evcon->bufev, EV_WRITE);
4073 bufferevent_setfd(evcon->bufev, fd);
4075 return (evcon);
4078 static int
4079 evhttp_associate_new_request_with_connection(struct evhttp_connection *evcon)
4081 struct evhttp *http = evcon->http_server;
4082 struct evhttp_request *req;
4083 if ((req = evhttp_request_new(evhttp_handle_request, http)) == NULL)
4084 return (-1);
4086 if ((req->remote_host = mm_strdup(evcon->address)) == NULL) {
4087 event_warn("%s: strdup", __func__);
4088 evhttp_request_free(req);
4089 return (-1);
4091 req->remote_port = evcon->port;
4093 req->evcon = evcon; /* the request ends up owning the connection */
4094 req->flags |= EVHTTP_REQ_OWN_CONNECTION;
4096 /* We did not present the request to the user user yet, so treat it as
4097 * if the user was done with the request. This allows us to free the
4098 * request on a persistent connection if the client drops it without
4099 * sending a request.
4101 req->userdone = 1;
4103 TAILQ_INSERT_TAIL(&evcon->requests, req, next);
4105 req->kind = EVHTTP_REQUEST;
4108 evhttp_start_read_(evcon);
4110 return (0);
4113 static void
4114 evhttp_get_request(struct evhttp *http, evutil_socket_t fd,
4115 struct sockaddr *sa, ev_socklen_t salen)
4117 struct evhttp_connection *evcon;
4119 evcon = evhttp_get_request_connection(http, fd, sa, salen);
4120 if (evcon == NULL) {
4121 event_sock_warn(fd, "%s: cannot get connection on "EV_SOCK_FMT,
4122 __func__, EV_SOCK_ARG(fd));
4123 evutil_closesocket(fd);
4124 return;
4127 /* the timeout can be used by the server to close idle connections */
4128 if (evutil_timerisset(&http->timeout))
4129 evhttp_connection_set_timeout_tv(evcon, &http->timeout);
4132 * if we want to accept more than one request on a connection,
4133 * we need to know which http server it belongs to.
4135 evcon->http_server = http;
4136 TAILQ_INSERT_TAIL(&http->connections, evcon, next);
4138 if (evhttp_associate_new_request_with_connection(evcon) == -1)
4139 evhttp_connection_free(evcon);
4144 * Network helper functions that we do not want to export to the rest of
4145 * the world.
4148 static void
4149 name_from_addr(struct sockaddr *sa, ev_socklen_t salen,
4150 char **phost, char **pport)
4152 char ntop[NI_MAXHOST];
4153 char strport[NI_MAXSERV];
4154 int ni_result;
4156 #ifdef EVENT__HAVE_GETNAMEINFO
4157 ni_result = getnameinfo(sa, salen,
4158 ntop, sizeof(ntop), strport, sizeof(strport),
4159 NI_NUMERICHOST|NI_NUMERICSERV);
4161 if (ni_result != 0) {
4162 #ifdef EAI_SYSTEM
4163 /* Windows doesn't have an EAI_SYSTEM. */
4164 if (ni_result == EAI_SYSTEM)
4165 event_err(1, "getnameinfo failed");
4166 else
4167 #endif
4168 event_errx(1, "getnameinfo failed: %s", gai_strerror(ni_result));
4169 return;
4171 #else
4172 ni_result = fake_getnameinfo(sa, salen,
4173 ntop, sizeof(ntop), strport, sizeof(strport),
4174 NI_NUMERICHOST|NI_NUMERICSERV);
4175 if (ni_result != 0)
4176 return;
4177 #endif
4179 *phost = mm_strdup(ntop);
4180 *pport = mm_strdup(strport);
4183 /* Create a non-blocking socket and bind it */
4184 /* todo: rename this function */
4185 static evutil_socket_t
4186 bind_socket_ai(struct evutil_addrinfo *ai, int reuse)
4188 evutil_socket_t fd;
4190 int on = 1, r;
4191 int serrno;
4193 /* Create listen socket */
4194 fd = evutil_socket_(ai ? ai->ai_family : AF_INET,
4195 SOCK_STREAM|EVUTIL_SOCK_NONBLOCK|EVUTIL_SOCK_CLOEXEC, 0);
4196 if (fd == -1) {
4197 event_sock_warn(-1, "socket");
4198 return (-1);
4201 if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (void *)&on, sizeof(on))<0)
4202 goto out;
4203 if (reuse) {
4204 if (evutil_make_listen_socket_reuseable(fd) < 0)
4205 goto out;
4208 if (ai != NULL) {
4209 r = bind(fd, ai->ai_addr, (ev_socklen_t)ai->ai_addrlen);
4210 if (r == -1)
4211 goto out;
4214 return (fd);
4216 out:
4217 serrno = EVUTIL_SOCKET_ERROR();
4218 evutil_closesocket(fd);
4219 EVUTIL_SET_SOCKET_ERROR(serrno);
4220 return (-1);
4223 static struct evutil_addrinfo *
4224 make_addrinfo(const char *address, ev_uint16_t port)
4226 struct evutil_addrinfo *ai = NULL;
4228 struct evutil_addrinfo hints;
4229 char strport[NI_MAXSERV];
4230 int ai_result;
4232 memset(&hints, 0, sizeof(hints));
4233 hints.ai_family = AF_UNSPEC;
4234 hints.ai_socktype = SOCK_STREAM;
4235 /* turn NULL hostname into INADDR_ANY, and skip looking up any address
4236 * types we don't have an interface to connect to. */
4237 hints.ai_flags = EVUTIL_AI_PASSIVE|EVUTIL_AI_ADDRCONFIG;
4238 evutil_snprintf(strport, sizeof(strport), "%d", port);
4239 if ((ai_result = evutil_getaddrinfo(address, strport, &hints, &ai))
4240 != 0) {
4241 if (ai_result == EVUTIL_EAI_SYSTEM)
4242 event_warn("getaddrinfo");
4243 else
4244 event_warnx("getaddrinfo: %s",
4245 evutil_gai_strerror(ai_result));
4246 return (NULL);
4249 return (ai);
4252 static evutil_socket_t
4253 bind_socket(const char *address, ev_uint16_t port, int reuse)
4255 evutil_socket_t fd;
4256 struct evutil_addrinfo *aitop = NULL;
4258 /* just create an unbound socket */
4259 if (address == NULL && port == 0)
4260 return bind_socket_ai(NULL, 0);
4262 aitop = make_addrinfo(address, port);
4264 if (aitop == NULL)
4265 return (-1);
4267 fd = bind_socket_ai(aitop, reuse);
4269 evutil_freeaddrinfo(aitop);
4271 return (fd);
4274 struct evhttp_uri {
4275 unsigned flags;
4276 char *scheme; /* scheme; e.g http, ftp etc */
4277 char *userinfo; /* userinfo (typically username:pass), or NULL */
4278 char *host; /* hostname, IP address, or NULL */
4279 int port; /* port, or zero */
4280 char *path; /* path, or "". */
4281 char *query; /* query, or NULL */
4282 char *fragment; /* fragment or NULL */
4285 struct evhttp_uri *
4286 evhttp_uri_new(void)
4288 struct evhttp_uri *uri = mm_calloc(sizeof(struct evhttp_uri), 1);
4289 if (uri)
4290 uri->port = -1;
4291 return uri;
4294 void
4295 evhttp_uri_set_flags(struct evhttp_uri *uri, unsigned flags)
4297 uri->flags = flags;
4300 /* Return true if the string starting at s and ending immediately before eos
4301 * is a valid URI scheme according to RFC3986
4303 static int
4304 scheme_ok(const char *s, const char *eos)
4306 /* scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." ) */
4307 EVUTIL_ASSERT(eos >= s);
4308 if (s == eos)
4309 return 0;
4310 if (!EVUTIL_ISALPHA_(*s))
4311 return 0;
4312 while (++s < eos) {
4313 if (! EVUTIL_ISALNUM_(*s) &&
4314 *s != '+' && *s != '-' && *s != '.')
4315 return 0;
4317 return 1;
4320 #define SUBDELIMS "!$&'()*+,;="
4322 /* Return true iff [s..eos) is a valid userinfo */
4323 static int
4324 userinfo_ok(const char *s, const char *eos)
4326 while (s < eos) {
4327 if (CHAR_IS_UNRESERVED(*s) ||
4328 strchr(SUBDELIMS, *s) ||
4329 *s == ':')
4330 ++s;
4331 else if (*s == '%' && s+2 < eos &&
4332 EVUTIL_ISXDIGIT_(s[1]) &&
4333 EVUTIL_ISXDIGIT_(s[2]))
4334 s += 3;
4335 else
4336 return 0;
4338 return 1;
4341 static int
4342 regname_ok(const char *s, const char *eos)
4344 while (s && s<eos) {
4345 if (CHAR_IS_UNRESERVED(*s) ||
4346 strchr(SUBDELIMS, *s))
4347 ++s;
4348 else if (*s == '%' &&
4349 EVUTIL_ISXDIGIT_(s[1]) &&
4350 EVUTIL_ISXDIGIT_(s[2]))
4351 s += 3;
4352 else
4353 return 0;
4355 return 1;
4358 static int
4359 parse_port(const char *s, const char *eos)
4361 int portnum = 0;
4362 while (s < eos) {
4363 if (! EVUTIL_ISDIGIT_(*s))
4364 return -1;
4365 portnum = (portnum * 10) + (*s - '0');
4366 if (portnum < 0)
4367 return -1;
4368 if (portnum > 65535)
4369 return -1;
4370 ++s;
4372 return portnum;
4375 /* returns 0 for bad, 1 for ipv6, 2 for IPvFuture */
4376 static int
4377 bracket_addr_ok(const char *s, const char *eos)
4379 if (s + 3 > eos || *s != '[' || *(eos-1) != ']')
4380 return 0;
4381 if (s[1] == 'v') {
4382 /* IPvFuture, or junk.
4383 "v" 1*HEXDIG "." 1*( unreserved / sub-delims / ":" )
4385 s += 2; /* skip [v */
4386 --eos;
4387 if (!EVUTIL_ISXDIGIT_(*s)) /*require at least one*/
4388 return 0;
4389 while (s < eos && *s != '.') {
4390 if (EVUTIL_ISXDIGIT_(*s))
4391 ++s;
4392 else
4393 return 0;
4395 if (*s != '.')
4396 return 0;
4397 ++s;
4398 while (s < eos) {
4399 if (CHAR_IS_UNRESERVED(*s) ||
4400 strchr(SUBDELIMS, *s) ||
4401 *s == ':')
4402 ++s;
4403 else
4404 return 0;
4406 return 2;
4407 } else {
4408 /* IPv6, or junk */
4409 char buf[64];
4410 ev_ssize_t n_chars = eos-s-2;
4411 struct in6_addr in6;
4412 if (n_chars >= 64) /* way too long */
4413 return 0;
4414 memcpy(buf, s+1, n_chars);
4415 buf[n_chars]='\0';
4416 return (evutil_inet_pton(AF_INET6,buf,&in6)==1) ? 1 : 0;
4420 static int
4421 parse_authority(struct evhttp_uri *uri, char *s, char *eos)
4423 char *cp, *port;
4424 EVUTIL_ASSERT(eos);
4425 if (eos == s) {
4426 uri->host = mm_strdup("");
4427 if (uri->host == NULL) {
4428 event_warn("%s: strdup", __func__);
4429 return -1;
4431 return 0;
4434 /* Optionally, we start with "userinfo@" */
4436 cp = strchr(s, '@');
4437 if (cp && cp < eos) {
4438 if (! userinfo_ok(s,cp))
4439 return -1;
4440 *cp++ = '\0';
4441 uri->userinfo = mm_strdup(s);
4442 if (uri->userinfo == NULL) {
4443 event_warn("%s: strdup", __func__);
4444 return -1;
4446 } else {
4447 cp = s;
4449 /* Optionally, we end with ":port" */
4450 for (port=eos-1; port >= cp && EVUTIL_ISDIGIT_(*port); --port)
4452 if (port >= cp && *port == ':') {
4453 if (port+1 == eos) /* Leave port unspecified; the RFC allows a
4454 * nil port */
4455 uri->port = -1;
4456 else if ((uri->port = parse_port(port+1, eos))<0)
4457 return -1;
4458 eos = port;
4460 /* Now, cp..eos holds the "host" port, which can be an IPv4Address,
4461 * an IP-Literal, or a reg-name */
4462 EVUTIL_ASSERT(eos >= cp);
4463 if (*cp == '[' && eos >= cp+2 && *(eos-1) == ']') {
4464 /* IPv6address, IP-Literal, or junk. */
4465 if (! bracket_addr_ok(cp, eos))
4466 return -1;
4467 } else {
4468 /* Make sure the host part is ok. */
4469 if (! regname_ok(cp,eos)) /* Match IPv4Address or reg-name */
4470 return -1;
4472 uri->host = mm_malloc(eos-cp+1);
4473 if (uri->host == NULL) {
4474 event_warn("%s: malloc", __func__);
4475 return -1;
4477 memcpy(uri->host, cp, eos-cp);
4478 uri->host[eos-cp] = '\0';
4479 return 0;
4483 static char *
4484 end_of_authority(char *cp)
4486 while (*cp) {
4487 if (*cp == '?' || *cp == '#' || *cp == '/')
4488 return cp;
4489 ++cp;
4491 return cp;
4494 enum uri_part {
4495 PART_PATH,
4496 PART_QUERY,
4497 PART_FRAGMENT
4500 /* Return the character after the longest prefix of 'cp' that matches...
4501 * *pchar / "/" if allow_qchars is false, or
4502 * *(pchar / "/" / "?") if allow_qchars is true.
4504 static char *
4505 end_of_path(char *cp, enum uri_part part, unsigned flags)
4507 if (flags & EVHTTP_URI_NONCONFORMANT) {
4508 /* If NONCONFORMANT:
4509 * Path is everything up to a # or ? or nul.
4510 * Query is everything up a # or nul
4511 * Fragment is everything up to a nul.
4513 switch (part) {
4514 case PART_PATH:
4515 while (*cp && *cp != '#' && *cp != '?')
4516 ++cp;
4517 break;
4518 case PART_QUERY:
4519 while (*cp && *cp != '#')
4520 ++cp;
4521 break;
4522 case PART_FRAGMENT:
4523 cp += strlen(cp);
4524 break;
4526 return cp;
4529 while (*cp) {
4530 if (CHAR_IS_UNRESERVED(*cp) ||
4531 strchr(SUBDELIMS, *cp) ||
4532 *cp == ':' || *cp == '@' || *cp == '/')
4533 ++cp;
4534 else if (*cp == '%' && EVUTIL_ISXDIGIT_(cp[1]) &&
4535 EVUTIL_ISXDIGIT_(cp[2]))
4536 cp += 3;
4537 else if (*cp == '?' && part != PART_PATH)
4538 ++cp;
4539 else
4540 return cp;
4542 return cp;
4545 static int
4546 path_matches_noscheme(const char *cp)
4548 while (*cp) {
4549 if (*cp == ':')
4550 return 0;
4551 else if (*cp == '/')
4552 return 1;
4553 ++cp;
4555 return 1;
4558 struct evhttp_uri *
4559 evhttp_uri_parse(const char *source_uri)
4561 return evhttp_uri_parse_with_flags(source_uri, 0);
4564 struct evhttp_uri *
4565 evhttp_uri_parse_with_flags(const char *source_uri, unsigned flags)
4567 char *readbuf = NULL, *readp = NULL, *token = NULL, *query = NULL;
4568 char *path = NULL, *fragment = NULL;
4569 int got_authority = 0;
4571 struct evhttp_uri *uri = mm_calloc(1, sizeof(struct evhttp_uri));
4572 if (uri == NULL) {
4573 event_warn("%s: calloc", __func__);
4574 goto err;
4576 uri->port = -1;
4577 uri->flags = flags;
4579 readbuf = mm_strdup(source_uri);
4580 if (readbuf == NULL) {
4581 event_warn("%s: strdup", __func__);
4582 goto err;
4585 readp = readbuf;
4586 token = NULL;
4588 /* We try to follow RFC3986 here as much as we can, and match
4589 the productions
4591 URI = scheme ":" hier-part [ "?" query ] [ "#" fragment ]
4593 relative-ref = relative-part [ "?" query ] [ "#" fragment ]
4596 /* 1. scheme: */
4597 token = strchr(readp, ':');
4598 if (token && scheme_ok(readp,token)) {
4599 *token = '\0';
4600 uri->scheme = mm_strdup(readp);
4601 if (uri->scheme == NULL) {
4602 event_warn("%s: strdup", __func__);
4603 goto err;
4605 readp = token+1; /* eat : */
4608 /* 2. Optionally, "//" then an 'authority' part. */
4609 if (readp[0]=='/' && readp[1] == '/') {
4610 char *authority;
4611 readp += 2;
4612 authority = readp;
4613 path = end_of_authority(readp);
4614 if (parse_authority(uri, authority, path) < 0)
4615 goto err;
4616 readp = path;
4617 got_authority = 1;
4620 /* 3. Query: path-abempty, path-absolute, path-rootless, or path-empty
4622 path = readp;
4623 readp = end_of_path(path, PART_PATH, flags);
4625 /* Query */
4626 if (*readp == '?') {
4627 *readp = '\0';
4628 ++readp;
4629 query = readp;
4630 readp = end_of_path(readp, PART_QUERY, flags);
4632 /* fragment */
4633 if (*readp == '#') {
4634 *readp = '\0';
4635 ++readp;
4636 fragment = readp;
4637 readp = end_of_path(readp, PART_FRAGMENT, flags);
4639 if (*readp != '\0') {
4640 goto err;
4643 /* These next two cases may be unreachable; I'm leaving them
4644 * in to be defensive. */
4645 /* If you didn't get an authority, the path can't begin with "//" */
4646 if (!got_authority && path[0]=='/' && path[1]=='/')
4647 goto err;
4648 /* If you did get an authority, the path must begin with "/" or be
4649 * empty. */
4650 if (got_authority && path[0] != '/' && path[0] != '\0')
4651 goto err;
4652 /* (End of maybe-unreachable cases) */
4654 /* If there was no scheme, the first part of the path (if any) must
4655 * have no colon in it. */
4656 if (! uri->scheme && !path_matches_noscheme(path))
4657 goto err;
4659 EVUTIL_ASSERT(path);
4660 uri->path = mm_strdup(path);
4661 if (uri->path == NULL) {
4662 event_warn("%s: strdup", __func__);
4663 goto err;
4666 if (query) {
4667 uri->query = mm_strdup(query);
4668 if (uri->query == NULL) {
4669 event_warn("%s: strdup", __func__);
4670 goto err;
4673 if (fragment) {
4674 uri->fragment = mm_strdup(fragment);
4675 if (uri->fragment == NULL) {
4676 event_warn("%s: strdup", __func__);
4677 goto err;
4681 mm_free(readbuf);
4683 return uri;
4684 err:
4685 if (uri)
4686 evhttp_uri_free(uri);
4687 if (readbuf)
4688 mm_free(readbuf);
4689 return NULL;
4692 void
4693 evhttp_uri_free(struct evhttp_uri *uri)
4695 #define URI_FREE_STR_(f) \
4696 if (uri->f) { \
4697 mm_free(uri->f); \
4700 URI_FREE_STR_(scheme);
4701 URI_FREE_STR_(userinfo);
4702 URI_FREE_STR_(host);
4703 URI_FREE_STR_(path);
4704 URI_FREE_STR_(query);
4705 URI_FREE_STR_(fragment);
4707 mm_free(uri);
4708 #undef URI_FREE_STR_
4711 char *
4712 evhttp_uri_join(struct evhttp_uri *uri, char *buf, size_t limit)
4714 struct evbuffer *tmp = 0;
4715 size_t joined_size = 0;
4716 char *output = NULL;
4718 #define URI_ADD_(f) evbuffer_add(tmp, uri->f, strlen(uri->f))
4720 if (!uri || !buf || !limit)
4721 return NULL;
4723 tmp = evbuffer_new();
4724 if (!tmp)
4725 return NULL;
4727 if (uri->scheme) {
4728 URI_ADD_(scheme);
4729 evbuffer_add(tmp, ":", 1);
4731 if (uri->host) {
4732 evbuffer_add(tmp, "//", 2);
4733 if (uri->userinfo)
4734 evbuffer_add_printf(tmp,"%s@", uri->userinfo);
4735 URI_ADD_(host);
4736 if (uri->port >= 0)
4737 evbuffer_add_printf(tmp,":%d", uri->port);
4739 if (uri->path && uri->path[0] != '/' && uri->path[0] != '\0')
4740 goto err;
4743 if (uri->path)
4744 URI_ADD_(path);
4746 if (uri->query) {
4747 evbuffer_add(tmp, "?", 1);
4748 URI_ADD_(query);
4751 if (uri->fragment) {
4752 evbuffer_add(tmp, "#", 1);
4753 URI_ADD_(fragment);
4756 evbuffer_add(tmp, "\0", 1); /* NUL */
4758 joined_size = evbuffer_get_length(tmp);
4760 if (joined_size > limit) {
4761 /* It doesn't fit. */
4762 evbuffer_free(tmp);
4763 return NULL;
4765 evbuffer_remove(tmp, buf, joined_size);
4767 output = buf;
4768 err:
4769 evbuffer_free(tmp);
4771 return output;
4772 #undef URI_ADD_
4775 const char *
4776 evhttp_uri_get_scheme(const struct evhttp_uri *uri)
4778 return uri->scheme;
4780 const char *
4781 evhttp_uri_get_userinfo(const struct evhttp_uri *uri)
4783 return uri->userinfo;
4785 const char *
4786 evhttp_uri_get_host(const struct evhttp_uri *uri)
4788 return uri->host;
4791 evhttp_uri_get_port(const struct evhttp_uri *uri)
4793 return uri->port;
4795 const char *
4796 evhttp_uri_get_path(const struct evhttp_uri *uri)
4798 return uri->path;
4800 const char *
4801 evhttp_uri_get_query(const struct evhttp_uri *uri)
4803 return uri->query;
4805 const char *
4806 evhttp_uri_get_fragment(const struct evhttp_uri *uri)
4808 return uri->fragment;
4811 #define URI_SET_STR_(f) do { \
4812 if (uri->f) \
4813 mm_free(uri->f); \
4814 if (f) { \
4815 if ((uri->f = mm_strdup(f)) == NULL) { \
4816 event_warn("%s: strdup()", __func__); \
4817 return -1; \
4819 } else { \
4820 uri->f = NULL; \
4822 } while(0)
4825 evhttp_uri_set_scheme(struct evhttp_uri *uri, const char *scheme)
4827 if (scheme && !scheme_ok(scheme, scheme+strlen(scheme)))
4828 return -1;
4830 URI_SET_STR_(scheme);
4831 return 0;
4834 evhttp_uri_set_userinfo(struct evhttp_uri *uri, const char *userinfo)
4836 if (userinfo && !userinfo_ok(userinfo, userinfo+strlen(userinfo)))
4837 return -1;
4838 URI_SET_STR_(userinfo);
4839 return 0;
4842 evhttp_uri_set_host(struct evhttp_uri *uri, const char *host)
4844 if (host) {
4845 if (host[0] == '[') {
4846 if (! bracket_addr_ok(host, host+strlen(host)))
4847 return -1;
4848 } else {
4849 if (! regname_ok(host, host+strlen(host)))
4850 return -1;
4854 URI_SET_STR_(host);
4855 return 0;
4858 evhttp_uri_set_port(struct evhttp_uri *uri, int port)
4860 if (port < -1)
4861 return -1;
4862 uri->port = port;
4863 return 0;
4865 #define end_of_cpath(cp,p,f) \
4866 ((const char*)(end_of_path(((char*)(cp)), (p), (f))))
4869 evhttp_uri_set_path(struct evhttp_uri *uri, const char *path)
4871 if (path && end_of_cpath(path, PART_PATH, uri->flags) != path+strlen(path))
4872 return -1;
4874 URI_SET_STR_(path);
4875 return 0;
4878 evhttp_uri_set_query(struct evhttp_uri *uri, const char *query)
4880 if (query && end_of_cpath(query, PART_QUERY, uri->flags) != query+strlen(query))
4881 return -1;
4882 URI_SET_STR_(query);
4883 return 0;
4886 evhttp_uri_set_fragment(struct evhttp_uri *uri, const char *fragment)
4888 if (fragment && end_of_cpath(fragment, PART_FRAGMENT, uri->flags) != fragment+strlen(fragment))
4889 return -1;
4890 URI_SET_STR_(fragment);
4891 return 0;