# renovate: datasource=github-tags depName=ngtcp2/nghttp3 versioning=semver registryUrl=https://github.com
nghttp3-version: 1.8.0
# renovate: datasource=github-tags depName=ngtcp2/ngtcp2 versioning=semver registryUrl=https://github.com
- ngtcp2-version: 1.11.0
+ ngtcp2-version: 1.12.0
# renovate: datasource=github-tags depName=nghttp2/nghttp2 versioning=semver registryUrl=https://github.com
nghttp2-version: 1.65.0
# renovate: datasource=github-tags depName=cloudflare/quiche versioning=semver registryUrl=https://github.com
runs-on: ubuntu-latest
steps:
+ - name: 'cache openssl'
+ uses: actions/cache@d4323d4df104b026a6aa633fdb11d772146be0bf # v4
+ id: cache-openssl-http3
+ env:
+ cache-name: cache-openssl-http3
+ with:
+ path: ~/openssl/build
+ key: ${{ runner.os }}-http3-build-${{ env.cache-name }}-${{ env.openssl-version }}
+
- name: 'cache quictls'
uses: actions/cache@d4323d4df104b026a6aa633fdb11d772146be0bf # v4
id: cache-quictls-no-deprecated
cache-name: cache-ngtcp2
with:
path: ~/ngtcp2/build
- key: ${{ runner.os }}-http3-build-${{ env.cache-name }}-${{ env.ngtcp2-version }}-${{ env.quictls-version }}-${{ env.gnutls-version }}-${{ env.wolfssl-version }}
+ key: ${{ runner.os }}-http3-build-${{ env.cache-name }}-${{ env.ngtcp2-version }}-${{ env.openssl-version }}-${{ env.quictls-version }}-${{ env.gnutls-version }}-${{ env.wolfssl-version }}
- name: 'cache nghttp2'
uses: actions/cache@d4323d4df104b026a6aa633fdb11d772146be0bf # v4
- id: settings
if: |
+ steps.cache-openssl-http3.outputs.cache-hit != 'true' ||
steps.cache-quictls-no-deprecated.outputs.cache-hit != 'true' ||
steps.cache-gnutls.outputs.cache-hit != 'true' ||
steps.cache-wolfssl.outputs.cache-hit != 'true' ||
echo 'CC=gcc-12' >> $GITHUB_ENV
echo 'CXX=g++-12' >> $GITHUB_ENV
+ - name: 'build openssl'
+ if: steps.cache-openssl-http3.outputs.cache-hit != 'true'
+ run: |
+ cd $HOME
+ git clone --quiet --depth=1 -b openssl-${{ env.openssl-version }} https://github.com/openssl/openssl
+ cd openssl
+ ./config --prefix=$PWD/build --libdir=lib no-makedepend no-apps no-docs no-tests
+ make
+ make -j1 install_sw
+
- name: 'build quictls'
if: steps.cache-quictls-no-deprecated.outputs.cache-hit != 'true'
run: |
- name: 'build ngtcp2'
if: steps.cache-ngtcp2.outputs.cache-hit != 'true'
+ # building twice to get crypto libs for ossl and quictls installed
run: |
cd $HOME
git clone --quiet --depth=1 -b v${{ env.ngtcp2-version }} https://github.com/ngtcp2/ngtcp2
cd ngtcp2
autoreconf -fi
./configure --disable-dependency-tracking --prefix=$PWD/build \
- PKG_CONFIG_PATH="$HOME/quictls/build/lib/pkgconfig:$HOME/gnutls/build/lib/pkgconfig:$HOME/wolfssl/build/lib/pkgconfig" \
+ PKG_CONFIG_PATH="$HOME/quictls/build/lib/pkgconfig" --enable-lib-only --with-quictls
+ make install
+ make clean
+ ./configure --disable-dependency-tracking --prefix=$PWD/build \
+ PKG_CONFIG_PATH="$HOME/openssl/build/lib/pkgconfig:$HOME/gnutls/build/lib/pkgconfig:$HOME/wolfssl/build/lib/pkgconfig" \
--enable-lib-only --with-openssl --with-gnutls --with-wolfssl
make install
fail-fast: false
matrix:
build:
+ - name: openssl
+ PKG_CONFIG_PATH: '$HOME/openssl/build/lib/pkgconfig:$HOME/nghttp3/build/lib/pkgconfig:$HOME/ngtcp2/build/lib/pkgconfig:$HOME/nghttp2/build/lib/pkgconfig'
+ configure: >-
+ LDFLAGS="-Wl,-rpath,$HOME/openssl/build/lib"
+ --with-ngtcp2=$HOME/ngtcp2/build --enable-warnings --enable-werror --enable-debug --disable-ntlm
+ --with-test-nghttpx="$HOME/nghttp2/build/bin/nghttpx"
+ --with-openssl=$HOME/openssl/build --enable-ssls-export
+ --with-libuv
+
- name: quictls
PKG_CONFIG_PATH: '$HOME/quictls/build/lib/pkgconfig:$HOME/nghttp3/build/lib/pkgconfig:$HOME/ngtcp2/build/lib/pkgconfig:$HOME/nghttp2/build/lib/pkgconfig'
configure: >-
-DCURL_USE_LIBUV=ON
- name: openssl-quic
- PKG_CONFIG_PATH: '$HOME/openssl/build/lib64/pkgconfig'
+ PKG_CONFIG_PATH: '$HOME/openssl/build/lib/pkgconfig'
configure: >-
- LDFLAGS="-Wl,-rpath,$HOME/openssl/build/lib64"
+ LDFLAGS="-Wl,-rpath,$HOME/openssl/build/lib"
--enable-warnings --enable-werror --enable-debug --disable-ntlm
--with-test-nghttpx="$HOME/nghttp2/build/bin/nghttpx"
--with-openssl=$HOME/openssl/build --with-openssl-quic
echo 'CC=gcc-12' >> $GITHUB_ENV
echo 'CXX=g++-12' >> $GITHUB_ENV
+ - name: 'cache openssl'
+ if: matrix.build.name == 'openssl' || matrix.build.name == 'openssl-quic'
+ uses: actions/cache@d4323d4df104b026a6aa633fdb11d772146be0bf # v4
+ id: cache-openssl-http3
+ env:
+ cache-name: cache-openssl-http3
+ with:
+ path: ~/openssl/build
+ key: ${{ runner.os }}-http3-build-${{ env.cache-name }}-${{ env.openssl-version }}
+ fail-on-cache-miss: true
+
- name: 'cache quictls'
uses: actions/cache@d4323d4df104b026a6aa633fdb11d772146be0bf # v4
id: cache-quictls-no-deprecated
cache-name: cache-ngtcp2
with:
path: ~/ngtcp2/build
- key: ${{ runner.os }}-http3-build-${{ env.cache-name }}-${{ env.ngtcp2-version }}-${{ env.quictls-version }}-${{ env.gnutls-version }}-${{ env.wolfssl-version }}
+ key: ${{ runner.os }}-http3-build-${{ env.cache-name }}-${{ env.ngtcp2-version }}-${{ env.openssl-version }}-${{ env.quictls-version }}-${{ env.gnutls-version }}-${{ env.wolfssl-version }}
fail-on-cache-miss: true
- name: 'cache nghttp2'
key: ${{ runner.os }}-http3-build-${{ env.cache-name }}-${{ env.nghttp2-version }}-${{ env.quictls-version }}-${{ env.ngtcp2-version }}-${{ env.nghttp3-version }}
fail-on-cache-miss: true
- - name: 'cache openssl'
- if: matrix.build.name == 'openssl-quic'
- uses: actions/cache@d4323d4df104b026a6aa633fdb11d772146be0bf # v4
- id: cache-openssl
- env:
- cache-name: cache-openssl
- with:
- path: ~/openssl/build
- key: ${{ runner.os }}-http3-build-${{ env.cache-name }}-${{ env.openssl-version }}
-
- - name: 'install openssl'
- if: matrix.build.name == 'openssl-quic' && steps.cache-openssl.outputs.cache-hit != 'true'
- run: |
- git clone --quiet --depth=1 -b openssl-${{ env.openssl-version }} https://github.com/openssl/openssl
- cd openssl
- ./config --prefix=$HOME/openssl/build no-makedepend no-apps no-docs no-tests
- make
- make -j1 install_sw
- cat exporters/openssl.pc
-
- name: 'cache quiche'
if: matrix.build.name == 'quiche'
uses: actions/cache@d4323d4df104b026a6aa633fdb11d772146be0bf # v4
fi
fi
-if test "x$USE_NGTCP2" = "x1" -a "x$OPENSSL_ENABLED" = "x1" -a "x$OPENSSL_IS_BORINGSSL" != "x1"; then
+if test "x$USE_NGTCP2" = "x1" -a "x$OPENSSL_ENABLED" = "x1" -a \
+ "x$OPENSSL_IS_BORINGSSL" != "x1" -a "x$OPENSSL_QUIC_API2" != "x1"; then
dnl backup the pre-ngtcp2_crypto_quictls variables
CLEANLDFLAGS="$LDFLAGS"
CLEANLDFLAGSPC="$LDFLAGSPC"
fi
fi
+if test "x$USE_NGTCP2" = "x1" -a "x$OPENSSL_ENABLED" = "x1" -a \
+ "x$OPENSSL_IS_BORINGSSL" != "x1" -a "x$OPENSSL_QUIC_API2" = "x1"; then
+ dnl backup the pre-ngtcp2_crypto_ossl variables
+ CLEANLDFLAGS="$LDFLAGS"
+ CLEANLDFLAGSPC="$LDFLAGSPC"
+ CLEANCPPFLAGS="$CPPFLAGS"
+ CLEANLIBS="$LIBS"
+
+ CURL_CHECK_PKGCONFIG(libngtcp2_crypto_ossl, $want_tcp2_path)
+
+ if test "$PKGCONFIG" != "no"; then
+ LIB_NGTCP2_CRYPTO_QUICTLS=`CURL_EXPORT_PCDIR([$want_tcp2_path])
+ $PKGCONFIG --libs-only-l libngtcp2_crypto_ossl`
+ AC_MSG_NOTICE([-l is $LIB_NGTCP2_CRYPTO_QUICTLS])
+
+ CPP_NGTCP2_CRYPTO_QUICTLS=`CURL_EXPORT_PCDIR([$want_tcp2_path]) dnl
+ $PKGCONFIG --cflags-only-I libngtcp2_crypto_ossl`
+ AC_MSG_NOTICE([-I is $CPP_NGTCP2_CRYPTO_QUICTLS])
+
+ LD_NGTCP2_CRYPTO_QUICTLS=`CURL_EXPORT_PCDIR([$want_tcp2_path])
+ $PKGCONFIG --libs-only-L libngtcp2_crypto_ossl`
+ AC_MSG_NOTICE([-L is $LD_NGTCP2_CRYPTO_QUICTLS])
+
+ LDFLAGS="$LDFLAGS $LD_NGTCP2_CRYPTO_QUICTLS"
+ LDFLAGSPC="$LDFLAGSPC $LD_NGTCP2_CRYPTO_QUICTLS"
+ CPPFLAGS="$CPPFLAGS $CPP_NGTCP2_CRYPTO_QUICTLS"
+ LIBS="$LIB_NGTCP2_CRYPTO_QUICTLS $LIBS"
+
+ if test "x$cross_compiling" != "xyes"; then
+ DIR_NGTCP2_CRYPTO_QUICTLS=`echo $LD_NGTCP2_CRYPTO_QUICTLS | $SED -e 's/^-L//'`
+ fi
+ AC_CHECK_LIB(ngtcp2_crypto_ossl, ngtcp2_crypto_recv_client_initial_cb,
+ [
+ AC_CHECK_HEADERS(ngtcp2/ngtcp2_crypto.h,
+ USE_NGTCP2=1
+ CURL_LIBRARY_PATH="$CURL_LIBRARY_PATH:$DIR_NGTCP2_CRYPTO_QUICTLS"
+ export CURL_LIBRARY_PATH
+ AC_MSG_NOTICE([Added $DIR_NGTCP2_CRYPTO_QUICTLS to CURL_LIBRARY_PATH])
+ LIBCURL_PC_REQUIRES_PRIVATE="$LIBCURL_PC_REQUIRES_PRIVATE libngtcp2_crypto_ossl"
+ AC_DEFINE(OPENSSL_QUIC_API2, 1, [openssl with new QUIC API])
+ )
+ ],
+ dnl not found, revert back to clean variables
+ LDFLAGS=$CLEANLDFLAGS
+ LDFLAGSPC=$CLEANLDFLAGSPC
+ CPPFLAGS=$CLEANCPPFLAGS
+ LIBS=$CLEANLIBS
+ )
+
+ else
+ dnl no ngtcp2_crypto_ossl pkg-config found, deal with it
+ if test X"$want_tcp2" != Xdefault; then
+ dnl To avoid link errors, we do not allow --with-ngtcp2 without
+ dnl a pkgconfig file
+ AC_MSG_ERROR([--with-ngtcp2 was specified but could not find ngtcp2_crypto_ossl pkg-config file.])
+ fi
+ fi
+fi
+
if test "x$USE_NGTCP2" = "x1" -a "x$OPENSSL_ENABLED" = "x1" -a "x$OPENSSL_IS_BORINGSSL" = "x1"; then
dnl backup the pre-ngtcp2_crypto_boringssl variables
CLEANLDFLAGS="$LDFLAGS"
The build examples use `$NGHTTP3_VERSION` and `$NGTCP2_VERSION` as placeholders
for the version you build.
+## Build with OpenSSL
+
+OpenSSL v3.5.0+ offers APIs for integration with *ngtcp2* v1.12.0+. Earlier
+versions do not work.
+
+Build OpenSSL (version 3.5.0 or newer):
+
+ % git clone --quiet --depth=1 -b openssl-$OPENSSL_VERSION https://github.com/openssl/openssl
+ % cd openssl
+ % ./config --prefix=<somewhere1> --libdir=lib
+ % make
+ % make install
+
+Build nghttp3:
+
+ % cd ..
+ % git clone -b $NGHTTP3_VERSION https://github.com/ngtcp2/nghttp3
+ % cd nghttp3
+ % git submodule update --init
+ % autoreconf -fi
+ % ./configure --prefix=<somewhere2> --enable-lib-only
+ % make
+ % make install
+
+Build ngtcp2:
+
+ % cd ..
+ % git clone -b $NGTCP2_VERSION https://github.com/ngtcp2/ngtcp2
+ % cd ngtcp2
+ % autoreconf -fi
+ % ./configure PKG_CONFIG_PATH=<somewhere1>/lib/pkgconfig:<somewhere2>/lib/pkgconfig LDFLAGS="-Wl,-rpath,<somewhere1>/lib" --prefix=<somewhere3> --enable-lib-only --with-openssl
+ % make
+ % make install
+
+Build curl:
+
+ % cd ..
+ % git clone https://github.com/curl/curl
+ % cd curl
+ % autoreconf -fi
+ % LDFLAGS="-Wl,-rpath,<somewhere1>/lib" ./configure --with-openssl=<somewhere1> --with-nghttp3=<somewhere2> --with-ngtcp2=<somewhere3>
+ % make
+ % make install
+
## Build with quictls
OpenSSL does not offer the required APIs for building a QUIC client. You need
% git clone --depth 1 -b openssl-3.1.4+quic https://github.com/quictls/openssl
% cd openssl
- % ./config enable-tls1_3 --prefix=<somewhere1>
+ % ./config enable-tls1_3 --prefix=<somewhere1> --libdir=lib
% make
% make install
% make
% make install
-For OpenSSL 3.0.0 or later builds on Linux for x86_64 architecture, substitute all occurrences of "/lib" with "/lib64"
-
## Build with GnuTLS
Build GnuTLS:
#include "transfer.h"
#include "vtls/vtls.h"
#include "vtls/vtls_scache.h"
+#include "vquic/vquic.h"
#include "url.h"
#include "getinfo.h"
#include "hostip.h"
goto fail;
}
+ if(!Curl_vquic_init()) {
+ DEBUGF(fprintf(stderr, "Error: Curl_vquic_init failed\n"));
+ goto fail;
+ }
+
if(Curl_win32_init(flags)) {
DEBUGF(fprintf(stderr, "Error: win32_init failed\n"));
goto fail;
#include <openssl/err.h>
#if defined(OPENSSL_IS_BORINGSSL) || defined(OPENSSL_IS_AWSLC)
#include <ngtcp2/ngtcp2_crypto_boringssl.h>
+#elif defined(OPENSSL_QUIC_API2)
+#include <ngtcp2/ngtcp2_crypto_ossl.h>
#else
#include <ngtcp2/ngtcp2_crypto_quictls.h>
#endif
struct cf_quic_ctx q;
struct ssl_peer peer;
struct curl_tls_ctx tls;
+#ifdef OPENSSL_QUIC_API2
+ ngtcp2_crypto_ossl_ctx *ossl_ctx;
+#endif
ngtcp2_path connected_path;
ngtcp2_conn *qconn;
ngtcp2_cid dcid;
ctx->qlogfd = -1;
Curl_vquic_tls_cleanup(&ctx->tls);
vquic_ctx_free(&ctx->q);
- if(ctx->h3conn)
+ if(ctx->h3conn) {
nghttp3_conn_del(ctx->h3conn);
- if(ctx->qconn)
+ ctx->h3conn = NULL;
+ }
+ if(ctx->qconn) {
ngtcp2_conn_del(ctx->qconn);
+ ctx->qconn = NULL;
+ }
+#ifdef OPENSSL_QUIC_API2
+ if(ctx->ossl_ctx) {
+ ngtcp2_crypto_ossl_ctx_del(ctx->ossl_ctx);
+ ctx->ossl_ctx = NULL;
+ }
+#endif
ctx->call_data = save;
}
{
CURL_TRC_CF(data, cf, "destroy");
if(cf->ctx) {
+ cf_ngtcp2_close(cf, data);
cf_ngtcp2_ctx_free(cf->ctx);
cf->ctx = NULL;
}
failf(data, "ngtcp2_crypto_boringssl_configure_client_context failed");
return CURLE_FAILED_INIT;
}
+#elif defined(OPENSSL_QUIC_API2)
+ /* nothing to do */
#else
if(ngtcp2_crypto_quictls_configure_client_context(ctx->ossl.ssl_ctx) != 0) {
failf(data, "ngtcp2_crypto_quictls_configure_client_context failed");
if(rc)
return CURLE_QUIC_CONNECT_ERROR;
+ ctx->conn_ref.get_conn = get_conn;
+ ctx->conn_ref.user_data = cf;
+
result = Curl_vquic_tls_init(&ctx->tls, cf, data, &ctx->peer, &ALPN_SPEC_H3,
cf_ngtcp2_tls_ctx_setup, &ctx->tls,
&ctx->conn_ref,
if(result)
return result;
-#ifdef USE_OPENSSL
+#if defined(USE_OPENSSL) && defined(OPENSSL_QUIC_API2)
+ if(ngtcp2_crypto_ossl_ctx_new(&ctx->ossl_ctx, ctx->tls.ossl.ssl) != 0) {
+ failf(data, "ngtcp2_crypto_ossl_ctx_new failed");
+ return CURLE_FAILED_INIT;
+ }
+ ngtcp2_conn_set_tls_native_handle(ctx->qconn, ctx->ossl_ctx);
+ if(ngtcp2_crypto_ossl_configure_client_session(ctx->tls.ossl.ssl) != 0) {
+ failf(data, "ngtcp2_crypto_ossl_configure_client_session failed");
+ return CURLE_FAILED_INIT;
+ }
+#elif defined(USE_OPENSSL)
SSL_set_quic_use_legacy_codepoint(ctx->tls.ossl.ssl, 0);
ngtcp2_conn_set_tls_native_handle(ctx->qconn, ctx->tls.ossl.ssl);
#elif defined(USE_GNUTLS)
ngtcp2_ccerr_default(&ctx->last_error);
- ctx->conn_ref.get_conn = get_conn;
- ctx->conn_ref.user_data = cf;
-
return CURLE_OK;
}
#endif
#include <ngtcp2/ngtcp2_crypto.h>
+#ifdef OPENSSL_QUIC_API2
+#include <ngtcp2/ngtcp2_crypto_ossl.h>
+#endif
#include <nghttp3/nghttp3.h>
#ifdef USE_OPENSSL
#include <openssl/ssl.h>
#define NW_SEND_CHUNKS 2
+int Curl_vquic_init(void)
+{
+#if defined(USE_NGTCP2) && defined(OPENSSL_QUIC_API2)
+ if(ngtcp2_crypto_ossl_init())
+ return 0;
+#endif
+
+ return 1;
+}
+
void Curl_quic_ver(char *p, size_t len)
{
#if defined(USE_NGTCP2) && defined(USE_NGHTTP3)
struct Curl_addrinfo;
void Curl_quic_ver(char *p, size_t len);
+int Curl_vquic_init(void);
CURLcode Curl_qlogdir(struct Curl_easy *data,
unsigned char *scid,
extern struct Curl_cftype Curl_cft_http3;
+#else
+#define Curl_vquic_init() 1
#endif /* !USE_HTTP3 */
CURLcode Curl_conn_may_http3(struct Curl_easy *data,
#define OSSL_PACKAGE "BoringSSL"
#elif defined(OPENSSL_IS_AWSLC)
#define OSSL_PACKAGE "AWS-LC"
-#elif (defined(USE_NGTCP2) && defined(USE_NGHTTP3)) || defined(USE_MSH3)
+#elif (defined(USE_NGTCP2) && defined(USE_NGHTTP3) && \
+ !defined(OPENSSL_QUIC_API2)) || defined(USE_MSH3)
#define OSSL_PACKAGE "quictls"
#else
#define OSSL_PACKAGE "OpenSSL"
fi
dnl is this OpenSSL (fork) providing the original QUIC API?
- AC_CHECK_FUNCS([SSL_set_quic_use_legacy_codepoint],
- [QUIC_ENABLED=yes])
+ AC_CHECK_FUNCS([SSL_set_quic_use_legacy_codepoint], [QUIC_ENABLED=yes])
if test "$QUIC_ENABLED" = "yes"; then
AC_MSG_NOTICE([OpenSSL fork speaks QUIC API])
else
- AC_MSG_NOTICE([OpenSSL version does not speak QUIC API])
+ AC_CHECK_FUNCS([SSL_set_quic_tls_cbs], [QUIC_ENABLED=yes])
+ if test "$QUIC_ENABLED" = "yes"; then
+ AC_MSG_NOTICE([OpenSSL with QUIC APIv2])
+ OPENSSL_QUIC_API2=1
+ else
+ AC_MSG_NOTICE([OpenSSL version does not speak any known QUIC API])
+ fi
fi
if test "$OPENSSL_ENABLED" = "1"; then