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