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