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