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