LCOV - code coverage report
Current view: directory - ipc/chromium/src/third_party/libevent - http.c (source / functions) Found Hit Coverage
Test: app.info Lines: 1115 0 0.0 %
Date: 2012-06-02 Functions: 92 0 0.0 %

       1                 : /*
       2                 :  * Copyright (c) 2002-2006 Niels Provos <provos@citi.umich.edu>
       3                 :  * All rights reserved.
       4                 :  *
       5                 :  * Redistribution and use in source and binary forms, with or without
       6                 :  * modification, are permitted provided that the following conditions
       7                 :  * are met:
       8                 :  * 1. Redistributions of source code must retain the above copyright
       9                 :  *    notice, this list of conditions and the following disclaimer.
      10                 :  * 2. Redistributions in binary form must reproduce the above copyright
      11                 :  *    notice, this list of conditions and the following disclaimer in the
      12                 :  *    documentation and/or other materials provided with the distribution.
      13                 :  * 3. The name of the author may not be used to endorse or promote products
      14                 :  *    derived from this software without specific prior written permission.
      15                 :  *
      16                 :  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
      17                 :  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
      18                 :  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
      19                 :  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
      20                 :  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
      21                 :  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
      22                 :  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
      23                 :  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
      24                 :  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
      25                 :  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
      26                 :  */
      27                 : 
      28                 : #ifdef HAVE_CONFIG_H
      29                 : #include "config.h"
      30                 : #endif
      31                 : 
      32                 : #ifdef HAVE_SYS_PARAM_H
      33                 : #include <sys/param.h>
      34                 : #endif
      35                 : #ifdef HAVE_SYS_TYPES_H
      36                 : #include <sys/types.h>
      37                 : #endif
      38                 : 
      39                 : #ifdef HAVE_SYS_TIME_H
      40                 : #include <sys/time.h>
      41                 : #endif
      42                 : #ifdef HAVE_SYS_IOCCOM_H
      43                 : #include <sys/ioccom.h>
      44                 : #endif
      45                 : 
      46                 : #ifndef WIN32
      47                 : #include <sys/resource.h>
      48                 : #include <sys/socket.h>
      49                 : #include <sys/stat.h>
      50                 : #include <sys/wait.h>
      51                 : #endif
      52                 : 
      53                 : #include <sys/queue.h>
      54                 : 
      55                 : #ifndef WIN32
      56                 : #include <netinet/in.h>
      57                 : #include <netdb.h>
      58                 : #endif
      59                 : 
      60                 : #ifdef WIN32
      61                 : #include <winsock2.h>
      62                 : #endif
      63                 : 
      64                 : #include <assert.h>
      65                 : #include <ctype.h>
      66                 : #include <errno.h>
      67                 : #include <stdio.h>
      68                 : #include <stdlib.h>
      69                 : #include <string.h>
      70                 : #ifndef WIN32
      71                 : #include <syslog.h>
      72                 : #endif
      73                 : #include <signal.h>
      74                 : #include <time.h>
      75                 : #ifdef HAVE_UNISTD_H
      76                 : #include <unistd.h>
      77                 : #endif
      78                 : #ifdef HAVE_FCNTL_H
      79                 : #include <fcntl.h>
      80                 : #endif
      81                 : 
      82                 : #undef timeout_pending
      83                 : #undef timeout_initialized
      84                 : 
      85                 : #include "strlcpy-internal.h"
      86                 : #include "event.h"
      87                 : #include "evhttp.h"
      88                 : #include "evutil.h"
      89                 : #include "log.h"
      90                 : #include "http-internal.h"
      91                 : #include "event-internal.h"
      92                 : 
      93                 : #ifdef WIN32
      94                 : #define strcasecmp _stricmp
      95                 : #define strncasecmp _strnicmp
      96                 : #define strdup _strdup
      97                 : #endif
      98                 : 
      99                 : #ifndef HAVE_GETNAMEINFO
     100                 : #define NI_MAXSERV 32
     101                 : #define NI_MAXHOST 1025
     102                 : 
     103                 : #define NI_NUMERICHOST 1
     104                 : #define NI_NUMERICSERV 2
     105                 : 
     106                 : int
     107                 : fake_getnameinfo(const struct sockaddr *sa, size_t salen, char *host, 
     108                 :         size_t hostlen, char *serv, size_t servlen, int flags)
     109                 : {
     110                 :         struct sockaddr_in *sin = (struct sockaddr_in *)sa;
     111                 :         
     112                 :         if (serv != NULL) {
     113                 :                                 char tmpserv[16];
     114                 :                                 evutil_snprintf(tmpserv, sizeof(tmpserv),
     115                 :                                         "%d", ntohs(sin->sin_port));
     116                 :                 if (strlcpy(serv, tmpserv, servlen) >= servlen)
     117                 :                         return (-1);
     118                 :         }
     119                 : 
     120                 :         if (host != NULL) {
     121                 :                 if (flags & NI_NUMERICHOST) {
     122                 :                         if (strlcpy(host, inet_ntoa(sin->sin_addr),
     123                 :                             hostlen) >= hostlen)
     124                 :                                 return (-1);
     125                 :                         else
     126                 :                                 return (0);
     127                 :                 } else {
     128                 :                                                 struct hostent *hp;
     129                 :                         hp = gethostbyaddr((char *)&sin->sin_addr, 
     130                 :                             sizeof(struct in_addr), AF_INET);
     131                 :                         if (hp == NULL)
     132                 :                                 return (-2);
     133                 :                         
     134                 :                         if (strlcpy(host, hp->h_name, hostlen) >= hostlen)
     135                 :                                 return (-1);
     136                 :                         else
     137                 :                                 return (0);
     138                 :                 }
     139                 :         }
     140                 :         return (0);
     141                 : }
     142                 : 
     143                 : #endif
     144                 : 
     145                 : #ifndef HAVE_GETADDRINFO
     146                 : struct addrinfo {
     147                 :         int ai_family;
     148                 :         int ai_socktype;
     149                 :         int ai_protocol;
     150                 :         size_t ai_addrlen;
     151                 :         struct sockaddr *ai_addr;
     152                 :         struct addrinfo *ai_next;
     153                 : };
     154                 : static int
     155                 : fake_getaddrinfo(const char *hostname, struct addrinfo *ai)
     156                 : {
     157                 :         struct hostent *he = NULL;
     158                 :         struct sockaddr_in *sa;
     159                 :         if (hostname) {
     160                 :                 he = gethostbyname(hostname);
     161                 :                 if (!he)
     162                 :                         return (-1);
     163                 :         }
     164                 :         ai->ai_family = he ? he->h_addrtype : AF_INET;
     165                 :         ai->ai_socktype = SOCK_STREAM;
     166                 :         ai->ai_protocol = 0;
     167                 :         ai->ai_addrlen = sizeof(struct sockaddr_in);
     168                 :         if (NULL == (ai->ai_addr = malloc(ai->ai_addrlen)))
     169                 :                 return (-1);
     170                 :         sa = (struct sockaddr_in*)ai->ai_addr;
     171                 :         memset(sa, 0, ai->ai_addrlen);
     172                 :         if (he) {
     173                 :                 sa->sin_family = he->h_addrtype;
     174                 :                 memcpy(&sa->sin_addr, he->h_addr_list[0], he->h_length);
     175                 :         } else {
     176                 :                 sa->sin_family = AF_INET;
     177                 :                 sa->sin_addr.s_addr = INADDR_ANY;
     178                 :         }
     179                 :         ai->ai_next = NULL;
     180                 :         return (0);
     181                 : }
     182                 : static void
     183                 : fake_freeaddrinfo(struct addrinfo *ai)
     184                 : {
     185                 :         free(ai->ai_addr);
     186                 : }
     187                 : #endif
     188                 : 
     189                 : #ifndef MIN
     190                 : #define MIN(a,b) (((a)<(b))?(a):(b))
     191                 : #endif
     192                 : 
     193                 : /* wrapper for setting the base from the http server */
     194                 : #define EVHTTP_BASE_SET(x, y) do { \
     195                 :         if ((x)->base != NULL) event_base_set((x)->base, y);      \
     196                 : } while (0) 
     197                 : 
     198                 : extern int debug;
     199                 : 
     200                 : static int socket_connect(int fd, const char *address, unsigned short port);
     201                 : static int bind_socket_ai(struct addrinfo *, int reuse);
     202                 : static int bind_socket(const char *, u_short, int reuse);
     203                 : static void name_from_addr(struct sockaddr *, socklen_t, char **, char **);
     204                 : static int evhttp_associate_new_request_with_connection(
     205                 :         struct evhttp_connection *evcon);
     206                 : static void evhttp_connection_start_detectclose(
     207                 :         struct evhttp_connection *evcon);
     208                 : static void evhttp_connection_stop_detectclose(
     209                 :         struct evhttp_connection *evcon);
     210                 : static void evhttp_request_dispatch(struct evhttp_connection* evcon);
     211                 : static void evhttp_read_firstline(struct evhttp_connection *evcon,
     212                 :                                   struct evhttp_request *req);
     213                 : static void evhttp_read_header(struct evhttp_connection *evcon,
     214                 :     struct evhttp_request *req);
     215                 : 
     216                 : void evhttp_read(int, short, void *);
     217                 : void evhttp_write(int, short, void *);
     218                 : 
     219                 : #ifndef HAVE_STRSEP
     220                 : /* strsep replacement for platforms that lack it.  Only works if
     221                 :  * del is one character long. */
     222                 : static char *
     223                 : strsep(char **s, const char *del)
     224                 : {
     225                 :         char *d, *tok;
     226                 :         assert(strlen(del) == 1);
     227                 :         if (!s || !*s)
     228                 :                 return NULL;
     229                 :         tok = *s;
     230                 :         d = strstr(tok, del);
     231                 :         if (d) {
     232                 :                 *d = '\0';
     233                 :                 *s = d + 1;
     234                 :         } else
     235                 :                 *s = NULL;
     236                 :         return tok;
     237                 : }
     238                 : #endif
     239                 : 
     240                 : static const char *
     241               0 : html_replace(char ch, char *buf)
     242                 : {
     243               0 :         switch (ch) {
     244                 :         case '<':
     245               0 :                 return "&lt;";
     246                 :         case '>':
     247               0 :                 return "&gt;";
     248                 :         case '"':
     249               0 :                 return "&quot;";
     250                 :         case '\'':
     251               0 :                 return "&#039;";
     252                 :         case '&':
     253               0 :                 return "&amp;";
     254                 :         default:
     255                 :                 break;
     256                 :         }
     257                 : 
     258                 :         /* Echo the character back */
     259               0 :         buf[0] = ch;
     260               0 :         buf[1] = '\0';
     261                 :         
     262               0 :         return buf;
     263                 : }
     264                 : 
     265                 : /*
     266                 :  * Replaces <, >, ", ' and & with &lt;, &gt;, &quot;,
     267                 :  * &#039; and &amp; correspondingly.
     268                 :  *
     269                 :  * The returned string needs to be freed by the caller.
     270                 :  */
     271                 : 
     272                 : char *
     273               0 : evhttp_htmlescape(const char *html)
     274                 : {
     275               0 :         int i, new_size = 0, old_size = strlen(html);
     276                 :         char *escaped_html, *p;
     277                 :         char scratch_space[2];
     278                 :         
     279               0 :         for (i = 0; i < old_size; ++i)
     280               0 :           new_size += strlen(html_replace(html[i], scratch_space));
     281                 : 
     282               0 :         p = escaped_html = malloc(new_size + 1);
     283               0 :         if (escaped_html == NULL)
     284               0 :                 event_err(1, "%s: malloc(%d)", __func__, new_size + 1);
     285               0 :         for (i = 0; i < old_size; ++i) {
     286               0 :                 const char *replaced = html_replace(html[i], scratch_space);
     287                 :                 /* this is length checked */
     288               0 :                 strcpy(p, replaced);
     289               0 :                 p += strlen(replaced);
     290                 :         }
     291                 : 
     292               0 :         *p = '\0';
     293                 : 
     294               0 :         return (escaped_html);
     295                 : }
     296                 : 
     297                 : static const char *
     298               0 : evhttp_method(enum evhttp_cmd_type type)
     299                 : {
     300                 :         const char *method;
     301                 : 
     302               0 :         switch (type) {
     303                 :         case EVHTTP_REQ_GET:
     304               0 :                 method = "GET";
     305               0 :                 break;
     306                 :         case EVHTTP_REQ_POST:
     307               0 :                 method = "POST";
     308               0 :                 break;
     309                 :         case EVHTTP_REQ_HEAD:
     310               0 :                 method = "HEAD";
     311               0 :                 break;
     312                 :         default:
     313               0 :                 method = NULL;
     314               0 :                 break;
     315                 :         }
     316                 : 
     317               0 :         return (method);
     318                 : }
     319                 : 
     320                 : static void
     321               0 : evhttp_add_event(struct event *ev, int timeout, int default_timeout)
     322                 : {
     323               0 :         if (timeout != 0) {
     324                 :                 struct timeval tv;
     325                 :                 
     326               0 :                 evutil_timerclear(&tv);
     327               0 :                 tv.tv_sec = timeout != -1 ? timeout : default_timeout;
     328               0 :                 event_add(ev, &tv);
     329                 :         } else {
     330               0 :                 event_add(ev, NULL);
     331                 :         }
     332               0 : }
     333                 : 
     334                 : void
     335               0 : evhttp_write_buffer(struct evhttp_connection *evcon,
     336                 :     void (*cb)(struct evhttp_connection *, void *), void *arg)
     337                 : {
     338                 :         event_debug(("%s: preparing to write buffer\n", __func__));
     339                 : 
     340                 :         /* Set call back */
     341               0 :         evcon->cb = cb;
     342               0 :         evcon->cb_arg = arg;
     343                 : 
     344                 :         /* check if the event is already pending */
     345               0 :         if (event_pending(&evcon->ev, EV_WRITE|EV_TIMEOUT, NULL))
     346               0 :                 event_del(&evcon->ev);
     347                 : 
     348               0 :         event_set(&evcon->ev, evcon->fd, EV_WRITE, evhttp_write, evcon);
     349               0 :         EVHTTP_BASE_SET(evcon, &evcon->ev);
     350               0 :         evhttp_add_event(&evcon->ev, evcon->timeout, HTTP_WRITE_TIMEOUT);
     351               0 : }
     352                 : 
     353                 : static int
     354               0 : evhttp_connected(struct evhttp_connection *evcon)
     355                 : {
     356               0 :         switch (evcon->state) {
     357                 :         case EVCON_DISCONNECTED:
     358                 :         case EVCON_CONNECTING:
     359               0 :                 return (0);
     360                 :         case EVCON_IDLE:
     361                 :         case EVCON_READING_FIRSTLINE:
     362                 :         case EVCON_READING_HEADERS:
     363                 :         case EVCON_READING_BODY:
     364                 :         case EVCON_READING_TRAILER:
     365                 :         case EVCON_WRITING:
     366                 :         default:
     367               0 :                 return (1);
     368                 :         }
     369                 : }
     370                 : 
     371                 : /*
     372                 :  * Create the headers need for an HTTP request
     373                 :  */
     374                 : static void
     375               0 : evhttp_make_header_request(struct evhttp_connection *evcon,
     376                 :     struct evhttp_request *req)
     377                 : {
     378                 :         char line[1024];
     379                 :         const char *method;
     380                 :         
     381               0 :         evhttp_remove_header(req->output_headers, "Accept-Encoding");
     382               0 :         evhttp_remove_header(req->output_headers, "Proxy-Connection");
     383                 : 
     384                 :         /* Generate request line */
     385               0 :         method = evhttp_method(req->type);
     386               0 :         evutil_snprintf(line, sizeof(line), "%s %s HTTP/%d.%d\r\n",
     387               0 :             method, req->uri, req->major, req->minor);
     388               0 :         evbuffer_add(evcon->output_buffer, line, strlen(line));
     389                 : 
     390                 :         /* Add the content length on a post request if missing */
     391               0 :         if (req->type == EVHTTP_REQ_POST &&
     392               0 :             evhttp_find_header(req->output_headers, "Content-Length") == NULL){
     393                 :                 char size[12];
     394               0 :                 evutil_snprintf(size, sizeof(size), "%ld",
     395               0 :                     (long)EVBUFFER_LENGTH(req->output_buffer));
     396               0 :                 evhttp_add_header(req->output_headers, "Content-Length", size);
     397                 :         }
     398               0 : }
     399                 : 
     400                 : static int
     401               0 : evhttp_is_connection_close(int flags, struct evkeyvalq* headers)
     402                 : {
     403               0 :         if (flags & EVHTTP_PROXY_REQUEST) {
     404                 :                 /* proxy connection */
     405               0 :                 const char *connection = evhttp_find_header(headers, "Proxy-Connection");
     406               0 :                 return (connection == NULL || strcasecmp(connection, "keep-alive") != 0);
     407                 :         } else {
     408               0 :                 const char *connection = evhttp_find_header(headers, "Connection");
     409               0 :                 return (connection != NULL && strcasecmp(connection, "close") == 0);
     410                 :         }
     411                 : }
     412                 : 
     413                 : static int
     414               0 : evhttp_is_connection_keepalive(struct evkeyvalq* headers)
     415                 : {
     416               0 :         const char *connection = evhttp_find_header(headers, "Connection");
     417               0 :         return (connection != NULL 
     418               0 :             && strncasecmp(connection, "keep-alive", 10) == 0);
     419                 : }
     420                 : 
     421                 : static void
     422               0 : evhttp_maybe_add_date_header(struct evkeyvalq *headers)
     423                 : {
     424               0 :         if (evhttp_find_header(headers, "Date") == NULL) {
     425                 :                 char date[50];
     426                 : #ifndef WIN32
     427                 :                 struct tm cur;
     428                 : #endif
     429                 :                 struct tm *cur_p;
     430               0 :                 time_t t = time(NULL);
     431                 : #ifdef WIN32
     432                 :                 cur_p = gmtime(&t);
     433                 : #else
     434               0 :                 gmtime_r(&t, &cur);
     435               0 :                 cur_p = &cur;
     436                 : #endif
     437               0 :                 if (strftime(date, sizeof(date),
     438                 :                         "%a, %d %b %Y %H:%M:%S GMT", cur_p) != 0) {
     439               0 :                         evhttp_add_header(headers, "Date", date);
     440                 :                 }
     441                 :         }
     442               0 : }
     443                 : 
     444                 : static void
     445               0 : evhttp_maybe_add_content_length_header(struct evkeyvalq *headers,
     446                 :     long content_length)
     447                 : {
     448               0 :         if (evhttp_find_header(headers, "Transfer-Encoding") == NULL &&
     449               0 :             evhttp_find_header(headers, "Content-Length") == NULL) {
     450                 :                 char len[12];
     451               0 :                 evutil_snprintf(len, sizeof(len), "%ld", content_length);
     452               0 :                 evhttp_add_header(headers, "Content-Length", len);
     453                 :         }
     454               0 : }
     455                 : 
     456                 : /*
     457                 :  * Create the headers needed for an HTTP reply
     458                 :  */
     459                 : 
     460                 : static void
     461               0 : evhttp_make_header_response(struct evhttp_connection *evcon,
     462                 :     struct evhttp_request *req)
     463                 : {
     464               0 :         int is_keepalive = evhttp_is_connection_keepalive(req->input_headers);
     465                 :         char line[1024];
     466               0 :         evutil_snprintf(line, sizeof(line), "HTTP/%d.%d %d %s\r\n",
     467               0 :             req->major, req->minor, req->response_code,
     468                 :             req->response_code_line);
     469               0 :         evbuffer_add(evcon->output_buffer, line, strlen(line));
     470                 : 
     471               0 :         if (req->major == 1) {
     472               0 :                 if (req->minor == 1)
     473               0 :                         evhttp_maybe_add_date_header(req->output_headers);
     474                 : 
     475                 :                 /*
     476                 :                  * if the protocol is 1.0; and the connection was keep-alive
     477                 :                  * we need to add a keep-alive header, too.
     478                 :                  */
     479               0 :                 if (req->minor == 0 && is_keepalive)
     480               0 :                         evhttp_add_header(req->output_headers,
     481                 :                             "Connection", "keep-alive");
     482                 : 
     483               0 :                 if (req->minor == 1 || is_keepalive) {
     484                 :                         /* 
     485                 :                          * we need to add the content length if the
     486                 :                          * user did not give it, this is required for
     487                 :                          * persistent connections to work.
     488                 :                          */
     489               0 :                         evhttp_maybe_add_content_length_header(
     490                 :                                 req->output_headers,
     491               0 :                                 (long)EVBUFFER_LENGTH(req->output_buffer));
     492                 :                 }
     493                 :         }
     494                 : 
     495                 :         /* Potentially add headers for unidentified content. */
     496               0 :         if (EVBUFFER_LENGTH(req->output_buffer)) {
     497               0 :                 if (evhttp_find_header(req->output_headers,
     498                 :                         "Content-Type") == NULL) {
     499               0 :                         evhttp_add_header(req->output_headers,
     500                 :                             "Content-Type", "text/html; charset=ISO-8859-1");
     501                 :                 }
     502                 :         }
     503                 : 
     504                 :         /* if the request asked for a close, we send a close, too */
     505               0 :         if (evhttp_is_connection_close(req->flags, req->input_headers)) {
     506               0 :                 evhttp_remove_header(req->output_headers, "Connection");
     507               0 :                 if (!(req->flags & EVHTTP_PROXY_REQUEST))
     508               0 :                     evhttp_add_header(req->output_headers, "Connection", "close");
     509               0 :                 evhttp_remove_header(req->output_headers, "Proxy-Connection");
     510                 :         }
     511               0 : }
     512                 : 
     513                 : void
     514               0 : evhttp_make_header(struct evhttp_connection *evcon, struct evhttp_request *req)
     515                 : {
     516                 :         char line[1024];
     517                 :         struct evkeyval *header;
     518                 : 
     519                 :         /*
     520                 :          * Depending if this is a HTTP request or response, we might need to
     521                 :          * add some new headers or remove existing headers.
     522                 :          */
     523               0 :         if (req->kind == EVHTTP_REQUEST) {
     524               0 :                 evhttp_make_header_request(evcon, req);
     525                 :         } else {
     526               0 :                 evhttp_make_header_response(evcon, req);
     527                 :         }
     528                 : 
     529               0 :         TAILQ_FOREACH(header, req->output_headers, next) {
     530               0 :                 evutil_snprintf(line, sizeof(line), "%s: %s\r\n",
     531                 :                     header->key, header->value);
     532               0 :                 evbuffer_add(evcon->output_buffer, line, strlen(line));
     533                 :         }
     534               0 :         evbuffer_add(evcon->output_buffer, "\r\n", 2);
     535                 : 
     536               0 :         if (EVBUFFER_LENGTH(req->output_buffer) > 0) {
     537                 :                 /*
     538                 :                  * For a request, we add the POST data, for a reply, this
     539                 :                  * is the regular data.
     540                 :                  */
     541               0 :                 evbuffer_add_buffer(evcon->output_buffer, req->output_buffer);
     542                 :         }
     543               0 : }
     544                 : 
     545                 : /* Separated host, port and file from URI */
     546                 : 
     547                 : int
     548               0 : evhttp_hostportfile(char *url, char **phost, u_short *pport, char **pfile)
     549                 : {
     550                 :         /* XXX not threadsafe. */
     551                 :         static char host[1024];
     552                 :         static char file[1024];
     553                 :         char *p;
     554                 :         const char *p2;
     555                 :         int len;
     556                 :         u_short port;
     557                 : 
     558               0 :         len = strlen(HTTP_PREFIX);
     559               0 :         if (strncasecmp(url, HTTP_PREFIX, len))
     560               0 :                 return (-1);
     561                 : 
     562               0 :         url += len;
     563                 : 
     564                 :         /* We might overrun */
     565               0 :         if (strlcpy(host, url, sizeof (host)) >= sizeof(host))
     566               0 :                 return (-1);
     567                 : 
     568               0 :         p = strchr(host, '/');
     569               0 :         if (p != NULL) {
     570               0 :                 *p = '\0';
     571               0 :                 p2 = p + 1;
     572                 :         } else
     573               0 :                 p2 = NULL;
     574                 : 
     575               0 :         if (pfile != NULL) {
     576                 :                 /* Generate request file */
     577               0 :                 if (p2 == NULL)
     578               0 :                         p2 = "";
     579               0 :                 evutil_snprintf(file, sizeof(file), "/%s", p2);
     580                 :         }
     581                 : 
     582               0 :         p = strchr(host, ':');
     583               0 :         if (p != NULL) {
     584               0 :                 *p = '\0';
     585               0 :                 port = atoi(p + 1);
     586                 : 
     587               0 :                 if (port == 0)
     588               0 :                         return (-1);
     589                 :         } else
     590               0 :                 port = HTTP_DEFAULTPORT;
     591                 : 
     592               0 :         if (phost != NULL)
     593               0 :                 *phost = host;
     594               0 :         if (pport != NULL)
     595               0 :                 *pport = port;
     596               0 :         if (pfile != NULL)
     597               0 :                 *pfile = file;
     598                 : 
     599               0 :         return (0);
     600                 : }
     601                 : 
     602                 : static int
     603               0 : evhttp_connection_incoming_fail(struct evhttp_request *req,
     604                 :     enum evhttp_connection_error error)
     605                 : {
     606               0 :         switch (error) {
     607                 :         case EVCON_HTTP_TIMEOUT:
     608                 :         case EVCON_HTTP_EOF:
     609                 :                 /* 
     610                 :                  * these are cases in which we probably should just
     611                 :                  * close the connection and not send a reply.  this
     612                 :                  * case may happen when a browser keeps a persistent
     613                 :                  * connection open and we timeout on the read.
     614                 :                  */
     615               0 :                 return (-1);
     616                 :         case EVCON_HTTP_INVALID_HEADER:
     617                 :         default:        /* xxx: probably should just error on default */
     618                 :                 /* the callback looks at the uri to determine errors */
     619               0 :                 if (req->uri) {
     620               0 :                         free(req->uri);
     621               0 :                         req->uri = NULL;
     622                 :                 }
     623                 : 
     624                 :                 /* 
     625                 :                  * the callback needs to send a reply, once the reply has
     626                 :                  * been send, the connection should get freed.
     627                 :                  */
     628               0 :                 (*req->cb)(req, req->cb_arg);
     629                 :         }
     630                 :         
     631               0 :         return (0);
     632                 : }
     633                 : 
     634                 : void
     635               0 : evhttp_connection_fail(struct evhttp_connection *evcon,
     636                 :     enum evhttp_connection_error error)
     637                 : {
     638               0 :         struct evhttp_request* req = TAILQ_FIRST(&evcon->requests);
     639                 :         void (*cb)(struct evhttp_request *, void *);
     640                 :         void *cb_arg;
     641               0 :         assert(req != NULL);
     642                 :         
     643               0 :         if (evcon->flags & EVHTTP_CON_INCOMING) {
     644                 :                 /* 
     645                 :                  * for incoming requests, there are two different
     646                 :                  * failure cases.  it's either a network level error
     647                 :                  * or an http layer error. for problems on the network
     648                 :                  * layer like timeouts we just drop the connections.
     649                 :                  * For HTTP problems, we might have to send back a
     650                 :                  * reply before the connection can be freed.
     651                 :                  */
     652               0 :                 if (evhttp_connection_incoming_fail(req, error) == -1)
     653               0 :                         evhttp_connection_free(evcon);
     654               0 :                 return;
     655                 :         }
     656                 : 
     657                 :         /* save the callback for later; the cb might free our object */
     658               0 :         cb = req->cb;
     659               0 :         cb_arg = req->cb_arg;
     660                 : 
     661               0 :         TAILQ_REMOVE(&evcon->requests, req, next);
     662               0 :         evhttp_request_free(req);
     663                 : 
     664                 :         /* xxx: maybe we should fail all requests??? */
     665                 : 
     666                 :         /* reset the connection */
     667               0 :         evhttp_connection_reset(evcon);
     668                 :         
     669                 :         /* We are trying the next request that was queued on us */
     670               0 :         if (TAILQ_FIRST(&evcon->requests) != NULL)
     671               0 :                 evhttp_connection_connect(evcon);
     672                 : 
     673                 :         /* inform the user */
     674               0 :         if (cb != NULL)
     675               0 :                 (*cb)(NULL, cb_arg);
     676                 : }
     677                 : 
     678                 : void
     679               0 : evhttp_write(int fd, short what, void *arg)
     680                 : {
     681               0 :         struct evhttp_connection *evcon = arg;
     682                 :         int n;
     683                 : 
     684               0 :         if (what == EV_TIMEOUT) {
     685               0 :                 evhttp_connection_fail(evcon, EVCON_HTTP_TIMEOUT);
     686               0 :                 return;
     687                 :         }
     688                 : 
     689               0 :         n = evbuffer_write(evcon->output_buffer, fd);
     690               0 :         if (n == -1) {
     691                 :                 event_debug(("%s: evbuffer_write", __func__));
     692               0 :                 evhttp_connection_fail(evcon, EVCON_HTTP_EOF);
     693               0 :                 return;
     694                 :         }
     695                 : 
     696               0 :         if (n == 0) {
     697                 :                 event_debug(("%s: write nothing", __func__));
     698               0 :                 evhttp_connection_fail(evcon, EVCON_HTTP_EOF);
     699               0 :                 return;
     700                 :         }
     701                 : 
     702               0 :         if (EVBUFFER_LENGTH(evcon->output_buffer) != 0) {
     703               0 :                 evhttp_add_event(&evcon->ev, 
     704                 :                     evcon->timeout, HTTP_WRITE_TIMEOUT);
     705               0 :                 return;
     706                 :         }
     707                 : 
     708                 :         /* Activate our call back */
     709               0 :         if (evcon->cb != NULL)
     710               0 :                 (*evcon->cb)(evcon, evcon->cb_arg);
     711                 : }
     712                 : 
     713                 : /**
     714                 :  * Advance the connection state.
     715                 :  * - If this is an outgoing connection, we've just processed the response;
     716                 :  *   idle or close the connection.
     717                 :  * - If this is an incoming connection, we've just processed the request;
     718                 :  *   respond.
     719                 :  */
     720                 : static void
     721               0 : evhttp_connection_done(struct evhttp_connection *evcon)
     722                 : {
     723               0 :         struct evhttp_request *req = TAILQ_FIRST(&evcon->requests);
     724               0 :         int con_outgoing = evcon->flags & EVHTTP_CON_OUTGOING;
     725                 : 
     726               0 :         if (con_outgoing) {
     727                 :                 /* idle or close the connection */
     728                 :                 int need_close;
     729               0 :                 TAILQ_REMOVE(&evcon->requests, req, next);
     730               0 :                 req->evcon = NULL;
     731                 : 
     732               0 :                 evcon->state = EVCON_IDLE;
     733                 : 
     734               0 :                 need_close = 
     735               0 :                     evhttp_is_connection_close(req->flags, req->input_headers)||
     736               0 :                     evhttp_is_connection_close(req->flags, req->output_headers);
     737                 : 
     738                 :                 /* check if we got asked to close the connection */
     739               0 :                 if (need_close)
     740               0 :                         evhttp_connection_reset(evcon);
     741                 : 
     742               0 :                 if (TAILQ_FIRST(&evcon->requests) != NULL) {
     743                 :                         /*
     744                 :                          * We have more requests; reset the connection
     745                 :                          * and deal with the next request.
     746                 :                          */
     747               0 :                         if (!evhttp_connected(evcon))
     748               0 :                                 evhttp_connection_connect(evcon);
     749                 :                         else
     750               0 :                                 evhttp_request_dispatch(evcon);
     751               0 :                 } else if (!need_close) {
     752                 :                         /*
     753                 :                          * The connection is going to be persistent, but we
     754                 :                          * need to detect if the other side closes it.
     755                 :                          */
     756               0 :                         evhttp_connection_start_detectclose(evcon);
     757                 :                 }
     758                 :         } else {
     759                 :                 /*
     760                 :                  * incoming connection - we need to leave the request on the
     761                 :                  * connection so that we can reply to it.
     762                 :                  */
     763               0 :                 evcon->state = EVCON_WRITING;
     764                 :         }
     765                 : 
     766                 :         /* notify the user of the request */
     767               0 :         (*req->cb)(req, req->cb_arg);
     768                 : 
     769                 :         /* if this was an outgoing request, we own and it's done. so free it */
     770               0 :         if (con_outgoing) {
     771               0 :                 evhttp_request_free(req);
     772                 :         }
     773               0 : }
     774                 : 
     775                 : /*
     776                 :  * Handles reading from a chunked request.
     777                 :  *   return ALL_DATA_READ:
     778                 :  *     all data has been read
     779                 :  *   return MORE_DATA_EXPECTED:
     780                 :  *     more data is expected
     781                 :  *   return DATA_CORRUPTED:
     782                 :  *     data is corrupted
     783                 :  *   return REQUEST_CANCLED:
     784                 :  *     request was canceled by the user calling evhttp_cancel_request
     785                 :  */
     786                 : 
     787                 : static enum message_read_status
     788               0 : evhttp_handle_chunked_read(struct evhttp_request *req, struct evbuffer *buf)
     789                 : {
     790                 :         int len;
     791                 : 
     792               0 :         while ((len = EVBUFFER_LENGTH(buf)) > 0) {
     793               0 :                 if (req->ntoread < 0) {
     794                 :                         /* Read chunk size */
     795                 :                         ev_int64_t ntoread;
     796               0 :                         char *p = evbuffer_readline(buf);
     797                 :                         char *endp;
     798                 :                         int error;
     799               0 :                         if (p == NULL)
     800               0 :                                 break;
     801                 :                         /* the last chunk is on a new line? */
     802               0 :                         if (strlen(p) == 0) {
     803               0 :                                 free(p);
     804               0 :                                 continue;
     805                 :                         }
     806               0 :                         ntoread = evutil_strtoll(p, &endp, 16);
     807               0 :                         error = (*p == '\0' ||
     808               0 :                             (*endp != '\0' && *endp != ' ') ||
     809                 :                             ntoread < 0);
     810               0 :                         free(p);
     811               0 :                         if (error) {
     812                 :                                 /* could not get chunk size */
     813               0 :                                 return (DATA_CORRUPTED);
     814                 :                         }
     815               0 :                         req->ntoread = ntoread;
     816               0 :                         if (req->ntoread == 0) {
     817                 :                                 /* Last chunk */
     818               0 :                                 return (ALL_DATA_READ);
     819                 :                         }
     820               0 :                         continue;
     821                 :                 }
     822                 : 
     823                 :                 /* don't have enough to complete a chunk; wait for more */
     824               0 :                 if (len < req->ntoread)
     825               0 :                         return (MORE_DATA_EXPECTED);
     826                 : 
     827                 :                 /* Completed chunk */
     828               0 :                 evbuffer_add(req->input_buffer,
     829               0 :                     EVBUFFER_DATA(buf), req->ntoread);
     830               0 :                 evbuffer_drain(buf, req->ntoread);
     831               0 :                 req->ntoread = -1;
     832               0 :                 if (req->chunk_cb != NULL) {
     833               0 :                         (*req->chunk_cb)(req, req->cb_arg);
     834               0 :                         evbuffer_drain(req->input_buffer,
     835               0 :                             EVBUFFER_LENGTH(req->input_buffer));
     836                 :                 }
     837                 :         }
     838                 : 
     839               0 :         return (MORE_DATA_EXPECTED);
     840                 : }
     841                 : 
     842                 : static void
     843               0 : evhttp_read_trailer(struct evhttp_connection *evcon, struct evhttp_request *req)
     844                 : {
     845               0 :         struct evbuffer *buf = evcon->input_buffer;
     846                 : 
     847               0 :         switch (evhttp_parse_headers(req, buf)) {
     848                 :         case DATA_CORRUPTED:
     849               0 :                 evhttp_connection_fail(evcon, EVCON_HTTP_INVALID_HEADER);
     850               0 :                 break;
     851                 :         case ALL_DATA_READ:
     852               0 :                 event_del(&evcon->ev);
     853               0 :                 evhttp_connection_done(evcon);
     854               0 :                 break;
     855                 :         case MORE_DATA_EXPECTED:
     856                 :         default:
     857               0 :                 evhttp_add_event(&evcon->ev, evcon->timeout,
     858                 :                     HTTP_READ_TIMEOUT);
     859               0 :                 break;
     860                 :         }
     861               0 : }
     862                 : 
     863                 : static void
     864               0 : evhttp_read_body(struct evhttp_connection *evcon, struct evhttp_request *req)
     865                 : {
     866               0 :         struct evbuffer *buf = evcon->input_buffer;
     867                 :         
     868               0 :         if (req->chunked) {
     869               0 :                 switch (evhttp_handle_chunked_read(req, buf)) {
     870                 :                 case ALL_DATA_READ:
     871                 :                         /* finished last chunk */
     872               0 :                         evcon->state = EVCON_READING_TRAILER;
     873               0 :                         evhttp_read_trailer(evcon, req);
     874               0 :                         return;
     875                 :                 case DATA_CORRUPTED:
     876                 :                         /* corrupted data */
     877               0 :                         evhttp_connection_fail(evcon,
     878                 :                             EVCON_HTTP_INVALID_HEADER);
     879               0 :                         return;
     880                 :                 case REQUEST_CANCELED:
     881                 :                         /* request canceled */
     882               0 :                         evhttp_request_free(req);
     883               0 :                         return;
     884                 :                 case MORE_DATA_EXPECTED:
     885                 :                 default:
     886                 :                         break;
     887                 :                 }
     888               0 :         } else if (req->ntoread < 0) {
     889                 :                 /* Read until connection close. */
     890               0 :                 evbuffer_add_buffer(req->input_buffer, buf);
     891               0 :         } else if (EVBUFFER_LENGTH(buf) >= req->ntoread) {
     892                 :                 /* Completed content length */
     893               0 :                 evbuffer_add(req->input_buffer, EVBUFFER_DATA(buf),
     894               0 :                     req->ntoread);
     895               0 :                 evbuffer_drain(buf, req->ntoread);
     896               0 :                 req->ntoread = 0;
     897               0 :                 evhttp_connection_done(evcon);
     898               0 :                 return;
     899                 :         }
     900                 :         /* Read more! */
     901               0 :         event_set(&evcon->ev, evcon->fd, EV_READ, evhttp_read, evcon);
     902               0 :         EVHTTP_BASE_SET(evcon, &evcon->ev);
     903               0 :         evhttp_add_event(&evcon->ev, evcon->timeout, HTTP_READ_TIMEOUT);
     904                 : }
     905                 : 
     906                 : /*
     907                 :  * Reads data into a buffer structure until no more data
     908                 :  * can be read on the file descriptor or we have read all
     909                 :  * the data that we wanted to read.
     910                 :  * Execute callback when done.
     911                 :  */
     912                 : 
     913                 : void
     914               0 : evhttp_read(int fd, short what, void *arg)
     915                 : {
     916               0 :         struct evhttp_connection *evcon = arg;
     917               0 :         struct evhttp_request *req = TAILQ_FIRST(&evcon->requests);
     918               0 :         struct evbuffer *buf = evcon->input_buffer;
     919                 :         int n, len;
     920                 : 
     921               0 :         if (what == EV_TIMEOUT) {
     922               0 :                 evhttp_connection_fail(evcon, EVCON_HTTP_TIMEOUT);
     923               0 :                 return;
     924                 :         }
     925               0 :         n = evbuffer_read(buf, fd, -1);
     926               0 :         len = EVBUFFER_LENGTH(buf);
     927                 :         event_debug(("%s: got %d on %d\n", __func__, n, fd));
     928                 :         
     929               0 :         if (n == -1) {
     930               0 :                 if (errno != EINTR && errno != EAGAIN) {
     931                 :                         event_debug(("%s: evbuffer_read", __func__));
     932               0 :                         evhttp_connection_fail(evcon, EVCON_HTTP_EOF);
     933                 :                 } else {
     934               0 :                         evhttp_add_event(&evcon->ev, evcon->timeout,
     935                 :                             HTTP_READ_TIMEOUT);        
     936                 :                 }
     937               0 :                 return;
     938               0 :         } else if (n == 0) {
     939                 :                 /* Connection closed */
     940               0 :                 evhttp_connection_done(evcon);
     941               0 :                 return;
     942                 :         }
     943                 : 
     944               0 :         switch (evcon->state) {
     945                 :         case EVCON_READING_FIRSTLINE:
     946               0 :                 evhttp_read_firstline(evcon, req);
     947               0 :                 break;
     948                 :         case EVCON_READING_HEADERS:
     949               0 :                 evhttp_read_header(evcon, req);
     950               0 :                 break;
     951                 :         case EVCON_READING_BODY:
     952               0 :                 evhttp_read_body(evcon, req);
     953               0 :                 break;
     954                 :         case EVCON_READING_TRAILER:
     955               0 :                 evhttp_read_trailer(evcon, req);
     956               0 :                 break;
     957                 :         case EVCON_DISCONNECTED:
     958                 :         case EVCON_CONNECTING:
     959                 :         case EVCON_IDLE:
     960                 :         case EVCON_WRITING:
     961                 :         default:
     962               0 :                 event_errx(1, "%s: illegal connection state %d",
     963               0 :                            __func__, evcon->state);
     964                 :         }
     965                 : }
     966                 : 
     967                 : static void
     968               0 : evhttp_write_connectioncb(struct evhttp_connection *evcon, void *arg)
     969                 : {
     970                 :         /* This is after writing the request to the server */
     971               0 :         struct evhttp_request *req = TAILQ_FIRST(&evcon->requests);
     972               0 :         assert(req != NULL);
     973                 : 
     974               0 :         assert(evcon->state == EVCON_WRITING);
     975                 : 
     976                 :         /* We are done writing our header and are now expecting the response */
     977               0 :         req->kind = EVHTTP_RESPONSE;
     978                 : 
     979               0 :         evhttp_start_read(evcon);
     980               0 : }
     981                 : 
     982                 : /*
     983                 :  * Clean up a connection object
     984                 :  */
     985                 : 
     986                 : void
     987               0 : evhttp_connection_free(struct evhttp_connection *evcon)
     988                 : {
     989                 :         struct evhttp_request *req;
     990                 : 
     991                 :         /* notify interested parties that this connection is going down */
     992               0 :         if (evcon->fd != -1) {
     993               0 :                 if (evhttp_connected(evcon) && evcon->closecb != NULL)
     994               0 :                         (*evcon->closecb)(evcon, evcon->closecb_arg);
     995                 :         }
     996                 : 
     997                 :         /* remove all requests that might be queued on this connection */
     998               0 :         while ((req = TAILQ_FIRST(&evcon->requests)) != NULL) {
     999               0 :                 TAILQ_REMOVE(&evcon->requests, req, next);
    1000               0 :                 evhttp_request_free(req);
    1001                 :         }
    1002                 : 
    1003               0 :         if (evcon->http_server != NULL) {
    1004               0 :                 struct evhttp *http = evcon->http_server;
    1005               0 :                 TAILQ_REMOVE(&http->connections, evcon, next);
    1006                 :         }
    1007                 : 
    1008               0 :         if (event_initialized(&evcon->close_ev))
    1009               0 :                 event_del(&evcon->close_ev);
    1010                 : 
    1011               0 :         if (event_initialized(&evcon->ev))
    1012               0 :                 event_del(&evcon->ev);
    1013                 :         
    1014               0 :         if (evcon->fd != -1)
    1015               0 :                 EVUTIL_CLOSESOCKET(evcon->fd);
    1016                 : 
    1017               0 :         if (evcon->bind_address != NULL)
    1018               0 :                 free(evcon->bind_address);
    1019                 : 
    1020               0 :         if (evcon->address != NULL)
    1021               0 :                 free(evcon->address);
    1022                 : 
    1023               0 :         if (evcon->input_buffer != NULL)
    1024               0 :                 evbuffer_free(evcon->input_buffer);
    1025                 : 
    1026               0 :         if (evcon->output_buffer != NULL)
    1027               0 :                 evbuffer_free(evcon->output_buffer);
    1028                 : 
    1029               0 :         free(evcon);
    1030               0 : }
    1031                 : 
    1032                 : void
    1033               0 : evhttp_connection_set_local_address(struct evhttp_connection *evcon,
    1034                 :     const char *address)
    1035                 : {
    1036               0 :         assert(evcon->state == EVCON_DISCONNECTED);
    1037               0 :         if (evcon->bind_address)
    1038               0 :                 free(evcon->bind_address);
    1039               0 :         if ((evcon->bind_address = strdup(address)) == NULL)
    1040               0 :                 event_err(1, "%s: strdup", __func__);
    1041               0 : }
    1042                 : 
    1043                 : 
    1044                 : static void
    1045               0 : evhttp_request_dispatch(struct evhttp_connection* evcon)
    1046                 : {
    1047               0 :         struct evhttp_request *req = TAILQ_FIRST(&evcon->requests);
    1048                 :         
    1049                 :         /* this should not usually happy but it's possible */
    1050               0 :         if (req == NULL)
    1051               0 :                 return;
    1052                 : 
    1053                 :         /* delete possible close detection events */
    1054               0 :         evhttp_connection_stop_detectclose(evcon);
    1055                 :         
    1056                 :         /* we assume that the connection is connected already */
    1057               0 :         assert(evcon->state == EVCON_IDLE);
    1058                 : 
    1059               0 :         evcon->state = EVCON_WRITING;
    1060                 : 
    1061                 :         /* Create the header from the store arguments */
    1062               0 :         evhttp_make_header(evcon, req);
    1063                 : 
    1064               0 :         evhttp_write_buffer(evcon, evhttp_write_connectioncb, NULL);
    1065                 : }
    1066                 : 
    1067                 : /* Reset our connection state */
    1068                 : void
    1069               0 : evhttp_connection_reset(struct evhttp_connection *evcon)
    1070                 : {
    1071               0 :         if (event_initialized(&evcon->ev))
    1072               0 :                 event_del(&evcon->ev);
    1073                 : 
    1074               0 :         if (evcon->fd != -1) {
    1075                 :                 /* inform interested parties about connection close */
    1076               0 :                 if (evhttp_connected(evcon) && evcon->closecb != NULL)
    1077               0 :                         (*evcon->closecb)(evcon, evcon->closecb_arg);
    1078                 : 
    1079               0 :                 EVUTIL_CLOSESOCKET(evcon->fd);
    1080               0 :                 evcon->fd = -1;
    1081                 :         }
    1082               0 :         evcon->state = EVCON_DISCONNECTED;
    1083               0 : }
    1084                 : 
    1085                 : static void
    1086               0 : evhttp_detect_close_cb(int fd, short what, void *arg)
    1087                 : {
    1088               0 :         struct evhttp_connection *evcon = arg;
    1089               0 :         evhttp_connection_reset(evcon);
    1090               0 : }
    1091                 : 
    1092                 : static void
    1093               0 : evhttp_connection_start_detectclose(struct evhttp_connection *evcon)
    1094                 : {
    1095               0 :         evcon->flags |= EVHTTP_CON_CLOSEDETECT;
    1096                 : 
    1097               0 :         if (event_initialized(&evcon->close_ev))
    1098               0 :                 event_del(&evcon->close_ev);
    1099               0 :         event_set(&evcon->close_ev, evcon->fd, EV_READ,
    1100                 :             evhttp_detect_close_cb, evcon);
    1101               0 :         EVHTTP_BASE_SET(evcon, &evcon->close_ev);
    1102               0 :         event_add(&evcon->close_ev, NULL);
    1103               0 : }
    1104                 : 
    1105                 : static void
    1106               0 : evhttp_connection_stop_detectclose(struct evhttp_connection *evcon)
    1107                 : {
    1108               0 :         evcon->flags &= ~EVHTTP_CON_CLOSEDETECT;
    1109               0 :         event_del(&evcon->close_ev);
    1110               0 : }
    1111                 : 
    1112                 : static void
    1113               0 : evhttp_connection_retry(int fd, short what, void *arg)
    1114                 : {
    1115               0 :         struct evhttp_connection *evcon = arg;
    1116                 : 
    1117               0 :         evcon->state = EVCON_DISCONNECTED;
    1118               0 :         evhttp_connection_connect(evcon);
    1119               0 : }
    1120                 : 
    1121                 : /*
    1122                 :  * Call back for asynchronous connection attempt.
    1123                 :  */
    1124                 : 
    1125                 : static void
    1126               0 : evhttp_connectioncb(int fd, short what, void *arg)
    1127                 : {
    1128               0 :         struct evhttp_connection *evcon = arg;
    1129                 :         int error;
    1130               0 :         socklen_t errsz = sizeof(error);
    1131                 :                 
    1132               0 :         if (what == EV_TIMEOUT) {
    1133                 :                 event_debug(("%s: connection timeout for \"%s:%d\" on %d",
    1134                 :                         __func__, evcon->address, evcon->port, evcon->fd));
    1135               0 :                 goto cleanup;
    1136                 :         }
    1137                 : 
    1138                 :         /* Check if the connection completed */
    1139               0 :         if (getsockopt(evcon->fd, SOL_SOCKET, SO_ERROR, (void*)&error,
    1140                 :                        &errsz) == -1) {
    1141                 :                 event_debug(("%s: getsockopt for \"%s:%d\" on %d",
    1142                 :                         __func__, evcon->address, evcon->port, evcon->fd));
    1143               0 :                 goto cleanup;
    1144                 :         }
    1145                 : 
    1146               0 :         if (error) {
    1147                 :                 event_debug(("%s: connect failed for \"%s:%d\" on %d: %s",
    1148                 :                     __func__, evcon->address, evcon->port, evcon->fd,
    1149                 :                         strerror(error)));
    1150               0 :                 goto cleanup;
    1151                 :         }
    1152                 : 
    1153                 :         /* We are connected to the server now */
    1154                 :         event_debug(("%s: connected to \"%s:%d\" on %d\n",
    1155                 :                         __func__, evcon->address, evcon->port, evcon->fd));
    1156                 : 
    1157                 :         /* Reset the retry count as we were successful in connecting */
    1158               0 :         evcon->retry_cnt = 0;
    1159               0 :         evcon->state = EVCON_IDLE;
    1160                 : 
    1161                 :         /* try to start requests that have queued up on this connection */
    1162               0 :         evhttp_request_dispatch(evcon);
    1163               0 :         return;
    1164                 : 
    1165                 :  cleanup:
    1166               0 :         if (evcon->retry_max < 0 || evcon->retry_cnt < evcon->retry_max) {
    1167               0 :                 evtimer_set(&evcon->ev, evhttp_connection_retry, evcon);
    1168               0 :                 EVHTTP_BASE_SET(evcon, &evcon->ev);
    1169               0 :                 evhttp_add_event(&evcon->ev, MIN(3600, 2 << evcon->retry_cnt),
    1170                 :                     HTTP_CONNECT_TIMEOUT);
    1171               0 :                 evcon->retry_cnt++;
    1172               0 :                 return;
    1173                 :         }
    1174               0 :         evhttp_connection_reset(evcon);
    1175                 : 
    1176                 :         /* for now, we just signal all requests by executing their callbacks */
    1177               0 :         while (TAILQ_FIRST(&evcon->requests) != NULL) {
    1178               0 :                 struct evhttp_request *request = TAILQ_FIRST(&evcon->requests);
    1179               0 :                 TAILQ_REMOVE(&evcon->requests, request, next);
    1180               0 :                 request->evcon = NULL;
    1181                 : 
    1182                 :                 /* we might want to set an error here */
    1183               0 :                 request->cb(request, request->cb_arg);
    1184               0 :                 evhttp_request_free(request);
    1185                 :         }
    1186                 : }
    1187                 : 
    1188                 : /*
    1189                 :  * Check if we got a valid response code.
    1190                 :  */
    1191                 : 
    1192                 : static int
    1193               0 : evhttp_valid_response_code(int code)
    1194                 : {
    1195               0 :         if (code == 0)
    1196               0 :                 return (0);
    1197                 : 
    1198               0 :         return (1);
    1199                 : }
    1200                 : 
    1201                 : /* Parses the status line of a web server */
    1202                 : 
    1203                 : static int
    1204               0 : evhttp_parse_response_line(struct evhttp_request *req, char *line)
    1205                 : {
    1206                 :         char *protocol;
    1207                 :         char *number;
    1208                 :         char *readable;
    1209                 : 
    1210               0 :         protocol = strsep(&line, " ");
    1211               0 :         if (line == NULL)
    1212               0 :                 return (-1);
    1213               0 :         number = strsep(&line, " ");
    1214               0 :         if (line == NULL)
    1215               0 :                 return (-1);
    1216               0 :         readable = line;
    1217                 : 
    1218               0 :         if (strcmp(protocol, "HTTP/1.0") == 0) {
    1219               0 :                 req->major = 1;
    1220               0 :                 req->minor = 0;
    1221               0 :         } else if (strcmp(protocol, "HTTP/1.1") == 0) {
    1222               0 :                 req->major = 1;
    1223               0 :                 req->minor = 1;
    1224                 :         } else {
    1225                 :                 event_debug(("%s: bad protocol \"%s\"",
    1226                 :                         __func__, protocol));
    1227               0 :                 return (-1);
    1228                 :         }
    1229                 : 
    1230               0 :         req->response_code = atoi(number);
    1231               0 :         if (!evhttp_valid_response_code(req->response_code)) {
    1232                 :                 event_debug(("%s: bad response code \"%s\"",
    1233                 :                         __func__, number));
    1234               0 :                 return (-1);
    1235                 :         }
    1236                 : 
    1237               0 :         if ((req->response_code_line = strdup(readable)) == NULL)
    1238               0 :                 event_err(1, "%s: strdup", __func__);
    1239                 : 
    1240               0 :         return (0);
    1241                 : }
    1242                 : 
    1243                 : /* Parse the first line of a HTTP request */
    1244                 : 
    1245                 : static int
    1246               0 : evhttp_parse_request_line(struct evhttp_request *req, char *line)
    1247                 : {
    1248                 :         char *method;
    1249                 :         char *uri;
    1250                 :         char *version;
    1251                 : 
    1252                 :         /* Parse the request line */
    1253               0 :         method = strsep(&line, " ");
    1254               0 :         if (line == NULL)
    1255               0 :                 return (-1);
    1256               0 :         uri = strsep(&line, " ");
    1257               0 :         if (line == NULL)
    1258               0 :                 return (-1);
    1259               0 :         version = strsep(&line, " ");
    1260               0 :         if (line != NULL)
    1261               0 :                 return (-1);
    1262                 : 
    1263                 :         /* First line */
    1264               0 :         if (strcmp(method, "GET") == 0) {
    1265               0 :                 req->type = EVHTTP_REQ_GET;
    1266               0 :         } else if (strcmp(method, "POST") == 0) {
    1267               0 :                 req->type = EVHTTP_REQ_POST;
    1268               0 :         } else if (strcmp(method, "HEAD") == 0) {
    1269               0 :                 req->type = EVHTTP_REQ_HEAD;
    1270                 :         } else {
    1271                 :                 event_debug(("%s: bad method %s on request %p from %s",
    1272                 :                         __func__, method, req, req->remote_host));
    1273               0 :                 return (-1);
    1274                 :         }
    1275                 : 
    1276               0 :         if (strcmp(version, "HTTP/1.0") == 0) {
    1277               0 :                 req->major = 1;
    1278               0 :                 req->minor = 0;
    1279               0 :         } else if (strcmp(version, "HTTP/1.1") == 0) {
    1280               0 :                 req->major = 1;
    1281               0 :                 req->minor = 1;
    1282                 :         } else {
    1283                 :                 event_debug(("%s: bad version %s on request %p from %s",
    1284                 :                         __func__, version, req, req->remote_host));
    1285               0 :                 return (-1);
    1286                 :         }
    1287                 : 
    1288               0 :         if ((req->uri = strdup(uri)) == NULL) {
    1289                 :                 event_debug(("%s: evhttp_decode_uri", __func__));
    1290               0 :                 return (-1);
    1291                 :         }
    1292                 : 
    1293                 :         /* determine if it's a proxy request */
    1294               0 :         if (strlen(req->uri) > 0 && req->uri[0] != '/')
    1295               0 :                 req->flags |= EVHTTP_PROXY_REQUEST;
    1296                 : 
    1297               0 :         return (0);
    1298                 : }
    1299                 : 
    1300                 : const char *
    1301               0 : evhttp_find_header(const struct evkeyvalq *headers, const char *key)
    1302                 : {
    1303                 :         struct evkeyval *header;
    1304                 : 
    1305               0 :         TAILQ_FOREACH(header, headers, next) {
    1306               0 :                 if (strcasecmp(header->key, key) == 0)
    1307               0 :                         return (header->value);
    1308                 :         }
    1309                 : 
    1310               0 :         return (NULL);
    1311                 : }
    1312                 : 
    1313                 : void
    1314               0 : evhttp_clear_headers(struct evkeyvalq *headers)
    1315                 : {
    1316                 :         struct evkeyval *header;
    1317                 : 
    1318               0 :         for (header = TAILQ_FIRST(headers);
    1319                 :             header != NULL;
    1320               0 :             header = TAILQ_FIRST(headers)) {
    1321               0 :                 TAILQ_REMOVE(headers, header, next);
    1322               0 :                 free(header->key);
    1323               0 :                 free(header->value);
    1324               0 :                 free(header);
    1325                 :         }
    1326               0 : }
    1327                 : 
    1328                 : /*
    1329                 :  * Returns 0,  if the header was successfully removed.
    1330                 :  * Returns -1, if the header could not be found.
    1331                 :  */
    1332                 : 
    1333                 : int
    1334               0 : evhttp_remove_header(struct evkeyvalq *headers, const char *key)
    1335                 : {
    1336                 :         struct evkeyval *header;
    1337                 : 
    1338               0 :         TAILQ_FOREACH(header, headers, next) {
    1339               0 :                 if (strcasecmp(header->key, key) == 0)
    1340               0 :                         break;
    1341                 :         }
    1342                 : 
    1343               0 :         if (header == NULL)
    1344               0 :                 return (-1);
    1345                 : 
    1346                 :         /* Free and remove the header that we found */
    1347               0 :         TAILQ_REMOVE(headers, header, next);
    1348               0 :         free(header->key);
    1349               0 :         free(header->value);
    1350               0 :         free(header);
    1351                 : 
    1352               0 :         return (0);
    1353                 : }
    1354                 : 
    1355                 : int
    1356               0 : evhttp_add_header(struct evkeyvalq *headers,
    1357                 :     const char *key, const char *value)
    1358                 : {
    1359               0 :         struct evkeyval *header = NULL;
    1360                 : 
    1361                 :         event_debug(("%s: key: %s val: %s\n", __func__, key, value));
    1362                 : 
    1363               0 :         if (strchr(value, '\r') != NULL || strchr(value, '\n') != NULL ||
    1364               0 :             strchr(key, '\r') != NULL || strchr(key, '\n') != NULL) {
    1365                 :                 /* drop illegal headers */
    1366                 :                 event_debug(("%s: dropping illegal header\n", __func__));
    1367               0 :                 return (-1);
    1368                 :         }
    1369                 : 
    1370               0 :         header = calloc(1, sizeof(struct evkeyval));
    1371               0 :         if (header == NULL) {
    1372               0 :                 event_warn("%s: calloc", __func__);
    1373               0 :                 return (-1);
    1374                 :         }
    1375               0 :         if ((header->key = strdup(key)) == NULL) {
    1376               0 :                 free(header);
    1377               0 :                 event_warn("%s: strdup", __func__);
    1378               0 :                 return (-1);
    1379                 :         }
    1380               0 :         if ((header->value = strdup(value)) == NULL) {
    1381               0 :                 free(header->key);
    1382               0 :                 free(header);
    1383               0 :                 event_warn("%s: strdup", __func__);
    1384               0 :                 return (-1);
    1385                 :         }
    1386                 : 
    1387               0 :         TAILQ_INSERT_TAIL(headers, header, next);
    1388                 : 
    1389               0 :         return (0);
    1390                 : }
    1391                 : 
    1392                 : /*
    1393                 :  * Parses header lines from a request or a response into the specified
    1394                 :  * request object given an event buffer.
    1395                 :  *
    1396                 :  * Returns
    1397                 :  *   DATA_CORRUPTED      on error
    1398                 :  *   MORE_DATA_EXPECTED  when we need to read more headers
    1399                 :  *   ALL_DATA_READ       when all headers have been read.
    1400                 :  */
    1401                 : 
    1402                 : enum message_read_status
    1403               0 : evhttp_parse_firstline(struct evhttp_request *req, struct evbuffer *buffer)
    1404                 : {
    1405                 :         char *line;
    1406               0 :         enum message_read_status status = ALL_DATA_READ;
    1407                 : 
    1408               0 :         line = evbuffer_readline(buffer);
    1409               0 :         if (line == NULL)
    1410               0 :                 return (MORE_DATA_EXPECTED);
    1411                 : 
    1412               0 :         switch (req->kind) {
    1413                 :         case EVHTTP_REQUEST:
    1414               0 :                 if (evhttp_parse_request_line(req, line) == -1)
    1415               0 :                         status = DATA_CORRUPTED;
    1416               0 :                 break;
    1417                 :         case EVHTTP_RESPONSE:
    1418               0 :                 if (evhttp_parse_response_line(req, line) == -1)
    1419               0 :                         status = DATA_CORRUPTED;
    1420               0 :                 break;
    1421                 :         default:
    1422               0 :                 status = DATA_CORRUPTED;
    1423                 :         }
    1424                 : 
    1425               0 :         free(line);
    1426               0 :         return (status);
    1427                 : }
    1428                 : 
    1429                 : static int
    1430               0 : evhttp_append_to_last_header(struct evkeyvalq *headers, const char *line)
    1431                 : {
    1432               0 :         struct evkeyval *header = TAILQ_LAST(headers, evkeyvalq);
    1433                 :         char *newval;
    1434                 :         size_t old_len, line_len;
    1435                 : 
    1436               0 :         if (header == NULL)
    1437               0 :                 return (-1);
    1438                 : 
    1439               0 :         old_len = strlen(header->value);
    1440               0 :         line_len = strlen(line);
    1441                 : 
    1442               0 :         newval = realloc(header->value, old_len + line_len + 1);
    1443               0 :         if (newval == NULL)
    1444               0 :                 return (-1);
    1445                 : 
    1446               0 :         memcpy(newval + old_len, line, line_len + 1);
    1447               0 :         header->value = newval;
    1448                 : 
    1449               0 :         return (0);
    1450                 : }
    1451                 : 
    1452                 : enum message_read_status
    1453               0 : evhttp_parse_headers(struct evhttp_request *req, struct evbuffer* buffer)
    1454                 : {
    1455                 :         char *line;
    1456               0 :         enum message_read_status status = MORE_DATA_EXPECTED;
    1457                 : 
    1458               0 :         struct evkeyvalq* headers = req->input_headers;
    1459               0 :         while ((line = evbuffer_readline(buffer))
    1460                 :                != NULL) {
    1461                 :                 char *skey, *svalue;
    1462                 : 
    1463               0 :                 if (*line == '\0') { /* Last header - Done */
    1464               0 :                         status = ALL_DATA_READ;
    1465               0 :                         free(line);
    1466               0 :                         break;
    1467                 :                 }
    1468                 : 
    1469                 :                 /* Check if this is a continuation line */
    1470               0 :                 if (*line == ' ' || *line == '\t') {
    1471               0 :                         if (evhttp_append_to_last_header(headers, line) == -1)
    1472               0 :                                 goto error;
    1473               0 :                         continue;
    1474                 :                 }
    1475                 : 
    1476                 :                 /* Processing of header lines */
    1477               0 :                 svalue = line;
    1478               0 :                 skey = strsep(&svalue, ":");
    1479               0 :                 if (svalue == NULL)
    1480               0 :                         goto error;
    1481                 : 
    1482               0 :                 svalue += strspn(svalue, " ");
    1483                 : 
    1484               0 :                 if (evhttp_add_header(headers, skey, svalue) == -1)
    1485               0 :                         goto error;
    1486                 : 
    1487               0 :                 free(line);
    1488                 :         }
    1489                 : 
    1490               0 :         return (status);
    1491                 : 
    1492                 :  error:
    1493               0 :         free(line);
    1494               0 :         return (DATA_CORRUPTED);
    1495                 : }
    1496                 : 
    1497                 : static int
    1498               0 : evhttp_get_body_length(struct evhttp_request *req)
    1499                 : {
    1500               0 :         struct evkeyvalq *headers = req->input_headers;
    1501                 :         const char *content_length;
    1502                 :         const char *connection;
    1503                 : 
    1504               0 :         content_length = evhttp_find_header(headers, "Content-Length");
    1505               0 :         connection = evhttp_find_header(headers, "Connection");
    1506                 :                 
    1507               0 :         if (content_length == NULL && connection == NULL)
    1508               0 :                 req->ntoread = -1;
    1509               0 :         else if (content_length == NULL &&
    1510               0 :             strcasecmp(connection, "Close") != 0) {
    1511                 :                 /* Bad combination, we don't know when it will end */
    1512               0 :                 event_warnx("%s: we got no content length, but the "
    1513                 :                     "server wants to keep the connection open: %s.",
    1514                 :                     __func__, connection);
    1515               0 :                 return (-1);
    1516               0 :         } else if (content_length == NULL) {
    1517               0 :                 req->ntoread = -1;
    1518                 :         } else {
    1519                 :                 char *endp;
    1520               0 :                 ev_int64_t ntoread = evutil_strtoll(content_length, &endp, 10);
    1521               0 :                 if (*content_length == '\0' || *endp != '\0' || ntoread < 0) {
    1522                 :                         event_debug(("%s: illegal content length: %s",
    1523                 :                                 __func__, content_length));
    1524               0 :                         return (-1);
    1525                 :                 }
    1526               0 :                 req->ntoread = ntoread;
    1527                 :         }
    1528                 :                 
    1529                 :         event_debug(("%s: bytes to read: %lld (in buffer %ld)\n",
    1530                 :                 __func__, req->ntoread,
    1531                 :                 EVBUFFER_LENGTH(req->evcon->input_buffer)));
    1532                 : 
    1533               0 :         return (0);
    1534                 : }
    1535                 : 
    1536                 : static void
    1537               0 : evhttp_get_body(struct evhttp_connection *evcon, struct evhttp_request *req)
    1538                 : {
    1539                 :         const char *xfer_enc;
    1540                 :         
    1541                 :         /* If this is a request without a body, then we are done */
    1542               0 :         if (req->kind == EVHTTP_REQUEST && req->type != EVHTTP_REQ_POST) {
    1543               0 :                 evhttp_connection_done(evcon);
    1544               0 :                 return;
    1545                 :         }
    1546               0 :         evcon->state = EVCON_READING_BODY;
    1547               0 :         xfer_enc = evhttp_find_header(req->input_headers, "Transfer-Encoding");
    1548               0 :         if (xfer_enc != NULL && strcasecmp(xfer_enc, "chunked") == 0) {
    1549               0 :                 req->chunked = 1;
    1550               0 :                 req->ntoread = -1;
    1551                 :         } else {
    1552               0 :                 if (evhttp_get_body_length(req) == -1) {
    1553               0 :                         evhttp_connection_fail(evcon,
    1554                 :                             EVCON_HTTP_INVALID_HEADER);
    1555               0 :                         return;
    1556                 :                 }
    1557                 :         }
    1558               0 :         evhttp_read_body(evcon, req);
    1559                 : }
    1560                 : 
    1561                 : static void
    1562               0 : evhttp_read_firstline(struct evhttp_connection *evcon,
    1563                 :                       struct evhttp_request *req)
    1564                 : {
    1565                 :         enum message_read_status res;
    1566                 : 
    1567               0 :         res = evhttp_parse_firstline(req, evcon->input_buffer);
    1568               0 :         if (res == DATA_CORRUPTED) {
    1569                 :                 /* Error while reading, terminate */
    1570                 :                 event_debug(("%s: bad header lines on %d\n",
    1571                 :                         __func__, evcon->fd));
    1572               0 :                 evhttp_connection_fail(evcon, EVCON_HTTP_INVALID_HEADER);
    1573               0 :                 return;
    1574               0 :         } else if (res == MORE_DATA_EXPECTED) {
    1575                 :                 /* Need more header lines */
    1576               0 :                 evhttp_add_event(&evcon->ev, 
    1577                 :                     evcon->timeout, HTTP_READ_TIMEOUT);
    1578               0 :                 return;
    1579                 :         }
    1580                 : 
    1581               0 :         evcon->state = EVCON_READING_HEADERS;
    1582               0 :         evhttp_read_header(evcon, req);
    1583                 : }
    1584                 : 
    1585                 : static void
    1586               0 : evhttp_read_header(struct evhttp_connection *evcon, struct evhttp_request *req)
    1587                 : {
    1588                 :         enum message_read_status res;
    1589               0 :         int fd = evcon->fd;
    1590                 : 
    1591               0 :         res = evhttp_parse_headers(req, evcon->input_buffer);
    1592               0 :         if (res == DATA_CORRUPTED) {
    1593                 :                 /* Error while reading, terminate */
    1594                 :                 event_debug(("%s: bad header lines on %d\n", __func__, fd));
    1595               0 :                 evhttp_connection_fail(evcon, EVCON_HTTP_INVALID_HEADER);
    1596               0 :                 return;
    1597               0 :         } else if (res == MORE_DATA_EXPECTED) {
    1598                 :                 /* Need more header lines */
    1599               0 :                 evhttp_add_event(&evcon->ev, 
    1600                 :                     evcon->timeout, HTTP_READ_TIMEOUT);
    1601               0 :                 return;
    1602                 :         }
    1603                 : 
    1604                 :         /* Done reading headers, do the real work */
    1605               0 :         switch (req->kind) {
    1606                 :         case EVHTTP_REQUEST:
    1607                 :                 event_debug(("%s: checking for post data on %d\n",
    1608                 :                                 __func__, fd));
    1609               0 :                 evhttp_get_body(evcon, req);
    1610               0 :                 break;
    1611                 : 
    1612                 :         case EVHTTP_RESPONSE:
    1613               0 :                 if (req->response_code == HTTP_NOCONTENT ||
    1614               0 :                     req->response_code == HTTP_NOTMODIFIED ||
    1615               0 :                     (req->response_code >= 100 && req->response_code < 200)) {
    1616                 :                         event_debug(("%s: skipping body for code %d\n",
    1617                 :                                         __func__, req->response_code));
    1618               0 :                         evhttp_connection_done(evcon);
    1619                 :                 } else {
    1620                 :                         event_debug(("%s: start of read body for %s on %d\n",
    1621                 :                                 __func__, req->remote_host, fd));
    1622               0 :                         evhttp_get_body(evcon, req);
    1623                 :                 }
    1624               0 :                 break;
    1625                 : 
    1626                 :         default:
    1627               0 :                 event_warnx("%s: bad header on %d", __func__, fd);
    1628               0 :                 evhttp_connection_fail(evcon, EVCON_HTTP_INVALID_HEADER);
    1629               0 :                 break;
    1630                 :         }
    1631                 : }
    1632                 : 
    1633                 : /*
    1634                 :  * Creates a TCP connection to the specified port and executes a callback
    1635                 :  * when finished.  Failure or sucess is indicate by the passed connection
    1636                 :  * object.
    1637                 :  *
    1638                 :  * Although this interface accepts a hostname, it is intended to take
    1639                 :  * only numeric hostnames so that non-blocking DNS resolution can
    1640                 :  * happen elsewhere.
    1641                 :  */
    1642                 : 
    1643                 : struct evhttp_connection *
    1644               0 : evhttp_connection_new(const char *address, unsigned short port)
    1645                 : {
    1646               0 :         struct evhttp_connection *evcon = NULL;
    1647                 :         
    1648                 :         event_debug(("Attempting connection to %s:%d\n", address, port));
    1649                 : 
    1650               0 :         if ((evcon = calloc(1, sizeof(struct evhttp_connection))) == NULL) {
    1651               0 :                 event_warn("%s: calloc failed", __func__);
    1652               0 :                 goto error;
    1653                 :         }
    1654                 : 
    1655               0 :         evcon->fd = -1;
    1656               0 :         evcon->port = port;
    1657                 : 
    1658               0 :         evcon->timeout = -1;
    1659               0 :         evcon->retry_cnt = evcon->retry_max = 0;
    1660                 : 
    1661               0 :         if ((evcon->address = strdup(address)) == NULL) {
    1662               0 :                 event_warn("%s: strdup failed", __func__);
    1663               0 :                 goto error;
    1664                 :         }
    1665                 : 
    1666               0 :         if ((evcon->input_buffer = evbuffer_new()) == NULL) {
    1667               0 :                 event_warn("%s: evbuffer_new failed", __func__);
    1668               0 :                 goto error;
    1669                 :         }
    1670                 : 
    1671               0 :         if ((evcon->output_buffer = evbuffer_new()) == NULL) {
    1672               0 :                 event_warn("%s: evbuffer_new failed", __func__);
    1673               0 :                 goto error;
    1674                 :         }
    1675                 :         
    1676               0 :         evcon->state = EVCON_DISCONNECTED;
    1677               0 :         TAILQ_INIT(&evcon->requests);
    1678                 : 
    1679               0 :         return (evcon);
    1680                 :         
    1681                 :  error:
    1682               0 :         if (evcon != NULL)
    1683               0 :                 evhttp_connection_free(evcon);
    1684               0 :         return (NULL);
    1685                 : }
    1686                 : 
    1687               0 : void evhttp_connection_set_base(struct evhttp_connection *evcon,
    1688                 :     struct event_base *base)
    1689                 : {
    1690               0 :         assert(evcon->base == NULL);
    1691               0 :         assert(evcon->state == EVCON_DISCONNECTED);
    1692               0 :         evcon->base = base;
    1693               0 : }
    1694                 : 
    1695                 : void
    1696               0 : evhttp_connection_set_timeout(struct evhttp_connection *evcon,
    1697                 :     int timeout_in_secs)
    1698                 : {
    1699               0 :         evcon->timeout = timeout_in_secs;
    1700               0 : }
    1701                 : 
    1702                 : void
    1703               0 : evhttp_connection_set_retries(struct evhttp_connection *evcon,
    1704                 :     int retry_max)
    1705                 : {
    1706               0 :         evcon->retry_max = retry_max;
    1707               0 : }
    1708                 : 
    1709                 : void
    1710               0 : evhttp_connection_set_closecb(struct evhttp_connection *evcon,
    1711                 :     void (*cb)(struct evhttp_connection *, void *), void *cbarg)
    1712                 : {
    1713               0 :         evcon->closecb = cb;
    1714               0 :         evcon->closecb_arg = cbarg;
    1715               0 : }
    1716                 : 
    1717                 : void
    1718               0 : evhttp_connection_get_peer(struct evhttp_connection *evcon,
    1719                 :     char **address, u_short *port)
    1720                 : {
    1721               0 :         *address = evcon->address;
    1722               0 :         *port = evcon->port;
    1723               0 : }
    1724                 : 
    1725                 : int
    1726               0 : evhttp_connection_connect(struct evhttp_connection *evcon)
    1727                 : {
    1728               0 :         if (evcon->state == EVCON_CONNECTING)
    1729               0 :                 return (0);
    1730                 :         
    1731               0 :         evhttp_connection_reset(evcon);
    1732                 : 
    1733               0 :         assert(!(evcon->flags & EVHTTP_CON_INCOMING));
    1734               0 :         evcon->flags |= EVHTTP_CON_OUTGOING;
    1735                 :         
    1736               0 :         evcon->fd = bind_socket(evcon->bind_address, 0 /*port*/, 0 /*reuse*/);
    1737               0 :         if (evcon->fd == -1) {
    1738                 :                 event_debug(("%s: failed to bind to \"%s\"",
    1739                 :                         __func__, evcon->bind_address));
    1740               0 :                 return (-1);
    1741                 :         }
    1742                 : 
    1743               0 :         if (socket_connect(evcon->fd, evcon->address, evcon->port) == -1) {
    1744               0 :                 EVUTIL_CLOSESOCKET(evcon->fd); evcon->fd = -1;
    1745               0 :                 return (-1);
    1746                 :         }
    1747                 : 
    1748                 :         /* Set up a callback for successful connection setup */
    1749               0 :         event_set(&evcon->ev, evcon->fd, EV_WRITE, evhttp_connectioncb, evcon);
    1750               0 :         EVHTTP_BASE_SET(evcon, &evcon->ev);
    1751               0 :         evhttp_add_event(&evcon->ev, evcon->timeout, HTTP_CONNECT_TIMEOUT);
    1752                 : 
    1753               0 :         evcon->state = EVCON_CONNECTING;
    1754                 :         
    1755               0 :         return (0);
    1756                 : }
    1757                 : 
    1758                 : /*
    1759                 :  * Starts an HTTP request on the provided evhttp_connection object.
    1760                 :  * If the connection object is not connected to the web server already,
    1761                 :  * this will start the connection.
    1762                 :  */
    1763                 : 
    1764                 : int
    1765               0 : evhttp_make_request(struct evhttp_connection *evcon,
    1766                 :     struct evhttp_request *req,
    1767                 :     enum evhttp_cmd_type type, const char *uri)
    1768                 : {
    1769                 :         /* We are making a request */
    1770               0 :         req->kind = EVHTTP_REQUEST;
    1771               0 :         req->type = type;
    1772               0 :         if (req->uri != NULL)
    1773               0 :                 free(req->uri);
    1774               0 :         if ((req->uri = strdup(uri)) == NULL)
    1775               0 :                 event_err(1, "%s: strdup", __func__);
    1776                 : 
    1777                 :         /* Set the protocol version if it is not supplied */
    1778               0 :         if (!req->major && !req->minor) {
    1779               0 :                 req->major = 1;
    1780               0 :                 req->minor = 1;
    1781                 :         }
    1782                 :         
    1783               0 :         assert(req->evcon == NULL);
    1784               0 :         req->evcon = evcon;
    1785               0 :         assert(!(req->flags & EVHTTP_REQ_OWN_CONNECTION));
    1786                 :         
    1787               0 :         TAILQ_INSERT_TAIL(&evcon->requests, req, next);
    1788                 : 
    1789                 :         /* If the connection object is not connected; make it so */
    1790               0 :         if (!evhttp_connected(evcon))
    1791               0 :                 return (evhttp_connection_connect(evcon));
    1792                 : 
    1793                 :         /*
    1794                 :          * If it's connected already and we are the first in the queue,
    1795                 :          * then we can dispatch this request immediately.  Otherwise, it
    1796                 :          * will be dispatched once the pending requests are completed.
    1797                 :          */
    1798               0 :         if (TAILQ_FIRST(&evcon->requests) == req)
    1799               0 :                 evhttp_request_dispatch(evcon);
    1800                 : 
    1801               0 :         return (0);
    1802                 : }
    1803                 : 
    1804                 : /*
    1805                 :  * Reads data from file descriptor into request structure
    1806                 :  * Request structure needs to be set up correctly.
    1807                 :  */
    1808                 : 
    1809                 : void
    1810               0 : evhttp_start_read(struct evhttp_connection *evcon)
    1811                 : {
    1812                 :         /* Set up an event to read the headers */
    1813               0 :         if (event_initialized(&evcon->ev))
    1814               0 :                 event_del(&evcon->ev);
    1815               0 :         event_set(&evcon->ev, evcon->fd, EV_READ, evhttp_read, evcon);
    1816               0 :         EVHTTP_BASE_SET(evcon, &evcon->ev);
    1817                 :         
    1818               0 :         evhttp_add_event(&evcon->ev, evcon->timeout, HTTP_READ_TIMEOUT);
    1819               0 :         evcon->state = EVCON_READING_FIRSTLINE;
    1820               0 : }
    1821                 : 
    1822                 : static void
    1823               0 : evhttp_send_done(struct evhttp_connection *evcon, void *arg)
    1824                 : {
    1825                 :         int need_close;
    1826               0 :         struct evhttp_request *req = TAILQ_FIRST(&evcon->requests);
    1827               0 :         TAILQ_REMOVE(&evcon->requests, req, next);
    1828                 : 
    1829                 :         /* delete possible close detection events */
    1830               0 :         evhttp_connection_stop_detectclose(evcon);
    1831                 :         
    1832               0 :         need_close =
    1833               0 :             (req->minor == 0 &&
    1834               0 :                 !evhttp_is_connection_keepalive(req->input_headers))||
    1835               0 :             evhttp_is_connection_close(req->flags, req->input_headers) ||
    1836               0 :             evhttp_is_connection_close(req->flags, req->output_headers);
    1837                 : 
    1838               0 :         assert(req->flags & EVHTTP_REQ_OWN_CONNECTION);
    1839               0 :         evhttp_request_free(req);
    1840                 : 
    1841               0 :         if (need_close) {
    1842               0 :                 evhttp_connection_free(evcon);
    1843               0 :                 return;
    1844                 :         } 
    1845                 : 
    1846                 :         /* we have a persistent connection; try to accept another request. */
    1847               0 :         if (evhttp_associate_new_request_with_connection(evcon) == -1)
    1848               0 :                 evhttp_connection_free(evcon);
    1849                 : }
    1850                 : 
    1851                 : /*
    1852                 :  * Returns an error page.
    1853                 :  */
    1854                 : 
    1855                 : void
    1856               0 : evhttp_send_error(struct evhttp_request *req, int error, const char *reason)
    1857                 : {
    1858                 : #define ERR_FORMAT "<HTML><HEAD>\n" \
    1859                 :             "<TITLE>%d %s</TITLE>\n" \
    1860                 :             "</HEAD><BODY>\n" \
    1861                 :             "<H1>Method Not Implemented</H1>\n" \
    1862                 :             "Invalid method in request<P>\n" \
    1863                 :             "</BODY></HTML>\n"
    1864                 : 
    1865               0 :         struct evbuffer *buf = evbuffer_new();
    1866                 : 
    1867                 :         /* close the connection on error */
    1868               0 :         evhttp_add_header(req->output_headers, "Connection", "close");
    1869                 : 
    1870               0 :         evhttp_response_code(req, error, reason);
    1871                 : 
    1872               0 :         evbuffer_add_printf(buf, ERR_FORMAT, error, reason);
    1873                 : 
    1874               0 :         evhttp_send_page(req, buf);
    1875                 : 
    1876               0 :         evbuffer_free(buf);
    1877                 : #undef ERR_FORMAT
    1878               0 : }
    1879                 : 
    1880                 : /* Requires that headers and response code are already set up */
    1881                 : 
    1882                 : static inline void
    1883               0 : evhttp_send(struct evhttp_request *req, struct evbuffer *databuf)
    1884                 : {
    1885               0 :         struct evhttp_connection *evcon = req->evcon;
    1886                 : 
    1887               0 :         assert(TAILQ_FIRST(&evcon->requests) == req);
    1888                 : 
    1889                 :         /* xxx: not sure if we really should expose the data buffer this way */
    1890               0 :         if (databuf != NULL)
    1891               0 :                 evbuffer_add_buffer(req->output_buffer, databuf);
    1892                 :         
    1893                 :         /* Adds headers to the response */
    1894               0 :         evhttp_make_header(evcon, req);
    1895                 : 
    1896               0 :         evhttp_write_buffer(evcon, evhttp_send_done, NULL);
    1897               0 : }
    1898                 : 
    1899                 : void
    1900               0 : evhttp_send_reply(struct evhttp_request *req, int code, const char *reason,
    1901                 :     struct evbuffer *databuf)
    1902                 : {
    1903                 :         /* set up to watch for client close */
    1904               0 :         evhttp_connection_start_detectclose(req->evcon);
    1905               0 :         evhttp_response_code(req, code, reason);
    1906                 :         
    1907               0 :         evhttp_send(req, databuf);
    1908               0 : }
    1909                 : 
    1910                 : void
    1911               0 : evhttp_send_reply_start(struct evhttp_request *req, int code,
    1912                 :     const char *reason)
    1913                 : {
    1914                 :         /* set up to watch for client close */
    1915               0 :         evhttp_connection_start_detectclose(req->evcon);
    1916               0 :         evhttp_response_code(req, code, reason);
    1917               0 :         if (req->major == 1 && req->minor == 1) {
    1918                 :                 /* use chunked encoding for HTTP/1.1 */
    1919               0 :                 evhttp_add_header(req->output_headers, "Transfer-Encoding",
    1920                 :                     "chunked");
    1921               0 :                 req->chunked = 1;
    1922                 :         }
    1923               0 :         evhttp_make_header(req->evcon, req);
    1924               0 :         evhttp_write_buffer(req->evcon, NULL, NULL);
    1925               0 : }
    1926                 : 
    1927                 : void
    1928               0 : evhttp_send_reply_chunk(struct evhttp_request *req, struct evbuffer *databuf)
    1929                 : {
    1930               0 :         if (req->chunked) {
    1931               0 :                 evbuffer_add_printf(req->evcon->output_buffer, "%x\r\n",
    1932                 :                                     (unsigned)EVBUFFER_LENGTH(databuf));
    1933                 :         }
    1934               0 :         evbuffer_add_buffer(req->evcon->output_buffer, databuf);
    1935               0 :         if (req->chunked) {
    1936               0 :                 evbuffer_add(req->evcon->output_buffer, "\r\n", 2);
    1937                 :         }
    1938               0 :         evhttp_write_buffer(req->evcon, NULL, NULL);
    1939               0 : }
    1940                 : 
    1941                 : void
    1942               0 : evhttp_send_reply_end(struct evhttp_request *req)
    1943                 : {
    1944               0 :         struct evhttp_connection *evcon = req->evcon;
    1945                 : 
    1946               0 :         if (req->chunked) {
    1947               0 :                 evbuffer_add(req->evcon->output_buffer, "0\r\n\r\n", 5);
    1948               0 :                 evhttp_write_buffer(req->evcon, evhttp_send_done, NULL);
    1949               0 :                 req->chunked = 0;
    1950               0 :         } else if (!event_pending(&evcon->ev, EV_WRITE|EV_TIMEOUT, NULL)) {
    1951                 :                 /* let the connection know that we are done with the request */
    1952               0 :                 evhttp_send_done(evcon, NULL);
    1953                 :         } else {
    1954                 :                 /* make the callback execute after all data has been written */
    1955               0 :                 evcon->cb = evhttp_send_done;
    1956               0 :                 evcon->cb_arg = NULL;
    1957                 :         }
    1958               0 : }
    1959                 : 
    1960                 : void
    1961               0 : evhttp_response_code(struct evhttp_request *req, int code, const char *reason)
    1962                 : {
    1963               0 :         req->kind = EVHTTP_RESPONSE;
    1964               0 :         req->response_code = code;
    1965               0 :         if (req->response_code_line != NULL)
    1966               0 :                 free(req->response_code_line);
    1967               0 :         req->response_code_line = strdup(reason);
    1968               0 : }
    1969                 : 
    1970                 : void
    1971               0 : evhttp_send_page(struct evhttp_request *req, struct evbuffer *databuf)
    1972                 : {
    1973               0 :         if (!req->major || !req->minor) {
    1974               0 :                 req->major = 1;
    1975               0 :                 req->minor = 1;
    1976                 :         }
    1977                 :         
    1978               0 :         if (req->kind != EVHTTP_RESPONSE)
    1979               0 :                 evhttp_response_code(req, 200, "OK");
    1980                 : 
    1981               0 :         evhttp_clear_headers(req->output_headers);
    1982               0 :         evhttp_add_header(req->output_headers, "Content-Type", "text/html");
    1983               0 :         evhttp_add_header(req->output_headers, "Connection", "close");
    1984                 : 
    1985               0 :         evhttp_send(req, databuf);
    1986               0 : }
    1987                 : 
    1988                 : static const char uri_chars[256] = {
    1989                 :         0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0,
    1990                 :         0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0,
    1991                 :         0, 1, 0, 0, 1, 0, 0, 1,   1, 1, 1, 1, 1, 1, 1, 1,
    1992                 :         1, 1, 1, 1, 1, 1, 1, 1,   1, 1, 1, 0, 0, 1, 0, 0,
    1993                 :         /* 64 */
    1994                 :         1, 1, 1, 1, 1, 1, 1, 1,   1, 1, 1, 1, 1, 1, 1, 1,
    1995                 :         1, 1, 1, 1, 1, 1, 1, 1,   1, 1, 1, 0, 0, 0, 0, 1,
    1996                 :         0, 1, 1, 1, 1, 1, 1, 1,   1, 1, 1, 1, 1, 1, 1, 1,
    1997                 :         1, 1, 1, 1, 1, 1, 1, 1,   1, 1, 1, 0, 0, 0, 1, 0,
    1998                 :         /* 128 */
    1999                 :         0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0,
    2000                 :         0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0,
    2001                 :         0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0,
    2002                 :         0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0,
    2003                 :         /* 192 */
    2004                 :         0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0,
    2005                 :         0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0,
    2006                 :         0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0,
    2007                 :         0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0,
    2008                 : };
    2009                 : 
    2010                 : /*
    2011                 :  * Helper functions to encode/decode a URI.
    2012                 :  * The returned string must be freed by the caller.
    2013                 :  */
    2014                 : char *
    2015               0 : evhttp_encode_uri(const char *uri)
    2016                 : {
    2017               0 :         struct evbuffer *buf = evbuffer_new();
    2018                 :         char *p;
    2019                 : 
    2020               0 :         for (p = (char *)uri; *p != '\0'; p++) {
    2021               0 :                 if (uri_chars[(u_char)(*p)]) {
    2022               0 :                         evbuffer_add(buf, p, 1);
    2023                 :                 } else {
    2024               0 :                         evbuffer_add_printf(buf, "%%%02X", (u_char)(*p));
    2025                 :                 }
    2026                 :         }
    2027               0 :         evbuffer_add(buf, "", 1);
    2028               0 :         p = strdup((char *)EVBUFFER_DATA(buf));
    2029               0 :         evbuffer_free(buf);
    2030                 :         
    2031               0 :         return (p);
    2032                 : }
    2033                 : 
    2034                 : char *
    2035               0 : evhttp_decode_uri(const char *uri)
    2036                 : {
    2037                 :         char c, *ret;
    2038               0 :         int i, j, in_query = 0;
    2039                 :         
    2040               0 :         ret = malloc(strlen(uri) + 1);
    2041               0 :         if (ret == NULL)
    2042               0 :                 event_err(1, "%s: malloc(%lu)", __func__,
    2043               0 :                           (unsigned long)(strlen(uri) + 1));
    2044                 :         
    2045               0 :         for (i = j = 0; uri[i] != '\0'; i++) {
    2046               0 :                 c = uri[i];
    2047               0 :                 if (c == '?') {
    2048               0 :                         in_query = 1;
    2049               0 :                 } else if (c == '+' && in_query) {
    2050               0 :                         c = ' ';
    2051               0 :                 } else if (c == '%' && isxdigit((unsigned char)uri[i+1]) &&
    2052               0 :                     isxdigit((unsigned char)uri[i+2])) {
    2053               0 :                         char tmp[] = { uri[i+1], uri[i+2], '\0' };
    2054               0 :                         c = (char)strtol(tmp, NULL, 16);
    2055               0 :                         i += 2;
    2056                 :                 }
    2057               0 :                 ret[j++] = c;
    2058                 :         }
    2059               0 :         ret[j] = '\0';
    2060                 :         
    2061               0 :         return (ret);
    2062                 : }
    2063                 : 
    2064                 : /* 
    2065                 :  * Helper function to parse out arguments in a query.
    2066                 :  * The arguments are separated by key and value.
    2067                 :  * URI should already be decoded.
    2068                 :  */
    2069                 : 
    2070                 : void
    2071               0 : evhttp_parse_query(const char *uri, struct evkeyvalq *headers)
    2072                 : {
    2073                 :         char *line;
    2074                 :         char *argument;
    2075                 :         char *p;
    2076                 : 
    2077               0 :         TAILQ_INIT(headers);
    2078                 : 
    2079                 :         /* No arguments - we are done */
    2080               0 :         if (strchr(uri, '?') == NULL)
    2081               0 :                 return;
    2082                 : 
    2083               0 :         if ((line = strdup(uri)) == NULL)
    2084               0 :                 event_err(1, "%s: strdup", __func__);
    2085                 : 
    2086                 : 
    2087               0 :         argument = line;
    2088                 : 
    2089                 :         /* We already know that there has to be a ? */
    2090               0 :         strsep(&argument, "?");
    2091                 : 
    2092               0 :         p = argument;
    2093               0 :         while (p != NULL && *p != '\0') {
    2094                 :                 char *key, *value;
    2095               0 :                 argument = strsep(&p, "&");
    2096                 : 
    2097               0 :                 value = argument;
    2098               0 :                 key = strsep(&value, "=");
    2099               0 :                 if (value == NULL)
    2100               0 :                         goto error;
    2101                 : 
    2102               0 :                 value = evhttp_decode_uri(value);
    2103                 :                 event_debug(("Query Param: %s -> %s\n", key, value));
    2104               0 :                 evhttp_add_header(headers, key, value);
    2105               0 :                 free(value);
    2106                 :         }
    2107                 : 
    2108                 :  error:
    2109               0 :         free(line);
    2110                 : }
    2111                 : 
    2112                 : static struct evhttp_cb *
    2113               0 : evhttp_dispatch_callback(struct httpcbq *callbacks, struct evhttp_request *req)
    2114                 : {
    2115                 :         struct evhttp_cb *cb;
    2116               0 :         size_t offset = 0;
    2117                 : 
    2118                 :         /* Test for different URLs */
    2119               0 :         char *p = strchr(req->uri, '?');
    2120               0 :         if (p != NULL)
    2121               0 :                 offset = (size_t)(p - req->uri);
    2122                 : 
    2123               0 :         TAILQ_FOREACH(cb, callbacks, next) {
    2124               0 :                 int res = 0;
    2125               0 :                 if (p == NULL) {
    2126               0 :                         res = strcmp(cb->what, req->uri) == 0;
    2127                 :                 } else {
    2128               0 :                         res = ((strncmp(cb->what, req->uri, offset) == 0) &&
    2129               0 :                                         (cb->what[offset] == '\0'));
    2130                 :                 }
    2131                 : 
    2132               0 :                 if (res)
    2133               0 :                         return (cb);
    2134                 :         }
    2135                 : 
    2136               0 :         return (NULL);
    2137                 : }
    2138                 : 
    2139                 : static void
    2140               0 : evhttp_handle_request(struct evhttp_request *req, void *arg)
    2141                 : {
    2142               0 :         struct evhttp *http = arg;
    2143               0 :         struct evhttp_cb *cb = NULL;
    2144                 : 
    2145               0 :         if (req->uri == NULL) {
    2146               0 :                 evhttp_send_error(req, HTTP_BADREQUEST, "Bad Request");
    2147               0 :                 return;
    2148                 :         }
    2149                 : 
    2150               0 :         if ((cb = evhttp_dispatch_callback(&http->callbacks, req)) != NULL) {
    2151               0 :                 (*cb->cb)(req, cb->cbarg);
    2152               0 :                 return;
    2153                 :         }
    2154                 : 
    2155                 :         /* Generic call back */
    2156               0 :         if (http->gencb) {
    2157               0 :                 (*http->gencb)(req, http->gencbarg);
    2158               0 :                 return;
    2159                 :         } else {
    2160                 :                 /* We need to send a 404 here */
    2161                 : #define ERR_FORMAT "<html><head>" \
    2162                 :                     "<title>404 Not Found</title>" \
    2163                 :                     "</head><body>" \
    2164                 :                     "<h1>Not Found</h1>" \
    2165                 :                     "<p>The requested URL %s was not found on this server.</p>"\
    2166                 :                     "</body></html>\n"
    2167                 : 
    2168               0 :                 char *escaped_html = evhttp_htmlescape(req->uri);
    2169               0 :                 struct evbuffer *buf = evbuffer_new();
    2170                 : 
    2171               0 :                 evhttp_response_code(req, HTTP_NOTFOUND, "Not Found");
    2172                 : 
    2173               0 :                 evbuffer_add_printf(buf, ERR_FORMAT, escaped_html);
    2174                 : 
    2175               0 :                 free(escaped_html);
    2176                 : 
    2177               0 :                 evhttp_send_page(req, buf);
    2178                 : 
    2179               0 :                 evbuffer_free(buf);
    2180                 : #undef ERR_FORMAT
    2181                 :         }
    2182                 : }
    2183                 : 
    2184                 : static void
    2185               0 : accept_socket(int fd, short what, void *arg)
    2186                 : {
    2187               0 :         struct evhttp *http = arg;
    2188                 :         struct sockaddr_storage ss;
    2189               0 :         socklen_t addrlen = sizeof(ss);
    2190                 :         int nfd;
    2191                 : 
    2192               0 :         if ((nfd = accept(fd, (struct sockaddr *)&ss, &addrlen)) == -1) {
    2193               0 :                 if (errno != EAGAIN && errno != EINTR)
    2194               0 :                         event_warn("%s: bad accept", __func__);
    2195               0 :                 return;
    2196                 :         }
    2197               0 :         if (evutil_make_socket_nonblocking(nfd) < 0)
    2198               0 :                 return;
    2199                 : 
    2200               0 :         evhttp_get_request(http, nfd, (struct sockaddr *)&ss, addrlen);
    2201                 : }
    2202                 : 
    2203                 : int
    2204               0 : evhttp_bind_socket(struct evhttp *http, const char *address, u_short port)
    2205                 : {
    2206                 :         int fd;
    2207                 :         int res;
    2208                 : 
    2209               0 :         if ((fd = bind_socket(address, port, 1 /*reuse*/)) == -1)
    2210               0 :                 return (-1);
    2211                 : 
    2212               0 :         if (listen(fd, 128) == -1) {
    2213               0 :                 event_warn("%s: listen", __func__);
    2214               0 :                 EVUTIL_CLOSESOCKET(fd);
    2215               0 :                 return (-1);
    2216                 :         }
    2217                 : 
    2218               0 :         res = evhttp_accept_socket(http, fd);
    2219                 :         
    2220                 :         if (res != -1)
    2221                 :                 event_debug(("Bound to port %d - Awaiting connections ... ",
    2222                 :                         port));
    2223                 : 
    2224               0 :         return (res);
    2225                 : }
    2226                 : 
    2227                 : int
    2228               0 : evhttp_accept_socket(struct evhttp *http, int fd)
    2229                 : {
    2230                 :         struct evhttp_bound_socket *bound;
    2231                 :         struct event *ev;
    2232                 :         int res;
    2233                 : 
    2234               0 :         bound = malloc(sizeof(struct evhttp_bound_socket));
    2235               0 :         if (bound == NULL)
    2236               0 :                 return (-1);
    2237                 : 
    2238               0 :         ev = &bound->bind_ev;
    2239                 : 
    2240                 :         /* Schedule the socket for accepting */
    2241               0 :         event_set(ev, fd, EV_READ | EV_PERSIST, accept_socket, http);
    2242               0 :         EVHTTP_BASE_SET(http, ev);
    2243                 : 
    2244               0 :         res = event_add(ev, NULL);
    2245                 : 
    2246               0 :         if (res == -1) {
    2247               0 :                 free(bound);
    2248               0 :                 return (-1);
    2249                 :         }
    2250                 : 
    2251               0 :         TAILQ_INSERT_TAIL(&http->sockets, bound, next);
    2252                 : 
    2253               0 :         return (0);
    2254                 : }
    2255                 : 
    2256                 : static struct evhttp*
    2257               0 : evhttp_new_object(void)
    2258                 : {
    2259               0 :         struct evhttp *http = NULL;
    2260                 : 
    2261               0 :         if ((http = calloc(1, sizeof(struct evhttp))) == NULL) {
    2262               0 :                 event_warn("%s: calloc", __func__);
    2263               0 :                 return (NULL);
    2264                 :         }
    2265                 : 
    2266               0 :         http->timeout = -1;
    2267                 : 
    2268               0 :         TAILQ_INIT(&http->sockets);
    2269               0 :         TAILQ_INIT(&http->callbacks);
    2270               0 :         TAILQ_INIT(&http->connections);
    2271                 : 
    2272               0 :         return (http);
    2273                 : }
    2274                 : 
    2275                 : struct evhttp *
    2276               0 : evhttp_new(struct event_base *base)
    2277                 : {
    2278               0 :         struct evhttp *http = evhttp_new_object();
    2279                 : 
    2280               0 :         http->base = base;
    2281                 : 
    2282               0 :         return (http);
    2283                 : }
    2284                 : 
    2285                 : /*
    2286                 :  * Start a web server on the specified address and port.
    2287                 :  */
    2288                 : 
    2289                 : struct evhttp *
    2290               0 : evhttp_start(const char *address, u_short port)
    2291                 : {
    2292               0 :         struct evhttp *http = evhttp_new_object();
    2293                 : 
    2294               0 :         if (evhttp_bind_socket(http, address, port) == -1) {
    2295               0 :                 free(http);
    2296               0 :                 return (NULL);
    2297                 :         }
    2298                 : 
    2299               0 :         return (http);
    2300                 : }
    2301                 : 
    2302                 : void
    2303               0 : evhttp_free(struct evhttp* http)
    2304                 : {
    2305                 :         struct evhttp_cb *http_cb;
    2306                 :         struct evhttp_connection *evcon;
    2307                 :         struct evhttp_bound_socket *bound;
    2308                 :         int fd;
    2309                 : 
    2310                 :         /* Remove the accepting part */
    2311               0 :         while ((bound = TAILQ_FIRST(&http->sockets)) != NULL) {
    2312               0 :                 TAILQ_REMOVE(&http->sockets, bound, next);
    2313                 : 
    2314               0 :                 fd = bound->bind_ev.ev_fd;
    2315               0 :                 event_del(&bound->bind_ev);
    2316               0 :                 EVUTIL_CLOSESOCKET(fd);
    2317                 : 
    2318               0 :                 free(bound);
    2319                 :         }
    2320                 : 
    2321               0 :         while ((evcon = TAILQ_FIRST(&http->connections)) != NULL) {
    2322                 :                 /* evhttp_connection_free removes the connection */
    2323               0 :                 evhttp_connection_free(evcon);
    2324                 :         }
    2325                 : 
    2326               0 :         while ((http_cb = TAILQ_FIRST(&http->callbacks)) != NULL) {
    2327               0 :                 TAILQ_REMOVE(&http->callbacks, http_cb, next);
    2328               0 :                 free(http_cb->what);
    2329               0 :                 free(http_cb);
    2330                 :         }
    2331                 :         
    2332               0 :         free(http);
    2333               0 : }
    2334                 : 
    2335                 : void
    2336               0 : evhttp_set_timeout(struct evhttp* http, int timeout_in_secs)
    2337                 : {
    2338               0 :         http->timeout = timeout_in_secs;
    2339               0 : }
    2340                 : 
    2341                 : void
    2342               0 : evhttp_set_cb(struct evhttp *http, const char *uri,
    2343                 :     void (*cb)(struct evhttp_request *, void *), void *cbarg)
    2344                 : {
    2345                 :         struct evhttp_cb *http_cb;
    2346                 : 
    2347               0 :         if ((http_cb = calloc(1, sizeof(struct evhttp_cb))) == NULL)
    2348               0 :                 event_err(1, "%s: calloc", __func__);
    2349                 : 
    2350               0 :         http_cb->what = strdup(uri);
    2351               0 :         http_cb->cb = cb;
    2352               0 :         http_cb->cbarg = cbarg;
    2353                 : 
    2354               0 :         TAILQ_INSERT_TAIL(&http->callbacks, http_cb, next);
    2355               0 : }
    2356                 : 
    2357                 : int
    2358               0 : evhttp_del_cb(struct evhttp *http, const char *uri)
    2359                 : {
    2360                 :         struct evhttp_cb *http_cb;
    2361                 : 
    2362               0 :         TAILQ_FOREACH(http_cb, &http->callbacks, next) {
    2363               0 :                 if (strcmp(http_cb->what, uri) == 0)
    2364               0 :                         break;
    2365                 :         }
    2366               0 :         if (http_cb == NULL)
    2367               0 :                 return (-1);
    2368                 : 
    2369               0 :         TAILQ_REMOVE(&http->callbacks, http_cb, next);
    2370               0 :         free(http_cb->what);
    2371               0 :         free(http_cb);
    2372                 : 
    2373               0 :         return (0);
    2374                 : }
    2375                 : 
    2376                 : void
    2377               0 : evhttp_set_gencb(struct evhttp *http,
    2378                 :     void (*cb)(struct evhttp_request *, void *), void *cbarg)
    2379                 : {
    2380               0 :         http->gencb = cb;
    2381               0 :         http->gencbarg = cbarg;
    2382               0 : }
    2383                 : 
    2384                 : /*
    2385                 :  * Request related functions
    2386                 :  */
    2387                 : 
    2388                 : struct evhttp_request *
    2389               0 : evhttp_request_new(void (*cb)(struct evhttp_request *, void *), void *arg)
    2390                 : {
    2391               0 :         struct evhttp_request *req = NULL;
    2392                 : 
    2393                 :         /* Allocate request structure */
    2394               0 :         if ((req = calloc(1, sizeof(struct evhttp_request))) == NULL) {
    2395               0 :                 event_warn("%s: calloc", __func__);
    2396               0 :                 goto error;
    2397                 :         }
    2398                 : 
    2399               0 :         req->kind = EVHTTP_RESPONSE;
    2400               0 :         req->input_headers = calloc(1, sizeof(struct evkeyvalq));
    2401               0 :         if (req->input_headers == NULL) {
    2402               0 :                 event_warn("%s: calloc", __func__);
    2403               0 :                 goto error;
    2404                 :         }
    2405               0 :         TAILQ_INIT(req->input_headers);
    2406                 : 
    2407               0 :         req->output_headers = calloc(1, sizeof(struct evkeyvalq));
    2408               0 :         if (req->output_headers == NULL) {
    2409               0 :                 event_warn("%s: calloc", __func__);
    2410               0 :                 goto error;
    2411                 :         }
    2412               0 :         TAILQ_INIT(req->output_headers);
    2413                 : 
    2414               0 :         if ((req->input_buffer = evbuffer_new()) == NULL) {
    2415               0 :                 event_warn("%s: evbuffer_new", __func__);
    2416               0 :                 goto error;
    2417                 :         }
    2418                 : 
    2419               0 :         if ((req->output_buffer = evbuffer_new()) == NULL) {
    2420               0 :                 event_warn("%s: evbuffer_new", __func__);
    2421               0 :                 goto error;
    2422                 :         }
    2423                 : 
    2424               0 :         req->cb = cb;
    2425               0 :         req->cb_arg = arg;
    2426                 : 
    2427               0 :         return (req);
    2428                 : 
    2429                 :  error:
    2430               0 :         if (req != NULL)
    2431               0 :                 evhttp_request_free(req);
    2432               0 :         return (NULL);
    2433                 : }
    2434                 : 
    2435                 : void
    2436               0 : evhttp_request_free(struct evhttp_request *req)
    2437                 : {
    2438               0 :         if (req->remote_host != NULL)
    2439               0 :                 free(req->remote_host);
    2440               0 :         if (req->uri != NULL)
    2441               0 :                 free(req->uri);
    2442               0 :         if (req->response_code_line != NULL)
    2443               0 :                 free(req->response_code_line);
    2444                 : 
    2445               0 :         evhttp_clear_headers(req->input_headers);
    2446               0 :         free(req->input_headers);
    2447                 : 
    2448               0 :         evhttp_clear_headers(req->output_headers);
    2449               0 :         free(req->output_headers);
    2450                 : 
    2451               0 :         if (req->input_buffer != NULL)
    2452               0 :                 evbuffer_free(req->input_buffer);
    2453                 : 
    2454               0 :         if (req->output_buffer != NULL)
    2455               0 :                 evbuffer_free(req->output_buffer);
    2456                 : 
    2457               0 :         free(req);
    2458               0 : }
    2459                 : 
    2460                 : void
    2461               0 : evhttp_request_set_chunked_cb(struct evhttp_request *req,
    2462                 :     void (*cb)(struct evhttp_request *, void *))
    2463                 : {
    2464               0 :         req->chunk_cb = cb;
    2465               0 : }
    2466                 : 
    2467                 : /*
    2468                 :  * Allows for inspection of the request URI
    2469                 :  */
    2470                 : 
    2471                 : const char *
    2472               0 : evhttp_request_uri(struct evhttp_request *req) {
    2473               0 :         if (req->uri == NULL)
    2474                 :                 event_debug(("%s: request %p has no uri\n", __func__, req));
    2475               0 :         return (req->uri);
    2476                 : }
    2477                 : 
    2478                 : /*
    2479                 :  * Takes a file descriptor to read a request from.
    2480                 :  * The callback is executed once the whole request has been read.
    2481                 :  */
    2482                 : 
    2483                 : static struct evhttp_connection*
    2484               0 : evhttp_get_request_connection(
    2485                 :         struct evhttp* http,
    2486                 :         int fd, struct sockaddr *sa, socklen_t salen)
    2487                 : {
    2488                 :         struct evhttp_connection *evcon;
    2489               0 :         char *hostname = NULL, *portname = NULL;
    2490                 : 
    2491               0 :         name_from_addr(sa, salen, &hostname, &portname);
    2492                 :         event_debug(("%s: new request from %s:%s on %d\n",
    2493                 :                         __func__, hostname, portname, fd));
    2494                 : 
    2495                 :         /* we need a connection object to put the http request on */
    2496               0 :         if ((evcon = evhttp_connection_new(hostname, atoi(portname))) == NULL)
    2497               0 :                 return (NULL);
    2498                 : 
    2499                 :         /* associate the base if we have one*/
    2500               0 :         evhttp_connection_set_base(evcon, http->base);
    2501                 : 
    2502               0 :         evcon->flags |= EVHTTP_CON_INCOMING;
    2503               0 :         evcon->state = EVCON_READING_FIRSTLINE;
    2504                 :         
    2505               0 :         evcon->fd = fd;
    2506                 : 
    2507               0 :         return (evcon);
    2508                 : }
    2509                 : 
    2510                 : static int
    2511               0 : evhttp_associate_new_request_with_connection(struct evhttp_connection *evcon)
    2512                 : {
    2513               0 :         struct evhttp *http = evcon->http_server;
    2514                 :         struct evhttp_request *req;
    2515               0 :         if ((req = evhttp_request_new(evhttp_handle_request, http)) == NULL)
    2516               0 :                 return (-1);
    2517                 : 
    2518               0 :         req->evcon = evcon;  /* the request ends up owning the connection */
    2519               0 :         req->flags |= EVHTTP_REQ_OWN_CONNECTION;
    2520                 :         
    2521               0 :         TAILQ_INSERT_TAIL(&evcon->requests, req, next);
    2522                 :         
    2523               0 :         req->kind = EVHTTP_REQUEST;
    2524                 :         
    2525               0 :         if ((req->remote_host = strdup(evcon->address)) == NULL)
    2526               0 :                 event_err(1, "%s: strdup", __func__);
    2527               0 :         req->remote_port = evcon->port;
    2528                 : 
    2529               0 :         evhttp_start_read(evcon);
    2530                 :         
    2531               0 :         return (0);
    2532                 : }
    2533                 : 
    2534                 : void
    2535               0 : evhttp_get_request(struct evhttp *http, int fd,
    2536                 :     struct sockaddr *sa, socklen_t salen)
    2537                 : {
    2538                 :         struct evhttp_connection *evcon;
    2539                 : 
    2540               0 :         evcon = evhttp_get_request_connection(http, fd, sa, salen);
    2541               0 :         if (evcon == NULL)
    2542               0 :                 return;
    2543                 : 
    2544                 :         /* the timeout can be used by the server to close idle connections */
    2545               0 :         if (http->timeout != -1)
    2546               0 :                 evhttp_connection_set_timeout(evcon, http->timeout);
    2547                 : 
    2548                 :         /* 
    2549                 :          * if we want to accept more than one request on a connection,
    2550                 :          * we need to know which http server it belongs to.
    2551                 :          */
    2552               0 :         evcon->http_server = http;
    2553               0 :         TAILQ_INSERT_TAIL(&http->connections, evcon, next);
    2554                 :         
    2555               0 :         if (evhttp_associate_new_request_with_connection(evcon) == -1)
    2556               0 :                 evhttp_connection_free(evcon);
    2557                 : }
    2558                 : 
    2559                 : 
    2560                 : /*
    2561                 :  * Network helper functions that we do not want to export to the rest of
    2562                 :  * the world.
    2563                 :  */
    2564                 : #if 0 /* Unused */
    2565                 : static struct addrinfo *
    2566                 : addr_from_name(char *address)
    2567                 : {
    2568                 : #ifdef HAVE_GETADDRINFO
    2569                 :         struct addrinfo ai, *aitop;
    2570                 :         int ai_result;
    2571                 : 
    2572                 :         memset(&ai, 0, sizeof(ai));
    2573                 :         ai.ai_family = AF_INET;
    2574                 :         ai.ai_socktype = SOCK_RAW;
    2575                 :         ai.ai_flags = 0;
    2576                 :         if ((ai_result = getaddrinfo(address, NULL, &ai, &aitop)) != 0) {
    2577                 :                 if ( ai_result == EAI_SYSTEM )
    2578                 :                         event_warn("getaddrinfo");
    2579                 :                 else
    2580                 :                         event_warnx("getaddrinfo: %s", gai_strerror(ai_result));
    2581                 :         }
    2582                 : 
    2583                 :         return (aitop);
    2584                 : #else
    2585                 :         assert(0);
    2586                 :         return NULL; /* XXXXX Use gethostbyname, if this function is ever used. */
    2587                 : #endif
    2588                 : }
    2589                 : #endif
    2590                 : 
    2591                 : static void
    2592               0 : name_from_addr(struct sockaddr *sa, socklen_t salen,
    2593                 :     char **phost, char **pport)
    2594                 : {
    2595                 :         char ntop[NI_MAXHOST];
    2596                 :         char strport[NI_MAXSERV];
    2597                 :         int ni_result;
    2598                 : 
    2599                 : #ifdef HAVE_GETNAMEINFO
    2600               0 :         ni_result = getnameinfo(sa, salen,
    2601                 :                 ntop, sizeof(ntop), strport, sizeof(strport),
    2602                 :                 NI_NUMERICHOST|NI_NUMERICSERV);
    2603                 :         
    2604               0 :         if (ni_result != 0) {
    2605               0 :                 if (ni_result == EAI_SYSTEM)
    2606               0 :                         event_err(1, "getnameinfo failed");
    2607                 :                 else
    2608               0 :                         event_errx(1, "getnameinfo failed: %s", gai_strerror(ni_result));
    2609               0 :                 return;
    2610                 :         }
    2611                 : #else
    2612                 :         ni_result = fake_getnameinfo(sa, salen,
    2613                 :                 ntop, sizeof(ntop), strport, sizeof(strport),
    2614                 :                 NI_NUMERICHOST|NI_NUMERICSERV);
    2615                 :         if (ni_result != 0)
    2616                 :                         return;
    2617                 : #endif
    2618               0 :         *phost = ntop;
    2619               0 :         *pport = strport;
    2620                 : }
    2621                 : 
    2622                 : /* Either connect or bind */
    2623                 : 
    2624                 : static int
    2625               0 : bind_socket_ai(struct addrinfo *ai, int reuse)
    2626                 : {
    2627               0 :         int fd, on = 1, r;
    2628                 :         int serrno;
    2629                 : 
    2630                 :         /* Create listen socket */
    2631               0 :         fd = socket(AF_INET, SOCK_STREAM, 0);
    2632               0 :         if (fd == -1) {
    2633               0 :                 event_warn("socket");
    2634               0 :                 return (-1);
    2635                 :         }
    2636                 : 
    2637               0 :         if (evutil_make_socket_nonblocking(fd) < 0)
    2638               0 :                 goto out;
    2639                 : 
    2640                 : #ifndef WIN32
    2641               0 :         if (fcntl(fd, F_SETFD, 1) == -1) {
    2642               0 :                 event_warn("fcntl(F_SETFD)");
    2643               0 :                 goto out;
    2644                 :         }
    2645                 : #endif
    2646                 : 
    2647               0 :         setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (void *)&on, sizeof(on));
    2648               0 :         if (reuse) {
    2649               0 :                 setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
    2650                 :                     (void *)&on, sizeof(on));
    2651                 :         }
    2652                 : 
    2653               0 :         r = bind(fd, ai->ai_addr, ai->ai_addrlen);
    2654               0 :         if (r == -1)
    2655               0 :                 goto out;
    2656                 : 
    2657               0 :         return (fd);
    2658                 : 
    2659                 :  out:
    2660               0 :         serrno = EVUTIL_SOCKET_ERROR();
    2661               0 :         EVUTIL_CLOSESOCKET(fd);
    2662               0 :         EVUTIL_SET_SOCKET_ERROR(serrno);
    2663               0 :         return (-1);
    2664                 : }
    2665                 : 
    2666                 : static struct addrinfo *
    2667               0 : make_addrinfo(const char *address, u_short port)
    2668                 : {
    2669               0 :         struct addrinfo *aitop = NULL;
    2670                 : 
    2671                 : #ifdef HAVE_GETADDRINFO
    2672                 :         struct addrinfo ai;
    2673                 :         char strport[NI_MAXSERV];
    2674                 :         int ai_result;
    2675                 : 
    2676               0 :         memset(&ai, 0, sizeof(ai));
    2677               0 :         ai.ai_family = AF_INET;
    2678               0 :         ai.ai_socktype = SOCK_STREAM;
    2679               0 :         ai.ai_flags = AI_PASSIVE;  /* turn NULL host name into INADDR_ANY */
    2680               0 :         evutil_snprintf(strport, sizeof(strport), "%d", port);
    2681               0 :         if ((ai_result = getaddrinfo(address, strport, &ai, &aitop)) != 0) {
    2682               0 :                 if ( ai_result == EAI_SYSTEM )
    2683               0 :                         event_warn("getaddrinfo");
    2684                 :                 else
    2685               0 :                         event_warnx("getaddrinfo: %s", gai_strerror(ai_result));
    2686               0 :                 return (NULL);
    2687                 :         }
    2688                 : #else
    2689                 :         static int cur;
    2690                 :         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. */
    2691                 :         if (++cur == 2) cur = 0;   /* allow calling this function twice */
    2692                 : 
    2693                 :         if (fake_getaddrinfo(address, &ai[cur]) < 0) {
    2694                 :                 event_warn("fake_getaddrinfo");
    2695                 :                 return (NULL);
    2696                 :         }
    2697                 :         aitop = &ai[cur];
    2698                 :         ((struct sockaddr_in *) aitop->ai_addr)->sin_port = htons(port);
    2699                 : #endif
    2700                 : 
    2701               0 :         return (aitop);
    2702                 : }
    2703                 : 
    2704                 : static int
    2705               0 : bind_socket(const char *address, u_short port, int reuse)
    2706                 : {
    2707                 :         int fd;
    2708               0 :         struct addrinfo *aitop = make_addrinfo(address, port);
    2709                 : 
    2710               0 :         if (aitop == NULL)
    2711               0 :                 return (-1);
    2712                 : 
    2713               0 :         fd = bind_socket_ai(aitop, reuse);
    2714                 : 
    2715                 : #ifdef HAVE_GETADDRINFO
    2716               0 :         freeaddrinfo(aitop);
    2717                 : #else
    2718                 :         fake_freeaddrinfo(aitop);
    2719                 : #endif
    2720                 : 
    2721               0 :         return (fd);
    2722                 : }
    2723                 : 
    2724                 : static int
    2725               0 : socket_connect(int fd, const char *address, unsigned short port)
    2726                 : {
    2727               0 :         struct addrinfo *ai = make_addrinfo(address, port);
    2728               0 :         int res = -1;
    2729                 : 
    2730               0 :         if (ai == NULL) {
    2731                 :                 event_debug(("%s: make_addrinfo: \"%s:%d\"",
    2732                 :                         __func__, address, port));
    2733               0 :                 return (-1);
    2734                 :         }
    2735                 : 
    2736               0 :         if (connect(fd, ai->ai_addr, ai->ai_addrlen) == -1) {
    2737                 : #ifdef WIN32
    2738                 :                 int tmp_error = WSAGetLastError();
    2739                 :                 if (tmp_error != WSAEWOULDBLOCK && tmp_error != WSAEINVAL &&
    2740                 :                     tmp_error != WSAEINPROGRESS) {
    2741                 :                         goto out;
    2742                 :                 }
    2743                 : #else
    2744               0 :                 if (errno != EINPROGRESS) {
    2745               0 :                         goto out;
    2746                 :                 }
    2747                 : #endif
    2748                 :         }
    2749                 : 
    2750                 :         /* everything is fine */
    2751               0 :         res = 0;
    2752                 : 
    2753                 : out:
    2754                 : #ifdef HAVE_GETADDRINFO
    2755               0 :         freeaddrinfo(ai);
    2756                 : #else
    2757                 :         fake_freeaddrinfo(ai);
    2758                 : #endif
    2759                 : 
    2760               0 :         return (res);
    2761                 : }

Generated by: LCOV version 1.7