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