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 @@ -931,18 +931,10 @@ 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! */ @@ -1002,10 +994,20 @@ 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.html