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