From cf6ba06cd445f1f4554701637d5bab581acfba98 Mon Sep 17 00:00:00 2001 From: dartraiden Date: Mon, 21 Apr 2025 09:33:29 +0300 Subject: libcurl: update to 8.13.0 --- libs/libcurl/src/cf-https-connect.c | 144 ++++++++++++++++++++---------------- 1 file changed, 82 insertions(+), 62 deletions(-) (limited to 'libs/libcurl/src/cf-https-connect.c') diff --git a/libs/libcurl/src/cf-https-connect.c b/libs/libcurl/src/cf-https-connect.c index ad1090f4a0..1cc4a03e49 100644 --- a/libs/libcurl/src/cf-https-connect.c +++ b/libs/libcurl/src/cf-https-connect.c @@ -175,7 +175,7 @@ static CURLcode cf_hc_baller_connect(struct cf_hc_baller *b, struct Curl_cfilter *save = cf->next; cf->next = b->cf; - b->result = Curl_conn_cf_connect(cf->next, data, FALSE, done); + b->result = Curl_conn_cf_connect(cf->next, data, done); b->cf = cf->next; /* it might mutate */ cf->next = save; return b->result; @@ -192,7 +192,7 @@ static void cf_hc_reset(struct Curl_cfilter *cf, struct Curl_easy *data) ctx->state = CF_HC_INIT; ctx->result = CURLE_OK; ctx->hard_eyeballs_timeout_ms = data->set.happy_eyeballs_timeout; - ctx->soft_eyeballs_timeout_ms = data->set.happy_eyeballs_timeout / 2; + ctx->soft_eyeballs_timeout_ms = data->set.happy_eyeballs_timeout / 4; } } @@ -263,8 +263,8 @@ static bool time_to_start_next(struct Curl_cfilter *cf, break; } if(i == idx) { - CURL_TRC_CF(data, cf, "all previous ballers have failed, time to start " - "baller %zu [%s]", idx, ctx->ballers[idx].name); + CURL_TRC_CF(data, cf, "all previous attempts failed, starting %s", + ctx->ballers[idx].name); return TRUE; } elapsed_ms = Curl_timediff(now, ctx->started); @@ -291,14 +291,13 @@ static bool time_to_start_next(struct Curl_cfilter *cf, static CURLcode cf_hc_connect(struct Curl_cfilter *cf, struct Curl_easy *data, - bool blocking, bool *done) + bool *done) { struct cf_hc_ctx *ctx = cf->ctx; struct curltime now; CURLcode result = CURLE_OK; size_t i, failed_ballers; - (void)blocking; if(cf->connected) { *done = TRUE; return CURLE_OK; @@ -316,7 +315,7 @@ static CURLcode cf_hc_connect(struct Curl_cfilter *cf, cf_hc_baller_init(&ctx->ballers[0], cf, data, cf->conn->transport); if(ctx->baller_count > 1) { Curl_expire(data, ctx->soft_eyeballs_timeout_ms, EXPIRE_ALPN_EYEBALLS); - CURL_TRC_CF(data, cf, "set expire for starting next baller in %ums", + CURL_TRC_CF(data, cf, "set next attempt to start in %ums", ctx->soft_eyeballs_timeout_ms); } ctx->state = CF_HC_CONNECT; @@ -352,7 +351,7 @@ static CURLcode cf_hc_connect(struct Curl_cfilter *cf, if(failed_ballers == ctx->baller_count) { /* all have failed. we give up */ - CURL_TRC_CF(data, cf, "connect, all failed"); + CURL_TRC_CF(data, cf, "connect, all attempts failed"); for(i = 0; i < ctx->baller_count; i++) { if(ctx->ballers[i].result) { result = ctx->ballers[i].result; @@ -451,7 +450,6 @@ static bool cf_hc_data_pending(struct Curl_cfilter *cf, if(cf->connected) return cf->next->cft->has_data_pending(cf->next, data); - CURL_TRC_CF((struct Curl_easy *)data, cf, "data_pending"); for(i = 0; i < ctx->baller_count; i++) if(cf_hc_baller_data_pending(&ctx->ballers[i], data)) return TRUE; @@ -607,8 +605,6 @@ static CURLcode cf_hc_create(struct Curl_cfilter **pcf, ctx->baller_count = alpn_count; result = Curl_cf_create(&cf, &Curl_cft_http_connect, ctx); - CURL_TRC_CF(data, cf, "created with %zu ALPNs -> %d", - ctx->baller_count, result); if(result) goto out; ctx = NULL; @@ -638,6 +634,17 @@ out: return result; } +static bool cf_https_alpns_contain(enum alpnid id, + enum alpnid *list, size_t len) +{ + size_t i; + for(i = 0; i < len; ++i) { + if(id == list[i]) + return TRUE; + } + return FALSE; +} + CURLcode Curl_cf_https_setup(struct Curl_easy *data, struct connectdata *conn, int sockindex, @@ -646,72 +653,85 @@ CURLcode Curl_cf_https_setup(struct Curl_easy *data, enum alpnid alpn_ids[2]; size_t alpn_count = 0; CURLcode result = CURLE_OK; + struct Curl_cfilter cf_fake, *cf = NULL; (void)sockindex; (void)remotehost; + /* we want to log for the filter before we create it, fake it. */ + memset(&cf_fake, 0, sizeof(cf_fake)); + cf_fake.cft = &Curl_cft_http_connect; + cf = &cf_fake; if(conn->bits.tls_enable_alpn) { - switch(data->state.httpwant) { - case CURL_HTTP_VERSION_NONE: - /* No preferences by transfer setup. Choose best defaults */ #ifdef USE_HTTPSRR - if(conn->dns_entry && conn->dns_entry->hinfo && - !conn->dns_entry->hinfo->no_def_alpn) { - size_t i, j; - for(i = 0; i < CURL_ARRAYSIZE(conn->dns_entry->hinfo->alpns) && - alpn_count < CURL_ARRAYSIZE(alpn_ids); ++i) { - bool present = FALSE; - enum alpnid alpn = conn->dns_entry->hinfo->alpns[i]; - for(j = 0; j < alpn_count; ++j) { - if(alpn == alpn_ids[j]) { - present = TRUE; - break; - } + /* Is there a HTTPSRR and if so, do its ALPNs it apply here? + * We are here after having selected a connection to a host+port and + * can no longer change that. Any HTTPSRR advice for other hosts and ports + * we need to ignore. */ + if(conn->dns_entry && conn->dns_entry->hinfo && + !conn->dns_entry->hinfo->no_def_alpn && /* ALPNs are defaults */ + (!conn->dns_entry->hinfo->target || /* for same host */ + !conn->dns_entry->hinfo->target[0] || + (conn->dns_entry->hinfo->target[0] == '.' && + !conn->dns_entry->hinfo->target[0])) && + (conn->dns_entry->hinfo->port < 0 || /* for same port */ + conn->dns_entry->hinfo->port == conn->remote_port)) { + size_t i; + for(i = 0; i < CURL_ARRAYSIZE(conn->dns_entry->hinfo->alpns) && + alpn_count < CURL_ARRAYSIZE(alpn_ids); ++i) { + enum alpnid alpn = conn->dns_entry->hinfo->alpns[i]; + if(cf_https_alpns_contain(alpn, alpn_ids, alpn_count)) + continue; + switch(alpn) { + case ALPN_h3: + if(Curl_conn_may_http3(data, conn)) + break; /* not possible */ + if(data->state.http_neg.allowed & CURL_HTTP_V3x) { + CURL_TRC_CF(data, cf, "adding h3 via HTTPS-RR"); + alpn_ids[alpn_count++] = alpn; } - if(!present) { - switch(alpn) { - case ALPN_h3: - if(Curl_conn_may_http3(data, conn)) - break; /* not possible */ - FALLTHROUGH(); - case ALPN_h2: - case ALPN_h1: - alpn_ids[alpn_count++] = alpn; - break; - default: /* ignore */ - break; - } + break; + case ALPN_h2: + if(data->state.http_neg.allowed & CURL_HTTP_V2x) { + CURL_TRC_CF(data, cf, "adding h2 via HTTPS-RR"); + alpn_ids[alpn_count++] = alpn; + } + break; + case ALPN_h1: + if(data->state.http_neg.allowed & CURL_HTTP_V1x) { + CURL_TRC_CF(data, cf, "adding h1 via HTTPS-RR"); + alpn_ids[alpn_count++] = alpn; } + break; + default: /* ignore */ + break; } } + } #endif - if(!alpn_count) - alpn_ids[alpn_count++] = ALPN_h2; - break; - case CURL_HTTP_VERSION_3ONLY: + + if((alpn_count < CURL_ARRAYSIZE(alpn_ids)) && + (data->state.http_neg.wanted & CURL_HTTP_V3x) && + !cf_https_alpns_contain(ALPN_h3, alpn_ids, alpn_count)) { result = Curl_conn_may_http3(data, conn); - if(result) /* cannot do it */ - goto out; - alpn_ids[alpn_count++] = ALPN_h3; - break; - case CURL_HTTP_VERSION_3: - /* We assume that silently not even trying H3 is ok here */ - if(Curl_conn_may_http3(data, conn) == CURLE_OK) + if(!result) { + CURL_TRC_CF(data, cf, "adding wanted h3"); alpn_ids[alpn_count++] = ALPN_h3; + } + else if(data->state.http_neg.wanted == CURL_HTTP_V3x) + goto out; /* only h3 allowed, not possible, error out */ + } + if((alpn_count < CURL_ARRAYSIZE(alpn_ids)) && + (data->state.http_neg.wanted & CURL_HTTP_V2x) && + !cf_https_alpns_contain(ALPN_h2, alpn_ids, alpn_count)) { + CURL_TRC_CF(data, cf, "adding wanted h2"); alpn_ids[alpn_count++] = ALPN_h2; - break; - case CURL_HTTP_VERSION_2_0: - case CURL_HTTP_VERSION_2TLS: - case CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE: - alpn_ids[alpn_count++] = ALPN_h2; - break; - case CURL_HTTP_VERSION_1_0: - case CURL_HTTP_VERSION_1_1: + } + else if((alpn_count < CURL_ARRAYSIZE(alpn_ids)) && + (data->state.http_neg.wanted & CURL_HTTP_V1x) && + !cf_https_alpns_contain(ALPN_h1, alpn_ids, alpn_count)) { + CURL_TRC_CF(data, cf, "adding wanted h1"); alpn_ids[alpn_count++] = ALPN_h1; - break; - default: - alpn_ids[alpn_count++] = ALPN_h2; - break; } } -- cgit v1.2.3