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