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