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