Coverage Report

Created: 2024-07-23 06:11

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