Compare commits

..

3 Commits

Author SHA1 Message Date
Tatsuhiro Tsujikawa
7b71996d98 Update man pages 2016-05-29 23:51:37 +09:00
Tatsuhiro Tsujikawa
e92cc26792 Bump up version number to 1.11.1 2016-05-29 23:44:59 +09:00
Tatsuhiro Tsujikawa
82d9ffa1ad nghttpx: Fix bug that timeout on h1 backend makes that backend unavailable 2016-05-29 23:43:31 +09:00
212 changed files with 9103 additions and 17434 deletions

View File

@@ -1,94 +1,57 @@
--- ---
Language: Cpp Language: Cpp
# BasedOnStyle: LLVM
AccessModifierOffset: -2 AccessModifierOffset: -2
AlignAfterOpenBracket: Align ConstructorInitializerIndentWidth: 4
AlignConsecutiveAssignments: false
AlignConsecutiveDeclarations: false
AlignEscapedNewlinesLeft: false AlignEscapedNewlinesLeft: false
AlignOperands: true
AlignTrailingComments: true AlignTrailingComments: true
AllowAllParametersOfDeclarationOnNextLine: true AllowAllParametersOfDeclarationOnNextLine: true
AllowShortBlocksOnASingleLine: false AllowShortBlocksOnASingleLine: false
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: All
AllowShortIfStatementsOnASingleLine: false AllowShortIfStatementsOnASingleLine: false
AllowShortLoopsOnASingleLine: false AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterDefinitionReturnType: None AllowShortFunctionsOnASingleLine: All
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: false
AlwaysBreakTemplateDeclarations: false AlwaysBreakTemplateDeclarations: false
BinPackArguments: true AlwaysBreakBeforeMultilineStrings: false
BinPackParameters: true BreakBeforeBinaryOperators: false
BraceWrapping:
AfterClass: false
AfterControlStatement: false
AfterEnum: false
AfterFunction: false
AfterNamespace: false
AfterObjCDeclaration: false
AfterStruct: false
AfterUnion: false
BeforeCatch: false
BeforeElse: false
IndentBraces: false
BreakBeforeBinaryOperators: None
BreakBeforeBraces: Attach
BreakBeforeTernaryOperators: true BreakBeforeTernaryOperators: true
BreakConstructorInitializersBeforeComma: false BreakConstructorInitializersBeforeComma: false
BreakAfterJavaFieldAnnotations: false BinPackParameters: true
BreakStringLiterals: true
ColumnLimit: 80 ColumnLimit: 80
CommentPragmas: '^ IWYU pragma:'
ConstructorInitializerAllOnOneLineOrOnePerLine: true ConstructorInitializerAllOnOneLineOrOnePerLine: true
ConstructorInitializerIndentWidth: 4
ContinuationIndentWidth: 4
Cpp11BracedListStyle: true
DerivePointerAlignment: false DerivePointerAlignment: false
DisableFormat: false
ExperimentalAutoDetectBinPacking: false ExperimentalAutoDetectBinPacking: false
ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ]
IncludeCategories:
- Regex: '^"(llvm|llvm-c|clang|clang-c)/'
Priority: 2
- Regex: '^(<|"(gtest|isl|json)/)'
Priority: 3
- Regex: '.*'
Priority: 1
IncludeIsMainRegex: '$'
IndentCaseLabels: false IndentCaseLabels: false
IndentWidth: 2
IndentWrappedFunctionNames: false IndentWrappedFunctionNames: false
JavaScriptQuotes: Leave IndentFunctionDeclarationAfterType: false
JavaScriptWrapImports: true
KeepEmptyLinesAtTheStartOfBlocks: true
MacroBlockBegin: ''
MacroBlockEnd: ''
MaxEmptyLinesToKeep: 1 MaxEmptyLinesToKeep: 1
KeepEmptyLinesAtTheStartOfBlocks: true
NamespaceIndentation: None NamespaceIndentation: None
ObjCBlockIndentWidth: 2
ObjCSpaceAfterProperty: false ObjCSpaceAfterProperty: false
ObjCSpaceBeforeProtocolList: true ObjCSpaceBeforeProtocolList: true
PenaltyBreakBeforeFirstCallParameter: 19 PenaltyBreakBeforeFirstCallParameter: 19
PenaltyBreakComment: 300 PenaltyBreakComment: 300
PenaltyBreakFirstLessLess: 120
PenaltyBreakString: 1000 PenaltyBreakString: 1000
PenaltyBreakFirstLessLess: 120
PenaltyExcessCharacter: 1000000 PenaltyExcessCharacter: 1000000
PenaltyReturnTypeOnItsOwnLine: 60 PenaltyReturnTypeOnItsOwnLine: 60
PointerAlignment: Right PointerAlignment: Right
ReflowComments: true
SortIncludes: false
SpaceAfterCStyleCast: false
SpaceBeforeAssignmentOperators: true
SpaceBeforeParens: ControlStatements
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 1 SpacesBeforeTrailingComments: 1
SpacesInAngles: false Cpp11BracedListStyle: true
SpacesInContainerLiterals: true
SpacesInCStyleCastParentheses: false
SpacesInParentheses: false
SpacesInSquareBrackets: false
Standard: Cpp11 Standard: Cpp11
IndentWidth: 2
TabWidth: 8 TabWidth: 8
UseTab: Never UseTab: Never
BreakBeforeBraces: Attach
SpacesInParentheses: false
SpacesInAngles: false
SpaceInEmptyParentheses: false
SpacesInCStyleCastParentheses: false
SpacesInContainerLiterals: true
SpaceBeforeAssignmentOperators: true
ContinuationIndentWidth: 4
CommentPragmas: '^ IWYU pragma:'
ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ]
SpaceBeforeParens: ControlStatements
DisableFormat: false
... ...

View File

@@ -43,7 +43,6 @@ before_script:
- git clone https://github.com/tatsuhiro-t/spdylay.git - git clone https://github.com/tatsuhiro-t/spdylay.git
- cd spdylay - cd spdylay
- autoreconf -i - autoreconf -i
# Don't use ASAN for spdylay since failmalloc does not work with it.
- ./configure --disable-src --disable-examples - ./configure --disable-src --disable-examples
- make check - make check
- export SPDYLAY_HOME=$PWD - export SPDYLAY_HOME=$PWD
@@ -51,13 +50,15 @@ before_script:
# Now build nghttp2 # Now build nghttp2
- if [ "$CI_BUILD" = "autotools" ]; then autoreconf -i; fi - if [ "$CI_BUILD" = "autotools" ]; then autoreconf -i; fi
- git submodule update --init - git submodule update --init
- if [ "$CI_BUILD" = "autotools" ]; then ./configure --enable-werror --with-mruby --with-neverbleed LIBSPDYLAY_CFLAGS="-I$SPDYLAY_HOME/lib/includes" LIBSPDYLAY_LIBS="-L$SPDYLAY_HOME/lib/.libs -lspdylay" CPPFLAGS=-fsanitize=address LDFLAGS=-fsanitize=address; fi - if [ "$CI_BUILD" = "autotools" ]; then ./configure --enable-werror --with-mruby --with-neverbleed LIBSPDYLAY_CFLAGS="-I$SPDYLAY_HOME/lib/includes" LIBSPDYLAY_LIBS="-L$SPDYLAY_HOME/lib/.libs -lspdylay"; fi
- if [ "$CI_BUILD" = "cmake" ]; then cmake -DENABLE_WERROR=1 -DWITH_MRUBY=1 -DWITH_NEVERBLEED=1 -DSPDYLAY_INCLUDE_DIR="$SPDYLAY_HOME/lib/includes" -DSPDYLAY_LIBRARY="$SPDYLAY_HOME/lib/.libs/libspdylay.so"; fi - if [ "$CI_BUILD" = "cmake" ]; then cmake -DENABLE_WERROR=1 -DWITH_MRUBY=1 -DWITH_NEVERBLEED=1 -DSPDYLAY_INCLUDE_DIR="$SPDYLAY_HOME/lib/includes" -DSPDYLAY_LIBRARY="$SPDYLAY_HOME/lib/.libs/libspdylay.so"; fi
script: script:
- make
- make check - make check
- cd integration-tests
# As of April, 23, 2016, golang http2 build fails, probably because # As of April, 23, 2016, golang http2 build fails, probably because
# the default go version is too old. # the default go version is too old.
# - cd integration-tests
# - export GOPATH="$PWD/integration-tests/golang" # - export GOPATH="$PWD/integration-tests/golang"
# - make itprep # - make itprep
# - make it # - make it

View File

@@ -32,7 +32,6 @@ Etienne Cimon
Fabian Möller Fabian Möller
Fabian Wiesel Fabian Wiesel
Gabi Davar Gabi Davar
Google Inc.
Jacob Champion Jacob Champion
Jan-E Jan-E
Janusz Dziemidowicz Janusz Dziemidowicz
@@ -72,7 +71,6 @@ Tomasz Buchert
Vernon Tang Vernon Tang
Viacheslav Biriukov Viacheslav Biriukov
Viktor Szépe Viktor Szépe
Wenfeng Liu
Xiaoguang Sun Xiaoguang Sun
Zhuoyun Wei Zhuoyun Wei
acesso acesso

View File

@@ -24,15 +24,15 @@
cmake_minimum_required(VERSION 3.0) cmake_minimum_required(VERSION 3.0)
# XXX using 1.8.90 instead of 1.9.0-DEV # XXX using 1.8.90 instead of 1.9.0-DEV
project(nghttp2 VERSION 1.16.1) project(nghttp2 VERSION 1.11.1)
# See versioning rule: # See versioning rule:
# http://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html # http://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html
set(LT_CURRENT 26) set(LT_CURRENT 22)
set(LT_REVISION 1) set(LT_REVISION 0)
set(LT_AGE 12) set(LT_AGE 8)
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake")
include(Version) include(Version)
math(EXPR LT_SOVERSION "${LT_CURRENT} - ${LT_AGE}") math(EXPR LT_SOVERSION "${LT_CURRENT} - ${LT_AGE}")
@@ -408,10 +408,10 @@ configure_file(cmakeconfig.h.in config.h)
# autotools-compatible names # autotools-compatible names
# Sphinx expects relative paths in the .rst files. Use the fact that the files # Sphinx expects relative paths in the .rst files. Use the fact that the files
# below are all one directory level deep. # below are all one directory level deep.
file(RELATIVE_PATH top_srcdir "${CMAKE_CURRENT_BINARY_DIR}/dir" "${CMAKE_CURRENT_SOURCE_DIR}") file(RELATIVE_PATH top_srcdir "${CMAKE_BINARY_DIR}/dir" "${CMAKE_SOURCE_DIR}")
file(RELATIVE_PATH top_builddir "${CMAKE_CURRENT_BINARY_DIR}/dir" "${CMAKE_CURRENT_BINARY_DIR}") file(RELATIVE_PATH top_builddir "${CMAKE_BINARY_DIR}/dir" "${CMAKE_BINARY_DIR}")
set(abs_top_srcdir "${CMAKE_CURRENT_SOURCE_DIR}") set(abs_top_srcdir "${CMAKE_SOURCE_DIR}")
set(abs_top_builddir "${CMAKE_CURRENT_BINARY_DIR}") set(abs_top_builddir "${CMAKE_BINARY_DIR}")
# libnghttp2.pc (pkg-config file) # libnghttp2.pc (pkg-config file)
set(prefix "${CMAKE_INSTALL_PREFIX}") set(prefix "${CMAKE_INSTALL_PREFIX}")
set(exec_prefix "${CMAKE_INSTALL_PREFIX}") set(exec_prefix "${CMAKE_INSTALL_PREFIX}")
@@ -450,7 +450,7 @@ foreach(name
endforeach() endforeach()
include_directories( include_directories(
"${CMAKE_CURRENT_BINARY_DIR}" # for config.h "${CMAKE_BINARY_DIR}" # for config.h
) )
# For use in src/CMakeLists.txt # For use in src/CMakeLists.txt
set(PKGDATADIR "${CMAKE_INSTALL_FULL_DATADIR}/${CMAKE_PROJECT_NAME}") set(PKGDATADIR "${CMAKE_INSTALL_FULL_DATADIR}/${CMAKE_PROJECT_NAME}")

View File

@@ -58,11 +58,6 @@ To build the documentation, you need to install:
* sphinx (http://sphinx-doc.org/) * sphinx (http://sphinx-doc.org/)
If you need libnghttp2 (C library) only, then the above packages are
all you need. Use ``--enable-lib-only`` to ensure that only
libnghttp2 is built. This avoids potential build error related to
building bundled applications.
To build and run the application programs (``nghttp``, ``nghttpd``, To build and run the application programs (``nghttp``, ``nghttpd``,
``nghttpx`` and ``h2load``) in the ``src`` directory, the following packages ``nghttpx`` and ``h2load``) in the ``src`` directory, the following packages
are required: are required:
@@ -181,23 +176,6 @@ To compile the source code, gcc >= 4.8.3 or clang >= 3.4 is required.
applications were not built, then using ``--enable-app`` may find applications were not built, then using ``--enable-app`` may find
that cause, such as the missing dependency. that cause, such as the missing dependency.
Notes for building on Windows (MSVC)
------------------------------------
The easiest way to build native Windows nghttp2 dll is use `cmake
<https://cmake.org/>`_. The free version of `Visual C++ Build Tools
<http://landinghub.visualstudio.com/visual-cpp-build-tools>`_ works
fine.
1. Install cmake for windows
2. Open "Visual C++ ... Native Build Tool Command Prompt", and inside
nghttp2 directly, run ``cmake``.
3. Then run ``cmake --build`` to build library.
4. nghttp2.dll, nghttp2.lib, nghttp2.exp are placed under lib directory.
Note that the above steps most likely produce nghttp2 library only.
No bundled applications are compiled.
Notes for building on Windows (Mingw/Cygwin) Notes for building on Windows (Mingw/Cygwin)
-------------------------------------------- --------------------------------------------
@@ -1375,7 +1353,7 @@ The extension module is called ``nghttp2``.
determined by the ``configure`` script. If the detected Python version is not determined by the ``configure`` script. If the detected Python version is not
what you expect, specify a path to Python executable in a ``PYTHON`` what you expect, specify a path to Python executable in a ``PYTHON``
variable as an argument to configure script (e.g., ``./configure variable as an argument to configure script (e.g., ``./configure
PYTHON=/usr/bin/python3.5``). PYTHON=/usr/bin/python3.4``).
The following example code illustrates basic usage of the HPACK compressor The following example code illustrates basic usage of the HPACK compressor
and decompressor in Python: and decompressor in Python:
@@ -1505,17 +1483,6 @@ See `Contribution Guidelines
<https://nghttp2.org/documentation/contribute.html>`_ for more <https://nghttp2.org/documentation/contribute.html>`_ for more
details. details.
Reporting vulnerability
-----------------------
If you find a vulnerability in our software, please send the email to
"tatsuhiro.t at gmail dot com" about its details instead of submitting
issues on github issue page. It is a standard practice not to
disclose vulnerability information publicly until a fixed version is
released, or mitigation is worked out.
In the future, we may setup a dedicated mail address for this purpose.
Release schedule Release schedule
---------------- ----------------
@@ -1528,8 +1495,3 @@ severe security bug fixes.
We have no plan to break API compatibility changes involving soname We have no plan to break API compatibility changes involving soname
bump, so MAJOR version will stay 1 for the foreseeable future. bump, so MAJOR version will stay 1 for the foreseeable future.
License
-------
The MIT License

View File

@@ -39,8 +39,9 @@ PATH="$TOOLCHAIN"/bin:"$PATH"
--without-libxml2 \ --without-libxml2 \
--disable-python-bindings \ --disable-python-bindings \
--disable-examples \ --disable-examples \
CC="$TOOLCHAIN"/bin/arm-linux-androideabi-gcc \ --enable-werror \
CXX="$TOOLCHAIN"/bin/arm-linux-androideabi-g++ \ CC="$TOOLCHAIN"/bin/clang \
CXX="$TOOLCHAIN"/bin/clang++ \
CPPFLAGS="-fPIE -I$PREFIX/include" \ CPPFLAGS="-fPIE -I$PREFIX/include" \
PKG_CONFIG_LIBDIR="$PREFIX/lib/pkgconfig" \ PKG_CONFIG_LIBDIR="$PREFIX/lib/pkgconfig" \
LDFLAGS="-fPIE -pie -L$PREFIX/lib" LDFLAGS="-fPIE -pie -L$PREFIX/lib"

View File

@@ -1,52 +0,0 @@
#!/usr/bin/env python
# script to extract commit author's name from standard input. The
# input should be <AUTHOR>:<EMAIL>, one per line.
# This script expects the input is created by git-log command:
#
# git log --format=%aN:%aE
#
# This script removes duplicates based on email address, breaking a
# tie with longer author name. Among the all author names extract the
# previous step, we remove duplicate by case-insensitive match.
#
# So we can do this in one line:
#
# git log --format=%aN:%aE | sort | uniq | ./author.py > authors
import sys
edict = {}
for line in sys.stdin:
author, email = line.strip().split(':', 1)
if email in edict:
an = edict[email]
if len(an) < len(author) or an > author:
sys.stderr.write(
'eliminated {} in favor of {}\n'.format(an, author))
edict[email] = author
else:
sys.stderr.write(
'eliminated {} in favor of {}\n'.format(author, an))
else:
edict[email] = author
names = list(sorted(edict.values()))
ndict = {}
for name in names:
lowname = name.lower()
if lowname in ndict:
an = ndict[lowname]
if an > name:
sys.stderr.write('eliminated {} in favor of {}\n'.format(an, name))
ndict[lowname] = name
else:
sys.stderr.write('eliminated {} in favor of {}\n'.format(name, an))
else:
ndict[lowname] = name
for name in sorted(ndict.values()):
print name

View File

@@ -25,7 +25,7 @@ dnl Do not change user variables!
dnl http://www.gnu.org/software/automake/manual/html_node/Flag-Variables-Ordering.html dnl http://www.gnu.org/software/automake/manual/html_node/Flag-Variables-Ordering.html
AC_PREREQ(2.61) AC_PREREQ(2.61)
AC_INIT([nghttp2], [1.16.1], [t-tujikawa@users.sourceforge.net]) AC_INIT([nghttp2], [1.11.1], [t-tujikawa@users.sourceforge.net])
AC_CONFIG_AUX_DIR([.]) AC_CONFIG_AUX_DIR([.])
AC_CONFIG_MACRO_DIR([m4]) AC_CONFIG_MACRO_DIR([m4])
AC_CONFIG_HEADERS([config.h]) AC_CONFIG_HEADERS([config.h])
@@ -44,9 +44,9 @@ m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
dnl See versioning rule: dnl See versioning rule:
dnl http://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html dnl http://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html
AC_SUBST(LT_CURRENT, 26) AC_SUBST(LT_CURRENT, 22)
AC_SUBST(LT_REVISION, 1) AC_SUBST(LT_REVISION, 0)
AC_SUBST(LT_AGE, 12) AC_SUBST(LT_AGE, 8)
major=`echo $PACKAGE_VERSION |cut -d. -f1 | sed -e "s/[^0-9]//g"` major=`echo $PACKAGE_VERSION |cut -d. -f1 | sed -e "s/[^0-9]//g"`
minor=`echo $PACKAGE_VERSION |cut -d. -f2 | sed -e "s/[^0-9]//g"` minor=`echo $PACKAGE_VERSION |cut -d. -f2 | sed -e "s/[^0-9]//g"`
@@ -234,41 +234,6 @@ std::map<int, int>().emplace(1, 2);
[have_std_map_emplace=no [have_std_map_emplace=no
AC_MSG_RESULT([no])]) AC_MSG_RESULT([no])])
# Check that std::atomic_* overloads for std::shared_ptr are
# available.
AC_MSG_CHECKING([whether std::atomic_* overloads for std::shared_ptr are available])
AC_COMPILE_IFELSE([AC_LANG_PROGRAM(
[[
#include <memory>
]],
[[
auto a = std::make_shared<int>(1000000007);
auto p = std::atomic_load(&a);
++*p;
std::atomic_store(&a, p);
]])],
[AC_DEFINE([HAVE_ATOMIC_STD_SHARED_PTR], [1],
[Define to 1 if you have the std::atomic_* overloads for std::shared_ptr.])
have_atomic_std_shared_ptr=yes
AC_MSG_RESULT([yes])],
[have_atomic_std_shared_ptr=no
AC_MSG_RESULT([no])])
# Check that thread_local storage specifier is available
AC_MSG_CHECKING([whether thread_local storage class specifier is available.])
AC_COMPILE_IFELSE([AC_LANG_PROGRAM(
,
[[
thread_local int a = 0;
(void)a;
]])],
[AC_DEFINE([HAVE_THREAD_LOCAL], [1],
[Define to 1 if you have thread_local storage specifier.])
have_thread_local=yes
AC_MSG_RESULT([yes])],
[have_Thread_local=no
AC_MSG_RESULT([no])])
CXXFLAGS=$save_CXXFLAGS CXXFLAGS=$save_CXXFLAGS
AC_LANG_POP() AC_LANG_POP()
@@ -281,7 +246,7 @@ TESTLDADD=
# Additional libraries required for programs under src directory. # Additional libraries required for programs under src directory.
APPLDFLAGS= APPLDFLAGS=
case "$host_os" in case "$host" in
*android*) *android*)
android_build=yes android_build=yes
# android does not need -pthread, but needs followng 3 libs for C++ # android does not need -pthread, but needs followng 3 libs for C++
@@ -293,12 +258,6 @@ case "$host_os" in
;; ;;
esac esac
case "$host_os" in
*solaris*)
APPLDFLAGS="$APPLDFLAGS -lsocket -lnsl"
;;
esac
# zlib # zlib
PKG_CHECK_MODULES([ZLIB], [zlib >= 1.2.3], [have_zlib=yes], [have_zlib=no]) PKG_CHECK_MODULES([ZLIB], [zlib >= 1.2.3], [have_zlib=yes], [have_zlib=no])
@@ -761,7 +720,6 @@ if test "x$werror" != "xno"; then
AX_CHECK_COMPILE_FLAG([-Wredundant-decls], [CFLAGS="$CFLAGS -Wredundant-decls"]) AX_CHECK_COMPILE_FLAG([-Wredundant-decls], [CFLAGS="$CFLAGS -Wredundant-decls"])
# Only work with Clang for the moment # Only work with Clang for the moment
AX_CHECK_COMPILE_FLAG([-Wheader-guard], [CFLAGS="$CFLAGS -Wheader-guard"]) AX_CHECK_COMPILE_FLAG([-Wheader-guard], [CFLAGS="$CFLAGS -Wheader-guard"])
AX_CHECK_COMPILE_FLAG([-Wsometimes-uninitialized], [CFLAGS="$CFLAGS -Wsometimes-uninitialized"])
# This is required because we pass format string as "const char*. # This is required because we pass format string as "const char*.
AX_CHECK_COMPILE_FLAG([-Wno-format-nonliteral], [CFLAGS="$CFLAGS -Wno-format-nonliteral"]) AX_CHECK_COMPILE_FLAG([-Wno-format-nonliteral], [CFLAGS="$CFLAGS -Wno-format-nonliteral"])
@@ -771,7 +729,6 @@ if test "x$werror" != "xno"; then
AX_CHECK_COMPILE_FLAG([-Wall], [CXXFLAGS="$CXXFLAGS -Wall"]) AX_CHECK_COMPILE_FLAG([-Wall], [CXXFLAGS="$CXXFLAGS -Wall"])
AX_CHECK_COMPILE_FLAG([-Werror], [CXXFLAGS="$CXXFLAGS -Werror"]) AX_CHECK_COMPILE_FLAG([-Werror], [CXXFLAGS="$CXXFLAGS -Werror"])
AX_CHECK_COMPILE_FLAG([-Wformat-security], [CXXFLAGS="$CXXFLAGS -Wformat-security"]) AX_CHECK_COMPILE_FLAG([-Wformat-security], [CXXFLAGS="$CXXFLAGS -Wformat-security"])
AX_CHECK_COMPILE_FLAG([-Wsometimes-uninitialized], [CXXFLAGS="$CXXFLAGS -Wsometimes-uninitialized"])
AC_LANG_POP() AC_LANG_POP()
fi fi
@@ -868,7 +825,6 @@ AC_MSG_NOTICE([summary of build options:
C preprocessor: ${CPP} C preprocessor: ${CPP}
CPPFLAGS: ${CPPFLAGS} CPPFLAGS: ${CPPFLAGS}
WARNCFLAGS: ${WARNCFLAGS} WARNCFLAGS: ${WARNCFLAGS}
WARNCXXFLAGS: ${WARNCXXFLAGS}
CXX1XCXXFLAGS: ${CXX1XCXXFLAGS} CXX1XCXXFLAGS: ${CXX1XCXXFLAGS}
EXTRACFLAG: ${EXTRACFLAG} EXTRACFLAG: ${EXTRACFLAG}
LIBS: ${LIBS} LIBS: ${LIBS}

View File

@@ -13,7 +13,6 @@ set(APIDOCS
nghttp2_hd_deflate_get_num_table_entries.rst nghttp2_hd_deflate_get_num_table_entries.rst
nghttp2_hd_deflate_get_table_entry.rst nghttp2_hd_deflate_get_table_entry.rst
nghttp2_hd_deflate_hd.rst nghttp2_hd_deflate_hd.rst
nghttp2_hd_deflate_hd_vec.rst
nghttp2_hd_deflate_new.rst nghttp2_hd_deflate_new.rst
nghttp2_hd_deflate_new2.rst nghttp2_hd_deflate_new2.rst
nghttp2_hd_inflate_change_table_size.rst nghttp2_hd_inflate_change_table_size.rst
@@ -24,7 +23,6 @@ set(APIDOCS
nghttp2_hd_inflate_get_num_table_entries.rst nghttp2_hd_inflate_get_num_table_entries.rst
nghttp2_hd_inflate_get_table_entry.rst nghttp2_hd_inflate_get_table_entry.rst
nghttp2_hd_inflate_hd.rst nghttp2_hd_inflate_hd.rst
nghttp2_hd_inflate_hd2.rst
nghttp2_hd_inflate_new.rst nghttp2_hd_inflate_new.rst
nghttp2_hd_inflate_new2.rst nghttp2_hd_inflate_new2.rst
nghttp2_http2_strerror.rst nghttp2_http2_strerror.rst
@@ -33,9 +31,7 @@ set(APIDOCS
nghttp2_option_del.rst nghttp2_option_del.rst
nghttp2_option_new.rst nghttp2_option_new.rst
nghttp2_option_set_builtin_recv_extension_type.rst nghttp2_option_set_builtin_recv_extension_type.rst
nghttp2_option_set_max_deflate_dynamic_table_size.rst
nghttp2_option_set_max_reserved_remote_streams.rst nghttp2_option_set_max_reserved_remote_streams.rst
nghttp2_option_set_max_send_header_block_length.rst
nghttp2_option_set_no_auto_ping_ack.rst nghttp2_option_set_no_auto_ping_ack.rst
nghttp2_option_set_no_auto_window_update.rst nghttp2_option_set_no_auto_window_update.rst
nghttp2_option_set_no_http_messaging.rst nghttp2_option_set_no_http_messaging.rst
@@ -58,15 +54,13 @@ set(APIDOCS
nghttp2_session_callbacks_set_on_begin_frame_callback.rst nghttp2_session_callbacks_set_on_begin_frame_callback.rst
nghttp2_session_callbacks_set_on_begin_headers_callback.rst nghttp2_session_callbacks_set_on_begin_headers_callback.rst
nghttp2_session_callbacks_set_on_data_chunk_recv_callback.rst nghttp2_session_callbacks_set_on_data_chunk_recv_callback.rst
nghttp2_session_callbacks_set_on_extension_chunk_recv_callback.rst
nghttp2_session_callbacks_set_on_frame_not_send_callback.rst nghttp2_session_callbacks_set_on_frame_not_send_callback.rst
nghttp2_session_callbacks_set_on_frame_recv_callback.rst nghttp2_session_callbacks_set_on_frame_recv_callback.rst
nghttp2_session_callbacks_set_on_extension_chunk_recv_callback.rst
nghttp2_session_callbacks_set_on_frame_send_callback.rst nghttp2_session_callbacks_set_on_frame_send_callback.rst
nghttp2_session_callbacks_set_on_header_callback.rst nghttp2_session_callbacks_set_on_header_callback.rst
nghttp2_session_callbacks_set_on_header_callback2.rst nghttp2_session_callbacks_set_on_header_callback2.rst
nghttp2_session_callbacks_set_on_invalid_frame_recv_callback.rst nghttp2_session_callbacks_set_on_invalid_frame_recv_callback.rst
nghttp2_session_callbacks_set_on_invalid_header_callback.rst
nghttp2_session_callbacks_set_on_invalid_header_callback2.rst
nghttp2_session_callbacks_set_on_stream_close_callback.rst nghttp2_session_callbacks_set_on_stream_close_callback.rst
nghttp2_session_callbacks_set_pack_extension_callback.rst nghttp2_session_callbacks_set_pack_extension_callback.rst
nghttp2_session_callbacks_set_recv_callback.rst nghttp2_session_callbacks_set_recv_callback.rst
@@ -74,9 +68,6 @@ set(APIDOCS
nghttp2_session_callbacks_set_send_callback.rst nghttp2_session_callbacks_set_send_callback.rst
nghttp2_session_callbacks_set_send_data_callback.rst nghttp2_session_callbacks_set_send_data_callback.rst
nghttp2_session_callbacks_set_unpack_extension_callback.rst nghttp2_session_callbacks_set_unpack_extension_callback.rst
nghttp2_session_change_stream_priority.rst
nghttp2_session_check_request_allowed.rst
nghttp2_session_check_server_session.rst
nghttp2_session_client_new.rst nghttp2_session_client_new.rst
nghttp2_session_client_new2.rst nghttp2_session_client_new2.rst
nghttp2_session_client_new3.rst nghttp2_session_client_new3.rst
@@ -88,11 +79,7 @@ set(APIDOCS
nghttp2_session_find_stream.rst nghttp2_session_find_stream.rst
nghttp2_session_get_effective_local_window_size.rst nghttp2_session_get_effective_local_window_size.rst
nghttp2_session_get_effective_recv_data_length.rst nghttp2_session_get_effective_recv_data_length.rst
nghttp2_session_get_hd_deflate_dynamic_table_size.rst
nghttp2_session_get_hd_inflate_dynamic_table_size.rst
nghttp2_session_get_last_proc_stream_id.rst nghttp2_session_get_last_proc_stream_id.rst
nghttp2_session_get_local_settings.rst
nghttp2_session_get_local_window_size.rst
nghttp2_session_get_next_stream_id.rst nghttp2_session_get_next_stream_id.rst
nghttp2_session_get_outbound_queue_size.rst nghttp2_session_get_outbound_queue_size.rst
nghttp2_session_get_remote_settings.rst nghttp2_session_get_remote_settings.rst
@@ -101,19 +88,20 @@ set(APIDOCS
nghttp2_session_get_stream_effective_local_window_size.rst nghttp2_session_get_stream_effective_local_window_size.rst
nghttp2_session_get_stream_effective_recv_data_length.rst nghttp2_session_get_stream_effective_recv_data_length.rst
nghttp2_session_get_stream_local_close.rst nghttp2_session_get_stream_local_close.rst
nghttp2_session_get_stream_local_window_size.rst
nghttp2_session_get_stream_remote_close.rst nghttp2_session_get_stream_remote_close.rst
nghttp2_session_get_stream_remote_window_size.rst nghttp2_session_get_stream_remote_window_size.rst
nghttp2_session_get_stream_user_data.rst nghttp2_session_get_stream_user_data.rst
nghttp2_session_mem_recv.rst nghttp2_session_mem_recv.rst
nghttp2_session_mem_send.rst nghttp2_session_mem_send.rst
nghttp2_session_recv.rst nghttp2_session_recv.rst
nghttp2_session_change_stream_priority.rst
nghttp2_session_check_request_allowed.rst
nghttp2_session_check_server_session.rst
nghttp2_session_resume_data.rst nghttp2_session_resume_data.rst
nghttp2_session_send.rst nghttp2_session_send.rst
nghttp2_session_server_new.rst nghttp2_session_server_new.rst
nghttp2_session_server_new2.rst nghttp2_session_server_new2.rst
nghttp2_session_server_new3.rst nghttp2_session_server_new3.rst
nghttp2_session_set_local_window_size.rst
nghttp2_session_set_next_stream_id.rst nghttp2_session_set_next_stream_id.rst
nghttp2_session_set_stream_user_data.rst nghttp2_session_set_stream_user_data.rst
nghttp2_session_terminate_session.rst nghttp2_session_terminate_session.rst
@@ -122,7 +110,6 @@ set(APIDOCS
nghttp2_session_upgrade2.rst nghttp2_session_upgrade2.rst
nghttp2_session_want_read.rst nghttp2_session_want_read.rst
nghttp2_session_want_write.rst nghttp2_session_want_write.rst
nghttp2_set_debug_vprintf_callback.rst
nghttp2_stream_get_first_child.rst nghttp2_stream_get_first_child.rst
nghttp2_stream_get_next_sibling.rst nghttp2_stream_get_next_sibling.rst
nghttp2_stream_get_parent.rst nghttp2_stream_get_parent.rst

View File

@@ -37,7 +37,6 @@ APIDOCS= \
nghttp2_hd_deflate_get_num_table_entries.rst \ nghttp2_hd_deflate_get_num_table_entries.rst \
nghttp2_hd_deflate_get_table_entry.rst \ nghttp2_hd_deflate_get_table_entry.rst \
nghttp2_hd_deflate_hd.rst \ nghttp2_hd_deflate_hd.rst \
nghttp2_hd_deflate_hd_vec.rst \
nghttp2_hd_deflate_new.rst \ nghttp2_hd_deflate_new.rst \
nghttp2_hd_deflate_new2.rst \ nghttp2_hd_deflate_new2.rst \
nghttp2_hd_inflate_change_table_size.rst \ nghttp2_hd_inflate_change_table_size.rst \
@@ -57,9 +56,7 @@ APIDOCS= \
nghttp2_option_del.rst \ nghttp2_option_del.rst \
nghttp2_option_new.rst \ nghttp2_option_new.rst \
nghttp2_option_set_builtin_recv_extension_type.rst \ nghttp2_option_set_builtin_recv_extension_type.rst \
nghttp2_option_set_max_deflate_dynamic_table_size.rst \
nghttp2_option_set_max_reserved_remote_streams.rst \ nghttp2_option_set_max_reserved_remote_streams.rst \
nghttp2_option_set_max_send_header_block_length.rst \
nghttp2_option_set_no_auto_ping_ack.rst \ nghttp2_option_set_no_auto_ping_ack.rst \
nghttp2_option_set_no_auto_window_update.rst \ nghttp2_option_set_no_auto_window_update.rst \
nghttp2_option_set_no_http_messaging.rst \ nghttp2_option_set_no_http_messaging.rst \
@@ -89,8 +86,6 @@ APIDOCS= \
nghttp2_session_callbacks_set_on_header_callback.rst \ nghttp2_session_callbacks_set_on_header_callback.rst \
nghttp2_session_callbacks_set_on_header_callback2.rst \ nghttp2_session_callbacks_set_on_header_callback2.rst \
nghttp2_session_callbacks_set_on_invalid_frame_recv_callback.rst \ nghttp2_session_callbacks_set_on_invalid_frame_recv_callback.rst \
nghttp2_session_callbacks_set_on_invalid_header_callback.rst \
nghttp2_session_callbacks_set_on_invalid_header_callback2.rst \
nghttp2_session_callbacks_set_on_stream_close_callback.rst \ nghttp2_session_callbacks_set_on_stream_close_callback.rst \
nghttp2_session_callbacks_set_pack_extension_callback.rst \ nghttp2_session_callbacks_set_pack_extension_callback.rst \
nghttp2_session_callbacks_set_recv_callback.rst \ nghttp2_session_callbacks_set_recv_callback.rst \
@@ -98,9 +93,6 @@ APIDOCS= \
nghttp2_session_callbacks_set_send_callback.rst \ nghttp2_session_callbacks_set_send_callback.rst \
nghttp2_session_callbacks_set_send_data_callback.rst \ nghttp2_session_callbacks_set_send_data_callback.rst \
nghttp2_session_callbacks_set_unpack_extension_callback.rst \ nghttp2_session_callbacks_set_unpack_extension_callback.rst \
nghttp2_session_change_stream_priority.rst \
nghttp2_session_check_request_allowed.rst \
nghttp2_session_check_server_session.rst \
nghttp2_session_client_new.rst \ nghttp2_session_client_new.rst \
nghttp2_session_client_new2.rst \ nghttp2_session_client_new2.rst \
nghttp2_session_client_new3.rst \ nghttp2_session_client_new3.rst \
@@ -112,11 +104,7 @@ APIDOCS= \
nghttp2_session_find_stream.rst \ nghttp2_session_find_stream.rst \
nghttp2_session_get_effective_local_window_size.rst \ nghttp2_session_get_effective_local_window_size.rst \
nghttp2_session_get_effective_recv_data_length.rst \ nghttp2_session_get_effective_recv_data_length.rst \
nghttp2_session_get_hd_deflate_dynamic_table_size.rst \
nghttp2_session_get_hd_inflate_dynamic_table_size.rst \
nghttp2_session_get_last_proc_stream_id.rst \ nghttp2_session_get_last_proc_stream_id.rst \
nghttp2_session_get_local_settings.rst \
nghttp2_session_get_local_window_size.rst \
nghttp2_session_get_next_stream_id.rst \ nghttp2_session_get_next_stream_id.rst \
nghttp2_session_get_outbound_queue_size.rst \ nghttp2_session_get_outbound_queue_size.rst \
nghttp2_session_get_remote_settings.rst \ nghttp2_session_get_remote_settings.rst \
@@ -125,19 +113,20 @@ APIDOCS= \
nghttp2_session_get_stream_effective_local_window_size.rst \ nghttp2_session_get_stream_effective_local_window_size.rst \
nghttp2_session_get_stream_effective_recv_data_length.rst \ nghttp2_session_get_stream_effective_recv_data_length.rst \
nghttp2_session_get_stream_local_close.rst \ nghttp2_session_get_stream_local_close.rst \
nghttp2_session_get_stream_local_window_size.rst \
nghttp2_session_get_stream_remote_close.rst \ nghttp2_session_get_stream_remote_close.rst \
nghttp2_session_get_stream_remote_window_size.rst \ nghttp2_session_get_stream_remote_window_size.rst \
nghttp2_session_get_stream_user_data.rst \ nghttp2_session_get_stream_user_data.rst \
nghttp2_session_mem_recv.rst \ nghttp2_session_mem_recv.rst \
nghttp2_session_mem_send.rst \ nghttp2_session_mem_send.rst \
nghttp2_session_recv.rst \ nghttp2_session_recv.rst \
nghttp2_session_change_stream_priority.rst \
nghttp2_session_check_request_allowed.rst \
nghttp2_session_check_server_session.rst \
nghttp2_session_resume_data.rst \ nghttp2_session_resume_data.rst \
nghttp2_session_send.rst \ nghttp2_session_send.rst \
nghttp2_session_server_new.rst \ nghttp2_session_server_new.rst \
nghttp2_session_server_new2.rst \ nghttp2_session_server_new2.rst \
nghttp2_session_server_new3.rst \ nghttp2_session_server_new3.rst \
nghttp2_session_set_local_window_size.rst \
nghttp2_session_set_next_stream_id.rst \ nghttp2_session_set_next_stream_id.rst \
nghttp2_session_set_stream_user_data.rst \ nghttp2_session_set_stream_user_data.rst \
nghttp2_session_terminate_session.rst \ nghttp2_session_terminate_session.rst \
@@ -146,7 +135,6 @@ APIDOCS= \
nghttp2_session_upgrade2.rst \ nghttp2_session_upgrade2.rst \
nghttp2_session_want_read.rst \ nghttp2_session_want_read.rst \
nghttp2_session_want_write.rst \ nghttp2_session_want_write.rst \
nghttp2_set_debug_vprintf_callback.rst \
nghttp2_stream_get_first_child.rst \ nghttp2_stream_get_first_child.rst \
nghttp2_stream_get_next_sibling.rst \ nghttp2_stream_get_next_sibling.rst \
nghttp2_stream_get_parent.rst \ nghttp2_stream_get_parent.rst \

View File

@@ -15,7 +15,6 @@ from docutils import nodes
from docutils.parsers.rst import directives from docutils.parsers.rst import directives
from sphinx import addnodes from sphinx import addnodes
from sphinx import version_info
from sphinx.roles import XRefRole from sphinx.roles import XRefRole
from sphinx.locale import l_, _ from sphinx.locale import l_, _
from sphinx.domains import Domain, ObjType, Index from sphinx.domains import Domain, ObjType, Index
@@ -232,8 +231,8 @@ class RubyObject(ObjectDescription):
indextext = self.get_index_text(modname, name_cls) indextext = self.get_index_text(modname, name_cls)
if indextext: if indextext:
self.indexnode['entries'].append( self.indexnode['entries'].append(('single', indextext,
_make_index('single', indextext, fullname, fullname)) fullname, fullname))
def before_content(self): def before_content(self):
# needed for automatic qualification of members (reset in subclasses) # needed for automatic qualification of members (reset in subclasses)
@@ -416,19 +415,11 @@ class RubyModule(Directive):
# modindex currently # modindex currently
if not noindex: if not noindex:
indextext = _('%s (module)') % modname indextext = _('%s (module)') % modname
inode = addnodes.index(entries=[_make_index( inode = addnodes.index(entries=[('single', indextext,
'single', indextext, 'module-' + modname, modname)]) 'module-' + modname, modname)])
ret.append(inode) ret.append(inode)
return ret return ret
def _make_index(entrytype, entryname, target, ignored, key=None):
# Sphinx 1.4 introduced backward incompatible changes, it now
# requires 5 tuples. Last one is categorization key. See
# http://www.sphinx-doc.org/en/stable/extdev/nodes.html#sphinx.addnodes.index
if version_info >= (1, 4, 0, '', 0):
return (entrytype, entryname, target, ignored, key)
else:
return (entrytype, entryname, target, ignored)
class RubyCurrentModule(Directive): class RubyCurrentModule(Directive):
""" """

View File

@@ -8,7 +8,7 @@ _h2load()
_get_comp_words_by_ref cur prev _get_comp_words_by_ref cur prev
case $cur in case $cur in
-*) -*)
COMPREPLY=( $( compgen -W '--connection-window-bits --clients --verbose --ciphers --rate --no-tls-proto --header-table-size --requests --base-uri --h1 --threads --npn-list --rate-period --data --version --connection-inactivity-timeout --timing-script-file --encoder-header-table-size --max-concurrent-streams --connection-active-timeout --input-file --help --window-bits --header ' -- "$cur" ) ) COMPREPLY=( $( compgen -W '--connection-window-bits --clients --verbose --ciphers --rate --no-tls-proto --requests --base-uri --h1 --threads --npn-list --rate-period --data --version --connection-inactivity-timeout --timing-script-file --max-concurrent-streams --connection-active-timeout --input-file --header --window-bits --help ' -- "$cur" ) )
;; ;;
*) *)
_filedir _filedir

View File

@@ -8,7 +8,7 @@ _nghttp()
_get_comp_words_by_ref cur prev _get_comp_words_by_ref cur prev
case $cur in case $cur in
-*) -*)
COMPREPLY=( $( compgen -W '--no-push --verbose --no-dep --get-assets --har --header-table-size --multiply --encoder-header-table-size --padding --hexdump --max-concurrent-streams --continuation --connection-window-bits --peer-max-concurrent-streams --timeout --data --no-content-length --version --color --cert --upgrade --remote-name --trailer --weight --help --key --null-out --window-bits --expect-continue --stat --header ' -- "$cur" ) ) COMPREPLY=( $( compgen -W '--no-push --verbose --no-dep --get-assets --har --header-table-size --multiply --padding --hexdump --max-concurrent-streams --continuation --connection-window-bits --peer-max-concurrent-streams --timeout --data --no-content-length --version --color --cert --upgrade --remote-name --trailer --weight --help --key --null-out --window-bits --expect-continue --stat --header ' -- "$cur" ) )
;; ;;
*) *)
_filedir _filedir

View File

@@ -8,7 +8,7 @@ _nghttpd()
_get_comp_words_by_ref cur prev _get_comp_words_by_ref cur prev
case $cur in case $cur in
-*) -*)
COMPREPLY=( $( compgen -W '--htdocs --verbose --daemon --echo-upload --error-gzip --push --header-table-size --encoder-header-table-size --padding --hexdump --max-concurrent-streams --no-tls --connection-window-bits --mime-types-file --no-content-length --workers --version --color --early-response --dh-param-file --trailer --address --window-bits --verify-client --help ' -- "$cur" ) ) COMPREPLY=( $( compgen -W '--htdocs --verbose --daemon --echo-upload --error-gzip --push --header-table-size --padding --hexdump --max-concurrent-streams --no-tls --connection-window-bits --mime-types-file --no-content-length --workers --version --color --early-response --dh-param-file --trailer --address --window-bits --verify-client --help ' -- "$cur" ) )
;; ;;
*) *)
_filedir _filedir

View File

@@ -8,7 +8,7 @@ _nghttpx()
_get_comp_words_by_ref cur prev _get_comp_words_by_ref cur prev
case $cur in case $cur in
-*) -*)
COMPREPLY=( $( compgen -W '--worker-read-rate --include --frontend-http2-dump-response-header --tls-ticket-key-file --verify-client-cacert --max-response-header-fields --backend-http2-window-size --backend-request-buffer --max-request-header-fields --fastopen --tls-ticket-key-memcached --conf --backend-http2-max-concurrent-streams --worker-write-burst --npn-list --fetch-ocsp-response-file --no-via --tls-session-cache-memcached-cert-file --no-http2-cipher-black-list --mruby-file --stream-read-timeout --backend-connect-timeout --forwarded-for --accesslog-syslog --frontend-http2-read-timeout --listener-disable-timeout --ciphers --strip-incoming-x-forwarded-for --no-server-rewrite --private-key-passwd-file --backend-keep-alive-timeout --backend-http-proxy-uri --rlimit-nofile --tls-ticket-key-memcached-cert-file --ocsp-update-interval --forwarded-by --tls-session-cache-memcached-private-key-file --error-page --backend-write-timeout --tls-dyn-rec-warmup-threshold --tls-ticket-key-memcached-max-retry --frontend-http2-window-size --http2-no-cookie-crumbling --worker-read-burst --dh-param-file --accesslog-format --errorlog-syslog --request-header-field-buffer --api-max-request-body --frontend-http2-decoder-dynamic-table-size --errorlog-file --frontend-http2-max-concurrent-streams --frontend-write-timeout --tls-ticket-key-cipher --read-burst --backend --server-name --insecure --backend-max-backoff --log-level --host-rewrite --tls-proto-list --tls-ticket-key-memcached-interval --frontend-http2-setting-timeout --frontend-http2-connection-window-size --worker-frontend-connections --syslog-facility --no-server-push --no-location-rewrite --tls-session-cache-memcached --no-ocsp --frontend-http2-encoder-dynamic-table-size --workers --add-forwarded --worker-write-rate --add-request-header --backend-http2-settings-timeout --subcert --ecdh-curves --no-kqueue --help --frontend-frame-debug --tls-sct-dir --pid-file --frontend-http2-dump-request-header --daemon --write-rate --altsvc --backend-http2-decoder-dynamic-table-size --user --add-x-forwarded-for --frontend-read-timeout --tls-ticket-key-memcached-max-fail --backlog --write-burst --backend-connections-per-host --response-header-field-buffer --tls-ticket-key-memcached-address-family --padding --tls-session-cache-memcached-address-family --stream-write-timeout --cacert --tls-ticket-key-memcached-private-key-file --backend-address-family --backend-http2-connection-window-size --version --add-response-header --backend-read-timeout --frontend-http2-optimize-window-size --frontend --accesslog-file --http2-proxy --backend-http2-encoder-dynamic-table-size --client-private-key-file --client-cert-file --accept-proxy-protocol --tls-dyn-rec-idle-timeout --frontend-http2-optimize-write-buffer-size --verify-client --backend-response-buffer --read-rate --backend-connections-per-frontend --strip-incoming-forwarded ' -- "$cur" ) ) COMPREPLY=( $( compgen -W '--worker-read-rate --include --frontend-http2-dump-response-header --tls-ticket-key-file --verify-client-cacert --max-response-header-fields --backend-request-buffer --max-request-header-fields --backend-http2-connection-window-bits --conf --backend-http2-max-concurrent-streams --worker-write-burst --npn-list --fetch-ocsp-response-file --no-via --tls-session-cache-memcached-cert-file --no-http2-cipher-black-list --mruby-file --no-server-push --stream-read-timeout --tls-ticket-key-memcached --forwarded-for --accesslog-syslog --frontend-http2-read-timeout --listener-disable-timeout --frontend-http2-connection-window-bits --ciphers --strip-incoming-x-forwarded-for --private-key-passwd-file --backend-keep-alive-timeout --backend-http-proxy-uri --rlimit-nofile --tls-ticket-key-memcached-cert-file --ocsp-update-interval --forwarded-by --tls-session-cache-memcached-private-key-file --error-page --backend-write-timeout --tls-dyn-rec-warmup-threshold --tls-ticket-key-memcached-max-retry --http2-no-cookie-crumbling --worker-read-burst --dh-param-file --accesslog-format --errorlog-syslog --request-header-field-buffer --errorlog-file --frontend-http2-max-concurrent-streams --frontend-write-timeout --tls-ticket-key-cipher --read-burst --backend --insecure --log-level --host-rewrite --tls-proto-list --tls-ticket-key-memcached-interval --frontend-http2-setting-timeout --worker-frontend-connections --syslog-facility --fastopen --no-location-rewrite --tls-session-cache-memcached --no-ocsp --backend-response-buffer --workers --add-forwarded --frontend-http2-window-bits --worker-write-rate --add-request-header --backend-http2-settings-timeout --subcert --no-kqueue --help --frontend-frame-debug --pid-file --frontend-http2-dump-request-header --daemon --write-rate --altsvc --user --add-x-forwarded-for --frontend-read-timeout --tls-ticket-key-memcached-max-fail --backlog --write-burst --backend-connections-per-host --backend-http2-window-bits --response-header-field-buffer --tls-ticket-key-memcached-address-family --padding --tls-session-cache-memcached-address-family --stream-write-timeout --cacert --tls-ticket-key-memcached-private-key-file --backend-address-family --version --add-response-header --backend-read-timeout --frontend --accesslog-file --http2-proxy --client-private-key-file --client-cert-file --accept-proxy-protocol --tls-dyn-rec-idle-timeout --verify-client --read-rate --backend-connections-per-frontend --strip-incoming-forwarded ' -- "$cur" ) )
;; ;;
*) *)
_filedir _filedir

View File

@@ -1,6 +1,6 @@
.\" Man page generated from reStructuredText. .\" Man page generated from reStructuredText.
. .
.TH "H2LOAD" "1" "Nov 13, 2016" "1.16.1" "nghttp2" .TH "H2LOAD" "1" "May 29, 2016" "1.11.1" "nghttp2"
.SH NAME .SH NAME
h2load \- HTTP/2 benchmarking tool h2load \- HTTP/2 benchmarking tool
. .
@@ -138,9 +138,7 @@ Default: \fBh2c\fP
.TP .TP
.B \-d, \-\-data=<PATH> .B \-d, \-\-data=<PATH>
Post FILE to server. The request method is changed to Post FILE to server. The request method is changed to
POST. For http/1.1 connection, if \fI\%\-d\fP is used, the POST.
maximum number of in\-flight pipelined requests is set to
1.
.UNINDENT .UNINDENT
.INDENT 0.0 .INDENT 0.0
.TP .TP
@@ -151,7 +149,7 @@ representing the number of connections to be made per
rate period. The maximum number of connections to be rate period. The maximum number of connections to be
made is given in \fI\%\-c\fP option. This rate will be made is given in \fI\%\-c\fP option. This rate will be
distributed among threads as evenly as possible. For distributed among threads as evenly as possible. For
example, with \fI\%\-t\fP2 and \fI\%\-r\fP4, each thread gets 2 example, with \fB\-t2\fP and \fB\-r4\fP, each thread gets 2
connections per period. When the rate is 0, the program connections per period. When the rate is 0, the program
will run as it normally does, creating connections at will run as it normally does, creating connections at
whatever variable rate it wants. The default value for whatever variable rate it wants. The default value for
@@ -242,23 +240,6 @@ http/1.1 for both http and https URI.
.UNINDENT .UNINDENT
.INDENT 0.0 .INDENT 0.0
.TP .TP
.B \-\-header\-table\-size=<SIZE>
Specify decoder header table size.
.sp
Default: \fB4K\fP
.UNINDENT
.INDENT 0.0
.TP
.B \-\-encoder\-header\-table\-size=<SIZE>
Specify encoder header table size. The decoder (server)
specifies the maximum dynamic table size it accepts.
Then the negotiated dynamic table size is the minimum of
this option value and the value which server specified.
.sp
Default: \fB4K\fP
.UNINDENT
.INDENT 0.0
.TP
.B \-v, \-\-verbose .B \-v, \-\-verbose
Output debug information. Output debug information.
.UNINDENT .UNINDENT
@@ -273,9 +254,6 @@ Display version information and exit.
Display this help and exit. Display this help and exit.
.UNINDENT .UNINDENT
.sp .sp
The <SIZE> argument is an integer and an optional unit (e.g., 10K is
10 * 1024). Units are K, M and G (powers of 1024).
.sp
The <DURATION> argument is an integer and an optional unit (e.g., 1s The <DURATION> argument is an integer and an optional unit (e.g., 1s
is 1 second and 500ms is 500 milliseconds). Units are h, m, s or ms is 1 second and 500ms is 500 milliseconds). Units are h, m, s or ms
(hours, minutes, seconds and milliseconds, respectively). If a unit (hours, minutes, seconds and milliseconds, respectively). If a unit
@@ -434,7 +412,7 @@ performance. To set smaller flow control window, use \fI\%\-w\fP and
window size described in HTTP/2 and SPDY protocol specification. window size described in HTTP/2 and SPDY protocol specification.
.SH SEE ALSO .SH SEE ALSO
.sp .sp
\fBnghttp(1)\fP, \fBnghttpd(1)\fP, \fBnghttpx(1)\fP \fInghttp(1)\fP, \fInghttpd(1)\fP, \fInghttpx(1)\fP
.SH AUTHOR .SH AUTHOR
Tatsuhiro Tsujikawa Tatsuhiro Tsujikawa
.SH COPYRIGHT .SH COPYRIGHT

View File

@@ -74,14 +74,14 @@ OPTIONS
.. option:: -w, --window-bits=<N> .. option:: -w, --window-bits=<N>
Sets the stream level initial window size to (2\*\*<N>)-1. Sets the stream level initial window size to (2\*\*<N>)-1.
For SPDY, 2\*\*<N> is used instead. For SPDY, 2**<N> is used instead.
Default: ``30`` Default: ``30``
.. option:: -W, --connection-window-bits=<N> .. option:: -W, --connection-window-bits=<N>
Sets the connection level initial window size to Sets the connection level initial window size to
(2\*\*<N>)-1. For SPDY, if <N> is strictly less than 16, (2**<N>)-1. For SPDY, if <N> is strictly less than 16,
this option is ignored. Otherwise 2\*\*<N> is used for this option is ignored. Otherwise 2\*\*<N> is used for
SPDY. SPDY.
@@ -108,9 +108,7 @@ OPTIONS
.. option:: -d, --data=<PATH> .. option:: -d, --data=<PATH>
Post FILE to server. The request method is changed to Post FILE to server. The request method is changed to
POST. For http/1.1 connection, if :option:`-d` is used, the POST.
maximum number of in-flight pipelined requests is set to
1.
.. option:: -r, --rate=<N> .. option:: -r, --rate=<N>
@@ -120,7 +118,7 @@ OPTIONS
rate period. The maximum number of connections to be rate period. The maximum number of connections to be
made is given in :option:`-c` option. This rate will be made is given in :option:`-c` option. This rate will be
distributed among threads as evenly as possible. For distributed among threads as evenly as possible. For
example, with :option:`-t`\2 and :option:`-r`\4, each thread gets 2 example, with :option:`-t2` and :option:`\-r4`, each thread gets 2
connections per period. When the rate is 0, the program connections per period. When the rate is 0, the program
will run as it normally does, creating connections at will run as it normally does, creating connections at
whatever variable rate it wants. The default value for whatever variable rate it wants. The default value for
@@ -202,21 +200,6 @@ OPTIONS
:option:`--no-tls-proto`\=http/1.1, which effectively force :option:`--no-tls-proto`\=http/1.1, which effectively force
http/1.1 for both http and https URI. http/1.1 for both http and https URI.
.. option:: --header-table-size=<SIZE>
Specify decoder header table size.
Default: ``4K``
.. option:: --encoder-header-table-size=<SIZE>
Specify encoder header table size. The decoder (server)
specifies the maximum dynamic table size it accepts.
Then the negotiated dynamic table size is the minimum of
this option value and the value which server specified.
Default: ``4K``
.. option:: -v, --verbose .. option:: -v, --verbose
Output debug information. Output debug information.
@@ -231,9 +214,6 @@ OPTIONS
The <SIZE> argument is an integer and an optional unit (e.g., 10K is
10 * 1024). Units are K, M and G (powers of 1024).
The <DURATION> argument is an integer and an optional unit (e.g., 1s The <DURATION> argument is an integer and an optional unit (e.g., 1s
is 1 second and 500ms is 500 milliseconds). Units are h, m, s or ms is 1 second and 500ms is 500 milliseconds). Units are h, m, s or ms
(hours, minutes, seconds and milliseconds, respectively). If a unit (hours, minutes, seconds and milliseconds, respectively). If a unit

View File

@@ -1,6 +1,6 @@
.\" Man page generated from reStructuredText. .\" Man page generated from reStructuredText.
. .
.TH "NGHTTP" "1" "Nov 13, 2016" "1.16.1" "nghttp2" .TH "NGHTTP" "1" "May 29, 2016" "1.11.1" "nghttp2"
.SH NAME .SH NAME
nghttp \- HTTP/2 client nghttp \- HTTP/2 client
. .
@@ -142,13 +142,10 @@ HTTP upgrade request is performed with OPTIONS method.
.INDENT 0.0 .INDENT 0.0
.TP .TP
.B \-p, \-\-weight=<WEIGHT> .B \-p, \-\-weight=<WEIGHT>
Sets weight of given URI. This option can be used Sets priority group weight. The valid value range is
multiple times, and N\-th \fI\%\-p\fP option sets weight of N\-th
URI in the command line. If the number of \fI\%\-p\fP option is
less than the number of URI, the last \fI\%\-p\fP option value is
repeated. If there is no \fI\%\-p\fP option, default weight, 16,
is assumed. The valid value range is
[1, 256], inclusive. [1, 256], inclusive.
.sp
Default: \fB16\fP
.UNINDENT .UNINDENT
.INDENT 0.0 .INDENT 0.0
.TP .TP
@@ -170,14 +167,6 @@ multiple header table size change.
.UNINDENT .UNINDENT
.INDENT 0.0 .INDENT 0.0
.TP .TP
.B \-\-encoder\-header\-table\-size=<SIZE>
Specify encoder header table size. The decoder (server)
specifies the maximum dynamic table size it accepts.
Then the negotiated dynamic table size is the minimum of
this option value and the value which server specified.
.UNINDENT
.INDENT 0.0
.TP
.B \-b, \-\-padding=<N> .B \-b, \-\-padding=<N>
Add at most <N> bytes to a frame payload as padding. Add at most <N> bytes to a frame payload as padding.
Specify 0 to disable padding. Specify 0 to disable padding.
@@ -311,7 +300,7 @@ stream 11 with the weight 12. The other resources (e.g., icon) depend
on stream 11 with the weight 2. on stream 11 with the weight 2.
.SH SEE ALSO .SH SEE ALSO
.sp .sp
\fBnghttpd(1)\fP, \fBnghttpx(1)\fP, \fBh2load(1)\fP \fInghttpd(1)\fP, \fInghttpx(1)\fP, \fIh2load(1)\fP
.SH AUTHOR .SH AUTHOR
Tatsuhiro Tsujikawa Tatsuhiro Tsujikawa
.SH COPYRIGHT .SH COPYRIGHT

View File

@@ -107,14 +107,11 @@ OPTIONS
.. option:: -p, --weight=<WEIGHT> .. option:: -p, --weight=<WEIGHT>
Sets weight of given URI. This option can be used Sets priority group weight. The valid value range is
multiple times, and N-th :option:`-p` option sets weight of N-th
URI in the command line. If the number of :option:`-p` option is
less than the number of URI, the last :option:`-p` option value is
repeated. If there is no :option:`-p` option, default weight, 16,
is assumed. The valid value range is
[1, 256], inclusive. [1, 256], inclusive.
Default: ``16``
.. option:: -M, --peer-max-concurrent-streams=<N> .. option:: -M, --peer-max-concurrent-streams=<N>
Use <N> as SETTINGS_MAX_CONCURRENT_STREAMS value of Use <N> as SETTINGS_MAX_CONCURRENT_STREAMS value of
@@ -131,13 +128,6 @@ OPTIONS
frame payload before the last value, to simulate frame payload before the last value, to simulate
multiple header table size change. multiple header table size change.
.. option:: --encoder-header-table-size=<SIZE>
Specify encoder header table size. The decoder (server)
specifies the maximum dynamic table size it accepts.
Then the negotiated dynamic table size is the minimum of
this option value and the value which server specified.
.. option:: -b, --padding=<N> .. option:: -b, --padding=<N>
Add at most <N> bytes to a frame payload as padding. Add at most <N> bytes to a frame payload as padding.
@@ -218,9 +208,7 @@ implementation.
When connection is established, nghttp sends 5 PRIORITY frames to idle When connection is established, nghttp sends 5 PRIORITY frames to idle
streams 3, 5, 7, 9 and 11 to create "anchor" nodes in dependency streams 3, 5, 7, 9 and 11 to create "anchor" nodes in dependency
tree: tree::
.. code-block:: text
+-----+ +-----+
|id=0 | |id=0 |

View File

@@ -12,9 +12,7 @@ implementation.
When connection is established, nghttp sends 5 PRIORITY frames to idle When connection is established, nghttp sends 5 PRIORITY frames to idle
streams 3, 5, 7, 9 and 11 to create "anchor" nodes in dependency streams 3, 5, 7, 9 and 11 to create "anchor" nodes in dependency
tree: tree::
.. code-block:: text
+-----+ +-----+
|id=0 | |id=0 |

View File

@@ -1,6 +1,6 @@
.\" Man page generated from reStructuredText. .\" Man page generated from reStructuredText.
. .
.TH "NGHTTPD" "1" "Nov 13, 2016" "1.16.1" "nghttp2" .TH "NGHTTPD" "1" "May 29, 2016" "1.11.1" "nghttp2"
.SH NAME .SH NAME
nghttpd \- HTTP/2 server nghttpd \- HTTP/2 server
. .
@@ -99,14 +99,6 @@ Specify decoder header table size.
.UNINDENT .UNINDENT
.INDENT 0.0 .INDENT 0.0
.TP .TP
.B \-\-encoder\-header\-table\-size=<SIZE>
Specify encoder header table size. The decoder (client)
specifies the maximum dynamic table size it accepts.
Then the negotiated dynamic table size is the minimum of
this option value and the value which client specified.
.UNINDENT
.INDENT 0.0
.TP
.B \-\-color .B \-\-color
Force colored log output. Force colored log output.
.UNINDENT .UNINDENT
@@ -217,7 +209,7 @@ The <SIZE> argument is an integer and an optional unit (e.g., 10K is
10 * 1024). Units are K, M and G (powers of 1024). 10 * 1024). Units are K, M and G (powers of 1024).
.SH SEE ALSO .SH SEE ALSO
.sp .sp
\fBnghttp(1)\fP, \fBnghttpx(1)\fP, \fBh2load(1)\fP \fInghttp(1)\fP, \fInghttpx(1)\fP, \fIh2load(1)\fP
.SH AUTHOR .SH AUTHOR
Tatsuhiro Tsujikawa Tatsuhiro Tsujikawa
.SH COPYRIGHT .SH COPYRIGHT

View File

@@ -70,13 +70,6 @@ OPTIONS
Specify decoder header table size. Specify decoder header table size.
.. option:: --encoder-header-table-size=<SIZE>
Specify encoder header table size. The decoder (client)
specifies the maximum dynamic table size it accepts.
Then the negotiated dynamic table size is the minimum of
this option value and the value which client specified.
.. option:: --color .. option:: --color
Force colored log output. Force colored log output.

View File

@@ -1,6 +1,6 @@
.\" Man page generated from reStructuredText. .\" Man page generated from reStructuredText.
. .
.TH "NGHTTPX" "1" "Nov 13, 2016" "1.16.1" "nghttp2" .TH "NGHTTPX" "1" "May 29, 2016" "1.11.1" "nghttp2"
.SH NAME .SH NAME
nghttpx \- HTTP/2 proxy nghttpx \- HTTP/2 proxy
. .
@@ -55,7 +55,7 @@ The options are categorized into several groups.
.SS Connections .SS Connections
.INDENT 0.0 .INDENT 0.0
.TP .TP
.B \-b, \-\-backend=(<HOST>,<PORT>|unix:<PATH>)[;[<PATTERN>[:...]][[;<PARAM>]...] .B \-b, \-\-backend=(<HOST>,<PORT>|unix:<PATH>)[;[<PATTERN>[:...]][[;PARAM]...]
Set backend host and port. The multiple backend Set backend host and port. The multiple backend
addresses are accepted by repeating this option. UNIX addresses are accepted by repeating this option. UNIX
domain socket can be specified by prefixing path name domain socket can be specified by prefixing path name
@@ -120,13 +120,12 @@ together forming load balancing group.
Several parameters <PARAM> are accepted after <PATTERN>. Several parameters <PARAM> are accepted after <PATTERN>.
The parameters are delimited by ";". The available The parameters are delimited by ";". The available
parameters are: "proto=<PROTO>", "tls", parameters are: "proto=<PROTO>", "tls",
"sni=<SNI_HOST>", "fall=<N>", "rise=<N>", and "sni=<SNI_HOST>", "fall=<N>", and "rise=<N>". The
"affinity=<METHOD>". The parameter consists of keyword, parameter consists of keyword, and optionally followed
and optionally followed by "=" and value. For example, by "=" and value. For example, the parameter "proto=h2"
the parameter "proto=h2" consists of the keyword "proto" consists of the keyword "proto" and value "h2". The
and value "h2". The parameter "tls" consists of the parameter "tls" consists of the keyword "tls" without
keyword "tls" without value. Each parameter is value. Each parameter is described as follows.
described as follows.
.sp .sp
The backend application protocol can be specified using The backend application protocol can be specified using
optional "proto" parameter, and in the form of optional "proto" parameter, and in the form of
@@ -161,20 +160,6 @@ eligible for load balancing target. If <N> is 0, a
backend is permanently offline, once it goes in that backend is permanently offline, once it goes in that
state, and this is the default behaviour. state, and this is the default behaviour.
.sp .sp
The session affinity is enabled using
"affinity=<METHOD>" parameter. If "ip" is given in
<METHOD>, client IP based session affinity is enabled.
If "none" is given in <METHOD>, session affinity is
disabled, and this is the default. The session affinity
is enabled per <PATTERN>. If at least one backend has
"affinity" parameter, and its <METHOD> is not "none",
session affinity is enabled for all backend servers
sharing the same <PATTERN>. It is advised to set
"affinity" parameter to all backend explicitly if
session affinity is desired. The session affinity may
break if one of the backend gets unreachable, or backend
settings are reloaded or replaced by API.
.sp
Since ";" and ":" are used as delimiter, <PATTERN> must Since ";" and ":" are used as delimiter, <PATTERN> must
not contain these characters. Since ";" has special not contain these characters. Since ";" has special
meaning in shell, the option value must be quoted. meaning in shell, the option value must be quoted.
@@ -183,7 +168,7 @@ Default: \fB127.0.0.1,80\fP
.UNINDENT .UNINDENT
.INDENT 0.0 .INDENT 0.0
.TP .TP
.B \-f, \-\-frontend=(<HOST>,<PORT>|unix:<PATH>)[[;<PARAM>]...] .B \-f, \-\-frontend=(<HOST>,<PORT>|unix:<PATH>)[;no\-tls]
Set frontend host and port. If <HOST> is \(aq*\(aq, it Set frontend host and port. If <HOST> is \(aq*\(aq, it
assumes all addresses including both IPv4 and IPv6. assumes all addresses including both IPv4 and IPv6.
UNIX domain socket can be specified by prefixing path UNIX domain socket can be specified by prefixing path
@@ -191,25 +176,9 @@ name with "unix:" (e.g., unix:/var/run/nghttpx.sock).
This option can be used multiple times to listen to This option can be used multiple times to listen to
multiple addresses. multiple addresses.
.sp .sp
This option can take 0 or more parameters, which are
described below. Note that "api" and "healthmon"
parameters are mutually exclusive.
.sp
Optionally, TLS can be disabled by specifying "no\-tls" Optionally, TLS can be disabled by specifying "no\-tls"
parameter. TLS is enabled by default. parameter. TLS is enabled by default.
.sp .sp
To make this frontend as API endpoint, specify "api"
parameter. This is disabled by default. It is
important to limit the access to the API frontend.
Otherwise, someone may change the backend server, and
break your services, or expose confidential information
to the outside the world.
.sp
To make this frontend as health monitor endpoint,
specify "healthmon" parameter. This is disabled by
default. Any requests which come through this address
are replied with 200 HTTP status, without no body.
.sp
Default: \fB*,3000\fP Default: \fB*,3000\fP
.UNINDENT .UNINDENT
.INDENT 0.0 .INDENT 0.0
@@ -456,14 +425,6 @@ Default: \fB30s\fP
.UNINDENT .UNINDENT
.INDENT 0.0 .INDENT 0.0
.TP .TP
.B \-\-backend\-connect\-timeout=<DURATION>
Specify timeout before establishing TCP connection to
backend.
.sp
Default: \fB30s\fP
.UNINDENT
.INDENT 0.0
.TP
.B \-\-backend\-keep\-alive\-timeout=<DURATION> .B \-\-backend\-keep\-alive\-timeout=<DURATION>
Specify keep\-alive timeout for backend connection. Specify keep\-alive timeout for backend connection.
.sp .sp
@@ -494,20 +455,6 @@ backend server.
.sp .sp
Default: \fB10s\fP Default: \fB10s\fP
.UNINDENT .UNINDENT
.INDENT 0.0
.TP
.B \-\-backend\-max\-backoff=<DURATION>
Specify maximum backoff interval. This is used when
doing health check against offline backend (see "fail"
parameter in \fI\%\-\-backend\fP option). It is also used to
limit the maximum interval to temporarily disable
backend when nghttpx failed to connect to it. These
intervals are calculated using exponential backoff, and
consecutive failed attempts increase the interval. This
option caps its maximum value.
.sp
Default: \fB2m\fP
.UNINDENT
.SS SSL/TLS .SS SSL/TLS
.INDENT 0.0 .INDENT 0.0
.TP .TP
@@ -517,17 +464,6 @@ described in OpenSSL ciphers(1).
.UNINDENT .UNINDENT
.INDENT 0.0 .INDENT 0.0
.TP .TP
.B \-\-ecdh\-curves=<LIST>
Set supported curve list for frontend connections.
<LIST> is a colon separated list of curve NID or names
in the preference order. The supported curves depend on
the linked OpenSSL library. This function requires
OpenSSL >= 1.0.2.
.sp
Default: \fBX25519:P\-256:P\-384:P\-521\fP
.UNINDENT
.INDENT 0.0
.TP
.B \-k, \-\-insecure .B \-k, \-\-insecure
Don\(aqt verify backend server\(aqs certificate if TLS is Don\(aqt verify backend server\(aqs certificate if TLS is
enabled for backend connections. enabled for backend connections.
@@ -550,21 +486,12 @@ password protected it\(aqll be requested interactively.
.UNINDENT .UNINDENT
.INDENT 0.0 .INDENT 0.0
.TP .TP
.B \-\-subcert=<KEYPATH>:<CERTPATH>[[;<PARAM>]...] .B \-\-subcert=<KEYPATH>:<CERTPATH>
Specify additional certificate and private key file. Specify additional certificate and private key file.
nghttpx will choose certificates based on the hostname nghttpx will choose certificates based on the hostname
indicated by client using TLS SNI extension. This indicated by client using TLS SNI extension. This
option can be used multiple times. To make OCSP option can be used multiple times. To make OCSP
stapling work, <CERTPATH> must be absolute path. stapling work, <CERTPATH> must be absolute path.
.sp
Additional parameter can be specified in <PARAM>. The
available <PARAM> is "sct\-dir=<DIR>".
.sp
"sct\-dir=<DIR>" specifies the path to directory which
contains *.sct files for TLS
signed_certificate_timestamp extension (RFC 6962). This
feature requires OpenSSL >= 1.0.2. See also
\fI\%\-\-tls\-sct\-dir\fP option.
.UNINDENT .UNINDENT
.INDENT 0.0 .INDENT 0.0
.TP .TP
@@ -807,18 +734,6 @@ Allow black listed cipher suite on HTTP/2 connection.
See \fI\%https://tools.ietf.org/html/rfc7540#appendix\-A\fP for See \fI\%https://tools.ietf.org/html/rfc7540#appendix\-A\fP for
the complete HTTP/2 cipher suites black list. the complete HTTP/2 cipher suites black list.
.UNINDENT .UNINDENT
.INDENT 0.0
.TP
.B \-\-tls\-sct\-dir=<DIR>
Specifies the directory where *.sct files exist. All
*.sct files in <DIR> are read, and sent as
extension_data of TLS signed_certificate_timestamp (RFC
6962) to client. These *.sct files are for the
certificate specified in positional command\-line
argument <CERT>, or certificate option in configuration
file. For additional certificates, use \fI\%\-\-subcert\fP
option. This option requires OpenSSL >= 1.0.2.
.UNINDENT
.SS HTTP/2 and SPDY .SS HTTP/2 and SPDY
.INDENT 0.0 .INDENT 0.0
.TP .TP
@@ -840,36 +755,37 @@ Default: \fB100\fP
.UNINDENT .UNINDENT
.INDENT 0.0 .INDENT 0.0
.TP .TP
.B \-\-frontend\-http2\-window\-size=<SIZE> .B \-\-frontend\-http2\-window\-bits=<N>
Sets the per\-stream initial window size of HTTP/2 and Sets the per\-stream initial window size of HTTP/2 SPDY
SPDY frontend connection. frontend connection. For HTTP/2, the size is 2**<N>\-1.
For SPDY, the size is 2**<N>.
.sp .sp
Default: \fB65535\fP Default: \fB16\fP
.UNINDENT .UNINDENT
.INDENT 0.0 .INDENT 0.0
.TP .TP
.B \-\-frontend\-http2\-connection\-window\-size=<SIZE> .B \-\-frontend\-http2\-connection\-window\-bits=<N>
Sets the per\-connection window size of HTTP/2 and SPDY Sets the per\-connection window size of HTTP/2 and SPDY
frontend connection. For SPDY connection, the value frontend connection. For HTTP/2, the size is
less than 64KiB is rounded up to 64KiB. 2**<N>\-1. For SPDY, the size is 2**<N>.
.sp .sp
Default: \fB65535\fP Default: \fB16\fP
.UNINDENT .UNINDENT
.INDENT 0.0 .INDENT 0.0
.TP .TP
.B \-\-backend\-http2\-window\-size=<SIZE> .B \-\-backend\-http2\-window\-bits=<N>
Sets the initial window size of HTTP/2 backend Sets the initial window size of HTTP/2 backend
connection. connection to 2**<N>\-1.
.sp .sp
Default: \fB65535\fP Default: \fB16\fP
.UNINDENT .UNINDENT
.INDENT 0.0 .INDENT 0.0
.TP .TP
.B \-\-backend\-http2\-connection\-window\-size=<SIZE> .B \-\-backend\-http2\-connection\-window\-bits=<N>
Sets the per\-connection window size of HTTP/2 backend Sets the per\-connection window size of HTTP/2 backend
connection. connection to 2**<N>\-1.
.sp .sp
Default: \fB2147483647\fP Default: \fB30\fP
.UNINDENT .UNINDENT
.INDENT 0.0 .INDENT 0.0
.TP .TP
@@ -895,71 +811,6 @@ backend session is relayed to frontend, and server push
via Link header field is also supported. SPDY frontend via Link header field is also supported. SPDY frontend
does not support server push. does not support server push.
.UNINDENT .UNINDENT
.INDENT 0.0
.TP
.B \-\-frontend\-http2\-optimize\-write\-buffer\-size
(Experimental) Enable write buffer size optimization in
frontend HTTP/2 TLS connection. This optimization aims
to reduce write buffer size so that it only contains
bytes which can send immediately. This makes server
more responsive to prioritized HTTP/2 stream because the
buffering of lower priority stream is reduced. This
option is only effective on recent Linux platform.
.UNINDENT
.INDENT 0.0
.TP
.B \-\-frontend\-http2\-optimize\-window\-size
(Experimental) Automatically tune connection level
window size of frontend HTTP/2 TLS connection. If this
feature is enabled, connection window size starts with
the default window size, 65535 bytes. nghttpx
automatically adjusts connection window size based on
TCP receiving window size. The maximum window size is
capped by the value specified by
\fI\%\-\-frontend\-http2\-connection\-window\-size\fP\&. Since the
stream is subject to stream level window size, it should
be adjusted using \fI\%\-\-frontend\-http2\-window\-size\fP option as
well. This option is only effective on recent Linux
platform.
.UNINDENT
.INDENT 0.0
.TP
.B \-\-frontend\-http2\-encoder\-dynamic\-table\-size=<SIZE>
Specify the maximum dynamic table size of HPACK encoder
in the frontend HTTP/2 connection. The decoder (client)
specifies the maximum dynamic table size it accepts.
Then the negotiated dynamic table size is the minimum of
this option value and the value which client specified.
.sp
Default: \fB4K\fP
.UNINDENT
.INDENT 0.0
.TP
.B \-\-frontend\-http2\-decoder\-dynamic\-table\-size=<SIZE>
Specify the maximum dynamic table size of HPACK decoder
in the frontend HTTP/2 connection.
.sp
Default: \fB4K\fP
.UNINDENT
.INDENT 0.0
.TP
.B \-\-backend\-http2\-encoder\-dynamic\-table\-size=<SIZE>
Specify the maximum dynamic table size of HPACK encoder
in the backend HTTP/2 connection. The decoder (backend)
specifies the maximum dynamic table size it accepts.
Then the negotiated dynamic table size is the minimum of
this option value and the value which backend specified.
.sp
Default: \fB4K\fP
.UNINDENT
.INDENT 0.0
.TP
.B \-\-backend\-http2\-decoder\-dynamic\-table\-size=<SIZE>
Specify the maximum dynamic table size of HPACK decoder
in the backend HTTP/2 connection.
.sp
Default: \fB4K\fP
.UNINDENT
.SS Mode .SS Mode
.INDENT 0.0 .INDENT 0.0
.TP .TP
@@ -1042,12 +893,6 @@ $ssl_session_id: session ID for SSL/TLS connection.
.IP \(bu 2 .IP \(bu 2
$ssl_session_reused: "r" if SSL/TLS session was $ssl_session_reused: "r" if SSL/TLS session was
reused. Otherwise, "." reused. Otherwise, "."
.IP \(bu 2
$backend_host: backend host used to fulfill the
request. "\-" if backend host is not available.
.IP \(bu 2
$backend_port: backend port used to fulfill the
request. "\-" if backend host is not available.
.UNINDENT .UNINDENT
.sp .sp
The variable can be enclosed by "{" and "}" for The variable can be enclosed by "{" and "}" for
@@ -1233,28 +1078,6 @@ originally generates HTTP error status code <CODE>.
HTTP status code. If error status code comes from HTTP status code. If error status code comes from
backend server, the custom error pages are not used. backend server, the custom error pages are not used.
.UNINDENT .UNINDENT
.INDENT 0.0
.TP
.B \-\-server\-name=<NAME>
Change server response header field value to <NAME>.
.sp
Default: \fBnghttpx nghttp2/1.16.1\fP
.UNINDENT
.INDENT 0.0
.TP
.B \-\-no\-server\-rewrite
Don\(aqt rewrite server header field in default mode. When
\fI\%\-\-http2\-proxy\fP is used, these headers will not be altered
regardless of this option.
.UNINDENT
.SS API
.INDENT 0.0
.TP
.B \-\-api\-max\-request\-body=<SIZE>
Set the maximum size of request body for API request.
.sp
Default: \fB16K\fP
.UNINDENT
.SS Debug .SS Debug
.INDENT 0.0 .INDENT 0.0
.TP .TP
@@ -1402,9 +1225,6 @@ Shutdown gracefully. First accept pending connections and stop
accepting connection. After all connections are handled, nghttpx accepting connection. After all connections are handled, nghttpx
exits. exits.
.TP .TP
.B SIGHUP
Reload configuration file given in \fI\%\-\-conf\fP\&.
.TP
.B SIGUSR1 .B SIGUSR1
Reopen log files. Reopen log files.
.TP .TP
@@ -1412,11 +1232,7 @@ Reopen log files.
Fork and execute nghttpx. It will execute the binary in the same Fork and execute nghttpx. It will execute the binary in the same
path with same command\-line arguments and environment variables. path with same command\-line arguments and environment variables.
After new process comes up, sending SIGQUIT to the original process After new process comes up, sending SIGQUIT to the original process
to perform hot swapping. The difference between SIGUSR2 + SIGQUIT to perform hot swapping.
and SIGHUP is that former is usually used to execute new binary, and
the master process is newly spawned. On the other hand, the latter
just reloads configuration file, and the same master process
continues to exist.
.UNINDENT .UNINDENT
.sp .sp
\fBNOTE:\fP \fBNOTE:\fP
@@ -1565,19 +1381,6 @@ If \fI\%\-\-tls\-ticket\-key\-file\fP is given, encryption key is read
from the given file. In this case, nghttpx does not rotate key from the given file. In this case, nghttpx does not rotate key
automatically. To rotate key, one has to restart nghttpx (see automatically. To rotate key, one has to restart nghttpx (see
SIGNALS). SIGNALS).
.SH CERTIFICATE TRANSPARENCY
.sp
nghttpx supports TLS \fBsigned_certificate_timestamp\fP extension (\fI\%RFC
6962\fP). The relevant options
are \fI\%\-\-tls\-sct\-dir\fP and \fBsct\-dir\fP parameter in
\fI\%\-\-subcert\fP\&. They takes a directory, and nghttpx reads all
files whose extension is \fB\&.sct\fP under the directory. The \fB*.sct\fP
files are encoded as \fBSignedCertificateTimestamp\fP struct described
in \fI\%section 3.2 of RFC 69662\fP\&. This format is
the same one used by \fI\%nginx\-ct\fP and \fI\%mod_ssl_ct\fP\&.
\fI\%ct\-submit\fP can be
used to submit certificates to log servers, and obtain the
\fBSignedCertificateTimestamp\fP struct which can be used with nghttpx.
.SH MRUBY SCRIPTING .SH MRUBY SCRIPTING
.sp .sp
\fBWARNING:\fP \fBWARNING:\fP
@@ -1669,11 +1472,6 @@ connection from client.
.B attribute [R] tls_used .B attribute [R] tls_used
Return true if TLS is used on the connection. Return true if TLS is used on the connection.
.UNINDENT .UNINDENT
.INDENT 7.0
.TP
.B attribute [R] tls_sni
Return the TLS SNI value which client sent in this connection.
.UNINDENT
.UNINDENT .UNINDENT
.INDENT 0.0 .INDENT 0.0
.TP .TP
@@ -1884,64 +1682,9 @@ App.new
.fi .fi
.UNINDENT .UNINDENT
.UNINDENT .UNINDENT
.SH API ENDPOINTS
.sp
nghttpx exposes API endpoints to manipulate it via HTTP based API. By
default, API endpoint is disabled. To enable it, add a dedicated
frontend for API using \fI\%\-\-frontend\fP option with "api"
parameter. All requests which come from this frontend address, will
be treated as API request.
.sp
The response is normally JSON dictionary, and at least includes the
following keys:
.INDENT 0.0
.TP
.B status
The status of the request processing. The following values are
defined:
.INDENT 7.0
.TP
.B Success
The request was successful.
.TP
.B Failure
The request was failed. No change has been made.
.UNINDENT
.TP
.B code
HTTP status code
.UNINDENT
.sp
We wrote "normally", since nghttpx may return ordinal HTML response in
some cases where the error has occurred before reaching API endpoint
(e.g., header field is too large).
.sp
The following section describes available API endpoints.
.SS PUT /api/v1beta1/backendconfig
.sp
This API replaces the current backend server settings with the
requested ones. The request method should be PUT, but POST is also
acceptable. The request body must be nghttpx configuration file
format. For configuration file format, see \fI\%FILES\fP section. The
line separator inside the request body must be single LF (0x0A).
Currently, only \fI\%backend\fP option is parsed, the
others are simply ignored. The semantics of this API is replace the
current backend with the backend options in request body. Describe
the desired set of backend severs, and nghttpx makes it happen. If
there is no \fI\%backend\fP option is found in request
body, the current set of backend is replaced with the \fI\%backend\fP option\(aqs default value, which is \fB127.0.0.1,80\fP\&.
.sp
The replacement is done instantly without breaking existing
connections or requests. It also avoids any process creation as is
the case with hot swapping with signals.
.sp
The one limitation is that only numeric IP address is allowd in
\fI\%backend\fP in request body while non numeric
hostname is allowed in command\-line or configuration file is read
using \fI\%\-\-conf\fP\&.
.SH SEE ALSO .SH SEE ALSO
.sp .sp
\fBnghttp(1)\fP, \fBnghttpd(1)\fP, \fBh2load(1)\fP \fInghttp(1)\fP, \fInghttpd(1)\fP, \fIh2load(1)\fP
.SH AUTHOR .SH AUTHOR
Tatsuhiro Tsujikawa Tatsuhiro Tsujikawa
.SH COPYRIGHT .SH COPYRIGHT

View File

@@ -37,7 +37,7 @@ The options are categorized into several groups.
Connections Connections
~~~~~~~~~~~ ~~~~~~~~~~~
.. option:: -b, --backend=(<HOST>,<PORT>|unix:<PATH>)[;[<PATTERN>[:...]][[;<PARAM>]...] .. option:: -b, --backend=(<HOST>,<PORT>|unix:<PATH>)[;[<PATTERN>[:...]][[;PARAM]...]
Set backend host and port. The multiple backend Set backend host and port. The multiple backend
@@ -70,7 +70,7 @@ Connections
Host can include "\*" in the left most position to Host can include "\*" in the left most position to
indicate wildcard match (only suffix match is done). indicate wildcard match (only suffix match is done).
The "\*" must match at least one character. For example, The "*" must match at least one character. For example,
host pattern "\*.nghttp2.org" matches against host pattern "\*.nghttp2.org" matches against
"www.nghttp2.org" and "git.ngttp2.org", but does not "www.nghttp2.org" and "git.ngttp2.org", but does not
match against "nghttp2.org". The exact hosts match match against "nghttp2.org". The exact hosts match
@@ -104,13 +104,12 @@ Connections
Several parameters <PARAM> are accepted after <PATTERN>. Several parameters <PARAM> are accepted after <PATTERN>.
The parameters are delimited by ";". The available The parameters are delimited by ";". The available
parameters are: "proto=<PROTO>", "tls", parameters are: "proto=<PROTO>", "tls",
"sni=<SNI_HOST>", "fall=<N>", "rise=<N>", and "sni=<SNI_HOST>", "fall=<N>", and "rise=<N>". The
"affinity=<METHOD>". The parameter consists of keyword, parameter consists of keyword, and optionally followed
and optionally followed by "=" and value. For example, by "=" and value. For example, the parameter "proto=h2"
the parameter "proto=h2" consists of the keyword "proto" consists of the keyword "proto" and value "h2". The
and value "h2". The parameter "tls" consists of the parameter "tls" consists of the keyword "tls" without
keyword "tls" without value. Each parameter is value. Each parameter is described as follows.
described as follows.
The backend application protocol can be specified using The backend application protocol can be specified using
optional "proto" parameter, and in the form of optional "proto" parameter, and in the form of
@@ -145,20 +144,6 @@ Connections
backend is permanently offline, once it goes in that backend is permanently offline, once it goes in that
state, and this is the default behaviour. state, and this is the default behaviour.
The session affinity is enabled using
"affinity=<METHOD>" parameter. If "ip" is given in
<METHOD>, client IP based session affinity is enabled.
If "none" is given in <METHOD>, session affinity is
disabled, and this is the default. The session affinity
is enabled per <PATTERN>. If at least one backend has
"affinity" parameter, and its <METHOD> is not "none",
session affinity is enabled for all backend servers
sharing the same <PATTERN>. It is advised to set
"affinity" parameter to all backend explicitly if
session affinity is desired. The session affinity may
break if one of the backend gets unreachable, or backend
settings are reloaded or replaced by API.
Since ";" and ":" are used as delimiter, <PATTERN> must Since ";" and ":" are used as delimiter, <PATTERN> must
not contain these characters. Since ";" has special not contain these characters. Since ";" has special
meaning in shell, the option value must be quoted. meaning in shell, the option value must be quoted.
@@ -166,7 +151,7 @@ Connections
Default: ``127.0.0.1,80`` Default: ``127.0.0.1,80``
.. option:: -f, --frontend=(<HOST>,<PORT>|unix:<PATH>)[[;<PARAM>]...] .. option:: -f, --frontend=(<HOST>,<PORT>|unix:<PATH>)[;no-tls]
Set frontend host and port. If <HOST> is '\*', it Set frontend host and port. If <HOST> is '\*', it
assumes all addresses including both IPv4 and IPv6. assumes all addresses including both IPv4 and IPv6.
@@ -175,25 +160,9 @@ Connections
This option can be used multiple times to listen to This option can be used multiple times to listen to
multiple addresses. multiple addresses.
This option can take 0 or more parameters, which are
described below. Note that "api" and "healthmon"
parameters are mutually exclusive.
Optionally, TLS can be disabled by specifying "no-tls" Optionally, TLS can be disabled by specifying "no-tls"
parameter. TLS is enabled by default. parameter. TLS is enabled by default.
To make this frontend as API endpoint, specify "api"
parameter. This is disabled by default. It is
important to limit the access to the API frontend.
Otherwise, someone may change the backend server, and
break your services, or expose confidential information
to the outside the world.
To make this frontend as health monitor endpoint,
specify "healthmon" parameter. This is disabled by
default. Any requests which come through this address
are replied with 200 HTTP status, without no body.
Default: ``*,3000`` Default: ``*,3000``
@@ -417,13 +386,6 @@ Timeout
Default: ``30s`` Default: ``30s``
.. option:: --backend-connect-timeout=<DURATION>
Specify timeout before establishing TCP connection to
backend.
Default: ``30s``
.. option:: --backend-keep-alive-timeout=<DURATION> .. option:: --backend-keep-alive-timeout=<DURATION>
Specify keep-alive timeout for backend connection. Specify keep-alive timeout for backend connection.
@@ -452,19 +414,6 @@ Timeout
Default: ``10s`` Default: ``10s``
.. option:: --backend-max-backoff=<DURATION>
Specify maximum backoff interval. This is used when
doing health check against offline backend (see "fail"
parameter in :option:`--backend` option). It is also used to
limit the maximum interval to temporarily disable
backend when nghttpx failed to connect to it. These
intervals are calculated using exponential backoff, and
consecutive failed attempts increase the interval. This
option caps its maximum value.
Default: ``2m``
SSL/TLS SSL/TLS
~~~~~~~ ~~~~~~~
@@ -474,16 +423,6 @@ SSL/TLS
Set allowed cipher list. The format of the string is Set allowed cipher list. The format of the string is
described in OpenSSL ciphers(1). described in OpenSSL ciphers(1).
.. option:: --ecdh-curves=<LIST>
Set supported curve list for frontend connections.
<LIST> is a colon separated list of curve NID or names
in the preference order. The supported curves depend on
the linked OpenSSL library. This function requires
OpenSSL >= 1.0.2.
Default: ``X25519:P-256:P-384:P-521``
.. option:: -k, --insecure .. option:: -k, --insecure
Don't verify backend server's certificate if TLS is Don't verify backend server's certificate if TLS is
@@ -503,7 +442,7 @@ SSL/TLS
private key. If none is given and the private key is private key. If none is given and the private key is
password protected it'll be requested interactively. password protected it'll be requested interactively.
.. option:: --subcert=<KEYPATH>:<CERTPATH>[[;<PARAM>]...] .. option:: --subcert=<KEYPATH>:<CERTPATH>
Specify additional certificate and private key file. Specify additional certificate and private key file.
nghttpx will choose certificates based on the hostname nghttpx will choose certificates based on the hostname
@@ -511,15 +450,6 @@ SSL/TLS
option can be used multiple times. To make OCSP option can be used multiple times. To make OCSP
stapling work, <CERTPATH> must be absolute path. stapling work, <CERTPATH> must be absolute path.
Additional parameter can be specified in <PARAM>. The
available <PARAM> is "sct-dir=<DIR>".
"sct-dir=<DIR>" specifies the path to directory which
contains \*.sct files for TLS
signed_certificate_timestamp extension (RFC 6962). This
feature requires OpenSSL >= 1.0.2. See also
:option:`--tls-sct-dir` option.
.. option:: --dh-param-file=<PATH> .. option:: --dh-param-file=<PATH>
Path to file that contains DH parameters in PEM format. Path to file that contains DH parameters in PEM format.
@@ -735,17 +665,6 @@ SSL/TLS
See https://tools.ietf.org/html/rfc7540#appendix-A for See https://tools.ietf.org/html/rfc7540#appendix-A for
the complete HTTP/2 cipher suites black list. the complete HTTP/2 cipher suites black list.
.. option:: --tls-sct-dir=<DIR>
Specifies the directory where \*.sct files exist. All
\*.sct files in <DIR> are read, and sent as
extension_data of TLS signed_certificate_timestamp (RFC
6962) to client. These \*.sct files are for the
certificate specified in positional command-line
argument <CERT>, or certificate option in configuration
file. For additional certificates, use :option:`--subcert`
option. This option requires OpenSSL >= 1.0.2.
HTTP/2 and SPDY HTTP/2 and SPDY
~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~
@@ -766,34 +685,35 @@ HTTP/2 and SPDY
Default: ``100`` Default: ``100``
.. option:: --frontend-http2-window-size=<SIZE> .. option:: --frontend-http2-window-bits=<N>
Sets the per-stream initial window size of HTTP/2 and Sets the per-stream initial window size of HTTP/2 SPDY
SPDY frontend connection. frontend connection. For HTTP/2, the size is 2\*\*<N>-1.
For SPDY, the size is 2\*\*<N>.
Default: ``65535`` Default: ``16``
.. option:: --frontend-http2-connection-window-size=<SIZE> .. option:: --frontend-http2-connection-window-bits=<N>
Sets the per-connection window size of HTTP/2 and SPDY Sets the per-connection window size of HTTP/2 and SPDY
frontend connection. For SPDY connection, the value frontend connection. For HTTP/2, the size is
less than 64KiB is rounded up to 64KiB. 2**<N>-1. For SPDY, the size is 2\*\*<N>.
Default: ``65535`` Default: ``16``
.. option:: --backend-http2-window-size=<SIZE> .. option:: --backend-http2-window-bits=<N>
Sets the initial window size of HTTP/2 backend Sets the initial window size of HTTP/2 backend
connection. connection to 2\*\*<N>-1.
Default: ``65535`` Default: ``16``
.. option:: --backend-http2-connection-window-size=<SIZE> .. option:: --backend-http2-connection-window-bits=<N>
Sets the per-connection window size of HTTP/2 backend Sets the per-connection window size of HTTP/2 backend
connection. connection to 2\*\*<N>-1.
Default: ``2147483647`` Default: ``30``
.. option:: --http2-no-cookie-crumbling .. option:: --http2-no-cookie-crumbling
@@ -816,65 +736,6 @@ HTTP/2 and SPDY
via Link header field is also supported. SPDY frontend via Link header field is also supported. SPDY frontend
does not support server push. does not support server push.
.. option:: --frontend-http2-optimize-write-buffer-size
(Experimental) Enable write buffer size optimization in
frontend HTTP/2 TLS connection. This optimization aims
to reduce write buffer size so that it only contains
bytes which can send immediately. This makes server
more responsive to prioritized HTTP/2 stream because the
buffering of lower priority stream is reduced. This
option is only effective on recent Linux platform.
.. option:: --frontend-http2-optimize-window-size
(Experimental) Automatically tune connection level
window size of frontend HTTP/2 TLS connection. If this
feature is enabled, connection window size starts with
the default window size, 65535 bytes. nghttpx
automatically adjusts connection window size based on
TCP receiving window size. The maximum window size is
capped by the value specified by
:option:`--frontend-http2-connection-window-size`\. Since the
stream is subject to stream level window size, it should
be adjusted using :option:`--frontend-http2-window-size` option as
well. This option is only effective on recent Linux
platform.
.. option:: --frontend-http2-encoder-dynamic-table-size=<SIZE>
Specify the maximum dynamic table size of HPACK encoder
in the frontend HTTP/2 connection. The decoder (client)
specifies the maximum dynamic table size it accepts.
Then the negotiated dynamic table size is the minimum of
this option value and the value which client specified.
Default: ``4K``
.. option:: --frontend-http2-decoder-dynamic-table-size=<SIZE>
Specify the maximum dynamic table size of HPACK decoder
in the frontend HTTP/2 connection.
Default: ``4K``
.. option:: --backend-http2-encoder-dynamic-table-size=<SIZE>
Specify the maximum dynamic table size of HPACK encoder
in the backend HTTP/2 connection. The decoder (backend)
specifies the maximum dynamic table size it accepts.
Then the negotiated dynamic table size is the minimum of
this option value and the value which backend specified.
Default: ``4K``
.. option:: --backend-http2-decoder-dynamic-table-size=<SIZE>
Specify the maximum dynamic table size of HPACK decoder
in the backend HTTP/2 connection.
Default: ``4K``
Mode Mode
~~~~ ~~~~
@@ -942,10 +803,6 @@ Logging
* $ssl_session_id: session ID for SSL/TLS connection. * $ssl_session_id: session ID for SSL/TLS connection.
* $ssl_session_reused: "r" if SSL/TLS session was * $ssl_session_reused: "r" if SSL/TLS session was
reused. Otherwise, "." reused. Otherwise, "."
* $backend_host: backend host used to fulfill the
request. "-" if backend host is not available.
* $backend_port: backend port used to fulfill the
request. "-" if backend host is not available.
The variable can be enclosed by "{" and "}" for The variable can be enclosed by "{" and "}" for
disambiguation (e.g., ${remote_addr}). disambiguation (e.g., ${remote_addr}).
@@ -1110,32 +967,10 @@ HTTP
Set file path to custom error page served when nghttpx Set file path to custom error page served when nghttpx
originally generates HTTP error status code <CODE>. originally generates HTTP error status code <CODE>.
<CODE> must be greater than or equal to 400, and at most <CODE> must be greater than or equal to 400, and at most
599. If "\*" is used instead of <CODE>, it matches all 599. If "*" is used instead of <CODE>, it matches all
HTTP status code. If error status code comes from HTTP status code. If error status code comes from
backend server, the custom error pages are not used. backend server, the custom error pages are not used.
.. option:: --server-name=<NAME>
Change server response header field value to <NAME>.
Default: ``nghttpx nghttp2/1.16.1``
.. option:: --no-server-rewrite
Don't rewrite server header field in default mode. When
:option:`--http2-proxy` is used, these headers will not be altered
regardless of this option.
API
~~~
.. option:: --api-max-request-body=<SIZE>
Set the maximum size of request body for API request.
Default: ``16K``
Debug Debug
~~~~~ ~~~~~
@@ -1274,9 +1109,6 @@ SIGQUIT
accepting connection. After all connections are handled, nghttpx accepting connection. After all connections are handled, nghttpx
exits. exits.
SIGHUP
Reload configuration file given in :option:`--conf`.
SIGUSR1 SIGUSR1
Reopen log files. Reopen log files.
@@ -1284,11 +1116,7 @@ SIGUSR2
Fork and execute nghttpx. It will execute the binary in the same Fork and execute nghttpx. It will execute the binary in the same
path with same command-line arguments and environment variables. path with same command-line arguments and environment variables.
After new process comes up, sending SIGQUIT to the original process After new process comes up, sending SIGQUIT to the original process
to perform hot swapping. The difference between SIGUSR2 + SIGQUIT to perform hot swapping.
and SIGHUP is that former is usually used to execute new binary, and
the master process is newly spawned. On the other hand, the latter
just reloads configuration file, and the same master process
continues to exist.
.. note:: .. note::
@@ -1317,7 +1145,7 @@ backend server and extracts URI-reference with parameter
and pushes those URIs to the frontend client. Here is a sample Link and pushes those URIs to the frontend client. Here is a sample Link
header field to initiate server push: header field to initiate server push:
.. code-block:: text .. code-block:: http
Link: </fonts/font.woff>; rel=preload Link: </fonts/font.woff>; rel=preload
Link: </css/theme.css>; rel=preload Link: </css/theme.css>; rel=preload
@@ -1434,24 +1262,6 @@ from the given file. In this case, nghttpx does not rotate key
automatically. To rotate key, one has to restart nghttpx (see automatically. To rotate key, one has to restart nghttpx (see
SIGNALS). SIGNALS).
CERTIFICATE TRANSPARENCY
------------------------
nghttpx supports TLS ``signed_certificate_timestamp`` extension (`RFC
6962 <https://tools.ietf.org/html/rfc6962>`_). The relevant options
are :option:`--tls-sct-dir` and ``sct-dir`` parameter in
:option:`--subcert`. They takes a directory, and nghttpx reads all
files whose extension is ``.sct`` under the directory. The ``*.sct``
files are encoded as ``SignedCertificateTimestamp`` struct described
in `section 3.2 of RFC 69662
<https://tools.ietf.org/html/rfc6962#section-3.2>`_. This format is
the same one used by `nginx-ct
<https://github.com/grahamedgecombe/nginx-ct>`_ and `mod_ssl_ct
<https://httpd.apache.org/docs/trunk/mod/mod_ssl_ct.html>`_.
`ct-submit <https://github.com/grahamedgecombe/ct-submit>`_ can be
used to submit certificates to log servers, and obtain the
``SignedCertificateTimestamp`` struct which can be used with nghttpx.
MRUBY SCRIPTING MRUBY SCRIPTING
--------------- ---------------
@@ -1534,10 +1344,6 @@ respectively.
Return true if TLS is used on the connection. Return true if TLS is used on the connection.
.. rb:attr_reader:: tls_sni
Return the TLS SNI value which client sent in this connection.
.. rb:class:: Request .. rb:class:: Request
Object to represent request from client. The modification to Object to represent request from client. The modification to
@@ -1716,62 +1522,6 @@ addresses:
App.new App.new
API ENDPOINTS
-------------
nghttpx exposes API endpoints to manipulate it via HTTP based API. By
default, API endpoint is disabled. To enable it, add a dedicated
frontend for API using :option:`--frontend` option with "api"
parameter. All requests which come from this frontend address, will
be treated as API request.
The response is normally JSON dictionary, and at least includes the
following keys:
status
The status of the request processing. The following values are
defined:
Success
The request was successful.
Failure
The request was failed. No change has been made.
code
HTTP status code
We wrote "normally", since nghttpx may return ordinal HTML response in
some cases where the error has occurred before reaching API endpoint
(e.g., header field is too large).
The following section describes available API endpoints.
PUT /api/v1beta1/backendconfig
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This API replaces the current backend server settings with the
requested ones. The request method should be PUT, but POST is also
acceptable. The request body must be nghttpx configuration file
format. For configuration file format, see `FILES`_ section. The
line separator inside the request body must be single LF (0x0A).
Currently, only :option:`backend <--backend>` option is parsed, the
others are simply ignored. The semantics of this API is replace the
current backend with the backend options in request body. Describe
the desired set of backend severs, and nghttpx makes it happen. If
there is no :option:`backend <--backend>` option is found in request
body, the current set of backend is replaced with the :option:`backend
<--backend>` option's default value, which is ``127.0.0.1,80``.
The replacement is done instantly without breaking existing
connections or requests. It also avoids any process creation as is
the case with hot swapping with signals.
The one limitation is that only numeric IP address is allowd in
:option:`backend <--backend>` in request body while non numeric
hostname is allowed in command-line or configuration file is read
using :option:`--conf`.
SEE ALSO SEE ALSO
-------- --------

View File

@@ -49,9 +49,6 @@ SIGQUIT
accepting connection. After all connections are handled, nghttpx accepting connection. After all connections are handled, nghttpx
exits. exits.
SIGHUP
Reload configuration file given in :option:`--conf`.
SIGUSR1 SIGUSR1
Reopen log files. Reopen log files.
@@ -59,11 +56,7 @@ SIGUSR2
Fork and execute nghttpx. It will execute the binary in the same Fork and execute nghttpx. It will execute the binary in the same
path with same command-line arguments and environment variables. path with same command-line arguments and environment variables.
After new process comes up, sending SIGQUIT to the original process After new process comes up, sending SIGQUIT to the original process
to perform hot swapping. The difference between SIGUSR2 + SIGQUIT to perform hot swapping.
and SIGHUP is that former is usually used to execute new binary, and
the master process is newly spawned. On the other hand, the latter
just reloads configuration file, and the same master process
continues to exist.
.. note:: .. note::
@@ -92,7 +85,7 @@ backend server and extracts URI-reference with parameter
and pushes those URIs to the frontend client. Here is a sample Link and pushes those URIs to the frontend client. Here is a sample Link
header field to initiate server push: header field to initiate server push:
.. code-block:: text .. code-block:: http
Link: </fonts/font.woff>; rel=preload Link: </fonts/font.woff>; rel=preload
Link: </css/theme.css>; rel=preload Link: </css/theme.css>; rel=preload
@@ -209,24 +202,6 @@ from the given file. In this case, nghttpx does not rotate key
automatically. To rotate key, one has to restart nghttpx (see automatically. To rotate key, one has to restart nghttpx (see
SIGNALS). SIGNALS).
CERTIFICATE TRANSPARENCY
------------------------
nghttpx supports TLS ``signed_certificate_timestamp`` extension (`RFC
6962 <https://tools.ietf.org/html/rfc6962>`_). The relevant options
are :option:`--tls-sct-dir` and ``sct-dir`` parameter in
:option:`--subcert`. They takes a directory, and nghttpx reads all
files whose extension is ``.sct`` under the directory. The ``*.sct``
files are encoded as ``SignedCertificateTimestamp`` struct described
in `section 3.2 of RFC 69662
<https://tools.ietf.org/html/rfc6962#section-3.2>`_. This format is
the same one used by `nginx-ct
<https://github.com/grahamedgecombe/nginx-ct>`_ and `mod_ssl_ct
<https://httpd.apache.org/docs/trunk/mod/mod_ssl_ct.html>`_.
`ct-submit <https://github.com/grahamedgecombe/ct-submit>`_ can be
used to submit certificates to log servers, and obtain the
``SignedCertificateTimestamp`` struct which can be used with nghttpx.
MRUBY SCRIPTING MRUBY SCRIPTING
--------------- ---------------
@@ -309,10 +284,6 @@ respectively.
Return true if TLS is used on the connection. Return true if TLS is used on the connection.
.. rb:attr_reader:: tls_sni
Return the TLS SNI value which client sent in this connection.
.. rb:class:: Request .. rb:class:: Request
Object to represent request from client. The modification to Object to represent request from client. The modification to
@@ -491,62 +462,6 @@ addresses:
App.new App.new
API ENDPOINTS
-------------
nghttpx exposes API endpoints to manipulate it via HTTP based API. By
default, API endpoint is disabled. To enable it, add a dedicated
frontend for API using :option:`--frontend` option with "api"
parameter. All requests which come from this frontend address, will
be treated as API request.
The response is normally JSON dictionary, and at least includes the
following keys:
status
The status of the request processing. The following values are
defined:
Success
The request was successful.
Failure
The request was failed. No change has been made.
code
HTTP status code
We wrote "normally", since nghttpx may return ordinal HTML response in
some cases where the error has occurred before reaching API endpoint
(e.g., header field is too large).
The following section describes available API endpoints.
PUT /api/v1beta1/backendconfig
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This API replaces the current backend server settings with the
requested ones. The request method should be PUT, but POST is also
acceptable. The request body must be nghttpx configuration file
format. For configuration file format, see `FILES`_ section. The
line separator inside the request body must be single LF (0x0A).
Currently, only :option:`backend <--backend>` option is parsed, the
others are simply ignored. The semantics of this API is replace the
current backend with the backend options in request body. Describe
the desired set of backend severs, and nghttpx makes it happen. If
there is no :option:`backend <--backend>` option is found in request
body, the current set of backend is replaced with the :option:`backend
<--backend>` option's default value, which is ``127.0.0.1,80``.
The replacement is done instantly without breaking existing
connections or requests. It also avoids any process creation as is
the case with hot swapping with signals.
The one limitation is that only numeric IP address is allowd in
:option:`backend <--backend>` in request body while non numeric
hostname is allowed in command-line or configuration file is read
using :option:`--conf`.
SEE ALSO SEE ALSO
-------- --------

View File

@@ -36,7 +36,7 @@ functions, and it also interacts with it via many API function calls.
An application can create as many :type:`nghttp2_session` object as it An application can create as many :type:`nghttp2_session` object as it
wants. But single :type:`nghttp2_session` object must be used by a wants. But single :type:`nghttp2_session` object must be used by a
single thread at the same time. This is not so hard to enforce since single thread at the same time. This is not so hard to enforce since
most event-based architecture applications use is single thread per most event-based architecture applicatons use is single thread per
core, and handling one connection I/O is done by single thread. core, and handling one connection I/O is done by single thread.
To feed input to :type:`nghttp2_session` object, one can use To feed input to :type:`nghttp2_session` object, one can use
@@ -177,55 +177,6 @@ Any deviation results in stream error of type PROTOCOL_ERROR. If
error is found in PUSH_PROMISE frame, stream error is raised against error is found in PUSH_PROMISE frame, stream error is raised against
promised stream. promised stream.
The order of transmission of the HTTP/2 frames
----------------------------------------------
This section describes the internals of libnghttp2 about the
scheduling of transmission of HTTP/2 frames. This is pretty much
internal stuff, so the details could change in the future versions of
the library.
libnghttp2 categorizes HTTP/2 frames into 4 categories: urgent,
regular, syn_stream, and data in the order of higher priority.
The urgent category includes PING and SETTINGS. They are sent with
highest priority. The order inside the category is FIFO.
The regular category includes frames other than PING, SETTINGS, DATA,
and HEADERS which does not create stream (which counts toward
concurrent stream limit). The order inside the category is FIFO.
The syn_stream category includes HEADERS frame which creates stream,
that counts toward the concurrent stream limit.
The data category includes DATA frame, and the scheduling among DATA
frames are determined by HTTP/2 dependency tree.
If the application wants to send frames in the specific order, and the
default transmission order does not fit, it has to schedule frames by
itself using the callbacks (e.g.,
:type:`nghttp2_on_frame_send_callback`).
RST_STREAM has special side effect when it is submitted by
`nghttp2_submit_rst_stream()`. It cancels all pending HEADERS and
DATA frames whose stream ID matches the one in the RST_STREAM frame.
This may cause unexpected behaviour for the application in some cases.
For example, suppose that application wants to send RST_STREAM after
sending response HEADERS and DATA. Because of the reason we mentioned
above, the following code does not work:
.. code-block:: c
nghttp2_submit_response(...)
nghttp2_submit_rst_stream(...)
RST_STREAM cancels HEADERS (and DATA), and just RST_STREAM is sent.
The correct way is use :type:`nghttp2_on_frame_send_callback`, and
after HEADERS and DATA frames are sent, issue
`nghttp2_submit_rst_stream()`. FYI,
:type:`nghttp2_on_frame_not_send_callback` tells you why frames are
not sent.
Implement user defined HTTP/2 non-critical extensions Implement user defined HTTP/2 non-critical extensions
----------------------------------------------------- -----------------------------------------------------

View File

@@ -17,16 +17,19 @@ installed in the following way. First, let us introduce
under ``$ANDROID_HOME/toolchain``. An user can freely choose the path under ``$ANDROID_HOME/toolchain``. An user can freely choose the path
for ``ANDROID_HOME``. For example, to install toolchain under for ``ANDROID_HOME``. For example, to install toolchain under
``$ANDROID_HOME/toolchain``, do this in the the directory where NDK is ``$ANDROID_HOME/toolchain``, do this in the the directory where NDK is
unpacked: unpacked::
.. code-block:: text $ build/tools/make-standalone-toolchain.sh \
--install-dir=$ANDROID_HOME/toolchain \
--toolchain=arm-linux-androideabi-4.9 \
--llvm-version=3.5 \
--platform=android-16
$ build/tools/make_standalone_toolchain.py \ The additional flag ``--system=linux-x86_64`` may be required if you
--arch arm --api 16 --stl gnustl are using x86_64 system.
--install-dir $ANDROID_HOME/toolchain
The API level (``--api``) is not important here because we don't use The platform level is not important here because we don't use Android
Android specific C/C++ API. specific C/C++ API.
The dependent libraries, such as OpenSSL and libev should be built The dependent libraries, such as OpenSSL and libev should be built
with the toolchain and installed under ``$ANDROID_HOME/usr/local``. with the toolchain and installed under ``$ANDROID_HOME/usr/local``.
@@ -42,9 +45,7 @@ spdylay as well.
Before running ``android-config`` and ``android-make``, Before running ``android-config`` and ``android-make``,
``ANDROID_HOME`` environment variable must be set to point to the ``ANDROID_HOME`` environment variable must be set to point to the
correct path. Also add ``$ANDROID_HOME/toolchain/bin`` to ``PATH``: correct path. Also add ``$ANDROID_HOME/toolchain/bin`` to ``PATH``::
.. code-block:: text
$ export PATH=$PATH:$ANDROID_HOME/toolchain/bin $ export PATH=$PATH:$ANDROID_HOME/toolchain/bin
@@ -132,24 +133,24 @@ To configure spdylay, use the following script:
#!/bin/sh -e #!/bin/sh -e
if [ -z "$ANDROID_HOME" ]; then if [ -z "$ANDROID_HOME" ]; then
echo 'No $ANDROID_HOME specified.' echo 'No $ANDROID_HOME specified.'
exit 1 exit 1
fi fi
PREFIX=$ANDROID_HOME/usr/local PREFIX=$ANDROID_HOME/usr/local
TOOLCHAIN=$ANDROID_HOME/toolchain TOOLCHAIN=$ANDROID_HOME/toolchain
PATH=$TOOLCHAIN/bin:$PATH PATH=$TOOLCHAIN/bin:$PATH
./configure \ ./configure \
--disable-shared \ --disable-shared \
--host=arm-linux-androideabi \ --host=arm-linux-androideabi \
--build=`dpkg-architecture -qDEB_BUILD_GNU_TYPE` \ --build=`dpkg-architecture -qDEB_BUILD_GNU_TYPE` \
--prefix=$PREFIX \ --prefix=$PREFIX \
--without-libxml2 \ --without-libxml2 \
--disable-src \ --disable-src \
--disable-examples \ --disable-examples \
CPPFLAGS="-I$PREFIX/include" \ CPPFLAGS="-I$PREFIX/include" \
PKG_CONFIG_LIBDIR="$PREFIX/lib/pkgconfig" \ PKG_CONFIG_LIBDIR="$PREFIX/lib/pkgconfig" \
LDFLAGS="-L$PREFIX/lib" LDFLAGS="-L$PREFIX/lib"
And run ``make install`` to build and install. And run ``make install`` to build and install.
@@ -158,8 +159,6 @@ then ``android-make`` to compile nghttp2 source files.
If all went well, application binaries, such as nghttpx, are created If all went well, application binaries, such as nghttpx, are created
under src directory. Strip debugging information from the binary under src directory. Strip debugging information from the binary
using the following command: using the following command::
.. code-block:: text
$ arm-linux-androideabi-strip src/nghttpx $ arm-linux-androideabi-strip src/nghttpx

View File

@@ -27,7 +27,7 @@ We use clang-format to format source code consistently. The
clang-format configuration file .clang-format is located at the root clang-format configuration file .clang-format is located at the root
directory. Since clang-format produces slightly different results directory. Since clang-format produces slightly different results
between versions, we currently use clang-format which comes with between versions, we currently use clang-format which comes with
clang-3.9. clang-3.6.
To detect any violation to the coding style, we recommend to setup git To detect any violation to the coding style, we recommend to setup git
pre-commit hook to check coding style of the changes you introduced. pre-commit hook to check coding style of the changes you introduced.
@@ -35,7 +35,7 @@ The pre-commit file is located at the root directory. Copy it under
.git/hooks and make sure that it is executable. The pre-commit script .git/hooks and make sure that it is executable. The pre-commit script
uses clang-format-diff.py to detect any style errors. If it is not in uses clang-format-diff.py to detect any style errors. If it is not in
your PATH or it exists under different name (e.g., your PATH or it exists under different name (e.g.,
clang-format-diff-3.9 in debian), either add it to PATH variable or clang-format-diff-3.6 in debian), either add it to PATH variable or
add git option ``clangformatdiff.binary`` to point to the script. add git option ``clangformatdiff.binary`` to point to the script.
For emacs users, integrating clang-format to emacs is very easy. For emacs users, integrating clang-format to emacs is very easy.

View File

@@ -48,16 +48,12 @@ explicitly.
The backend is supposed to be Web server. For example, to make The backend is supposed to be Web server. For example, to make
nghttpx listen to encrypted HTTP/2 requests at port 8443, and a nghttpx listen to encrypted HTTP/2 requests at port 8443, and a
backend Web server is configured to listen to HTTP request at port backend Web server is configured to listen to HTTP request at port
8080 in the same host, run nghttpx command-line like this: 8080 in the same host, run nghttpx command-line like this::
.. code-block:: text
$ nghttpx -f0.0.0.0,8443 -b127.0.0.1,8080 /path/to/server.key /path/to/server.crt $ nghttpx -f0.0.0.0,8443 -b127.0.0.1,8080 /path/to/server.key /path/to/server.crt
Then HTTP/2 enabled client can access to the nghttpx in HTTP/2. For Then HTTP/2 enabled client can access to the nghttpx in HTTP/2. For
example, you can send GET request to the server using nghttp: example, you can send GET request to the server using nghttp::
.. code-block:: text
$ nghttp -nv https://localhost:8443/ $ nghttp -nv https://localhost:8443/
@@ -93,9 +89,7 @@ connection, use :option:`--backend` option, and specify ``h2`` in
For example, to make nghttpx listen to encrypted HTTP/2 requests at For example, to make nghttpx listen to encrypted HTTP/2 requests at
port 8443, and a backend HTTP proxy server is configured to listen to port 8443, and a backend HTTP proxy server is configured to listen to
HTTP/1 request at port 8080 in the same host, run nghttpx command-line HTTP/1 request at port 8080 in the same host, run nghttpx command-line
like this: like this::
.. code-block:: text
$ nghttpx -s -f'*,8443' -b127.0.0.1,8080 /path/to/server.key /path/to/server.crt $ nghttpx -s -f'*,8443' -b127.0.0.1,8080 /path/to/server.key /path/to/server.crt
@@ -124,17 +118,13 @@ to proxy.pac file, something like this:
file:///path/to/proxy.pac file:///path/to/proxy.pac
For Chromium, use following command-line: For Chromium, use following command-line::
.. code-block:: text
$ google-chrome --proxy-pac-url=file:///path/to/proxy.pac --use-npn $ google-chrome --proxy-pac-url=file:///path/to/proxy.pac --use-npn
As HTTP/1 proxy server, Squid may work as out-of-box. Traffic server As HTTP/1 proxy server, Squid may work as out-of-box. Traffic server
requires to be configured as forward proxy. Here is the minimum requires to be configured as forward proxy. Here is the minimum
configuration items to edit: configuration items to edit::
.. code-block:: text
CONFIG proxy.config.reverse_proxy.enabled INT 0 CONFIG proxy.config.reverse_proxy.enabled INT 0
CONFIG proxy.config.url_remap.remap_required INT 0 CONFIG proxy.config.url_remap.remap_required INT 0
@@ -144,11 +134,6 @@ Consult Traffic server `documentation
to know how to configure traffic server as forward proxy and its to know how to configure traffic server as forward proxy and its
security implications. security implications.
ALPN support
------------
ALPN support requires OpenSSL >= 1.0.2.
Disable frontend SSL/TLS Disable frontend SSL/TLS
------------------------ ------------------------
@@ -167,9 +152,9 @@ Enable SSL/TLS on memcached connection
-------------------------------------- --------------------------------------
By default, memcached connection is not encrypted. To enable By default, memcached connection is not encrypted. To enable
encryption, use ``tls`` keyword in encryption, use :option:`--tls-ticket-key-memcached-tls` for TLS
:option:`--tls-ticket-key-memcached` for TLS ticket key, and ticket key, and use :option:`--tls-session-cache-memcached-tls` for
:option:`--tls-session-cache-memcached` for TLS session cache. TLS session cache.
Specifying additional server certificates Specifying additional server certificates
----------------------------------------- -----------------------------------------
@@ -211,17 +196,17 @@ Rewriting location header field
nghttpx automatically rewrites location response header field if the nghttpx automatically rewrites location response header field if the
following all conditions satisfy: following all conditions satisfy:
* In the default mode (:option:`--http2-proxy` is not used) * URI in location header field is not absolute URI or is not https URI.
* :option:`--no-location-rewrite` is not used
* URI in location header field is an absolute URI
* URI in location header field includes non empty host component. * URI in location header field includes non empty host component.
* host (without port) in URI in location header field must match the * host (without port) in URI in location header field must match the
host appearing in ``:authority`` or ``host`` header field. host appearing in :authority or host header field.
When rewrite happens, URI scheme is replaced with the ones used in When rewrite happens, URI scheme and port are replaced with the ones
frontend, and authority is replaced with which appears in used in frontend, and host is replaced with which appears in
``:authority``, or ``host`` request header field. ``:authority`` :authority or host request header field. :authority header field has
header field has precedence over ``host``. precedence. If the above conditions are not met with the host value
in :authority header field, rewrite is retried with the value in host
header field.
Hot swapping Hot swapping
------------ ------------
@@ -236,9 +221,6 @@ all existing frontend connections are done, the current process will
exit. At this point, only new nghttpx process exists and serves exit. At this point, only new nghttpx process exists and serves
incoming requests. incoming requests.
If you want to just reload configuration file without executing new
binary, send SIGHUP to nghttpx master process.
Re-opening log files Re-opening log files
-------------------- --------------------

View File

@@ -13,7 +13,7 @@ The extension module is called ``nghttp2``.
determined by configure script. If the detected Python version is not determined by configure script. If the detected Python version is not
what you expect, specify a path to Python executable in ``PYTHON`` what you expect, specify a path to Python executable in ``PYTHON``
variable as an argument to configure script (e.g., ``./configure variable as an argument to configure script (e.g., ``./configure
PYTHON=/usr/bin/python3.5``). PYTHON=/usr/bin/python3.4``).
HPACK API HPACK API
--------- ---------
@@ -136,15 +136,13 @@ HTTP/2 servers
.. note:: .. note::
We use :py:mod:`asyncio` for HTTP/2 server classes, and ALPN. We use :py:mod:`asyncio` for HTTP/2 server classes. Therefore,
Therefore, Python 3.5 or later is required to use these objects. Python 3.4 or later is required to use these objects. To
To explicitly configure nghttp2 build to use Python 3.5, specify explicitly configure nghttp2 build to use Python 3.4, specify the
the ``PYTHON`` variable to the path to Python 3.5 executable when ``PYTHON`` variable to the path to Python 3.4 executable when
invoking configure script like this: invoking configure script like this::
.. code-block:: text $ ./configure PYTHON=/usr/bin/python3.4
$ ./configure PYTHON=/usr/bin/python3.5
.. py:class:: HTTP2Server(address, RequestHandlerClass, ssl=None) .. py:class:: HTTP2Server(address, RequestHandlerClass, ssl=None)

View File

@@ -7,9 +7,7 @@ the end of this page. It also resides in the examples directory in
the archive or repository. the archive or repository.
This simple client takes a single HTTPS URI and retrieves the resource This simple client takes a single HTTPS URI and retrieves the resource
at the URI. The synopsis is: at the URI. The synopsis is::
.. code-block:: text
$ libevent-client HTTPS_URI $ libevent-client HTTPS_URI
@@ -33,17 +31,6 @@ protocol the library supports::
return SSL_TLSEXT_ERR_OK; return SSL_TLSEXT_ERR_OK;
} }
If you are following TLS related RFC, you know that NPN is not the
standardized way to negotiate HTTP/2. NPN itself is not event
published as RFC. The standard way to negotiate HTTP/2 is ALPN,
Application-Layer Protocol Negotiation Extension, defined in `RFC 7301
<https://tools.ietf.org/html/rfc7301>`_. The one caveat of ALPN is
that OpenSSL >= 1.0.2 is required. We use macro to enable/disable
ALPN support depending on OpenSSL version. OpenSSL's ALPN
implementation does not require callback function like the above. But
we have to instruct OpenSSL SSL_CTX to use ALPN, which we'll talk
about soon.
The callback is added to the SSL_CTX object using The callback is added to the SSL_CTX object using
``SSL_CTX_set_next_proto_select_cb()``:: ``SSL_CTX_set_next_proto_select_cb()``::
@@ -59,18 +46,9 @@ The callback is added to the SSL_CTX object using
SSL_OP_NO_COMPRESSION | SSL_OP_NO_COMPRESSION |
SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION); SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION);
SSL_CTX_set_next_proto_select_cb(ssl_ctx, select_next_proto_cb, NULL); SSL_CTX_set_next_proto_select_cb(ssl_ctx, select_next_proto_cb, NULL);
#if OPENSSL_VERSION_NUMBER >= 0x10002000L
SSL_CTX_set_alpn_protos(ssl_ctx, (const unsigned char *)"\x02h2", 3);
#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L
return ssl_ctx; return ssl_ctx;
} }
Here we see ``SSL_CTX_get_alpn_protos()`` function call. We instructs
OpenSSL to notify the server that we support h2, ALPN identifier for
HTTP/2.
The example client defines a couple of structs: The example client defines a couple of structs:
We define and use a ``http2_session_data`` structure to store data We define and use a ``http2_session_data`` structure to store data
@@ -146,27 +124,7 @@ underlying network socket::
if (events & BEV_EVENT_CONNECTED) { if (events & BEV_EVENT_CONNECTED) {
int fd = bufferevent_getfd(bev); int fd = bufferevent_getfd(bev);
int val = 1; int val = 1;
const unsigned char *alpn = NULL;
unsigned int alpnlen = 0;
SSL *ssl;
fprintf(stderr, "Connected\n"); fprintf(stderr, "Connected\n");
ssl = bufferevent_openssl_get_ssl(session_data->bev);
SSL_get0_next_proto_negotiated(ssl, &alpn, &alpnlen);
#if OPENSSL_VERSION_NUMBER >= 0x10002000L
if (alpn == NULL) {
SSL_get0_alpn_selected(ssl, &alpn, &alpnlen);
}
#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L
if (alpn == NULL || alpnlen != 2 || memcmp("h2", alpn, 2) != 0) {
fprintf(stderr, "h2 is not negotiated\n");
delete_http2_session_data(session_data);
return;
}
setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char *)&val, sizeof(val)); setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char *)&val, sizeof(val));
initialize_nghttp2_session(session_data); initialize_nghttp2_session(session_data);
send_client_connection_header(session_data); send_client_connection_header(session_data);
@@ -186,9 +144,6 @@ underlying network socket::
delete_http2_session_data(session_data); delete_http2_session_data(session_data);
} }
Here we validate that HTTP/2 is negotiated, and if not, drop
connection.
For ``BEV_EVENT_EOF``, ``BEV_EVENT_ERROR``, and ``BEV_EVENT_TIMEOUT`` For ``BEV_EVENT_EOF``, ``BEV_EVENT_ERROR``, and ``BEV_EVENT_TIMEOUT``
events, we just simply tear down the connection. events, we just simply tear down the connection.

View File

@@ -78,16 +78,15 @@ header data. To initialize the object, use
int nghttp2_hd_inflate_new(nghttp2_hd_inflater **inflater_ptr); int nghttp2_hd_inflate_new(nghttp2_hd_inflater **inflater_ptr);
To inflate header data, use `nghttp2_hd_inflate_hd2()`:: To inflate header data, use `nghttp2_hd_inflate_hd()`::
ssize_t nghttp2_hd_inflate_hd2(nghttp2_hd_inflater *inflater, ssize_t nghttp2_hd_inflate_hd(nghttp2_hd_inflater *inflater,
nghttp2_nv *nv_out, int *inflate_flags, nghttp2_nv *nv_out, int *inflate_flags,
const uint8_t *in, size_t inlen, uint8_t *in, size_t inlen, int in_final);
int in_final);
`nghttp2_hd_inflate_hd2()` reads a stream of bytes and outputs a `nghttp2_hd_inflate_hd()` reads a stream of bytes and outputs a single
single header field at a time. Multiple calls are normally required to header field at a time. Multiple calls are normally required to read a
read a full stream of bytes and output all of the header fields. full stream of bytes and output all of the header fields.
The *inflater* is the inflater object initialized above. The *nv_out* The *inflater* is the inflater object initialized above. The *nv_out*
is a pointer to a :type:`nghttp2_nv` into which one header field may is a pointer to a :type:`nghttp2_nv` into which one header field may
@@ -119,7 +118,11 @@ If *in_final* is zero and the :macro:`NGHTTP2_HD_INFLATE_EMIT` flag is
not set, it indicates that all given data was processed. The caller not set, it indicates that all given data was processed. The caller
is required to pass additional data. is required to pass additional data.
Example usage of `nghttp2_hd_inflate_hd2()` is shown in the It is important to note that the function may produce one or more
header fields even if *inlen* is 0 when *in_final* is nonzero, due to
differential encoding.
Example usage of `nghttp2_hd_inflate_hd()` is shown in the
`inflate_header_block()` function in `deflate.c`_. `inflate_header_block()` function in `deflate.c`_.
Finally, to delete a :type:`nghttp2_hd_inflater` object, use Finally, to delete a :type:`nghttp2_hd_inflater` object, use

View File

@@ -10,9 +10,7 @@ archive or repository.
This simple server takes 3 arguments: The port number to listen on, This simple server takes 3 arguments: The port number to listen on,
the path to your SSL/TLS private key file, and the path to your the path to your SSL/TLS private key file, and the path to your
certificate file. The synopsis is: certificate file. The synopsis is::
.. code-block:: text
$ libevent-server PORT /path/to/server.key /path/to/server.crt $ libevent-server PORT /path/to/server.key /path/to/server.crt
@@ -27,17 +25,7 @@ application protocols the server supports to a client. In this
example program, when creating the ``SSL_CTX`` object, we store the example program, when creating the ``SSL_CTX`` object, we store the
application protocol name in the wire format of NPN in a statically application protocol name in the wire format of NPN in a statically
allocated buffer. This is safe because we only create one ``SSL_CTX`` allocated buffer. This is safe because we only create one ``SSL_CTX``
object in the program's entire lifetime. object in the program's entire lifetime::
If you are following TLS related RFC, you know that NPN is not the
standardized way to negotiate HTTP/2. NPN itself is not even
published as RFC. The standard way to negotiate HTTP/2 is ALPN,
Application-Layer Protocol Negotiation Extension, defined in `RFC 7301
<https://tools.ietf.org/html/rfc7301>`_. The one caveat of ALPN is
that OpenSSL >= 1.0.2 is required. We use macro to enable/disable
ALPN support depending on OpenSSL version. In ALPN, client sends the
list of supported application protocols, and server selects one of
them. We provide the callback for it::
static unsigned char next_proto_list[256]; static unsigned char next_proto_list[256];
static size_t next_proto_list_len; static size_t next_proto_list_len;
@@ -49,22 +37,6 @@ them. We provide the callback for it::
return SSL_TLSEXT_ERR_OK; return SSL_TLSEXT_ERR_OK;
} }
#if OPENSSL_VERSION_NUMBER >= 0x10002000L
static int alpn_select_proto_cb(SSL *ssl _U_, const unsigned char **out,
unsigned char *outlen, const unsigned char *in,
unsigned int inlen, void *arg _U_) {
int rv;
rv = nghttp2_select_next_protocol((unsigned char **)out, outlen, in, inlen);
if (rv != 1) {
return SSL_TLSEXT_ERR_NOACK;
}
return SSL_TLSEXT_ERR_OK;
}
#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L
static SSL_CTX *create_ssl_ctx(const char *key_file, const char *cert_file) { static SSL_CTX *create_ssl_ctx(const char *key_file, const char *cert_file) {
SSL_CTX *ssl_ctx; SSL_CTX *ssl_ctx;
EC_KEY *ecdh; EC_KEY *ecdh;
@@ -79,11 +51,6 @@ them. We provide the callback for it::
next_proto_list_len = 1 + NGHTTP2_PROTO_VERSION_ID_LEN; next_proto_list_len = 1 + NGHTTP2_PROTO_VERSION_ID_LEN;
SSL_CTX_set_next_protos_advertised_cb(ssl_ctx, next_proto_cb, NULL); SSL_CTX_set_next_protos_advertised_cb(ssl_ctx, next_proto_cb, NULL);
#if OPENSSL_VERSION_NUMBER >= 0x10002000L
SSL_CTX_set_alpn_select_cb(ssl_ctx, alpn_select_proto_cb, NULL);
#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L
return ssl_ctx; return ssl_ctx;
} }
@@ -97,11 +64,6 @@ OpenSSL implementation, we just assign the pointer to the NPN buffers
we filled in earlier. The NPN callback function is set to the we filled in earlier. The NPN callback function is set to the
``SSL_CTX`` object using ``SSL_CTX_set_next_protos_advertised_cb()``. ``SSL_CTX`` object using ``SSL_CTX_set_next_protos_advertised_cb()``.
In ``alpn_select_proto_cb()``, we use `nghttp2_select_next_protocol()`
to select application protocol. The `nghttp2_select_next_protocol()`
returns 1 only if it selected h2 (ALPN identifier for HTTP/2), and out
parameters were assigned accordingly.
Next, let's take a look at the main structures used by the example Next, let's take a look at the main structures used by the example
application: application:
@@ -205,31 +167,11 @@ underlying network socket::
static void eventcb(struct bufferevent *bev _U_, short events, void *ptr) { static void eventcb(struct bufferevent *bev _U_, short events, void *ptr) {
http2_session_data *session_data = (http2_session_data *)ptr; http2_session_data *session_data = (http2_session_data *)ptr;
if (events & BEV_EVENT_CONNECTED) { if (events & BEV_EVENT_CONNECTED) {
const unsigned char *alpn = NULL;
unsigned int alpnlen = 0;
SSL *ssl;
fprintf(stderr, "%s connected\n", session_data->client_addr); fprintf(stderr, "%s connected\n", session_data->client_addr);
ssl = bufferevent_openssl_get_ssl(session_data->bev);
SSL_get0_next_proto_negotiated(ssl, &alpn, &alpnlen);
#if OPENSSL_VERSION_NUMBER >= 0x10002000L
if (alpn == NULL) {
SSL_get0_alpn_selected(ssl, &alpn, &alpnlen);
}
#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L
if (alpn == NULL || alpnlen != 2 || memcmp("h2", alpn, 2) != 0) {
fprintf(stderr, "%s h2 is not negotiated\n", session_data->client_addr);
delete_http2_session_data(session_data);
return;
}
initialize_nghttp2_session(session_data); initialize_nghttp2_session(session_data);
if (send_server_connection_header(session_data) != 0 || if (send_server_connection_header(session_data) != 0) {
session_send(session_data) != 0) {
delete_http2_session_data(session_data); delete_http2_session_data(session_data);
return; return;
} }
@@ -246,9 +188,6 @@ underlying network socket::
delete_http2_session_data(session_data); delete_http2_session_data(session_data);
} }
Here we validate that HTTP/2 is negotiated, and if not, drop
connection.
For the ``BEV_EVENT_EOF``, ``BEV_EVENT_ERROR``, and For the ``BEV_EVENT_EOF``, ``BEV_EVENT_ERROR``, and
``BEV_EVENT_TIMEOUT`` events, we just simply tear down the connection. ``BEV_EVENT_TIMEOUT`` events, we just simply tear down the connection.
The ``delete_http2_session_data()`` function destroys the The ``delete_http2_session_data()`` function destroys the

View File

@@ -66,13 +66,13 @@ enum { IO_NONE, WANT_READ, WANT_WRITE };
#define MAKE_NV(NAME, VALUE) \ #define MAKE_NV(NAME, VALUE) \
{ \ { \
(uint8_t *)NAME, (uint8_t *)VALUE, sizeof(NAME) - 1, sizeof(VALUE) - 1, \ (uint8_t *) NAME, (uint8_t *)VALUE, sizeof(NAME) - 1, sizeof(VALUE) - 1, \
NGHTTP2_NV_FLAG_NONE \ NGHTTP2_NV_FLAG_NONE \
} }
#define MAKE_NV_CS(NAME, VALUE) \ #define MAKE_NV_CS(NAME, VALUE) \
{ \ { \
(uint8_t *)NAME, (uint8_t *)VALUE, sizeof(NAME) - 1, strlen(VALUE), \ (uint8_t *) NAME, (uint8_t *)VALUE, sizeof(NAME) - 1, strlen(VALUE), \
NGHTTP2_NV_FLAG_NONE \ NGHTTP2_NV_FLAG_NONE \
} }
@@ -219,9 +219,9 @@ static int on_frame_send_callback(nghttp2_session *session,
const nghttp2_nv *nva = frame->headers.nva; const nghttp2_nv *nva = frame->headers.nva;
printf("[INFO] C ----------------------------> S (HEADERS)\n"); printf("[INFO] C ----------------------------> S (HEADERS)\n");
for (i = 0; i < frame->headers.nvlen; ++i) { for (i = 0; i < frame->headers.nvlen; ++i) {
fwrite(nva[i].name, 1, nva[i].namelen, stdout); fwrite(nva[i].name, nva[i].namelen, 1, stdout);
printf(": "); printf(": ");
fwrite(nva[i].value, 1, nva[i].valuelen, stdout); fwrite(nva[i].value, nva[i].valuelen, 1, stdout);
printf("\n"); printf("\n");
} }
} }
@@ -249,9 +249,9 @@ static int on_frame_recv_callback(nghttp2_session *session,
if (req) { if (req) {
printf("[INFO] C <---------------------------- S (HEADERS)\n"); printf("[INFO] C <---------------------------- S (HEADERS)\n");
for (i = 0; i < frame->headers.nvlen; ++i) { for (i = 0; i < frame->headers.nvlen; ++i) {
fwrite(nva[i].name, 1, nva[i].namelen, stdout); fwrite(nva[i].name, nva[i].namelen, 1, stdout);
printf(": "); printf(": ");
fwrite(nva[i].value, 1, nva[i].valuelen, stdout); fwrite(nva[i].value, nva[i].valuelen, 1, stdout);
printf("\n"); printf("\n");
} }
} }
@@ -457,12 +457,11 @@ static void ctl_poll(struct pollfd *pollfd, struct Connection *connection) {
static void submit_request(struct Connection *connection, struct Request *req) { static void submit_request(struct Connection *connection, struct Request *req) {
int32_t stream_id; int32_t stream_id;
/* Make sure that the last item is NULL */ /* Make sure that the last item is NULL */
const nghttp2_nv nva[] = {MAKE_NV(":method", "GET"), const nghttp2_nv nva[] = {
MAKE_NV_CS(":path", req->path), MAKE_NV(":method", "GET"), MAKE_NV_CS(":path", req->path),
MAKE_NV(":scheme", "https"), MAKE_NV(":scheme", "https"), MAKE_NV_CS(":authority", req->hostport),
MAKE_NV_CS(":authority", req->hostport), MAKE_NV("accept", "*/*"),
MAKE_NV("accept", "*/*"), MAKE_NV("user-agent", "nghttp2/" NGHTTP2_VERSION)};
MAKE_NV("user-agent", "nghttp2/" NGHTTP2_VERSION)};
stream_id = nghttp2_submit_request(connection->session, NULL, nva, stream_id = nghttp2_submit_request(connection->session, NULL, nva,
sizeof(nva) / sizeof(nva[0]), NULL, req); sizeof(nva) / sizeof(nva[0]), NULL, req);
@@ -563,11 +562,7 @@ static void fetch_uri(const struct URI *uri) {
diec("nghttp2_session_client_new", rv); diec("nghttp2_session_client_new", rv);
} }
rv = nghttp2_submit_settings(connection.session, NGHTTP2_FLAG_NONE, NULL, 0); nghttp2_submit_settings(connection.session, NGHTTP2_FLAG_NONE, NULL, 0);
if (rv != 0) {
diec("nghttp2_submit_settings", rv);
}
/* Submit the HTTP request to the outbound queue. */ /* Submit the HTTP request to the outbound queue. */
submit_request(&connection, &req); submit_request(&connection, &req);
@@ -696,6 +691,9 @@ int main(int argc, char **argv) {
act.sa_handler = SIG_IGN; act.sa_handler = SIG_IGN;
sigaction(SIGPIPE, &act, 0); sigaction(SIGPIPE, &act, 0);
#ifndef OPENSSL_IS_BORINGSSL
OPENSSL_config(NULL);
#endif /* OPENSSL_IS_BORINGSSL */
SSL_load_error_strings(); SSL_load_error_strings();
SSL_library_init(); SSL_library_init();

View File

@@ -33,7 +33,7 @@
#define MAKE_NV(K, V) \ #define MAKE_NV(K, V) \
{ \ { \
(uint8_t *)K, (uint8_t *)V, sizeof(K) - 1, sizeof(V) - 1, \ (uint8_t *) K, (uint8_t *)V, sizeof(K) - 1, sizeof(V) - 1, \
NGHTTP2_NV_FLAG_NONE \ NGHTTP2_NV_FLAG_NONE \
} }
@@ -109,9 +109,9 @@ static void deflate(nghttp2_hd_deflater *deflater,
printf("Input (%zu byte(s)):\n\n", sum); printf("Input (%zu byte(s)):\n\n", sum);
for (i = 0; i < nvlen; ++i) { for (i = 0; i < nvlen; ++i) {
fwrite(nva[i].name, 1, nva[i].namelen, stdout); fwrite(nva[i].name, nva[i].namelen, 1, stdout);
printf(": "); printf(": ");
fwrite(nva[i].value, 1, nva[i].valuelen, stdout); fwrite(nva[i].value, nva[i].valuelen, 1, stdout);
printf("\n"); printf("\n");
} }
@@ -186,9 +186,9 @@ int inflate_header_block(nghttp2_hd_inflater *inflater, uint8_t *in,
inlen -= proclen; inlen -= proclen;
if (inflate_flags & NGHTTP2_HD_INFLATE_EMIT) { if (inflate_flags & NGHTTP2_HD_INFLATE_EMIT) {
fwrite(nv.name, 1, nv.namelen, stderr); fwrite(nv.name, nv.namelen, 1, stderr);
fprintf(stderr, ": "); fprintf(stderr, ": ");
fwrite(nv.value, 1, nv.valuelen, stderr); fwrite(nv.value, nv.valuelen, 1, stderr);
fprintf(stderr, "\n"); fprintf(stderr, "\n");
} }

View File

@@ -179,9 +179,9 @@ static void delete_http2_session_data(http2_session_data *session_data) {
static void print_header(FILE *f, const uint8_t *name, size_t namelen, static void print_header(FILE *f, const uint8_t *name, size_t namelen,
const uint8_t *value, size_t valuelen) { const uint8_t *value, size_t valuelen) {
fwrite(name, 1, namelen, f); fwrite(name, namelen, 1, f);
fprintf(f, ": "); fprintf(f, ": ");
fwrite(value, 1, valuelen, f); fwrite(value, valuelen, 1, f);
fprintf(f, "\n"); fprintf(f, "\n");
} }
@@ -272,7 +272,7 @@ static int on_data_chunk_recv_callback(nghttp2_session *session _U_,
void *user_data) { void *user_data) {
http2_session_data *session_data = (http2_session_data *)user_data; http2_session_data *session_data = (http2_session_data *)user_data;
if (session_data->stream_data->stream_id == stream_id) { if (session_data->stream_data->stream_id == stream_id) {
fwrite(data, 1, len, stdout); fwrite(data, len, 1, stdout);
} }
return 0; return 0;
} }
@@ -322,11 +322,6 @@ static SSL_CTX *create_ssl_ctx(void) {
SSL_OP_NO_COMPRESSION | SSL_OP_NO_COMPRESSION |
SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION); SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION);
SSL_CTX_set_next_proto_select_cb(ssl_ctx, select_next_proto_cb, NULL); SSL_CTX_set_next_proto_select_cb(ssl_ctx, select_next_proto_cb, NULL);
#if OPENSSL_VERSION_NUMBER >= 0x10002000L
SSL_CTX_set_alpn_protos(ssl_ctx, (const unsigned char *)"\x02h2", 3);
#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L
return ssl_ctx; return ssl_ctx;
} }
@@ -383,13 +378,13 @@ static void send_client_connection_header(http2_session_data *session_data) {
#define MAKE_NV(NAME, VALUE, VALUELEN) \ #define MAKE_NV(NAME, VALUE, VALUELEN) \
{ \ { \
(uint8_t *)NAME, (uint8_t *)VALUE, sizeof(NAME) - 1, VALUELEN, \ (uint8_t *) NAME, (uint8_t *)VALUE, sizeof(NAME) - 1, VALUELEN, \
NGHTTP2_NV_FLAG_NONE \ NGHTTP2_NV_FLAG_NONE \
} }
#define MAKE_NV2(NAME, VALUE) \ #define MAKE_NV2(NAME, VALUE) \
{ \ { \
(uint8_t *)NAME, (uint8_t *)VALUE, sizeof(NAME) - 1, sizeof(VALUE) - 1, \ (uint8_t *) NAME, (uint8_t *)VALUE, sizeof(NAME) - 1, sizeof(VALUE) - 1, \
NGHTTP2_NV_FLAG_NONE \ NGHTTP2_NV_FLAG_NONE \
} }
@@ -480,27 +475,7 @@ static void eventcb(struct bufferevent *bev, short events, void *ptr) {
if (events & BEV_EVENT_CONNECTED) { if (events & BEV_EVENT_CONNECTED) {
int fd = bufferevent_getfd(bev); int fd = bufferevent_getfd(bev);
int val = 1; int val = 1;
const unsigned char *alpn = NULL;
unsigned int alpnlen = 0;
SSL *ssl;
fprintf(stderr, "Connected\n"); fprintf(stderr, "Connected\n");
ssl = bufferevent_openssl_get_ssl(session_data->bev);
SSL_get0_next_proto_negotiated(ssl, &alpn, &alpnlen);
#if OPENSSL_VERSION_NUMBER >= 0x10002000L
if (alpn == NULL) {
SSL_get0_alpn_selected(ssl, &alpn, &alpnlen);
}
#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L
if (alpn == NULL || alpnlen != 2 || memcmp("h2", alpn, 2) != 0) {
fprintf(stderr, "h2 is not negotiated\n");
delete_http2_session_data(session_data);
return;
}
setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char *)&val, sizeof(val)); setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char *)&val, sizeof(val));
initialize_nghttp2_session(session_data); initialize_nghttp2_session(session_data);
send_client_connection_header(session_data); send_client_connection_header(session_data);
@@ -594,6 +569,9 @@ int main(int argc, char **argv) {
act.sa_handler = SIG_IGN; act.sa_handler = SIG_IGN;
sigaction(SIGPIPE, &act, NULL); sigaction(SIGPIPE, &act, NULL);
#ifndef OPENSSL_IS_BORINGSSL
OPENSSL_config(NULL);
#endif /* OPENSSL_IS_BORINGSSL */
SSL_load_error_strings(); SSL_load_error_strings();
SSL_library_init(); SSL_library_init();

View File

@@ -79,7 +79,7 @@
#define MAKE_NV(NAME, VALUE) \ #define MAKE_NV(NAME, VALUE) \
{ \ { \
(uint8_t *)NAME, (uint8_t *)VALUE, sizeof(NAME) - 1, sizeof(VALUE) - 1, \ (uint8_t *) NAME, (uint8_t *)VALUE, sizeof(NAME) - 1, sizeof(VALUE) - 1, \
NGHTTP2_NV_FLAG_NONE \ NGHTTP2_NV_FLAG_NONE \
} }
@@ -116,22 +116,6 @@ static int next_proto_cb(SSL *s _U_, const unsigned char **data,
return SSL_TLSEXT_ERR_OK; return SSL_TLSEXT_ERR_OK;
} }
#if OPENSSL_VERSION_NUMBER >= 0x10002000L
static int alpn_select_proto_cb(SSL *ssl _U_, const unsigned char **out,
unsigned char *outlen, const unsigned char *in,
unsigned int inlen, void *arg _U_) {
int rv;
rv = nghttp2_select_next_protocol((unsigned char **)out, outlen, in, inlen);
if (rv != 1) {
return SSL_TLSEXT_ERR_NOACK;
}
return SSL_TLSEXT_ERR_OK;
}
#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L
/* Create SSL_CTX. */ /* Create SSL_CTX. */
static SSL_CTX *create_ssl_ctx(const char *key_file, const char *cert_file) { static SSL_CTX *create_ssl_ctx(const char *key_file, const char *cert_file) {
SSL_CTX *ssl_ctx; SSL_CTX *ssl_ctx;
@@ -168,11 +152,6 @@ static SSL_CTX *create_ssl_ctx(const char *key_file, const char *cert_file) {
next_proto_list_len = 1 + NGHTTP2_PROTO_VERSION_ID_LEN; next_proto_list_len = 1 + NGHTTP2_PROTO_VERSION_ID_LEN;
SSL_CTX_set_next_protos_advertised_cb(ssl_ctx, next_proto_cb, NULL); SSL_CTX_set_next_protos_advertised_cb(ssl_ctx, next_proto_cb, NULL);
#if OPENSSL_VERSION_NUMBER >= 0x10002000L
SSL_CTX_set_alpn_select_cb(ssl_ctx, alpn_select_proto_cb, NULL);
#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L
return ssl_ctx; return ssl_ctx;
} }
@@ -661,31 +640,11 @@ static void writecb(struct bufferevent *bev, void *ptr) {
static void eventcb(struct bufferevent *bev _U_, short events, void *ptr) { static void eventcb(struct bufferevent *bev _U_, short events, void *ptr) {
http2_session_data *session_data = (http2_session_data *)ptr; http2_session_data *session_data = (http2_session_data *)ptr;
if (events & BEV_EVENT_CONNECTED) { if (events & BEV_EVENT_CONNECTED) {
const unsigned char *alpn = NULL;
unsigned int alpnlen = 0;
SSL *ssl;
fprintf(stderr, "%s connected\n", session_data->client_addr); fprintf(stderr, "%s connected\n", session_data->client_addr);
ssl = bufferevent_openssl_get_ssl(session_data->bev);
SSL_get0_next_proto_negotiated(ssl, &alpn, &alpnlen);
#if OPENSSL_VERSION_NUMBER >= 0x10002000L
if (alpn == NULL) {
SSL_get0_alpn_selected(ssl, &alpn, &alpnlen);
}
#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L
if (alpn == NULL || alpnlen != 2 || memcmp("h2", alpn, 2) != 0) {
fprintf(stderr, "%s h2 is not negotiated\n", session_data->client_addr);
delete_http2_session_data(session_data);
return;
}
initialize_nghttp2_session(session_data); initialize_nghttp2_session(session_data);
if (send_server_connection_header(session_data) != 0 || if (send_server_connection_header(session_data) != 0) {
session_send(session_data) != 0) {
delete_http2_session_data(session_data); delete_http2_session_data(session_data);
return; return;
} }
@@ -781,6 +740,9 @@ int main(int argc, char **argv) {
act.sa_handler = SIG_IGN; act.sa_handler = SIG_IGN;
sigaction(SIGPIPE, &act, NULL); sigaction(SIGPIPE, &act, NULL);
#ifndef OPENSSL_IS_BORINGSSL
OPENSSL_config(NULL);
#endif /* OPENSSL_IS_BORINGSSL */
SSL_load_error_strings(); SSL_load_error_strings();
SSL_library_init(); SSL_library_init();

View File

@@ -88,8 +88,7 @@ def build_header(headers):
c = k[-1] c = k[-1]
if c not in ent: if c not in ent:
ent[c] = [] ent[c] = []
if k not in ent[c]: ent[c].append(k)
ent[c].append(k)
return res return res
@@ -107,7 +106,7 @@ def gen_enum():
def gen_index_header(): def gen_index_header():
print '''\ print '''\
static int32_t lookup_token(const uint8_t *name, size_t namelen) { static inline int32_t lookup_token(const uint8_t *name, size_t namelen) {
switch (namelen) {''' switch (namelen) {'''
b = build_header(HEADERS) b = build_header(HEADERS)
for size in sorted(b.keys()): for size in sorted(b.keys()):
@@ -122,7 +121,7 @@ static int32_t lookup_token(const uint8_t *name, size_t namelen) {
case '{}':'''.format(c) case '{}':'''.format(c)
for k in headers: for k in headers:
print '''\ print '''\
if (memeq("{}", name, {})) {{ if (lstreq("{}", name, {})) {{
return {}; return {};
}}'''.format(k[:-1], size - 1, to_enum_hd(k)) }}'''.format(k[:-1], size - 1, to_enum_hd(k))
print '''\ print '''\

View File

@@ -132,23 +132,6 @@ OPTIONS = [
"no-kqueue", "no-kqueue",
"frontend-http2-settings-timeout", "frontend-http2-settings-timeout",
"backend-http2-settings-timeout", "backend-http2-settings-timeout",
"api-max-request-body",
"backend-max-backoff",
"server-name",
"no-server-rewrite",
"frontend-http2-optimize-write-buffer-size",
"frontend-http2-optimize-window-size",
"frontend-http2-window-size",
"frontend-http2-connection-window-size",
"backend-http2-window-size",
"backend-http2-connection-window-size",
"frontend-http2-encoder-dynamic-table-size",
"frontend-http2-decoder-dynamic-table-size",
"backend-http2-encoder-dynamic-table-size",
"backend-http2-decoder-dynamic-table-size",
"ecdh-curves",
"tls-sct-dir",
"backend-connect-timeout",
] ]
LOGVARS = [ LOGVARS = [
@@ -167,8 +150,6 @@ LOGVARS = [
"ssl_protocol", "ssl_protocol",
"ssl_session_id", "ssl_session_id",
"ssl_session_reused", "ssl_session_reused",
"backend_host",
"backend_port",
] ]
if __name__ == '__main__': if __name__ == '__main__':

View File

@@ -160,15 +160,13 @@ DESCRIPTION
print(line.strip()) print(line.strip())
def format_text(text): def format_text(text):
# escape *, but don't escape * if it is used as bullet list. # escape *
m = re.match(r'^\s*\*\s+', text) if len(text) > len(arg_indent):
if m: text = text[:len(arg_indent) + 1] + re.sub(r'\*', r'\*', text[len(arg_indent) + 1:])
text = text[:len(m.group(0))] + re.sub(r'\*', r'\*', text[len(m.group(0)):])
else: else:
text = re.sub(r'\*', r'\*', text) text = re.sub(r'\*', r'\*', text)
# markup option reference # markup option reference
text = re.sub(r'(^|\s)(-[a-zA-Z0-9]|--[a-zA-Z0-9-]+)', text = re.sub(r'(^|\s)(-[a-zA-Z0-9-]+)', r'\1:option:`\2`', text)
r'\1:option:`\2`', text)
# sphinx does not like markup like ':option:`-f`='. We need # sphinx does not like markup like ':option:`-f`='. We need
# backslash between ` and =. # backslash between ` and =.
text = re.sub(r'(:option:`.*?`)(\S)', r'\1\\\2', text) text = re.sub(r'(:option:`.*?`)(\S)', r'\1\\\2', text)

View File

@@ -3,7 +3,6 @@ package nghttp2
import ( import (
"bufio" "bufio"
"bytes" "bytes"
"encoding/json"
"fmt" "fmt"
"golang.org/x/net/http2/hpack" "golang.org/x/net/http2/hpack"
"golang.org/x/net/websocket" "golang.org/x/net/websocket"
@@ -160,9 +159,8 @@ func TestH1H1GracefulShutdown(t *testing.T) {
} }
want := io.EOF want := io.EOF
b := make([]byte, 256) if _, err := st.conn.Read(nil); err == nil || err != want {
if _, err := st.conn.Read(b); err == nil || err != want { t.Errorf("st.conn.Read(): %v; want %v", err, want)
t.Errorf("st.conn.Read(): %v; want %v, %v", err, want)
} }
} }
@@ -795,197 +793,3 @@ func TestH1H2RespPhaseReturn(t *testing.T) {
t.Errorf("body = %v; want %v", got, want) t.Errorf("body = %v; want %v", got, want)
} }
} }
// TestH1APIBackendconfig exercise backendconfig API endpoint routine
// for successful case.
func TestH1APIBackendconfig(t *testing.T) {
st := newServerTesterConnectPort([]string{"-f127.0.0.1,3010;api;no-tls"}, t, func(w http.ResponseWriter, r *http.Request) {
t.Fatalf("request should not be forwarded")
}, 3010)
defer st.Close()
res, err := st.http1(requestParam{
name: "TestH1APIBackendconfig",
path: "/api/v1beta1/backendconfig",
method: "PUT",
body: []byte(`# comment
backend=127.0.0.1,3011
`),
})
if err != nil {
t.Fatalf("Error st.http1() = %v", err)
}
if got, want := res.status, 200; got != want {
t.Errorf("res.status: %v; want %v", got, want)
}
var apiResp APIResponse
err = json.Unmarshal(res.body, &apiResp)
if err != nil {
t.Fatalf("Error unmarshaling API response: %v", err)
}
if got, want := apiResp.Status, "Success"; got != want {
t.Errorf("apiResp.Status: %v; want %v", got, want)
}
if got, want := apiResp.Code, 200; got != want {
t.Errorf("apiResp.Status: %v; want %v", got, want)
}
}
// TestH1APIBackendconfigQuery exercise backendconfig API endpoint
// routine with query.
func TestH1APIBackendconfigQuery(t *testing.T) {
st := newServerTesterConnectPort([]string{"-f127.0.0.1,3010;api;no-tls"}, t, func(w http.ResponseWriter, r *http.Request) {
t.Fatalf("request should not be forwarded")
}, 3010)
defer st.Close()
res, err := st.http1(requestParam{
name: "TestH1APIBackendconfigQuery",
path: "/api/v1beta1/backendconfig?foo=bar",
method: "PUT",
body: []byte(`# comment
backend=127.0.0.1,3011
`),
})
if err != nil {
t.Fatalf("Error st.http1() = %v", err)
}
if got, want := res.status, 200; got != want {
t.Errorf("res.status: %v; want %v", got, want)
}
var apiResp APIResponse
err = json.Unmarshal(res.body, &apiResp)
if err != nil {
t.Fatalf("Error unmarshaling API response: %v", err)
}
if got, want := apiResp.Status, "Success"; got != want {
t.Errorf("apiResp.Status: %v; want %v", got, want)
}
if got, want := apiResp.Code, 200; got != want {
t.Errorf("apiResp.Status: %v; want %v", got, want)
}
}
// TestH1APIBackendconfigBadMethod exercise backendconfig API endpoint
// routine with bad method.
func TestH1APIBackendconfigBadMethod(t *testing.T) {
st := newServerTesterConnectPort([]string{"-f127.0.0.1,3010;api;no-tls"}, t, func(w http.ResponseWriter, r *http.Request) {
t.Fatalf("request should not be forwarded")
}, 3010)
defer st.Close()
res, err := st.http1(requestParam{
name: "TestH1APIBackendconfigBadMethod",
path: "/api/v1beta1/backendconfig",
method: "GET",
body: []byte(`# comment
backend=127.0.0.1,3011
`),
})
if err != nil {
t.Fatalf("Error st.http1() = %v", err)
}
if got, want := res.status, 405; got != want {
t.Errorf("res.status: %v; want %v", got, want)
}
var apiResp APIResponse
err = json.Unmarshal(res.body, &apiResp)
if err != nil {
t.Fatalf("Error unmarshaling API response: %v", err)
}
if got, want := apiResp.Status, "Failure"; got != want {
t.Errorf("apiResp.Status: %v; want %v", got, want)
}
if got, want := apiResp.Code, 405; got != want {
t.Errorf("apiResp.Status: %v; want %v", got, want)
}
}
// TestH1APINotFound exercise backendconfig API endpoint routine when
// API endpoint is not found.
func TestH1APINotFound(t *testing.T) {
st := newServerTesterConnectPort([]string{"-f127.0.0.1,3010;api;no-tls"}, t, func(w http.ResponseWriter, r *http.Request) {
t.Fatalf("request should not be forwarded")
}, 3010)
defer st.Close()
res, err := st.http1(requestParam{
name: "TestH1APINotFound",
path: "/api/notfound",
method: "GET",
body: []byte(`# comment
backend=127.0.0.1,3011
`),
})
if err != nil {
t.Fatalf("Error st.http1() = %v", err)
}
if got, want := res.status, 404; got != want {
t.Errorf("res.status: %v; want %v", got, want)
}
var apiResp APIResponse
err = json.Unmarshal(res.body, &apiResp)
if err != nil {
t.Fatalf("Error unmarshaling API response: %v", err)
}
if got, want := apiResp.Status, "Failure"; got != want {
t.Errorf("apiResp.Status: %v; want %v", got, want)
}
if got, want := apiResp.Code, 404; got != want {
t.Errorf("apiResp.Status: %v; want %v", got, want)
}
}
// TestH1Healthmon tests health monitor endpoint.
func TestH1Healthmon(t *testing.T) {
st := newServerTesterConnectPort([]string{"-f127.0.0.1,3011;healthmon;no-tls"}, t, func(w http.ResponseWriter, r *http.Request) {
t.Fatalf("request should not be forwarded")
}, 3011)
defer st.Close()
res, err := st.http1(requestParam{
name: "TestH1Healthmon",
path: "/alpha/bravo",
})
if err != nil {
t.Fatalf("Error st.http1() = %v", err)
}
if got, want := res.status, 200; got != want {
t.Errorf("res.status: %v; want %v", got, want)
}
}
// TestH1ResponseBeforeRequestEnd tests the situation where response
// ends before request body finishes.
func TestH1ResponseBeforeRequestEnd(t *testing.T) {
st := newServerTester([]string{"--mruby-file=" + testDir + "/req-return.rb"}, t, func(w http.ResponseWriter, r *http.Request) {
t.Fatal("request should not be forwarded")
})
defer st.Close()
if _, err := io.WriteString(st.conn, fmt.Sprintf(`POST / HTTP/1.1
Host: %v
Test-Case: TestH1ResponseBeforeRequestEnd
Content-Length: 1000000
`, 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)
}
if got, want := resp.StatusCode, 404; got != want {
t.Errorf("status: %v; want %v", got, want)
}
}

View File

@@ -2,7 +2,6 @@ package nghttp2
import ( import (
"crypto/tls" "crypto/tls"
"encoding/json"
"fmt" "fmt"
"golang.org/x/net/http2" "golang.org/x/net/http2"
"golang.org/x/net/http2/hpack" "golang.org/x/net/http2/hpack"
@@ -1844,190 +1843,3 @@ func TestH2H2RespPhaseReturn(t *testing.T) {
t.Errorf("body = %v; want %v", got, want) t.Errorf("body = %v; want %v", got, want)
} }
} }
// TestH2APIBackendconfig exercise backendconfig API endpoint routine
// for successful case.
func TestH2APIBackendconfig(t *testing.T) {
st := newServerTesterConnectPort([]string{"-f127.0.0.1,3010;api;no-tls"}, t, func(w http.ResponseWriter, r *http.Request) {
t.Fatalf("request should not be forwarded")
}, 3010)
defer st.Close()
res, err := st.http2(requestParam{
name: "TestH2APIBackendconfig",
path: "/api/v1beta1/backendconfig",
method: "PUT",
body: []byte(`# comment
backend=127.0.0.1,3011
`),
})
if err != nil {
t.Fatalf("Error st.http2() = %v", err)
}
if got, want := res.status, 200; got != want {
t.Errorf("res.status: %v; want %v", got, want)
}
var apiResp APIResponse
err = json.Unmarshal(res.body, &apiResp)
if err != nil {
t.Fatalf("Error unmarshaling API response: %v", err)
}
if got, want := apiResp.Status, "Success"; got != want {
t.Errorf("apiResp.Status: %v; want %v", got, want)
}
if got, want := apiResp.Code, 200; got != want {
t.Errorf("apiResp.Status: %v; want %v", got, want)
}
}
// TestH2APIBackendconfigQuery exercise backendconfig API endpoint
// routine with query.
func TestH2APIBackendconfigQuery(t *testing.T) {
st := newServerTesterConnectPort([]string{"-f127.0.0.1,3010;api;no-tls"}, t, func(w http.ResponseWriter, r *http.Request) {
t.Fatalf("request should not be forwarded")
}, 3010)
defer st.Close()
res, err := st.http2(requestParam{
name: "TestH2APIBackendconfigQuery",
path: "/api/v1beta1/backendconfig?foo=bar",
method: "PUT",
body: []byte(`# comment
backend=127.0.0.1,3011
`),
})
if err != nil {
t.Fatalf("Error st.http2() = %v", err)
}
if got, want := res.status, 200; got != want {
t.Errorf("res.status: %v; want %v", got, want)
}
var apiResp APIResponse
err = json.Unmarshal(res.body, &apiResp)
if err != nil {
t.Fatalf("Error unmarshaling API response: %v", err)
}
if got, want := apiResp.Status, "Success"; got != want {
t.Errorf("apiResp.Status: %v; want %v", got, want)
}
if got, want := apiResp.Code, 200; got != want {
t.Errorf("apiResp.Status: %v; want %v", got, want)
}
}
// TestH2APIBackendconfigBadMethod exercise backendconfig API endpoint
// routine with bad method.
func TestH2APIBackendconfigBadMethod(t *testing.T) {
st := newServerTesterConnectPort([]string{"-f127.0.0.1,3010;api;no-tls"}, t, func(w http.ResponseWriter, r *http.Request) {
t.Fatalf("request should not be forwarded")
}, 3010)
defer st.Close()
res, err := st.http2(requestParam{
name: "TestH2APIBackendconfigBadMethod",
path: "/api/v1beta1/backendconfig",
method: "GET",
body: []byte(`# comment
backend=127.0.0.1,3011
`),
})
if err != nil {
t.Fatalf("Error st.http2() = %v", err)
}
if got, want := res.status, 405; got != want {
t.Errorf("res.status: %v; want %v", got, want)
}
var apiResp APIResponse
err = json.Unmarshal(res.body, &apiResp)
if err != nil {
t.Fatalf("Error unmarshaling API response: %v", err)
}
if got, want := apiResp.Status, "Failure"; got != want {
t.Errorf("apiResp.Status: %v; want %v", got, want)
}
if got, want := apiResp.Code, 405; got != want {
t.Errorf("apiResp.Status: %v; want %v", got, want)
}
}
// TestH2APINotFound exercise backendconfig API endpoint routine when
// API endpoint is not found.
func TestH2APINotFound(t *testing.T) {
st := newServerTesterConnectPort([]string{"-f127.0.0.1,3010;api;no-tls"}, t, func(w http.ResponseWriter, r *http.Request) {
t.Fatalf("request should not be forwarded")
}, 3010)
defer st.Close()
res, err := st.http2(requestParam{
name: "TestH2APINotFound",
path: "/api/notfound",
method: "GET",
body: []byte(`# comment
backend=127.0.0.1,3011
`),
})
if err != nil {
t.Fatalf("Error st.http2() = %v", err)
}
if got, want := res.status, 404; got != want {
t.Errorf("res.status: %v; want %v", got, want)
}
var apiResp APIResponse
err = json.Unmarshal(res.body, &apiResp)
if err != nil {
t.Fatalf("Error unmarshaling API response: %v", err)
}
if got, want := apiResp.Status, "Failure"; got != want {
t.Errorf("apiResp.Status: %v; want %v", got, want)
}
if got, want := apiResp.Code, 404; got != want {
t.Errorf("apiResp.Status: %v; want %v", got, want)
}
}
// TestH2Healthmon tests health monitor endpoint.
func TestH2Healthmon(t *testing.T) {
st := newServerTesterConnectPort([]string{"-f127.0.0.1,3011;healthmon;no-tls"}, t, func(w http.ResponseWriter, r *http.Request) {
t.Fatalf("request should not be forwarded")
}, 3011)
defer st.Close()
res, err := st.http2(requestParam{
name: "TestH2Healthmon",
path: "/alpha/bravo",
})
if err != nil {
t.Fatalf("Error st.http2() = %v", err)
}
if got, want := res.status, 200; got != want {
t.Errorf("res.status: %v; want %v", got, want)
}
}
// TestH2ResponseBeforeRequestEnd tests the situation where response
// ends before request body finishes.
func TestH2ResponseBeforeRequestEnd(t *testing.T) {
st := newServerTester([]string{"--mruby-file=" + testDir + "/req-return.rb"}, t, func(w http.ResponseWriter, r *http.Request) {
t.Fatal("request should not be forwarded")
})
defer st.Close()
res, err := st.http2(requestParam{
name: "TestH2ResponseBeforeRequestEnd",
noEndStream: true,
})
if err != nil {
t.Fatalf("Error st.http2() = %v", err)
}
if got, want := res.status, 404; got != want {
t.Errorf("res.status: %v; want %v", got, want)
}
}

View File

@@ -1,7 +1,6 @@
package nghttp2 package nghttp2
import ( import (
"encoding/json"
"github.com/tatsuhiro-t/spdy" "github.com/tatsuhiro-t/spdy"
"golang.org/x/net/http2/hpack" "golang.org/x/net/http2/hpack"
"net/http" "net/http"
@@ -475,190 +474,3 @@ func TestS3H2RespPhaseReturn(t *testing.T) {
t.Errorf("body = %v; want %v", got, want) t.Errorf("body = %v; want %v", got, want)
} }
} }
// TestS3APIBackendconfig exercise backendconfig API endpoint routine
// for successful case.
func TestS3APIBackendconfig(t *testing.T) {
st := newServerTesterTLSConnectPort([]string{"--npn-list=spdy/3.1", "-f127.0.0.1,3010;api"}, t, func(w http.ResponseWriter, r *http.Request) {
t.Fatalf("request should not be forwarded")
}, 3010)
defer st.Close()
res, err := st.spdy(requestParam{
name: "TestS3APIBackendconfig",
path: "/api/v1beta1/backendconfig",
method: "PUT",
body: []byte(`# comment
backend=127.0.0.1,3011
`),
})
if err != nil {
t.Fatalf("Error st.spdy() = %v", err)
}
if got, want := res.status, 200; got != want {
t.Errorf("res.status: %v; want %v", got, want)
}
var apiResp APIResponse
err = json.Unmarshal(res.body, &apiResp)
if err != nil {
t.Fatalf("Error unmarshaling API response: %v", err)
}
if got, want := apiResp.Status, "Success"; got != want {
t.Errorf("apiResp.Status: %v; want %v", got, want)
}
if got, want := apiResp.Code, 200; got != want {
t.Errorf("apiResp.Status: %v; want %v", got, want)
}
}
// TestS3APIBackendconfigQuery exercise backendconfig API endpoint
// routine with query.
func TestS3APIBackendconfigQuery(t *testing.T) {
st := newServerTesterTLSConnectPort([]string{"--npn-list=spdy/3.1", "-f127.0.0.1,3010;api"}, t, func(w http.ResponseWriter, r *http.Request) {
t.Fatalf("request should not be forwarded")
}, 3010)
defer st.Close()
res, err := st.spdy(requestParam{
name: "TestS3APIBackendconfigQuery",
path: "/api/v1beta1/backendconfig?foo=bar",
method: "PUT",
body: []byte(`# comment
backend=127.0.0.1,3011
`),
})
if err != nil {
t.Fatalf("Error st.spdy() = %v", err)
}
if got, want := res.status, 200; got != want {
t.Errorf("res.status: %v; want %v", got, want)
}
var apiResp APIResponse
err = json.Unmarshal(res.body, &apiResp)
if err != nil {
t.Fatalf("Error unmarshaling API response: %v", err)
}
if got, want := apiResp.Status, "Success"; got != want {
t.Errorf("apiResp.Status: %v; want %v", got, want)
}
if got, want := apiResp.Code, 200; got != want {
t.Errorf("apiResp.Status: %v; want %v", got, want)
}
}
// TestS3APIBackendconfigBadMethod exercise backendconfig API endpoint
// routine with bad method.
func TestS3APIBackendconfigBadMethod(t *testing.T) {
st := newServerTesterTLSConnectPort([]string{"--npn-list=spdy/3.1", "-f127.0.0.1,3010;api"}, t, func(w http.ResponseWriter, r *http.Request) {
t.Fatalf("request should not be forwarded")
}, 3010)
defer st.Close()
res, err := st.spdy(requestParam{
name: "TestS3APIBackendconfigBadMethod",
path: "/api/v1beta1/backendconfig",
method: "GET",
body: []byte(`# comment
backend=127.0.0.1,3011
`),
})
if err != nil {
t.Fatalf("Error st.spdy() = %v", err)
}
if got, want := res.status, 405; got != want {
t.Errorf("res.status: %v; want %v", got, want)
}
var apiResp APIResponse
err = json.Unmarshal(res.body, &apiResp)
if err != nil {
t.Fatalf("Error unmarshaling API response: %v", err)
}
if got, want := apiResp.Status, "Failure"; got != want {
t.Errorf("apiResp.Status: %v; want %v", got, want)
}
if got, want := apiResp.Code, 405; got != want {
t.Errorf("apiResp.Status: %v; want %v", got, want)
}
}
// TestS3APINotFound exercise backendconfig API endpoint routine when
// API endpoint is not found.
func TestS3APINotFound(t *testing.T) {
st := newServerTesterTLSConnectPort([]string{"--npn-list=spdy/3.1", "-f127.0.0.1,3010;api"}, t, func(w http.ResponseWriter, r *http.Request) {
t.Fatalf("request should not be forwarded")
}, 3010)
defer st.Close()
res, err := st.spdy(requestParam{
name: "TestS3APINotFound",
path: "/api/notfound",
method: "GET",
body: []byte(`# comment
backend=127.0.0.1,3011
`),
})
if err != nil {
t.Fatalf("Error st.spdy() = %v", err)
}
if got, want := res.status, 404; got != want {
t.Errorf("res.status: %v; want %v", got, want)
}
var apiResp APIResponse
err = json.Unmarshal(res.body, &apiResp)
if err != nil {
t.Fatalf("Error unmarshaling API response: %v", err)
}
if got, want := apiResp.Status, "Failure"; got != want {
t.Errorf("apiResp.Status: %v; want %v", got, want)
}
if got, want := apiResp.Code, 404; got != want {
t.Errorf("apiResp.Status: %v; want %v", got, want)
}
}
// TestS3Healthmon tests health monitor endpoint.
func TestS3Healthmon(t *testing.T) {
st := newServerTesterTLSConnectPort([]string{"--npn-list=spdy/3.1", "-f127.0.0.1,3011;healthmon"}, t, func(w http.ResponseWriter, r *http.Request) {
t.Fatalf("request should not be forwarded")
}, 3011)
defer st.Close()
res, err := st.spdy(requestParam{
name: "TestS3Healthmon",
path: "/alpha/bravo",
})
if err != nil {
t.Fatalf("Error st.spdy() = %v", err)
}
if got, want := res.status, 200; got != want {
t.Errorf("res.status: %v; want %v", got, want)
}
}
// TestS3ResponseBeforeRequestEnd tests the situation where response
// ends before request body finishes.
func TestS3ResponseBeforeRequestEnd(t *testing.T) {
st := newServerTesterTLS([]string{"--npn-list=spdy/3.1", "--mruby-file=" + testDir + "/req-return.rb"}, t, func(w http.ResponseWriter, r *http.Request) {
t.Fatal("request should not be forwarded")
})
defer st.Close()
res, err := st.spdy(requestParam{
name: "TestS3ResponseBeforeRequestEnd",
noEndStream: true,
})
if err != nil {
t.Fatalf("Error st.spdy() = %v", err)
}
if got, want := res.status, 404; got != want {
t.Errorf("res.status: %v; want %v", got, want)
}
}

View File

@@ -66,36 +66,27 @@ type serverTester struct {
// newServerTester creates test context for plain TCP frontend // newServerTester creates test context for plain TCP frontend
// connection. // connection.
func newServerTester(args []string, t *testing.T, handler http.HandlerFunc) *serverTester { func newServerTester(args []string, t *testing.T, handler http.HandlerFunc) *serverTester {
return newServerTesterInternal(args, t, handler, false, serverPort, nil) return newServerTesterInternal(args, t, handler, false, nil)
}
func newServerTesterConnectPort(args []string, t *testing.T, handler http.HandlerFunc, port int) *serverTester {
return newServerTesterInternal(args, t, handler, false, port, nil)
} }
func newServerTesterHandler(args []string, t *testing.T, handler http.Handler) *serverTester { func newServerTesterHandler(args []string, t *testing.T, handler http.Handler) *serverTester {
return newServerTesterInternal(args, t, handler, false, serverPort, nil) return newServerTesterInternal(args, t, handler, false, nil)
} }
// newServerTester creates test context for TLS frontend connection. // newServerTester creates test context for TLS frontend connection.
func newServerTesterTLS(args []string, t *testing.T, handler http.HandlerFunc) *serverTester { func newServerTesterTLS(args []string, t *testing.T, handler http.HandlerFunc) *serverTester {
return newServerTesterInternal(args, t, handler, true, serverPort, nil) return newServerTesterInternal(args, t, handler, true, nil)
}
func newServerTesterTLSConnectPort(args []string, t *testing.T, handler http.HandlerFunc, port int) *serverTester {
return newServerTesterInternal(args, t, handler, true, port, nil)
} }
// newServerTester creates test context for TLS frontend connection // newServerTester creates test context for TLS frontend connection
// with given clientConfig // with given clientConfig
func newServerTesterTLSConfig(args []string, t *testing.T, handler http.HandlerFunc, clientConfig *tls.Config) *serverTester { func newServerTesterTLSConfig(args []string, t *testing.T, handler http.HandlerFunc, clientConfig *tls.Config) *serverTester {
return newServerTesterInternal(args, t, handler, true, serverPort, clientConfig) return newServerTesterInternal(args, t, handler, true, clientConfig)
} }
// newServerTesterInternal creates test context. If frontendTLS is // newServerTesterInternal creates test context. If frontendTLS is
// true, set up TLS frontend connection. connectPort is the server // true, set up TLS frontend connection.
// side port where client connection is made. func newServerTesterInternal(src_args []string, t *testing.T, handler http.Handler, frontendTLS bool, clientConfig *tls.Config) *serverTester {
func newServerTesterInternal(src_args []string, t *testing.T, handler http.Handler, frontendTLS bool, connectPort int, clientConfig *tls.Config) *serverTester {
ts := httptest.NewUnstartedServer(handler) ts := httptest.NewUnstartedServer(handler)
args := []string{} args := []string{}
@@ -147,7 +138,7 @@ func newServerTesterInternal(src_args []string, t *testing.T, handler http.Handl
args = append(args, fmt.Sprintf("-f127.0.0.1,%v;%v", serverPort, noTLS), b, args = append(args, fmt.Sprintf("-f127.0.0.1,%v;%v", serverPort, noTLS), b,
"--errorlog-file="+logDir+"/log.txt", "-LINFO") "--errorlog-file="+logDir+"/log.txt", "-LINFO")
authority := fmt.Sprintf("127.0.0.1:%v", connectPort) authority := fmt.Sprintf("127.0.0.1:%v", serverPort)
st := &serverTester{ st := &serverTester{
cmd: exec.Command(serverBin, args...), cmd: exec.Command(serverBin, args...),
@@ -169,8 +160,6 @@ func newServerTesterInternal(src_args []string, t *testing.T, handler http.Handl
retry := 0 retry := 0
for { for {
time.Sleep(50 * time.Millisecond)
var conn net.Conn var conn net.Conn
var err error var err error
if frontendTLS { if frontendTLS {
@@ -181,7 +170,7 @@ func newServerTesterInternal(src_args []string, t *testing.T, handler http.Handl
tlsConfig = clientConfig tlsConfig = clientConfig
} }
tlsConfig.InsecureSkipVerify = true tlsConfig.InsecureSkipVerify = true
tlsConfig.NextProtos = []string{"h2", "spdy/3.1"} tlsConfig.NextProtos = []string{"h2-14", "spdy/3.1"}
conn, err = tls.Dial("tcp", authority, tlsConfig) conn, err = tls.Dial("tcp", authority, tlsConfig)
} else { } else {
conn, err = net.Dial("tcp", authority) conn, err = net.Dial("tcp", authority)
@@ -192,6 +181,7 @@ func newServerTesterInternal(src_args []string, t *testing.T, handler http.Handl
st.Close() st.Close()
st.t.Fatalf("Error server is not responding too long; server command-line arguments may be invalid") st.t.Fatalf("Error server is not responding too long; server command-line arguments may be invalid")
} }
time.Sleep(150 * time.Millisecond)
continue continue
} }
if frontendTLS { if frontendTLS {
@@ -297,7 +287,6 @@ type requestParam struct {
body []byte // request body body []byte // request body
trailer []hpack.HeaderField // trailer part trailer []hpack.HeaderField // trailer part
httpUpgrade bool // true if upgraded to HTTP/2 through HTTP Upgrade httpUpgrade bool // true if upgraded to HTTP/2 through HTTP Upgrade
noEndStream bool // true if END_STREAM should not be sent
} }
// wrapper for request body to set trailer part // wrapper for request body to set trailer part
@@ -381,9 +370,8 @@ func (st *serverTester) http1(rp requestParam) (*serverResponse, error) {
if err != nil { if err != nil {
st.t.Fatalf("Error parsing URL from st.url %v: %v", st.url, err) st.t.Fatalf("Error parsing URL from st.url %v: %v", st.url, err)
} }
u.Path = "" u.Path = rp.path
u.RawQuery = "" reqURL = u.String()
reqURL = u.String() + rp.path
} }
req, err := http.NewRequest(method, reqURL, body) req, err := http.NewRequest(method, reqURL, body)
@@ -472,7 +460,7 @@ func (st *serverTester) spdy(rp requestParam) (*serverResponse, error) {
} }
var synStreamFlags spdy.ControlFlags var synStreamFlags spdy.ControlFlags
if len(rp.body) == 0 && !rp.noEndStream { if len(rp.body) == 0 {
synStreamFlags = spdy.ControlFlagFin synStreamFlags = spdy.ControlFlagFin
} }
if err := st.spdyFr.WriteFrame(&spdy.SynStreamFrame{ if err := st.spdyFr.WriteFrame(&spdy.SynStreamFrame{
@@ -486,13 +474,9 @@ func (st *serverTester) spdy(rp requestParam) (*serverResponse, error) {
} }
if len(rp.body) != 0 { if len(rp.body) != 0 {
var dataFlags spdy.DataFlags
if !rp.noEndStream {
dataFlags = spdy.DataFlagFin
}
if err := st.spdyFr.WriteFrame(&spdy.DataFrame{ if err := st.spdyFr.WriteFrame(&spdy.DataFrame{
StreamId: id, StreamId: id,
Flags: dataFlags, Flags: spdy.DataFlagFin,
Data: rp.body, Data: rp.body,
}); err != nil { }); err != nil {
return nil, err return nil, err
@@ -605,7 +589,7 @@ func (st *serverTester) http2(rp requestParam) (*serverResponse, error) {
err := st.fr.WriteHeaders(http2.HeadersFrameParam{ err := st.fr.WriteHeaders(http2.HeadersFrameParam{
StreamID: id, StreamID: id,
EndStream: len(rp.body) == 0 && len(rp.trailer) == 0 && !rp.noEndStream, EndStream: len(rp.body) == 0 && len(rp.trailer) == 0,
EndHeaders: true, EndHeaders: true,
BlockFragment: st.headerBlkBuf.Bytes(), BlockFragment: st.headerBlkBuf.Bytes(),
}) })
@@ -615,7 +599,7 @@ func (st *serverTester) http2(rp requestParam) (*serverResponse, error) {
if len(rp.body) != 0 { if len(rp.body) != 0 {
// TODO we assume rp.body fits in 1 frame // TODO we assume rp.body fits in 1 frame
if err := st.fr.WriteData(id, len(rp.trailer) == 0 && !rp.noEndStream, rp.body); err != nil { if err := st.fr.WriteData(id, len(rp.trailer) == 0, rp.body); err != nil {
return nil, err return nil, err
} }
} }
@@ -762,8 +746,3 @@ func cloneHeader(h http.Header) http.Header {
} }
func noopHandler(w http.ResponseWriter, r *http.Request) {} func noopHandler(w http.ResponseWriter, r *http.Request) {}
type APIResponse struct {
Status string `json:"status,omitempty"`
Code int `json:"code,omitempty"`
}

View File

@@ -23,7 +23,6 @@ set(NGHTTP2_SOURCES
nghttp2_mem.c nghttp2_mem.c
nghttp2_http.c nghttp2_http.c
nghttp2_rcbuf.c nghttp2_rcbuf.c
nghttp2_debug.c
) )
# Public shared library # Public shared library

View File

@@ -48,8 +48,7 @@ OBJECTS = nghttp2_pq.c nghttp2_map.c nghttp2_queue.c \
nghttp2_callbacks.c \ nghttp2_callbacks.c \
nghttp2_mem.c \ nghttp2_mem.c \
nghttp2_http.c \ nghttp2_http.c \
nghttp2_rcbuf.c \ nghttp2_rcbuf.c
nghttp2_debug.c
HFILES = nghttp2_pq.h nghttp2_int.h nghttp2_map.h nghttp2_queue.h \ HFILES = nghttp2_pq.h nghttp2_int.h nghttp2_map.h nghttp2_queue.h \
nghttp2_frame.h \ nghttp2_frame.h \
@@ -64,8 +63,7 @@ HFILES = nghttp2_pq.h nghttp2_int.h nghttp2_map.h nghttp2_queue.h \
nghttp2_callbacks.h \ nghttp2_callbacks.h \
nghttp2_mem.h \ nghttp2_mem.h \
nghttp2_http.h \ nghttp2_http.h \
nghttp2_rcbuf.h \ nghttp2_rcbuf.h
nghttp2_debug.h
libnghttp2_la_SOURCES = $(HFILES) $(OBJECTS) libnghttp2_la_SOURCES = $(HFILES) $(OBJECTS)
libnghttp2_la_LDFLAGS = -no-undefined \ libnghttp2_la_LDFLAGS = -no-undefined \

View File

@@ -45,7 +45,6 @@ extern "C" {
#include <inttypes.h> #include <inttypes.h>
#endif /* !defined(_MSC_VER) || (_MSC_VER >= 1800) */ #endif /* !defined(_MSC_VER) || (_MSC_VER >= 1800) */
#include <sys/types.h> #include <sys/types.h>
#include <stdarg.h>
#include <nghttp2/nghttp2ver.h> #include <nghttp2/nghttp2ver.h>
@@ -82,7 +81,7 @@ extern "C" {
/** /**
* @macro * @macro
* *
* The serialized form of ALPN protocol identifier this library * The seriazlied form of ALPN protocol identifier this library
* supports. Notice that first byte is the length of following * supports. Notice that first byte is the length of following
* protocol identifier. This is the same wire format of `TLS ALPN * protocol identifier. This is the same wire format of `TLS ALPN
* extension <https://tools.ietf.org/html/rfc7301>`_. This is useful * extension <https://tools.ietf.org/html/rfc7301>`_. This is useful
@@ -669,10 +668,6 @@ typedef enum {
/** /**
* @macro * @macro
* *
* .. warning::
*
* Deprecated. The initial max concurrent streams is 0xffffffffu.
*
* Default maximum number of incoming concurrent streams. Use * Default maximum number of incoming concurrent streams. Use
* `nghttp2_submit_settings()` with * `nghttp2_submit_settings()` with
* :enum:`NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS` to change the * :enum:`NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS` to change the
@@ -861,13 +856,8 @@ typedef enum {
* achieved by returning :enum:`NGHTTP2_ERR_DEFERRED` without reading * achieved by returning :enum:`NGHTTP2_ERR_DEFERRED` without reading
* any data in this invocation. The library removes DATA frame from * any data in this invocation. The library removes DATA frame from
* the outgoing queue temporarily. To move back deferred DATA frame * the outgoing queue temporarily. To move back deferred DATA frame
* to outgoing queue, call `nghttp2_session_resume_data()`. * to outgoing queue, call `nghttp2_session_resume_data()`. In case
* * of error, there are 2 choices. Returning
* If the application just wants to return from
* `nghttp2_session_send()` or `nghttp2_session_mem_send()` without
* sending anything, return :enum:`NGHTTP2_ERR_PAUSE`.
*
* In case of error, there are 2 choices. Returning
* :enum:`NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE` will close the stream * :enum:`NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE` will close the stream
* by issuing RST_STREAM with :enum:`NGHTTP2_INTERNAL_ERROR`. If a * by issuing RST_STREAM with :enum:`NGHTTP2_INTERNAL_ERROR`. If a
* different error code is desirable, use * different error code is desirable, use
@@ -1464,19 +1454,9 @@ typedef int (*nghttp2_on_data_chunk_recv_callback)(nghttp2_session *session,
* `nghttp2_session_server_new()`. * `nghttp2_session_server_new()`.
* *
* The implementation of this function must return 0 if it succeeds. * The implementation of this function must return 0 if it succeeds.
* It can also return :enum:`NGHTTP2_ERR_CANCEL` to cancel the * If nonzero is returned, it is treated as fatal error and
* transmission of the given frame. * `nghttp2_session_send()` and `nghttp2_session_mem_send()` functions
* * immediately return :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`.
* If there is a fatal error while executing this callback, the
* implementation should return :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`,
* which makes `nghttp2_session_send()` and
* `nghttp2_session_mem_send()` functions immediately return
* :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`.
*
* If the other value is returned, it is treated as if
* :enum:`NGHTTP2_ERR_CALLBACK_FAILURE` is returned. But the
* implementation should not rely on this since the library may define
* new return value to extend its capability.
* *
* To set this callback to :type:`nghttp2_session_callbacks`, use * To set this callback to :type:`nghttp2_session_callbacks`, use
* `nghttp2_session_callbacks_set_before_frame_send_callback()`. * `nghttp2_session_callbacks_set_before_frame_send_callback()`.
@@ -1727,69 +1707,6 @@ typedef int (*nghttp2_on_header_callback2)(nghttp2_session *session,
nghttp2_rcbuf *value, uint8_t flags, nghttp2_rcbuf *value, uint8_t flags,
void *user_data); void *user_data);
/**
* @functypedef
*
* Callback function invoked when a invalid header name/value pair is
* received for the |frame|.
*
* The parameter and behaviour are similar to
* :type:`nghttp2_on_header_callback`. The difference is that this
* callback is only invoked when a invalid header name/value pair is
* received which is silently ignored if this callback is not set.
* Only invalid regular header field are passed to this callback. In
* other words, invalid pseudo header field is not passed to this
* callback. Also header fields which includes upper cased latter are
* also treated as error without passing them to this callback.
*
* This callback is only considered if HTTP messaging validation is
* turned on (which is on by default, see
* `nghttp2_option_set_no_http_messaging()`).
*
* With this callback, application inspects the incoming invalid
* field, and it also can reset stream from this callback by returning
* :enum:`NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE`. By default, the
* error code is :enum:`NGHTTP2_INTERNAL_ERROR`. To change the error
* code, call `nghttp2_submit_rst_stream()` with the error code of
* choice in addition to returning
* :enum:`NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE`.
*/
typedef int (*nghttp2_on_invalid_header_callback)(
nghttp2_session *session, const nghttp2_frame *frame, const uint8_t *name,
size_t namelen, const uint8_t *value, size_t valuelen, uint8_t flags,
void *user_data);
/**
* @functypedef
*
* Callback function invoked when a invalid header name/value pair is
* received for the |frame|.
*
* The parameter and behaviour are similar to
* :type:`nghttp2_on_header_callback2`. The difference is that this
* callback is only invoked when a invalid header name/value pair is
* received which is silently ignored if this callback is not set.
* Only invalid regular header field are passed to this callback. In
* other words, invalid pseudo header field is not passed to this
* callback. Also header fields which includes upper cased latter are
* also treated as error without passing them to this callback.
*
* This callback is only considered if HTTP messaging validation is
* turned on (which is on by default, see
* `nghttp2_option_set_no_http_messaging()`).
*
* With this callback, application inspects the incoming invalid
* field, and it also can reset stream from this callback by returning
* :enum:`NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE`. By default, the
* error code is :enum:`NGHTTP2_INTERNAL_ERROR`. To change the error
* code, call `nghttp2_submit_rst_stream()` with the error code of
* choice in addition to returning
* :enum:`NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE`.
*/
typedef int (*nghttp2_on_invalid_header_callback2)(
nghttp2_session *session, const nghttp2_frame *frame, nghttp2_rcbuf *name,
nghttp2_rcbuf *value, uint8_t flags, void *user_data);
/** /**
* @functypedef * @functypedef
* *
@@ -2148,29 +2065,6 @@ NGHTTP2_EXTERN void nghttp2_session_callbacks_set_on_header_callback2(
nghttp2_session_callbacks *cbs, nghttp2_session_callbacks *cbs,
nghttp2_on_header_callback2 on_header_callback2); nghttp2_on_header_callback2 on_header_callback2);
/**
* @function
*
* Sets callback function invoked when a invalid header name/value
* pair is received. If both
* `nghttp2_session_callbacks_set_on_invalid_header_callback()` and
* `nghttp2_session_callbacks_set_on_invalid_header_callback2()` are
* used to set callbacks, the latter takes the precedence.
*/
NGHTTP2_EXTERN void nghttp2_session_callbacks_set_on_invalid_header_callback(
nghttp2_session_callbacks *cbs,
nghttp2_on_invalid_header_callback on_invalid_header_callback);
/**
* @function
*
* Sets callback function invoked when a invalid header name/value
* pair is received.
*/
NGHTTP2_EXTERN void nghttp2_session_callbacks_set_on_invalid_header_callback2(
nghttp2_session_callbacks *cbs,
nghttp2_on_invalid_header_callback2 on_invalid_header_callback2);
/** /**
* @function * @function
* *
@@ -2518,34 +2412,6 @@ nghttp2_option_set_builtin_recv_extension_type(nghttp2_option *option,
NGHTTP2_EXTERN void nghttp2_option_set_no_auto_ping_ack(nghttp2_option *option, NGHTTP2_EXTERN void nghttp2_option_set_no_auto_ping_ack(nghttp2_option *option,
int val); int val);
/**
* @function
*
* This option sets the maximum length of header block (a set of
* header fields per one HEADERS frame) to send. The length of a
* given set of header fields is calculated using
* `nghttp2_hd_deflate_bound()`. The default value is 64KiB. If
* application attempts to send header fields larger than this limit,
* the transmission of the frame fails with error code
* :enum:`NGHTTP2_ERR_FRAME_SIZE_ERROR`.
*/
NGHTTP2_EXTERN void
nghttp2_option_set_max_send_header_block_length(nghttp2_option *option,
size_t val);
/**
* @function
*
* This option sets the maximum dynamic table size for deflating
* header fields. The default value is 4KiB. In HTTP/2, receiver of
* deflated header block can specify maximum dynamic table size. The
* actual maximum size is the minimum of the size receiver specified
* and this option value.
*/
NGHTTP2_EXTERN void
nghttp2_option_set_max_deflate_dynamic_table_size(nghttp2_option *option,
size_t val);
/** /**
* @function * @function
* *
@@ -2738,20 +2604,14 @@ NGHTTP2_EXTERN void nghttp2_session_del(nghttp2_session *session);
* *
* 6. :type:`nghttp2_before_frame_send_callback` is invoked. * 6. :type:`nghttp2_before_frame_send_callback` is invoked.
* *
* 7. If :enum:`NGHTTP2_ERR_CANCEL` is returned from * 7. :type:`nghttp2_send_callback` is invoked one or more times to
* :type:`nghttp2_before_frame_send_callback`, the current frame
* transmission is canceled, and
* :type:`nghttp2_on_frame_not_send_callback` is invoked. Abort
* the following steps.
*
* 8. :type:`nghttp2_send_callback` is invoked one or more times to
* send the frame. * send the frame.
* *
* 9. :type:`nghttp2_on_frame_send_callback` is invoked. * 8. :type:`nghttp2_on_frame_send_callback` is invoked.
* *
* 10. If the transmission of the frame triggers closure of the * 9. If the transmission of the frame triggers closure of the stream,
* stream, the stream is closed and * the stream is closed and
* :type:`nghttp2_on_stream_close_callback` is invoked. * :type:`nghttp2_on_stream_close_callback` is invoked.
* *
* This function returns 0 if it succeeds, or one of the following * This function returns 0 if it succeeds, or one of the following
* negative error codes: * negative error codes:
@@ -2802,8 +2662,8 @@ NGHTTP2_EXTERN int nghttp2_session_send(nghttp2_session *session);
* buffer up small chunks of data as necessary to avoid this * buffer up small chunks of data as necessary to avoid this
* situation. * situation.
*/ */
NGHTTP2_EXTERN ssize_t nghttp2_session_mem_send(nghttp2_session *session, NGHTTP2_EXTERN ssize_t
const uint8_t **data_ptr); nghttp2_session_mem_send(nghttp2_session *session, const uint8_t **data_ptr);
/** /**
* @function * @function
@@ -2843,13 +2703,12 @@ NGHTTP2_EXTERN ssize_t nghttp2_session_mem_send(nghttp2_session *session,
* taken. If the frame is either HEADERS or PUSH_PROMISE, * taken. If the frame is either HEADERS or PUSH_PROMISE,
* :type:`nghttp2_on_begin_headers_callback` is invoked. Then * :type:`nghttp2_on_begin_headers_callback` is invoked. Then
* :type:`nghttp2_on_header_callback` is invoked for each header * :type:`nghttp2_on_header_callback` is invoked for each header
* name/value pair. For invalid header field, * name/value pair. After all name/value pairs are emitted
* :type:`nghttp2_on_invalid_header_callback` is called. After * successfully, :type:`nghttp2_on_frame_recv_callback` is
* all name/value pairs are emitted successfully, * invoked. For other frames,
* :type:`nghttp2_on_frame_recv_callback` is invoked. For other * :type:`nghttp2_on_frame_recv_callback` is invoked. If the
* frames, :type:`nghttp2_on_frame_recv_callback` is invoked. * reception of the frame triggers the closure of the stream,
* If the reception of the frame triggers the closure of the * :type:`nghttp2_on_stream_close_callback` is invoked.
* stream, :type:`nghttp2_on_stream_close_callback` is invoked.
* *
* 3. If the received frame is unpacked but is interpreted as * 3. If the received frame is unpacked but is interpreted as
* invalid, :type:`nghttp2_on_invalid_frame_recv_callback` is * invalid, :type:`nghttp2_on_invalid_frame_recv_callback` is
@@ -3018,8 +2877,9 @@ nghttp2_session_get_outbound_queue_size(nghttp2_session *session);
* *
* This function returns -1 if it fails. * This function returns -1 if it fails.
*/ */
NGHTTP2_EXTERN int32_t nghttp2_session_get_stream_effective_recv_data_length( NGHTTP2_EXTERN int32_t
nghttp2_session *session, int32_t stream_id); nghttp2_session_get_stream_effective_recv_data_length(nghttp2_session *session,
int32_t stream_id);
/** /**
* @function * @function
@@ -3029,32 +2889,11 @@ NGHTTP2_EXTERN int32_t nghttp2_session_get_stream_effective_recv_data_length(
* `nghttp2_submit_window_update()`. This function takes into account * `nghttp2_submit_window_update()`. This function takes into account
* that and returns effective window size. * that and returns effective window size.
* *
* This function does not take into account the amount of received
* data from the remote endpoint. Use
* `nghttp2_session_get_stream_local_window_size()` to know the amount
* of data the remote endpoint can send without receiving stream level
* WINDOW_UPDATE frame. Note that each stream is still subject to the
* connection level flow control.
*
* This function returns -1 if it fails. * This function returns -1 if it fails.
*/ */
NGHTTP2_EXTERN int32_t nghttp2_session_get_stream_effective_local_window_size( NGHTTP2_EXTERN int32_t
nghttp2_session *session, int32_t stream_id); nghttp2_session_get_stream_effective_local_window_size(nghttp2_session *session,
int32_t stream_id);
/**
* @function
*
* Returns the amount of flow-controlled payload (e.g., DATA) that the
* remote endpoint can send without receiving stream level
* WINDOW_UPDATE frame. It is also subject to the connection level
* flow control. So the actual amount of data to send is
* min(`nghttp2_session_get_stream_local_window_size()`,
* `nghttp2_session_get_local_window_size()`).
*
* This function returns -1 if it fails.
*/
NGHTTP2_EXTERN int32_t nghttp2_session_get_stream_local_window_size(
nghttp2_session *session, int32_t stream_id);
/** /**
* @function * @function
@@ -3081,32 +2920,11 @@ nghttp2_session_get_effective_recv_data_length(nghttp2_session *session);
* `nghttp2_submit_window_update()`. This function takes into account * `nghttp2_submit_window_update()`. This function takes into account
* that and returns effective window size. * that and returns effective window size.
* *
* This function does not take into account the amount of received
* data from the remote endpoint. Use
* `nghttp2_session_get_local_window_size()` to know the amount of
* data the remote endpoint can send without receiving
* connection-level WINDOW_UPDATE frame. Note that each stream is
* still subject to the stream level flow control.
*
* This function returns -1 if it fails. * This function returns -1 if it fails.
*/ */
NGHTTP2_EXTERN int32_t NGHTTP2_EXTERN int32_t
nghttp2_session_get_effective_local_window_size(nghttp2_session *session); nghttp2_session_get_effective_local_window_size(nghttp2_session *session);
/**
* @function
*
* Returns the amount of flow-controlled payload (e.g., DATA) that the
* remote endpoint can send without receiving connection level
* WINDOW_UPDATE frame. Note that each stream is still subject to the
* stream level flow control (see
* `nghttp2_session_get_stream_local_window_size()`).
*
* This function returns -1 if it fails.
*/
NGHTTP2_EXTERN int32_t
nghttp2_session_get_local_window_size(nghttp2_session *session);
/** /**
* @function * @function
* *
@@ -3121,8 +2939,9 @@ nghttp2_session_get_local_window_size(nghttp2_session *session);
* *
* This function returns -1 if it fails. * This function returns -1 if it fails.
*/ */
NGHTTP2_EXTERN int32_t nghttp2_session_get_stream_remote_window_size( NGHTTP2_EXTERN int32_t
nghttp2_session *session, int32_t stream_id); nghttp2_session_get_stream_remote_window_size(nghttp2_session *session,
int32_t stream_id);
/** /**
* @function * @function
@@ -3154,24 +2973,6 @@ NGHTTP2_EXTERN int
nghttp2_session_get_stream_remote_close(nghttp2_session *session, nghttp2_session_get_stream_remote_close(nghttp2_session *session,
int32_t stream_id); int32_t stream_id);
/**
* @function
*
* Returns the current dynamic table size of HPACK inflater, including
* the overhead 32 bytes per entry described in RFC 7541.
*/
NGHTTP2_EXTERN size_t
nghttp2_session_get_hd_inflate_dynamic_table_size(nghttp2_session *session);
/**
* @function
*
* Returns the current dynamic table size of HPACK deflater including
* the overhead 32 bytes per entry described in RFC 7541.
*/
NGHTTP2_EXTERN size_t
nghttp2_session_get_hd_deflate_dynamic_table_size(nghttp2_session *session);
/** /**
* @function * @function
* *
@@ -3275,18 +3076,9 @@ NGHTTP2_EXTERN int nghttp2_submit_shutdown_notice(nghttp2_session *session);
* The |id| must be one of values defined in * The |id| must be one of values defined in
* :enum:`nghttp2_settings_id`. * :enum:`nghttp2_settings_id`.
*/ */
NGHTTP2_EXTERN uint32_t nghttp2_session_get_remote_settings( NGHTTP2_EXTERN uint32_t
nghttp2_session *session, nghttp2_settings_id id); nghttp2_session_get_remote_settings(nghttp2_session *session,
nghttp2_settings_id id);
/**
* @function
*
* Returns the value of SETTINGS |id| of local endpoint acknowledged
* by the remote endpoint. The |id| must be one of the values defined
* in :enum:`nghttp2_settings_id`.
*/
NGHTTP2_EXTERN uint32_t nghttp2_session_get_local_settings(
nghttp2_session *session, nghttp2_settings_id id);
/** /**
* @function * @function
@@ -3581,8 +3373,9 @@ NGHTTP2_EXTERN int nghttp2_session_upgrade2(nghttp2_session *session,
* :enum:`NGHTTP2_ERR_INSUFF_BUFSIZE` * :enum:`NGHTTP2_ERR_INSUFF_BUFSIZE`
* The provided |buflen| size is too small to hold the output. * The provided |buflen| size is too small to hold the output.
*/ */
NGHTTP2_EXTERN ssize_t nghttp2_pack_settings_payload( NGHTTP2_EXTERN ssize_t
uint8_t *buf, size_t buflen, const nghttp2_settings_entry *iv, size_t niv); nghttp2_pack_settings_payload(uint8_t *buf, size_t buflen,
const nghttp2_settings_entry *iv, size_t niv);
/** /**
* @function * @function
@@ -3707,10 +3500,12 @@ nghttp2_priority_spec_check_default(const nghttp2_priority_spec *pri_spec);
* frame. * frame.
* *
*/ */
NGHTTP2_EXTERN int32_t nghttp2_submit_request( NGHTTP2_EXTERN int32_t
nghttp2_session *session, const nghttp2_priority_spec *pri_spec, nghttp2_submit_request(nghttp2_session *session,
const nghttp2_nv *nva, size_t nvlen, const nghttp2_data_provider *data_prd, const nghttp2_priority_spec *pri_spec,
void *stream_user_data); const nghttp2_nv *nva, size_t nvlen,
const nghttp2_data_provider *data_prd,
void *stream_user_data);
/** /**
* @function * @function
@@ -3788,8 +3583,8 @@ nghttp2_submit_response(nghttp2_session *session, int32_t stream_id,
* *
* The |nva| is an array of name/value pair :type:`nghttp2_nv` with * The |nva| is an array of name/value pair :type:`nghttp2_nv` with
* |nvlen| elements. The application is responsible not to include * |nvlen| elements. The application is responsible not to include
* pseudo-header fields (header field whose name starts with ":") in * required pseudo-header fields (header field whose name starts with
* |nva|. * ":") in |nva|.
* *
* This function creates copies of all name/value pairs in |nva|. It * This function creates copies of all name/value pairs in |nva|. It
* also lower-cases all names in |nva|. The order of elements in * also lower-cases all names in |nva|. The order of elements in
@@ -3804,20 +3599,20 @@ nghttp2_submit_response(nghttp2_session *session, int32_t stream_id,
* :type:`nghttp2_on_frame_not_send_callback` is called. * :type:`nghttp2_on_frame_not_send_callback` is called.
* *
* For server, trailer fields must follow response HEADERS or response * For server, trailer fields must follow response HEADERS or response
* DATA without END_STREAM flat set. The library does not enforce * DATA with END_STREAM flag set. The library does not enforce this
* this requirement, and applications should do this for themselves. * requirement, and applications should do this for themselves. If
* If `nghttp2_submit_trailer()` is called before any response HEADERS * `nghttp2_submit_trailer()` is called before any response HEADERS
* submission (usually by `nghttp2_submit_response()`), the content of * submission (usually by `nghttp2_submit_response()`), the content of
* |nva| will be sent as response headers, which will result in error. * |nva| will be sent as response headers, which will result in error.
* *
* This function has the same effect with `nghttp2_submit_headers()`, * This function has the same effect with `nghttp2_submit_headers()`,
* with flags = :enum:`NGHTTP2_FLAG_END_STREAM` and both pri_spec and * with flags = :enum:`NGHTTP2_FLAG_END_HEADERS` and both pri_spec and
* stream_user_data to NULL. * stream_user_data to NULL.
* *
* To submit trailer fields after `nghttp2_submit_response()` is * To submit trailer fields after `nghttp2_submit_response()` is
* called, the application has to specify * called, the application has to specify
* :type:`nghttp2_data_provider` to `nghttp2_submit_response()`. * :type:`nghttp2_data_provider` to `nghttp2_submit_response()`. In
* Inside of :type:`nghttp2_data_source_read_callback`, when setting * side :type:`nghttp2_data_source_read_callback`, when setting
* :enum:`NGHTTP2_DATA_FLAG_EOF`, also set * :enum:`NGHTTP2_DATA_FLAG_EOF`, also set
* :enum:`NGHTTP2_DATA_FLAG_NO_END_STREAM`. After that, the * :enum:`NGHTTP2_DATA_FLAG_NO_END_STREAM`. After that, the
* application can send trailer fields using * application can send trailer fields using
@@ -3925,10 +3720,11 @@ NGHTTP2_EXTERN int nghttp2_submit_trailer(nghttp2_session *session,
* frame. * frame.
* *
*/ */
NGHTTP2_EXTERN int32_t nghttp2_submit_headers( NGHTTP2_EXTERN int32_t
nghttp2_session *session, uint8_t flags, int32_t stream_id, nghttp2_submit_headers(nghttp2_session *session, uint8_t flags,
const nghttp2_priority_spec *pri_spec, const nghttp2_nv *nva, size_t nvlen, int32_t stream_id, const nghttp2_priority_spec *pri_spec,
void *stream_user_data); const nghttp2_nv *nva, size_t nvlen,
void *stream_user_data);
/** /**
* @function * @function
@@ -4136,9 +3932,10 @@ NGHTTP2_EXTERN int nghttp2_submit_settings(nghttp2_session *session,
* is called for this frame. * is called for this frame.
* *
*/ */
NGHTTP2_EXTERN int32_t nghttp2_submit_push_promise( NGHTTP2_EXTERN int32_t
nghttp2_session *session, uint8_t flags, int32_t stream_id, nghttp2_submit_push_promise(nghttp2_session *session, uint8_t flags,
const nghttp2_nv *nva, size_t nvlen, void *promised_stream_user_data); int32_t stream_id, const nghttp2_nv *nva,
size_t nvlen, void *promised_stream_user_data);
/** /**
* @function * @function
@@ -4274,17 +4071,14 @@ nghttp2_session_check_server_session(nghttp2_session *session);
* that value as window_size_increment is queued. If the * that value as window_size_increment is queued. If the
* |window_size_increment| is larger than the received bytes from the * |window_size_increment| is larger than the received bytes from the
* remote endpoint, the local window size is increased by that * remote endpoint, the local window size is increased by that
* difference. If the sole purpose is to increase the local window * difference.
* size, consider to use `nghttp2_session_set_local_window_size()`.
* *
* If the |window_size_increment| is negative, the local window size * If the |window_size_increment| is negative, the local window size
* is decreased by -|window_size_increment|. If automatic * is decreased by -|window_size_increment|. If automatic
* WINDOW_UPDATE is enabled * WINDOW_UPDATE is enabled
* (`nghttp2_option_set_no_auto_window_update()`), and the library * (`nghttp2_option_set_no_auto_window_update()`), and the library
* decided that the WINDOW_UPDATE should be submitted, then * decided that the WINDOW_UPDATE should be submitted, then
* WINDOW_UPDATE is queued with the current received bytes count. If * WINDOW_UPDATE is queued with the current received bytes count.
* the sole purpose is to decrease the local window size, consider to
* use `nghttp2_session_set_local_window_size()`.
* *
* If the |window_size_increment| is 0, the function does nothing and * If the |window_size_increment| is 0, the function does nothing and
* returns 0. * returns 0.
@@ -4302,44 +4096,6 @@ NGHTTP2_EXTERN int nghttp2_submit_window_update(nghttp2_session *session,
int32_t stream_id, int32_t stream_id,
int32_t window_size_increment); int32_t window_size_increment);
/**
* @function
*
* Set local window size (local endpoints's window size) to the given
* |window_size| for the given stream denoted by |stream_id|. To
* change connection level window size, specify 0 to |stream_id|. To
* increase window size, this function may submit WINDOW_UPDATE frame
* to transmission queue.
*
* The |flags| is currently ignored and should be
* :enum:`NGHTTP2_FLAG_NONE`.
*
* This sounds similar to `nghttp2_submit_window_update()`, but there
* are 2 differences. The first difference is that this function
* takes the absolute value of window size to set, rather than the
* delta. To change the window size, this may be easier to use since
* the application just declares the intended window size, rather than
* calculating delta. The second difference is that
* `nghttp2_submit_window_update()` affects the received bytes count
* which has not acked yet. By the specification of
* `nghttp2_submit_window_update()`, to strictly increase the local
* window size, we have to submit delta including all received bytes
* count, which might not be desirable in some cases. On the other
* hand, this function does not affect the received bytes count. It
* just sets the local window size to the given value.
*
* This function returns 0 if it succeeds, or one of the following
* negative error codes:
*
* :enum:`NGHTTP2_ERR_INVALID_ARGUMENT`
* The |stream_id| is negative.
* :enum:`NGHTTP2_ERR_NOMEM`
* Out of memory.
*/
NGHTTP2_EXTERN int
nghttp2_session_set_local_window_size(nghttp2_session *session, uint8_t flags,
int32_t stream_id, int32_t window_size);
/** /**
* @function * @function
* *
@@ -4586,7 +4342,7 @@ typedef struct nghttp2_hd_deflater nghttp2_hd_deflater;
* *
* Initializes |*deflater_ptr| for deflating name/values pairs. * Initializes |*deflater_ptr| for deflating name/values pairs.
* *
* The |max_deflate_dynamic_table_size| is the upper bound of header * The |deflate_hd_table_bufsize_max| is the upper bound of header
* table size the deflater will use. * table size the deflater will use.
* *
* If this function fails, |*deflater_ptr| is left untouched. * If this function fails, |*deflater_ptr| is left untouched.
@@ -4597,9 +4353,8 @@ typedef struct nghttp2_hd_deflater nghttp2_hd_deflater;
* :enum:`NGHTTP2_ERR_NOMEM` * :enum:`NGHTTP2_ERR_NOMEM`
* Out of memory. * Out of memory.
*/ */
NGHTTP2_EXTERN int NGHTTP2_EXTERN int nghttp2_hd_deflate_new(nghttp2_hd_deflater **deflater_ptr,
nghttp2_hd_deflate_new(nghttp2_hd_deflater **deflater_ptr, size_t deflate_hd_table_bufsize_max);
size_t max_deflate_dynamic_table_size);
/** /**
* @function * @function
@@ -4616,10 +4371,9 @@ nghttp2_hd_deflate_new(nghttp2_hd_deflater **deflater_ptr,
* The library code does not refer to |mem| pointer after this * The library code does not refer to |mem| pointer after this
* function returns, so the application can safely free it. * function returns, so the application can safely free it.
*/ */
NGHTTP2_EXTERN int NGHTTP2_EXTERN int nghttp2_hd_deflate_new2(nghttp2_hd_deflater **deflater_ptr,
nghttp2_hd_deflate_new2(nghttp2_hd_deflater **deflater_ptr, size_t deflate_hd_table_bufsize_max,
size_t max_deflate_dynamic_table_size, nghttp2_mem *mem);
nghttp2_mem *mem);
/** /**
* @function * @function
@@ -4632,18 +4386,18 @@ NGHTTP2_EXTERN void nghttp2_hd_deflate_del(nghttp2_hd_deflater *deflater);
* @function * @function
* *
* Changes header table size of the |deflater| to * Changes header table size of the |deflater| to
* |settings_max_dynamic_table_size| bytes. This may trigger eviction * |settings_hd_table_bufsize_max| bytes. This may trigger eviction
* in the dynamic table. * in the dynamic table.
* *
* The |settings_max_dynamic_table_size| should be the value received * The |settings_hd_table_bufsize_max| should be the value received in
* in SETTINGS_HEADER_TABLE_SIZE. * SETTINGS_HEADER_TABLE_SIZE.
* *
* The deflater never uses more memory than * The deflater never uses more memory than
* ``max_deflate_dynamic_table_size`` bytes specified in * ``deflate_hd_table_bufsize_max`` bytes specified in
* `nghttp2_hd_deflate_new()`. Therefore, if * `nghttp2_hd_deflate_new()`. Therefore, if
* |settings_max_dynamic_table_size| > * |settings_hd_table_bufsize_max| > ``deflate_hd_table_bufsize_max``,
* ``max_deflate_dynamic_table_size``, resulting maximum table size * resulting maximum table size becomes
* becomes ``max_deflate_dynamic_table_size``. * ``deflate_hd_table_bufsize_max``.
* *
* This function returns 0 if it succeeds, or one of the following * This function returns 0 if it succeeds, or one of the following
* negative error codes: * negative error codes:
@@ -4653,7 +4407,7 @@ NGHTTP2_EXTERN void nghttp2_hd_deflate_del(nghttp2_hd_deflater *deflater);
*/ */
NGHTTP2_EXTERN int NGHTTP2_EXTERN int
nghttp2_hd_deflate_change_table_size(nghttp2_hd_deflater *deflater, nghttp2_hd_deflate_change_table_size(nghttp2_hd_deflater *deflater,
size_t settings_max_dynamic_table_size); size_t settings_hd_table_bufsize_max);
/** /**
* @function * @function
@@ -4682,43 +4436,9 @@ nghttp2_hd_deflate_change_table_size(nghttp2_hd_deflater *deflater,
* :enum:`NGHTTP2_ERR_INSUFF_BUFSIZE` * :enum:`NGHTTP2_ERR_INSUFF_BUFSIZE`
* The provided |buflen| size is too small to hold the output. * The provided |buflen| size is too small to hold the output.
*/ */
NGHTTP2_EXTERN ssize_t nghttp2_hd_deflate_hd(nghttp2_hd_deflater *deflater, NGHTTP2_EXTERN ssize_t
uint8_t *buf, size_t buflen, nghttp2_hd_deflate_hd(nghttp2_hd_deflater *deflater, uint8_t *buf,
const nghttp2_nv *nva, size_t buflen, const nghttp2_nv *nva, size_t nvlen);
size_t nvlen);
/**
* @function
*
* Deflates the |nva|, which has the |nvlen| name/value pairs, into
* the |veclen| size of buf vector |vec|. The each size of buffer
* must be set in len field of :type:`nghttp2_vec`. If and only if
* one chunk is filled up completely, next chunk will be used. If
* |vec| is not large enough to store the deflated header block, this
* function fails with :enum:`NGHTTP2_ERR_INSUFF_BUFSIZE`. The caller
* should use `nghttp2_hd_deflate_bound()` to know the upper bound of
* buffer size required to deflate given header name/value pairs.
*
* Once this function fails, subsequent call of this function always
* returns :enum:`NGHTTP2_ERR_HEADER_COMP`.
*
* After this function returns, it is safe to delete the |nva|.
*
* This function returns 0 if it succeeds, or one of the following
* negative error codes:
*
* :enum:`NGHTTP2_ERR_NOMEM`
* Out of memory.
* :enum:`NGHTTP2_ERR_HEADER_COMP`
* Deflation process has failed.
* :enum:`NGHTTP2_ERR_INSUFF_BUFSIZE`
* The provided |buflen| size is too small to hold the output.
*/
NGHTTP2_EXTERN ssize_t nghttp2_hd_deflate_hd_vec(nghttp2_hd_deflater *deflater,
const nghttp2_vec *vec,
size_t veclen,
const nghttp2_nv *nva,
size_t nvlen);
/** /**
* @function * @function
@@ -4827,8 +4547,8 @@ NGHTTP2_EXTERN void nghttp2_hd_inflate_del(nghttp2_hd_inflater *inflater);
* Changes header table size in the |inflater|. This may trigger * Changes header table size in the |inflater|. This may trigger
* eviction in the dynamic table. * eviction in the dynamic table.
* *
* The |settings_max_dynamic_table_size| should be the value * The |settings_hd_table_bufsize_max| should be the value transmitted
* transmitted in SETTINGS_HEADER_TABLE_SIZE. * in SETTINGS_HEADER_TABLE_SIZE.
* *
* This function must not be called while header block is being * This function must not be called while header block is being
* inflated. In other words, this function must be called after * inflated. In other words, this function must be called after
@@ -4849,7 +4569,7 @@ NGHTTP2_EXTERN void nghttp2_hd_inflate_del(nghttp2_hd_inflater *inflater);
*/ */
NGHTTP2_EXTERN int NGHTTP2_EXTERN int
nghttp2_hd_inflate_change_table_size(nghttp2_hd_inflater *inflater, nghttp2_hd_inflate_change_table_size(nghttp2_hd_inflater *inflater,
size_t settings_max_dynamic_table_size); size_t settings_hd_table_bufsize_max);
/** /**
* @enum * @enum
@@ -4972,14 +4692,10 @@ NGHTTP2_EXTERN ssize_t nghttp2_hd_inflate_hd(nghttp2_hd_inflater *inflater,
* *
* The application should call this function repeatedly until the * The application should call this function repeatedly until the
* ``(*inflate_flags) & NGHTTP2_HD_INFLATE_FINAL`` is nonzero and * ``(*inflate_flags) & NGHTTP2_HD_INFLATE_FINAL`` is nonzero and
* return value is non-negative. If that happens, all given input * return value is non-negative. This means the all input values are
* data (|inlen| bytes) are processed successfully. Then the * processed successfully. Then the application must call
* application must call `nghttp2_hd_inflate_end_headers()` to prepare * `nghttp2_hd_inflate_end_headers()` to prepare for the next header
* for the next header block input. * block input.
*
* In other words, if |in_final| is nonzero, and this function returns
* |inlen|, you can assert that :enum:`NGHTTP2_HD_INFLATE_FINAL` is
* set in |*inflate_flags|.
* *
* The caller can feed complete compressed header block. It also can * The caller can feed complete compressed header block. It also can
* feed it in several chunks. The caller must set |in_final| to * feed it in several chunks. The caller must set |in_final| to
@@ -5038,11 +4754,10 @@ NGHTTP2_EXTERN ssize_t nghttp2_hd_inflate_hd(nghttp2_hd_inflater *inflater,
* } * }
* *
*/ */
NGHTTP2_EXTERN ssize_t nghttp2_hd_inflate_hd2(nghttp2_hd_inflater *inflater, NGHTTP2_EXTERN ssize_t
nghttp2_nv *nv_out, nghttp2_hd_inflate_hd2(nghttp2_hd_inflater *inflater, nghttp2_nv *nv_out,
int *inflate_flags, int *inflate_flags, const uint8_t *in, size_t inlen,
const uint8_t *in, size_t inlen, int in_final);
int in_final);
/** /**
* @function * @function
@@ -5232,42 +4947,6 @@ NGHTTP2_EXTERN int32_t nghttp2_stream_get_weight(nghttp2_stream *stream);
NGHTTP2_EXTERN int32_t NGHTTP2_EXTERN int32_t
nghttp2_stream_get_sum_dependency_weight(nghttp2_stream *stream); nghttp2_stream_get_sum_dependency_weight(nghttp2_stream *stream);
/**
* @functypedef
*
* Callback function invoked when the library outputs debug logging.
* The function is called with arguments suitable for ``vfprintf(3)``
*
* The debug output is only enabled if the library is built with
* ``DEBUGBUILD`` macro defined.
*/
typedef void (*nghttp2_debug_vprintf_callback)(const char *format,
va_list args);
/**
* @function
*
* Sets a debug output callback called by the library when built with
* ``DEBUGBUILD`` macro defined. If this option is not used, debug
* log is written into standard error output.
*
* For builds without ``DEBUGBUILD`` macro defined, this function is
* noop.
*
* Note that building with ``DEBUGBUILD`` may cause significant
* performance penalty to libnghttp2 because of extra processing. It
* should be used for debugging purpose only.
*
* .. Warning::
*
* Building with ``DEBUGBUILD`` may cause significant performance
* penalty to libnghttp2 because of extra processing. It should be
* used for debugging purpose only. We write this two times because
* this is important.
*/
NGHTTP2_EXTERN void nghttp2_set_debug_vprintf_callback(
nghttp2_debug_vprintf_callback debug_vprintf_callback);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@@ -27,7 +27,6 @@
#include <stdio.h> #include <stdio.h>
#include "nghttp2_helper.h" #include "nghttp2_helper.h"
#include "nghttp2_debug.h"
void nghttp2_buf_init(nghttp2_buf *buf) { void nghttp2_buf_init(nghttp2_buf *buf) {
buf->begin = NULL; buf->begin = NULL;
@@ -224,54 +223,13 @@ int nghttp2_bufs_wrap_init(nghttp2_bufs *bufs, uint8_t *begin, size_t len,
return 0; return 0;
} }
int nghttp2_bufs_wrap_init2(nghttp2_bufs *bufs, const nghttp2_vec *vec,
size_t veclen, nghttp2_mem *mem) {
size_t i = 0;
nghttp2_buf_chain *cur_chain;
nghttp2_buf_chain *head_chain;
nghttp2_buf_chain **dst_chain = &head_chain;
if (veclen == 0) {
return nghttp2_bufs_wrap_init(bufs, NULL, 0, mem);
}
head_chain = nghttp2_mem_malloc(mem, sizeof(nghttp2_buf_chain) * veclen);
if (head_chain == NULL) {
return NGHTTP2_ERR_NOMEM;
}
for (i = 0; i < veclen; ++i) {
cur_chain = &head_chain[i];
cur_chain->next = NULL;
nghttp2_buf_wrap_init(&cur_chain->buf, vec[i].base, vec[i].len);
*dst_chain = cur_chain;
dst_chain = &cur_chain->next;
}
bufs->mem = mem;
bufs->offset = 0;
bufs->head = head_chain;
bufs->cur = bufs->head;
/* We don't use chunk_length since no allocation is expected. */
bufs->chunk_length = 0;
bufs->chunk_used = veclen;
bufs->max_chunk = veclen;
bufs->chunk_keep = veclen;
return 0;
}
void nghttp2_bufs_wrap_free(nghttp2_bufs *bufs) { void nghttp2_bufs_wrap_free(nghttp2_bufs *bufs) {
if (bufs == NULL) { if (bufs == NULL) {
return; return;
} }
if (bufs->head) { nghttp2_mem_free(bufs->mem, bufs->head);
nghttp2_mem_free(bufs->mem, bufs->head); bufs->head = NULL;
}
} }
void nghttp2_bufs_seek_last_present(nghttp2_bufs *bufs) { void nghttp2_bufs_seek_last_present(nghttp2_bufs *bufs) {
@@ -298,6 +256,12 @@ size_t nghttp2_bufs_len(nghttp2_bufs *bufs) {
return len; return len;
} }
static size_t bufs_avail(nghttp2_bufs *bufs) {
return nghttp2_buf_avail(&bufs->cur->buf) +
(bufs->chunk_length - bufs->offset) *
(bufs->max_chunk - bufs->chunk_used);
}
static int bufs_alloc_chain(nghttp2_bufs *bufs) { static int bufs_alloc_chain(nghttp2_bufs *bufs) {
int rv; int rv;
nghttp2_buf_chain *chain; nghttp2_buf_chain *chain;
@@ -317,8 +281,9 @@ static int bufs_alloc_chain(nghttp2_bufs *bufs) {
return rv; return rv;
} }
DEBUGF("new buffer %zu bytes allocated for bufs %p, used %zu\n", DEBUGF(fprintf(stderr,
bufs->chunk_length, bufs, bufs->chunk_used); "new buffer %zu bytes allocated for bufs %p, used %zu\n",
bufs->chunk_length, bufs, bufs->chunk_used));
++bufs->chunk_used; ++bufs->chunk_used;
@@ -336,6 +301,10 @@ int nghttp2_bufs_add(nghttp2_bufs *bufs, const void *data, size_t len) {
nghttp2_buf *buf; nghttp2_buf *buf;
const uint8_t *p; const uint8_t *p;
if (bufs_avail(bufs) < len) {
return NGHTTP2_ERR_BUFFER_ERROR;
}
p = data; p = data;
while (len) { while (len) {

View File

@@ -138,9 +138,7 @@ typedef struct {
nghttp2_buf_chain *cur; nghttp2_buf_chain *cur;
/* Memory allocator */ /* Memory allocator */
nghttp2_mem *mem; nghttp2_mem *mem;
/* The buffer capacity of each buf. This field may be 0 if /* The buffer capacity of each buf */
nghttp2_bufs is initialized by nghttp2_bufs_wrap_init* family
functions. */
size_t chunk_length; size_t chunk_length;
/* The maximum number of nghttp2_buf_chain */ /* The maximum number of nghttp2_buf_chain */
size_t max_chunk; size_t max_chunk;
@@ -199,13 +197,10 @@ void nghttp2_bufs_free(nghttp2_bufs *bufs);
/* /*
* Initializes |bufs| using supplied buffer |begin| of length |len|. * Initializes |bufs| using supplied buffer |begin| of length |len|.
* The first buffer bufs->head uses buffer |begin|. The buffer size * The first buffer bufs->head uses buffer |begin|. The buffer size
* is fixed and no extra chunk buffer is allocated. In other * is fixed and no allocate extra chunk buffer is allocated. In other
* words, max_chunk = chunk_keep = 1. To free the resource allocated * words, max_chunk = chunk_keep = 1. To free the resource allocated
* for |bufs|, use nghttp2_bufs_wrap_free(). * for |bufs|, use nghttp2_bufs_wrap_free().
* *
* Don't use the function which performs allocation, such as
* nghttp2_bufs_realloc().
*
* This function returns 0 if it succeeds, or one of the following * This function returns 0 if it succeeds, or one of the following
* negative error codes: * negative error codes:
* *
@@ -215,25 +210,6 @@ void nghttp2_bufs_free(nghttp2_bufs *bufs);
int nghttp2_bufs_wrap_init(nghttp2_bufs *bufs, uint8_t *begin, size_t len, int nghttp2_bufs_wrap_init(nghttp2_bufs *bufs, uint8_t *begin, size_t len,
nghttp2_mem *mem); nghttp2_mem *mem);
/*
* Initializes |bufs| using supplied |veclen| size of buf vector
* |vec|. The number of buffers is fixed and no extra chunk buffer is
* allocated. In other words, max_chunk = chunk_keep = |in_len|. To
* free the resource allocated for |bufs|, use
* nghttp2_bufs_wrap_free().
*
* Don't use the function which performs allocation, such as
* nghttp2_bufs_realloc().
*
* This function returns 0 if it succeeds, or one of the following
* negative error codes:
*
* NGHTTP2_ERR_NOMEM
* Out of memory.
*/
int nghttp2_bufs_wrap_init2(nghttp2_bufs *bufs, const nghttp2_vec *vec,
size_t veclen, nghttp2_mem *mem);
/* /*
* Frees any related resource to the |bufs|. This function does not * Frees any related resource to the |bufs|. This function does not
* free supplied buffer provided in nghttp2_bufs_wrap_init(). * free supplied buffer provided in nghttp2_bufs_wrap_init().
@@ -405,7 +381,7 @@ int nghttp2_bufs_next_present(nghttp2_bufs *bufs);
#define nghttp2_bufs_cur_avail(BUFS) nghttp2_buf_avail(&(BUFS)->cur->buf) #define nghttp2_bufs_cur_avail(BUFS) nghttp2_buf_avail(&(BUFS)->cur->buf)
/* /*
* Returns the total buffer length of |bufs|. * Returns the buffer length of |bufs|.
*/ */
size_t nghttp2_bufs_len(nghttp2_bufs *bufs); size_t nghttp2_bufs_len(nghttp2_bufs *bufs);

View File

@@ -110,18 +110,6 @@ void nghttp2_session_callbacks_set_on_header_callback2(
cbs->on_header_callback2 = on_header_callback2; cbs->on_header_callback2 = on_header_callback2;
} }
void nghttp2_session_callbacks_set_on_invalid_header_callback(
nghttp2_session_callbacks *cbs,
nghttp2_on_invalid_header_callback on_invalid_header_callback) {
cbs->on_invalid_header_callback = on_invalid_header_callback;
}
void nghttp2_session_callbacks_set_on_invalid_header_callback2(
nghttp2_session_callbacks *cbs,
nghttp2_on_invalid_header_callback2 on_invalid_header_callback2) {
cbs->on_invalid_header_callback2 = on_invalid_header_callback2;
}
void nghttp2_session_callbacks_set_select_padding_callback( void nghttp2_session_callbacks_set_select_padding_callback(
nghttp2_session_callbacks *cbs, nghttp2_session_callbacks *cbs,
nghttp2_select_padding_callback select_padding_callback) { nghttp2_select_padding_callback select_padding_callback) {

View File

@@ -92,13 +92,6 @@ struct nghttp2_session_callbacks {
*/ */
nghttp2_on_header_callback on_header_callback; nghttp2_on_header_callback on_header_callback;
nghttp2_on_header_callback2 on_header_callback2; nghttp2_on_header_callback2 on_header_callback2;
/**
* Callback function invoked when a invalid header name/value pair
* is received which is silently ignored if these callbacks are not
* set.
*/
nghttp2_on_invalid_header_callback on_invalid_header_callback;
nghttp2_on_invalid_header_callback2 on_invalid_header_callback2;
/** /**
* Callback function invoked when the library asks application how * Callback function invoked when the library asks application how
* many padding bytes are required for the transmission of the given * many padding bytes are required for the transmission of the given

View File

@@ -1,58 +0,0 @@
/*
* nghttp2 - HTTP/2 C Library
*
* Copyright (c) 2016 Tatsuhiro Tsujikawa
*
* 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.
*/
#include "nghttp2_debug.h"
#include <stdio.h>
#ifdef DEBUGBUILD
static void nghttp2_default_debug_vfprintf_callback(const char *fmt,
va_list args) {
vfprintf(stderr, fmt, args);
}
static nghttp2_debug_vprintf_callback static_debug_vprintf_callback =
nghttp2_default_debug_vfprintf_callback;
void nghttp2_debug_vprintf(const char *format, ...) {
if (static_debug_vprintf_callback) {
va_list args;
va_start(args, format);
static_debug_vprintf_callback(format, args);
va_end(args);
}
}
void nghttp2_set_debug_vprintf_callback(
nghttp2_debug_vprintf_callback debug_vprintf_callback) {
static_debug_vprintf_callback = debug_vprintf_callback;
}
#else /* !DEBUGBUILD */
void nghttp2_set_debug_vprintf_callback(
nghttp2_debug_vprintf_callback debug_vprintf_callback _U_) {}
#endif /* !DEBUGBUILD */

View File

@@ -1,43 +0,0 @@
/*
* nghttp2 - HTTP/2 C Library
*
* Copyright (c) 2016 Tatsuhiro Tsujikawa
*
* 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.
*/
#ifndef NGHTTP2_DEBUG_H
#define NGHTTP2_DEBUG_H
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif /* HAVE_CONFIG_H */
#include <nghttp2/nghttp2.h>
#ifdef DEBUGBUILD
#define DEBUGF(...) nghttp2_debug_vprintf(__VA_ARGS__)
void nghttp2_debug_vprintf(const char *format, ...);
#else
#define DEBUGF(...) \
do { \
} while (0)
#endif
#endif /* NGHTTP2_DEBUG_H */

View File

@@ -32,7 +32,6 @@
#include "nghttp2_helper.h" #include "nghttp2_helper.h"
#include "nghttp2_net.h" #include "nghttp2_net.h"
#include "nghttp2_priority_spec.h" #include "nghttp2_priority_spec.h"
#include "nghttp2_debug.h"
void nghttp2_frame_pack_frame_hd(uint8_t *buf, const nghttp2_frame_hd *hd) { void nghttp2_frame_pack_frame_hd(uint8_t *buf, const nghttp2_frame_hd *hd) {
nghttp2_put_uint32be(&buf[0], (uint32_t)(hd->length << 8)); nghttp2_put_uint32be(&buf[0], (uint32_t)(hd->length << 8));
@@ -253,7 +252,8 @@ static int frame_pack_headers_shared(nghttp2_bufs *bufs,
hd = *frame_hd; hd = *frame_hd;
hd.length = nghttp2_buf_len(buf); hd.length = nghttp2_buf_len(buf);
DEBUGF("send: HEADERS/PUSH_PROMISE, payloadlen=%zu\n", hd.length); DEBUGF(fprintf(stderr, "send: HEADERS/PUSH_PROMISE, payloadlen=%zu\n",
hd.length));
/* We have multiple frame buffers, which means one or more /* We have multiple frame buffers, which means one or more
CONTINUATION frame is involved. Remove END_HEADERS flag from the CONTINUATION frame is involved. Remove END_HEADERS flag from the
@@ -278,7 +278,8 @@ static int frame_pack_headers_shared(nghttp2_bufs *bufs,
hd.length = nghttp2_buf_len(buf); hd.length = nghttp2_buf_len(buf);
DEBUGF("send: int CONTINUATION, payloadlen=%zu\n", hd.length); DEBUGF(fprintf(stderr, "send: int CONTINUATION, payloadlen=%zu\n",
hd.length));
buf->pos -= NGHTTP2_FRAME_HDLEN; buf->pos -= NGHTTP2_FRAME_HDLEN;
nghttp2_frame_pack_frame_hd(buf->pos, &hd); nghttp2_frame_pack_frame_hd(buf->pos, &hd);
@@ -289,7 +290,8 @@ static int frame_pack_headers_shared(nghttp2_bufs *bufs,
/* Set END_HEADERS flag for last CONTINUATION */ /* Set END_HEADERS flag for last CONTINUATION */
hd.flags = NGHTTP2_FLAG_END_HEADERS; hd.flags = NGHTTP2_FLAG_END_HEADERS;
DEBUGF("send: last CONTINUATION, payloadlen=%zu\n", hd.length); DEBUGF(fprintf(stderr, "send: last CONTINUATION, payloadlen=%zu\n",
hd.length));
buf->pos -= NGHTTP2_FRAME_HDLEN; buf->pos -= NGHTTP2_FRAME_HDLEN;
nghttp2_frame_pack_frame_hd(buf->pos, &hd); nghttp2_frame_pack_frame_hd(buf->pos, &hd);
@@ -928,7 +930,7 @@ static void frame_set_pad(nghttp2_buf *buf, size_t padlen, int framehd_only) {
size_t trail_padlen; size_t trail_padlen;
size_t newlen; size_t newlen;
DEBUGF("send: padlen=%zu, shift left 1 bytes\n", padlen); DEBUGF(fprintf(stderr, "send: padlen=%zu, shift left 1 bytes\n", padlen));
memmove(buf->pos - 1, buf->pos, NGHTTP2_FRAME_HDLEN); memmove(buf->pos - 1, buf->pos, NGHTTP2_FRAME_HDLEN);
@@ -958,7 +960,7 @@ int nghttp2_frame_add_pad(nghttp2_bufs *bufs, nghttp2_frame_hd *hd,
nghttp2_buf *buf; nghttp2_buf *buf;
if (padlen == 0) { if (padlen == 0) {
DEBUGF("send: padlen = 0, nothing to do\n"); DEBUGF(fprintf(stderr, "send: padlen = 0, nothing to do\n"));
return 0; return 0;
} }
@@ -992,7 +994,8 @@ int nghttp2_frame_add_pad(nghttp2_bufs *bufs, nghttp2_frame_hd *hd,
hd->length += padlen; hd->length += padlen;
hd->flags |= NGHTTP2_FLAG_PADDED; hd->flags |= NGHTTP2_FLAG_PADDED;
DEBUGF("send: final payloadlen=%zu, padlen=%zu\n", hd->length, padlen); DEBUGF(fprintf(stderr, "send: final payloadlen=%zu, padlen=%zu\n", hd->length,
padlen));
return 0; return 0;
} }

View File

@@ -52,12 +52,14 @@
#define NGHTTP2_FRAMEBUF_CHUNKLEN \ #define NGHTTP2_FRAMEBUF_CHUNKLEN \
(NGHTTP2_FRAME_HDLEN + 1 + NGHTTP2_MAX_PAYLOADLEN) (NGHTTP2_FRAME_HDLEN + 1 + NGHTTP2_MAX_PAYLOADLEN)
/* Number of inbound buffer */
#define NGHTTP2_FRAMEBUF_MAX_NUM 5
/* The default length of DATA frame payload. */ /* The default length of DATA frame payload. */
#define NGHTTP2_DATA_PAYLOADLEN NGHTTP2_MAX_FRAME_SIZE_MIN #define NGHTTP2_DATA_PAYLOADLEN NGHTTP2_MAX_FRAME_SIZE_MIN
/* Maximum headers block size to send, calculated using /* Maximum headers payload length, calculated in compressed form.
nghttp2_hd_deflate_bound(). This is the default value, and can be This applies to transmission only. */
overridden by nghttp2_option_set_max_send_header_block_size(). */
#define NGHTTP2_MAX_HEADERSLEN 65536 #define NGHTTP2_MAX_HEADERSLEN 65536
/* The number of bytes for each SETTINGS entry */ /* The number of bytes for each SETTINGS entry */

File diff suppressed because it is too large Load Diff

View File

@@ -288,7 +288,7 @@ int nghttp2_hd_deflate_init(nghttp2_hd_deflater *deflater, nghttp2_mem *mem);
/* /*
* Initializes |deflater| for deflating name/values pairs. * Initializes |deflater| for deflating name/values pairs.
* *
* The encoder only uses up to |max_deflate_dynamic_table_size| bytes * The encoder only uses up to |deflate_hd_table_bufsize_max| bytes
* for header table even if the larger value is specified later in * for header table even if the larger value is specified later in
* nghttp2_hd_change_table_size(). * nghttp2_hd_change_table_size().
* *
@@ -299,7 +299,7 @@ int nghttp2_hd_deflate_init(nghttp2_hd_deflater *deflater, nghttp2_mem *mem);
* Out of memory. * Out of memory.
*/ */
int nghttp2_hd_deflate_init2(nghttp2_hd_deflater *deflater, int nghttp2_hd_deflate_init2(nghttp2_hd_deflater *deflater,
size_t max_deflate_dynamic_table_size, size_t deflate_hd_table_bufsize_max,
nghttp2_mem *mem); nghttp2_mem *mem);
/* /*
@@ -372,7 +372,7 @@ int nghttp2_hd_emit_table_size(nghttp2_bufs *bufs, size_t table_size);
nghttp2_hd_nv nghttp2_hd_table_get(nghttp2_hd_context *context, size_t index); nghttp2_hd_nv nghttp2_hd_table_get(nghttp2_hd_context *context, size_t index);
/* For unittesting purpose */ /* For unittesting purpose */
ssize_t nghttp2_hd_decode_length(uint32_t *res, size_t *shift_ptr, int *fin, ssize_t nghttp2_hd_decode_length(uint32_t *res, size_t *shift_ptr, int *final,
uint32_t initial, size_t shift, uint8_t *in, uint32_t initial, size_t shift, uint8_t *in,
uint8_t *last, size_t prefix); uint8_t *last, size_t prefix);
@@ -410,8 +410,8 @@ void nghttp2_hd_huff_decode_context_init(nghttp2_hd_huff_decode_context *ctx);
* will be written to |buf|. This function assumes that |buf| has the * will be written to |buf|. This function assumes that |buf| has the
* enough room to store the decoded byte string. * enough room to store the decoded byte string.
* *
* The caller must set the |fin| to nonzero if the given input is the * The caller must set the |final| to nonzero if the given input is
* final block. * the final block.
* *
* This function returns the number of read bytes from the |in|. * This function returns the number of read bytes from the |in|.
* *
@@ -425,6 +425,6 @@ void nghttp2_hd_huff_decode_context_init(nghttp2_hd_huff_decode_context *ctx);
*/ */
ssize_t nghttp2_hd_huff_decode(nghttp2_hd_huff_decode_context *ctx, ssize_t nghttp2_hd_huff_decode(nghttp2_hd_huff_decode_context *ctx,
nghttp2_buf *buf, const uint8_t *src, nghttp2_buf *buf, const uint8_t *src,
size_t srclen, int fin); size_t srclen, int final);
#endif /* NGHTTP2_HD_H */ #endif /* NGHTTP2_HD_H */

View File

@@ -64,44 +64,15 @@ static ssize_t huff_encode_sym(nghttp2_bufs *bufs, size_t *avail_ptr,
code <<= 8 - (nbits & 0x7); code <<= 8 - (nbits & 0x7);
} }
/* we lose at most 3 bytes, but it is not critical in practice */
if (*avail_ptr < (nbits + 7) / 8) { if (*avail_ptr < (nbits + 7) / 8) {
/* slow path */ rv = nghttp2_bufs_advance(bufs);
if (nbits > 24) {
rv = nghttp2_bufs_addb(bufs, (uint8_t)(code >> 24));
if (rv != 0) {
return rv;
}
nbits -= 8;
}
if (nbits > 16) {
rv = nghttp2_bufs_addb(bufs, (uint8_t)(code >> 16));
if (rv != 0) {
return rv;
}
nbits -= 8;
}
if (nbits > 8) {
rv = nghttp2_bufs_addb(bufs, (uint8_t)(code >> 8));
if (rv != 0) {
return rv;
}
nbits -= 8;
}
if (nbits == 8) {
rv = nghttp2_bufs_addb(bufs, (uint8_t)code);
if (rv != 0) {
return rv;
}
*avail_ptr = nghttp2_bufs_cur_avail(bufs);
return 8;
}
rv = nghttp2_bufs_addb_hold(bufs, (uint8_t)code);
if (rv != 0) { if (rv != 0) {
return rv; return rv;
} }
*avail_ptr = nghttp2_bufs_cur_avail(bufs); *avail_ptr = nghttp2_bufs_cur_avail(bufs);
return (ssize_t)(8 - nbits); /* we assume that we at least 3 buffer space available */
assert(*avail_ptr >= 3);
} }
/* fast path, since most code is less than 8 */ /* fast path, since most code is less than 8 */

File diff suppressed because it is too large Load Diff

View File

@@ -189,8 +189,8 @@ int nghttp2_adjust_local_window_size(int32_t *local_window_size_ptr,
account it in *delta_ptr. */ account it in *delta_ptr. */
*recv_window_size_ptr = recv_reduction_delta; *recv_window_size_ptr = recv_reduction_delta;
} }
/* recv_reduction_delta must be paid from *delta_ptr, since it was /* recv_reduction_delta must be paied from *delta_ptr, since it
added in window size reduction (see below). */ was added in window size reduction (see below). */
*delta_ptr -= recv_reduction_delta; *delta_ptr -= recv_reduction_delta;
return 0; return 0;
@@ -213,38 +213,6 @@ int nghttp2_adjust_local_window_size(int32_t *local_window_size_ptr,
return 0; return 0;
} }
int nghttp2_increase_local_window_size(int32_t *local_window_size_ptr,
int32_t *recv_window_size_ptr,
int32_t *recv_reduction_ptr,
int32_t *delta_ptr) {
int32_t recv_reduction_delta;
int32_t delta;
delta = *delta_ptr;
assert(delta >= 0);
/* The delta size is strictly more than received bytes. Increase
local_window_size by that difference |delta|. */
if (*local_window_size_ptr > NGHTTP2_MAX_WINDOW_SIZE - delta) {
return NGHTTP2_ERR_FLOW_CONTROL;
}
*local_window_size_ptr += delta;
/* If there is recv_reduction due to earlier window_size
reduction, we have to adjust it too. */
recv_reduction_delta = nghttp2_min(*recv_reduction_ptr, delta);
*recv_reduction_ptr -= recv_reduction_delta;
*recv_window_size_ptr += recv_reduction_delta;
/* recv_reduction_delta must be paid from *delta_ptr, since it was
added in window size reduction (see below). */
*delta_ptr -= recv_reduction_delta;
return 0;
}
int nghttp2_should_send_window_update(int32_t local_window_size, int nghttp2_should_send_window_update(int32_t local_window_size,
int32_t recv_window_size) { int32_t recv_window_size) {
return recv_window_size > 0 && recv_window_size >= local_window_size / 2; return recv_window_size > 0 && recv_window_size >= local_window_size / 2;
@@ -338,70 +306,58 @@ const char *nghttp2_strerror(int error_code) {
/* Generated by gennmchartbl.py */ /* Generated by gennmchartbl.py */
static int VALID_HD_NAME_CHARS[] = { static int VALID_HD_NAME_CHARS[] = {
0 /* NUL */, 0 /* SOH */, 0 /* STX */, 0 /* ETX */, 0 /* NUL */, 0 /* SOH */, 0 /* STX */, 0 /* ETX */, 0 /* EOT */,
0 /* EOT */, 0 /* ENQ */, 0 /* ACK */, 0 /* BEL */, 0 /* ENQ */, 0 /* ACK */, 0 /* BEL */, 0 /* BS */, 0 /* HT */,
0 /* BS */, 0 /* HT */, 0 /* LF */, 0 /* VT */, 0 /* LF */, 0 /* VT */, 0 /* FF */, 0 /* CR */, 0 /* SO */,
0 /* FF */, 0 /* CR */, 0 /* SO */, 0 /* SI */, 0 /* SI */, 0 /* DLE */, 0 /* DC1 */, 0 /* DC2 */, 0 /* DC3 */,
0 /* DLE */, 0 /* DC1 */, 0 /* DC2 */, 0 /* DC3 */, 0 /* DC4 */, 0 /* NAK */, 0 /* SYN */, 0 /* ETB */, 0 /* CAN */,
0 /* DC4 */, 0 /* NAK */, 0 /* SYN */, 0 /* ETB */, 0 /* EM */, 0 /* SUB */, 0 /* ESC */, 0 /* FS */, 0 /* GS */,
0 /* CAN */, 0 /* EM */, 0 /* SUB */, 0 /* ESC */, 0 /* RS */, 0 /* US */, 0 /* SPC */, 1 /* ! */, 0 /* " */,
0 /* FS */, 0 /* GS */, 0 /* RS */, 0 /* US */, 1 /* # */, 1 /* $ */, 1 /* % */, 1 /* & */, 1 /* ' */,
0 /* SPC */, 1 /* ! */, 0 /* " */, 1 /* # */, 0 /* ( */, 0 /* ) */, 1 /* * */, 1 /* + */, 0 /* , */,
1 /* $ */, 1 /* % */, 1 /* & */, 1 /* ' */, 1 /* - */, 1 /* . */, 0 /* / */, 1 /* 0 */, 1 /* 1 */,
0 /* ( */, 0 /* ) */, 1 /* * */, 1 /* + */, 1 /* 2 */, 1 /* 3 */, 1 /* 4 */, 1 /* 5 */, 1 /* 6 */,
0 /* , */, 1 /* - */, 1 /* . */, 0 /* / */, 1 /* 7 */, 1 /* 8 */, 1 /* 9 */, 0 /* : */, 0 /* ; */,
1 /* 0 */, 1 /* 1 */, 1 /* 2 */, 1 /* 3 */, 0 /* < */, 0 /* = */, 0 /* > */, 0 /* ? */, 0 /* @ */,
1 /* 4 */, 1 /* 5 */, 1 /* 6 */, 1 /* 7 */, 0 /* A */, 0 /* B */, 0 /* C */, 0 /* D */, 0 /* E */,
1 /* 8 */, 1 /* 9 */, 0 /* : */, 0 /* ; */, 0 /* F */, 0 /* G */, 0 /* H */, 0 /* I */, 0 /* J */,
0 /* < */, 0 /* = */, 0 /* > */, 0 /* ? */, 0 /* K */, 0 /* L */, 0 /* M */, 0 /* N */, 0 /* O */,
0 /* @ */, 0 /* A */, 0 /* B */, 0 /* C */, 0 /* P */, 0 /* Q */, 0 /* R */, 0 /* S */, 0 /* T */,
0 /* D */, 0 /* E */, 0 /* F */, 0 /* G */, 0 /* U */, 0 /* V */, 0 /* W */, 0 /* X */, 0 /* Y */,
0 /* H */, 0 /* I */, 0 /* J */, 0 /* K */, 0 /* Z */, 0 /* [ */, 0 /* \ */, 0 /* ] */, 1 /* ^ */,
0 /* L */, 0 /* M */, 0 /* N */, 0 /* O */, 1 /* _ */, 1 /* ` */, 1 /* a */, 1 /* b */, 1 /* c */,
0 /* P */, 0 /* Q */, 0 /* R */, 0 /* S */, 1 /* d */, 1 /* e */, 1 /* f */, 1 /* g */, 1 /* h */,
0 /* T */, 0 /* U */, 0 /* V */, 0 /* W */, 1 /* i */, 1 /* j */, 1 /* k */, 1 /* l */, 1 /* m */,
0 /* X */, 0 /* Y */, 0 /* Z */, 0 /* [ */, 1 /* n */, 1 /* o */, 1 /* p */, 1 /* q */, 1 /* r */,
0 /* \ */, 0 /* ] */, 1 /* ^ */, 1 /* _ */, 1 /* s */, 1 /* t */, 1 /* u */, 1 /* v */, 1 /* w */,
1 /* ` */, 1 /* a */, 1 /* b */, 1 /* c */, 1 /* x */, 1 /* y */, 1 /* z */, 0 /* { */, 1 /* | */,
1 /* d */, 1 /* e */, 1 /* f */, 1 /* g */, 0 /* } */, 1 /* ~ */, 0 /* DEL */, 0 /* 0x80 */, 0 /* 0x81 */,
1 /* h */, 1 /* i */, 1 /* j */, 1 /* k */, 0 /* 0x82 */, 0 /* 0x83 */, 0 /* 0x84 */, 0 /* 0x85 */, 0 /* 0x86 */,
1 /* l */, 1 /* m */, 1 /* n */, 1 /* o */, 0 /* 0x87 */, 0 /* 0x88 */, 0 /* 0x89 */, 0 /* 0x8a */, 0 /* 0x8b */,
1 /* p */, 1 /* q */, 1 /* r */, 1 /* s */, 0 /* 0x8c */, 0 /* 0x8d */, 0 /* 0x8e */, 0 /* 0x8f */, 0 /* 0x90 */,
1 /* t */, 1 /* u */, 1 /* v */, 1 /* w */, 0 /* 0x91 */, 0 /* 0x92 */, 0 /* 0x93 */, 0 /* 0x94 */, 0 /* 0x95 */,
1 /* x */, 1 /* y */, 1 /* z */, 0 /* { */, 0 /* 0x96 */, 0 /* 0x97 */, 0 /* 0x98 */, 0 /* 0x99 */, 0 /* 0x9a */,
1 /* | */, 0 /* } */, 1 /* ~ */, 0 /* DEL */, 0 /* 0x9b */, 0 /* 0x9c */, 0 /* 0x9d */, 0 /* 0x9e */, 0 /* 0x9f */,
0 /* 0x80 */, 0 /* 0x81 */, 0 /* 0x82 */, 0 /* 0x83 */, 0 /* 0xa0 */, 0 /* 0xa1 */, 0 /* 0xa2 */, 0 /* 0xa3 */, 0 /* 0xa4 */,
0 /* 0x84 */, 0 /* 0x85 */, 0 /* 0x86 */, 0 /* 0x87 */, 0 /* 0xa5 */, 0 /* 0xa6 */, 0 /* 0xa7 */, 0 /* 0xa8 */, 0 /* 0xa9 */,
0 /* 0x88 */, 0 /* 0x89 */, 0 /* 0x8a */, 0 /* 0x8b */, 0 /* 0xaa */, 0 /* 0xab */, 0 /* 0xac */, 0 /* 0xad */, 0 /* 0xae */,
0 /* 0x8c */, 0 /* 0x8d */, 0 /* 0x8e */, 0 /* 0x8f */, 0 /* 0xaf */, 0 /* 0xb0 */, 0 /* 0xb1 */, 0 /* 0xb2 */, 0 /* 0xb3 */,
0 /* 0x90 */, 0 /* 0x91 */, 0 /* 0x92 */, 0 /* 0x93 */, 0 /* 0xb4 */, 0 /* 0xb5 */, 0 /* 0xb6 */, 0 /* 0xb7 */, 0 /* 0xb8 */,
0 /* 0x94 */, 0 /* 0x95 */, 0 /* 0x96 */, 0 /* 0x97 */, 0 /* 0xb9 */, 0 /* 0xba */, 0 /* 0xbb */, 0 /* 0xbc */, 0 /* 0xbd */,
0 /* 0x98 */, 0 /* 0x99 */, 0 /* 0x9a */, 0 /* 0x9b */, 0 /* 0xbe */, 0 /* 0xbf */, 0 /* 0xc0 */, 0 /* 0xc1 */, 0 /* 0xc2 */,
0 /* 0x9c */, 0 /* 0x9d */, 0 /* 0x9e */, 0 /* 0x9f */, 0 /* 0xc3 */, 0 /* 0xc4 */, 0 /* 0xc5 */, 0 /* 0xc6 */, 0 /* 0xc7 */,
0 /* 0xa0 */, 0 /* 0xa1 */, 0 /* 0xa2 */, 0 /* 0xa3 */, 0 /* 0xc8 */, 0 /* 0xc9 */, 0 /* 0xca */, 0 /* 0xcb */, 0 /* 0xcc */,
0 /* 0xa4 */, 0 /* 0xa5 */, 0 /* 0xa6 */, 0 /* 0xa7 */, 0 /* 0xcd */, 0 /* 0xce */, 0 /* 0xcf */, 0 /* 0xd0 */, 0 /* 0xd1 */,
0 /* 0xa8 */, 0 /* 0xa9 */, 0 /* 0xaa */, 0 /* 0xab */, 0 /* 0xd2 */, 0 /* 0xd3 */, 0 /* 0xd4 */, 0 /* 0xd5 */, 0 /* 0xd6 */,
0 /* 0xac */, 0 /* 0xad */, 0 /* 0xae */, 0 /* 0xaf */, 0 /* 0xd7 */, 0 /* 0xd8 */, 0 /* 0xd9 */, 0 /* 0xda */, 0 /* 0xdb */,
0 /* 0xb0 */, 0 /* 0xb1 */, 0 /* 0xb2 */, 0 /* 0xb3 */, 0 /* 0xdc */, 0 /* 0xdd */, 0 /* 0xde */, 0 /* 0xdf */, 0 /* 0xe0 */,
0 /* 0xb4 */, 0 /* 0xb5 */, 0 /* 0xb6 */, 0 /* 0xb7 */, 0 /* 0xe1 */, 0 /* 0xe2 */, 0 /* 0xe3 */, 0 /* 0xe4 */, 0 /* 0xe5 */,
0 /* 0xb8 */, 0 /* 0xb9 */, 0 /* 0xba */, 0 /* 0xbb */, 0 /* 0xe6 */, 0 /* 0xe7 */, 0 /* 0xe8 */, 0 /* 0xe9 */, 0 /* 0xea */,
0 /* 0xbc */, 0 /* 0xbd */, 0 /* 0xbe */, 0 /* 0xbf */, 0 /* 0xeb */, 0 /* 0xec */, 0 /* 0xed */, 0 /* 0xee */, 0 /* 0xef */,
0 /* 0xc0 */, 0 /* 0xc1 */, 0 /* 0xc2 */, 0 /* 0xc3 */, 0 /* 0xf0 */, 0 /* 0xf1 */, 0 /* 0xf2 */, 0 /* 0xf3 */, 0 /* 0xf4 */,
0 /* 0xc4 */, 0 /* 0xc5 */, 0 /* 0xc6 */, 0 /* 0xc7 */, 0 /* 0xf5 */, 0 /* 0xf6 */, 0 /* 0xf7 */, 0 /* 0xf8 */, 0 /* 0xf9 */,
0 /* 0xc8 */, 0 /* 0xc9 */, 0 /* 0xca */, 0 /* 0xcb */, 0 /* 0xfa */, 0 /* 0xfb */, 0 /* 0xfc */, 0 /* 0xfd */, 0 /* 0xfe */,
0 /* 0xcc */, 0 /* 0xcd */, 0 /* 0xce */, 0 /* 0xcf */, 0 /* 0xff */
0 /* 0xd0 */, 0 /* 0xd1 */, 0 /* 0xd2 */, 0 /* 0xd3 */,
0 /* 0xd4 */, 0 /* 0xd5 */, 0 /* 0xd6 */, 0 /* 0xd7 */,
0 /* 0xd8 */, 0 /* 0xd9 */, 0 /* 0xda */, 0 /* 0xdb */,
0 /* 0xdc */, 0 /* 0xdd */, 0 /* 0xde */, 0 /* 0xdf */,
0 /* 0xe0 */, 0 /* 0xe1 */, 0 /* 0xe2 */, 0 /* 0xe3 */,
0 /* 0xe4 */, 0 /* 0xe5 */, 0 /* 0xe6 */, 0 /* 0xe7 */,
0 /* 0xe8 */, 0 /* 0xe9 */, 0 /* 0xea */, 0 /* 0xeb */,
0 /* 0xec */, 0 /* 0xed */, 0 /* 0xee */, 0 /* 0xef */,
0 /* 0xf0 */, 0 /* 0xf1 */, 0 /* 0xf2 */, 0 /* 0xf3 */,
0 /* 0xf4 */, 0 /* 0xf5 */, 0 /* 0xf6 */, 0 /* 0xf7 */,
0 /* 0xf8 */, 0 /* 0xf9 */, 0 /* 0xfa */, 0 /* 0xfb */,
0 /* 0xfc */, 0 /* 0xfd */, 0 /* 0xfe */, 0 /* 0xff */
}; };
int nghttp2_check_header_name(const uint8_t *name, size_t len) { int nghttp2_check_header_name(const uint8_t *name, size_t len) {
@@ -426,70 +382,58 @@ int nghttp2_check_header_name(const uint8_t *name, size_t len) {
/* Generated by genvchartbl.py */ /* Generated by genvchartbl.py */
static int VALID_HD_VALUE_CHARS[] = { static int VALID_HD_VALUE_CHARS[] = {
0 /* NUL */, 0 /* SOH */, 0 /* STX */, 0 /* ETX */, 0 /* NUL */, 0 /* SOH */, 0 /* STX */, 0 /* ETX */, 0 /* EOT */,
0 /* EOT */, 0 /* ENQ */, 0 /* ACK */, 0 /* BEL */, 0 /* ENQ */, 0 /* ACK */, 0 /* BEL */, 0 /* BS */, 1 /* HT */,
0 /* BS */, 1 /* HT */, 0 /* LF */, 0 /* VT */, 0 /* LF */, 0 /* VT */, 0 /* FF */, 0 /* CR */, 0 /* SO */,
0 /* FF */, 0 /* CR */, 0 /* SO */, 0 /* SI */, 0 /* SI */, 0 /* DLE */, 0 /* DC1 */, 0 /* DC2 */, 0 /* DC3 */,
0 /* DLE */, 0 /* DC1 */, 0 /* DC2 */, 0 /* DC3 */, 0 /* DC4 */, 0 /* NAK */, 0 /* SYN */, 0 /* ETB */, 0 /* CAN */,
0 /* DC4 */, 0 /* NAK */, 0 /* SYN */, 0 /* ETB */, 0 /* EM */, 0 /* SUB */, 0 /* ESC */, 0 /* FS */, 0 /* GS */,
0 /* CAN */, 0 /* EM */, 0 /* SUB */, 0 /* ESC */, 0 /* RS */, 0 /* US */, 1 /* SPC */, 1 /* ! */, 1 /* " */,
0 /* FS */, 0 /* GS */, 0 /* RS */, 0 /* US */, 1 /* # */, 1 /* $ */, 1 /* % */, 1 /* & */, 1 /* ' */,
1 /* SPC */, 1 /* ! */, 1 /* " */, 1 /* # */, 1 /* ( */, 1 /* ) */, 1 /* * */, 1 /* + */, 1 /* , */,
1 /* $ */, 1 /* % */, 1 /* & */, 1 /* ' */, 1 /* - */, 1 /* . */, 1 /* / */, 1 /* 0 */, 1 /* 1 */,
1 /* ( */, 1 /* ) */, 1 /* * */, 1 /* + */, 1 /* 2 */, 1 /* 3 */, 1 /* 4 */, 1 /* 5 */, 1 /* 6 */,
1 /* , */, 1 /* - */, 1 /* . */, 1 /* / */, 1 /* 7 */, 1 /* 8 */, 1 /* 9 */, 1 /* : */, 1 /* ; */,
1 /* 0 */, 1 /* 1 */, 1 /* 2 */, 1 /* 3 */, 1 /* < */, 1 /* = */, 1 /* > */, 1 /* ? */, 1 /* @ */,
1 /* 4 */, 1 /* 5 */, 1 /* 6 */, 1 /* 7 */, 1 /* A */, 1 /* B */, 1 /* C */, 1 /* D */, 1 /* E */,
1 /* 8 */, 1 /* 9 */, 1 /* : */, 1 /* ; */, 1 /* F */, 1 /* G */, 1 /* H */, 1 /* I */, 1 /* J */,
1 /* < */, 1 /* = */, 1 /* > */, 1 /* ? */, 1 /* K */, 1 /* L */, 1 /* M */, 1 /* N */, 1 /* O */,
1 /* @ */, 1 /* A */, 1 /* B */, 1 /* C */, 1 /* P */, 1 /* Q */, 1 /* R */, 1 /* S */, 1 /* T */,
1 /* D */, 1 /* E */, 1 /* F */, 1 /* G */, 1 /* U */, 1 /* V */, 1 /* W */, 1 /* X */, 1 /* Y */,
1 /* H */, 1 /* I */, 1 /* J */, 1 /* K */, 1 /* Z */, 1 /* [ */, 1 /* \ */, 1 /* ] */, 1 /* ^ */,
1 /* L */, 1 /* M */, 1 /* N */, 1 /* O */, 1 /* _ */, 1 /* ` */, 1 /* a */, 1 /* b */, 1 /* c */,
1 /* P */, 1 /* Q */, 1 /* R */, 1 /* S */, 1 /* d */, 1 /* e */, 1 /* f */, 1 /* g */, 1 /* h */,
1 /* T */, 1 /* U */, 1 /* V */, 1 /* W */, 1 /* i */, 1 /* j */, 1 /* k */, 1 /* l */, 1 /* m */,
1 /* X */, 1 /* Y */, 1 /* Z */, 1 /* [ */, 1 /* n */, 1 /* o */, 1 /* p */, 1 /* q */, 1 /* r */,
1 /* \ */, 1 /* ] */, 1 /* ^ */, 1 /* _ */, 1 /* s */, 1 /* t */, 1 /* u */, 1 /* v */, 1 /* w */,
1 /* ` */, 1 /* a */, 1 /* b */, 1 /* c */, 1 /* x */, 1 /* y */, 1 /* z */, 1 /* { */, 1 /* | */,
1 /* d */, 1 /* e */, 1 /* f */, 1 /* g */, 1 /* } */, 1 /* ~ */, 0 /* DEL */, 1 /* 0x80 */, 1 /* 0x81 */,
1 /* h */, 1 /* i */, 1 /* j */, 1 /* k */, 1 /* 0x82 */, 1 /* 0x83 */, 1 /* 0x84 */, 1 /* 0x85 */, 1 /* 0x86 */,
1 /* l */, 1 /* m */, 1 /* n */, 1 /* o */, 1 /* 0x87 */, 1 /* 0x88 */, 1 /* 0x89 */, 1 /* 0x8a */, 1 /* 0x8b */,
1 /* p */, 1 /* q */, 1 /* r */, 1 /* s */, 1 /* 0x8c */, 1 /* 0x8d */, 1 /* 0x8e */, 1 /* 0x8f */, 1 /* 0x90 */,
1 /* t */, 1 /* u */, 1 /* v */, 1 /* w */, 1 /* 0x91 */, 1 /* 0x92 */, 1 /* 0x93 */, 1 /* 0x94 */, 1 /* 0x95 */,
1 /* x */, 1 /* y */, 1 /* z */, 1 /* { */, 1 /* 0x96 */, 1 /* 0x97 */, 1 /* 0x98 */, 1 /* 0x99 */, 1 /* 0x9a */,
1 /* | */, 1 /* } */, 1 /* ~ */, 0 /* DEL */, 1 /* 0x9b */, 1 /* 0x9c */, 1 /* 0x9d */, 1 /* 0x9e */, 1 /* 0x9f */,
1 /* 0x80 */, 1 /* 0x81 */, 1 /* 0x82 */, 1 /* 0x83 */, 1 /* 0xa0 */, 1 /* 0xa1 */, 1 /* 0xa2 */, 1 /* 0xa3 */, 1 /* 0xa4 */,
1 /* 0x84 */, 1 /* 0x85 */, 1 /* 0x86 */, 1 /* 0x87 */, 1 /* 0xa5 */, 1 /* 0xa6 */, 1 /* 0xa7 */, 1 /* 0xa8 */, 1 /* 0xa9 */,
1 /* 0x88 */, 1 /* 0x89 */, 1 /* 0x8a */, 1 /* 0x8b */, 1 /* 0xaa */, 1 /* 0xab */, 1 /* 0xac */, 1 /* 0xad */, 1 /* 0xae */,
1 /* 0x8c */, 1 /* 0x8d */, 1 /* 0x8e */, 1 /* 0x8f */, 1 /* 0xaf */, 1 /* 0xb0 */, 1 /* 0xb1 */, 1 /* 0xb2 */, 1 /* 0xb3 */,
1 /* 0x90 */, 1 /* 0x91 */, 1 /* 0x92 */, 1 /* 0x93 */, 1 /* 0xb4 */, 1 /* 0xb5 */, 1 /* 0xb6 */, 1 /* 0xb7 */, 1 /* 0xb8 */,
1 /* 0x94 */, 1 /* 0x95 */, 1 /* 0x96 */, 1 /* 0x97 */, 1 /* 0xb9 */, 1 /* 0xba */, 1 /* 0xbb */, 1 /* 0xbc */, 1 /* 0xbd */,
1 /* 0x98 */, 1 /* 0x99 */, 1 /* 0x9a */, 1 /* 0x9b */, 1 /* 0xbe */, 1 /* 0xbf */, 1 /* 0xc0 */, 1 /* 0xc1 */, 1 /* 0xc2 */,
1 /* 0x9c */, 1 /* 0x9d */, 1 /* 0x9e */, 1 /* 0x9f */, 1 /* 0xc3 */, 1 /* 0xc4 */, 1 /* 0xc5 */, 1 /* 0xc6 */, 1 /* 0xc7 */,
1 /* 0xa0 */, 1 /* 0xa1 */, 1 /* 0xa2 */, 1 /* 0xa3 */, 1 /* 0xc8 */, 1 /* 0xc9 */, 1 /* 0xca */, 1 /* 0xcb */, 1 /* 0xcc */,
1 /* 0xa4 */, 1 /* 0xa5 */, 1 /* 0xa6 */, 1 /* 0xa7 */, 1 /* 0xcd */, 1 /* 0xce */, 1 /* 0xcf */, 1 /* 0xd0 */, 1 /* 0xd1 */,
1 /* 0xa8 */, 1 /* 0xa9 */, 1 /* 0xaa */, 1 /* 0xab */, 1 /* 0xd2 */, 1 /* 0xd3 */, 1 /* 0xd4 */, 1 /* 0xd5 */, 1 /* 0xd6 */,
1 /* 0xac */, 1 /* 0xad */, 1 /* 0xae */, 1 /* 0xaf */, 1 /* 0xd7 */, 1 /* 0xd8 */, 1 /* 0xd9 */, 1 /* 0xda */, 1 /* 0xdb */,
1 /* 0xb0 */, 1 /* 0xb1 */, 1 /* 0xb2 */, 1 /* 0xb3 */, 1 /* 0xdc */, 1 /* 0xdd */, 1 /* 0xde */, 1 /* 0xdf */, 1 /* 0xe0 */,
1 /* 0xb4 */, 1 /* 0xb5 */, 1 /* 0xb6 */, 1 /* 0xb7 */, 1 /* 0xe1 */, 1 /* 0xe2 */, 1 /* 0xe3 */, 1 /* 0xe4 */, 1 /* 0xe5 */,
1 /* 0xb8 */, 1 /* 0xb9 */, 1 /* 0xba */, 1 /* 0xbb */, 1 /* 0xe6 */, 1 /* 0xe7 */, 1 /* 0xe8 */, 1 /* 0xe9 */, 1 /* 0xea */,
1 /* 0xbc */, 1 /* 0xbd */, 1 /* 0xbe */, 1 /* 0xbf */, 1 /* 0xeb */, 1 /* 0xec */, 1 /* 0xed */, 1 /* 0xee */, 1 /* 0xef */,
1 /* 0xc0 */, 1 /* 0xc1 */, 1 /* 0xc2 */, 1 /* 0xc3 */, 1 /* 0xf0 */, 1 /* 0xf1 */, 1 /* 0xf2 */, 1 /* 0xf3 */, 1 /* 0xf4 */,
1 /* 0xc4 */, 1 /* 0xc5 */, 1 /* 0xc6 */, 1 /* 0xc7 */, 1 /* 0xf5 */, 1 /* 0xf6 */, 1 /* 0xf7 */, 1 /* 0xf8 */, 1 /* 0xf9 */,
1 /* 0xc8 */, 1 /* 0xc9 */, 1 /* 0xca */, 1 /* 0xcb */, 1 /* 0xfa */, 1 /* 0xfb */, 1 /* 0xfc */, 1 /* 0xfd */, 1 /* 0xfe */,
1 /* 0xcc */, 1 /* 0xcd */, 1 /* 0xce */, 1 /* 0xcf */, 1 /* 0xff */
1 /* 0xd0 */, 1 /* 0xd1 */, 1 /* 0xd2 */, 1 /* 0xd3 */,
1 /* 0xd4 */, 1 /* 0xd5 */, 1 /* 0xd6 */, 1 /* 0xd7 */,
1 /* 0xd8 */, 1 /* 0xd9 */, 1 /* 0xda */, 1 /* 0xdb */,
1 /* 0xdc */, 1 /* 0xdd */, 1 /* 0xde */, 1 /* 0xdf */,
1 /* 0xe0 */, 1 /* 0xe1 */, 1 /* 0xe2 */, 1 /* 0xe3 */,
1 /* 0xe4 */, 1 /* 0xe5 */, 1 /* 0xe6 */, 1 /* 0xe7 */,
1 /* 0xe8 */, 1 /* 0xe9 */, 1 /* 0xea */, 1 /* 0xeb */,
1 /* 0xec */, 1 /* 0xed */, 1 /* 0xee */, 1 /* 0xef */,
1 /* 0xf0 */, 1 /* 0xf1 */, 1 /* 0xf2 */, 1 /* 0xf3 */,
1 /* 0xf4 */, 1 /* 0xf5 */, 1 /* 0xf6 */, 1 /* 0xf7 */,
1 /* 0xf8 */, 1 /* 0xf9 */, 1 /* 0xfa */, 1 /* 0xfb */,
1 /* 0xfc */, 1 /* 0xfd */, 1 /* 0xfe */, 1 /* 0xff */
}; };
int nghttp2_check_header_value(const uint8_t *value, size_t len) { int nghttp2_check_header_value(const uint8_t *value, size_t len) {

View File

@@ -89,22 +89,6 @@ int nghttp2_adjust_local_window_size(int32_t *local_window_size_ptr,
int32_t *recv_reduction_ptr, int32_t *recv_reduction_ptr,
int32_t *delta_ptr); int32_t *delta_ptr);
/*
* This function works like nghttp2_adjust_local_window_size(). The
* difference is that this function assumes *delta_ptr >= 0, and
* *recv_window_size_ptr is not decreased by *delta_ptr.
*
* This function returns 0 if it succeeds, or one of the following
* negative error codes:
*
* NGHTTP2_ERR_FLOW_CONTROL
* local_window_size overflow or gets negative.
*/
int nghttp2_increase_local_window_size(int32_t *local_window_size_ptr,
int32_t *recv_window_size_ptr,
int32_t *recv_reduction_ptr,
int32_t *delta_ptr);
/* /*
* Returns non-zero if the function decided that WINDOW_UPDATE should * Returns non-zero if the function decided that WINDOW_UPDATE should
* be sent. * be sent.

View File

@@ -286,70 +286,58 @@ static int http_response_on_header(nghttp2_stream *stream, nghttp2_hd_nv *nv,
/* Generated by genauthroitychartbl.py */ /* Generated by genauthroitychartbl.py */
static char VALID_AUTHORITY_CHARS[] = { static char VALID_AUTHORITY_CHARS[] = {
0 /* NUL */, 0 /* SOH */, 0 /* STX */, 0 /* ETX */, 0 /* NUL */, 0 /* SOH */, 0 /* STX */, 0 /* ETX */, 0 /* EOT */,
0 /* EOT */, 0 /* ENQ */, 0 /* ACK */, 0 /* BEL */, 0 /* ENQ */, 0 /* ACK */, 0 /* BEL */, 0 /* BS */, 0 /* HT */,
0 /* BS */, 0 /* HT */, 0 /* LF */, 0 /* VT */, 0 /* LF */, 0 /* VT */, 0 /* FF */, 0 /* CR */, 0 /* SO */,
0 /* FF */, 0 /* CR */, 0 /* SO */, 0 /* SI */, 0 /* SI */, 0 /* DLE */, 0 /* DC1 */, 0 /* DC2 */, 0 /* DC3 */,
0 /* DLE */, 0 /* DC1 */, 0 /* DC2 */, 0 /* DC3 */, 0 /* DC4 */, 0 /* NAK */, 0 /* SYN */, 0 /* ETB */, 0 /* CAN */,
0 /* DC4 */, 0 /* NAK */, 0 /* SYN */, 0 /* ETB */, 0 /* EM */, 0 /* SUB */, 0 /* ESC */, 0 /* FS */, 0 /* GS */,
0 /* CAN */, 0 /* EM */, 0 /* SUB */, 0 /* ESC */, 0 /* RS */, 0 /* US */, 0 /* SPC */, 1 /* ! */, 0 /* " */,
0 /* FS */, 0 /* GS */, 0 /* RS */, 0 /* US */, 0 /* # */, 1 /* $ */, 1 /* % */, 1 /* & */, 1 /* ' */,
0 /* SPC */, 1 /* ! */, 0 /* " */, 0 /* # */, 1 /* ( */, 1 /* ) */, 1 /* * */, 1 /* + */, 1 /* , */,
1 /* $ */, 1 /* % */, 1 /* & */, 1 /* ' */, 1 /* - */, 1 /* . */, 0 /* / */, 1 /* 0 */, 1 /* 1 */,
1 /* ( */, 1 /* ) */, 1 /* * */, 1 /* + */, 1 /* 2 */, 1 /* 3 */, 1 /* 4 */, 1 /* 5 */, 1 /* 6 */,
1 /* , */, 1 /* - */, 1 /* . */, 0 /* / */, 1 /* 7 */, 1 /* 8 */, 1 /* 9 */, 1 /* : */, 1 /* ; */,
1 /* 0 */, 1 /* 1 */, 1 /* 2 */, 1 /* 3 */, 0 /* < */, 1 /* = */, 0 /* > */, 0 /* ? */, 1 /* @ */,
1 /* 4 */, 1 /* 5 */, 1 /* 6 */, 1 /* 7 */, 1 /* A */, 1 /* B */, 1 /* C */, 1 /* D */, 1 /* E */,
1 /* 8 */, 1 /* 9 */, 1 /* : */, 1 /* ; */, 1 /* F */, 1 /* G */, 1 /* H */, 1 /* I */, 1 /* J */,
0 /* < */, 1 /* = */, 0 /* > */, 0 /* ? */, 1 /* K */, 1 /* L */, 1 /* M */, 1 /* N */, 1 /* O */,
1 /* @ */, 1 /* A */, 1 /* B */, 1 /* C */, 1 /* P */, 1 /* Q */, 1 /* R */, 1 /* S */, 1 /* T */,
1 /* D */, 1 /* E */, 1 /* F */, 1 /* G */, 1 /* U */, 1 /* V */, 1 /* W */, 1 /* X */, 1 /* Y */,
1 /* H */, 1 /* I */, 1 /* J */, 1 /* K */, 1 /* Z */, 1 /* [ */, 0 /* \ */, 1 /* ] */, 0 /* ^ */,
1 /* L */, 1 /* M */, 1 /* N */, 1 /* O */, 1 /* _ */, 0 /* ` */, 1 /* a */, 1 /* b */, 1 /* c */,
1 /* P */, 1 /* Q */, 1 /* R */, 1 /* S */, 1 /* d */, 1 /* e */, 1 /* f */, 1 /* g */, 1 /* h */,
1 /* T */, 1 /* U */, 1 /* V */, 1 /* W */, 1 /* i */, 1 /* j */, 1 /* k */, 1 /* l */, 1 /* m */,
1 /* X */, 1 /* Y */, 1 /* Z */, 1 /* [ */, 1 /* n */, 1 /* o */, 1 /* p */, 1 /* q */, 1 /* r */,
0 /* \ */, 1 /* ] */, 0 /* ^ */, 1 /* _ */, 1 /* s */, 1 /* t */, 1 /* u */, 1 /* v */, 1 /* w */,
0 /* ` */, 1 /* a */, 1 /* b */, 1 /* c */, 1 /* x */, 1 /* y */, 1 /* z */, 0 /* { */, 0 /* | */,
1 /* d */, 1 /* e */, 1 /* f */, 1 /* g */, 0 /* } */, 1 /* ~ */, 0 /* DEL */, 0 /* 0x80 */, 0 /* 0x81 */,
1 /* h */, 1 /* i */, 1 /* j */, 1 /* k */, 0 /* 0x82 */, 0 /* 0x83 */, 0 /* 0x84 */, 0 /* 0x85 */, 0 /* 0x86 */,
1 /* l */, 1 /* m */, 1 /* n */, 1 /* o */, 0 /* 0x87 */, 0 /* 0x88 */, 0 /* 0x89 */, 0 /* 0x8a */, 0 /* 0x8b */,
1 /* p */, 1 /* q */, 1 /* r */, 1 /* s */, 0 /* 0x8c */, 0 /* 0x8d */, 0 /* 0x8e */, 0 /* 0x8f */, 0 /* 0x90 */,
1 /* t */, 1 /* u */, 1 /* v */, 1 /* w */, 0 /* 0x91 */, 0 /* 0x92 */, 0 /* 0x93 */, 0 /* 0x94 */, 0 /* 0x95 */,
1 /* x */, 1 /* y */, 1 /* z */, 0 /* { */, 0 /* 0x96 */, 0 /* 0x97 */, 0 /* 0x98 */, 0 /* 0x99 */, 0 /* 0x9a */,
0 /* | */, 0 /* } */, 1 /* ~ */, 0 /* DEL */, 0 /* 0x9b */, 0 /* 0x9c */, 0 /* 0x9d */, 0 /* 0x9e */, 0 /* 0x9f */,
0 /* 0x80 */, 0 /* 0x81 */, 0 /* 0x82 */, 0 /* 0x83 */, 0 /* 0xa0 */, 0 /* 0xa1 */, 0 /* 0xa2 */, 0 /* 0xa3 */, 0 /* 0xa4 */,
0 /* 0x84 */, 0 /* 0x85 */, 0 /* 0x86 */, 0 /* 0x87 */, 0 /* 0xa5 */, 0 /* 0xa6 */, 0 /* 0xa7 */, 0 /* 0xa8 */, 0 /* 0xa9 */,
0 /* 0x88 */, 0 /* 0x89 */, 0 /* 0x8a */, 0 /* 0x8b */, 0 /* 0xaa */, 0 /* 0xab */, 0 /* 0xac */, 0 /* 0xad */, 0 /* 0xae */,
0 /* 0x8c */, 0 /* 0x8d */, 0 /* 0x8e */, 0 /* 0x8f */, 0 /* 0xaf */, 0 /* 0xb0 */, 0 /* 0xb1 */, 0 /* 0xb2 */, 0 /* 0xb3 */,
0 /* 0x90 */, 0 /* 0x91 */, 0 /* 0x92 */, 0 /* 0x93 */, 0 /* 0xb4 */, 0 /* 0xb5 */, 0 /* 0xb6 */, 0 /* 0xb7 */, 0 /* 0xb8 */,
0 /* 0x94 */, 0 /* 0x95 */, 0 /* 0x96 */, 0 /* 0x97 */, 0 /* 0xb9 */, 0 /* 0xba */, 0 /* 0xbb */, 0 /* 0xbc */, 0 /* 0xbd */,
0 /* 0x98 */, 0 /* 0x99 */, 0 /* 0x9a */, 0 /* 0x9b */, 0 /* 0xbe */, 0 /* 0xbf */, 0 /* 0xc0 */, 0 /* 0xc1 */, 0 /* 0xc2 */,
0 /* 0x9c */, 0 /* 0x9d */, 0 /* 0x9e */, 0 /* 0x9f */, 0 /* 0xc3 */, 0 /* 0xc4 */, 0 /* 0xc5 */, 0 /* 0xc6 */, 0 /* 0xc7 */,
0 /* 0xa0 */, 0 /* 0xa1 */, 0 /* 0xa2 */, 0 /* 0xa3 */, 0 /* 0xc8 */, 0 /* 0xc9 */, 0 /* 0xca */, 0 /* 0xcb */, 0 /* 0xcc */,
0 /* 0xa4 */, 0 /* 0xa5 */, 0 /* 0xa6 */, 0 /* 0xa7 */, 0 /* 0xcd */, 0 /* 0xce */, 0 /* 0xcf */, 0 /* 0xd0 */, 0 /* 0xd1 */,
0 /* 0xa8 */, 0 /* 0xa9 */, 0 /* 0xaa */, 0 /* 0xab */, 0 /* 0xd2 */, 0 /* 0xd3 */, 0 /* 0xd4 */, 0 /* 0xd5 */, 0 /* 0xd6 */,
0 /* 0xac */, 0 /* 0xad */, 0 /* 0xae */, 0 /* 0xaf */, 0 /* 0xd7 */, 0 /* 0xd8 */, 0 /* 0xd9 */, 0 /* 0xda */, 0 /* 0xdb */,
0 /* 0xb0 */, 0 /* 0xb1 */, 0 /* 0xb2 */, 0 /* 0xb3 */, 0 /* 0xdc */, 0 /* 0xdd */, 0 /* 0xde */, 0 /* 0xdf */, 0 /* 0xe0 */,
0 /* 0xb4 */, 0 /* 0xb5 */, 0 /* 0xb6 */, 0 /* 0xb7 */, 0 /* 0xe1 */, 0 /* 0xe2 */, 0 /* 0xe3 */, 0 /* 0xe4 */, 0 /* 0xe5 */,
0 /* 0xb8 */, 0 /* 0xb9 */, 0 /* 0xba */, 0 /* 0xbb */, 0 /* 0xe6 */, 0 /* 0xe7 */, 0 /* 0xe8 */, 0 /* 0xe9 */, 0 /* 0xea */,
0 /* 0xbc */, 0 /* 0xbd */, 0 /* 0xbe */, 0 /* 0xbf */, 0 /* 0xeb */, 0 /* 0xec */, 0 /* 0xed */, 0 /* 0xee */, 0 /* 0xef */,
0 /* 0xc0 */, 0 /* 0xc1 */, 0 /* 0xc2 */, 0 /* 0xc3 */, 0 /* 0xf0 */, 0 /* 0xf1 */, 0 /* 0xf2 */, 0 /* 0xf3 */, 0 /* 0xf4 */,
0 /* 0xc4 */, 0 /* 0xc5 */, 0 /* 0xc6 */, 0 /* 0xc7 */, 0 /* 0xf5 */, 0 /* 0xf6 */, 0 /* 0xf7 */, 0 /* 0xf8 */, 0 /* 0xf9 */,
0 /* 0xc8 */, 0 /* 0xc9 */, 0 /* 0xca */, 0 /* 0xcb */, 0 /* 0xfa */, 0 /* 0xfb */, 0 /* 0xfc */, 0 /* 0xfd */, 0 /* 0xfe */,
0 /* 0xcc */, 0 /* 0xcd */, 0 /* 0xce */, 0 /* 0xcf */, 0 /* 0xff */
0 /* 0xd0 */, 0 /* 0xd1 */, 0 /* 0xd2 */, 0 /* 0xd3 */,
0 /* 0xd4 */, 0 /* 0xd5 */, 0 /* 0xd6 */, 0 /* 0xd7 */,
0 /* 0xd8 */, 0 /* 0xd9 */, 0 /* 0xda */, 0 /* 0xdb */,
0 /* 0xdc */, 0 /* 0xdd */, 0 /* 0xde */, 0 /* 0xdf */,
0 /* 0xe0 */, 0 /* 0xe1 */, 0 /* 0xe2 */, 0 /* 0xe3 */,
0 /* 0xe4 */, 0 /* 0xe5 */, 0 /* 0xe6 */, 0 /* 0xe7 */,
0 /* 0xe8 */, 0 /* 0xe9 */, 0 /* 0xea */, 0 /* 0xeb */,
0 /* 0xec */, 0 /* 0xed */, 0 /* 0xee */, 0 /* 0xef */,
0 /* 0xf0 */, 0 /* 0xf1 */, 0 /* 0xf2 */, 0 /* 0xf3 */,
0 /* 0xf4 */, 0 /* 0xf5 */, 0 /* 0xf6 */, 0 /* 0xf7 */,
0 /* 0xf8 */, 0 /* 0xf9 */, 0 /* 0xfa */, 0 /* 0xfb */,
0 /* 0xfc */, 0 /* 0xfd */, 0 /* 0xfe */, 0 /* 0xff */
}; };
static int check_authority(const uint8_t *value, size_t len) { static int check_authority(const uint8_t *value, size_t len) {

View File

@@ -29,10 +29,16 @@
#include <config.h> #include <config.h>
#endif /* HAVE_CONFIG_H */ #endif /* HAVE_CONFIG_H */
#include <nghttp2/nghttp2.h>
/* Macros, types and constants for internal use */ /* Macros, types and constants for internal use */
#ifdef DEBUGBUILD
#define DEBUGF(x) x
#else
#define DEBUGF(x) \
do { \
} while (0)
#endif
/* "less" function, return nonzero if |lhs| is less than |rhs|. */ /* "less" function, return nonzero if |lhs| is less than |rhs|. */
typedef int (*nghttp2_less)(const void *lhs, const void *rhs); typedef int (*nghttp2_less)(const void *lhs, const void *rhs);

View File

@@ -52,8 +52,8 @@ void nghttp2_mem_free(nghttp2_mem *mem, void *ptr) {
mem->free(ptr, mem->mem_user_data); mem->free(ptr, mem->mem_user_data);
} }
void nghttp2_mem_free2(nghttp2_free free_func, void *ptr, void *mem_user_data) { void nghttp2_mem_free2(nghttp2_free free, void *ptr, void *mem_user_data) {
free_func(ptr, mem_user_data); free(ptr, mem_user_data);
} }
void *nghttp2_mem_calloc(nghttp2_mem *mem, size_t nmemb, size_t size) { void *nghttp2_mem_calloc(nghttp2_mem *mem, size_t nmemb, size_t size) {

View File

@@ -38,7 +38,7 @@ nghttp2_mem *nghttp2_mem_default(void);
|mem|. */ |mem|. */
void *nghttp2_mem_malloc(nghttp2_mem *mem, size_t size); void *nghttp2_mem_malloc(nghttp2_mem *mem, size_t size);
void nghttp2_mem_free(nghttp2_mem *mem, void *ptr); void nghttp2_mem_free(nghttp2_mem *mem, void *ptr);
void nghttp2_mem_free2(nghttp2_free free_func, void *ptr, void *mem_user_data); void nghttp2_mem_free2(nghttp2_free free, void *ptr, void *mem_user_data);
void *nghttp2_mem_calloc(nghttp2_mem *mem, size_t nmemb, size_t size); void *nghttp2_mem_calloc(nghttp2_mem *mem, size_t nmemb, size_t size);
void *nghttp2_mem_realloc(nghttp2_mem *mem, void *ptr, size_t size); void *nghttp2_mem_realloc(nghttp2_mem *mem, void *ptr, size_t size);

View File

@@ -30,7 +30,7 @@ static int select_next_protocol(unsigned char **out, unsigned char *outlen,
const unsigned char *in, unsigned int inlen, const unsigned char *in, unsigned int inlen,
const char *key, unsigned int keylen) { const char *key, unsigned int keylen) {
unsigned int i; unsigned int i;
for (i = 0; i + keylen <= inlen; i += (unsigned int)(in[i] + 1)) { for (i = 0; i + keylen <= inlen; i += (unsigned int)(in [i] + 1)) {
if (memcmp(&in[i], key, keylen) == 0) { if (memcmp(&in[i], key, keylen) == 0) {
*out = (unsigned char *)&in[i + 1]; *out = (unsigned char *)&in[i + 1];
*outlen = in[i]; *outlen = in[i];

View File

@@ -95,15 +95,3 @@ void nghttp2_option_set_no_auto_ping_ack(nghttp2_option *option, int val) {
option->opt_set_mask |= NGHTTP2_OPT_NO_AUTO_PING_ACK; option->opt_set_mask |= NGHTTP2_OPT_NO_AUTO_PING_ACK;
option->no_auto_ping_ack = val; option->no_auto_ping_ack = val;
} }
void nghttp2_option_set_max_send_header_block_length(nghttp2_option *option,
size_t val) {
option->opt_set_mask |= NGHTTP2_OPT_MAX_SEND_HEADER_BLOCK_LENGTH;
option->max_send_header_block_length = val;
}
void nghttp2_option_set_max_deflate_dynamic_table_size(nghttp2_option *option,
size_t val) {
option->opt_set_mask |= NGHTTP2_OPT_MAX_DEFLATE_DYNAMIC_TABLE_SIZE;
option->max_deflate_dynamic_table_size = val;
}

View File

@@ -62,23 +62,13 @@ typedef enum {
NGHTTP2_OPT_MAX_RESERVED_REMOTE_STREAMS = 1 << 4, NGHTTP2_OPT_MAX_RESERVED_REMOTE_STREAMS = 1 << 4,
NGHTTP2_OPT_USER_RECV_EXT_TYPES = 1 << 5, NGHTTP2_OPT_USER_RECV_EXT_TYPES = 1 << 5,
NGHTTP2_OPT_NO_AUTO_PING_ACK = 1 << 6, NGHTTP2_OPT_NO_AUTO_PING_ACK = 1 << 6,
NGHTTP2_OPT_BUILTIN_RECV_EXT_TYPES = 1 << 7, NGHTTP2_OPT_BUILTIN_RECV_EXT_TYPES = 1 << 7
NGHTTP2_OPT_MAX_SEND_HEADER_BLOCK_LENGTH = 1 << 8,
NGHTTP2_OPT_MAX_DEFLATE_DYNAMIC_TABLE_SIZE = 1 << 9,
} nghttp2_option_flag; } nghttp2_option_flag;
/** /**
* Struct to store option values for nghttp2_session. * Struct to store option values for nghttp2_session.
*/ */
struct nghttp2_option { struct nghttp2_option {
/**
* NGHTTP2_OPT_MAX_SEND_HEADER_BLOCK_LENGTH
*/
size_t max_send_header_block_length;
/**
* NGHTTP2_OPT_MAX_DEFLATE_DYNAMIC_TABLE_SIZE
*/
size_t max_deflate_dynamic_table_size;
/** /**
* Bitwise OR of nghttp2_option_flag to determine that which fields * Bitwise OR of nghttp2_option_flag to determine that which fields
* are specified. * are specified.

File diff suppressed because it is too large Load Diff

View File

@@ -97,9 +97,6 @@ typedef struct {
these frames in this number, it is considered suspicious. */ these frames in this number, it is considered suspicious. */
#define NGHTTP2_MAX_OBQ_FLOOD_ITEM 10000 #define NGHTTP2_MAX_OBQ_FLOOD_ITEM 10000
/* The default value of maximum number of concurrent streams. */
#define NGHTTP2_DEFAULT_MAX_CONCURRENT_STREAMS 0xffffffffu
/* Internal state when receiving incoming frame */ /* Internal state when receiving incoming frame */
typedef enum { typedef enum {
/* Receiving frame header */ /* Receiving frame header */
@@ -259,9 +256,6 @@ struct nghttp2_session {
size_t nvbuflen; size_t nvbuflen;
/* Counter for detecting flooding in outbound queue */ /* Counter for detecting flooding in outbound queue */
size_t obq_flood_counter_; size_t obq_flood_counter_;
/* The maximum length of header block to send. Calculated by the
same way as nghttp2_hd_deflate_bound() does. */
size_t max_send_header_block_length;
/* Next Stream ID. Made unsigned int to detect >= (1 << 31). */ /* Next Stream ID. Made unsigned int to detect >= (1 << 31). */
uint32_t next_stream_id; uint32_t next_stream_id;
/* The last stream ID this session initiated. For client session, /* The last stream ID this session initiated. For client session,

View File

@@ -29,7 +29,6 @@
#include "nghttp2_session.h" #include "nghttp2_session.h"
#include "nghttp2_helper.h" #include "nghttp2_helper.h"
#include "nghttp2_debug.h"
/* Maximum distance between any two stream's cycle in the same /* Maximum distance between any two stream's cycle in the same
prirority queue. Imagine stream A's cycle is A, and stream B's prirority queue. Imagine stream A's cycle is A, and stream B's
@@ -153,11 +152,11 @@ static int stream_obq_push(nghttp2_stream *dep_stream, nghttp2_stream *stream) {
stream_next_cycle(stream, dep_stream->descendant_last_cycle); stream_next_cycle(stream, dep_stream->descendant_last_cycle);
stream->seq = dep_stream->descendant_next_seq++; stream->seq = dep_stream->descendant_next_seq++;
DEBUGF("stream: stream=%d obq push cycle=%d\n", stream->stream_id, DEBUGF(fprintf(stderr, "stream: stream=%d obq push cycle=%d\n",
stream->cycle); stream->stream_id, stream->cycle));
DEBUGF("stream: push stream %d to stream %d\n", stream->stream_id, DEBUGF(fprintf(stderr, "stream: push stream %d to stream %d\n",
dep_stream->stream_id); stream->stream_id, dep_stream->stream_id));
rv = nghttp2_pq_push(&dep_stream->obq, &stream->pq_entry); rv = nghttp2_pq_push(&dep_stream->obq, &stream->pq_entry);
if (rv != 0) { if (rv != 0) {
@@ -184,8 +183,8 @@ static void stream_obq_remove(nghttp2_stream *stream) {
} }
for (; dep_stream; stream = dep_stream, dep_stream = dep_stream->dep_prev) { for (; dep_stream; stream = dep_stream, dep_stream = dep_stream->dep_prev) {
DEBUGF("stream: remove stream %d from stream %d\n", stream->stream_id, DEBUGF(fprintf(stderr, "stream: remove stream %d from stream %d\n",
dep_stream->stream_id); stream->stream_id, dep_stream->stream_id));
nghttp2_pq_remove(&dep_stream->obq, &stream->pq_entry); nghttp2_pq_remove(&dep_stream->obq, &stream->pq_entry);
@@ -215,8 +214,8 @@ static int stream_obq_move(nghttp2_stream *dest, nghttp2_stream *src,
return 0; return 0;
} }
DEBUGF("stream: remove stream %d from stream %d (move)\n", stream->stream_id, DEBUGF(fprintf(stderr, "stream: remove stream %d from stream %d (move)\n",
src->stream_id); stream->stream_id, src->stream_id));
nghttp2_pq_remove(&src->obq, &stream->pq_entry); nghttp2_pq_remove(&src->obq, &stream->pq_entry);
stream->queued = 0; stream->queued = 0;
@@ -239,8 +238,8 @@ void nghttp2_stream_reschedule(nghttp2_stream *stream) {
nghttp2_pq_push(&dep_stream->obq, &stream->pq_entry); nghttp2_pq_push(&dep_stream->obq, &stream->pq_entry);
DEBUGF("stream: stream=%d obq resched cycle=%d\n", stream->stream_id, DEBUGF(fprintf(stderr, "stream: stream=%d obq resched cycle=%d\n",
stream->cycle); stream->stream_id, stream->cycle));
dep_stream->last_writelen = stream->last_writelen; dep_stream->last_writelen = stream->last_writelen;
} }
@@ -299,8 +298,8 @@ void nghttp2_stream_change_weight(nghttp2_stream *stream, int32_t weight) {
nghttp2_pq_push(&dep_stream->obq, &stream->pq_entry); nghttp2_pq_push(&dep_stream->obq, &stream->pq_entry);
DEBUGF("stream: stream=%d obq resched cycle=%d\n", stream->stream_id, DEBUGF(fprintf(stderr, "stream: stream=%d obq resched cycle=%d\n",
stream->cycle); stream->stream_id, stream->cycle));
} }
static nghttp2_stream *stream_last_sib(nghttp2_stream *stream) { static nghttp2_stream *stream_last_sib(nghttp2_stream *stream) {
@@ -482,7 +481,8 @@ int nghttp2_stream_attach_item(nghttp2_stream *stream,
assert((stream->flags & NGHTTP2_STREAM_FLAG_DEFERRED_ALL) == 0); assert((stream->flags & NGHTTP2_STREAM_FLAG_DEFERRED_ALL) == 0);
assert(stream->item == NULL); assert(stream->item == NULL);
DEBUGF("stream: stream=%d attach item=%p\n", stream->stream_id, item); DEBUGF(fprintf(stderr, "stream: stream=%d attach item=%p\n",
stream->stream_id, item));
stream->item = item; stream->item = item;
@@ -500,7 +500,8 @@ int nghttp2_stream_attach_item(nghttp2_stream *stream,
} }
int nghttp2_stream_detach_item(nghttp2_stream *stream) { int nghttp2_stream_detach_item(nghttp2_stream *stream) {
DEBUGF("stream: stream=%d detach item=%p\n", stream->stream_id, stream->item); DEBUGF(fprintf(stderr, "stream: stream=%d detach item=%p\n",
stream->stream_id, stream->item));
stream->item = NULL; stream->item = NULL;
stream->flags = (uint8_t)(stream->flags & ~NGHTTP2_STREAM_FLAG_DEFERRED_ALL); stream->flags = (uint8_t)(stream->flags & ~NGHTTP2_STREAM_FLAG_DEFERRED_ALL);
@@ -511,8 +512,8 @@ int nghttp2_stream_detach_item(nghttp2_stream *stream) {
int nghttp2_stream_defer_item(nghttp2_stream *stream, uint8_t flags) { int nghttp2_stream_defer_item(nghttp2_stream *stream, uint8_t flags) {
assert(stream->item); assert(stream->item);
DEBUGF("stream: stream=%d defer item=%p cause=%02x\n", stream->stream_id, DEBUGF(fprintf(stderr, "stream: stream=%d defer item=%p cause=%02x\n",
stream->item, flags); stream->stream_id, stream->item, flags));
stream->flags |= flags; stream->flags |= flags;
@@ -522,8 +523,8 @@ int nghttp2_stream_defer_item(nghttp2_stream *stream, uint8_t flags) {
int nghttp2_stream_resume_deferred_item(nghttp2_stream *stream, uint8_t flags) { int nghttp2_stream_resume_deferred_item(nghttp2_stream *stream, uint8_t flags) {
assert(stream->item); assert(stream->item);
DEBUGF("stream: stream=%d resume item=%p flags=%02x\n", stream->stream_id, DEBUGF(fprintf(stderr, "stream: stream=%d resume item=%p flags=%02x\n",
stream->item, flags); stream->stream_id, stream->item, flags));
stream->flags = (uint8_t)(stream->flags & ~flags); stream->flags = (uint8_t)(stream->flags & ~flags);
@@ -592,8 +593,9 @@ int nghttp2_stream_dep_insert(nghttp2_stream *dep_stream,
nghttp2_stream *si; nghttp2_stream *si;
int rv; int rv;
DEBUGF("stream: dep_insert dep_stream(%p)=%d, stream(%p)=%d\n", dep_stream, DEBUGF(fprintf(stderr,
dep_stream->stream_id, stream, stream->stream_id); "stream: dep_insert dep_stream(%p)=%d, stream(%p)=%d\n",
dep_stream, dep_stream->stream_id, stream, stream->stream_id));
stream->sum_dep_weight = dep_stream->sum_dep_weight; stream->sum_dep_weight = dep_stream->sum_dep_weight;
dep_stream->sum_dep_weight = stream->weight; dep_stream->sum_dep_weight = stream->weight;
@@ -738,8 +740,8 @@ static void unlink_dep(nghttp2_stream *stream) {
void nghttp2_stream_dep_add(nghttp2_stream *dep_stream, void nghttp2_stream_dep_add(nghttp2_stream *dep_stream,
nghttp2_stream *stream) { nghttp2_stream *stream) {
DEBUGF("stream: dep_add dep_stream(%p)=%d, stream(%p)=%d\n", dep_stream, DEBUGF(fprintf(stderr, "stream: dep_add dep_stream(%p)=%d, stream(%p)=%d\n",
dep_stream->stream_id, stream, stream->stream_id); dep_stream, dep_stream->stream_id, stream, stream->stream_id));
dep_stream->sum_dep_weight += stream->weight; dep_stream->sum_dep_weight += stream->weight;
@@ -757,7 +759,8 @@ int nghttp2_stream_dep_remove(nghttp2_stream *stream) {
int32_t sum_dep_weight_delta; int32_t sum_dep_weight_delta;
int rv; int rv;
DEBUGF("stream: dep_remove stream(%p)=%d\n", stream, stream->stream_id); DEBUGF(fprintf(stderr, "stream: dep_remove stream(%p)=%d\n", stream,
stream->stream_id));
/* Distribute weight of |stream| to direct descendants */ /* Distribute weight of |stream| to direct descendants */
sum_dep_weight_delta = -stream->weight; sum_dep_weight_delta = -stream->weight;
@@ -810,8 +813,9 @@ int nghttp2_stream_dep_insert_subtree(nghttp2_stream *dep_stream,
nghttp2_stream *si; nghttp2_stream *si;
int rv; int rv;
DEBUGF("stream: dep_insert_subtree dep_stream(%p)=%d stream(%p)=%d\n", DEBUGF(fprintf(stderr, "stream: dep_insert_subtree dep_stream(%p)=%d "
dep_stream, dep_stream->stream_id, stream, stream->stream_id); "stream(%p)=%d\n",
dep_stream, dep_stream->stream_id, stream, stream->stream_id));
stream->sum_dep_weight += dep_stream->sum_dep_weight; stream->sum_dep_weight += dep_stream->sum_dep_weight;
dep_stream->sum_dep_weight = stream->weight; dep_stream->sum_dep_weight = stream->weight;
@@ -858,8 +862,9 @@ int nghttp2_stream_dep_add_subtree(nghttp2_stream *dep_stream,
nghttp2_stream *stream) { nghttp2_stream *stream) {
int rv; int rv;
DEBUGF("stream: dep_add_subtree dep_stream(%p)=%d stream(%p)=%d\n", DEBUGF(fprintf(stderr, "stream: dep_add_subtree dep_stream(%p)=%d "
dep_stream, dep_stream->stream_id, stream, stream->stream_id); "stream(%p)=%d\n",
dep_stream, dep_stream->stream_id, stream, stream->stream_id));
dep_stream->sum_dep_weight += stream->weight; dep_stream->sum_dep_weight += stream->weight;
@@ -884,8 +889,8 @@ int nghttp2_stream_dep_add_subtree(nghttp2_stream *dep_stream,
void nghttp2_stream_dep_remove_subtree(nghttp2_stream *stream) { void nghttp2_stream_dep_remove_subtree(nghttp2_stream *stream) {
nghttp2_stream *next, *dep_prev; nghttp2_stream *next, *dep_prev;
DEBUGF("stream: dep_remove_subtree stream(%p)=%d\n", stream, DEBUGF(fprintf(stderr, "stream: dep_remove_subtree stream(%p)=%d\n", stream,
stream->stream_id); stream->stream_id));
assert(stream->dep_prev); assert(stream->dep_prev);

View File

@@ -410,75 +410,6 @@ int nghttp2_submit_window_update(nghttp2_session *session, uint8_t flags,
return 0; return 0;
} }
int nghttp2_session_set_local_window_size(nghttp2_session *session,
uint8_t flags, int32_t stream_id,
int32_t window_size) {
int32_t window_size_increment;
nghttp2_stream *stream;
int rv;
if (window_size < 0) {
return NGHTTP2_ERR_INVALID_ARGUMENT;
}
flags = 0;
if (stream_id == 0) {
window_size_increment = window_size - session->local_window_size;
if (window_size_increment == 0) {
return 0;
}
if (window_size_increment < 0) {
return nghttp2_adjust_local_window_size(
&session->local_window_size, &session->recv_window_size,
&session->recv_reduction, &window_size_increment);
}
rv = nghttp2_increase_local_window_size(
&session->local_window_size, &session->recv_window_size,
&session->recv_reduction, &window_size_increment);
if (rv != 0) {
return rv;
}
} else {
stream = nghttp2_session_get_stream(session, stream_id);
if (stream == NULL) {
return 0;
}
window_size_increment = window_size - stream->local_window_size;
if (window_size_increment == 0) {
return 0;
}
if (window_size_increment < 0) {
return nghttp2_adjust_local_window_size(
&stream->local_window_size, &stream->recv_window_size,
&stream->recv_reduction, &window_size_increment);
}
rv = nghttp2_increase_local_window_size(
&stream->local_window_size, &stream->recv_window_size,
&stream->recv_reduction, &window_size_increment);
if (rv != 0) {
return rv;
}
}
if (window_size_increment > 0) {
return nghttp2_session_add_window_update(session, flags, stream_id,
window_size_increment);
}
return 0;
}
int nghttp2_submit_altsvc(nghttp2_session *session, uint8_t flags _U_, int nghttp2_submit_altsvc(nghttp2_session *session, uint8_t flags _U_,
int32_t stream_id, const uint8_t *origin, int32_t stream_id, const uint8_t *origin,
size_t origin_len, const uint8_t *field_value, size_t origin_len, const uint8_t *field_value,

View File

@@ -12,7 +12,7 @@ if [ -z "$CLANGFORMATDIFF" ]; then
CLANGFORMATDIFF=clang-format-diff.py CLANGFORMATDIFF=clang-format-diff.py
fi fi
errors=`git diff-index --cached --diff-filter=ACMR -p HEAD lib src examples tests | $CLANGFORMATDIFF -p1` errors=`git diff-index --cached --diff-filter=ACMR -p HEAD -- | $CLANGFORMATDIFF -p1`
if [ -n "$errors" ]; then if [ -n "$errors" ]; then
echo "$errors" echo "$errors"

View File

@@ -260,7 +260,6 @@ try:
import email.utils import email.utils
import datetime import datetime
import time import time
import ssl as tls
from urllib.parse import urlparse from urllib.parse import urlparse
except ImportError: except ImportError:
asyncio = None asyncio = None
@@ -295,25 +294,6 @@ def wrap_body(body):
# string and flag. # string and flag.
return body return body
def negotiated_protocol(ssl_obj):
protocol = ssl_obj.selected_alpn_protocol()
if protocol:
logging.info('alpn, protocol:%s', protocol)
return protocol
protocol = ssl_obj.selected_npn_protocol()
if protocol:
logging.info('npn, protocol:%s', protocol)
return protocol
return None
def set_application_protocol(ssl_ctx):
app_protos = [cnghttp2.NGHTTP2_PROTO_VERSION_ID.decode('utf-8')]
ssl_ctx.set_npn_protocols(app_protos)
if tls.HAS_ALPN:
ssl_ctx.set_alpn_protocols(app_protos)
cdef _get_stream_user_data(cnghttp2.nghttp2_session *session, cdef _get_stream_user_data(cnghttp2.nghttp2_session *session,
int32_t stream_id): int32_t stream_id):
cdef void *stream_user_data cdef void *stream_user_data
@@ -922,8 +902,6 @@ cdef class _HTTP2SessionCore(_HTTP2SessionCoreBase):
return promised_handler return promised_handler
def connection_lost(self): def connection_lost(self):
self._stop_settings_timer()
for handler in self.handlers: for handler in self.handlers:
handler.on_close(cnghttp2.NGHTTP2_INTERNAL_ERROR) handler.on_close(cnghttp2.NGHTTP2_INTERNAL_ERROR)
self.handlers = set() self.handlers = set()
@@ -1306,8 +1284,8 @@ if asyncio:
logging.info('failed to set tcp-nodelay: %s', str(e)) logging.info('failed to set tcp-nodelay: %s', str(e))
ssl_ctx = self.transport.get_extra_info('sslcontext') ssl_ctx = self.transport.get_extra_info('sslcontext')
if ssl_ctx: if ssl_ctx:
ssl_obj = self.transport.get_extra_info('ssl_object') protocol = sock.selected_npn_protocol()
protocol = negotiated_protocol(ssl_obj) logging.info('npn, protocol:%s', protocol)
if protocol is None or protocol.encode('utf-8') != \ if protocol is None or protocol.encode('utf-8') != \
cnghttp2.NGHTTP2_PROTO_VERSION_ID: cnghttp2.NGHTTP2_PROTO_VERSION_ID:
self.transport.abort() self.transport.abort()
@@ -1368,7 +1346,8 @@ if asyncio:
self.loop = asyncio.get_event_loop() self.loop = asyncio.get_event_loop()
if ssl: if ssl:
set_application_protocol(ssl) ssl.set_npn_protocols([cnghttp2.NGHTTP2_PROTO_VERSION_ID\
.decode('utf-8')])
coro = self.loop.create_server(session_factory, coro = self.loop.create_server(session_factory,
host=address[0], port=address[1], host=address[0], port=address[1],
@@ -1537,8 +1516,8 @@ if asyncio:
sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
ssl_ctx = self.transport.get_extra_info('sslcontext') ssl_ctx = self.transport.get_extra_info('sslcontext')
if ssl_ctx: if ssl_ctx:
ssl_obj = self.transport.get_extra_info('ssl_object') protocol = sock.selected_npn_protocol()
protocol = negotiated_protocol(ssl_obj) logging.info('npn, protocol:%s', protocol)
if protocol is None or protocol.encode('utf-8') != \ if protocol is None or protocol.encode('utf-8') != \
cnghttp2.NGHTTP2_PROTO_VERSION_ID: cnghttp2.NGHTTP2_PROTO_VERSION_ID:
self.transport.abort() self.transport.abort()
@@ -1615,7 +1594,8 @@ if asyncio:
return self.session return self.session
if ssl: if ssl:
set_application_protocol(ssl) ssl.set_npn_protocols([cnghttp2.NGHTTP2_PROTO_VERSION_ID\
.decode('utf-8')])
self.loop = loop self.loop = loop
if not self.loop: if not self.loop:

View File

@@ -109,10 +109,6 @@ if(ENABLE_APP)
shrpx_worker_process.cc shrpx_worker_process.cc
shrpx_signal.cc shrpx_signal.cc
shrpx_router.cc shrpx_router.cc
shrpx_api_downstream_connection.cc
shrpx_health_monitor_downstream_connection.cc
shrpx_exec.cc
xsi_strerror.c
) )
if(HAVE_SPDYLAY) if(HAVE_SPDYLAY)
list(APPEND NGHTTPX_SRCS list(APPEND NGHTTPX_SRCS
@@ -152,7 +148,6 @@ if(ENABLE_APP)
shrpx_config_test.cc shrpx_config_test.cc
shrpx_worker_test.cc shrpx_worker_test.cc
shrpx_http_test.cc shrpx_http_test.cc
shrpx_router_test.cc
http2_test.cc http2_test.cc
util_test.cc util_test.cc
nghttp2_gzip_test.c nghttp2_gzip_test.c
@@ -168,7 +163,7 @@ if(ENABLE_APP)
) )
target_include_directories(nghttpx-unittest PRIVATE ${CUNIT_INCLUDE_DIRS}) target_include_directories(nghttpx-unittest PRIVATE ${CUNIT_INCLUDE_DIRS})
target_compile_definitions(nghttpx-unittest target_compile_definitions(nghttpx-unittest
PRIVATE "-DNGHTTP2_SRC_DIR=\"${CMAKE_SOURCE_DIR}/src\"" PRIVATE "-DNGHTTP2_TESTS_DIR=\"${CMAKE_SOURCE_DIR}/tests\""
) )
target_link_libraries(nghttpx-unittest nghttpx_static ${CUNIT_LIBRARIES}) target_link_libraries(nghttpx-unittest nghttpx_static ${CUNIT_LIBRARIES})
if(HAVE_MRUBY) if(HAVE_MRUBY)

View File

@@ -96,7 +96,6 @@ Config::Config()
num_worker(1), num_worker(1),
max_concurrent_streams(100), max_concurrent_streams(100),
header_table_size(-1), header_table_size(-1),
encoder_header_table_size(-1),
window_bits(-1), window_bits(-1),
connection_window_bits(-1), connection_window_bits(-1),
port(0), port(0),
@@ -232,7 +231,6 @@ public:
config_(config), config_(config),
ssl_ctx_(ssl_ctx), ssl_ctx_(ssl_ctx),
callbacks_(nullptr), callbacks_(nullptr),
option_(nullptr),
next_session_id_(1), next_session_id_(1),
tstamp_cached_(ev_now(loop)), tstamp_cached_(ev_now(loop)),
cached_date_(util::http_date(tstamp_cached_)) { cached_date_(util::http_date(tstamp_cached_)) {
@@ -240,13 +238,6 @@ public:
fill_callback(callbacks_, config_); fill_callback(callbacks_, config_);
nghttp2_option_new(&option_);
if (config_->encoder_header_table_size != -1) {
nghttp2_option_set_max_deflate_dynamic_table_size(
option_, config_->encoder_header_table_size);
}
ev_timer_init(&release_fd_timer_, release_fd_cb, 0., RELEASE_FD_TIMEOUT); ev_timer_init(&release_fd_timer_, release_fd_cb, 0., RELEASE_FD_TIMEOUT);
release_fd_timer_.data = this; release_fd_timer_.data = this;
} }
@@ -255,7 +246,6 @@ public:
for (auto handler : handlers_) { for (auto handler : handlers_) {
delete handler; delete handler;
} }
nghttp2_option_del(option_);
nghttp2_session_callbacks_del(callbacks_); nghttp2_session_callbacks_del(callbacks_);
} }
void add_handler(Http2Handler *handler) { handlers_.insert(handler); } void add_handler(Http2Handler *handler) { handlers_.insert(handler); }
@@ -293,7 +283,6 @@ public:
return session_id; return session_id;
} }
const nghttp2_session_callbacks *get_callbacks() const { return callbacks_; } const nghttp2_session_callbacks *get_callbacks() const { return callbacks_; }
const nghttp2_option *get_option() const { return option_; }
void accept_connection(int fd) { void accept_connection(int fd) {
util::make_socket_nodelay(fd); util::make_socket_nodelay(fd);
SSL *ssl = nullptr; SSL *ssl = nullptr;
@@ -419,7 +408,6 @@ private:
const Config *config_; const Config *config_;
SSL_CTX *ssl_ctx_; SSL_CTX *ssl_ctx_;
nghttp2_session_callbacks *callbacks_; nghttp2_session_callbacks *callbacks_;
nghttp2_option *option_;
ev_timer release_fd_timer_; ev_timer release_fd_timer_;
int64_t next_session_id_; int64_t next_session_id_;
ev_tstamp tstamp_cached_; ev_tstamp tstamp_cached_;
@@ -837,8 +825,7 @@ int Http2Handler::on_write() { return write_(*this); }
int Http2Handler::connection_made() { int Http2Handler::connection_made() {
int r; int r;
r = nghttp2_session_server_new2(&session_, sessions_->get_callbacks(), this, r = nghttp2_session_server_new(&session_, sessions_->get_callbacks(), this);
sessions_->get_option());
if (r != 0) { if (r != 0) {
return r; return r;
@@ -869,9 +856,10 @@ int Http2Handler::connection_made() {
} }
if (config->connection_window_bits != -1) { if (config->connection_window_bits != -1) {
r = nghttp2_session_set_local_window_size( r = nghttp2_submit_window_update(
session_, NGHTTP2_FLAG_NONE, 0, session_, NGHTTP2_FLAG_NONE, 0,
(1 << config->connection_window_bits) - 1); (1 << config->connection_window_bits) - 1 -
NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE);
if (r != 0) { if (r != 0) {
return r; return r;
} }
@@ -1301,7 +1289,7 @@ void prepare_response(Stream *stream, Http2Handler *hd,
p = std::copy(std::begin(htdocs), std::end(htdocs), p); p = std::copy(std::begin(htdocs), std::end(htdocs), p);
p = std::copy(std::begin(path), std::end(path), p); p = std::copy(std::begin(path), std::end(path), p);
if (trailing_slash) { if (trailing_slash) {
std::copy(std::begin(DEFAULT_HTML), std::end(DEFAULT_HTML), p); p = std::copy(std::begin(DEFAULT_HTML), std::end(DEFAULT_HTML), p);
} }
} }
@@ -2082,7 +2070,7 @@ int alpn_select_proto_cb(SSL *ssl, const unsigned char **out,
std::cout << "[ALPN] client offers:" << std::endl; std::cout << "[ALPN] client offers:" << std::endl;
} }
if (config->verbose) { if (config->verbose) {
for (unsigned int i = 0; i < inlen; i += in[i] + 1) { for (unsigned int i = 0; i < inlen; i += in [i] + 1) {
std::cout << " * "; std::cout << " * ";
std::cout.write(reinterpret_cast<const char *>(&in[i + 1]), in[i]); std::cout.write(reinterpret_cast<const char *>(&in[i + 1]), in[i]);
std::cout << std::endl; std::cout << std::endl;

View File

@@ -69,7 +69,6 @@ struct Config {
size_t num_worker; size_t num_worker;
size_t max_concurrent_streams; size_t max_concurrent_streams;
ssize_t header_table_size; ssize_t header_table_size;
ssize_t encoder_header_table_size;
int window_bits; int window_bits;
int connection_window_bits; int connection_window_bits;
uint16_t port; uint16_t port;

View File

@@ -22,10 +22,7 @@
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
SUBDIRS = includes SUBDIRS = includes
EXTRA_DIST = \ EXTRA_DIST = CMakeLists.txt
CMakeLists.txt \
test.example.com.pem \
test.nghttp2.org.pem
bin_PROGRAMS = bin_PROGRAMS =
check_PROGRAMS = check_PROGRAMS =
@@ -135,12 +132,7 @@ NGHTTPX_SRCS = \
shrpx_process.h \ shrpx_process.h \
shrpx_signal.cc shrpx_signal.h \ shrpx_signal.cc shrpx_signal.h \
shrpx_router.cc shrpx_router.h \ shrpx_router.cc shrpx_router.h \
shrpx_api_downstream_connection.cc shrpx_api_downstream_connection.h \ buffer.h memchunk.h template.h allocator.h
shrpx_health_monitor_downstream_connection.cc \
shrpx_health_monitor_downstream_connection.h \
shrpx_exec.cc shrpx_exec.h \
buffer.h memchunk.h template.h allocator.h \
xsi_strerror.c xsi_strerror.h
if HAVE_SPDYLAY if HAVE_SPDYLAY
NGHTTPX_SRCS += shrpx_spdy_upstream.cc shrpx_spdy_upstream.h NGHTTPX_SRCS += shrpx_spdy_upstream.cc shrpx_spdy_upstream.h
@@ -182,7 +174,6 @@ nghttpx_unittest_SOURCES = shrpx-unittest.cc \
shrpx_config_test.cc shrpx_config_test.h \ shrpx_config_test.cc shrpx_config_test.h \
shrpx_worker_test.cc shrpx_worker_test.h \ shrpx_worker_test.cc shrpx_worker_test.h \
shrpx_http_test.cc shrpx_http_test.h \ shrpx_http_test.cc shrpx_http_test.h \
shrpx_router_test.cc shrpx_router_test.h \
http2_test.cc http2_test.h \ http2_test.cc http2_test.h \
util_test.cc util_test.h \ util_test.cc util_test.h \
nghttp2_gzip_test.c nghttp2_gzip_test.h \ nghttp2_gzip_test.c nghttp2_gzip_test.h \
@@ -192,7 +183,7 @@ nghttpx_unittest_SOURCES = shrpx-unittest.cc \
template_test.cc template_test.h \ template_test.cc template_test.h \
base64_test.cc base64_test.h base64_test.cc base64_test.h
nghttpx_unittest_CPPFLAGS = ${AM_CPPFLAGS} \ nghttpx_unittest_CPPFLAGS = ${AM_CPPFLAGS} \
-DNGHTTP2_SRC_DIR=\"$(top_srcdir)/src\" -DNGHTTP2_TESTS_DIR=\"$(top_srcdir)/tests\"
nghttpx_unittest_LDADD = libnghttpx.a ${LDADD} @CUNIT_LIBS@ @TESTLDADD@ nghttpx_unittest_LDADD = libnghttpx.a ${LDADD} @CUNIT_LIBS@ @TESTLDADD@
if HAVE_MRUBY if HAVE_MRUBY

View File

@@ -29,8 +29,6 @@
#include <sys/uio.h> #include <sys/uio.h>
#include <cassert>
#include "template.h" #include "template.h"
namespace nghttp2 { namespace nghttp2 {
@@ -47,58 +45,29 @@ struct MemBlock {
// BlockAllocator allocates memory block with given size at once, and // BlockAllocator allocates memory block with given size at once, and
// cuts the region from it when allocation is requested. If the // cuts the region from it when allocation is requested. If the
// requested size is larger than given threshold (plus small internal // requested size is larger than given threshold, it will be allocated
// overhead), it will be allocated in a distinct buffer on demand. // in a distinct buffer on demand.
// The |isolation_threshold| must be less than or equal to
// |block_size|.
struct BlockAllocator { struct BlockAllocator {
BlockAllocator(size_t block_size, size_t isolation_threshold) BlockAllocator(size_t block_size, size_t isolation_threshold)
: retain(nullptr), : retain(nullptr),
head(nullptr), head(nullptr),
block_size(block_size), block_size(block_size),
isolation_threshold(std::min(block_size, isolation_threshold)) { isolation_threshold(std::min(block_size, isolation_threshold)) {}
assert(isolation_threshold <= block_size);
}
~BlockAllocator() { reset(); } ~BlockAllocator() {
BlockAllocator(BlockAllocator &&other) noexcept
: retain(other.retain),
head(other.head),
block_size(other.block_size),
isolation_threshold(other.isolation_threshold) {
other.retain = nullptr;
other.head = nullptr;
}
BlockAllocator &operator=(BlockAllocator &&other) noexcept {
reset();
retain = other.retain;
head = other.head;
block_size = other.block_size;
isolation_threshold = other.isolation_threshold;
other.retain = nullptr;
other.head = nullptr;
return *this;
}
BlockAllocator(const BlockAllocator &) = delete;
BlockAllocator &operator=(const BlockAllocator &) = delete;
void reset() {
for (auto mb = retain; mb;) { for (auto mb = retain; mb;) {
auto next = mb->next; auto next = mb->next;
delete[] reinterpret_cast<uint8_t *>(mb); delete[] reinterpret_cast<uint8_t *>(mb);
mb = next; mb = next;
} }
retain = nullptr;
head = nullptr;
} }
BlockAllocator(BlockAllocator &&) = default;
BlockAllocator &operator=(BlockAllocator &&) = default;
BlockAllocator(const BlockAllocator &) = delete;
BlockAllocator &operator=(const BlockAllocator &) = delete;
MemBlock *alloc_mem_block(size_t size) { MemBlock *alloc_mem_block(size_t size) {
auto block = new uint8_t[sizeof(MemBlock) + size]; auto block = new uint8_t[sizeof(MemBlock) + size];
auto mb = reinterpret_cast<MemBlock *>(block); auto mb = reinterpret_cast<MemBlock *>(block);
@@ -111,60 +80,20 @@ struct BlockAllocator {
} }
void *alloc(size_t size) { void *alloc(size_t size) {
if (size + sizeof(size_t) >= isolation_threshold) { if (size >= isolation_threshold) {
auto len = std::max(static_cast<size_t>(16), size); auto mb = alloc_mem_block(size);
// We will store the allocated size in size_t field.
auto mb = alloc_mem_block(len + sizeof(size_t));
auto sp = reinterpret_cast<size_t *>(mb->begin);
*sp = len;
mb->last = mb->end; mb->last = mb->end;
return mb->begin + sizeof(size_t); return mb->begin;
} }
if (!head || if (!head || head->end - head->last < static_cast<ssize_t>(size)) {
head->end - head->last < static_cast<ssize_t>(size + sizeof(size_t))) {
head = alloc_mem_block(block_size); head = alloc_mem_block(block_size);
} }
// We will store the allocated size in size_t field. auto res = head->last;
auto res = head->last + sizeof(size_t);
auto sp = reinterpret_cast<size_t *>(head->last);
*sp = size;
head->last = reinterpret_cast<uint8_t *>( head->last = reinterpret_cast<uint8_t *>(
(reinterpret_cast<intptr_t>(res + size) + 0xf) & ~0xf); (reinterpret_cast<intptr_t>(head->last + size) + 0xf) & ~0xf);
return res;
}
// Returns allocated size for memory pointed by |ptr|. We assume
// that |ptr| was returned from alloc() or realloc().
size_t get_alloc_length(void *ptr) {
return *reinterpret_cast<size_t *>(static_cast<uint8_t *>(ptr) -
sizeof(size_t));
}
// Allocates memory of at least |size| bytes. If |ptr| is nullptr,
// this is equivalent to alloc(size). If |ptr| is not nullptr,
// obtain the allocated size for |ptr|, assuming that |ptr| was
// returned from alloc() or realloc(). If the allocated size is
// greater than or equal to size, |ptr| is returned. Otherwise,
// allocates at least |size| bytes of memory, and the original
// content pointed by |ptr| is copied to the newly allocated memory.
void *realloc(void *ptr, size_t size) {
if (!ptr) {
return alloc(size);
}
auto alloclen = get_alloc_length(ptr);
auto p = reinterpret_cast<uint8_t *>(ptr);
if (size <= alloclen) {
return ptr;
}
auto nalloclen = std::max(size + 1, alloclen * 2);
auto res = alloc(nalloclen);
std::copy_n(p, alloclen, static_cast<uint8_t *>(res));
return res; return res;
} }
@@ -232,30 +161,6 @@ StringRef concat_string_ref(BlockAllocator &alloc, Args &&... args) {
return StringRef{dst, len}; return StringRef{dst, len};
} }
// Returns the string which is the concatenation of |value| and |args|
// in the given order. The resulting string will be NULL-terminated.
// This function assumes that the pointer value value.c_str() was
// obtained from alloc.alloc() or alloc.realloc(), and attempts to use
// unused memory region by using alloc.realloc(). If value is empty,
// then just call concat_string_ref().
template <typename BlockAllocator, typename... Args>
StringRef realloc_concat_string_ref(BlockAllocator &alloc,
const StringRef &value, Args &&... args) {
if (value.empty()) {
return concat_string_ref(alloc, std::forward<Args>(args)...);
}
auto len =
value.size() + concat_string_ref_count(0, std::forward<Args>(args)...);
auto dst = static_cast<uint8_t *>(
alloc.realloc(const_cast<uint8_t *>(value.byte()), len + 1));
auto p = dst + value.size();
p = concat_string_ref_copy(p, std::forward<Args>(args)...);
*p = '\0';
return StringRef{dst, len};
}
struct ByteRef { struct ByteRef {
// The pointer to the beginning of the buffer. // The pointer to the beginning of the buffer.
uint8_t *base; uint8_t *base;

View File

@@ -334,8 +334,7 @@ void print_frame(print_type ptype, const nghttp2_frame *frame) {
frame->goaway.error_code, frame->goaway.error_code,
static_cast<unsigned int>(frame->goaway.opaque_data_len), static_cast<unsigned int>(frame->goaway.opaque_data_len),
util::ascii_dump(frame->goaway.opaque_data, util::ascii_dump(frame->goaway.opaque_data,
frame->goaway.opaque_data_len) frame->goaway.opaque_data_len).c_str());
.c_str());
break; break;
case NGHTTP2_WINDOW_UPDATE: case NGHTTP2_WINDOW_UPDATE:
print_frame_attr_indent(); print_frame_attr_indent();

View File

@@ -373,8 +373,9 @@ bool session_impl::setup_session() {
{NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE, window_size}}}; {NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE, window_size}}};
nghttp2_submit_settings(session_, NGHTTP2_FLAG_NONE, iv.data(), iv.size()); nghttp2_submit_settings(session_, NGHTTP2_FLAG_NONE, iv.data(), iv.size());
// increase connection window size up to window_size // increase connection window size up to window_size
nghttp2_session_set_local_window_size(session_, NGHTTP2_FLAG_NONE, 0, nghttp2_submit_window_update(session_, NGHTTP2_FLAG_NONE, 0,
window_size); window_size -
NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE);
return true; return true;
} }
@@ -503,7 +504,7 @@ const request *session_impl::submit(boost::system::error_code &ec,
} }
auto nva = std::vector<nghttp2_nv>(); auto nva = std::vector<nghttp2_nv>();
nva.reserve(4 + h.size()); nva.reserve(3 + h.size());
nva.push_back(http2::make_nv_ls(":method", method)); nva.push_back(http2::make_nv_ls(":method", method));
nva.push_back(http2::make_nv_ls(":scheme", uref.scheme)); nva.push_back(http2::make_nv_ls(":scheme", uref.scheme));
nva.push_back(http2::make_nv_ls(":path", path)); nva.push_back(http2::make_nv_ls(":path", path));
@@ -521,13 +522,13 @@ const request *session_impl::submit(boost::system::error_code &ec,
if (cb) { if (cb) {
strm->request().impl().on_read(std::move(cb)); strm->request().impl().on_read(std::move(cb));
prd.source.ptr = strm.get(); prd.source.ptr = strm.get();
prd.read_callback = [](nghttp2_session *session, int32_t stream_id, prd.read_callback =
uint8_t *buf, size_t length, uint32_t *data_flags, [](nghttp2_session *session, int32_t stream_id, uint8_t *buf,
nghttp2_data_source *source, size_t length, uint32_t *data_flags, nghttp2_data_source *source,
void *user_data) -> ssize_t { void *user_data) -> ssize_t {
auto strm = static_cast<stream *>(source->ptr); auto strm = static_cast<stream *>(source->ptr);
return strm->request().impl().call_on_read(buf, length, data_flags); return strm->request().impl().call_on_read(buf, length, data_flags);
}; };
prdptr = &prd; prdptr = &prd;
} }

View File

@@ -74,12 +74,10 @@ public:
virtual void start_connect(tcp::resolver::iterator endpoint_it) = 0; virtual void start_connect(tcp::resolver::iterator endpoint_it) = 0;
virtual tcp::socket &socket() = 0; virtual tcp::socket &socket() = 0;
virtual void read_socket( virtual void read_socket(std::function<
std::function<void(const boost::system::error_code &ec, std::size_t n)> void(const boost::system::error_code &ec, std::size_t n)> h) = 0;
h) = 0; virtual void write_socket(std::function<
virtual void write_socket( void(const boost::system::error_code &ec, std::size_t n)> h) = 0;
std::function<void(const boost::system::error_code &ec, std::size_t n)>
h) = 0;
virtual void shutdown_socket() = 0; virtual void shutdown_socket() = 0;
void shutdown(); void shutdown();

View File

@@ -44,12 +44,10 @@ public:
virtual void start_connect(tcp::resolver::iterator endpoint_it); virtual void start_connect(tcp::resolver::iterator endpoint_it);
virtual tcp::socket &socket(); virtual tcp::socket &socket();
virtual void read_socket( virtual void read_socket(std::function<
std::function<void(const boost::system::error_code &ec, std::size_t n)> void(const boost::system::error_code &ec, std::size_t n)> h);
h); virtual void write_socket(std::function<
virtual void write_socket( void(const boost::system::error_code &ec, std::size_t n)> h);
std::function<void(const boost::system::error_code &ec, std::size_t n)>
h);
virtual void shutdown_socket(); virtual void shutdown_socket();
private: private:

View File

@@ -47,12 +47,10 @@ public:
virtual void start_connect(tcp::resolver::iterator endpoint_it); virtual void start_connect(tcp::resolver::iterator endpoint_it);
virtual tcp::socket &socket(); virtual tcp::socket &socket();
virtual void read_socket( virtual void read_socket(std::function<
std::function<void(const boost::system::error_code &ec, std::size_t n)> void(const boost::system::error_code &ec, std::size_t n)> h);
h); virtual void write_socket(std::function<
virtual void write_socket( void(const boost::system::error_code &ec, std::size_t n)> h);
std::function<void(const boost::system::error_code &ec, std::size_t n)>
h);
virtual void shutdown_socket(); virtual void shutdown_socket();
private: private:

View File

@@ -113,22 +113,22 @@ generator_cb file_generator(const std::string &path) {
generator_cb file_generator_from_fd(int fd) { generator_cb file_generator_from_fd(int fd) {
auto d = defer_shared(close, fd); auto d = defer_shared(close, fd);
return [fd, d](uint8_t *buf, size_t len, return [fd, d](uint8_t *buf, size_t len, uint32_t *data_flags)
uint32_t *data_flags) -> generator_cb::result_type { -> generator_cb::result_type {
ssize_t n; ssize_t n;
while ((n = read(fd, buf, len)) == -1 && errno == EINTR) while ((n = read(fd, buf, len)) == -1 && errno == EINTR)
; ;
if (n == -1) { if (n == -1) {
return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE; return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
} }
if (n == 0) { if (n == 0) {
*data_flags |= NGHTTP2_DATA_FLAG_EOF; *data_flags |= NGHTTP2_DATA_FLAG_EOF;
} }
return n; return n;
}; };
} }
bool check_path(const std::string &path) { return util::check_path(path); } bool check_path(const std::string &path) { return util::check_path(path); }

View File

@@ -58,7 +58,7 @@ void io_service_pool::run(bool asynchronous) {
// Create a pool of threads to run all of the io_services. // Create a pool of threads to run all of the io_services.
for (std::size_t i = 0; i < io_services_.size(); ++i) { for (std::size_t i = 0; i < io_services_.size(); ++i) {
futures_.push_back(std::async(std::launch::async, futures_.push_back(std::async(std::launch::async,
(size_t(boost::asio::io_service::*)(void)) & (size_t (boost::asio::io_service::*)(void)) &
boost::asio::io_service::run, boost::asio::io_service::run,
io_services_[i])); io_services_[i]));
} }

View File

@@ -130,8 +130,8 @@ void server::start_accept(boost::asio::ssl::context &tls_context,
acceptor.async_accept( acceptor.async_accept(
new_connection->socket().lowest_layer(), new_connection->socket().lowest_layer(),
[this, &tls_context, &acceptor, &mux, [this, &tls_context, &acceptor, &mux, new_connection](
new_connection](const boost::system::error_code &e) { const boost::system::error_code &e) {
if (!e) { if (!e) {
new_connection->socket().lowest_layer().set_option( new_connection->socket().lowest_layer().set_option(
tcp::no_delay(true)); tcp::no_delay(true));

View File

@@ -245,7 +245,6 @@ http2_handler::http2_handler(boost::asio::io_service &io_service,
buf_(nullptr), buf_(nullptr),
buflen_(0), buflen_(0),
inside_callback_(false), inside_callback_(false),
write_signaled_(false),
tstamp_cached_(time(nullptr)), tstamp_cached_(time(nullptr)),
formatted_date_(util::http_date(tstamp_cached_)) {} formatted_date_(util::http_date(tstamp_cached_)) {}
@@ -346,13 +345,13 @@ int http2_handler::start_response(stream &strm) {
auto &req = strm.request().impl(); auto &req = strm.request().impl();
if (::nghttp2::http2::expect_response_body(req.method(), res.status_code())) { if (::nghttp2::http2::expect_response_body(req.method(), res.status_code())) {
prd.source.ptr = &strm; prd.source.ptr = &strm;
prd.read_callback = [](nghttp2_session *session, int32_t stream_id, prd.read_callback =
uint8_t *buf, size_t length, uint32_t *data_flags, [](nghttp2_session *session, int32_t stream_id, uint8_t *buf,
nghttp2_data_source *source, size_t length, uint32_t *data_flags, nghttp2_data_source *source,
void *user_data) -> ssize_t { void *user_data) -> ssize_t {
auto &strm = *static_cast<stream *>(source->ptr); auto &strm = *static_cast<stream *>(source->ptr);
return strm.response().impl().call_read(buf, length, data_flags); return strm.response().impl().call_read(buf, length, data_flags);
}; };
prd_ptr = &prd; prd_ptr = &prd;
} }
rv = nghttp2_submit_response(session_, strm.get_stream_id(), nva.data(), rv = nghttp2_submit_response(session_, strm.get_stream_id(), nva.data(),
@@ -404,17 +403,12 @@ void http2_handler::stream_error(int32_t stream_id, uint32_t error_code) {
} }
void http2_handler::signal_write() { void http2_handler::signal_write() {
if (!inside_callback_ && !write_signaled_) { if (!inside_callback_) {
write_signaled_ = true; initiate_write();
auto self = shared_from_this();
io_service_.post([self]() { self->initiate_write(); });
} }
} }
void http2_handler::initiate_write() { void http2_handler::initiate_write() { writefun_(); }
write_signaled_ = false;
writefun_();
}
void http2_handler::resume(stream &strm) { void http2_handler::resume(stream &strm) {
nghttp2_session_resume_data(session_, strm.get_stream_id()); nghttp2_session_resume_data(session_, strm.get_stream_id());

View File

@@ -160,9 +160,6 @@ private:
const uint8_t *buf_; const uint8_t *buf_;
std::size_t buflen_; std::size_t buflen_;
bool inside_callback_; bool inside_callback_;
// true if we have pending on_write call. This avoids repeated call
// of io_service::post.
bool write_signaled_;
time_t tstamp_cached_; time_t tstamp_cached_;
std::string formatted_date_; std::string formatted_date_;
}; };

View File

@@ -29,9 +29,6 @@
#include <string> #include <string>
#include "template.h"
#include "allocator.h"
namespace nghttp2 { namespace nghttp2 {
namespace base64 { namespace base64 {
@@ -90,8 +87,7 @@ InputIt next_decode_input(InputIt first, InputIt last, const int *tbl) {
return first; return first;
} }
template <typename InputIt, typename OutputIt> template <typename InputIt> std::string decode(InputIt first, InputIt last) {
OutputIt decode(InputIt first, InputIt last, OutputIt d_first) {
static constexpr int INDEX_TABLE[] = { static constexpr int INDEX_TABLE[] = {
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
@@ -108,29 +104,37 @@ OutputIt decode(InputIt first, InputIt last, OutputIt d_first) {
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1}; -1, -1, -1, -1};
assert(std::distance(first, last) % 4 == 0); auto len = last - first;
auto p = d_first; if (len % 4 != 0) {
return "";
}
std::string res;
res.resize(len / 4 * 3);
auto p = std::begin(res);
for (; first != last;) { for (; first != last;) {
uint32_t n = 0; uint32_t n = 0;
for (int i = 1; i <= 4; ++i, ++first) { for (int i = 1; i <= 4; ++i, ++first) {
auto idx = INDEX_TABLE[static_cast<size_t>(*first)]; auto idx = INDEX_TABLE[static_cast<size_t>(*first)];
if (idx == -1) { if (idx == -1) {
if (i <= 2) { if (i <= 2) {
return d_first; return "";
} }
if (i == 3) { if (i == 3) {
if (*first == '=' && *(first + 1) == '=' && first + 2 == last) { if (*first == '=' && *(first + 1) == '=' && first + 2 == last) {
*p++ = n >> 16; *p++ = n >> 16;
return p; res.resize(p - std::begin(res));
return res;
} }
return d_first; return "";
} }
if (*first == '=' && first + 1 == last) { if (*first == '=' && first + 1 == last) {
*p++ = n >> 16; *p++ = n >> 16;
*p++ = n >> 8 & 0xffu; *p++ = n >> 8 & 0xffu;
return p; res.resize(p - std::begin(res));
return res;
} }
return d_first; return "";
} }
n += idx << (24 - i * 6); n += idx << (24 - i * 6);
@@ -141,37 +145,9 @@ OutputIt decode(InputIt first, InputIt last, OutputIt d_first) {
*p++ = n & 0xffu; *p++ = n & 0xffu;
} }
return p;
}
template <typename InputIt> std::string decode(InputIt first, InputIt last) {
auto len = std::distance(first, last);
if (len % 4 != 0) {
return "";
}
std::string res;
res.resize(len / 4 * 3);
res.erase(decode(first, last, std::begin(res)), std::end(res));
return res; return res;
} }
template <typename InputIt>
StringRef decode(BlockAllocator &balloc, InputIt first, InputIt last) {
auto len = std::distance(first, last);
if (len % 4 != 0) {
return StringRef::from_lit("");
}
auto iov = make_byte_ref(balloc, len / 4 * 3 + 1);
auto p = iov.base;
p = decode(first, last, p);
*p = '\0';
return StringRef{iov.base, p};
}
} // namespace base64 } // namespace base64
} // namespace nghttp2 } // namespace nghttp2

View File

@@ -59,40 +59,31 @@ void test_base64_encode(void) {
} }
void test_base64_decode(void) { void test_base64_decode(void) {
BlockAllocator balloc(4096, 4096);
{ {
std::string in = "/w=="; std::string in = "/w==";
auto out = base64::decode(std::begin(in), std::end(in)); auto out = base64::decode(std::begin(in), std::end(in));
CU_ASSERT("\xff" == out); CU_ASSERT("\xff" == out);
CU_ASSERT("\xff" == base64::decode(balloc, std::begin(in), std::end(in)));
} }
{ {
std::string in = "//4="; std::string in = "//4=";
auto out = base64::decode(std::begin(in), std::end(in)); auto out = base64::decode(std::begin(in), std::end(in));
CU_ASSERT("\xff\xfe" == out); CU_ASSERT("\xff\xfe" == out);
CU_ASSERT("\xff\xfe" ==
base64::decode(balloc, std::begin(in), std::end(in)));
} }
{ {
std::string in = "//79"; std::string in = "//79";
auto out = base64::decode(std::begin(in), std::end(in)); auto out = base64::decode(std::begin(in), std::end(in));
CU_ASSERT("\xff\xfe\xfd" == out); CU_ASSERT("\xff\xfe\xfd" == out);
CU_ASSERT("\xff\xfe\xfd" ==
base64::decode(balloc, std::begin(in), std::end(in)));
} }
{ {
std::string in = "//79/A=="; std::string in = "//79/A==";
auto out = base64::decode(std::begin(in), std::end(in)); auto out = base64::decode(std::begin(in), std::end(in));
CU_ASSERT("\xff\xfe\xfd\xfc" == out); CU_ASSERT("\xff\xfe\xfd\xfc" == out);
CU_ASSERT("\xff\xfe\xfd\xfc" ==
base64::decode(balloc, std::begin(in), std::end(in)));
} }
{ {
// we check the number of valid input must be multiples of 4 // we check the number of valid input must be multiples of 4
std::string in = "//79="; std::string in = "//79=";
auto out = base64::decode(std::begin(in), std::end(in)); auto out = base64::decode(std::begin(in), std::end(in));
CU_ASSERT("" == out); CU_ASSERT("" == out);
CU_ASSERT("" == base64::decode(balloc, std::begin(in), std::end(in)));
} }
{ {
// ending invalid character at the boundary of multiples of 4 is // ending invalid character at the boundary of multiples of 4 is
@@ -100,21 +91,18 @@ void test_base64_decode(void) {
std::string in = "bmdodHRw\n"; std::string in = "bmdodHRw\n";
auto out = base64::decode(std::begin(in), std::end(in)); auto out = base64::decode(std::begin(in), std::end(in));
CU_ASSERT("" == out); CU_ASSERT("" == out);
CU_ASSERT("" == base64::decode(balloc, std::begin(in), std::end(in)));
} }
{ {
// after seeing '=', subsequent input must be also '='. // after seeing '=', subsequent input must be also '='.
std::string in = "//79/A=A"; std::string in = "//79/A=A";
auto out = base64::decode(std::begin(in), std::end(in)); auto out = base64::decode(std::begin(in), std::end(in));
CU_ASSERT("" == out); CU_ASSERT("" == out);
CU_ASSERT("" == base64::decode(balloc, std::begin(in), std::end(in)));
} }
{ {
// additional '=' at the end is bad // additional '=' at the end is bad
std::string in = "//79/A======"; std::string in = "//79/A======";
auto out = base64::decode(std::begin(in), std::end(in)); auto out = base64::decode(std::begin(in), std::end(in));
CU_ASSERT("" == out); CU_ASSERT("" == out);
CU_ASSERT("" == base64::decode(balloc, std::begin(in), std::end(in)));
} }
} }

View File

@@ -1,17 +0,0 @@
{
"signing": {
"default": {
"expiry": "87600h"
},
"profiles": {
"server": {
"expiry": "87600h",
"usages": [
"signing",
"key encipherment",
"server auth"
]
}
}
}
}

View File

@@ -1,27 +0,0 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEpQIBAAKCAQEA1kVkF8QSUwW/HV9EFRPSMoiOVmYwB8vqKDtT0d6MFiKAM8/Y
JFUq2uKlUydgT4IPE7PATvVcIj3GtL9XzPhscqYO/S0Y7scyTE2VAPmtz+StPWf2
wZ1IQR09HrnDTc44KvYGZpefBZkD9UjbmJ9a1ZmJjJiMr3hTnKE/sxZ2+dMsnMZX
N822cfaHyTN+T0+Tyw5vBBboCDsZzxmf+9FFIDJNs3NL34cR8EZRhpfaegapH8bt
OJ+D+RZ2kg7E/YYkGcS6NodvTjSUFCFHpWjHCfTFhn/owBIAooCdWorh6dc8Q72l
AodwNLXS8uuPgPqM5s4Cz57m7Zgs4OilNmIdawIDAQABAoIBAQCwqLtygLye6KD+
RXorapEmCsJX5553/x6Klwdvg+25ni5XCWjp47IWj0DBQzi7tL5bfxrxvod8z7QR
d6SbIMLA77px8Ima7G7CzEAqcrBkM+TFOP8P+G4HCWVH/N5SOtDCUt9KHH4Grna9
95jdx5yreRAX8/oh/bHp9GRBcicbpwYMVWOnjTE2seEUYQOpdpYdP4bOPUvAju0l
mwmy2/dDGmbibktN3sdHEhDodKu+Znv7nFZo0jzhlyoXse653WcvaQeZZYuojvSe
Sr92DvPp7UaYrb4KvT7ujXiPavSV2m/4EmGtyqevUf2dZ6sfMXZjmXsjWz9txhWp
4BgbHyHRAoGBAPqyuNj2CDD3FE7N3Hxyba8d+ZtsVUNawjq2gwOvT9NLsMstOGyH
OCc1v4W6Sq4w1wo4nIJyY8kNZwtReaTHOPZlDgBhVvk/x8eLBu+QTMRyocRt1LoD
8HyKxWSAnYTtCh/GUEQ37amIqvOJ5GNL+25WDzevLa5kMYWG743uxEupAoGBANrN
c/fVxepvP0GISlLpL3aZCFGAjMrq3xUYcf/w4wPoMq6AdpIPeRVBmJ1/Uqw1FkV8
NRKJNPE2YcMuv8iMeQlacoPd34KT9ob80EYVlMwAkeC0NK+FfiM/UteR0wB49gmi
ugX9YlJytOP9aUgPvEGT6l+XtgGC44W1TQWe62zzAoGBAKZenNU+0UjNb6isbToZ
Jjkkh1Vhm2PLg0I7hM6ZNTxf6r+rDtrXEajTvnocmxrmRo796r+W8immv09/jl6P
53l8rsIJ1xIqBYai+MNa29cyy6/zw0x++MVtwnlj8SUZubJEhVgAVbRAglKEnBBZ
iE48xnSJyKMG0uZuGePzJEmhAoGBAIOHJcNBumum3DuklikpC+MbMyjrQbdpYRjp
TP4x7AWZO34ysxQyQPNKL1feBfCHKRA0DiNKX4zwx+vw2lDQQKIiwNwMMCPqljOn
HfxDVOMdJJQTP+iTMrQ1iLMVceXC0QQR0glvu/8b/SlgWD19WAmDxUwZgst9xw/F
YLuUQKmJAoGAREeTugd4hc0U/YV/BQQjSCLhl11EtVry/oQMHj8KZpIJhP7tj8lw
hSE0+z04oMhiTeq55PYKQkTo5l6V4PW0zfpEwlKEEm0erab1G9Ddh7us47XFcKLl
Rmk192EVZ0lQuzftsYv7dzRLiAR7yDFXwD1ELIK/uPkwBtu7wtHlq+M=
-----END RSA PRIVATE KEY-----

View File

@@ -1,17 +0,0 @@
-----BEGIN CERTIFICATE REQUEST-----
MIICwjCCAaoCAQAwXjELMAkGA1UEBhMCQVUxEzARBgNVBAgTClNvbWUtU3RhdGUx
ITAfBgNVBAoTGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDEXMBUGA1UEAxMOY2Eu
bmdodHRwMi5vcmcwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDWRWQX
xBJTBb8dX0QVE9IyiI5WZjAHy+ooO1PR3owWIoAzz9gkVSra4qVTJ2BPgg8Ts8BO
9VwiPca0v1fM+Gxypg79LRjuxzJMTZUA+a3P5K09Z/bBnUhBHT0eucNNzjgq9gZm
l58FmQP1SNuYn1rVmYmMmIyveFOcoT+zFnb50yycxlc3zbZx9ofJM35PT5PLDm8E
FugIOxnPGZ/70UUgMk2zc0vfhxHwRlGGl9p6Bqkfxu04n4P5FnaSDsT9hiQZxLo2
h29ONJQUIUelaMcJ9MWGf+jAEgCigJ1aiuHp1zxDvaUCh3A0tdLy64+A+ozmzgLP
nubtmCzg6KU2Yh1rAgMBAAGgHzAdBgkqhkiG9w0BCQ4xEDAOMAwGA1UdEwQFMAMB
Af8wDQYJKoZIhvcNAQELBQADggEBACI5v8GbOXKv38h9/tuGEwJ9uxpYEljgGt8h
QL5lwfEifh/7A8b39b9JEzWk5hnMRCOb8J6Jc3/6nmVgtKkQ+Mceupqpwsp1gT/v
uUoAkJE03Iuja9zLhHmy74oZ7LWOQrZ1T7Z0eGQ+5u+LBZiPKnKxmkLCQoUPTbc4
NQ9BbKhr8OaoJ4DDvJnszcL7to6kih7SkdoNZsq4zB0/ai/cPhvoVgkYfbLH2++D
Tcs7TqU2L7gKzqXUtHeAKM2y81ewL7QTrcYzgiW86s3NmquxZG5pq0mjD+P4BYLc
MOdnCxKbBuE/1R29pa6+JKgc46jOa2yRgv5+8rXkkpu53Ke3FGc=
-----END CERTIFICATE REQUEST-----

View File

@@ -1,17 +0,0 @@
{
"CN": "ca.nghttp2.org",
"key": {
"algo": "rsa",
"size": 2048
},
"ca": {
"expiry": "87600h"
},
"names": [
{
"C": "AU",
"ST": "Some-State",
"O": "Internet Widgits Pty Ltd"
}
]
}

View File

@@ -1,22 +0,0 @@
-----BEGIN CERTIFICATE-----
MIIDrTCCApWgAwIBAgIUe4dvx8haIjsT3ZpNCMrl62Xk6E0wDQYJKoZIhvcNAQEL
BQAwXjELMAkGA1UEBhMCQVUxEzARBgNVBAgTClNvbWUtU3RhdGUxITAfBgNVBAoT
GEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDEXMBUGA1UEAxMOY2EubmdodHRwMi5v
cmcwHhcNMTYwNjI1MDkzMzAwWhcNMjYwNjIzMDkzMzAwWjBeMQswCQYDVQQGEwJB
VTETMBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0
cyBQdHkgTHRkMRcwFQYDVQQDEw5jYS5uZ2h0dHAyLm9yZzCCASIwDQYJKoZIhvcN
AQEBBQADggEPADCCAQoCggEBANZFZBfEElMFvx1fRBUT0jKIjlZmMAfL6ig7U9He
jBYigDPP2CRVKtripVMnYE+CDxOzwE71XCI9xrS/V8z4bHKmDv0tGO7HMkxNlQD5
rc/krT1n9sGdSEEdPR65w03OOCr2BmaXnwWZA/VI25ifWtWZiYyYjK94U5yhP7MW
dvnTLJzGVzfNtnH2h8kzfk9Pk8sObwQW6Ag7Gc8Zn/vRRSAyTbNzS9+HEfBGUYaX
2noGqR/G7Tifg/kWdpIOxP2GJBnEujaHb040lBQhR6Voxwn0xYZ/6MASAKKAnVqK
4enXPEO9pQKHcDS10vLrj4D6jObOAs+e5u2YLODopTZiHWsCAwEAAaNjMGEwDgYD
VR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFNA5xVR1Zcax
RJL9VC6pzuLmvduGMB8GA1UdIwQYMBaAFNA5xVR1ZcaxRJL9VC6pzuLmvduGMA0G
CSqGSIb3DQEBCwUAA4IBAQCmdVfn/hUyEdvkKG7svg5d8o6BENOj8695KtWmzJjK
zxH8J5Vy3mn89XrHQ+BOYXCDPyhs0aDS8aq3Z+HY0n9z1oAicyGzlVwZQQNX3YId
Y2vcf7qu/2ATm/1S+mebE1/EXMUlWISKKUYXjggCwFgjDhH87Ai+A8MKScVdmqgL
Hf+fRSzH3ToW7BCXlRl5bPAq2g+v1ALYc8wU9cT1MYm4dqAXh870LGFyUpaSWmFr
TtX1DXBTgLp62syNlDthAvGigYFDtCa4cDM2vdTD9wpec2V9EKpfVqiRDDuYjUVX
UXl27MvkNWnEBKCIoNv5abWXpZVG2zQdEMmUOkVuAXUC
-----END CERTIFICATE-----

View File

@@ -181,9 +181,7 @@ static int deflate_hd_json(json_t *obj, nghttp2_hd_deflater *deflater,
static nghttp2_hd_deflater *init_deflater() { static nghttp2_hd_deflater *init_deflater() {
nghttp2_hd_deflater *deflater; nghttp2_hd_deflater *deflater;
nghttp2_hd_deflate_new(&deflater, config.deflate_table_size); nghttp2_hd_deflate_new(&deflater, config.deflate_table_size);
if (config.table_size != NGHTTP2_DEFAULT_HEADER_TABLE_SIZE) { nghttp2_hd_deflate_change_table_size(deflater, config.table_size);
nghttp2_hd_deflate_change_table_size(deflater, config.table_size);
}
return deflater; return deflater;
} }
@@ -369,8 +367,7 @@ OPTIONS:
buffer. buffer.
Default: 4096 Default: 4096
-d, --dump-header-table -d, --dump-header-table
Output dynamic header table.)" Output dynamic header table.)" << std::endl;
<< std::endl;
} }
static struct option long_options[] = { static struct option long_options[] = {

View File

@@ -92,8 +92,6 @@ Config::Config()
conn_active_timeout(0.), conn_active_timeout(0.),
conn_inactivity_timeout(0.), conn_inactivity_timeout(0.),
no_tls_proto(PROTO_HTTP2), no_tls_proto(PROTO_HTTP2),
header_table_size(4_k),
encoder_header_table_size(4_k),
data_fd(-1), data_fd(-1),
port(0), port(0),
default_port(0), default_port(0),
@@ -271,7 +269,7 @@ bool check_stop_client_request_timeout(Client *client, ev_timer *w) {
auto nreq = client->req_todo - client->req_started; auto nreq = client->req_todo - client->req_started;
if (nreq == 0 || if (nreq == 0 ||
client->streams.size() >= client->session->max_concurrent_streams()) { client->streams.size() >= (size_t)config.max_concurrent_streams) {
// no more requests to make, stop timer // no more requests to make, stop timer
ev_timer_stop(client->worker->loop, w); ev_timer_stop(client->worker->loop, w);
return true; return true;
@@ -320,8 +318,7 @@ void client_request_timeout_cb(struct ev_loop *loop, ev_timer *w, int revents) {
} // namespace } // namespace
Client::Client(uint32_t id, Worker *worker, size_t req_todo) Client::Client(uint32_t id, Worker *worker, size_t req_todo)
: wb(&worker->mcpool), : cstat{},
cstat{},
worker(worker), worker(worker),
ssl(nullptr), ssl(nullptr),
next_addr(config.addrs), next_addr(config.addrs),
@@ -333,8 +330,7 @@ Client::Client(uint32_t id, Worker *worker, size_t req_todo)
req_done(0), req_done(0),
id(id), id(id),
fd(-1), fd(-1),
new_connection_requested(false), new_connection_requested(false) {
final(false) {
ev_io_init(&wev, writecb, 0, EV_WRITE); ev_io_init(&wev, writecb, 0, EV_WRITE);
ev_io_init(&rev, readcb, 0, EV_READ); ev_io_init(&rev, readcb, 0, EV_READ);
@@ -522,8 +518,6 @@ void Client::disconnect() {
close(fd); close(fd);
fd = -1; fd = -1;
} }
final = false;
} }
int Client::submit_request() { int Client::submit_request() {
@@ -866,7 +860,7 @@ int Client::connection_made() {
if (!config.timing_script) { if (!config.timing_script) {
auto nreq = auto nreq =
std::min(req_todo - req_started, session->max_concurrent_streams()); std::min(req_todo - req_started, (size_t)config.max_concurrent_streams);
for (; nreq > 0; --nreq) { for (; nreq > 0; --nreq) {
if (submit_request() != 0) { if (submit_request() != 0) {
process_request_failure(); process_request_failure();
@@ -913,10 +907,6 @@ int Client::on_read(const uint8_t *data, size_t len) {
} }
int Client::on_write() { int Client::on_write() {
if (wb.rleft() >= BACKOFF_WRITE_BUFFER_THRES) {
return 0;
}
if (session->on_write() != 0) { if (session->on_write() != 0) {
return -1; return -1;
} }
@@ -950,32 +940,28 @@ int Client::read_clear() {
} }
int Client::write_clear() { int Client::write_clear() {
std::array<struct iovec, 2> iov;
for (;;) { for (;;) {
if (wb.rleft() > 0) {
ssize_t nwrite;
while ((nwrite = write(fd, wb.pos, wb.rleft())) == -1 && errno == EINTR)
;
if (nwrite == -1) {
if (errno == EAGAIN || errno == EWOULDBLOCK) {
ev_io_start(worker->loop, &wev);
return 0;
}
return -1;
}
wb.drain(nwrite);
continue;
}
wb.reset();
if (on_write() != 0) { if (on_write() != 0) {
return -1; return -1;
} }
if (wb.rleft() == 0) {
auto iovcnt = wb.riovec(iov.data(), iov.size());
if (iovcnt == 0) {
break; break;
} }
ssize_t nwrite;
while ((nwrite = writev(fd, iov.data(), iovcnt)) == -1 && errno == EINTR)
;
if (nwrite == -1) {
if (errno == EAGAIN || errno == EWOULDBLOCK) {
ev_io_start(worker->loop, &wev);
return 0;
}
return -1;
}
wb.drain(nwrite);
} }
ev_io_stop(worker->loop, &wev); ev_io_stop(worker->loop, &wev);
@@ -1068,36 +1054,35 @@ int Client::read_tls() {
int Client::write_tls() { int Client::write_tls() {
ERR_clear_error(); ERR_clear_error();
struct iovec iov;
for (;;) { for (;;) {
if (wb.rleft() > 0) {
auto rv = SSL_write(ssl, wb.pos, wb.rleft());
if (rv <= 0) {
auto err = SSL_get_error(ssl, rv);
switch (err) {
case SSL_ERROR_WANT_READ:
// renegotiation started
return -1;
case SSL_ERROR_WANT_WRITE:
ev_io_start(worker->loop, &wev);
return 0;
default:
return -1;
}
}
wb.drain(rv);
continue;
}
wb.reset();
if (on_write() != 0) { if (on_write() != 0) {
return -1; return -1;
} }
if (wb.rleft() == 0) {
auto iovcnt = wb.riovec(&iov, 1);
if (iovcnt == 0) {
break; break;
} }
auto rv = SSL_write(ssl, iov.iov_base, iov.iov_len);
if (rv <= 0) {
auto err = SSL_get_error(ssl, rv);
switch (err) {
case SSL_ERROR_WANT_READ:
// renegotiation started
return -1;
case SSL_ERROR_WANT_WRITE:
ev_io_start(worker->loop, &wev);
return 0;
default:
return -1;
}
}
wb.drain(rv);
} }
ev_io_stop(worker->loop, &wev); ev_io_stop(worker->loop, &wev);
@@ -1339,8 +1324,7 @@ process_time_stats(const std::vector<std::unique_ptr<Worker>> &workers) {
} }
request_times.push_back( request_times.push_back(
std::chrono::duration_cast<std::chrono::duration<double>>( std::chrono::duration_cast<std::chrono::duration<double>>(
req_stat.stream_close_time - req_stat.request_time) req_stat.stream_close_time - req_stat.request_time).count());
.count());
} }
const auto &stat = w->stats; const auto &stat = w->stats;
@@ -1349,8 +1333,7 @@ process_time_stats(const std::vector<std::unique_ptr<Worker>> &workers) {
if (recorded(cstat.client_start_time) && if (recorded(cstat.client_start_time) &&
recorded(cstat.client_end_time)) { recorded(cstat.client_end_time)) {
auto t = std::chrono::duration_cast<std::chrono::duration<double>>( auto t = std::chrono::duration_cast<std::chrono::duration<double>>(
cstat.client_end_time - cstat.client_start_time) cstat.client_end_time - cstat.client_start_time).count();
.count();
if (t > 1e-9) { if (t > 1e-9) {
rps_values.push_back(cstat.req_success / t); rps_values.push_back(cstat.req_success / t);
} }
@@ -1364,8 +1347,7 @@ process_time_stats(const std::vector<std::unique_ptr<Worker>> &workers) {
connect_times.push_back( connect_times.push_back(
std::chrono::duration_cast<std::chrono::duration<double>>( std::chrono::duration_cast<std::chrono::duration<double>>(
cstat.connect_time - cstat.connect_start_time) cstat.connect_time - cstat.connect_start_time).count());
.count());
if (!recorded(cstat.ttfb)) { if (!recorded(cstat.ttfb)) {
continue; continue;
@@ -1373,8 +1355,7 @@ process_time_stats(const std::vector<std::unique_ptr<Worker>> &workers) {
ttfb_times.push_back( ttfb_times.push_back(
std::chrono::duration_cast<std::chrono::duration<double>>( std::chrono::duration_cast<std::chrono::duration<double>>(
cstat.ttfb - cstat.connect_start_time) cstat.ttfb - cstat.connect_start_time).count());
.count());
} }
} }
@@ -1591,27 +1572,6 @@ std::unique_ptr<Worker> create_worker(uint32_t id, SSL_CTX *ssl_ctx,
} }
} // namespace } // namespace
namespace {
int parse_header_table_size(uint32_t &dst, const char *opt,
const char *optarg) {
auto n = util::parse_uint_with_unit(optarg);
if (n == -1) {
std::cerr << "--" << opt << ": Bad option value: " << optarg << std::endl;
return -1;
}
if (n > std::numeric_limits<uint32_t>::max()) {
std::cerr << "--" << opt
<< ": Value too large. It should be less than or equal to "
<< std::numeric_limits<uint32_t>::max() << std::endl;
return -1;
}
dst = n;
return 0;
}
} // namespace
namespace { namespace {
void print_version(std::ostream &out) { void print_version(std::ostream &out) {
out << "h2load nghttp2/" NGHTTP2_VERSION << std::endl; out << "h2load nghttp2/" NGHTTP2_VERSION << std::endl;
@@ -1621,8 +1581,7 @@ void print_version(std::ostream &out) {
namespace { namespace {
void print_usage(std::ostream &out) { void print_usage(std::ostream &out) {
out << R"(Usage: h2load [OPTIONS]... [URI]... out << R"(Usage: h2load [OPTIONS]... [URI]...
benchmarking tool for HTTP/2 and SPDY server)" benchmarking tool for HTTP/2 and SPDY server)" << std::endl;
<< std::endl;
} }
} // namespace } // namespace
@@ -1654,17 +1613,14 @@ Options:
with --timing-script-file option, this option specifies with --timing-script-file option, this option specifies
the number of requests each client performs rather than the number of requests each client performs rather than
the number of requests across all clients. the number of requests across all clients.
Default: )" Default: )" << config.nreqs << R"(
<< config.nreqs << R"(
-c, --clients=<N> -c, --clients=<N>
Number of concurrent clients. With -r option, this Number of concurrent clients. With -r option, this
specifies the maximum number of connections to be made. specifies the maximum number of connections to be made.
Default: )" Default: )" << config.nclients << R"(
<< config.nclients << R"(
-t, --threads=<N> -t, --threads=<N>
Number of native threads. Number of native threads.
Default: )" Default: )" << config.nthreads << R"(
<< config.nthreads << R"(
-i, --input-file=<PATH> -i, --input-file=<PATH>
Path of a file with multiple URIs are separated by EOLs. Path of a file with multiple URIs are separated by EOLs.
This option will disable URIs getting from command-line. This option will disable URIs getting from command-line.
@@ -1683,15 +1639,13 @@ Options:
-w, --window-bits=<N> -w, --window-bits=<N>
Sets the stream level initial window size to (2**<N>)-1. Sets the stream level initial window size to (2**<N>)-1.
For SPDY, 2**<N> is used instead. For SPDY, 2**<N> is used instead.
Default: )" Default: )" << config.window_bits << R"(
<< config.window_bits << R"(
-W, --connection-window-bits=<N> -W, --connection-window-bits=<N>
Sets the connection level initial window size to Sets the connection level initial window size to
(2**<N>)-1. For SPDY, if <N> is strictly less than 16, (2**<N>)-1. For SPDY, if <N> is strictly less than 16,
this option is ignored. Otherwise 2**<N> is used for this option is ignored. Otherwise 2**<N> is used for
SPDY. SPDY.
Default: )" Default: )" << config.connection_window_bits << R"(
<< config.connection_window_bits << R"(
-H, --header=<HEADER> -H, --header=<HEADER>
Add/Override a header to the requests. Add/Override a header to the requests.
--ciphers=<SUITE> --ciphers=<SUITE>
@@ -1709,15 +1663,11 @@ Options:
Available protocols: )"; Available protocols: )";
#endif // !HAVE_SPDYLAY #endif // !HAVE_SPDYLAY
out << NGHTTP2_CLEARTEXT_PROTO_VERSION_ID << R"( and out << NGHTTP2_CLEARTEXT_PROTO_VERSION_ID << R"( and
)" )" << NGHTTP2_H1_1 << R"(
<< NGHTTP2_H1_1 << R"( Default: )" << NGHTTP2_CLEARTEXT_PROTO_VERSION_ID << R"(
Default: )"
<< NGHTTP2_CLEARTEXT_PROTO_VERSION_ID << R"(
-d, --data=<PATH> -d, --data=<PATH>
Post FILE to server. The request method is changed to Post FILE to server. The request method is changed to
POST. For http/1.1 connection, if -d is used, the POST.
maximum number of in-flight pipelined requests is set to
1.
-r, --rate=<N> -r, --rate=<N>
Specifies the fixed rate at which connections are Specifies the fixed rate at which connections are
created. The rate must be a positive integer, created. The rate must be a positive integer,
@@ -1786,22 +1736,10 @@ Options:
NPN. The parameter must be delimited by a single comma NPN. The parameter must be delimited by a single comma
only and any white spaces are treated as a part of only and any white spaces are treated as a part of
protocol string. protocol string.
Default: )" Default: )" << DEFAULT_NPN_LIST << R"(
<< DEFAULT_NPN_LIST << R"(
--h1 Short hand for --npn-list=http/1.1 --h1 Short hand for --npn-list=http/1.1
--no-tls-proto=http/1.1, which effectively force --no-tls-proto=http/1.1, which effectively force
http/1.1 for both http and https URI. http/1.1 for both http and https URI.
--header-table-size=<SIZE>
Specify decoder header table size.
Default: )"
<< util::utos_unit(config.header_table_size) << R"(
--encoder-header-table-size=<SIZE>
Specify encoder header table size. The decoder (server)
specifies the maximum dynamic table size it accepts.
Then the negotiated dynamic table size is the minimum of
this option value and the value which server specified.
Default: )"
<< util::utos_unit(config.encoder_header_table_size) << R"(
-v, --verbose -v, --verbose
Output debug information. Output debug information.
--version Display version information and exit. --version Display version information and exit.
@@ -1809,14 +1747,10 @@ Options:
-- --
The <SIZE> argument is an integer and an optional unit (e.g., 10K is
10 * 1024). Units are K, M and G (powers of 1024).
The <DURATION> argument is an integer and an optional unit (e.g., 1s The <DURATION> argument is an integer and an optional unit (e.g., 1s
is 1 second and 500ms is 500 milliseconds). Units are h, m, s or ms is 1 second and 500ms is 500 milliseconds). Units are h, m, s or ms
(hours, minutes, seconds and milliseconds, respectively). If a unit (hours, minutes, seconds and milliseconds, respectively). If a unit
is omitted, a second is used as unit.)" is omitted, a second is used as unit.)" << std::endl;
<< std::endl;
} }
} // namespace } // namespace
@@ -1854,8 +1788,6 @@ int main(int argc, char **argv) {
{"npn-list", required_argument, &flag, 4}, {"npn-list", required_argument, &flag, 4},
{"rate-period", required_argument, &flag, 5}, {"rate-period", required_argument, &flag, 5},
{"h1", no_argument, &flag, 6}, {"h1", no_argument, &flag, 6},
{"header-table-size", required_argument, &flag, 7},
{"encoder-header-table-size", required_argument, &flag, 8},
{nullptr, 0, nullptr, 0}}; {nullptr, 0, nullptr, 0}};
int option_index = 0; int option_index = 0;
auto c = getopt_long(argc, argv, "hvW:c:d:m:n:p:t:w:H:i:r:T:N:B:", auto c = getopt_long(argc, argv, "hvW:c:d:m:n:p:t:w:H:i:r:T:N:B:",
@@ -2056,20 +1988,6 @@ int main(int argc, char **argv) {
util::parse_config_str_list(StringRef::from_lit("http/1.1")); util::parse_config_str_list(StringRef::from_lit("http/1.1"));
config.no_tls_proto = Config::PROTO_HTTP1_1; config.no_tls_proto = Config::PROTO_HTTP1_1;
break; break;
case 7:
// --header-table-size
if (parse_header_table_size(config.header_table_size,
"header-table-size", optarg) != 0) {
exit(EXIT_FAILURE);
}
break;
case 8:
// --encoder-header-table-size
if (parse_header_table_size(config.encoder_header_table_size,
"encoder-header-table-size", optarg) != 0) {
exit(EXIT_FAILURE);
}
break;
} }
break; break;
default: default:
@@ -2137,8 +2055,7 @@ int main(int argc, char **argv) {
if (config.nreqs > uris.size()) { if (config.nreqs > uris.size()) {
std::cerr << "-n: the number of requests must be less than or equal " std::cerr << "-n: the number of requests must be less than or equal "
"to the number of timing script entries. Setting number " "to the number of timing script entries. Setting number "
"of requests to " "of requests to " << uris.size() << std::endl;
<< uris.size() << std::endl;
config.nreqs = uris.size(); config.nreqs = uris.size();
} }
@@ -2188,8 +2105,7 @@ int main(int argc, char **argv) {
if (config.nclients < config.nthreads) { if (config.nclients < config.nthreads) {
std::cerr << "-c, -t: the number of clients must be greater than or equal " std::cerr << "-c, -t: the number of clients must be greater than or equal "
"to the number of threads." "to the number of threads." << std::endl;
<< std::endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
@@ -2202,8 +2118,7 @@ int main(int argc, char **argv) {
if (config.rate > config.nclients) { if (config.rate > config.nclients) {
std::cerr << "-r, -c: the connection rate must be smaller than or equal " std::cerr << "-r, -c: the connection rate must be smaller than or equal "
"to the number of clients." "to the number of clients." << std::endl;
<< std::endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
} }
@@ -2299,11 +2214,6 @@ int main(int argc, char **argv) {
} }
} }
std::string content_length_str;
if (config.data_fd != -1) {
content_length_str = util::utos(config.data_length);
}
auto method_it = auto method_it =
std::find_if(std::begin(shared_nva), std::end(shared_nva), std::find_if(std::begin(shared_nva), std::end(shared_nva),
[](const Header &nv) { return nv.name == ":method"; }); [](const Header &nv) { return nv.name == ":method"; });
@@ -2334,20 +2244,14 @@ int main(int argc, char **argv) {
h1req += nv.value; h1req += nv.value;
h1req += "\r\n"; h1req += "\r\n";
} }
if (!content_length_str.empty()) {
h1req += "Content-Length: ";
h1req += content_length_str;
h1req += "\r\n";
}
h1req += "\r\n"; h1req += "\r\n";
config.h1reqs.push_back(std::move(h1req)); config.h1reqs.push_back(std::move(h1req));
// For nghttp2 // For nghttp2
std::vector<nghttp2_nv> nva; std::vector<nghttp2_nv> nva;
// 2 for :path, and possible content-length // 1 for :path
nva.reserve(2 + shared_nva.size()); nva.reserve(1 + shared_nva.size());
nva.push_back(http2::make_nv_ls(":path", req)); nva.push_back(http2::make_nv_ls(":path", req));
@@ -2355,18 +2259,12 @@ int main(int argc, char **argv) {
nva.push_back(http2::make_nv(nv.name, nv.value, false)); nva.push_back(http2::make_nv(nv.name, nv.value, false));
} }
if (!content_length_str.empty()) {
nva.push_back(http2::make_nv(StringRef::from_lit("content-length"),
StringRef{content_length_str}));
}
config.nva.push_back(std::move(nva)); config.nva.push_back(std::move(nva));
// For spdylay // For spdylay
std::vector<const char *> cva; std::vector<const char *> cva;
// 3 for :path, :version, and possible content-length, 1 for // 2 for :path and :version, 1 for terminal nullptr
// terminal nullptr cva.reserve(2 * (2 + shared_nva.size()) + 1);
cva.reserve(2 * (3 + shared_nva.size()) + 1);
cva.push_back(":path"); cva.push_back(":path");
cva.push_back(req.c_str()); cva.push_back(req.c_str());
@@ -2381,12 +2279,6 @@ int main(int argc, char **argv) {
} }
cva.push_back(":version"); cva.push_back(":version");
cva.push_back("HTTP/1.1"); cva.push_back("HTTP/1.1");
if (!content_length_str.empty()) {
cva.push_back("content-length");
cva.push_back(content_length_str.c_str());
}
cva.push_back(nullptr); cva.push_back(nullptr);
config.nv.push_back(std::move(cva)); config.nv.push_back(std::move(cva));
@@ -2550,29 +2442,26 @@ int main(int argc, char **argv) {
} }
std::cout << std::fixed << std::setprecision(2) << R"( std::cout << std::fixed << std::setprecision(2) << R"(
finished in )" finished in )" << util::format_duration(duration) << ", " << rps << " req/s, "
<< util::format_duration(duration) << ", " << rps << " req/s, "
<< util::utos_funit(bps) << R"(B/s << util::utos_funit(bps) << R"(B/s
requests: )" << stats.req_todo requests: )" << stats.req_todo << " total, " << stats.req_started
<< " total, " << stats.req_started << " started, " << stats.req_done << " started, " << stats.req_done << " done, "
<< " done, " << stats.req_status_success << " succeeded, " << stats.req_status_success << " succeeded, " << stats.req_failed
<< stats.req_failed << " failed, " << stats.req_error << " failed, " << stats.req_error << " errored, "
<< " errored, " << stats.req_timedout << R"( timeout << stats.req_timedout << R"( timeout
status codes: )" status codes: )" << stats.status[2] << " 2xx, " << stats.status[3] << " 3xx, "
<< stats.status[2] << " 2xx, " << stats.status[3] << " 3xx, "
<< stats.status[4] << " 4xx, " << stats.status[5] << R"( 5xx << stats.status[4] << " 4xx, " << stats.status[5] << R"( 5xx
traffic: )" << util::utos_funit(stats.bytes_total) traffic: )" << util::utos_funit(stats.bytes_total) << "B (" << stats.bytes_total
<< "B (" << stats.bytes_total << ") total, " << ") total, " << util::utos_funit(stats.bytes_head) << "B ("
<< util::utos_funit(stats.bytes_head) << "B (" << stats.bytes_head << stats.bytes_head << ") headers (space savings "
<< ") headers (space savings " << header_space_savings * 100 << header_space_savings * 100 << "%), "
<< "%), " << util::utos_funit(stats.bytes_body) << "B (" << util::utos_funit(stats.bytes_body) << "B (" << stats.bytes_body
<< stats.bytes_body << R"() data << R"() data
min max mean sd +/- sd min max mean sd +/- sd
time for request: )" time for request: )" << std::setw(10) << util::format_duration(ts.request.min)
<< std::setw(10) << util::format_duration(ts.request.min) << " " << " " << std::setw(10) << util::format_duration(ts.request.max)
<< std::setw(10) << util::format_duration(ts.request.max) << " " << " " << std::setw(10) << util::format_duration(ts.request.mean)
<< std::setw(10) << util::format_duration(ts.request.mean) << " " << " " << std::setw(10) << util::format_duration(ts.request.sd)
<< std::setw(10) << util::format_duration(ts.request.sd)
<< std::setw(9) << util::dtos(ts.request.within_sd) << "%" << std::setw(9) << util::dtos(ts.request.within_sd) << "%"
<< "\ntime for connect: " << std::setw(10) << "\ntime for connect: " << std::setw(10)
<< util::format_duration(ts.connect.min) << " " << std::setw(10) << util::format_duration(ts.connect.min) << " " << std::setw(10)

View File

@@ -50,15 +50,13 @@
#include <openssl/ssl.h> #include <openssl/ssl.h>
#include "http2.h" #include "http2.h"
#include "memchunk.h" #include "buffer.h"
#include "template.h" #include "template.h"
using namespace nghttp2; using namespace nghttp2;
namespace h2load { namespace h2load {
constexpr auto BACKOFF_WRITE_BUFFER_THRES = 16_k;
class Session; class Session;
struct Worker; struct Worker;
@@ -96,8 +94,6 @@ struct Config {
PROTO_SPDY3_1, PROTO_SPDY3_1,
PROTO_HTTP1_1 PROTO_HTTP1_1
} no_tls_proto; } no_tls_proto;
uint32_t header_table_size;
uint32_t encoder_header_table_size;
// file descriptor for upload data // file descriptor for upload data
int data_fd; int data_fd;
uint16_t port; uint16_t port;
@@ -229,7 +225,6 @@ struct Sampling {
}; };
struct Worker { struct Worker {
MemchunkPool mcpool;
Stats stats; Stats stats;
Sampling request_times_smp; Sampling request_times_smp;
Sampling client_smp; Sampling client_smp;
@@ -272,7 +267,6 @@ struct Stream {
}; };
struct Client { struct Client {
DefaultMemchunks wb;
std::unordered_map<int32_t, Stream> streams; std::unordered_map<int32_t, Stream> streams;
ClientStat cstat; ClientStat cstat;
std::unique_ptr<Session> session; std::unique_ptr<Session> session;
@@ -299,13 +293,11 @@ struct Client {
// The client id per worker // The client id per worker
uint32_t id; uint32_t id;
int fd; int fd;
Buffer<64_k> wb;
ev_timer conn_active_watcher; ev_timer conn_active_watcher;
ev_timer conn_inactivity_watcher; ev_timer conn_inactivity_watcher;
std::string selected_proto; std::string selected_proto;
bool new_connection_requested; bool new_connection_requested;
// true if the current connection will be closed, and no more new
// request cannot be processed.
bool final;
enum { ERR_CONNECT_FAIL = -100 }; enum { ERR_CONNECT_FAIL = -100 };

View File

@@ -57,7 +57,7 @@ namespace {
int htp_msg_begincb(http_parser *htp) { int htp_msg_begincb(http_parser *htp) {
auto session = static_cast<Http1Session *>(htp->data); auto session = static_cast<Http1Session *>(htp->data);
if (session->stream_resp_counter_ > session->stream_req_counter_) { if (session->stream_resp_counter_ >= session->stream_req_counter_) {
return -1; return -1;
} }
@@ -82,21 +82,16 @@ int htp_msg_completecb(http_parser *htp) {
auto session = static_cast<Http1Session *>(htp->data); auto session = static_cast<Http1Session *>(htp->data);
auto client = session->get_client(); auto client = session->get_client();
client->final = http_should_keep_alive(htp) == 0; auto final = http_should_keep_alive(htp) == 0;
auto req_stat = client->get_req_stat(session->stream_resp_counter_); auto req_stat = client->get_req_stat(session->stream_resp_counter_);
assert(req_stat); assert(req_stat);
auto config = client->worker->config; client->on_stream_close(session->stream_resp_counter_, true, final);
if (req_stat->data_offset >= config->data_length) {
client->on_stream_close(session->stream_resp_counter_, true, client->final);
}
session->stream_resp_counter_ += 2; session->stream_resp_counter_ += 2;
if (client->final) { if (final) {
session->stream_req_counter_ = session->stream_resp_counter_;
http_parser_pause(htp, 1); http_parser_pause(htp, 1);
// Connection is going down. If we have still request to do, // Connection is going down. If we have still request to do,
// create new connection and keep on doing the job. // create new connection and keep on doing the job.
@@ -174,16 +169,12 @@ int Http1Session::submit_request() {
auto req_stat = client_->get_req_stat(stream_req_counter_); auto req_stat = client_->get_req_stat(stream_req_counter_);
client_->record_request_time(req_stat); client_->record_request_time(req_stat);
client_->wb.append(req); client_->wb.write(req.c_str(), req.size());
if (config->data_fd == -1 || config->data_length == 0) { // increment for next request
// increment for next request stream_req_counter_ += 2;
stream_req_counter_ += 2;
return 0; return 0;
}
return on_write();
} }
int Http1Session::on_read(const uint8_t *data, size_t len) { int Http1Session::on_read(const uint8_t *data, size_t len) {
@@ -215,51 +206,6 @@ int Http1Session::on_write() {
if (complete_) { if (complete_) {
return -1; return -1;
} }
auto config = client_->worker->config;
auto req_stat = client_->get_req_stat(stream_req_counter_);
if (!req_stat) {
return 0;
}
if (req_stat->data_offset < config->data_length) {
auto req_stat = client_->get_req_stat(stream_req_counter_);
auto &wb = client_->wb;
// TODO unfortunately, wb has no interface to use with read(2)
// family functions.
std::array<uint8_t, 16_k> buf;
ssize_t nread;
while ((nread = pread(config->data_fd, buf.data(), buf.size(),
req_stat->data_offset)) == -1 &&
errno == EINTR)
;
if (nread == -1) {
return -1;
}
req_stat->data_offset += nread;
wb.append(buf.data(), nread);
if (client_->worker->config->verbose) {
std::cout << "[send " << nread << " byte(s)]" << std::endl;
}
if (req_stat->data_offset == config->data_length) {
// increment for next request
stream_req_counter_ += 2;
if (stream_resp_counter_ == stream_req_counter_) {
// Response has already been received
client_->on_stream_close(stream_resp_counter_ - 2, true,
client_->final);
}
}
}
return 0; return 0;
} }
@@ -267,10 +213,4 @@ void Http1Session::terminate() { complete_ = true; }
Client *Http1Session::get_client() { return client_; } Client *Http1Session::get_client() { return client_; }
size_t Http1Session::max_concurrent_streams() {
auto config = client_->worker->config;
return config->data_fd == -1 ? config->max_concurrent_streams : 1;
}
} // namespace h2load } // namespace h2load

Some files were not shown because too many files have changed in this diff Show More