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