Buy commercial curl support from WolfSSL. We help you work
out your issues, debug your libcurl applications, use the API, port to new
platforms, add new features and more. With a team lead by the curl founder
himself.
RE: Connection takes too long in dual-stack if IPv6 starting family is not available or blocked and has multiple addresses.
- Contemporary messages sorted: [ by date ] [ by thread ] [ by subject ] [ by author ] [ by messages with attachments ]
From: Daniel Stenberg via curl-library <curl-library_at_cool.haxx.se>
Date: Mon, 7 Jun 2021 13:36:00 +0200 (CEST)
On Fri, 4 Jun 2021, Dmitry Karpov wrote:
(I've put the CC back to the libcurl list to allow everyone to participate)
> Initially, I also had the same idea to use happy eyeballs timeout to cover
> cases of connection socket errors, but with host resolutions having multiple
> IPv6 addresses, it was really a waste of time to try next addresses of the
> failed family knowing that they would definitely fail. I think that in the
> current state, when Curl tries family addresses sequentially, happy eyeball
> timeout should be applied only for "good" connections that don't issue
> socket errors, and socket errors should be probably treated as a "family
> failure".
Hm, what if we also consider the first *error* on IPv6 as a signal to kick off
the IPv4 connect in addition to the timeout? See updated patch below.
> If Curl tried parallel connections for all addresses inside the family
> instead of doing it sequentially, then the idea to apply happy eyeballs
> timeout to the socket errors would work very well. Parallel connections
> would allow to fail the family much faster if something was wrong with it,
> and this would also be beneficial because the client would get the fastest
> connection inside the family - which is nice.
Yes, and I'm not against trying this out - this idea has been mentioned before
in HTTP implementor "circles". I would however imagine that it would need to
be capped at some value because some names will return MANY addresses so this
could be rather excessive, which could become a problem for apps who fire up
many transfers at once.
--- patch proposal v2
diff --git a/lib/connect.c b/lib/connect.c
index d9317f378..76e9d50dd 100644
--- a/lib/connect.c
+++ b/lib/connect.c
_at__at_ -931,18 +931,10 _at__at_ CURLcode Curl_is_connected(struct Curl_easy *data,
conn->timeoutms_per_addr[i]) {
infof(data, "After %" CURL_FORMAT_TIMEDIFF_T
"ms connect time, move on!\n", conn->timeoutms_per_addr[i]);
error = ETIMEDOUT;
}
-
- /* should we try another protocol family? */
- if(i == 0 && !conn->bits.parallel_connect &&
- (Curl_timediff(now, conn->connecttime) >=
- data->set.happy_eyeballs_timeout)) {
- conn->bits.parallel_connect = TRUE; /* starting now */
- trynextip(data, conn, sockindex, 1);
- }
}
else if(rc == CURL_CSELECT_OUT || conn->bits.tcp_fastopen) {
if(verifyconnect(conn->tempsock[i], &error)) {
/* we are connected with TCP, awesome! */
_at__at_ -1002,10 +994,20 _at__at_ CURLcode Curl_is_connected(struct Curl_easy *data,
conn->tempsock[other] == CURL_SOCKET_BAD)
/* the last attempt failed and no other sockets remain open */
result = status;
}
}
+
+ if(!rc || error) {
+ /* should we try another protocol family? */
+ if(i == 0 && !conn->bits.parallel_connect &&
+ (error || (Curl_timediff(now, conn->connecttime) >=
+ data->set.happy_eyeballs_timeout))) {
+ conn->bits.parallel_connect = TRUE; /* starting now */
+ trynextip(data, conn, sockindex, 1);
+ }
+ }
}
if(result &&
(conn->tempsock[0] == CURL_SOCKET_BAD) &&
(conn->tempsock[1] == CURL_SOCKET_BAD)) {
Date: Mon, 7 Jun 2021 13:36:00 +0200 (CEST)
On Fri, 4 Jun 2021, Dmitry Karpov wrote:
(I've put the CC back to the libcurl list to allow everyone to participate)
> Initially, I also had the same idea to use happy eyeballs timeout to cover
> cases of connection socket errors, but with host resolutions having multiple
> IPv6 addresses, it was really a waste of time to try next addresses of the
> failed family knowing that they would definitely fail. I think that in the
> current state, when Curl tries family addresses sequentially, happy eyeball
> timeout should be applied only for "good" connections that don't issue
> socket errors, and socket errors should be probably treated as a "family
> failure".
Hm, what if we also consider the first *error* on IPv6 as a signal to kick off
the IPv4 connect in addition to the timeout? See updated patch below.
> If Curl tried parallel connections for all addresses inside the family
> instead of doing it sequentially, then the idea to apply happy eyeballs
> timeout to the socket errors would work very well. Parallel connections
> would allow to fail the family much faster if something was wrong with it,
> and this would also be beneficial because the client would get the fastest
> connection inside the family - which is nice.
Yes, and I'm not against trying this out - this idea has been mentioned before
in HTTP implementor "circles". I would however imagine that it would need to
be capped at some value because some names will return MANY addresses so this
could be rather excessive, which could become a problem for apps who fire up
many transfers at once.
--- patch proposal v2
diff --git a/lib/connect.c b/lib/connect.c
index d9317f378..76e9d50dd 100644
--- a/lib/connect.c
+++ b/lib/connect.c
_at__at_ -931,18 +931,10 _at__at_ CURLcode Curl_is_connected(struct Curl_easy *data,
conn->timeoutms_per_addr[i]) {
infof(data, "After %" CURL_FORMAT_TIMEDIFF_T
"ms connect time, move on!\n", conn->timeoutms_per_addr[i]);
error = ETIMEDOUT;
}
-
- /* should we try another protocol family? */
- if(i == 0 && !conn->bits.parallel_connect &&
- (Curl_timediff(now, conn->connecttime) >=
- data->set.happy_eyeballs_timeout)) {
- conn->bits.parallel_connect = TRUE; /* starting now */
- trynextip(data, conn, sockindex, 1);
- }
}
else if(rc == CURL_CSELECT_OUT || conn->bits.tcp_fastopen) {
if(verifyconnect(conn->tempsock[i], &error)) {
/* we are connected with TCP, awesome! */
_at__at_ -1002,10 +994,20 _at__at_ CURLcode Curl_is_connected(struct Curl_easy *data,
conn->tempsock[other] == CURL_SOCKET_BAD)
/* the last attempt failed and no other sockets remain open */
result = status;
}
}
+
+ if(!rc || error) {
+ /* should we try another protocol family? */
+ if(i == 0 && !conn->bits.parallel_connect &&
+ (error || (Curl_timediff(now, conn->connecttime) >=
+ data->set.happy_eyeballs_timeout))) {
+ conn->bits.parallel_connect = TRUE; /* starting now */
+ trynextip(data, conn, sockindex, 1);
+ }
+ }
}
if(result &&
(conn->tempsock[0] == CURL_SOCKET_BAD) &&
(conn->tempsock[1] == CURL_SOCKET_BAD)) {
-- / daniel.haxx.se ------------------------------------------------------------------- Unsubscribe: https://cool.haxx.se/list/listinfo/curl-library Etiquette: https://curl.se/mail/etiquette.htmlReceived on 2021-06-07