From 91138b014d960d2ef6ce9cd0ca237d0220b2458d Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Tue, 24 Jun 2025 08:34:58 +0200 Subject: [PATCH] vquic: drop msh3 It has never been properly functional in curl while there are several alternatives that are. Closes #17729 --- .github/labeler.yml | 1 - .github/scripts/cmp-config.pl | 1 - .github/workflows/linux.yml | 35 +- CMake/FindMSH3.cmake | 72 --- CMakeLists.txt | 28 +- Makefile.am | 1 - configure.ac | 95 +-- docs/DEPRECATE.md | 15 +- docs/HTTP3.md | 62 +- docs/INSTALL-CMAKE.md | 5 - lib/Makefile.inc | 2 - lib/cf-socket.c | 10 +- lib/cf-socket.h | 8 - lib/config-os400.h | 4 - lib/curl_config.h.cmake | 3 - lib/curl_setup.h | 2 +- lib/http.h | 4 - lib/socketpair.c | 2 + lib/socketpair.h | 5 +- lib/vquic/curl_msh3.c | 1095 -------------------------------- lib/vquic/curl_msh3.h | 46 -- lib/vquic/vquic.c | 5 - lib/vtls/openssl.c | 4 +- tests/http/scorecard.py | 2 +- tests/http/test_02_download.py | 8 - tests/http/test_03_goaway.py | 2 - tests/http/test_05_errors.py | 4 - tests/http/test_07_upload.py | 46 -- tests/http/test_08_caddy.py | 16 - winbuild/Makefile.vc | 22 - winbuild/MakefileBuild.vc | 27 - winbuild/README.md | 2 - 32 files changed, 22 insertions(+), 1612 deletions(-) delete mode 100644 CMake/FindMSH3.cmake delete mode 100644 lib/vquic/curl_msh3.c delete mode 100644 lib/vquic/curl_msh3.h diff --git a/.github/labeler.yml b/.github/labeler.yml index 696d77ee03..42a891e623 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -282,7 +282,6 @@ HTTP/3: .github/workflows/ngtcp2*,\ .github/workflows/quiche*,\ .github/workflows/osslq*,\ - CMake/FindMSH3.cmake,\ CMake/FindNGHTTP3.cmake,\ CMake/FindNGTCP2.cmake,\ docs/HTTP3.md,\ diff --git a/.github/scripts/cmp-config.pl b/.github/scripts/cmp-config.pl index 930168c812..cb47870fe3 100755 --- a/.github/scripts/cmp-config.pl +++ b/.github/scripts/cmp-config.pl @@ -55,7 +55,6 @@ my %remove = ( '#define HAVE_LIBSSL 1' => 1, '#define HAVE_LIBWOLFSSH' => 1, '#define HAVE_LIBZSTD 1' => 1, - '#define HAVE_MSH3_H 1' => 1, '#define HAVE_NGHTTP2_NGHTTP2_H 1' => 1, '#define HAVE_NGHTTP3_NGHTTP3_H 1' => 1, '#define HAVE_NGTCP2_NGTCP2_CRYPTO_H 1' => 1, diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml index 5555afd856..2044060ce2 100644 --- a/.github/workflows/linux.yml +++ b/.github/workflows/linux.yml @@ -49,8 +49,6 @@ env: WOLFSSH_VERSION: 1.4.19 # renovate: datasource=github-tags depName=Mbed-TLS/mbedtls versioning=semver registryUrl=https://github.com MBEDTLS_VERSION: 3.6.4 - # renovate: datasource=github-tags depName=nibanks/msh3 versioning=semver registryUrl=https://github.com - MSH3_VERSION: 0.6.0 # renovate: datasource=github-tags depName=awslabs/aws-lc versioning=semver registryUrl=https://github.com AWSLC_VERSION: 1.56.0 # handled in renovate.json @@ -127,19 +125,7 @@ jobs: install_steps: skipall generate: -DCURL_USE_MBEDTLS=ON -DENABLE_DEBUG=ON -DCURL_USE_PKGCONFIG=OFF -DCURL_COMPLETION_FISH=ON -DCURL_COMPLETION_ZSH=ON - - name: 'msh3' - install_packages: zlib1g-dev - install_steps: quictls msh3 - LDFLAGS: -Wl,-rpath,/home/runner/msh3/lib -Wl,-rpath,/home/runner/quictls/lib - configure: --with-msh3=/home/runner/msh3 --with-openssl=/home/runner/quictls --enable-debug - - - name: 'msh3' - install_packages: zlib1g-dev - install_steps: quictls msh3 skipall - PKG_CONFIG_PATH: /home/runner/msh3/lib/pkgconfig # Broken as of v0.6.0 - generate: -DOPENSSL_ROOT_DIR=/home/runner/quictls -DUSE_MSH3=ON -DMSH3_INCLUDE_DIR=/home/runner/msh3/include -DMSH3_LIBRARY=/home/runner/msh3/lib/libmsh3.so -DENABLE_DEBUG=ON - - - name: 'awslc' + - name: awslc install_packages: zlib1g-dev install_steps: awslc pytest configure: LDFLAGS=-Wl,-rpath,/home/runner/awslc/lib --with-openssl=/home/runner/awslc --enable-ech @@ -500,25 +486,6 @@ jobs: make make -j1 install_sw - - name: 'cache msh3' - if: ${{ contains(matrix.build.install_steps, 'msh3') }} - uses: actions/cache@d4323d4df104b026a6aa633fdb11d772146be0bf # v4 - id: cache-msh3 - env: - cache-name: cache-msh3 - with: - path: ~/msh3 - key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ env.MSH3_VERSION }} - - - name: 'build msh3' - if: ${{ contains(matrix.build.install_steps, 'msh3') && steps.cache-msh3.outputs.cache-hit != 'true' }} - run: | - git clone --quiet --depth=1 -b "v${MSH3_VERSION}" --recursive https://github.com/nibanks/msh3 - cd msh3 - cmake -B . -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=/home/runner/msh3 - cmake --build . - cmake --install . - - name: 'cache awslc' if: ${{ contains(matrix.build.install_steps, 'awslc') }} uses: actions/cache@d4323d4df104b026a6aa633fdb11d772146be0bf # v4 diff --git a/CMake/FindMSH3.cmake b/CMake/FindMSH3.cmake deleted file mode 100644 index da38d45823..0000000000 --- a/CMake/FindMSH3.cmake +++ /dev/null @@ -1,72 +0,0 @@ -#*************************************************************************** -# _ _ ____ _ -# Project ___| | | | _ \| | -# / __| | | | |_) | | -# | (__| |_| | _ <| |___ -# \___|\___/|_| \_\_____| -# -# Copyright (C) Daniel Stenberg, , 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 -# -########################################################################### -# Find the msh3 library -# -# Input variables: -# -# - `MSH3_INCLUDE_DIR`: The msh3 include directory. -# - `MSH3_LIBRARY`: Path to `msh3` library. -# -# Result variables: -# -# - `MSH3_FOUND`: System has msh3. -# - `MSH3_INCLUDE_DIRS`: The msh3 include directories. -# - `MSH3_LIBRARIES`: The msh3 library names. -# - `MSH3_LIBRARY_DIRS`: The msh3 library directories. -# - `MSH3_PC_REQUIRES`: The msh3 pkg-config packages. -# - `MSH3_CFLAGS`: Required compiler flags. -# - `MSH3_VERSION`: Version of msh3. - -set(MSH3_PC_REQUIRES "libmsh3") - -if(CURL_USE_PKGCONFIG AND - NOT DEFINED MSH3_INCLUDE_DIR AND - NOT DEFINED MSH3_LIBRARY) - find_package(PkgConfig QUIET) - pkg_check_modules(MSH3 ${MSH3_PC_REQUIRES}) -endif() - -if(MSH3_FOUND) - string(REPLACE ";" " " MSH3_CFLAGS "${MSH3_CFLAGS}") - message(STATUS "Found MSH3 (via pkg-config): ${MSH3_INCLUDE_DIRS} (found version \"${MSH3_VERSION}\")") -else() - set(MSH3_PC_REQUIRES "") # Depend on pkg-config only when found via pkg-config - - find_path(MSH3_INCLUDE_DIR NAMES "msh3.h") - find_library(MSH3_LIBRARY NAMES "msh3") - - include(FindPackageHandleStandardArgs) - find_package_handle_standard_args(MSH3 - REQUIRED_VARS - MSH3_INCLUDE_DIR - MSH3_LIBRARY - ) - - if(MSH3_FOUND) - set(MSH3_INCLUDE_DIRS ${MSH3_INCLUDE_DIR}) - set(MSH3_LIBRARIES ${MSH3_LIBRARY}) - endif() - - mark_as_advanced(MSH3_INCLUDE_DIR MSH3_LIBRARY) -endif() diff --git a/CMakeLists.txt b/CMakeLists.txt index 8d6a475f53..d9d4acf160 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1162,30 +1162,8 @@ if(USE_QUICHE) endif() endif() -option(USE_MSH3 "Use msh3/msquic library for HTTP/3 support" OFF) -if(USE_MSH3) - if(USE_NGTCP2 OR USE_QUICHE) - message(FATAL_ERROR "Only one HTTP/3 backend can be selected") - endif() - if(NOT WIN32) - if(NOT USE_OPENSSL) - message(FATAL_ERROR "msh3/msquic requires OpenSSL fork with QUIC API") - endif() - curl_openssl_check_quic() - endif() - find_package(MSH3 REQUIRED) - list(APPEND CURL_LIBS ${MSH3_LIBRARIES}) - list(APPEND CURL_LIBDIRS ${MSH3_LIBRARY_DIRS}) - list(APPEND LIBCURL_PC_REQUIRES_PRIVATE ${MSH3_PC_REQUIRES}) - include_directories(SYSTEM ${MSH3_INCLUDE_DIRS}) - link_directories(${MSH3_LIBRARY_DIRS}) - if(MSH3_CFLAGS) - string(APPEND CMAKE_C_FLAGS " ${MSH3_CFLAGS}") - endif() -endif() - if(USE_OPENSSL_QUIC) - if(USE_NGTCP2 OR USE_QUICHE OR USE_MSH3) + if(USE_NGTCP2 OR USE_QUICHE) message(FATAL_ERROR "Only one HTTP/3 backend can be selected") endif() find_package(OpenSSL 3.3.0 REQUIRED) @@ -1202,7 +1180,7 @@ if(USE_OPENSSL_QUIC) endif() endif() -if(CURL_WITH_MULTI_SSL AND (USE_NGTCP2 OR USE_QUICHE OR USE_MSH3 OR USE_OPENSSL_QUIC)) +if(CURL_WITH_MULTI_SSL AND (USE_NGTCP2 OR USE_QUICHE OR USE_OPENSSL_QUIC)) message(FATAL_ERROR "MultiSSL cannot be enabled with HTTP/3 and vice versa.") endif() @@ -2169,7 +2147,7 @@ curl_add_if("NTLM" NOT CURL_DISABLE_NTLM AND (_use_curl_ntlm_core OR USE_WINDOWS_SSPI)) curl_add_if("TLS-SRP" USE_TLS_SRP) curl_add_if("HTTP2" USE_NGHTTP2) -curl_add_if("HTTP3" USE_NGTCP2 OR USE_QUICHE OR USE_MSH3 OR USE_OPENSSL_QUIC) +curl_add_if("HTTP3" USE_NGTCP2 OR USE_QUICHE OR USE_OPENSSL_QUIC) curl_add_if("MultiSSL" CURL_WITH_MULTI_SSL) curl_add_if("HTTPS-proxy" NOT CURL_DISABLE_PROXY AND _ssl_enabled AND (USE_OPENSSL OR USE_GNUTLS OR USE_SCHANNEL OR USE_RUSTLS OR USE_MBEDTLS OR diff --git a/Makefile.am b/Makefile.am index 08d59e807f..515fa3c8b4 100644 --- a/Makefile.am +++ b/Makefile.am @@ -43,7 +43,6 @@ CMAKE_DIST = \ CMake/FindLibssh.cmake \ CMake/FindLibssh2.cmake \ CMake/FindLibuv.cmake \ - CMake/FindMSH3.cmake \ CMake/FindMbedTLS.cmake \ CMake/FindNGHTTP2.cmake \ CMake/FindNGHTTP3.cmake \ diff --git a/configure.ac b/configure.ac index 373e859f8c..9b1096fcb9 100644 --- a/configure.ac +++ b/configure.ac @@ -173,7 +173,7 @@ curl_headers_msg="enabled (--disable-headers-api)" ssl_backends= curl_h1_msg="enabled (internal)" curl_h2_msg="no (--with-nghttp2)" - curl_h3_msg="no (--with-ngtcp2 --with-nghttp3, --with-quiche, --with-openssl-quic, --with-msh3)" + curl_h3_msg="no (--with-ngtcp2 --with-nghttp3, --with-quiche, --with-openssl-quic)" enable_altsvc="yes" hsts="yes" @@ -3781,97 +3781,6 @@ if test X"$want_quiche" != Xno; then fi fi -dnl ********************************************************************** -dnl Check for msh3/msquic (QUIC) -dnl ********************************************************************** - -OPT_MSH3="no" - -if test "x$disable_http" = "xyes" -o "x$USE_NGTCP" = "x1"; then - # without HTTP or with ngtcp2, msh3 is no use - OPT_MSH3="no" -fi - -AC_ARG_WITH(msh3, -AS_HELP_STRING([--with-msh3=PATH],[Enable msh3 usage]) -AS_HELP_STRING([--without-msh3],[Disable msh3 usage]), - [OPT_MSH3=$withval]) -case "$OPT_MSH3" in - no) - dnl --without-msh3 option used - want_msh3="no" - ;; - yes) - dnl --with-msh3 option used without path - want_msh3="default" - want_msh3_path="" - ;; - *) - dnl --with-msh3 option used with path - want_msh3="yes" - want_msh3_path="$withval" - ;; -esac - -if test X"$want_msh3" != Xno; then - - dnl msh3 on non-Windows needs an OpenSSL with the QUIC API - if test "$curl_cv_native_windows" != "yes"; then - if test "$QUIC_ENABLED" != "yes"; then - AC_MSG_ERROR([the detected TLS library does not support QUIC, making --with-msh3 a no-no]) - fi - if test "$OPENSSL_ENABLED" != "1"; then - AC_MSG_ERROR([msh3/msquic requires OpenSSL]) - fi - fi - - if test "$NGHTTP3_ENABLED" = 1; then - AC_MSG_ERROR([--with-msh3 and --with-ngtcp2 are mutually exclusive]) - fi - if test "$USE_QUICHE" = 1; then - AC_MSG_ERROR([--with-msh3 and --with-quiche are mutually exclusive]) - fi - - dnl backup the pre-msh3 variables - CLEANLDFLAGS="$LDFLAGS" - CLEANLDFLAGSPC="$LDFLAGSPC" - CLEANCPPFLAGS="$CPPFLAGS" - CLEANLIBS="$LIBS" - - if test -n "$want_msh3_path"; then - LD_MSH3="-L$want_msh3_path/lib" - CPP_MSH3="-I$want_msh3_path/include" - DIR_MSH3="$want_msh3_path/lib" - LDFLAGS="$LDFLAGS $LD_MSH3" - LDFLAGSPC="$LDFLAGSPC $LD_MSH3" - CPPFLAGS="$CPPFLAGS $CPP_MSH3" - fi - LIBS="-lmsh3 $LIBS" - - AC_CHECK_LIB(msh3, MsH3ApiOpen, - [ - AC_CHECK_HEADERS(msh3.h, - curl_h3_msg="enabled (msh3)" - AC_DEFINE(USE_MSH3, 1, [if msh3 is in use]) - USE_MSH3=1 - CURL_LIBRARY_PATH="$CURL_LIBRARY_PATH:$DIR_MSH3" - export CURL_LIBRARY_PATH - AC_MSG_NOTICE([Added $DIR_MSH3 to CURL_LIBRARY_PATH]) - dnl FIXME: Enable when msh3 was detected via pkg-config - if false; then - LIBCURL_PC_REQUIRES_PRIVATE="$LIBCURL_PC_REQUIRES_PRIVATE libmsh3" - fi - experimental="$experimental HTTP3" - ) - ], - dnl not found, revert back to clean variables - LDFLAGS=$CLEANLDFLAGS - LDFLAGSPC=$CLEANLDFLAGSPC - CPPFLAGS=$CLEANCPPFLAGS - LIBS=$CLEANLIBS - ) -fi - dnl ********************************************************************** dnl libuv is only ever used for debug purposes dnl ********************************************************************** @@ -5316,7 +5225,7 @@ if test "x$USE_NGHTTP2" = "x1"; then fi if test "x$USE_NGTCP2_H3" = "x1" -o "x$USE_QUICHE" = "x1" \ - -o "x$USE_OPENSSL_H3" = "x1" -o "x$USE_MSH3" = "x1"; then + -o "x$USE_OPENSSL_H3" = "x1"; then if test "x$CURL_WITH_MULTI_SSL" = "x1"; then AC_MSG_ERROR([MultiSSL cannot be enabled with HTTP/3 and vice versa]) fi diff --git a/docs/DEPRECATE.md b/docs/DEPRECATE.md index 862b82f8d4..814610d0f8 100644 --- a/docs/DEPRECATE.md +++ b/docs/DEPRECATE.md @@ -16,20 +16,6 @@ how your use case cannot be satisfied properly using a workaround. Nothing is currently scheduled to be removed. -## msh3 support - -The msh3 backed for QUIC and HTTP/3 was introduced in April 2022 but has never -been made to work properly. It has seen no visible traction or developer -activity from the msh3 main author (or anyone else seemingly interested) in -two years. As a non-functional backend, it only adds friction and "weight" to -the development and maintenance. - -Meanwhile, we have a fully working backend in the ngtcp2 one and we have two -fully working backends in OpenSSL-QUIC and quiche well on their way of ending -their experimental status in a future. - -We remove msh3 support from the curl source tree in July 2025. - ## winbuild build system curl drops support for the winbuild build method after September 2025. @@ -78,3 +64,4 @@ Making the new minimum target Windows version Vista / Server 2008. - Support for Visual Studio 2005 and older (removed in 8.13.0) - Secure Transport (removed in 8.15.0) - BearSSL (removed in 8.15.0) + - msh3 (removed in 8.16.0) diff --git a/docs/HTTP3.md b/docs/HTTP3.md index b75daa43a8..95901196f4 100644 --- a/docs/HTTP3.md +++ b/docs/HTTP3.md @@ -23,13 +23,10 @@ QUIC libraries we are using: [OpenSSL 3.2+ QUIC](https://github.com/openssl/openssl) - **EXPERIMENTAL** -[msh3](https://github.com/nibanks/msh3) (with [msquic](https://github.com/microsoft/msquic)) - **EXPERIMENTAL** - ## Experimental HTTP/3 support in curl is considered **EXPERIMENTAL** until further notice -when built to use *quiche* or *msh3*. Only the *ngtcp2* backend is not -experimental. +when built to use *quiche*. Only the *ngtcp2* backend is not experimental. Further development and tweaking of the HTTP/3 support in curl happens in the master branch using pull-requests, just like ordinary changes. @@ -300,63 +297,6 @@ You can build curl with cmake: If `make install` results in `Permission denied` error, you need to prepend it with `sudo`. -# msh3 (msquic) version - -**Note**: The msquic HTTP/3 backend is immature and is not properly functional -one as of September 2023. Feel free to help us test it and improve it, but -there is no point in filing bugs about it just yet. - -msh3 support is **EXPERIMENTAL** - -## Build Linux (with quictls fork of OpenSSL) - -Build msh3: - - % git clone -b v0.6.0 --depth 1 --recursive https://github.com/nibanks/msh3 - % cd msh3 && mkdir build && cd build - % cmake -G 'Unix Makefiles' -DCMAKE_BUILD_TYPE=RelWithDebInfo .. - % cmake --build . - % cmake --install . - -Build curl: - - % git clone https://github.com/curl/curl - % cd curl - % autoreconf -fi - % ./configure LDFLAGS="-Wl,-rpath,/usr/local/lib" --with-msh3=/usr/local --with-openssl - % make - % make install - -Run from `/usr/local/bin/curl`. - -## Build Windows - -Build msh3: - - % git clone -b v0.6.0 --depth 1 --recursive https://github.com/nibanks/msh3 - % cd msh3 && mkdir build && cd build - % cmake -G 'Visual Studio 17 2022' -DCMAKE_BUILD_TYPE=RelWithDebInfo .. - % cmake --build . --config Release - % cmake --install . --config Release - -**Note** - On Windows, Schannel is used for TLS support by default. If you -with to use (the quictls fork of) OpenSSL, specify the `-DQUIC_TLS=openssl` -option to the generate command above. Also note that OpenSSL brings with it an -additional set of build dependencies not specified here. - -Build curl (in [Visual Studio Command -prompt](../winbuild/README.md#open-a-command-prompt)): - - % git clone https://github.com/curl/curl - % cd curl/winbuild - % nmake /f Makefile.vc mode=dll WITH_MSH3=dll MSH3_PATH="C:/Program Files/msh3" MACHINE=x64 - -Run in the `C:/Program Files/msh3/lib` directory, copy `curl.exe` to that -directory, or copy `msquic.dll` and `msh3.dll` from that directory to the -`curl.exe` directory. For example: - - % C:\Program Files\msh3\lib> F:\curl\builds\libcurl-vc-x64-release-dll-ipv6-sspi-schannel-msh3\bin\curl.exe --http3 https://curl.se/ - # `--http3` Use only HTTP/3: diff --git a/docs/INSTALL-CMAKE.md b/docs/INSTALL-CMAKE.md index 7fe8d1db2e..7220e328e1 100644 --- a/docs/INSTALL-CMAKE.md +++ b/docs/INSTALL-CMAKE.md @@ -372,7 +372,6 @@ Details via CMake - `USE_APPLE_IDN`: Use Apple built-in IDN support. Default: `OFF` - `USE_LIBIDN2`: Use libidn2 for IDN support. Default: `ON` - `USE_LIBRTMP`: Enable librtmp from rtmpdump. Default: `OFF` -- `USE_MSH3`: Use msh3/msquic library for HTTP/3 support. Default: `OFF` - `USE_NGHTTP2`: Use nghttp2 library. Default: `ON` - `USE_NGTCP2`: Use ngtcp2 and nghttp3 libraries for HTTP/3 support. Default: `OFF` - `USE_QUICHE`: Use quiche library for HTTP/3 support. Default: `OFF` @@ -429,8 +428,6 @@ Details via CMake - `MBEDTLS_LIBRARY`: Path to `mbedtls` library. - `MBEDX509_LIBRARY`: Path to `mbedx509` library. - `MBEDCRYPTO_LIBRARY`: Path to `mbedcrypto` library. -- `MSH3_INCLUDE_DIR`: The msh3 include directory. -- `MSH3_LIBRARY`: Path to `msh3` library. - `NGHTTP2_INCLUDE_DIR`: The nghttp2 include directory. - `NGHTTP2_LIBRARY`: Path to `nghttp2` library. - `NGHTTP3_INCLUDE_DIR`: The nghttp3 include directory. @@ -577,7 +574,6 @@ winbuild options | Equivalent CMake options `RTLIBCFG`: `static` | `CURL_STATIC_CRT=ON` `ENABLE_IDN` | `USE_WIN32_IDN=ON` `ENABLE_IPV6` | `ENABLE_IPV6=ON` -`ENABLE_MSH3` | `USE_MSH3=ON` `ENABLE_NGHTTP2` | `USE_NGHTTP2=ON` `ENABLE_OPENSSL_AUTO_LOAD_CONFIG` | `CURL_DISABLE_OPENSSL_AUTO_LOAD_CONFIG=OFF` (default) `ENABLE_SCHANNEL` | `CURL_USE_SCHANNEL=ON` @@ -587,7 +583,6 @@ winbuild options | Equivalent CMake options `WITH_DEVEL` | see individual `*_INCLUDE_DIR` and `*_LIBRARY` options and `OPENSSL_ROOT_DIR` `WITH_CARES`, `CARES_PATH` | `ENABLE_ARES=ON`, optional: `CARES_INCLUDE_DIR`, `CARES_LIBRARY` `WITH_MBEDTLS`, `MBEDTLS_PATH` | `CURL_USE_MBEDTLS=ON`, optional: `MBEDTLS_INCLUDE_DIR`, `MBEDTLS_LIBRARY`, `MBEDX509_LIBRARY`, `MBEDCRYPTO_LIBRARY` -`WITH_MSH3`, `MSH_PATH` | `USE_MSH3=ON`, optional: `MSH3_INCLUDE_DIR`, `MSH3_LIBRARY` `WITH_NGHTTP2`, `NGHTTP2_PATH` | `USE_NGHTTP2=ON`, optional: `NGHTTP2_INCLUDE_DIR`, `NGHTTP2_LIBRARY` `WITH_SSH`, `SSH_PATH` | `CURL_USE_LIBSSH=ON`, optional: `LIBSSH_INCLUDE_DIR`, `LIBSSH_LIBRARY` `WITH_SSH2`, `SSH2_PATH` | `CURL_USE_LIBSSH2=ON`, optional: `LIBSSH2_INCLUDE_DIR`, `LIBSSH2_LIBRARY` diff --git a/lib/Makefile.inc b/lib/Makefile.inc index 257e104de9..b4a27bfdcf 100644 --- a/lib/Makefile.inc +++ b/lib/Makefile.inc @@ -110,7 +110,6 @@ LIB_VTLS_HFILES = \ vtls/x509asn1.h LIB_VQUIC_CFILES = \ - vquic/curl_msh3.c \ vquic/curl_ngtcp2.c \ vquic/curl_osslq.c \ vquic/curl_quiche.c \ @@ -118,7 +117,6 @@ LIB_VQUIC_CFILES = \ vquic/vquic-tls.c LIB_VQUIC_HFILES = \ - vquic/curl_msh3.h \ vquic/curl_ngtcp2.h \ vquic/curl_osslq.h \ vquic/curl_quiche.h \ diff --git a/lib/cf-socket.c b/lib/cf-socket.c index 273258feaf..3d535a0e10 100644 --- a/lib/cf-socket.c +++ b/lib/cf-socket.c @@ -307,9 +307,9 @@ tcpkeepalive(struct Curl_easy *data, * Assign the address `ai` to the Curl_sockaddr_ex `dest` and * set the transport used. */ -CURLcode Curl_sock_assign_addr(struct Curl_sockaddr_ex *dest, - const struct Curl_addrinfo *ai, - int transport) +static CURLcode sock_assign_addr(struct Curl_sockaddr_ex *dest, + const struct Curl_addrinfo *ai, + int transport) { /* * The Curl_sockaddr_ex structure is basically libcurl's external API @@ -406,7 +406,7 @@ CURLcode Curl_socket_open(struct Curl_easy *data, /* if the caller does not want info back, use a local temp copy */ addr = &dummy; - result = Curl_sock_assign_addr(addr, ai, transport); + result = sock_assign_addr(addr, ai, transport); if(result) return result; @@ -949,7 +949,7 @@ static CURLcode cf_socket_ctx_init(struct cf_socket_ctx *ctx, ctx->sock = CURL_SOCKET_BAD; ctx->transport = transport; - result = Curl_sock_assign_addr(&ctx->addr, ai, transport); + result = sock_assign_addr(&ctx->addr, ai, transport); if(result) return result; diff --git a/lib/cf-socket.h b/lib/cf-socket.h index 90daf079a0..88c08fe7c0 100644 --- a/lib/cf-socket.h +++ b/lib/cf-socket.h @@ -91,14 +91,6 @@ void Curl_sndbuf_init(curl_socket_t sockfd); #define Curl_sndbuf_init(y) Curl_nop_stmt #endif -/** - * Assign the address `ai` to the Curl_sockaddr_ex `dest` and - * set the transport used. - */ -CURLcode Curl_sock_assign_addr(struct Curl_sockaddr_ex *dest, - const struct Curl_addrinfo *ai, - int transport); - /** * Creates a cfilter that opens a TCP socket to the given address * when calling its `connect` implementation. diff --git a/lib/config-os400.h b/lib/config-os400.h index 064338ed2a..bccdb4a897 100644 --- a/lib/config-os400.h +++ b/lib/config-os400.h @@ -203,10 +203,6 @@ /* Define if you have the ANSI C header files. */ #define STDC_HEADERS -/* Define to enable HTTP3 support (experimental, requires NGTCP2, quiche or - MSH3) */ -#undef USE_HTTP3 - /* Version number of package */ #undef VERSION diff --git a/lib/curl_config.h.cmake b/lib/curl_config.h.cmake index 0838ddccfb..55701675e7 100644 --- a/lib/curl_config.h.cmake +++ b/lib/curl_config.h.cmake @@ -761,9 +761,6 @@ ${SIZEOF_TIME_T_CODE} /* Define to 1 if you have the quiche_conn_set_qlog_fd function. */ #cmakedefine HAVE_QUICHE_CONN_SET_QLOG_FD 1 -/* to enable msh3 */ -#cmakedefine USE_MSH3 1 - /* if Unix domain sockets are enabled */ #cmakedefine USE_UNIX_SOCKETS 1 diff --git a/lib/curl_setup.h b/lib/curl_setup.h index 4dc46f7a73..5f982ea61a 100644 --- a/lib/curl_setup.h +++ b/lib/curl_setup.h @@ -986,7 +986,7 @@ int getpwuid_r(uid_t uid, struct passwd *pwd, char *buf, #if (defined(USE_NGTCP2) && defined(USE_NGHTTP3)) || \ (defined(USE_OPENSSL_QUIC) && defined(USE_NGHTTP3)) || \ - defined(USE_QUICHE) || defined(USE_MSH3) + defined(USE_QUICHE) #ifdef CURL_WITH_MULTI_SSL #error "MultiSSL combined with QUIC is not supported" diff --git a/lib/http.h b/lib/http.h index 8876f38044..3553eff0c6 100644 --- a/lib/http.h +++ b/lib/http.h @@ -25,10 +25,6 @@ ***************************************************************************/ #include "curl_setup.h" -#if defined(USE_MSH3) && !defined(_WIN32) -#include -#endif - #include "bufq.h" #include "dynhds.h" #include "ws.h" diff --git a/lib/socketpair.c b/lib/socketpair.c index 1d1d5a66f3..93df9071ef 100644 --- a/lib/socketpair.c +++ b/lib/socketpair.c @@ -84,6 +84,7 @@ int Curl_pipe(curl_socket_t socks[2], bool nonblocking) #ifndef CURL_DISABLE_SOCKETPAIR #ifdef HAVE_SOCKETPAIR +#ifdef USE_SOCKETPAIR int Curl_socketpair(int domain, int type, int protocol, curl_socket_t socks[2], bool nonblocking) { @@ -104,6 +105,7 @@ int Curl_socketpair(int domain, int type, int protocol, #endif return 0; } +#endif /* USE_SOCKETPAIR */ #else /* !HAVE_SOCKETPAIR */ #ifdef _WIN32 /* diff --git a/lib/socketpair.h b/lib/socketpair.h index 5541899445..e601f5f71b 100644 --- a/lib/socketpair.h +++ b/lib/socketpair.h @@ -66,8 +66,9 @@ int Curl_pipe(curl_socket_t socks[2], bool nonblocking); #define SOCKETPAIR_TYPE SOCK_STREAM #endif -#define wakeup_create(p,nb)\ -Curl_socketpair(SOCKETPAIR_FAMILY, SOCKETPAIR_TYPE, 0, p, nb) +#define USE_SOCKETPAIR +#define wakeup_create(p,nb) \ + Curl_socketpair(SOCKETPAIR_FAMILY, SOCKETPAIR_TYPE, 0, p, nb) #endif /* USE_EVENTFD */ diff --git a/lib/vquic/curl_msh3.c b/lib/vquic/curl_msh3.c deleted file mode 100644 index 6566447ba1..0000000000 --- a/lib/vquic/curl_msh3.c +++ /dev/null @@ -1,1095 +0,0 @@ -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) Daniel Stenberg, , 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" - -#ifdef USE_MSH3 - -#include "../urldata.h" -#include "../hash.h" -#include "../uint-hash.h" -#include "../curlx/timeval.h" -#include "../multiif.h" -#include "../sendf.h" -#include "../curl_trc.h" -#include "../cfilters.h" -#include "../cf-socket.h" -#include "../connect.h" -#include "../progress.h" -#include "../http1.h" -#include "curl_msh3.h" -#include "../socketpair.h" -#include "../vtls/vtls.h" -#include "vquic.h" -#include "vquic_int.h" - -/* The last 3 #include files should be in this order */ -#include "../curl_printf.h" -#include "../curl_memory.h" -#include "../memdebug.h" - -#ifdef CURL_DISABLE_SOCKETPAIR -#error "MSH3 cannot be build with CURL_DISABLE_SOCKETPAIR set" -#endif - -#define H3_STREAM_WINDOW_SIZE (128 * 1024) -#define H3_STREAM_CHUNK_SIZE (16 * 1024) -#define H3_STREAM_RECV_CHUNKS \ - (H3_STREAM_WINDOW_SIZE / H3_STREAM_CHUNK_SIZE) - -#ifdef _WIN32 -#define msh3_lock CRITICAL_SECTION -#define msh3_lock_initialize(lock) InitializeCriticalSection(lock) -#define msh3_lock_uninitialize(lock) DeleteCriticalSection(lock) -#define msh3_lock_acquire(lock) EnterCriticalSection(lock) -#define msh3_lock_release(lock) LeaveCriticalSection(lock) -#else /* !_WIN32 */ -#include -#define msh3_lock pthread_mutex_t -#define msh3_lock_initialize(lock) do { \ - pthread_mutexattr_t attr; \ - pthread_mutexattr_init(&attr); \ - pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); \ - pthread_mutex_init(lock, &attr); \ - pthread_mutexattr_destroy(&attr); \ -} while(0) -#define msh3_lock_uninitialize(lock) pthread_mutex_destroy(lock) -#define msh3_lock_acquire(lock) pthread_mutex_lock(lock) -#define msh3_lock_release(lock) pthread_mutex_unlock(lock) -#endif /* _WIN32 */ - - -static void MSH3_CALL msh3_conn_connected(MSH3_CONNECTION *Connection, - void *IfContext); -static void MSH3_CALL msh3_conn_shutdown_complete(MSH3_CONNECTION *Connection, - void *IfContext); -static void MSH3_CALL msh3_conn_new_request(MSH3_CONNECTION *Connection, - void *IfContext, - MSH3_REQUEST *Request); -static void MSH3_CALL msh3_header_received(MSH3_REQUEST *Request, - void *IfContext, - const MSH3_HEADER *Header); -static bool MSH3_CALL msh3_data_received(MSH3_REQUEST *Request, - void *IfContext, uint32_t *Length, - const uint8_t *Data); -static void MSH3_CALL msh3_complete(MSH3_REQUEST *Request, void *IfContext, - bool Aborted, uint64_t AbortError); -static void MSH3_CALL msh3_shutdown_complete(MSH3_REQUEST *Request, - void *IfContext); -static void MSH3_CALL msh3_data_sent(MSH3_REQUEST *Request, - void *IfContext, void *SendContext); - - -void Curl_msh3_ver(char *p, size_t len) -{ - uint32_t v[4]; - MsH3Version(v); - (void)msnprintf(p, len, "msh3/%d.%d.%d.%d", v[0], v[1], v[2], v[3]); -} - -#define SP_LOCAL 0 -#define SP_REMOTE 1 - -struct cf_msh3_ctx { - MSH3_API *api; - MSH3_CONNECTION *qconn; - struct Curl_sockaddr_ex addr; - curl_socket_t sock[2]; /* fake socket pair until we get support in msh3 */ - char l_ip[MAX_IPADR_LEN]; /* local IP as string */ - int l_port; /* local port number */ - struct cf_call_data call_data; - struct curltime connect_started; /* time the current attempt started */ - struct curltime handshake_at; /* time connect handshake finished */ - struct uint_hash streams; /* hash `data->mid` to `stream_ctx` */ - /* Flags written by msh3/msquic thread */ - BIT(handshake_complete); - BIT(handshake_succeeded); - BIT(connected); - BIT(initialized); - /* Flags written by curl thread */ - BIT(verbose); - BIT(active); -}; - -static void h3_stream_hash_free(unsigned int id, void *stream); - -static CURLcode cf_msh3_ctx_init(struct cf_msh3_ctx *ctx, - const struct Curl_addrinfo *ai) -{ - CURLcode result; - - DEBUGASSERT(!ctx->initialized); - Curl_uint_hash_init(&ctx->streams, 63, h3_stream_hash_free); - - result = Curl_sock_assign_addr(&ctx->addr, ai, TRNSPRT_QUIC); - if(result) - return result; - - ctx->sock[SP_LOCAL] = CURL_SOCKET_BAD; - ctx->sock[SP_REMOTE] = CURL_SOCKET_BAD; - ctx->initialized = TRUE; - - return result; -} - -static void cf_msh3_ctx_free(struct cf_msh3_ctx *ctx) -{ - if(ctx && ctx->initialized) { - Curl_uint_hash_destroy(&ctx->streams); - } - free(ctx); -} - -static struct cf_msh3_ctx *h3_get_msh3_ctx(struct Curl_easy *data); - -/* How to access `call_data` from a cf_msh3 filter */ -#undef CF_CTX_CALL_DATA -#define CF_CTX_CALL_DATA(cf) \ - ((struct cf_msh3_ctx *)(cf)->ctx)->call_data - -/** - * All about the H3 internals of a stream - */ -struct h3_stream_ctx { - struct MSH3_REQUEST *req; - struct bufq recvbuf; /* h3 response */ -#ifdef _WIN32 - CRITICAL_SECTION recv_lock; -#else /* !_WIN32 */ - pthread_mutex_t recv_lock; -#endif /* _WIN32 */ - uint64_t error3; /* HTTP/3 stream error code */ - int status_code; /* HTTP status code */ - CURLcode recv_error; - BIT(closed); - BIT(reset); - BIT(upload_done); - BIT(firstheader); /* FALSE until headers arrive */ - BIT(recv_header_complete); -}; - -static void h3_stream_ctx_free(struct h3_stream_ctx *stream) -{ - Curl_bufq_free(&stream->recvbuf); - free(stream); -} - -static void h3_stream_hash_free(unsigned int id, void *stream) -{ - (void)id; - DEBUGASSERT(stream); - h3_stream_ctx_free((struct h3_stream_ctx *)stream); -} - -static CURLcode h3_data_setup(struct Curl_cfilter *cf, - struct Curl_easy *data) -{ - struct cf_msh3_ctx *ctx = cf->ctx; - struct h3_stream_ctx *stream = H3_STREAM_CTX(ctx, data); - - if(stream) - return CURLE_OK; - - stream = calloc(1, sizeof(*stream)); - if(!stream) - return CURLE_OUT_OF_MEMORY; - - stream->req = ZERO_NULL; - msh3_lock_initialize(&stream->recv_lock); - Curl_bufq_init2(&stream->recvbuf, H3_STREAM_CHUNK_SIZE, - H3_STREAM_RECV_CHUNKS, BUFQ_OPT_SOFT_LIMIT); - CURL_TRC_CF(data, cf, "data setup"); - - if(!Curl_uint_hash_set(&ctx->streams, data->mid, stream)) { - h3_stream_ctx_free(stream); - return CURLE_OUT_OF_MEMORY; - } - - return CURLE_OK; -} - -static void h3_data_done(struct Curl_cfilter *cf, struct Curl_easy *data) -{ - struct cf_msh3_ctx *ctx = cf->ctx; - struct h3_stream_ctx *stream = H3_STREAM_CTX(ctx, data); - - (void)cf; - if(stream) { - CURL_TRC_CF(data, cf, "easy handle is done"); - Curl_uint_hash_remove(&ctx->streams, data->mid); - } -} - -static void drain_stream_from_other_thread(struct Curl_easy *data, - struct h3_stream_ctx *stream) -{ - (void)data; - (void)stream; - /* cannot expire from other thread. - here is the disconnect between msh3 and curl */ -} - -static void h3_drain_stream(struct Curl_cfilter *cf, - struct Curl_easy *data) -{ - (void)cf; - Curl_multi_mark_dirty(data); -} - -static const MSH3_CONNECTION_IF msh3_conn_if = { - msh3_conn_connected, - msh3_conn_shutdown_complete, - msh3_conn_new_request -}; - -static void MSH3_CALL msh3_conn_connected(MSH3_CONNECTION *Connection, - void *IfContext) -{ - struct Curl_cfilter *cf = IfContext; - struct cf_msh3_ctx *ctx = cf->ctx; - struct Curl_easy *data = CF_DATA_CURRENT(cf); - (void)Connection; - - CURL_TRC_CF(data, cf, "[MSH3] connected"); - ctx->handshake_succeeded = TRUE; - ctx->connected = TRUE; - ctx->handshake_complete = TRUE; -} - -static void MSH3_CALL msh3_conn_shutdown_complete(MSH3_CONNECTION *Connection, - void *IfContext) -{ - struct Curl_cfilter *cf = IfContext; - struct cf_msh3_ctx *ctx = cf->ctx; - struct Curl_easy *data = CF_DATA_CURRENT(cf); - - (void)Connection; - CURL_TRC_CF(data, cf, "[MSH3] shutdown complete"); - ctx->connected = FALSE; - ctx->handshake_complete = TRUE; -} - -static void MSH3_CALL msh3_conn_new_request(MSH3_CONNECTION *Connection, - void *IfContext, - MSH3_REQUEST *Request) -{ - (void)Connection; - (void)IfContext; - (void)Request; -} - -static const MSH3_REQUEST_IF msh3_request_if = { - msh3_header_received, - msh3_data_received, - msh3_complete, - msh3_shutdown_complete, - msh3_data_sent -}; - -/* Decode HTTP status code. Returns -1 if no valid status code was - decoded. (duplicate from http2.c) */ -static int decode_status_code(const char *value, size_t len) -{ - int i; - int res; - - if(len != 3) { - return -1; - } - - res = 0; - - for(i = 0; i < 3; ++i) { - char c = value[i]; - - if(c < '0' || c > '9') { - return -1; - } - - res *= 10; - res += c - '0'; - } - - return res; -} - -/* - * write_resp_raw() copies response data in raw format to the `data`'s - * receive buffer. If not enough space is available, it appends to the - * `data`'s overflow buffer. - */ -static CURLcode write_resp_raw(struct Curl_easy *data, - const void *mem, size_t memlen) -{ - struct cf_msh3_ctx *ctx = h3_get_msh3_ctx(data); - struct h3_stream_ctx *stream = H3_STREAM_CTX(ctx, data); - CURLcode result = CURLE_OK; - size_t nwritten; - - if(!stream) - return CURLE_RECV_ERROR; - - result = Curl_bufq_write(&stream->recvbuf, mem, memlen, &nwritten); - if(result) - return result; - - if(nwritten < memlen) { - /* This MUST not happen. Our recbuf is dimensioned to hold the - * full max_stream_window and then some for this very reason. */ - DEBUGASSERT(0); - return CURLE_RECV_ERROR; - } - return result; -} - -static void MSH3_CALL msh3_header_received(MSH3_REQUEST *Request, - void *userp, - const MSH3_HEADER *hd) -{ - struct Curl_easy *data = userp; - struct cf_msh3_ctx *ctx = h3_get_msh3_ctx(data); - struct h3_stream_ctx *stream = H3_STREAM_CTX(ctx, data); - CURLcode result; - (void)Request; - - DEBUGF(infof(data, "[MSH3] header received, stream=%d", !!stream)); - if(!stream || stream->recv_header_complete) { - return; - } - - msh3_lock_acquire(&stream->recv_lock); - - if((hd->NameLength == 7) && - !strncmp(HTTP_PSEUDO_STATUS, (const char *)hd->Name, 7)) { - char line[14]; /* status line is always 13 characters long */ - size_t ncopy; - - DEBUGASSERT(!stream->firstheader); - stream->status_code = decode_status_code(hd->Value, hd->ValueLength); - DEBUGASSERT(stream->status_code != -1); - ncopy = msnprintf(line, sizeof(line), "HTTP/3 %03d \r\n", - stream->status_code); - result = write_resp_raw(data, line, ncopy); - if(result) - stream->recv_error = result; - stream->firstheader = TRUE; - } - else { - /* store as an HTTP1-style header */ - DEBUGASSERT(stream->firstheader); - result = write_resp_raw(data, hd->Name, hd->NameLength); - if(!result) - result = write_resp_raw(data, ": ", 2); - if(!result) - result = write_resp_raw(data, hd->Value, hd->ValueLength); - if(!result) - result = write_resp_raw(data, "\r\n", 2); - if(result) { - stream->recv_error = result; - } - } - - drain_stream_from_other_thread(data, stream); - msh3_lock_release(&stream->recv_lock); -} - -static bool MSH3_CALL msh3_data_received(MSH3_REQUEST *Request, - void *IfContext, uint32_t *buflen, - const uint8_t *buf) -{ - struct Curl_easy *data = IfContext; - struct cf_msh3_ctx *ctx = h3_get_msh3_ctx(data); - struct h3_stream_ctx *stream = H3_STREAM_CTX(ctx, data); - CURLcode result; - bool rv = FALSE; - - /* We would like to limit the amount of data we are buffer here. There seems - * to be no mechanism in msh3 to adjust flow control and it is undocumented - * what happens if we return FALSE here or less length (buflen is an inout - * parameter). - */ - (void)Request; - if(!stream) - return FALSE; - - msh3_lock_acquire(&stream->recv_lock); - - if(!stream->recv_header_complete) { - result = write_resp_raw(data, "\r\n", 2); - if(result) { - stream->recv_error = result; - goto out; - } - stream->recv_header_complete = TRUE; - } - - result = write_resp_raw(data, buf, *buflen); - if(result) { - stream->recv_error = result; - } - rv = TRUE; - -out: - msh3_lock_release(&stream->recv_lock); - return rv; -} - -static void MSH3_CALL msh3_complete(MSH3_REQUEST *Request, void *IfContext, - bool aborted, uint64_t error) -{ - struct Curl_easy *data = IfContext; - struct cf_msh3_ctx *ctx = h3_get_msh3_ctx(data); - struct h3_stream_ctx *stream = H3_STREAM_CTX(ctx, data); - - (void)Request; - if(!stream) - return; - msh3_lock_acquire(&stream->recv_lock); - stream->closed = TRUE; - stream->recv_header_complete = TRUE; - if(error) - stream->error3 = error; - if(aborted) - stream->reset = TRUE; - msh3_lock_release(&stream->recv_lock); -} - -static void MSH3_CALL msh3_shutdown_complete(MSH3_REQUEST *Request, - void *IfContext) -{ - struct Curl_easy *data = IfContext; - struct cf_msh3_ctx *ctx = h3_get_msh3_ctx(data); - struct h3_stream_ctx *stream = H3_STREAM_CTX(ctx, data); - - if(!stream) - return; - (void)Request; - (void)stream; -} - -static void MSH3_CALL msh3_data_sent(MSH3_REQUEST *Request, - void *IfContext, void *SendContext) -{ - struct Curl_easy *data = IfContext; - struct cf_msh3_ctx *ctx = h3_get_msh3_ctx(data); - struct h3_stream_ctx *stream = H3_STREAM_CTX(ctx, data); - if(!stream) - return; - (void)Request; - (void)stream; - (void)SendContext; -} - -static CURLcode recv_closed_stream(struct Curl_cfilter *cf, - struct Curl_easy *data, - size_t *pnread) -{ - struct cf_msh3_ctx *ctx = cf->ctx; - struct h3_stream_ctx *stream = H3_STREAM_CTX(ctx, data); - - (void)cf; - *pnread = 0; - if(!stream) - return CURLE_RECV_ERROR; - - if(stream->reset) { - failf(data, "HTTP/3 stream reset by server"); - CURL_TRC_CF(data, cf, "cf_recv, was reset"); - return CURLE_PARTIAL_FILE; - } - else if(stream->error3) { - failf(data, "HTTP/3 stream was not closed cleanly: (error %zd)", - (ssize_t)stream->error3); - CURL_TRC_CF(data, cf, "cf_recv, closed uncleanly"); - return CURLE_HTTP3; - } - else { - CURL_TRC_CF(data, cf, "cf_recv, closed ok"); - } - return CURLE_OK; -} - -static void set_quic_expire(struct Curl_cfilter *cf, struct Curl_easy *data) -{ - struct cf_msh3_ctx *ctx = cf->ctx; - struct h3_stream_ctx *stream = H3_STREAM_CTX(ctx, data); - - /* we have no indication from msh3 when it would be a good time - * to juggle the connection again. So, we compromise by calling - * us again every some milliseconds. */ - (void)cf; - if(stream && stream->req && !stream->closed) { - Curl_expire(data, 10, EXPIRE_QUIC); - } - else { - Curl_expire(data, 50, EXPIRE_QUIC); - } -} - -static CURLcode cf_msh3_recv(struct Curl_cfilter *cf, struct Curl_easy *data, - char *buf, size_t len, size_t *pnread) -{ - struct cf_msh3_ctx *ctx = cf->ctx; - struct h3_stream_ctx *stream = H3_STREAM_CTX(ctx, data); - struct cf_call_data save; - CURLcode result = CURLE_OK; - - *pnread = 0; - CURL_TRC_CF(data, cf, "cf_recv(len=%zu), stream=%d", len, !!stream); - if(!stream) - return CURLE_RECV_ERROR; - CF_DATA_SAVE(save, cf, data); - - msh3_lock_acquire(&stream->recv_lock); - - if(stream->recv_error) { - failf(data, "request aborted"); - result = stream->recv_error; - goto out; - } - - if(!Curl_bufq_is_empty(&stream->recvbuf)) { - result = Curl_bufq_cread(&stream->recvbuf, buf, len, pnread); - CURL_TRC_CF(data, cf, "read recvbuf(len=%zu) -> %d, %zu", - len, result, *pnread); - if(result) - goto out; - if(stream->closed) - h3_drain_stream(cf, data); - } - else if(stream->closed) { - result = recv_closed_stream(cf, data, pnread); - goto out; - } - else { - CURL_TRC_CF(data, cf, "req: nothing here, call again"); - result = CURLE_AGAIN; - } - -out: - msh3_lock_release(&stream->recv_lock); - set_quic_expire(cf, data); - CF_DATA_RESTORE(cf, save); - return result; -} - -static CURLcode cf_msh3_send(struct Curl_cfilter *cf, struct Curl_easy *data, - const void *buf, size_t len, bool eos, - size_t *pnwritten) -{ - struct cf_msh3_ctx *ctx = cf->ctx; - struct h3_stream_ctx *stream = H3_STREAM_CTX(ctx, data); - struct h1_req_parser h1; - struct dynhds h2_headers; - MSH3_HEADER *nva = NULL; - size_t nheader, i; - ssize_t nwritten = -1; - struct cf_call_data save; - CURLcode result = CURLE_OK; - - *pnwritten = 0; - CF_DATA_SAVE(save, cf, data); - - Curl_h1_req_parse_init(&h1, H1_PARSE_DEFAULT_MAX_LINE_LEN); - Curl_dynhds_init(&h2_headers, 0, DYN_HTTP_REQUEST); - - /* Sizes must match for cast below to work" */ - DEBUGASSERT(stream); - CURL_TRC_CF(data, cf, "req: send %zu bytes", len); - - if(!stream->req) { - /* The first send on the request contains the headers and possibly some - data. Parse out the headers and create the request, then if there is - any data left over go ahead and send it too. */ - nwritten = Curl_h1_req_parse_read(&h1, buf, len, NULL, 0, &result); - if(nwritten < 0) - goto out; - DEBUGASSERT(h1.done); - DEBUGASSERT(h1.req); - *pnwritten = (size_t)nwritten; - - result = Curl_http_req_to_h2(&h2_headers, h1.req, data); - if(result) - goto out; - - nheader = Curl_dynhds_count(&h2_headers); - nva = malloc(sizeof(MSH3_HEADER) * nheader); - if(!nva) { - result = CURLE_OUT_OF_MEMORY; - goto out; - } - - for(i = 0; i < nheader; ++i) { - struct dynhds_entry *e = Curl_dynhds_getn(&h2_headers, i); - nva[i].Name = e->name; - nva[i].NameLength = e->namelen; - nva[i].Value = e->value; - nva[i].ValueLength = e->valuelen; - } - - CURL_TRC_CF(data, cf, "req: send %zu headers", nheader); - stream->req = MsH3RequestOpen(ctx->qconn, &msh3_request_if, data, - nva, nheader, - eos ? MSH3_REQUEST_FLAG_FIN : - MSH3_REQUEST_FLAG_NONE); - if(!stream->req) { - failf(data, "request open failed"); - result = CURLE_SEND_ERROR; - } - result = CURLE_OK; - *pnwritten = len; - goto out; - } - else { - /* request is open */ - CURL_TRC_CF(data, cf, "req: send %zu body bytes", len); - if(len > 0xFFFFFFFF) { - len = 0xFFFFFFFF; - } - - if(!MsH3RequestSend(stream->req, MSH3_REQUEST_FLAG_NONE, buf, - (uint32_t)len, stream)) { - result = CURLE_SEND_ERROR; - goto out; - } - - /* msh3/msquic will hold onto this memory until the send complete event. - How do we make sure curl does not free it until then? */ - result = CURLE_OK; - *pnwritten = len; - } - -out: - set_quic_expire(cf, data); - free(nva); - Curl_h1_req_parse_free(&h1); - Curl_dynhds_free(&h2_headers); - CF_DATA_RESTORE(cf, save); - return result; -} - -static void cf_msh3_adjust_pollset(struct Curl_cfilter *cf, - struct Curl_easy *data, - struct easy_pollset *ps) -{ - struct cf_msh3_ctx *ctx = cf->ctx; - struct h3_stream_ctx *stream = H3_STREAM_CTX(ctx, data); - struct cf_call_data save; - - CF_DATA_SAVE(save, cf, data); - if(stream && ctx->sock[SP_LOCAL] != CURL_SOCKET_BAD) { - if(stream->recv_error) { - Curl_pollset_add_in(data, ps, ctx->sock[SP_LOCAL]); - h3_drain_stream(cf, data); - } - else if(stream->req) { - Curl_pollset_add_out(data, ps, ctx->sock[SP_LOCAL]); - h3_drain_stream(cf, data); - } - } -} - -static bool cf_msh3_data_pending(struct Curl_cfilter *cf, - const struct Curl_easy *data) -{ - struct cf_msh3_ctx *ctx = cf->ctx; - struct h3_stream_ctx *stream = H3_STREAM_CTX(ctx, data); - struct cf_call_data save; - bool pending = FALSE; - - CF_DATA_SAVE(save, cf, data); - - (void)cf; - if(stream && stream->req) { - msh3_lock_acquire(&stream->recv_lock); - CURL_TRC_CF((struct Curl_easy *)CURL_UNCONST(data), cf, - "data pending = %zu", - Curl_bufq_len(&stream->recvbuf)); - pending = !Curl_bufq_is_empty(&stream->recvbuf); - msh3_lock_release(&stream->recv_lock); - if(pending) - h3_drain_stream(cf, (struct Curl_easy *)CURL_UNCONST(data)); - } - - CF_DATA_RESTORE(cf, save); - return pending; -} - -static CURLcode h3_data_pause(struct Curl_cfilter *cf, - struct Curl_easy *data, - bool pause) -{ - if(!pause) { - h3_drain_stream(cf, data); - Curl_expire(data, 0, EXPIRE_RUN_NOW); - } - return CURLE_OK; -} - -static CURLcode cf_msh3_data_event(struct Curl_cfilter *cf, - struct Curl_easy *data, - int event, int arg1, void *arg2) -{ - struct cf_msh3_ctx *ctx = cf->ctx; - struct h3_stream_ctx *stream = H3_STREAM_CTX(ctx, data); - struct cf_call_data save; - CURLcode result = CURLE_OK; - - CF_DATA_SAVE(save, cf, data); - - (void)arg1; - (void)arg2; - switch(event) { - case CF_CTRL_DATA_SETUP: - result = h3_data_setup(cf, data); - break; - case CF_CTRL_DATA_PAUSE: - result = h3_data_pause(cf, data, (arg1 != 0)); - break; - case CF_CTRL_DATA_DONE: - h3_data_done(cf, data); - break; - case CF_CTRL_DATA_DONE_SEND: - CURL_TRC_CF(data, cf, "req: send done"); - if(stream) { - stream->upload_done = TRUE; - if(stream->req) { - char buf[1]; - if(!MsH3RequestSend(stream->req, MSH3_REQUEST_FLAG_FIN, - buf, 0, data)) { - result = CURLE_SEND_ERROR; - } - } - } - break; - default: - break; - } - - CF_DATA_RESTORE(cf, save); - return result; -} - -static CURLcode cf_connect_start(struct Curl_cfilter *cf, - struct Curl_easy *data) -{ - struct cf_msh3_ctx *ctx = cf->ctx; - struct ssl_primary_config *conn_config; - MSH3_ADDR addr = {0}; - CURLcode result; - bool verify; - - DEBUGASSERT(ctx->initialized); - conn_config = Curl_ssl_cf_get_primary_config(cf); - if(!conn_config) - return CURLE_FAILED_INIT; - verify = !!conn_config->verifypeer; - - memcpy(&addr, &ctx->addr.curl_sa_addr, ctx->addr.addrlen); - MSH3_SET_PORT(&addr, (uint16_t)cf->conn->remote_port); - - if(verify && (conn_config->CAfile || conn_config->CApath)) { - /* Note there's currently no way to provide trust anchors to MSH3 and - that causes tests to fail. */ - CURL_TRC_CF(data, cf, "non-standard CA not supported, " - "attempting with built-in verification"); - } - - CURL_TRC_CF(data, cf, "connecting to %s:%d (verify=%d)", - cf->conn->host.name, (int)cf->conn->remote_port, verify); - - ctx->api = MsH3ApiOpen(); - if(!ctx->api) { - failf(data, "cannot create msh3 api"); - return CURLE_FAILED_INIT; - } - - ctx->qconn = MsH3ConnectionOpen(ctx->api, - &msh3_conn_if, - cf, - cf->conn->host.name, - &addr, - !verify); - if(!ctx->qconn) { - failf(data, "cannot create msh3 connection"); - if(ctx->api) { - MsH3ApiClose(ctx->api); - ctx->api = NULL; - } - return CURLE_FAILED_INIT; - } - - result = h3_data_setup(cf, data); - if(result) - return result; - - return CURLE_OK; -} - -static CURLcode cf_msh3_connect(struct Curl_cfilter *cf, - struct Curl_easy *data, - bool *done) -{ - struct cf_msh3_ctx *ctx = cf->ctx; - struct cf_call_data save; - CURLcode result = CURLE_OK; - - if(cf->connected) { - *done = TRUE; - return CURLE_OK; - } - - CF_DATA_SAVE(save, cf, data); - - if(ctx->sock[SP_LOCAL] == CURL_SOCKET_BAD) { - if(Curl_socketpair(AF_UNIX, SOCK_STREAM, 0, &ctx->sock[0], FALSE) < 0) { - ctx->sock[SP_LOCAL] = CURL_SOCKET_BAD; - ctx->sock[SP_REMOTE] = CURL_SOCKET_BAD; - return CURLE_COULDNT_CONNECT; - } - } - - *done = FALSE; - if(!ctx->qconn) { - ctx->connect_started = curlx_now(); - result = cf_connect_start(cf, data); - if(result) - goto out; - } - - if(ctx->handshake_complete) { - ctx->handshake_at = curlx_now(); - if(ctx->handshake_succeeded) { - CURL_TRC_CF(data, cf, "handshake succeeded"); - cf->conn->bits.multiplex = TRUE; /* at least potentially multiplexed */ - cf->connected = TRUE; - cf->conn->alpn = CURL_HTTP_VERSION_3; - *done = TRUE; - connkeep(cf->conn, "HTTP/3 default"); - Curl_pgrsTime(data, TIMER_APPCONNECT); - } - else { - failf(data, "failed to connect, handshake failed"); - result = CURLE_COULDNT_CONNECT; - } - } - -out: - CF_DATA_RESTORE(cf, save); - return result; -} - -static void cf_msh3_close(struct Curl_cfilter *cf, struct Curl_easy *data) -{ - struct cf_msh3_ctx *ctx = cf->ctx; - struct cf_call_data save; - - (void)data; - CF_DATA_SAVE(save, cf, data); - - if(ctx) { - CURL_TRC_CF(data, cf, "destroying"); - if(ctx->qconn) { - MsH3ConnectionClose(ctx->qconn); - ctx->qconn = NULL; - } - if(ctx->api) { - MsH3ApiClose(ctx->api); - ctx->api = NULL; - } - - if(ctx->active) { - /* We share our socket at cf->conn->sock[cf->sockindex] when active. - * If it is no longer there, someone has stolen (and hopefully - * closed it) and we just forget about it. - */ - ctx->active = FALSE; - if(ctx->sock[SP_LOCAL] == cf->conn->sock[cf->sockindex]) { - CURL_TRC_CF(data, cf, "cf_msh3_close(%d) active", - (int)ctx->sock[SP_LOCAL]); - cf->conn->sock[cf->sockindex] = CURL_SOCKET_BAD; - } - else { - CURL_TRC_CF(data, cf, "cf_socket_close(%d) no longer at " - "conn->sock[], discarding", (int)ctx->sock[SP_LOCAL]); - ctx->sock[SP_LOCAL] = CURL_SOCKET_BAD; - } - } - if(ctx->sock[SP_LOCAL] != CURL_SOCKET_BAD) { - sclose(ctx->sock[SP_LOCAL]); - } - if(ctx->sock[SP_REMOTE] != CURL_SOCKET_BAD) { - sclose(ctx->sock[SP_REMOTE]); - } - ctx->sock[SP_LOCAL] = CURL_SOCKET_BAD; - ctx->sock[SP_REMOTE] = CURL_SOCKET_BAD; - } - CF_DATA_RESTORE(cf, save); -} - -static void cf_msh3_destroy(struct Curl_cfilter *cf, struct Curl_easy *data) -{ - struct cf_call_data save; - - CF_DATA_SAVE(save, cf, data); - cf_msh3_close(cf, data); - if(cf->ctx) { - cf_msh3_ctx_free(cf->ctx); - cf->ctx = NULL; - } - /* no CF_DATA_RESTORE(cf, save); its gone */ -} - -static CURLcode cf_msh3_query(struct Curl_cfilter *cf, - struct Curl_easy *data, - int query, int *pres1, void *pres2) -{ - struct cf_msh3_ctx *ctx = cf->ctx; - - switch(query) { - case CF_QUERY_MAX_CONCURRENT: { - /* We do not have access to this so far, fake it */ - (void)ctx; - *pres1 = 100; - return CURLE_OK; - } - case CF_QUERY_TIMER_CONNECT: { - struct curltime *when = pres2; - /* we do not know when the first byte arrived */ - if(cf->connected) - *when = ctx->handshake_at; - return CURLE_OK; - } - case CF_QUERY_TIMER_APPCONNECT: { - struct curltime *when = pres2; - if(cf->connected) - *when = ctx->handshake_at; - return CURLE_OK; - } - case CF_QUERY_HTTP_VERSION: - *pres1 = 30; - return CURLE_OK; - default: - break; - } - return cf->next ? - cf->next->cft->query(cf->next, data, query, pres1, pres2) : - CURLE_UNKNOWN_OPTION; -} - -static bool cf_msh3_conn_is_alive(struct Curl_cfilter *cf, - struct Curl_easy *data, - bool *input_pending) -{ - struct cf_msh3_ctx *ctx = cf->ctx; - - (void)data; - *input_pending = FALSE; - return ctx && ctx->sock[SP_LOCAL] != CURL_SOCKET_BAD && ctx->qconn && - ctx->connected; -} - -struct Curl_cftype Curl_cft_http3 = { - "HTTP/3", - CF_TYPE_IP_CONNECT | CF_TYPE_SSL | CF_TYPE_MULTIPLEX | CF_TYPE_HTTP, - 0, - cf_msh3_destroy, - cf_msh3_connect, - cf_msh3_close, - Curl_cf_def_shutdown, - cf_msh3_adjust_pollset, - cf_msh3_data_pending, - cf_msh3_send, - cf_msh3_recv, - cf_msh3_data_event, - cf_msh3_conn_is_alive, - Curl_cf_def_conn_keep_alive, - cf_msh3_query, -}; - -static struct cf_msh3_ctx *h3_get_msh3_ctx(struct Curl_easy *data) -{ - if(data && data->conn) { - struct Curl_cfilter *cf = data->conn->cfilter[FIRSTSOCKET]; - while(cf) { - if(cf->cft == &Curl_cft_http3) - return cf->ctx; - cf = cf->next; - } - } - DEBUGF(infof(data, "no filter context found")); - return NULL; -} - -CURLcode Curl_cf_msh3_create(struct Curl_cfilter **pcf, - struct Curl_easy *data, - struct connectdata *conn, - const struct Curl_addrinfo *ai) -{ - struct cf_msh3_ctx *ctx = NULL; - struct Curl_cfilter *cf = NULL; - CURLcode result; - - (void)data; - (void)conn; - (void)ai; /* msh3 resolves itself? */ - ctx = calloc(1, sizeof(*ctx)); - if(!ctx) { - result = CURLE_OUT_OF_MEMORY; - goto out; - } - - result = cf_msh3_ctx_init(ctx, ai); - if(result) - goto out; - - result = Curl_cf_create(&cf, &Curl_cft_http3, ctx); - -out: - *pcf = (!result) ? cf : NULL; - if(result) { - Curl_safefree(cf); - cf_msh3_ctx_free(ctx); - } - - return result; -} - -bool Curl_conn_is_msh3(const struct Curl_easy *data, - const struct connectdata *conn, - int sockindex) -{ - struct Curl_cfilter *cf = conn ? conn->cfilter[sockindex] : NULL; - - (void)data; - for(; cf; cf = cf->next) { - if(cf->cft == &Curl_cft_http3) - return TRUE; - if(cf->cft->flags & CF_TYPE_IP_CONNECT) - return FALSE; - } - return FALSE; -} - -#endif /* USE_MSH3 */ diff --git a/lib/vquic/curl_msh3.h b/lib/vquic/curl_msh3.h deleted file mode 100644 index d2862c2d89..0000000000 --- a/lib/vquic/curl_msh3.h +++ /dev/null @@ -1,46 +0,0 @@ -#ifndef HEADER_CURL_VQUIC_CURL_MSH3_H -#define HEADER_CURL_VQUIC_CURL_MSH3_H -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) Daniel Stenberg, , 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" - -#ifdef USE_MSH3 - -#include - -void Curl_msh3_ver(char *p, size_t len); - -CURLcode Curl_cf_msh3_create(struct Curl_cfilter **pcf, - struct Curl_easy *data, - struct connectdata *conn, - const struct Curl_addrinfo *ai); - -bool Curl_conn_is_msh3(const struct Curl_easy *data, - const struct connectdata *conn, - int sockindex); - -#endif /* USE_MSQUIC */ - -#endif /* HEADER_CURL_VQUIC_CURL_MSH3_H */ diff --git a/lib/vquic/vquic.c b/lib/vquic/vquic.c index c686058ae8..3a55053720 100644 --- a/lib/vquic/vquic.c +++ b/lib/vquic/vquic.c @@ -35,7 +35,6 @@ #include "../curlx/dynbuf.h" #include "../cfilters.h" #include "../curl_trc.h" -#include "curl_msh3.h" #include "curl_ngtcp2.h" #include "curl_osslq.h" #include "curl_quiche.h" @@ -76,8 +75,6 @@ void Curl_quic_ver(char *p, size_t len) Curl_osslq_ver(p, len); #elif defined(USE_QUICHE) Curl_quiche_ver(p, len); -#elif defined(USE_MSH3) - Curl_msh3_ver(p, len); #endif } @@ -691,8 +688,6 @@ CURLcode Curl_cf_quic_create(struct Curl_cfilter **pcf, 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) - return Curl_cf_msh3_create(pcf, data, conn, ai); #else *pcf = NULL; (void)data; diff --git a/lib/vtls/openssl.c b/lib/vtls/openssl.c index ebe762a89a..76c4968d8b 100644 --- a/lib/vtls/openssl.c +++ b/lib/vtls/openssl.c @@ -219,8 +219,8 @@ static void ossl_provider_cleanup(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(OPENSSL_QUIC_API2)) || defined(USE_MSH3) +#elif (defined(USE_NGTCP2) && defined(USE_NGHTTP3) && \ + !defined(OPENSSL_QUIC_API2)) #define OSSL_PACKAGE "quictls" #else #define OSSL_PACKAGE "OpenSSL" diff --git a/tests/http/scorecard.py b/tests/http/scorecard.py index 8e0e6ce5f8..d6ff5dbfdf 100644 --- a/tests/http/scorecard.py +++ b/tests/http/scorecard.py @@ -586,7 +586,7 @@ class ScoreRunner: score['meta']['protocol'] = 'h3' if not self.env.have_h3_curl(): raise ScoreCardError('curl does not support HTTP/3') - for lib in ['ngtcp2', 'quiche', 'msh3', 'nghttp3']: + for lib in ['ngtcp2', 'quiche', 'nghttp3']: if self.env.curl_uses_lib(lib): score['meta']['implementation'] = lib break diff --git a/tests/http/test_02_download.py b/tests/http/test_02_download.py index c806452afc..405a5e006d 100644 --- a/tests/http/test_02_download.py +++ b/tests/http/test_02_download.py @@ -114,8 +114,6 @@ class TestDownload: def test_02_05_download_many_sequential(self, env: Env, httpd, nghttpx, proto): if proto == 'h3' and not env.have_h3(): pytest.skip("h3 not supported") - if proto == 'h3' and env.curl_uses_lib('msh3'): - pytest.skip("msh3 shaky here") if proto == 'h2' and env.curl_uses_lib('mbedtls') and \ sys.platform.startswith('darwin') and env.ci_run: pytest.skip('mbedtls 3.6.3 fails this test on macOS CI runners') @@ -220,8 +218,6 @@ class TestDownload: def test_02_11_10MB_parallel(self, env: Env, httpd, nghttpx, proto): if proto == 'h3' and not env.have_h3(): pytest.skip("h3 not supported") - if proto == 'h3' and env.curl_uses_lib('msh3'): - pytest.skip("msh3 stalls here") count = 3 urln = f'https://{env.authority_for(env.domain1, proto)}/data-10m?[0-{count-1}]' curl = CurlClient(env=env) @@ -258,8 +254,6 @@ class TestDownload: def test_02_14_not_found(self, env: Env, httpd, nghttpx, proto): if proto == 'h3' and not env.have_h3(): pytest.skip("h3 not supported") - if proto == 'h3' and env.curl_uses_lib('msh3'): - pytest.skip("msh3 stalls here") count = 5 urln = f'https://{env.authority_for(env.domain1, proto)}/not-found?[0-{count-1}]' curl = CurlClient(env=env) @@ -274,8 +268,6 @@ class TestDownload: def test_02_15_fail_not_found(self, env: Env, httpd, nghttpx, proto): if proto == 'h3' and not env.have_h3(): pytest.skip("h3 not supported") - if proto == 'h3' and env.curl_uses_lib('msh3'): - pytest.skip("msh3 stalls here") count = 5 urln = f'https://{env.authority_for(env.domain1, proto)}/not-found?[0-{count-1}]' curl = CurlClient(env=env) diff --git a/tests/http/test_03_goaway.py b/tests/http/test_03_goaway.py index 9a7ebbab4e..2688210a84 100644 --- a/tests/http/test_03_goaway.py +++ b/tests/http/test_03_goaway.py @@ -74,8 +74,6 @@ class TestGoAway: @pytest.mark.skipif(condition=not Env.have_h3(), reason="h3 not supported") def test_03_02_h3_goaway(self, env: Env, httpd, nghttpx): proto = 'h3' - if proto == 'h3' and env.curl_uses_lib('msh3'): - pytest.skip("msh3 stalls here") if proto == 'h3' and env.curl_uses_ossl_quic(): pytest.skip('OpenSSL QUIC fails here') count = 3 diff --git a/tests/http/test_05_errors.py b/tests/http/test_05_errors.py index f6aae1ad15..d24879b3ac 100644 --- a/tests/http/test_05_errors.py +++ b/tests/http/test_05_errors.py @@ -42,8 +42,6 @@ class TestErrors: def test_05_01_partial_1(self, env: Env, httpd, nghttpx, proto): if proto == 'h3' and not env.have_h3(): pytest.skip("h3 not supported") - if proto == 'h3' and env.curl_uses_lib('msh3'): - pytest.skip("msh3 stalls here") count = 1 curl = CurlClient(env=env) urln = f'https://{env.authority_for(env.domain1, proto)}' \ @@ -66,8 +64,6 @@ class TestErrors: pytest.skip("h3 not supported") if proto == 'h3' and env.curl_uses_ossl_quic(): pytest.skip("openssl-quic is flaky in yielding proper error codes") - if proto == 'h3' and env.curl_uses_lib('msh3'): - pytest.skip("msh3 stalls here") count = 20 curl = CurlClient(env=env) urln = f'https://{env.authority_for(env.domain1, proto)}' \ diff --git a/tests/http/test_07_upload.py b/tests/http/test_07_upload.py index 56adeffdae..ae6f0ab9ed 100644 --- a/tests/http/test_07_upload.py +++ b/tests/http/test_07_upload.py @@ -55,8 +55,6 @@ class TestUpload: def test_07_01_upload_1_small(self, env: Env, httpd, nghttpx, proto): if proto == 'h3' and not env.have_h3(): pytest.skip("h3 not supported") - if proto == 'h3' and env.curl_uses_lib('msh3'): - pytest.skip("msh3 fails here") data = '0123456789' curl = CurlClient(env=env) url = f'https://{env.authority_for(env.domain1, proto)}/curltest/echo?id=[0-0]' @@ -70,8 +68,6 @@ class TestUpload: def test_07_02_upload_1_large(self, env: Env, httpd, nghttpx, proto): if proto == 'h3' and not env.have_h3(): pytest.skip("h3 not supported") - if proto == 'h3' and env.curl_uses_lib('msh3'): - pytest.skip("msh3 fails here") fdata = os.path.join(env.gen_dir, 'data-100k') curl = CurlClient(env=env) url = f'https://{env.authority_for(env.domain1, proto)}/curltest/echo?id=[0-0]' @@ -86,8 +82,6 @@ class TestUpload: def test_07_10_upload_sequential(self, env: Env, httpd, nghttpx, proto): if proto == 'h3' and not env.have_h3(): pytest.skip("h3 not supported") - if proto == 'h3' and env.curl_uses_lib('msh3'): - pytest.skip("msh3 stalls here") count = 20 data = '0123456789' curl = CurlClient(env=env) @@ -103,8 +97,6 @@ class TestUpload: def test_07_11_upload_parallel(self, env: Env, httpd, nghttpx, proto): if proto == 'h3' and not env.have_h3(): pytest.skip("h3 not supported") - if proto == 'h3' and env.curl_uses_lib('msh3'): - pytest.skip("msh3 stalls here") # limit since we use a separate connection in h1 count = 20 data = '0123456789' @@ -122,8 +114,6 @@ class TestUpload: def test_07_12_upload_seq_large(self, env: Env, httpd, nghttpx, proto): if proto == 'h3' and not env.have_h3(): pytest.skip("h3 not supported") - if proto == 'h3' and env.curl_uses_lib('msh3'): - pytest.skip("msh3 stalls here") fdata = os.path.join(env.gen_dir, 'data-100k') count = 10 curl = CurlClient(env=env) @@ -141,8 +131,6 @@ class TestUpload: def test_07_13_upload_seq_large(self, env: Env, httpd, nghttpx, proto): if proto == 'h3' and not env.have_h3(): pytest.skip("h3 not supported") - if proto == 'h3' and env.curl_uses_lib('msh3'): - pytest.skip("msh3 stalls here") fdata = os.path.join(env.gen_dir, 'data-10m') count = 2 curl = CurlClient(env=env) @@ -162,8 +150,6 @@ class TestUpload: def test_07_14_upload_stdin(self, env: Env, httpd, nghttpx, proto, indata): if proto == 'h3' and not env.have_h3(): pytest.skip("h3 not supported") - if proto == 'h3' and env.curl_uses_lib('msh3'): - pytest.skip("msh3 stalls here") count = 1 curl = CurlClient(env=env) url = f'https://{env.authority_for(env.domain1, proto)}/curltest/put?id=[0-{count-1}]' @@ -226,8 +212,6 @@ class TestUpload: def test_07_20_upload_parallel(self, env: Env, httpd, nghttpx, proto): if proto == 'h3' and not env.have_h3(): pytest.skip("h3 not supported") - if proto == 'h3' and env.curl_uses_lib('msh3'): - pytest.skip("msh3 stalls here") # limit since we use a separate connection in h1 count = 10 data = '0123456789' @@ -245,8 +229,6 @@ class TestUpload: def test_07_21_upload_parallel_large(self, env: Env, httpd, nghttpx, proto): if proto == 'h3' and not env.have_h3(): pytest.skip("h3 not supported") - if proto == 'h3' and env.curl_uses_lib('msh3'): - pytest.skip("msh3 stalls here") fdata = os.path.join(env.gen_dir, 'data-100k') # limit since we use a separate connection in h1 count = 10 @@ -262,8 +244,6 @@ class TestUpload: def test_07_22_upload_parallel_fail(self, env: Env, httpd, nghttpx, proto): if proto == 'h3' and not env.have_h3(): pytest.skip("h3 not supported") - if proto == 'h3' and env.curl_uses_lib('msh3'): - pytest.skip("msh3 stalls here") fdata = os.path.join(env.gen_dir, 'data-10m') count = 20 curl = CurlClient(env=env) @@ -280,8 +260,6 @@ class TestUpload: def test_07_30_put_100k(self, env: Env, httpd, nghttpx, proto): if proto == 'h3' and not env.have_h3(): pytest.skip("h3 not supported") - if proto == 'h3' and env.curl_uses_lib('msh3'): - pytest.skip("msh3 fails here") fdata = os.path.join(env.gen_dir, 'data-100k') count = 1 curl = CurlClient(env=env) @@ -300,8 +278,6 @@ class TestUpload: def test_07_31_put_10m(self, env: Env, httpd, nghttpx, proto): if proto == 'h3' and not env.have_h3(): pytest.skip("h3 not supported") - if proto == 'h3' and env.curl_uses_lib('msh3'): - pytest.skip("msh3 fails here") fdata = os.path.join(env.gen_dir, 'data-10m') count = 1 curl = CurlClient(env=env) @@ -320,8 +296,6 @@ class TestUpload: def test_07_32_issue_10591(self, env: Env, httpd, nghttpx, proto): if proto == 'h3' and not env.have_h3(): pytest.skip("h3 not supported") - if proto == 'h3' and env.curl_uses_lib('msh3'): - pytest.skip("msh3 fails here") fdata = os.path.join(env.gen_dir, 'data-10m') count = 1 curl = CurlClient(env=env) @@ -416,8 +390,6 @@ class TestUpload: pytest.skip("h3 not supported") if proto == 'h3' and env.curl_uses_ossl_quic(): pytest.skip("OpenSSL's own QUIC is flaky here") - if proto == 'h3' and env.curl_uses_lib('msh3'): - pytest.skip("msh3 fails here") data = '0123456789' * 10 curl = CurlClient(env=env) url = f'https://{env.authority_for(env.domain1, proto)}/curltest/echo{redir}?id=[0-0]' @@ -435,8 +407,6 @@ class TestUpload: pytest.skip("h3 not supported") if proto == 'h3' and env.curl_uses_ossl_quic(): pytest.skip("OpenSSL's own QUIC is flaky here") - if proto == 'h3' and env.curl_uses_lib('msh3'): - pytest.skip("msh3 fails here") data = '0123456789' * 10 curl = CurlClient(env=env) url = f'https://{env.authority_for(env.domain1, proto)}/curltest/echo307?id=[0-0]' @@ -452,8 +422,6 @@ class TestUpload: def test_07_38_form_small(self, env: Env, httpd, nghttpx, proto): if proto == 'h3' and not env.have_h3(): pytest.skip("h3 not supported") - if proto == 'h3' and env.curl_uses_lib('msh3'): - pytest.skip("msh3 fails here") curl = CurlClient(env=env) url = f'https://{env.authority_for(env.domain1, proto)}/curltest/echo?id=[0-0]' r = curl.http_form(urls=[url], alpn_proto=proto, form={ @@ -466,8 +434,6 @@ class TestUpload: def test_07_39_post_urlenc_small(self, env: Env, httpd, nghttpx, proto): if proto == 'h3' and not env.have_h3(): pytest.skip("h3 not supported") - if proto == 'h3' and env.curl_uses_lib('msh3'): - pytest.skip("msh3 fails here") fdata = os.path.join(env.gen_dir, 'data-63k') curl = CurlClient(env=env) url = f'https://{env.authority_for(env.domain1, proto)}/curltest/echo?id=[0-0]' @@ -484,8 +450,6 @@ class TestUpload: def test_07_40_post_urlenc_large(self, env: Env, httpd, nghttpx, proto): if proto == 'h3' and not env.have_h3(): pytest.skip("h3 not supported") - if proto == 'h3' and env.curl_uses_lib('msh3'): - pytest.skip("msh3 fails here") fdata = os.path.join(env.gen_dir, 'data-64k') curl = CurlClient(env=env) url = f'https://{env.authority_for(env.domain1, proto)}/curltest/echo?id=[0-0]' @@ -506,8 +470,6 @@ class TestUpload: def test_07_41_post_urlenc_small(self, env: Env, httpd, nghttpx, proto): if proto == 'h3' and not env.have_h3(): pytest.skip("h3 not supported") - if proto == 'h3' and env.curl_uses_lib('msh3'): - pytest.skip("msh3 fails here") if proto == 'h3' and env.curl_uses_lib('quiche'): pytest.skip("quiche has CWND issues with large requests") fdata = os.path.join(env.gen_dir, 'data-63k') @@ -541,8 +503,6 @@ class TestUpload: def test_07_42a_upload_disconnect(self, env: Env, httpd, nghttpx, proto): if proto == 'h3' and not env.have_h3(): pytest.skip("h3 not supported") - if proto == 'h3' and env.curl_uses_lib('msh3'): - pytest.skip("msh3 fails here") client = LocalClient(name='upload_pausing', env=env, timeout=60) if not client.exists(): pytest.skip(f'example client not built: {client.name}') @@ -563,8 +523,6 @@ class TestUpload: def test_07_42b_upload_disconnect(self, env: Env, httpd, nghttpx, proto): if proto == 'h3' and not env.have_h3(): pytest.skip("h3 not supported") - if proto == 'h3' and env.curl_uses_lib('msh3'): - pytest.skip("msh3 fails here") client = LocalClient(name='upload_pausing', env=env, timeout=60) if not client.exists(): pytest.skip(f'example client not built: {client.name}') @@ -580,8 +538,6 @@ class TestUpload: def test_07_42c_upload_disconnect(self, env: Env, httpd, nghttpx, proto): if proto == 'h3' and not env.have_h3(): pytest.skip("h3 not supported") - if proto == 'h3' and env.curl_uses_lib('msh3'): - pytest.skip("msh3 fails here") client = LocalClient(name='upload_pausing', env=env, timeout=60) if not client.exists(): pytest.skip(f'example client not built: {client.name}') @@ -598,8 +554,6 @@ class TestUpload: pytest.skip("h3 not supported") if proto == 'h3' and env.curl_uses_ossl_quic(): pytest.skip("openssl-quic is flaky in filed PUTs") - if proto == 'h3' and env.curl_uses_lib('msh3'): - pytest.skip("msh3 fails here") fdata = os.path.join(env.gen_dir, 'data-10m') count = 1 max_upload = 128 * 1024 diff --git a/tests/http/test_08_caddy.py b/tests/http/test_08_caddy.py index 3c62de886b..679cd84988 100644 --- a/tests/http/test_08_caddy.py +++ b/tests/http/test_08_caddy.py @@ -72,8 +72,6 @@ class TestCaddy: def test_08_01_download_1(self, env: Env, caddy: Caddy, proto): if proto == 'h3' and not env.have_h3_curl(): pytest.skip("h3 not supported in curl") - if proto == 'h3' and env.curl_uses_lib('msh3'): - pytest.skip("msh3 itself crashes") curl = CurlClient(env=env) url = f'https://{env.domain1}:{caddy.port}/data.json' r = curl.http_download(urls=[url], alpn_proto=proto) @@ -84,8 +82,6 @@ class TestCaddy: def test_08_02_download_1mb_sequential(self, env: Env, caddy: Caddy, proto): if proto == 'h3' and not env.have_h3_curl(): pytest.skip("h3 not supported in curl") - if proto == 'h3' and env.curl_uses_lib('msh3'): - pytest.skip("msh3 itself crashes") count = 50 curl = CurlClient(env=env) urln = f'https://{env.domain1}:{caddy.port}/data1.data?[0-{count-1}]' @@ -97,8 +93,6 @@ class TestCaddy: def test_08_03_download_1mb_parallel(self, env: Env, caddy: Caddy, proto): if proto == 'h3' and not env.have_h3_curl(): pytest.skip("h3 not supported in curl") - if proto == 'h3' and env.curl_uses_lib('msh3'): - pytest.skip("msh3 itself crashes") count = 20 curl = CurlClient(env=env) urln = f'https://{env.domain1}:{caddy.port}/data1.data?[0-{count-1}]' @@ -119,8 +113,6 @@ class TestCaddy: def test_08_04a_download_10mb_sequential(self, env: Env, caddy: Caddy, proto): if proto == 'h3' and not env.have_h3_curl(): pytest.skip("h3 not supported in curl") - if proto == 'h3' and env.curl_uses_lib('msh3'): - pytest.skip("msh3 itself crashes") count = 40 curl = CurlClient(env=env) urln = f'https://{env.domain1}:{caddy.port}/data5.data?[0-{count-1}]' @@ -134,8 +126,6 @@ class TestCaddy: def test_08_04b_download_10mb_sequential(self, env: Env, caddy: Caddy, proto): if proto == 'h3' and not env.have_h3_curl(): pytest.skip("h3 not supported in curl") - if proto == 'h3' and env.curl_uses_lib('msh3'): - pytest.skip("msh3 itself crashes") count = 20 curl = CurlClient(env=env) urln = f'https://{env.domain1}:{caddy.port}/data10.data?[0-{count-1}]' @@ -149,8 +139,6 @@ class TestCaddy: def test_08_05_download_1mb_parallel(self, env: Env, caddy: Caddy, proto): if proto == 'h3' and not env.have_h3_curl(): pytest.skip("h3 not supported in curl") - if proto == 'h3' and env.curl_uses_lib('msh3'): - pytest.skip("msh3 itself crashes") if proto == 'http/1.1' and env.curl_uses_lib('mbedtls'): pytest.skip("mbedtls 3.6.0 fails on 50 connections with: " "ssl_handshake returned: (-0x7F00) SSL - Memory allocation failed") @@ -172,8 +160,6 @@ class TestCaddy: def test_08_06_post_parallel(self, env: Env, httpd, caddy, proto): if proto == 'h3' and not env.have_h3(): pytest.skip("h3 not supported") - if proto == 'h3' and env.curl_uses_lib('msh3'): - pytest.skip("msh3 stalls here") # limit since we use a separate connection in h1 count = 20 data = '0123456789' @@ -191,8 +177,6 @@ class TestCaddy: def test_08_07_put_large(self, env: Env, httpd, caddy, proto): if proto == 'h3' and not env.have_h3(): pytest.skip("h3 not supported") - if proto == 'h3' and env.curl_uses_lib('msh3'): - pytest.skip("msh3 stalls here") # limit since we use a separate connection in h1< count = 1 fdata = os.path.join(env.gen_dir, 'data-10m') diff --git a/winbuild/Makefile.vc b/winbuild/Makefile.vc index 1f1e6d550c..1a202cb559 100644 --- a/winbuild/Makefile.vc +++ b/winbuild/Makefile.vc @@ -164,23 +164,6 @@ NGHTTP2 = static USE_NGHTTP2 = false !ENDIF -!IF "$(ENABLE_MSH3)"=="yes" -# compatibility bit, WITH_MSH3 is the correct flag -WITH_MSH3 = dll -USE_MSH3 = true -MSH3 = dll -!ELSEIF "$(WITH_MSH3)"=="dll" -USE_MSH3 = true -MSH3 = dll -!ELSEIF "$(WITH_MSH3)"=="static" -USE_MSH3 = true -MSH3 = static -!ENDIF - -!IFNDEF USE_MSH3 -USE_MSH3 = false -!ENDIF - !IF "$(WITH_MBEDTLS)"=="dll" || "$(WITH_MBEDTLS)"=="static" USE_MBEDTLS = true MBEDTLS = $(WITH_MBEDTLS) @@ -281,10 +264,6 @@ CONFIG_NAME_LIB = $(CONFIG_NAME_LIB)-schannel CONFIG_NAME_LIB = $(CONFIG_NAME_LIB)-nghttp2-$(NGHTTP2) !ENDIF -!IF "$(USE_MSH3)"=="true" -CONFIG_NAME_LIB = $(CONFIG_NAME_LIB)-msh3 -!ENDIF - !MESSAGE configuration name: $(CONFIG_NAME_LIB) # Note these directories are removed by this makefile's 'clean' so they should @@ -308,7 +287,6 @@ $(MODE): @SET CONFIG_NAME_LIB=$(CONFIG_NAME_LIB) @SET MACHINE=$(MACHINE) @SET USE_NGHTTP2=$(USE_NGHTTP2) - @SET USE_MSH3=$(USE_MSH3) @SET USE_IDN=$(USE_IDN) @SET USE_IPV6=$(USE_IPV6) @SET USE_SSPI=$(USE_SSPI) diff --git a/winbuild/MakefileBuild.vc b/winbuild/MakefileBuild.vc index 1d8ffcc736..8d1dd28881 100644 --- a/winbuild/MakefileBuild.vc +++ b/winbuild/MakefileBuild.vc @@ -171,27 +171,6 @@ NGHTTP2_LIBS = nghttp2.lib !ENDIF !ENDIF -!IFDEF MSH3_PATH -MSH3_INC_DIR = $(MSH3_PATH)\include -MSH3_LIB_DIR = $(MSH3_PATH)\lib -MSH3_LFLAGS = $(MSH3_LFLAGS) "/LIBPATH:$(MSH3_LIB_DIR)" -!ELSE -MSH3_INC_DIR = $(DEVEL_INCLUDE) -MSH3_LIB_DIR = $(DEVEL_LIB) -!ENDIF - -!IF "$(WITH_MSH3)"=="dll" -MSH3_CFLAGS = /DUSE_MSH3 /I"$(MSH3_INC_DIR)" -MSH3_LIBS = msh3.lib -!ELSEIF "$(WITH_MSH3)"=="static" -MSH3_CFLAGS = /DUSE_MSH3 /DMSH3_STATICLIB /I"$(MSH3_INC_DIR)" -!IF EXISTS("$(NGHTTP2_LIB_DIR)\msh3_static.lib") -MSH3_LIBS = msh3_static.lib -!ELSE -MSH3_LIBS = msh3.lib -!ENDIF -!ENDIF - !IFDEF MBEDTLS_PATH MBEDTLS_INC_DIR = $(MBEDTLS_PATH)\include MBEDTLS_LIB_DIR = $(MBEDTLS_PATH)\lib @@ -540,11 +519,6 @@ CFLAGS = $(CFLAGS) $(NGHTTP2_CFLAGS) LFLAGS = $(LFLAGS) $(NGHTTP2_LFLAGS) $(NGHTTP2_LIBS) !ENDIF -!IF "$(USE_MSH3)"=="true" -CFLAGS = $(CFLAGS) $(MSH3_CFLAGS) -LFLAGS = $(LFLAGS) $(MSH3_LFLAGS) $(MSH3_LIBS) -!ENDIF - !IF "$(GEN_PDB)"=="true" CFLAGS = $(CFLAGS) $(CFLAGS_PDB) /Fd"$(LIB_DIROBJ)\$(PDB)" LFLAGS = $(LFLAGS) $(LFLAGS_PDB) @@ -601,7 +575,6 @@ package: $(TARGET) $(TARGET): $(LIB_OBJS) $(LIB_DIROBJ) $(DIRDIST) @echo Using SSL: $(USE_SSL) @echo Using NGHTTP2: $(USE_NGHTTP2) - @echo Using MSH3: $(USE_MSH3) @echo Using c-ares: $(USE_CARES) @echo Using SSH2: $(USE_SSH2) @echo Using SSH: $(USE_SSH) diff --git a/winbuild/README.md b/winbuild/README.md index 3667587a0d..691e2dbc8d 100644 --- a/winbuild/README.md +++ b/winbuild/README.md @@ -80,7 +80,6 @@ where `` is one or many of: Defaults to sibling directory: `../deps` - `WITH_SSL=` - Enable OpenSSL support, DLL or static - `WITH_NGHTTP2=` - Enable HTTP/2 support, DLL or static - - `WITH_MSH3=` - Enable (experimental) HTTP/3 support, DLL or static - `WITH_MBEDTLS=` - Enable mbedTLS support, DLL or static - `WITH_WOLFSSL=` - Enable wolfSSL support, DLL or static - `WITH_CARES=` - Enable c-ares support, DLL or static @@ -106,7 +105,6 @@ where `` is one or many of: - `MBEDTLS_PATH=` - Custom path for mbedTLS - `WOLFSSL_PATH=` - Custom path for wolfSSL - `NGHTTP2_PATH=` - Custom path for nghttp2 - - `MSH3_PATH=` - Custom path for msh3 - `SSH_PATH=` - Custom path for libssh - `SSH2_PATH=` - Custom path for libssh2 - `SSL_PATH=` - Custom path for OpenSSL -- 2.47.2