mirror of
https://github.com/curl/curl.git
synced 2026-08-24 12:33:37 +03:00
easy: reset errorbuf on eyeballing success
Any failf() that fill the errorbuf need to be forgotten once happy eyeballing finds a succssful winner. Because the errorbuf, once set, is not overwritten with future error information. Adds test_05_05 to verify. Reported-by: Tim Friedrich Brüggemann Fixes #20608 Closes #20613
This commit is contained in:
parent
36c2c7626f
commit
f1c9d5e484
7 changed files with 47 additions and 0 deletions
|
|
@ -58,6 +58,10 @@ only send 800.
|
|||
The percentage of send() calls that should be answered with EAGAIN at random.
|
||||
QUIC only.
|
||||
|
||||
## `CURL_DBG_SOCK_FAIL_IPV6`
|
||||
|
||||
Fail opening of sockets for the IPv6 address family.
|
||||
|
||||
## `CURL_DEBUG`
|
||||
|
||||
Trace logging behavior as an alternative to calling curl_global_trace(3).
|
||||
|
|
|
|||
|
|
@ -222,6 +222,8 @@ static CURLcode baller_connected(struct Curl_cfilter *cf,
|
|||
/* install the winning filter below this one. */
|
||||
cf->next = winner->cf;
|
||||
winner->cf = NULL;
|
||||
/* whatever errors where reported by ballers, clear our errorbuf */
|
||||
Curl_reset_fail(data);
|
||||
|
||||
#ifdef USE_NGHTTP2
|
||||
{
|
||||
|
|
|
|||
|
|
@ -427,6 +427,10 @@ evaluate:
|
|||
addr = cf_ai_iter_next(&bs->addr_iter);
|
||||
ai_family = bs->addr_iter.ai_family;
|
||||
}
|
||||
/* We are (re-)starting attempts. We are not interested in
|
||||
* keeping old failure information. The new attempt will either
|
||||
* succeed or persist new failure. */
|
||||
Curl_reset_fail(data);
|
||||
|
||||
if(addr) { /* try another address */
|
||||
result = cf_ip_attempt_new(&a, cf, data, addr, ai_family,
|
||||
|
|
@ -793,6 +797,8 @@ static CURLcode cf_ip_happy_connect(struct Curl_cfilter *cf,
|
|||
ctx->ballers.winner->cf = NULL;
|
||||
cf_ip_happy_ctx_clear(cf, data);
|
||||
Curl_expire_done(data, EXPIRE_HAPPY_EYEBALLS);
|
||||
/* whatever errors where reported by ballers, clear our errorbuf */
|
||||
Curl_reset_fail(data);
|
||||
|
||||
if(cf->conn->scheme->protocol & PROTO_FAMILY_SSH)
|
||||
Curl_pgrsTime(data, TIMER_APPCONNECT); /* we are connected already */
|
||||
|
|
|
|||
|
|
@ -332,6 +332,12 @@ static CURLcode socket_open(struct Curl_easy *data,
|
|||
}
|
||||
else {
|
||||
/* opensocket callback not set, so simply create the socket now */
|
||||
#ifdef DEBUGBUILD
|
||||
if((addr->family == AF_INET6) && getenv("CURL_DBG_SOCK_FAIL_IPV6")) {
|
||||
failf(data, "CURL_DBG_SOCK_FAIL_IPV6: failed to open socket");
|
||||
return CURLE_COULDNT_CONNECT;
|
||||
}
|
||||
#endif
|
||||
*sockfd = CURL_SOCKET(addr->family, addr->socktype, addr->protocol);
|
||||
if((*sockfd == CURL_SOCKET_BAD) && (SOCKERRNO == SOCKENOMEM))
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
|
|
|
|||
|
|
@ -194,6 +194,13 @@ void Curl_failf(struct Curl_easy *data, const char *fmt, ...)
|
|||
}
|
||||
}
|
||||
|
||||
void Curl_reset_fail(struct Curl_easy *data)
|
||||
{
|
||||
if(data->set.errorbuffer)
|
||||
data->set.errorbuffer[0] = 0;
|
||||
data->state.errorbuf = FALSE;
|
||||
}
|
||||
|
||||
#ifdef CURLVERBOSE
|
||||
struct curl_trc_feat Curl_trc_feat_multi = {
|
||||
"MULTI",
|
||||
|
|
|
|||
|
|
@ -61,6 +61,11 @@ void Curl_failf(struct Curl_easy *data,
|
|||
|
||||
#define failf Curl_failf
|
||||
|
||||
/* In case failf() reported into the errorbuf, clear it again.
|
||||
* This is used to clear information from happy eyeballing attempts
|
||||
* when ultimately a successful attempt was made. */
|
||||
void Curl_reset_fail(struct Curl_easy *data);
|
||||
|
||||
#define CURL_LOG_LVL_NONE 0
|
||||
#define CURL_LOG_LVL_INFO 1
|
||||
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@
|
|||
###########################################################################
|
||||
#
|
||||
import logging
|
||||
import os
|
||||
import pytest
|
||||
|
||||
from testenv import Env, CurlClient
|
||||
|
|
@ -123,3 +124,19 @@ class TestErrors:
|
|||
else:
|
||||
r.check_exit_code(0)
|
||||
r.check_response(http_status=200, count=count)
|
||||
|
||||
# Make a connect with a fail for '::1' and wrong certificate for '127.0.0.1'
|
||||
# The error message reported needs to be from the certificate.
|
||||
# verifies issue #20608
|
||||
@pytest.mark.parametrize("proto", Env.http_h1_h2_protos())
|
||||
def test_05_05_failed_peer(self, env: Env, proto, httpd, nghttpx):
|
||||
domain = f'invalid.{env.tld}'
|
||||
url = f'https://{domain}:{env.port_for(proto)}/'
|
||||
run_env = os.environ.copy()
|
||||
run_env['CURL_DBG_SOCK_FAIL_IPV6'] = '1'
|
||||
curl = CurlClient(env=env, run_env=run_env)
|
||||
r = curl.http_download(urls=[url], alpn_proto=proto, extra_args=[
|
||||
'--resolve', f'{domain}:{env.port_for(proto)}:::1,127.0.0.1',
|
||||
])
|
||||
assert r.exit_code == 60, f'{r}'
|
||||
assert r.stats[0]['errormsg'] != 'CURL_DBG_SOCK_FAIL_IPV6: failed to open socket'
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue