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