summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Stenberg <daniel@haxx.se>2022-09-21 08:52:57 +0200
committerDaniel Stenberg <daniel@haxx.se>2022-09-22 09:47:59 +0200
commit46f3fe0e75aa4cd1ae057b3703a6ddd272356813 (patch)
treedc40f3b20165838a8e04184613a636224b91dc1d
parent7295e62c66cac62751a0a9964dc317048d145524 (diff)
downloadcurl-46f3fe0e75aa4cd1ae057b3703a6ddd272356813.tar.gz
hostip: lazily wait to figure out if IPv6 works until needed
The check may take many milliseconds, so now it is performed once the value is first needed. Also, this change makes sure that the value is not used if the resolve is set to be IPv4-only. Closes #9553
-rw-r--r--lib/asyn-ares.c7
-rw-r--r--lib/asyn-thread.c2
-rw-r--r--lib/doh.c2
-rw-r--r--lib/hostip.c6
-rw-r--r--lib/hostip6.c2
-rw-r--r--lib/multi.c1
-rw-r--r--lib/multihandle.h10
7 files changed, 17 insertions, 13 deletions
diff --git a/lib/asyn-ares.c b/lib/asyn-ares.c
index 1f3965541..cbc0e2ea7 100644
--- a/lib/asyn-ares.c
+++ b/lib/asyn-ares.c
@@ -779,10 +779,9 @@ struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct Curl_easy *data,
int pf = PF_INET;
memset(&hints, 0, sizeof(hints));
#ifdef CURLRES_IPV6
- if(Curl_ipv6works(data))
+ if((data->conn->ip_version != CURL_IPRESOLVE_V4) && Curl_ipv6works(data))
/* The stack seems to be IPv6-enabled */
- if(data->conn->ip_version != CURL_IPRESOLVE_V4)
- pf = PF_UNSPEC;
+ pf = PF_UNSPEC;
#endif /* CURLRES_IPV6 */
hints.ai_family = pf;
hints.ai_socktype = (data->conn->transport == TRNSPRT_TCP)?
@@ -795,7 +794,7 @@ struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct Curl_easy *data,
#else
#ifdef HAVE_CARES_IPV6
- if(Curl_ipv6works(data) && data->conn->ip_version != CURL_IPRESOLVE_V4) {
+ if((data->conn->ip_version != CURL_IPRESOLVE_V4) && Curl_ipv6works(data)) {
/* The stack seems to be IPv6-enabled */
res->num_pending = 2;
diff --git a/lib/asyn-thread.c b/lib/asyn-thread.c
index 68fddf0b2..8b375eb5e 100644
--- a/lib/asyn-thread.c
+++ b/lib/asyn-thread.c
@@ -707,7 +707,7 @@ struct Curl_addrinfo *Curl_resolver_getaddrinfo(struct Curl_easy *data,
*waitp = 0; /* default to synchronous response */
#ifdef CURLRES_IPV6
- if(Curl_ipv6works(data) && data->conn->ip_version != CURL_IPRESOLVE_V4)
+ if((data->conn->ip_version != CURL_IPRESOLVE_V4) && Curl_ipv6works(data))
/* The stack seems to be IPv6-enabled */
pf = PF_UNSPEC;
#endif /* CURLRES_IPV6 */
diff --git a/lib/doh.c b/lib/doh.c
index 29399772b..3b1d5d60e 100644
--- a/lib/doh.c
+++ b/lib/doh.c
@@ -396,7 +396,7 @@ struct Curl_addrinfo *Curl_doh(struct Curl_easy *data,
goto error;
dohp->pending++;
- if(Curl_ipv6works(data) && conn->ip_version != CURL_IPRESOLVE_V4) {
+ if((conn->ip_version != CURL_IPRESOLVE_V4) && Curl_ipv6works(data)) {
/* create IPv6 DoH request */
result = dohprobe(data, &dohp->probe[DOH_PROBE_SLOT_IPADDR_V6],
DNS_TYPE_AAAA, hostname, data->set.str[STRING_DOH],
diff --git a/lib/hostip.c b/lib/hostip.c
index ec27602dc..0eb565a2e 100644
--- a/lib/hostip.c
+++ b/lib/hostip.c
@@ -569,7 +569,11 @@ bool Curl_ipv6works(struct Curl_easy *data)
have the info kept for fast re-use */
DEBUGASSERT(data);
DEBUGASSERT(data->multi);
- return data->multi->ipv6_works;
+ if(data->multi->ipv6_up == IPV6_UNKNOWN) {
+ bool works = Curl_ipv6works(NULL);
+ data->multi->ipv6_up = works ? IPV6_WORKS : IPV6_DEAD;
+ }
+ return data->multi->ipv6_up == IPV6_WORKS;
}
else {
int ipv6_works = -1;
diff --git a/lib/hostip6.c b/lib/hostip6.c
index 4e8e916ce..c62c254c7 100644
--- a/lib/hostip6.c
+++ b/lib/hostip6.c
@@ -117,7 +117,7 @@ struct Curl_addrinfo *Curl_getaddrinfo(struct Curl_easy *data,
*waitp = 0; /* synchronous response only */
- if(Curl_ipv6works(data) && data->conn->ip_version != CURL_IPRESOLVE_V4)
+ if((data->conn->ip_version != CURL_IPRESOLVE_V4) && Curl_ipv6works(data))
/* The stack seems to be IPv6-enabled */
pf = PF_UNSPEC;
diff --git a/lib/multi.c b/lib/multi.c
index 01b27f770..d9d7d8c0a 100644
--- a/lib/multi.c
+++ b/lib/multi.c
@@ -417,7 +417,6 @@ struct Curl_multi *Curl_multi_handle(int hashsize, /* socket hash */
/* -1 means it not set by user, use the default value */
multi->maxconnects = -1;
multi->max_concurrent_streams = 100;
- multi->ipv6_works = Curl_ipv6works(NULL);
#ifdef USE_WINSOCK
multi->wsa_event = WSACreateEvent();
diff --git a/lib/multihandle.h b/lib/multihandle.h
index 76a67a89a..a997784ea 100644
--- a/lib/multihandle.h
+++ b/lib/multihandle.h
@@ -150,11 +150,13 @@ struct Curl_multi {
0 is used for read, 1 is used for write */
#endif
#endif
- /* multiplexing wanted */
- bool multiplexing;
- bool recheckstate; /* see Curl_multi_connchanged */
+#define IPV6_UNKNOWN 0
+#define IPV6_DEAD 1
+#define IPV6_WORKS 2
+ unsigned char ipv6_up; /* IPV6_* defined */
+ bool multiplexing; /* multiplexing wanted */
+ bool recheckstate; /* see Curl_multi_connchanged */
bool in_callback; /* true while executing a callback */
- bool ipv6_works;
#ifdef USE_OPENSSL
bool ssl_seeded;
#endif