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