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