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