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