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