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