Home | History | Annotate | Line # | Download | only in dist
      1  1.5  christos /*	$NetBSD: http.c,v 1.5 2021/04/07 03:36:48 christos Exp $	*/
      2  1.5  christos 
      3  1.1    plunky /*
      4  1.2  christos  * Copyright (c) 2002-2007 Niels Provos <provos (at) citi.umich.edu>
      5  1.2  christos  * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson
      6  1.1    plunky  *
      7  1.1    plunky  * Redistribution and use in source and binary forms, with or without
      8  1.1    plunky  * modification, are permitted provided that the following conditions
      9  1.1    plunky  * are met:
     10  1.1    plunky  * 1. Redistributions of source code must retain the above copyright
     11  1.1    plunky  *    notice, this list of conditions and the following disclaimer.
     12  1.1    plunky  * 2. Redistributions in binary form must reproduce the above copyright
     13  1.1    plunky  *    notice, this list of conditions and the following disclaimer in the
     14  1.1    plunky  *    documentation and/or other materials provided with the distribution.
     15  1.1    plunky  * 3. The name of the author may not be used to endorse or promote products
     16  1.1    plunky  *    derived from this software without specific prior written permission.
     17  1.1    plunky  *
     18  1.1    plunky  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     19  1.1    plunky  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     20  1.1    plunky  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     21  1.1    plunky  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     22  1.1    plunky  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     23  1.1    plunky  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     24  1.1    plunky  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     25  1.1    plunky  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     26  1.1    plunky  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     27  1.1    plunky  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     28  1.1    plunky  */
     29  1.1    plunky 
     30  1.2  christos #include "event2/event-config.h"
     31  1.2  christos #include <sys/cdefs.h>
     32  1.5  christos __RCSID("$NetBSD: http.c,v 1.5 2021/04/07 03:36:48 christos Exp $");
     33  1.4  christos #include "evconfig-private.h"
     34  1.1    plunky 
     35  1.4  christos #ifdef EVENT__HAVE_SYS_PARAM_H
     36  1.1    plunky #include <sys/param.h>
     37  1.1    plunky #endif
     38  1.4  christos #ifdef EVENT__HAVE_SYS_TYPES_H
     39  1.1    plunky #include <sys/types.h>
     40  1.1    plunky #endif
     41  1.1    plunky 
     42  1.4  christos #ifdef HAVE_SYS_IOCCOM_H
     43  1.4  christos #include <sys/ioccom.h>
     44  1.4  christos #endif
     45  1.4  christos #ifdef EVENT__HAVE_SYS_RESOURCE_H
     46  1.4  christos #include <sys/resource.h>
     47  1.4  christos #endif
     48  1.4  christos #ifdef EVENT__HAVE_SYS_TIME_H
     49  1.1    plunky #include <sys/time.h>
     50  1.1    plunky #endif
     51  1.4  christos #ifdef EVENT__HAVE_SYS_WAIT_H
     52  1.4  christos #include <sys/wait.h>
     53  1.1    plunky #endif
     54  1.1    plunky 
     55  1.4  christos #ifndef _WIN32
     56  1.1    plunky #include <sys/socket.h>
     57  1.1    plunky #include <sys/stat.h>
     58  1.5  christos #else /* _WIN32 */
     59  1.2  christos #include <winsock2.h>
     60  1.2  christos #include <ws2tcpip.h>
     61  1.5  christos #endif /* _WIN32 */
     62  1.5  christos 
     63  1.5  christos #ifdef EVENT__HAVE_SYS_UN_H
     64  1.5  christos #include <sys/un.h>
     65  1.5  christos #endif
     66  1.5  christos #ifdef EVENT__HAVE_AFUNIX_H
     67  1.5  christos #include <afunix.h>
     68  1.1    plunky #endif
     69  1.1    plunky 
     70  1.1    plunky #include <sys/queue.h>
     71  1.1    plunky 
     72  1.4  christos #ifdef EVENT__HAVE_NETINET_IN_H
     73  1.1    plunky #include <netinet/in.h>
     74  1.2  christos #endif
     75  1.4  christos #ifdef EVENT__HAVE_ARPA_INET_H
     76  1.2  christos #include <arpa/inet.h>
     77  1.2  christos #endif
     78  1.4  christos #ifdef EVENT__HAVE_NETDB_H
     79  1.1    plunky #include <netdb.h>
     80  1.1    plunky #endif
     81  1.1    plunky 
     82  1.4  christos #ifdef _WIN32
     83  1.1    plunky #include <winsock2.h>
     84  1.1    plunky #endif
     85  1.1    plunky 
     86  1.1    plunky #include <errno.h>
     87  1.1    plunky #include <stdio.h>
     88  1.1    plunky #include <stdlib.h>
     89  1.1    plunky #include <string.h>
     90  1.4  christos #ifndef _WIN32
     91  1.1    plunky #include <syslog.h>
     92  1.5  christos #endif /* !_WIN32 */
     93  1.1    plunky #include <signal.h>
     94  1.4  christos #ifdef EVENT__HAVE_UNISTD_H
     95  1.1    plunky #include <unistd.h>
     96  1.1    plunky #endif
     97  1.4  christos #ifdef EVENT__HAVE_FCNTL_H
     98  1.1    plunky #include <fcntl.h>
     99  1.1    plunky #endif
    100  1.1    plunky 
    101  1.1    plunky #undef timeout_pending
    102  1.1    plunky #undef timeout_initialized
    103  1.1    plunky 
    104  1.1    plunky #include "strlcpy-internal.h"
    105  1.2  christos #include "event2/http.h"
    106  1.2  christos #include "event2/event.h"
    107  1.2  christos #include "event2/buffer.h"
    108  1.2  christos #include "event2/bufferevent.h"
    109  1.2  christos #include "event2/http_struct.h"
    110  1.2  christos #include "event2/http_compat.h"
    111  1.2  christos #include "event2/util.h"
    112  1.2  christos #include "event2/listener.h"
    113  1.2  christos #include "log-internal.h"
    114  1.2  christos #include "util-internal.h"
    115  1.1    plunky #include "http-internal.h"
    116  1.2  christos #include "mm-internal.h"
    117  1.2  christos #include "bufferevent-internal.h"
    118  1.1    plunky 
    119  1.4  christos #ifndef EVENT__HAVE_GETNAMEINFO
    120  1.1    plunky #define NI_MAXSERV 32
    121  1.1    plunky #define NI_MAXHOST 1025
    122  1.1    plunky 
    123  1.2  christos #ifndef NI_NUMERICHOST
    124  1.1    plunky #define NI_NUMERICHOST 1
    125  1.2  christos #endif
    126  1.2  christos 
    127  1.2  christos #ifndef NI_NUMERICSERV
    128  1.1    plunky #define NI_NUMERICSERV 2
    129  1.2  christos #endif
    130  1.1    plunky 
    131  1.1    plunky static int
    132  1.2  christos fake_getnameinfo(const struct sockaddr *sa, size_t salen, char *host,
    133  1.1    plunky 	size_t hostlen, char *serv, size_t servlen, int flags)
    134  1.1    plunky {
    135  1.2  christos 	struct sockaddr_in *sin = (struct sockaddr_in *)sa;
    136  1.1    plunky 
    137  1.2  christos 	if (serv != NULL) {
    138  1.2  christos 		char tmpserv[16];
    139  1.2  christos 		evutil_snprintf(tmpserv, sizeof(tmpserv),
    140  1.2  christos 		    "%d", ntohs(sin->sin_port));
    141  1.2  christos 		if (strlcpy(serv, tmpserv, servlen) >= servlen)
    142  1.1    plunky 			return (-1);
    143  1.1    plunky 	}
    144  1.2  christos 
    145  1.2  christos 	if (host != NULL) {
    146  1.2  christos 		if (flags & NI_NUMERICHOST) {
    147  1.2  christos 			if (strlcpy(host, inet_ntoa(sin->sin_addr),
    148  1.2  christos 			    hostlen) >= hostlen)
    149  1.2  christos 				return (-1);
    150  1.2  christos 			else
    151  1.2  christos 				return (0);
    152  1.2  christos 		} else {
    153  1.2  christos 			struct hostent *hp;
    154  1.2  christos 			hp = gethostbyaddr((char *)&sin->sin_addr,
    155  1.2  christos 			    sizeof(struct in_addr), AF_INET);
    156  1.2  christos 			if (hp == NULL)
    157  1.2  christos 				return (-2);
    158  1.2  christos 
    159  1.2  christos 			if (strlcpy(host, hp->h_name, hostlen) >= hostlen)
    160  1.2  christos 				return (-1);
    161  1.2  christos 			else
    162  1.2  christos 				return (0);
    163  1.2  christos 		}
    164  1.1    plunky 	}
    165  1.1    plunky 	return (0);
    166  1.1    plunky }
    167  1.2  christos 
    168  1.1    plunky #endif
    169  1.1    plunky 
    170  1.2  christos #define REQ_VERSION_BEFORE(req, major_v, minor_v)			\
    171  1.2  christos 	((req)->major < (major_v) ||					\
    172  1.2  christos 	    ((req)->major == (major_v) && (req)->minor < (minor_v)))
    173  1.2  christos 
    174  1.2  christos #define REQ_VERSION_ATLEAST(req, major_v, minor_v)			\
    175  1.2  christos 	((req)->major > (major_v) ||					\
    176  1.2  christos 	    ((req)->major == (major_v) && (req)->minor >= (minor_v)))
    177  1.2  christos 
    178  1.1    plunky #ifndef MIN
    179  1.1    plunky #define MIN(a,b) (((a)<(b))?(a):(b))
    180  1.1    plunky #endif
    181  1.1    plunky 
    182  1.1    plunky extern int debug;
    183  1.1    plunky 
    184  1.5  christos static evutil_socket_t create_bind_socket_nonblock(struct evutil_addrinfo *, int reuse);
    185  1.2  christos static evutil_socket_t bind_socket(const char *, ev_uint16_t, int reuse);
    186  1.2  christos static void name_from_addr(struct sockaddr *, ev_socklen_t, char **, char **);
    187  1.5  christos static struct evhttp_uri *evhttp_uri_parse_authority(char *source_uri);
    188  1.1    plunky static int evhttp_associate_new_request_with_connection(
    189  1.1    plunky 	struct evhttp_connection *evcon);
    190  1.1    plunky static void evhttp_connection_start_detectclose(
    191  1.1    plunky 	struct evhttp_connection *evcon);
    192  1.1    plunky static void evhttp_connection_stop_detectclose(
    193  1.1    plunky 	struct evhttp_connection *evcon);
    194  1.1    plunky static void evhttp_request_dispatch(struct evhttp_connection* evcon);
    195  1.1    plunky static void evhttp_read_firstline(struct evhttp_connection *evcon,
    196  1.1    plunky 				  struct evhttp_request *req);
    197  1.1    plunky static void evhttp_read_header(struct evhttp_connection *evcon,
    198  1.1    plunky     struct evhttp_request *req);
    199  1.1    plunky static int evhttp_add_header_internal(struct evkeyvalq *headers,
    200  1.1    plunky     const char *key, const char *value);
    201  1.2  christos static const char *evhttp_response_phrase_internal(int code);
    202  1.2  christos static void evhttp_get_request(struct evhttp *, evutil_socket_t, struct sockaddr *, ev_socklen_t);
    203  1.2  christos static void evhttp_write_buffer(struct evhttp_connection *,
    204  1.2  christos     void (*)(struct evhttp_connection *, void *), void *);
    205  1.2  christos static void evhttp_make_header(struct evhttp_connection *, struct evhttp_request *);
    206  1.2  christos 
    207  1.2  christos /* callbacks for bufferevent */
    208  1.2  christos static void evhttp_read_cb(struct bufferevent *, void *);
    209  1.2  christos static void evhttp_write_cb(struct bufferevent *, void *);
    210  1.2  christos static void evhttp_error_cb(struct bufferevent *bufev, short what, void *arg);
    211  1.2  christos static int evhttp_find_vhost(struct evhttp *http, struct evhttp **outhttp,
    212  1.2  christos 		  const char *hostname);
    213  1.1    plunky 
    214  1.4  christos #ifndef EVENT__HAVE_STRSEP
    215  1.1    plunky /* strsep replacement for platforms that lack it.  Only works if
    216  1.1    plunky  * del is one character long. */
    217  1.1    plunky static char *
    218  1.1    plunky strsep(char **s, const char *del)
    219  1.1    plunky {
    220  1.1    plunky 	char *d, *tok;
    221  1.2  christos 	EVUTIL_ASSERT(strlen(del) == 1);
    222  1.1    plunky 	if (!s || !*s)
    223  1.1    plunky 		return NULL;
    224  1.1    plunky 	tok = *s;
    225  1.1    plunky 	d = strstr(tok, del);
    226  1.1    plunky 	if (d) {
    227  1.1    plunky 		*d = '\0';
    228  1.1    plunky 		*s = d + 1;
    229  1.1    plunky 	} else
    230  1.1    plunky 		*s = NULL;
    231  1.1    plunky 	return tok;
    232  1.1    plunky }
    233  1.1    plunky #endif
    234  1.1    plunky 
    235  1.2  christos static size_t
    236  1.2  christos html_replace(const char ch, const char **escaped)
    237  1.1    plunky {
    238  1.1    plunky 	switch (ch) {
    239  1.1    plunky 	case '<':
    240  1.2  christos 		*escaped = "&lt;";
    241  1.2  christos 		return 4;
    242  1.1    plunky 	case '>':
    243  1.2  christos 		*escaped = "&gt;";
    244  1.2  christos 		return 4;
    245  1.1    plunky 	case '"':
    246  1.2  christos 		*escaped = "&quot;";
    247  1.2  christos 		return 6;
    248  1.1    plunky 	case '\'':
    249  1.2  christos 		*escaped = "&#039;";
    250  1.2  christos 		return 6;
    251  1.1    plunky 	case '&':
    252  1.2  christos 		*escaped = "&amp;";
    253  1.2  christos 		return 5;
    254  1.1    plunky 	default:
    255  1.1    plunky 		break;
    256  1.1    plunky 	}
    257  1.1    plunky 
    258  1.2  christos 	return 1;
    259  1.1    plunky }
    260  1.1    plunky 
    261  1.1    plunky /*
    262  1.1    plunky  * Replaces <, >, ", ' and & with &lt;, &gt;, &quot;,
    263  1.1    plunky  * &#039; and &amp; correspondingly.
    264  1.1    plunky  *
    265  1.1    plunky  * The returned string needs to be freed by the caller.
    266  1.1    plunky  */
    267  1.1    plunky 
    268  1.1    plunky char *
    269  1.1    plunky evhttp_htmlescape(const char *html)
    270  1.1    plunky {
    271  1.2  christos 	size_t i;
    272  1.2  christos 	size_t new_size = 0, old_size = 0;
    273  1.1    plunky 	char *escaped_html, *p;
    274  1.2  christos 
    275  1.2  christos 	if (html == NULL)
    276  1.2  christos 		return (NULL);
    277  1.2  christos 
    278  1.2  christos 	old_size = strlen(html);
    279  1.2  christos 	for (i = 0; i < old_size; ++i) {
    280  1.2  christos 		const char *replaced = NULL;
    281  1.2  christos 		const size_t replace_size = html_replace(html[i], &replaced);
    282  1.2  christos 		if (replace_size > EV_SIZE_MAX - new_size) {
    283  1.2  christos 			event_warn("%s: html_replace overflow", __func__);
    284  1.2  christos 			return (NULL);
    285  1.2  christos 		}
    286  1.2  christos 		new_size += replace_size;
    287  1.2  christos 	}
    288  1.2  christos 
    289  1.2  christos 	if (new_size == EV_SIZE_MAX)
    290  1.2  christos 		return (NULL);
    291  1.2  christos 	p = escaped_html = mm_malloc(new_size + 1);
    292  1.2  christos 	if (escaped_html == NULL) {
    293  1.2  christos 		event_warn("%s: malloc(%lu)", __func__,
    294  1.2  christos 		           (unsigned long)(new_size + 1));
    295  1.2  christos 		return (NULL);
    296  1.2  christos 	}
    297  1.1    plunky 	for (i = 0; i < old_size; ++i) {
    298  1.2  christos 		const char *replaced = &html[i];
    299  1.2  christos 		const size_t len = html_replace(html[i], &replaced);
    300  1.2  christos 		memcpy(p, replaced, len);
    301  1.2  christos 		p += len;
    302  1.1    plunky 	}
    303  1.1    plunky 
    304  1.1    plunky 	*p = '\0';
    305  1.1    plunky 
    306  1.1    plunky 	return (escaped_html);
    307  1.1    plunky }
    308  1.1    plunky 
    309  1.2  christos /** Given an evhttp_cmd_type, returns a constant string containing the
    310  1.2  christos  * equivalent HTTP command, or NULL if the evhttp_command_type is
    311  1.2  christos  * unrecognized. */
    312  1.1    plunky static const char *
    313  1.1    plunky evhttp_method(enum evhttp_cmd_type type)
    314  1.1    plunky {
    315  1.1    plunky 	const char *method;
    316  1.1    plunky 
    317  1.1    plunky 	switch (type) {
    318  1.1    plunky 	case EVHTTP_REQ_GET:
    319  1.1    plunky 		method = "GET";
    320  1.1    plunky 		break;
    321  1.1    plunky 	case EVHTTP_REQ_POST:
    322  1.1    plunky 		method = "POST";
    323  1.1    plunky 		break;
    324  1.1    plunky 	case EVHTTP_REQ_HEAD:
    325  1.1    plunky 		method = "HEAD";
    326  1.1    plunky 		break;
    327  1.2  christos 	case EVHTTP_REQ_PUT:
    328  1.2  christos 		method = "PUT";
    329  1.2  christos 		break;
    330  1.2  christos 	case EVHTTP_REQ_DELETE:
    331  1.2  christos 		method = "DELETE";
    332  1.2  christos 		break;
    333  1.2  christos 	case EVHTTP_REQ_OPTIONS:
    334  1.2  christos 		method = "OPTIONS";
    335  1.2  christos 		break;
    336  1.2  christos 	case EVHTTP_REQ_TRACE:
    337  1.2  christos 		method = "TRACE";
    338  1.2  christos 		break;
    339  1.2  christos 	case EVHTTP_REQ_CONNECT:
    340  1.2  christos 		method = "CONNECT";
    341  1.2  christos 		break;
    342  1.2  christos 	case EVHTTP_REQ_PATCH:
    343  1.2  christos 		method = "PATCH";
    344  1.2  christos 		break;
    345  1.1    plunky 	default:
    346  1.1    plunky 		method = NULL;
    347  1.1    plunky 		break;
    348  1.1    plunky 	}
    349  1.1    plunky 
    350  1.1    plunky 	return (method);
    351  1.1    plunky }
    352  1.1    plunky 
    353  1.2  christos /**
    354  1.2  christos  * Determines if a response should have a body.
    355  1.2  christos  * Follows the rules in RFC 2616 section 4.3.
    356  1.2  christos  * @return 1 if the response MUST have a body; 0 if the response MUST NOT have
    357  1.2  christos  *     a body.
    358  1.2  christos  */
    359  1.2  christos static int
    360  1.2  christos evhttp_response_needs_body(struct evhttp_request *req)
    361  1.2  christos {
    362  1.2  christos 	return (req->response_code != HTTP_NOCONTENT &&
    363  1.2  christos 		req->response_code != HTTP_NOTMODIFIED &&
    364  1.2  christos 		(req->response_code < 100 || req->response_code >= 200) &&
    365  1.5  christos 		req->type != EVHTTP_REQ_CONNECT &&
    366  1.2  christos 		req->type != EVHTTP_REQ_HEAD);
    367  1.2  christos }
    368  1.2  christos 
    369  1.2  christos /** Helper: called after we've added some data to an evcon's bufferevent's
    370  1.2  christos  * output buffer.  Sets the evconn's writing-is-done callback, and puts
    371  1.2  christos  * the bufferevent into writing mode.
    372  1.2  christos  */
    373  1.2  christos static void
    374  1.1    plunky evhttp_write_buffer(struct evhttp_connection *evcon,
    375  1.1    plunky     void (*cb)(struct evhttp_connection *, void *), void *arg)
    376  1.1    plunky {
    377  1.1    plunky 	event_debug(("%s: preparing to write buffer\n", __func__));
    378  1.1    plunky 
    379  1.1    plunky 	/* Set call back */
    380  1.1    plunky 	evcon->cb = cb;
    381  1.1    plunky 	evcon->cb_arg = arg;
    382  1.1    plunky 
    383  1.2  christos 	/* Disable the read callback: we don't actually care about data;
    384  1.5  christos 	 * we only care about close detection. (We don't disable reading --
    385  1.5  christos 	 * EV_READ, since we *do* want to learn about any close events.) */
    386  1.2  christos 	bufferevent_setcb(evcon->bufev,
    387  1.2  christos 	    NULL, /*read*/
    388  1.2  christos 	    evhttp_write_cb,
    389  1.2  christos 	    evhttp_error_cb,
    390  1.2  christos 	    evcon);
    391  1.3       spz 
    392  1.5  christos 	bufferevent_enable(evcon->bufev, EV_READ|EV_WRITE);
    393  1.2  christos }
    394  1.2  christos 
    395  1.2  christos static void
    396  1.2  christos evhttp_send_continue_done(struct evhttp_connection *evcon, void *arg)
    397  1.2  christos {
    398  1.2  christos 	bufferevent_disable(evcon->bufev, EV_WRITE);
    399  1.2  christos }
    400  1.2  christos 
    401  1.2  christos static void
    402  1.2  christos evhttp_send_continue(struct evhttp_connection *evcon,
    403  1.2  christos 			struct evhttp_request *req)
    404  1.2  christos {
    405  1.2  christos 	bufferevent_enable(evcon->bufev, EV_WRITE);
    406  1.2  christos 	evbuffer_add_printf(bufferevent_get_output(evcon->bufev),
    407  1.2  christos 			"HTTP/%d.%d 100 Continue\r\n\r\n",
    408  1.2  christos 			req->major, req->minor);
    409  1.2  christos 	evcon->cb = evhttp_send_continue_done;
    410  1.2  christos 	evcon->cb_arg = NULL;
    411  1.2  christos 	bufferevent_setcb(evcon->bufev,
    412  1.2  christos 	    evhttp_read_cb,
    413  1.2  christos 	    evhttp_write_cb,
    414  1.2  christos 	    evhttp_error_cb,
    415  1.2  christos 	    evcon);
    416  1.1    plunky }
    417  1.1    plunky 
    418  1.2  christos /** Helper: returns true iff evconn is in any connected state. */
    419  1.1    plunky static int
    420  1.1    plunky evhttp_connected(struct evhttp_connection *evcon)
    421  1.1    plunky {
    422  1.1    plunky 	switch (evcon->state) {
    423  1.1    plunky 	case EVCON_DISCONNECTED:
    424  1.1    plunky 	case EVCON_CONNECTING:
    425  1.1    plunky 		return (0);
    426  1.1    plunky 	case EVCON_IDLE:
    427  1.1    plunky 	case EVCON_READING_FIRSTLINE:
    428  1.1    plunky 	case EVCON_READING_HEADERS:
    429  1.1    plunky 	case EVCON_READING_BODY:
    430  1.1    plunky 	case EVCON_READING_TRAILER:
    431  1.1    plunky 	case EVCON_WRITING:
    432  1.1    plunky 	default:
    433  1.1    plunky 		return (1);
    434  1.1    plunky 	}
    435  1.1    plunky }
    436  1.1    plunky 
    437  1.2  christos /* Create the headers needed for an outgoing HTTP request, adds them to
    438  1.2  christos  * the request's header list, and writes the request line to the
    439  1.2  christos  * connection's output buffer.
    440  1.1    plunky  */
    441  1.1    plunky static void
    442  1.1    plunky evhttp_make_header_request(struct evhttp_connection *evcon,
    443  1.1    plunky     struct evhttp_request *req)
    444  1.1    plunky {
    445  1.1    plunky 	const char *method;
    446  1.2  christos 
    447  1.1    plunky 	evhttp_remove_header(req->output_headers, "Proxy-Connection");
    448  1.1    plunky 
    449  1.1    plunky 	/* Generate request line */
    450  1.4  christos 	if (!(method = evhttp_method(req->type))) {
    451  1.4  christos 		method = "NULL";
    452  1.4  christos 	}
    453  1.4  christos 
    454  1.2  christos 	evbuffer_add_printf(bufferevent_get_output(evcon->bufev),
    455  1.2  christos 	    "%s %s HTTP/%d.%d\r\n",
    456  1.1    plunky 	    method, req->uri, req->major, req->minor);
    457  1.1    plunky 
    458  1.2  christos 	/* Add the content length on a post or put request if missing */
    459  1.2  christos 	if ((req->type == EVHTTP_REQ_POST || req->type == EVHTTP_REQ_PUT) &&
    460  1.1    plunky 	    evhttp_find_header(req->output_headers, "Content-Length") == NULL){
    461  1.2  christos 		char size[22];
    462  1.2  christos 		evutil_snprintf(size, sizeof(size), EV_SIZE_FMT,
    463  1.2  christos 		    EV_SIZE_ARG(evbuffer_get_length(req->output_buffer)));
    464  1.1    plunky 		evhttp_add_header(req->output_headers, "Content-Length", size);
    465  1.1    plunky 	}
    466  1.1    plunky }
    467  1.1    plunky 
    468  1.2  christos /** Return true if the list of headers in 'headers', intepreted with respect
    469  1.2  christos  * to flags, means that we should send a "connection: close" when the request
    470  1.2  christos  * is done. */
    471  1.1    plunky static int
    472  1.1    plunky evhttp_is_connection_close(int flags, struct evkeyvalq* headers)
    473  1.1    plunky {
    474  1.1    plunky 	if (flags & EVHTTP_PROXY_REQUEST) {
    475  1.1    plunky 		/* proxy connection */
    476  1.1    plunky 		const char *connection = evhttp_find_header(headers, "Proxy-Connection");
    477  1.2  christos 		return (connection == NULL || evutil_ascii_strcasecmp(connection, "keep-alive") != 0);
    478  1.1    plunky 	} else {
    479  1.1    plunky 		const char *connection = evhttp_find_header(headers, "Connection");
    480  1.2  christos 		return (connection != NULL && evutil_ascii_strcasecmp(connection, "close") == 0);
    481  1.1    plunky 	}
    482  1.1    plunky }
    483  1.4  christos static int
    484  1.4  christos evhttp_is_request_connection_close(struct evhttp_request *req)
    485  1.4  christos {
    486  1.5  christos 	if (req->type == EVHTTP_REQ_CONNECT)
    487  1.5  christos 		return 0;
    488  1.5  christos 
    489  1.4  christos 	return
    490  1.4  christos 		evhttp_is_connection_close(req->flags, req->input_headers) ||
    491  1.4  christos 		evhttp_is_connection_close(req->flags, req->output_headers);
    492  1.4  christos }
    493  1.1    plunky 
    494  1.2  christos /* Return true iff 'headers' contains 'Connection: keep-alive' */
    495  1.1    plunky static int
    496  1.1    plunky evhttp_is_connection_keepalive(struct evkeyvalq* headers)
    497  1.1    plunky {
    498  1.1    plunky 	const char *connection = evhttp_find_header(headers, "Connection");
    499  1.2  christos 	return (connection != NULL
    500  1.2  christos 	    && evutil_ascii_strncasecmp(connection, "keep-alive", 10) == 0);
    501  1.1    plunky }
    502  1.1    plunky 
    503  1.2  christos /* Add a correct "Date" header to headers, unless it already has one. */
    504  1.1    plunky static void
    505  1.1    plunky evhttp_maybe_add_date_header(struct evkeyvalq *headers)
    506  1.1    plunky {
    507  1.1    plunky 	if (evhttp_find_header(headers, "Date") == NULL) {
    508  1.1    plunky 		char date[50];
    509  1.4  christos 		if (sizeof(date) - evutil_date_rfc1123(date, sizeof(date), NULL) > 0) {
    510  1.1    plunky 			evhttp_add_header(headers, "Date", date);
    511  1.1    plunky 		}
    512  1.1    plunky 	}
    513  1.1    plunky }
    514  1.1    plunky 
    515  1.2  christos /* Add a "Content-Length" header with value 'content_length' to headers,
    516  1.2  christos  * unless it already has a content-length or transfer-encoding header. */
    517  1.1    plunky static void
    518  1.1    plunky evhttp_maybe_add_content_length_header(struct evkeyvalq *headers,
    519  1.2  christos     size_t content_length)
    520  1.1    plunky {
    521  1.1    plunky 	if (evhttp_find_header(headers, "Transfer-Encoding") == NULL &&
    522  1.1    plunky 	    evhttp_find_header(headers,	"Content-Length") == NULL) {
    523  1.2  christos 		char len[22];
    524  1.2  christos 		evutil_snprintf(len, sizeof(len), EV_SIZE_FMT,
    525  1.2  christos 		    EV_SIZE_ARG(content_length));
    526  1.1    plunky 		evhttp_add_header(headers, "Content-Length", len);
    527  1.1    plunky 	}
    528  1.1    plunky }
    529  1.1    plunky 
    530  1.1    plunky /*
    531  1.2  christos  * Create the headers needed for an HTTP reply in req->output_headers,
    532  1.2  christos  * and write the first HTTP response for req line to evcon.
    533  1.1    plunky  */
    534  1.1    plunky static void
    535  1.1    plunky evhttp_make_header_response(struct evhttp_connection *evcon,
    536  1.1    plunky     struct evhttp_request *req)
    537  1.1    plunky {
    538  1.1    plunky 	int is_keepalive = evhttp_is_connection_keepalive(req->input_headers);
    539  1.2  christos 	evbuffer_add_printf(bufferevent_get_output(evcon->bufev),
    540  1.2  christos 	    "HTTP/%d.%d %d %s\r\n",
    541  1.1    plunky 	    req->major, req->minor, req->response_code,
    542  1.1    plunky 	    req->response_code_line);
    543  1.1    plunky 
    544  1.1    plunky 	if (req->major == 1) {
    545  1.2  christos 		if (req->minor >= 1)
    546  1.1    plunky 			evhttp_maybe_add_date_header(req->output_headers);
    547  1.1    plunky 
    548  1.1    plunky 		/*
    549  1.1    plunky 		 * if the protocol is 1.0; and the connection was keep-alive
    550  1.1    plunky 		 * we need to add a keep-alive header, too.
    551  1.1    plunky 		 */
    552  1.1    plunky 		if (req->minor == 0 && is_keepalive)
    553  1.1    plunky 			evhttp_add_header(req->output_headers,
    554  1.1    plunky 			    "Connection", "keep-alive");
    555  1.1    plunky 
    556  1.2  christos 		if ((req->minor >= 1 || is_keepalive) &&
    557  1.2  christos 		    evhttp_response_needs_body(req)) {
    558  1.2  christos 			/*
    559  1.1    plunky 			 * we need to add the content length if the
    560  1.1    plunky 			 * user did not give it, this is required for
    561  1.1    plunky 			 * persistent connections to work.
    562  1.1    plunky 			 */
    563  1.1    plunky 			evhttp_maybe_add_content_length_header(
    564  1.1    plunky 				req->output_headers,
    565  1.2  christos 				evbuffer_get_length(req->output_buffer));
    566  1.1    plunky 		}
    567  1.1    plunky 	}
    568  1.1    plunky 
    569  1.1    plunky 	/* Potentially add headers for unidentified content. */
    570  1.2  christos 	if (evhttp_response_needs_body(req)) {
    571  1.1    plunky 		if (evhttp_find_header(req->output_headers,
    572  1.4  christos 			"Content-Type") == NULL
    573  1.4  christos 		    && evcon->http_server->default_content_type) {
    574  1.1    plunky 			evhttp_add_header(req->output_headers,
    575  1.4  christos 			    "Content-Type",
    576  1.4  christos 			    evcon->http_server->default_content_type);
    577  1.1    plunky 		}
    578  1.1    plunky 	}
    579  1.1    plunky 
    580  1.1    plunky 	/* if the request asked for a close, we send a close, too */
    581  1.1    plunky 	if (evhttp_is_connection_close(req->flags, req->input_headers)) {
    582  1.1    plunky 		evhttp_remove_header(req->output_headers, "Connection");
    583  1.1    plunky 		if (!(req->flags & EVHTTP_PROXY_REQUEST))
    584  1.1    plunky 		    evhttp_add_header(req->output_headers, "Connection", "close");
    585  1.1    plunky 		evhttp_remove_header(req->output_headers, "Proxy-Connection");
    586  1.1    plunky 	}
    587  1.1    plunky }
    588  1.1    plunky 
    589  1.4  christos enum expect { NO, CONTINUE, OTHER };
    590  1.4  christos static enum expect evhttp_have_expect(struct evhttp_request *req, int input)
    591  1.4  christos {
    592  1.4  christos 	const char *expect;
    593  1.4  christos 	struct evkeyvalq *h = input ? req->input_headers : req->output_headers;
    594  1.4  christos 
    595  1.4  christos 	if (!(req->kind == EVHTTP_REQUEST) || !REQ_VERSION_ATLEAST(req, 1, 1))
    596  1.4  christos 		return NO;
    597  1.4  christos 
    598  1.4  christos 	expect = evhttp_find_header(h, "Expect");
    599  1.4  christos 	if (!expect)
    600  1.4  christos 		return NO;
    601  1.4  christos 
    602  1.4  christos 	return !evutil_ascii_strcasecmp(expect, "100-continue") ? CONTINUE : OTHER;
    603  1.4  christos }
    604  1.4  christos 
    605  1.4  christos 
    606  1.2  christos /** Generate all headers appropriate for sending the http request in req (or
    607  1.2  christos  * the response, if we're sending a response), and write them to evcon's
    608  1.2  christos  * bufferevent. Also writes all data from req->output_buffer */
    609  1.2  christos static void
    610  1.1    plunky evhttp_make_header(struct evhttp_connection *evcon, struct evhttp_request *req)
    611  1.1    plunky {
    612  1.1    plunky 	struct evkeyval *header;
    613  1.2  christos 	struct evbuffer *output = bufferevent_get_output(evcon->bufev);
    614  1.1    plunky 
    615  1.1    plunky 	/*
    616  1.1    plunky 	 * Depending if this is a HTTP request or response, we might need to
    617  1.1    plunky 	 * add some new headers or remove existing headers.
    618  1.1    plunky 	 */
    619  1.1    plunky 	if (req->kind == EVHTTP_REQUEST) {
    620  1.1    plunky 		evhttp_make_header_request(evcon, req);
    621  1.1    plunky 	} else {
    622  1.1    plunky 		evhttp_make_header_response(evcon, req);
    623  1.1    plunky 	}
    624  1.1    plunky 
    625  1.1    plunky 	TAILQ_FOREACH(header, req->output_headers, next) {
    626  1.2  christos 		evbuffer_add_printf(output, "%s: %s\r\n",
    627  1.1    plunky 		    header->key, header->value);
    628  1.1    plunky 	}
    629  1.2  christos 	evbuffer_add(output, "\r\n", 2);
    630  1.1    plunky 
    631  1.4  christos 	if (evhttp_have_expect(req, 0) != CONTINUE &&
    632  1.4  christos 		evbuffer_get_length(req->output_buffer)) {
    633  1.1    plunky 		/*
    634  1.1    plunky 		 * For a request, we add the POST data, for a reply, this
    635  1.1    plunky 		 * is the regular data.
    636  1.1    plunky 		 */
    637  1.2  christos 		evbuffer_add_buffer(output, req->output_buffer);
    638  1.1    plunky 	}
    639  1.1    plunky }
    640  1.1    plunky 
    641  1.2  christos void
    642  1.2  christos evhttp_connection_set_max_headers_size(struct evhttp_connection *evcon,
    643  1.2  christos     ev_ssize_t new_max_headers_size)
    644  1.2  christos {
    645  1.2  christos 	if (new_max_headers_size<0)
    646  1.2  christos 		evcon->max_headers_size = EV_SIZE_MAX;
    647  1.2  christos 	else
    648  1.2  christos 		evcon->max_headers_size = new_max_headers_size;
    649  1.2  christos }
    650  1.2  christos void
    651  1.2  christos evhttp_connection_set_max_body_size(struct evhttp_connection* evcon,
    652  1.2  christos     ev_ssize_t new_max_body_size)
    653  1.1    plunky {
    654  1.2  christos 	if (new_max_body_size<0)
    655  1.2  christos 		evcon->max_body_size = EV_UINT64_MAX;
    656  1.2  christos 	else
    657  1.2  christos 		evcon->max_body_size = new_max_body_size;
    658  1.1    plunky }
    659  1.1    plunky 
    660  1.1    plunky static int
    661  1.1    plunky evhttp_connection_incoming_fail(struct evhttp_request *req,
    662  1.4  christos     enum evhttp_request_error error)
    663  1.1    plunky {
    664  1.1    plunky 	switch (error) {
    665  1.4  christos 		case EVREQ_HTTP_DATA_TOO_LONG:
    666  1.4  christos 			req->response_code = HTTP_ENTITYTOOLARGE;
    667  1.4  christos 			break;
    668  1.4  christos 		default:
    669  1.4  christos 			req->response_code = HTTP_BADREQUEST;
    670  1.4  christos 	}
    671  1.4  christos 
    672  1.4  christos 	switch (error) {
    673  1.4  christos 	case EVREQ_HTTP_TIMEOUT:
    674  1.4  christos 	case EVREQ_HTTP_EOF:
    675  1.2  christos 		/*
    676  1.1    plunky 		 * these are cases in which we probably should just
    677  1.1    plunky 		 * close the connection and not send a reply.  this
    678  1.1    plunky 		 * case may happen when a browser keeps a persistent
    679  1.2  christos 		 * connection open and we timeout on the read.  when
    680  1.2  christos 		 * the request is still being used for sending, we
    681  1.2  christos 		 * need to disassociated it from the connection here.
    682  1.1    plunky 		 */
    683  1.2  christos 		if (!req->userdone) {
    684  1.2  christos 			/* remove it so that it will not be freed */
    685  1.2  christos 			TAILQ_REMOVE(&req->evcon->requests, req, next);
    686  1.2  christos 			/* indicate that this request no longer has a
    687  1.2  christos 			 * connection object
    688  1.2  christos 			 */
    689  1.2  christos 			req->evcon = NULL;
    690  1.2  christos 		}
    691  1.1    plunky 		return (-1);
    692  1.4  christos 	case EVREQ_HTTP_INVALID_HEADER:
    693  1.4  christos 	case EVREQ_HTTP_BUFFER_ERROR:
    694  1.4  christos 	case EVREQ_HTTP_REQUEST_CANCEL:
    695  1.4  christos 	case EVREQ_HTTP_DATA_TOO_LONG:
    696  1.1    plunky 	default:	/* xxx: probably should just error on default */
    697  1.1    plunky 		/* the callback looks at the uri to determine errors */
    698  1.1    plunky 		if (req->uri) {
    699  1.2  christos 			mm_free(req->uri);
    700  1.1    plunky 			req->uri = NULL;
    701  1.1    plunky 		}
    702  1.2  christos 		if (req->uri_elems) {
    703  1.2  christos 			evhttp_uri_free(req->uri_elems);
    704  1.2  christos 			req->uri_elems = NULL;
    705  1.2  christos 		}
    706  1.1    plunky 
    707  1.2  christos 		/*
    708  1.1    plunky 		 * the callback needs to send a reply, once the reply has
    709  1.1    plunky 		 * been send, the connection should get freed.
    710  1.1    plunky 		 */
    711  1.1    plunky 		(*req->cb)(req, req->cb_arg);
    712  1.1    plunky 	}
    713  1.2  christos 
    714  1.1    plunky 	return (0);
    715  1.1    plunky }
    716  1.1    plunky 
    717  1.4  christos /* Free connection ownership of which can be acquired by user using
    718  1.4  christos  * evhttp_request_own(). */
    719  1.4  christos static inline void
    720  1.4  christos evhttp_request_free_auto(struct evhttp_request *req)
    721  1.4  christos {
    722  1.4  christos 	if (!(req->flags & EVHTTP_USER_OWNED))
    723  1.4  christos 		evhttp_request_free(req);
    724  1.4  christos }
    725  1.4  christos 
    726  1.4  christos static void
    727  1.4  christos evhttp_request_free_(struct evhttp_connection *evcon, struct evhttp_request *req)
    728  1.4  christos {
    729  1.4  christos 	TAILQ_REMOVE(&evcon->requests, req, next);
    730  1.4  christos 	evhttp_request_free_auto(req);
    731  1.4  christos }
    732  1.4  christos 
    733  1.2  christos /* Called when evcon has experienced a (non-recoverable? -NM) error, as
    734  1.2  christos  * given in error. If it's an outgoing connection, reset the connection,
    735  1.2  christos  * retry any pending requests, and inform the user.  If it's incoming,
    736  1.2  christos  * delegates to evhttp_connection_incoming_fail(). */
    737  1.1    plunky void
    738  1.4  christos evhttp_connection_fail_(struct evhttp_connection *evcon,
    739  1.4  christos     enum evhttp_request_error error)
    740  1.1    plunky {
    741  1.4  christos 	const int errsave = EVUTIL_SOCKET_ERROR();
    742  1.1    plunky 	struct evhttp_request* req = TAILQ_FIRST(&evcon->requests);
    743  1.1    plunky 	void (*cb)(struct evhttp_request *, void *);
    744  1.1    plunky 	void *cb_arg;
    745  1.4  christos 	void (*error_cb)(enum evhttp_request_error, void *);
    746  1.4  christos 	void *error_cb_arg;
    747  1.2  christos 	EVUTIL_ASSERT(req != NULL);
    748  1.2  christos 
    749  1.2  christos 	bufferevent_disable(evcon->bufev, EV_READ|EV_WRITE);
    750  1.2  christos 
    751  1.1    plunky 	if (evcon->flags & EVHTTP_CON_INCOMING) {
    752  1.2  christos 		/*
    753  1.1    plunky 		 * for incoming requests, there are two different
    754  1.1    plunky 		 * failure cases.  it's either a network level error
    755  1.1    plunky 		 * or an http layer error. for problems on the network
    756  1.1    plunky 		 * layer like timeouts we just drop the connections.
    757  1.1    plunky 		 * For HTTP problems, we might have to send back a
    758  1.1    plunky 		 * reply before the connection can be freed.
    759  1.1    plunky 		 */
    760  1.1    plunky 		if (evhttp_connection_incoming_fail(req, error) == -1)
    761  1.1    plunky 			evhttp_connection_free(evcon);
    762  1.1    plunky 		return;
    763  1.1    plunky 	}
    764  1.1    plunky 
    765  1.4  christos 	error_cb = req->error_cb;
    766  1.4  christos 	error_cb_arg = req->cb_arg;
    767  1.2  christos 	/* when the request was canceled, the callback is not executed */
    768  1.4  christos 	if (error != EVREQ_HTTP_REQUEST_CANCEL) {
    769  1.2  christos 		/* save the callback for later; the cb might free our object */
    770  1.2  christos 		cb = req->cb;
    771  1.2  christos 		cb_arg = req->cb_arg;
    772  1.2  christos 	} else {
    773  1.2  christos 		cb = NULL;
    774  1.2  christos 		cb_arg = NULL;
    775  1.2  christos 	}
    776  1.1    plunky 
    777  1.2  christos 	/* do not fail all requests; the next request is going to get
    778  1.2  christos 	 * send over a new connection.   when a user cancels a request,
    779  1.2  christos 	 * all other pending requests should be processed as normal
    780  1.2  christos 	 */
    781  1.4  christos 	evhttp_request_free_(evcon, req);
    782  1.1    plunky 
    783  1.1    plunky 	/* reset the connection */
    784  1.4  christos 	evhttp_connection_reset_(evcon);
    785  1.2  christos 
    786  1.1    plunky 	/* We are trying the next request that was queued on us */
    787  1.1    plunky 	if (TAILQ_FIRST(&evcon->requests) != NULL)
    788  1.4  christos 		evhttp_connection_connect_(evcon);
    789  1.5  christos 	else
    790  1.5  christos 		if ((evcon->flags & EVHTTP_CON_OUTGOING) &&
    791  1.5  christos 		    (evcon->flags & EVHTTP_CON_AUTOFREE)) {
    792  1.5  christos 			evhttp_connection_free(evcon);
    793  1.5  christos 		}
    794  1.4  christos 
    795  1.4  christos 	/* The call to evhttp_connection_reset_ overwrote errno.
    796  1.4  christos 	 * Let's restore the original errno, so that the user's
    797  1.4  christos 	 * callback can have a better idea of what the error was.
    798  1.4  christos 	 */
    799  1.4  christos 	EVUTIL_SET_SOCKET_ERROR(errsave);
    800  1.1    plunky 
    801  1.1    plunky 	/* inform the user */
    802  1.4  christos 	if (error_cb != NULL)
    803  1.4  christos 		error_cb(error, error_cb_arg);
    804  1.1    plunky 	if (cb != NULL)
    805  1.1    plunky 		(*cb)(NULL, cb_arg);
    806  1.1    plunky }
    807  1.1    plunky 
    808  1.2  christos /* Bufferevent callback: invoked when any data has been written from an
    809  1.2  christos  * http connection's bufferevent */
    810  1.2  christos static void
    811  1.2  christos evhttp_write_cb(struct bufferevent *bufev, void *arg)
    812  1.1    plunky {
    813  1.1    plunky 	struct evhttp_connection *evcon = arg;
    814  1.1    plunky 
    815  1.1    plunky 	/* Activate our call back */
    816  1.1    plunky 	if (evcon->cb != NULL)
    817  1.1    plunky 		(*evcon->cb)(evcon, evcon->cb_arg);
    818  1.1    plunky }
    819  1.1    plunky 
    820  1.1    plunky /**
    821  1.1    plunky  * Advance the connection state.
    822  1.1    plunky  * - If this is an outgoing connection, we've just processed the response;
    823  1.1    plunky  *   idle or close the connection.
    824  1.1    plunky  * - If this is an incoming connection, we've just processed the request;
    825  1.1    plunky  *   respond.
    826  1.1    plunky  */
    827  1.1    plunky static void
    828  1.1    plunky evhttp_connection_done(struct evhttp_connection *evcon)
    829  1.1    plunky {
    830  1.1    plunky 	struct evhttp_request *req = TAILQ_FIRST(&evcon->requests);
    831  1.1    plunky 	int con_outgoing = evcon->flags & EVHTTP_CON_OUTGOING;
    832  1.4  christos 	int free_evcon = 0;
    833  1.1    plunky 
    834  1.1    plunky 	if (con_outgoing) {
    835  1.1    plunky 		/* idle or close the connection */
    836  1.4  christos 		int need_close = evhttp_is_request_connection_close(req);
    837  1.1    plunky 		TAILQ_REMOVE(&evcon->requests, req, next);
    838  1.1    plunky 		req->evcon = NULL;
    839  1.1    plunky 
    840  1.1    plunky 		evcon->state = EVCON_IDLE;
    841  1.1    plunky 
    842  1.1    plunky 		/* check if we got asked to close the connection */
    843  1.1    plunky 		if (need_close)
    844  1.4  christos 			evhttp_connection_reset_(evcon);
    845  1.1    plunky 
    846  1.1    plunky 		if (TAILQ_FIRST(&evcon->requests) != NULL) {
    847  1.1    plunky 			/*
    848  1.1    plunky 			 * We have more requests; reset the connection
    849  1.1    plunky 			 * and deal with the next request.
    850  1.1    plunky 			 */
    851  1.1    plunky 			if (!evhttp_connected(evcon))
    852  1.4  christos 				evhttp_connection_connect_(evcon);
    853  1.1    plunky 			else
    854  1.1    plunky 				evhttp_request_dispatch(evcon);
    855  1.1    plunky 		} else if (!need_close) {
    856  1.1    plunky 			/*
    857  1.1    plunky 			 * The connection is going to be persistent, but we
    858  1.1    plunky 			 * need to detect if the other side closes it.
    859  1.1    plunky 			 */
    860  1.1    plunky 			evhttp_connection_start_detectclose(evcon);
    861  1.4  christos 		} else if ((evcon->flags & EVHTTP_CON_AUTOFREE)) {
    862  1.4  christos 			/*
    863  1.4  christos 			 * If we have no more requests that need completion
    864  1.4  christos 			 * and we're not waiting for the connection to close
    865  1.4  christos 			 */
    866  1.4  christos 			 free_evcon = 1;
    867  1.1    plunky 		}
    868  1.1    plunky 	} else {
    869  1.1    plunky 		/*
    870  1.1    plunky 		 * incoming connection - we need to leave the request on the
    871  1.1    plunky 		 * connection so that we can reply to it.
    872  1.1    plunky 		 */
    873  1.1    plunky 		evcon->state = EVCON_WRITING;
    874  1.1    plunky 	}
    875  1.1    plunky 
    876  1.1    plunky 	/* notify the user of the request */
    877  1.1    plunky 	(*req->cb)(req, req->cb_arg);
    878  1.1    plunky 
    879  1.4  christos 	/* if this was an outgoing request, we own and it's done. so free it. */
    880  1.4  christos 	if (con_outgoing) {
    881  1.4  christos 		evhttp_request_free_auto(req);
    882  1.4  christos 	}
    883  1.4  christos 
    884  1.4  christos 	/* If this was the last request of an outgoing connection and we're
    885  1.4  christos 	 * not waiting to receive a connection close event and we want to
    886  1.4  christos 	 * automatically free the connection. We check to ensure our request
    887  1.4  christos 	 * list is empty one last time just in case our callback added a
    888  1.4  christos 	 * new request.
    889  1.2  christos 	 */
    890  1.4  christos 	if (free_evcon && TAILQ_FIRST(&evcon->requests) == NULL) {
    891  1.4  christos 		evhttp_connection_free(evcon);
    892  1.1    plunky 	}
    893  1.1    plunky }
    894  1.1    plunky 
    895  1.1    plunky /*
    896  1.1    plunky  * Handles reading from a chunked request.
    897  1.1    plunky  *   return ALL_DATA_READ:
    898  1.1    plunky  *     all data has been read
    899  1.1    plunky  *   return MORE_DATA_EXPECTED:
    900  1.1    plunky  *     more data is expected
    901  1.1    plunky  *   return DATA_CORRUPTED:
    902  1.1    plunky  *     data is corrupted
    903  1.2  christos  *   return REQUEST_CANCELED:
    904  1.1    plunky  *     request was canceled by the user calling evhttp_cancel_request
    905  1.2  christos  *   return DATA_TOO_LONG:
    906  1.2  christos  *     ran over the maximum limit
    907  1.1    plunky  */
    908  1.1    plunky 
    909  1.1    plunky static enum message_read_status
    910  1.1    plunky evhttp_handle_chunked_read(struct evhttp_request *req, struct evbuffer *buf)
    911  1.1    plunky {
    912  1.2  christos 	if (req == NULL || buf == NULL) {
    913  1.2  christos 	    return DATA_CORRUPTED;
    914  1.2  christos 	}
    915  1.2  christos 
    916  1.2  christos 	while (1) {
    917  1.2  christos 		size_t buflen;
    918  1.2  christos 
    919  1.2  christos 		if ((buflen = evbuffer_get_length(buf)) == 0) {
    920  1.2  christos 			break;
    921  1.2  christos 		}
    922  1.2  christos 
    923  1.2  christos 		/* evbuffer_get_length returns size_t, but len variable is ssize_t,
    924  1.2  christos 		 * check for overflow conditions */
    925  1.2  christos 		if (buflen > EV_SSIZE_MAX) {
    926  1.2  christos 			return DATA_CORRUPTED;
    927  1.2  christos 		}
    928  1.1    plunky 
    929  1.1    plunky 		if (req->ntoread < 0) {
    930  1.1    plunky 			/* Read chunk size */
    931  1.1    plunky 			ev_int64_t ntoread;
    932  1.2  christos 			char *p = evbuffer_readln(buf, NULL, EVBUFFER_EOL_CRLF);
    933  1.1    plunky 			char *endp;
    934  1.1    plunky 			int error;
    935  1.1    plunky 			if (p == NULL)
    936  1.1    plunky 				break;
    937  1.1    plunky 			/* the last chunk is on a new line? */
    938  1.1    plunky 			if (strlen(p) == 0) {
    939  1.2  christos 				mm_free(p);
    940  1.1    plunky 				continue;
    941  1.1    plunky 			}
    942  1.1    plunky 			ntoread = evutil_strtoll(p, &endp, 16);
    943  1.1    plunky 			error = (*p == '\0' ||
    944  1.1    plunky 			    (*endp != '\0' && *endp != ' ') ||
    945  1.1    plunky 			    ntoread < 0);
    946  1.2  christos 			mm_free(p);
    947  1.1    plunky 			if (error) {
    948  1.1    plunky 				/* could not get chunk size */
    949  1.1    plunky 				return (DATA_CORRUPTED);
    950  1.1    plunky 			}
    951  1.2  christos 
    952  1.2  christos 			/* ntoread is signed int64, body_size is unsigned size_t, check for under/overflow conditions */
    953  1.2  christos 			if ((ev_uint64_t)ntoread > EV_SIZE_MAX - req->body_size) {
    954  1.2  christos 			    return DATA_CORRUPTED;
    955  1.2  christos 			}
    956  1.2  christos 
    957  1.2  christos 			if (req->body_size + (size_t)ntoread > req->evcon->max_body_size) {
    958  1.2  christos 				/* failed body length test */
    959  1.2  christos 				event_debug(("Request body is too long"));
    960  1.2  christos 				return (DATA_TOO_LONG);
    961  1.2  christos 			}
    962  1.2  christos 
    963  1.2  christos 			req->body_size += (size_t)ntoread;
    964  1.1    plunky 			req->ntoread = ntoread;
    965  1.1    plunky 			if (req->ntoread == 0) {
    966  1.1    plunky 				/* Last chunk */
    967  1.1    plunky 				return (ALL_DATA_READ);
    968  1.1    plunky 			}
    969  1.1    plunky 			continue;
    970  1.1    plunky 		}
    971  1.1    plunky 
    972  1.2  christos 		/* req->ntoread is signed int64, len is ssize_t, based on arch,
    973  1.2  christos 		 * ssize_t could only be 32b, check for these conditions */
    974  1.2  christos 		if (req->ntoread > EV_SSIZE_MAX) {
    975  1.2  christos 			return DATA_CORRUPTED;
    976  1.2  christos 		}
    977  1.2  christos 
    978  1.1    plunky 		/* don't have enough to complete a chunk; wait for more */
    979  1.2  christos 		if (req->ntoread > 0 && buflen < (ev_uint64_t)req->ntoread)
    980  1.1    plunky 			return (MORE_DATA_EXPECTED);
    981  1.1    plunky 
    982  1.1    plunky 		/* Completed chunk */
    983  1.2  christos 		evbuffer_remove_buffer(buf, req->input_buffer, (size_t)req->ntoread);
    984  1.1    plunky 		req->ntoread = -1;
    985  1.1    plunky 		if (req->chunk_cb != NULL) {
    986  1.2  christos 			req->flags |= EVHTTP_REQ_DEFER_FREE;
    987  1.1    plunky 			(*req->chunk_cb)(req, req->cb_arg);
    988  1.1    plunky 			evbuffer_drain(req->input_buffer,
    989  1.2  christos 			    evbuffer_get_length(req->input_buffer));
    990  1.2  christos 			req->flags &= ~EVHTTP_REQ_DEFER_FREE;
    991  1.2  christos 			if ((req->flags & EVHTTP_REQ_NEEDS_FREE) != 0) {
    992  1.2  christos 				return (REQUEST_CANCELED);
    993  1.2  christos 			}
    994  1.1    plunky 		}
    995  1.1    plunky 	}
    996  1.1    plunky 
    997  1.1    plunky 	return (MORE_DATA_EXPECTED);
    998  1.1    plunky }
    999  1.1    plunky 
   1000  1.1    plunky static void
   1001  1.1    plunky evhttp_read_trailer(struct evhttp_connection *evcon, struct evhttp_request *req)
   1002  1.1    plunky {
   1003  1.2  christos 	struct evbuffer *buf = bufferevent_get_input(evcon->bufev);
   1004  1.1    plunky 
   1005  1.4  christos 	switch (evhttp_parse_headers_(req, buf)) {
   1006  1.1    plunky 	case DATA_CORRUPTED:
   1007  1.2  christos 	case DATA_TOO_LONG:
   1008  1.4  christos 		evhttp_connection_fail_(evcon, EVREQ_HTTP_DATA_TOO_LONG);
   1009  1.1    plunky 		break;
   1010  1.1    plunky 	case ALL_DATA_READ:
   1011  1.2  christos 		bufferevent_disable(evcon->bufev, EV_READ);
   1012  1.1    plunky 		evhttp_connection_done(evcon);
   1013  1.1    plunky 		break;
   1014  1.1    plunky 	case MORE_DATA_EXPECTED:
   1015  1.2  christos 	case REQUEST_CANCELED: /* ??? */
   1016  1.1    plunky 	default:
   1017  1.1    plunky 		break;
   1018  1.1    plunky 	}
   1019  1.1    plunky }
   1020  1.1    plunky 
   1021  1.1    plunky static void
   1022  1.4  christos evhttp_lingering_close(struct evhttp_connection *evcon,
   1023  1.4  christos 	struct evhttp_request *req)
   1024  1.4  christos {
   1025  1.4  christos 	struct evbuffer *buf = bufferevent_get_input(evcon->bufev);
   1026  1.4  christos 
   1027  1.4  christos 	size_t n = evbuffer_get_length(buf);
   1028  1.4  christos 	if (n > (size_t) req->ntoread)
   1029  1.4  christos 		n = (size_t) req->ntoread;
   1030  1.4  christos 	req->ntoread -= n;
   1031  1.4  christos 	req->body_size += n;
   1032  1.4  christos 
   1033  1.4  christos 	event_debug(("Request body is too long, left " EV_I64_FMT,
   1034  1.4  christos 		EV_I64_ARG(req->ntoread)));
   1035  1.4  christos 
   1036  1.4  christos 	evbuffer_drain(buf, n);
   1037  1.4  christos 	if (!req->ntoread)
   1038  1.4  christos 		evhttp_connection_fail_(evcon, EVREQ_HTTP_DATA_TOO_LONG);
   1039  1.4  christos }
   1040  1.4  christos static void
   1041  1.4  christos evhttp_lingering_fail(struct evhttp_connection *evcon,
   1042  1.4  christos 	struct evhttp_request *req)
   1043  1.4  christos {
   1044  1.4  christos 	if (evcon->flags & EVHTTP_CON_LINGERING_CLOSE)
   1045  1.4  christos 		evhttp_lingering_close(evcon, req);
   1046  1.4  christos 	else
   1047  1.4  christos 		evhttp_connection_fail_(evcon, EVREQ_HTTP_DATA_TOO_LONG);
   1048  1.4  christos }
   1049  1.4  christos 
   1050  1.4  christos static void
   1051  1.1    plunky evhttp_read_body(struct evhttp_connection *evcon, struct evhttp_request *req)
   1052  1.1    plunky {
   1053  1.2  christos 	struct evbuffer *buf = bufferevent_get_input(evcon->bufev);
   1054  1.2  christos 
   1055  1.1    plunky 	if (req->chunked) {
   1056  1.1    plunky 		switch (evhttp_handle_chunked_read(req, buf)) {
   1057  1.1    plunky 		case ALL_DATA_READ:
   1058  1.1    plunky 			/* finished last chunk */
   1059  1.1    plunky 			evcon->state = EVCON_READING_TRAILER;
   1060  1.1    plunky 			evhttp_read_trailer(evcon, req);
   1061  1.1    plunky 			return;
   1062  1.1    plunky 		case DATA_CORRUPTED:
   1063  1.4  christos 		case DATA_TOO_LONG:
   1064  1.1    plunky 			/* corrupted data */
   1065  1.4  christos 			evhttp_connection_fail_(evcon,
   1066  1.4  christos 			    EVREQ_HTTP_DATA_TOO_LONG);
   1067  1.1    plunky 			return;
   1068  1.1    plunky 		case REQUEST_CANCELED:
   1069  1.1    plunky 			/* request canceled */
   1070  1.4  christos 			evhttp_request_free_auto(req);
   1071  1.1    plunky 			return;
   1072  1.1    plunky 		case MORE_DATA_EXPECTED:
   1073  1.1    plunky 		default:
   1074  1.1    plunky 			break;
   1075  1.1    plunky 		}
   1076  1.1    plunky 	} else if (req->ntoread < 0) {
   1077  1.1    plunky 		/* Read until connection close. */
   1078  1.2  christos 		if ((size_t)(req->body_size + evbuffer_get_length(buf)) < req->body_size) {
   1079  1.4  christos 			evhttp_connection_fail_(evcon, EVREQ_HTTP_INVALID_HEADER);
   1080  1.2  christos 			return;
   1081  1.2  christos 		}
   1082  1.2  christos 
   1083  1.2  christos 		req->body_size += evbuffer_get_length(buf);
   1084  1.1    plunky 		evbuffer_add_buffer(req->input_buffer, buf);
   1085  1.2  christos 	} else if (req->chunk_cb != NULL || evbuffer_get_length(buf) >= (size_t)req->ntoread) {
   1086  1.2  christos 		/* XXX: the above get_length comparison has to be fixed for overflow conditions! */
   1087  1.2  christos 		/* We've postponed moving the data until now, but we're
   1088  1.2  christos 		 * about to use it. */
   1089  1.2  christos 		size_t n = evbuffer_get_length(buf);
   1090  1.2  christos 
   1091  1.2  christos 		if (n > (size_t) req->ntoread)
   1092  1.2  christos 			n = (size_t) req->ntoread;
   1093  1.2  christos 		req->ntoread -= n;
   1094  1.2  christos 		req->body_size += n;
   1095  1.2  christos 		evbuffer_remove_buffer(buf, req->input_buffer, n);
   1096  1.2  christos 	}
   1097  1.2  christos 
   1098  1.2  christos 	if (req->body_size > req->evcon->max_body_size ||
   1099  1.2  christos 	    (!req->chunked && req->ntoread >= 0 &&
   1100  1.2  christos 		(size_t)req->ntoread > req->evcon->max_body_size)) {
   1101  1.2  christos 		/* XXX: The above casted comparison must checked for overflow */
   1102  1.2  christos 		/* failed body length test */
   1103  1.4  christos 
   1104  1.4  christos 		evhttp_lingering_fail(evcon, req);
   1105  1.2  christos 		return;
   1106  1.2  christos 	}
   1107  1.2  christos 
   1108  1.2  christos 	if (evbuffer_get_length(req->input_buffer) > 0 && req->chunk_cb != NULL) {
   1109  1.2  christos 		req->flags |= EVHTTP_REQ_DEFER_FREE;
   1110  1.2  christos 		(*req->chunk_cb)(req, req->cb_arg);
   1111  1.2  christos 		req->flags &= ~EVHTTP_REQ_DEFER_FREE;
   1112  1.2  christos 		evbuffer_drain(req->input_buffer,
   1113  1.2  christos 		    evbuffer_get_length(req->input_buffer));
   1114  1.2  christos 		if ((req->flags & EVHTTP_REQ_NEEDS_FREE) != 0) {
   1115  1.4  christos 			evhttp_request_free_auto(req);
   1116  1.2  christos 			return;
   1117  1.2  christos 		}
   1118  1.2  christos 	}
   1119  1.2  christos 
   1120  1.4  christos 	if (!req->ntoread) {
   1121  1.2  christos 		bufferevent_disable(evcon->bufev, EV_READ);
   1122  1.1    plunky 		/* Completed content length */
   1123  1.1    plunky 		evhttp_connection_done(evcon);
   1124  1.1    plunky 		return;
   1125  1.1    plunky 	}
   1126  1.1    plunky }
   1127  1.1    plunky 
   1128  1.2  christos #define get_deferred_queue(evcon)		\
   1129  1.4  christos 	((evcon)->base)
   1130  1.2  christos 
   1131  1.1    plunky /*
   1132  1.2  christos  * Gets called when more data becomes available
   1133  1.1    plunky  */
   1134  1.1    plunky 
   1135  1.2  christos static void
   1136  1.2  christos evhttp_read_cb(struct bufferevent *bufev, void *arg)
   1137  1.1    plunky {
   1138  1.1    plunky 	struct evhttp_connection *evcon = arg;
   1139  1.1    plunky 	struct evhttp_request *req = TAILQ_FIRST(&evcon->requests);
   1140  1.1    plunky 
   1141  1.2  christos 	/* Cancel if it's pending. */
   1142  1.4  christos 	event_deferred_cb_cancel_(get_deferred_queue(evcon),
   1143  1.2  christos 	    &evcon->read_more_deferred_cb);
   1144  1.1    plunky 
   1145  1.1    plunky 	switch (evcon->state) {
   1146  1.1    plunky 	case EVCON_READING_FIRSTLINE:
   1147  1.1    plunky 		evhttp_read_firstline(evcon, req);
   1148  1.2  christos 		/* note the request may have been freed in
   1149  1.2  christos 		 * evhttp_read_body */
   1150  1.1    plunky 		break;
   1151  1.1    plunky 	case EVCON_READING_HEADERS:
   1152  1.1    plunky 		evhttp_read_header(evcon, req);
   1153  1.2  christos 		/* note the request may have been freed in
   1154  1.2  christos 		 * evhttp_read_body */
   1155  1.1    plunky 		break;
   1156  1.1    plunky 	case EVCON_READING_BODY:
   1157  1.1    plunky 		evhttp_read_body(evcon, req);
   1158  1.2  christos 		/* note the request may have been freed in
   1159  1.2  christos 		 * evhttp_read_body */
   1160  1.1    plunky 		break;
   1161  1.1    plunky 	case EVCON_READING_TRAILER:
   1162  1.1    plunky 		evhttp_read_trailer(evcon, req);
   1163  1.1    plunky 		break;
   1164  1.2  christos 	case EVCON_IDLE:
   1165  1.2  christos 		{
   1166  1.2  christos #ifdef USE_DEBUG
   1167  1.2  christos 			struct evbuffer *input;
   1168  1.2  christos 			size_t total_len;
   1169  1.2  christos 
   1170  1.2  christos 			input = bufferevent_get_input(evcon->bufev);
   1171  1.2  christos 			total_len = evbuffer_get_length(input);
   1172  1.2  christos 			event_debug(("%s: read "EV_SIZE_FMT
   1173  1.2  christos 				" bytes in EVCON_IDLE state,"
   1174  1.2  christos 				" resetting connection",
   1175  1.2  christos 				__func__, EV_SIZE_ARG(total_len)));
   1176  1.2  christos #endif
   1177  1.2  christos 
   1178  1.4  christos 			evhttp_connection_reset_(evcon);
   1179  1.2  christos 		}
   1180  1.2  christos 		break;
   1181  1.1    plunky 	case EVCON_DISCONNECTED:
   1182  1.1    plunky 	case EVCON_CONNECTING:
   1183  1.1    plunky 	case EVCON_WRITING:
   1184  1.1    plunky 	default:
   1185  1.1    plunky 		event_errx(1, "%s: illegal connection state %d",
   1186  1.1    plunky 			   __func__, evcon->state);
   1187  1.1    plunky 	}
   1188  1.1    plunky }
   1189  1.1    plunky 
   1190  1.1    plunky static void
   1191  1.4  christos evhttp_deferred_read_cb(struct event_callback *cb, void *data)
   1192  1.2  christos {
   1193  1.2  christos 	struct evhttp_connection *evcon = data;
   1194  1.5  christos 	struct bufferevent *bev = evcon->bufev;
   1195  1.5  christos 	if (bev->readcb)
   1196  1.5  christos 		(bev->readcb)(evcon->bufev, evcon);
   1197  1.2  christos }
   1198  1.2  christos 
   1199  1.2  christos static void
   1200  1.1    plunky evhttp_write_connectioncb(struct evhttp_connection *evcon, void *arg)
   1201  1.1    plunky {
   1202  1.1    plunky 	/* This is after writing the request to the server */
   1203  1.1    plunky 	struct evhttp_request *req = TAILQ_FIRST(&evcon->requests);
   1204  1.4  christos 	struct evbuffer *output = bufferevent_get_output(evcon->bufev);
   1205  1.2  christos 	EVUTIL_ASSERT(req != NULL);
   1206  1.1    plunky 
   1207  1.2  christos 	EVUTIL_ASSERT(evcon->state == EVCON_WRITING);
   1208  1.1    plunky 
   1209  1.4  christos 	/* We need to wait until we've written all of our output data before we can
   1210  1.4  christos 	 * continue */
   1211  1.4  christos 	if (evbuffer_get_length(output) > 0)
   1212  1.4  christos 		return;
   1213  1.4  christos 
   1214  1.1    plunky 	/* We are done writing our header and are now expecting the response */
   1215  1.1    plunky 	req->kind = EVHTTP_RESPONSE;
   1216  1.1    plunky 
   1217  1.4  christos 	evhttp_start_read_(evcon);
   1218  1.1    plunky }
   1219  1.1    plunky 
   1220  1.1    plunky /*
   1221  1.1    plunky  * Clean up a connection object
   1222  1.1    plunky  */
   1223  1.1    plunky 
   1224  1.1    plunky void
   1225  1.1    plunky evhttp_connection_free(struct evhttp_connection *evcon)
   1226  1.1    plunky {
   1227  1.1    plunky 	struct evhttp_request *req;
   1228  1.5  christos 	int need_close = 0;
   1229  1.1    plunky 
   1230  1.1    plunky 	/* notify interested parties that this connection is going down */
   1231  1.1    plunky 	if (evcon->fd != -1) {
   1232  1.1    plunky 		if (evhttp_connected(evcon) && evcon->closecb != NULL)
   1233  1.1    plunky 			(*evcon->closecb)(evcon, evcon->closecb_arg);
   1234  1.1    plunky 	}
   1235  1.1    plunky 
   1236  1.2  christos 	/* remove all requests that might be queued on this
   1237  1.2  christos 	 * connection.  for server connections, this should be empty.
   1238  1.2  christos 	 * because it gets dequeued either in evhttp_connection_done or
   1239  1.4  christos 	 * evhttp_connection_fail_.
   1240  1.2  christos 	 */
   1241  1.1    plunky 	while ((req = TAILQ_FIRST(&evcon->requests)) != NULL) {
   1242  1.4  christos 		evhttp_request_free_(evcon, req);
   1243  1.1    plunky 	}
   1244  1.1    plunky 
   1245  1.1    plunky 	if (evcon->http_server != NULL) {
   1246  1.1    plunky 		struct evhttp *http = evcon->http_server;
   1247  1.1    plunky 		TAILQ_REMOVE(&http->connections, evcon, next);
   1248  1.1    plunky 	}
   1249  1.1    plunky 
   1250  1.2  christos 	if (event_initialized(&evcon->retry_ev)) {
   1251  1.2  christos 		event_del(&evcon->retry_ev);
   1252  1.2  christos 		event_debug_unassign(&evcon->retry_ev);
   1253  1.2  christos 	}
   1254  1.2  christos 
   1255  1.4  christos 	event_deferred_cb_cancel_(get_deferred_queue(evcon),
   1256  1.2  christos 	    &evcon->read_more_deferred_cb);
   1257  1.2  christos 
   1258  1.5  christos 	if (evcon->bufev != NULL) {
   1259  1.5  christos 		need_close =
   1260  1.5  christos 			!(bufferevent_get_options_(evcon->bufev) & BEV_OPT_CLOSE_ON_FREE);
   1261  1.5  christos 		if (evcon->fd == -1)
   1262  1.5  christos 			evcon->fd = bufferevent_getfd(evcon->bufev);
   1263  1.5  christos 
   1264  1.5  christos 		bufferevent_free(evcon->bufev);
   1265  1.5  christos 	}
   1266  1.4  christos 
   1267  1.2  christos 	if (evcon->fd != -1) {
   1268  1.2  christos 		shutdown(evcon->fd, EVUTIL_SHUT_WR);
   1269  1.5  christos 		if (need_close)
   1270  1.4  christos 			evutil_closesocket(evcon->fd);
   1271  1.2  christos 	}
   1272  1.1    plunky 
   1273  1.1    plunky 	if (evcon->bind_address != NULL)
   1274  1.2  christos 		mm_free(evcon->bind_address);
   1275  1.1    plunky 
   1276  1.1    plunky 	if (evcon->address != NULL)
   1277  1.2  christos 		mm_free(evcon->address);
   1278  1.1    plunky 
   1279  1.2  christos 	mm_free(evcon);
   1280  1.1    plunky }
   1281  1.1    plunky 
   1282  1.1    plunky void
   1283  1.4  christos evhttp_connection_free_on_completion(struct evhttp_connection *evcon) {
   1284  1.4  christos 	evcon->flags |= EVHTTP_CON_AUTOFREE;
   1285  1.4  christos }
   1286  1.4  christos 
   1287  1.4  christos void
   1288  1.1    plunky evhttp_connection_set_local_address(struct evhttp_connection *evcon,
   1289  1.1    plunky     const char *address)
   1290  1.1    plunky {
   1291  1.2  christos 	EVUTIL_ASSERT(evcon->state == EVCON_DISCONNECTED);
   1292  1.1    plunky 	if (evcon->bind_address)
   1293  1.2  christos 		mm_free(evcon->bind_address);
   1294  1.2  christos 	if ((evcon->bind_address = mm_strdup(address)) == NULL)
   1295  1.2  christos 		event_warn("%s: strdup", __func__);
   1296  1.1    plunky }
   1297  1.1    plunky 
   1298  1.1    plunky void
   1299  1.1    plunky evhttp_connection_set_local_port(struct evhttp_connection *evcon,
   1300  1.2  christos     ev_uint16_t port)
   1301  1.1    plunky {
   1302  1.2  christos 	EVUTIL_ASSERT(evcon->state == EVCON_DISCONNECTED);
   1303  1.1    plunky 	evcon->bind_port = port;
   1304  1.1    plunky }
   1305  1.1    plunky 
   1306  1.1    plunky static void
   1307  1.1    plunky evhttp_request_dispatch(struct evhttp_connection* evcon)
   1308  1.1    plunky {
   1309  1.1    plunky 	struct evhttp_request *req = TAILQ_FIRST(&evcon->requests);
   1310  1.2  christos 
   1311  1.1    plunky 	/* this should not usually happy but it's possible */
   1312  1.1    plunky 	if (req == NULL)
   1313  1.1    plunky 		return;
   1314  1.1    plunky 
   1315  1.5  christos 	EVUTIL_ASSERT(req->kind == EVHTTP_REQUEST);
   1316  1.5  christos 
   1317  1.1    plunky 	/* delete possible close detection events */
   1318  1.1    plunky 	evhttp_connection_stop_detectclose(evcon);
   1319  1.2  christos 
   1320  1.1    plunky 	/* we assume that the connection is connected already */
   1321  1.2  christos 	EVUTIL_ASSERT(evcon->state == EVCON_IDLE);
   1322  1.1    plunky 
   1323  1.1    plunky 	evcon->state = EVCON_WRITING;
   1324  1.1    plunky 
   1325  1.1    plunky 	/* Create the header from the store arguments */
   1326  1.1    plunky 	evhttp_make_header(evcon, req);
   1327  1.1    plunky 
   1328  1.1    plunky 	evhttp_write_buffer(evcon, evhttp_write_connectioncb, NULL);
   1329  1.1    plunky }
   1330  1.1    plunky 
   1331  1.2  christos /* Reset our connection state: disables reading/writing, closes our fd (if
   1332  1.2  christos * any), clears out buffers, and puts us in state DISCONNECTED. */
   1333  1.1    plunky void
   1334  1.4  christos evhttp_connection_reset_(struct evhttp_connection *evcon)
   1335  1.1    plunky {
   1336  1.2  christos 	struct evbuffer *tmp;
   1337  1.4  christos 	int err;
   1338  1.2  christos 
   1339  1.5  christos 	bufferevent_setcb(evcon->bufev, NULL, NULL, NULL, NULL);
   1340  1.5  christos 
   1341  1.2  christos 	/* XXXX This is not actually an optimal fix.  Instead we ought to have
   1342  1.2  christos 	   an API for "stop connecting", or use bufferevent_setfd to turn off
   1343  1.2  christos 	   connecting.  But for Libevent 2.0, this seems like a minimal change
   1344  1.2  christos 	   least likely to disrupt the rest of the bufferevent and http code.
   1345  1.2  christos 
   1346  1.2  christos 	   Why is this here?  If the fd is set in the bufferevent, and the
   1347  1.2  christos 	   bufferevent is connecting, then you can't actually stop the
   1348  1.2  christos 	   bufferevent from trying to connect with bufferevent_disable().  The
   1349  1.2  christos 	   connect will never trigger, since we close the fd, but the timeout
   1350  1.4  christos 	   might.  That caused an assertion failure in evhttp_connection_fail_.
   1351  1.2  christos 	*/
   1352  1.4  christos 	bufferevent_disable_hard_(evcon->bufev, EV_READ|EV_WRITE);
   1353  1.4  christos 
   1354  1.4  christos 	if (evcon->fd == -1)
   1355  1.4  christos 		evcon->fd = bufferevent_getfd(evcon->bufev);
   1356  1.1    plunky 
   1357  1.1    plunky 	if (evcon->fd != -1) {
   1358  1.1    plunky 		/* inform interested parties about connection close */
   1359  1.1    plunky 		if (evhttp_connected(evcon) && evcon->closecb != NULL)
   1360  1.1    plunky 			(*evcon->closecb)(evcon, evcon->closecb_arg);
   1361  1.1    plunky 
   1362  1.2  christos 		shutdown(evcon->fd, EVUTIL_SHUT_WR);
   1363  1.2  christos 		evutil_closesocket(evcon->fd);
   1364  1.1    plunky 		evcon->fd = -1;
   1365  1.1    plunky 	}
   1366  1.5  christos 	err = bufferevent_setfd(evcon->bufev, -1);
   1367  1.5  christos 	EVUTIL_ASSERT(!err && "setfd");
   1368  1.1    plunky 
   1369  1.2  christos 	/* we need to clean up any buffered data */
   1370  1.2  christos 	tmp = bufferevent_get_output(evcon->bufev);
   1371  1.4  christos 	err = evbuffer_drain(tmp, -1);
   1372  1.4  christos 	EVUTIL_ASSERT(!err && "drain output");
   1373  1.2  christos 	tmp = bufferevent_get_input(evcon->bufev);
   1374  1.4  christos 	err = evbuffer_drain(tmp, -1);
   1375  1.4  christos 	EVUTIL_ASSERT(!err && "drain input");
   1376  1.4  christos 
   1377  1.4  christos 	evcon->flags &= ~EVHTTP_CON_READING_ERROR;
   1378  1.1    plunky 
   1379  1.2  christos 	evcon->state = EVCON_DISCONNECTED;
   1380  1.1    plunky }
   1381  1.1    plunky 
   1382  1.1    plunky static void
   1383  1.1    plunky evhttp_connection_start_detectclose(struct evhttp_connection *evcon)
   1384  1.1    plunky {
   1385  1.1    plunky 	evcon->flags |= EVHTTP_CON_CLOSEDETECT;
   1386  1.2  christos 	bufferevent_enable(evcon->bufev, EV_READ);
   1387  1.1    plunky }
   1388  1.1    plunky 
   1389  1.1    plunky static void
   1390  1.1    plunky evhttp_connection_stop_detectclose(struct evhttp_connection *evcon)
   1391  1.1    plunky {
   1392  1.1    plunky 	evcon->flags &= ~EVHTTP_CON_CLOSEDETECT;
   1393  1.2  christos 	bufferevent_disable(evcon->bufev, EV_READ);
   1394  1.1    plunky }
   1395  1.1    plunky 
   1396  1.1    plunky static void
   1397  1.2  christos evhttp_connection_retry(evutil_socket_t fd, short what, void *arg)
   1398  1.1    plunky {
   1399  1.1    plunky 	struct evhttp_connection *evcon = arg;
   1400  1.1    plunky 
   1401  1.1    plunky 	evcon->state = EVCON_DISCONNECTED;
   1402  1.4  christos 	evhttp_connection_connect_(evcon);
   1403  1.1    plunky }
   1404  1.1    plunky 
   1405  1.1    plunky static void
   1406  1.2  christos evhttp_connection_cb_cleanup(struct evhttp_connection *evcon)
   1407  1.1    plunky {
   1408  1.2  christos 	struct evcon_requestq requests;
   1409  1.1    plunky 
   1410  1.4  christos 	evhttp_connection_reset_(evcon);
   1411  1.1    plunky 	if (evcon->retry_max < 0 || evcon->retry_cnt < evcon->retry_max) {
   1412  1.4  christos 		struct timeval tv_retry = evcon->initial_retry_timeout;
   1413  1.4  christos 		int i;
   1414  1.2  christos 		evtimer_assign(&evcon->retry_ev, evcon->base, evhttp_connection_retry, evcon);
   1415  1.2  christos 		/* XXXX handle failure from evhttp_add_event */
   1416  1.4  christos 		for (i=0; i < evcon->retry_cnt; ++i) {
   1417  1.4  christos 			tv_retry.tv_usec *= 2;
   1418  1.4  christos 			if (tv_retry.tv_usec > 1000000) {
   1419  1.4  christos 				tv_retry.tv_usec -= 1000000;
   1420  1.4  christos 				tv_retry.tv_sec += 1;
   1421  1.4  christos 			}
   1422  1.4  christos 			tv_retry.tv_sec *= 2;
   1423  1.4  christos 			if (tv_retry.tv_sec > 3600) {
   1424  1.4  christos 				tv_retry.tv_sec = 3600;
   1425  1.4  christos 				tv_retry.tv_usec = 0;
   1426  1.4  christos 			}
   1427  1.4  christos 		}
   1428  1.4  christos 		event_add(&evcon->retry_ev, &tv_retry);
   1429  1.1    plunky 		evcon->retry_cnt++;
   1430  1.1    plunky 		return;
   1431  1.1    plunky 	}
   1432  1.1    plunky 
   1433  1.2  christos 	/*
   1434  1.2  christos 	 * User callback can do evhttp_make_request() on the same
   1435  1.2  christos 	 * evcon so new request will be added to evcon->requests.  To
   1436  1.2  christos 	 * avoid freeing it prematurely we iterate over the copy of
   1437  1.2  christos 	 * the queue.
   1438  1.2  christos 	 */
   1439  1.2  christos 	TAILQ_INIT(&requests);
   1440  1.1    plunky 	while (TAILQ_FIRST(&evcon->requests) != NULL) {
   1441  1.1    plunky 		struct evhttp_request *request = TAILQ_FIRST(&evcon->requests);
   1442  1.1    plunky 		TAILQ_REMOVE(&evcon->requests, request, next);
   1443  1.2  christos 		TAILQ_INSERT_TAIL(&requests, request, next);
   1444  1.2  christos 	}
   1445  1.2  christos 
   1446  1.2  christos 	/* for now, we just signal all requests by executing their callbacks */
   1447  1.2  christos 	while (TAILQ_FIRST(&requests) != NULL) {
   1448  1.2  christos 		struct evhttp_request *request = TAILQ_FIRST(&requests);
   1449  1.2  christos 		TAILQ_REMOVE(&requests, request, next);
   1450  1.1    plunky 		request->evcon = NULL;
   1451  1.1    plunky 
   1452  1.1    plunky 		/* we might want to set an error here */
   1453  1.1    plunky 		request->cb(request, request->cb_arg);
   1454  1.4  christos 		evhttp_request_free_auto(request);
   1455  1.1    plunky 	}
   1456  1.1    plunky }
   1457  1.1    plunky 
   1458  1.2  christos static void
   1459  1.4  christos evhttp_connection_read_on_write_error(struct evhttp_connection *evcon,
   1460  1.4  christos     struct evhttp_request *req)
   1461  1.4  christos {
   1462  1.4  christos 	struct evbuffer *buf;
   1463  1.4  christos 
   1464  1.4  christos 	/** Second time, we can't read anything */
   1465  1.4  christos 	if (evcon->flags & EVHTTP_CON_READING_ERROR) {
   1466  1.4  christos 		evcon->flags &= ~EVHTTP_CON_READING_ERROR;
   1467  1.4  christos 		evhttp_connection_fail_(evcon, EVREQ_HTTP_EOF);
   1468  1.4  christos 		return;
   1469  1.4  christos 	}
   1470  1.4  christos 
   1471  1.4  christos 	req->kind = EVHTTP_RESPONSE;
   1472  1.4  christos 
   1473  1.4  christos 	buf = bufferevent_get_output(evcon->bufev);
   1474  1.4  christos 	evbuffer_unfreeze(buf, 1);
   1475  1.4  christos 	evbuffer_drain(buf, evbuffer_get_length(buf));
   1476  1.4  christos 	evbuffer_freeze(buf, 1);
   1477  1.4  christos 
   1478  1.4  christos 	evhttp_start_read_(evcon);
   1479  1.4  christos 	evcon->flags |= EVHTTP_CON_READING_ERROR;
   1480  1.4  christos }
   1481  1.4  christos 
   1482  1.4  christos static void
   1483  1.2  christos evhttp_error_cb(struct bufferevent *bufev, short what, void *arg)
   1484  1.2  christos {
   1485  1.2  christos 	struct evhttp_connection *evcon = arg;
   1486  1.2  christos 	struct evhttp_request *req = TAILQ_FIRST(&evcon->requests);
   1487  1.1    plunky 
   1488  1.4  christos 	if (evcon->fd == -1)
   1489  1.4  christos 		evcon->fd = bufferevent_getfd(bufev);
   1490  1.4  christos 
   1491  1.2  christos 	switch (evcon->state) {
   1492  1.2  christos 	case EVCON_CONNECTING:
   1493  1.2  christos 		if (what & BEV_EVENT_TIMEOUT) {
   1494  1.2  christos 			event_debug(("%s: connection timeout for \"%s:%d\" on "
   1495  1.2  christos 				EV_SOCK_FMT,
   1496  1.2  christos 				__func__, evcon->address, evcon->port,
   1497  1.2  christos 				EV_SOCK_ARG(evcon->fd)));
   1498  1.2  christos 			evhttp_connection_cb_cleanup(evcon);
   1499  1.2  christos 			return;
   1500  1.2  christos 		}
   1501  1.2  christos 		break;
   1502  1.2  christos 
   1503  1.2  christos 	case EVCON_READING_BODY:
   1504  1.2  christos 		if (!req->chunked && req->ntoread < 0
   1505  1.2  christos 		    && what == (BEV_EVENT_READING|BEV_EVENT_EOF)) {
   1506  1.2  christos 			/* EOF on read can be benign */
   1507  1.2  christos 			evhttp_connection_done(evcon);
   1508  1.2  christos 			return;
   1509  1.2  christos 		}
   1510  1.2  christos 		break;
   1511  1.2  christos 
   1512  1.2  christos 	case EVCON_DISCONNECTED:
   1513  1.2  christos 	case EVCON_IDLE:
   1514  1.2  christos 	case EVCON_READING_FIRSTLINE:
   1515  1.2  christos 	case EVCON_READING_HEADERS:
   1516  1.2  christos 	case EVCON_READING_TRAILER:
   1517  1.2  christos 	case EVCON_WRITING:
   1518  1.2  christos 	default:
   1519  1.2  christos 		break;
   1520  1.2  christos 	}
   1521  1.2  christos 
   1522  1.2  christos 	/* when we are in close detect mode, a read error means that
   1523  1.2  christos 	 * the other side closed their connection.
   1524  1.2  christos 	 */
   1525  1.2  christos 	if (evcon->flags & EVHTTP_CON_CLOSEDETECT) {
   1526  1.2  christos 		evcon->flags &= ~EVHTTP_CON_CLOSEDETECT;
   1527  1.2  christos 		EVUTIL_ASSERT(evcon->http_server == NULL);
   1528  1.2  christos 		/* For connections from the client, we just
   1529  1.2  christos 		 * reset the connection so that it becomes
   1530  1.2  christos 		 * disconnected.
   1531  1.2  christos 		 */
   1532  1.2  christos 		EVUTIL_ASSERT(evcon->state == EVCON_IDLE);
   1533  1.4  christos 		evhttp_connection_reset_(evcon);
   1534  1.4  christos 
   1535  1.4  christos 		/*
   1536  1.4  christos 		 * If we have no more requests that need completion
   1537  1.4  christos 		 * and we want to auto-free the connection when all
   1538  1.4  christos 		 * requests have been completed.
   1539  1.4  christos 		 */
   1540  1.4  christos 		if (TAILQ_FIRST(&evcon->requests) == NULL
   1541  1.4  christos 		  && (evcon->flags & EVHTTP_CON_OUTGOING)
   1542  1.4  christos 		  && (evcon->flags & EVHTTP_CON_AUTOFREE)) {
   1543  1.4  christos 			evhttp_connection_free(evcon);
   1544  1.4  christos 		}
   1545  1.2  christos 		return;
   1546  1.2  christos 	}
   1547  1.2  christos 
   1548  1.2  christos 	if (what & BEV_EVENT_TIMEOUT) {
   1549  1.4  christos 		evhttp_connection_fail_(evcon, EVREQ_HTTP_TIMEOUT);
   1550  1.2  christos 	} else if (what & (BEV_EVENT_EOF|BEV_EVENT_ERROR)) {
   1551  1.4  christos 		if (what & BEV_EVENT_WRITING &&
   1552  1.4  christos 			evcon->flags & EVHTTP_CON_READ_ON_WRITE_ERROR) {
   1553  1.4  christos 			evhttp_connection_read_on_write_error(evcon, req);
   1554  1.4  christos 			return;
   1555  1.4  christos 		}
   1556  1.4  christos 
   1557  1.5  christos 		if (what & BEV_EVENT_READING &&
   1558  1.5  christos 			evcon->flags & EVHTTP_CON_READ_ON_WRITE_ERROR &&
   1559  1.5  christos 			evbuffer_get_length(bufferevent_get_input(bufev))) {
   1560  1.5  christos 			event_deferred_cb_schedule_(get_deferred_queue(evcon),
   1561  1.5  christos 			    &evcon->read_more_deferred_cb);
   1562  1.5  christos 			return;
   1563  1.5  christos 		}
   1564  1.5  christos 
   1565  1.4  christos 		evhttp_connection_fail_(evcon, EVREQ_HTTP_EOF);
   1566  1.4  christos 	} else if (what == BEV_EVENT_CONNECTED) {
   1567  1.2  christos 	} else {
   1568  1.4  christos 		evhttp_connection_fail_(evcon, EVREQ_HTTP_BUFFER_ERROR);
   1569  1.2  christos 	}
   1570  1.2  christos }
   1571  1.2  christos 
   1572  1.2  christos /*
   1573  1.2  christos  * Event callback for asynchronous connection attempt.
   1574  1.2  christos  */
   1575  1.2  christos static void
   1576  1.2  christos evhttp_connection_cb(struct bufferevent *bufev, short what, void *arg)
   1577  1.2  christos {
   1578  1.2  christos 	struct evhttp_connection *evcon = arg;
   1579  1.2  christos 	int error;
   1580  1.2  christos 	ev_socklen_t errsz = sizeof(error);
   1581  1.2  christos 
   1582  1.4  christos 	if (evcon->fd == -1)
   1583  1.4  christos 		evcon->fd = bufferevent_getfd(bufev);
   1584  1.4  christos 
   1585  1.2  christos 	if (!(what & BEV_EVENT_CONNECTED)) {
   1586  1.2  christos 		/* some operating systems return ECONNREFUSED immediately
   1587  1.2  christos 		 * when connecting to a local address.  the cleanup is going
   1588  1.2  christos 		 * to reschedule this function call.
   1589  1.2  christos 		 */
   1590  1.4  christos #ifndef _WIN32
   1591  1.2  christos 		if (errno == ECONNREFUSED)
   1592  1.2  christos 			goto cleanup;
   1593  1.2  christos #endif
   1594  1.2  christos 		evhttp_error_cb(bufev, what, arg);
   1595  1.2  christos 		return;
   1596  1.2  christos 	}
   1597  1.2  christos 
   1598  1.4  christos 	if (evcon->fd == -1) {
   1599  1.4  christos 		event_debug(("%s: bufferevent_getfd returned -1",
   1600  1.4  christos 			__func__));
   1601  1.4  christos 		goto cleanup;
   1602  1.4  christos 	}
   1603  1.4  christos 
   1604  1.2  christos 	/* Check if the connection completed */
   1605  1.2  christos 	if (getsockopt(evcon->fd, SOL_SOCKET, SO_ERROR, (void*)&error,
   1606  1.2  christos 		       &errsz) == -1) {
   1607  1.2  christos 		event_debug(("%s: getsockopt for \"%s:%d\" on "EV_SOCK_FMT,
   1608  1.2  christos 			__func__, evcon->address, evcon->port,
   1609  1.2  christos 			EV_SOCK_ARG(evcon->fd)));
   1610  1.2  christos 		goto cleanup;
   1611  1.2  christos 	}
   1612  1.2  christos 
   1613  1.2  christos 	if (error) {
   1614  1.2  christos 		event_debug(("%s: connect failed for \"%s:%d\" on "
   1615  1.2  christos 			EV_SOCK_FMT": %s",
   1616  1.2  christos 			__func__, evcon->address, evcon->port,
   1617  1.2  christos 			EV_SOCK_ARG(evcon->fd),
   1618  1.2  christos 			evutil_socket_error_to_string(error)));
   1619  1.2  christos 		goto cleanup;
   1620  1.2  christos 	}
   1621  1.2  christos 
   1622  1.2  christos 	/* We are connected to the server now */
   1623  1.2  christos 	event_debug(("%s: connected to \"%s:%d\" on "EV_SOCK_FMT"\n",
   1624  1.2  christos 			__func__, evcon->address, evcon->port,
   1625  1.2  christos 			EV_SOCK_ARG(evcon->fd)));
   1626  1.2  christos 
   1627  1.2  christos 	/* Reset the retry count as we were successful in connecting */
   1628  1.2  christos 	evcon->retry_cnt = 0;
   1629  1.2  christos 	evcon->state = EVCON_IDLE;
   1630  1.2  christos 
   1631  1.2  christos 	/* reset the bufferevent cbs */
   1632  1.2  christos 	bufferevent_setcb(evcon->bufev,
   1633  1.2  christos 	    evhttp_read_cb,
   1634  1.2  christos 	    evhttp_write_cb,
   1635  1.2  christos 	    evhttp_error_cb,
   1636  1.2  christos 	    evcon);
   1637  1.2  christos 
   1638  1.4  christos 	if (!evutil_timerisset(&evcon->timeout)) {
   1639  1.4  christos 		const struct timeval read_tv = { HTTP_READ_TIMEOUT, 0 };
   1640  1.4  christos 		const struct timeval write_tv = { HTTP_WRITE_TIMEOUT, 0 };
   1641  1.4  christos 		bufferevent_set_timeouts(evcon->bufev, &read_tv, &write_tv);
   1642  1.4  christos 	} else {
   1643  1.4  christos 		bufferevent_set_timeouts(evcon->bufev, &evcon->timeout, &evcon->timeout);
   1644  1.2  christos 	}
   1645  1.2  christos 
   1646  1.2  christos 	/* try to start requests that have queued up on this connection */
   1647  1.2  christos 	evhttp_request_dispatch(evcon);
   1648  1.2  christos 	return;
   1649  1.2  christos 
   1650  1.2  christos  cleanup:
   1651  1.2  christos 	evhttp_connection_cb_cleanup(evcon);
   1652  1.2  christos }
   1653  1.2  christos 
   1654  1.2  christos /*
   1655  1.2  christos  * Check if we got a valid response code.
   1656  1.2  christos  */
   1657  1.2  christos 
   1658  1.2  christos static int
   1659  1.2  christos evhttp_valid_response_code(int code)
   1660  1.2  christos {
   1661  1.2  christos 	if (code == 0)
   1662  1.2  christos 		return (0);
   1663  1.1    plunky 
   1664  1.1    plunky 	return (1);
   1665  1.1    plunky }
   1666  1.1    plunky 
   1667  1.2  christos static int
   1668  1.2  christos evhttp_parse_http_version(const char *version, struct evhttp_request *req)
   1669  1.2  christos {
   1670  1.2  christos 	int major, minor;
   1671  1.2  christos 	char ch;
   1672  1.2  christos 	int n = sscanf(version, "HTTP/%d.%d%c", &major, &minor, &ch);
   1673  1.2  christos 	if (n != 2 || major > 1) {
   1674  1.2  christos 		event_debug(("%s: bad version %s on message %p from %s",
   1675  1.2  christos 			__func__, version, req, req->remote_host));
   1676  1.2  christos 		return (-1);
   1677  1.2  christos 	}
   1678  1.2  christos 	req->major = major;
   1679  1.2  christos 	req->minor = minor;
   1680  1.2  christos 	return (0);
   1681  1.2  christos }
   1682  1.2  christos 
   1683  1.1    plunky /* Parses the status line of a web server */
   1684  1.1    plunky 
   1685  1.1    plunky static int
   1686  1.1    plunky evhttp_parse_response_line(struct evhttp_request *req, char *line)
   1687  1.1    plunky {
   1688  1.1    plunky 	char *protocol;
   1689  1.1    plunky 	char *number;
   1690  1.2  christos 	const char *readable = "";
   1691  1.1    plunky 
   1692  1.1    plunky 	protocol = strsep(&line, " ");
   1693  1.1    plunky 	if (line == NULL)
   1694  1.1    plunky 		return (-1);
   1695  1.1    plunky 	number = strsep(&line, " ");
   1696  1.2  christos 	if (line != NULL)
   1697  1.2  christos 		readable = line;
   1698  1.1    plunky 
   1699  1.2  christos 	if (evhttp_parse_http_version(protocol, req) < 0)
   1700  1.1    plunky 		return (-1);
   1701  1.1    plunky 
   1702  1.1    plunky 	req->response_code = atoi(number);
   1703  1.1    plunky 	if (!evhttp_valid_response_code(req->response_code)) {
   1704  1.1    plunky 		event_debug(("%s: bad response code \"%s\"",
   1705  1.1    plunky 			__func__, number));
   1706  1.1    plunky 		return (-1);
   1707  1.1    plunky 	}
   1708  1.1    plunky 
   1709  1.4  christos 	if (req->response_code_line != NULL)
   1710  1.4  christos 		mm_free(req->response_code_line);
   1711  1.2  christos 	if ((req->response_code_line = mm_strdup(readable)) == NULL) {
   1712  1.2  christos 		event_warn("%s: strdup", __func__);
   1713  1.2  christos 		return (-1);
   1714  1.2  christos 	}
   1715  1.1    plunky 
   1716  1.1    plunky 	return (0);
   1717  1.1    plunky }
   1718  1.1    plunky 
   1719  1.1    plunky /* Parse the first line of a HTTP request */
   1720  1.1    plunky 
   1721  1.1    plunky static int
   1722  1.5  christos evhttp_parse_request_line(struct evhttp_request *req, char *line, size_t len)
   1723  1.1    plunky {
   1724  1.5  christos 	char *eos = line + len;
   1725  1.1    plunky 	char *method;
   1726  1.1    plunky 	char *uri;
   1727  1.1    plunky 	char *version;
   1728  1.2  christos 	const char *hostname;
   1729  1.2  christos 	const char *scheme;
   1730  1.4  christos 	size_t method_len;
   1731  1.4  christos 	enum evhttp_cmd_type type;
   1732  1.1    plunky 
   1733  1.5  christos 	while (eos > line && *(eos-1) == ' ') {
   1734  1.5  christos 		*(eos-1) = '\0';
   1735  1.5  christos 		--eos;
   1736  1.5  christos 		--len;
   1737  1.5  christos 	}
   1738  1.5  christos 	if (len < strlen("GET / HTTP/1.0"))
   1739  1.5  christos 		return -1;
   1740  1.5  christos 
   1741  1.1    plunky 	/* Parse the request line */
   1742  1.1    plunky 	method = strsep(&line, " ");
   1743  1.5  christos 	if (!line)
   1744  1.5  christos 		return -1;
   1745  1.5  christos 	uri = line;
   1746  1.5  christos 	version = strrchr(uri, ' ');
   1747  1.5  christos 	if (!version || uri == version)
   1748  1.5  christos 		return -1;
   1749  1.5  christos 	*version = '\0';
   1750  1.5  christos 	version++;
   1751  1.1    plunky 
   1752  1.4  christos 	method_len = (uri - method) - 1;
   1753  1.4  christos 	type       = EVHTTP_REQ_UNKNOWN_;
   1754  1.4  christos 
   1755  1.1    plunky 	/* First line */
   1756  1.4  christos 	switch (method_len) {
   1757  1.4  christos 	    case 3:
   1758  1.4  christos 		/* The length of the method string is 3, meaning it can only be one of two methods: GET or PUT */
   1759  1.4  christos 
   1760  1.4  christos 		/* Since both GET and PUT share the same character 'T' at the end,
   1761  1.4  christos 		 * if the string doesn't have 'T', we can immediately determine this
   1762  1.4  christos 		 * is an invalid HTTP method */
   1763  1.4  christos 
   1764  1.4  christos 		if (method[2] != 'T') {
   1765  1.4  christos 		    break;
   1766  1.4  christos 		}
   1767  1.4  christos 
   1768  1.4  christos 		switch (*method) {
   1769  1.4  christos 		    case 'G':
   1770  1.4  christos 			/* This first byte is 'G', so make sure the next byte is
   1771  1.4  christos 			 * 'E', if it isn't then this isn't a valid method */
   1772  1.4  christos 
   1773  1.4  christos 			if (method[1] == 'E') {
   1774  1.4  christos 			    type = EVHTTP_REQ_GET;
   1775  1.4  christos 			}
   1776  1.4  christos 
   1777  1.4  christos 			break;
   1778  1.4  christos 		    case 'P':
   1779  1.4  christos 			/* First byte is P, check second byte for 'U', if not,
   1780  1.4  christos 			 * we know it's an invalid method */
   1781  1.4  christos 			if (method[1] == 'U') {
   1782  1.4  christos 			    type = EVHTTP_REQ_PUT;
   1783  1.4  christos 			}
   1784  1.4  christos 			break;
   1785  1.4  christos 		    default:
   1786  1.4  christos 			break;
   1787  1.4  christos 		}
   1788  1.4  christos 		break;
   1789  1.4  christos 	    case 4:
   1790  1.4  christos 		/* The method length is 4 bytes, leaving only the methods "POST" and "HEAD" */
   1791  1.4  christos 		switch (*method) {
   1792  1.4  christos 		    case 'P':
   1793  1.4  christos 			if (method[3] == 'T' && method[2] == 'S' && method[1] == 'O') {
   1794  1.4  christos 			    type = EVHTTP_REQ_POST;
   1795  1.4  christos 			}
   1796  1.4  christos 			break;
   1797  1.4  christos 		    case 'H':
   1798  1.4  christos 			if (method[3] == 'D' && method[2] == 'A' && method[1] == 'E') {
   1799  1.4  christos 			    type = EVHTTP_REQ_HEAD;
   1800  1.4  christos 			}
   1801  1.4  christos 			break;
   1802  1.4  christos 		    default:
   1803  1.4  christos 			break;
   1804  1.4  christos 		}
   1805  1.4  christos 		break;
   1806  1.4  christos 	    case 5:
   1807  1.4  christos 		/* Method length is 5 bytes, which can only encompass PATCH and TRACE */
   1808  1.4  christos 		switch (*method) {
   1809  1.4  christos 		    case 'P':
   1810  1.4  christos 			if (method[4] == 'H' && method[3] == 'C' && method[2] == 'T' && method[1] == 'A') {
   1811  1.4  christos 			    type = EVHTTP_REQ_PATCH;
   1812  1.4  christos 			}
   1813  1.4  christos 			break;
   1814  1.4  christos 		    case 'T':
   1815  1.4  christos 			if (method[4] == 'E' && method[3] == 'C' && method[2] == 'A' && method[1] == 'R') {
   1816  1.4  christos 			    type = EVHTTP_REQ_TRACE;
   1817  1.4  christos 			}
   1818  1.4  christos 
   1819  1.4  christos 			break;
   1820  1.4  christos 		    default:
   1821  1.4  christos 			break;
   1822  1.4  christos 		}
   1823  1.4  christos 		break;
   1824  1.4  christos 	    case 6:
   1825  1.4  christos 		/* Method length is 6, only valid method 6 bytes in length is DELEte */
   1826  1.4  christos 
   1827  1.4  christos 		/* If the first byte isn't 'D' then it's invalid */
   1828  1.4  christos 		if (*method != 'D') {
   1829  1.4  christos 		    break;
   1830  1.4  christos 		}
   1831  1.4  christos 
   1832  1.4  christos 		if (method[5] == 'E' && method[4] == 'T' && method[3] == 'E' && method[2] == 'L' && method[1] == 'E') {
   1833  1.4  christos 		    type = EVHTTP_REQ_DELETE;
   1834  1.4  christos 		}
   1835  1.4  christos 
   1836  1.4  christos 		break;
   1837  1.4  christos 	    case 7:
   1838  1.4  christos 		/* Method length is 7, only valid methods are "OPTIONS" and "CONNECT" */
   1839  1.4  christos 		switch (*method) {
   1840  1.4  christos 		    case 'O':
   1841  1.4  christos 			if (method[6] == 'S' && method[5] == 'N' && method[4] == 'O' &&
   1842  1.4  christos 				method[3] == 'I' && method[2] == 'T' && method[1] == 'P') {
   1843  1.4  christos 			    type = EVHTTP_REQ_OPTIONS;
   1844  1.4  christos 			}
   1845  1.4  christos 
   1846  1.4  christos 		       	break;
   1847  1.4  christos 		    case 'C':
   1848  1.4  christos 			if (method[6] == 'T' && method[5] == 'C' && method[4] == 'E' &&
   1849  1.4  christos 				method[3] == 'N' && method[2] == 'N' && method[1] == 'O') {
   1850  1.4  christos 			    type = EVHTTP_REQ_CONNECT;
   1851  1.4  christos 			}
   1852  1.4  christos 
   1853  1.4  christos 			break;
   1854  1.4  christos 		    default:
   1855  1.4  christos 			break;
   1856  1.4  christos 		}
   1857  1.4  christos 		break;
   1858  1.4  christos 	} /* switch */
   1859  1.4  christos 
   1860  1.4  christos 	if ((int)type == EVHTTP_REQ_UNKNOWN_) {
   1861  1.4  christos 	        event_debug(("%s: bad method %s on request %p from %s",
   1862  1.1    plunky 			__func__, method, req, req->remote_host));
   1863  1.4  christos                 /* No error yet; we'll give a better error later when
   1864  1.4  christos                  * we see that req->type is unsupported. */
   1865  1.2  christos 	}
   1866  1.4  christos 
   1867  1.4  christos 	req->type = type;
   1868  1.2  christos 
   1869  1.2  christos 	if (evhttp_parse_http_version(version, req) < 0)
   1870  1.5  christos 		return -1;
   1871  1.1    plunky 
   1872  1.2  christos 	if ((req->uri = mm_strdup(uri)) == NULL) {
   1873  1.2  christos 		event_debug(("%s: mm_strdup", __func__));
   1874  1.5  christos 		return -1;
   1875  1.1    plunky 	}
   1876  1.1    plunky 
   1877  1.5  christos 	if (type == EVHTTP_REQ_CONNECT) {
   1878  1.5  christos 		if ((req->uri_elems = evhttp_uri_parse_authority(req->uri)) == NULL) {
   1879  1.5  christos 			return -1;
   1880  1.5  christos 		}
   1881  1.5  christos 	} else {
   1882  1.5  christos 		if ((req->uri_elems = evhttp_uri_parse_with_flags(req->uri,
   1883  1.5  christos 			    EVHTTP_URI_NONCONFORMANT)) == NULL) {
   1884  1.5  christos 			return -1;
   1885  1.5  christos 		}
   1886  1.1    plunky 	}
   1887  1.1    plunky 
   1888  1.2  christos 	/* If we have an absolute-URI, check to see if it is an http request
   1889  1.2  christos 	   for a known vhost or server alias. If we don't know about this
   1890  1.2  christos 	   host, we consider it a proxy request. */
   1891  1.2  christos 	scheme = evhttp_uri_get_scheme(req->uri_elems);
   1892  1.2  christos 	hostname = evhttp_uri_get_host(req->uri_elems);
   1893  1.2  christos 	if (scheme && (!evutil_ascii_strcasecmp(scheme, "http") ||
   1894  1.2  christos 		       !evutil_ascii_strcasecmp(scheme, "https")) &&
   1895  1.2  christos 	    hostname &&
   1896  1.2  christos 	    !evhttp_find_vhost(req->evcon->http_server, NULL, hostname))
   1897  1.1    plunky 		req->flags |= EVHTTP_PROXY_REQUEST;
   1898  1.1    plunky 
   1899  1.5  christos 	return 0;
   1900  1.1    plunky }
   1901  1.1    plunky 
   1902  1.1    plunky const char *
   1903  1.1    plunky evhttp_find_header(const struct evkeyvalq *headers, const char *key)
   1904  1.1    plunky {
   1905  1.1    plunky 	struct evkeyval *header;
   1906  1.1    plunky 
   1907  1.1    plunky 	TAILQ_FOREACH(header, headers, next) {
   1908  1.2  christos 		if (evutil_ascii_strcasecmp(header->key, key) == 0)
   1909  1.1    plunky 			return (header->value);
   1910  1.1    plunky 	}
   1911  1.1    plunky 
   1912  1.1    plunky 	return (NULL);
   1913  1.1    plunky }
   1914  1.1    plunky 
   1915  1.1    plunky void
   1916  1.1    plunky evhttp_clear_headers(struct evkeyvalq *headers)
   1917  1.1    plunky {
   1918  1.1    plunky 	struct evkeyval *header;
   1919  1.1    plunky 
   1920  1.1    plunky 	for (header = TAILQ_FIRST(headers);
   1921  1.1    plunky 	    header != NULL;
   1922  1.1    plunky 	    header = TAILQ_FIRST(headers)) {
   1923  1.1    plunky 		TAILQ_REMOVE(headers, header, next);
   1924  1.2  christos 		mm_free(header->key);
   1925  1.2  christos 		mm_free(header->value);
   1926  1.2  christos 		mm_free(header);
   1927  1.1    plunky 	}
   1928  1.1    plunky }
   1929  1.1    plunky 
   1930  1.1    plunky /*
   1931  1.1    plunky  * Returns 0,  if the header was successfully removed.
   1932  1.1    plunky  * Returns -1, if the header could not be found.
   1933  1.1    plunky  */
   1934  1.1    plunky 
   1935  1.1    plunky int
   1936  1.1    plunky evhttp_remove_header(struct evkeyvalq *headers, const char *key)
   1937  1.1    plunky {
   1938  1.1    plunky 	struct evkeyval *header;
   1939  1.1    plunky 
   1940  1.1    plunky 	TAILQ_FOREACH(header, headers, next) {
   1941  1.2  christos 		if (evutil_ascii_strcasecmp(header->key, key) == 0)
   1942  1.1    plunky 			break;
   1943  1.1    plunky 	}
   1944  1.1    plunky 
   1945  1.1    plunky 	if (header == NULL)
   1946  1.1    plunky 		return (-1);
   1947  1.1    plunky 
   1948  1.1    plunky 	/* Free and remove the header that we found */
   1949  1.1    plunky 	TAILQ_REMOVE(headers, header, next);
   1950  1.2  christos 	mm_free(header->key);
   1951  1.2  christos 	mm_free(header->value);
   1952  1.2  christos 	mm_free(header);
   1953  1.1    plunky 
   1954  1.1    plunky 	return (0);
   1955  1.1    plunky }
   1956  1.1    plunky 
   1957  1.1    plunky static int
   1958  1.1    plunky evhttp_header_is_valid_value(const char *value)
   1959  1.1    plunky {
   1960  1.1    plunky 	const char *p = value;
   1961  1.1    plunky 
   1962  1.1    plunky 	while ((p = strpbrk(p, "\r\n")) != NULL) {
   1963  1.1    plunky 		/* we really expect only one new line */
   1964  1.1    plunky 		p += strspn(p, "\r\n");
   1965  1.1    plunky 		/* we expect a space or tab for continuation */
   1966  1.1    plunky 		if (*p != ' ' && *p != '\t')
   1967  1.1    plunky 			return (0);
   1968  1.1    plunky 	}
   1969  1.1    plunky 	return (1);
   1970  1.1    plunky }
   1971  1.1    plunky 
   1972  1.1    plunky int
   1973  1.1    plunky evhttp_add_header(struct evkeyvalq *headers,
   1974  1.1    plunky     const char *key, const char *value)
   1975  1.1    plunky {
   1976  1.1    plunky 	event_debug(("%s: key: %s val: %s\n", __func__, key, value));
   1977  1.1    plunky 
   1978  1.1    plunky 	if (strchr(key, '\r') != NULL || strchr(key, '\n') != NULL) {
   1979  1.1    plunky 		/* drop illegal headers */
   1980  1.1    plunky 		event_debug(("%s: dropping illegal header key\n", __func__));
   1981  1.1    plunky 		return (-1);
   1982  1.1    plunky 	}
   1983  1.2  christos 
   1984  1.1    plunky 	if (!evhttp_header_is_valid_value(value)) {
   1985  1.1    plunky 		event_debug(("%s: dropping illegal header value\n", __func__));
   1986  1.1    plunky 		return (-1);
   1987  1.1    plunky 	}
   1988  1.1    plunky 
   1989  1.1    plunky 	return (evhttp_add_header_internal(headers, key, value));
   1990  1.1    plunky }
   1991  1.1    plunky 
   1992  1.1    plunky static int
   1993  1.1    plunky evhttp_add_header_internal(struct evkeyvalq *headers,
   1994  1.1    plunky     const char *key, const char *value)
   1995  1.1    plunky {
   1996  1.2  christos 	struct evkeyval *header = mm_calloc(1, sizeof(struct evkeyval));
   1997  1.1    plunky 	if (header == NULL) {
   1998  1.1    plunky 		event_warn("%s: calloc", __func__);
   1999  1.1    plunky 		return (-1);
   2000  1.1    plunky 	}
   2001  1.2  christos 	if ((header->key = mm_strdup(key)) == NULL) {
   2002  1.2  christos 		mm_free(header);
   2003  1.1    plunky 		event_warn("%s: strdup", __func__);
   2004  1.1    plunky 		return (-1);
   2005  1.1    plunky 	}
   2006  1.2  christos 	if ((header->value = mm_strdup(value)) == NULL) {
   2007  1.2  christos 		mm_free(header->key);
   2008  1.2  christos 		mm_free(header);
   2009  1.1    plunky 		event_warn("%s: strdup", __func__);
   2010  1.1    plunky 		return (-1);
   2011  1.1    plunky 	}
   2012  1.1    plunky 
   2013  1.1    plunky 	TAILQ_INSERT_TAIL(headers, header, next);
   2014  1.1    plunky 
   2015  1.1    plunky 	return (0);
   2016  1.1    plunky }
   2017  1.1    plunky 
   2018  1.1    plunky /*
   2019  1.1    plunky  * Parses header lines from a request or a response into the specified
   2020  1.1    plunky  * request object given an event buffer.
   2021  1.1    plunky  *
   2022  1.1    plunky  * Returns
   2023  1.1    plunky  *   DATA_CORRUPTED      on error
   2024  1.1    plunky  *   MORE_DATA_EXPECTED  when we need to read more headers
   2025  1.1    plunky  *   ALL_DATA_READ       when all headers have been read.
   2026  1.1    plunky  */
   2027  1.1    plunky 
   2028  1.1    plunky enum message_read_status
   2029  1.4  christos evhttp_parse_firstline_(struct evhttp_request *req, struct evbuffer *buffer)
   2030  1.1    plunky {
   2031  1.1    plunky 	char *line;
   2032  1.1    plunky 	enum message_read_status status = ALL_DATA_READ;
   2033  1.1    plunky 
   2034  1.5  christos 	size_t len;
   2035  1.2  christos 	/* XXX try */
   2036  1.5  christos 	line = evbuffer_readln(buffer, &len, EVBUFFER_EOL_CRLF);
   2037  1.2  christos 	if (line == NULL) {
   2038  1.2  christos 		if (req->evcon != NULL &&
   2039  1.2  christos 		    evbuffer_get_length(buffer) > req->evcon->max_headers_size)
   2040  1.2  christos 			return (DATA_TOO_LONG);
   2041  1.2  christos 		else
   2042  1.2  christos 			return (MORE_DATA_EXPECTED);
   2043  1.2  christos 	}
   2044  1.2  christos 
   2045  1.5  christos 	if (req->evcon != NULL && len > req->evcon->max_headers_size) {
   2046  1.2  christos 		mm_free(line);
   2047  1.2  christos 		return (DATA_TOO_LONG);
   2048  1.2  christos 	}
   2049  1.2  christos 
   2050  1.5  christos 	req->headers_size = len;
   2051  1.1    plunky 
   2052  1.1    plunky 	switch (req->kind) {
   2053  1.1    plunky 	case EVHTTP_REQUEST:
   2054  1.5  christos 		if (evhttp_parse_request_line(req, line, len) == -1)
   2055  1.1    plunky 			status = DATA_CORRUPTED;
   2056  1.1    plunky 		break;
   2057  1.1    plunky 	case EVHTTP_RESPONSE:
   2058  1.1    plunky 		if (evhttp_parse_response_line(req, line) == -1)
   2059  1.1    plunky 			status = DATA_CORRUPTED;
   2060  1.1    plunky 		break;
   2061  1.1    plunky 	default:
   2062  1.1    plunky 		status = DATA_CORRUPTED;
   2063  1.1    plunky 	}
   2064  1.1    plunky 
   2065  1.2  christos 	mm_free(line);
   2066  1.1    plunky 	return (status);
   2067  1.1    plunky }
   2068  1.1    plunky 
   2069  1.1    plunky static int
   2070  1.4  christos evhttp_append_to_last_header(struct evkeyvalq *headers, char *line)
   2071  1.1    plunky {
   2072  1.1    plunky 	struct evkeyval *header = TAILQ_LAST(headers, evkeyvalq);
   2073  1.1    plunky 	char *newval;
   2074  1.1    plunky 	size_t old_len, line_len;
   2075  1.1    plunky 
   2076  1.1    plunky 	if (header == NULL)
   2077  1.1    plunky 		return (-1);
   2078  1.1    plunky 
   2079  1.1    plunky 	old_len = strlen(header->value);
   2080  1.4  christos 
   2081  1.4  christos 	/* Strip space from start and end of line. */
   2082  1.4  christos 	while (*line == ' ' || *line == '\t')
   2083  1.4  christos 		++line;
   2084  1.4  christos 	evutil_rtrim_lws_(line);
   2085  1.4  christos 
   2086  1.1    plunky 	line_len = strlen(line);
   2087  1.1    plunky 
   2088  1.4  christos 	newval = mm_realloc(header->value, old_len + line_len + 2);
   2089  1.1    plunky 	if (newval == NULL)
   2090  1.1    plunky 		return (-1);
   2091  1.1    plunky 
   2092  1.4  christos 	newval[old_len] = ' ';
   2093  1.4  christos 	memcpy(newval + old_len + 1, line, line_len + 1);
   2094  1.1    plunky 	header->value = newval;
   2095  1.1    plunky 
   2096  1.1    plunky 	return (0);
   2097  1.1    plunky }
   2098  1.1    plunky 
   2099  1.1    plunky enum message_read_status
   2100  1.4  christos evhttp_parse_headers_(struct evhttp_request *req, struct evbuffer* buffer)
   2101  1.1    plunky {
   2102  1.2  christos 	enum message_read_status errcode = DATA_CORRUPTED;
   2103  1.1    plunky 	char *line;
   2104  1.1    plunky 	enum message_read_status status = MORE_DATA_EXPECTED;
   2105  1.1    plunky 
   2106  1.1    plunky 	struct evkeyvalq* headers = req->input_headers;
   2107  1.5  christos 	size_t len;
   2108  1.5  christos 	while ((line = evbuffer_readln(buffer, &len, EVBUFFER_EOL_CRLF))
   2109  1.1    plunky 	       != NULL) {
   2110  1.1    plunky 		char *skey, *svalue;
   2111  1.1    plunky 
   2112  1.5  christos 		req->headers_size += len;
   2113  1.2  christos 
   2114  1.2  christos 		if (req->evcon != NULL &&
   2115  1.2  christos 		    req->headers_size > req->evcon->max_headers_size) {
   2116  1.2  christos 			errcode = DATA_TOO_LONG;
   2117  1.2  christos 			goto error;
   2118  1.2  christos 		}
   2119  1.2  christos 
   2120  1.1    plunky 		if (*line == '\0') { /* Last header - Done */
   2121  1.1    plunky 			status = ALL_DATA_READ;
   2122  1.2  christos 			mm_free(line);
   2123  1.1    plunky 			break;
   2124  1.1    plunky 		}
   2125  1.1    plunky 
   2126  1.1    plunky 		/* Check if this is a continuation line */
   2127  1.1    plunky 		if (*line == ' ' || *line == '\t') {
   2128  1.1    plunky 			if (evhttp_append_to_last_header(headers, line) == -1)
   2129  1.1    plunky 				goto error;
   2130  1.2  christos 			mm_free(line);
   2131  1.1    plunky 			continue;
   2132  1.1    plunky 		}
   2133  1.1    plunky 
   2134  1.1    plunky 		/* Processing of header lines */
   2135  1.1    plunky 		svalue = line;
   2136  1.1    plunky 		skey = strsep(&svalue, ":");
   2137  1.1    plunky 		if (svalue == NULL)
   2138  1.1    plunky 			goto error;
   2139  1.1    plunky 
   2140  1.1    plunky 		svalue += strspn(svalue, " ");
   2141  1.4  christos 		evutil_rtrim_lws_(svalue);
   2142  1.1    plunky 
   2143  1.1    plunky 		if (evhttp_add_header(headers, skey, svalue) == -1)
   2144  1.1    plunky 			goto error;
   2145  1.1    plunky 
   2146  1.2  christos 		mm_free(line);
   2147  1.2  christos 	}
   2148  1.2  christos 
   2149  1.2  christos 	if (status == MORE_DATA_EXPECTED) {
   2150  1.2  christos 		if (req->evcon != NULL &&
   2151  1.2  christos 		req->headers_size + evbuffer_get_length(buffer) > req->evcon->max_headers_size)
   2152  1.2  christos 			return (DATA_TOO_LONG);
   2153  1.1    plunky 	}
   2154  1.1    plunky 
   2155  1.1    plunky 	return (status);
   2156  1.1    plunky 
   2157  1.1    plunky  error:
   2158  1.2  christos 	mm_free(line);
   2159  1.2  christos 	return (errcode);
   2160  1.1    plunky }
   2161  1.1    plunky 
   2162  1.1    plunky static int
   2163  1.1    plunky evhttp_get_body_length(struct evhttp_request *req)
   2164  1.1    plunky {
   2165  1.1    plunky 	struct evkeyvalq *headers = req->input_headers;
   2166  1.1    plunky 	const char *content_length;
   2167  1.1    plunky 	const char *connection;
   2168  1.1    plunky 
   2169  1.1    plunky 	content_length = evhttp_find_header(headers, "Content-Length");
   2170  1.1    plunky 	connection = evhttp_find_header(headers, "Connection");
   2171  1.2  christos 
   2172  1.1    plunky 	if (content_length == NULL && connection == NULL)
   2173  1.1    plunky 		req->ntoread = -1;
   2174  1.1    plunky 	else if (content_length == NULL &&
   2175  1.2  christos 	    evutil_ascii_strcasecmp(connection, "Close") != 0) {
   2176  1.5  christos 		req->ntoread = 0;
   2177  1.1    plunky 	} else if (content_length == NULL) {
   2178  1.1    plunky 		req->ntoread = -1;
   2179  1.1    plunky 	} else {
   2180  1.1    plunky 		char *endp;
   2181  1.1    plunky 		ev_int64_t ntoread = evutil_strtoll(content_length, &endp, 10);
   2182  1.1    plunky 		if (*content_length == '\0' || *endp != '\0' || ntoread < 0) {
   2183  1.1    plunky 			event_debug(("%s: illegal content length: %s",
   2184  1.1    plunky 				__func__, content_length));
   2185  1.1    plunky 			return (-1);
   2186  1.1    plunky 		}
   2187  1.1    plunky 		req->ntoread = ntoread;
   2188  1.1    plunky 	}
   2189  1.2  christos 
   2190  1.2  christos 	event_debug(("%s: bytes to read: "EV_I64_FMT" (in buffer "EV_SIZE_FMT")\n",
   2191  1.2  christos 		__func__, EV_I64_ARG(req->ntoread),
   2192  1.2  christos 		EV_SIZE_ARG(evbuffer_get_length(bufferevent_get_input(req->evcon->bufev)))));
   2193  1.1    plunky 
   2194  1.1    plunky 	return (0);
   2195  1.1    plunky }
   2196  1.1    plunky 
   2197  1.2  christos static int
   2198  1.2  christos evhttp_method_may_have_body(enum evhttp_cmd_type type)
   2199  1.2  christos {
   2200  1.2  christos 	switch (type) {
   2201  1.2  christos 	case EVHTTP_REQ_POST:
   2202  1.2  christos 	case EVHTTP_REQ_PUT:
   2203  1.2  christos 	case EVHTTP_REQ_PATCH:
   2204  1.5  christos 
   2205  1.2  christos 	case EVHTTP_REQ_GET:
   2206  1.2  christos 	case EVHTTP_REQ_DELETE:
   2207  1.2  christos 	case EVHTTP_REQ_OPTIONS:
   2208  1.2  christos 	case EVHTTP_REQ_CONNECT:
   2209  1.5  christos 		return 1;
   2210  1.5  christos 
   2211  1.5  christos 	case EVHTTP_REQ_TRACE:
   2212  1.5  christos 	case EVHTTP_REQ_HEAD:
   2213  1.2  christos 	default:
   2214  1.2  christos 		return 0;
   2215  1.2  christos 	}
   2216  1.2  christos }
   2217  1.2  christos 
   2218  1.1    plunky static void
   2219  1.1    plunky evhttp_get_body(struct evhttp_connection *evcon, struct evhttp_request *req)
   2220  1.1    plunky {
   2221  1.1    plunky 	const char *xfer_enc;
   2222  1.2  christos 
   2223  1.1    plunky 	/* If this is a request without a body, then we are done */
   2224  1.2  christos 	if (req->kind == EVHTTP_REQUEST &&
   2225  1.2  christos 	    !evhttp_method_may_have_body(req->type)) {
   2226  1.1    plunky 		evhttp_connection_done(evcon);
   2227  1.1    plunky 		return;
   2228  1.1    plunky 	}
   2229  1.1    plunky 	evcon->state = EVCON_READING_BODY;
   2230  1.1    plunky 	xfer_enc = evhttp_find_header(req->input_headers, "Transfer-Encoding");
   2231  1.2  christos 	if (xfer_enc != NULL && evutil_ascii_strcasecmp(xfer_enc, "chunked") == 0) {
   2232  1.1    plunky 		req->chunked = 1;
   2233  1.1    plunky 		req->ntoread = -1;
   2234  1.1    plunky 	} else {
   2235  1.1    plunky 		if (evhttp_get_body_length(req) == -1) {
   2236  1.4  christos 			evhttp_connection_fail_(evcon, EVREQ_HTTP_INVALID_HEADER);
   2237  1.1    plunky 			return;
   2238  1.1    plunky 		}
   2239  1.2  christos 		if (req->kind == EVHTTP_REQUEST && req->ntoread < 1) {
   2240  1.2  christos 			/* An incoming request with no content-length and no
   2241  1.2  christos 			 * transfer-encoding has no body. */
   2242  1.2  christos 			evhttp_connection_done(evcon);
   2243  1.2  christos 			return;
   2244  1.2  christos 		}
   2245  1.2  christos 	}
   2246  1.2  christos 
   2247  1.2  christos 	/* Should we send a 100 Continue status line? */
   2248  1.4  christos 	switch (evhttp_have_expect(req, 1)) {
   2249  1.4  christos 		case CONTINUE:
   2250  1.2  christos 				/* XXX It would be nice to do some sanity
   2251  1.2  christos 				   checking here. Does the resource exist?
   2252  1.2  christos 				   Should the resource accept post requests? If
   2253  1.2  christos 				   no, we should respond with an error. For
   2254  1.2  christos 				   now, just optimistically tell the client to
   2255  1.2  christos 				   send their message body. */
   2256  1.2  christos 				if (req->ntoread > 0) {
   2257  1.2  christos 					/* ntoread is ev_int64_t, max_body_size is ev_uint64_t */
   2258  1.4  christos 					if ((req->evcon->max_body_size <= EV_INT64_MAX) &&
   2259  1.4  christos 						(ev_uint64_t)req->ntoread > req->evcon->max_body_size) {
   2260  1.4  christos 						evhttp_lingering_fail(evcon, req);
   2261  1.2  christos 						return;
   2262  1.2  christos 					}
   2263  1.2  christos 				}
   2264  1.2  christos 				if (!evbuffer_get_length(bufferevent_get_input(evcon->bufev)))
   2265  1.2  christos 					evhttp_send_continue(evcon, req);
   2266  1.4  christos 			break;
   2267  1.4  christos 		case OTHER:
   2268  1.4  christos 			evhttp_send_error(req, HTTP_EXPECTATIONFAILED, NULL);
   2269  1.4  christos 			return;
   2270  1.4  christos 		case NO: break;
   2271  1.1    plunky 	}
   2272  1.2  christos 
   2273  1.1    plunky 	evhttp_read_body(evcon, req);
   2274  1.2  christos 	/* note the request may have been freed in evhttp_read_body */
   2275  1.1    plunky }
   2276  1.1    plunky 
   2277  1.1    plunky static void
   2278  1.1    plunky evhttp_read_firstline(struct evhttp_connection *evcon,
   2279  1.1    plunky 		      struct evhttp_request *req)
   2280  1.1    plunky {
   2281  1.1    plunky 	enum message_read_status res;
   2282  1.1    plunky 
   2283  1.4  christos 	res = evhttp_parse_firstline_(req, bufferevent_get_input(evcon->bufev));
   2284  1.2  christos 	if (res == DATA_CORRUPTED || res == DATA_TOO_LONG) {
   2285  1.1    plunky 		/* Error while reading, terminate */
   2286  1.2  christos 		event_debug(("%s: bad header lines on "EV_SOCK_FMT"\n",
   2287  1.2  christos 			__func__, EV_SOCK_ARG(evcon->fd)));
   2288  1.4  christos 		evhttp_connection_fail_(evcon, EVREQ_HTTP_INVALID_HEADER);
   2289  1.1    plunky 		return;
   2290  1.1    plunky 	} else if (res == MORE_DATA_EXPECTED) {
   2291  1.1    plunky 		/* Need more header lines */
   2292  1.1    plunky 		return;
   2293  1.1    plunky 	}
   2294  1.1    plunky 
   2295  1.1    plunky 	evcon->state = EVCON_READING_HEADERS;
   2296  1.1    plunky 	evhttp_read_header(evcon, req);
   2297  1.1    plunky }
   2298  1.1    plunky 
   2299  1.1    plunky static void
   2300  1.2  christos evhttp_read_header(struct evhttp_connection *evcon,
   2301  1.2  christos 		   struct evhttp_request *req)
   2302  1.1    plunky {
   2303  1.1    plunky 	enum message_read_status res;
   2304  1.2  christos 	evutil_socket_t fd = evcon->fd;
   2305  1.1    plunky 
   2306  1.4  christos 	res = evhttp_parse_headers_(req, bufferevent_get_input(evcon->bufev));
   2307  1.2  christos 	if (res == DATA_CORRUPTED || res == DATA_TOO_LONG) {
   2308  1.1    plunky 		/* Error while reading, terminate */
   2309  1.2  christos 		event_debug(("%s: bad header lines on "EV_SOCK_FMT"\n",
   2310  1.2  christos 			__func__, EV_SOCK_ARG(fd)));
   2311  1.4  christos 		evhttp_connection_fail_(evcon, EVREQ_HTTP_INVALID_HEADER);
   2312  1.1    plunky 		return;
   2313  1.1    plunky 	} else if (res == MORE_DATA_EXPECTED) {
   2314  1.1    plunky 		/* Need more header lines */
   2315  1.1    plunky 		return;
   2316  1.1    plunky 	}
   2317  1.1    plunky 
   2318  1.4  christos 	/* Callback can shut down connection with negative return value */
   2319  1.4  christos 	if (req->header_cb != NULL) {
   2320  1.4  christos 		if ((*req->header_cb)(req, req->cb_arg) < 0) {
   2321  1.4  christos 			evhttp_connection_fail_(evcon, EVREQ_HTTP_EOF);
   2322  1.4  christos 			return;
   2323  1.4  christos 		}
   2324  1.4  christos 	}
   2325  1.2  christos 
   2326  1.1    plunky 	/* Done reading headers, do the real work */
   2327  1.1    plunky 	switch (req->kind) {
   2328  1.1    plunky 	case EVHTTP_REQUEST:
   2329  1.2  christos 		event_debug(("%s: checking for post data on "EV_SOCK_FMT"\n",
   2330  1.2  christos 			__func__, EV_SOCK_ARG(fd)));
   2331  1.1    plunky 		evhttp_get_body(evcon, req);
   2332  1.2  christos 		/* note the request may have been freed in evhttp_get_body */
   2333  1.1    plunky 		break;
   2334  1.1    plunky 
   2335  1.1    plunky 	case EVHTTP_RESPONSE:
   2336  1.2  christos 		/* Start over if we got a 100 Continue response. */
   2337  1.2  christos 		if (req->response_code == 100) {
   2338  1.4  christos 			struct evbuffer *output = bufferevent_get_output(evcon->bufev);
   2339  1.4  christos 			evbuffer_add_buffer(output, req->output_buffer);
   2340  1.4  christos 			evhttp_start_write_(evcon);
   2341  1.2  christos 			return;
   2342  1.2  christos 		}
   2343  1.2  christos 		if (!evhttp_response_needs_body(req)) {
   2344  1.1    plunky 			event_debug(("%s: skipping body for code %d\n",
   2345  1.1    plunky 					__func__, req->response_code));
   2346  1.1    plunky 			evhttp_connection_done(evcon);
   2347  1.1    plunky 		} else {
   2348  1.2  christos 			event_debug(("%s: start of read body for %s on "
   2349  1.2  christos 				EV_SOCK_FMT"\n",
   2350  1.2  christos 				__func__, req->remote_host, EV_SOCK_ARG(fd)));
   2351  1.1    plunky 			evhttp_get_body(evcon, req);
   2352  1.2  christos 			/* note the request may have been freed in
   2353  1.2  christos 			 * evhttp_get_body */
   2354  1.1    plunky 		}
   2355  1.1    plunky 		break;
   2356  1.1    plunky 
   2357  1.1    plunky 	default:
   2358  1.2  christos 		event_warnx("%s: bad header on "EV_SOCK_FMT, __func__,
   2359  1.2  christos 		    EV_SOCK_ARG(fd));
   2360  1.4  christos 		evhttp_connection_fail_(evcon, EVREQ_HTTP_INVALID_HEADER);
   2361  1.1    plunky 		break;
   2362  1.1    plunky 	}
   2363  1.2  christos 	/* request may have been freed above */
   2364  1.1    plunky }
   2365  1.1    plunky 
   2366  1.1    plunky /*
   2367  1.1    plunky  * Creates a TCP connection to the specified port and executes a callback
   2368  1.2  christos  * when finished.  Failure or success is indicate by the passed connection
   2369  1.1    plunky  * object.
   2370  1.1    plunky  *
   2371  1.1    plunky  * Although this interface accepts a hostname, it is intended to take
   2372  1.1    plunky  * only numeric hostnames so that non-blocking DNS resolution can
   2373  1.1    plunky  * happen elsewhere.
   2374  1.1    plunky  */
   2375  1.1    plunky 
   2376  1.1    plunky struct evhttp_connection *
   2377  1.4  christos evhttp_connection_new(const char *address, ev_uint16_t port)
   2378  1.1    plunky {
   2379  1.2  christos 	return (evhttp_connection_base_new(NULL, NULL, address, port));
   2380  1.2  christos }
   2381  1.2  christos 
   2382  1.2  christos struct evhttp_connection *
   2383  1.4  christos evhttp_connection_base_bufferevent_new(struct event_base *base, struct evdns_base *dnsbase, struct bufferevent* bev,
   2384  1.4  christos     const char *address, ev_uint16_t port)
   2385  1.2  christos {
   2386  1.1    plunky 	struct evhttp_connection *evcon = NULL;
   2387  1.2  christos 
   2388  1.1    plunky 	event_debug(("Attempting connection to %s:%d\n", address, port));
   2389  1.1    plunky 
   2390  1.2  christos 	if ((evcon = mm_calloc(1, sizeof(struct evhttp_connection))) == NULL) {
   2391  1.1    plunky 		event_warn("%s: calloc failed", __func__);
   2392  1.1    plunky 		goto error;
   2393  1.1    plunky 	}
   2394  1.1    plunky 
   2395  1.1    plunky 	evcon->fd = -1;
   2396  1.1    plunky 	evcon->port = port;
   2397  1.1    plunky 
   2398  1.2  christos 	evcon->max_headers_size = EV_SIZE_MAX;
   2399  1.2  christos 	evcon->max_body_size = EV_SIZE_MAX;
   2400  1.2  christos 
   2401  1.4  christos 	evutil_timerclear(&evcon->timeout);
   2402  1.1    plunky 	evcon->retry_cnt = evcon->retry_max = 0;
   2403  1.1    plunky 
   2404  1.2  christos 	if ((evcon->address = mm_strdup(address)) == NULL) {
   2405  1.1    plunky 		event_warn("%s: strdup failed", __func__);
   2406  1.1    plunky 		goto error;
   2407  1.1    plunky 	}
   2408  1.1    plunky 
   2409  1.4  christos 	if (bev == NULL) {
   2410  1.4  christos 		if (!(bev = bufferevent_socket_new(base, -1, 0))) {
   2411  1.4  christos 			event_warn("%s: bufferevent_socket_new failed", __func__);
   2412  1.4  christos 			goto error;
   2413  1.4  christos 		}
   2414  1.1    plunky 	}
   2415  1.1    plunky 
   2416  1.4  christos 	bufferevent_setcb(bev, evhttp_read_cb, evhttp_write_cb, evhttp_error_cb, evcon);
   2417  1.4  christos 	evcon->bufev = bev;
   2418  1.4  christos 
   2419  1.1    plunky 	evcon->state = EVCON_DISCONNECTED;
   2420  1.1    plunky 	TAILQ_INIT(&evcon->requests);
   2421  1.1    plunky 
   2422  1.4  christos 	evcon->initial_retry_timeout.tv_sec = 2;
   2423  1.4  christos 	evcon->initial_retry_timeout.tv_usec = 0;
   2424  1.4  christos 
   2425  1.2  christos 	if (base != NULL) {
   2426  1.2  christos 		evcon->base = base;
   2427  1.4  christos 		if (bufferevent_get_base(bev) != base)
   2428  1.4  christos 			bufferevent_base_set(base, evcon->bufev);
   2429  1.2  christos 	}
   2430  1.2  christos 
   2431  1.4  christos 	event_deferred_cb_init_(
   2432  1.4  christos 	    &evcon->read_more_deferred_cb,
   2433  1.4  christos 	    bufferevent_get_priority(bev),
   2434  1.2  christos 	    evhttp_deferred_read_cb, evcon);
   2435  1.2  christos 
   2436  1.2  christos 	evcon->dns_base = dnsbase;
   2437  1.4  christos 	evcon->ai_family = AF_UNSPEC;
   2438  1.2  christos 
   2439  1.1    plunky 	return (evcon);
   2440  1.2  christos 
   2441  1.1    plunky  error:
   2442  1.1    plunky 	if (evcon != NULL)
   2443  1.1    plunky 		evhttp_connection_free(evcon);
   2444  1.1    plunky 	return (NULL);
   2445  1.1    plunky }
   2446  1.1    plunky 
   2447  1.4  christos struct bufferevent* evhttp_connection_get_bufferevent(struct evhttp_connection *evcon)
   2448  1.2  christos {
   2449  1.2  christos 	return evcon->bufev;
   2450  1.2  christos }
   2451  1.2  christos 
   2452  1.4  christos struct evhttp *
   2453  1.4  christos evhttp_connection_get_server(struct evhttp_connection *evcon)
   2454  1.4  christos {
   2455  1.4  christos 	return evcon->http_server;
   2456  1.4  christos }
   2457  1.4  christos 
   2458  1.4  christos struct evhttp_connection *
   2459  1.4  christos evhttp_connection_base_new(struct event_base *base, struct evdns_base *dnsbase,
   2460  1.4  christos     const char *address, ev_uint16_t port)
   2461  1.4  christos {
   2462  1.4  christos 	return evhttp_connection_base_bufferevent_new(base, dnsbase, NULL, address, port);
   2463  1.4  christos }
   2464  1.4  christos 
   2465  1.4  christos void evhttp_connection_set_family(struct evhttp_connection *evcon,
   2466  1.4  christos 	int family)
   2467  1.4  christos {
   2468  1.4  christos 	evcon->ai_family = family;
   2469  1.4  christos }
   2470  1.4  christos 
   2471  1.4  christos int evhttp_connection_set_flags(struct evhttp_connection *evcon,
   2472  1.4  christos 	int flags)
   2473  1.4  christos {
   2474  1.4  christos 	int avail_flags = 0;
   2475  1.4  christos 	avail_flags |= EVHTTP_CON_REUSE_CONNECTED_ADDR;
   2476  1.4  christos 	avail_flags |= EVHTTP_CON_READ_ON_WRITE_ERROR;
   2477  1.4  christos 
   2478  1.4  christos 	if (flags & ~avail_flags || flags > EVHTTP_CON_PUBLIC_FLAGS_END)
   2479  1.4  christos 		return 1;
   2480  1.4  christos 	evcon->flags &= ~avail_flags;
   2481  1.4  christos 
   2482  1.4  christos 	evcon->flags |= flags;
   2483  1.4  christos 
   2484  1.4  christos 	return 0;
   2485  1.4  christos }
   2486  1.4  christos 
   2487  1.2  christos void
   2488  1.2  christos evhttp_connection_set_base(struct evhttp_connection *evcon,
   2489  1.1    plunky     struct event_base *base)
   2490  1.1    plunky {
   2491  1.2  christos 	EVUTIL_ASSERT(evcon->base == NULL);
   2492  1.2  christos 	EVUTIL_ASSERT(evcon->state == EVCON_DISCONNECTED);
   2493  1.1    plunky 	evcon->base = base;
   2494  1.2  christos 	bufferevent_base_set(base, evcon->bufev);
   2495  1.1    plunky }
   2496  1.1    plunky 
   2497  1.1    plunky void
   2498  1.1    plunky evhttp_connection_set_timeout(struct evhttp_connection *evcon,
   2499  1.1    plunky     int timeout_in_secs)
   2500  1.1    plunky {
   2501  1.4  christos 	if (timeout_in_secs == -1)
   2502  1.4  christos 		evhttp_connection_set_timeout_tv(evcon, NULL);
   2503  1.4  christos 	else {
   2504  1.4  christos 		struct timeval tv;
   2505  1.4  christos 		tv.tv_sec = timeout_in_secs;
   2506  1.4  christos 		tv.tv_usec = 0;
   2507  1.4  christos 		evhttp_connection_set_timeout_tv(evcon, &tv);
   2508  1.4  christos 	}
   2509  1.4  christos }
   2510  1.2  christos 
   2511  1.4  christos void
   2512  1.4  christos evhttp_connection_set_timeout_tv(struct evhttp_connection *evcon,
   2513  1.4  christos     const struct timeval* tv)
   2514  1.4  christos {
   2515  1.4  christos 	if (tv) {
   2516  1.4  christos 		evcon->timeout = *tv;
   2517  1.4  christos 		bufferevent_set_timeouts(evcon->bufev, &evcon->timeout, &evcon->timeout);
   2518  1.4  christos 	} else {
   2519  1.4  christos 		const struct timeval read_tv = { HTTP_READ_TIMEOUT, 0 };
   2520  1.4  christos 		const struct timeval write_tv = { HTTP_WRITE_TIMEOUT, 0 };
   2521  1.4  christos 		evutil_timerclear(&evcon->timeout);
   2522  1.4  christos 		bufferevent_set_timeouts(evcon->bufev, &read_tv, &write_tv);
   2523  1.4  christos 	}
   2524  1.4  christos }
   2525  1.4  christos 
   2526  1.4  christos void
   2527  1.4  christos evhttp_connection_set_initial_retry_tv(struct evhttp_connection *evcon,
   2528  1.4  christos     const struct timeval *tv)
   2529  1.4  christos {
   2530  1.4  christos 	if (tv) {
   2531  1.4  christos 		evcon->initial_retry_timeout = *tv;
   2532  1.4  christos 	} else {
   2533  1.4  christos 		evutil_timerclear(&evcon->initial_retry_timeout);
   2534  1.4  christos 		evcon->initial_retry_timeout.tv_sec = 2;
   2535  1.4  christos 	}
   2536  1.1    plunky }
   2537  1.1    plunky 
   2538  1.1    plunky void
   2539  1.1    plunky evhttp_connection_set_retries(struct evhttp_connection *evcon,
   2540  1.1    plunky     int retry_max)
   2541  1.1    plunky {
   2542  1.1    plunky 	evcon->retry_max = retry_max;
   2543  1.1    plunky }
   2544  1.1    plunky 
   2545  1.1    plunky void
   2546  1.1    plunky evhttp_connection_set_closecb(struct evhttp_connection *evcon,
   2547  1.1    plunky     void (*cb)(struct evhttp_connection *, void *), void *cbarg)
   2548  1.1    plunky {
   2549  1.1    plunky 	evcon->closecb = cb;
   2550  1.1    plunky 	evcon->closecb_arg = cbarg;
   2551  1.1    plunky }
   2552  1.1    plunky 
   2553  1.1    plunky void
   2554  1.1    plunky evhttp_connection_get_peer(struct evhttp_connection *evcon,
   2555  1.2  christos     char **address, ev_uint16_t *port)
   2556  1.1    plunky {
   2557  1.1    plunky 	*address = evcon->address;
   2558  1.1    plunky 	*port = evcon->port;
   2559  1.1    plunky }
   2560  1.1    plunky 
   2561  1.4  christos const struct sockaddr*
   2562  1.4  christos evhttp_connection_get_addr(struct evhttp_connection *evcon)
   2563  1.4  christos {
   2564  1.4  christos 	return bufferevent_socket_get_conn_address_(evcon->bufev);
   2565  1.4  christos }
   2566  1.4  christos 
   2567  1.1    plunky int
   2568  1.4  christos evhttp_connection_connect_(struct evhttp_connection *evcon)
   2569  1.1    plunky {
   2570  1.3       spz 	int old_state = evcon->state;
   2571  1.4  christos 	const char *address = evcon->address;
   2572  1.4  christos 	const struct sockaddr *sa = evhttp_connection_get_addr(evcon);
   2573  1.4  christos 	int ret;
   2574  1.3       spz 
   2575  1.1    plunky 	if (evcon->state == EVCON_CONNECTING)
   2576  1.1    plunky 		return (0);
   2577  1.2  christos 
   2578  1.4  christos 	evhttp_connection_reset_(evcon);
   2579  1.1    plunky 
   2580  1.2  christos 	EVUTIL_ASSERT(!(evcon->flags & EVHTTP_CON_INCOMING));
   2581  1.1    plunky 	evcon->flags |= EVHTTP_CON_OUTGOING;
   2582  1.2  christos 
   2583  1.4  christos 	if (evcon->bind_address || evcon->bind_port) {
   2584  1.4  christos 		evcon->fd = bind_socket(
   2585  1.4  christos 			evcon->bind_address, evcon->bind_port, 0 /*reuse*/);
   2586  1.4  christos 		if (evcon->fd == -1) {
   2587  1.4  christos 			event_debug(("%s: failed to bind to \"%s\"",
   2588  1.4  christos 				__func__, evcon->bind_address));
   2589  1.4  christos 			return (-1);
   2590  1.4  christos 		}
   2591  1.4  christos 
   2592  1.5  christos 		if (bufferevent_setfd(evcon->bufev, evcon->fd))
   2593  1.5  christos 			return (-1);
   2594  1.4  christos 	} else {
   2595  1.5  christos 		if (bufferevent_setfd(evcon->bufev, -1))
   2596  1.5  christos 			return (-1);
   2597  1.1    plunky 	}
   2598  1.1    plunky 
   2599  1.2  christos 	/* Set up a callback for successful connection setup */
   2600  1.2  christos 	bufferevent_setcb(evcon->bufev,
   2601  1.2  christos 	    NULL /* evhttp_read_cb */,
   2602  1.2  christos 	    NULL /* evhttp_write_cb */,
   2603  1.2  christos 	    evhttp_connection_cb,
   2604  1.2  christos 	    evcon);
   2605  1.4  christos 	if (!evutil_timerisset(&evcon->timeout)) {
   2606  1.4  christos 		const struct timeval conn_tv = { HTTP_CONNECT_TIMEOUT, 0 };
   2607  1.4  christos 		bufferevent_set_timeouts(evcon->bufev, &conn_tv, &conn_tv);
   2608  1.4  christos 	} else {
   2609  1.4  christos 		bufferevent_set_timeouts(evcon->bufev, &evcon->timeout, &evcon->timeout);
   2610  1.4  christos 	}
   2611  1.2  christos 	/* make sure that we get a write callback */
   2612  1.5  christos 	if (bufferevent_enable(evcon->bufev, EV_WRITE))
   2613  1.5  christos 		return (-1);
   2614  1.2  christos 
   2615  1.3       spz 	evcon->state = EVCON_CONNECTING;
   2616  1.3       spz 
   2617  1.4  christos 	if (evcon->flags & EVHTTP_CON_REUSE_CONNECTED_ADDR &&
   2618  1.4  christos 		sa &&
   2619  1.4  christos 		(sa->sa_family == AF_INET || sa->sa_family == AF_INET6)) {
   2620  1.4  christos 		int socklen = sizeof(struct sockaddr_in);
   2621  1.4  christos 		if (sa->sa_family == AF_INET6) {
   2622  1.4  christos 			socklen = sizeof(struct sockaddr_in6);
   2623  1.4  christos 		}
   2624  1.4  christos 		ret = bufferevent_socket_connect(evcon->bufev, sa, socklen);
   2625  1.4  christos 	} else {
   2626  1.4  christos 		ret = bufferevent_socket_connect_hostname(evcon->bufev,
   2627  1.4  christos 				evcon->dns_base, evcon->ai_family, address, evcon->port);
   2628  1.4  christos 	}
   2629  1.4  christos 
   2630  1.4  christos 	if (ret < 0) {
   2631  1.3       spz 		evcon->state = old_state;
   2632  1.2  christos 		event_sock_warn(evcon->fd, "%s: connection to \"%s\" failed",
   2633  1.2  christos 		    __func__, evcon->address);
   2634  1.2  christos 		/* some operating systems return ECONNREFUSED immediately
   2635  1.2  christos 		 * when connecting to a local address.  the cleanup is going
   2636  1.2  christos 		 * to reschedule this function call.
   2637  1.2  christos 		 */
   2638  1.2  christos 		evhttp_connection_cb_cleanup(evcon);
   2639  1.2  christos 		return (0);
   2640  1.1    plunky 	}
   2641  1.1    plunky 
   2642  1.1    plunky 	return (0);
   2643  1.1    plunky }
   2644  1.1    plunky 
   2645  1.1    plunky /*
   2646  1.1    plunky  * Starts an HTTP request on the provided evhttp_connection object.
   2647  1.1    plunky  * If the connection object is not connected to the web server already,
   2648  1.1    plunky  * this will start the connection.
   2649  1.1    plunky  */
   2650  1.1    plunky 
   2651  1.1    plunky int
   2652  1.1    plunky evhttp_make_request(struct evhttp_connection *evcon,
   2653  1.1    plunky     struct evhttp_request *req,
   2654  1.1    plunky     enum evhttp_cmd_type type, const char *uri)
   2655  1.1    plunky {
   2656  1.1    plunky 	/* We are making a request */
   2657  1.1    plunky 	req->kind = EVHTTP_REQUEST;
   2658  1.1    plunky 	req->type = type;
   2659  1.1    plunky 	if (req->uri != NULL)
   2660  1.2  christos 		mm_free(req->uri);
   2661  1.2  christos 	if ((req->uri = mm_strdup(uri)) == NULL) {
   2662  1.2  christos 		event_warn("%s: strdup", __func__);
   2663  1.4  christos 		evhttp_request_free_auto(req);
   2664  1.2  christos 		return (-1);
   2665  1.2  christos 	}
   2666  1.1    plunky 
   2667  1.1    plunky 	/* Set the protocol version if it is not supplied */
   2668  1.1    plunky 	if (!req->major && !req->minor) {
   2669  1.1    plunky 		req->major = 1;
   2670  1.1    plunky 		req->minor = 1;
   2671  1.1    plunky 	}
   2672  1.2  christos 
   2673  1.2  christos 	EVUTIL_ASSERT(req->evcon == NULL);
   2674  1.1    plunky 	req->evcon = evcon;
   2675  1.2  christos 	EVUTIL_ASSERT(!(req->flags & EVHTTP_REQ_OWN_CONNECTION));
   2676  1.2  christos 
   2677  1.4  christos 	TAILQ_INSERT_TAIL(&evcon->requests, req, next);
   2678  1.1    plunky 
   2679  1.5  christos 	/* We do not want to conflict with retry_ev */
   2680  1.5  christos 	if (evcon->retry_cnt)
   2681  1.5  christos 		return (0);
   2682  1.5  christos 
   2683  1.1    plunky 	/* If the connection object is not connected; make it so */
   2684  1.2  christos 	if (!evhttp_connected(evcon)) {
   2685  1.4  christos 		int res = evhttp_connection_connect_(evcon);
   2686  1.4  christos 		/* evhttp_connection_fail_(), which is called through
   2687  1.4  christos 		 * evhttp_connection_connect_(), assumes that req lies in
   2688  1.4  christos 		 * evcon->requests.  Thus, enqueue the request in advance and
   2689  1.4  christos 		 * remove it in the error case. */
   2690  1.4  christos 		if (res != 0)
   2691  1.4  christos 			TAILQ_REMOVE(&evcon->requests, req, next);
   2692  1.2  christos 
   2693  1.5  christos 		return (res);
   2694  1.2  christos 	}
   2695  1.1    plunky 
   2696  1.1    plunky 	/*
   2697  1.1    plunky 	 * If it's connected already and we are the first in the queue,
   2698  1.1    plunky 	 * then we can dispatch this request immediately.  Otherwise, it
   2699  1.1    plunky 	 * will be dispatched once the pending requests are completed.
   2700  1.1    plunky 	 */
   2701  1.1    plunky 	if (TAILQ_FIRST(&evcon->requests) == req)
   2702  1.1    plunky 		evhttp_request_dispatch(evcon);
   2703  1.1    plunky 
   2704  1.1    plunky 	return (0);
   2705  1.1    plunky }
   2706  1.1    plunky 
   2707  1.2  christos void
   2708  1.2  christos evhttp_cancel_request(struct evhttp_request *req)
   2709  1.2  christos {
   2710  1.2  christos 	struct evhttp_connection *evcon = req->evcon;
   2711  1.2  christos 	if (evcon != NULL) {
   2712  1.2  christos 		/* We need to remove it from the connection */
   2713  1.2  christos 		if (TAILQ_FIRST(&evcon->requests) == req) {
   2714  1.2  christos 			/* it's currently being worked on, so reset
   2715  1.2  christos 			 * the connection.
   2716  1.2  christos 			 */
   2717  1.4  christos 			evhttp_connection_fail_(evcon,
   2718  1.4  christos 			    EVREQ_HTTP_REQUEST_CANCEL);
   2719  1.2  christos 
   2720  1.2  christos 			/* connection fail freed the request */
   2721  1.2  christos 			return;
   2722  1.2  christos 		} else {
   2723  1.2  christos 			/* otherwise, we can just remove it from the
   2724  1.2  christos 			 * queue
   2725  1.2  christos 			 */
   2726  1.2  christos 			TAILQ_REMOVE(&evcon->requests, req, next);
   2727  1.2  christos 		}
   2728  1.2  christos 	}
   2729  1.2  christos 
   2730  1.4  christos 	evhttp_request_free_auto(req);
   2731  1.2  christos }
   2732  1.2  christos 
   2733  1.1    plunky /*
   2734  1.1    plunky  * Reads data from file descriptor into request structure
   2735  1.1    plunky  * Request structure needs to be set up correctly.
   2736  1.1    plunky  */
   2737  1.1    plunky 
   2738  1.1    plunky void
   2739  1.4  christos evhttp_start_read_(struct evhttp_connection *evcon)
   2740  1.1    plunky {
   2741  1.2  christos 	bufferevent_disable(evcon->bufev, EV_WRITE);
   2742  1.2  christos 	bufferevent_enable(evcon->bufev, EV_READ);
   2743  1.4  christos 
   2744  1.1    plunky 	evcon->state = EVCON_READING_FIRSTLINE;
   2745  1.2  christos 	/* Reset the bufferevent callbacks */
   2746  1.2  christos 	bufferevent_setcb(evcon->bufev,
   2747  1.2  christos 	    evhttp_read_cb,
   2748  1.2  christos 	    evhttp_write_cb,
   2749  1.2  christos 	    evhttp_error_cb,
   2750  1.2  christos 	    evcon);
   2751  1.2  christos 
   2752  1.2  christos 	/* If there's still data pending, process it next time through the
   2753  1.2  christos 	 * loop.  Don't do it now; that could get recusive. */
   2754  1.2  christos 	if (evbuffer_get_length(bufferevent_get_input(evcon->bufev))) {
   2755  1.4  christos 		event_deferred_cb_schedule_(get_deferred_queue(evcon),
   2756  1.2  christos 		    &evcon->read_more_deferred_cb);
   2757  1.2  christos 	}
   2758  1.1    plunky }
   2759  1.1    plunky 
   2760  1.4  christos void
   2761  1.4  christos evhttp_start_write_(struct evhttp_connection *evcon)
   2762  1.4  christos {
   2763  1.4  christos 	bufferevent_disable(evcon->bufev, EV_WRITE);
   2764  1.4  christos 	bufferevent_enable(evcon->bufev, EV_READ);
   2765  1.4  christos 
   2766  1.4  christos 	evcon->state = EVCON_WRITING;
   2767  1.4  christos 	evhttp_write_buffer(evcon, evhttp_write_connectioncb, NULL);
   2768  1.4  christos }
   2769  1.4  christos 
   2770  1.1    plunky static void
   2771  1.1    plunky evhttp_send_done(struct evhttp_connection *evcon, void *arg)
   2772  1.1    plunky {
   2773  1.1    plunky 	int need_close;
   2774  1.1    plunky 	struct evhttp_request *req = TAILQ_FIRST(&evcon->requests);
   2775  1.1    plunky 	TAILQ_REMOVE(&evcon->requests, req, next);
   2776  1.1    plunky 
   2777  1.4  christos 	if (req->on_complete_cb != NULL) {
   2778  1.4  christos 		req->on_complete_cb(req, req->on_complete_cb_arg);
   2779  1.4  christos 	}
   2780  1.4  christos 
   2781  1.1    plunky 	need_close =
   2782  1.2  christos 	    (REQ_VERSION_BEFORE(req, 1, 1) &&
   2783  1.4  christos 	    !evhttp_is_connection_keepalive(req->input_headers)) ||
   2784  1.4  christos 	    evhttp_is_request_connection_close(req);
   2785  1.1    plunky 
   2786  1.2  christos 	EVUTIL_ASSERT(req->flags & EVHTTP_REQ_OWN_CONNECTION);
   2787  1.1    plunky 	evhttp_request_free(req);
   2788  1.1    plunky 
   2789  1.1    plunky 	if (need_close) {
   2790  1.1    plunky 		evhttp_connection_free(evcon);
   2791  1.1    plunky 		return;
   2792  1.2  christos 	}
   2793  1.1    plunky 
   2794  1.1    plunky 	/* we have a persistent connection; try to accept another request. */
   2795  1.2  christos 	if (evhttp_associate_new_request_with_connection(evcon) == -1) {
   2796  1.1    plunky 		evhttp_connection_free(evcon);
   2797  1.2  christos 	}
   2798  1.1    plunky }
   2799  1.1    plunky 
   2800  1.1    plunky /*
   2801  1.1    plunky  * Returns an error page.
   2802  1.1    plunky  */
   2803  1.1    plunky 
   2804  1.1    plunky void
   2805  1.1    plunky evhttp_send_error(struct evhttp_request *req, int error, const char *reason)
   2806  1.1    plunky {
   2807  1.2  christos 
   2808  1.1    plunky #define ERR_FORMAT "<HTML><HEAD>\n" \
   2809  1.1    plunky 	    "<TITLE>%d %s</TITLE>\n" \
   2810  1.1    plunky 	    "</HEAD><BODY>\n" \
   2811  1.2  christos 	    "<H1>%s</H1>\n" \
   2812  1.1    plunky 	    "</BODY></HTML>\n"
   2813  1.1    plunky 
   2814  1.1    plunky 	struct evbuffer *buf = evbuffer_new();
   2815  1.2  christos 	if (buf == NULL) {
   2816  1.2  christos 		/* if we cannot allocate memory; we just drop the connection */
   2817  1.2  christos 		evhttp_connection_free(req->evcon);
   2818  1.2  christos 		return;
   2819  1.2  christos 	}
   2820  1.2  christos 	if (reason == NULL) {
   2821  1.2  christos 		reason = evhttp_response_phrase_internal(error);
   2822  1.2  christos 	}
   2823  1.1    plunky 
   2824  1.4  christos 	evhttp_response_code_(req, error, reason);
   2825  1.1    plunky 
   2826  1.2  christos 	evbuffer_add_printf(buf, ERR_FORMAT, error, reason, reason);
   2827  1.1    plunky 
   2828  1.4  christos 	evhttp_send_page_(req, buf);
   2829  1.1    plunky 
   2830  1.1    plunky 	evbuffer_free(buf);
   2831  1.1    plunky #undef ERR_FORMAT
   2832  1.1    plunky }
   2833  1.1    plunky 
   2834  1.1    plunky /* Requires that headers and response code are already set up */
   2835  1.1    plunky 
   2836  1.1    plunky static inline void
   2837  1.1    plunky evhttp_send(struct evhttp_request *req, struct evbuffer *databuf)
   2838  1.1    plunky {
   2839  1.1    plunky 	struct evhttp_connection *evcon = req->evcon;
   2840  1.1    plunky 
   2841  1.2  christos 	if (evcon == NULL) {
   2842  1.2  christos 		evhttp_request_free(req);
   2843  1.2  christos 		return;
   2844  1.2  christos 	}
   2845  1.2  christos 
   2846  1.2  christos 	EVUTIL_ASSERT(TAILQ_FIRST(&evcon->requests) == req);
   2847  1.2  christos 
   2848  1.2  christos 	/* we expect no more calls form the user on this request */
   2849  1.2  christos 	req->userdone = 1;
   2850  1.1    plunky 
   2851  1.1    plunky 	/* xxx: not sure if we really should expose the data buffer this way */
   2852  1.1    plunky 	if (databuf != NULL)
   2853  1.1    plunky 		evbuffer_add_buffer(req->output_buffer, databuf);
   2854  1.2  christos 
   2855  1.1    plunky 	/* Adds headers to the response */
   2856  1.1    plunky 	evhttp_make_header(evcon, req);
   2857  1.1    plunky 
   2858  1.1    plunky 	evhttp_write_buffer(evcon, evhttp_send_done, NULL);
   2859  1.1    plunky }
   2860  1.1    plunky 
   2861  1.1    plunky void
   2862  1.1    plunky evhttp_send_reply(struct evhttp_request *req, int code, const char *reason,
   2863  1.1    plunky     struct evbuffer *databuf)
   2864  1.1    plunky {
   2865  1.4  christos 	evhttp_response_code_(req, code, reason);
   2866  1.2  christos 
   2867  1.1    plunky 	evhttp_send(req, databuf);
   2868  1.1    plunky }
   2869  1.1    plunky 
   2870  1.1    plunky void
   2871  1.1    plunky evhttp_send_reply_start(struct evhttp_request *req, int code,
   2872  1.1    plunky     const char *reason)
   2873  1.1    plunky {
   2874  1.4  christos 	evhttp_response_code_(req, code, reason);
   2875  1.5  christos 
   2876  1.5  christos 	if (req->evcon == NULL)
   2877  1.5  christos 		return;
   2878  1.5  christos 
   2879  1.2  christos 	if (evhttp_find_header(req->output_headers, "Content-Length") == NULL &&
   2880  1.2  christos 	    REQ_VERSION_ATLEAST(req, 1, 1) &&
   2881  1.2  christos 	    evhttp_response_needs_body(req)) {
   2882  1.2  christos 		/*
   2883  1.2  christos 		 * prefer HTTP/1.1 chunked encoding to closing the connection;
   2884  1.2  christos 		 * note RFC 2616 section 4.4 forbids it with Content-Length:
   2885  1.2  christos 		 * and it's not necessary then anyway.
   2886  1.2  christos 		 */
   2887  1.1    plunky 		evhttp_add_header(req->output_headers, "Transfer-Encoding",
   2888  1.1    plunky 		    "chunked");
   2889  1.1    plunky 		req->chunked = 1;
   2890  1.2  christos 	} else {
   2891  1.2  christos 		req->chunked = 0;
   2892  1.1    plunky 	}
   2893  1.1    plunky 	evhttp_make_header(req->evcon, req);
   2894  1.1    plunky 	evhttp_write_buffer(req->evcon, NULL, NULL);
   2895  1.1    plunky }
   2896  1.1    plunky 
   2897  1.1    plunky void
   2898  1.4  christos evhttp_send_reply_chunk_with_cb(struct evhttp_request *req, struct evbuffer *databuf,
   2899  1.4  christos     void (*cb)(struct evhttp_connection *, void *), void *arg)
   2900  1.1    plunky {
   2901  1.2  christos 	struct evhttp_connection *evcon = req->evcon;
   2902  1.2  christos 	struct evbuffer *output;
   2903  1.2  christos 
   2904  1.2  christos 	if (evcon == NULL)
   2905  1.2  christos 		return;
   2906  1.2  christos 
   2907  1.2  christos 	output = bufferevent_get_output(evcon->bufev);
   2908  1.2  christos 
   2909  1.2  christos 	if (evbuffer_get_length(databuf) == 0)
   2910  1.2  christos 		return;
   2911  1.2  christos 	if (!evhttp_response_needs_body(req))
   2912  1.2  christos 		return;
   2913  1.1    plunky 	if (req->chunked) {
   2914  1.2  christos 		evbuffer_add_printf(output, "%x\r\n",
   2915  1.2  christos 				    (unsigned)evbuffer_get_length(databuf));
   2916  1.1    plunky 	}
   2917  1.2  christos 	evbuffer_add_buffer(output, databuf);
   2918  1.1    plunky 	if (req->chunked) {
   2919  1.2  christos 		evbuffer_add(output, "\r\n", 2);
   2920  1.1    plunky 	}
   2921  1.4  christos 	evhttp_write_buffer(evcon, cb, arg);
   2922  1.1    plunky }
   2923  1.1    plunky 
   2924  1.1    plunky void
   2925  1.4  christos evhttp_send_reply_chunk(struct evhttp_request *req, struct evbuffer *databuf)
   2926  1.4  christos {
   2927  1.4  christos 	evhttp_send_reply_chunk_with_cb(req, databuf, NULL, NULL);
   2928  1.4  christos }
   2929  1.4  christos void
   2930  1.1    plunky evhttp_send_reply_end(struct evhttp_request *req)
   2931  1.1    plunky {
   2932  1.1    plunky 	struct evhttp_connection *evcon = req->evcon;
   2933  1.2  christos 	struct evbuffer *output;
   2934  1.2  christos 
   2935  1.2  christos 	if (evcon == NULL) {
   2936  1.2  christos 		evhttp_request_free(req);
   2937  1.2  christos 		return;
   2938  1.2  christos 	}
   2939  1.2  christos 
   2940  1.2  christos 	output = bufferevent_get_output(evcon->bufev);
   2941  1.2  christos 
   2942  1.2  christos 	/* we expect no more calls form the user on this request */
   2943  1.2  christos 	req->userdone = 1;
   2944  1.1    plunky 
   2945  1.1    plunky 	if (req->chunked) {
   2946  1.2  christos 		evbuffer_add(output, "0\r\n\r\n", 5);
   2947  1.1    plunky 		evhttp_write_buffer(req->evcon, evhttp_send_done, NULL);
   2948  1.1    plunky 		req->chunked = 0;
   2949  1.2  christos 	} else if (evbuffer_get_length(output) == 0) {
   2950  1.1    plunky 		/* let the connection know that we are done with the request */
   2951  1.1    plunky 		evhttp_send_done(evcon, NULL);
   2952  1.1    plunky 	} else {
   2953  1.1    plunky 		/* make the callback execute after all data has been written */
   2954  1.1    plunky 		evcon->cb = evhttp_send_done;
   2955  1.1    plunky 		evcon->cb_arg = NULL;
   2956  1.1    plunky 	}
   2957  1.1    plunky }
   2958  1.1    plunky 
   2959  1.2  christos static const char *informational_phrases[] = {
   2960  1.2  christos 	/* 100 */ "Continue",
   2961  1.2  christos 	/* 101 */ "Switching Protocols"
   2962  1.2  christos };
   2963  1.2  christos 
   2964  1.2  christos static const char *success_phrases[] = {
   2965  1.2  christos 	/* 200 */ "OK",
   2966  1.2  christos 	/* 201 */ "Created",
   2967  1.2  christos 	/* 202 */ "Accepted",
   2968  1.2  christos 	/* 203 */ "Non-Authoritative Information",
   2969  1.2  christos 	/* 204 */ "No Content",
   2970  1.2  christos 	/* 205 */ "Reset Content",
   2971  1.2  christos 	/* 206 */ "Partial Content"
   2972  1.2  christos };
   2973  1.2  christos 
   2974  1.2  christos static const char *redirection_phrases[] = {
   2975  1.2  christos 	/* 300 */ "Multiple Choices",
   2976  1.2  christos 	/* 301 */ "Moved Permanently",
   2977  1.2  christos 	/* 302 */ "Found",
   2978  1.2  christos 	/* 303 */ "See Other",
   2979  1.2  christos 	/* 304 */ "Not Modified",
   2980  1.2  christos 	/* 305 */ "Use Proxy",
   2981  1.2  christos 	/* 307 */ "Temporary Redirect"
   2982  1.2  christos };
   2983  1.2  christos 
   2984  1.2  christos static const char *client_error_phrases[] = {
   2985  1.2  christos 	/* 400 */ "Bad Request",
   2986  1.2  christos 	/* 401 */ "Unauthorized",
   2987  1.2  christos 	/* 402 */ "Payment Required",
   2988  1.2  christos 	/* 403 */ "Forbidden",
   2989  1.2  christos 	/* 404 */ "Not Found",
   2990  1.2  christos 	/* 405 */ "Method Not Allowed",
   2991  1.2  christos 	/* 406 */ "Not Acceptable",
   2992  1.2  christos 	/* 407 */ "Proxy Authentication Required",
   2993  1.2  christos 	/* 408 */ "Request Time-out",
   2994  1.2  christos 	/* 409 */ "Conflict",
   2995  1.2  christos 	/* 410 */ "Gone",
   2996  1.2  christos 	/* 411 */ "Length Required",
   2997  1.2  christos 	/* 412 */ "Precondition Failed",
   2998  1.2  christos 	/* 413 */ "Request Entity Too Large",
   2999  1.2  christos 	/* 414 */ "Request-URI Too Large",
   3000  1.2  christos 	/* 415 */ "Unsupported Media Type",
   3001  1.2  christos 	/* 416 */ "Requested range not satisfiable",
   3002  1.2  christos 	/* 417 */ "Expectation Failed"
   3003  1.2  christos };
   3004  1.2  christos 
   3005  1.2  christos static const char *server_error_phrases[] = {
   3006  1.2  christos 	/* 500 */ "Internal Server Error",
   3007  1.2  christos 	/* 501 */ "Not Implemented",
   3008  1.2  christos 	/* 502 */ "Bad Gateway",
   3009  1.2  christos 	/* 503 */ "Service Unavailable",
   3010  1.2  christos 	/* 504 */ "Gateway Time-out",
   3011  1.2  christos 	/* 505 */ "HTTP Version not supported"
   3012  1.2  christos };
   3013  1.2  christos 
   3014  1.2  christos struct response_class {
   3015  1.2  christos 	const char *name;
   3016  1.2  christos 	size_t num_responses;
   3017  1.2  christos 	const char **responses;
   3018  1.2  christos };
   3019  1.2  christos 
   3020  1.2  christos #ifndef MEMBERSOF
   3021  1.2  christos #define MEMBERSOF(x) (sizeof(x)/sizeof(x[0]))
   3022  1.2  christos #endif
   3023  1.2  christos 
   3024  1.2  christos static const struct response_class response_classes[] = {
   3025  1.2  christos 	/* 1xx */ { "Informational", MEMBERSOF(informational_phrases), informational_phrases },
   3026  1.2  christos 	/* 2xx */ { "Success", MEMBERSOF(success_phrases), success_phrases },
   3027  1.2  christos 	/* 3xx */ { "Redirection", MEMBERSOF(redirection_phrases), redirection_phrases },
   3028  1.2  christos 	/* 4xx */ { "Client Error", MEMBERSOF(client_error_phrases), client_error_phrases },
   3029  1.2  christos 	/* 5xx */ { "Server Error", MEMBERSOF(server_error_phrases), server_error_phrases }
   3030  1.2  christos };
   3031  1.2  christos 
   3032  1.2  christos static const char *
   3033  1.2  christos evhttp_response_phrase_internal(int code)
   3034  1.2  christos {
   3035  1.2  christos 	int klass = code / 100 - 1;
   3036  1.2  christos 	int subcode = code % 100;
   3037  1.2  christos 
   3038  1.2  christos 	/* Unknown class - can't do any better here */
   3039  1.2  christos 	if (klass < 0 || klass >= (int) MEMBERSOF(response_classes))
   3040  1.2  christos 		return "Unknown Status Class";
   3041  1.2  christos 
   3042  1.2  christos 	/* Unknown sub-code, return class name at least */
   3043  1.2  christos 	if (subcode >= (int) response_classes[klass].num_responses)
   3044  1.2  christos 		return response_classes[klass].name;
   3045  1.2  christos 
   3046  1.2  christos 	return response_classes[klass].responses[subcode];
   3047  1.2  christos }
   3048  1.2  christos 
   3049  1.1    plunky void
   3050  1.4  christos evhttp_response_code_(struct evhttp_request *req, int code, const char *reason)
   3051  1.1    plunky {
   3052  1.1    plunky 	req->kind = EVHTTP_RESPONSE;
   3053  1.1    plunky 	req->response_code = code;
   3054  1.1    plunky 	if (req->response_code_line != NULL)
   3055  1.2  christos 		mm_free(req->response_code_line);
   3056  1.2  christos 	if (reason == NULL)
   3057  1.2  christos 		reason = evhttp_response_phrase_internal(code);
   3058  1.2  christos 	req->response_code_line = mm_strdup(reason);
   3059  1.2  christos 	if (req->response_code_line == NULL) {
   3060  1.2  christos 		event_warn("%s: strdup", __func__);
   3061  1.2  christos 		/* XXX what else can we do? */
   3062  1.2  christos 	}
   3063  1.1    plunky }
   3064  1.1    plunky 
   3065  1.1    plunky void
   3066  1.4  christos evhttp_send_page_(struct evhttp_request *req, struct evbuffer *databuf)
   3067  1.1    plunky {
   3068  1.1    plunky 	if (!req->major || !req->minor) {
   3069  1.1    plunky 		req->major = 1;
   3070  1.1    plunky 		req->minor = 1;
   3071  1.1    plunky 	}
   3072  1.2  christos 
   3073  1.1    plunky 	if (req->kind != EVHTTP_RESPONSE)
   3074  1.4  christos 		evhttp_response_code_(req, 200, "OK");
   3075  1.1    plunky 
   3076  1.1    plunky 	evhttp_clear_headers(req->output_headers);
   3077  1.1    plunky 	evhttp_add_header(req->output_headers, "Content-Type", "text/html");
   3078  1.1    plunky 	evhttp_add_header(req->output_headers, "Connection", "close");
   3079  1.1    plunky 
   3080  1.1    plunky 	evhttp_send(req, databuf);
   3081  1.1    plunky }
   3082  1.1    plunky 
   3083  1.1    plunky static const char uri_chars[256] = {
   3084  1.2  christos 	/* 0 */
   3085  1.1    plunky 	0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0,
   3086  1.1    plunky 	0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0,
   3087  1.2  christos 	0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 1, 1, 0,
   3088  1.2  christos 	1, 1, 1, 1, 1, 1, 1, 1,   1, 1, 0, 0, 0, 0, 0, 0,
   3089  1.1    plunky 	/* 64 */
   3090  1.2  christos 	0, 1, 1, 1, 1, 1, 1, 1,   1, 1, 1, 1, 1, 1, 1, 1,
   3091  1.1    plunky 	1, 1, 1, 1, 1, 1, 1, 1,   1, 1, 1, 0, 0, 0, 0, 1,
   3092  1.1    plunky 	0, 1, 1, 1, 1, 1, 1, 1,   1, 1, 1, 1, 1, 1, 1, 1,
   3093  1.1    plunky 	1, 1, 1, 1, 1, 1, 1, 1,   1, 1, 1, 0, 0, 0, 1, 0,
   3094  1.1    plunky 	/* 128 */
   3095  1.1    plunky 	0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0,
   3096  1.1    plunky 	0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0,
   3097  1.1    plunky 	0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0,
   3098  1.1    plunky 	0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0,
   3099  1.1    plunky 	/* 192 */
   3100  1.1    plunky 	0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0,
   3101  1.1    plunky 	0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0,
   3102  1.1    plunky 	0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0,
   3103  1.1    plunky 	0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0,
   3104  1.1    plunky };
   3105  1.1    plunky 
   3106  1.2  christos #define CHAR_IS_UNRESERVED(c)			\
   3107  1.2  christos 	(uri_chars[(unsigned char)(c)])
   3108  1.2  christos 
   3109  1.1    plunky /*
   3110  1.2  christos  * Helper functions to encode/decode a string for inclusion in a URI.
   3111  1.1    plunky  * The returned string must be freed by the caller.
   3112  1.1    plunky  */
   3113  1.1    plunky char *
   3114  1.2  christos evhttp_uriencode(const char *uri, ev_ssize_t len, int space_as_plus)
   3115  1.1    plunky {
   3116  1.1    plunky 	struct evbuffer *buf = evbuffer_new();
   3117  1.2  christos 	const char *p, *end;
   3118  1.5  christos 	char *result = NULL;
   3119  1.2  christos 
   3120  1.5  christos 	if (!buf) {
   3121  1.5  christos 		goto out;
   3122  1.4  christos 	}
   3123  1.4  christos 
   3124  1.4  christos 	if (len >= 0) {
   3125  1.4  christos 		if (uri + len < uri) {
   3126  1.5  christos 			goto out;
   3127  1.4  christos 		}
   3128  1.4  christos 
   3129  1.4  christos 		end = uri + len;
   3130  1.4  christos 	} else {
   3131  1.4  christos 		size_t slen = strlen(uri);
   3132  1.4  christos 
   3133  1.4  christos 		if (slen >= EV_SSIZE_MAX) {
   3134  1.4  christos 			/* we don't want to mix signed and unsigned */
   3135  1.5  christos 			goto out;
   3136  1.4  christos 		}
   3137  1.4  christos 
   3138  1.4  christos 		if (uri + slen < uri) {
   3139  1.5  christos 			goto out;
   3140  1.4  christos 		}
   3141  1.2  christos 
   3142  1.4  christos 		end = uri + slen;
   3143  1.4  christos 	}
   3144  1.1    plunky 
   3145  1.2  christos 	for (p = uri; p < end; p++) {
   3146  1.2  christos 		if (CHAR_IS_UNRESERVED(*p)) {
   3147  1.1    plunky 			evbuffer_add(buf, p, 1);
   3148  1.2  christos 		} else if (*p == ' ' && space_as_plus) {
   3149  1.2  christos 			evbuffer_add(buf, "+", 1);
   3150  1.1    plunky 		} else {
   3151  1.2  christos 			evbuffer_add_printf(buf, "%%%02X", (unsigned char)(*p));
   3152  1.1    plunky 		}
   3153  1.1    plunky 	}
   3154  1.4  christos 
   3155  1.2  christos 	evbuffer_add(buf, "", 1); /* NUL-terminator. */
   3156  1.2  christos 	result = mm_malloc(evbuffer_get_length(buf));
   3157  1.4  christos 
   3158  1.2  christos 	if (result)
   3159  1.2  christos 		evbuffer_remove(buf, result, evbuffer_get_length(buf));
   3160  1.4  christos 
   3161  1.5  christos out:
   3162  1.5  christos 	if (buf)
   3163  1.5  christos 		evbuffer_free(buf);
   3164  1.5  christos 	return result;
   3165  1.2  christos }
   3166  1.2  christos 
   3167  1.2  christos char *
   3168  1.2  christos evhttp_encode_uri(const char *str)
   3169  1.2  christos {
   3170  1.2  christos 	return evhttp_uriencode(str, -1, 0);
   3171  1.1    plunky }
   3172  1.1    plunky 
   3173  1.1    plunky /*
   3174  1.2  christos  * @param decode_plus_ctl: if 1, we decode plus into space.  If 0, we don't.
   3175  1.2  christos  *     If -1, when true we transform plus to space only after we've seen
   3176  1.2  christos  *     a ?.  -1 is deprecated.
   3177  1.2  christos  * @return the number of bytes written to 'ret'.
   3178  1.1    plunky  */
   3179  1.4  christos int
   3180  1.1    plunky evhttp_decode_uri_internal(
   3181  1.2  christos 	const char *uri, size_t length, char *ret, int decode_plus_ctl)
   3182  1.1    plunky {
   3183  1.1    plunky 	char c;
   3184  1.2  christos 	int j;
   3185  1.2  christos 	int decode_plus = (decode_plus_ctl == 1) ? 1: 0;
   3186  1.2  christos 	unsigned i;
   3187  1.2  christos 
   3188  1.2  christos 	for (i = j = 0; i < length; i++) {
   3189  1.1    plunky 		c = uri[i];
   3190  1.1    plunky 		if (c == '?') {
   3191  1.2  christos 			if (decode_plus_ctl < 0)
   3192  1.2  christos 				decode_plus = 1;
   3193  1.2  christos 		} else if (c == '+' && decode_plus) {
   3194  1.1    plunky 			c = ' ';
   3195  1.4  christos 		} else if ((i + 2) < length && c == '%' &&
   3196  1.4  christos 			EVUTIL_ISXDIGIT_(uri[i+1]) && EVUTIL_ISXDIGIT_(uri[i+2])) {
   3197  1.2  christos 			char tmp[3];
   3198  1.2  christos 			tmp[0] = uri[i+1];
   3199  1.2  christos 			tmp[1] = uri[i+2];
   3200  1.2  christos 			tmp[2] = '\0';
   3201  1.1    plunky 			c = (char)strtol(tmp, NULL, 16);
   3202  1.1    plunky 			i += 2;
   3203  1.1    plunky 		}
   3204  1.1    plunky 		ret[j++] = c;
   3205  1.1    plunky 	}
   3206  1.1    plunky 	ret[j] = '\0';
   3207  1.1    plunky 
   3208  1.1    plunky 	return (j);
   3209  1.1    plunky }
   3210  1.1    plunky 
   3211  1.2  christos /* deprecated */
   3212  1.1    plunky char *
   3213  1.1    plunky evhttp_decode_uri(const char *uri)
   3214  1.1    plunky {
   3215  1.1    plunky 	char *ret;
   3216  1.1    plunky 
   3217  1.2  christos 	if ((ret = mm_malloc(strlen(uri) + 1)) == NULL) {
   3218  1.2  christos 		event_warn("%s: malloc(%lu)", __func__,
   3219  1.1    plunky 			  (unsigned long)(strlen(uri) + 1));
   3220  1.2  christos 		return (NULL);
   3221  1.2  christos 	}
   3222  1.1    plunky 
   3223  1.1    plunky 	evhttp_decode_uri_internal(uri, strlen(uri),
   3224  1.2  christos 	    ret, -1 /*always_decode_plus*/);
   3225  1.1    plunky 
   3226  1.1    plunky 	return (ret);
   3227  1.1    plunky }
   3228  1.1    plunky 
   3229  1.2  christos char *
   3230  1.2  christos evhttp_uridecode(const char *uri, int decode_plus, size_t *size_out)
   3231  1.2  christos {
   3232  1.2  christos 	char *ret;
   3233  1.2  christos 	int n;
   3234  1.2  christos 
   3235  1.2  christos 	if ((ret = mm_malloc(strlen(uri) + 1)) == NULL) {
   3236  1.2  christos 		event_warn("%s: malloc(%lu)", __func__,
   3237  1.2  christos 			  (unsigned long)(strlen(uri) + 1));
   3238  1.2  christos 		return (NULL);
   3239  1.2  christos 	}
   3240  1.2  christos 
   3241  1.2  christos 	n = evhttp_decode_uri_internal(uri, strlen(uri),
   3242  1.2  christos 	    ret, !!decode_plus/*always_decode_plus*/);
   3243  1.2  christos 
   3244  1.2  christos 	if (size_out) {
   3245  1.2  christos 		EVUTIL_ASSERT(n >= 0);
   3246  1.2  christos 		*size_out = (size_t)n;
   3247  1.2  christos 	}
   3248  1.2  christos 
   3249  1.2  christos 	return (ret);
   3250  1.2  christos }
   3251  1.2  christos 
   3252  1.2  christos /*
   3253  1.1    plunky  * Helper function to parse out arguments in a query.
   3254  1.1    plunky  * The arguments are separated by key and value.
   3255  1.1    plunky  */
   3256  1.1    plunky 
   3257  1.2  christos static int
   3258  1.2  christos evhttp_parse_query_impl(const char *str, struct evkeyvalq *headers,
   3259  1.2  christos     int is_whole_uri)
   3260  1.1    plunky {
   3261  1.2  christos 	char *line=NULL;
   3262  1.1    plunky 	char *argument;
   3263  1.1    plunky 	char *p;
   3264  1.2  christos 	const char *query_part;
   3265  1.2  christos 	int result = -1;
   3266  1.2  christos 	struct evhttp_uri *uri=NULL;
   3267  1.1    plunky 
   3268  1.1    plunky 	TAILQ_INIT(headers);
   3269  1.1    plunky 
   3270  1.2  christos 	if (is_whole_uri) {
   3271  1.2  christos 		uri = evhttp_uri_parse(str);
   3272  1.2  christos 		if (!uri)
   3273  1.2  christos 			goto error;
   3274  1.2  christos 		query_part = evhttp_uri_get_query(uri);
   3275  1.2  christos 	} else {
   3276  1.2  christos 		query_part = str;
   3277  1.2  christos 	}
   3278  1.2  christos 
   3279  1.1    plunky 	/* No arguments - we are done */
   3280  1.2  christos 	if (!query_part || !strlen(query_part)) {
   3281  1.2  christos 		result = 0;
   3282  1.2  christos 		goto done;
   3283  1.2  christos 	}
   3284  1.1    plunky 
   3285  1.2  christos 	if ((line = mm_strdup(query_part)) == NULL) {
   3286  1.2  christos 		event_warn("%s: strdup", __func__);
   3287  1.2  christos 		goto error;
   3288  1.2  christos 	}
   3289  1.1    plunky 
   3290  1.2  christos 	p = argument = line;
   3291  1.1    plunky 	while (p != NULL && *p != '\0') {
   3292  1.1    plunky 		char *key, *value, *decoded_value;
   3293  1.5  christos 		int err;
   3294  1.1    plunky 		argument = strsep(&p, "&");
   3295  1.1    plunky 
   3296  1.1    plunky 		value = argument;
   3297  1.1    plunky 		key = strsep(&value, "=");
   3298  1.2  christos 		if (value == NULL || *key == '\0') {
   3299  1.1    plunky 			goto error;
   3300  1.2  christos 		}
   3301  1.1    plunky 
   3302  1.2  christos 		if ((decoded_value = mm_malloc(strlen(value) + 1)) == NULL) {
   3303  1.2  christos 			event_warn("%s: mm_malloc", __func__);
   3304  1.2  christos 			goto error;
   3305  1.2  christos 		}
   3306  1.1    plunky 		evhttp_decode_uri_internal(value, strlen(value),
   3307  1.1    plunky 		    decoded_value, 1 /*always_decode_plus*/);
   3308  1.1    plunky 		event_debug(("Query Param: %s -> %s\n", key, decoded_value));
   3309  1.5  christos 		err = evhttp_add_header_internal(headers, key, decoded_value);
   3310  1.2  christos 		mm_free(decoded_value);
   3311  1.5  christos 		if (err)
   3312  1.5  christos 			goto error;
   3313  1.1    plunky 	}
   3314  1.1    plunky 
   3315  1.2  christos 	result = 0;
   3316  1.2  christos 	goto done;
   3317  1.2  christos error:
   3318  1.2  christos 	evhttp_clear_headers(headers);
   3319  1.2  christos done:
   3320  1.2  christos 	if (line)
   3321  1.2  christos 		mm_free(line);
   3322  1.2  christos 	if (uri)
   3323  1.2  christos 		evhttp_uri_free(uri);
   3324  1.2  christos 	return result;
   3325  1.2  christos }
   3326  1.2  christos 
   3327  1.2  christos int
   3328  1.2  christos evhttp_parse_query(const char *uri, struct evkeyvalq *headers)
   3329  1.2  christos {
   3330  1.2  christos 	return evhttp_parse_query_impl(uri, headers, 1);
   3331  1.2  christos }
   3332  1.2  christos int
   3333  1.2  christos evhttp_parse_query_str(const char *uri, struct evkeyvalq *headers)
   3334  1.2  christos {
   3335  1.2  christos 	return evhttp_parse_query_impl(uri, headers, 0);
   3336  1.1    plunky }
   3337  1.1    plunky 
   3338  1.1    plunky static struct evhttp_cb *
   3339  1.1    plunky evhttp_dispatch_callback(struct httpcbq *callbacks, struct evhttp_request *req)
   3340  1.1    plunky {
   3341  1.1    plunky 	struct evhttp_cb *cb;
   3342  1.1    plunky 	size_t offset = 0;
   3343  1.2  christos 	char *translated;
   3344  1.2  christos 	const char *path;
   3345  1.1    plunky 
   3346  1.1    plunky 	/* Test for different URLs */
   3347  1.2  christos 	path = evhttp_uri_get_path(req->uri_elems);
   3348  1.2  christos 	offset = strlen(path);
   3349  1.2  christos 	if ((translated = mm_malloc(offset + 1)) == NULL)
   3350  1.2  christos 		return (NULL);
   3351  1.2  christos 	evhttp_decode_uri_internal(path, offset, translated,
   3352  1.2  christos 	    0 /* decode_plus */);
   3353  1.1    plunky 
   3354  1.1    plunky 	TAILQ_FOREACH(cb, callbacks, next) {
   3355  1.2  christos 		if (!strcmp(cb->what, translated)) {
   3356  1.2  christos 			mm_free(translated);
   3357  1.2  christos 			return (cb);
   3358  1.2  christos 		}
   3359  1.2  christos 	}
   3360  1.2  christos 
   3361  1.2  christos 	mm_free(translated);
   3362  1.2  christos 	return (NULL);
   3363  1.2  christos }
   3364  1.2  christos 
   3365  1.2  christos 
   3366  1.2  christos static int
   3367  1.2  christos prefix_suffix_match(const char *pattern, const char *name, int ignorecase)
   3368  1.2  christos {
   3369  1.2  christos 	char c;
   3370  1.2  christos 
   3371  1.2  christos 	while (1) {
   3372  1.2  christos 		switch (c = *pattern++) {
   3373  1.2  christos 		case '\0':
   3374  1.2  christos 			return *name == '\0';
   3375  1.2  christos 
   3376  1.2  christos 		case '*':
   3377  1.2  christos 			while (*name != '\0') {
   3378  1.2  christos 				if (prefix_suffix_match(pattern, name,
   3379  1.2  christos 					ignorecase))
   3380  1.2  christos 					return (1);
   3381  1.2  christos 				++name;
   3382  1.2  christos 			}
   3383  1.2  christos 			return (0);
   3384  1.2  christos 		default:
   3385  1.2  christos 			if (c != *name) {
   3386  1.2  christos 				if (!ignorecase ||
   3387  1.4  christos 				    EVUTIL_TOLOWER_(c) != EVUTIL_TOLOWER_(*name))
   3388  1.2  christos 					return (0);
   3389  1.2  christos 			}
   3390  1.2  christos 			++name;
   3391  1.2  christos 		}
   3392  1.2  christos 	}
   3393  1.2  christos 	/* NOTREACHED */
   3394  1.2  christos }
   3395  1.2  christos 
   3396  1.2  christos /*
   3397  1.2  christos    Search the vhost hierarchy beginning with http for a server alias
   3398  1.2  christos    matching hostname.  If a match is found, and outhttp is non-null,
   3399  1.2  christos    outhttp is set to the matching http object and 1 is returned.
   3400  1.2  christos */
   3401  1.2  christos 
   3402  1.2  christos static int
   3403  1.2  christos evhttp_find_alias(struct evhttp *http, struct evhttp **outhttp,
   3404  1.2  christos 		  const char *hostname)
   3405  1.2  christos {
   3406  1.2  christos 	struct evhttp_server_alias *alias;
   3407  1.2  christos 	struct evhttp *vhost;
   3408  1.2  christos 
   3409  1.2  christos 	TAILQ_FOREACH(alias, &http->aliases, next) {
   3410  1.2  christos 		/* XXX Do we need to handle IP addresses? */
   3411  1.2  christos 		if (!evutil_ascii_strcasecmp(alias->alias, hostname)) {
   3412  1.2  christos 			if (outhttp)
   3413  1.2  christos 				*outhttp = http;
   3414  1.2  christos 			return 1;
   3415  1.1    plunky 		}
   3416  1.2  christos 	}
   3417  1.1    plunky 
   3418  1.2  christos 	/* XXX It might be good to avoid recursion here, but I don't
   3419  1.2  christos 	   see a way to do that w/o a list. */
   3420  1.2  christos 	TAILQ_FOREACH(vhost, &http->virtualhosts, next_vhost) {
   3421  1.2  christos 		if (evhttp_find_alias(vhost, outhttp, hostname))
   3422  1.2  christos 			return 1;
   3423  1.1    plunky 	}
   3424  1.1    plunky 
   3425  1.2  christos 	return 0;
   3426  1.2  christos }
   3427  1.2  christos 
   3428  1.2  christos /*
   3429  1.2  christos    Attempts to find the best http object to handle a request for a hostname.
   3430  1.2  christos    All aliases for the root http object and vhosts are searched for an exact
   3431  1.2  christos    match. Then, the vhost hierarchy is traversed again for a matching
   3432  1.2  christos    pattern.
   3433  1.2  christos 
   3434  1.2  christos    If an alias or vhost is matched, 1 is returned, and outhttp, if non-null,
   3435  1.2  christos    is set with the best matching http object. If there are no matches, the
   3436  1.2  christos    root http object is stored in outhttp and 0 is returned.
   3437  1.2  christos */
   3438  1.2  christos 
   3439  1.2  christos static int
   3440  1.2  christos evhttp_find_vhost(struct evhttp *http, struct evhttp **outhttp,
   3441  1.2  christos 		  const char *hostname)
   3442  1.2  christos {
   3443  1.2  christos 	struct evhttp *vhost;
   3444  1.2  christos 	struct evhttp *oldhttp;
   3445  1.2  christos 	int match_found = 0;
   3446  1.2  christos 
   3447  1.2  christos 	if (evhttp_find_alias(http, outhttp, hostname))
   3448  1.2  christos 		return 1;
   3449  1.2  christos 
   3450  1.2  christos 	do {
   3451  1.2  christos 		oldhttp = http;
   3452  1.2  christos 		TAILQ_FOREACH(vhost, &http->virtualhosts, next_vhost) {
   3453  1.2  christos 			if (prefix_suffix_match(vhost->vhost_pattern,
   3454  1.2  christos 				hostname, 1 /* ignorecase */)) {
   3455  1.2  christos 				http = vhost;
   3456  1.2  christos 				match_found = 1;
   3457  1.2  christos 				break;
   3458  1.2  christos 			}
   3459  1.2  christos 		}
   3460  1.2  christos 	} while (oldhttp != http);
   3461  1.2  christos 
   3462  1.2  christos 	if (outhttp)
   3463  1.2  christos 		*outhttp = http;
   3464  1.2  christos 
   3465  1.2  christos 	return match_found;
   3466  1.1    plunky }
   3467  1.1    plunky 
   3468  1.1    plunky static void
   3469  1.1    plunky evhttp_handle_request(struct evhttp_request *req, void *arg)
   3470  1.1    plunky {
   3471  1.1    plunky 	struct evhttp *http = arg;
   3472  1.1    plunky 	struct evhttp_cb *cb = NULL;
   3473  1.2  christos 	const char *hostname;
   3474  1.2  christos 
   3475  1.2  christos 	/* we have a new request on which the user needs to take action */
   3476  1.2  christos 	req->userdone = 0;
   3477  1.2  christos 
   3478  1.5  christos 	bufferevent_disable(req->evcon->bufev, EV_READ);
   3479  1.5  christos 
   3480  1.2  christos 	if (req->type == 0 || req->uri == NULL) {
   3481  1.4  christos 		evhttp_send_error(req, req->response_code, NULL);
   3482  1.2  christos 		return;
   3483  1.2  christos 	}
   3484  1.1    plunky 
   3485  1.2  christos 	if ((http->allowed_methods & req->type) == 0) {
   3486  1.2  christos 		event_debug(("Rejecting disallowed method %x (allowed: %x)\n",
   3487  1.2  christos 			(unsigned)req->type, (unsigned)http->allowed_methods));
   3488  1.2  christos 		evhttp_send_error(req, HTTP_NOTIMPLEMENTED, NULL);
   3489  1.1    plunky 		return;
   3490  1.1    plunky 	}
   3491  1.1    plunky 
   3492  1.2  christos 	/* handle potential virtual hosts */
   3493  1.2  christos 	hostname = evhttp_request_get_host(req);
   3494  1.2  christos 	if (hostname != NULL) {
   3495  1.2  christos 		evhttp_find_vhost(http, &http, hostname);
   3496  1.2  christos 	}
   3497  1.2  christos 
   3498  1.1    plunky 	if ((cb = evhttp_dispatch_callback(&http->callbacks, req)) != NULL) {
   3499  1.1    plunky 		(*cb->cb)(req, cb->cbarg);
   3500  1.1    plunky 		return;
   3501  1.1    plunky 	}
   3502  1.1    plunky 
   3503  1.1    plunky 	/* Generic call back */
   3504  1.1    plunky 	if (http->gencb) {
   3505  1.1    plunky 		(*http->gencb)(req, http->gencbarg);
   3506  1.1    plunky 		return;
   3507  1.1    plunky 	} else {
   3508  1.1    plunky 		/* We need to send a 404 here */
   3509  1.1    plunky #define ERR_FORMAT "<html><head>" \
   3510  1.1    plunky 		    "<title>404 Not Found</title>" \
   3511  1.1    plunky 		    "</head><body>" \
   3512  1.1    plunky 		    "<h1>Not Found</h1>" \
   3513  1.1    plunky 		    "<p>The requested URL %s was not found on this server.</p>"\
   3514  1.1    plunky 		    "</body></html>\n"
   3515  1.1    plunky 
   3516  1.2  christos 		char *escaped_html;
   3517  1.2  christos 		struct evbuffer *buf;
   3518  1.2  christos 
   3519  1.2  christos 		if ((escaped_html = evhttp_htmlescape(req->uri)) == NULL) {
   3520  1.2  christos 			evhttp_connection_free(req->evcon);
   3521  1.2  christos 			return;
   3522  1.2  christos 		}
   3523  1.2  christos 
   3524  1.2  christos 		if ((buf = evbuffer_new()) == NULL) {
   3525  1.2  christos 			mm_free(escaped_html);
   3526  1.2  christos 			evhttp_connection_free(req->evcon);
   3527  1.2  christos 			return;
   3528  1.2  christos 		}
   3529  1.1    plunky 
   3530  1.4  christos 		evhttp_response_code_(req, HTTP_NOTFOUND, "Not Found");
   3531  1.1    plunky 
   3532  1.1    plunky 		evbuffer_add_printf(buf, ERR_FORMAT, escaped_html);
   3533  1.1    plunky 
   3534  1.2  christos 		mm_free(escaped_html);
   3535  1.1    plunky 
   3536  1.4  christos 		evhttp_send_page_(req, buf);
   3537  1.1    plunky 
   3538  1.1    plunky 		evbuffer_free(buf);
   3539  1.1    plunky #undef ERR_FORMAT
   3540  1.1    plunky 	}
   3541  1.1    plunky }
   3542  1.1    plunky 
   3543  1.2  christos /* Listener callback when a connection arrives at a server. */
   3544  1.1    plunky static void
   3545  1.2  christos accept_socket_cb(struct evconnlistener *listener, evutil_socket_t nfd, struct sockaddr *peer_sa, int peer_socklen, void *arg)
   3546  1.1    plunky {
   3547  1.1    plunky 	struct evhttp *http = arg;
   3548  1.1    plunky 
   3549  1.2  christos 	evhttp_get_request(http, nfd, peer_sa, peer_socklen);
   3550  1.2  christos }
   3551  1.1    plunky 
   3552  1.2  christos int
   3553  1.2  christos evhttp_bind_socket(struct evhttp *http, const char *address, ev_uint16_t port)
   3554  1.2  christos {
   3555  1.2  christos 	struct evhttp_bound_socket *bound =
   3556  1.2  christos 		evhttp_bind_socket_with_handle(http, address, port);
   3557  1.2  christos 	if (bound == NULL)
   3558  1.2  christos 		return (-1);
   3559  1.2  christos 	return (0);
   3560  1.1    plunky }
   3561  1.1    plunky 
   3562  1.2  christos struct evhttp_bound_socket *
   3563  1.2  christos evhttp_bind_socket_with_handle(struct evhttp *http, const char *address, ev_uint16_t port)
   3564  1.1    plunky {
   3565  1.2  christos 	evutil_socket_t fd;
   3566  1.2  christos 	struct evhttp_bound_socket *bound;
   3567  1.5  christos 	int serrno;
   3568  1.1    plunky 
   3569  1.1    plunky 	if ((fd = bind_socket(address, port, 1 /*reuse*/)) == -1)
   3570  1.2  christos 		return (NULL);
   3571  1.1    plunky 
   3572  1.1    plunky 	if (listen(fd, 128) == -1) {
   3573  1.5  christos 		serrno = EVUTIL_SOCKET_ERROR();
   3574  1.2  christos 		event_sock_warn(fd, "%s: listen", __func__);
   3575  1.2  christos 		evutil_closesocket(fd);
   3576  1.5  christos 		EVUTIL_SET_SOCKET_ERROR(serrno);
   3577  1.2  christos 		return (NULL);
   3578  1.1    plunky 	}
   3579  1.1    plunky 
   3580  1.2  christos 	bound = evhttp_accept_socket_with_handle(http, fd);
   3581  1.2  christos 
   3582  1.2  christos 	if (bound != NULL) {
   3583  1.1    plunky 		event_debug(("Bound to port %d - Awaiting connections ... ",
   3584  1.1    plunky 			port));
   3585  1.2  christos 		return (bound);
   3586  1.2  christos 	}
   3587  1.1    plunky 
   3588  1.2  christos 	return (NULL);
   3589  1.1    plunky }
   3590  1.1    plunky 
   3591  1.1    plunky int
   3592  1.2  christos evhttp_accept_socket(struct evhttp *http, evutil_socket_t fd)
   3593  1.1    plunky {
   3594  1.2  christos 	struct evhttp_bound_socket *bound =
   3595  1.2  christos 		evhttp_accept_socket_with_handle(http, fd);
   3596  1.1    plunky 	if (bound == NULL)
   3597  1.1    plunky 		return (-1);
   3598  1.2  christos 	return (0);
   3599  1.2  christos }
   3600  1.1    plunky 
   3601  1.4  christos void
   3602  1.4  christos evhttp_foreach_bound_socket(struct evhttp *http,
   3603  1.4  christos                             evhttp_bound_socket_foreach_fn *function,
   3604  1.4  christos                             void *argument)
   3605  1.4  christos {
   3606  1.4  christos 	struct evhttp_bound_socket *bound;
   3607  1.4  christos 
   3608  1.4  christos 	TAILQ_FOREACH(bound, &http->sockets, next)
   3609  1.4  christos 		function(bound, argument);
   3610  1.4  christos }
   3611  1.1    plunky 
   3612  1.2  christos struct evhttp_bound_socket *
   3613  1.2  christos evhttp_accept_socket_with_handle(struct evhttp *http, evutil_socket_t fd)
   3614  1.2  christos {
   3615  1.2  christos 	struct evhttp_bound_socket *bound;
   3616  1.2  christos 	struct evconnlistener *listener;
   3617  1.2  christos 	const int flags =
   3618  1.2  christos 	    LEV_OPT_REUSEABLE|LEV_OPT_CLOSE_ON_EXEC|LEV_OPT_CLOSE_ON_FREE;
   3619  1.2  christos 
   3620  1.2  christos 	listener = evconnlistener_new(http->base, NULL, NULL,
   3621  1.2  christos 	    flags,
   3622  1.2  christos 	    0, /* Backlog is '0' because we already said 'listen' */
   3623  1.2  christos 	    fd);
   3624  1.2  christos 	if (!listener)
   3625  1.2  christos 		return (NULL);
   3626  1.2  christos 
   3627  1.2  christos 	bound = evhttp_bind_listener(http, listener);
   3628  1.2  christos 	if (!bound) {
   3629  1.2  christos 		evconnlistener_free(listener);
   3630  1.2  christos 		return (NULL);
   3631  1.2  christos 	}
   3632  1.2  christos 	return (bound);
   3633  1.2  christos }
   3634  1.1    plunky 
   3635  1.2  christos struct evhttp_bound_socket *
   3636  1.2  christos evhttp_bind_listener(struct evhttp *http, struct evconnlistener *listener)
   3637  1.2  christos {
   3638  1.2  christos 	struct evhttp_bound_socket *bound;
   3639  1.1    plunky 
   3640  1.2  christos 	bound = mm_malloc(sizeof(struct evhttp_bound_socket));
   3641  1.2  christos 	if (bound == NULL)
   3642  1.2  christos 		return (NULL);
   3643  1.1    plunky 
   3644  1.2  christos 	bound->listener = listener;
   3645  1.1    plunky 	TAILQ_INSERT_TAIL(&http->sockets, bound, next);
   3646  1.1    plunky 
   3647  1.2  christos 	evconnlistener_set_cb(listener, accept_socket_cb, http);
   3648  1.2  christos 	return bound;
   3649  1.2  christos }
   3650  1.2  christos 
   3651  1.2  christos evutil_socket_t
   3652  1.2  christos evhttp_bound_socket_get_fd(struct evhttp_bound_socket *bound)
   3653  1.2  christos {
   3654  1.2  christos 	return evconnlistener_get_fd(bound->listener);
   3655  1.2  christos }
   3656  1.2  christos 
   3657  1.2  christos struct evconnlistener *
   3658  1.2  christos evhttp_bound_socket_get_listener(struct evhttp_bound_socket *bound)
   3659  1.2  christos {
   3660  1.2  christos 	return bound->listener;
   3661  1.2  christos }
   3662  1.2  christos 
   3663  1.2  christos void
   3664  1.2  christos evhttp_del_accept_socket(struct evhttp *http, struct evhttp_bound_socket *bound)
   3665  1.2  christos {
   3666  1.2  christos 	TAILQ_REMOVE(&http->sockets, bound, next);
   3667  1.2  christos 	evconnlistener_free(bound->listener);
   3668  1.2  christos 	mm_free(bound);
   3669  1.1    plunky }
   3670  1.1    plunky 
   3671  1.1    plunky static struct evhttp*
   3672  1.1    plunky evhttp_new_object(void)
   3673  1.1    plunky {
   3674  1.1    plunky 	struct evhttp *http = NULL;
   3675  1.1    plunky 
   3676  1.2  christos 	if ((http = mm_calloc(1, sizeof(struct evhttp))) == NULL) {
   3677  1.1    plunky 		event_warn("%s: calloc", __func__);
   3678  1.1    plunky 		return (NULL);
   3679  1.1    plunky 	}
   3680  1.1    plunky 
   3681  1.4  christos 	evutil_timerclear(&http->timeout);
   3682  1.2  christos 	evhttp_set_max_headers_size(http, EV_SIZE_MAX);
   3683  1.2  christos 	evhttp_set_max_body_size(http, EV_SIZE_MAX);
   3684  1.4  christos 	evhttp_set_default_content_type(http, "text/html; charset=ISO-8859-1");
   3685  1.2  christos 	evhttp_set_allowed_methods(http,
   3686  1.2  christos 	    EVHTTP_REQ_GET |
   3687  1.2  christos 	    EVHTTP_REQ_POST |
   3688  1.2  christos 	    EVHTTP_REQ_HEAD |
   3689  1.2  christos 	    EVHTTP_REQ_PUT |
   3690  1.2  christos 	    EVHTTP_REQ_DELETE);
   3691  1.1    plunky 
   3692  1.1    plunky 	TAILQ_INIT(&http->sockets);
   3693  1.1    plunky 	TAILQ_INIT(&http->callbacks);
   3694  1.1    plunky 	TAILQ_INIT(&http->connections);
   3695  1.2  christos 	TAILQ_INIT(&http->virtualhosts);
   3696  1.2  christos 	TAILQ_INIT(&http->aliases);
   3697  1.1    plunky 
   3698  1.1    plunky 	return (http);
   3699  1.1    plunky }
   3700  1.1    plunky 
   3701  1.1    plunky struct evhttp *
   3702  1.1    plunky evhttp_new(struct event_base *base)
   3703  1.1    plunky {
   3704  1.2  christos 	struct evhttp *http = NULL;
   3705  1.1    plunky 
   3706  1.2  christos 	http = evhttp_new_object();
   3707  1.2  christos 	if (http == NULL)
   3708  1.2  christos 		return (NULL);
   3709  1.1    plunky 	http->base = base;
   3710  1.1    plunky 
   3711  1.1    plunky 	return (http);
   3712  1.1    plunky }
   3713  1.1    plunky 
   3714  1.1    plunky /*
   3715  1.1    plunky  * Start a web server on the specified address and port.
   3716  1.1    plunky  */
   3717  1.1    plunky 
   3718  1.1    plunky struct evhttp *
   3719  1.4  christos evhttp_start(const char *address, ev_uint16_t port)
   3720  1.1    plunky {
   3721  1.2  christos 	struct evhttp *http = NULL;
   3722  1.1    plunky 
   3723  1.2  christos 	http = evhttp_new_object();
   3724  1.2  christos 	if (http == NULL)
   3725  1.2  christos 		return (NULL);
   3726  1.1    plunky 	if (evhttp_bind_socket(http, address, port) == -1) {
   3727  1.2  christos 		mm_free(http);
   3728  1.1    plunky 		return (NULL);
   3729  1.1    plunky 	}
   3730  1.1    plunky 
   3731  1.1    plunky 	return (http);
   3732  1.1    plunky }
   3733  1.1    plunky 
   3734  1.1    plunky void
   3735  1.1    plunky evhttp_free(struct evhttp* http)
   3736  1.1    plunky {
   3737  1.1    plunky 	struct evhttp_cb *http_cb;
   3738  1.1    plunky 	struct evhttp_connection *evcon;
   3739  1.1    plunky 	struct evhttp_bound_socket *bound;
   3740  1.2  christos 	struct evhttp* vhost;
   3741  1.2  christos 	struct evhttp_server_alias *alias;
   3742  1.1    plunky 
   3743  1.1    plunky 	/* Remove the accepting part */
   3744  1.1    plunky 	while ((bound = TAILQ_FIRST(&http->sockets)) != NULL) {
   3745  1.1    plunky 		TAILQ_REMOVE(&http->sockets, bound, next);
   3746  1.1    plunky 
   3747  1.2  christos 		evconnlistener_free(bound->listener);
   3748  1.1    plunky 
   3749  1.2  christos 		mm_free(bound);
   3750  1.1    plunky 	}
   3751  1.1    plunky 
   3752  1.1    plunky 	while ((evcon = TAILQ_FIRST(&http->connections)) != NULL) {
   3753  1.1    plunky 		/* evhttp_connection_free removes the connection */
   3754  1.1    plunky 		evhttp_connection_free(evcon);
   3755  1.1    plunky 	}
   3756  1.1    plunky 
   3757  1.1    plunky 	while ((http_cb = TAILQ_FIRST(&http->callbacks)) != NULL) {
   3758  1.1    plunky 		TAILQ_REMOVE(&http->callbacks, http_cb, next);
   3759  1.2  christos 		mm_free(http_cb->what);
   3760  1.2  christos 		mm_free(http_cb);
   3761  1.2  christos 	}
   3762  1.2  christos 
   3763  1.2  christos 	while ((vhost = TAILQ_FIRST(&http->virtualhosts)) != NULL) {
   3764  1.2  christos 		TAILQ_REMOVE(&http->virtualhosts, vhost, next_vhost);
   3765  1.2  christos 
   3766  1.2  christos 		evhttp_free(vhost);
   3767  1.2  christos 	}
   3768  1.2  christos 
   3769  1.2  christos 	if (http->vhost_pattern != NULL)
   3770  1.2  christos 		mm_free(http->vhost_pattern);
   3771  1.2  christos 
   3772  1.2  christos 	while ((alias = TAILQ_FIRST(&http->aliases)) != NULL) {
   3773  1.2  christos 		TAILQ_REMOVE(&http->aliases, alias, next);
   3774  1.2  christos 		mm_free(alias->alias);
   3775  1.2  christos 		mm_free(alias);
   3776  1.2  christos 	}
   3777  1.2  christos 
   3778  1.2  christos 	mm_free(http);
   3779  1.2  christos }
   3780  1.2  christos 
   3781  1.2  christos int
   3782  1.2  christos evhttp_add_virtual_host(struct evhttp* http, const char *pattern,
   3783  1.2  christos     struct evhttp* vhost)
   3784  1.2  christos {
   3785  1.2  christos 	/* a vhost can only be a vhost once and should not have bound sockets */
   3786  1.2  christos 	if (vhost->vhost_pattern != NULL ||
   3787  1.2  christos 	    TAILQ_FIRST(&vhost->sockets) != NULL)
   3788  1.2  christos 		return (-1);
   3789  1.2  christos 
   3790  1.2  christos 	vhost->vhost_pattern = mm_strdup(pattern);
   3791  1.2  christos 	if (vhost->vhost_pattern == NULL)
   3792  1.2  christos 		return (-1);
   3793  1.2  christos 
   3794  1.2  christos 	TAILQ_INSERT_TAIL(&http->virtualhosts, vhost, next_vhost);
   3795  1.2  christos 
   3796  1.2  christos 	return (0);
   3797  1.2  christos }
   3798  1.2  christos 
   3799  1.2  christos int
   3800  1.2  christos evhttp_remove_virtual_host(struct evhttp* http, struct evhttp* vhost)
   3801  1.2  christos {
   3802  1.2  christos 	if (vhost->vhost_pattern == NULL)
   3803  1.2  christos 		return (-1);
   3804  1.2  christos 
   3805  1.2  christos 	TAILQ_REMOVE(&http->virtualhosts, vhost, next_vhost);
   3806  1.2  christos 
   3807  1.2  christos 	mm_free(vhost->vhost_pattern);
   3808  1.2  christos 	vhost->vhost_pattern = NULL;
   3809  1.2  christos 
   3810  1.2  christos 	return (0);
   3811  1.2  christos }
   3812  1.2  christos 
   3813  1.2  christos int
   3814  1.2  christos evhttp_add_server_alias(struct evhttp *http, const char *alias)
   3815  1.2  christos {
   3816  1.2  christos 	struct evhttp_server_alias *evalias;
   3817  1.2  christos 
   3818  1.2  christos 	evalias = mm_calloc(1, sizeof(*evalias));
   3819  1.2  christos 	if (!evalias)
   3820  1.2  christos 		return -1;
   3821  1.2  christos 
   3822  1.2  christos 	evalias->alias = mm_strdup(alias);
   3823  1.2  christos 	if (!evalias->alias) {
   3824  1.2  christos 		mm_free(evalias);
   3825  1.2  christos 		return -1;
   3826  1.2  christos 	}
   3827  1.2  christos 
   3828  1.2  christos 	TAILQ_INSERT_TAIL(&http->aliases, evalias, next);
   3829  1.2  christos 
   3830  1.2  christos 	return 0;
   3831  1.2  christos }
   3832  1.2  christos 
   3833  1.2  christos int
   3834  1.2  christos evhttp_remove_server_alias(struct evhttp *http, const char *alias)
   3835  1.2  christos {
   3836  1.2  christos 	struct evhttp_server_alias *evalias;
   3837  1.2  christos 
   3838  1.2  christos 	TAILQ_FOREACH(evalias, &http->aliases, next) {
   3839  1.2  christos 		if (evutil_ascii_strcasecmp(evalias->alias, alias) == 0) {
   3840  1.2  christos 			TAILQ_REMOVE(&http->aliases, evalias, next);
   3841  1.2  christos 			mm_free(evalias->alias);
   3842  1.2  christos 			mm_free(evalias);
   3843  1.2  christos 			return 0;
   3844  1.2  christos 		}
   3845  1.1    plunky 	}
   3846  1.2  christos 
   3847  1.2  christos 	return -1;
   3848  1.1    plunky }
   3849  1.1    plunky 
   3850  1.1    plunky void
   3851  1.1    plunky evhttp_set_timeout(struct evhttp* http, int timeout_in_secs)
   3852  1.1    plunky {
   3853  1.4  christos 	if (timeout_in_secs == -1) {
   3854  1.4  christos 		evhttp_set_timeout_tv(http, NULL);
   3855  1.4  christos 	} else {
   3856  1.4  christos 		struct timeval tv;
   3857  1.4  christos 		tv.tv_sec = timeout_in_secs;
   3858  1.4  christos 		tv.tv_usec = 0;
   3859  1.4  christos 		evhttp_set_timeout_tv(http, &tv);
   3860  1.4  christos 	}
   3861  1.4  christos }
   3862  1.4  christos 
   3863  1.4  christos void
   3864  1.4  christos evhttp_set_timeout_tv(struct evhttp* http, const struct timeval* tv)
   3865  1.4  christos {
   3866  1.4  christos 	if (tv) {
   3867  1.4  christos 		http->timeout = *tv;
   3868  1.4  christos 	} else {
   3869  1.4  christos 		evutil_timerclear(&http->timeout);
   3870  1.4  christos 	}
   3871  1.4  christos }
   3872  1.4  christos 
   3873  1.4  christos int evhttp_set_flags(struct evhttp *http, int flags)
   3874  1.4  christos {
   3875  1.4  christos 	int avail_flags = 0;
   3876  1.4  christos 	avail_flags |= EVHTTP_SERVER_LINGERING_CLOSE;
   3877  1.4  christos 
   3878  1.4  christos 	if (flags & ~avail_flags)
   3879  1.4  christos 		return 1;
   3880  1.4  christos 	http->flags &= ~avail_flags;
   3881  1.4  christos 
   3882  1.4  christos 	http->flags |= flags;
   3883  1.4  christos 
   3884  1.4  christos 	return 0;
   3885  1.1    plunky }
   3886  1.1    plunky 
   3887  1.1    plunky void
   3888  1.2  christos evhttp_set_max_headers_size(struct evhttp* http, ev_ssize_t max_headers_size)
   3889  1.2  christos {
   3890  1.2  christos 	if (max_headers_size < 0)
   3891  1.2  christos 		http->default_max_headers_size = EV_SIZE_MAX;
   3892  1.2  christos 	else
   3893  1.2  christos 		http->default_max_headers_size = max_headers_size;
   3894  1.2  christos }
   3895  1.2  christos 
   3896  1.2  christos void
   3897  1.2  christos evhttp_set_max_body_size(struct evhttp* http, ev_ssize_t max_body_size)
   3898  1.2  christos {
   3899  1.2  christos 	if (max_body_size < 0)
   3900  1.2  christos 		http->default_max_body_size = EV_UINT64_MAX;
   3901  1.2  christos 	else
   3902  1.2  christos 		http->default_max_body_size = max_body_size;
   3903  1.2  christos }
   3904  1.2  christos 
   3905  1.2  christos void
   3906  1.4  christos evhttp_set_default_content_type(struct evhttp *http,
   3907  1.4  christos 	const char *content_type) {
   3908  1.4  christos 	http->default_content_type = content_type;
   3909  1.4  christos }
   3910  1.4  christos 
   3911  1.4  christos void
   3912  1.2  christos evhttp_set_allowed_methods(struct evhttp* http, ev_uint16_t methods)
   3913  1.2  christos {
   3914  1.2  christos 	http->allowed_methods = methods;
   3915  1.2  christos }
   3916  1.2  christos 
   3917  1.2  christos int
   3918  1.1    plunky evhttp_set_cb(struct evhttp *http, const char *uri,
   3919  1.1    plunky     void (*cb)(struct evhttp_request *, void *), void *cbarg)
   3920  1.1    plunky {
   3921  1.1    plunky 	struct evhttp_cb *http_cb;
   3922  1.1    plunky 
   3923  1.2  christos 	TAILQ_FOREACH(http_cb, &http->callbacks, next) {
   3924  1.2  christos 		if (strcmp(http_cb->what, uri) == 0)
   3925  1.2  christos 			return (-1);
   3926  1.2  christos 	}
   3927  1.2  christos 
   3928  1.2  christos 	if ((http_cb = mm_calloc(1, sizeof(struct evhttp_cb))) == NULL) {
   3929  1.2  christos 		event_warn("%s: calloc", __func__);
   3930  1.2  christos 		return (-2);
   3931  1.2  christos 	}
   3932  1.1    plunky 
   3933  1.2  christos 	http_cb->what = mm_strdup(uri);
   3934  1.2  christos 	if (http_cb->what == NULL) {
   3935  1.2  christos 		event_warn("%s: strdup", __func__);
   3936  1.2  christos 		mm_free(http_cb);
   3937  1.2  christos 		return (-3);
   3938  1.2  christos 	}
   3939  1.1    plunky 	http_cb->cb = cb;
   3940  1.1    plunky 	http_cb->cbarg = cbarg;
   3941  1.1    plunky 
   3942  1.1    plunky 	TAILQ_INSERT_TAIL(&http->callbacks, http_cb, next);
   3943  1.2  christos 
   3944  1.2  christos 	return (0);
   3945  1.1    plunky }
   3946  1.1    plunky 
   3947  1.1    plunky int
   3948  1.1    plunky evhttp_del_cb(struct evhttp *http, const char *uri)
   3949  1.1    plunky {
   3950  1.1    plunky 	struct evhttp_cb *http_cb;
   3951  1.1    plunky 
   3952  1.1    plunky 	TAILQ_FOREACH(http_cb, &http->callbacks, next) {
   3953  1.1    plunky 		if (strcmp(http_cb->what, uri) == 0)
   3954  1.1    plunky 			break;
   3955  1.1    plunky 	}
   3956  1.1    plunky 	if (http_cb == NULL)
   3957  1.1    plunky 		return (-1);
   3958  1.1    plunky 
   3959  1.1    plunky 	TAILQ_REMOVE(&http->callbacks, http_cb, next);
   3960  1.2  christos 	mm_free(http_cb->what);
   3961  1.2  christos 	mm_free(http_cb);
   3962  1.1    plunky 
   3963  1.1    plunky 	return (0);
   3964  1.1    plunky }
   3965  1.1    plunky 
   3966  1.1    plunky void
   3967  1.1    plunky evhttp_set_gencb(struct evhttp *http,
   3968  1.1    plunky     void (*cb)(struct evhttp_request *, void *), void *cbarg)
   3969  1.1    plunky {
   3970  1.1    plunky 	http->gencb = cb;
   3971  1.1    plunky 	http->gencbarg = cbarg;
   3972  1.1    plunky }
   3973  1.1    plunky 
   3974  1.4  christos void
   3975  1.4  christos evhttp_set_bevcb(struct evhttp *http,
   3976  1.4  christos     struct bufferevent* (*cb)(struct event_base *, void *), void *cbarg)
   3977  1.4  christos {
   3978  1.4  christos 	http->bevcb = cb;
   3979  1.4  christos 	http->bevcbarg = cbarg;
   3980  1.4  christos }
   3981  1.4  christos 
   3982  1.1    plunky /*
   3983  1.1    plunky  * Request related functions
   3984  1.1    plunky  */
   3985  1.1    plunky 
   3986  1.1    plunky struct evhttp_request *
   3987  1.1    plunky evhttp_request_new(void (*cb)(struct evhttp_request *, void *), void *arg)
   3988  1.1    plunky {
   3989  1.1    plunky 	struct evhttp_request *req = NULL;
   3990  1.1    plunky 
   3991  1.1    plunky 	/* Allocate request structure */
   3992  1.2  christos 	if ((req = mm_calloc(1, sizeof(struct evhttp_request))) == NULL) {
   3993  1.1    plunky 		event_warn("%s: calloc", __func__);
   3994  1.1    plunky 		goto error;
   3995  1.1    plunky 	}
   3996  1.1    plunky 
   3997  1.2  christos 	req->headers_size = 0;
   3998  1.2  christos 	req->body_size = 0;
   3999  1.2  christos 
   4000  1.1    plunky 	req->kind = EVHTTP_RESPONSE;
   4001  1.2  christos 	req->input_headers = mm_calloc(1, sizeof(struct evkeyvalq));
   4002  1.1    plunky 	if (req->input_headers == NULL) {
   4003  1.1    plunky 		event_warn("%s: calloc", __func__);
   4004  1.1    plunky 		goto error;
   4005  1.1    plunky 	}
   4006  1.1    plunky 	TAILQ_INIT(req->input_headers);
   4007  1.1    plunky 
   4008  1.2  christos 	req->output_headers = mm_calloc(1, sizeof(struct evkeyvalq));
   4009  1.1    plunky 	if (req->output_headers == NULL) {
   4010  1.1    plunky 		event_warn("%s: calloc", __func__);
   4011  1.1    plunky 		goto error;
   4012  1.1    plunky 	}
   4013  1.1    plunky 	TAILQ_INIT(req->output_headers);
   4014  1.1    plunky 
   4015  1.1    plunky 	if ((req->input_buffer = evbuffer_new()) == NULL) {
   4016  1.1    plunky 		event_warn("%s: evbuffer_new", __func__);
   4017  1.1    plunky 		goto error;
   4018  1.1    plunky 	}
   4019  1.1    plunky 
   4020  1.1    plunky 	if ((req->output_buffer = evbuffer_new()) == NULL) {
   4021  1.1    plunky 		event_warn("%s: evbuffer_new", __func__);
   4022  1.1    plunky 		goto error;
   4023  1.1    plunky 	}
   4024  1.1    plunky 
   4025  1.1    plunky 	req->cb = cb;
   4026  1.1    plunky 	req->cb_arg = arg;
   4027  1.1    plunky 
   4028  1.1    plunky 	return (req);
   4029  1.1    plunky 
   4030  1.1    plunky  error:
   4031  1.1    plunky 	if (req != NULL)
   4032  1.1    plunky 		evhttp_request_free(req);
   4033  1.1    plunky 	return (NULL);
   4034  1.1    plunky }
   4035  1.1    plunky 
   4036  1.1    plunky void
   4037  1.1    plunky evhttp_request_free(struct evhttp_request *req)
   4038  1.1    plunky {
   4039  1.2  christos 	if ((req->flags & EVHTTP_REQ_DEFER_FREE) != 0) {
   4040  1.2  christos 		req->flags |= EVHTTP_REQ_NEEDS_FREE;
   4041  1.2  christos 		return;
   4042  1.2  christos 	}
   4043  1.2  christos 
   4044  1.1    plunky 	if (req->remote_host != NULL)
   4045  1.2  christos 		mm_free(req->remote_host);
   4046  1.1    plunky 	if (req->uri != NULL)
   4047  1.2  christos 		mm_free(req->uri);
   4048  1.2  christos 	if (req->uri_elems != NULL)
   4049  1.2  christos 		evhttp_uri_free(req->uri_elems);
   4050  1.1    plunky 	if (req->response_code_line != NULL)
   4051  1.2  christos 		mm_free(req->response_code_line);
   4052  1.2  christos 	if (req->host_cache != NULL)
   4053  1.2  christos 		mm_free(req->host_cache);
   4054  1.1    plunky 
   4055  1.1    plunky 	evhttp_clear_headers(req->input_headers);
   4056  1.2  christos 	mm_free(req->input_headers);
   4057  1.1    plunky 
   4058  1.1    plunky 	evhttp_clear_headers(req->output_headers);
   4059  1.2  christos 	mm_free(req->output_headers);
   4060  1.1    plunky 
   4061  1.1    plunky 	if (req->input_buffer != NULL)
   4062  1.1    plunky 		evbuffer_free(req->input_buffer);
   4063  1.1    plunky 
   4064  1.1    plunky 	if (req->output_buffer != NULL)
   4065  1.1    plunky 		evbuffer_free(req->output_buffer);
   4066  1.1    plunky 
   4067  1.2  christos 	mm_free(req);
   4068  1.2  christos }
   4069  1.2  christos 
   4070  1.2  christos void
   4071  1.2  christos evhttp_request_own(struct evhttp_request *req)
   4072  1.2  christos {
   4073  1.2  christos 	req->flags |= EVHTTP_USER_OWNED;
   4074  1.2  christos }
   4075  1.2  christos 
   4076  1.2  christos int
   4077  1.2  christos evhttp_request_is_owned(struct evhttp_request *req)
   4078  1.2  christos {
   4079  1.2  christos 	return (req->flags & EVHTTP_USER_OWNED) != 0;
   4080  1.2  christos }
   4081  1.2  christos 
   4082  1.2  christos struct evhttp_connection *
   4083  1.2  christos evhttp_request_get_connection(struct evhttp_request *req)
   4084  1.2  christos {
   4085  1.2  christos 	return req->evcon;
   4086  1.2  christos }
   4087  1.2  christos 
   4088  1.2  christos struct event_base *
   4089  1.2  christos evhttp_connection_get_base(struct evhttp_connection *conn)
   4090  1.2  christos {
   4091  1.2  christos 	return conn->base;
   4092  1.1    plunky }
   4093  1.1    plunky 
   4094  1.1    plunky void
   4095  1.1    plunky evhttp_request_set_chunked_cb(struct evhttp_request *req,
   4096  1.1    plunky     void (*cb)(struct evhttp_request *, void *))
   4097  1.1    plunky {
   4098  1.1    plunky 	req->chunk_cb = cb;
   4099  1.1    plunky }
   4100  1.1    plunky 
   4101  1.4  christos void
   4102  1.4  christos evhttp_request_set_header_cb(struct evhttp_request *req,
   4103  1.4  christos     int (*cb)(struct evhttp_request *, void *))
   4104  1.4  christos {
   4105  1.4  christos 	req->header_cb = cb;
   4106  1.4  christos }
   4107  1.4  christos 
   4108  1.4  christos void
   4109  1.4  christos evhttp_request_set_error_cb(struct evhttp_request *req,
   4110  1.4  christos     void (*cb)(enum evhttp_request_error, void *))
   4111  1.4  christos {
   4112  1.4  christos 	req->error_cb = cb;
   4113  1.4  christos }
   4114  1.4  christos 
   4115  1.4  christos void
   4116  1.4  christos evhttp_request_set_on_complete_cb(struct evhttp_request *req,
   4117  1.4  christos     void (*cb)(struct evhttp_request *, void *), void *cb_arg)
   4118  1.4  christos {
   4119  1.4  christos 	req->on_complete_cb = cb;
   4120  1.4  christos 	req->on_complete_cb_arg = cb_arg;
   4121  1.4  christos }
   4122  1.4  christos 
   4123  1.1    plunky /*
   4124  1.1    plunky  * Allows for inspection of the request URI
   4125  1.1    plunky  */
   4126  1.1    plunky 
   4127  1.1    plunky const char *
   4128  1.2  christos evhttp_request_get_uri(const struct evhttp_request *req) {
   4129  1.1    plunky 	if (req->uri == NULL)
   4130  1.1    plunky 		event_debug(("%s: request %p has no uri\n", __func__, req));
   4131  1.1    plunky 	return (req->uri);
   4132  1.1    plunky }
   4133  1.1    plunky 
   4134  1.2  christos const struct evhttp_uri *
   4135  1.2  christos evhttp_request_get_evhttp_uri(const struct evhttp_request *req) {
   4136  1.2  christos 	if (req->uri_elems == NULL)
   4137  1.2  christos 		event_debug(("%s: request %p has no uri elems\n",
   4138  1.2  christos 			    __func__, req));
   4139  1.2  christos 	return (req->uri_elems);
   4140  1.2  christos }
   4141  1.2  christos 
   4142  1.2  christos const char *
   4143  1.2  christos evhttp_request_get_host(struct evhttp_request *req)
   4144  1.2  christos {
   4145  1.2  christos 	const char *host = NULL;
   4146  1.2  christos 
   4147  1.2  christos 	if (req->host_cache)
   4148  1.2  christos 		return req->host_cache;
   4149  1.2  christos 
   4150  1.2  christos 	if (req->uri_elems)
   4151  1.2  christos 		host = evhttp_uri_get_host(req->uri_elems);
   4152  1.2  christos 	if (!host && req->input_headers) {
   4153  1.2  christos 		const char *p;
   4154  1.2  christos 		size_t len;
   4155  1.2  christos 
   4156  1.2  christos 		host = evhttp_find_header(req->input_headers, "Host");
   4157  1.2  christos 		/* The Host: header may include a port. Remove it here
   4158  1.2  christos 		   to be consistent with uri_elems case above. */
   4159  1.2  christos 		if (host) {
   4160  1.2  christos 			p = host + strlen(host) - 1;
   4161  1.4  christos 			while (p > host && EVUTIL_ISDIGIT_(*p))
   4162  1.2  christos 				--p;
   4163  1.2  christos 			if (p > host && *p == ':') {
   4164  1.2  christos 				len = p - host;
   4165  1.2  christos 				req->host_cache = mm_malloc(len + 1);
   4166  1.2  christos 				if (!req->host_cache) {
   4167  1.2  christos 					event_warn("%s: malloc", __func__);
   4168  1.2  christos 					return NULL;
   4169  1.2  christos 				}
   4170  1.2  christos 				memcpy(req->host_cache, host, len);
   4171  1.2  christos 				req->host_cache[len] = '\0';
   4172  1.2  christos 				host = req->host_cache;
   4173  1.2  christos 			}
   4174  1.2  christos 		}
   4175  1.2  christos 	}
   4176  1.2  christos 
   4177  1.2  christos 	return host;
   4178  1.2  christos }
   4179  1.2  christos 
   4180  1.2  christos enum evhttp_cmd_type
   4181  1.2  christos evhttp_request_get_command(const struct evhttp_request *req) {
   4182  1.2  christos 	return (req->type);
   4183  1.2  christos }
   4184  1.2  christos 
   4185  1.2  christos int
   4186  1.2  christos evhttp_request_get_response_code(const struct evhttp_request *req)
   4187  1.2  christos {
   4188  1.2  christos 	return req->response_code;
   4189  1.2  christos }
   4190  1.2  christos 
   4191  1.4  christos const char *
   4192  1.4  christos evhttp_request_get_response_code_line(const struct evhttp_request *req)
   4193  1.4  christos {
   4194  1.4  christos 	return req->response_code_line;
   4195  1.4  christos }
   4196  1.4  christos 
   4197  1.2  christos /** Returns the input headers */
   4198  1.2  christos struct evkeyvalq *evhttp_request_get_input_headers(struct evhttp_request *req)
   4199  1.2  christos {
   4200  1.2  christos 	return (req->input_headers);
   4201  1.2  christos }
   4202  1.2  christos 
   4203  1.2  christos /** Returns the output headers */
   4204  1.2  christos struct evkeyvalq *evhttp_request_get_output_headers(struct evhttp_request *req)
   4205  1.2  christos {
   4206  1.2  christos 	return (req->output_headers);
   4207  1.2  christos }
   4208  1.2  christos 
   4209  1.2  christos /** Returns the input buffer */
   4210  1.2  christos struct evbuffer *evhttp_request_get_input_buffer(struct evhttp_request *req)
   4211  1.2  christos {
   4212  1.2  christos 	return (req->input_buffer);
   4213  1.2  christos }
   4214  1.2  christos 
   4215  1.2  christos /** Returns the output buffer */
   4216  1.2  christos struct evbuffer *evhttp_request_get_output_buffer(struct evhttp_request *req)
   4217  1.2  christos {
   4218  1.2  christos 	return (req->output_buffer);
   4219  1.2  christos }
   4220  1.2  christos 
   4221  1.2  christos 
   4222  1.2  christos /*
   4223  1.2  christos  * Takes a file descriptor to read a request from.
   4224  1.2  christos  * The callback is executed once the whole request has been read.
   4225  1.2  christos  */
   4226  1.1    plunky 
   4227  1.1    plunky static struct evhttp_connection*
   4228  1.1    plunky evhttp_get_request_connection(
   4229  1.1    plunky 	struct evhttp* http,
   4230  1.2  christos 	evutil_socket_t fd, struct sockaddr *sa, ev_socklen_t salen)
   4231  1.1    plunky {
   4232  1.1    plunky 	struct evhttp_connection *evcon;
   4233  1.1    plunky 	char *hostname = NULL, *portname = NULL;
   4234  1.4  christos 	struct bufferevent* bev = NULL;
   4235  1.1    plunky 
   4236  1.5  christos #ifdef EVENT__HAVE_STRUCT_SOCKADDR_UN
   4237  1.5  christos 	if (sa->sa_family == AF_UNIX) {
   4238  1.5  christos 		struct sockaddr_un *sa_un = (struct sockaddr_un *)sa;
   4239  1.5  christos 		sa_un->sun_path[0] = '\0';
   4240  1.5  christos 	}
   4241  1.5  christos #endif
   4242  1.5  christos 
   4243  1.1    plunky 	name_from_addr(sa, salen, &hostname, &portname);
   4244  1.1    plunky 	if (hostname == NULL || portname == NULL) {
   4245  1.2  christos 		if (hostname) mm_free(hostname);
   4246  1.2  christos 		if (portname) mm_free(portname);
   4247  1.1    plunky 		return (NULL);
   4248  1.1    plunky 	}
   4249  1.1    plunky 
   4250  1.2  christos 	event_debug(("%s: new request from %s:%s on "EV_SOCK_FMT"\n",
   4251  1.2  christos 		__func__, hostname, portname, EV_SOCK_ARG(fd)));
   4252  1.1    plunky 
   4253  1.1    plunky 	/* we need a connection object to put the http request on */
   4254  1.4  christos 	if (http->bevcb != NULL) {
   4255  1.4  christos 		bev = (*http->bevcb)(http->base, http->bevcbarg);
   4256  1.4  christos 	}
   4257  1.4  christos 	evcon = evhttp_connection_base_bufferevent_new(
   4258  1.4  christos 		http->base, NULL, bev, hostname, atoi(portname));
   4259  1.2  christos 	mm_free(hostname);
   4260  1.2  christos 	mm_free(portname);
   4261  1.1    plunky 	if (evcon == NULL)
   4262  1.1    plunky 		return (NULL);
   4263  1.1    plunky 
   4264  1.2  christos 	evcon->max_headers_size = http->default_max_headers_size;
   4265  1.2  christos 	evcon->max_body_size = http->default_max_body_size;
   4266  1.4  christos 	if (http->flags & EVHTTP_SERVER_LINGERING_CLOSE)
   4267  1.4  christos 		evcon->flags |= EVHTTP_CON_LINGERING_CLOSE;
   4268  1.1    plunky 
   4269  1.1    plunky 	evcon->flags |= EVHTTP_CON_INCOMING;
   4270  1.1    plunky 	evcon->state = EVCON_READING_FIRSTLINE;
   4271  1.2  christos 
   4272  1.1    plunky 	evcon->fd = fd;
   4273  1.1    plunky 
   4274  1.5  christos 	if (bufferevent_setfd(evcon->bufev, fd))
   4275  1.5  christos 		goto err;
   4276  1.5  christos 	if (bufferevent_enable(evcon->bufev, EV_READ))
   4277  1.5  christos 		goto err;
   4278  1.5  christos 	if (bufferevent_disable(evcon->bufev, EV_WRITE))
   4279  1.5  christos 		goto err;
   4280  1.5  christos 	bufferevent_socket_set_conn_address_(evcon->bufev, sa, salen);
   4281  1.2  christos 
   4282  1.1    plunky 	return (evcon);
   4283  1.5  christos 
   4284  1.5  christos err:
   4285  1.5  christos 	evhttp_connection_free(evcon);
   4286  1.5  christos 	return (NULL);
   4287  1.1    plunky }
   4288  1.1    plunky 
   4289  1.1    plunky static int
   4290  1.1    plunky evhttp_associate_new_request_with_connection(struct evhttp_connection *evcon)
   4291  1.1    plunky {
   4292  1.1    plunky 	struct evhttp *http = evcon->http_server;
   4293  1.1    plunky 	struct evhttp_request *req;
   4294  1.1    plunky 	if ((req = evhttp_request_new(evhttp_handle_request, http)) == NULL)
   4295  1.1    plunky 		return (-1);
   4296  1.1    plunky 
   4297  1.2  christos 	if ((req->remote_host = mm_strdup(evcon->address)) == NULL) {
   4298  1.2  christos 		event_warn("%s: strdup", __func__);
   4299  1.2  christos 		evhttp_request_free(req);
   4300  1.2  christos 		return (-1);
   4301  1.2  christos 	}
   4302  1.2  christos 	req->remote_port = evcon->port;
   4303  1.2  christos 
   4304  1.1    plunky 	req->evcon = evcon;	/* the request ends up owning the connection */
   4305  1.1    plunky 	req->flags |= EVHTTP_REQ_OWN_CONNECTION;
   4306  1.2  christos 
   4307  1.2  christos 	/* We did not present the request to the user user yet, so treat it as
   4308  1.2  christos 	 * if the user was done with the request.  This allows us to free the
   4309  1.2  christos 	 * request on a persistent connection if the client drops it without
   4310  1.2  christos 	 * sending a request.
   4311  1.2  christos 	 */
   4312  1.2  christos 	req->userdone = 1;
   4313  1.2  christos 
   4314  1.1    plunky 	TAILQ_INSERT_TAIL(&evcon->requests, req, next);
   4315  1.2  christos 
   4316  1.1    plunky 	req->kind = EVHTTP_REQUEST;
   4317  1.2  christos 
   4318  1.1    plunky 
   4319  1.4  christos 	evhttp_start_read_(evcon);
   4320  1.2  christos 
   4321  1.1    plunky 	return (0);
   4322  1.1    plunky }
   4323  1.1    plunky 
   4324  1.2  christos static void
   4325  1.2  christos evhttp_get_request(struct evhttp *http, evutil_socket_t fd,
   4326  1.2  christos     struct sockaddr *sa, ev_socklen_t salen)
   4327  1.1    plunky {
   4328  1.1    plunky 	struct evhttp_connection *evcon;
   4329  1.1    plunky 
   4330  1.1    plunky 	evcon = evhttp_get_request_connection(http, fd, sa, salen);
   4331  1.2  christos 	if (evcon == NULL) {
   4332  1.2  christos 		event_sock_warn(fd, "%s: cannot get connection on "EV_SOCK_FMT,
   4333  1.2  christos 		    __func__, EV_SOCK_ARG(fd));
   4334  1.2  christos 		evutil_closesocket(fd);
   4335  1.1    plunky 		return;
   4336  1.2  christos 	}
   4337  1.1    plunky 
   4338  1.1    plunky 	/* the timeout can be used by the server to close idle connections */
   4339  1.4  christos 	if (evutil_timerisset(&http->timeout))
   4340  1.4  christos 		evhttp_connection_set_timeout_tv(evcon, &http->timeout);
   4341  1.1    plunky 
   4342  1.2  christos 	/*
   4343  1.1    plunky 	 * if we want to accept more than one request on a connection,
   4344  1.1    plunky 	 * we need to know which http server it belongs to.
   4345  1.1    plunky 	 */
   4346  1.1    plunky 	evcon->http_server = http;
   4347  1.1    plunky 	TAILQ_INSERT_TAIL(&http->connections, evcon, next);
   4348  1.2  christos 
   4349  1.1    plunky 	if (evhttp_associate_new_request_with_connection(evcon) == -1)
   4350  1.1    plunky 		evhttp_connection_free(evcon);
   4351  1.1    plunky }
   4352  1.1    plunky 
   4353  1.1    plunky 
   4354  1.1    plunky /*
   4355  1.1    plunky  * Network helper functions that we do not want to export to the rest of
   4356  1.1    plunky  * the world.
   4357  1.1    plunky  */
   4358  1.1    plunky 
   4359  1.1    plunky static void
   4360  1.2  christos name_from_addr(struct sockaddr *sa, ev_socklen_t salen,
   4361  1.1    plunky     char **phost, char **pport)
   4362  1.1    plunky {
   4363  1.1    plunky 	char ntop[NI_MAXHOST];
   4364  1.1    plunky 	char strport[NI_MAXSERV];
   4365  1.1    plunky 	int ni_result;
   4366  1.1    plunky 
   4367  1.4  christos #ifdef EVENT__HAVE_GETNAMEINFO
   4368  1.1    plunky 	ni_result = getnameinfo(sa, salen,
   4369  1.1    plunky 		ntop, sizeof(ntop), strport, sizeof(strport),
   4370  1.1    plunky 		NI_NUMERICHOST|NI_NUMERICSERV);
   4371  1.2  christos 
   4372  1.1    plunky 	if (ni_result != 0) {
   4373  1.2  christos #ifdef EAI_SYSTEM
   4374  1.2  christos 		/* Windows doesn't have an EAI_SYSTEM. */
   4375  1.1    plunky 		if (ni_result == EAI_SYSTEM)
   4376  1.1    plunky 			event_err(1, "getnameinfo failed");
   4377  1.1    plunky 		else
   4378  1.2  christos #endif
   4379  1.1    plunky 			event_errx(1, "getnameinfo failed: %s", gai_strerror(ni_result));
   4380  1.1    plunky 		return;
   4381  1.1    plunky 	}
   4382  1.1    plunky #else
   4383  1.1    plunky 	ni_result = fake_getnameinfo(sa, salen,
   4384  1.1    plunky 		ntop, sizeof(ntop), strport, sizeof(strport),
   4385  1.1    plunky 		NI_NUMERICHOST|NI_NUMERICSERV);
   4386  1.1    plunky 	if (ni_result != 0)
   4387  1.1    plunky 			return;
   4388  1.1    plunky #endif
   4389  1.2  christos 
   4390  1.2  christos 	*phost = mm_strdup(ntop);
   4391  1.2  christos 	*pport = mm_strdup(strport);
   4392  1.1    plunky }
   4393  1.1    plunky 
   4394  1.1    plunky /* Create a non-blocking socket and bind it */
   4395  1.2  christos static evutil_socket_t
   4396  1.5  christos create_bind_socket_nonblock(struct evutil_addrinfo *ai, int reuse)
   4397  1.1    plunky {
   4398  1.2  christos 	evutil_socket_t fd;
   4399  1.2  christos 
   4400  1.2  christos 	int on = 1, r;
   4401  1.1    plunky 	int serrno;
   4402  1.1    plunky 
   4403  1.2  christos 	/* Create listen socket */
   4404  1.4  christos 	fd = evutil_socket_(ai ? ai->ai_family : AF_INET,
   4405  1.4  christos 	    SOCK_STREAM|EVUTIL_SOCK_NONBLOCK|EVUTIL_SOCK_CLOEXEC, 0);
   4406  1.2  christos 	if (fd == -1) {
   4407  1.2  christos 			event_sock_warn(-1, "socket");
   4408  1.2  christos 			return (-1);
   4409  1.2  christos 	}
   4410  1.1    plunky 
   4411  1.2  christos 	if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (void *)&on, sizeof(on))<0)
   4412  1.2  christos 		goto out;
   4413  1.1    plunky 	if (reuse) {
   4414  1.2  christos 		if (evutil_make_listen_socket_reuseable(fd) < 0)
   4415  1.2  christos 			goto out;
   4416  1.1    plunky 	}
   4417  1.1    plunky 
   4418  1.1    plunky 	if (ai != NULL) {
   4419  1.2  christos 		r = bind(fd, ai->ai_addr, (ev_socklen_t)ai->ai_addrlen);
   4420  1.1    plunky 		if (r == -1)
   4421  1.1    plunky 			goto out;
   4422  1.1    plunky 	}
   4423  1.1    plunky 
   4424  1.1    plunky 	return (fd);
   4425  1.1    plunky 
   4426  1.1    plunky  out:
   4427  1.1    plunky 	serrno = EVUTIL_SOCKET_ERROR();
   4428  1.2  christos 	evutil_closesocket(fd);
   4429  1.1    plunky 	EVUTIL_SET_SOCKET_ERROR(serrno);
   4430  1.1    plunky 	return (-1);
   4431  1.1    plunky }
   4432  1.1    plunky 
   4433  1.2  christos static struct evutil_addrinfo *
   4434  1.2  christos make_addrinfo(const char *address, ev_uint16_t port)
   4435  1.1    plunky {
   4436  1.2  christos 	struct evutil_addrinfo *ai = NULL;
   4437  1.1    plunky 
   4438  1.2  christos 	struct evutil_addrinfo hints;
   4439  1.2  christos 	char strport[NI_MAXSERV];
   4440  1.2  christos 	int ai_result;
   4441  1.1    plunky 
   4442  1.2  christos 	memset(&hints, 0, sizeof(hints));
   4443  1.2  christos 	hints.ai_family = AF_UNSPEC;
   4444  1.2  christos 	hints.ai_socktype = SOCK_STREAM;
   4445  1.2  christos 	/* turn NULL hostname into INADDR_ANY, and skip looking up any address
   4446  1.2  christos 	 * types we don't have an interface to connect to. */
   4447  1.2  christos 	hints.ai_flags = EVUTIL_AI_PASSIVE|EVUTIL_AI_ADDRCONFIG;
   4448  1.2  christos 	evutil_snprintf(strport, sizeof(strport), "%d", port);
   4449  1.2  christos 	if ((ai_result = evutil_getaddrinfo(address, strport, &hints, &ai))
   4450  1.2  christos 	    != 0) {
   4451  1.2  christos 		if (ai_result == EVUTIL_EAI_SYSTEM)
   4452  1.2  christos 			event_warn("getaddrinfo");
   4453  1.2  christos 		else
   4454  1.2  christos 			event_warnx("getaddrinfo: %s",
   4455  1.2  christos 			    evutil_gai_strerror(ai_result));
   4456  1.1    plunky 		return (NULL);
   4457  1.1    plunky 	}
   4458  1.1    plunky 
   4459  1.2  christos 	return (ai);
   4460  1.1    plunky }
   4461  1.1    plunky 
   4462  1.2  christos static evutil_socket_t
   4463  1.2  christos bind_socket(const char *address, ev_uint16_t port, int reuse)
   4464  1.1    plunky {
   4465  1.2  christos 	evutil_socket_t fd;
   4466  1.2  christos 	struct evutil_addrinfo *aitop = NULL;
   4467  1.1    plunky 
   4468  1.1    plunky 	/* just create an unbound socket */
   4469  1.1    plunky 	if (address == NULL && port == 0)
   4470  1.5  christos 		return create_bind_socket_nonblock(NULL, 0);
   4471  1.2  christos 
   4472  1.1    plunky 	aitop = make_addrinfo(address, port);
   4473  1.1    plunky 
   4474  1.1    plunky 	if (aitop == NULL)
   4475  1.1    plunky 		return (-1);
   4476  1.1    plunky 
   4477  1.5  christos 	fd = create_bind_socket_nonblock(aitop, reuse);
   4478  1.1    plunky 
   4479  1.2  christos 	evutil_freeaddrinfo(aitop);
   4480  1.1    plunky 
   4481  1.1    plunky 	return (fd);
   4482  1.1    plunky }
   4483  1.1    plunky 
   4484  1.2  christos struct evhttp_uri {
   4485  1.2  christos 	unsigned flags;
   4486  1.2  christos 	char *scheme; /* scheme; e.g http, ftp etc */
   4487  1.2  christos 	char *userinfo; /* userinfo (typically username:pass), or NULL */
   4488  1.2  christos 	char *host; /* hostname, IP address, or NULL */
   4489  1.2  christos 	int port; /* port, or zero */
   4490  1.2  christos 	char *path; /* path, or "". */
   4491  1.2  christos 	char *query; /* query, or NULL */
   4492  1.2  christos 	char *fragment; /* fragment or NULL */
   4493  1.2  christos };
   4494  1.2  christos 
   4495  1.2  christos struct evhttp_uri *
   4496  1.2  christos evhttp_uri_new(void)
   4497  1.2  christos {
   4498  1.2  christos 	struct evhttp_uri *uri = mm_calloc(sizeof(struct evhttp_uri), 1);
   4499  1.2  christos 	if (uri)
   4500  1.2  christos 		uri->port = -1;
   4501  1.2  christos 	return uri;
   4502  1.2  christos }
   4503  1.2  christos 
   4504  1.2  christos void
   4505  1.2  christos evhttp_uri_set_flags(struct evhttp_uri *uri, unsigned flags)
   4506  1.2  christos {
   4507  1.2  christos 	uri->flags = flags;
   4508  1.2  christos }
   4509  1.2  christos 
   4510  1.2  christos /* Return true if the string starting at s and ending immediately before eos
   4511  1.2  christos  * is a valid URI scheme according to RFC3986
   4512  1.2  christos  */
   4513  1.2  christos static int
   4514  1.2  christos scheme_ok(const char *s, const char *eos)
   4515  1.2  christos {
   4516  1.2  christos 	/* scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." ) */
   4517  1.2  christos 	EVUTIL_ASSERT(eos >= s);
   4518  1.2  christos 	if (s == eos)
   4519  1.2  christos 		return 0;
   4520  1.4  christos 	if (!EVUTIL_ISALPHA_(*s))
   4521  1.2  christos 		return 0;
   4522  1.2  christos 	while (++s < eos) {
   4523  1.4  christos 		if (! EVUTIL_ISALNUM_(*s) &&
   4524  1.2  christos 		    *s != '+' && *s != '-' && *s != '.')
   4525  1.2  christos 			return 0;
   4526  1.2  christos 	}
   4527  1.2  christos 	return 1;
   4528  1.2  christos }
   4529  1.2  christos 
   4530  1.2  christos #define SUBDELIMS "!$&'()*+,;="
   4531  1.2  christos 
   4532  1.2  christos /* Return true iff [s..eos) is a valid userinfo */
   4533  1.2  christos static int
   4534  1.2  christos userinfo_ok(const char *s, const char *eos)
   4535  1.2  christos {
   4536  1.2  christos 	while (s < eos) {
   4537  1.2  christos 		if (CHAR_IS_UNRESERVED(*s) ||
   4538  1.2  christos 		    strchr(SUBDELIMS, *s) ||
   4539  1.2  christos 		    *s == ':')
   4540  1.2  christos 			++s;
   4541  1.2  christos 		else if (*s == '%' && s+2 < eos &&
   4542  1.4  christos 		    EVUTIL_ISXDIGIT_(s[1]) &&
   4543  1.4  christos 		    EVUTIL_ISXDIGIT_(s[2]))
   4544  1.2  christos 			s += 3;
   4545  1.2  christos 		else
   4546  1.2  christos 			return 0;
   4547  1.2  christos 	}
   4548  1.2  christos 	return 1;
   4549  1.2  christos }
   4550  1.2  christos 
   4551  1.2  christos static int
   4552  1.2  christos regname_ok(const char *s, const char *eos)
   4553  1.2  christos {
   4554  1.2  christos 	while (s && s<eos) {
   4555  1.2  christos 		if (CHAR_IS_UNRESERVED(*s) ||
   4556  1.2  christos 		    strchr(SUBDELIMS, *s))
   4557  1.2  christos 			++s;
   4558  1.2  christos 		else if (*s == '%' &&
   4559  1.4  christos 		    EVUTIL_ISXDIGIT_(s[1]) &&
   4560  1.4  christos 		    EVUTIL_ISXDIGIT_(s[2]))
   4561  1.2  christos 			s += 3;
   4562  1.2  christos 		else
   4563  1.2  christos 			return 0;
   4564  1.2  christos 	}
   4565  1.2  christos 	return 1;
   4566  1.2  christos }
   4567  1.2  christos 
   4568  1.2  christos static int
   4569  1.2  christos parse_port(const char *s, const char *eos)
   4570  1.2  christos {
   4571  1.2  christos 	int portnum = 0;
   4572  1.2  christos 	while (s < eos) {
   4573  1.4  christos 		if (! EVUTIL_ISDIGIT_(*s))
   4574  1.2  christos 			return -1;
   4575  1.2  christos 		portnum = (portnum * 10) + (*s - '0');
   4576  1.2  christos 		if (portnum < 0)
   4577  1.2  christos 			return -1;
   4578  1.4  christos 		if (portnum > 65535)
   4579  1.4  christos 			return -1;
   4580  1.2  christos 		++s;
   4581  1.2  christos 	}
   4582  1.2  christos 	return portnum;
   4583  1.2  christos }
   4584  1.2  christos 
   4585  1.2  christos /* returns 0 for bad, 1 for ipv6, 2 for IPvFuture */
   4586  1.2  christos static int
   4587  1.2  christos bracket_addr_ok(const char *s, const char *eos)
   4588  1.2  christos {
   4589  1.2  christos 	if (s + 3 > eos || *s != '[' || *(eos-1) != ']')
   4590  1.2  christos 		return 0;
   4591  1.2  christos 	if (s[1] == 'v') {
   4592  1.2  christos 		/* IPvFuture, or junk.
   4593  1.2  christos 		   "v" 1*HEXDIG "." 1*( unreserved / sub-delims / ":" )
   4594  1.2  christos 		 */
   4595  1.2  christos 		s += 2; /* skip [v */
   4596  1.2  christos 		--eos;
   4597  1.4  christos 		if (!EVUTIL_ISXDIGIT_(*s)) /*require at least one*/
   4598  1.2  christos 			return 0;
   4599  1.2  christos 		while (s < eos && *s != '.') {
   4600  1.4  christos 			if (EVUTIL_ISXDIGIT_(*s))
   4601  1.2  christos 				++s;
   4602  1.2  christos 			else
   4603  1.2  christos 				return 0;
   4604  1.2  christos 		}
   4605  1.2  christos 		if (*s != '.')
   4606  1.2  christos 			return 0;
   4607  1.2  christos 		++s;
   4608  1.2  christos 		while (s < eos) {
   4609  1.2  christos 			if (CHAR_IS_UNRESERVED(*s) ||
   4610  1.2  christos 			    strchr(SUBDELIMS, *s) ||
   4611  1.2  christos 			    *s == ':')
   4612  1.2  christos 				++s;
   4613  1.2  christos 			else
   4614  1.2  christos 				return 0;
   4615  1.2  christos 		}
   4616  1.2  christos 		return 2;
   4617  1.2  christos 	} else {
   4618  1.2  christos 		/* IPv6, or junk */
   4619  1.2  christos 		char buf[64];
   4620  1.2  christos 		ev_ssize_t n_chars = eos-s-2;
   4621  1.2  christos 		struct in6_addr in6;
   4622  1.2  christos 		if (n_chars >= 64) /* way too long */
   4623  1.2  christos 			return 0;
   4624  1.2  christos 		memcpy(buf, s+1, n_chars);
   4625  1.2  christos 		buf[n_chars]='\0';
   4626  1.2  christos 		return (evutil_inet_pton(AF_INET6,buf,&in6)==1) ? 1 : 0;
   4627  1.2  christos 	}
   4628  1.2  christos }
   4629  1.2  christos 
   4630  1.1    plunky static int
   4631  1.2  christos parse_authority(struct evhttp_uri *uri, char *s, char *eos)
   4632  1.1    plunky {
   4633  1.2  christos 	char *cp, *port;
   4634  1.2  christos 	EVUTIL_ASSERT(eos);
   4635  1.2  christos 	if (eos == s) {
   4636  1.2  christos 		uri->host = mm_strdup("");
   4637  1.2  christos 		if (uri->host == NULL) {
   4638  1.2  christos 			event_warn("%s: strdup", __func__);
   4639  1.2  christos 			return -1;
   4640  1.2  christos 		}
   4641  1.2  christos 		return 0;
   4642  1.2  christos 	}
   4643  1.1    plunky 
   4644  1.2  christos 	/* Optionally, we start with "userinfo@" */
   4645  1.2  christos 
   4646  1.2  christos 	cp = strchr(s, '@');
   4647  1.2  christos 	if (cp && cp < eos) {
   4648  1.2  christos 		if (! userinfo_ok(s,cp))
   4649  1.2  christos 			return -1;
   4650  1.2  christos 		*cp++ = '\0';
   4651  1.2  christos 		uri->userinfo = mm_strdup(s);
   4652  1.2  christos 		if (uri->userinfo == NULL) {
   4653  1.2  christos 			event_warn("%s: strdup", __func__);
   4654  1.2  christos 			return -1;
   4655  1.2  christos 		}
   4656  1.2  christos 	} else {
   4657  1.2  christos 		cp = s;
   4658  1.2  christos 	}
   4659  1.2  christos 	/* Optionally, we end with ":port" */
   4660  1.4  christos 	for (port=eos-1; port >= cp && EVUTIL_ISDIGIT_(*port); --port)
   4661  1.2  christos 		;
   4662  1.2  christos 	if (port >= cp && *port == ':') {
   4663  1.2  christos 		if (port+1 == eos) /* Leave port unspecified; the RFC allows a
   4664  1.2  christos 				    * nil port */
   4665  1.2  christos 			uri->port = -1;
   4666  1.2  christos 		else if ((uri->port = parse_port(port+1, eos))<0)
   4667  1.2  christos 			return -1;
   4668  1.2  christos 		eos = port;
   4669  1.2  christos 	}
   4670  1.2  christos 	/* Now, cp..eos holds the "host" port, which can be an IPv4Address,
   4671  1.2  christos 	 * an IP-Literal, or a reg-name */
   4672  1.2  christos 	EVUTIL_ASSERT(eos >= cp);
   4673  1.2  christos 	if (*cp == '[' && eos >= cp+2 && *(eos-1) == ']') {
   4674  1.2  christos 		/* IPv6address, IP-Literal, or junk. */
   4675  1.2  christos 		if (! bracket_addr_ok(cp, eos))
   4676  1.2  christos 			return -1;
   4677  1.2  christos 	} else {
   4678  1.2  christos 		/* Make sure the host part is ok. */
   4679  1.2  christos 		if (! regname_ok(cp,eos)) /* Match IPv4Address or reg-name */
   4680  1.2  christos 			return -1;
   4681  1.2  christos 	}
   4682  1.2  christos 	uri->host = mm_malloc(eos-cp+1);
   4683  1.2  christos 	if (uri->host == NULL) {
   4684  1.2  christos 		event_warn("%s: malloc", __func__);
   4685  1.2  christos 		return -1;
   4686  1.2  christos 	}
   4687  1.2  christos 	memcpy(uri->host, cp, eos-cp);
   4688  1.2  christos 	uri->host[eos-cp] = '\0';
   4689  1.2  christos 	return 0;
   4690  1.2  christos 
   4691  1.2  christos }
   4692  1.2  christos 
   4693  1.2  christos static char *
   4694  1.2  christos end_of_authority(char *cp)
   4695  1.2  christos {
   4696  1.2  christos 	while (*cp) {
   4697  1.2  christos 		if (*cp == '?' || *cp == '#' || *cp == '/')
   4698  1.2  christos 			return cp;
   4699  1.2  christos 		++cp;
   4700  1.2  christos 	}
   4701  1.2  christos 	return cp;
   4702  1.2  christos }
   4703  1.2  christos 
   4704  1.2  christos enum uri_part {
   4705  1.2  christos 	PART_PATH,
   4706  1.2  christos 	PART_QUERY,
   4707  1.2  christos 	PART_FRAGMENT
   4708  1.2  christos };
   4709  1.2  christos 
   4710  1.2  christos /* Return the character after the longest prefix of 'cp' that matches...
   4711  1.2  christos  *   *pchar / "/" if allow_qchars is false, or
   4712  1.2  christos  *   *(pchar / "/" / "?") if allow_qchars is true.
   4713  1.2  christos  */
   4714  1.2  christos static char *
   4715  1.2  christos end_of_path(const char *cp, enum uri_part part, unsigned flags)
   4716  1.2  christos {
   4717  1.2  christos 	if (flags & EVHTTP_URI_NONCONFORMANT) {
   4718  1.2  christos 		/* If NONCONFORMANT:
   4719  1.2  christos 		 *   Path is everything up to a # or ? or nul.
   4720  1.2  christos 		 *   Query is everything up a # or nul
   4721  1.2  christos 		 *   Fragment is everything up to a nul.
   4722  1.2  christos 		 */
   4723  1.2  christos 		switch (part) {
   4724  1.2  christos 		case PART_PATH:
   4725  1.2  christos 			while (*cp && *cp != '#' && *cp != '?')
   4726  1.2  christos 				++cp;
   4727  1.2  christos 			break;
   4728  1.2  christos 		case PART_QUERY:
   4729  1.2  christos 			while (*cp && *cp != '#')
   4730  1.2  christos 				++cp;
   4731  1.2  christos 			break;
   4732  1.2  christos 		case PART_FRAGMENT:
   4733  1.2  christos 			cp += strlen(cp);
   4734  1.2  christos 			break;
   4735  1.2  christos 		};
   4736  1.2  christos 		return __UNCONST(cp);
   4737  1.2  christos 	}
   4738  1.2  christos 
   4739  1.2  christos 	while (*cp) {
   4740  1.2  christos 		if (CHAR_IS_UNRESERVED(*cp) ||
   4741  1.2  christos 		    strchr(SUBDELIMS, *cp) ||
   4742  1.2  christos 		    *cp == ':' || *cp == '@' || *cp == '/')
   4743  1.2  christos 			++cp;
   4744  1.4  christos 		else if (*cp == '%' && EVUTIL_ISXDIGIT_(cp[1]) &&
   4745  1.4  christos 		    EVUTIL_ISXDIGIT_(cp[2]))
   4746  1.2  christos 			cp += 3;
   4747  1.2  christos 		else if (*cp == '?' && part != PART_PATH)
   4748  1.2  christos 			++cp;
   4749  1.2  christos 		else
   4750  1.2  christos 			return __UNCONST(cp);
   4751  1.2  christos 	}
   4752  1.2  christos 	return __UNCONST(cp);
   4753  1.2  christos }
   4754  1.2  christos 
   4755  1.2  christos static int
   4756  1.2  christos path_matches_noscheme(const char *cp)
   4757  1.2  christos {
   4758  1.2  christos 	while (*cp) {
   4759  1.2  christos 		if (*cp == ':')
   4760  1.2  christos 			return 0;
   4761  1.2  christos 		else if (*cp == '/')
   4762  1.2  christos 			return 1;
   4763  1.2  christos 		++cp;
   4764  1.2  christos 	}
   4765  1.2  christos 	return 1;
   4766  1.2  christos }
   4767  1.2  christos 
   4768  1.2  christos struct evhttp_uri *
   4769  1.2  christos evhttp_uri_parse(const char *source_uri)
   4770  1.2  christos {
   4771  1.2  christos 	return evhttp_uri_parse_with_flags(source_uri, 0);
   4772  1.2  christos }
   4773  1.2  christos 
   4774  1.2  christos struct evhttp_uri *
   4775  1.2  christos evhttp_uri_parse_with_flags(const char *source_uri, unsigned flags)
   4776  1.2  christos {
   4777  1.2  christos 	char *readbuf = NULL, *readp = NULL, *token = NULL, *query = NULL;
   4778  1.2  christos 	char *path = NULL, *fragment = NULL;
   4779  1.2  christos 	int got_authority = 0;
   4780  1.2  christos 
   4781  1.2  christos 	struct evhttp_uri *uri = mm_calloc(1, sizeof(struct evhttp_uri));
   4782  1.2  christos 	if (uri == NULL) {
   4783  1.2  christos 		event_warn("%s: calloc", __func__);
   4784  1.2  christos 		goto err;
   4785  1.2  christos 	}
   4786  1.2  christos 	uri->port = -1;
   4787  1.2  christos 	uri->flags = flags;
   4788  1.2  christos 
   4789  1.2  christos 	readbuf = mm_strdup(source_uri);
   4790  1.2  christos 	if (readbuf == NULL) {
   4791  1.2  christos 		event_warn("%s: strdup", __func__);
   4792  1.2  christos 		goto err;
   4793  1.2  christos 	}
   4794  1.2  christos 
   4795  1.2  christos 	readp = readbuf;
   4796  1.2  christos 	token = NULL;
   4797  1.2  christos 
   4798  1.2  christos 	/* We try to follow RFC3986 here as much as we can, and match
   4799  1.2  christos 	   the productions
   4800  1.2  christos 
   4801  1.2  christos 	      URI = scheme ":" hier-part [ "?" query ] [ "#" fragment ]
   4802  1.2  christos 
   4803  1.2  christos 	      relative-ref  = relative-part [ "?" query ] [ "#" fragment ]
   4804  1.2  christos 	 */
   4805  1.2  christos 
   4806  1.2  christos 	/* 1. scheme: */
   4807  1.2  christos 	token = strchr(readp, ':');
   4808  1.2  christos 	if (token && scheme_ok(readp,token)) {
   4809  1.2  christos 		*token = '\0';
   4810  1.2  christos 		uri->scheme = mm_strdup(readp);
   4811  1.2  christos 		if (uri->scheme == NULL) {
   4812  1.2  christos 			event_warn("%s: strdup", __func__);
   4813  1.2  christos 			goto err;
   4814  1.2  christos 		}
   4815  1.2  christos 		readp = token+1; /* eat : */
   4816  1.2  christos 	}
   4817  1.2  christos 
   4818  1.2  christos 	/* 2. Optionally, "//" then an 'authority' part. */
   4819  1.2  christos 	if (readp[0]=='/' && readp[1] == '/') {
   4820  1.2  christos 		char *authority;
   4821  1.2  christos 		readp += 2;
   4822  1.2  christos 		authority = readp;
   4823  1.2  christos 		path = end_of_authority(readp);
   4824  1.2  christos 		if (parse_authority(uri, authority, path) < 0)
   4825  1.2  christos 			goto err;
   4826  1.2  christos 		readp = path;
   4827  1.2  christos 		got_authority = 1;
   4828  1.2  christos 	}
   4829  1.2  christos 
   4830  1.2  christos 	/* 3. Query: path-abempty, path-absolute, path-rootless, or path-empty
   4831  1.2  christos 	 */
   4832  1.2  christos 	path = readp;
   4833  1.2  christos 	readp = end_of_path(path, PART_PATH, flags);
   4834  1.2  christos 
   4835  1.2  christos 	/* Query */
   4836  1.2  christos 	if (*readp == '?') {
   4837  1.2  christos 		*readp = '\0';
   4838  1.2  christos 		++readp;
   4839  1.2  christos 		query = readp;
   4840  1.2  christos 		readp = end_of_path(readp, PART_QUERY, flags);
   4841  1.2  christos 	}
   4842  1.2  christos 	/* fragment */
   4843  1.2  christos 	if (*readp == '#') {
   4844  1.2  christos 		*readp = '\0';
   4845  1.2  christos 		++readp;
   4846  1.2  christos 		fragment = readp;
   4847  1.2  christos 		readp = end_of_path(readp, PART_FRAGMENT, flags);
   4848  1.2  christos 	}
   4849  1.2  christos 	if (*readp != '\0') {
   4850  1.2  christos 		goto err;
   4851  1.2  christos 	}
   4852  1.2  christos 
   4853  1.2  christos 	/* These next two cases may be unreachable; I'm leaving them
   4854  1.2  christos 	 * in to be defensive. */
   4855  1.2  christos 	/* If you didn't get an authority, the path can't begin with "//" */
   4856  1.2  christos 	if (!got_authority && path[0]=='/' && path[1]=='/')
   4857  1.2  christos 		goto err;
   4858  1.2  christos 	/* If you did get an authority, the path must begin with "/" or be
   4859  1.2  christos 	 * empty. */
   4860  1.2  christos 	if (got_authority && path[0] != '/' && path[0] != '\0')
   4861  1.2  christos 		goto err;
   4862  1.2  christos 	/* (End of maybe-unreachable cases) */
   4863  1.2  christos 
   4864  1.2  christos 	/* If there was no scheme, the first part of the path (if any) must
   4865  1.2  christos 	 * have no colon in it. */
   4866  1.2  christos 	if (! uri->scheme && !path_matches_noscheme(path))
   4867  1.2  christos 		goto err;
   4868  1.2  christos 
   4869  1.2  christos 	EVUTIL_ASSERT(path);
   4870  1.2  christos 	uri->path = mm_strdup(path);
   4871  1.2  christos 	if (uri->path == NULL) {
   4872  1.2  christos 		event_warn("%s: strdup", __func__);
   4873  1.2  christos 		goto err;
   4874  1.1    plunky 	}
   4875  1.1    plunky 
   4876  1.2  christos 	if (query) {
   4877  1.2  christos 		uri->query = mm_strdup(query);
   4878  1.2  christos 		if (uri->query == NULL) {
   4879  1.2  christos 			event_warn("%s: strdup", __func__);
   4880  1.2  christos 			goto err;
   4881  1.2  christos 		}
   4882  1.2  christos 	}
   4883  1.2  christos 	if (fragment) {
   4884  1.2  christos 		uri->fragment = mm_strdup(fragment);
   4885  1.2  christos 		if (uri->fragment == NULL) {
   4886  1.2  christos 			event_warn("%s: strdup", __func__);
   4887  1.2  christos 			goto err;
   4888  1.1    plunky 		}
   4889  1.2  christos 	}
   4890  1.2  christos 
   4891  1.2  christos 	mm_free(readbuf);
   4892  1.2  christos 
   4893  1.2  christos 	return uri;
   4894  1.2  christos err:
   4895  1.2  christos 	if (uri)
   4896  1.2  christos 		evhttp_uri_free(uri);
   4897  1.2  christos 	if (readbuf)
   4898  1.2  christos 		mm_free(readbuf);
   4899  1.2  christos 	return NULL;
   4900  1.2  christos }
   4901  1.2  christos 
   4902  1.5  christos static struct evhttp_uri *
   4903  1.5  christos evhttp_uri_parse_authority(char *source_uri)
   4904  1.5  christos {
   4905  1.5  christos 	struct evhttp_uri *uri = mm_calloc(1, sizeof(struct evhttp_uri));
   4906  1.5  christos 	char *end;
   4907  1.5  christos 
   4908  1.5  christos 	if (uri == NULL) {
   4909  1.5  christos 		event_warn("%s: calloc", __func__);
   4910  1.5  christos 		goto err;
   4911  1.5  christos 	}
   4912  1.5  christos 	uri->port = -1;
   4913  1.5  christos 	uri->flags = 0;
   4914  1.5  christos 
   4915  1.5  christos 	end = end_of_authority(source_uri);
   4916  1.5  christos 	if (parse_authority(uri, source_uri, end) < 0)
   4917  1.5  christos 		goto err;
   4918  1.5  christos 
   4919  1.5  christos 	uri->path = mm_strdup("");
   4920  1.5  christos 	if (uri->path == NULL) {
   4921  1.5  christos 		event_warn("%s: strdup", __func__);
   4922  1.5  christos 		goto err;
   4923  1.5  christos 	}
   4924  1.5  christos 
   4925  1.5  christos 	return uri;
   4926  1.5  christos err:
   4927  1.5  christos 	if (uri)
   4928  1.5  christos 		evhttp_uri_free(uri);
   4929  1.5  christos 	return NULL;
   4930  1.5  christos }
   4931  1.5  christos 
   4932  1.2  christos void
   4933  1.2  christos evhttp_uri_free(struct evhttp_uri *uri)
   4934  1.2  christos {
   4935  1.4  christos #define URI_FREE_STR_(f)		\
   4936  1.2  christos 	if (uri->f) {			\
   4937  1.2  christos 		mm_free(uri->f);		\
   4938  1.2  christos 	}
   4939  1.2  christos 
   4940  1.4  christos 	URI_FREE_STR_(scheme);
   4941  1.4  christos 	URI_FREE_STR_(userinfo);
   4942  1.4  christos 	URI_FREE_STR_(host);
   4943  1.4  christos 	URI_FREE_STR_(path);
   4944  1.4  christos 	URI_FREE_STR_(query);
   4945  1.4  christos 	URI_FREE_STR_(fragment);
   4946  1.2  christos 
   4947  1.2  christos 	mm_free(uri);
   4948  1.4  christos #undef URI_FREE_STR_
   4949  1.2  christos }
   4950  1.2  christos 
   4951  1.2  christos char *
   4952  1.2  christos evhttp_uri_join(struct evhttp_uri *uri, char *buf, size_t limit)
   4953  1.2  christos {
   4954  1.2  christos 	struct evbuffer *tmp = 0;
   4955  1.2  christos 	size_t joined_size = 0;
   4956  1.2  christos 	char *output = NULL;
   4957  1.2  christos 
   4958  1.4  christos #define URI_ADD_(f)	evbuffer_add(tmp, uri->f, strlen(uri->f))
   4959  1.2  christos 
   4960  1.2  christos 	if (!uri || !buf || !limit)
   4961  1.2  christos 		return NULL;
   4962  1.2  christos 
   4963  1.2  christos 	tmp = evbuffer_new();
   4964  1.2  christos 	if (!tmp)
   4965  1.2  christos 		return NULL;
   4966  1.2  christos 
   4967  1.2  christos 	if (uri->scheme) {
   4968  1.4  christos 		URI_ADD_(scheme);
   4969  1.2  christos 		evbuffer_add(tmp, ":", 1);
   4970  1.2  christos 	}
   4971  1.2  christos 	if (uri->host) {
   4972  1.2  christos 		evbuffer_add(tmp, "//", 2);
   4973  1.2  christos 		if (uri->userinfo)
   4974  1.2  christos 			evbuffer_add_printf(tmp,"%s@", uri->userinfo);
   4975  1.4  christos 		URI_ADD_(host);
   4976  1.2  christos 		if (uri->port >= 0)
   4977  1.2  christos 			evbuffer_add_printf(tmp,":%d", uri->port);
   4978  1.2  christos 
   4979  1.2  christos 		if (uri->path && uri->path[0] != '/' && uri->path[0] != '\0')
   4980  1.2  christos 			goto err;
   4981  1.2  christos 	}
   4982  1.2  christos 
   4983  1.2  christos 	if (uri->path)
   4984  1.4  christos 		URI_ADD_(path);
   4985  1.2  christos 
   4986  1.2  christos 	if (uri->query) {
   4987  1.2  christos 		evbuffer_add(tmp, "?", 1);
   4988  1.4  christos 		URI_ADD_(query);
   4989  1.2  christos 	}
   4990  1.2  christos 
   4991  1.2  christos 	if (uri->fragment) {
   4992  1.2  christos 		evbuffer_add(tmp, "#", 1);
   4993  1.4  christos 		URI_ADD_(fragment);
   4994  1.2  christos 	}
   4995  1.2  christos 
   4996  1.2  christos 	evbuffer_add(tmp, "\0", 1); /* NUL */
   4997  1.2  christos 
   4998  1.2  christos 	joined_size = evbuffer_get_length(tmp);
   4999  1.2  christos 
   5000  1.2  christos 	if (joined_size > limit) {
   5001  1.2  christos 		/* It doesn't fit. */
   5002  1.2  christos 		evbuffer_free(tmp);
   5003  1.2  christos 		return NULL;
   5004  1.2  christos 	}
   5005  1.2  christos        	evbuffer_remove(tmp, buf, joined_size);
   5006  1.2  christos 
   5007  1.2  christos 	output = buf;
   5008  1.2  christos err:
   5009  1.2  christos 	evbuffer_free(tmp);
   5010  1.2  christos 
   5011  1.2  christos 	return output;
   5012  1.4  christos #undef URI_ADD_
   5013  1.2  christos }
   5014  1.2  christos 
   5015  1.2  christos const char *
   5016  1.2  christos evhttp_uri_get_scheme(const struct evhttp_uri *uri)
   5017  1.2  christos {
   5018  1.2  christos 	return uri->scheme;
   5019  1.2  christos }
   5020  1.2  christos const char *
   5021  1.2  christos evhttp_uri_get_userinfo(const struct evhttp_uri *uri)
   5022  1.2  christos {
   5023  1.2  christos 	return uri->userinfo;
   5024  1.2  christos }
   5025  1.2  christos const char *
   5026  1.2  christos evhttp_uri_get_host(const struct evhttp_uri *uri)
   5027  1.2  christos {
   5028  1.2  christos 	return uri->host;
   5029  1.2  christos }
   5030  1.2  christos int
   5031  1.2  christos evhttp_uri_get_port(const struct evhttp_uri *uri)
   5032  1.2  christos {
   5033  1.2  christos 	return uri->port;
   5034  1.2  christos }
   5035  1.2  christos const char *
   5036  1.2  christos evhttp_uri_get_path(const struct evhttp_uri *uri)
   5037  1.2  christos {
   5038  1.2  christos 	return uri->path;
   5039  1.2  christos }
   5040  1.2  christos const char *
   5041  1.2  christos evhttp_uri_get_query(const struct evhttp_uri *uri)
   5042  1.2  christos {
   5043  1.2  christos 	return uri->query;
   5044  1.2  christos }
   5045  1.2  christos const char *
   5046  1.2  christos evhttp_uri_get_fragment(const struct evhttp_uri *uri)
   5047  1.2  christos {
   5048  1.2  christos 	return uri->fragment;
   5049  1.2  christos }
   5050  1.2  christos 
   5051  1.4  christos #define URI_SET_STR_(f) do {					\
   5052  1.2  christos 	if (uri->f)						\
   5053  1.2  christos 		mm_free(uri->f);				\
   5054  1.2  christos 	if (f) {						\
   5055  1.2  christos 		if ((uri->f = mm_strdup(f)) == NULL) {		\
   5056  1.2  christos 			event_warn("%s: strdup()", __func__);	\
   5057  1.2  christos 			return -1;				\
   5058  1.2  christos 		}						\
   5059  1.2  christos 	} else {						\
   5060  1.2  christos 		uri->f = NULL;					\
   5061  1.2  christos 	}							\
   5062  1.2  christos 	} while(0)
   5063  1.2  christos 
   5064  1.2  christos int
   5065  1.2  christos evhttp_uri_set_scheme(struct evhttp_uri *uri, const char *scheme)
   5066  1.2  christos {
   5067  1.2  christos 	if (scheme && !scheme_ok(scheme, scheme+strlen(scheme)))
   5068  1.2  christos 		return -1;
   5069  1.2  christos 
   5070  1.4  christos 	URI_SET_STR_(scheme);
   5071  1.2  christos 	return 0;
   5072  1.2  christos }
   5073  1.2  christos int
   5074  1.2  christos evhttp_uri_set_userinfo(struct evhttp_uri *uri, const char *userinfo)
   5075  1.2  christos {
   5076  1.2  christos 	if (userinfo && !userinfo_ok(userinfo, userinfo+strlen(userinfo)))
   5077  1.2  christos 		return -1;
   5078  1.4  christos 	URI_SET_STR_(userinfo);
   5079  1.2  christos 	return 0;
   5080  1.2  christos }
   5081  1.2  christos int
   5082  1.2  christos evhttp_uri_set_host(struct evhttp_uri *uri, const char *host)
   5083  1.2  christos {
   5084  1.2  christos 	if (host) {
   5085  1.2  christos 		if (host[0] == '[') {
   5086  1.2  christos 			if (! bracket_addr_ok(host, host+strlen(host)))
   5087  1.2  christos 				return -1;
   5088  1.2  christos 		} else {
   5089  1.2  christos 			if (! regname_ok(host, host+strlen(host)))
   5090  1.2  christos 				return -1;
   5091  1.1    plunky 		}
   5092  1.1    plunky 	}
   5093  1.1    plunky 
   5094  1.4  christos 	URI_SET_STR_(host);
   5095  1.2  christos 	return 0;
   5096  1.2  christos }
   5097  1.2  christos int
   5098  1.2  christos evhttp_uri_set_port(struct evhttp_uri *uri, int port)
   5099  1.2  christos {
   5100  1.2  christos 	if (port < -1)
   5101  1.2  christos 		return -1;
   5102  1.2  christos 	uri->port = port;
   5103  1.2  christos 	return 0;
   5104  1.2  christos }
   5105  1.2  christos #define end_of_cpath(cp,p,f) \
   5106  1.2  christos 	((const char*)(end_of_path(((const char*)(cp)), (p), (f))))
   5107  1.1    plunky 
   5108  1.2  christos int
   5109  1.2  christos evhttp_uri_set_path(struct evhttp_uri *uri, const char *path)
   5110  1.2  christos {
   5111  1.2  christos 	if (path && end_of_cpath(path, PART_PATH, uri->flags) != path+strlen(path))
   5112  1.2  christos 		return -1;
   5113  1.1    plunky 
   5114  1.4  christos 	URI_SET_STR_(path);
   5115  1.2  christos 	return 0;
   5116  1.2  christos }
   5117  1.2  christos int
   5118  1.2  christos evhttp_uri_set_query(struct evhttp_uri *uri, const char *query)
   5119  1.2  christos {
   5120  1.2  christos 	if (query && end_of_cpath(query, PART_QUERY, uri->flags) != query+strlen(query))
   5121  1.2  christos 		return -1;
   5122  1.4  christos 	URI_SET_STR_(query);
   5123  1.2  christos 	return 0;
   5124  1.2  christos }
   5125  1.2  christos int
   5126  1.2  christos evhttp_uri_set_fragment(struct evhttp_uri *uri, const char *fragment)
   5127  1.2  christos {
   5128  1.2  christos 	if (fragment && end_of_cpath(fragment, PART_FRAGMENT, uri->flags) != fragment+strlen(fragment))
   5129  1.2  christos 		return -1;
   5130  1.4  christos 	URI_SET_STR_(fragment);
   5131  1.2  christos 	return 0;
   5132  1.1    plunky }
   5133