15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Copyright (c) 2002-2006 Niels Provos <provos@citi.umich.edu> 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * All rights reserved. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Redistribution and use in source and binary forms, with or without 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * modification, are permitted provided that the following conditions 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * are met: 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 1. Redistributions of source code must retain the above copyright 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * notice, this list of conditions and the following disclaimer. 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 2. Redistributions in binary form must reproduce the above copyright 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * notice, this list of conditions and the following disclaimer in the 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * documentation and/or other materials provided with the distribution. 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 3. The name of the author may not be used to endorse or promote products 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * derived from this software without specific prior written permission. 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef HAVE_CONFIG_H 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "config.h" 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef HAVE_SYS_PARAM_H 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/param.h> 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef HAVE_SYS_TYPES_H 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/types.h> 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef HAVE_SYS_TIME_H 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/time.h> 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef HAVE_SYS_IOCCOM_H 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/ioccom.h> 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef WIN32 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/resource.h> 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/socket.h> 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/stat.h> 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/wait.h> 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/queue.h> 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef WIN32 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <netinet/in.h> 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <netdb.h> 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef WIN32 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <winsock2.h> 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <assert.h> 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <ctype.h> 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <errno.h> 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stdio.h> 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stdlib.h> 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string.h> 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef WIN32 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <syslog.h> 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <signal.h> 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <time.h> 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef HAVE_UNISTD_H 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <unistd.h> 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef HAVE_FCNTL_H 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <fcntl.h> 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#undef timeout_pending 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#undef timeout_initialized 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "strlcpy-internal.h" 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "event.h" 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "evhttp.h" 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "evutil.h" 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "log.h" 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "http-internal.h" 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef WIN32 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define strcasecmp _stricmp 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define strncasecmp _strnicmp 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define strdup _strdup 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef HAVE_GETNAMEINFO 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define NI_MAXSERV 32 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define NI_MAXHOST 1025 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define NI_NUMERICHOST 1 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define NI_NUMERICSERV 2 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)fake_getnameinfo(const struct sockaddr *sa, size_t salen, char *host, 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t hostlen, char *serv, size_t servlen, int flags) 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct sockaddr_in *sin = (struct sockaddr_in *)sa; 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (serv != NULL) { 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char tmpserv[16]; 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evutil_snprintf(tmpserv, sizeof(tmpserv), 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "%d", ntohs(sin->sin_port)); 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (strlcpy(serv, tmpserv, servlen) >= servlen) 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (-1); 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (host != NULL) { 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (flags & NI_NUMERICHOST) { 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (strlcpy(host, inet_ntoa(sin->sin_addr), 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hostlen) >= hostlen) 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (-1); 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (0); 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct hostent *hp; 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hp = gethostbyaddr((char *)&sin->sin_addr, 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sizeof(struct in_addr), AF_INET); 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (hp == NULL) 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (-2); 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (strlcpy(host, hp->h_name, hostlen) >= hostlen) 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (-1); 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (0); 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (0); 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef HAVE_GETADDRINFO 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct addrinfo { 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int ai_family; 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int ai_socktype; 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int ai_protocol; 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t ai_addrlen; 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct sockaddr *ai_addr; 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct addrinfo *ai_next; 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)fake_getaddrinfo(const char *hostname, struct addrinfo *ai) 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct hostent *he = NULL; 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct sockaddr_in *sa; 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (hostname) { 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) he = gethostbyname(hostname); 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!he) 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (-1); 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ai->ai_family = he ? he->h_addrtype : AF_INET; 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ai->ai_socktype = SOCK_STREAM; 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ai->ai_protocol = 0; 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ai->ai_addrlen = sizeof(struct sockaddr_in); 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (NULL == (ai->ai_addr = malloc(ai->ai_addrlen))) 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (-1); 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sa = (struct sockaddr_in*)ai->ai_addr; 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memset(sa, 0, ai->ai_addrlen); 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (he) { 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sa->sin_family = he->h_addrtype; 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memcpy(&sa->sin_addr, he->h_addr_list[0], he->h_length); 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sa->sin_family = AF_INET; 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sa->sin_addr.s_addr = INADDR_ANY; 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ai->ai_next = NULL; 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (0); 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)fake_freeaddrinfo(struct addrinfo *ai) 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free(ai->ai_addr); 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef MIN 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define MIN(a,b) (((a)<(b))?(a):(b)) 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* wrapper for setting the base from the http server */ 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define EVHTTP_BASE_SET(x, y) do { \ 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((x)->base != NULL) event_base_set((x)->base, y); \ 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} while (0) 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)extern int debug; 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int socket_connect(int fd, const char *address, unsigned short port); 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int bind_socket_ai(struct addrinfo *, int reuse); 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int bind_socket(const char *, u_short, int reuse); 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void name_from_addr(struct sockaddr *, socklen_t, char **, char **); 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int evhttp_associate_new_request_with_connection( 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct evhttp_connection *evcon); 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void evhttp_connection_start_detectclose( 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct evhttp_connection *evcon); 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void evhttp_connection_stop_detectclose( 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct evhttp_connection *evcon); 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void evhttp_request_dispatch(struct evhttp_connection* evcon); 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void evhttp_read_firstline(struct evhttp_connection *evcon, 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct evhttp_request *req); 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void evhttp_read_header(struct evhttp_connection *evcon, 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct evhttp_request *req); 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int evhttp_add_header_internal(struct evkeyvalq *headers, 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char *key, const char *value); 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int evhttp_decode_uri_internal(const char *uri, size_t length, 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char *ret, int always_decode_plus); 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void evhttp_read(int, short, void *); 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void evhttp_write(int, short, void *); 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef HAVE_STRSEP 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* strsep replacement for platforms that lack it. Only works if 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * del is one character long. */ 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static char * 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)strsep(char **s, const char *del) 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char *d, *tok; 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert(strlen(del) == 1); 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!s || !*s) 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tok = *s; 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) d = strstr(tok, del); 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (d) { 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *d = '\0'; 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *s = d + 1; 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *s = NULL; 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return tok; 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const char * 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)html_replace(char ch, char *buf) 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (ch) { 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case '<': 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "<"; 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case '>': 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ">"; 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case '"': 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return """; 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case '\'': 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "'"; 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case '&': 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "&"; 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Echo the character back */ 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buf[0] = ch; 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buf[1] = '\0'; 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return buf; 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Replaces <, >, ", ' and & with <, >, ", 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * ' and & correspondingly. 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The returned string needs to be freed by the caller. 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)char * 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)evhttp_htmlescape(const char *html) 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int i, new_size = 0, old_size = strlen(html); 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char *escaped_html, *p; 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char scratch_space[2]; 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (i = 0; i < old_size; ++i) 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new_size += strlen(html_replace(html[i], scratch_space)); 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) p = escaped_html = malloc(new_size + 1); 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (escaped_html == NULL) 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event_err(1, "%s: malloc(%d)", __func__, new_size + 1); 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (i = 0; i < old_size; ++i) { 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char *replaced = html_replace(html[i], scratch_space); 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* this is length checked */ 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) strcpy(p, replaced); 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) p += strlen(replaced); 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *p = '\0'; 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (escaped_html); 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const char * 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)evhttp_method(enum evhttp_cmd_type type) 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char *method; 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (type) { 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case EVHTTP_REQ_GET: 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) method = "GET"; 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case EVHTTP_REQ_POST: 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) method = "POST"; 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case EVHTTP_REQ_HEAD: 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) method = "HEAD"; 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) method = NULL; 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (method); 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)evhttp_add_event(struct event *ev, int timeout, int default_timeout) 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (timeout != 0) { 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct timeval tv; 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evutil_timerclear(&tv); 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tv.tv_sec = timeout != -1 ? timeout : default_timeout; 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event_add(ev, &tv); 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event_add(ev, NULL); 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)evhttp_write_buffer(struct evhttp_connection *evcon, 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void (*cb)(struct evhttp_connection *, void *), void *arg) 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event_debug(("%s: preparing to write buffer\n", __func__)); 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Set call back */ 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evcon->cb = cb; 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evcon->cb_arg = arg; 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* check if the event is already pending */ 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (event_pending(&evcon->ev, EV_WRITE|EV_TIMEOUT, NULL)) 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event_del(&evcon->ev); 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event_set(&evcon->ev, evcon->fd, EV_WRITE, evhttp_write, evcon); 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EVHTTP_BASE_SET(evcon, &evcon->ev); 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evhttp_add_event(&evcon->ev, evcon->timeout, HTTP_WRITE_TIMEOUT); 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)evhttp_connected(struct evhttp_connection *evcon) 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (evcon->state) { 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case EVCON_DISCONNECTED: 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case EVCON_CONNECTING: 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (0); 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case EVCON_IDLE: 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case EVCON_READING_FIRSTLINE: 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case EVCON_READING_HEADERS: 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case EVCON_READING_BODY: 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case EVCON_READING_TRAILER: 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case EVCON_WRITING: 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (1); 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Create the headers needed for an HTTP request 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)evhttp_make_header_request(struct evhttp_connection *evcon, 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct evhttp_request *req) 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char *method; 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evhttp_remove_header(req->output_headers, "Proxy-Connection"); 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Generate request line */ 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) method = evhttp_method(req->type); 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evbuffer_add_printf(evcon->output_buffer, "%s %s HTTP/%d.%d\r\n", 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) method, req->uri, req->major, req->minor); 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Add the content length on a post request if missing */ 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (req->type == EVHTTP_REQ_POST && 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evhttp_find_header(req->output_headers, "Content-Length") == NULL){ 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char size[12]; 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evutil_snprintf(size, sizeof(size), "%ld", 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (long)EVBUFFER_LENGTH(req->output_buffer)); 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evhttp_add_header(req->output_headers, "Content-Length", size); 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)evhttp_is_connection_close(int flags, struct evkeyvalq* headers) 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (flags & EVHTTP_PROXY_REQUEST) { 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* proxy connection */ 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char *connection = evhttp_find_header(headers, "Proxy-Connection"); 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (connection == NULL || strcasecmp(connection, "keep-alive") != 0); 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char *connection = evhttp_find_header(headers, "Connection"); 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (connection != NULL && strcasecmp(connection, "close") == 0); 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)evhttp_is_connection_keepalive(struct evkeyvalq* headers) 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char *connection = evhttp_find_header(headers, "Connection"); 4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (connection != NULL 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) && strncasecmp(connection, "keep-alive", 10) == 0); 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)evhttp_maybe_add_date_header(struct evkeyvalq *headers) 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (evhttp_find_header(headers, "Date") == NULL) { 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char date[50]; 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef WIN32 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct tm cur; 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct tm *cur_p; 4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) time_t t = time(NULL); 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef WIN32 4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cur_p = gmtime(&t); 4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gmtime_r(&t, &cur); 4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cur_p = &cur; 4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (strftime(date, sizeof(date), 4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "%a, %d %b %Y %H:%M:%S GMT", cur_p) != 0) { 4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evhttp_add_header(headers, "Date", date); 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void 4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)evhttp_maybe_add_content_length_header(struct evkeyvalq *headers, 4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) long content_length) 4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (evhttp_find_header(headers, "Transfer-Encoding") == NULL && 4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evhttp_find_header(headers, "Content-Length") == NULL) { 4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char len[12]; 4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evutil_snprintf(len, sizeof(len), "%ld", content_length); 4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evhttp_add_header(headers, "Content-Length", len); 4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Create the headers needed for an HTTP reply 4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void 4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)evhttp_make_header_response(struct evhttp_connection *evcon, 4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct evhttp_request *req) 4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int is_keepalive = evhttp_is_connection_keepalive(req->input_headers); 4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evbuffer_add_printf(evcon->output_buffer, "HTTP/%d.%d %d %s\r\n", 4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req->major, req->minor, req->response_code, 4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req->response_code_line); 4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (req->major == 1) { 4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (req->minor == 1) 4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evhttp_maybe_add_date_header(req->output_headers); 4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* 4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * if the protocol is 1.0; and the connection was keep-alive 4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * we need to add a keep-alive header, too. 4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (req->minor == 0 && is_keepalive) 4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evhttp_add_header(req->output_headers, 4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Connection", "keep-alive"); 4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (req->minor == 1 || is_keepalive) { 4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* 4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * we need to add the content length if the 4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * user did not give it, this is required for 4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * persistent connections to work. 4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evhttp_maybe_add_content_length_header( 4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req->output_headers, 4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (long)EVBUFFER_LENGTH(req->output_buffer)); 4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Potentially add headers for unidentified content. */ 4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (EVBUFFER_LENGTH(req->output_buffer)) { 4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (evhttp_find_header(req->output_headers, 4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Content-Type") == NULL) { 4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evhttp_add_header(req->output_headers, 4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Content-Type", "text/html; charset=ISO-8859-1"); 4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* if the request asked for a close, we send a close, too */ 5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (evhttp_is_connection_close(req->flags, req->input_headers)) { 5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evhttp_remove_header(req->output_headers, "Connection"); 5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!(req->flags & EVHTTP_PROXY_REQUEST)) 5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evhttp_add_header(req->output_headers, "Connection", "close"); 5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evhttp_remove_header(req->output_headers, "Proxy-Connection"); 5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void 5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)evhttp_make_header(struct evhttp_connection *evcon, struct evhttp_request *req) 5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct evkeyval *header; 5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* 5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Depending if this is a HTTP request or response, we might need to 5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * add some new headers or remove existing headers. 5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (req->kind == EVHTTP_REQUEST) { 5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evhttp_make_header_request(evcon, req); 5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evhttp_make_header_response(evcon, req); 5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TAILQ_FOREACH(header, req->output_headers, next) { 5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evbuffer_add_printf(evcon->output_buffer, "%s: %s\r\n", 5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) header->key, header->value); 5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evbuffer_add(evcon->output_buffer, "\r\n", 2); 5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (EVBUFFER_LENGTH(req->output_buffer) > 0) { 5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* 5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * For a request, we add the POST data, for a reply, this 5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * is the regular data. 5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evbuffer_add_buffer(evcon->output_buffer, req->output_buffer); 5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Separated host, port and file from URI */ 5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int 5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)evhttp_hostportfile(char *url, char **phost, u_short *pport, char **pfile) 5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* XXX not threadsafe. */ 5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static char host[1024]; 5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static char file[1024]; 5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char *p; 5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char *p2; 5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int len; 5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) u_short port; 5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) len = strlen(HTTP_PREFIX); 5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (strncasecmp(url, HTTP_PREFIX, len)) 5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (-1); 5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url += len; 5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* We might overrun */ 5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (strlcpy(host, url, sizeof (host)) >= sizeof(host)) 5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (-1); 5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) p = strchr(host, '/'); 5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (p != NULL) { 5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *p = '\0'; 5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) p2 = p + 1; 5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else 5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) p2 = NULL; 5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (pfile != NULL) { 5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Generate request file */ 5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (p2 == NULL) 5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) p2 = ""; 5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evutil_snprintf(file, sizeof(file), "/%s", p2); 5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) p = strchr(host, ':'); 5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (p != NULL) { 5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *p = '\0'; 5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) port = atoi(p + 1); 5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (port == 0) 5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (-1); 5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else 5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) port = HTTP_DEFAULTPORT; 5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (phost != NULL) 5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *phost = host; 5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (pport != NULL) 5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *pport = port; 5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (pfile != NULL) 5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *pfile = file; 5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (0); 5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int 5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)evhttp_connection_incoming_fail(struct evhttp_request *req, 6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) enum evhttp_connection_error error) 6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (error) { 6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case EVCON_HTTP_TIMEOUT: 6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case EVCON_HTTP_EOF: 6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* 6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * these are cases in which we probably should just 6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * close the connection and not send a reply. this 6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * case may happen when a browser keeps a persistent 6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * connection open and we timeout on the read. 6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (-1); 6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case EVCON_HTTP_INVALID_HEADER: 6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: /* xxx: probably should just error on default */ 6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* the callback looks at the uri to determine errors */ 6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (req->uri) { 6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free(req->uri); 6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req->uri = NULL; 6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* 6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * the callback needs to send a reply, once the reply has 6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * been send, the connection should get freed. 6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (*req->cb)(req, req->cb_arg); 6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (0); 6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void 6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)evhttp_connection_fail(struct evhttp_connection *evcon, 6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) enum evhttp_connection_error error) 6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct evhttp_request* req = TAILQ_FIRST(&evcon->requests); 6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void (*cb)(struct evhttp_request *, void *); 6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void *cb_arg; 6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert(req != NULL); 6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (evcon->flags & EVHTTP_CON_INCOMING) { 6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* 6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * for incoming requests, there are two different 6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * failure cases. it's either a network level error 6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * or an http layer error. for problems on the network 6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * layer like timeouts we just drop the connections. 6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * For HTTP problems, we might have to send back a 6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * reply before the connection can be freed. 6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (evhttp_connection_incoming_fail(req, error) == -1) 6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evhttp_connection_free(evcon); 6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* save the callback for later; the cb might free our object */ 6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cb = req->cb; 6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cb_arg = req->cb_arg; 6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TAILQ_REMOVE(&evcon->requests, req, next); 6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evhttp_request_free(req); 6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* xxx: maybe we should fail all requests??? */ 6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* reset the connection */ 6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evhttp_connection_reset(evcon); 6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* We are trying the next request that was queued on us */ 6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (TAILQ_FIRST(&evcon->requests) != NULL) 6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evhttp_connection_connect(evcon); 6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* inform the user */ 6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (cb != NULL) 6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (*cb)(NULL, cb_arg); 6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void 6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)evhttp_write(int fd, short what, void *arg) 6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct evhttp_connection *evcon = arg; 6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int n; 6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (what == EV_TIMEOUT) { 6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evhttp_connection_fail(evcon, EVCON_HTTP_TIMEOUT); 6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) n = evbuffer_write(evcon->output_buffer, fd); 6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (n == -1) { 6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event_debug(("%s: evbuffer_write", __func__)); 6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evhttp_connection_fail(evcon, EVCON_HTTP_EOF); 6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (n == 0) { 6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event_debug(("%s: write nothing", __func__)); 6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evhttp_connection_fail(evcon, EVCON_HTTP_EOF); 6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (EVBUFFER_LENGTH(evcon->output_buffer) != 0) { 6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evhttp_add_event(&evcon->ev, 7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evcon->timeout, HTTP_WRITE_TIMEOUT); 7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Activate our call back */ 7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (evcon->cb != NULL) 7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (*evcon->cb)(evcon, evcon->cb_arg); 7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Advance the connection state. 7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * - If this is an outgoing connection, we've just processed the response; 7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * idle or close the connection. 7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * - If this is an incoming connection, we've just processed the request; 7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * respond. 7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void 7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)evhttp_connection_done(struct evhttp_connection *evcon) 7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct evhttp_request *req = TAILQ_FIRST(&evcon->requests); 7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int con_outgoing = evcon->flags & EVHTTP_CON_OUTGOING; 7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (con_outgoing) { 7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* idle or close the connection */ 7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int need_close; 7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TAILQ_REMOVE(&evcon->requests, req, next); 7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req->evcon = NULL; 7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evcon->state = EVCON_IDLE; 7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) need_close = 7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evhttp_is_connection_close(req->flags, req->input_headers)|| 7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evhttp_is_connection_close(req->flags, req->output_headers); 7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* check if we got asked to close the connection */ 7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (need_close) 7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evhttp_connection_reset(evcon); 7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (TAILQ_FIRST(&evcon->requests) != NULL) { 7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* 7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * We have more requests; reset the connection 7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * and deal with the next request. 7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!evhttp_connected(evcon)) 7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evhttp_connection_connect(evcon); 7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evhttp_request_dispatch(evcon); 7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (!need_close) { 7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* 7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The connection is going to be persistent, but we 7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * need to detect if the other side closes it. 7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evhttp_connection_start_detectclose(evcon); 7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* 7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * incoming connection - we need to leave the request on the 7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * connection so that we can reply to it. 7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evcon->state = EVCON_WRITING; 7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* notify the user of the request */ 7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (*req->cb)(req, req->cb_arg); 7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* if this was an outgoing request, we own and it's done. so free it */ 7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (con_outgoing) { 7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evhttp_request_free(req); 7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Handles reading from a chunked request. 7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * return ALL_DATA_READ: 7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * all data has been read 7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * return MORE_DATA_EXPECTED: 7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * more data is expected 7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * return DATA_CORRUPTED: 7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * data is corrupted 7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * return REQUEST_CANCLED: 7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * request was canceled by the user calling evhttp_cancel_request 7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static enum message_read_status 7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)evhttp_handle_chunked_read(struct evhttp_request *req, struct evbuffer *buf) 7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int len; 7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while ((len = EVBUFFER_LENGTH(buf)) > 0) { 7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (req->ntoread < 0) { 7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Read chunk size */ 7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ev_int64_t ntoread; 7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char *p = evbuffer_readline(buf); 7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char *endp; 7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int error; 7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (p == NULL) 7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* the last chunk is on a new line? */ 7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (strlen(p) == 0) { 7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free(p); 8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ntoread = evutil_strtoll(p, &endp, 16); 8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error = (*p == '\0' || 8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (*endp != '\0' && *endp != ' ') || 8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ntoread < 0); 8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free(p); 8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (error) { 8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* could not get chunk size */ 8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (DATA_CORRUPTED); 8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req->ntoread = ntoread; 8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (req->ntoread == 0) { 8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Last chunk */ 8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (ALL_DATA_READ); 8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* don't have enough to complete a chunk; wait for more */ 8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (len < req->ntoread) 8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (MORE_DATA_EXPECTED); 8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Completed chunk */ 8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evbuffer_add(req->input_buffer, 8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EVBUFFER_DATA(buf), (size_t)req->ntoread); 8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evbuffer_drain(buf, (size_t)req->ntoread); 8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req->ntoread = -1; 8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (req->chunk_cb != NULL) { 8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (*req->chunk_cb)(req, req->cb_arg); 8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evbuffer_drain(req->input_buffer, 8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EVBUFFER_LENGTH(req->input_buffer)); 8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (MORE_DATA_EXPECTED); 8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void 8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)evhttp_read_trailer(struct evhttp_connection *evcon, struct evhttp_request *req) 8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct evbuffer *buf = evcon->input_buffer; 8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (evhttp_parse_headers(req, buf)) { 8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case DATA_CORRUPTED: 8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evhttp_connection_fail(evcon, EVCON_HTTP_INVALID_HEADER); 8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case ALL_DATA_READ: 8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event_del(&evcon->ev); 8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evhttp_connection_done(evcon); 8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case MORE_DATA_EXPECTED: 8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evhttp_add_event(&evcon->ev, evcon->timeout, 8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HTTP_READ_TIMEOUT); 8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void 8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)evhttp_read_body(struct evhttp_connection *evcon, struct evhttp_request *req) 8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 8625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct evbuffer *buf = evcon->input_buffer; 8635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (req->chunked) { 8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (evhttp_handle_chunked_read(req, buf)) { 8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case ALL_DATA_READ: 8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* finished last chunk */ 8685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evcon->state = EVCON_READING_TRAILER; 8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evhttp_read_trailer(evcon, req); 8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case DATA_CORRUPTED: 8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* corrupted data */ 8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evhttp_connection_fail(evcon, 8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EVCON_HTTP_INVALID_HEADER); 8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case REQUEST_CANCELED: 8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* request canceled */ 8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evhttp_request_free(req); 8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case MORE_DATA_EXPECTED: 8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 8835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (req->ntoread < 0) { 8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Read until connection close. */ 8865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evbuffer_add_buffer(req->input_buffer, buf); 8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (EVBUFFER_LENGTH(buf) >= req->ntoread) { 8885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Completed content length */ 8895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evbuffer_add(req->input_buffer, EVBUFFER_DATA(buf), 8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (size_t)req->ntoread); 8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evbuffer_drain(buf, (size_t)req->ntoread); 8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req->ntoread = 0; 8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evhttp_connection_done(evcon); 8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Read more! */ 8975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event_set(&evcon->ev, evcon->fd, EV_READ, evhttp_read, evcon); 8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EVHTTP_BASE_SET(evcon, &evcon->ev); 8995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evhttp_add_event(&evcon->ev, evcon->timeout, HTTP_READ_TIMEOUT); 9005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 9035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Reads data into a buffer structure until no more data 9045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * can be read on the file descriptor or we have read all 9055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * the data that we wanted to read. 9065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Execute callback when done. 9075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 9085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void 9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)evhttp_read(int fd, short what, void *arg) 9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct evhttp_connection *evcon = arg; 9135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct evhttp_request *req = TAILQ_FIRST(&evcon->requests); 9145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct evbuffer *buf = evcon->input_buffer; 9155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int n, len; 9165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (what == EV_TIMEOUT) { 9185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evhttp_connection_fail(evcon, EVCON_HTTP_TIMEOUT); 9195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 9205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) n = evbuffer_read(buf, fd, -1); 9225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) len = EVBUFFER_LENGTH(buf); 9235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event_debug(("%s: got %d on %d\n", __func__, n, fd)); 9245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (n == -1) { 9265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (errno != EINTR && errno != EAGAIN) { 9275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event_debug(("%s: evbuffer_read", __func__)); 9285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evhttp_connection_fail(evcon, EVCON_HTTP_EOF); 9295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 9305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evhttp_add_event(&evcon->ev, evcon->timeout, 9315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HTTP_READ_TIMEOUT); 9325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 9345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (n == 0) { 9355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Connection closed */ 9365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evhttp_connection_done(evcon); 9375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 9385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (evcon->state) { 9415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case EVCON_READING_FIRSTLINE: 9425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evhttp_read_firstline(evcon, req); 9435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 9445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case EVCON_READING_HEADERS: 9455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evhttp_read_header(evcon, req); 9465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 9475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case EVCON_READING_BODY: 9485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evhttp_read_body(evcon, req); 9495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 9505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case EVCON_READING_TRAILER: 9515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evhttp_read_trailer(evcon, req); 9525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 9535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case EVCON_DISCONNECTED: 9545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case EVCON_CONNECTING: 9555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case EVCON_IDLE: 9565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case EVCON_WRITING: 9575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 9585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event_errx(1, "%s: illegal connection state %d", 9595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) __func__, evcon->state); 9605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void 9645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)evhttp_write_connectioncb(struct evhttp_connection *evcon, void *arg) 9655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 9665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* This is after writing the request to the server */ 9675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct evhttp_request *req = TAILQ_FIRST(&evcon->requests); 9685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert(req != NULL); 9695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert(evcon->state == EVCON_WRITING); 9715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* We are done writing our header and are now expecting the response */ 9735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req->kind = EVHTTP_RESPONSE; 9745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evhttp_start_read(evcon); 9765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 9795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Clean up a connection object 9805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 9815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void 9835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)evhttp_connection_free(struct evhttp_connection *evcon) 9845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 9855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct evhttp_request *req; 9865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* notify interested parties that this connection is going down */ 9885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (evcon->fd != -1) { 9895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (evhttp_connected(evcon) && evcon->closecb != NULL) 9905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (*evcon->closecb)(evcon, evcon->closecb_arg); 9915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* remove all requests that might be queued on this connection */ 9945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while ((req = TAILQ_FIRST(&evcon->requests)) != NULL) { 9955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TAILQ_REMOVE(&evcon->requests, req, next); 9965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evhttp_request_free(req); 9975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (evcon->http_server != NULL) { 10005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct evhttp *http = evcon->http_server; 10015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TAILQ_REMOVE(&http->connections, evcon, next); 10025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (event_initialized(&evcon->close_ev)) 10055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event_del(&evcon->close_ev); 10065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (event_initialized(&evcon->ev)) 10085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event_del(&evcon->ev); 10095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (evcon->fd != -1) 10115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EVUTIL_CLOSESOCKET(evcon->fd); 10125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (evcon->bind_address != NULL) 10145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free(evcon->bind_address); 10155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (evcon->address != NULL) 10175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free(evcon->address); 10185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (evcon->input_buffer != NULL) 10205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evbuffer_free(evcon->input_buffer); 10215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (evcon->output_buffer != NULL) 10235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evbuffer_free(evcon->output_buffer); 10245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free(evcon); 10265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void 10295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)evhttp_connection_set_local_address(struct evhttp_connection *evcon, 10305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char *address) 10315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 10325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert(evcon->state == EVCON_DISCONNECTED); 10335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (evcon->bind_address) 10345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free(evcon->bind_address); 10355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((evcon->bind_address = strdup(address)) == NULL) 10365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event_err(1, "%s: strdup", __func__); 10375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void 10405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)evhttp_connection_set_local_port(struct evhttp_connection *evcon, 10415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned short port) 10425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 10435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert(evcon->state == EVCON_DISCONNECTED); 10445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evcon->bind_port = port; 10455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void 10485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)evhttp_request_dispatch(struct evhttp_connection* evcon) 10495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 10505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct evhttp_request *req = TAILQ_FIRST(&evcon->requests); 10515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* this should not usually happy but it's possible */ 10535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (req == NULL) 10545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 10555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* delete possible close detection events */ 10575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evhttp_connection_stop_detectclose(evcon); 10585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* we assume that the connection is connected already */ 10605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert(evcon->state == EVCON_IDLE); 10615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evcon->state = EVCON_WRITING; 10635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Create the header from the store arguments */ 10655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evhttp_make_header(evcon, req); 10665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evhttp_write_buffer(evcon, evhttp_write_connectioncb, NULL); 10685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Reset our connection state */ 10715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void 10725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)evhttp_connection_reset(struct evhttp_connection *evcon) 10735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 10745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (event_initialized(&evcon->ev)) 10755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event_del(&evcon->ev); 10765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (evcon->fd != -1) { 10785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* inform interested parties about connection close */ 10795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (evhttp_connected(evcon) && evcon->closecb != NULL) 10805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (*evcon->closecb)(evcon, evcon->closecb_arg); 10815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EVUTIL_CLOSESOCKET(evcon->fd); 10835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evcon->fd = -1; 10845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evcon->state = EVCON_DISCONNECTED; 10865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evbuffer_drain(evcon->input_buffer, 10885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EVBUFFER_LENGTH(evcon->input_buffer)); 10895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evbuffer_drain(evcon->output_buffer, 10905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EVBUFFER_LENGTH(evcon->output_buffer)); 10915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void 10945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)evhttp_detect_close_cb(int fd, short what, void *arg) 10955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 10965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct evhttp_connection *evcon = arg; 10975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evhttp_connection_reset(evcon); 10985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void 11015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)evhttp_connection_start_detectclose(struct evhttp_connection *evcon) 11025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 11035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evcon->flags |= EVHTTP_CON_CLOSEDETECT; 11045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (event_initialized(&evcon->close_ev)) 11065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event_del(&evcon->close_ev); 11075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event_set(&evcon->close_ev, evcon->fd, EV_READ, 11085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evhttp_detect_close_cb, evcon); 11095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EVHTTP_BASE_SET(evcon, &evcon->close_ev); 11105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event_add(&evcon->close_ev, NULL); 11115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 11125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void 11145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)evhttp_connection_stop_detectclose(struct evhttp_connection *evcon) 11155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 11165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evcon->flags &= ~EVHTTP_CON_CLOSEDETECT; 11175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event_del(&evcon->close_ev); 11185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 11195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void 11215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)evhttp_connection_retry(int fd, short what, void *arg) 11225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 11235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct evhttp_connection *evcon = arg; 11245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evcon->state = EVCON_DISCONNECTED; 11265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evhttp_connection_connect(evcon); 11275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 11285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 11305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Call back for asynchronous connection attempt. 11315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 11325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void 11345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)evhttp_connectioncb(int fd, short what, void *arg) 11355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 11365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct evhttp_connection *evcon = arg; 11375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int error; 11385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) socklen_t errsz = sizeof(error); 11395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (what == EV_TIMEOUT) { 11415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event_debug(("%s: connection timeout for \"%s:%d\" on %d", 11425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) __func__, evcon->address, evcon->port, evcon->fd)); 11435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) goto cleanup; 11445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Check if the connection completed */ 11475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (getsockopt(evcon->fd, SOL_SOCKET, SO_ERROR, (void*)&error, 11485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &errsz) == -1) { 11495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event_debug(("%s: getsockopt for \"%s:%d\" on %d", 11505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) __func__, evcon->address, evcon->port, evcon->fd)); 11515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) goto cleanup; 11525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (error) { 11555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event_debug(("%s: connect failed for \"%s:%d\" on %d: %s", 11565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) __func__, evcon->address, evcon->port, evcon->fd, 11575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) strerror(error))); 11585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) goto cleanup; 11595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* We are connected to the server now */ 11625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event_debug(("%s: connected to \"%s:%d\" on %d\n", 11635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) __func__, evcon->address, evcon->port, evcon->fd)); 11645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Reset the retry count as we were successful in connecting */ 11665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evcon->retry_cnt = 0; 11675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evcon->state = EVCON_IDLE; 11685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* try to start requests that have queued up on this connection */ 11705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evhttp_request_dispatch(evcon); 11715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 11725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cleanup: 11745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (evcon->retry_max < 0 || evcon->retry_cnt < evcon->retry_max) { 11755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evtimer_set(&evcon->ev, evhttp_connection_retry, evcon); 11765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EVHTTP_BASE_SET(evcon, &evcon->ev); 11775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evhttp_add_event(&evcon->ev, MIN(3600, 2 << evcon->retry_cnt), 11785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HTTP_CONNECT_TIMEOUT); 11795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evcon->retry_cnt++; 11805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 11815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evhttp_connection_reset(evcon); 11835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* for now, we just signal all requests by executing their callbacks */ 11855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (TAILQ_FIRST(&evcon->requests) != NULL) { 11865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct evhttp_request *request = TAILQ_FIRST(&evcon->requests); 11875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TAILQ_REMOVE(&evcon->requests, request, next); 11885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request->evcon = NULL; 11895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* we might want to set an error here */ 11915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request->cb(request, request->cb_arg); 11925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evhttp_request_free(request); 11935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 11955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 11975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Check if we got a valid response code. 11985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 11995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int 12015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)evhttp_valid_response_code(int code) 12025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 12035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (code == 0) 12045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (0); 12055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (1); 12075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 12085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Parses the status line of a web server */ 12105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int 12125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)evhttp_parse_response_line(struct evhttp_request *req, char *line) 12135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 12145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char *protocol; 12155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char *number; 12165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char *readable; 12175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protocol = strsep(&line, " "); 12195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (line == NULL) 12205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (-1); 12215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) number = strsep(&line, " "); 12225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (line == NULL) 12235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (-1); 12245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) readable = line; 12255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (strcmp(protocol, "HTTP/1.0") == 0) { 12275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req->major = 1; 12285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req->minor = 0; 12295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (strcmp(protocol, "HTTP/1.1") == 0) { 12305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req->major = 1; 12315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req->minor = 1; 12325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 12335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event_debug(("%s: bad protocol \"%s\"", 12345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) __func__, protocol)); 12355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (-1); 12365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req->response_code = atoi(number); 12395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!evhttp_valid_response_code(req->response_code)) { 12405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event_debug(("%s: bad response code \"%s\"", 12415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) __func__, number)); 12425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (-1); 12435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((req->response_code_line = strdup(readable)) == NULL) 12465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event_err(1, "%s: strdup", __func__); 12475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (0); 12495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 12505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Parse the first line of a HTTP request */ 12525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int 12545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)evhttp_parse_request_line(struct evhttp_request *req, char *line) 12555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 12565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char *method; 12575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char *uri; 12585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char *version; 12595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Parse the request line */ 12615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) method = strsep(&line, " "); 12625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (line == NULL) 12635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (-1); 12645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uri = strsep(&line, " "); 12655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (line == NULL) 12665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (-1); 12675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) version = strsep(&line, " "); 12685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (line != NULL) 12695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (-1); 12705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* First line */ 12725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (strcmp(method, "GET") == 0) { 12735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req->type = EVHTTP_REQ_GET; 12745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (strcmp(method, "POST") == 0) { 12755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req->type = EVHTTP_REQ_POST; 12765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (strcmp(method, "HEAD") == 0) { 12775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req->type = EVHTTP_REQ_HEAD; 12785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 12795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event_debug(("%s: bad method %s on request %p from %s", 12805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) __func__, method, req, req->remote_host)); 12815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (-1); 12825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (strcmp(version, "HTTP/1.0") == 0) { 12855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req->major = 1; 12865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req->minor = 0; 12875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (strcmp(version, "HTTP/1.1") == 0) { 12885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req->major = 1; 12895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req->minor = 1; 12905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 12915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event_debug(("%s: bad version %s on request %p from %s", 12925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) __func__, version, req, req->remote_host)); 12935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (-1); 12945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((req->uri = strdup(uri)) == NULL) { 12975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event_debug(("%s: evhttp_decode_uri", __func__)); 12985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (-1); 12995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 13005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* determine if it's a proxy request */ 13025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (strlen(req->uri) > 0 && req->uri[0] != '/') 13035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req->flags |= EVHTTP_PROXY_REQUEST; 13045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (0); 13065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 13075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char * 13095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)evhttp_find_header(const struct evkeyvalq *headers, const char *key) 13105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 13115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct evkeyval *header; 13125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TAILQ_FOREACH(header, headers, next) { 13145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (strcasecmp(header->key, key) == 0) 13155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (header->value); 13165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 13175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (NULL); 13195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 13205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void 13225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)evhttp_clear_headers(struct evkeyvalq *headers) 13235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 13245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct evkeyval *header; 13255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (header = TAILQ_FIRST(headers); 13275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) header != NULL; 13285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) header = TAILQ_FIRST(headers)) { 13295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TAILQ_REMOVE(headers, header, next); 13305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free(header->key); 13315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free(header->value); 13325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free(header); 13335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 13345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 13355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 13375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Returns 0, if the header was successfully removed. 13385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Returns -1, if the header could not be found. 13395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 13405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int 13425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)evhttp_remove_header(struct evkeyvalq *headers, const char *key) 13435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 13445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct evkeyval *header; 13455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TAILQ_FOREACH(header, headers, next) { 13475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (strcasecmp(header->key, key) == 0) 13485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 13495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 13505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (header == NULL) 13525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (-1); 13535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Free and remove the header that we found */ 13555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TAILQ_REMOVE(headers, header, next); 13565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free(header->key); 13575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free(header->value); 13585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free(header); 13595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (0); 13615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 13625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int 13645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)evhttp_header_is_valid_value(const char *value) 13655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 13665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char *p = value; 13675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while ((p = strpbrk(p, "\r\n")) != NULL) { 13695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* we really expect only one new line */ 13705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) p += strspn(p, "\r\n"); 13715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* we expect a space or tab for continuation */ 13725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (*p != ' ' && *p != '\t') 13735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (0); 13745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 13755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (1); 13765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 13775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int 13795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)evhttp_add_header(struct evkeyvalq *headers, 13805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char *key, const char *value) 13815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 13825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event_debug(("%s: key: %s val: %s\n", __func__, key, value)); 13835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (strchr(key, '\r') != NULL || strchr(key, '\n') != NULL) { 13855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* drop illegal headers */ 13865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event_debug(("%s: dropping illegal header key\n", __func__)); 13875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (-1); 13885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 13895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!evhttp_header_is_valid_value(value)) { 13915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event_debug(("%s: dropping illegal header value\n", __func__)); 13925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (-1); 13935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 13945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (evhttp_add_header_internal(headers, key, value)); 13965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 13975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int 13995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)evhttp_add_header_internal(struct evkeyvalq *headers, 14005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char *key, const char *value) 14015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 14025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct evkeyval *header = calloc(1, sizeof(struct evkeyval)); 14035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (header == NULL) { 14045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event_warn("%s: calloc", __func__); 14055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (-1); 14065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 14075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((header->key = strdup(key)) == NULL) { 14085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free(header); 14095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event_warn("%s: strdup", __func__); 14105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (-1); 14115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 14125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((header->value = strdup(value)) == NULL) { 14135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free(header->key); 14145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free(header); 14155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event_warn("%s: strdup", __func__); 14165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (-1); 14175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 14185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TAILQ_INSERT_TAIL(headers, header, next); 14205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (0); 14225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 14235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 14255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Parses header lines from a request or a response into the specified 14265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * request object given an event buffer. 14275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 14285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Returns 14295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * DATA_CORRUPTED on error 14305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * MORE_DATA_EXPECTED when we need to read more headers 14315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * ALL_DATA_READ when all headers have been read. 14325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 14335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)enum message_read_status 14355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)evhttp_parse_firstline(struct evhttp_request *req, struct evbuffer *buffer) 14365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 14375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char *line; 14385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) enum message_read_status status = ALL_DATA_READ; 14395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) line = evbuffer_readline(buffer); 14415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (line == NULL) 14425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (MORE_DATA_EXPECTED); 14435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (req->kind) { 14455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case EVHTTP_REQUEST: 14465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (evhttp_parse_request_line(req, line) == -1) 14475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) status = DATA_CORRUPTED; 14485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 14495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case EVHTTP_RESPONSE: 14505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (evhttp_parse_response_line(req, line) == -1) 14515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) status = DATA_CORRUPTED; 14525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 14535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 14545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) status = DATA_CORRUPTED; 14555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 14565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free(line); 14585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (status); 14595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 14605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int 14625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)evhttp_append_to_last_header(struct evkeyvalq *headers, const char *line) 14635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 14645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct evkeyval *header = TAILQ_LAST(headers, evkeyvalq); 14655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char *newval; 14665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t old_len, line_len; 14675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (header == NULL) 14695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (-1); 14705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) old_len = strlen(header->value); 14725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) line_len = strlen(line); 14735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) newval = realloc(header->value, old_len + line_len + 1); 14755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (newval == NULL) 14765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (-1); 14775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memcpy(newval + old_len, line, line_len + 1); 14795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) header->value = newval; 14805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (0); 14825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 14835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)enum message_read_status 14855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)evhttp_parse_headers(struct evhttp_request *req, struct evbuffer* buffer) 14865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 14875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char *line; 14885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) enum message_read_status status = MORE_DATA_EXPECTED; 14895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct evkeyvalq* headers = req->input_headers; 14915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while ((line = evbuffer_readline(buffer)) 14925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) != NULL) { 14935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char *skey, *svalue; 14945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (*line == '\0') { /* Last header - Done */ 14965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) status = ALL_DATA_READ; 14975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free(line); 14985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 14995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 15005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Check if this is a continuation line */ 15025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (*line == ' ' || *line == '\t') { 15035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (evhttp_append_to_last_header(headers, line) == -1) 15045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) goto error; 15055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free(line); 15065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 15075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 15085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Processing of header lines */ 15105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) svalue = line; 15115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) skey = strsep(&svalue, ":"); 15125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (svalue == NULL) 15135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) goto error; 15145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) svalue += strspn(svalue, " "); 15165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (evhttp_add_header(headers, skey, svalue) == -1) 15185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) goto error; 15195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free(line); 15215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 15225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (status); 15245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error: 15265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free(line); 15275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (DATA_CORRUPTED); 15285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 15295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int 15315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)evhttp_get_body_length(struct evhttp_request *req) 15325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 15335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct evkeyvalq *headers = req->input_headers; 15345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char *content_length; 15355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char *connection; 15365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content_length = evhttp_find_header(headers, "Content-Length"); 15385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) connection = evhttp_find_header(headers, "Connection"); 15395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (content_length == NULL && connection == NULL) 15415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req->ntoread = -1; 15425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else if (content_length == NULL && 15435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) strcasecmp(connection, "Close") != 0) { 15445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Bad combination, we don't know when it will end */ 15455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event_warnx("%s: we got no content length, but the " 15465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "server wants to keep the connection open: %s.", 15475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) __func__, connection); 15485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (-1); 15495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (content_length == NULL) { 15505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req->ntoread = -1; 15515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 15525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char *endp; 15535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ev_int64_t ntoread = evutil_strtoll(content_length, &endp, 10); 15545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (*content_length == '\0' || *endp != '\0' || ntoread < 0) { 15555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event_debug(("%s: illegal content length: %s", 15565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) __func__, content_length)); 15575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (-1); 15585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 15595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req->ntoread = ntoread; 15605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 15615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event_debug(("%s: bytes to read: %lld (in buffer %ld)\n", 15635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) __func__, req->ntoread, 15645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EVBUFFER_LENGTH(req->evcon->input_buffer))); 15655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (0); 15675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 15685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void 15705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)evhttp_get_body(struct evhttp_connection *evcon, struct evhttp_request *req) 15715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 15725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char *xfer_enc; 15735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* If this is a request without a body, then we are done */ 15755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (req->kind == EVHTTP_REQUEST && req->type != EVHTTP_REQ_POST) { 15765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evhttp_connection_done(evcon); 15775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 15785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 15795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evcon->state = EVCON_READING_BODY; 15805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) xfer_enc = evhttp_find_header(req->input_headers, "Transfer-Encoding"); 15815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (xfer_enc != NULL && strcasecmp(xfer_enc, "chunked") == 0) { 15825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req->chunked = 1; 15835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req->ntoread = -1; 15845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 15855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (evhttp_get_body_length(req) == -1) { 15865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evhttp_connection_fail(evcon, 15875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EVCON_HTTP_INVALID_HEADER); 15885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 15895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 15905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 15915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evhttp_read_body(evcon, req); 15925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 15935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void 15955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)evhttp_read_firstline(struct evhttp_connection *evcon, 15965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct evhttp_request *req) 15975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 15985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) enum message_read_status res; 15995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) res = evhttp_parse_firstline(req, evcon->input_buffer); 16015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (res == DATA_CORRUPTED) { 16025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Error while reading, terminate */ 16035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event_debug(("%s: bad header lines on %d\n", 16045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) __func__, evcon->fd)); 16055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evhttp_connection_fail(evcon, EVCON_HTTP_INVALID_HEADER); 16065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 16075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (res == MORE_DATA_EXPECTED) { 16085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Need more header lines */ 16095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evhttp_add_event(&evcon->ev, 16105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evcon->timeout, HTTP_READ_TIMEOUT); 16115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 16125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 16135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evcon->state = EVCON_READING_HEADERS; 16155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evhttp_read_header(evcon, req); 16165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 16175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void 16195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)evhttp_read_header(struct evhttp_connection *evcon, struct evhttp_request *req) 16205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 16215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) enum message_read_status res; 16225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int fd = evcon->fd; 16235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) res = evhttp_parse_headers(req, evcon->input_buffer); 16255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (res == DATA_CORRUPTED) { 16265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Error while reading, terminate */ 16275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event_debug(("%s: bad header lines on %d\n", __func__, fd)); 16285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evhttp_connection_fail(evcon, EVCON_HTTP_INVALID_HEADER); 16295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 16305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (res == MORE_DATA_EXPECTED) { 16315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Need more header lines */ 16325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evhttp_add_event(&evcon->ev, 16335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evcon->timeout, HTTP_READ_TIMEOUT); 16345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 16355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 16365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Done reading headers, do the real work */ 16385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (req->kind) { 16395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case EVHTTP_REQUEST: 16405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event_debug(("%s: checking for post data on %d\n", 16415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) __func__, fd)); 16425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evhttp_get_body(evcon, req); 16435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 16445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case EVHTTP_RESPONSE: 16465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (req->response_code == HTTP_NOCONTENT || 16475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req->response_code == HTTP_NOTMODIFIED || 16485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (req->response_code >= 100 && req->response_code < 200)) { 16495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event_debug(("%s: skipping body for code %d\n", 16505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) __func__, req->response_code)); 16515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evhttp_connection_done(evcon); 16525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 16535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event_debug(("%s: start of read body for %s on %d\n", 16545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) __func__, req->remote_host, fd)); 16555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evhttp_get_body(evcon, req); 16565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 16575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 16585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 16605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event_warnx("%s: bad header on %d", __func__, fd); 16615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evhttp_connection_fail(evcon, EVCON_HTTP_INVALID_HEADER); 16625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 16635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 16645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 16655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 16675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Creates a TCP connection to the specified port and executes a callback 16685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * when finished. Failure or sucess is indicate by the passed connection 16695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * object. 16705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 16715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Although this interface accepts a hostname, it is intended to take 16725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * only numeric hostnames so that non-blocking DNS resolution can 16735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * happen elsewhere. 16745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 16755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct evhttp_connection * 16775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)evhttp_connection_new(const char *address, unsigned short port) 16785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 16795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct evhttp_connection *evcon = NULL; 16805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event_debug(("Attempting connection to %s:%d\n", address, port)); 16825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((evcon = calloc(1, sizeof(struct evhttp_connection))) == NULL) { 16845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event_warn("%s: calloc failed", __func__); 16855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) goto error; 16865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 16875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evcon->fd = -1; 16895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evcon->port = port; 16905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evcon->timeout = -1; 16925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evcon->retry_cnt = evcon->retry_max = 0; 16935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((evcon->address = strdup(address)) == NULL) { 16955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event_warn("%s: strdup failed", __func__); 16965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) goto error; 16975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 16985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((evcon->input_buffer = evbuffer_new()) == NULL) { 17005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event_warn("%s: evbuffer_new failed", __func__); 17015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) goto error; 17025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 17035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((evcon->output_buffer = evbuffer_new()) == NULL) { 17055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event_warn("%s: evbuffer_new failed", __func__); 17065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) goto error; 17075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 17085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evcon->state = EVCON_DISCONNECTED; 17105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TAILQ_INIT(&evcon->requests); 17115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (evcon); 17135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error: 17155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (evcon != NULL) 17165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evhttp_connection_free(evcon); 17175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (NULL); 17185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 17195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void evhttp_connection_set_base(struct evhttp_connection *evcon, 17215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct event_base *base) 17225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 17235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert(evcon->base == NULL); 17245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert(evcon->state == EVCON_DISCONNECTED); 17255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evcon->base = base; 17265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 17275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void 17295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)evhttp_connection_set_timeout(struct evhttp_connection *evcon, 17305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int timeout_in_secs) 17315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 17325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evcon->timeout = timeout_in_secs; 17335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 17345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void 17365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)evhttp_connection_set_retries(struct evhttp_connection *evcon, 17375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int retry_max) 17385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 17395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evcon->retry_max = retry_max; 17405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 17415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void 17435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)evhttp_connection_set_closecb(struct evhttp_connection *evcon, 17445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void (*cb)(struct evhttp_connection *, void *), void *cbarg) 17455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 17465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evcon->closecb = cb; 17475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evcon->closecb_arg = cbarg; 17485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 17495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void 17515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)evhttp_connection_get_peer(struct evhttp_connection *evcon, 17525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char **address, u_short *port) 17535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 17545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *address = evcon->address; 17555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *port = evcon->port; 17565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 17575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int 17595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)evhttp_connection_connect(struct evhttp_connection *evcon) 17605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 17615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (evcon->state == EVCON_CONNECTING) 17625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (0); 17635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evhttp_connection_reset(evcon); 17655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert(!(evcon->flags & EVHTTP_CON_INCOMING)); 17675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evcon->flags |= EVHTTP_CON_OUTGOING; 17685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evcon->fd = bind_socket( 17705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evcon->bind_address, evcon->bind_port, 0 /*reuse*/); 17715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (evcon->fd == -1) { 17725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event_debug(("%s: failed to bind to \"%s\"", 17735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) __func__, evcon->bind_address)); 17745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (-1); 17755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 17765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (socket_connect(evcon->fd, evcon->address, evcon->port) == -1) { 17785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EVUTIL_CLOSESOCKET(evcon->fd); evcon->fd = -1; 17795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (-1); 17805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 17815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Set up a callback for successful connection setup */ 17835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event_set(&evcon->ev, evcon->fd, EV_WRITE, evhttp_connectioncb, evcon); 17845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EVHTTP_BASE_SET(evcon, &evcon->ev); 17855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evhttp_add_event(&evcon->ev, evcon->timeout, HTTP_CONNECT_TIMEOUT); 17865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evcon->state = EVCON_CONNECTING; 17885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (0); 17905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 17915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 17935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Starts an HTTP request on the provided evhttp_connection object. 17945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * If the connection object is not connected to the web server already, 17955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * this will start the connection. 17965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 17975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int 17995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)evhttp_make_request(struct evhttp_connection *evcon, 18005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct evhttp_request *req, 18015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) enum evhttp_cmd_type type, const char *uri) 18025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 18035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* We are making a request */ 18045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req->kind = EVHTTP_REQUEST; 18055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req->type = type; 18065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (req->uri != NULL) 18075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free(req->uri); 18085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((req->uri = strdup(uri)) == NULL) 18095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event_err(1, "%s: strdup", __func__); 18105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Set the protocol version if it is not supplied */ 18125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!req->major && !req->minor) { 18135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req->major = 1; 18145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req->minor = 1; 18155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 18165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert(req->evcon == NULL); 18185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req->evcon = evcon; 18195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert(!(req->flags & EVHTTP_REQ_OWN_CONNECTION)); 18205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TAILQ_INSERT_TAIL(&evcon->requests, req, next); 18225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* If the connection object is not connected; make it so */ 18245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!evhttp_connected(evcon)) 18255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (evhttp_connection_connect(evcon)); 18265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* 18285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * If it's connected already and we are the first in the queue, 18295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * then we can dispatch this request immediately. Otherwise, it 18305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * will be dispatched once the pending requests are completed. 18315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 18325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (TAILQ_FIRST(&evcon->requests) == req) 18335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evhttp_request_dispatch(evcon); 18345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (0); 18365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 18375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 18395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Reads data from file descriptor into request structure 18405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Request structure needs to be set up correctly. 18415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 18425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void 18445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)evhttp_start_read(struct evhttp_connection *evcon) 18455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 18465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Set up an event to read the headers */ 18475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (event_initialized(&evcon->ev)) 18485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event_del(&evcon->ev); 18495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event_set(&evcon->ev, evcon->fd, EV_READ, evhttp_read, evcon); 18505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EVHTTP_BASE_SET(evcon, &evcon->ev); 18515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evhttp_add_event(&evcon->ev, evcon->timeout, HTTP_READ_TIMEOUT); 18535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evcon->state = EVCON_READING_FIRSTLINE; 18545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 18555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void 18575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)evhttp_send_done(struct evhttp_connection *evcon, void *arg) 18585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 18595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int need_close; 18605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct evhttp_request *req = TAILQ_FIRST(&evcon->requests); 18615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TAILQ_REMOVE(&evcon->requests, req, next); 18625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* delete possible close detection events */ 18645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evhttp_connection_stop_detectclose(evcon); 18655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) need_close = 18675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (req->minor == 0 && 18685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !evhttp_is_connection_keepalive(req->input_headers))|| 18695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evhttp_is_connection_close(req->flags, req->input_headers) || 18705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evhttp_is_connection_close(req->flags, req->output_headers); 18715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert(req->flags & EVHTTP_REQ_OWN_CONNECTION); 18735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evhttp_request_free(req); 18745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (need_close) { 18765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evhttp_connection_free(evcon); 18775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 18785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 18795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* we have a persistent connection; try to accept another request. */ 18815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (evhttp_associate_new_request_with_connection(evcon) == -1) 18825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evhttp_connection_free(evcon); 18835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 18845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 18865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Returns an error page. 18875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 18885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void 18905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)evhttp_send_error(struct evhttp_request *req, int error, const char *reason) 18915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 18925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define ERR_FORMAT "<HTML><HEAD>\n" \ 18935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "<TITLE>%d %s</TITLE>\n" \ 18945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "</HEAD><BODY>\n" \ 18955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "<H1>Method Not Implemented</H1>\n" \ 18965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Invalid method in request<P>\n" \ 18975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "</BODY></HTML>\n" 18985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct evbuffer *buf = evbuffer_new(); 19005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* close the connection on error */ 19025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evhttp_add_header(req->output_headers, "Connection", "close"); 19035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evhttp_response_code(req, error, reason); 19055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evbuffer_add_printf(buf, ERR_FORMAT, error, reason); 19075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evhttp_send_page(req, buf); 19095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evbuffer_free(buf); 19115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#undef ERR_FORMAT 19125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 19135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Requires that headers and response code are already set up */ 19155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static inline void 19175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)evhttp_send(struct evhttp_request *req, struct evbuffer *databuf) 19185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 19195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct evhttp_connection *evcon = req->evcon; 19205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert(TAILQ_FIRST(&evcon->requests) == req); 19225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* xxx: not sure if we really should expose the data buffer this way */ 19245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (databuf != NULL) 19255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evbuffer_add_buffer(req->output_buffer, databuf); 19265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Adds headers to the response */ 19285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evhttp_make_header(evcon, req); 19295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evhttp_write_buffer(evcon, evhttp_send_done, NULL); 19315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 19325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void 19345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)evhttp_send_reply(struct evhttp_request *req, int code, const char *reason, 19355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct evbuffer *databuf) 19365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 19375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evhttp_response_code(req, code, reason); 19385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evhttp_send(req, databuf); 19405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 19415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void 19435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)evhttp_send_reply_start(struct evhttp_request *req, int code, 19445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char *reason) 19455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 19465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evhttp_response_code(req, code, reason); 19475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (req->major == 1 && req->minor == 1) { 19485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* use chunked encoding for HTTP/1.1 */ 19495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evhttp_add_header(req->output_headers, "Transfer-Encoding", 19505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "chunked"); 19515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req->chunked = 1; 19525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 19535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evhttp_make_header(req->evcon, req); 19545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evhttp_write_buffer(req->evcon, NULL, NULL); 19555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 19565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void 19585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)evhttp_send_reply_chunk(struct evhttp_request *req, struct evbuffer *databuf) 19595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 19605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (req->chunked) { 19615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evbuffer_add_printf(req->evcon->output_buffer, "%x\r\n", 19625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (unsigned)EVBUFFER_LENGTH(databuf)); 19635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 19645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evbuffer_add_buffer(req->evcon->output_buffer, databuf); 19655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (req->chunked) { 19665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evbuffer_add(req->evcon->output_buffer, "\r\n", 2); 19675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 19685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evhttp_write_buffer(req->evcon, NULL, NULL); 19695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 19705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void 19725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)evhttp_send_reply_end(struct evhttp_request *req) 19735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 19745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct evhttp_connection *evcon = req->evcon; 19755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (req->chunked) { 19775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evbuffer_add(req->evcon->output_buffer, "0\r\n\r\n", 5); 19785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evhttp_write_buffer(req->evcon, evhttp_send_done, NULL); 19795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req->chunked = 0; 19805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (!event_pending(&evcon->ev, EV_WRITE|EV_TIMEOUT, NULL)) { 19815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* let the connection know that we are done with the request */ 19825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evhttp_send_done(evcon, NULL); 19835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 19845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* make the callback execute after all data has been written */ 19855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evcon->cb = evhttp_send_done; 19865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evcon->cb_arg = NULL; 19875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 19885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 19895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void 19915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)evhttp_response_code(struct evhttp_request *req, int code, const char *reason) 19925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 19935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req->kind = EVHTTP_RESPONSE; 19945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req->response_code = code; 19955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (req->response_code_line != NULL) 19965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free(req->response_code_line); 19975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req->response_code_line = strdup(reason); 19985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 19995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void 20015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)evhttp_send_page(struct evhttp_request *req, struct evbuffer *databuf) 20025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 20035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!req->major || !req->minor) { 20045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req->major = 1; 20055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req->minor = 1; 20065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 20075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (req->kind != EVHTTP_RESPONSE) 20095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evhttp_response_code(req, 200, "OK"); 20105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evhttp_clear_headers(req->output_headers); 20125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evhttp_add_header(req->output_headers, "Content-Type", "text/html"); 20135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evhttp_add_header(req->output_headers, "Connection", "close"); 20145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evhttp_send(req, databuf); 20165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 20175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const char uri_chars[256] = { 20195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 0, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 20225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 20235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* 64 */ 20245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 20255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 20265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 20275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 20285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* 128 */ 20295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* 192 */ 20345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 20395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 20415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Helper functions to encode/decode a URI. 20425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The returned string must be freed by the caller. 20435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 20445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)char * 20455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)evhttp_encode_uri(const char *uri) 20465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 20475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct evbuffer *buf = evbuffer_new(); 20485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char *p; 20495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (p = (char *)uri; *p != '\0'; p++) { 20515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (uri_chars[(u_char)(*p)]) { 20525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evbuffer_add(buf, p, 1); 20535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 20545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evbuffer_add_printf(buf, "%%%02X", (u_char)(*p)); 20555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 20565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 20575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evbuffer_add(buf, "", 1); 20585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) p = strdup((char *)EVBUFFER_DATA(buf)); 20595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evbuffer_free(buf); 20605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (p); 20625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 20635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 20655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param always_decode_plus: when true we transform plus to space even 20665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * if we have not seen a ?. 20675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 20685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int 20695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)evhttp_decode_uri_internal( 20705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char *uri, size_t length, char *ret, int always_decode_plus) 20715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 20725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char c; 20735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int i, j, in_query = always_decode_plus; 20745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (i = j = 0; uri[i] != '\0'; i++) { 20765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) c = uri[i]; 20775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (c == '?') { 20785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) in_query = 1; 20795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (c == '+' && in_query) { 20805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) c = ' '; 20815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (c == '%' && isxdigit((unsigned char)uri[i+1]) && 20825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) isxdigit((unsigned char)uri[i+2])) { 20835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char tmp[] = { uri[i+1], uri[i+2], '\0' }; 20845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) c = (char)strtol(tmp, NULL, 16); 20855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) i += 2; 20865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 20875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ret[j++] = c; 20885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 20895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ret[j] = '\0'; 20905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (j); 20925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 20935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)char * 20955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)evhttp_decode_uri(const char *uri) 20965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 20975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char *ret; 20985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((ret = malloc(strlen(uri) + 1)) == NULL) 21005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event_err(1, "%s: malloc(%lu)", __func__, 21015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (unsigned long)(strlen(uri) + 1)); 21025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evhttp_decode_uri_internal(uri, strlen(uri), 21045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ret, 0 /*always_decode_plus*/); 21055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (ret); 21075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 21085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 21105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Helper function to parse out arguments in a query. 21115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The arguments are separated by key and value. 21125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 21135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void 21155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)evhttp_parse_query(const char *uri, struct evkeyvalq *headers) 21165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 21175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char *line; 21185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char *argument; 21195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char *p; 21205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TAILQ_INIT(headers); 21225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* No arguments - we are done */ 21245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (strchr(uri, '?') == NULL) 21255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 21265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((line = strdup(uri)) == NULL) 21285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event_err(1, "%s: strdup", __func__); 21295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) argument = line; 21325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* We already know that there has to be a ? */ 21345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) strsep(&argument, "?"); 21355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) p = argument; 21375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (p != NULL && *p != '\0') { 21385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char *key, *value, *decoded_value; 21395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) argument = strsep(&p, "&"); 21405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) value = argument; 21425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) key = strsep(&value, "="); 21435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (value == NULL) 21445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) goto error; 21455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((decoded_value = malloc(strlen(value) + 1)) == NULL) 21475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event_err(1, "%s: malloc", __func__); 21485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evhttp_decode_uri_internal(value, strlen(value), 21505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) decoded_value, 1 /*always_decode_plus*/); 21515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event_debug(("Query Param: %s -> %s\n", key, decoded_value)); 21525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evhttp_add_header_internal(headers, key, decoded_value); 21535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free(decoded_value); 21545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 21555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error: 21575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free(line); 21585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 21595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static struct evhttp_cb * 21615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)evhttp_dispatch_callback(struct httpcbq *callbacks, struct evhttp_request *req) 21625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 21635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct evhttp_cb *cb; 21645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t offset = 0; 21655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Test for different URLs */ 21675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char *p = strchr(req->uri, '?'); 21685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (p != NULL) 21695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) offset = (size_t)(p - req->uri); 21705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TAILQ_FOREACH(cb, callbacks, next) { 21725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int res = 0; 21735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (p == NULL) { 21745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) res = strcmp(cb->what, req->uri) == 0; 21755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 21765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) res = ((strncmp(cb->what, req->uri, offset) == 0) && 21775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (cb->what[offset] == '\0')); 21785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 21795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (res) 21815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (cb); 21825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 21835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (NULL); 21855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 21865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void 21885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)evhttp_handle_request(struct evhttp_request *req, void *arg) 21895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 21905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct evhttp *http = arg; 21915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct evhttp_cb *cb = NULL; 21925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (req->uri == NULL) { 21945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evhttp_send_error(req, HTTP_BADREQUEST, "Bad Request"); 21955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 21965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 21975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((cb = evhttp_dispatch_callback(&http->callbacks, req)) != NULL) { 21995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (*cb->cb)(req, cb->cbarg); 22005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 22015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 22025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Generic call back */ 22045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (http->gencb) { 22055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (*http->gencb)(req, http->gencbarg); 22065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 22075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 22085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* We need to send a 404 here */ 22095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define ERR_FORMAT "<html><head>" \ 22105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "<title>404 Not Found</title>" \ 22115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "</head><body>" \ 22125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "<h1>Not Found</h1>" \ 22135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "<p>The requested URL %s was not found on this server.</p>"\ 22145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "</body></html>\n" 22155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char *escaped_html = evhttp_htmlescape(req->uri); 22175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct evbuffer *buf = evbuffer_new(); 22185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evhttp_response_code(req, HTTP_NOTFOUND, "Not Found"); 22205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evbuffer_add_printf(buf, ERR_FORMAT, escaped_html); 22225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free(escaped_html); 22245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evhttp_send_page(req, buf); 22265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evbuffer_free(buf); 22285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#undef ERR_FORMAT 22295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 22305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 22315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void 22335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)accept_socket(int fd, short what, void *arg) 22345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 22355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct evhttp *http = arg; 22365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct sockaddr_storage ss; 22375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) socklen_t addrlen = sizeof(ss); 22385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int nfd; 22395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((nfd = accept(fd, (struct sockaddr *)&ss, &addrlen)) == -1) { 22415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (errno != EAGAIN && errno != EINTR) 22425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event_warn("%s: bad accept", __func__); 22435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 22445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 22455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (evutil_make_socket_nonblocking(nfd) < 0) 22465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 22475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evhttp_get_request(http, nfd, (struct sockaddr *)&ss, addrlen); 22495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 22505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int 22525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)evhttp_bind_socket(struct evhttp *http, const char *address, u_short port) 22535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 22545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int fd; 22555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int res; 22565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((fd = bind_socket(address, port, 1 /*reuse*/)) == -1) 22585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (-1); 22595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (listen(fd, 128) == -1) { 22615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event_warn("%s: listen", __func__); 22625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EVUTIL_CLOSESOCKET(fd); 22635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (-1); 22645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 22655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) res = evhttp_accept_socket(http, fd); 22675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (res != -1) 22695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event_debug(("Bound to port %d - Awaiting connections ... ", 22705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) port)); 22715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (res); 22735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 22745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int 22765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)evhttp_accept_socket(struct evhttp *http, int fd) 22775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 22785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct evhttp_bound_socket *bound; 22795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct event *ev; 22805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int res; 22815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bound = malloc(sizeof(struct evhttp_bound_socket)); 22835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (bound == NULL) 22845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (-1); 22855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ev = &bound->bind_ev; 22875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Schedule the socket for accepting */ 22895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event_set(ev, fd, EV_READ | EV_PERSIST, accept_socket, http); 22905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EVHTTP_BASE_SET(http, ev); 22915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) res = event_add(ev, NULL); 22935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (res == -1) { 22955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free(bound); 22965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (-1); 22975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 22985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TAILQ_INSERT_TAIL(&http->sockets, bound, next); 23005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (0); 23025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 23035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static struct evhttp* 23055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)evhttp_new_object(void) 23065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 23075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct evhttp *http = NULL; 23085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((http = calloc(1, sizeof(struct evhttp))) == NULL) { 23105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event_warn("%s: calloc", __func__); 23115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (NULL); 23125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 23135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) http->timeout = -1; 23155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TAILQ_INIT(&http->sockets); 23175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TAILQ_INIT(&http->callbacks); 23185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TAILQ_INIT(&http->connections); 23195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (http); 23215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 23225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct evhttp * 23245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)evhttp_new(struct event_base *base) 23255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 23265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct evhttp *http = evhttp_new_object(); 23275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) http->base = base; 23295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (http); 23315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 23325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 23345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Start a web server on the specified address and port. 23355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 23365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct evhttp * 23385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)evhttp_start(const char *address, u_short port) 23395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 23405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct evhttp *http = evhttp_new_object(); 23415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (evhttp_bind_socket(http, address, port) == -1) { 23435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free(http); 23445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (NULL); 23455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 23465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (http); 23485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 23495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void 23515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)evhttp_free(struct evhttp* http) 23525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 23535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct evhttp_cb *http_cb; 23545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct evhttp_connection *evcon; 23555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct evhttp_bound_socket *bound; 23565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int fd; 23575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Remove the accepting part */ 23595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while ((bound = TAILQ_FIRST(&http->sockets)) != NULL) { 23605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TAILQ_REMOVE(&http->sockets, bound, next); 23615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fd = bound->bind_ev.ev_fd; 23635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event_del(&bound->bind_ev); 23645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EVUTIL_CLOSESOCKET(fd); 23655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free(bound); 23675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 23685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while ((evcon = TAILQ_FIRST(&http->connections)) != NULL) { 23705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* evhttp_connection_free removes the connection */ 23715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evhttp_connection_free(evcon); 23725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 23735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while ((http_cb = TAILQ_FIRST(&http->callbacks)) != NULL) { 23755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TAILQ_REMOVE(&http->callbacks, http_cb, next); 23765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free(http_cb->what); 23775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free(http_cb); 23785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 23795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free(http); 23815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 23825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void 23845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)evhttp_set_timeout(struct evhttp* http, int timeout_in_secs) 23855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 23865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) http->timeout = timeout_in_secs; 23875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 23885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void 23905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)evhttp_set_cb(struct evhttp *http, const char *uri, 23915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void (*cb)(struct evhttp_request *, void *), void *cbarg) 23925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 23935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct evhttp_cb *http_cb; 23945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((http_cb = calloc(1, sizeof(struct evhttp_cb))) == NULL) 23965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event_err(1, "%s: calloc", __func__); 23975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) http_cb->what = strdup(uri); 23995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) http_cb->cb = cb; 24005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) http_cb->cbarg = cbarg; 24015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TAILQ_INSERT_TAIL(&http->callbacks, http_cb, next); 24035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 24045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int 24065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)evhttp_del_cb(struct evhttp *http, const char *uri) 24075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 24085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct evhttp_cb *http_cb; 24095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TAILQ_FOREACH(http_cb, &http->callbacks, next) { 24115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (strcmp(http_cb->what, uri) == 0) 24125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 24135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 24145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (http_cb == NULL) 24155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (-1); 24165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TAILQ_REMOVE(&http->callbacks, http_cb, next); 24185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free(http_cb->what); 24195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free(http_cb); 24205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (0); 24225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 24235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void 24255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)evhttp_set_gencb(struct evhttp *http, 24265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void (*cb)(struct evhttp_request *, void *), void *cbarg) 24275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 24285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) http->gencb = cb; 24295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) http->gencbarg = cbarg; 24305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 24315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 24335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Request related functions 24345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 24355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct evhttp_request * 24375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)evhttp_request_new(void (*cb)(struct evhttp_request *, void *), void *arg) 24385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 24395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct evhttp_request *req = NULL; 24405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Allocate request structure */ 24425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((req = calloc(1, sizeof(struct evhttp_request))) == NULL) { 24435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event_warn("%s: calloc", __func__); 24445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) goto error; 24455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 24465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req->kind = EVHTTP_RESPONSE; 24485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req->input_headers = calloc(1, sizeof(struct evkeyvalq)); 24495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (req->input_headers == NULL) { 24505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event_warn("%s: calloc", __func__); 24515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) goto error; 24525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 24535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TAILQ_INIT(req->input_headers); 24545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req->output_headers = calloc(1, sizeof(struct evkeyvalq)); 24565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (req->output_headers == NULL) { 24575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event_warn("%s: calloc", __func__); 24585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) goto error; 24595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 24605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TAILQ_INIT(req->output_headers); 24615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((req->input_buffer = evbuffer_new()) == NULL) { 24635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event_warn("%s: evbuffer_new", __func__); 24645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) goto error; 24655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 24665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((req->output_buffer = evbuffer_new()) == NULL) { 24685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event_warn("%s: evbuffer_new", __func__); 24695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) goto error; 24705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 24715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req->cb = cb; 24735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req->cb_arg = arg; 24745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (req); 24765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error: 24785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (req != NULL) 24795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evhttp_request_free(req); 24805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (NULL); 24815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 24825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void 24845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)evhttp_request_free(struct evhttp_request *req) 24855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 24865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (req->remote_host != NULL) 24875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free(req->remote_host); 24885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (req->uri != NULL) 24895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free(req->uri); 24905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (req->response_code_line != NULL) 24915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free(req->response_code_line); 24925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evhttp_clear_headers(req->input_headers); 24945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free(req->input_headers); 24955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evhttp_clear_headers(req->output_headers); 24975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free(req->output_headers); 24985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (req->input_buffer != NULL) 25005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evbuffer_free(req->input_buffer); 25015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 25025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (req->output_buffer != NULL) 25035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evbuffer_free(req->output_buffer); 25045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 25055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free(req); 25065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 25075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 25085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void 25095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)evhttp_request_set_chunked_cb(struct evhttp_request *req, 25105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void (*cb)(struct evhttp_request *, void *)) 25115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 25125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req->chunk_cb = cb; 25135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 25145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 25155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 25165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Allows for inspection of the request URI 25175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 25185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 25195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char * 25205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)evhttp_request_uri(struct evhttp_request *req) { 25215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (req->uri == NULL) 25225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event_debug(("%s: request %p has no uri\n", __func__, req)); 25235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (req->uri); 25245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 25255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 25265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 25275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Takes a file descriptor to read a request from. 25285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The callback is executed once the whole request has been read. 25295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 25305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 25315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static struct evhttp_connection* 25325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)evhttp_get_request_connection( 25335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct evhttp* http, 25345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int fd, struct sockaddr *sa, socklen_t salen) 25355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 25365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct evhttp_connection *evcon; 25375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char *hostname = NULL, *portname = NULL; 25385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 25395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) name_from_addr(sa, salen, &hostname, &portname); 25405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (hostname == NULL || portname == NULL) { 25415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (hostname) free(hostname); 25425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (portname) free(portname); 25435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (NULL); 25445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 25455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 25465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event_debug(("%s: new request from %s:%s on %d\n", 25475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) __func__, hostname, portname, fd)); 25485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 25495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* we need a connection object to put the http request on */ 25505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evcon = evhttp_connection_new(hostname, atoi(portname)); 25515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free(hostname); 25525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free(portname); 25535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (evcon == NULL) 25545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (NULL); 25555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 25565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* associate the base if we have one*/ 25575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evhttp_connection_set_base(evcon, http->base); 25585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 25595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evcon->flags |= EVHTTP_CON_INCOMING; 25605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evcon->state = EVCON_READING_FIRSTLINE; 25615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 25625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evcon->fd = fd; 25635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 25645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (evcon); 25655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 25665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 25675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int 25685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)evhttp_associate_new_request_with_connection(struct evhttp_connection *evcon) 25695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 25705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct evhttp *http = evcon->http_server; 25715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct evhttp_request *req; 25725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((req = evhttp_request_new(evhttp_handle_request, http)) == NULL) 25735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (-1); 25745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 25755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req->evcon = evcon; /* the request ends up owning the connection */ 25765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req->flags |= EVHTTP_REQ_OWN_CONNECTION; 25775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 25785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TAILQ_INSERT_TAIL(&evcon->requests, req, next); 25795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 25805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req->kind = EVHTTP_REQUEST; 25815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 25825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((req->remote_host = strdup(evcon->address)) == NULL) 25835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event_err(1, "%s: strdup", __func__); 25845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) req->remote_port = evcon->port; 25855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 25865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evhttp_start_read(evcon); 25875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 25885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (0); 25895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 25905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 25915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void 25925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)evhttp_get_request(struct evhttp *http, int fd, 25935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct sockaddr *sa, socklen_t salen) 25945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 25955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct evhttp_connection *evcon; 25965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 25975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evcon = evhttp_get_request_connection(http, fd, sa, salen); 25985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (evcon == NULL) 25995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 26005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 26015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* the timeout can be used by the server to close idle connections */ 26025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (http->timeout != -1) 26035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evhttp_connection_set_timeout(evcon, http->timeout); 26045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 26055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* 26065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * if we want to accept more than one request on a connection, 26075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * we need to know which http server it belongs to. 26085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 26095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evcon->http_server = http; 26105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TAILQ_INSERT_TAIL(&http->connections, evcon, next); 26115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 26125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (evhttp_associate_new_request_with_connection(evcon) == -1) 26135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evhttp_connection_free(evcon); 26145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 26155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 26165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 26175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 26185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Network helper functions that we do not want to export to the rest of 26195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * the world. 26205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 26215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if 0 /* Unused */ 26225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static struct addrinfo * 26235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)addr_from_name(char *address) 26245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 26255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef HAVE_GETADDRINFO 26265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct addrinfo ai, *aitop; 26275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int ai_result; 26285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 26295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memset(&ai, 0, sizeof(ai)); 26305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ai.ai_family = AF_INET; 26315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ai.ai_socktype = SOCK_RAW; 26325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ai.ai_flags = 0; 26335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((ai_result = getaddrinfo(address, NULL, &ai, &aitop)) != 0) { 26345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ( ai_result == EAI_SYSTEM ) 26355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event_warn("getaddrinfo"); 26365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 26375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event_warnx("getaddrinfo: %s", gai_strerror(ai_result)); 26385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 26395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 26405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (aitop); 26415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 26425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert(0); 26435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; /* XXXXX Use gethostbyname, if this function is ever used. */ 26445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 26455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 26465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 26475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 26485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void 26495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)name_from_addr(struct sockaddr *sa, socklen_t salen, 26505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char **phost, char **pport) 26515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 26525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char ntop[NI_MAXHOST]; 26535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char strport[NI_MAXSERV]; 26545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int ni_result; 26555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 26565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef HAVE_GETNAMEINFO 26575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ni_result = getnameinfo(sa, salen, 26585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ntop, sizeof(ntop), strport, sizeof(strport), 26595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NI_NUMERICHOST|NI_NUMERICSERV); 26605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 26615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ni_result != 0) { 26625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ni_result == EAI_SYSTEM) 26635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event_err(1, "getnameinfo failed"); 26645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 26655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event_errx(1, "getnameinfo failed: %s", gai_strerror(ni_result)); 26665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 26675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 26685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 26695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ni_result = fake_getnameinfo(sa, salen, 26705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ntop, sizeof(ntop), strport, sizeof(strport), 26715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NI_NUMERICHOST|NI_NUMERICSERV); 26725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ni_result != 0) 26735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 26745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 26755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *phost = strdup(ntop); 26765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *pport = strdup(strport); 26775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 26785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 26795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Create a non-blocking socket and bind it */ 26805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* todo: rename this function */ 26815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int 26825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bind_socket_ai(struct addrinfo *ai, int reuse) 26835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 26845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int fd, on = 1, r; 26855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int serrno; 26865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 26875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Create listen socket */ 26885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fd = socket(AF_INET, SOCK_STREAM, 0); 26895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (fd == -1) { 26905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event_warn("socket"); 26915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (-1); 26925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 26935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 26945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (evutil_make_socket_nonblocking(fd) < 0) 26955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) goto out; 26965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 26975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef WIN32 26985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (fcntl(fd, F_SETFD, 1) == -1) { 26995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event_warn("fcntl(F_SETFD)"); 27005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) goto out; 27015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 27025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 27035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 27045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (void *)&on, sizeof(on)); 27055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (reuse) { 27065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, 27075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (void *)&on, sizeof(on)); 27085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 27095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 27105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ai != NULL) { 27115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) r = bind(fd, ai->ai_addr, ai->ai_addrlen); 27125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (r == -1) 27135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) goto out; 27145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 27155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 27165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (fd); 27175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 27185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) out: 27195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) serrno = EVUTIL_SOCKET_ERROR(); 27205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EVUTIL_CLOSESOCKET(fd); 27215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EVUTIL_SET_SOCKET_ERROR(serrno); 27225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (-1); 27235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 27245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 27255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static struct addrinfo * 27265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)make_addrinfo(const char *address, u_short port) 27275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 27285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct addrinfo *aitop = NULL; 27295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 27305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef HAVE_GETADDRINFO 27315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct addrinfo ai; 27325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char strport[NI_MAXSERV]; 27335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int ai_result; 27345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 27355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memset(&ai, 0, sizeof(ai)); 27365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ai.ai_family = AF_INET; 27375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ai.ai_socktype = SOCK_STREAM; 27385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ai.ai_flags = AI_PASSIVE; /* turn NULL host name into INADDR_ANY */ 27395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) evutil_snprintf(strport, sizeof(strport), "%d", port); 27405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((ai_result = getaddrinfo(address, strport, &ai, &aitop)) != 0) { 27415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ( ai_result == EAI_SYSTEM ) 27425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event_warn("getaddrinfo"); 27435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 27445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event_warnx("getaddrinfo: %s", gai_strerror(ai_result)); 27455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (NULL); 27465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 27475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 27485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static int cur; 27495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static struct addrinfo ai[2]; /* We will be returning the address of some of this memory so it has to last even after this call. */ 27505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (++cur == 2) cur = 0; /* allow calling this function twice */ 27515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 27525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (fake_getaddrinfo(address, &ai[cur]) < 0) { 27535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event_warn("fake_getaddrinfo"); 27545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (NULL); 27555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 27565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) aitop = &ai[cur]; 27575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ((struct sockaddr_in *) aitop->ai_addr)->sin_port = htons(port); 27585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 27595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 27605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (aitop); 27615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 27625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 27635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int 27645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bind_socket(const char *address, u_short port, int reuse) 27655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 27665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int fd; 27675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct addrinfo *aitop = NULL; 27685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 27695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* just create an unbound socket */ 27705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (address == NULL && port == 0) 27715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return bind_socket_ai(NULL, 0); 27725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 27735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) aitop = make_addrinfo(address, port); 27745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 27755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (aitop == NULL) 27765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (-1); 27775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 27785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fd = bind_socket_ai(aitop, reuse); 27795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 27805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef HAVE_GETADDRINFO 27815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) freeaddrinfo(aitop); 27825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 27835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fake_freeaddrinfo(aitop); 27845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 27855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 27865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (fd); 27875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 27885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 27895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int 27905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)socket_connect(int fd, const char *address, unsigned short port) 27915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 27925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct addrinfo *ai = make_addrinfo(address, port); 27935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int res = -1; 27945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 27955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ai == NULL) { 27965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event_debug(("%s: make_addrinfo: \"%s:%d\"", 27975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) __func__, address, port)); 27985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (-1); 27995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 28005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 28015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (connect(fd, ai->ai_addr, ai->ai_addrlen) == -1) { 28025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef WIN32 28035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int tmp_error = WSAGetLastError(); 28045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (tmp_error != WSAEWOULDBLOCK && tmp_error != WSAEINVAL && 28055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tmp_error != WSAEINPROGRESS) { 28065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) goto out; 28075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 28085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 28095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (errno != EINPROGRESS) { 28105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) goto out; 28115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 28125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 28135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 28145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 28155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* everything is fine */ 28165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) res = 0; 28175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 28185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)out: 28195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef HAVE_GETADDRINFO 28205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) freeaddrinfo(ai); 28215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 28225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fake_freeaddrinfo(ai); 28235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 28245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 28255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (res); 28265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2827