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