summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2023-11-05 10:02:47 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2023-11-05 10:02:47 +0000
commitaaaca4aff27689abcae851c4caea1cdb06e03acb (patch)
treef4881338d3525d6890f65a916bf2caae1fae1bb3
parentAdding debian version 1.57.0-1. (diff)
downloadnghttp2-aaaca4aff27689abcae851c4caea1cdb06e03acb.tar.xz
nghttp2-aaaca4aff27689abcae851c4caea1cdb06e03acb.zip
Merging upstream version 1.58.0.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
-rw-r--r--.github/workflows/build.yml4
-rw-r--r--AUTHORS1
-rw-r--r--CMakeLists.txt75
-rw-r--r--Makefile.am4
-rw-r--r--README.rst16
-rw-r--r--cmake/PickyWarningsC.cmake163
-rw-r--r--cmake/PickyWarningsCXX.cmake117
-rw-r--r--configure.ac12
-rw-r--r--doc/h2load.12
-rw-r--r--doc/nghttp.12
-rw-r--r--doc/nghttpd.12
-rw-r--r--doc/nghttpx.16
-rw-r--r--doc/nghttpx.1.rst4
-rw-r--r--doc/sources/security.rst17
-rw-r--r--docker/Dockerfile4
-rw-r--r--go.mod6
-rw-r--r--go.sum12
-rw-r--r--integration-tests/CMakeLists.txt7
-rw-r--r--integration-tests/Makefile.am3
-rw-r--r--integration-tests/nghttpx_http1_test.go139
-rw-r--r--integration-tests/server_tester.go76
-rw-r--r--integration-tests/server_tester_http3.go90
-rw-r--r--lib/nghttp2_map.c2
-rw-r--r--lib/nghttp2_map.h2
-rw-r--r--lib/nghttp2_time.c14
-rw-r--r--src/http2.cc129
-rw-r--r--src/http2.h5
-rw-r--r--src/http2_test.cc57
-rw-r--r--src/http2_test.h1
-rw-r--r--src/shrpx-unittest.cc2
-rw-r--r--src/shrpx.cc9
-rw-r--r--src/shrpx_config.cc4
-rw-r--r--src/shrpx_downstream.cc6
-rw-r--r--src/shrpx_http3_upstream.cc20
-rw-r--r--src/shrpx_http3_upstream.h1
-rw-r--r--src/shrpx_http_downstream_connection.cc15
-rw-r--r--src/shrpx_https_upstream.cc15
-rw-r--r--src/util.cc68
-rw-r--r--tests/Makefile.am1
39 files changed, 881 insertions, 232 deletions
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 262c471..9d87efa 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -9,8 +9,8 @@ env:
OPENSSL1_VERSION: 1_1_1w+quic
OPENSSL3_VERSION: 3.1.2+quic
BORINGSSL_VERSION: 6ca49385b168f47a50e7172d82a590b218f55e4d
- NGHTTP3_VERSION: v0.15.0
- NGTCP2_VERSION: v0.19.1
+ NGHTTP3_VERSION: v1.0.0
+ NGTCP2_VERSION: v1.0.1
jobs:
build-cache:
diff --git a/AUTHORS b/AUTHORS
index 8bcf579..bb1ae74 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -17,6 +17,7 @@ github issues [2].
Adam Gołębiowski
Alek Storm
Alex Nalivko
+Alexandr Vlasov
Alexandros Konstantinakis-Karmis
Alexis La Goutte
Amir Livneh
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 42ec478..2c4139d 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -24,12 +24,12 @@
cmake_minimum_required(VERSION 3.0)
# XXX using 1.8.90 instead of 1.9.0-DEV
-project(nghttp2 VERSION 1.57.0)
+project(nghttp2 VERSION 1.58.0)
# See versioning rule:
# https://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html
set(LT_CURRENT 39)
-set(LT_REVISION 0)
+set(LT_REVISION 1)
set(LT_AGE 25)
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH})
@@ -343,74 +343,12 @@ if(CMAKE_C_COMPILER_ID MATCHES "MSVC")
endif()
else()
if(ENABLE_WERROR)
- extract_valid_c_flags(WARNCFLAGS -Werror)
- extract_valid_c_flags(WARNCXXFLAGS -Werror)
+ set(WARNCFLAGS "-Werror")
+ set(WARNCXXFLAGS "-Werror")
endif()
- # For C compiler
- extract_valid_c_flags(WARNCFLAGS
- -Wall
- -Wextra
- -Wmissing-prototypes
- -Wstrict-prototypes
- -Wmissing-declarations
- -Wpointer-arith
- -Wdeclaration-after-statement
- -Wformat-security
- -Wwrite-strings
- -Wshadow
- -Winline
- -Wnested-externs
- -Wfloat-equal
- -Wundef
- -Wendif-labels
- -Wempty-body
- -Wcast-align
- -Wclobbered
- -Wvla
- -Wpragmas
- -Wunreachable-code
- -Waddress
- -Wattributes
- -Wdiv-by-zero
- -Wshorten-64-to-32
-
- -Wconversion
- -Wextended-offsetof
- -Wformat-nonliteral
- -Wlanguage-extension-token
- -Wmissing-field-initializers
- -Wmissing-noreturn
- -Wmissing-variable-declarations
- # Not used because we cannot change public structs
- # -Wpadded
- -Wsign-conversion
- # Not used because this basically disallows default case
- # -Wswitch-enum
- -Wunreachable-code-break
- -Wunused-macros
- -Wunused-parameter
- -Wredundant-decls
- # Only work with Clang for the moment
- -Wheader-guard
- # This is required because we pass format string as "const char*.
- -Wno-format-nonliteral
- )
-
- extract_valid_cxx_flags(WARNCXXFLAGS
- # For C++ compiler
- -Wall
- -Wformat-security
- )
-endif()
-
-if(ENABLE_STATIC_CRT)
- foreach(lang C CXX)
- foreach(suffix "" _DEBUG _MINSIZEREL _RELEASE _RELWITHDEBINFO)
- set(var "CMAKE_${lang}_FLAGS${suffix}")
- string(REPLACE "/MD" "/MT" ${var} "${${var}}")
- endforeach()
- endforeach()
+ include(PickyWarningsC)
+ include(PickyWarningsCXX)
endif()
if(ENABLE_DEBUG)
@@ -506,6 +444,7 @@ message(STATUS "summary of build options:
CXXFLAGS: ${CMAKE_CXX_FLAGS_${_build_type}} ${CMAKE_CXX_FLAGS}
WARNCFLAGS: ${WARNCFLAGS}
CXX1XCXXFLAGS: ${CXX1XCXXFLAGS}
+ WARNCXXFLAGS: ${WARNCXXFLAGS}
Python:
Python: ${Python3_EXECUTABLE}
Python3_VERSION: ${Python3_VERSION}
diff --git a/Makefile.am b/Makefile.am
index 894165b..683b989 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -44,7 +44,9 @@ EXTRA_DIST = nghttpx.conf.sample proxy.pac.sample android-config android-env \
cmake/FindLibbpf.cmake \
cmake/FindLibnghttp3.cmake \
cmake/FindLibngtcp2.cmake \
- cmake/FindLibngtcp2_crypto_quictls.cmake
+ cmake/FindLibngtcp2_crypto_quictls.cmake \
+ cmake/PickyWarningsC.cmake \
+ cmake/PickyWarningsCXX.cmake
.PHONY: clang-format
diff --git a/README.rst b/README.rst
index a513759..1934341 100644
--- a/README.rst
+++ b/README.rst
@@ -130,8 +130,8 @@ following libraries are required:
<https://github.com/quictls/openssl/tree/OpenSSL_1_1_1w+quic>`_; or
`BoringSSL <https://boringssl.googlesource.com/boringssl/>`_ (commit
6ca49385b168f47a50e7172d82a590b218f55e4d)
-* `ngtcp2 <https://github.com/ngtcp2/ngtcp2>`_ 0.19.x
-* `nghttp3 <https://github.com/ngtcp2/nghttp3>`_ 0.15.x
+* `ngtcp2 <https://github.com/ngtcp2/ngtcp2>`_ >= 1.0.0
+* `nghttp3 <https://github.com/ngtcp2/nghttp3>`_ >= 1.0.0
Use ``--enable-http3`` configure option to enable HTTP/3 feature for
h2load and nghttpx.
@@ -354,7 +354,7 @@ Build nghttp3:
.. code-block:: text
- $ git clone --depth 1 -b v0.15.0 https://github.com/ngtcp2/nghttp3
+ $ git clone --depth 1 -b v1.0.0 https://github.com/ngtcp2/nghttp3
$ cd nghttp3
$ autoreconf -i
$ ./configure --prefix=$PWD/build --enable-lib-only
@@ -366,7 +366,7 @@ Build ngtcp2:
.. code-block:: text
- $ git clone --depth 1 -b v0.19.1 https://github.com/ngtcp2/ngtcp2
+ $ git clone --depth 1 -b v1.0.1 https://github.com/ngtcp2/ngtcp2
$ cd ngtcp2
$ autoreconf -i
$ ./configure --prefix=$PWD/build --enable-lib-only \
@@ -1456,12 +1456,10 @@ released, or mitigation is worked out.
In the future, we may setup a dedicated mail address for this purpose.
-Release schedule
-----------------
+Versioning
+----------
-In general, we follow `Semantic Versioning <http://semver.org/>`_. We
-release MINOR version update every month, and usually we ship it
-around 25th day of every month.
+In general, we follow `Semantic Versioning <http://semver.org/>`_.
We may release PATCH releases between the regular releases, mainly for
severe security bug fixes.
diff --git a/cmake/PickyWarningsC.cmake b/cmake/PickyWarningsC.cmake
new file mode 100644
index 0000000..50eb789
--- /dev/null
+++ b/cmake/PickyWarningsC.cmake
@@ -0,0 +1,163 @@
+# nghttp2
+#
+# Copyright (c) 2023 nghttp2 contributors
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+# C
+
+include(CheckCCompilerFlag)
+
+if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX OR CMAKE_C_COMPILER_ID MATCHES "Clang")
+
+ # https://clang.llvm.org/docs/DiagnosticsReference.html
+ # https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html
+
+ # WPICKY_ENABLE = Options we want to enable as-is.
+ # WPICKY_DETECT = Options we want to test first and enable if available.
+
+ # Prefer the -Wextra alias with clang.
+ if(CMAKE_C_COMPILER_ID MATCHES "Clang")
+ set(WPICKY_ENABLE "-Wextra")
+ else()
+ set(WPICKY_ENABLE "-W")
+ endif()
+
+ list(APPEND WPICKY_ENABLE
+ -Wall
+ )
+
+ # ----------------------------------
+ # Add new options here, if in doubt:
+ # ----------------------------------
+ set(WPICKY_DETECT
+ )
+
+ # Assume these options always exist with both clang and gcc.
+ # Require clang 3.0 / gcc 2.95 or later.
+ list(APPEND WPICKY_ENABLE
+ -Wconversion # clang 3.0 gcc 2.95
+ -Winline # clang 1.0 gcc 1.0
+ -Wmissing-declarations # clang 1.0 gcc 2.7
+ -Wmissing-prototypes # clang 1.0 gcc 1.0
+ -Wnested-externs # clang 1.0 gcc 2.7
+ -Wpointer-arith # clang 1.0 gcc 1.4
+ -Wshadow # clang 1.0 gcc 2.95
+ -Wundef # clang 1.0 gcc 2.95
+ -Wwrite-strings # clang 1.0 gcc 1.4
+ )
+
+ # Always enable with clang, version dependent with gcc
+ set(WPICKY_COMMON_OLD
+ -Waddress # clang 3.0 gcc 4.3
+ -Wattributes # clang 3.0 gcc 4.1
+ -Wcast-align # clang 1.0 gcc 4.2
+ -Wdeclaration-after-statement # clang 1.0 gcc 3.4
+ -Wdiv-by-zero # clang 3.0 gcc 4.1
+ -Wempty-body # clang 3.0 gcc 4.3
+ -Wendif-labels # clang 1.0 gcc 3.3
+ -Wfloat-equal # clang 1.0 gcc 2.96 (3.0)
+ -Wformat-nonliteral # clang 3.0 gcc 4.1
+ -Wformat-security # clang 3.0 gcc 4.1
+ -Wmissing-field-initializers # clang 3.0 gcc 4.1
+ -Wmissing-noreturn # clang 3.0 gcc 4.1
+ -Wno-format-nonliteral # clang 1.0 gcc 2.96 (3.0) # This is required because we pass format string as "const char*"
+ # -Wpadded # clang 3.0 gcc 4.1 # Not used because we cannot change public structs
+ -Wredundant-decls # clang 3.0 gcc 4.1
+ -Wsign-conversion # clang 3.0 gcc 4.3
+ -Wstrict-prototypes # clang 1.0 gcc 3.3
+ # -Wswitch-enum # clang 3.0 gcc 4.1 # Not used because this basically disallows default case
+ -Wunreachable-code # clang 3.0 gcc 4.1
+ -Wunused-macros # clang 3.0 gcc 4.1
+ -Wunused-parameter # clang 3.0 gcc 4.1
+ -Wvla # clang 2.8 gcc 4.3
+ )
+
+ set(WPICKY_COMMON
+ -Wpragmas # clang 3.5 gcc 4.1 appleclang 6.0
+ )
+
+ if(CMAKE_C_COMPILER_ID MATCHES "Clang")
+ list(APPEND WPICKY_ENABLE
+ ${WPICKY_COMMON_OLD}
+ -Wshorten-64-to-32 # clang 1.0
+ -Wlanguage-extension-token # clang 3.0
+ )
+ # Enable based on compiler version
+ if((CMAKE_C_COMPILER_ID STREQUAL "Clang" AND NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 3.6) OR
+ (CMAKE_C_COMPILER_ID STREQUAL "AppleClang" AND NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 6.3))
+ list(APPEND WPICKY_ENABLE
+ ${WPICKY_COMMON}
+ -Wunreachable-code-break # clang 3.5 appleclang 6.0
+ -Wheader-guard # clang 3.4 appleclang 5.1
+ )
+ endif()
+ if((CMAKE_C_COMPILER_ID STREQUAL "Clang" AND NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 3.9) OR
+ (CMAKE_C_COMPILER_ID STREQUAL "AppleClang" AND NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 8.3))
+ list(APPEND WPICKY_ENABLE
+ -Wmissing-variable-declarations # clang 3.2 appleclang 4.6
+ )
+ endif()
+ if((CMAKE_C_COMPILER_ID STREQUAL "Clang" AND NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 5.0) OR
+ (CMAKE_C_COMPILER_ID STREQUAL "AppleClang" AND NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 9.4))
+ list(APPEND WPICKY_ENABLE
+ )
+ endif()
+ if((CMAKE_C_COMPILER_ID STREQUAL "Clang" AND NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 7.0) OR
+ (CMAKE_C_COMPILER_ID STREQUAL "AppleClang" AND NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 10.3))
+ list(APPEND WPICKY_ENABLE
+ )
+ endif()
+ else() # gcc
+ list(APPEND WPICKY_DETECT
+ ${WPICKY_COMMON}
+ )
+ # Enable based on compiler version
+ if(NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 4.3)
+ list(APPEND WPICKY_ENABLE
+ ${WPICKY_COMMON_OLD}
+ -Wclobbered # gcc 4.3
+ )
+ endif()
+ endif()
+
+ #
+
+ unset(_wpicky)
+
+ foreach(_CCOPT IN LISTS WPICKY_ENABLE)
+ set(_wpicky "${_wpicky} ${_CCOPT}")
+ endforeach()
+
+ foreach(_CCOPT IN LISTS WPICKY_DETECT)
+ # surprisingly, CHECK_C_COMPILER_FLAG needs a new variable to store each new
+ # test result in.
+ string(MAKE_C_IDENTIFIER "OPT${_CCOPT}" _optvarname)
+ # GCC only warns about unknown -Wno- options if there are also other diagnostic messages,
+ # so test for the positive form instead
+ string(REPLACE "-Wno-" "-W" _CCOPT_ON "${_CCOPT}")
+ check_c_compiler_flag(${_CCOPT_ON} ${_optvarname})
+ if(${_optvarname})
+ set(_wpicky "${_wpicky} ${_CCOPT}")
+ endif()
+ endforeach()
+
+ set(WARNCFLAGS "${WARNCFLAGS} ${_wpicky}")
+endif()
diff --git a/cmake/PickyWarningsCXX.cmake b/cmake/PickyWarningsCXX.cmake
new file mode 100644
index 0000000..4699733
--- /dev/null
+++ b/cmake/PickyWarningsCXX.cmake
@@ -0,0 +1,117 @@
+# nghttp2
+#
+# Copyright (c) 2023 nghttp2 contributors
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+# C++
+
+include(CheckCXXCompilerFlag)
+
+if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
+
+ # https://clang.llvm.org/docs/DiagnosticsReference.html
+ # https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html
+
+ # WPICKY_ENABLE = Options we want to enable as-is.
+ # WPICKY_DETECT = Options we want to test first and enable if available.
+
+ set(WPICKY_ENABLE "-Wall")
+
+ # ----------------------------------
+ # Add new options here, if in doubt:
+ # ----------------------------------
+ set(WPICKY_DETECT
+ )
+
+ # Assume these options always exist with both clang and gcc.
+ # Require clang 3.0 / gcc 2.95 or later.
+ list(APPEND WPICKY_ENABLE
+ )
+
+ # Always enable with clang, version dependent with gcc
+ set(WPICKY_COMMON_OLD
+ -Wformat-security # clang 3.0 gcc 4.1
+ )
+
+ set(WPICKY_COMMON
+ )
+
+ if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
+ list(APPEND WPICKY_ENABLE
+ ${WPICKY_COMMON_OLD}
+ )
+ # Enable based on compiler version
+ if((CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 3.6) OR
+ (CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang" AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 6.3))
+ list(APPEND WPICKY_ENABLE
+ ${WPICKY_COMMON}
+ )
+ endif()
+ if((CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 3.9) OR
+ (CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang" AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 8.3))
+ list(APPEND WPICKY_ENABLE
+ )
+ endif()
+ if((CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 5.0) OR
+ (CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang" AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 9.4))
+ list(APPEND WPICKY_ENABLE
+ )
+ endif()
+ if((CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 7.0) OR
+ (CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang" AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 10.3))
+ list(APPEND WPICKY_ENABLE
+ )
+ endif()
+ else() # gcc
+ list(APPEND WPICKY_DETECT
+ ${WPICKY_COMMON}
+ )
+ # Enable based on compiler version
+ if(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.3)
+ list(APPEND WPICKY_ENABLE
+ ${WPICKY_COMMON_OLD}
+ )
+ endif()
+ endif()
+
+ #
+
+ unset(_wpicky)
+
+ foreach(_CCOPT IN LISTS WPICKY_ENABLE)
+ set(_wpicky "${_wpicky} ${_CCOPT}")
+ endforeach()
+
+ foreach(_CCOPT IN LISTS WPICKY_DETECT)
+ # surprisingly, CHECK_CXX_COMPILER_FLAG needs a new variable to store each new
+ # test result in.
+ string(MAKE_C_IDENTIFIER "OPT${_CCOPT}" _optvarname)
+ # GCC only warns about unknown -Wno- options if there are also other diagnostic messages,
+ # so test for the positive form instead
+ string(REPLACE "-Wno-" "-W" _CCOPT_ON "${_CCOPT}")
+ check_cxx_compiler_flag(${_CCOPT_ON} ${_optvarname})
+ if(${_optvarname})
+ set(_wpicky "${_wpicky} ${_CCOPT}")
+ endif()
+ endforeach()
+
+ set(WARNCXXFLAGS "${WARNCXXFLAGS} ${_wpicky}")
+endif()
diff --git a/configure.ac b/configure.ac
index e3e743a..ad9b316 100644
--- a/configure.ac
+++ b/configure.ac
@@ -25,7 +25,7 @@ dnl Do not change user variables!
dnl https://www.gnu.org/software/automake/manual/html_node/Flag-Variables-Ordering.html
AC_PREREQ(2.61)
-AC_INIT([nghttp2], [1.57.0], [t-tujikawa@users.sourceforge.net])
+AC_INIT([nghttp2], [1.58.0], [t-tujikawa@users.sourceforge.net])
AC_CONFIG_AUX_DIR([.])
AC_CONFIG_MACRO_DIR([m4])
AC_CONFIG_HEADERS([config.h])
@@ -45,7 +45,7 @@ m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
dnl See versioning rule:
dnl https://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html
AC_SUBST(LT_CURRENT, 39)
-AC_SUBST(LT_REVISION, 0)
+AC_SUBST(LT_REVISION, 1)
AC_SUBST(LT_AGE, 25)
major=`echo $PACKAGE_VERSION |cut -d. -f1 | sed -e "s/[^0-9]//g"`
@@ -233,7 +233,7 @@ fi
save_CXXFLAGS="$CXXFLAGS"
CXXFLAGS=
-AX_CXX_COMPILE_STDCXX([14], [noext], [optional])
+AX_CXX_COMPILE_STDCXX([14], [], [optional])
CXX1XCXXFLAGS="$CXXFLAGS"
CXXFLAGS="$save_CXXFLAGS"
@@ -508,7 +508,7 @@ fi
# ngtcp2 (for src)
have_libngtcp2=no
if test "x${request_libngtcp2}" != "xno"; then
- PKG_CHECK_MODULES([LIBNGTCP2], [libngtcp2 >= 0.19.0], [have_libngtcp2=yes],
+ PKG_CHECK_MODULES([LIBNGTCP2], [libngtcp2 >= 1.0.0], [have_libngtcp2=yes],
[have_libngtcp2=no])
if test "x${have_libngtcp2}" = "xno"; then
AC_MSG_NOTICE($LIBNGTCP2_PKG_ERRORS)
@@ -525,7 +525,7 @@ have_libngtcp2_crypto_quictls=no
if test "x${have_ssl_is_quic}" = "xyes" &&
test "x${request_libngtcp2}" != "xno"; then
PKG_CHECK_MODULES([LIBNGTCP2_CRYPTO_QUICTLS],
- [libngtcp2_crypto_quictls >= 0.19.0],
+ [libngtcp2_crypto_quictls >= 1.0.0],
[have_libngtcp2_crypto_quictls=yes],
[have_libngtcp2_crypto_quictls=no])
if test "x${have_libngtcp2_crypto_quictls}" = "xno"; then
@@ -567,7 +567,7 @@ fi
# nghttp3 (for src)
have_libnghttp3=no
if test "x${request_libnghttp3}" != "xno"; then
- PKG_CHECK_MODULES([LIBNGHTTP3], [libnghttp3 >= 0.15.0], [have_libnghttp3=yes],
+ PKG_CHECK_MODULES([LIBNGHTTP3], [libnghttp3 >= 1.0.0], [have_libnghttp3=yes],
[have_libnghttp3=no])
if test "x${have_libnghttp3}" = "xno"; then
AC_MSG_NOTICE($LIBNGHTTP3_PKG_ERRORS)
diff --git a/doc/h2load.1 b/doc/h2load.1
index 58d826a..9f4cec5 100644
--- a/doc/h2load.1
+++ b/doc/h2load.1
@@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
..
-.TH "H2LOAD" "1" "Oct 10, 2023" "1.57.0" "nghttp2"
+.TH "H2LOAD" "1" "Oct 27, 2023" "1.58.0" "nghttp2"
.SH NAME
h2load \- HTTP/2 benchmarking tool
.SH SYNOPSIS
diff --git a/doc/nghttp.1 b/doc/nghttp.1
index 025ff99..4bf274f 100644
--- a/doc/nghttp.1
+++ b/doc/nghttp.1
@@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
..
-.TH "NGHTTP" "1" "Oct 10, 2023" "1.57.0" "nghttp2"
+.TH "NGHTTP" "1" "Oct 27, 2023" "1.58.0" "nghttp2"
.SH NAME
nghttp \- HTTP/2 client
.SH SYNOPSIS
diff --git a/doc/nghttpd.1 b/doc/nghttpd.1
index 847af30..232757d 100644
--- a/doc/nghttpd.1
+++ b/doc/nghttpd.1
@@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
..
-.TH "NGHTTPD" "1" "Oct 10, 2023" "1.57.0" "nghttp2"
+.TH "NGHTTPD" "1" "Oct 27, 2023" "1.58.0" "nghttp2"
.SH NAME
nghttpd \- HTTP/2 server
.SH SYNOPSIS
diff --git a/doc/nghttpx.1 b/doc/nghttpx.1
index 1542a26..1aaa47e 100644
--- a/doc/nghttpx.1
+++ b/doc/nghttpx.1
@@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
..
-.TH "NGHTTPX" "1" "Oct 10, 2023" "1.57.0" "nghttp2"
+.TH "NGHTTPX" "1" "Oct 27, 2023" "1.58.0" "nghttp2"
.SH NAME
nghttpx \- HTTP/2 proxy
.SH SYNOPSIS
@@ -1834,8 +1834,8 @@ NEW_TOKEN frame in the previous connection.
.TP
.B \-\-frontend\-quic\-congestion\-controller=<CC>
Specify a congestion controller algorithm for a frontend
-QUIC connection. <CC> should be one of \(dqcubic\(dq, \(dqbbr\(dq,
-and \(dqbbrv2\(dq.
+QUIC connection. <CC> should be either \(dqcubic\(dq or
+\(dqbbr\(dq.
.sp
Default: \fBcubic\fP
.UNINDENT
diff --git a/doc/nghttpx.1.rst b/doc/nghttpx.1.rst
index a103745..b70b163 100644
--- a/doc/nghttpx.1.rst
+++ b/doc/nghttpx.1.rst
@@ -1675,8 +1675,8 @@ HTTP/3 and QUIC
.. option:: --frontend-quic-congestion-controller=<CC>
Specify a congestion controller algorithm for a frontend
- QUIC connection. <CC> should be one of "cubic", "bbr",
- and "bbrv2".
+ QUIC connection. <CC> should be either "cubic" or
+ "bbr".
Default: ``cubic``
diff --git a/doc/sources/security.rst b/doc/sources/security.rst
index ab27eab..5a8fcd0 100644
--- a/doc/sources/security.rst
+++ b/doc/sources/security.rst
@@ -20,19 +20,14 @@ privately. We also discuss the disclosure date to the public.
We make a new release with the fix at the same time when the
vulnerability is disclosed to public.
-At least 7 days before the public disclosure date, we will post
-security advisory (which includes all the details of the vulnerability
-and the possible mitigation strategies) and the patches to fix the
-issue to `distros@openwall
-<https://oss-security.openwall.org/wiki/mailing-lists/distros>`_
-mailing list. We also open a new issue on `nghttp2 issue tracker
+At least 7 days before the public disclosure date, we open a new issue
+on `nghttp2 issue tracker
<https://github.com/nghttp2/nghttp2/issues>`_ which notifies that the
upcoming release will have a security fix. The ``SECURITY`` label is
-attached to this kind of issue.
+attached to this kind of issue. The issue is not opened if a
+vulnerability is already disclosed, and it is publicly known that
+nghttp2 is affected by that.
Before few hours of new release, we merge the fixes to the master
branch (and/or a release branch if necessary) and make a new release.
-Security advisory is disclosed on GitHub. We also post the
-vulnerability information to `oss-security
-<https://oss-security.openwall.org/wiki/mailing-lists/oss-security>`_
-mailing list.
+Security advisory is disclosed on GitHub.
diff --git a/docker/Dockerfile b/docker/Dockerfile
index 0c51708..e7b5496 100644
--- a/docker/Dockerfile
+++ b/docker/Dockerfile
@@ -15,7 +15,7 @@ RUN git clone --depth 1 -b OpenSSL_1_1_1w+quic https://github.com/quictls/openss
cd .. && \
rm -rf openssl
-RUN git clone --depth 1 -b v0.15.0 https://github.com/ngtcp2/nghttp3 && \
+RUN git clone --depth 1 -b v1.0.0 https://github.com/ngtcp2/nghttp3 && \
cd nghttp3 && \
autoreconf -i && \
./configure --enable-lib-only && \
@@ -24,7 +24,7 @@ RUN git clone --depth 1 -b v0.15.0 https://github.com/ngtcp2/nghttp3 && \
cd .. && \
rm -rf nghttp3
-RUN git clone --depth 1 -b v0.19.1 https://github.com/ngtcp2/ngtcp2 && \
+RUN git clone --depth 1 -b v1.0.1 https://github.com/ngtcp2/ngtcp2 && \
cd ngtcp2 && \
autoreconf -i && \
./configure --enable-lib-only \
diff --git a/go.mod b/go.mod
index 62582c7..a2b31c1 100644
--- a/go.mod
+++ b/go.mod
@@ -6,7 +6,7 @@ require (
github.com/bradfitz/gomemcache v0.0.0-20230124162541-5f7a7d875746
github.com/quic-go/quic-go v0.35.1
github.com/tatsuhiro-t/go-nghttp2 v0.0.0-20150408091349-4742878d9c90
- golang.org/x/net v0.15.0
+ golang.org/x/net v0.17.0
)
require (
@@ -17,10 +17,10 @@ require (
github.com/quic-go/qpack v0.4.0 // indirect
github.com/quic-go/qtls-go1-19 v0.3.2 // indirect
github.com/quic-go/qtls-go1-20 v0.2.2 // indirect
- golang.org/x/crypto v0.13.0 // indirect
+ golang.org/x/crypto v0.14.0 // indirect
golang.org/x/exp v0.0.0-20221205204356-47842c84f3db // indirect
golang.org/x/mod v0.8.0 // indirect
- golang.org/x/sys v0.12.0 // indirect
+ golang.org/x/sys v0.13.0 // indirect
golang.org/x/text v0.13.0 // indirect
golang.org/x/tools v0.6.0 // indirect
)
diff --git a/go.sum b/go.sum
index 240b266..49f9e87 100644
--- a/go.sum
+++ b/go.sum
@@ -36,8 +36,8 @@ github.com/tatsuhiro-t/go-nghttp2 v0.0.0-20150408091349-4742878d9c90/go.mod h1:Y
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
-golang.org/x/crypto v0.13.0 h1:mvySKfSWJ+UKUii46M40LOvyWfN0s2U+46/jDd0e6Ck=
-golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
+golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc=
+golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
golang.org/x/exp v0.0.0-20221205204356-47842c84f3db h1:D/cFflL63o2KSLJIwjlcIt8PR064j/xsmdEJL/YvY/o=
golang.org/x/exp v0.0.0-20221205204356-47842c84f3db/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
@@ -46,8 +46,8 @@ golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
-golang.org/x/net v0.15.0 h1:ugBLEUaxABaB5AJqW9enI0ACdci2RUd4eP51NTBvuJ8=
-golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
+golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM=
+golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -56,8 +56,8 @@ golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o=
-golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE=
+golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
diff --git a/integration-tests/CMakeLists.txt b/integration-tests/CMakeLists.txt
index d9385a5..0815cb3 100644
--- a/integration-tests/CMakeLists.txt
+++ b/integration-tests/CMakeLists.txt
@@ -2,6 +2,7 @@ set(GO_FILES
nghttpx_http1_test.go
nghttpx_http2_test.go
server_tester.go
+ server_tester_http3.go
)
# XXX unused
@@ -40,7 +41,11 @@ if(NOT CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_CURRENT_BINARY_DIR)
endforeach()
endif()
+if(ENABLE_HTTP3)
+ set(GO_TEST_TAGS quic)
+endif()
+
add_custom_target(it
- COMMAND sh setenv go test -v
+ COMMAND sh setenv go test -v --tags=${GO_TEST_TAGS}
DEPENDS ${GO_BUILD_FILES}
)
diff --git a/integration-tests/Makefile.am b/integration-tests/Makefile.am
index 38cd119..21166ed 100644
--- a/integration-tests/Makefile.am
+++ b/integration-tests/Makefile.am
@@ -25,7 +25,8 @@ GO_FILES = \
nghttpx_http1_test.go \
nghttpx_http2_test.go \
nghttpx_http3_test.go \
- server_tester.go
+ server_tester.go \
+ server_tester_http3.go
EXTRA_DIST = \
CMakeLists.txt \
diff --git a/integration-tests/nghttpx_http1_test.go b/integration-tests/nghttpx_http1_test.go
index ca74a2e..740396d 100644
--- a/integration-tests/nghttpx_http1_test.go
+++ b/integration-tests/nghttpx_http1_test.go
@@ -1490,3 +1490,142 @@ func TestH1H1ChunkedEndsPrematurely(t *testing.T) {
t.Fatal("st.http1() should fail")
}
}
+
+// TestH1H1RequestMalformedTransferEncoding tests that server rejects
+// request which contains malformed transfer-encoding.
+func TestH1H1RequestMalformedTransferEncoding(t *testing.T) {
+ opts := options{
+ handler: func(w http.ResponseWriter, r *http.Request) {
+ t.Errorf("server should not forward bad request")
+ },
+ }
+ st := newServerTester(t, opts)
+ defer st.Close()
+
+ if _, err := io.WriteString(st.conn, fmt.Sprintf("GET / HTTP/1.1\r\nHost: %v\r\nTest-Case: TestH1H1RequestMalformedTransferEncoding\r\nTransfer-Encoding: ,chunked\r\n\r\n",
+ st.authority)); err != nil {
+ t.Fatalf("Error io.WriteString() = %v", err)
+ }
+
+ resp, err := http.ReadResponse(bufio.NewReader(st.conn), nil)
+ if err != nil {
+ t.Fatalf("Error http.ReadResponse() = %v", err)
+ }
+
+ defer resp.Body.Close()
+
+ if got, want := resp.StatusCode, http.StatusBadRequest; got != want {
+ t.Errorf("status: %v; want %v", got, want)
+ }
+}
+
+// TestH1H1ResponseMalformedTransferEncoding tests a request fails if
+// its response contains malformed transfer-encoding.
+func TestH1H1ResponseMalformedTransferEncoding(t *testing.T) {
+ opts := options{
+ handler: func(w http.ResponseWriter, r *http.Request) {
+ hj, ok := w.(http.Hijacker)
+ if !ok {
+ http.Error(w, "Could not hijack the connection", http.StatusInternalServerError)
+ return
+ }
+ conn, bufrw, err := hj.Hijack()
+ if err != nil {
+ http.Error(w, err.Error(), http.StatusInternalServerError)
+ return
+ }
+ defer conn.Close()
+ if _, err := bufrw.WriteString("HTTP/1.1 200\r\nTransfer-Encoding: ,chunked\r\n\r\n"); err != nil {
+ t.Fatalf("Error bufrw.WriteString() = %v", err)
+ }
+ bufrw.Flush()
+ },
+ }
+ st := newServerTester(t, opts)
+ defer st.Close()
+
+ res, err := st.http1(requestParam{
+ name: "TestH1H1ResponseMalformedTransferEncoding",
+ })
+ if err != nil {
+ t.Fatalf("Error st.http1() = %v", err)
+ }
+ if got, want := res.status, http.StatusBadGateway; got != want {
+ t.Errorf("res.status: %v; want %v", got, want)
+ }
+}
+
+// TestH1H1ResponseUnknownTransferEncoding tests a request succeeds if
+// its response contains unknown transfer-encoding.
+func TestH1H1ResponseUnknownTransferEncoding(t *testing.T) {
+ opts := options{
+ handler: func(w http.ResponseWriter, r *http.Request) {
+ hj, ok := w.(http.Hijacker)
+ if !ok {
+ http.Error(w, "Could not hijack the connection", http.StatusInternalServerError)
+ return
+ }
+ conn, bufrw, err := hj.Hijack()
+ if err != nil {
+ http.Error(w, err.Error(), http.StatusInternalServerError)
+ return
+ }
+ defer conn.Close()
+ if _, err := bufrw.WriteString("HTTP/1.1 200\r\nTransfer-Encoding: foo\r\n\r\n"); err != nil {
+ t.Fatalf("Error bufrw.WriteString() = %v", err)
+ }
+ bufrw.Flush()
+ },
+ }
+ st := newServerTester(t, opts)
+ defer st.Close()
+
+ if _, err := io.WriteString(st.conn, fmt.Sprintf("GET / HTTP/1.1\r\nHost: %v\r\nTest-Case: TestH1H1ResponseUnknownTransferEncoding\r\n\r\n",
+ st.authority)); err != nil {
+ t.Fatalf("Error: io.WriteString() = %v", err)
+ }
+
+ r := bufio.NewReader(st.conn)
+
+ resp := make([]byte, 4096)
+
+ resplen, err := r.Read(resp)
+ if err != nil {
+ t.Fatalf("Error: r.Read() = %v", err)
+ }
+
+ resp = resp[:resplen]
+
+ const expect = "HTTP/1.1 200 OK\r\nTransfer-Encoding: foo\r\nConnection: close\r\nServer: nghttpx\r\nVia: 1.1 nghttpx\r\n\r\n"
+
+ if got, want := string(resp), expect; got != want {
+ t.Errorf("resp = %v, want %v", got, want)
+ }
+}
+
+// TestH1H1RequestHTTP10TransferEncoding tests that server rejects
+// HTTP/1.0 request which contains transfer-encoding.
+func TestH1H1RequestHTTP10TransferEncoding(t *testing.T) {
+ opts := options{
+ handler: func(w http.ResponseWriter, r *http.Request) {
+ t.Errorf("server should not forward bad request")
+ },
+ }
+ st := newServerTester(t, opts)
+ defer st.Close()
+
+ if _, err := io.WriteString(st.conn, "GET / HTTP/1.0\r\nTest-Case: TestH1H1RequestHTTP10TransferEncoding\r\nTransfer-Encoding: chunked\r\n\r\n"); err != nil {
+ t.Fatalf("Error io.WriteString() = %v", err)
+ }
+
+ resp, err := http.ReadResponse(bufio.NewReader(st.conn), nil)
+ if err != nil {
+ t.Fatalf("Error http.ReadResponse() = %v", err)
+ }
+
+ defer resp.Body.Close()
+
+ if got, want := resp.StatusCode, http.StatusBadRequest; got != want {
+ t.Errorf("status: %v; want %v", got, want)
+ }
+}
diff --git a/integration-tests/server_tester.go b/integration-tests/server_tester.go
index b341aaa..6a4ce65 100644
--- a/integration-tests/server_tester.go
+++ b/integration-tests/server_tester.go
@@ -22,7 +22,6 @@ import (
"testing"
"time"
- "github.com/quic-go/quic-go/http3"
"github.com/tatsuhiro-t/go-nghttp2"
"golang.org/x/net/http2"
"golang.org/x/net/http2/hpack"
@@ -390,81 +389,6 @@ func (st *serverTester) websocket(rp requestParam) *serverResponse {
return res
}
-func (st *serverTester) http3(rp requestParam) (*serverResponse, error) {
- rt := &http3.RoundTripper{
- TLSClientConfig: &tls.Config{
- InsecureSkipVerify: true,
- },
- }
-
- defer rt.Close()
-
- c := &http.Client{
- Transport: rt,
- }
-
- method := "GET"
- if rp.method != "" {
- method = rp.method
- }
-
- var body io.Reader
-
- if rp.body != nil {
- body = bytes.NewBuffer(rp.body)
- }
-
- reqURL := st.url
-
- if rp.path != "" {
- u, err := url.Parse(st.url)
- if err != nil {
- st.t.Fatalf("Error parsing URL from st.url %v: %v", st.url, err)
- }
- u.Path = ""
- u.RawQuery = ""
- reqURL = u.String() + rp.path
- }
-
- ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
- defer cancel()
-
- req, err := http.NewRequestWithContext(ctx, method, reqURL, body)
- if err != nil {
- return nil, err
- }
-
- for _, h := range rp.header {
- req.Header.Add(h.Name, h.Value)
- }
-
- req.Header.Add("Test-Case", rp.name)
-
- // TODO http3 package does not support trailer at the time of
- // this writing.
-
- resp, err := c.Do(req)
- if err != nil {
- return nil, err
- }
-
- defer resp.Body.Close()
-
- respBody, err := io.ReadAll(resp.Body)
- if err != nil {
- return nil, err
- }
-
- res := &serverResponse{
- status: resp.StatusCode,
- header: resp.Header,
- body: respBody,
- connClose: resp.Close,
- }
-
- return res, nil
-}
-
func (st *serverTester) http1(rp requestParam) (*serverResponse, error) {
method := "GET"
if rp.method != "" {
diff --git a/integration-tests/server_tester_http3.go b/integration-tests/server_tester_http3.go
new file mode 100644
index 0000000..7bbc4e7
--- /dev/null
+++ b/integration-tests/server_tester_http3.go
@@ -0,0 +1,90 @@
+//go:build quic
+
+package nghttp2
+
+import (
+ "bytes"
+ "context"
+ "crypto/tls"
+ "io"
+ "net/http"
+ "net/url"
+ "time"
+
+ "github.com/quic-go/quic-go/http3"
+)
+
+func (st *serverTester) http3(rp requestParam) (*serverResponse, error) {
+ rt := &http3.RoundTripper{
+ TLSClientConfig: &tls.Config{
+ InsecureSkipVerify: true,
+ },
+ }
+
+ defer rt.Close()
+
+ c := &http.Client{
+ Transport: rt,
+ }
+
+ method := "GET"
+ if rp.method != "" {
+ method = rp.method
+ }
+
+ var body io.Reader
+
+ if rp.body != nil {
+ body = bytes.NewBuffer(rp.body)
+ }
+
+ reqURL := st.url
+
+ if rp.path != "" {
+ u, err := url.Parse(st.url)
+ if err != nil {
+ st.t.Fatalf("Error parsing URL from st.url %v: %v", st.url, err)
+ }
+ u.Path = ""
+ u.RawQuery = ""
+ reqURL = u.String() + rp.path
+ }
+
+ ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
+ defer cancel()
+
+ req, err := http.NewRequestWithContext(ctx, method, reqURL, body)
+ if err != nil {
+ return nil, err
+ }
+
+ for _, h := range rp.header {
+ req.Header.Add(h.Name, h.Value)
+ }
+
+ req.Header.Add("Test-Case", rp.name)
+
+ // TODO http3 package does not support trailer at the time of
+ // this writing.
+
+ resp, err := c.Do(req)
+ if err != nil {
+ return nil, err
+ }
+
+ defer resp.Body.Close()
+
+ respBody, err := io.ReadAll(resp.Body)
+ if err != nil {
+ return nil, err
+ }
+
+ res := &serverResponse{
+ status: resp.StatusCode,
+ header: resp.Header,
+ body: respBody,
+ connClose: resp.Close,
+ }
+
+ return res, nil
+}
diff --git a/lib/nghttp2_map.c b/lib/nghttp2_map.c
index 5f63fc2..0aaaf29 100644
--- a/lib/nghttp2_map.c
+++ b/lib/nghttp2_map.c
@@ -126,6 +126,7 @@ static void map_bucket_set_data(nghttp2_map_bucket *bkt, uint32_t hash,
bkt->data = data;
}
+#ifndef WIN32
void nghttp2_map_print_distance(nghttp2_map *map) {
uint32_t i;
size_t idx;
@@ -145,6 +146,7 @@ void nghttp2_map_print_distance(nghttp2_map *map) {
distance(map->tablelen, map->tablelenbits, bkt, idx));
}
}
+#endif /* !WIN32 */
static int insert(nghttp2_map_bucket *table, uint32_t tablelen,
uint32_t tablelenbits, uint32_t hash,
diff --git a/lib/nghttp2_map.h b/lib/nghttp2_map.h
index d90245a..236d282 100644
--- a/lib/nghttp2_map.h
+++ b/lib/nghttp2_map.h
@@ -131,6 +131,8 @@ size_t nghttp2_map_size(nghttp2_map *map);
int nghttp2_map_each(nghttp2_map *map, int (*func)(void *data, void *ptr),
void *ptr);
+#ifndef WIN32
void nghttp2_map_print_distance(nghttp2_map *map);
+#endif /* !WIN32 */
#endif /* NGHTTP2_MAP_H */
diff --git a/lib/nghttp2_time.c b/lib/nghttp2_time.c
index 2a5f1a6..897556f 100644
--- a/lib/nghttp2_time.c
+++ b/lib/nghttp2_time.c
@@ -32,7 +32,7 @@
# include <sysinfoapi.h>
#endif /* HAVE_SYSINFOAPI_H */
-#ifndef HAVE_GETTICKCOUNT64
+#if !defined(HAVE_GETTICKCOUNT64) || defined(__CYGWIN__)
static uint64_t time_now_sec(void) {
time_t t = time(NULL);
@@ -42,9 +42,11 @@ static uint64_t time_now_sec(void) {
return (uint64_t)t;
}
-#endif /* HAVE_GETTICKCOUNT64 */
+#endif /* !HAVE_GETTICKCOUNT64 || __CYGWIN__ */
-#ifdef HAVE_CLOCK_GETTIME
+#if defined(HAVE_GETTICKCOUNT64) && !defined(__CYGWIN__)
+uint64_t nghttp2_time_now_sec(void) { return GetTickCount64() / 1000; }
+#elif defined(HAVE_CLOCK_GETTIME)
uint64_t nghttp2_time_now_sec(void) {
struct timespec tp;
int rv = clock_gettime(CLOCK_MONOTONIC, &tp);
@@ -55,8 +57,6 @@ uint64_t nghttp2_time_now_sec(void) {
return (uint64_t)tp.tv_sec;
}
-#elif defined(HAVE_GETTICKCOUNT64)
-uint64_t nghttp2_time_now_sec(void) { return GetTickCount64() / 1000; }
-#else /* !HAVE_CLOCK_GETTIME && !HAVE_GETTICKCOUNT64 */
+#else /* (!HAVE_CLOCK_GETTIME || __CYGWIN__) && !HAVE_GETTICKCOUNT64 */
uint64_t nghttp2_time_now_sec(void) { return time_now_sec(); }
-#endif /* !HAVE_CLOCK_GETTIME && !HAVE_GETTICKCOUNT64 */
+#endif /* (!HAVE_CLOCK_GETTIME || __CYGWIN__) && !HAVE_GETTICKCOUNT64 */
diff --git a/src/http2.cc b/src/http2.cc
index 7685879..07d0144 100644
--- a/src/http2.cc
+++ b/src/http2.cc
@@ -1044,12 +1044,39 @@ InputIt skip_to_right_dquote(InputIt first, InputIt last) {
switch (*first) {
case '"':
return first;
+ // quoted-pair
case '\\':
++first;
if (first == last) {
return first;
}
+
+ switch (*first) {
+ case '\t':
+ case ' ':
+ break;
+ default:
+ if ((0x21 <= *first && *first <= 0x7e) /* VCHAR */ ||
+ (0x80 <= *first && *first <= 0xff) /* obs-text */) {
+ break;
+ }
+
+ return last;
+ }
+
+ break;
+ // qdtext
+ case '\t':
+ case ' ':
+ case '!':
break;
+ default:
+ if ((0x23 <= *first && *first <= 0x5b) ||
+ (0x5d <= *first && *first <= 0x7e)) {
+ break;
+ }
+
+ return last;
}
++first;
}
@@ -1957,6 +1984,108 @@ bool legacy_http1(int major, int minor) {
return major <= 0 || (major == 1 && minor == 0);
}
+bool check_transfer_encoding(const StringRef &s) {
+ if (s.empty()) {
+ return false;
+ }
+
+ auto it = std::begin(s);
+
+ for (;;) {
+ // token
+ if (!util::in_token(*it)) {
+ return false;
+ }
+
+ ++it;
+
+ for (; it != std::end(s) && util::in_token(*it); ++it)
+ ;
+
+ if (it == std::end(s)) {
+ return true;
+ }
+
+ for (;;) {
+ // OWS
+ it = skip_lws(it, std::end(s));
+ if (it == std::end(s)) {
+ return false;
+ }
+
+ if (*it == ',') {
+ ++it;
+
+ it = skip_lws(it, std::end(s));
+ if (it == std::end(s)) {
+ return false;
+ }
+
+ break;
+ }
+
+ if (*it != ';') {
+ return false;
+ }
+
+ ++it;
+
+ // transfer-parameter follows
+
+ // OWS
+ it = skip_lws(it, std::end(s));
+ if (it == std::end(s)) {
+ return false;
+ }
+
+ // token
+ if (!util::in_token(*it)) {
+ return false;
+ }
+
+ ++it;
+
+ for (; it != std::end(s) && util::in_token(*it); ++it)
+ ;
+
+ if (it == std::end(s)) {
+ return false;
+ }
+
+ // No BWS allowed
+ if (*it != '=') {
+ return false;
+ }
+
+ ++it;
+
+ if (util::in_token(*it)) {
+ // token
+ ++it;
+
+ for (; it != std::end(s) && util::in_token(*it); ++it)
+ ;
+ } else if (*it == '"') {
+ // quoted-string
+ ++it;
+
+ it = skip_to_right_dquote(it, std::end(s));
+ if (it == std::end(s)) {
+ return false;
+ }
+
+ ++it;
+ } else {
+ return false;
+ }
+
+ if (it == std::end(s)) {
+ return true;
+ }
+ }
+ }
+}
+
} // namespace http2
} // namespace nghttp2
diff --git a/src/http2.h b/src/http2.h
index fc88e4d..e5b4f1b 100644
--- a/src/http2.h
+++ b/src/http2.h
@@ -444,6 +444,11 @@ StringRef make_websocket_accept_token(uint8_t *dest, const StringRef &key);
// HTTP/0.9 or HTTP/1.0).
bool legacy_http1(int major, int minor);
+// Returns true if transfer-encoding field value |s| conforms RFC
+// strictly. This function does not allow empty value, BWS, and empty
+// list elements.
+bool check_transfer_encoding(const StringRef &s);
+
} // namespace http2
} // namespace nghttp2
diff --git a/src/http2_test.cc b/src/http2_test.cc
index 5760726..f8be9f4 100644
--- a/src/http2_test.cc
+++ b/src/http2_test.cc
@@ -1189,4 +1189,61 @@ void test_http2_contains_trailers(void) {
CU_ASSERT(http2::contains_trailers(StringRef::from_lit(",trailers")));
}
+void test_http2_check_transfer_encoding(void) {
+ CU_ASSERT(http2::check_transfer_encoding(StringRef::from_lit("chunked")));
+ CU_ASSERT(http2::check_transfer_encoding(StringRef::from_lit("foo,chunked")));
+ CU_ASSERT(
+ http2::check_transfer_encoding(StringRef::from_lit("foo, chunked")));
+ CU_ASSERT(
+ http2::check_transfer_encoding(StringRef::from_lit("foo , chunked")));
+ CU_ASSERT(
+ http2::check_transfer_encoding(StringRef::from_lit("chunked;foo=bar")));
+ CU_ASSERT(
+ http2::check_transfer_encoding(StringRef::from_lit("chunked ; foo=bar")));
+ CU_ASSERT(http2::check_transfer_encoding(
+ StringRef::from_lit(R"(chunked;foo="bar")")));
+ CU_ASSERT(http2::check_transfer_encoding(
+ StringRef::from_lit(R"(chunked;foo="\bar\"";FOO=BAR)")));
+ CU_ASSERT(
+ http2::check_transfer_encoding(StringRef::from_lit(R"(chunked;foo="")")));
+ CU_ASSERT(http2::check_transfer_encoding(
+ StringRef::from_lit(R"(chunked;foo="bar" , gzip)")));
+
+ CU_ASSERT(!http2::check_transfer_encoding(StringRef{}));
+ CU_ASSERT(!http2::check_transfer_encoding(StringRef::from_lit(",chunked")));
+ CU_ASSERT(!http2::check_transfer_encoding(StringRef::from_lit("chunked,")));
+ CU_ASSERT(!http2::check_transfer_encoding(StringRef::from_lit("chunked, ")));
+ CU_ASSERT(
+ !http2::check_transfer_encoding(StringRef::from_lit("foo,,chunked")));
+ CU_ASSERT(
+ !http2::check_transfer_encoding(StringRef::from_lit("chunked;foo")));
+ CU_ASSERT(!http2::check_transfer_encoding(StringRef::from_lit("chunked;")));
+ CU_ASSERT(
+ !http2::check_transfer_encoding(StringRef::from_lit("chunked;foo=bar;")));
+ CU_ASSERT(
+ !http2::check_transfer_encoding(StringRef::from_lit("chunked;?=bar")));
+ CU_ASSERT(
+ !http2::check_transfer_encoding(StringRef::from_lit("chunked;=bar")));
+ CU_ASSERT(!http2::check_transfer_encoding(StringRef::from_lit("chunked;;")));
+ CU_ASSERT(!http2::check_transfer_encoding(StringRef::from_lit("chunked?")));
+ CU_ASSERT(!http2::check_transfer_encoding(StringRef::from_lit(",")));
+ CU_ASSERT(!http2::check_transfer_encoding(StringRef::from_lit(" ")));
+ CU_ASSERT(!http2::check_transfer_encoding(StringRef::from_lit(";")));
+ CU_ASSERT(!http2::check_transfer_encoding(StringRef::from_lit("\"")));
+ CU_ASSERT(!http2::check_transfer_encoding(
+ StringRef::from_lit(R"(chunked;foo="bar)")));
+ CU_ASSERT(!http2::check_transfer_encoding(
+ StringRef::from_lit(R"(chunked;foo="bar\)")));
+ CU_ASSERT(
+ !http2::check_transfer_encoding(StringRef::from_lit(R"(chunked;foo="bar\)"
+ "\x0a"
+ R"(")")));
+ CU_ASSERT(
+ !http2::check_transfer_encoding(StringRef::from_lit(R"(chunked;foo=")"
+ "\x0a"
+ R"(")")));
+ CU_ASSERT(!http2::check_transfer_encoding(
+ StringRef::from_lit(R"(chunked;foo="bar",,gzip)")));
+}
+
} // namespace shrpx
diff --git a/src/http2_test.h b/src/http2_test.h
index 0d63020..382470d 100644
--- a/src/http2_test.h
+++ b/src/http2_test.h
@@ -47,6 +47,7 @@ void test_http2_rewrite_clean_path(void);
void test_http2_get_pure_path_component(void);
void test_http2_construct_push_component(void);
void test_http2_contains_trailers(void);
+void test_http2_check_transfer_encoding(void);
} // namespace shrpx
diff --git a/src/shrpx-unittest.cc b/src/shrpx-unittest.cc
index 417ed54..07373d5 100644
--- a/src/shrpx-unittest.cc
+++ b/src/shrpx-unittest.cc
@@ -109,6 +109,8 @@ int main(int argc, char *argv[]) {
shrpx::test_http2_construct_push_component) ||
!CU_add_test(pSuite, "http2_contains_trailers",
shrpx::test_http2_contains_trailers) ||
+ !CU_add_test(pSuite, "http2_check_transfer_encoding",
+ shrpx::test_http2_check_transfer_encoding) ||
!CU_add_test(pSuite, "downstream_field_store_append_last_header",
shrpx::test_downstream_field_store_append_last_header) ||
!CU_add_test(pSuite, "downstream_field_store_header",
diff --git a/src/shrpx.cc b/src/shrpx.cc
index d510b7e..a6ed8f8 100644
--- a/src/shrpx.cc
+++ b/src/shrpx.cc
@@ -3522,15 +3522,12 @@ HTTP/3 and QUIC:
NEW_TOKEN frame in the previous connection.
--frontend-quic-congestion-controller=<CC>
Specify a congestion controller algorithm for a frontend
- QUIC connection. <CC> should be one of "cubic", "bbr",
- and "bbrv2".
+ QUIC connection. <CC> should be either "cubic" or
+ "bbr".
Default: )"
<< (config->quic.upstream.congestion_controller == NGTCP2_CC_ALGO_CUBIC
? "cubic"
- : (config->quic.upstream.congestion_controller ==
- NGTCP2_CC_ALGO_BBR
- ? "bbr"
- : "bbrv2"))
+ : "bbr")
<< R"(
--frontend-quic-secret-file=<PATH>
Path to file that contains secure random data to be used
diff --git a/src/shrpx_config.cc b/src/shrpx_config.cc
index 453261c..bcb48eb 100644
--- a/src/shrpx_config.cc
+++ b/src/shrpx_config.cc
@@ -4116,10 +4116,8 @@ int parse_config(Config *config, int optid, const StringRef &opt,
config->quic.upstream.congestion_controller = NGTCP2_CC_ALGO_CUBIC;
} else if (util::strieq_l("bbr", optarg)) {
config->quic.upstream.congestion_controller = NGTCP2_CC_ALGO_BBR;
- } else if (util::strieq_l("bbrv2", optarg)) {
- config->quic.upstream.congestion_controller = NGTCP2_CC_ALGO_BBR_V2;
} else {
- LOG(ERROR) << opt << ": must be one of cubic, bbr, and bbrv2";
+ LOG(ERROR) << opt << ": must be either cubic or bbr";
return -1;
}
#endif // ENABLE_HTTP3
diff --git a/src/shrpx_downstream.cc b/src/shrpx_downstream.cc
index 245e00b..9ea52b4 100644
--- a/src/shrpx_downstream.cc
+++ b/src/shrpx_downstream.cc
@@ -864,9 +864,6 @@ void Downstream::inspect_http1_request() {
auto transfer_encoding = req_.fs.header(http2::HD_TRANSFER_ENCODING);
if (transfer_encoding) {
req_.fs.content_length = -1;
- if (util::iends_with_l(transfer_encoding->value, "chunked")) {
- chunked_request_ = true;
- }
}
auto expect = req_.fs.header(http2::HD_EXPECT);
@@ -879,9 +876,6 @@ void Downstream::inspect_http1_response() {
auto transfer_encoding = resp_.fs.header(http2::HD_TRANSFER_ENCODING);
if (transfer_encoding) {
resp_.fs.content_length = -1;
- if (util::iends_with_l(transfer_encoding->value, "chunked")) {
- chunked_response_ = true;
- }
}
}
diff --git a/src/shrpx_http3_upstream.cc b/src/shrpx_http3_upstream.cc
index 5bc3bff..bc5c400 100644
--- a/src/shrpx_http3_upstream.cc
+++ b/src/shrpx_http3_upstream.cc
@@ -421,7 +421,7 @@ int stream_reset(ngtcp2_conn *conn, int64_t stream_id, uint64_t final_size,
void *stream_user_data) {
auto upstream = static_cast<Http3Upstream *>(user_data);
- if (upstream->http_shutdown_stream_read(stream_id) != 0) {
+ if (upstream->stream_reset(stream_id) != 0) {
return NGTCP2_ERR_CALLBACK_FAILURE;
}
@@ -429,6 +429,24 @@ int stream_reset(ngtcp2_conn *conn, int64_t stream_id, uint64_t final_size,
}
} // namespace
+int Http3Upstream::stream_reset(int64_t stream_id) {
+ if (http_shutdown_stream_read(stream_id) != 0) {
+ return -1;
+ }
+
+ if (ngtcp2_is_bidi_stream(stream_id)) {
+ auto rv = ngtcp2_conn_shutdown_stream_write(conn_, 0, stream_id,
+ NGHTTP3_H3_NO_ERROR);
+ if (rv != 0) {
+ ULOG(ERROR, this) << "ngtcp2_conn_shutdown_stream_write: "
+ << ngtcp2_strerror(rv);
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
int Http3Upstream::http_shutdown_stream_read(int64_t stream_id) {
if (!httpconn_) {
return 0;
diff --git a/src/shrpx_http3_upstream.h b/src/shrpx_http3_upstream.h
index 89dfc17..1807652 100644
--- a/src/shrpx_http3_upstream.h
+++ b/src/shrpx_http3_upstream.h
@@ -125,6 +125,7 @@ public:
void consume(int64_t stream_id, size_t nconsumed);
void remove_downstream(Downstream *downstream);
int stream_close(int64_t stream_id, uint64_t app_error_code);
+ int stream_reset(int64_t stream_id);
void log_response_headers(Downstream *downstream,
const std::vector<nghttp3_nv> &nva) const;
int http_acked_stream_data(Downstream *downstream, uint64_t datalen);
diff --git a/src/shrpx_http_downstream_connection.cc b/src/shrpx_http_downstream_connection.cc
index e464471..bdb4294 100644
--- a/src/shrpx_http_downstream_connection.cc
+++ b/src/shrpx_http_downstream_connection.cc
@@ -929,6 +929,11 @@ int htp_hdrs_completecb(llhttp_t *htp) {
for (auto &kv : resp.fs.headers()) {
kv.value = util::rstrip(balloc, kv.value);
+
+ if (kv.token == http2::HD_TRANSFER_ENCODING &&
+ !http2::check_transfer_encoding(kv.value)) {
+ return -1;
+ }
}
auto config = get_config();
@@ -1004,6 +1009,16 @@ int htp_hdrs_completecb(llhttp_t *htp) {
resp.connection_close = !llhttp_should_keep_alive(htp);
downstream->set_response_state(DownstreamState::HEADER_COMPLETE);
downstream->inspect_http1_response();
+
+ if (htp->flags & F_CHUNKED) {
+ downstream->set_chunked_response(true);
+ }
+
+ auto transfer_encoding = resp.fs.header(http2::HD_TRANSFER_ENCODING);
+ if (transfer_encoding && !downstream->get_chunked_response()) {
+ resp.connection_close = true;
+ }
+
if (downstream->get_upgraded()) {
// content-length must be ignored for upgraded connection.
resp.fs.content_length = -1;
diff --git a/src/shrpx_https_upstream.cc b/src/shrpx_https_upstream.cc
index 79cc22a..49d2088 100644
--- a/src/shrpx_https_upstream.cc
+++ b/src/shrpx_https_upstream.cc
@@ -345,6 +345,11 @@ int htp_hdrs_completecb(llhttp_t *htp) {
for (auto &kv : req.fs.headers()) {
kv.value = util::rstrip(balloc, kv.value);
+
+ if (kv.token == http2::HD_TRANSFER_ENCODING &&
+ !http2::check_transfer_encoding(kv.value)) {
+ return -1;
+ }
}
auto lgconf = log_config();
@@ -414,6 +419,16 @@ int htp_hdrs_completecb(llhttp_t *htp) {
downstream->inspect_http1_request();
+ if (htp->flags & F_CHUNKED) {
+ downstream->set_chunked_request(true);
+ }
+
+ auto transfer_encoding = req.fs.header(http2::HD_TRANSFER_ENCODING);
+ if (transfer_encoding &&
+ http2::legacy_http1(req.http_major, req.http_minor)) {
+ return -1;
+ }
+
auto faddr = handler->get_upstream_addr();
auto config = get_config();
diff --git a/src/util.cc b/src/util.cc
index 6abfc3e..9d0c1bd 100644
--- a/src/util.cc
+++ b/src/util.cc
@@ -105,17 +105,34 @@ int nghttp2_inet_pton(int af, const char *src, void *dst) {
const char UPPER_XDIGITS[] = "0123456789ABCDEF";
bool in_rfc3986_unreserved_chars(const char c) {
- static constexpr char unreserved[] = {'-', '.', '_', '~'};
- return is_alpha(c) || is_digit(c) ||
- std::find(std::begin(unreserved), std::end(unreserved), c) !=
- std::end(unreserved);
+ switch (c) {
+ case '-':
+ case '.':
+ case '_':
+ case '~':
+ return true;
+ }
+
+ return is_alpha(c) || is_digit(c);
}
bool in_rfc3986_sub_delims(const char c) {
- static constexpr char sub_delims[] = {'!', '$', '&', '\'', '(', ')',
- '*', '+', ',', ';', '='};
- return std::find(std::begin(sub_delims), std::end(sub_delims), c) !=
- std::end(sub_delims);
+ switch (c) {
+ case '!':
+ case '$':
+ case '&':
+ case '\'':
+ case '(':
+ case ')':
+ case '*':
+ case '+':
+ case ',':
+ case ';':
+ case '=':
+ return true;
+ }
+
+ return false;
}
std::string percent_encode(const unsigned char *target, size_t len) {
@@ -140,16 +157,37 @@ std::string percent_encode(const std::string &target) {
}
bool in_token(char c) {
- static constexpr char extra[] = {'!', '#', '$', '%', '&', '\'', '*', '+',
- '-', '.', '^', '_', '`', '|', '~'};
- return is_alpha(c) || is_digit(c) ||
- std::find(std::begin(extra), std::end(extra), c) != std::end(extra);
+ switch (c) {
+ case '!':
+ case '#':
+ case '$':
+ case '%':
+ case '&':
+ case '\'':
+ case '*':
+ case '+':
+ case '-':
+ case '.':
+ case '^':
+ case '_':
+ case '`':
+ case '|':
+ case '~':
+ return true;
+ }
+
+ return is_alpha(c) || is_digit(c);
}
bool in_attr_char(char c) {
- static constexpr char bad[] = {'*', '\'', '%'};
- return util::in_token(c) &&
- std::find(std::begin(bad), std::end(bad), c) == std::end(bad);
+ switch (c) {
+ case '*':
+ case '\'':
+ case '%':
+ return false;
+ }
+
+ return util::in_token(c);
}
StringRef percent_encode_token(BlockAllocator &balloc,
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 98d72b6..e6cdde1 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -81,6 +81,7 @@ AM_CFLAGS = $(WARNCFLAGS) \
-I${top_srcdir}/lib/includes \
-I${top_builddir}/lib/includes \
-DBUILDING_NGHTTP2 \
+ -DNGHTTP2_STATICLIB \
@CUNIT_CFLAGS@ @DEFS@
TESTS = main