alt-svc: more flexibility on same destination

When the Alt-Svc points to the same host and port, add the destination
ALPN to the `wanted` versions and set it also as the `preferred` version
in negotiations.

This allows Alt-Svc for h3 to point to h2 and have it tried first. Also,
this allows Alt-Svc to say http/1.1 is preferred and changes the ALPN
protocol ordering for the TLS handshake.

Add tests in various combination to verify this works.

Reported-by: yushicheng7788 on github
Fixes #19740
Closes #19874
This commit is contained in:
Stefan Eissing 2025-12-08 13:36:19 +01:00 committed by Daniel Stenberg
parent f450f3801b
commit 5ed7b5b01b
No known key found for this signature in database
GPG key ID: 5CC908FDB71E12C2
9 changed files with 135 additions and 49 deletions

View file

@ -710,6 +710,31 @@ CURLcode Curl_cf_https_setup(struct Curl_easy *data,
}
#endif
/* Add preferred HTTP version ALPN first */
if(data->state.http_neg.preferred &&
(alpn_count < CURL_ARRAYSIZE(alpn_ids)) &&
(data->state.http_neg.preferred & data->state.http_neg.allowed)) {
enum alpnid alpn_pref = ALPN_none;
switch(data->state.http_neg.preferred) {
case CURL_HTTP_V3x:
if(!Curl_conn_may_http3(data, conn, conn->transport_wanted))
alpn_pref = ALPN_h3;
break;
case CURL_HTTP_V2x:
alpn_pref = ALPN_h2;
break;
case CURL_HTTP_V1x:
alpn_pref = ALPN_h1;
break;
default:
break;
}
if(alpn_pref &&
!cf_https_alpns_contain(alpn_pref, alpn_ids, alpn_count)) {
alpn_ids[alpn_count++] = alpn_pref;
}
}
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)) {