diff options
author | Azat Khuzhin <a3at.mail@gmail.com> | 2015-10-08 11:50:53 +0300 |
---|---|---|
committer | Azat Khuzhin <a3at.mail@gmail.com> | 2015-10-08 11:51:55 +0300 |
commit | a4a7c1aeddc3100cb8d24450bd9adcd2d1cd9a56 (patch) | |
tree | 5f9ce9990cbca6c2544c49697211694c04a02a10 | |
parent | 571dbac81af7a378d6fad0728c3eb3d7be89785f (diff) | |
parent | 066a4f6fd12dedbc5597787e48dc03a9c556ad0e (diff) | |
download | libevent-a4a7c1aeddc3100cb8d24450bd9adcd2d1cd9a56.tar.gz |
Merge branch 'fix-http-for-ipv6-backport-for-2.0' into patches-2.0
This patchset is just a backport from upstream (with minor fixes to function
names in tests) of 2ecd894725e167dcc1f22f9292f98e41299df6cc ("Merge pull
request #39 from azat/fix-http-for-ipv6")
* fix-http-for-ipv6-backport-for-2.0:
Add regress test ipv6_for_domain.
Fix ipv6 support for http. When URL contain domain, not IP address.
Fixes #287
-rw-r--r-- | http.c | 25 | ||||
-rw-r--r-- | test/regress_http.c | 109 |
2 files changed, 91 insertions, 43 deletions
@@ -1325,6 +1325,9 @@ evhttp_error_cb(struct bufferevent *bufev, short what, void *arg) struct evhttp_connection *evcon = arg; struct evhttp_request *req = TAILQ_FIRST(&evcon->requests); + if (evcon->fd == -1) + evcon->fd = bufferevent_getfd(bufev); + switch (evcon->state) { case EVCON_CONNECTING: if (what & BEV_EVENT_TIMEOUT) { @@ -1390,6 +1393,9 @@ evhttp_connection_cb(struct bufferevent *bufev, short what, void *arg) int error; ev_socklen_t errsz = sizeof(error); + if (evcon->fd == -1) + evcon->fd = bufferevent_getfd(bufev); + if (!(what & BEV_EVENT_CONNECTED)) { /* some operating systems return ECONNREFUSED immediately * when connecting to a local address. the cleanup is going @@ -2191,16 +2197,21 @@ evhttp_connection_connect(struct evhttp_connection *evcon) EVUTIL_ASSERT(!(evcon->flags & EVHTTP_CON_INCOMING)); evcon->flags |= EVHTTP_CON_OUTGOING; - evcon->fd = bind_socket( - evcon->bind_address, evcon->bind_port, 0 /*reuse*/); - if (evcon->fd == -1) { - event_debug(("%s: failed to bind to \"%s\"", - __func__, evcon->bind_address)); - return (-1); + if (evcon->bind_address || evcon->bind_port) { + evcon->fd = bind_socket( + evcon->bind_address, evcon->bind_port, 0 /*reuse*/); + if (evcon->fd == -1) { + event_debug(("%s: failed to bind to \"%s\"", + __func__, evcon->bind_address)); + return (-1); + } + + bufferevent_setfd(evcon->bufev, evcon->fd); + } else { + bufferevent_setfd(evcon->bufev, -1); } /* Set up a callback for successful connection setup */ - bufferevent_setfd(evcon->bufev, evcon->fd); bufferevent_setcb(evcon->bufev, NULL /* evhttp_read_cb */, NULL /* evhttp_write_cb */, diff --git a/test/regress_http.c b/test/regress_http.c index 9ece455b..47350d05 100644 --- a/test/regress_http.c +++ b/test/regress_http.c @@ -80,12 +80,16 @@ static void http_large_delay_cb(struct evhttp_request *req, void *arg); static void http_badreq_cb(struct evhttp_request *req, void *arg); static void http_dispatcher_cb(struct evhttp_request *req, void *arg); static int -http_bind(struct evhttp *myhttp, ev_uint16_t *pport) +http_bind(struct evhttp *myhttp, ev_uint16_t *pport, int ipv6) { int port; struct evhttp_bound_socket *sock; - sock = evhttp_bind_socket_with_handle(myhttp, "127.0.0.1", *pport); + if (ipv6) + sock = evhttp_bind_socket_with_handle(myhttp, "::1", *pport); + else + sock = evhttp_bind_socket_with_handle(myhttp, "127.0.0.1", *pport); + if (sock == NULL) event_errx(1, "Could not start web server"); @@ -98,14 +102,14 @@ http_bind(struct evhttp *myhttp, ev_uint16_t *pport) } static struct evhttp * -http_setup(ev_uint16_t *pport, struct event_base *base) +http_setup(ev_uint16_t *pport, struct event_base *base, int ipv6) { struct evhttp *myhttp; /* Try a few different ports */ myhttp = evhttp_new(base); - if (http_bind(myhttp, pport) < 0) + if (http_bind(myhttp, pport, ipv6) < 0) return NULL; /* Register a callback for certain types of requests */ @@ -365,10 +369,10 @@ http_basic_test(void *arg) test_ok = 0; - http = http_setup(&port, data->base); + http = http_setup(&port, data->base, 0); /* bind to a second socket */ - if (http_bind(http, &port2) == -1) { + if (http_bind(http, &port2, 0) == -1) { fprintf(stdout, "FAILED (bind)\n"); exit(1); } @@ -553,10 +557,10 @@ http_bad_request_test(void *arg) test_ok = 0; exit_base = data->base; - http = http_setup(&port, data->base); + http = http_setup(&port, data->base, 0); /* bind to a second socket */ - if (http_bind(http, &port2) == -1) + if (http_bind(http, &port2, 0) == -1) TT_DIE(("Bind socket failed")); /* NULL request test */ @@ -671,7 +675,7 @@ http_delete_test(void *arg) test_ok = 0; - http = http_setup(&port, data->base); + http = http_setup(&port, data->base, 0); fd = http_connect("127.0.0.1", port); @@ -732,7 +736,7 @@ http_allowed_methods_test(void *arg) exit_base = data->base; test_ok = 0; - http = http_setup(&port, data->base); + http = http_setup(&port, data->base, 0); fd1 = http_connect("127.0.0.1", port); @@ -823,7 +827,7 @@ static void http_request_done(struct evhttp_request *, void *); static void http_request_empty_done(struct evhttp_request *, void *); static void -_http_connection_test(struct basic_test_data *data, int persistent) +_http_connection_test(struct basic_test_data *data, int persistent, const char *address, struct evdns_base *dnsbase, int ipv6) { ev_uint16_t port = 0; struct evhttp_connection *evcon = NULL; @@ -831,9 +835,9 @@ _http_connection_test(struct basic_test_data *data, int persistent) test_ok = 0; - http = http_setup(&port, data->base); + http = http_setup(&port, data->base, ipv6); - evcon = evhttp_connection_base_new(data->base, NULL, "127.0.0.1", port); + evcon = evhttp_connection_base_new(data->base, dnsbase, address, port); tt_assert(evcon); tt_assert(evhttp_connection_get_base(evcon) == data->base); @@ -906,12 +910,12 @@ _http_connection_test(struct basic_test_data *data, int persistent) static void http_connection_test(void *arg) { - _http_connection_test(arg, 0); + _http_connection_test(arg, 0, "127.0.0.1", NULL, 0); } static void http_persist_connection_test(void *arg) { - _http_connection_test(arg, 1); + _http_connection_test(arg, 1, "127.0.0.1", NULL, 0); } static struct regress_dns_server_table search_table[] = { @@ -943,7 +947,7 @@ http_connection_async_test(void *arg) test_ok = 0; - http = http_setup(&port, data->base); + http = http_setup(&port, data->base, 0); evcon = evhttp_connection_base_new(data->base, dns_base, "127.0.0.1", port); tt_assert(evcon); @@ -1052,7 +1056,7 @@ http_cancel_test(void *arg) test_ok = 0; - http = http_setup(&port, data->base); + http = http_setup(&port, data->base, 0); evcon = evhttp_connection_base_new(data->base, NULL, "127.0.0.1", port); tt_assert(evcon); @@ -1174,7 +1178,7 @@ http_virtual_host_test(void *arg) exit_base = data->base; - http = http_setup(&port, data->base); + http = http_setup(&port, data->base, 0); /* virtual host */ second = evhttp_new(NULL); @@ -1415,7 +1419,7 @@ http_dispatcher_test(void *arg) test_ok = 0; - http = http_setup(&port, data->base); + http = http_setup(&port, data->base, 0); evcon = evhttp_connection_base_new(data->base, NULL, "127.0.0.1", port); tt_assert(evcon); @@ -1465,7 +1469,7 @@ http_post_test(void *arg) test_ok = 0; - http = http_setup(&port, data->base); + http = http_setup(&port, data->base, 0); evcon = evhttp_connection_base_new(data->base, NULL, "127.0.0.1", port); tt_assert(evcon); @@ -1605,7 +1609,7 @@ http_put_test(void *arg) test_ok = 0; - http = http_setup(&port, data->base); + http = http_setup(&port, data->base, 0); evcon = evhttp_connection_base_new(data->base, NULL, "127.0.0.1", port); tt_assert(evcon); @@ -1731,7 +1735,7 @@ http_failure_test(void *arg) test_ok = 0; - http = http_setup(&port, data->base); + http = http_setup(&port, data->base, 0); fd = http_connect("127.0.0.1", port); @@ -1818,7 +1822,7 @@ _http_close_detection(struct basic_test_data *data, int with_delay) struct evhttp_request *req = NULL; test_ok = 0; - http = http_setup(&port, data->base); + http = http_setup(&port, data->base, 0); /* 2 second timeout */ evhttp_set_timeout(http, 1); @@ -2481,7 +2485,7 @@ http_base_test(void *ptr) test_ok = 0; base = event_base_new(); - http = http_setup(&port, base); + http = http_setup(&port, base, 0); fd = http_connect("127.0.0.1", port); @@ -2563,7 +2567,7 @@ _http_incomplete_test(struct basic_test_data *data, int use_timeout) test_ok = 0; - http = http_setup(&port, data->base); + http = http_setup(&port, data->base, 0); evhttp_set_timeout(http, 1); fd = http_connect("127.0.0.1", port); @@ -2777,7 +2781,7 @@ http_chunk_out_test(void *arg) exit_base = data->base; test_ok = 0; - http = http_setup(&port, data->base); + http = http_setup(&port, data->base, 0); fd = http_connect("127.0.0.1", port); @@ -2849,7 +2853,7 @@ http_stream_out_test(void *arg) test_ok = 0; exit_base = data->base; - http = http_setup(&port, data->base); + http = http_setup(&port, data->base, 0); evcon = evhttp_connection_base_new(data->base, NULL, "127.0.0.1", port); tt_assert(evcon); @@ -2917,7 +2921,7 @@ _http_stream_in_test(struct basic_test_data *data, char const *url, ev_uint16_t port = 0; exit_base = data->base; - http = http_setup(&port, data->base); + http = http_setup(&port, data->base, 0); evcon = evhttp_connection_base_new(data->base, NULL,"127.0.0.1", port); tt_assert(evcon); @@ -2988,7 +2992,7 @@ http_stream_in_cancel_test(void *arg) struct evhttp_request *req = NULL; ev_uint16_t port = 0; - http = http_setup(&port, data->base); + http = http_setup(&port, data->base, 0); evcon = evhttp_connection_base_new(data->base, NULL, "127.0.0.1", port); tt_assert(evcon); @@ -3044,7 +3048,7 @@ http_connection_fail_test(void *arg) test_ok = 0; /* auto detect a port */ - http = http_setup(&port, data->base); + http = http_setup(&port, data->base, 0); evhttp_free(http); http = NULL; @@ -3094,7 +3098,7 @@ static void http_make_web_server(evutil_socket_t fd, short what, void *arg) { ev_uint16_t port = *(ev_uint16_t*)arg; - http = http_setup(&port, http_make_web_server_base); + http = http_setup(&port, http_make_web_server_base, 0); } static void @@ -3110,7 +3114,7 @@ http_connection_retry_test(void *arg) test_ok = 0; /* auto detect a port */ - http = http_setup(&port, data->base); + http = http_setup(&port, data->base, 0); evhttp_free(http); http = NULL; @@ -3260,7 +3264,7 @@ http_multi_line_header_test(void *arg) test_ok = 0; - http = http_setup(&port, data->base); + http = http_setup(&port, data->base, 0); fd = http_connect("127.0.0.1", port); @@ -3315,7 +3319,7 @@ http_negative_content_length_test(void *arg) test_ok = 0; - http = http_setup(&port, data->base); + http = http_setup(&port, data->base, 0); evcon = evhttp_connection_base_new(data->base, NULL, "127.0.0.1", port); tt_assert(evcon); @@ -3374,7 +3378,7 @@ http_data_length_constraints_test(void *arg) test_ok = 0; - http = http_setup(&port, data->base); + http = http_setup(&port, data->base, 0); evcon = evhttp_connection_base_new(data->base, NULL, "127.0.0.1", port); tt_assert(evcon); @@ -3532,7 +3536,7 @@ http_terminate_chunked_test(void *arg) test_ok = 0; - http = http_setup(&port, data->base); + http = http_setup(&port, data->base, 0); evhttp_del_cb(http, "/test"); tt_assert(evhttp_set_cb(http, "/test", terminate_chunked_cb, &terminate_state) == 0); @@ -3573,6 +3577,37 @@ http_terminate_chunked_test(void *arg) evhttp_free(http); } +static struct regress_dns_server_table ipv6_search_table[] = { + { "localhost", "AAAA", "::1", 0 }, + { NULL, NULL, NULL, 0 } +}; + +static void +http_ipv6_for_domain_test(void *arg) +{ + struct basic_test_data *data = arg; + struct evdns_base *dns_base = NULL; + ev_uint16_t portnum = 0; + char address[64]; + + tt_assert(regress_dnsserver(data->base, &portnum, ipv6_search_table)); + + dns_base = evdns_base_new(data->base, 0/* init name servers */); + tt_assert(dns_base); + + /* Add ourself as the only nameserver, and make sure we really are + * the only nameserver. */ + evutil_snprintf(address, sizeof(address), "127.0.0.1:%d", portnum); + evdns_base_nameserver_ip_add(dns_base, address); + + _http_connection_test(arg, 0 /* not persistent */, "localhost", dns_base, 1 /* ipv6 */); + + end: + if (dns_base) + evdns_base_free(dns_base, 0); + regress_clean_dnsserver(); +} + #define HTTP_LEGACY(name) \ { #name, run_legacy_test_fn, TT_ISOLATED|TT_LEGACY, &legacy_setup, \ http_##name##_test } @@ -3620,6 +3655,8 @@ struct testcase_t http_testcases[] = { HTTP(connection_retry), HTTP(data_length_constraints), + HTTP(ipv6_for_domain), + END_OF_TESTCASES }; |