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