http3: initial support for OpenSSL 3.2 QUIC stack

- HTTP/3 for curl using OpenSSL's own QUIC stack together
  with nghttp3
- configure with `--with-openssl-quic` to enable curl to
  build this. This requires the nghttp3 library
- implementation with the following restrictions:
  * macOS has to use an unconnected UDP socket due to an
    issue in OpenSSL's datagram implementation
    See https://github.com/openssl/openssl/issues/23251
    This makes connections to non-reponsive servers hang.
  * GET requests will send the indicator that they have
    no body in a separate QUIC packet. This may result
    in processing delays or Transfer-Encodings on proxied
    requests
  * uploads that encounter blocks will use 100% cpu as
    detection of these flow control issue is not working
    (we have not figured out to pry that from OpenSSL).

Closes #12734
This commit is contained in:
Stefan Eissing 2024-01-18 13:07:07 +01:00 committed by Daniel Stenberg
parent f81a335e85
commit 0535f6ec71
No known key found for this signature in database
GPG key ID: 5CC908FDB71E12C2
15 changed files with 2698 additions and 16 deletions

View file

@ -78,6 +78,7 @@ LIB_VTLS_HFILES = \
LIB_VQUIC_CFILES = \
vquic/curl_msh3.c \
vquic/curl_ngtcp2.c \
vquic/curl_osslq.c \
vquic/curl_quiche.c \
vquic/vquic.c \
vquic/vquic-tls.c
@ -85,6 +86,7 @@ LIB_VQUIC_CFILES = \
LIB_VQUIC_HFILES = \
vquic/curl_msh3.h \
vquic/curl_ngtcp2.h \
vquic/curl_osslq.h \
vquic/curl_quiche.h \
vquic/vquic.h \
vquic/vquic_int.h \

View file

@ -1630,11 +1630,17 @@ static CURLcode cf_udp_setup_quic(struct Curl_cfilter *cf,
/* QUIC needs a connected socket, nonblocking */
DEBUGASSERT(ctx->sock != CURL_SOCKET_BAD);
#if defined(__APPLE__) && defined(USE_OPENSSL_QUIC)
(void)rc;
/* On macOS OpenSSL QUIC fails on connected sockets.
* see: <https://github.com/openssl/openssl/issues/23251> */
#else
rc = connect(ctx->sock, &ctx->addr.sa_addr, ctx->addr.addrlen);
if(-1 == rc) {
return socket_connect_result(data, ctx->r_ip, SOCKERRNO);
}
ctx->sock_connected = TRUE;
#endif
set_local_ip(cf, data);
CURL_TRC_CF(data, cf, "%s socket %" CURL_FORMAT_SOCKET_T
" connected: [%s:%d] -> [%s:%d]",

View file

@ -827,6 +827,7 @@ int getpwuid_r(uid_t uid, struct passwd *pwd, char *buf,
#endif
#if (defined(USE_NGTCP2) && defined(USE_NGHTTP3)) || \
(defined(USE_OPENSSL_QUIC) && defined(USE_NGHTTP3)) || \
defined(USE_QUICHE) || defined(USE_MSH3)
#define ENABLE_QUIC
#define USE_HTTP3

2239
lib/vquic/curl_osslq.c Normal file

File diff suppressed because it is too large Load diff

51
lib/vquic/curl_osslq.h Normal file
View file

@ -0,0 +1,51 @@
#ifndef HEADER_CURL_VQUIC_CURL_OSSLQ_H
#define HEADER_CURL_VQUIC_CURL_OSSLQ_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* SPDX-License-Identifier: curl
*
***************************************************************************/
#include "curl_setup.h"
#if defined(USE_OPENSSL_QUIC) && defined(USE_NGHTTP3)
#ifdef HAVE_NETINET_UDP_H
#include <netinet/udp.h>
#endif
struct Curl_cfilter;
#include "urldata.h"
void Curl_osslq_ver(char *p, size_t len);
CURLcode Curl_cf_osslq_create(struct Curl_cfilter **pcf,
struct Curl_easy *data,
struct connectdata *conn,
const struct Curl_addrinfo *ai);
bool Curl_conn_is_osslq(const struct Curl_easy *data,
const struct connectdata *conn,
int sockindex);
#endif
#endif /* HEADER_CURL_VQUIC_CURL_OSSLQ_H */

View file

@ -97,7 +97,11 @@ static CURLcode curl_ossl_init_ctx(struct quic_tls_ctx *ctx,
CURLcode result = CURLE_FAILED_INIT;
DEBUGASSERT(!ctx->ssl_ctx);
#ifdef USE_OPENSSL_QUIC
ctx->ssl_ctx = SSL_CTX_new(OSSL_QUIC_client_method());
#else
ctx->ssl_ctx = SSL_CTX_new(TLS_method());
#endif
if(!ctx->ssl_ctx) {
result = CURLE_OUT_OF_MEMORY;
goto out;
@ -216,7 +220,9 @@ static CURLcode curl_ossl_init_ssl(struct quic_tls_ctx *ctx,
SSL_set_app_data(ctx->ssl, user_data);
SSL_set_connect_state(ctx->ssl);
#ifndef USE_OPENSSL_QUIC
SSL_set_quic_use_legacy_codepoint(ctx->ssl, 0);
#endif
if(alpn)
SSL_set_alpn_protos(ctx->ssl, (const uint8_t *)alpn, (int)alpn_len);

View file

@ -46,6 +46,7 @@
#include "curl_trc.h"
#include "curl_msh3.h"
#include "curl_ngtcp2.h"
#include "curl_osslq.h"
#include "curl_quiche.h"
#include "rand.h"
#include "vquic.h"
@ -74,6 +75,8 @@ void Curl_quic_ver(char *p, size_t len)
{
#if defined(USE_NGTCP2) && defined(USE_NGHTTP3)
Curl_ngtcp2_ver(p, len);
#elif defined(USE_OPENSSL_QUIC) && defined(USE_NGHTTP3)
Curl_osslq_ver(p, len);
#elif defined(USE_QUICHE)
Curl_quiche_ver(p, len);
#elif defined(USE_MSH3)
@ -608,6 +611,8 @@ CURLcode Curl_cf_quic_create(struct Curl_cfilter **pcf,
DEBUGASSERT(transport == TRNSPRT_QUIC);
#if defined(USE_NGTCP2) && defined(USE_NGHTTP3)
return Curl_cf_ngtcp2_create(pcf, data, conn, ai);
#elif defined(USE_OPENSSL_QUIC) && defined(USE_NGHTTP3)
return Curl_cf_osslq_create(pcf, data, conn, ai);
#elif defined(USE_QUICHE)
return Curl_cf_quiche_create(pcf, data, conn, ai);
#elif defined(USE_MSH3)
@ -627,6 +632,8 @@ bool Curl_conn_is_http3(const struct Curl_easy *data,
{
#if defined(USE_NGTCP2) && defined(USE_NGHTTP3)
return Curl_conn_is_ngtcp2(data, conn, sockindex);
#elif defined(USE_OPENSSL_QUIC) && defined(USE_NGHTTP3)
return Curl_conn_is_osslq(data, conn, sockindex);
#elif defined(USE_QUICHE)
return Curl_conn_is_quiche(data, conn, sockindex);
#elif defined(USE_MSH3)