summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAzat Khuzhin <a3at.mail@gmail.com>2015-10-08 11:50:53 +0300
committerAzat Khuzhin <a3at.mail@gmail.com>2015-10-08 11:51:55 +0300
commita4a7c1aeddc3100cb8d24450bd9adcd2d1cd9a56 (patch)
tree5f9ce9990cbca6c2544c49697211694c04a02a10
parent571dbac81af7a378d6fad0728c3eb3d7be89785f (diff)
parent066a4f6fd12dedbc5597787e48dc03a9c556ad0e (diff)
downloadlibevent-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.c25
-rw-r--r--test/regress_http.c109
2 files changed, 91 insertions, 43 deletions
diff --git a/http.c b/http.c
index 377597ea..ea70de50 100644
--- a/http.c
+++ b/http.c
@@ -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
};