mirror of
https://github.com/curl/curl.git
synced 2026-04-15 00:31:41 +03:00
http: version negotiation
Translate the `data->set.httpwant` which is one of the consts from the public API (CURL_HTTP_VERSION_*) into a major version mask plus additional flags for internal handling. `Curl_http_neg_init()` does the translation and flags setting in http.c, using new internal consts CURL_HTTP_V1x, CURL_HTTP_V2x and CURL_HTTP_V3x for the major versions. The flags are - only_10: when the application explicity asked fro HTTP/1.0 - h2_upgrade: when the application asks for upgrading 1.1 to 2. - h2_prior_knowledge: when directly talking h2 without ALPN - accept_09: when a HTTP/0.9 response is acceptable. The Alt-Svc and HTTPS RR redirections from one ALPN to another obey the allowed major versions. If a transfer has only h3 enabled, Alt-Svc redirection to h2 is ignored. This is the current implementation. It can be debated if Alt-Svc should be able to override the allowed major versions. Added test_12_06 to verify the current restriction. Closes #16100
This commit is contained in:
parent
f7fcbb8127
commit
db72b8d4d0
13 changed files with 255 additions and 190 deletions
|
|
@ -651,67 +651,56 @@ CURLcode Curl_cf_https_setup(struct Curl_easy *data,
|
|||
(void)remotehost;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
if(present)
|
||||
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)
|
||||
alpn_ids[alpn_count++] = alpn;
|
||||
break;
|
||||
case ALPN_h2:
|
||||
if(data->state.http_neg.allowed & CURL_HTTP_V2x)
|
||||
alpn_ids[alpn_count++] = alpn;
|
||||
break;
|
||||
case ALPN_h1:
|
||||
if(data->state.http_neg.allowed & CURL_HTTP_V1x)
|
||||
alpn_ids[alpn_count++] = alpn;
|
||||
break;
|
||||
default: /* ignore */
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if(!alpn_count)
|
||||
|
||||
if(!alpn_count) {
|
||||
if(data->state.http_neg.allowed & CURL_HTTP_V3x) {
|
||||
result = Curl_conn_may_http3(data, conn);
|
||||
if(!result)
|
||||
alpn_ids[alpn_count++] = ALPN_h3;
|
||||
else if(data->state.http_neg.allowed == CURL_HTTP_V3x)
|
||||
goto out; /* only h3 allowed, not possible, error out */
|
||||
}
|
||||
if(data->state.http_neg.allowed & CURL_HTTP_V2x)
|
||||
alpn_ids[alpn_count++] = ALPN_h2;
|
||||
break;
|
||||
case CURL_HTTP_VERSION_3ONLY:
|
||||
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)
|
||||
alpn_ids[alpn_count++] = ALPN_h3;
|
||||
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:
|
||||
alpn_ids[alpn_count++] = ALPN_h1;
|
||||
break;
|
||||
default:
|
||||
alpn_ids[alpn_count++] = ALPN_h2;
|
||||
break;
|
||||
else if(data->state.http_neg.allowed & CURL_HTTP_V1x)
|
||||
alpn_ids[alpn_count++] = ALPN_h1;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue