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