diff options
Diffstat (limited to 'libs/libcurl/src/cf-https-connect.c')
-rw-r--r-- | libs/libcurl/src/cf-https-connect.c | 144 |
1 files changed, 82 insertions, 62 deletions
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;
}
}
|