connect: stop halving the remaining timeout when less than 600 ms left

When curl wants to connect to a host, it always has a TIMEOUT. The
maximum time it is allowed to spend until a connect is confirmed.

curl will try to connect to each of the IP adresses returned for the
host. Two loops, one for each IP family.

During the connect loop, while curl has more than one IP address left to
try within a single address family, curl has traditionally allowed (time
left/2) for *this* connect attempt. This, to not get stuck on the
initial addresses in case the timeout but still allow later addresses to
get attempted.

This has the downside that when users set a very short timeout and the
host has a large number of IP addresses, the effective result might be
that every attempt gets a little too short time.

This change stop doing the divided-by-two if the total time left is
below a threshold. This threshold is 600 milliseconds.

Closes #11693
This commit is contained in:
Daniel Stenberg 2023-08-18 13:41:16 +02:00
parent a181b4a053
commit 748da39b94
No known key found for this signature in database
GPG key ID: 5CC908FDB71E12C2

View file

@ -381,6 +381,11 @@ struct cf_he_ctx {
struct curltime started;
};
/* when there are more than one IP address left to use, this macro returns how
much of the given timeout to spend on *this* attempt */
#define TIMEOUT_LARGE 600
#define USETIME(ms) ((ms > TIMEOUT_LARGE) ? (ms / 2) : ms)
static CURLcode eyeballer_new(struct eyeballer **pballer,
cf_ip_connect_create *cf_create,
const struct Curl_addrinfo *addr,
@ -408,7 +413,7 @@ static CURLcode eyeballer_new(struct eyeballer **pballer,
baller->primary = primary;
baller->delay_ms = delay_ms;
baller->timeoutms = addr_next_match(baller->addr, baller->ai_family)?
timeout_ms / 2 : timeout_ms;
USETIME(timeout_ms) : timeout_ms;
baller->timeout_id = timeout_id;
baller->result = CURLE_COULDNT_CONNECT;
@ -501,7 +506,7 @@ static CURLcode baller_start(struct Curl_cfilter *cf,
while(baller->addr) {
baller->started = Curl_now();
baller->timeoutms = addr_next_match(baller->addr, baller->ai_family) ?
timeoutms / 2 : timeoutms;
USETIME(timeoutms) : timeoutms;
baller_initiate(cf, data, baller);
if(!baller->result)
break;