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