tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

regress_http.c (132164B)


      1 /*
      2 * Copyright (c) 2003-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 #include "util-internal.h"
     28 
     29 #ifdef _WIN32
     30 #include <winsock2.h>
     31 #include <ws2tcpip.h>
     32 #include <windows.h>
     33 #endif
     34 
     35 #include "event2/event-config.h"
     36 
     37 #include <sys/types.h>
     38 #include <sys/stat.h>
     39 #ifdef EVENT__HAVE_SYS_TIME_H
     40 #include <sys/time.h>
     41 #endif
     42 #include <sys/queue.h>
     43 #ifndef _WIN32
     44 #include <sys/socket.h>
     45 #include <signal.h>
     46 #include <unistd.h>
     47 #include <netdb.h>
     48 #endif
     49 #include <fcntl.h>
     50 #include <stdlib.h>
     51 #include <stdio.h>
     52 #include <string.h>
     53 #include <errno.h>
     54 
     55 #include "event2/dns.h"
     56 
     57 #include "event2/event.h"
     58 #include "event2/http.h"
     59 #include "event2/buffer.h"
     60 #include "event2/bufferevent.h"
     61 #include "event2/bufferevent_ssl.h"
     62 #include "event2/util.h"
     63 #include "event2/listener.h"
     64 #include "log-internal.h"
     65 #include "http-internal.h"
     66 #include "regress.h"
     67 #include "regress_testutils.h"
     68 
     69 #define ARRAY_SIZE(x) (sizeof(x)/sizeof((x)[0]))
     70 
     71 /* set if a test needs to call loopexit on a base */
     72 static struct event_base *exit_base;
     73 
     74 static char const BASIC_REQUEST_BODY[] = "This is funny";
     75 
     76 static void http_basic_cb(struct evhttp_request *req, void *arg);
     77 static void http_timeout_cb(struct evhttp_request *req, void *arg);
     78 static void http_large_cb(struct evhttp_request *req, void *arg);
     79 static void http_chunked_cb(struct evhttp_request *req, void *arg);
     80 static void http_post_cb(struct evhttp_request *req, void *arg);
     81 static void http_put_cb(struct evhttp_request *req, void *arg);
     82 static void http_delete_cb(struct evhttp_request *req, void *arg);
     83 static void http_delay_cb(struct evhttp_request *req, void *arg);
     84 static void http_large_delay_cb(struct evhttp_request *req, void *arg);
     85 static void http_badreq_cb(struct evhttp_request *req, void *arg);
     86 static void http_dispatcher_cb(struct evhttp_request *req, void *arg);
     87 static void http_on_complete_cb(struct evhttp_request *req, void *arg);
     88 
     89 #define HTTP_BIND_IPV6 1
     90 #define HTTP_BIND_SSL 2
     91 #define HTTP_SSL_FILTER 4
     92 static int
     93 http_bind(struct evhttp *myhttp, ev_uint16_t *pport, int mask)
     94 {
     95 int port;
     96 struct evhttp_bound_socket *sock;
     97 int ipv6 = mask & HTTP_BIND_IPV6;
     98 
     99 if (ipv6)
    100 	sock = evhttp_bind_socket_with_handle(myhttp, "::1", *pport);
    101 else
    102 	sock = evhttp_bind_socket_with_handle(myhttp, "127.0.0.1", *pport);
    103 
    104 if (sock == NULL) {
    105 	if (ipv6)
    106 		return -1;
    107 	else
    108 		event_errx(1, "Could not start web server");
    109 }
    110 
    111 port = regress_get_socket_port(evhttp_bound_socket_get_fd(sock));
    112 if (port < 0)
    113 	return -1;
    114 *pport = (ev_uint16_t) port;
    115 
    116 return 0;
    117 }
    118 
    119 #ifdef EVENT__HAVE_OPENSSL
    120 static struct bufferevent *
    121 https_bev(struct event_base *base, void *arg)
    122 {
    123 SSL *ssl = SSL_new(get_ssl_ctx());
    124 
    125 SSL_use_certificate(ssl, ssl_getcert(ssl_getkey()));
    126 SSL_use_PrivateKey(ssl, ssl_getkey());
    127 
    128 return bufferevent_openssl_socket_new(
    129 	base, -1, ssl, BUFFEREVENT_SSL_ACCEPTING,
    130 	BEV_OPT_CLOSE_ON_FREE);
    131 }
    132 #endif
    133 static struct evhttp *
    134 http_setup_gencb(ev_uint16_t *pport, struct event_base *base, int mask,
    135 void (*cb)(struct evhttp_request *, void *), void *cbarg)
    136 {
    137 struct evhttp *myhttp;
    138 
    139 /* Try a few different ports */
    140 myhttp = evhttp_new(base);
    141 
    142 if (http_bind(myhttp, pport, mask) < 0)
    143 	return NULL;
    144 #ifdef EVENT__HAVE_OPENSSL
    145 if (mask & HTTP_BIND_SSL) {
    146 	init_ssl();
    147 	evhttp_set_bevcb(myhttp, https_bev, NULL);
    148 }
    149 #endif
    150 
    151 evhttp_set_gencb(myhttp, cb, cbarg);
    152 
    153 /* Register a callback for certain types of requests */
    154 evhttp_set_cb(myhttp, "/test", http_basic_cb, myhttp);
    155 evhttp_set_cb(myhttp, "/test nonconformant", http_basic_cb, myhttp);
    156 evhttp_set_cb(myhttp, "/timeout", http_timeout_cb, myhttp);
    157 evhttp_set_cb(myhttp, "/large", http_large_cb, base);
    158 evhttp_set_cb(myhttp, "/chunked", http_chunked_cb, base);
    159 evhttp_set_cb(myhttp, "/streamed", http_chunked_cb, base);
    160 evhttp_set_cb(myhttp, "/postit", http_post_cb, base);
    161 evhttp_set_cb(myhttp, "/putit", http_put_cb, base);
    162 evhttp_set_cb(myhttp, "/deleteit", http_delete_cb, base);
    163 evhttp_set_cb(myhttp, "/delay", http_delay_cb, base);
    164 evhttp_set_cb(myhttp, "/largedelay", http_large_delay_cb, base);
    165 evhttp_set_cb(myhttp, "/badrequest", http_badreq_cb, base);
    166 evhttp_set_cb(myhttp, "/oncomplete", http_on_complete_cb, base);
    167 evhttp_set_cb(myhttp, "/", http_dispatcher_cb, base);
    168 return (myhttp);
    169 }
    170 static struct evhttp *
    171 http_setup(ev_uint16_t *pport, struct event_base *base, int mask)
    172 { return http_setup_gencb(pport, base, mask, NULL, NULL); }
    173 
    174 #ifndef NI_MAXSERV
    175 #define NI_MAXSERV 1024
    176 #endif
    177 
    178 static evutil_socket_t
    179 http_connect(const char *address, ev_uint16_t port)
    180 {
    181 /* Stupid code for connecting */
    182 struct evutil_addrinfo ai, *aitop;
    183 char strport[NI_MAXSERV];
    184 
    185 struct sockaddr *sa;
    186 size_t slen;
    187 evutil_socket_t fd;
    188 
    189 memset(&ai, 0, sizeof(ai));
    190 ai.ai_family = AF_INET;
    191 ai.ai_socktype = SOCK_STREAM;
    192 evutil_snprintf(strport, sizeof(strport), "%d", port);
    193 if (evutil_getaddrinfo(address, strport, &ai, &aitop) != 0) {
    194 	event_warn("getaddrinfo");
    195 	return (-1);
    196 }
    197 sa = aitop->ai_addr;
    198 slen = aitop->ai_addrlen;
    199 
    200 fd = socket(AF_INET, SOCK_STREAM, 0);
    201 if (fd == -1)
    202 	event_err(1, "socket failed");
    203 
    204 evutil_make_socket_nonblocking(fd);
    205 if (connect(fd, sa, slen) == -1) {
    206 #ifdef _WIN32
    207 	int tmp_err = WSAGetLastError();
    208 	if (tmp_err != WSAEINPROGRESS && tmp_err != WSAEINVAL &&
    209 	    tmp_err != WSAEWOULDBLOCK)
    210 		event_err(1, "connect failed");
    211 #else
    212 	if (errno != EINPROGRESS)
    213 		event_err(1, "connect failed");
    214 #endif
    215 }
    216 
    217 evutil_freeaddrinfo(aitop);
    218 
    219 return (fd);
    220 }
    221 
    222 /* Helper: do a strcmp on the contents of buf and the string s. */
    223 static int
    224 evbuffer_datacmp(struct evbuffer *buf, const char *s)
    225 {
    226 size_t b_sz = evbuffer_get_length(buf);
    227 size_t s_sz = strlen(s);
    228 unsigned char *d;
    229 int r;
    230 
    231 if (b_sz < s_sz)
    232 	return -1;
    233 
    234 d = evbuffer_pullup(buf, s_sz);
    235 if (!d)
    236 	d = (unsigned char *)"";
    237 if ((r = memcmp(d, s, s_sz)))
    238 	return r;
    239 
    240 if (b_sz > s_sz)
    241 	return 1;
    242 else
    243 	return 0;
    244 }
    245 
    246 /* Helper: Return true iff buf contains s */
    247 static int
    248 evbuffer_contains(struct evbuffer *buf, const char *s)
    249 {
    250 struct evbuffer_ptr ptr;
    251 ptr = evbuffer_search(buf, s, strlen(s), NULL);
    252 return ptr.pos != -1;
    253 }
    254 
    255 static void
    256 http_readcb(struct bufferevent *bev, void *arg)
    257 {
    258 const char *what = BASIC_REQUEST_BODY;
    259 struct event_base *my_base = arg;
    260 
    261 if (evbuffer_contains(bufferevent_get_input(bev), what)) {
    262 	struct evhttp_request *req = evhttp_request_new(NULL, NULL);
    263 	enum message_read_status done;
    264 
    265 	/* req->kind = EVHTTP_RESPONSE; */
    266 	done = evhttp_parse_firstline_(req, bufferevent_get_input(bev));
    267 	if (done != ALL_DATA_READ)
    268 		goto out;
    269 
    270 	done = evhttp_parse_headers_(req, bufferevent_get_input(bev));
    271 	if (done != ALL_DATA_READ)
    272 		goto out;
    273 
    274 	if (done == 1 &&
    275 	    evhttp_find_header(evhttp_request_get_input_headers(req),
    276 		"Content-Type") != NULL)
    277 		test_ok++;
    278 
    279  out:
    280 	evhttp_request_free(req);
    281 	bufferevent_disable(bev, EV_READ);
    282 	if (exit_base)
    283 		event_base_loopexit(exit_base, NULL);
    284 	else if (my_base)
    285 		event_base_loopexit(my_base, NULL);
    286 	else {
    287 		fprintf(stderr, "No way to exit loop!\n");
    288 		exit(1);
    289 	}
    290 }
    291 }
    292 
    293 static void
    294 http_writecb(struct bufferevent *bev, void *arg)
    295 {
    296 if (evbuffer_get_length(bufferevent_get_output(bev)) == 0) {
    297 	/* enable reading of the reply */
    298 	bufferevent_enable(bev, EV_READ);
    299 	test_ok++;
    300 }
    301 }
    302 
    303 static void
    304 http_errorcb(struct bufferevent *bev, short what, void *arg)
    305 {
    306 /** For ssl */
    307 if (what & BEV_EVENT_CONNECTED)
    308 	return;
    309 test_ok = -2;
    310 event_base_loopexit(arg, NULL);
    311 }
    312 
    313 static int found_multi = 0;
    314 static int found_multi2 = 0;
    315 
    316 static void
    317 http_basic_cb(struct evhttp_request *req, void *arg)
    318 {
    319 struct evbuffer *evb = evbuffer_new();
    320 struct evhttp_connection *evcon;
    321 int empty = evhttp_find_header(evhttp_request_get_input_headers(req), "Empty") != NULL;
    322 
    323 TT_BLATHER(("%s: called\n", __func__));
    324 evbuffer_add_printf(evb, BASIC_REQUEST_BODY);
    325 
    326 evcon = evhttp_request_get_connection(req);
    327 tt_assert(evhttp_connection_get_server(evcon) == arg);
    328 
    329 {
    330 	const struct sockaddr *sa;
    331 	char addrbuf[128];
    332 
    333 	sa = evhttp_connection_get_addr(evcon);
    334 	tt_assert(sa);
    335 
    336 	if (sa->sa_family == AF_INET) {
    337 		evutil_format_sockaddr_port_((struct sockaddr *)sa, addrbuf, sizeof(addrbuf));
    338 		tt_assert(!strncmp(addrbuf, "127.0.0.1:", strlen("127.0.0.1:")));
    339 	} else if (sa->sa_family == AF_INET6) {
    340 		evutil_format_sockaddr_port_((struct sockaddr *)sa, addrbuf, sizeof(addrbuf));
    341 		tt_assert(!strncmp(addrbuf, "[::1]:", strlen("[::1]:")));
    342 	} else {
    343 		tt_fail_msg("Unsupported family");
    344 	}
    345 }
    346 
    347 /* For multi-line headers test */
    348 {
    349 	const char *multi =
    350 	    evhttp_find_header(evhttp_request_get_input_headers(req),"X-Multi");
    351 	if (multi) {
    352 		found_multi = !strcmp(multi,"aaaaaaaa a END");
    353 		if (strcmp("END", multi + strlen(multi) - 3) == 0)
    354 			test_ok++;
    355 		if (evhttp_find_header(evhttp_request_get_input_headers(req), "X-Last"))
    356 			test_ok++;
    357 	}
    358 }
    359 {
    360 	const char *multi2 =
    361 	    evhttp_find_header(evhttp_request_get_input_headers(req),"X-Multi-Extra-WS");
    362 	if (multi2) {
    363 		found_multi2 = !strcmp(multi2,"libevent 2.1");
    364 	}
    365 }
    366 
    367 
    368 /* injecting a bad content-length */
    369 if (evhttp_find_header(evhttp_request_get_input_headers(req), "X-Negative"))
    370 	evhttp_add_header(evhttp_request_get_output_headers(req),
    371 	    "Content-Length", "-100");
    372 
    373 /* allow sending of an empty reply */
    374 evhttp_send_reply(req, HTTP_OK, "Everything is fine",
    375     !empty ? evb : NULL);
    376 
    377 end:
    378 evbuffer_free(evb);
    379 }
    380 
    381 static void http_timeout_reply_cb(evutil_socket_t fd, short events, void *arg)
    382 {
    383 struct evhttp_request *req = arg;
    384 evhttp_send_reply(req, HTTP_OK, "Everything is fine", NULL);
    385 test_ok++;
    386 }
    387 static void
    388 http_timeout_cb(struct evhttp_request *req, void *arg)
    389 {
    390 struct timeval when = { 0, 100 };
    391 event_base_once(exit_base, -1, EV_TIMEOUT,
    392     http_timeout_reply_cb, req, &when);
    393 }
    394 
    395 static void
    396 http_large_cb(struct evhttp_request *req, void *arg)
    397 {
    398 struct evbuffer *evb = evbuffer_new();
    399 int i;
    400 
    401 for (i = 0; i < 1<<20; ++i) {
    402 	evbuffer_add_printf(evb, BASIC_REQUEST_BODY);
    403 }
    404 evhttp_send_reply(req, HTTP_OK, "Everything is fine", evb);
    405 evbuffer_free(evb);
    406 }
    407 
    408 static char const* const CHUNKS[] = {
    409 "This is funny",
    410 "but not hilarious.",
    411 "bwv 1052"
    412 };
    413 
    414 struct chunk_req_state {
    415 struct event_base *base;
    416 struct evhttp_request *req;
    417 int i;
    418 };
    419 
    420 static void
    421 http_chunked_trickle_cb(evutil_socket_t fd, short events, void *arg)
    422 {
    423 struct evbuffer *evb = evbuffer_new();
    424 struct chunk_req_state *state = arg;
    425 struct timeval when = { 0, 0 };
    426 
    427 evbuffer_add_printf(evb, "%s", CHUNKS[state->i]);
    428 evhttp_send_reply_chunk(state->req, evb);
    429 evbuffer_free(evb);
    430 
    431 if (++state->i < (int) (sizeof(CHUNKS)/sizeof(CHUNKS[0]))) {
    432 	event_base_once(state->base, -1, EV_TIMEOUT,
    433 	    http_chunked_trickle_cb, state, &when);
    434 } else {
    435 	evhttp_send_reply_end(state->req);
    436 	free(state);
    437 }
    438 }
    439 
    440 static void
    441 http_chunked_cb(struct evhttp_request *req, void *arg)
    442 {
    443 struct timeval when = { 0, 0 };
    444 struct chunk_req_state *state = malloc(sizeof(struct chunk_req_state));
    445 TT_BLATHER(("%s: called\n", __func__));
    446 
    447 memset(state, 0, sizeof(struct chunk_req_state));
    448 state->req = req;
    449 state->base = arg;
    450 
    451 if (strcmp(evhttp_request_get_uri(req), "/streamed") == 0) {
    452 	evhttp_add_header(evhttp_request_get_output_headers(req), "Content-Length", "39");
    453 }
    454 
    455 /* generate a chunked/streamed reply */
    456 evhttp_send_reply_start(req, HTTP_OK, "Everything is fine");
    457 
    458 /* but trickle it across several iterations to ensure we're not
    459  * assuming it comes all at once */
    460 event_base_once(arg, -1, EV_TIMEOUT, http_chunked_trickle_cb, state, &when);
    461 }
    462 
    463 static struct bufferevent *
    464 create_bev(struct event_base *base, evutil_socket_t fd, int ssl_mask, int flags_)
    465 {
    466 int flags = BEV_OPT_DEFER_CALLBACKS | flags_;
    467 struct bufferevent *bev = NULL;
    468 
    469 if (!ssl_mask) {
    470 	bev = bufferevent_socket_new(base, fd, flags);
    471 } else {
    472 #ifdef EVENT__HAVE_OPENSSL
    473 	SSL *ssl = SSL_new(get_ssl_ctx());
    474 	if (ssl_mask & HTTP_SSL_FILTER) {
    475 		struct bufferevent *underlying =
    476 			bufferevent_socket_new(base, fd, flags);
    477 		bev = bufferevent_openssl_filter_new(
    478 			base, underlying, ssl, BUFFEREVENT_SSL_CONNECTING, flags);
    479 	} else {
    480 		bev = bufferevent_openssl_socket_new(
    481 			base, fd, ssl, BUFFEREVENT_SSL_CONNECTING, flags);
    482 	}
    483 	bufferevent_openssl_set_allow_dirty_shutdown(bev, 1);
    484 #endif
    485 }
    486 
    487 return bev;
    488 }
    489 
    490 static void
    491 http_half_writecb(struct bufferevent *bev, void *arg)
    492 {
    493 if (evbuffer_get_length(bufferevent_get_output(bev)) == 0) {
    494 	if (!test_ok) {
    495 		const char http_request[] = "host\r\n"
    496 			"Connection: close\r\n"
    497 			"\r\n";
    498 		bufferevent_write(bev, http_request, strlen(http_request));
    499 	}
    500 	/* enable reading of the reply */
    501 	bufferevent_enable(bev, EV_READ);
    502 	test_ok++;
    503 }
    504 }
    505 
    506 static void
    507 http_basic_test_impl(void *arg, int ssl, const char *request_line)
    508 {
    509 struct basic_test_data *data = arg;
    510 struct bufferevent *bev = NULL;
    511 evutil_socket_t fd;
    512 const char *http_request;
    513 ev_uint16_t port = 0, port2 = 0;
    514 int server_flags = ssl ? HTTP_BIND_SSL : 0;
    515 struct evhttp *http = http_setup(&port, data->base, server_flags);
    516 struct evbuffer *out;
    517 
    518 exit_base = data->base;
    519 
    520 /* bind to a second socket */
    521 if (http_bind(http, &port2, server_flags) == -1) {
    522 	fprintf(stdout, "FAILED (bind)\n");
    523 	exit(1);
    524 }
    525 
    526 fd = http_connect("127.0.0.1", port);
    527 
    528 /* Stupid thing to send a request */
    529 bev = create_bev(data->base, fd, ssl, BEV_OPT_CLOSE_ON_FREE);
    530 bufferevent_setcb(bev, http_readcb, http_half_writecb,
    531     http_errorcb, data->base);
    532 out = bufferevent_get_output(bev);
    533 
    534 /* first half of the http request */
    535 evbuffer_add_printf(out,
    536     "%s\r\n"
    537     "Host: some", request_line);
    538 
    539 test_ok = 0;
    540 event_base_dispatch(data->base);
    541 tt_int_op(test_ok, ==, 3);
    542 
    543 /* connect to the second port */
    544 bufferevent_free(bev);
    545 
    546 fd = http_connect("127.0.0.1", port2);
    547 
    548 /* Stupid thing to send a request */
    549 bev = create_bev(data->base, fd, ssl, BEV_OPT_CLOSE_ON_FREE);
    550 bufferevent_setcb(bev, http_readcb, http_writecb,
    551     http_errorcb, data->base);
    552 out = bufferevent_get_output(bev);
    553 
    554 evbuffer_add_printf(out,
    555     "%s\r\n"
    556     "Host: somehost\r\n"
    557     "Connection: close\r\n"
    558     "\r\n", request_line);
    559 
    560 test_ok = 0;
    561 event_base_dispatch(data->base);
    562 tt_int_op(test_ok, ==, 2);
    563 
    564 /* Connect to the second port again. This time, send an absolute uri. */
    565 bufferevent_free(bev);
    566 
    567 fd = http_connect("127.0.0.1", port2);
    568 
    569 /* Stupid thing to send a request */
    570 bev = create_bev(data->base, fd, ssl, BEV_OPT_CLOSE_ON_FREE);
    571 bufferevent_setcb(bev, http_readcb, http_writecb,
    572     http_errorcb, data->base);
    573 
    574 http_request =
    575     "GET http://somehost.net/test HTTP/1.1\r\n"
    576     "Host: somehost\r\n"
    577     "Connection: close\r\n"
    578     "\r\n";
    579 
    580 bufferevent_write(bev, http_request, strlen(http_request));
    581 
    582 test_ok = 0;
    583 event_base_dispatch(data->base);
    584 tt_int_op(test_ok, ==, 2);
    585 
    586 evhttp_free(http);
    587 end:
    588 if (bev)
    589 	bufferevent_free(bev);
    590 }
    591 static void http_basic_test(void *arg)\
    592 { http_basic_test_impl(arg, 0, "GET /test HTTP/1.1"); }
    593 static void http_basic_trailing_space_test(void *arg)
    594 { http_basic_test_impl(arg, 0, "GET /test HTTP/1.1 "); }
    595 
    596 
    597 static void
    598 http_delay_reply(evutil_socket_t fd, short what, void *arg)
    599 {
    600 struct evhttp_request *req = arg;
    601 
    602 evhttp_send_reply(req, HTTP_OK, "Everything is fine", NULL);
    603 
    604 ++test_ok;
    605 }
    606 
    607 static void
    608 http_delay_cb(struct evhttp_request *req, void *arg)
    609 {
    610 struct timeval tv;
    611 evutil_timerclear(&tv);
    612 tv.tv_sec = 0;
    613 tv.tv_usec = 200 * 1000;
    614 
    615 event_base_once(arg, -1, EV_TIMEOUT, http_delay_reply, req, &tv);
    616 }
    617 
    618 static void
    619 http_badreq_cb(struct evhttp_request *req, void *arg)
    620 {
    621 struct evbuffer *buf = evbuffer_new();
    622 
    623 evhttp_add_header(evhttp_request_get_output_headers(req), "Content-Type", "text/xml; charset=UTF-8");
    624 evbuffer_add_printf(buf, "Hello, %s!", "127.0.0.1");
    625 
    626 evhttp_send_reply(req, HTTP_OK, "OK", buf);
    627 evbuffer_free(buf);
    628 }
    629 
    630 static void
    631 http_badreq_errorcb(struct bufferevent *bev, short what, void *arg)
    632 {
    633 TT_BLATHER(("%s: called (what=%04x, arg=%p)", __func__, what, arg));
    634 /* ignore */
    635 }
    636 
    637 static void
    638 http_badreq_readcb(struct bufferevent *bev, void *arg)
    639 {
    640 const char *what = "Hello, 127.0.0.1";
    641 const char *bad_request = "400 Bad Request";
    642 
    643 if (evbuffer_contains(bufferevent_get_input(bev), bad_request)) {
    644 	TT_FAIL(("%s:bad request detected", __func__));
    645 	bufferevent_disable(bev, EV_READ);
    646 	event_base_loopexit(arg, NULL);
    647 	return;
    648 }
    649 
    650 if (evbuffer_contains(bufferevent_get_input(bev), what)) {
    651 	struct evhttp_request *req = evhttp_request_new(NULL, NULL);
    652 	enum message_read_status done;
    653 
    654 	/* req->kind = EVHTTP_RESPONSE; */
    655 	done = evhttp_parse_firstline_(req, bufferevent_get_input(bev));
    656 	if (done != ALL_DATA_READ)
    657 		goto out;
    658 
    659 	done = evhttp_parse_headers_(req, bufferevent_get_input(bev));
    660 	if (done != ALL_DATA_READ)
    661 		goto out;
    662 
    663 	if (done == 1 &&
    664 	    evhttp_find_header(evhttp_request_get_input_headers(req),
    665 		"Content-Type") != NULL)
    666 		test_ok++;
    667 
    668 out:
    669 	evhttp_request_free(req);
    670 	evbuffer_drain(bufferevent_get_input(bev), evbuffer_get_length(bufferevent_get_input(bev)));
    671 }
    672 
    673 shutdown(bufferevent_getfd(bev), EVUTIL_SHUT_WR);
    674 }
    675 
    676 static void
    677 http_badreq_successcb(evutil_socket_t fd, short what, void *arg)
    678 {
    679 TT_BLATHER(("%s: called (what=%04x, arg=%p)", __func__, what, arg));
    680 event_base_loopexit(exit_base, NULL);
    681 }
    682 
    683 static void
    684 http_bad_request_test(void *arg)
    685 {
    686 struct basic_test_data *data = arg;
    687 struct timeval tv;
    688 struct bufferevent *bev = NULL;
    689 evutil_socket_t fd = EVUTIL_INVALID_SOCKET;
    690 const char *http_request;
    691 ev_uint16_t port=0, port2=0;
    692 struct evhttp *http = http_setup(&port, data->base, 0);
    693 
    694 test_ok = 0;
    695 exit_base = data->base;
    696 
    697 /* bind to a second socket */
    698 if (http_bind(http, &port2, 0) == -1)
    699 	TT_DIE(("Bind socket failed"));
    700 
    701 /* NULL request test */
    702 fd = http_connect("127.0.0.1", port);
    703 tt_assert(fd != EVUTIL_INVALID_SOCKET);
    704 
    705 /* Stupid thing to send a request */
    706 bev = bufferevent_socket_new(data->base, fd, 0);
    707 bufferevent_setcb(bev, http_badreq_readcb, http_writecb,
    708     http_badreq_errorcb, data->base);
    709 bufferevent_enable(bev, EV_READ);
    710 
    711 /* real NULL request */
    712 http_request = "";
    713 
    714 bufferevent_write(bev, http_request, strlen(http_request));
    715 
    716 shutdown(fd, EVUTIL_SHUT_WR);
    717 timerclear(&tv);
    718 tv.tv_usec = 10000;
    719 event_base_once(data->base, -1, EV_TIMEOUT, http_badreq_successcb, bev, &tv);
    720 
    721 event_base_dispatch(data->base);
    722 
    723 bufferevent_free(bev);
    724 evutil_closesocket(fd);
    725 
    726 if (test_ok != 0) {
    727 	fprintf(stdout, "FAILED\n");
    728 	exit(1);
    729 }
    730 
    731 /* Second answer (BAD REQUEST) on connection close */
    732 
    733 /* connect to the second port */
    734 fd = http_connect("127.0.0.1", port2);
    735 tt_assert(fd != EVUTIL_INVALID_SOCKET);
    736 
    737 /* Stupid thing to send a request */
    738 bev = bufferevent_socket_new(data->base, fd, 0);
    739 bufferevent_setcb(bev, http_badreq_readcb, http_writecb,
    740     http_badreq_errorcb, data->base);
    741 bufferevent_enable(bev, EV_READ);
    742 
    743 /* first half of the http request */
    744 http_request =
    745 	"GET /badrequest HTTP/1.0\r\n"	\
    746 	"Connection: Keep-Alive\r\n"	\
    747 	"\r\n";
    748 
    749 bufferevent_write(bev, http_request, strlen(http_request));
    750 
    751 timerclear(&tv);
    752 tv.tv_usec = 10000;
    753 event_base_once(data->base, -1, EV_TIMEOUT, http_badreq_successcb, bev, &tv);
    754 
    755 event_base_dispatch(data->base);
    756 
    757 tt_int_op(test_ok, ==, 2);
    758 
    759 end:
    760 evhttp_free(http);
    761 if (bev)
    762 	bufferevent_free(bev);
    763 if (fd >= 0)
    764 	evutil_closesocket(fd);
    765 }
    766 
    767 static struct evhttp_connection *delayed_client;
    768 
    769 static void
    770 http_large_delay_cb(struct evhttp_request *req, void *arg)
    771 {
    772 struct timeval tv;
    773 evutil_timerclear(&tv);
    774 tv.tv_usec = 500000;
    775 
    776 event_base_once(arg, -1, EV_TIMEOUT, http_delay_reply, req, &tv);
    777 evhttp_connection_fail_(delayed_client, EVREQ_HTTP_EOF);
    778 }
    779 
    780 /*
    781 * HTTP DELETE test,  just piggyback on the basic test
    782 */
    783 
    784 static void
    785 http_delete_cb(struct evhttp_request *req, void *arg)
    786 {
    787 struct evbuffer *evb = evbuffer_new();
    788 int empty = evhttp_find_header(evhttp_request_get_input_headers(req), "Empty") != NULL;
    789 
    790 /* Expecting a DELETE request */
    791 if (evhttp_request_get_command(req) != EVHTTP_REQ_DELETE) {
    792 	fprintf(stdout, "FAILED (delete type)\n");
    793 	exit(1);
    794 }
    795 
    796 TT_BLATHER(("%s: called\n", __func__));
    797 evbuffer_add_printf(evb, BASIC_REQUEST_BODY);
    798 
    799 /* allow sending of an empty reply */
    800 evhttp_send_reply(req, HTTP_OK, "Everything is fine",
    801     !empty ? evb : NULL);
    802 
    803 evbuffer_free(evb);
    804 }
    805 
    806 static void
    807 http_delete_test(void *arg)
    808 {
    809 struct basic_test_data *data = arg;
    810 struct bufferevent *bev;
    811 evutil_socket_t fd = EVUTIL_INVALID_SOCKET;
    812 const char *http_request;
    813 ev_uint16_t port = 0;
    814 struct evhttp *http = http_setup(&port, data->base, 0);
    815 
    816 exit_base = data->base;
    817 test_ok = 0;
    818 
    819 tt_assert(http);
    820 fd = http_connect("127.0.0.1", port);
    821 tt_assert(fd != EVUTIL_INVALID_SOCKET);
    822 
    823 /* Stupid thing to send a request */
    824 bev = bufferevent_socket_new(data->base, fd, 0);
    825 bufferevent_setcb(bev, http_readcb, http_writecb,
    826     http_errorcb, data->base);
    827 
    828 http_request =
    829     "DELETE /deleteit HTTP/1.1\r\n"
    830     "Host: somehost\r\n"
    831     "Connection: close\r\n"
    832     "\r\n";
    833 
    834 bufferevent_write(bev, http_request, strlen(http_request));
    835 
    836 event_base_dispatch(data->base);
    837 
    838 bufferevent_free(bev);
    839 evutil_closesocket(fd);
    840 fd = EVUTIL_INVALID_SOCKET;
    841 
    842 evhttp_free(http);
    843 
    844 tt_int_op(test_ok, ==, 2);
    845 end:
    846 if (fd >= 0)
    847 	evutil_closesocket(fd);
    848 }
    849 
    850 static void
    851 http_sent_cb(struct evhttp_request *req, void *arg)
    852 {
    853 ev_uintptr_t val = (ev_uintptr_t)arg;
    854 struct evbuffer *b;
    855 
    856 if (val != 0xDEADBEEF) {
    857 	fprintf(stdout, "FAILED on_complete_cb argument\n");
    858 	exit(1);
    859 }
    860 
    861 b = evhttp_request_get_output_buffer(req);
    862 if (evbuffer_get_length(b) != 0) {
    863 	fprintf(stdout, "FAILED on_complete_cb output buffer not written\n");
    864 	exit(1);
    865 }
    866 
    867 TT_BLATHER(("%s: called\n", __func__));
    868 
    869 ++test_ok;
    870 }
    871 
    872 static void
    873 http_on_complete_cb(struct evhttp_request *req, void *arg)
    874 {
    875 struct evbuffer *evb = evbuffer_new();
    876 
    877 evhttp_request_set_on_complete_cb(req, http_sent_cb, (void *)0xDEADBEEF);
    878 
    879 TT_BLATHER(("%s: called\n", __func__));
    880 evbuffer_add_printf(evb, BASIC_REQUEST_BODY);
    881 
    882 /* allow sending of an empty reply */
    883 evhttp_send_reply(req, HTTP_OK, "Everything is fine", evb);
    884 
    885 evbuffer_free(evb);
    886 
    887 ++test_ok;
    888 }
    889 
    890 static void
    891 http_on_complete_test(void *arg)
    892 {
    893 struct basic_test_data *data = arg;
    894 struct bufferevent *bev;
    895 evutil_socket_t fd = EVUTIL_INVALID_SOCKET;
    896 const char *http_request;
    897 ev_uint16_t port = 0;
    898 struct evhttp *http = http_setup(&port, data->base, 0);
    899 
    900 exit_base = data->base;
    901 test_ok = 0;
    902 
    903 fd = http_connect("127.0.0.1", port);
    904 tt_assert(fd != EVUTIL_INVALID_SOCKET);
    905 
    906 /* Stupid thing to send a request */
    907 bev = bufferevent_socket_new(data->base, fd, 0);
    908 bufferevent_setcb(bev, http_readcb, http_writecb,
    909     http_errorcb, data->base);
    910 
    911 http_request =
    912     "GET /oncomplete HTTP/1.1\r\n"
    913     "Host: somehost\r\n"
    914     "Connection: close\r\n"
    915     "\r\n";
    916 
    917 bufferevent_write(bev, http_request, strlen(http_request));
    918 
    919 event_base_dispatch(data->base);
    920 
    921 bufferevent_free(bev);
    922 
    923 evhttp_free(http);
    924 
    925 tt_int_op(test_ok, ==, 4);
    926 end:
    927 if (fd >= 0)
    928 	evutil_closesocket(fd);
    929 }
    930 
    931 static void
    932 http_allowed_methods_eventcb(struct bufferevent *bev, short what, void *arg)
    933 {
    934 char **output = arg;
    935 if ((what & (BEV_EVENT_ERROR|BEV_EVENT_EOF))) {
    936 	char buf[4096];
    937 	int n;
    938 	n = evbuffer_remove(bufferevent_get_input(bev), buf,
    939 	    sizeof(buf)-1);
    940 	if (n >= 0) {
    941 		buf[n]='\0';
    942 		if (*output)
    943 			free(*output);
    944 		*output = strdup(buf);
    945 	}
    946 	event_base_loopexit(exit_base, NULL);
    947 }
    948 }
    949 
    950 static void
    951 http_allowed_methods_test(void *arg)
    952 {
    953 struct basic_test_data *data = arg;
    954 struct bufferevent *bev1, *bev2, *bev3;
    955 evutil_socket_t fd1=-1, fd2=-1, fd3=-1;
    956 const char *http_request;
    957 char *result1=NULL, *result2=NULL, *result3=NULL;
    958 ev_uint16_t port = 0;
    959 struct evhttp *http = http_setup(&port, data->base, 0);
    960 
    961 exit_base = data->base;
    962 test_ok = 0;
    963 
    964 fd1 = http_connect("127.0.0.1", port);
    965 tt_assert(fd1 != EVUTIL_INVALID_SOCKET);
    966 
    967 /* GET is out; PATCH is in. */
    968 evhttp_set_allowed_methods(http, EVHTTP_REQ_PATCH);
    969 
    970 /* Stupid thing to send a request */
    971 bev1 = bufferevent_socket_new(data->base, fd1, 0);
    972 bufferevent_enable(bev1, EV_READ|EV_WRITE);
    973 bufferevent_setcb(bev1, NULL, NULL,
    974     http_allowed_methods_eventcb, &result1);
    975 
    976 http_request =
    977     "GET /index.html HTTP/1.1\r\n"
    978     "Host: somehost\r\n"
    979     "Connection: close\r\n"
    980     "\r\n";
    981 
    982 bufferevent_write(bev1, http_request, strlen(http_request));
    983 
    984 event_base_dispatch(data->base);
    985 
    986 fd2 = http_connect("127.0.0.1", port);
    987 tt_assert(fd2 != EVUTIL_INVALID_SOCKET);
    988 
    989 bev2 = bufferevent_socket_new(data->base, fd2, 0);
    990 bufferevent_enable(bev2, EV_READ|EV_WRITE);
    991 bufferevent_setcb(bev2, NULL, NULL,
    992     http_allowed_methods_eventcb, &result2);
    993 
    994 http_request =
    995     "PATCH /test HTTP/1.1\r\n"
    996     "Host: somehost\r\n"
    997     "Connection: close\r\n"
    998     "\r\n";
    999 
   1000 bufferevent_write(bev2, http_request, strlen(http_request));
   1001 
   1002 event_base_dispatch(data->base);
   1003 
   1004 fd3 = http_connect("127.0.0.1", port);
   1005 tt_assert(fd3 != EVUTIL_INVALID_SOCKET);
   1006 
   1007 bev3 = bufferevent_socket_new(data->base, fd3, 0);
   1008 bufferevent_enable(bev3, EV_READ|EV_WRITE);
   1009 bufferevent_setcb(bev3, NULL, NULL,
   1010     http_allowed_methods_eventcb, &result3);
   1011 
   1012 http_request =
   1013     "FLOOP /test HTTP/1.1\r\n"
   1014     "Host: somehost\r\n"
   1015     "Connection: close\r\n"
   1016     "\r\n";
   1017 
   1018 bufferevent_write(bev3, http_request, strlen(http_request));
   1019 
   1020 event_base_dispatch(data->base);
   1021 
   1022 bufferevent_free(bev1);
   1023 bufferevent_free(bev2);
   1024 bufferevent_free(bev3);
   1025 
   1026 evhttp_free(http);
   1027 
   1028 /* Method known but disallowed */
   1029 tt_assert(result1);
   1030 tt_assert(!strncmp(result1, "HTTP/1.1 501 ", strlen("HTTP/1.1 501 ")));
   1031 
   1032 /* Method known and allowed */
   1033 tt_assert(result2);
   1034 tt_assert(!strncmp(result2, "HTTP/1.1 200 ", strlen("HTTP/1.1 200 ")));
   1035 
   1036 /* Method unknown */
   1037 tt_assert(result3);
   1038 tt_assert(!strncmp(result3, "HTTP/1.1 501 ", strlen("HTTP/1.1 501 ")));
   1039 
   1040 end:
   1041 if (result1)
   1042 	free(result1);
   1043 if (result2)
   1044 	free(result2);
   1045 if (result3)
   1046 	free(result3);
   1047 if (fd1 >= 0)
   1048 	evutil_closesocket(fd1);
   1049 if (fd2 >= 0)
   1050 	evutil_closesocket(fd2);
   1051 if (fd3 >= 0)
   1052 	evutil_closesocket(fd3);
   1053 }
   1054 
   1055 static void http_request_no_action_done(struct evhttp_request *, void *);
   1056 static void http_request_done(struct evhttp_request *, void *);
   1057 static void http_request_empty_done(struct evhttp_request *, void *);
   1058 
   1059 static void
   1060 http_connection_test_(struct basic_test_data *data, int persistent,
   1061 const char *address, struct evdns_base *dnsbase, int ipv6, int family,
   1062 int ssl)
   1063 {
   1064 ev_uint16_t port = 0;
   1065 struct evhttp_connection *evcon = NULL;
   1066 struct evhttp_request *req = NULL;
   1067 struct evhttp *http;
   1068 
   1069 int mask = 0;
   1070 if (ipv6)
   1071 	mask |= HTTP_BIND_IPV6;
   1072 if (ssl)
   1073 	mask |= HTTP_BIND_SSL;
   1074 
   1075 http = http_setup(&port, data->base, mask);
   1076 
   1077 test_ok = 0;
   1078 if (!http && ipv6) {
   1079 	tt_skip();
   1080 }
   1081 tt_assert(http);
   1082 
   1083 if (ssl) {
   1084 #ifdef EVENT__HAVE_OPENSSL
   1085 	SSL *ssl = SSL_new(get_ssl_ctx());
   1086 	struct bufferevent *bev = bufferevent_openssl_socket_new(
   1087 		data->base, -1, ssl,
   1088 		BUFFEREVENT_SSL_CONNECTING, BEV_OPT_DEFER_CALLBACKS);
   1089 	bufferevent_openssl_set_allow_dirty_shutdown(bev, 1);
   1090 
   1091 	evcon = evhttp_connection_base_bufferevent_new(data->base, dnsbase, bev, address, port);
   1092 #else
   1093 	tt_skip();
   1094 #endif
   1095 } else {
   1096 	evcon = evhttp_connection_base_new(data->base, dnsbase, address, port);
   1097 }
   1098 tt_assert(evcon);
   1099 evhttp_connection_set_family(evcon, family);
   1100 
   1101 tt_assert(evhttp_connection_get_base(evcon) == data->base);
   1102 
   1103 exit_base = data->base;
   1104 
   1105 tt_assert(evhttp_connection_get_server(evcon) == NULL);
   1106 
   1107 /*
   1108  * At this point, we want to schedule a request to the HTTP
   1109  * server using our make request method.
   1110  */
   1111 req = evhttp_request_new(http_request_done, (void*) BASIC_REQUEST_BODY);
   1112 
   1113 /* Add the information that we care about */
   1114 evhttp_add_header(evhttp_request_get_output_headers(req), "Host", "somehost");
   1115 
   1116 /* We give ownership of the request to the connection */
   1117 if (evhttp_make_request(evcon, req, EVHTTP_REQ_GET, "/test") == -1) {
   1118 	fprintf(stdout, "FAILED\n");
   1119 	exit(1);
   1120 }
   1121 
   1122 event_base_dispatch(data->base);
   1123 
   1124 tt_assert(test_ok);
   1125 
   1126 /* try to make another request over the same connection */
   1127 test_ok = 0;
   1128 
   1129 req = evhttp_request_new(http_request_done, (void*) BASIC_REQUEST_BODY);
   1130 
   1131 /* Add the information that we care about */
   1132 evhttp_add_header(evhttp_request_get_output_headers(req), "Host", "somehost");
   1133 
   1134 /*
   1135  * if our connections are not supposed to be persistent; request
   1136  * a close from the server.
   1137  */
   1138 if (!persistent)
   1139 	evhttp_add_header(evhttp_request_get_output_headers(req), "Connection", "close");
   1140 
   1141 /* We give ownership of the request to the connection */
   1142 if (evhttp_make_request(evcon, req, EVHTTP_REQ_GET, "/test") == -1) {
   1143 	tt_abort_msg("couldn't make request");
   1144 }
   1145 
   1146 event_base_dispatch(data->base);
   1147 
   1148 /* make another request: request empty reply */
   1149 test_ok = 0;
   1150 
   1151 req = evhttp_request_new(http_request_empty_done, data->base);
   1152 
   1153 /* Add the information that we care about */
   1154 evhttp_add_header(evhttp_request_get_output_headers(req), "Empty", "itis");
   1155 
   1156 /* We give ownership of the request to the connection */
   1157 if (evhttp_make_request(evcon, req, EVHTTP_REQ_GET, "/test") == -1) {
   1158 	tt_abort_msg("Couldn't make request");
   1159 }
   1160 
   1161 event_base_dispatch(data->base);
   1162 
   1163 end:
   1164 if (evcon)
   1165 	evhttp_connection_free(evcon);
   1166 if (http)
   1167 	evhttp_free(http);
   1168 }
   1169 
   1170 static void
   1171 http_connection_test(void *arg)
   1172 {
   1173 http_connection_test_(arg, 0, "127.0.0.1", NULL, 0, AF_UNSPEC, 0);
   1174 }
   1175 static void
   1176 http_persist_connection_test(void *arg)
   1177 {
   1178 http_connection_test_(arg, 1, "127.0.0.1", NULL, 0, AF_UNSPEC, 0);
   1179 }
   1180 
   1181 static struct regress_dns_server_table search_table[] = {
   1182 { "localhost", "A", "127.0.0.1", 0, 0 },
   1183 { NULL, NULL, NULL, 0, 0 }
   1184 };
   1185 
   1186 static void
   1187 http_connection_async_test(void *arg)
   1188 {
   1189 struct basic_test_data *data = arg;
   1190 ev_uint16_t port = 0;
   1191 struct evhttp_connection *evcon = NULL;
   1192 struct evhttp_request *req = NULL;
   1193 struct evdns_base *dns_base = NULL;
   1194 ev_uint16_t portnum = 0;
   1195 char address[64];
   1196 struct evhttp *http = http_setup(&port, data->base, 0);
   1197 
   1198 exit_base = data->base;
   1199 tt_assert(regress_dnsserver(data->base, &portnum, search_table));
   1200 
   1201 dns_base = evdns_base_new(data->base, 0/* init name servers */);
   1202 tt_assert(dns_base);
   1203 
   1204 /* Add ourself as the only nameserver, and make sure we really are
   1205  * the only nameserver. */
   1206 evutil_snprintf(address, sizeof(address), "127.0.0.1:%d", portnum);
   1207 evdns_base_nameserver_ip_add(dns_base, address);
   1208 
   1209 test_ok = 0;
   1210 
   1211 evcon = evhttp_connection_base_new(data->base, dns_base, "127.0.0.1", port);
   1212 tt_assert(evcon);
   1213 
   1214 /*
   1215  * At this point, we want to schedule a request to the HTTP
   1216  * server using our make request method.
   1217  */
   1218 
   1219 req = evhttp_request_new(http_request_done, (void*) BASIC_REQUEST_BODY);
   1220 
   1221 /* Add the information that we care about */
   1222 evhttp_add_header(evhttp_request_get_output_headers(req), "Host", "somehost");
   1223 
   1224 /* We give ownership of the request to the connection */
   1225 if (evhttp_make_request(evcon, req, EVHTTP_REQ_GET, "/test") == -1) {
   1226 	fprintf(stdout, "FAILED\n");
   1227 	exit(1);
   1228 }
   1229 
   1230 event_base_dispatch(data->base);
   1231 
   1232 tt_assert(test_ok);
   1233 
   1234 /* try to make another request over the same connection */
   1235 test_ok = 0;
   1236 
   1237 req = evhttp_request_new(http_request_done, (void*) BASIC_REQUEST_BODY);
   1238 
   1239 /* Add the information that we care about */
   1240 evhttp_add_header(evhttp_request_get_output_headers(req), "Host", "somehost");
   1241 
   1242 /*
   1243  * if our connections are not supposed to be persistent; request
   1244  * a close from the server.
   1245  */
   1246 evhttp_add_header(evhttp_request_get_output_headers(req), "Connection", "close");
   1247 
   1248 /* We give ownership of the request to the connection */
   1249 if (evhttp_make_request(evcon, req, EVHTTP_REQ_GET, "/test") == -1) {
   1250 	tt_abort_msg("couldn't make request");
   1251 }
   1252 
   1253 event_base_dispatch(data->base);
   1254 
   1255 /* make another request: request empty reply */
   1256 test_ok = 0;
   1257 
   1258 req = evhttp_request_new(http_request_empty_done, data->base);
   1259 
   1260 /* Add the information that we care about */
   1261 evhttp_add_header(evhttp_request_get_output_headers(req), "Empty", "itis");
   1262 
   1263 /* We give ownership of the request to the connection */
   1264 if (evhttp_make_request(evcon, req, EVHTTP_REQ_GET, "/test") == -1) {
   1265 	tt_abort_msg("Couldn't make request");
   1266 }
   1267 
   1268 event_base_dispatch(data->base);
   1269 
   1270 end:
   1271 if (evcon)
   1272 	evhttp_connection_free(evcon);
   1273 if (http)
   1274 	evhttp_free(http);
   1275 if (dns_base)
   1276 	evdns_base_free(dns_base, 0);
   1277 regress_clean_dnsserver();
   1278 }
   1279 
   1280 static void
   1281 http_autofree_connection_test(void *arg)
   1282 {
   1283 struct basic_test_data *data = arg;
   1284 ev_uint16_t port = 0;
   1285 struct evhttp_connection *evcon = NULL;
   1286 struct evhttp_request *req[2] = { NULL };
   1287 struct evhttp *http = http_setup(&port, data->base, 0);
   1288 size_t i;
   1289 
   1290 test_ok = 0;
   1291 
   1292 evcon = evhttp_connection_base_new(data->base, NULL, "127.0.0.1", port);
   1293 tt_assert(evcon);
   1294 
   1295 /*
   1296  * At this point, we want to schedule two request to the HTTP
   1297  * server using our make request method.
   1298  */
   1299 req[0] = evhttp_request_new(http_request_empty_done, data->base);
   1300 req[1] = evhttp_request_new(http_request_empty_done, data->base);
   1301 
   1302 /* Add the information that we care about */
   1303 for (i = 0; i < ARRAY_SIZE(req); ++i) {
   1304 	evhttp_add_header(evhttp_request_get_output_headers(req[i]), "Host", "somehost");
   1305 	evhttp_add_header(evhttp_request_get_output_headers(req[i]), "Connection", "close");
   1306 	evhttp_add_header(evhttp_request_get_output_headers(req[i]), "Empty", "itis");
   1307 
   1308 	if (evhttp_make_request(evcon, req[i], EVHTTP_REQ_GET, "/test") == -1) {
   1309 		tt_abort_msg("couldn't make request");
   1310 	}
   1311 }
   1312 
   1313 /*
   1314  * Tell libevent to free the connection when the request completes
   1315  *	We then set the evcon pointer to NULL since we don't want to free it
   1316  *	when this function ends.
   1317  */
   1318 evhttp_connection_free_on_completion(evcon);
   1319 evcon = NULL;
   1320 
   1321 for (i = 0; i < ARRAY_SIZE(req); ++i)
   1322 	event_base_dispatch(data->base);
   1323 
   1324 /* at this point, the http server should have no connection */
   1325 tt_assert(TAILQ_FIRST(&http->connections) == NULL);
   1326 
   1327 end:
   1328 if (evcon)
   1329 	evhttp_connection_free(evcon);
   1330 if (http)
   1331 	evhttp_free(http);
   1332 }
   1333 
   1334 static void
   1335 http_request_never_call(struct evhttp_request *req, void *arg)
   1336 {
   1337 fprintf(stdout, "FAILED\n");
   1338 exit(1);
   1339 }
   1340 static void
   1341 http_failed_request_done(struct evhttp_request *req, void *arg)
   1342 {
   1343 tt_assert(!req);
   1344 end:
   1345 event_base_loopexit(arg, NULL);
   1346 }
   1347 #ifndef _WIN32
   1348 static void
   1349 http_timed_out_request_done(struct evhttp_request *req, void *arg)
   1350 {
   1351 tt_assert(req);
   1352 tt_int_op(evhttp_request_get_response_code(req), !=, HTTP_OK);
   1353 end:
   1354 event_base_loopexit(arg, NULL);
   1355 }
   1356 #endif
   1357 
   1358 static void
   1359 http_request_error_cb_with_cancel(enum evhttp_request_error error, void *arg)
   1360 {
   1361 if (error != EVREQ_HTTP_REQUEST_CANCEL) {
   1362 	fprintf(stderr, "FAILED\n");
   1363 	exit(1);
   1364 }
   1365 test_ok = 1;
   1366 
   1367 {
   1368 	struct timeval tv;
   1369 	evutil_timerclear(&tv);
   1370 	tv.tv_sec = 0;
   1371 	tv.tv_usec = 500 * 1000;
   1372 	event_base_loopexit(exit_base, &tv);
   1373 }
   1374 }
   1375 static void
   1376 http_do_cancel(evutil_socket_t fd, short what, void *arg)
   1377 {
   1378 struct evhttp_request *req = arg;
   1379 evhttp_cancel_request(req);
   1380 ++test_ok;
   1381 }
   1382 static void
   1383 http_no_write(struct evbuffer *buffer, const struct evbuffer_cb_info *info, void *arg)
   1384 {
   1385 fprintf(stdout, "FAILED\n");
   1386 exit(1);
   1387 }
   1388 static void
   1389 http_free_evcons(struct evhttp_connection **evcons)
   1390 {
   1391 struct evhttp_connection *evcon, **orig = evcons;
   1392 
   1393 if (!evcons)
   1394 	return;
   1395 
   1396 while ((evcon = *evcons++)) {
   1397 	evhttp_connection_free(evcon);
   1398 }
   1399 free(orig);
   1400 }
   1401 /** fill the backlog to force server drop packages for timeouts */
   1402 static struct evhttp_connection **
   1403 http_fill_backlog(struct event_base *base, int port)
   1404 {
   1405 #define BACKLOG_SIZE 256
   1406 	struct evhttp_connection **evcon = malloc(sizeof(*evcon) * (BACKLOG_SIZE + 1));
   1407 	int i;
   1408 
   1409 	for (i = 0; i < BACKLOG_SIZE; ++i) {
   1410 		struct evhttp_request *req;
   1411 
   1412 		evcon[i] = evhttp_connection_base_new(base, NULL, "127.0.0.1", port);
   1413 		tt_assert(evcon[i]);
   1414 		evhttp_connection_set_timeout(evcon[i], 5);
   1415 
   1416 		req = evhttp_request_new(http_request_never_call, NULL);
   1417 		tt_assert(req);
   1418 		tt_int_op(evhttp_make_request(evcon[i], req, EVHTTP_REQ_GET, "/delay"), !=, -1);
   1419 	}
   1420 	evcon[i] = NULL;
   1421 
   1422 	return evcon;
   1423 end:
   1424 	fprintf(stderr, "Couldn't fill the backlog");
   1425 	return NULL;
   1426 }
   1427 
   1428 enum http_cancel_test_type {
   1429 BASIC = 1,
   1430 BY_HOST = 2,
   1431 NO_NS = 4,
   1432 INACTIVE_SERVER = 8,
   1433 SERVER_TIMEOUT = 16,
   1434 NS_TIMEOUT = 32,
   1435 };
   1436 static struct evhttp_request *
   1437 http_cancel_test_bad_request_new(enum http_cancel_test_type type,
   1438 struct event_base *base)
   1439 {
   1440 #ifndef _WIN32
   1441 if (!(type & NO_NS) && (type & SERVER_TIMEOUT))
   1442 	return evhttp_request_new(http_timed_out_request_done, base);
   1443 else
   1444 #endif
   1445 if ((type & INACTIVE_SERVER) || (type & NO_NS))
   1446 	return evhttp_request_new(http_failed_request_done, base);
   1447 else
   1448 	return NULL;
   1449 }
   1450 static void
   1451 http_cancel_test(void *arg)
   1452 {
   1453 struct basic_test_data *data = arg;
   1454 ev_uint16_t port = 0;
   1455 struct evhttp_connection *evcon = NULL;
   1456 struct evhttp_request *req = NULL;
   1457 struct bufferevent *bufev = NULL;
   1458 struct timeval tv;
   1459 struct evdns_base *dns_base = NULL;
   1460 ev_uint16_t portnum = 0;
   1461 char address[64];
   1462 struct evhttp *inactive_http = NULL;
   1463 struct event_base *inactive_base = NULL;
   1464 struct evhttp_connection **evcons = NULL;
   1465 struct event_base *base_to_fill = data->base;
   1466 
   1467 enum http_cancel_test_type type =
   1468 	(enum http_cancel_test_type)data->setup_data;
   1469 struct evhttp *http = http_setup(&port, data->base, 0);
   1470 
   1471 if (type & BY_HOST) {
   1472 	const char *timeout = (type & NS_TIMEOUT) ? "6" : "3";
   1473 
   1474 	tt_assert(regress_dnsserver(data->base, &portnum, search_table));
   1475 
   1476 	dns_base = evdns_base_new(data->base, 0/* init name servers */);
   1477 	tt_assert(dns_base);
   1478 
   1479 	/** XXX: Hack the port to make timeout after resolving */
   1480 	if (type & NO_NS)
   1481 		++portnum;
   1482 
   1483 	evutil_snprintf(address, sizeof(address), "127.0.0.1:%d", portnum);
   1484 	evdns_base_nameserver_ip_add(dns_base, address);
   1485 
   1486 	evdns_base_set_option(dns_base, "timeout:", timeout);
   1487 	evdns_base_set_option(dns_base, "initial-probe-timeout:", timeout);
   1488 	evdns_base_set_option(dns_base, "attempts:", "1");
   1489 }
   1490 
   1491 exit_base = data->base;
   1492 
   1493 test_ok = 0;
   1494 
   1495 if (type & INACTIVE_SERVER) {
   1496 	port = 0;
   1497 	inactive_base = event_base_new();
   1498 	inactive_http = http_setup(&port, inactive_base, 0);
   1499 
   1500 	base_to_fill = inactive_base;
   1501 }
   1502 
   1503 if (type & SERVER_TIMEOUT)
   1504 	evcons = http_fill_backlog(base_to_fill, port);
   1505 
   1506 evcon = evhttp_connection_base_new(
   1507 	data->base, dns_base,
   1508 	type & BY_HOST ? "localhost" : "127.0.0.1",
   1509 	port);
   1510 if (type & INACTIVE_SERVER)
   1511 	evhttp_connection_set_timeout(evcon, 5);
   1512 tt_assert(evcon);
   1513 
   1514 bufev = evhttp_connection_get_bufferevent(evcon);
   1515 /* Guarantee that we stack in connect() not after waiting EV_READ after
   1516  * write() */
   1517 if (type & SERVER_TIMEOUT)
   1518 	evbuffer_add_cb(bufferevent_get_output(bufev), http_no_write, NULL);
   1519 
   1520 /*
   1521  * At this point, we want to schedule a request to the HTTP
   1522  * server using our make request method.
   1523  */
   1524 
   1525 req = evhttp_request_new(http_request_never_call, NULL);
   1526 evhttp_request_set_error_cb(req, http_request_error_cb_with_cancel);
   1527 
   1528 /* Add the information that we care about */
   1529 evhttp_add_header(evhttp_request_get_output_headers(req), "Host", "somehost");
   1530 
   1531 /* We give ownership of the request to the connection */
   1532 tt_int_op(evhttp_make_request(evcon, req, EVHTTP_REQ_GET, "/delay"),
   1533 	  !=, -1);
   1534 
   1535 evutil_timerclear(&tv);
   1536 tv.tv_sec = 0;
   1537 tv.tv_usec = 100 * 1000;
   1538 
   1539 event_base_once(data->base, -1, EV_TIMEOUT, http_do_cancel, req, &tv);
   1540 
   1541 event_base_dispatch(data->base);
   1542 
   1543 if (type & NO_NS || type & INACTIVE_SERVER)
   1544 	tt_int_op(test_ok, ==, 2); /** no servers responses */
   1545 else
   1546 	tt_int_op(test_ok, ==, 3);
   1547 
   1548 /* try to make another request over the same connection */
   1549 test_ok = 0;
   1550 
   1551 http_free_evcons(evcons);
   1552 if (type & SERVER_TIMEOUT)
   1553 	evcons = http_fill_backlog(base_to_fill, port);
   1554 
   1555 req = http_cancel_test_bad_request_new(type, data->base);
   1556 if (!req)
   1557 	req = evhttp_request_new(http_request_done, (void*) BASIC_REQUEST_BODY);
   1558 
   1559 /* Add the information that we care about */
   1560 evhttp_add_header(evhttp_request_get_output_headers(req), "Host", "somehost");
   1561 
   1562 /* We give ownership of the request to the connection */
   1563 tt_int_op(evhttp_make_request(evcon, req, EVHTTP_REQ_GET, "/test"),
   1564 	  !=, -1);
   1565 
   1566 event_base_dispatch(data->base);
   1567 
   1568 /* make another request: request empty reply */
   1569 test_ok = 0;
   1570 
   1571 http_free_evcons(evcons);
   1572 if (type & SERVER_TIMEOUT)
   1573 	evcons = http_fill_backlog(base_to_fill, port);
   1574 
   1575 req = http_cancel_test_bad_request_new(type, data->base);
   1576 if (!req)
   1577 	req = evhttp_request_new(http_request_empty_done, data->base);
   1578 
   1579 /* Add the information that we care about */
   1580 evhttp_add_header(evhttp_request_get_output_headers(req), "Empty", "itis");
   1581 
   1582 /* We give ownership of the request to the connection */
   1583 tt_int_op(evhttp_make_request(evcon, req, EVHTTP_REQ_GET, "/test"),
   1584 	  !=, -1);
   1585 
   1586 event_base_dispatch(data->base);
   1587 
   1588 end:
   1589 http_free_evcons(evcons);
   1590 if (bufev)
   1591 	evbuffer_remove_cb(bufferevent_get_output(bufev), http_no_write, NULL);
   1592 if (evcon)
   1593 	evhttp_connection_free(evcon);
   1594 if (http)
   1595 	evhttp_free(http);
   1596 if (dns_base)
   1597 	evdns_base_free(dns_base, 0);
   1598 regress_clean_dnsserver();
   1599 if (inactive_http)
   1600 	evhttp_free(inactive_http);
   1601 if (inactive_base)
   1602 	event_base_free(inactive_base);
   1603 }
   1604 
   1605 static void
   1606 http_request_no_action_done(struct evhttp_request *req, void *arg)
   1607 {
   1608 EVUTIL_ASSERT(exit_base);
   1609 event_base_loopexit(exit_base, NULL);
   1610 }
   1611 
   1612 static void
   1613 http_request_done(struct evhttp_request *req, void *arg)
   1614 {
   1615 const char *what = arg;
   1616 
   1617 if (!req) {
   1618 	fprintf(stderr, "FAILED\n");
   1619 	exit(1);
   1620 }
   1621 
   1622 if (evhttp_request_get_response_code(req) != HTTP_OK) {
   1623 	fprintf(stderr, "FAILED\n");
   1624 	exit(1);
   1625 }
   1626 
   1627 if (evhttp_find_header(evhttp_request_get_input_headers(req), "Content-Type") == NULL) {
   1628 	fprintf(stderr, "FAILED\n");
   1629 	exit(1);
   1630 }
   1631 
   1632 if (evbuffer_get_length(evhttp_request_get_input_buffer(req)) != strlen(what)) {
   1633 	fprintf(stderr, "FAILED\n");
   1634 	exit(1);
   1635 }
   1636 
   1637 if (evbuffer_datacmp(evhttp_request_get_input_buffer(req), what) != 0) {
   1638 	fprintf(stderr, "FAILED\n");
   1639 	exit(1);
   1640 }
   1641 
   1642 test_ok = 1;
   1643 EVUTIL_ASSERT(exit_base);
   1644 event_base_loopexit(exit_base, NULL);
   1645 }
   1646 
   1647 static void
   1648 http_request_expect_error(struct evhttp_request *req, void *arg)
   1649 {
   1650 if (evhttp_request_get_response_code(req) == HTTP_OK) {
   1651 	fprintf(stderr, "FAILED\n");
   1652 	exit(1);
   1653 }
   1654 
   1655 test_ok = 1;
   1656 EVUTIL_ASSERT(arg);
   1657 event_base_loopexit(arg, NULL);
   1658 }
   1659 
   1660 /* test virtual hosts */
   1661 static void
   1662 http_virtual_host_test(void *arg)
   1663 {
   1664 struct basic_test_data *data = arg;
   1665 ev_uint16_t port = 0;
   1666 struct evhttp_connection *evcon = NULL;
   1667 struct evhttp_request *req = NULL;
   1668 struct evhttp *second = NULL, *third = NULL;
   1669 evutil_socket_t fd;
   1670 struct bufferevent *bev;
   1671 const char *http_request;
   1672 struct evhttp *http = http_setup(&port, data->base, 0);
   1673 
   1674 exit_base = data->base;
   1675 
   1676 /* virtual host */
   1677 second = evhttp_new(NULL);
   1678 evhttp_set_cb(second, "/funnybunny", http_basic_cb, http);
   1679 third = evhttp_new(NULL);
   1680 evhttp_set_cb(third, "/blackcoffee", http_basic_cb, http);
   1681 
   1682 if (evhttp_add_virtual_host(http, "foo.com", second) == -1) {
   1683 	tt_abort_msg("Couldn't add vhost");
   1684 }
   1685 
   1686 if (evhttp_add_virtual_host(http, "bar.*.foo.com", third) == -1) {
   1687 	tt_abort_msg("Couldn't add wildcarded vhost");
   1688 }
   1689 
   1690 /* add some aliases to the vhosts */
   1691 tt_assert(evhttp_add_server_alias(second, "manolito.info") == 0);
   1692 tt_assert(evhttp_add_server_alias(third, "bonkers.org") == 0);
   1693 
   1694 evcon = evhttp_connection_base_new(data->base, NULL, "127.0.0.1", port);
   1695 tt_assert(evcon);
   1696 
   1697 /* make a request with a different host and expect an error */
   1698 req = evhttp_request_new(http_request_expect_error, data->base);
   1699 
   1700 /* Add the information that we care about */
   1701 evhttp_add_header(evhttp_request_get_output_headers(req), "Host", "somehost");
   1702 
   1703 /* We give ownership of the request to the connection */
   1704 if (evhttp_make_request(evcon, req, EVHTTP_REQ_GET,
   1705 	"/funnybunny") == -1) {
   1706 	tt_abort_msg("Couldn't make request");
   1707 }
   1708 
   1709 event_base_dispatch(data->base);
   1710 
   1711 tt_assert(test_ok == 1);
   1712 
   1713 test_ok = 0;
   1714 
   1715 /* make a request with the right host and expect a response */
   1716 req = evhttp_request_new(http_request_done, (void*) BASIC_REQUEST_BODY);
   1717 
   1718 /* Add the information that we care about */
   1719 evhttp_add_header(evhttp_request_get_output_headers(req), "Host", "foo.com");
   1720 
   1721 /* We give ownership of the request to the connection */
   1722 if (evhttp_make_request(evcon, req, EVHTTP_REQ_GET,
   1723 	"/funnybunny") == -1) {
   1724 	fprintf(stdout, "FAILED\n");
   1725 	exit(1);
   1726 }
   1727 
   1728 event_base_dispatch(data->base);
   1729 
   1730 tt_assert(test_ok == 1);
   1731 
   1732 test_ok = 0;
   1733 
   1734 /* make a request with the right host and expect a response */
   1735 req = evhttp_request_new(http_request_done, (void*) BASIC_REQUEST_BODY);
   1736 
   1737 /* Add the information that we care about */
   1738 evhttp_add_header(evhttp_request_get_output_headers(req), "Host", "bar.magic.foo.com");
   1739 
   1740 /* We give ownership of the request to the connection */
   1741 if (evhttp_make_request(evcon, req, EVHTTP_REQ_GET,
   1742 	"/blackcoffee") == -1) {
   1743 	tt_abort_msg("Couldn't make request");
   1744 }
   1745 
   1746 event_base_dispatch(data->base);
   1747 
   1748 tt_assert(test_ok == 1)
   1749 
   1750 test_ok = 0;
   1751 
   1752 /* make a request with the right host and expect a response */
   1753 req = evhttp_request_new(http_request_done, (void*) BASIC_REQUEST_BODY);
   1754 
   1755 /* Add the information that we care about */
   1756 evhttp_add_header(evhttp_request_get_output_headers(req), "Host", "manolito.info");
   1757 
   1758 /* We give ownership of the request to the connection */
   1759 if (evhttp_make_request(evcon, req, EVHTTP_REQ_GET,
   1760 	"/funnybunny") == -1) {
   1761 	tt_abort_msg("Couldn't make request");
   1762 }
   1763 
   1764 event_base_dispatch(data->base);
   1765 
   1766 tt_assert(test_ok == 1)
   1767 
   1768 test_ok = 0;
   1769 
   1770 /* make a request with the right host and expect a response */
   1771 req = evhttp_request_new(http_request_done, (void*) BASIC_REQUEST_BODY);
   1772 
   1773 /* Add the Host header. This time with the optional port. */
   1774 evhttp_add_header(evhttp_request_get_output_headers(req), "Host", "bonkers.org:8000");
   1775 
   1776 /* We give ownership of the request to the connection */
   1777 if (evhttp_make_request(evcon, req, EVHTTP_REQ_GET,
   1778 	"/blackcoffee") == -1) {
   1779 	tt_abort_msg("Couldn't make request");
   1780 }
   1781 
   1782 event_base_dispatch(data->base);
   1783 
   1784 tt_assert(test_ok == 1)
   1785 
   1786 test_ok = 0;
   1787 
   1788 /* Now make a raw request with an absolute URI. */
   1789 fd = http_connect("127.0.0.1", port);
   1790 tt_assert(fd != EVUTIL_INVALID_SOCKET);
   1791 
   1792 /* Stupid thing to send a request */
   1793 bev = bufferevent_socket_new(data->base, fd, 0);
   1794 bufferevent_setcb(bev, http_readcb, http_writecb,
   1795     http_errorcb, NULL);
   1796 
   1797 /* The host in the URI should override the Host: header */
   1798 http_request =
   1799     "GET http://manolito.info/funnybunny HTTP/1.1\r\n"
   1800     "Host: somehost\r\n"
   1801     "Connection: close\r\n"
   1802     "\r\n";
   1803 
   1804 bufferevent_write(bev, http_request, strlen(http_request));
   1805 
   1806 event_base_dispatch(data->base);
   1807 
   1808 tt_int_op(test_ok, ==, 2);
   1809 
   1810 bufferevent_free(bev);
   1811 evutil_closesocket(fd);
   1812 
   1813 end:
   1814 if (evcon)
   1815 	evhttp_connection_free(evcon);
   1816 if (http)
   1817 	evhttp_free(http);
   1818 }
   1819 
   1820 
   1821 /* test date header and content length */
   1822 
   1823 static void
   1824 http_request_empty_done(struct evhttp_request *req, void *arg)
   1825 {
   1826 if (!req) {
   1827 	fprintf(stderr, "FAILED\n");
   1828 	exit(1);
   1829 }
   1830 
   1831 if (evhttp_request_get_response_code(req) != HTTP_OK) {
   1832 	fprintf(stderr, "FAILED\n");
   1833 	exit(1);
   1834 }
   1835 
   1836 if (evhttp_find_header(evhttp_request_get_input_headers(req), "Date") == NULL) {
   1837 	fprintf(stderr, "FAILED\n");
   1838 	exit(1);
   1839 }
   1840 
   1841 
   1842 if (evhttp_find_header(evhttp_request_get_input_headers(req), "Content-Length") == NULL) {
   1843 	fprintf(stderr, "FAILED\n");
   1844 	exit(1);
   1845 }
   1846 
   1847 if (strcmp(evhttp_find_header(evhttp_request_get_input_headers(req), "Content-Length"),
   1848 	"0")) {
   1849 	fprintf(stderr, "FAILED\n");
   1850 	exit(1);
   1851 }
   1852 
   1853 if (evbuffer_get_length(evhttp_request_get_input_buffer(req)) != 0) {
   1854 	fprintf(stderr, "FAILED\n");
   1855 	exit(1);
   1856 }
   1857 
   1858 test_ok = 1;
   1859 EVUTIL_ASSERT(arg);
   1860 event_base_loopexit(arg, NULL);
   1861 }
   1862 
   1863 /*
   1864 * HTTP DISPATCHER test
   1865 */
   1866 
   1867 void
   1868 http_dispatcher_cb(struct evhttp_request *req, void *arg)
   1869 {
   1870 
   1871 struct evbuffer *evb = evbuffer_new();
   1872 TT_BLATHER(("%s: called\n", __func__));
   1873 evbuffer_add_printf(evb, "DISPATCHER_TEST");
   1874 
   1875 evhttp_send_reply(req, HTTP_OK, "Everything is fine", evb);
   1876 
   1877 evbuffer_free(evb);
   1878 }
   1879 
   1880 static void
   1881 http_dispatcher_test_done(struct evhttp_request *req, void *arg)
   1882 {
   1883 struct event_base *base = arg;
   1884 const char *what = "DISPATCHER_TEST";
   1885 
   1886 if (!req) {
   1887 	fprintf(stderr, "FAILED\n");
   1888 	exit(1);
   1889 }
   1890 
   1891 if (evhttp_request_get_response_code(req) != HTTP_OK) {
   1892 	fprintf(stderr, "FAILED\n");
   1893 	exit(1);
   1894 }
   1895 
   1896 if (evhttp_find_header(evhttp_request_get_input_headers(req), "Content-Type") == NULL) {
   1897 	fprintf(stderr, "FAILED (content type)\n");
   1898 	exit(1);
   1899 }
   1900 
   1901 if (evbuffer_get_length(evhttp_request_get_input_buffer(req)) != strlen(what)) {
   1902 	fprintf(stderr, "FAILED (length %lu vs %lu)\n",
   1903 	    (unsigned long)evbuffer_get_length(evhttp_request_get_input_buffer(req)), (unsigned long)strlen(what));
   1904 	exit(1);
   1905 }
   1906 
   1907 if (evbuffer_datacmp(evhttp_request_get_input_buffer(req), what) != 0) {
   1908 	fprintf(stderr, "FAILED (data)\n");
   1909 	exit(1);
   1910 }
   1911 
   1912 test_ok = 1;
   1913 event_base_loopexit(base, NULL);
   1914 }
   1915 
   1916 static void
   1917 http_dispatcher_test(void *arg)
   1918 {
   1919 struct basic_test_data *data = arg;
   1920 ev_uint16_t port = 0;
   1921 struct evhttp_connection *evcon = NULL;
   1922 struct evhttp_request *req = NULL;
   1923 struct evhttp *http = http_setup(&port, data->base, 0);
   1924 
   1925 test_ok = 0;
   1926 
   1927 evcon = evhttp_connection_base_new(data->base, NULL, "127.0.0.1", port);
   1928 tt_assert(evcon);
   1929 
   1930 /* also bind to local host */
   1931 evhttp_connection_set_local_address(evcon, "127.0.0.1");
   1932 
   1933 /*
   1934  * At this point, we want to schedule an HTTP GET request
   1935  * server using our make request method.
   1936  */
   1937 
   1938 req = evhttp_request_new(http_dispatcher_test_done, data->base);
   1939 tt_assert(req);
   1940 
   1941 /* Add the information that we care about */
   1942 evhttp_add_header(evhttp_request_get_output_headers(req), "Host", "somehost");
   1943 
   1944 if (evhttp_make_request(evcon, req, EVHTTP_REQ_GET, "/?arg=val") == -1) {
   1945 	tt_abort_msg("Couldn't make request");
   1946 }
   1947 
   1948 event_base_dispatch(data->base);
   1949 
   1950 end:
   1951 if (evcon)
   1952 	evhttp_connection_free(evcon);
   1953 if (http)
   1954 	evhttp_free(http);
   1955 }
   1956 
   1957 /*
   1958 * HTTP POST test.
   1959 */
   1960 
   1961 void http_postrequest_done(struct evhttp_request *, void *);
   1962 
   1963 #define POST_DATA "Okay.  Not really printf"
   1964 
   1965 static void
   1966 http_post_test(void *arg)
   1967 {
   1968 struct basic_test_data *data = arg;
   1969 ev_uint16_t port = 0;
   1970 struct evhttp_connection *evcon = NULL;
   1971 struct evhttp_request *req = NULL;
   1972 struct evhttp *http = http_setup(&port, data->base, 0);
   1973 
   1974 test_ok = 0;
   1975 
   1976 evcon = evhttp_connection_base_new(data->base, NULL, "127.0.0.1", port);
   1977 tt_assert(evcon);
   1978 
   1979 /*
   1980  * At this point, we want to schedule an HTTP POST request
   1981  * server using our make request method.
   1982  */
   1983 
   1984 req = evhttp_request_new(http_postrequest_done, data->base);
   1985 tt_assert(req);
   1986 
   1987 /* Add the information that we care about */
   1988 evhttp_add_header(evhttp_request_get_output_headers(req), "Host", "somehost");
   1989 evbuffer_add_printf(evhttp_request_get_output_buffer(req), POST_DATA);
   1990 
   1991 if (evhttp_make_request(evcon, req, EVHTTP_REQ_POST, "/postit") == -1) {
   1992 	tt_abort_msg("Couldn't make request");
   1993 }
   1994 
   1995 event_base_dispatch(data->base);
   1996 
   1997 tt_int_op(test_ok, ==, 1);
   1998 
   1999 test_ok = 0;
   2000 
   2001 req = evhttp_request_new(http_postrequest_done, data->base);
   2002 tt_assert(req);
   2003 
   2004 /* Now try with 100-continue. */
   2005 
   2006 /* Add the information that we care about */
   2007 evhttp_add_header(evhttp_request_get_output_headers(req), "Host", "somehost");
   2008 evhttp_add_header(evhttp_request_get_output_headers(req), "Expect", "100-continue");
   2009 evbuffer_add_printf(evhttp_request_get_output_buffer(req), POST_DATA);
   2010 
   2011 if (evhttp_make_request(evcon, req, EVHTTP_REQ_POST, "/postit") == -1) {
   2012 	tt_abort_msg("Couldn't make request");
   2013 }
   2014 
   2015 event_base_dispatch(data->base);
   2016 
   2017 tt_int_op(test_ok, ==, 1);
   2018 
   2019 evhttp_connection_free(evcon);
   2020 evhttp_free(http);
   2021 
   2022 end:
   2023 ;
   2024 }
   2025 
   2026 void
   2027 http_post_cb(struct evhttp_request *req, void *arg)
   2028 {
   2029 struct evbuffer *evb;
   2030 TT_BLATHER(("%s: called\n", __func__));
   2031 
   2032 /* Yes, we are expecting a post request */
   2033 if (evhttp_request_get_command(req) != EVHTTP_REQ_POST) {
   2034 	fprintf(stdout, "FAILED (post type)\n");
   2035 	exit(1);
   2036 }
   2037 
   2038 if (evbuffer_get_length(evhttp_request_get_input_buffer(req)) != strlen(POST_DATA)) {
   2039 	fprintf(stdout, "FAILED (length: %lu vs %lu)\n",
   2040 	    (unsigned long) evbuffer_get_length(evhttp_request_get_input_buffer(req)), (unsigned long) strlen(POST_DATA));
   2041 	exit(1);
   2042 }
   2043 
   2044 if (evbuffer_datacmp(evhttp_request_get_input_buffer(req), POST_DATA) != 0) {
   2045 	fprintf(stdout, "FAILED (data)\n");
   2046 	fprintf(stdout, "Got :%s\n", evbuffer_pullup(evhttp_request_get_input_buffer(req),-1));
   2047 	fprintf(stdout, "Want:%s\n", POST_DATA);
   2048 	exit(1);
   2049 }
   2050 
   2051 evb = evbuffer_new();
   2052 evbuffer_add_printf(evb, BASIC_REQUEST_BODY);
   2053 
   2054 evhttp_send_reply(req, HTTP_OK, "Everything is fine", evb);
   2055 
   2056 evbuffer_free(evb);
   2057 }
   2058 
   2059 void
   2060 http_postrequest_done(struct evhttp_request *req, void *arg)
   2061 {
   2062 const char *what = BASIC_REQUEST_BODY;
   2063 struct event_base *base = arg;
   2064 
   2065 if (req == NULL) {
   2066 	fprintf(stderr, "FAILED (timeout)\n");
   2067 	exit(1);
   2068 }
   2069 
   2070 if (evhttp_request_get_response_code(req) != HTTP_OK) {
   2071 
   2072 	fprintf(stderr, "FAILED (response code)\n");
   2073 	exit(1);
   2074 }
   2075 
   2076 if (evhttp_find_header(evhttp_request_get_input_headers(req), "Content-Type") == NULL) {
   2077 	fprintf(stderr, "FAILED (content type)\n");
   2078 	exit(1);
   2079 }
   2080 
   2081 if (evbuffer_get_length(evhttp_request_get_input_buffer(req)) != strlen(what)) {
   2082 	fprintf(stderr, "FAILED (length %lu vs %lu)\n",
   2083 	    (unsigned long)evbuffer_get_length(evhttp_request_get_input_buffer(req)), (unsigned long)strlen(what));
   2084 	exit(1);
   2085 }
   2086 
   2087 if (evbuffer_datacmp(evhttp_request_get_input_buffer(req), what) != 0) {
   2088 	fprintf(stderr, "FAILED (data)\n");
   2089 	exit(1);
   2090 }
   2091 
   2092 test_ok = 1;
   2093 event_base_loopexit(base, NULL);
   2094 }
   2095 
   2096 /*
   2097 * HTTP PUT test, basically just like POST, but ...
   2098 */
   2099 
   2100 void http_putrequest_done(struct evhttp_request *, void *);
   2101 
   2102 #define PUT_DATA "Hi, I'm some PUT data"
   2103 
   2104 static void
   2105 http_put_test(void *arg)
   2106 {
   2107 struct basic_test_data *data = arg;
   2108 ev_uint16_t port = 0;
   2109 struct evhttp_connection *evcon = NULL;
   2110 struct evhttp_request *req = NULL;
   2111 struct evhttp *http = http_setup(&port, data->base, 0);
   2112 
   2113 test_ok = 0;
   2114 
   2115 evcon = evhttp_connection_base_new(data->base, NULL, "127.0.0.1", port);
   2116 tt_assert(evcon);
   2117 
   2118 /*
   2119  * Schedule the HTTP PUT request
   2120  */
   2121 
   2122 req = evhttp_request_new(http_putrequest_done, data->base);
   2123 tt_assert(req);
   2124 
   2125 /* Add the information that we care about */
   2126 evhttp_add_header(evhttp_request_get_output_headers(req), "Host", "someotherhost");
   2127 evbuffer_add_printf(evhttp_request_get_output_buffer(req), PUT_DATA);
   2128 
   2129 if (evhttp_make_request(evcon, req, EVHTTP_REQ_PUT, "/putit") == -1) {
   2130 	tt_abort_msg("Couldn't make request");
   2131 }
   2132 
   2133 event_base_dispatch(data->base);
   2134 
   2135 evhttp_connection_free(evcon);
   2136 evhttp_free(http);
   2137 
   2138 tt_int_op(test_ok, ==, 1);
   2139 end:
   2140 ;
   2141 }
   2142 
   2143 void
   2144 http_put_cb(struct evhttp_request *req, void *arg)
   2145 {
   2146 struct evbuffer *evb;
   2147 TT_BLATHER(("%s: called\n", __func__));
   2148 
   2149 /* Expecting a PUT request */
   2150 if (evhttp_request_get_command(req) != EVHTTP_REQ_PUT) {
   2151 	fprintf(stdout, "FAILED (put type)\n");
   2152 	exit(1);
   2153 }
   2154 
   2155 if (evbuffer_get_length(evhttp_request_get_input_buffer(req)) != strlen(PUT_DATA)) {
   2156 	fprintf(stdout, "FAILED (length: %lu vs %lu)\n",
   2157 	    (unsigned long)evbuffer_get_length(evhttp_request_get_input_buffer(req)), (unsigned long)strlen(PUT_DATA));
   2158 	exit(1);
   2159 }
   2160 
   2161 if (evbuffer_datacmp(evhttp_request_get_input_buffer(req), PUT_DATA) != 0) {
   2162 	fprintf(stdout, "FAILED (data)\n");
   2163 	fprintf(stdout, "Got :%s\n", evbuffer_pullup(evhttp_request_get_input_buffer(req),-1));
   2164 	fprintf(stdout, "Want:%s\n", PUT_DATA);
   2165 	exit(1);
   2166 }
   2167 
   2168 evb = evbuffer_new();
   2169 evbuffer_add_printf(evb, "That ain't funny");
   2170 
   2171 evhttp_send_reply(req, HTTP_OK, "Everything is great", evb);
   2172 
   2173 evbuffer_free(evb);
   2174 }
   2175 
   2176 void
   2177 http_putrequest_done(struct evhttp_request *req, void *arg)
   2178 {
   2179 struct event_base *base = arg;
   2180 const char *what = "That ain't funny";
   2181 
   2182 if (req == NULL) {
   2183 	fprintf(stderr, "FAILED (timeout)\n");
   2184 	exit(1);
   2185 }
   2186 
   2187 if (evhttp_request_get_response_code(req) != HTTP_OK) {
   2188 
   2189 	fprintf(stderr, "FAILED (response code)\n");
   2190 	exit(1);
   2191 }
   2192 
   2193 if (evhttp_find_header(evhttp_request_get_input_headers(req), "Content-Type") == NULL) {
   2194 	fprintf(stderr, "FAILED (content type)\n");
   2195 	exit(1);
   2196 }
   2197 
   2198 if (evbuffer_get_length(evhttp_request_get_input_buffer(req)) != strlen(what)) {
   2199 	fprintf(stderr, "FAILED (length %lu vs %lu)\n",
   2200 	    (unsigned long)evbuffer_get_length(evhttp_request_get_input_buffer(req)), (unsigned long)strlen(what));
   2201 	exit(1);
   2202 }
   2203 
   2204 
   2205 if (evbuffer_datacmp(evhttp_request_get_input_buffer(req), what) != 0) {
   2206 	fprintf(stderr, "FAILED (data)\n");
   2207 	exit(1);
   2208 }
   2209 
   2210 test_ok = 1;
   2211 event_base_loopexit(base, NULL);
   2212 }
   2213 
   2214 static void
   2215 http_failure_readcb(struct bufferevent *bev, void *arg)
   2216 {
   2217 const char *what = "400 Bad Request";
   2218 if (evbuffer_contains(bufferevent_get_input(bev), what)) {
   2219 	test_ok = 2;
   2220 	bufferevent_disable(bev, EV_READ);
   2221 	event_base_loopexit(arg, NULL);
   2222 }
   2223 }
   2224 
   2225 /*
   2226 * Testing that the HTTP server can deal with a malformed request.
   2227 */
   2228 static void
   2229 http_failure_test(void *arg)
   2230 {
   2231 struct basic_test_data *data = arg;
   2232 struct bufferevent *bev;
   2233 evutil_socket_t fd = EVUTIL_INVALID_SOCKET;
   2234 const char *http_request;
   2235 ev_uint16_t port = 0;
   2236 struct evhttp *http = http_setup(&port, data->base, 0);
   2237 
   2238 test_ok = 0;
   2239 
   2240 fd = http_connect("127.0.0.1", port);
   2241 tt_assert(fd != EVUTIL_INVALID_SOCKET);
   2242 
   2243 /* Stupid thing to send a request */
   2244 bev = bufferevent_socket_new(data->base, fd, 0);
   2245 bufferevent_setcb(bev, http_failure_readcb, http_writecb,
   2246     http_errorcb, data->base);
   2247 
   2248 http_request = "illegal request\r\n";
   2249 
   2250 bufferevent_write(bev, http_request, strlen(http_request));
   2251 
   2252 event_base_dispatch(data->base);
   2253 
   2254 bufferevent_free(bev);
   2255 
   2256 evhttp_free(http);
   2257 
   2258 tt_int_op(test_ok, ==, 2);
   2259 end:
   2260 if (fd >= 0)
   2261 	evutil_closesocket(fd);
   2262 }
   2263 
   2264 static void
   2265 close_detect_done(struct evhttp_request *req, void *arg)
   2266 {
   2267 struct timeval tv;
   2268 tt_assert(req);
   2269 tt_assert(evhttp_request_get_response_code(req) == HTTP_OK);
   2270 
   2271 test_ok = 1;
   2272 
   2273 end:
   2274 evutil_timerclear(&tv);
   2275 tv.tv_usec = 150000;
   2276 event_base_loopexit(arg, &tv);
   2277 }
   2278 
   2279 static void
   2280 close_detect_launch(evutil_socket_t fd, short what, void *arg)
   2281 {
   2282 struct evhttp_connection *evcon = arg;
   2283 struct event_base *base = evhttp_connection_get_base(evcon);
   2284 struct evhttp_request *req;
   2285 
   2286 req = evhttp_request_new(close_detect_done, base);
   2287 
   2288 /* Add the information that we care about */
   2289 evhttp_add_header(evhttp_request_get_output_headers(req), "Host", "somehost");
   2290 
   2291 /* We give ownership of the request to the connection */
   2292 if (evhttp_make_request(evcon, req, EVHTTP_REQ_GET, "/test") == -1) {
   2293 	tt_fail_msg("Couldn't make request");
   2294 }
   2295 }
   2296 
   2297 static void
   2298 close_detect_cb(struct evhttp_request *req, void *arg)
   2299 {
   2300 struct evhttp_connection *evcon = arg;
   2301 struct event_base *base = evhttp_connection_get_base(evcon);
   2302 struct timeval tv;
   2303 
   2304 if (req != NULL && evhttp_request_get_response_code(req) != HTTP_OK) {
   2305 	tt_abort_msg("Failed");
   2306 }
   2307 
   2308 evutil_timerclear(&tv);
   2309 tv.tv_sec = 0;   /* longer than the http time out */
   2310 tv.tv_usec = 600000;   /* longer than the http time out */
   2311 
   2312 /* launch a new request on the persistent connection in .3 seconds */
   2313 event_base_once(base, -1, EV_TIMEOUT, close_detect_launch, evcon, &tv);
   2314 end:
   2315 ;
   2316 }
   2317 
   2318 
   2319 static void
   2320 http_close_detection_(struct basic_test_data *data, int with_delay)
   2321 {
   2322 ev_uint16_t port = 0;
   2323 struct evhttp_connection *evcon = NULL;
   2324 struct evhttp_request *req = NULL;
   2325 const struct timeval sec_tenth = { 0, 100000 };
   2326 struct evhttp *http = http_setup(&port, data->base, 0);
   2327 
   2328 test_ok = 0;
   2329 
   2330 /* .1 second timeout */
   2331 evhttp_set_timeout_tv(http, &sec_tenth);
   2332 
   2333 evcon = evhttp_connection_base_new(data->base, NULL,
   2334     "127.0.0.1", port);
   2335 tt_assert(evcon);
   2336 evhttp_connection_set_timeout_tv(evcon, &sec_tenth);
   2337 
   2338 
   2339 tt_assert(evcon);
   2340 delayed_client = evcon;
   2341 
   2342 /*
   2343  * At this point, we want to schedule a request to the HTTP
   2344  * server using our make request method.
   2345  */
   2346 
   2347 req = evhttp_request_new(close_detect_cb, evcon);
   2348 
   2349 /* Add the information that we care about */
   2350 evhttp_add_header(evhttp_request_get_output_headers(req), "Host", "somehost");
   2351 
   2352 /* We give ownership of the request to the connection */
   2353 if (evhttp_make_request(evcon,
   2354     req, EVHTTP_REQ_GET, with_delay ? "/largedelay" : "/test") == -1) {
   2355 	tt_abort_msg("couldn't make request");
   2356 }
   2357 
   2358 event_base_dispatch(data->base);
   2359 
   2360 /* at this point, the http server should have no connection */
   2361 tt_assert(TAILQ_FIRST(&http->connections) == NULL);
   2362 
   2363 end:
   2364 if (evcon)
   2365 	evhttp_connection_free(evcon);
   2366 if (http)
   2367 	evhttp_free(http);
   2368 }
   2369 static void
   2370 http_close_detection_test(void *arg)
   2371 {
   2372 http_close_detection_(arg, 0);
   2373 }
   2374 static void
   2375 http_close_detection_delay_test(void *arg)
   2376 {
   2377 http_close_detection_(arg, 1);
   2378 }
   2379 
   2380 static void
   2381 http_highport_test(void *arg)
   2382 {
   2383 struct basic_test_data *data = arg;
   2384 int i = -1;
   2385 struct evhttp *myhttp = NULL;
   2386 
   2387 /* Try a few different ports */
   2388 for (i = 0; i < 50; ++i) {
   2389 	myhttp = evhttp_new(data->base);
   2390 	if (evhttp_bind_socket(myhttp, "127.0.0.1", 65535 - i) == 0) {
   2391 		test_ok = 1;
   2392 		evhttp_free(myhttp);
   2393 		return;
   2394 	}
   2395 	evhttp_free(myhttp);
   2396 }
   2397 
   2398 tt_fail_msg("Couldn't get a high port");
   2399 }
   2400 
   2401 static void
   2402 http_bad_header_test(void *ptr)
   2403 {
   2404 struct evkeyvalq headers;
   2405 
   2406 TAILQ_INIT(&headers);
   2407 
   2408 tt_want(evhttp_add_header(&headers, "One", "Two") == 0);
   2409 tt_want(evhttp_add_header(&headers, "One", "Two\r\n Three") == 0);
   2410 tt_want(evhttp_add_header(&headers, "One\r", "Two") == -1);
   2411 tt_want(evhttp_add_header(&headers, "One\n", "Two") == -1);
   2412 tt_want(evhttp_add_header(&headers, "One", "Two\r") == -1);
   2413 tt_want(evhttp_add_header(&headers, "One", "Two\n") == -1);
   2414 
   2415 evhttp_clear_headers(&headers);
   2416 }
   2417 
   2418 static int validate_header(
   2419 const struct evkeyvalq* headers,
   2420 const char *key, const char *value)
   2421 {
   2422 const char *real_val = evhttp_find_header(headers, key);
   2423 tt_assert(real_val != NULL);
   2424 tt_want(strcmp(real_val, value) == 0);
   2425 end:
   2426 return (0);
   2427 }
   2428 
   2429 static void
   2430 http_parse_query_test(void *ptr)
   2431 {
   2432 struct evkeyvalq headers;
   2433 int r;
   2434 
   2435 TAILQ_INIT(&headers);
   2436 
   2437 r = evhttp_parse_query("http://www.test.com/?q=test", &headers);
   2438 tt_want(validate_header(&headers, "q", "test") == 0);
   2439 tt_int_op(r, ==, 0);
   2440 evhttp_clear_headers(&headers);
   2441 
   2442 r = evhttp_parse_query("http://www.test.com/?q=test&foo=bar", &headers);
   2443 tt_want(validate_header(&headers, "q", "test") == 0);
   2444 tt_want(validate_header(&headers, "foo", "bar") == 0);
   2445 tt_int_op(r, ==, 0);
   2446 evhttp_clear_headers(&headers);
   2447 
   2448 r = evhttp_parse_query("http://www.test.com/?q=test+foo", &headers);
   2449 tt_want(validate_header(&headers, "q", "test foo") == 0);
   2450 tt_int_op(r, ==, 0);
   2451 evhttp_clear_headers(&headers);
   2452 
   2453 r = evhttp_parse_query("http://www.test.com/?q=test%0Afoo", &headers);
   2454 tt_want(validate_header(&headers, "q", "test\nfoo") == 0);
   2455 tt_int_op(r, ==, 0);
   2456 evhttp_clear_headers(&headers);
   2457 
   2458 r = evhttp_parse_query("http://www.test.com/?q=test%0Dfoo", &headers);
   2459 tt_want(validate_header(&headers, "q", "test\rfoo") == 0);
   2460 tt_int_op(r, ==, 0);
   2461 evhttp_clear_headers(&headers);
   2462 
   2463 r = evhttp_parse_query("http://www.test.com/?q=test&&q2", &headers);
   2464 tt_int_op(r, ==, -1);
   2465 evhttp_clear_headers(&headers);
   2466 
   2467 r = evhttp_parse_query("http://www.test.com/?q=test+this", &headers);
   2468 tt_want(validate_header(&headers, "q", "test this") == 0);
   2469 tt_int_op(r, ==, 0);
   2470 evhttp_clear_headers(&headers);
   2471 
   2472 r = evhttp_parse_query("http://www.test.com/?q=test&q2=foo", &headers);
   2473 tt_int_op(r, ==, 0);
   2474 tt_want(validate_header(&headers, "q", "test") == 0);
   2475 tt_want(validate_header(&headers, "q2", "foo") == 0);
   2476 evhttp_clear_headers(&headers);
   2477 
   2478 r = evhttp_parse_query("http://www.test.com/?q&q2=foo", &headers);
   2479 tt_int_op(r, ==, -1);
   2480 evhttp_clear_headers(&headers);
   2481 
   2482 r = evhttp_parse_query("http://www.test.com/?q=foo&q2", &headers);
   2483 tt_int_op(r, ==, -1);
   2484 evhttp_clear_headers(&headers);
   2485 
   2486 r = evhttp_parse_query("http://www.test.com/?q=foo&q2&q3=x", &headers);
   2487 tt_int_op(r, ==, -1);
   2488 evhttp_clear_headers(&headers);
   2489 
   2490 r = evhttp_parse_query("http://www.test.com/?q=&q2=&q3=", &headers);
   2491 tt_int_op(r, ==, 0);
   2492 tt_want(validate_header(&headers, "q", "") == 0);
   2493 tt_want(validate_header(&headers, "q2", "") == 0);
   2494 tt_want(validate_header(&headers, "q3", "") == 0);
   2495 evhttp_clear_headers(&headers);
   2496 
   2497 end:
   2498 evhttp_clear_headers(&headers);
   2499 }
   2500 static void
   2501 http_parse_query_str_test(void *ptr)
   2502 {
   2503 struct evkeyvalq headers;
   2504 int r;
   2505 
   2506 TAILQ_INIT(&headers);
   2507 
   2508 r = evhttp_parse_query_str("http://www.test.com/?q=test", &headers);
   2509 tt_assert(evhttp_find_header(&headers, "q") == NULL);
   2510 tt_int_op(r, ==, 0);
   2511 evhttp_clear_headers(&headers);
   2512 
   2513 r = evhttp_parse_query_str("q=test", &headers);
   2514 tt_want(validate_header(&headers, "q", "test") == 0);
   2515 tt_int_op(r, ==, 0);
   2516 evhttp_clear_headers(&headers);
   2517 
   2518 end:
   2519 evhttp_clear_headers(&headers);
   2520 }
   2521 
   2522 static void
   2523 http_parse_uri_test(void *ptr)
   2524 {
   2525 const int nonconform = (ptr != NULL);
   2526 const unsigned parse_flags =
   2527     nonconform ? EVHTTP_URI_NONCONFORMANT : 0;
   2528 struct evhttp_uri *uri = NULL;
   2529 char url_tmp[4096];
   2530 #define URI_PARSE(uri) \
   2531 evhttp_uri_parse_with_flags((uri), parse_flags)
   2532 
   2533 #define TT_URI(want) do { 						\
   2534 char *ret = evhttp_uri_join(uri, url_tmp, sizeof(url_tmp));	\
   2535 tt_want(ret != NULL);						\
   2536 tt_want(ret == url_tmp);					\
   2537 if (strcmp(ret,want) != 0)					\
   2538 	TT_FAIL(("\"%s\" != \"%s\"",ret,want));			\
   2539 } while(0)
   2540 
   2541 tt_want(evhttp_uri_join(NULL, 0, 0) == NULL);
   2542 tt_want(evhttp_uri_join(NULL, url_tmp, 0) == NULL);
   2543 tt_want(evhttp_uri_join(NULL, url_tmp, sizeof(url_tmp)) == NULL);
   2544 
   2545 /* bad URIs: parsing */
   2546 #define BAD(s) do {							\
   2547 	if (URI_PARSE(s) != NULL)				\
   2548 		TT_FAIL(("Expected error parsing \"%s\"",s));	\
   2549 } while(0)
   2550 /* Nonconformant URIs we can parse: parsing */
   2551 #define NCF(s) do {							\
   2552 	uri = URI_PARSE(s);					\
   2553 	if (uri != NULL && !nonconform) {			\
   2554 		TT_FAIL(("Expected error parsing \"%s\"",s));	\
   2555 	} else if (uri == NULL && nonconform) {			\
   2556 		TT_FAIL(("Couldn't parse nonconformant URI \"%s\"", \
   2557 			s));					\
   2558 	}							\
   2559 	if (uri) {						\
   2560 		tt_want(evhttp_uri_join(uri, url_tmp,		\
   2561 			sizeof(url_tmp)));			\
   2562 		evhttp_uri_free(uri);				\
   2563 	}							\
   2564 } while(0)
   2565 
   2566 NCF("http://www.test.com/ why hello");
   2567 NCF("http://www.test.com/why-hello\x01");
   2568 NCF("http://www.test.com/why-hello?\x01");
   2569 NCF("http://www.test.com/why-hello#\x01");
   2570 BAD("http://www.\x01.test.com/why-hello");
   2571 BAD("http://www.%7test.com/why-hello");
   2572 NCF("http://www.test.com/why-hell%7o");
   2573 BAD("h%3ttp://www.test.com/why-hello");
   2574 NCF("http://www.test.com/why-hello%7");
   2575 NCF("http://www.test.com/why-hell%7o");
   2576 NCF("http://www.test.com/foo?ba%r");
   2577 NCF("http://www.test.com/foo#ba%r");
   2578 BAD("99:99/foo");
   2579 BAD("http://www.test.com:999x/");
   2580 BAD("http://www.test.com:x/");
   2581 BAD("http://[hello-there]/");
   2582 BAD("http://[::1]]/");
   2583 BAD("http://[::1/");
   2584 BAD("http://[foob/");
   2585 BAD("http://[/");
   2586 BAD("http://[ffff:ffff:ffff:ffff:Ffff:ffff:ffff:"
   2587             "ffff:ffff:ffff:ffff:ffff:ffff:ffff]/");
   2588 BAD("http://[vX.foo]/");
   2589 BAD("http://[vX.foo]/");
   2590 BAD("http://[v.foo]/");
   2591 BAD("http://[v5.fo%o]/");
   2592 BAD("http://[v5X]/");
   2593 BAD("http://[v5]/");
   2594 BAD("http://[]/");
   2595 BAD("http://f\x01red@www.example.com/");
   2596 BAD("http://f%0red@www.example.com/");
   2597 BAD("http://www.example.com:9999999999999999999999999999999999999/");
   2598 BAD("http://www.example.com:hihi/");
   2599 BAD("://www.example.com/");
   2600 
   2601 /* bad URIs: joining */
   2602 uri = evhttp_uri_new();
   2603 tt_want(0==evhttp_uri_set_host(uri, "www.example.com"));
   2604 tt_want(evhttp_uri_join(uri, url_tmp, sizeof(url_tmp)) != NULL);
   2605 /* not enough space: */
   2606 tt_want(evhttp_uri_join(uri, url_tmp, 3) == NULL);
   2607 /* host is set, but path doesn't start with "/": */
   2608 tt_want(0==evhttp_uri_set_path(uri, "hi_mom"));
   2609 tt_want(evhttp_uri_join(uri, url_tmp, sizeof(url_tmp)) == NULL);
   2610 tt_want(evhttp_uri_join(uri, NULL, sizeof(url_tmp))==NULL);
   2611 tt_want(evhttp_uri_join(uri, url_tmp, 0)==NULL);
   2612 evhttp_uri_free(uri);
   2613 uri = URI_PARSE("mailto:foo@bar");
   2614 tt_want(uri != NULL);
   2615 tt_want(evhttp_uri_get_host(uri) == NULL);
   2616 tt_want(evhttp_uri_get_userinfo(uri) == NULL);
   2617 tt_want(evhttp_uri_get_port(uri) == -1);
   2618 tt_want(!strcmp(evhttp_uri_get_scheme(uri), "mailto"));
   2619 tt_want(!strcmp(evhttp_uri_get_path(uri), "foo@bar"));
   2620 tt_want(evhttp_uri_get_query(uri) == NULL);
   2621 tt_want(evhttp_uri_get_fragment(uri) == NULL);
   2622 TT_URI("mailto:foo@bar");
   2623 evhttp_uri_free(uri);
   2624 
   2625 uri = evhttp_uri_new();
   2626 /* Bad URI usage: setting invalid values */
   2627 tt_want(-1 == evhttp_uri_set_scheme(uri,""));
   2628 tt_want(-1 == evhttp_uri_set_scheme(uri,"33"));
   2629 tt_want(-1 == evhttp_uri_set_scheme(uri,"hi!"));
   2630 tt_want(-1 == evhttp_uri_set_userinfo(uri,"hello@"));
   2631 tt_want(-1 == evhttp_uri_set_host(uri,"[1.2.3.4]"));
   2632 tt_want(-1 == evhttp_uri_set_host(uri,"["));
   2633 tt_want(-1 == evhttp_uri_set_host(uri,"www.[foo].com"));
   2634 tt_want(-1 == evhttp_uri_set_port(uri,-3));
   2635 tt_want(-1 == evhttp_uri_set_path(uri,"hello?world"));
   2636 tt_want(-1 == evhttp_uri_set_query(uri,"hello#world"));
   2637 tt_want(-1 == evhttp_uri_set_fragment(uri,"hello#world"));
   2638 /* Valid URI usage: setting valid values */
   2639 tt_want(0 == evhttp_uri_set_scheme(uri,"http"));
   2640 tt_want(0 == evhttp_uri_set_scheme(uri,NULL));
   2641 tt_want(0 == evhttp_uri_set_userinfo(uri,"username:pass"));
   2642 tt_want(0 == evhttp_uri_set_userinfo(uri,NULL));
   2643 tt_want(0 == evhttp_uri_set_host(uri,"www.example.com"));
   2644 tt_want(0 == evhttp_uri_set_host(uri,"1.2.3.4"));
   2645 tt_want(0 == evhttp_uri_set_host(uri,"[1:2:3:4::]"));
   2646 tt_want(0 == evhttp_uri_set_host(uri,"[v7.wobblewobble]"));
   2647 tt_want(0 == evhttp_uri_set_host(uri,NULL));
   2648 tt_want(0 == evhttp_uri_set_host(uri,""));
   2649 tt_want(0 == evhttp_uri_set_port(uri, -1));
   2650 tt_want(0 == evhttp_uri_set_port(uri, 80));
   2651 tt_want(0 == evhttp_uri_set_port(uri, 65535));
   2652 tt_want(0 == evhttp_uri_set_path(uri, ""));
   2653 tt_want(0 == evhttp_uri_set_path(uri, "/documents/public/index.html"));
   2654 tt_want(0 == evhttp_uri_set_path(uri, NULL));
   2655 tt_want(0 == evhttp_uri_set_query(uri, "key=val&key2=val2"));
   2656 tt_want(0 == evhttp_uri_set_query(uri, "keyvalblarg"));
   2657 tt_want(0 == evhttp_uri_set_query(uri, ""));
   2658 tt_want(0 == evhttp_uri_set_query(uri, NULL));
   2659 tt_want(0 == evhttp_uri_set_fragment(uri, ""));
   2660 tt_want(0 == evhttp_uri_set_fragment(uri, "here?i?am"));
   2661 tt_want(0 == evhttp_uri_set_fragment(uri, NULL));
   2662 evhttp_uri_free(uri);
   2663 
   2664 /* Valid parsing */
   2665 uri = URI_PARSE("http://www.test.com/?q=t%33est");
   2666 tt_want(strcmp(evhttp_uri_get_scheme(uri), "http") == 0);
   2667 tt_want(strcmp(evhttp_uri_get_host(uri), "www.test.com") == 0);
   2668 tt_want(strcmp(evhttp_uri_get_path(uri), "/") == 0);
   2669 tt_want(strcmp(evhttp_uri_get_query(uri), "q=t%33est") == 0);
   2670 tt_want(evhttp_uri_get_userinfo(uri) == NULL);
   2671 tt_want(evhttp_uri_get_port(uri) == -1);
   2672 tt_want(evhttp_uri_get_fragment(uri) == NULL);
   2673 TT_URI("http://www.test.com/?q=t%33est");
   2674 evhttp_uri_free(uri);
   2675 
   2676 uri = URI_PARSE("http://%77ww.test.com");
   2677 tt_want(strcmp(evhttp_uri_get_scheme(uri), "http") == 0);
   2678 tt_want(strcmp(evhttp_uri_get_host(uri), "%77ww.test.com") == 0);
   2679 tt_want(strcmp(evhttp_uri_get_path(uri), "") == 0);
   2680 tt_want(evhttp_uri_get_query(uri) == NULL);
   2681 tt_want(evhttp_uri_get_userinfo(uri) == NULL);
   2682 tt_want(evhttp_uri_get_port(uri) == -1);
   2683 tt_want(evhttp_uri_get_fragment(uri) == NULL);
   2684 TT_URI("http://%77ww.test.com");
   2685 evhttp_uri_free(uri);
   2686 
   2687 uri = URI_PARSE("http://www.test.com?q=test");
   2688 tt_want(strcmp(evhttp_uri_get_scheme(uri), "http") == 0);
   2689 tt_want(strcmp(evhttp_uri_get_host(uri), "www.test.com") == 0);
   2690 tt_want(strcmp(evhttp_uri_get_path(uri), "") == 0);
   2691 tt_want(strcmp(evhttp_uri_get_query(uri), "q=test") == 0);
   2692 tt_want(evhttp_uri_get_userinfo(uri) == NULL);
   2693 tt_want(evhttp_uri_get_port(uri) == -1);
   2694 tt_want(evhttp_uri_get_fragment(uri) == NULL);
   2695 TT_URI("http://www.test.com?q=test");
   2696 evhttp_uri_free(uri);
   2697 
   2698 uri = URI_PARSE("http://www.test.com#fragment");
   2699 tt_want(strcmp(evhttp_uri_get_scheme(uri), "http") == 0);
   2700 tt_want(strcmp(evhttp_uri_get_host(uri), "www.test.com") == 0);
   2701 tt_want(strcmp(evhttp_uri_get_path(uri), "") == 0);
   2702 tt_want(evhttp_uri_get_query(uri) == NULL);
   2703 tt_want(evhttp_uri_get_userinfo(uri) == NULL);
   2704 tt_want(evhttp_uri_get_port(uri) == -1);
   2705 tt_want_str_op(evhttp_uri_get_fragment(uri), ==, "fragment");
   2706 TT_URI("http://www.test.com#fragment");
   2707 evhttp_uri_free(uri);
   2708 
   2709 uri = URI_PARSE("http://8000/");
   2710 tt_want(strcmp(evhttp_uri_get_scheme(uri), "http") == 0);
   2711 tt_want(strcmp(evhttp_uri_get_host(uri), "8000") == 0);
   2712 tt_want(strcmp(evhttp_uri_get_path(uri), "/") == 0);
   2713 tt_want(evhttp_uri_get_query(uri) == NULL);
   2714 tt_want(evhttp_uri_get_userinfo(uri) == NULL);
   2715 tt_want(evhttp_uri_get_port(uri) == -1);
   2716 tt_want(evhttp_uri_get_fragment(uri) == NULL);
   2717 TT_URI("http://8000/");
   2718 evhttp_uri_free(uri);
   2719 
   2720 uri = URI_PARSE("http://:8000/");
   2721 tt_want(strcmp(evhttp_uri_get_scheme(uri), "http") == 0);
   2722 tt_want(strcmp(evhttp_uri_get_host(uri), "") == 0);
   2723 tt_want(strcmp(evhttp_uri_get_path(uri), "/") == 0);
   2724 tt_want(evhttp_uri_get_query(uri) == NULL);
   2725 tt_want(evhttp_uri_get_userinfo(uri) == NULL);
   2726 tt_want(evhttp_uri_get_port(uri) == 8000);
   2727 tt_want(evhttp_uri_get_fragment(uri) == NULL);
   2728 TT_URI("http://:8000/");
   2729 evhttp_uri_free(uri);
   2730 
   2731 uri = URI_PARSE("http://www.test.com:/"); /* empty port */
   2732 tt_want(strcmp(evhttp_uri_get_scheme(uri), "http") == 0);
   2733 tt_want(strcmp(evhttp_uri_get_host(uri), "www.test.com") == 0);
   2734 tt_want_str_op(evhttp_uri_get_path(uri), ==, "/");
   2735 tt_want(evhttp_uri_get_query(uri) == NULL);
   2736 tt_want(evhttp_uri_get_userinfo(uri) == NULL);
   2737 tt_want(evhttp_uri_get_port(uri) == -1);
   2738 tt_want(evhttp_uri_get_fragment(uri) == NULL);
   2739 TT_URI("http://www.test.com/");
   2740 evhttp_uri_free(uri);
   2741 
   2742 uri = URI_PARSE("http://www.test.com:"); /* empty port 2 */
   2743 tt_want(strcmp(evhttp_uri_get_scheme(uri), "http") == 0);
   2744 tt_want(strcmp(evhttp_uri_get_host(uri), "www.test.com") == 0);
   2745 tt_want(strcmp(evhttp_uri_get_path(uri), "") == 0);
   2746 tt_want(evhttp_uri_get_query(uri) == NULL);
   2747 tt_want(evhttp_uri_get_userinfo(uri) == NULL);
   2748 tt_want(evhttp_uri_get_port(uri) == -1);
   2749 tt_want(evhttp_uri_get_fragment(uri) == NULL);
   2750 TT_URI("http://www.test.com");
   2751 evhttp_uri_free(uri);
   2752 
   2753 uri = URI_PARSE("ftp://www.test.com/?q=test");
   2754 tt_want(strcmp(evhttp_uri_get_scheme(uri), "ftp") == 0);
   2755 tt_want(strcmp(evhttp_uri_get_host(uri), "www.test.com") == 0);
   2756 tt_want(strcmp(evhttp_uri_get_path(uri), "/") == 0);
   2757 tt_want(strcmp(evhttp_uri_get_query(uri), "q=test") == 0);
   2758 tt_want(evhttp_uri_get_userinfo(uri) == NULL);
   2759 tt_want(evhttp_uri_get_port(uri) == -1);
   2760 tt_want(evhttp_uri_get_fragment(uri) == NULL);
   2761 TT_URI("ftp://www.test.com/?q=test");
   2762 evhttp_uri_free(uri);
   2763 
   2764 uri = URI_PARSE("ftp://[::1]:999/?q=test");
   2765 tt_want(strcmp(evhttp_uri_get_scheme(uri), "ftp") == 0);
   2766 tt_want(strcmp(evhttp_uri_get_host(uri), "[::1]") == 0);
   2767 tt_want(strcmp(evhttp_uri_get_path(uri), "/") == 0);
   2768 tt_want(strcmp(evhttp_uri_get_query(uri), "q=test") == 0);
   2769 tt_want(evhttp_uri_get_userinfo(uri) == NULL);
   2770 tt_want(evhttp_uri_get_port(uri) == 999);
   2771 tt_want(evhttp_uri_get_fragment(uri) == NULL);
   2772 TT_URI("ftp://[::1]:999/?q=test");
   2773 evhttp_uri_free(uri);
   2774 
   2775 uri = URI_PARSE("ftp://[ff00::127.0.0.1]/?q=test");
   2776 tt_want(strcmp(evhttp_uri_get_scheme(uri), "ftp") == 0);
   2777 tt_want(strcmp(evhttp_uri_get_host(uri), "[ff00::127.0.0.1]") == 0);
   2778 tt_want(strcmp(evhttp_uri_get_path(uri), "/") == 0);
   2779 tt_want(strcmp(evhttp_uri_get_query(uri), "q=test") == 0);
   2780 tt_want(evhttp_uri_get_userinfo(uri) == NULL);
   2781 tt_want(evhttp_uri_get_port(uri) == -1);
   2782 tt_want(evhttp_uri_get_fragment(uri) == NULL);
   2783 TT_URI("ftp://[ff00::127.0.0.1]/?q=test");
   2784 evhttp_uri_free(uri);
   2785 
   2786 uri = URI_PARSE("ftp://[v99.not_(any:time)_soon]/?q=test");
   2787 tt_want(strcmp(evhttp_uri_get_scheme(uri), "ftp") == 0);
   2788 tt_want(strcmp(evhttp_uri_get_host(uri), "[v99.not_(any:time)_soon]") == 0);
   2789 tt_want(strcmp(evhttp_uri_get_path(uri), "/") == 0);
   2790 tt_want(strcmp(evhttp_uri_get_query(uri), "q=test") == 0);
   2791 tt_want(evhttp_uri_get_userinfo(uri) == NULL);
   2792 tt_want(evhttp_uri_get_port(uri) == -1);
   2793 tt_want(evhttp_uri_get_fragment(uri) == NULL);
   2794 TT_URI("ftp://[v99.not_(any:time)_soon]/?q=test");
   2795 evhttp_uri_free(uri);
   2796 
   2797 uri = URI_PARSE("scheme://user:pass@foo.com:42/?q=test&s=some+thing#fragment");
   2798 tt_want(strcmp(evhttp_uri_get_scheme(uri), "scheme") == 0);
   2799 tt_want(strcmp(evhttp_uri_get_userinfo(uri), "user:pass") == 0);
   2800 tt_want(strcmp(evhttp_uri_get_host(uri), "foo.com") == 0);
   2801 tt_want(evhttp_uri_get_port(uri) == 42);
   2802 tt_want(strcmp(evhttp_uri_get_path(uri), "/") == 0);
   2803 tt_want(strcmp(evhttp_uri_get_query(uri), "q=test&s=some+thing") == 0);
   2804 tt_want(strcmp(evhttp_uri_get_fragment(uri), "fragment") == 0);
   2805 TT_URI("scheme://user:pass@foo.com:42/?q=test&s=some+thing#fragment");
   2806 evhttp_uri_free(uri);
   2807 
   2808 uri = URI_PARSE("scheme://user@foo.com/#fragment");
   2809 tt_want(strcmp(evhttp_uri_get_scheme(uri), "scheme") == 0);
   2810 tt_want(strcmp(evhttp_uri_get_userinfo(uri), "user") == 0);
   2811 tt_want(strcmp(evhttp_uri_get_host(uri), "foo.com") == 0);
   2812 tt_want(evhttp_uri_get_port(uri) == -1);
   2813 tt_want(strcmp(evhttp_uri_get_path(uri), "/") == 0);
   2814 tt_want(evhttp_uri_get_query(uri) == NULL);
   2815 tt_want(strcmp(evhttp_uri_get_fragment(uri), "fragment") == 0);
   2816 TT_URI("scheme://user@foo.com/#fragment");
   2817 evhttp_uri_free(uri);
   2818 
   2819 uri = URI_PARSE("scheme://%75ser@foo.com/#frag@ment");
   2820 tt_want(strcmp(evhttp_uri_get_scheme(uri), "scheme") == 0);
   2821 tt_want(strcmp(evhttp_uri_get_userinfo(uri), "%75ser") == 0);
   2822 tt_want(strcmp(evhttp_uri_get_host(uri), "foo.com") == 0);
   2823 tt_want(evhttp_uri_get_port(uri) == -1);
   2824 tt_want(strcmp(evhttp_uri_get_path(uri), "/") == 0);
   2825 tt_want(evhttp_uri_get_query(uri) == NULL);
   2826 tt_want(strcmp(evhttp_uri_get_fragment(uri), "frag@ment") == 0);
   2827 TT_URI("scheme://%75ser@foo.com/#frag@ment");
   2828 evhttp_uri_free(uri);
   2829 
   2830 uri = URI_PARSE("file:///some/path/to/the/file");
   2831 tt_want(strcmp(evhttp_uri_get_scheme(uri), "file") == 0);
   2832 tt_want(evhttp_uri_get_userinfo(uri) == NULL);
   2833 tt_want(strcmp(evhttp_uri_get_host(uri), "") == 0);
   2834 tt_want(evhttp_uri_get_port(uri) == -1);
   2835 tt_want(strcmp(evhttp_uri_get_path(uri), "/some/path/to/the/file") == 0);
   2836 tt_want(evhttp_uri_get_query(uri) == NULL);
   2837 tt_want(evhttp_uri_get_fragment(uri) == NULL);
   2838 TT_URI("file:///some/path/to/the/file");
   2839 evhttp_uri_free(uri);
   2840 
   2841 uri = URI_PARSE("///some/path/to/the-file");
   2842 tt_want(uri != NULL);
   2843 tt_want(evhttp_uri_get_scheme(uri) == NULL);
   2844 tt_want(evhttp_uri_get_userinfo(uri) == NULL);
   2845 tt_want(strcmp(evhttp_uri_get_host(uri), "") == 0);
   2846 tt_want(evhttp_uri_get_port(uri) == -1);
   2847 tt_want(strcmp(evhttp_uri_get_path(uri), "/some/path/to/the-file") == 0);
   2848 tt_want(evhttp_uri_get_query(uri) == NULL);
   2849 tt_want(evhttp_uri_get_fragment(uri) == NULL);
   2850 TT_URI("///some/path/to/the-file");
   2851 evhttp_uri_free(uri);
   2852 
   2853 uri = URI_PARSE("/s:ome/path/to/the-file?q=99#fred");
   2854 tt_want(uri != NULL);
   2855 tt_want(evhttp_uri_get_scheme(uri) == NULL);
   2856 tt_want(evhttp_uri_get_userinfo(uri) == NULL);
   2857 tt_want(evhttp_uri_get_host(uri) == NULL);
   2858 tt_want(evhttp_uri_get_port(uri) == -1);
   2859 tt_want(strcmp(evhttp_uri_get_path(uri), "/s:ome/path/to/the-file") == 0);
   2860 tt_want(strcmp(evhttp_uri_get_query(uri), "q=99") == 0);
   2861 tt_want(strcmp(evhttp_uri_get_fragment(uri), "fred") == 0);
   2862 TT_URI("/s:ome/path/to/the-file?q=99#fred");
   2863 evhttp_uri_free(uri);
   2864 
   2865 uri = URI_PARSE("relative/path/with/co:lon");
   2866 tt_want(uri != NULL);
   2867 tt_want(evhttp_uri_get_scheme(uri) == NULL);
   2868 tt_want(evhttp_uri_get_userinfo(uri) == NULL);
   2869 tt_want(evhttp_uri_get_host(uri) == NULL);
   2870 tt_want(evhttp_uri_get_port(uri) == -1);
   2871 tt_want(strcmp(evhttp_uri_get_path(uri), "relative/path/with/co:lon") == 0);
   2872 tt_want(evhttp_uri_get_query(uri) == NULL);
   2873 tt_want(evhttp_uri_get_fragment(uri) == NULL);
   2874 TT_URI("relative/path/with/co:lon");
   2875 evhttp_uri_free(uri);
   2876 
   2877 uri = URI_PARSE("bob?q=99&q2=q?33#fr?ed");
   2878 tt_want(uri != NULL);
   2879 tt_want(evhttp_uri_get_scheme(uri) == NULL);
   2880 tt_want(evhttp_uri_get_userinfo(uri) == NULL);
   2881 tt_want(evhttp_uri_get_host(uri) == NULL);
   2882 tt_want(evhttp_uri_get_port(uri) == -1);
   2883 tt_want(strcmp(evhttp_uri_get_path(uri), "bob") == 0);
   2884 tt_want(strcmp(evhttp_uri_get_query(uri), "q=99&q2=q?33") == 0);
   2885 tt_want(strcmp(evhttp_uri_get_fragment(uri), "fr?ed") == 0);
   2886 TT_URI("bob?q=99&q2=q?33#fr?ed");
   2887 evhttp_uri_free(uri);
   2888 
   2889 uri = URI_PARSE("#fr?ed");
   2890 tt_want(uri != NULL);
   2891 tt_want(evhttp_uri_get_scheme(uri) == NULL);
   2892 tt_want(evhttp_uri_get_userinfo(uri) == NULL);
   2893 tt_want(evhttp_uri_get_host(uri) == NULL);
   2894 tt_want(evhttp_uri_get_port(uri) == -1);
   2895 tt_want(strcmp(evhttp_uri_get_path(uri), "") == 0);
   2896 tt_want(evhttp_uri_get_query(uri) == NULL);
   2897 tt_want(strcmp(evhttp_uri_get_fragment(uri), "fr?ed") == 0);
   2898 TT_URI("#fr?ed");
   2899 evhttp_uri_free(uri);
   2900 #undef URI_PARSE
   2901 #undef TT_URI
   2902 #undef BAD
   2903 }
   2904 
   2905 static void
   2906 http_uriencode_test(void *ptr)
   2907 {
   2908 char *s=NULL, *s2=NULL;
   2909 size_t sz;
   2910 int bytes_decoded;
   2911 
   2912 #define ENC(from,want,plus) do {				\
   2913 	s = evhttp_uriencode((from), -1, (plus));	\
   2914 	tt_assert(s);					\
   2915 	tt_str_op(s,==,(want));				\
   2916 	sz = -1;					\
   2917 	s2 = evhttp_uridecode((s), (plus), &sz);	\
   2918 	tt_assert(s2);					\
   2919 	tt_str_op(s2,==,(from));			\
   2920 	tt_int_op(sz,==,strlen(from));			\
   2921 	free(s);					\
   2922 	free(s2);					\
   2923 	s = s2 = NULL;					\
   2924 } while (0)
   2925 
   2926 #define DEC(from,want,dp) do {					\
   2927 	s = evhttp_uridecode((from),(dp),&sz);		\
   2928 	tt_assert(s);					\
   2929 	tt_str_op(s,==,(want));				\
   2930 	tt_int_op(sz,==,strlen(want));			\
   2931 	free(s);					\
   2932 	s = NULL;					\
   2933 } while (0)
   2934 
   2935 #define OLD_DEC(from,want)  do {				\
   2936 	s = evhttp_decode_uri((from));			\
   2937 	tt_assert(s);					\
   2938 	tt_str_op(s,==,(want));				\
   2939 	free(s);					\
   2940 	s = NULL;					\
   2941 } while (0)
   2942 
   2943 
   2944      	ENC("Hello", "Hello",0);
   2945 ENC("99", "99",0);
   2946 ENC("", "",0);
   2947 ENC(
   2948  "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ123456789-.~_",
   2949  "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ123456789-.~_",0);
   2950 ENC(" ", "%20",0);
   2951 ENC(" ", "+",1);
   2952 ENC("\xff\xf0\xe0", "%FF%F0%E0",0);
   2953 ENC("\x01\x19", "%01%19",1);
   2954 ENC("http://www.ietf.org/rfc/rfc3986.txt",
   2955     "http%3A%2F%2Fwww.ietf.org%2Frfc%2Frfc3986.txt",1);
   2956 
   2957 ENC("1+2=3", "1%2B2%3D3",1);
   2958 ENC("1+2=3", "1%2B2%3D3",0);
   2959 
   2960 /* Now try encoding with internal NULs. */
   2961 s = evhttp_uriencode("hello\0world", 11, 0);
   2962 tt_assert(s);
   2963 tt_str_op(s,==,"hello%00world");
   2964 free(s);
   2965 s = NULL;
   2966 
   2967 /* Now try decoding just part of string. */
   2968 s = malloc(6 + 1 /* NUL byte */);
   2969 bytes_decoded = evhttp_decode_uri_internal("hello%20%20", 6, s, 0);
   2970 tt_assert(s);
   2971 tt_int_op(bytes_decoded,==,6);
   2972 tt_str_op(s,==,"hello%");
   2973 free(s);
   2974 s = NULL;
   2975 
   2976 /* Now try out some decoding cases that we don't generate with
   2977  * encode_uri: Make sure that malformed stuff doesn't crash... */
   2978 DEC("%%xhello th+ere \xff",
   2979     "%%xhello th+ere \xff", 0);
   2980 /* Make sure plus decoding works */
   2981 DEC("plus+should%20work+", "plus should work ",1);
   2982 /* Try some lowercase hex */
   2983 DEC("%f0%a0%b0", "\xf0\xa0\xb0",1);
   2984 
   2985 /* Try an internal NUL. */
   2986 sz = 0;
   2987 s = evhttp_uridecode("%00%00x%00%00", 1, &sz);
   2988 tt_int_op(sz,==,5);
   2989 tt_assert(!memcmp(s, "\0\0x\0\0", 5));
   2990 free(s);
   2991 s = NULL;
   2992 
   2993 /* Try with size == NULL */
   2994 sz = 0;
   2995 s = evhttp_uridecode("%00%00x%00%00", 1, NULL);
   2996 tt_assert(!memcmp(s, "\0\0x\0\0", 5));
   2997 free(s);
   2998 s = NULL;
   2999 
   3000 /* Test out the crazy old behavior of the deprecated
   3001  * evhttp_decode_uri */
   3002 OLD_DEC("http://example.com/normal+path/?key=val+with+spaces",
   3003         "http://example.com/normal+path/?key=val with spaces");
   3004 
   3005 end:
   3006 if (s)
   3007 	free(s);
   3008 if (s2)
   3009 	free(s2);
   3010 #undef ENC
   3011 #undef DEC
   3012 #undef OLD_DEC
   3013 }
   3014 
   3015 static void
   3016 http_base_test(void *ptr)
   3017 {
   3018 struct event_base *base = NULL;
   3019 struct bufferevent *bev;
   3020 evutil_socket_t fd;
   3021 const char *http_request;
   3022 ev_uint16_t port = 0;
   3023 struct evhttp *http;
   3024 
   3025 test_ok = 0;
   3026 base = event_base_new();
   3027 tt_assert(base);
   3028 http = http_setup(&port, base, 0);
   3029 
   3030 fd = http_connect("127.0.0.1", port);
   3031 tt_assert(fd != EVUTIL_INVALID_SOCKET);
   3032 
   3033 /* Stupid thing to send a request */
   3034 bev = bufferevent_socket_new(base, fd, 0);
   3035 bufferevent_setcb(bev, http_readcb, http_writecb,
   3036     http_errorcb, base);
   3037 bufferevent_base_set(base, bev);
   3038 
   3039 http_request =
   3040     "GET /test HTTP/1.1\r\n"
   3041     "Host: somehost\r\n"
   3042     "Connection: close\r\n"
   3043     "\r\n";
   3044 
   3045 bufferevent_write(bev, http_request, strlen(http_request));
   3046 
   3047 event_base_dispatch(base);
   3048 
   3049 bufferevent_free(bev);
   3050 evutil_closesocket(fd);
   3051 
   3052 evhttp_free(http);
   3053 
   3054 tt_int_op(test_ok, ==, 2);
   3055 
   3056 end:
   3057 if (base)
   3058 	event_base_free(base);
   3059 }
   3060 
   3061 /*
   3062 * the server is just going to close the connection if it times out during
   3063 * reading the headers.
   3064 */
   3065 
   3066 static void
   3067 http_incomplete_readcb(struct bufferevent *bev, void *arg)
   3068 {
   3069 test_ok = -1;
   3070 event_base_loopexit(exit_base,NULL);
   3071 }
   3072 
   3073 static void
   3074 http_incomplete_errorcb(struct bufferevent *bev, short what, void *arg)
   3075 {
   3076 /** For ssl */
   3077 if (what & BEV_EVENT_CONNECTED)
   3078 	return;
   3079 
   3080 if (what == (BEV_EVENT_READING|BEV_EVENT_EOF))
   3081 	test_ok++;
   3082 else
   3083 	test_ok = -2;
   3084 event_base_loopexit(exit_base,NULL);
   3085 }
   3086 
   3087 static void
   3088 http_incomplete_writecb(struct bufferevent *bev, void *arg)
   3089 {
   3090 if (arg != NULL) {
   3091 	evutil_socket_t fd = *(evutil_socket_t *)arg;
   3092 	/* terminate the write side to simulate EOF */
   3093 	shutdown(fd, EVUTIL_SHUT_WR);
   3094 }
   3095 if (evbuffer_get_length(bufferevent_get_output(bev)) == 0) {
   3096 	/* enable reading of the reply */
   3097 	bufferevent_enable(bev, EV_READ);
   3098 	test_ok++;
   3099 }
   3100 }
   3101 
   3102 static void
   3103 http_incomplete_test_(struct basic_test_data *data, int use_timeout, int ssl)
   3104 {
   3105 struct bufferevent *bev;
   3106 evutil_socket_t fd;
   3107 const char *http_request;
   3108 ev_uint16_t port = 0;
   3109 struct timeval tv_start, tv_end;
   3110 struct evhttp *http = http_setup(&port, data->base, ssl ? HTTP_BIND_SSL : 0);
   3111 
   3112 exit_base = data->base;
   3113 test_ok = 0;
   3114 
   3115 evhttp_set_timeout(http, 1);
   3116 
   3117 fd = http_connect("127.0.0.1", port);
   3118 tt_assert(fd != EVUTIL_INVALID_SOCKET);
   3119 
   3120 /* Stupid thing to send a request */
   3121 bev = create_bev(data->base, fd, ssl, 0);
   3122 bufferevent_setcb(bev,
   3123     http_incomplete_readcb, http_incomplete_writecb,
   3124     http_incomplete_errorcb, use_timeout ? NULL : &fd);
   3125 
   3126 http_request =
   3127     "GET /test HTTP/1.1\r\n"
   3128     "Host: somehost\r\n";
   3129 
   3130 bufferevent_write(bev, http_request, strlen(http_request));
   3131 
   3132 evutil_gettimeofday(&tv_start, NULL);
   3133 
   3134 event_base_dispatch(data->base);
   3135 
   3136 evutil_gettimeofday(&tv_end, NULL);
   3137 evutil_timersub(&tv_end, &tv_start, &tv_end);
   3138 
   3139 bufferevent_free(bev);
   3140 if (use_timeout) {
   3141 	evutil_closesocket(fd);
   3142 	fd = EVUTIL_INVALID_SOCKET;
   3143 }
   3144 
   3145 evhttp_free(http);
   3146 
   3147 if (use_timeout && tv_end.tv_sec >= 3) {
   3148 	tt_abort_msg("time");
   3149 } else if (!use_timeout && tv_end.tv_sec >= 1) {
   3150 	/* we should be done immediately */
   3151 	tt_abort_msg("time");
   3152 }
   3153 
   3154 tt_int_op(test_ok, ==, 2);
   3155 end:
   3156 if (fd >= 0)
   3157 	evutil_closesocket(fd);
   3158 }
   3159 static void http_incomplete_test(void *arg)
   3160 { http_incomplete_test_(arg, 0, 0); }
   3161 static void http_incomplete_timeout_test(void *arg)
   3162 { http_incomplete_test_(arg, 1, 0); }
   3163 
   3164 
   3165 /*
   3166 * the server is going to reply with chunked data.
   3167 */
   3168 
   3169 static void
   3170 http_chunked_readcb(struct bufferevent *bev, void *arg)
   3171 {
   3172 /* nothing here */
   3173 }
   3174 
   3175 static void
   3176 http_chunked_errorcb(struct bufferevent *bev, short what, void *arg)
   3177 {
   3178 struct evhttp_request *req = NULL;
   3179 
   3180 /** SSL */
   3181 if (what & BEV_EVENT_CONNECTED)
   3182 	return;
   3183 
   3184 if (!test_ok)
   3185 	goto out;
   3186 
   3187 test_ok = -1;
   3188 
   3189 if ((what & BEV_EVENT_EOF) != 0) {
   3190 	const char *header;
   3191 	enum message_read_status done;
   3192 	req = evhttp_request_new(NULL, NULL);
   3193 
   3194 	/* req->kind = EVHTTP_RESPONSE; */
   3195 	done = evhttp_parse_firstline_(req, bufferevent_get_input(bev));
   3196 	if (done != ALL_DATA_READ)
   3197 		goto out;
   3198 
   3199 	done = evhttp_parse_headers_(req, bufferevent_get_input(bev));
   3200 	if (done != ALL_DATA_READ)
   3201 		goto out;
   3202 
   3203 	header = evhttp_find_header(evhttp_request_get_input_headers(req), "Transfer-Encoding");
   3204 	if (header == NULL || strcmp(header, "chunked"))
   3205 		goto out;
   3206 
   3207 	header = evhttp_find_header(evhttp_request_get_input_headers(req), "Connection");
   3208 	if (header == NULL || strcmp(header, "close"))
   3209 		goto out;
   3210 
   3211 	header = evbuffer_readln(bufferevent_get_input(bev), NULL, EVBUFFER_EOL_CRLF);
   3212 	if (header == NULL)
   3213 		goto out;
   3214 	/* 13 chars */
   3215 	if (strcmp(header, "d")) {
   3216 		free((void*)header);
   3217 		goto out;
   3218 	}
   3219 	free((void*)header);
   3220 
   3221 	if (strncmp((char *)evbuffer_pullup(bufferevent_get_input(bev), 13),
   3222 		"This is funny", 13))
   3223 		goto out;
   3224 
   3225 	evbuffer_drain(bufferevent_get_input(bev), 13 + 2);
   3226 
   3227 	header = evbuffer_readln(bufferevent_get_input(bev), NULL, EVBUFFER_EOL_CRLF);
   3228 	if (header == NULL)
   3229 		goto out;
   3230 	/* 18 chars */
   3231 	if (strcmp(header, "12"))
   3232 		goto out;
   3233 	free((char *)header);
   3234 
   3235 	if (strncmp((char *)evbuffer_pullup(bufferevent_get_input(bev), 18),
   3236 		"but not hilarious.", 18))
   3237 		goto out;
   3238 
   3239 	evbuffer_drain(bufferevent_get_input(bev), 18 + 2);
   3240 
   3241 	header = evbuffer_readln(bufferevent_get_input(bev), NULL, EVBUFFER_EOL_CRLF);
   3242 	if (header == NULL)
   3243 		goto out;
   3244 	/* 8 chars */
   3245 	if (strcmp(header, "8")) {
   3246 		free((void*)header);
   3247 		goto out;
   3248 	}
   3249 	free((char *)header);
   3250 
   3251 	if (strncmp((char *)evbuffer_pullup(bufferevent_get_input(bev), 8),
   3252 		"bwv 1052.", 8))
   3253 		goto out;
   3254 
   3255 	evbuffer_drain(bufferevent_get_input(bev), 8 + 2);
   3256 
   3257 	header = evbuffer_readln(bufferevent_get_input(bev), NULL, EVBUFFER_EOL_CRLF);
   3258 	if (header == NULL)
   3259 		goto out;
   3260 	/* 0 chars */
   3261 	if (strcmp(header, "0")) {
   3262 		free((void*)header);
   3263 		goto out;
   3264 	}
   3265 	free((void *)header);
   3266 
   3267 	test_ok = 2;
   3268 }
   3269 
   3270 out:
   3271 if (req)
   3272 	evhttp_request_free(req);
   3273 
   3274 event_base_loopexit(arg, NULL);
   3275 }
   3276 
   3277 static void
   3278 http_chunked_writecb(struct bufferevent *bev, void *arg)
   3279 {
   3280 if (evbuffer_get_length(bufferevent_get_output(bev)) == 0) {
   3281 	/* enable reading of the reply */
   3282 	bufferevent_enable(bev, EV_READ);
   3283 	test_ok++;
   3284 }
   3285 }
   3286 
   3287 static void
   3288 http_chunked_request_done(struct evhttp_request *req, void *arg)
   3289 {
   3290 if (evhttp_request_get_response_code(req) != HTTP_OK) {
   3291 	fprintf(stderr, "FAILED\n");
   3292 	exit(1);
   3293 }
   3294 
   3295 if (evhttp_find_header(evhttp_request_get_input_headers(req),
   3296 	"Transfer-Encoding") == NULL) {
   3297 	fprintf(stderr, "FAILED\n");
   3298 	exit(1);
   3299 }
   3300 
   3301 if (evbuffer_get_length(evhttp_request_get_input_buffer(req)) != 13 + 18 + 8) {
   3302 	fprintf(stderr, "FAILED\n");
   3303 	exit(1);
   3304 }
   3305 
   3306 if (strncmp((char *)evbuffer_pullup(evhttp_request_get_input_buffer(req), 13 + 18 + 8),
   3307 	"This is funnybut not hilarious.bwv 1052",
   3308 	13 + 18 + 8)) {
   3309 	fprintf(stderr, "FAILED\n");
   3310 	exit(1);
   3311 }
   3312 
   3313 test_ok = 1;
   3314 event_base_loopexit(arg, NULL);
   3315 }
   3316 
   3317 static void
   3318 http_chunk_out_test_impl(void *arg, int ssl)
   3319 {
   3320 struct basic_test_data *data = arg;
   3321 struct bufferevent *bev = NULL;
   3322 evutil_socket_t fd;
   3323 const char *http_request;
   3324 ev_uint16_t port = 0;
   3325 struct timeval tv_start, tv_end;
   3326 struct evhttp_connection *evcon = NULL;
   3327 struct evhttp_request *req = NULL;
   3328 int i;
   3329 struct evhttp *http = http_setup(&port, data->base, ssl ? HTTP_BIND_SSL : 0);
   3330 
   3331 exit_base = data->base;
   3332 test_ok = 0;
   3333 
   3334 fd = http_connect("127.0.0.1", port);
   3335 tt_assert(fd != EVUTIL_INVALID_SOCKET);
   3336 
   3337 /* Stupid thing to send a request */
   3338 bev = create_bev(data->base, fd, ssl, BEV_OPT_CLOSE_ON_FREE);
   3339 bufferevent_setcb(bev,
   3340     http_chunked_readcb, http_chunked_writecb,
   3341     http_chunked_errorcb, data->base);
   3342 
   3343 http_request =
   3344     "GET /chunked HTTP/1.1\r\n"
   3345     "Host: somehost\r\n"
   3346     "Connection: close\r\n"
   3347     "\r\n";
   3348 
   3349 bufferevent_write(bev, http_request, strlen(http_request));
   3350 
   3351 evutil_gettimeofday(&tv_start, NULL);
   3352 
   3353 event_base_dispatch(data->base);
   3354 
   3355 bufferevent_free(bev);
   3356 bev = NULL;
   3357 
   3358 evutil_gettimeofday(&tv_end, NULL);
   3359 evutil_timersub(&tv_end, &tv_start, &tv_end);
   3360 
   3361 tt_int_op(tv_end.tv_sec, <, 1);
   3362 
   3363 tt_int_op(test_ok, ==, 2);
   3364 
   3365 /* now try again with the regular connection object */
   3366 bev = create_bev(data->base, -1, ssl, BEV_OPT_CLOSE_ON_FREE);
   3367 evcon = evhttp_connection_base_bufferevent_new(
   3368 	data->base, NULL, bev, "127.0.0.1", port);
   3369 tt_assert(evcon);
   3370 
   3371 /* make two requests to check the keepalive behavior */
   3372 for (i = 0; i < 2; i++) {
   3373 	test_ok = 0;
   3374 	req = evhttp_request_new(http_chunked_request_done, data->base);
   3375 
   3376 	/* Add the information that we care about */
   3377 	evhttp_add_header(evhttp_request_get_output_headers(req), "Host", "somehost");
   3378 
   3379 	/* We give ownership of the request to the connection */
   3380 	if (evhttp_make_request(evcon, req, EVHTTP_REQ_GET, "/chunked") == -1) {
   3381 		tt_abort_msg("Couldn't make request");
   3382 	}
   3383 
   3384 	event_base_dispatch(data->base);
   3385 
   3386 	tt_assert(test_ok == 1);
   3387 }
   3388 
   3389 end:
   3390 if (evcon)
   3391 	evhttp_connection_free(evcon);
   3392 if (http)
   3393 	evhttp_free(http);
   3394 }
   3395 static void http_chunk_out_test(void *arg)
   3396 { http_chunk_out_test_impl(arg, 0); }
   3397 
   3398 static void
   3399 http_stream_out_test_impl(void *arg, int ssl)
   3400 {
   3401 struct basic_test_data *data = arg;
   3402 ev_uint16_t port = 0;
   3403 struct evhttp_connection *evcon = NULL;
   3404 struct evhttp_request *req = NULL;
   3405 struct bufferevent *bev;
   3406 struct evhttp *http = http_setup(&port, data->base, ssl ? HTTP_BIND_SSL : 0);
   3407 
   3408 test_ok = 0;
   3409 exit_base = data->base;
   3410 
   3411 bev = create_bev(data->base, -1, ssl, 0);
   3412 evcon = evhttp_connection_base_bufferevent_new(
   3413 	data->base, NULL, bev, "127.0.0.1", port);
   3414 tt_assert(evcon);
   3415 
   3416 /*
   3417  * At this point, we want to schedule a request to the HTTP
   3418  * server using our make request method.
   3419  */
   3420 
   3421 req = evhttp_request_new(http_request_done,
   3422     (void *)"This is funnybut not hilarious.bwv 1052");
   3423 
   3424 /* Add the information that we care about */
   3425 evhttp_add_header(evhttp_request_get_output_headers(req), "Host", "somehost");
   3426 
   3427 /* We give ownership of the request to the connection */
   3428 if (evhttp_make_request(evcon, req, EVHTTP_REQ_GET, "/streamed")
   3429     == -1) {
   3430 	tt_abort_msg("Couldn't make request");
   3431 }
   3432 
   3433 event_base_dispatch(data->base);
   3434 
   3435 end:
   3436 if (evcon)
   3437 	evhttp_connection_free(evcon);
   3438 if (http)
   3439 	evhttp_free(http);
   3440 }
   3441 static void http_stream_out_test(void *arg)
   3442 { http_stream_out_test_impl(arg, 0); }
   3443 
   3444 static void
   3445 http_stream_in_chunk(struct evhttp_request *req, void *arg)
   3446 {
   3447 struct evbuffer *reply = arg;
   3448 
   3449 if (evhttp_request_get_response_code(req) != HTTP_OK) {
   3450 	fprintf(stderr, "FAILED\n");
   3451 	exit(1);
   3452 }
   3453 
   3454 evbuffer_add_buffer(reply, evhttp_request_get_input_buffer(req));
   3455 }
   3456 
   3457 static void
   3458 http_stream_in_done(struct evhttp_request *req, void *arg)
   3459 {
   3460 if (evbuffer_get_length(evhttp_request_get_input_buffer(req)) != 0) {
   3461 	fprintf(stderr, "FAILED\n");
   3462 	exit(1);
   3463 }
   3464 
   3465 event_base_loopexit(exit_base, NULL);
   3466 }
   3467 
   3468 /**
   3469 * Makes a request and reads the response in chunks.
   3470 */
   3471 static void
   3472 http_stream_in_test_(struct basic_test_data *data, char const *url,
   3473    size_t expected_len, char const *expected)
   3474 {
   3475 struct evhttp_connection *evcon;
   3476 struct evbuffer *reply = evbuffer_new();
   3477 struct evhttp_request *req = NULL;
   3478 ev_uint16_t port = 0;
   3479 struct evhttp *http = http_setup(&port, data->base, 0);
   3480 
   3481 exit_base = data->base;
   3482 
   3483 evcon = evhttp_connection_base_new(data->base, NULL,"127.0.0.1", port);
   3484 tt_assert(evcon);
   3485 
   3486 req = evhttp_request_new(http_stream_in_done, reply);
   3487 evhttp_request_set_chunked_cb(req, http_stream_in_chunk);
   3488 
   3489 /* We give ownership of the request to the connection */
   3490 if (evhttp_make_request(evcon, req, EVHTTP_REQ_GET, url) == -1) {
   3491 	tt_abort_msg("Couldn't make request");
   3492 }
   3493 
   3494 event_base_dispatch(data->base);
   3495 
   3496 if (evbuffer_get_length(reply) != expected_len) {
   3497 	TT_DIE(("reply length %lu; expected %lu; FAILED (%s)\n",
   3498 			(unsigned long)evbuffer_get_length(reply),
   3499 			(unsigned long)expected_len,
   3500 			(char*)evbuffer_pullup(reply, -1)));
   3501 }
   3502 
   3503 if (memcmp(evbuffer_pullup(reply, -1), expected, expected_len) != 0) {
   3504 	tt_abort_msg("Memory mismatch");
   3505 }
   3506 
   3507 test_ok = 1;
   3508 end:
   3509 if (reply)
   3510 	evbuffer_free(reply);
   3511 if (evcon)
   3512 	evhttp_connection_free(evcon);
   3513 if (http)
   3514 	evhttp_free(http);
   3515 }
   3516 
   3517 static void
   3518 http_stream_in_test(void *arg)
   3519 {
   3520 http_stream_in_test_(arg, "/chunked", 13 + 18 + 8,
   3521     "This is funnybut not hilarious.bwv 1052");
   3522 
   3523 http_stream_in_test_(arg, "/test", strlen(BASIC_REQUEST_BODY),
   3524     BASIC_REQUEST_BODY);
   3525 }
   3526 
   3527 static void
   3528 http_stream_in_cancel_chunk(struct evhttp_request *req, void *arg)
   3529 {
   3530 tt_int_op(evhttp_request_get_response_code(req), ==, HTTP_OK);
   3531 
   3532 end:
   3533 evhttp_cancel_request(req);
   3534 event_base_loopexit(arg, NULL);
   3535 }
   3536 
   3537 static void
   3538 http_stream_in_cancel_done(struct evhttp_request *req, void *arg)
   3539 {
   3540 /* should never be called */
   3541 tt_fail_msg("In cancel done");
   3542 }
   3543 
   3544 static void
   3545 http_stream_in_cancel_test(void *arg)
   3546 {
   3547 struct basic_test_data *data = arg;
   3548 struct evhttp_connection *evcon;
   3549 struct evhttp_request *req = NULL;
   3550 ev_uint16_t port = 0;
   3551 struct evhttp *http = http_setup(&port, data->base, 0);
   3552 
   3553 evcon = evhttp_connection_base_new(data->base, NULL, "127.0.0.1", port);
   3554 tt_assert(evcon);
   3555 
   3556 req = evhttp_request_new(http_stream_in_cancel_done, data->base);
   3557 evhttp_request_set_chunked_cb(req, http_stream_in_cancel_chunk);
   3558 
   3559 /* We give ownership of the request to the connection */
   3560 if (evhttp_make_request(evcon, req, EVHTTP_REQ_GET, "/chunked") == -1) {
   3561 	tt_abort_msg("Couldn't make request");
   3562 }
   3563 
   3564 event_base_dispatch(data->base);
   3565 
   3566 test_ok = 1;
   3567 end:
   3568 evhttp_connection_free(evcon);
   3569 evhttp_free(http);
   3570 
   3571 }
   3572 
   3573 static void
   3574 http_connection_fail_done(struct evhttp_request *req, void *arg)
   3575 {
   3576 struct evhttp_connection *evcon = arg;
   3577 struct event_base *base = evhttp_connection_get_base(evcon);
   3578 
   3579 /* An ENETUNREACH error results in an unrecoverable
   3580  * evhttp_connection error (see evhttp_connection_fail_()).  The
   3581  * connection will be reset, and the user will be notified with a NULL
   3582  * req parameter. */
   3583 tt_assert(!req);
   3584 
   3585 evhttp_connection_free(evcon);
   3586 
   3587 test_ok = 1;
   3588 
   3589 end:
   3590 event_base_loopexit(base, NULL);
   3591 }
   3592 
   3593 /* Test unrecoverable evhttp_connection errors by generating an ENETUNREACH
   3594 * error on connection. */
   3595 static void
   3596 http_connection_fail_test_impl(void *arg, int ssl)
   3597 {
   3598 struct basic_test_data *data = arg;
   3599 ev_uint16_t port = 0;
   3600 struct evhttp_connection *evcon = NULL;
   3601 struct evhttp_request *req = NULL;
   3602 struct bufferevent *bev;
   3603 struct evhttp *http = http_setup(&port, data->base, ssl ? HTTP_BIND_SSL : 0);
   3604 
   3605 exit_base = data->base;
   3606 test_ok = 0;
   3607 
   3608 /* auto detect a port */
   3609 evhttp_free(http);
   3610 
   3611 bev = create_bev(data->base, -1, ssl, 0);
   3612 /* Pick an unroutable address. This administratively scoped multicast
   3613  * address should do when working with TCP. */
   3614 evcon = evhttp_connection_base_bufferevent_new(
   3615 	data->base, NULL, bev, "239.10.20.30", 80);
   3616 tt_assert(evcon);
   3617 
   3618 /*
   3619  * At this point, we want to schedule an HTTP GET request
   3620  * server using our make request method.
   3621  */
   3622 
   3623 req = evhttp_request_new(http_connection_fail_done, evcon);
   3624 tt_assert(req);
   3625 
   3626 if (evhttp_make_request(evcon, req, EVHTTP_REQ_GET, "/") == -1) {
   3627 	tt_abort_msg("Couldn't make request");
   3628 }
   3629 
   3630 event_base_dispatch(data->base);
   3631 
   3632 tt_int_op(test_ok, ==, 1);
   3633 
   3634 end:
   3635 ;
   3636 }
   3637 static void http_connection_fail_test(void *arg)
   3638 { http_connection_fail_test_impl(arg, 0); }
   3639 
   3640 static void
   3641 http_connection_retry_done(struct evhttp_request *req, void *arg)
   3642 {
   3643 tt_assert(req);
   3644 tt_int_op(evhttp_request_get_response_code(req), !=, HTTP_OK);
   3645 if (evhttp_find_header(evhttp_request_get_input_headers(req), "Content-Type") != NULL) {
   3646 	tt_abort_msg("(content type)\n");
   3647 }
   3648 
   3649 tt_uint_op(evbuffer_get_length(evhttp_request_get_input_buffer(req)), ==, 0);
   3650 
   3651 test_ok = 1;
   3652 end:
   3653 event_base_loopexit(arg,NULL);
   3654 }
   3655 
   3656 struct http_server
   3657 {
   3658 ev_uint16_t port;
   3659 int ssl;
   3660 struct evhttp *http;
   3661 };
   3662 static struct event_base *http_make_web_server_base=NULL;
   3663 static void
   3664 http_make_web_server(evutil_socket_t fd, short what, void *arg)
   3665 {
   3666 struct http_server *hs = (struct http_server *)arg;
   3667 hs->http = http_setup(&hs->port, http_make_web_server_base, hs->ssl ? HTTP_BIND_SSL : 0);
   3668 }
   3669 
   3670 static void
   3671 http_simple_test_impl(void *arg, int ssl, int dirty, const char *uri)
   3672 {
   3673 struct basic_test_data *data = arg;
   3674 struct evhttp_connection *evcon = NULL;
   3675 struct evhttp_request *req = NULL;
   3676 struct bufferevent *bev;
   3677 struct http_server hs = { 0, ssl, NULL, };
   3678 struct evhttp *http = http_setup(&hs.port, data->base, ssl ? HTTP_BIND_SSL : 0);
   3679 
   3680 exit_base = data->base;
   3681 test_ok = 0;
   3682 
   3683 bev = create_bev(data->base, -1, ssl, 0);
   3684 #ifdef EVENT__HAVE_OPENSSL
   3685 bufferevent_openssl_set_allow_dirty_shutdown(bev, dirty);
   3686 #endif
   3687 
   3688 evcon = evhttp_connection_base_bufferevent_new(
   3689 	data->base, NULL, bev, "127.0.0.1", hs.port);
   3690 tt_assert(evcon);
   3691 evhttp_connection_set_local_address(evcon, "127.0.0.1");
   3692 
   3693 req = evhttp_request_new(http_request_done, (void*) BASIC_REQUEST_BODY);
   3694 tt_assert(req);
   3695 
   3696 if (evhttp_make_request(evcon, req, EVHTTP_REQ_GET, uri) == -1)
   3697 	tt_abort_msg("Couldn't make request");
   3698 
   3699 event_base_dispatch(data->base);
   3700 tt_int_op(test_ok, ==, 1);
   3701 
   3702 end:
   3703 if (evcon)
   3704 	evhttp_connection_free(evcon);
   3705 if (http)
   3706 	evhttp_free(http);
   3707 }
   3708 static void http_simple_test(void *arg)
   3709 { http_simple_test_impl(arg, 0, 0, "/test"); }
   3710 static void http_simple_nonconformant_test(void *arg)
   3711 { http_simple_test_impl(arg, 0, 0, "/test nonconformant"); }
   3712 
   3713 static void
   3714 http_connection_retry_test_basic(void *arg, const char *addr, struct evdns_base *dns_base, int ssl)
   3715 {
   3716 struct basic_test_data *data = arg;
   3717 struct evhttp_connection *evcon = NULL;
   3718 struct evhttp_request *req = NULL;
   3719 struct timeval tv, tv_start, tv_end;
   3720 struct bufferevent *bev;
   3721 struct http_server hs = { 0, ssl, NULL, };
   3722 struct evhttp *http = http_setup(&hs.port, data->base, ssl ? HTTP_BIND_SSL : 0);
   3723 
   3724 exit_base = data->base;
   3725 test_ok = 0;
   3726 
   3727 /* auto detect a port */
   3728 evhttp_free(http);
   3729 
   3730 bev = create_bev(data->base, -1, ssl, 0);
   3731 evcon = evhttp_connection_base_bufferevent_new(data->base, dns_base, bev, addr, hs.port);
   3732 tt_assert(evcon);
   3733 if (dns_base)
   3734 	tt_assert(!evhttp_connection_set_flags(evcon, EVHTTP_CON_REUSE_CONNECTED_ADDR));
   3735 
   3736 evhttp_connection_set_timeout(evcon, 1);
   3737 /* also bind to local host */
   3738 evhttp_connection_set_local_address(evcon, "127.0.0.1");
   3739 
   3740 /*
   3741  * At this point, we want to schedule an HTTP GET request
   3742  * server using our make request method.
   3743  */
   3744 
   3745 req = evhttp_request_new(http_connection_retry_done, data->base);
   3746 tt_assert(req);
   3747 
   3748 /* Add the information that we care about */
   3749 evhttp_add_header(evhttp_request_get_output_headers(req), "Host", "somehost");
   3750 
   3751 if (evhttp_make_request(evcon, req, EVHTTP_REQ_GET,
   3752 	"/?arg=val") == -1) {
   3753 	tt_abort_msg("Couldn't make request");
   3754 }
   3755 
   3756 evutil_gettimeofday(&tv_start, NULL);
   3757 event_base_dispatch(data->base);
   3758 evutil_gettimeofday(&tv_end, NULL);
   3759 evutil_timersub(&tv_end, &tv_start, &tv_end);
   3760 tt_int_op(tv_end.tv_sec, <, 1);
   3761 
   3762 tt_int_op(test_ok, ==, 1);
   3763 
   3764 /*
   3765  * now test the same but with retries
   3766  */
   3767 test_ok = 0;
   3768 /** Shutdown dns server, to test conn_address reusing */
   3769 if (dns_base)
   3770 	regress_clean_dnsserver();
   3771 
   3772 {
   3773 	const struct timeval tv_timeout = { 0, 500000 };
   3774 	const struct timeval tv_retry = { 0, 500000 };
   3775 	evhttp_connection_set_timeout_tv(evcon, &tv_timeout);
   3776 	evhttp_connection_set_initial_retry_tv(evcon, &tv_retry);
   3777 }
   3778 evhttp_connection_set_retries(evcon, 1);
   3779 
   3780 req = evhttp_request_new(http_connection_retry_done, data->base);
   3781 tt_assert(req);
   3782 
   3783 /* Add the information that we care about */
   3784 evhttp_add_header(evhttp_request_get_output_headers(req), "Host", "somehost");
   3785 
   3786 if (evhttp_make_request(evcon, req, EVHTTP_REQ_GET,
   3787 	"/?arg=val") == -1) {
   3788 	tt_abort_msg("Couldn't make request");
   3789 }
   3790 
   3791 evutil_gettimeofday(&tv_start, NULL);
   3792 event_base_dispatch(data->base);
   3793 evutil_gettimeofday(&tv_end, NULL);
   3794 
   3795 /* fails fast, .5 sec to wait to retry, fails fast again. */
   3796 test_timeval_diff_leq(&tv_start, &tv_end, 500, 200);
   3797 
   3798 tt_assert(test_ok == 1);
   3799 
   3800 /*
   3801  * now test the same but with retries and give it a web server
   3802  * at the end
   3803  */
   3804 test_ok = 0;
   3805 
   3806 evhttp_connection_set_timeout(evcon, 1);
   3807 evhttp_connection_set_retries(evcon, 3);
   3808 
   3809 req = evhttp_request_new(http_dispatcher_test_done, data->base);
   3810 tt_assert(req);
   3811 
   3812 /* Add the information that we care about */
   3813 evhttp_add_header(evhttp_request_get_output_headers(req), "Host", "somehost");
   3814 
   3815 if (evhttp_make_request(evcon, req, EVHTTP_REQ_GET,
   3816 	"/?arg=val") == -1) {
   3817 	tt_abort_msg("Couldn't make request");
   3818 }
   3819 
   3820 /* start up a web server .2 seconds after the connection tried
   3821  * to send a request
   3822  */
   3823 evutil_timerclear(&tv);
   3824 tv.tv_usec = 200000;
   3825 http_make_web_server_base = data->base;
   3826 event_base_once(data->base, -1, EV_TIMEOUT, http_make_web_server, &hs, &tv);
   3827 
   3828 evutil_gettimeofday(&tv_start, NULL);
   3829 event_base_dispatch(data->base);
   3830 evutil_gettimeofday(&tv_end, NULL);
   3831 /* We'll wait twice as long as we did last time. */
   3832 test_timeval_diff_leq(&tv_start, &tv_end, 1000, 400);
   3833 
   3834 tt_int_op(test_ok, ==, 1);
   3835 
   3836 end:
   3837 if (evcon)
   3838 	evhttp_connection_free(evcon);
   3839 if (http)
   3840 	evhttp_free(hs.http);
   3841 }
   3842 
   3843 static void
   3844 http_connection_retry_conn_address_test_impl(void *arg, int ssl)
   3845 {
   3846 struct basic_test_data *data = arg;
   3847 ev_uint16_t portnum = 0;
   3848 struct evdns_base *dns_base = NULL;
   3849 char address[64];
   3850 
   3851 tt_assert(regress_dnsserver(data->base, &portnum, search_table));
   3852 dns_base = evdns_base_new(data->base, 0/* init name servers */);
   3853 tt_assert(dns_base);
   3854 
   3855 /* Add ourself as the only nameserver, and make sure we really are
   3856  * the only nameserver. */
   3857 evutil_snprintf(address, sizeof(address), "127.0.0.1:%d", portnum);
   3858 evdns_base_nameserver_ip_add(dns_base, address);
   3859 
   3860 http_connection_retry_test_basic(arg, "localhost", dns_base, ssl);
   3861 
   3862 end:
   3863 if (dns_base)
   3864 	evdns_base_free(dns_base, 0);
   3865 /** dnsserver will be cleaned in http_connection_retry_test_basic() */
   3866 }
   3867 static void http_connection_retry_conn_address_test(void *arg)
   3868 { http_connection_retry_conn_address_test_impl(arg, 0); }
   3869 
   3870 static void
   3871 http_connection_retry_test_impl(void *arg, int ssl)
   3872 {
   3873 http_connection_retry_test_basic(arg, "127.0.0.1", NULL, ssl);
   3874 }
   3875 static void
   3876 http_connection_retry_test(void *arg)
   3877 { http_connection_retry_test_impl(arg, 0); }
   3878 
   3879 static void
   3880 http_primitives(void *ptr)
   3881 {
   3882 char *escaped = NULL;
   3883 struct evhttp *http = NULL;
   3884 
   3885 escaped = evhttp_htmlescape("<script>");
   3886 tt_assert(escaped);
   3887 tt_str_op(escaped, ==, "&lt;script&gt;");
   3888 free(escaped);
   3889 
   3890 escaped = evhttp_htmlescape("\"\'&");
   3891 tt_assert(escaped);
   3892 tt_str_op(escaped, ==, "&quot;&#039;&amp;");
   3893 
   3894 http = evhttp_new(NULL);
   3895 tt_assert(http);
   3896 tt_int_op(evhttp_set_cb(http, "/test", http_basic_cb, http), ==, 0);
   3897 tt_int_op(evhttp_set_cb(http, "/test", http_basic_cb, http), ==, -1);
   3898 tt_int_op(evhttp_del_cb(http, "/test"), ==, 0);
   3899 tt_int_op(evhttp_del_cb(http, "/test"), ==, -1);
   3900 tt_int_op(evhttp_set_cb(http, "/test", http_basic_cb, http), ==, 0);
   3901 
   3902 end:
   3903 if (escaped)
   3904 	free(escaped);
   3905 if (http)
   3906 	evhttp_free(http);
   3907 }
   3908 
   3909 static void
   3910 http_multi_line_header_test(void *arg)
   3911 {
   3912 struct basic_test_data *data = arg;
   3913 struct bufferevent *bev= NULL;
   3914 evutil_socket_t fd = EVUTIL_INVALID_SOCKET;
   3915 const char *http_start_request;
   3916 ev_uint16_t port = 0;
   3917 struct evhttp *http = http_setup(&port, data->base, 0);
   3918 
   3919 exit_base = data->base;
   3920 test_ok = 0;
   3921 
   3922 tt_ptr_op(http, !=, NULL);
   3923 
   3924 fd = http_connect("127.0.0.1", port);
   3925 tt_assert(fd != EVUTIL_INVALID_SOCKET);
   3926 
   3927 /* Stupid thing to send a request */
   3928 bev = bufferevent_socket_new(data->base, fd, 0);
   3929 tt_ptr_op(bev, !=, NULL);
   3930 bufferevent_setcb(bev, http_readcb, http_writecb,
   3931     http_errorcb, data->base);
   3932 
   3933 http_start_request =
   3934     "GET /test HTTP/1.1\r\n"
   3935     "Host: somehost\r\n"
   3936     "Connection: close\r\n"
   3937     "X-Multi-Extra-WS:  libevent  \r\n"
   3938     "\t\t\t2.1 \r\n"
   3939     "X-Multi:  aaaaaaaa\r\n"
   3940     " a\r\n"
   3941     "\tEND\r\n"
   3942     "X-Last: last\r\n"
   3943     "\r\n";
   3944 
   3945 bufferevent_write(bev, http_start_request, strlen(http_start_request));
   3946 found_multi = found_multi2 = 0;
   3947 
   3948 event_base_dispatch(data->base);
   3949 
   3950 tt_int_op(found_multi, ==, 1);
   3951 tt_int_op(found_multi2, ==, 1);
   3952 tt_int_op(test_ok, ==, 4);
   3953 end:
   3954 if (bev)
   3955 	bufferevent_free(bev);
   3956 if (fd >= 0)
   3957 	evutil_closesocket(fd);
   3958 if (http)
   3959 	evhttp_free(http);
   3960 }
   3961 
   3962 static void
   3963 http_request_bad(struct evhttp_request *req, void *arg)
   3964 {
   3965 if (req != NULL) {
   3966 	fprintf(stderr, "FAILED\n");
   3967 	exit(1);
   3968 }
   3969 
   3970 test_ok = 1;
   3971 event_base_loopexit(arg, NULL);
   3972 }
   3973 
   3974 static void
   3975 http_negative_content_length_test(void *arg)
   3976 {
   3977 struct basic_test_data *data = arg;
   3978 ev_uint16_t port = 0;
   3979 struct evhttp_connection *evcon = NULL;
   3980 struct evhttp_request *req = NULL;
   3981 struct evhttp *http = http_setup(&port, data->base, 0);
   3982 
   3983 test_ok = 0;
   3984 
   3985 evcon = evhttp_connection_base_new(data->base, NULL, "127.0.0.1", port);
   3986 tt_assert(evcon);
   3987 
   3988 /*
   3989  * At this point, we want to schedule a request to the HTTP
   3990  * server using our make request method.
   3991  */
   3992 
   3993 req = evhttp_request_new(http_request_bad, data->base);
   3994 
   3995 /* Cause the response to have a negative content-length */
   3996 evhttp_add_header(evhttp_request_get_output_headers(req), "X-Negative", "makeitso");
   3997 
   3998 /* We give ownership of the request to the connection */
   3999 if (evhttp_make_request(evcon, req, EVHTTP_REQ_GET, "/test") == -1) {
   4000 	tt_abort_msg("Couldn't make request");
   4001 }
   4002 
   4003 event_base_dispatch(data->base);
   4004 
   4005 end:
   4006 if (evcon)
   4007 	evhttp_connection_free(evcon);
   4008 if (http)
   4009 	evhttp_free(http);
   4010 }
   4011 
   4012 
   4013 static void
   4014 http_data_length_constraints_test_done(struct evhttp_request *req, void *arg)
   4015 {
   4016 tt_assert(req);
   4017 tt_int_op(evhttp_request_get_response_code(req), ==, HTTP_BADREQUEST);
   4018 end:
   4019 event_base_loopexit(arg, NULL);
   4020 }
   4021 static void
   4022 http_large_entity_test_done(struct evhttp_request *req, void *arg)
   4023 {
   4024 tt_assert(req);
   4025 tt_int_op(evhttp_request_get_response_code(req), ==, HTTP_ENTITYTOOLARGE);
   4026 end:
   4027 event_base_loopexit(arg, NULL);
   4028 }
   4029 static void
   4030 http_expectation_failed_done(struct evhttp_request *req, void *arg)
   4031 {
   4032 tt_assert(req);
   4033 tt_int_op(evhttp_request_get_response_code(req), ==, HTTP_EXPECTATIONFAILED);
   4034 end:
   4035 event_base_loopexit(arg, NULL);
   4036 }
   4037 
   4038 static void
   4039 http_data_length_constraints_test_impl(void *arg, int read_on_write_error)
   4040 {
   4041 struct basic_test_data *data = arg;
   4042 ev_uint16_t port = 0;
   4043 struct evhttp_connection *evcon = NULL;
   4044 struct evhttp_request *req = NULL;
   4045 char *long_str = NULL;
   4046 const size_t continue_size = 1<<20;
   4047 const size_t size = (1<<20) * 3;
   4048 void (*cb)(struct evhttp_request *, void *);
   4049 struct evhttp *http = http_setup(&port, data->base, 0);
   4050 
   4051 test_ok = 0;
   4052 cb = http_failed_request_done;
   4053 if (read_on_write_error)
   4054 	cb = http_data_length_constraints_test_done;
   4055 
   4056 tt_assert(continue_size < size);
   4057 
   4058 long_str = malloc(size);
   4059 memset(long_str, 'a', size);
   4060 long_str[size - 1] = '\0';
   4061 
   4062 TT_BLATHER(("Creating connection to :%i", port));
   4063 evcon = evhttp_connection_base_new(data->base, NULL, "127.0.0.1", port);
   4064 tt_assert(evcon);
   4065 
   4066 if (read_on_write_error)
   4067 	tt_assert(!evhttp_connection_set_flags(evcon, EVHTTP_CON_READ_ON_WRITE_ERROR));
   4068 
   4069 evhttp_connection_set_local_address(evcon, "127.0.0.1");
   4070 
   4071 evhttp_set_max_headers_size(http, size - 1);
   4072 TT_BLATHER(("Set max header size %zu", size - 1));
   4073 
   4074 req = evhttp_request_new(http_data_length_constraints_test_done, data->base);
   4075 tt_assert(req);
   4076 evhttp_add_header(evhttp_request_get_output_headers(req), "Host", "somehost");
   4077 evhttp_add_header(evhttp_request_get_output_headers(req), "Longheader", long_str);
   4078 TT_BLATHER(("GET /?arg=val"));
   4079 if (evhttp_make_request(evcon, req, EVHTTP_REQ_GET, "/?arg=val") == -1) {
   4080 	tt_abort_msg("Couldn't make request");
   4081 }
   4082 event_base_dispatch(data->base);
   4083 
   4084 req = evhttp_request_new(http_data_length_constraints_test_done, data->base);
   4085 tt_assert(req);
   4086 evhttp_add_header(evhttp_request_get_output_headers(req), "Host", "somehost");
   4087 /* GET /?arg=verylongvalue HTTP/1.1 */
   4088 TT_BLATHER(("GET %s", long_str));
   4089 if (evhttp_make_request(evcon, req, EVHTTP_REQ_GET, long_str) == -1) {
   4090 	tt_abort_msg("Couldn't make request");
   4091 }
   4092 event_base_dispatch(data->base);
   4093 
   4094 evhttp_set_max_body_size(http, size - 2);
   4095 TT_BLATHER(("Set body header size %zu", size - 2));
   4096 
   4097 if (read_on_write_error)
   4098 	cb = http_large_entity_test_done;
   4099 req = evhttp_request_new(cb, data->base);
   4100 evhttp_add_header(evhttp_request_get_output_headers(req), "Host", "somehost");
   4101 evbuffer_add_printf(evhttp_request_get_output_buffer(req), "%s", long_str);
   4102 TT_BLATHER(("POST /"));
   4103 if (evhttp_make_request(evcon, req, EVHTTP_REQ_POST, "/") == -1) {
   4104 	tt_abort_msg("Couldn't make request");
   4105 }
   4106 event_base_dispatch(data->base);
   4107 
   4108 req = evhttp_request_new(http_large_entity_test_done, data->base);
   4109 evhttp_add_header(evhttp_request_get_output_headers(req), "Host", "somehost");
   4110 evhttp_add_header(evhttp_request_get_output_headers(req), "Expect", "100-continue");
   4111 evbuffer_add_printf(evhttp_request_get_output_buffer(req), "%s", long_str);
   4112 TT_BLATHER(("POST / (Expect: 100-continue, http_large_entity_test_done)"));
   4113 if (evhttp_make_request(evcon, req, EVHTTP_REQ_POST, "/") == -1) {
   4114 	tt_abort_msg("Couldn't make request");
   4115 }
   4116 event_base_dispatch(data->base);
   4117 
   4118 long_str[continue_size] = '\0';
   4119 
   4120 req = evhttp_request_new(http_dispatcher_test_done, data->base);
   4121 evhttp_add_header(evhttp_request_get_output_headers(req), "Host", "somehost");
   4122 evhttp_add_header(evhttp_request_get_output_headers(req), "Expect", "100-continue");
   4123 evbuffer_add_printf(evhttp_request_get_output_buffer(req), "%s", long_str);
   4124 TT_BLATHER(("POST / (Expect: 100-continue, http_dispatcher_test_done)"));
   4125 if (evhttp_make_request(evcon, req, EVHTTP_REQ_POST, "/") == -1) {
   4126 	tt_abort_msg("Couldn't make request");
   4127 }
   4128 event_base_dispatch(data->base);
   4129 
   4130 if (read_on_write_error)
   4131 	cb = http_expectation_failed_done;
   4132 req = evhttp_request_new(cb, data->base);
   4133 evhttp_add_header(evhttp_request_get_output_headers(req), "Host", "somehost");
   4134 evhttp_add_header(evhttp_request_get_output_headers(req), "Expect", "101-continue");
   4135 evbuffer_add_printf(evhttp_request_get_output_buffer(req), "%s", long_str);
   4136 TT_BLATHER(("POST / (Expect: 101-continue)"));
   4137 if (evhttp_make_request(evcon, req, EVHTTP_REQ_POST, "/") == -1) {
   4138 	tt_abort_msg("Couldn't make request");
   4139 }
   4140 event_base_dispatch(data->base);
   4141 
   4142 test_ok = 1;
   4143 end:
   4144 if (evcon)
   4145 	evhttp_connection_free(evcon);
   4146 if (http)
   4147 	evhttp_free(http);
   4148 if (long_str)
   4149 	free(long_str);
   4150 }
   4151 static void http_data_length_constraints_test(void *arg)
   4152 { http_data_length_constraints_test_impl(arg, 0); }
   4153 static void http_read_on_write_error_test(void *arg)
   4154 { http_data_length_constraints_test_impl(arg, 1); }
   4155 
   4156 static void
   4157 http_lingering_close_test_impl(void *arg, int lingering)
   4158 {
   4159 struct basic_test_data *data = arg;
   4160 ev_uint16_t port = 0;
   4161 struct evhttp_connection *evcon = NULL;
   4162 struct evhttp_request *req = NULL;
   4163 char *long_str = NULL;
   4164 size_t size = (1<<20) * 3;
   4165 void (*cb)(struct evhttp_request *, void *);
   4166 struct evhttp *http = http_setup(&port, data->base, 0);
   4167 
   4168 test_ok = 0;
   4169 
   4170 if (lingering)
   4171 	tt_assert(!evhttp_set_flags(http, EVHTTP_SERVER_LINGERING_CLOSE));
   4172 evhttp_set_max_body_size(http, size / 2);
   4173 
   4174 evcon = evhttp_connection_base_new(data->base, NULL, "127.0.0.1", port);
   4175 tt_assert(evcon);
   4176 evhttp_connection_set_local_address(evcon, "127.0.0.1");
   4177 
   4178 /*
   4179  * At this point, we want to schedule an HTTP GET request
   4180  * server using our make request method.
   4181  */
   4182 
   4183 long_str = malloc(size);
   4184 memset(long_str, 'a', size);
   4185 long_str[size - 1] = '\0';
   4186 
   4187 if (lingering)
   4188 	cb = http_large_entity_test_done;
   4189 else
   4190 	cb = http_failed_request_done;
   4191 req = evhttp_request_new(cb, data->base);
   4192 tt_assert(req);
   4193 evhttp_add_header(evhttp_request_get_output_headers(req), "Host", "somehost");
   4194 evbuffer_add_printf(evhttp_request_get_output_buffer(req), "%s", long_str);
   4195 if (evhttp_make_request(evcon, req, EVHTTP_REQ_POST, "/") == -1) {
   4196 	tt_abort_msg("Couldn't make request");
   4197 }
   4198 event_base_dispatch(data->base);
   4199 
   4200 test_ok = 1;
   4201 end:
   4202 if (evcon)
   4203 	evhttp_connection_free(evcon);
   4204 if (http)
   4205 	evhttp_free(http);
   4206 if (long_str)
   4207 	free(long_str);
   4208 }
   4209 static void http_non_lingering_close_test(void *arg)
   4210 { http_lingering_close_test_impl(arg, 0); }
   4211 static void http_lingering_close_test(void *arg)
   4212 { http_lingering_close_test_impl(arg, 1); }
   4213 
   4214 /*
   4215 * Testing client reset of server chunked connections
   4216 */
   4217 
   4218 struct terminate_state {
   4219 struct event_base *base;
   4220 struct evhttp_request *req;
   4221 struct bufferevent *bev;
   4222 evutil_socket_t fd;
   4223 int gotclosecb: 1;
   4224 int oneshot: 1;
   4225 };
   4226 
   4227 static void
   4228 terminate_chunked_trickle_cb(evutil_socket_t fd, short events, void *arg)
   4229 {
   4230 struct terminate_state *state = arg;
   4231 struct evbuffer *evb;
   4232 
   4233 if (!state->req) {
   4234 	return;
   4235 }
   4236 
   4237 if (evhttp_request_get_connection(state->req) == NULL) {
   4238 	test_ok = 1;
   4239 	evhttp_request_free(state->req);
   4240 	event_base_loopexit(state->base,NULL);
   4241 	return;
   4242 }
   4243 
   4244 evb = evbuffer_new();
   4245 evbuffer_add_printf(evb, "%p", evb);
   4246 evhttp_send_reply_chunk(state->req, evb);
   4247 evbuffer_free(evb);
   4248 
   4249 if (!state->oneshot) {
   4250 	struct timeval tv;
   4251 	tv.tv_sec = 0;
   4252 	tv.tv_usec = 3000;
   4253 	EVUTIL_ASSERT(state);
   4254 	EVUTIL_ASSERT(state->base);
   4255 	event_base_once(state->base, -1, EV_TIMEOUT, terminate_chunked_trickle_cb, arg, &tv);
   4256 }
   4257 }
   4258 
   4259 static void
   4260 terminate_chunked_close_cb(struct evhttp_connection *evcon, void *arg)
   4261 {
   4262 struct terminate_state *state = arg;
   4263 state->gotclosecb = 1;
   4264 
   4265 /** TODO: though we can do this unconditionally */
   4266 if (state->oneshot) {
   4267 	evhttp_request_free(state->req);
   4268 	state->req = NULL;
   4269 	event_base_loopexit(state->base,NULL);
   4270 }
   4271 }
   4272 
   4273 static void
   4274 terminate_chunked_cb(struct evhttp_request *req, void *arg)
   4275 {
   4276 struct terminate_state *state = arg;
   4277 struct timeval tv;
   4278 
   4279 /* we want to know if this connection closes on us */
   4280 evhttp_connection_set_closecb(
   4281 	evhttp_request_get_connection(req),
   4282 	terminate_chunked_close_cb, arg);
   4283 
   4284 state->req = req;
   4285 
   4286 evhttp_send_reply_start(req, HTTP_OK, "OK");
   4287 
   4288 tv.tv_sec = 0;
   4289 tv.tv_usec = 3000;
   4290 event_base_once(state->base, -1, EV_TIMEOUT, terminate_chunked_trickle_cb, arg, &tv);
   4291 }
   4292 
   4293 static void
   4294 terminate_chunked_client(evutil_socket_t fd, short event, void *arg)
   4295 {
   4296 struct terminate_state *state = arg;
   4297 bufferevent_free(state->bev);
   4298 evutil_closesocket(state->fd);
   4299 }
   4300 
   4301 static void
   4302 terminate_readcb(struct bufferevent *bev, void *arg)
   4303 {
   4304 /* just drop the data */
   4305 evbuffer_drain(bufferevent_get_input(bev), -1);
   4306 }
   4307 
   4308 
   4309 static void
   4310 http_terminate_chunked_test_impl(void *arg, int oneshot)
   4311 {
   4312 struct basic_test_data *data = arg;
   4313 struct bufferevent *bev = NULL;
   4314 struct timeval tv;
   4315 const char *http_request;
   4316 ev_uint16_t port = 0;
   4317 evutil_socket_t fd = EVUTIL_INVALID_SOCKET;
   4318 struct terminate_state terminate_state;
   4319 struct evhttp *http = http_setup(&port, data->base, 0);
   4320 
   4321 test_ok = 0;
   4322 
   4323 evhttp_del_cb(http, "/test");
   4324 tt_assert(evhttp_set_cb(http, "/test",
   4325 	terminate_chunked_cb, &terminate_state) == 0);
   4326 
   4327 fd = http_connect("127.0.0.1", port);
   4328 tt_assert(fd != EVUTIL_INVALID_SOCKET);
   4329 
   4330 /* Stupid thing to send a request */
   4331 bev = bufferevent_socket_new(data->base, fd, 0);
   4332 bufferevent_setcb(bev, terminate_readcb, http_writecb,
   4333     http_errorcb, data->base);
   4334 
   4335 memset(&terminate_state, 0, sizeof(terminate_state));
   4336 terminate_state.base = data->base;
   4337 terminate_state.fd = fd;
   4338 terminate_state.bev = bev;
   4339 terminate_state.gotclosecb = 0;
   4340 terminate_state.oneshot = oneshot;
   4341 
   4342 /* first half of the http request */
   4343 http_request =
   4344     "GET /test HTTP/1.1\r\n"
   4345     "Host: some\r\n\r\n";
   4346 
   4347 bufferevent_write(bev, http_request, strlen(http_request));
   4348 evutil_timerclear(&tv);
   4349 tv.tv_usec = 10000;
   4350 event_base_once(data->base, -1, EV_TIMEOUT, terminate_chunked_client, &terminate_state,
   4351     &tv);
   4352 
   4353 event_base_dispatch(data->base);
   4354 
   4355 if (terminate_state.gotclosecb == 0)
   4356 	test_ok = 0;
   4357 
   4358 end:
   4359 if (fd >= 0)
   4360 	evutil_closesocket(fd);
   4361 if (http)
   4362 	evhttp_free(http);
   4363 }
   4364 static void
   4365 http_terminate_chunked_test(void *arg)
   4366 {
   4367 http_terminate_chunked_test_impl(arg, 0);
   4368 }
   4369 static void
   4370 http_terminate_chunked_oneshot_test(void *arg)
   4371 {
   4372 http_terminate_chunked_test_impl(arg, 1);
   4373 }
   4374 
   4375 static struct regress_dns_server_table ipv6_search_table[] = {
   4376 { "localhost", "AAAA", "::1", 0, 0 },
   4377 { NULL, NULL, NULL, 0, 0 }
   4378 };
   4379 
   4380 static void
   4381 http_ipv6_for_domain_test_impl(void *arg, int family)
   4382 {
   4383 struct basic_test_data *data = arg;
   4384 struct evdns_base *dns_base = NULL;
   4385 ev_uint16_t portnum = 0;
   4386 char address[64];
   4387 
   4388 tt_assert(regress_dnsserver(data->base, &portnum, ipv6_search_table));
   4389 
   4390 dns_base = evdns_base_new(data->base, 0/* init name servers */);
   4391 tt_assert(dns_base);
   4392 
   4393 /* Add ourself as the only nameserver, and make sure we really are
   4394  * the only nameserver. */
   4395 evutil_snprintf(address, sizeof(address), "127.0.0.1:%d", portnum);
   4396 evdns_base_nameserver_ip_add(dns_base, address);
   4397 
   4398 http_connection_test_(arg, 0 /* not persistent */, "localhost", dns_base,
   4399 	1 /* ipv6 */, family, 0);
   4400 
   4401 end:
   4402 if (dns_base)
   4403 	evdns_base_free(dns_base, 0);
   4404 regress_clean_dnsserver();
   4405 }
   4406 static void
   4407 http_ipv6_for_domain_test(void *arg)
   4408 {
   4409 http_ipv6_for_domain_test_impl(arg, AF_UNSPEC);
   4410 }
   4411 
   4412 static void
   4413 http_request_get_addr_on_close(struct evhttp_connection *evcon, void *arg)
   4414 {
   4415 const struct sockaddr *storage;
   4416 char addrbuf[128];
   4417 char local[] = "127.0.0.1:";
   4418 
   4419 test_ok = 0;
   4420 tt_assert(evcon);
   4421 
   4422 storage = evhttp_connection_get_addr(evcon);
   4423 tt_assert(storage);
   4424 
   4425 evutil_format_sockaddr_port_((struct sockaddr *)storage, addrbuf, sizeof(addrbuf));
   4426 tt_assert(!strncmp(addrbuf, local, sizeof(local) - 1));
   4427 
   4428 test_ok = 1;
   4429 return;
   4430 
   4431 end:
   4432 test_ok = 0;
   4433 }
   4434 
   4435 static void
   4436 http_get_addr_test(void *arg)
   4437 {
   4438 struct basic_test_data *data = arg;
   4439 ev_uint16_t port = 0;
   4440 struct evhttp_connection *evcon = NULL;
   4441 struct evhttp_request *req = NULL;
   4442 struct evhttp *http = http_setup(&port, data->base, 0);
   4443 
   4444 test_ok = 0;
   4445 exit_base = data->base;
   4446 
   4447 evcon = evhttp_connection_base_new(data->base, NULL, "127.0.0.1", port);
   4448 tt_assert(evcon);
   4449 evhttp_connection_set_closecb(evcon, http_request_get_addr_on_close, arg);
   4450 
   4451 /*
   4452  * At this point, we want to schedule a request to the HTTP
   4453  * server using our make request method.
   4454  */
   4455 
   4456 req = evhttp_request_new(http_request_done, (void *)BASIC_REQUEST_BODY);
   4457 
   4458 /* We give ownership of the request to the connection */
   4459 if (evhttp_make_request(evcon, req, EVHTTP_REQ_GET, "/test") == -1) {
   4460 	tt_abort_msg("Couldn't make request");
   4461 }
   4462 
   4463 event_base_dispatch(data->base);
   4464 
   4465 http_request_get_addr_on_close(evcon, NULL);
   4466 
   4467 end:
   4468 if (evcon)
   4469 	evhttp_connection_free(evcon);
   4470 if (http)
   4471 	evhttp_free(http);
   4472 }
   4473 
   4474 static void
   4475 http_set_family_test(void *arg)
   4476 {
   4477 http_connection_test_(arg, 0, "127.0.0.1", NULL, 0, AF_UNSPEC, 0);
   4478 }
   4479 static void
   4480 http_set_family_ipv4_test(void *arg)
   4481 {
   4482 http_connection_test_(arg, 0, "127.0.0.1", NULL, 0, AF_INET, 0);
   4483 }
   4484 static void
   4485 http_set_family_ipv6_test(void *arg)
   4486 {
   4487 http_ipv6_for_domain_test_impl(arg, AF_INET6);
   4488 }
   4489 
   4490 static void
   4491 http_write_during_read(evutil_socket_t fd, short what, void *arg)
   4492 {
   4493 struct bufferevent *bev = arg;
   4494 struct timeval tv;
   4495 
   4496 bufferevent_write(bev, "foobar", strlen("foobar"));
   4497 
   4498 evutil_timerclear(&tv);
   4499 tv.tv_sec = 1;
   4500 event_base_loopexit(exit_base, &tv);
   4501 }
   4502 static void
   4503 http_write_during_read_test_impl(void *arg, int ssl)
   4504 {
   4505 struct basic_test_data *data = arg;
   4506 ev_uint16_t port = 0;
   4507 struct bufferevent *bev = NULL;
   4508 struct timeval tv;
   4509 evutil_socket_t fd;
   4510 const char *http_request;
   4511 struct evhttp *http = http_setup(&port, data->base, ssl ? HTTP_BIND_SSL : 0);
   4512 
   4513 test_ok = 0;
   4514 exit_base = data->base;
   4515 
   4516 fd = http_connect("127.0.0.1", port);
   4517 tt_assert(fd != EVUTIL_INVALID_SOCKET);
   4518 bev = create_bev(data->base, fd, 0, 0);
   4519 bufferevent_setcb(bev, NULL, NULL, NULL, data->base);
   4520 bufferevent_disable(bev, EV_READ);
   4521 
   4522 http_request =
   4523     "GET /large HTTP/1.1\r\n"
   4524     "Host: somehost\r\n"
   4525     "\r\n";
   4526 
   4527 bufferevent_write(bev, http_request, strlen(http_request));
   4528 evutil_timerclear(&tv);
   4529 tv.tv_usec = 10000;
   4530 event_base_once(data->base, -1, EV_TIMEOUT, http_write_during_read, bev, &tv);
   4531 
   4532 event_base_dispatch(data->base);
   4533 
   4534 end:
   4535 if (bev)
   4536 	bufferevent_free(bev);
   4537 if (http)
   4538 	evhttp_free(http);
   4539 }
   4540 static void http_write_during_read_test(void *arg)
   4541 { http_write_during_read_test_impl(arg, 0); }
   4542 
   4543 static void
   4544 http_request_own_test(void *arg)
   4545 {
   4546 struct basic_test_data *data = arg;
   4547 ev_uint16_t port = 0;
   4548 struct evhttp_connection *evcon = NULL;
   4549 struct evhttp_request *req = NULL;
   4550 struct evhttp *http = http_setup(&port, data->base, 0);
   4551 
   4552 test_ok = 0;
   4553 exit_base = data->base;
   4554 
   4555 evhttp_free(http);
   4556 
   4557 evcon = evhttp_connection_base_new(data->base, NULL, "127.0.0.1", port);
   4558 tt_assert(evcon);
   4559 
   4560 req = evhttp_request_new(http_request_no_action_done, NULL);
   4561 
   4562 if (evhttp_make_request(evcon, req, EVHTTP_REQ_GET, "/test") == -1) {
   4563 	tt_abort_msg("Couldn't make request");
   4564 }
   4565 evhttp_request_own(req);
   4566 
   4567 event_base_dispatch(data->base);
   4568 
   4569 end:
   4570 if (evcon)
   4571 	evhttp_connection_free(evcon);
   4572 if (req)
   4573 	evhttp_request_free(req);
   4574 
   4575 test_ok = 1;
   4576 }
   4577 
   4578 static void http_run_bev_request(struct event_base *base, int port,
   4579 const char *fmt, ...)
   4580 {
   4581 struct bufferevent *bev = NULL;
   4582 va_list ap;
   4583 evutil_socket_t fd;
   4584 struct evbuffer *out;
   4585 
   4586 fd = http_connect("127.0.0.1", port);
   4587 tt_assert(fd != EVUTIL_INVALID_SOCKET);
   4588 
   4589 /* Stupid thing to send a request */
   4590 bev = create_bev(base, fd, 0, 0);
   4591 bufferevent_setcb(bev, http_readcb, http_writecb,
   4592     http_errorcb, base);
   4593 out = bufferevent_get_output(bev);
   4594 
   4595 va_start(ap, fmt);
   4596 evbuffer_add_vprintf(out, fmt, ap);
   4597 va_end(ap);
   4598 
   4599 event_base_dispatch(base);
   4600 
   4601 end:
   4602 if (bev)
   4603 	bufferevent_free(bev);
   4604 }
   4605 static void
   4606 http_request_extra_body_test(void *arg)
   4607 {
   4608 struct basic_test_data *data = arg;
   4609 struct bufferevent *bev = NULL;
   4610 ev_uint16_t port = 0;
   4611 int i;
   4612 struct evhttp *http =
   4613 	http_setup_gencb(&port, data->base, 0, http_timeout_cb, NULL);
   4614 struct evbuffer *body = NULL;
   4615 
   4616 exit_base = data->base;
   4617 test_ok = 0;
   4618 
   4619 body = evbuffer_new();
   4620 for (i = 0; i < 10000; ++i)
   4621 	evbuffer_add_printf(body, "this is the body that HEAD should not have");
   4622 
   4623 http_run_bev_request(data->base, port,
   4624 	"HEAD /timeout HTTP/1.1\r\n"
   4625 	"Host: somehost\r\n"
   4626 	"Connection: close\r\n"
   4627 	"Content-Length: %i\r\n"
   4628 	"\r\n%s",
   4629 	(int)evbuffer_get_length(body),
   4630 	evbuffer_pullup(body, -1)
   4631 );
   4632 tt_assert(test_ok == -2);
   4633 
   4634 http_run_bev_request(data->base, port,
   4635 	"HEAD /__gencb__ HTTP/1.1\r\n"
   4636 	"Host: somehost\r\n"
   4637 	"Connection: close\r\n"
   4638 	"Content-Length: %i\r\n"
   4639 	"\r\n%s",
   4640 	(int)evbuffer_get_length(body),
   4641 	evbuffer_pullup(body, -1)
   4642 );
   4643 tt_assert(test_ok == -2);
   4644 
   4645 end:
   4646 evhttp_free(http);
   4647 if (bev)
   4648 	bufferevent_free(bev);
   4649 if (body)
   4650 	evbuffer_free(body);
   4651 }
   4652 
   4653 #define HTTP_LEGACY(name)						\
   4654 { #name, run_legacy_test_fn, TT_ISOLATED|TT_LEGACY, &legacy_setup, \
   4655 	    http_##name##_test }
   4656 
   4657 #define HTTP_CAST_ARG(a) ((void *)(a))
   4658 #define HTTP_OFF_N(title, name, arg) \
   4659 { #title, http_##name##_test, TT_ISOLATED|TT_OFF_BY_DEFAULT, &basic_setup, HTTP_CAST_ARG(arg) }
   4660 #define HTTP_RET_N(title, name, test_opts, arg) \
   4661 { #title, http_##name##_test, TT_ISOLATED|TT_RETRIABLE|test_opts, &basic_setup, HTTP_CAST_ARG(arg) }
   4662 #define HTTP_N(title, name, test_opts, arg) \
   4663 { #title, http_##name##_test, TT_ISOLATED|test_opts, &basic_setup, HTTP_CAST_ARG(arg) }
   4664 #define HTTP(name) HTTP_N(name, name, 0, NULL)
   4665 #define HTTPS(name) \
   4666 { "https_" #name, https_##name##_test, TT_ISOLATED, &basic_setup, NULL }
   4667 
   4668 #ifdef EVENT__HAVE_OPENSSL
   4669 static void https_basic_test(void *arg)
   4670 { http_basic_test_impl(arg, 1, "GET /test HTTP/1.1"); }
   4671 static void https_filter_basic_test(void *arg)
   4672 { http_basic_test_impl(arg, 1 | HTTP_SSL_FILTER, "GET /test HTTP/1.1"); }
   4673 static void https_incomplete_test(void *arg)
   4674 { http_incomplete_test_(arg, 0, 1); }
   4675 static void https_incomplete_timeout_test(void *arg)
   4676 { http_incomplete_test_(arg, 1, 1); }
   4677 static void https_simple_test(void *arg)
   4678 { http_simple_test_impl(arg, 1, 0, "/test"); }
   4679 static void https_simple_dirty_test(void *arg)
   4680 { http_simple_test_impl(arg, 1, 1, "/test"); }
   4681 static void https_connection_retry_conn_address_test(void *arg)
   4682 { http_connection_retry_conn_address_test_impl(arg, 1); }
   4683 static void https_connection_retry_test(void *arg)
   4684 { http_connection_retry_test_impl(arg, 1); }
   4685 static void https_chunk_out_test(void *arg)
   4686 { http_chunk_out_test_impl(arg, 1); }
   4687 static void https_filter_chunk_out_test(void *arg)
   4688 { http_chunk_out_test_impl(arg, 1 | HTTP_SSL_FILTER); }
   4689 static void https_stream_out_test(void *arg)
   4690 { http_stream_out_test_impl(arg, 1); }
   4691 static void https_connection_fail_test(void *arg)
   4692 { http_connection_fail_test_impl(arg, 1); }
   4693 static void https_write_during_read_test(void *arg)
   4694 { http_write_during_read_test_impl(arg, 1); }
   4695 static void https_connection_test(void *arg)
   4696 { http_connection_test_(arg, 0, "127.0.0.1", NULL, 0, AF_UNSPEC, 1); }
   4697 static void https_persist_connection_test(void *arg)
   4698 { http_connection_test_(arg, 1, "127.0.0.1", NULL, 0, AF_UNSPEC, 1); }
   4699 #endif
   4700 
   4701 struct testcase_t http_testcases[] = {
   4702 { "primitives", http_primitives, 0, NULL, NULL },
   4703 { "base", http_base_test, TT_FORK, NULL, NULL },
   4704 { "bad_headers", http_bad_header_test, 0, NULL, NULL },
   4705 { "parse_query", http_parse_query_test, 0, NULL, NULL },
   4706 { "parse_query_str", http_parse_query_str_test, 0, NULL, NULL },
   4707 { "parse_uri", http_parse_uri_test, 0, NULL, NULL },
   4708 { "parse_uri_nc", http_parse_uri_test, 0, &basic_setup, (void*)"nc" },
   4709 { "uriencode", http_uriencode_test, 0, NULL, NULL },
   4710 HTTP(basic),
   4711 HTTP(basic_trailing_space),
   4712 HTTP(simple),
   4713 HTTP(simple_nonconformant),
   4714 
   4715 HTTP_N(cancel, cancel, 0, BASIC),
   4716 HTTP_RET_N(cancel_by_host, cancel, 0, BY_HOST),
   4717 HTTP_RET_N(cancel_by_host_inactive_server, cancel, TT_NO_LOGS, BY_HOST | INACTIVE_SERVER),
   4718 HTTP_RET_N(cancel_by_host_no_ns, cancel, TT_NO_LOGS, BY_HOST | NO_NS),
   4719 HTTP_N(cancel_inactive_server, cancel, 0, INACTIVE_SERVER),
   4720 HTTP_N(cancel_by_host_no_ns_inactive_server, cancel, TT_NO_LOGS, BY_HOST | NO_NS | INACTIVE_SERVER),
   4721 HTTP_OFF_N(cancel_by_host_server_timeout, cancel, BY_HOST | INACTIVE_SERVER | SERVER_TIMEOUT),
   4722 HTTP_OFF_N(cancel_server_timeout, cancel, INACTIVE_SERVER | SERVER_TIMEOUT),
   4723 HTTP_OFF_N(cancel_by_host_no_ns_server_timeout, cancel, BY_HOST | NO_NS | INACTIVE_SERVER | SERVER_TIMEOUT),
   4724 HTTP_OFF_N(cancel_by_host_ns_timeout_server_timeout, cancel, BY_HOST | NO_NS | NS_TIMEOUT | INACTIVE_SERVER | SERVER_TIMEOUT),
   4725 HTTP_RET_N(cancel_by_host_ns_timeout, cancel, TT_NO_LOGS, BY_HOST | NO_NS | NS_TIMEOUT),
   4726 HTTP_RET_N(cancel_by_host_ns_timeout_inactive_server, cancel, TT_NO_LOGS, BY_HOST | NO_NS | NS_TIMEOUT | INACTIVE_SERVER),
   4727 
   4728 HTTP(virtual_host),
   4729 HTTP(post),
   4730 HTTP(put),
   4731 HTTP(delete),
   4732 HTTP(allowed_methods),
   4733 HTTP(failure),
   4734 HTTP(connection),
   4735 HTTP(persist_connection),
   4736 HTTP(autofree_connection),
   4737 HTTP(connection_async),
   4738 HTTP(close_detection),
   4739 HTTP(close_detection_delay),
   4740 HTTP(bad_request),
   4741 HTTP(incomplete),
   4742 HTTP(incomplete_timeout),
   4743 HTTP(terminate_chunked),
   4744 HTTP(terminate_chunked_oneshot),
   4745 HTTP(on_complete),
   4746 
   4747 HTTP(highport),
   4748 HTTP(dispatcher),
   4749 HTTP(multi_line_header),
   4750 HTTP(negative_content_length),
   4751 HTTP(chunk_out),
   4752 HTTP(stream_out),
   4753 
   4754 HTTP(stream_in),
   4755 HTTP(stream_in_cancel),
   4756 
   4757 HTTP(connection_fail),
   4758 { "connection_retry", http_connection_retry_test, TT_ISOLATED|TT_OFF_BY_DEFAULT, &basic_setup, NULL },
   4759 { "connection_retry_conn_address", http_connection_retry_conn_address_test,
   4760   TT_ISOLATED|TT_OFF_BY_DEFAULT, &basic_setup, NULL },
   4761 
   4762 HTTP(data_length_constraints),
   4763 HTTP(read_on_write_error),
   4764 HTTP(non_lingering_close),
   4765 HTTP(lingering_close),
   4766 
   4767 HTTP(ipv6_for_domain),
   4768 HTTP(get_addr),
   4769 
   4770 HTTP(set_family),
   4771 HTTP(set_family_ipv4),
   4772 HTTP(set_family_ipv6),
   4773 
   4774 HTTP(write_during_read),
   4775 HTTP(request_own),
   4776 
   4777 HTTP(request_extra_body),
   4778 
   4779 #ifdef EVENT__HAVE_OPENSSL
   4780 HTTPS(basic),
   4781 HTTPS(filter_basic),
   4782 HTTPS(simple),
   4783 HTTPS(simple_dirty),
   4784 HTTPS(incomplete),
   4785 HTTPS(incomplete_timeout),
   4786 { "https_connection_retry", https_connection_retry_test, TT_ISOLATED|TT_OFF_BY_DEFAULT, &basic_setup, NULL },
   4787 { "https_connection_retry_conn_address", https_connection_retry_conn_address_test,
   4788   TT_ISOLATED|TT_OFF_BY_DEFAULT, &basic_setup, NULL },
   4789 HTTPS(chunk_out),
   4790 HTTPS(filter_chunk_out),
   4791 HTTPS(stream_out),
   4792 HTTPS(connection_fail),
   4793 HTTPS(write_during_read),
   4794 HTTPS(connection),
   4795 HTTPS(persist_connection),
   4796 #endif
   4797 
   4798 END_OF_TESTCASES
   4799 };
   4800 
   4801 struct testcase_t http_iocp_testcases[] = {
   4802 { "simple", http_simple_test, TT_FORK|TT_NEED_BASE|TT_ENABLE_IOCP, &basic_setup, NULL },
   4803 #ifdef EVENT__HAVE_OPENSSL
   4804 { "https_simple", https_simple_test, TT_FORK|TT_NEED_BASE|TT_ENABLE_IOCP, &basic_setup, NULL },
   4805 #endif
   4806 END_OF_TESTCASES
   4807 };