mirror of
https://github.com/nghttp2/nghttp2.git
synced 2025-12-07 18:48:54 +08:00
Compare commits
99 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c5e087b103 | ||
|
|
fb65839653 | ||
|
|
1da27af832 | ||
|
|
c29ac85281 | ||
|
|
1b5fe4a477 | ||
|
|
cdf01d1af8 | ||
|
|
2e54284906 | ||
|
|
b13c97f04f | ||
|
|
c817b2a3e0 | ||
|
|
a354577eff | ||
|
|
09a95983b9 | ||
|
|
25d6df290e | ||
|
|
bd9edc8e76 | ||
|
|
b28998694b | ||
|
|
0b5008eee3 | ||
|
|
a6d128836d | ||
|
|
ea4e5cec19 | ||
|
|
bfeb1ee182 | ||
|
|
2b28011c86 | ||
|
|
66c5ea2216 | ||
|
|
66abd8cbd3 | ||
|
|
a142e81994 | ||
|
|
97b7012ccd | ||
|
|
39d293551a | ||
|
|
fe56b875b4 | ||
|
|
d1035d439a | ||
|
|
532791209e | ||
|
|
ed0b7864d7 | ||
|
|
d2ca281ca1 | ||
|
|
3792c573cd | ||
|
|
ab8ee3fbce | ||
|
|
c2cfab6d9c | ||
|
|
a99667350e | ||
|
|
053703eeab | ||
|
|
3a4e26247b | ||
|
|
a25f19560c | ||
|
|
2af27bb921 | ||
|
|
731c7c0f92 | ||
|
|
b487cf1d19 | ||
|
|
41a2f6de00 | ||
|
|
075254e5a0 | ||
|
|
3daa0de1e6 | ||
|
|
972e372402 | ||
|
|
65c91ba729 | ||
|
|
3ffade5f8a | ||
|
|
33ad4cc2b8 | ||
|
|
f029a09cef | ||
|
|
9468b16f1e | ||
|
|
d4b19d7a5a | ||
|
|
632292731f | ||
|
|
89500e2ab3 | ||
|
|
bc1c6c07b3 | ||
|
|
2fdb959ea1 | ||
|
|
93c4d8bc34 | ||
|
|
504633eadd | ||
|
|
3884aa166e | ||
|
|
ec7abfeabb | ||
|
|
de79d05ad9 | ||
|
|
8b4fd9bd13 | ||
|
|
be8a327258 | ||
|
|
58c1e2bb55 | ||
|
|
5d0a2f5fdb | ||
|
|
4f5a769d01 | ||
|
|
8df2c0090d | ||
|
|
c92aabb6e6 | ||
|
|
c00c44abbe | ||
|
|
92582ce519 | ||
|
|
1291b76986 | ||
|
|
6d291e98e0 | ||
|
|
68498a307c | ||
|
|
a7d73d90db | ||
|
|
69fd5b557d | ||
|
|
3792abd447 | ||
|
|
d55323e575 | ||
|
|
96104d0895 | ||
|
|
2f7dd5ec65 | ||
|
|
8c0fe8f93f | ||
|
|
85ccbd4f95 | ||
|
|
f3b142293c | ||
|
|
4b34dd1965 | ||
|
|
4ae7fe91d6 | ||
|
|
41ac5f7e4e | ||
|
|
343dbafe7d | ||
|
|
5003886591 | ||
|
|
f7de260969 | ||
|
|
69daeb040c | ||
|
|
fdc53b1a76 | ||
|
|
b6247f5391 | ||
|
|
40983f461e | ||
|
|
80ba5ad341 | ||
|
|
0f3a369e12 | ||
|
|
d9edee47aa | ||
|
|
a65b0acd9e | ||
|
|
67c2c481ea | ||
|
|
57c1db3db4 | ||
|
|
cc963b4862 | ||
|
|
2bccc5cf70 | ||
|
|
93404696ac | ||
|
|
a0fc33ecd5 |
4
.github/dependabot.yml
vendored
4
.github/dependabot.yml
vendored
@@ -4,3 +4,7 @@ updates:
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
- package-ecosystem: "gomod"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
|
||||
82
.github/workflows/build.yml
vendored
82
.github/workflows/build.yml
vendored
@@ -7,11 +7,11 @@ permissions: read-all
|
||||
env:
|
||||
LIBBPF_VERSION: v1.3.0
|
||||
OPENSSL1_VERSION: 1_1_1w+quic
|
||||
OPENSSL3_VERSION: 3.1.4+quic
|
||||
BORINGSSL_VERSION: f42be90d665b6a376177648ccbb76fbbd6497c13
|
||||
AWSLC_VERSION: v1.20.0
|
||||
NGHTTP3_VERSION: v1.1.0
|
||||
NGTCP2_VERSION: v1.2.0
|
||||
OPENSSL3_VERSION: 3.1.5+quic
|
||||
BORINGSSL_VERSION: 8e6a26d128484b886e6dcbfa558b993d38950bb5
|
||||
AWSLC_VERSION: v1.21.0
|
||||
NGHTTP3_VERSION: v1.2.0
|
||||
NGTCP2_VERSION: v1.3.0
|
||||
|
||||
jobs:
|
||||
build-cache:
|
||||
@@ -25,26 +25,26 @@ jobs:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Restore libbpf cache
|
||||
id: cache-libbpf
|
||||
uses: actions/cache@v3
|
||||
uses: actions/cache@v4
|
||||
if: runner.os == 'Linux'
|
||||
with:
|
||||
path: libbpf/build
|
||||
key: ${{ runner.os }}-libbpf-${{ env.LIBBPF_VERSION }}
|
||||
- name: Restore OpenSSL v1.1.1 cache
|
||||
id: cache-openssl1
|
||||
uses: actions/cache@v3
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: openssl1/build
|
||||
key: ${{ runner.os }}-openssl-${{ env.OPENSSL1_VERSION }}
|
||||
- name: Restore OpenSSL v3.x cache
|
||||
id: cache-openssl3
|
||||
uses: actions/cache@v3
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: openssl3/build
|
||||
key: ${{ runner.os }}-openssl-${{ env.OPENSSL3_VERSION }}
|
||||
- name: Restore BoringSSL cache
|
||||
id: cache-boringssl
|
||||
uses: actions/cache@v3
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
boringssl/build/crypto/libcrypto.a
|
||||
@@ -53,7 +53,7 @@ jobs:
|
||||
key: ${{ runner.os }}-boringssl-${{ env.BORINGSSL_VERSION }}
|
||||
- name: Restore aws-lc cache
|
||||
id: cache-awslc
|
||||
uses: actions/cache@v3
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
aws-lc/build/crypto/libcrypto.a
|
||||
@@ -62,19 +62,19 @@ jobs:
|
||||
key: ${{ runner.os }}-awslc-${{ env.AWSLC_VERSION }}
|
||||
- name: Restore nghttp3 cache
|
||||
id: cache-nghttp3
|
||||
uses: actions/cache@v3
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: nghttp3/build
|
||||
key: ${{ runner.os }}-nghttp3-${{ env.NGHTTP3_VERSION }}
|
||||
- name: Restore ngtcp2 + quictls/openssl v1.1.1 cache
|
||||
id: cache-ngtcp2-openssl1
|
||||
uses: actions/cache@v3
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ngtcp2-openssl1/build
|
||||
key: ${{ runner.os }}-ngtcp2-${{ env.NGTCP2_VERSION }}-openssl-${{ env.OPENSSL1_VERSION }}
|
||||
- name: Restore ngtcp2 + quictls/openssl v3.x cache
|
||||
id: cache-ngtcp2-openssl3
|
||||
uses: actions/cache@v3
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ngtcp2-openssl3/build
|
||||
key: ${{ runner.os }}-ngtcp2-${{ env.NGTCP2_VERSION }}-openssl-${{ env.OPENSSL3_VERSION }}
|
||||
@@ -93,6 +93,7 @@ jobs:
|
||||
- name: Linux setup
|
||||
if: runner.os == 'Linux' && steps.settings.outputs.needs-build == 'true'
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install \
|
||||
g++-12 \
|
||||
clang-15 \
|
||||
@@ -137,8 +138,11 @@ jobs:
|
||||
- name: Build BoringSSL
|
||||
if: steps.cache-boringssl.outputs.cache-hit != 'true'
|
||||
run: |
|
||||
git clone https://boringssl.googlesource.com/boringssl
|
||||
mkdir boringssl
|
||||
cd boringssl
|
||||
git init
|
||||
git remote add origin https://boringssl.googlesource.com/boringssl
|
||||
git fetch origin --depth 1 ${{ env.BORINGSSL_VERSION }}
|
||||
git checkout ${{ env.BORINGSSL_VERSION }}
|
||||
mkdir build
|
||||
cd build
|
||||
@@ -156,6 +160,7 @@ jobs:
|
||||
run: |
|
||||
git clone --depth 1 -b ${{ env.NGHTTP3_VERSION}} https://github.com/ngtcp2/nghttp3
|
||||
cd nghttp3
|
||||
git submodule update --init --depth 1
|
||||
autoreconf -i
|
||||
./configure --prefix=$PWD/build --enable-lib-only
|
||||
make -j"$(nproc 2> /dev/null || sysctl -n hw.ncpu)" check
|
||||
@@ -165,6 +170,7 @@ jobs:
|
||||
run: |
|
||||
git clone --depth 1 -b ${{ env.NGTCP2_VERSION }} https://github.com/ngtcp2/ngtcp2 ngtcp2-openssl1
|
||||
cd ngtcp2-openssl1
|
||||
git submodule update --init --depth 1
|
||||
autoreconf -i
|
||||
./configure --prefix=$PWD/build --enable-lib-only \
|
||||
PKG_CONFIG_PATH="../openssl1/build/lib/pkgconfig" \
|
||||
@@ -178,6 +184,7 @@ jobs:
|
||||
run: |
|
||||
git clone --depth 1 -b ${{ env.NGTCP2_VERSION }} https://github.com/ngtcp2/ngtcp2 ngtcp2-openssl3
|
||||
cd ngtcp2-openssl3
|
||||
git submodule update --init --depth 1
|
||||
autoreconf -i
|
||||
./configure --prefix=$PWD/build --enable-lib-only \
|
||||
PKG_CONFIG_PATH="../openssl3/build/lib/pkgconfig" \
|
||||
@@ -228,6 +235,7 @@ jobs:
|
||||
- name: Linux setup
|
||||
if: runner.os == 'Linux'
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install \
|
||||
g++-12 \
|
||||
clang-15 \
|
||||
@@ -237,7 +245,6 @@ jobs:
|
||||
libtool \
|
||||
pkg-config \
|
||||
zlib1g-dev \
|
||||
libcunit1-dev \
|
||||
libssl-dev \
|
||||
libxml2-dev \
|
||||
libev-dev \
|
||||
@@ -246,6 +253,7 @@ jobs:
|
||||
libjemalloc-dev \
|
||||
libc-ares-dev \
|
||||
libelf-dev \
|
||||
libbrotli-dev \
|
||||
cmake \
|
||||
cmake-data
|
||||
echo 'CPPFLAGS=-fsanitize=address,undefined -fno-sanitize-recover=undefined -g' >> $GITHUB_ENV
|
||||
@@ -257,8 +265,8 @@ jobs:
|
||||
libev \
|
||||
libevent \
|
||||
c-ares \
|
||||
cunit \
|
||||
libressl \
|
||||
brotli \
|
||||
autoconf \
|
||||
automake \
|
||||
pkg-config \
|
||||
@@ -285,7 +293,7 @@ jobs:
|
||||
echo 'CC=gcc' >> $GITHUB_ENV
|
||||
echo 'CXX=g++' >> $GITHUB_ENV
|
||||
- name: Restore libbpf cache
|
||||
uses: actions/cache/restore@v3
|
||||
uses: actions/cache/restore@v4
|
||||
if: matrix.http3 == 'http3' && matrix.compiler == 'clang' && runner.os == 'Linux'
|
||||
with:
|
||||
path: libbpf/build
|
||||
@@ -302,21 +310,21 @@ jobs:
|
||||
echo 'EXTRA_AUTOTOOLS_OPTS='"$EXTRA_AUTOTOOLS_OPTS" >> $GITHUB_ENV
|
||||
echo 'EXTRA_CMAKE_OPTS='"$EXTRA_CMAKE_OPTS" >> $GITHUB_ENV
|
||||
- name: Restore quictls/openssl v1.1.1 cache
|
||||
uses: actions/cache/restore@v3
|
||||
uses: actions/cache/restore@v4
|
||||
if: matrix.http3 == 'http3' && matrix.openssl == 'openssl1'
|
||||
with:
|
||||
path: openssl1/build
|
||||
key: ${{ runner.os }}-openssl-${{ env.OPENSSL1_VERSION }}
|
||||
fail-on-cache-miss: true
|
||||
- name: Restore quictls/openssl v3.x cache
|
||||
uses: actions/cache/restore@v3
|
||||
uses: actions/cache/restore@v4
|
||||
if: matrix.http3 == 'http3' && matrix.openssl == 'openssl3'
|
||||
with:
|
||||
path: openssl3/build
|
||||
key: ${{ runner.os }}-openssl-${{ env.OPENSSL3_VERSION }}
|
||||
fail-on-cache-miss: true
|
||||
- name: Restore BoringSSL cache
|
||||
uses: actions/cache/restore@v3
|
||||
uses: actions/cache/restore@v4
|
||||
if: matrix.openssl == 'boringssl'
|
||||
with:
|
||||
path: |
|
||||
@@ -326,7 +334,7 @@ jobs:
|
||||
key: ${{ runner.os }}-boringssl-${{ env.BORINGSSL_VERSION }}
|
||||
fail-on-cache-miss: true
|
||||
- name: Restore aws-lc cache
|
||||
uses: actions/cache/restore@v3
|
||||
uses: actions/cache/restore@v4
|
||||
if: matrix.openssl == 'awslc'
|
||||
with:
|
||||
path: |
|
||||
@@ -364,21 +372,21 @@ jobs:
|
||||
echo 'BORINGSSL_LIBS='"$OPENSSL_LIBS" >> $GITHUB_ENV
|
||||
echo 'EXTRA_AUTOTOOLS_OPTS='"$EXTRA_AUTOTOOLS_OPTS" >> $GITHUB_ENV
|
||||
- name: Restore nghttp3 cache
|
||||
uses: actions/cache/restore@v3
|
||||
uses: actions/cache/restore@v4
|
||||
if: matrix.http3 == 'http3'
|
||||
with:
|
||||
path: nghttp3/build
|
||||
key: ${{ runner.os }}-nghttp3-${{ env.NGHTTP3_VERSION }}
|
||||
fail-on-cache-miss: true
|
||||
- name: Restore ngtcp2 + quictls/openssl v1.1.1 cache + BoringSSL
|
||||
uses: actions/cache/restore@v3
|
||||
uses: actions/cache/restore@v4
|
||||
if: matrix.http3 == 'http3' && (matrix.openssl == 'openssl1' || matrix.openssl == 'boringssl')
|
||||
with:
|
||||
path: ngtcp2-openssl1/build
|
||||
key: ${{ runner.os }}-ngtcp2-${{ env.NGTCP2_VERSION }}-openssl-${{ env.OPENSSL1_VERSION }}
|
||||
fail-on-cache-miss: true
|
||||
- name: Restore ngtcp2 + quictls/openssl v3.x cache + aws-lc
|
||||
uses: actions/cache/restore@v3
|
||||
uses: actions/cache/restore@v4
|
||||
if: matrix.http3 == 'http3' && (matrix.openssl == 'openssl3' || matrix.openssl == 'awslc')
|
||||
with:
|
||||
path: ngtcp2-openssl3/build
|
||||
@@ -398,7 +406,7 @@ jobs:
|
||||
echo 'EXTRA_CMAKE_OPTS='"$EXTRA_CMAKE_OPTS" >> $GITHUB_ENV
|
||||
- name: Setup git submodules
|
||||
run: |
|
||||
git submodule update --init
|
||||
git submodule update --init --depth 1
|
||||
- name: Configure autotools
|
||||
run: |
|
||||
autoreconf -i
|
||||
@@ -430,12 +438,12 @@ jobs:
|
||||
if: matrix.buildtool == 'autotools' && runner.os == 'Linux'
|
||||
run: |
|
||||
make -j"$(nproc)" distcheck \
|
||||
DISTCHECK_CONFIGURE_FLAGS="--with-mruby --with-neverbleed --with-libev --enable-werror $EXTRA_AUTOTOOLS_OPTS CPPFLAGS=\"$CPPFLAGS\" LDFLAGS=\"$LDFLAGS\""
|
||||
DISTCHECK_CONFIGURE_FLAGS="--with-mruby --with-neverbleed --with-libev --with-libbrotlienc --with-libbrotlidec --enable-werror $EXTRA_AUTOTOOLS_OPTS CPPFLAGS=\"$CPPFLAGS\" LDFLAGS=\"$LDFLAGS\""
|
||||
- name: Build nghttp2 with autotools (MacOS)
|
||||
if: matrix.buildtool == 'autotools' && runner.os == 'macOS'
|
||||
run: |
|
||||
make -j"$(sysctl -n hw.ncpu)" distcheck \
|
||||
DISTCHECK_CONFIGURE_FLAGS="--with-mruby --with-libev --enable-werror $EXTRA_AUTOTOOLS_OPTS CPPFLAGS=\"$CPPFLAGS\" LDFLAGS=\"$LDFLAGS\""
|
||||
DISTCHECK_CONFIGURE_FLAGS="--with-mruby --with-libev --with-libbrotlienc --with-libbrotlidec --enable-werror $EXTRA_AUTOTOOLS_OPTS CPPFLAGS=\"$CPPFLAGS\" LDFLAGS=\"$LDFLAGS\""
|
||||
- name: Build nghttp2 with cmake
|
||||
if: matrix.buildtool == 'cmake'
|
||||
run: |
|
||||
@@ -478,20 +486,12 @@ jobs:
|
||||
libtool \
|
||||
pkg-config \
|
||||
wine
|
||||
- name: Build CUnit
|
||||
run: |
|
||||
curl -LO https://jaist.dl.sourceforge.net/project/cunit/CUnit/2.1-3/CUnit-2.1-3.tar.bz2
|
||||
tar xf CUnit-2.1-3.tar.bz2
|
||||
cd CUnit-2.1-3
|
||||
./bootstrap
|
||||
./configure --disable-shared --host="$HOST" --prefix="$PWD/build"
|
||||
make -j$(nproc) install
|
||||
- name: Configure autotools
|
||||
run: |
|
||||
git submodule update --init --depth 1
|
||||
autoreconf -i && \
|
||||
./configure --enable-werror --enable-lib-only --with-cunit \
|
||||
--host="$HOST" PKG_CONFIG_PATH="$PWD/CUnit-2.1-3/build/lib/pkgconfig" \
|
||||
CFLAGS="-g -O2 -D_WIN32_WINNT=0x0600"
|
||||
./configure --enable-werror --enable-lib-only --host="$HOST" \
|
||||
CFLAGS="-g -O2 -D_WIN32_WINNT=0x0600" LIBS="-pthread"
|
||||
- name: Build nghttp2
|
||||
run: |
|
||||
make -j$(nproc)
|
||||
@@ -499,6 +499,7 @@ jobs:
|
||||
- name: Run tests
|
||||
if: matrix.host == 'x86_64-w64-mingw32'
|
||||
run: |
|
||||
export WINEPATH=/usr/x86_64-w64-mingw32/lib
|
||||
cd tests
|
||||
wine main.exe
|
||||
|
||||
@@ -516,11 +517,10 @@ jobs:
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: microsoft/setup-msbuild@v1
|
||||
- run: |
|
||||
vcpkg --triplet=${{ matrix.arch }}-windows install cunit
|
||||
- uses: microsoft/setup-msbuild@v2
|
||||
- name: Configure cmake
|
||||
run: |
|
||||
git submodule update --init --depth 1
|
||||
mkdir build
|
||||
cd build
|
||||
cmake -DCMAKE_TOOLCHAIN_FILE=C:/vcpkg/scripts/buildsystems/vcpkg.cmake -DCMAKE_GENERATOR_PLATFORM=${{ matrix.platform }} -DVCPKG_TARGET_TRIPLET=${{ matrix.arch}}-windows ..
|
||||
|
||||
24
.github/workflows/docker.yaml
vendored
Normal file
24
.github/workflows/docker.yaml
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
name: docker-build
|
||||
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- docker/Dockerfile
|
||||
branches:
|
||||
- '**'
|
||||
|
||||
permissions: read-all
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-22.04
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
- name: Build
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
context: docker
|
||||
build-args: NGHTTP2_BRANCH=${{ github.ref_name }}
|
||||
8
.gitignore
vendored
8
.gitignore
vendored
@@ -42,6 +42,7 @@ rules.ninja
|
||||
lib*.so
|
||||
lib*.so.*
|
||||
lib*.a
|
||||
|
||||
# generated by "make test" with cmake
|
||||
Testing/
|
||||
|
||||
@@ -54,3 +55,10 @@ _VC_ROOT/
|
||||
.depend.MSVC
|
||||
*.pyd
|
||||
*.egg-info/
|
||||
|
||||
# Build Directories
|
||||
build/
|
||||
|
||||
# IDEs
|
||||
cmake-*
|
||||
.idea/
|
||||
|
||||
3
.gitmodules
vendored
3
.gitmodules
vendored
@@ -5,3 +5,6 @@
|
||||
path = third-party/neverbleed
|
||||
url = https://github.com/tatsuhiro-t/neverbleed.git
|
||||
branch = nghttp2
|
||||
[submodule "tests/munit"]
|
||||
path = tests/munit
|
||||
url = https://github.com/ngtcp2/munit
|
||||
|
||||
1
AUTHORS
1
AUTHORS
@@ -112,6 +112,7 @@ Rudi Heitbaum
|
||||
Ryo Ota
|
||||
Scott Mitchell
|
||||
Sebastiaan Deckers
|
||||
Sergey Fedorov
|
||||
Shelley Vohr
|
||||
Simon Frankenberger
|
||||
Simone Basso
|
||||
|
||||
@@ -22,15 +22,15 @@
|
||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
cmake_minimum_required(VERSION 3.14)
|
||||
# XXX using 1.8.90 instead of 1.9.0-DEV
|
||||
project(nghttp2 VERSION 1.59.0)
|
||||
project(nghttp2 VERSION 1.60.0)
|
||||
|
||||
# See versioning rule:
|
||||
# https://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html
|
||||
set(LT_CURRENT 40)
|
||||
set(LT_CURRENT 41)
|
||||
set(LT_REVISION 0)
|
||||
set(LT_AGE 26)
|
||||
set(LT_AGE 27)
|
||||
|
||||
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH})
|
||||
include(Version)
|
||||
@@ -60,6 +60,8 @@ if(NOT ENABLE_LIB_ONLY)
|
||||
find_package(Libev 4.11)
|
||||
find_package(Libcares 1.7.5)
|
||||
find_package(ZLIB 1.2.3)
|
||||
find_package(Libbrotlienc 1.0.9)
|
||||
find_package(Libbrotlidec 1.0.9)
|
||||
endif()
|
||||
|
||||
find_package(OpenSSL 1.1.1)
|
||||
@@ -165,12 +167,8 @@ endif()
|
||||
# XXX shouldn't ${CMAKE_DL_LIBS} be appended to OPENSSL_LIBRARIES instead of
|
||||
# APP_LIBRARIES if it is really specific to OpenSSL?
|
||||
|
||||
find_package(CUnit 2.1)
|
||||
enable_testing()
|
||||
set(HAVE_CUNIT ${CUNIT_FOUND})
|
||||
if(HAVE_CUNIT)
|
||||
add_custom_target(check COMMAND ${CMAKE_CTEST_COMMAND})
|
||||
endif()
|
||||
add_custom_target(check COMMAND ${CMAKE_CTEST_COMMAND})
|
||||
|
||||
# openssl (for src)
|
||||
include(CheckSymbolExists)
|
||||
@@ -222,6 +220,13 @@ endif()
|
||||
# jemalloc
|
||||
set(HAVE_JEMALLOC ${JEMALLOC_FOUND})
|
||||
|
||||
# libbrotli (for src)
|
||||
set(HAVE_LIBBROTLIENC ${LIBBROTLIENC_FOUND})
|
||||
set(HAVE_LIBBROTLIDEC ${LIBBROTLIDEC_FOUND})
|
||||
if(LIBBROTLIENC_FOUND AND LIBBROTLIDEC_FOUND)
|
||||
set(HAVE_LIBBROTLI 1)
|
||||
endif()
|
||||
|
||||
# libbpf (for bpf)
|
||||
set(HAVE_LIBBPF ${LIBBPF_FOUND})
|
||||
if(LIBBPF_FOUND)
|
||||
@@ -458,7 +463,6 @@ message(STATUS "summary of build options:
|
||||
Python: ${Python3_EXECUTABLE}
|
||||
Python3_VERSION: ${Python3_VERSION}
|
||||
Test:
|
||||
CUnit: ${HAVE_CUNIT} (LIBS='${CUNIT_LIBRARIES}')
|
||||
Failmalloc: ${ENABLE_FAILMALLOC}
|
||||
Libs:
|
||||
OpenSSL: ${HAVE_OPENSSL} (LIBS='${OPENSSL_LIBRARIES}')
|
||||
@@ -474,6 +478,8 @@ message(STATUS "summary of build options:
|
||||
Jemalloc: ${HAVE_JEMALLOC} (LIBS='${JEMALLOC_LIBRARIES}')
|
||||
Zlib: ${HAVE_ZLIB} (LIBS='${ZLIB_LIBRARIES}')
|
||||
Systemd: ${HAVE_SYSTEMD} (LIBS='${SYSTEMD_LIBRARIES}')
|
||||
Libbrotlienc: ${HAVE_LIBBROTLIENC} (LIBS='${LIBBROTLIENC_LIBRARIES}')
|
||||
Libbrotlidec: ${HAVE_LIBBROTLIDEC} (LIBS='${LIBBROTLIDEC_LIBRARIES}')
|
||||
Third-party:
|
||||
http-parser: ${ENABLE_THIRD_PARTY}
|
||||
MRuby: ${HAVE_MRUBY}
|
||||
|
||||
@@ -11,8 +11,8 @@ option(ENABLE_EXAMPLES "Build examples"
|
||||
${ENABLE_EXAMPLES_DEFAULT})
|
||||
option(ENABLE_FAILMALLOC "Build failmalloc test program" ON)
|
||||
option(ENABLE_LIB_ONLY "Build libnghttp2 only. This is a short hand for -DENABLE_APP=0 -DENABLE_EXAMPLES=0 -DENABLE_HPACK_TOOLS=0")
|
||||
option(ENABLE_STATIC_LIB "Build libnghttp2 in static mode also")
|
||||
option(ENABLE_SHARED_LIB "Build libnghttp2 as a shared library" ON)
|
||||
option(BUILD_SHARED_LIBS "Build libnghttp2 as a shared library" ON)
|
||||
option(BUILD_STATIC_LIBS "Build libnghttp2 in static mode also" OFF)
|
||||
option(ENABLE_STATIC_CRT "Build libnghttp2 against the MS LIBCMT[d]")
|
||||
option(ENABLE_HTTP3 "Enable HTTP/3 support" OFF)
|
||||
option(ENABLE_DOC "Build documentation" ON)
|
||||
|
||||
@@ -35,7 +35,6 @@ EXTRA_DIST = nghttpx.conf.sample proxy.pac.sample android-config android-env \
|
||||
cmake/ExtractValidFlags.cmake \
|
||||
cmake/FindJemalloc.cmake \
|
||||
cmake/FindLibev.cmake \
|
||||
cmake/FindCUnit.cmake \
|
||||
cmake/Version.cmake \
|
||||
cmake/FindLibevent.cmake \
|
||||
cmake/FindJansson.cmake \
|
||||
@@ -45,6 +44,8 @@ EXTRA_DIST = nghttpx.conf.sample proxy.pac.sample android-config android-env \
|
||||
cmake/FindLibnghttp3.cmake \
|
||||
cmake/FindLibngtcp2.cmake \
|
||||
cmake/FindLibngtcp2_crypto_quictls.cmake \
|
||||
cmake/FindLibbrotlienc.cmake \
|
||||
cmake/FindLibbrotlidec.cmake \
|
||||
cmake/PickyWarningsC.cmake \
|
||||
cmake/PickyWarningsCXX.cmake
|
||||
|
||||
|
||||
58
README.rst
58
README.rst
@@ -48,11 +48,6 @@ The following package is required to build the libnghttp2 library:
|
||||
|
||||
* pkg-config >= 0.20
|
||||
|
||||
To build and run the unit test programs, the following package is
|
||||
required:
|
||||
|
||||
* cunit >= 2.1
|
||||
|
||||
To build the documentation, you need to install:
|
||||
|
||||
* sphinx (http://sphinx-doc.org/)
|
||||
@@ -100,6 +95,11 @@ To mitigate heap fragmentation in long running server programs
|
||||
Alpine Linux currently does not support malloc replacement
|
||||
due to musl limitations. See details in issue `#762 <https://github.com/nghttp2/nghttp2/issues/762>`_.
|
||||
|
||||
For BoringSSL or aws-lc build, to enable :rfc:`8879` TLS Certificate
|
||||
Compression in applications, the following library is required:
|
||||
|
||||
* libbrotli-dev >= 1.0.9
|
||||
|
||||
To enable mruby support for nghttpx, `mruby
|
||||
<https://github.com/mruby/mruby>`_ is required. We need to build
|
||||
mruby with C++ ABI explicitly turned on, and probably need other
|
||||
@@ -127,7 +127,7 @@ following libraries are required:
|
||||
<https://github.com/quictls/openssl/tree/OpenSSL_1_1_1w+quic>`_; or
|
||||
LibreSSL (does not support 0RTT); or aws-lc; or
|
||||
`BoringSSL <https://boringssl.googlesource.com/boringssl/>`_ (commit
|
||||
f42be90d665b6a376177648ccbb76fbbd6497c13)
|
||||
8e6a26d128484b886e6dcbfa558b993d38950bb5)
|
||||
* `ngtcp2 <https://github.com/ngtcp2/ngtcp2>`_ >= 1.0.0
|
||||
* `nghttp3 <https://github.com/ngtcp2/nghttp3>`_ >= 1.1.0
|
||||
|
||||
@@ -205,7 +205,7 @@ required packages:
|
||||
|
||||
sudo apt-get install g++ clang make binutils autoconf automake \
|
||||
autotools-dev libtool pkg-config \
|
||||
zlib1g-dev libcunit1-dev libssl-dev libxml2-dev libev-dev \
|
||||
zlib1g-dev libssl-dev libxml2-dev libev-dev \
|
||||
libevent-dev libjansson-dev \
|
||||
libc-ares-dev libjemalloc-dev libsystemd-dev \
|
||||
ruby-dev bison libelf-dev
|
||||
@@ -337,23 +337,24 @@ connections alive during reload.
|
||||
|
||||
The detailed steps to build HTTP/3 enabled h2load and nghttpx follow.
|
||||
|
||||
Build custom OpenSSL:
|
||||
Build aws-lc:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
$ git clone --depth 1 -b OpenSSL_1_1_1w+quic https://github.com/quictls/openssl
|
||||
$ cd openssl
|
||||
$ ./config --prefix=$PWD/build --openssldir=/etc/ssl
|
||||
$ make -j$(nproc)
|
||||
$ make install_sw
|
||||
$ git clone --depth 1 -b v1.21.0 https://github.com/aws/aws-lc
|
||||
$ cd aws-lc
|
||||
$ cmake -B build -DDISABLE_GO=ON --install-prefix=$PWD/opt
|
||||
$ make -j$(nproc) -C build
|
||||
$ cmake --install build
|
||||
$ cd ..
|
||||
|
||||
Build nghttp3:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
$ git clone --depth 1 -b v1.1.0 https://github.com/ngtcp2/nghttp3
|
||||
$ git clone --depth 1 -b v1.2.0 https://github.com/ngtcp2/nghttp3
|
||||
$ cd nghttp3
|
||||
$ git submodule update --init --depth 1
|
||||
$ autoreconf -i
|
||||
$ ./configure --prefix=$PWD/build --enable-lib-only
|
||||
$ make -j$(nproc)
|
||||
@@ -364,11 +365,13 @@ Build ngtcp2:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
$ git clone --depth 1 -b v1.2.0 https://github.com/ngtcp2/ngtcp2
|
||||
$ git clone --depth 1 -b v1.3.0 https://github.com/ngtcp2/ngtcp2
|
||||
$ cd ngtcp2
|
||||
$ git submodule update --init --depth 1
|
||||
$ autoreconf -i
|
||||
$ ./configure --prefix=$PWD/build --enable-lib-only \
|
||||
PKG_CONFIG_PATH="$PWD/../openssl/build/lib/pkgconfig"
|
||||
$ ./configure --prefix=$PWD/build --enable-lib-only --with-boringssl \
|
||||
BORINGSSL_CFLAGS="-I$PWD/../aws-lc/opt/include" \
|
||||
BORINGSSL_LIBS="-L$PWD/../aws-lc/opt/lib -lssl -lcrypto"
|
||||
$ make -j$(nproc)
|
||||
$ make install
|
||||
$ cd ..
|
||||
@@ -391,10 +394,10 @@ Build nghttp2:
|
||||
$ cd nghttp2
|
||||
$ git submodule update --init
|
||||
$ autoreconf -i
|
||||
$ ./configure --with-mruby --with-neverbleed --enable-http3 --with-libbpf \
|
||||
CC=clang-14 CXX=clang++-14 \
|
||||
PKG_CONFIG_PATH="$PWD/../openssl/build/lib/pkgconfig:$PWD/../nghttp3/build/lib/pkgconfig:$PWD/../ngtcp2/build/lib/pkgconfig:$PWD/../libbpf/build/lib64/pkgconfig" \
|
||||
LDFLAGS="$LDFLAGS -Wl,-rpath,$PWD/../openssl/build/lib -Wl,-rpath,$PWD/../libbpf/build/lib64"
|
||||
$ ./configure --with-mruby --enable-http3 --with-libbpf \
|
||||
CC=clang-15 CXX=clang++-15 \
|
||||
PKG_CONFIG_PATH="$PWD/../aws-lc/opt/lib/pkgconfig:$PWD/../nghttp3/build/lib/pkgconfig:$PWD/../ngtcp2/build/lib/pkgconfig:$PWD/../libbpf/build/lib64/pkgconfig" \
|
||||
LDFLAGS="$LDFLAGS -Wl,-rpath,$PWD/../aws-lc/opt/lib -Wl,-rpath,$PWD/../libbpf/build/lib64"
|
||||
$ make -j$(nproc)
|
||||
|
||||
The eBPF program ``reuseport_kern.o`` should be found under bpf
|
||||
@@ -479,7 +482,7 @@ Previously nghttp2 library did not send client magic, which is first
|
||||
24 bytes byte string of client connection preface, and client
|
||||
applications have to send it by themselves. Since v1.0.0, client
|
||||
magic is sent by library via first call of ``nghttp2_session_send()``
|
||||
or ``nghttp2_session_mem_send()``.
|
||||
or ``nghttp2_session_mem_send2()``.
|
||||
|
||||
The client applications which send client magic must remove the
|
||||
relevant code.
|
||||
@@ -1446,17 +1449,6 @@ See `Contribution Guidelines
|
||||
<https://nghttp2.org/documentation/contribute.html>`_ for more
|
||||
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.
|
||||
|
||||
Versioning
|
||||
----------
|
||||
|
||||
|
||||
@@ -1,16 +1,15 @@
|
||||
Security Process
|
||||
================
|
||||
# Security Process
|
||||
|
||||
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
|
||||
If you find a vulnerability in our software, please report it via
|
||||
GitHub "Private vulnerability reporting" feature at
|
||||
https://github.com/nghttp2/nghttp2/security 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.
|
||||
released, or mitigation is worked out.
|
||||
|
||||
If we identify that the reported issue is really a vulnerability, we
|
||||
open a new security advisory draft using `GitHub security feature
|
||||
<https://github.com/nghttp2/nghttp2/security>`_ and discuss the
|
||||
open a new security advisory draft using [GitHub security
|
||||
feature](https://github.com/nghttp2/nghttp2/security) and discuss the
|
||||
mitigation and bug fixes there. The fixes are committed to the
|
||||
private repository.
|
||||
|
||||
@@ -21,12 +20,11 @@ We make a new release with the fix at the same time when the
|
||||
vulnerability is disclosed to public.
|
||||
|
||||
At least 7 days before the public disclosure date, we open a new issue
|
||||
on `nghttp2 issue tracker
|
||||
<https://github.com/nghttp2/nghttp2/issues>`_ which notifies that the
|
||||
upcoming release will have a security fix. The ``SECURITY`` label is
|
||||
attached to this kind of issue. The issue is not opened if a
|
||||
vulnerability is already disclosed, and it is publicly known that
|
||||
nghttp2 is affected by that.
|
||||
on [nghttp2 issue tracker](https://github.com/nghttp2/nghttp2/issues)
|
||||
which notifies that the upcoming release will have a security fix.
|
||||
The `SECURITY` label is attached to this kind of issue. The issue is
|
||||
not opened if a vulnerability is already disclosed, and it is publicly
|
||||
known that nghttp2 is affected by that.
|
||||
|
||||
Before few hours of new release, we merge the fixes to the master
|
||||
branch (and/or a release branch if necessary) and make a new release.
|
||||
@@ -42,11 +42,6 @@
|
||||
License is Public Domain. Commit hash:
|
||||
12e7744b4919e9d55de75b7ab566326a1c8e7a67 */
|
||||
|
||||
#define AES_BLOCKLEN \
|
||||
16 /* Block length in bytes - AES is 128b block \
|
||||
only */
|
||||
|
||||
#define AES_KEYLEN 16 /* Key length in bytes */
|
||||
#define AES_keyExpSize 176
|
||||
|
||||
struct AES_ctx {
|
||||
@@ -57,7 +52,6 @@ struct AES_ctx {
|
||||
in AES. Value=4 */
|
||||
#define Nb 4
|
||||
|
||||
#define Nk 4 /* The number of 32 bit words in a key. */
|
||||
#define Nr 10 /* The number of rounds in AES Cipher. */
|
||||
|
||||
/* state - array holding the intermediate results during
|
||||
@@ -68,31 +62,6 @@ typedef __u8 state_t[4][4];
|
||||
read-only storage instead of RAM The numbers below can be computed
|
||||
dynamically trading ROM for RAM - This can be useful in (embedded)
|
||||
bootloader applications, where ROM is often limited. */
|
||||
static const __u8 sbox[256] = {
|
||||
/* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
|
||||
0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b,
|
||||
0xfe, 0xd7, 0xab, 0x76, 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0,
|
||||
0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, 0xb7, 0xfd, 0x93, 0x26,
|
||||
0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
|
||||
0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2,
|
||||
0xeb, 0x27, 0xb2, 0x75, 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0,
|
||||
0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, 0x53, 0xd1, 0x00, 0xed,
|
||||
0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
|
||||
0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f,
|
||||
0x50, 0x3c, 0x9f, 0xa8, 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5,
|
||||
0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, 0xcd, 0x0c, 0x13, 0xec,
|
||||
0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
|
||||
0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14,
|
||||
0xde, 0x5e, 0x0b, 0xdb, 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c,
|
||||
0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, 0xe7, 0xc8, 0x37, 0x6d,
|
||||
0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
|
||||
0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f,
|
||||
0x4b, 0xbd, 0x8b, 0x8a, 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e,
|
||||
0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, 0xe1, 0xf8, 0x98, 0x11,
|
||||
0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
|
||||
0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f,
|
||||
0xb0, 0x54, 0xbb, 0x16};
|
||||
|
||||
static const __u8 rsbox[256] = {
|
||||
0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e,
|
||||
0x81, 0xf3, 0xd7, 0xfb, 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87,
|
||||
@@ -117,78 +86,6 @@ static const __u8 rsbox[256] = {
|
||||
0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63,
|
||||
0x55, 0x21, 0x0c, 0x7d};
|
||||
|
||||
/* The round constant word array, Rcon[i], contains the values given
|
||||
by x to the power (i-1) being powers of x (x is denoted as {02}) in
|
||||
the field GF(2^8) */
|
||||
static const __u8 Rcon[11] = {0x8d, 0x01, 0x02, 0x04, 0x08, 0x10,
|
||||
0x20, 0x40, 0x80, 0x1b, 0x36};
|
||||
|
||||
#define getSBoxValue(num) (sbox[(num)])
|
||||
|
||||
/* This function produces Nb(Nr+1) round keys. The round keys are used
|
||||
in each round to decrypt the states. */
|
||||
static void KeyExpansion(__u8 *RoundKey, const __u8 *Key) {
|
||||
unsigned i, j, k;
|
||||
__u8 tempa[4]; /* Used for the column/row operations */
|
||||
|
||||
/* The first round key is the key itself. */
|
||||
for (i = 0; i < Nk; ++i) {
|
||||
RoundKey[(i * 4) + 0] = Key[(i * 4) + 0];
|
||||
RoundKey[(i * 4) + 1] = Key[(i * 4) + 1];
|
||||
RoundKey[(i * 4) + 2] = Key[(i * 4) + 2];
|
||||
RoundKey[(i * 4) + 3] = Key[(i * 4) + 3];
|
||||
}
|
||||
|
||||
/* All other round keys are found from the previous round keys. */
|
||||
for (i = Nk; i < Nb * (Nr + 1); ++i) {
|
||||
{
|
||||
k = (i - 1) * 4;
|
||||
tempa[0] = RoundKey[k + 0];
|
||||
tempa[1] = RoundKey[k + 1];
|
||||
tempa[2] = RoundKey[k + 2];
|
||||
tempa[3] = RoundKey[k + 3];
|
||||
}
|
||||
|
||||
if (i % Nk == 0) {
|
||||
/* This function shifts the 4 bytes in a word to the left once.
|
||||
[a0,a1,a2,a3] becomes [a1,a2,a3,a0] */
|
||||
|
||||
/* Function RotWord() */
|
||||
{
|
||||
const __u8 u8tmp = tempa[0];
|
||||
tempa[0] = tempa[1];
|
||||
tempa[1] = tempa[2];
|
||||
tempa[2] = tempa[3];
|
||||
tempa[3] = u8tmp;
|
||||
}
|
||||
|
||||
/* SubWord() is a function that takes a four-byte input word and
|
||||
applies the S-box to each of the four bytes to produce an
|
||||
output word. */
|
||||
|
||||
/* Function Subword() */
|
||||
{
|
||||
tempa[0] = getSBoxValue(tempa[0]);
|
||||
tempa[1] = getSBoxValue(tempa[1]);
|
||||
tempa[2] = getSBoxValue(tempa[2]);
|
||||
tempa[3] = getSBoxValue(tempa[3]);
|
||||
}
|
||||
|
||||
tempa[0] = tempa[0] ^ Rcon[i / Nk];
|
||||
}
|
||||
j = i * 4;
|
||||
k = (i - Nk) * 4;
|
||||
RoundKey[j + 0] = RoundKey[k + 0] ^ tempa[0];
|
||||
RoundKey[j + 1] = RoundKey[k + 1] ^ tempa[1];
|
||||
RoundKey[j + 2] = RoundKey[k + 2] ^ tempa[2];
|
||||
RoundKey[j + 3] = RoundKey[k + 3] ^ tempa[3];
|
||||
}
|
||||
}
|
||||
|
||||
static void AES_init_ctx(struct AES_ctx *ctx, const __u8 *key) {
|
||||
KeyExpansion(ctx->RoundKey, key);
|
||||
}
|
||||
|
||||
/* This function adds the round key to state. The round key is added
|
||||
to the state by an XOR function. */
|
||||
static void AddRoundKey(__u8 round, state_t *state, const __u8 *RoundKey) {
|
||||
@@ -439,11 +336,18 @@ struct {
|
||||
|
||||
struct {
|
||||
__uint(type, BPF_MAP_TYPE_ARRAY);
|
||||
__uint(max_entries, 3);
|
||||
__uint(max_entries, 1);
|
||||
__type(key, __u32);
|
||||
__type(value, __u64);
|
||||
} sk_info SEC(".maps");
|
||||
|
||||
struct {
|
||||
__uint(type, BPF_MAP_TYPE_ARRAY);
|
||||
__uint(max_entries, 1);
|
||||
__type(key, __u32);
|
||||
__type(value, struct AES_ctx);
|
||||
} aes_key SEC(".maps");
|
||||
|
||||
typedef struct quic_hd {
|
||||
__u8 *dcid;
|
||||
__u32 dcidlen;
|
||||
@@ -573,13 +477,12 @@ static __u32 sk_index_from_dcid(const quic_hd *qhd,
|
||||
SEC("sk_reuseport")
|
||||
int select_reuseport(struct sk_reuseport_md *reuse_md) {
|
||||
__u32 sk_index, *psk_index;
|
||||
__u64 *pnum_socks, *pkey;
|
||||
__u32 zero = 0, key_high_idx = 1, key_low_idx = 2;
|
||||
__u64 *pnum_socks;
|
||||
__u32 zero = 0;
|
||||
int rv;
|
||||
quic_hd qhd;
|
||||
__u8 qpktbuf[6 + MAX_DCIDLEN];
|
||||
struct AES_ctx aes_ctx;
|
||||
__u8 key[AES_KEYLEN];
|
||||
struct AES_ctx *aes_ctx;
|
||||
__u8 *cid_prefix;
|
||||
|
||||
if (bpf_skb_load_bytes(reuse_md, sizeof(struct udphdr), qpktbuf,
|
||||
@@ -592,33 +495,22 @@ int select_reuseport(struct sk_reuseport_md *reuse_md) {
|
||||
return SK_DROP;
|
||||
}
|
||||
|
||||
pkey = bpf_map_lookup_elem(&sk_info, &key_high_idx);
|
||||
if (pkey == NULL) {
|
||||
aes_ctx = bpf_map_lookup_elem(&aes_key, &zero);
|
||||
if (aes_ctx == NULL) {
|
||||
return SK_DROP;
|
||||
}
|
||||
|
||||
__builtin_memcpy(key, pkey, sizeof(*pkey));
|
||||
|
||||
pkey = bpf_map_lookup_elem(&sk_info, &key_low_idx);
|
||||
if (pkey == NULL) {
|
||||
return SK_DROP;
|
||||
}
|
||||
|
||||
__builtin_memcpy(key + sizeof(*pkey), pkey, sizeof(*pkey));
|
||||
|
||||
rv = parse_quic(&qhd, qpktbuf, qpktbuf + sizeof(qpktbuf));
|
||||
if (rv != 0) {
|
||||
return SK_DROP;
|
||||
}
|
||||
|
||||
AES_init_ctx(&aes_ctx, key);
|
||||
|
||||
switch (qhd.type) {
|
||||
case NGTCP2_PKT_INITIAL:
|
||||
case NGTCP2_PKT_0RTT:
|
||||
if (qhd.dcidlen == SV_DCIDLEN) {
|
||||
cid_prefix = qhd.dcid + CID_PREFIX_OFFSET;
|
||||
AES_ECB_decrypt(&aes_ctx, cid_prefix);
|
||||
AES_ECB_decrypt(aes_ctx, cid_prefix);
|
||||
|
||||
psk_index = bpf_map_lookup_elem(&cid_prefix_map, cid_prefix);
|
||||
if (psk_index != NULL) {
|
||||
@@ -638,7 +530,7 @@ int select_reuseport(struct sk_reuseport_md *reuse_md) {
|
||||
}
|
||||
|
||||
cid_prefix = qhd.dcid + CID_PREFIX_OFFSET;
|
||||
AES_ECB_decrypt(&aes_ctx, cid_prefix);
|
||||
AES_ECB_decrypt(aes_ctx, cid_prefix);
|
||||
|
||||
psk_index = bpf_map_lookup_elem(&cid_prefix_map, cid_prefix);
|
||||
if (psk_index == NULL) {
|
||||
|
||||
@@ -1,40 +0,0 @@
|
||||
# - Try to find cunit
|
||||
# Once done this will define
|
||||
# CUNIT_FOUND - System has cunit
|
||||
# CUNIT_INCLUDE_DIRS - The cunit include directories
|
||||
# CUNIT_LIBRARIES - The libraries needed to use cunit
|
||||
|
||||
find_package(PkgConfig QUIET)
|
||||
pkg_check_modules(PC_CUNIT QUIET cunit)
|
||||
|
||||
find_path(CUNIT_INCLUDE_DIR
|
||||
NAMES CUnit/CUnit.h
|
||||
HINTS ${PC_CUNIT_INCLUDE_DIRS}
|
||||
)
|
||||
find_library(CUNIT_LIBRARY
|
||||
NAMES cunit
|
||||
HINTS ${PC_CUNIT_LIBRARY_DIRS}
|
||||
)
|
||||
|
||||
if(CUNIT_INCLUDE_DIR)
|
||||
set(_version_regex "^#define[ \t]+CU_VERSION[ \t]+\"([^\"]+)\".*")
|
||||
file(STRINGS "${CUNIT_INCLUDE_DIR}/CUnit/CUnit.h"
|
||||
CUNIT_VERSION REGEX "${_version_regex}")
|
||||
string(REGEX REPLACE "${_version_regex}" "\\1"
|
||||
CUNIT_VERSION "${CUNIT_VERSION}")
|
||||
unset(_version_regex)
|
||||
endif()
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
# handle the QUIETLY and REQUIRED arguments and set CUNIT_FOUND to TRUE
|
||||
# if all listed variables are TRUE and the requested version matches.
|
||||
find_package_handle_standard_args(CUnit REQUIRED_VARS
|
||||
CUNIT_LIBRARY CUNIT_INCLUDE_DIR
|
||||
VERSION_VAR CUNIT_VERSION)
|
||||
|
||||
if(CUNIT_FOUND)
|
||||
set(CUNIT_LIBRARIES ${CUNIT_LIBRARY})
|
||||
set(CUNIT_INCLUDE_DIRS ${CUNIT_INCLUDE_DIR})
|
||||
endif()
|
||||
|
||||
mark_as_advanced(CUNIT_INCLUDE_DIR CUNIT_LIBRARY)
|
||||
36
cmake/FindLibbrotlidec.cmake
Normal file
36
cmake/FindLibbrotlidec.cmake
Normal file
@@ -0,0 +1,36 @@
|
||||
# - Try to find libbrotlidec
|
||||
# Once done this will define
|
||||
# LIBBROTLIDEC_FOUND - System has libbrotlidec
|
||||
# LIBBROTLIDEC_INCLUDE_DIRS - The libbrotlidec include directories
|
||||
# LIBBROTLIDEC_LIBRARIES - The libraries needed to use libbrotlidec
|
||||
|
||||
find_package(PkgConfig QUIET)
|
||||
pkg_check_modules(PC_LIBBROTLIDEC QUIET libbrotlidec)
|
||||
|
||||
find_path(LIBBROTLIDEC_INCLUDE_DIR
|
||||
NAMES brotli/decode.h
|
||||
HINTS ${PC_LIBBROTLIDEC_INCLUDE_DIRS}
|
||||
)
|
||||
find_library(LIBBROTLIDEC_LIBRARY
|
||||
NAMES brotlidec
|
||||
HINTS ${PC_LIBBROTLIDEC_LIBRARY_DIRS}
|
||||
)
|
||||
|
||||
if(PC_LIBBROTLIDEC_FOUND)
|
||||
set(LIBBROTLIDEC_VERSION ${PC_LIBBROTLIDEC_VERSION})
|
||||
endif()
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
# handle the QUIETLY and REQUIRED arguments and set LIBBROTLIDEC_FOUND
|
||||
# to TRUE if all listed variables are TRUE and the requested version
|
||||
# matches.
|
||||
find_package_handle_standard_args(Libbrotlidec REQUIRED_VARS
|
||||
LIBBROTLIDEC_LIBRARY LIBBROTLIDEC_INCLUDE_DIR
|
||||
VERSION_VAR LIBBROTLIDEC_VERSION)
|
||||
|
||||
if(LIBBROTLIDEC_FOUND)
|
||||
set(LIBBROTLIDEC_LIBRARIES ${LIBBROTLIDEC_LIBRARY})
|
||||
set(LIBBROTLIDEC_INCLUDE_DIRS ${LIBBROTLIDEC_INCLUDE_DIR})
|
||||
endif()
|
||||
|
||||
mark_as_advanced(LIBBROTLIDEC_INCLUDE_DIR LIBBROTLIDEC_LIBRARY)
|
||||
36
cmake/FindLibbrotlienc.cmake
Normal file
36
cmake/FindLibbrotlienc.cmake
Normal file
@@ -0,0 +1,36 @@
|
||||
# - Try to find libbrotlienc
|
||||
# Once done this will define
|
||||
# LIBBROTLIENC_FOUND - System has libbrotlienc
|
||||
# LIBBROTLIENC_INCLUDE_DIRS - The libbrotlienc include directories
|
||||
# LIBBROTLIENC_LIBRARIES - The libraries needed to use libbrotlienc
|
||||
|
||||
find_package(PkgConfig QUIET)
|
||||
pkg_check_modules(PC_LIBBROTLIENC QUIET libbrotlienc)
|
||||
|
||||
find_path(LIBBROTLIENC_INCLUDE_DIR
|
||||
NAMES brotli/encode.h
|
||||
HINTS ${PC_LIBBROTLIENC_INCLUDE_DIRS}
|
||||
)
|
||||
find_library(LIBBROTLIENC_LIBRARY
|
||||
NAMES brotlienc
|
||||
HINTS ${PC_LIBBROTLIENC_LIBRARY_DIRS}
|
||||
)
|
||||
|
||||
if(PC_LIBBROTLIENC_FOUND)
|
||||
set(LIBBROTLIENC_VERSION ${PC_LIBBROTLIENC_VERSION})
|
||||
endif()
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
# handle the QUIETLY and REQUIRED arguments and set LIBBROTLIENC_FOUND
|
||||
# to TRUE if all listed variables are TRUE and the requested version
|
||||
# matches.
|
||||
find_package_handle_standard_args(Libbrotlienc REQUIRED_VARS
|
||||
LIBBROTLIENC_LIBRARY LIBBROTLIENC_INCLUDE_DIR
|
||||
VERSION_VAR LIBBROTLIENC_VERSION)
|
||||
|
||||
if(LIBBROTLIENC_FOUND)
|
||||
set(LIBBROTLIENC_LIBRARIES ${LIBBROTLIENC_LIBRARY})
|
||||
set(LIBBROTLIENC_INCLUDE_DIRS ${LIBBROTLIENC_INCLUDE_DIR})
|
||||
endif()
|
||||
|
||||
mark_as_advanced(LIBBROTLIENC_INCLUDE_DIR LIBBROTLIENC_LIBRARY)
|
||||
@@ -85,7 +85,6 @@ if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX OR CMAKE_C_COMPILER_ID MA
|
||||
-Wstrict-prototypes # clang 1.0 gcc 3.3
|
||||
# -Wswitch-enum # clang 3.0 gcc 4.1 # Not used because this basically disallows default case
|
||||
-Wunreachable-code # clang 3.0 gcc 4.1
|
||||
-Wunused-macros # clang 3.0 gcc 4.1
|
||||
-Wunused-parameter # clang 3.0 gcc 4.1
|
||||
-Wvla # clang 2.8 gcc 4.3
|
||||
)
|
||||
|
||||
@@ -99,3 +99,6 @@
|
||||
|
||||
/* Define to 1 if you have `libev` library. */
|
||||
#cmakedefine HAVE_LIBEV 1
|
||||
|
||||
/* Define to 1 if you have `libbrotlienc` and `libbrotlidec` libraries. */
|
||||
#cmakedefine HAVE_LIBBROTLI 1
|
||||
|
||||
102
configure.ac
102
configure.ac
@@ -25,7 +25,7 @@ dnl Do not change user variables!
|
||||
dnl https://www.gnu.org/software/automake/manual/html_node/Flag-Variables-Ordering.html
|
||||
|
||||
AC_PREREQ(2.61)
|
||||
AC_INIT([nghttp2], [1.59.0], [t-tujikawa@users.sourceforge.net])
|
||||
AC_INIT([nghttp2], [1.60.0], [t-tujikawa@users.sourceforge.net])
|
||||
AC_CONFIG_AUX_DIR([.])
|
||||
AC_CONFIG_MACRO_DIR([m4])
|
||||
AC_CONFIG_HEADERS([config.h])
|
||||
@@ -44,9 +44,9 @@ m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
|
||||
|
||||
dnl See versioning rule:
|
||||
dnl https://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html
|
||||
AC_SUBST(LT_CURRENT, 40)
|
||||
AC_SUBST(LT_CURRENT, 41)
|
||||
AC_SUBST(LT_REVISION, 0)
|
||||
AC_SUBST(LT_AGE, 26)
|
||||
AC_SUBST(LT_AGE, 27)
|
||||
|
||||
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"`
|
||||
@@ -137,11 +137,6 @@ AC_ARG_WITH([libev],
|
||||
[Use libev [default=check]])],
|
||||
[request_libev=$withval], [request_libev=check])
|
||||
|
||||
AC_ARG_WITH([cunit],
|
||||
[AS_HELP_STRING([--with-cunit],
|
||||
[Use cunit [default=check]])],
|
||||
[request_cunit=$withval], [request_cunit=check])
|
||||
|
||||
AC_ARG_WITH([jemalloc],
|
||||
[AS_HELP_STRING([--with-jemalloc],
|
||||
[Use jemalloc [default=check]])],
|
||||
@@ -177,6 +172,16 @@ AC_ARG_WITH([libbpf],
|
||||
[Use libbpf [default=no]])],
|
||||
[request_libbpf=$withval], [request_libbpf=no])
|
||||
|
||||
AC_ARG_WITH([libbrotlienc],
|
||||
[AS_HELP_STRING([--with-libbrotlienc],
|
||||
[Use libbrotlienc [default=no]])],
|
||||
[request_libbrotlienc=$withval], [request_libbrotlienc=no])
|
||||
|
||||
AC_ARG_WITH([libbrotlidec],
|
||||
[AS_HELP_STRING([--with-libbrotlidec],
|
||||
[Use libbrotlidec [default=no]])],
|
||||
[request_libbrotlidec=$withval], [request_libbrotlidec=no])
|
||||
|
||||
dnl Define variables
|
||||
AC_ARG_VAR([LIBEV_CFLAGS], [C compiler flags for libev, skipping any checks])
|
||||
AC_ARG_VAR([LIBEV_LIBS], [linker flags for libev, skipping any checks])
|
||||
@@ -377,43 +382,6 @@ case "${host_os}" in
|
||||
;;
|
||||
esac
|
||||
|
||||
# cunit
|
||||
have_cunit=no
|
||||
if test "x${request_cunit}" != "xno"; then
|
||||
PKG_CHECK_MODULES([CUNIT], [cunit >= 2.1], [have_cunit=yes], [have_cunit=no])
|
||||
# If pkg-config does not find cunit, check it using AC_CHECK_LIB. We
|
||||
# do this because Debian (Ubuntu) lacks pkg-config file for cunit.
|
||||
if test "x${have_cunit}" = "xno"; then
|
||||
AC_MSG_WARN([${CUNIT_PKG_ERRORS}])
|
||||
AC_CHECK_LIB([cunit], [CU_initialize_registry],
|
||||
[have_cunit=yes], [have_cunit=no])
|
||||
if test "x${have_cunit}" = "xyes"; then
|
||||
CUNIT_LIBS="-lcunit"
|
||||
CUNIT_CFLAGS=""
|
||||
AC_SUBST([CUNIT_LIBS])
|
||||
AC_SUBST([CUNIT_CFLAGS])
|
||||
fi
|
||||
fi
|
||||
if test "x${have_cunit}" = "xyes"; then
|
||||
# cunit in Mac OS X requires ncurses. Note that in Mac OS X, test
|
||||
# program can be built without -lncurses, but it emits runtime
|
||||
# error.
|
||||
case "${build}" in
|
||||
*-apple-darwin*)
|
||||
CUNIT_LIBS="$CUNIT_LIBS -lncurses"
|
||||
AC_SUBST([CUNIT_LIBS])
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
fi
|
||||
|
||||
if test "x${request_cunit}" = "xyes" &&
|
||||
test "x${have_cunit}" != "xyes"; then
|
||||
AC_MSG_ERROR([cunit was requested (--with-cunit) but not found])
|
||||
fi
|
||||
|
||||
AM_CONDITIONAL([HAVE_CUNIT], [ test "x${have_cunit}" = "xyes" ])
|
||||
|
||||
# libev (for src)
|
||||
have_libev=no
|
||||
if test "x${request_libev}" != "xno"; then
|
||||
@@ -626,6 +594,47 @@ fi
|
||||
|
||||
AM_CONDITIONAL([HAVE_LIBBPF], [ test "x${have_libbpf}" = "xyes" ])
|
||||
|
||||
# libbrotlienc (for src)
|
||||
have_libbrotlienc=no
|
||||
if test "x${request_libbrotlienc}" != "xno"; then
|
||||
PKG_CHECK_MODULES([LIBBROTLIENC], [libbrotlienc >= 1.0.9],
|
||||
[have_libbrotlienc=yes],
|
||||
[have_libbrotlienc=no])
|
||||
if test "x${have_libbrotlienc}" = "xno"; then
|
||||
AC_MSG_NOTICE($LIBBROTLIENC_PKG_ERRORS)
|
||||
fi
|
||||
fi
|
||||
|
||||
if test "x${request_libbrotlienc}" = "xyes" &&
|
||||
test "x${have_libbrotlienc}" != "xyes"; then
|
||||
AC_MSG_ERROR([libbrotlienc was requested (--with-libbrotlienc) but not found])
|
||||
fi
|
||||
|
||||
# libbrotlidec (for src)
|
||||
have_libbrotlidec=no
|
||||
if test "x${request_libbrotlidec}" != "xno"; then
|
||||
PKG_CHECK_MODULES([LIBBROTLIDEC], [libbrotlidec >= 1.0.9],
|
||||
[have_libbrotlidec=yes],
|
||||
[have_libbrotlidec=no])
|
||||
if test "x${have_libbrotlidec}" = "xno"; then
|
||||
AC_MSG_NOTICE($LIBBROTLIDEC_PKG_ERRORS)
|
||||
fi
|
||||
fi
|
||||
|
||||
if test "x${request_libbrotlidec}" = "xyes" &&
|
||||
test "x${have_libbrotlidec}" != "xyes"; then
|
||||
AC_MSG_ERROR([libbrotlidec was requested (--with-libbrotlidec) but not found])
|
||||
fi
|
||||
|
||||
have_libbrotli=no
|
||||
if test "x${have_libbrotlienc}" = "xyes" &&
|
||||
test "x${have_libbrotlidec}" = "xyes"; then
|
||||
have_libbrotli=yes
|
||||
|
||||
AC_DEFINE([HAVE_LIBBROTLI], [1],
|
||||
[Define to 1 if you have `libbrotlienc` and `libbrotlidec` libraries.])
|
||||
fi
|
||||
|
||||
# libevent_openssl (for examples)
|
||||
# 2.0.8 is required because we use evconnlistener_set_error_cb()
|
||||
have_libevent_openssl=no
|
||||
@@ -1155,7 +1164,6 @@ AC_MSG_NOTICE([summary of build options:
|
||||
Python: ${PYTHON}
|
||||
PYTHON_VERSION: ${PYTHON_VERSION}
|
||||
Test:
|
||||
CUnit: ${have_cunit} (CFLAGS='${CUNIT_CFLAGS}' LIBS='${CUNIT_LIBS}')
|
||||
Failmalloc: ${enable_failmalloc}
|
||||
Libs:
|
||||
OpenSSL: ${have_openssl} (CFLAGS='${OPENSSL_CFLAGS}' LIBS='${OPENSSL_LIBS}')
|
||||
@@ -1172,6 +1180,8 @@ AC_MSG_NOTICE([summary of build options:
|
||||
Jemalloc: ${have_jemalloc} (CFLAGS='${JEMALLOC_CFLAGS}' LIBS='${JEMALLOC_LIBS}')
|
||||
Zlib: ${have_zlib} (CFLAGS='${ZLIB_CFLAGS}' LIBS='${ZLIB_LIBS}')
|
||||
Systemd: ${have_libsystemd} (CFLAGS='${SYSTEMD_CFLAGS}' LIBS='${SYSTEMD_LIBS}')
|
||||
Libbrotlienc: ${have_libbrotlienc} (CFLAGS="${LIBBROTLIENC_CFLAGS}' LIBS='${LIBBROTLIENC_LIBS}')
|
||||
Libbrotlidec: ${have_libbrotlidec} (CFLAGS="${LIBBROTLIDEC_CFLAGS}' LIBS='${LIBBROTLIDEC_LIBS}')
|
||||
Third-party:
|
||||
http-parser: ${enable_third_party}
|
||||
MRuby: ${have_mruby} (CFLAGS='${LIBMRUBY_CFLAGS}' LIBS='${LIBMRUBY_LIBS}')
|
||||
|
||||
@@ -42,7 +42,9 @@ APIDOCS= \
|
||||
nghttp2_hd_deflate_get_num_table_entries.rst \
|
||||
nghttp2_hd_deflate_get_table_entry.rst \
|
||||
nghttp2_hd_deflate_hd.rst \
|
||||
nghttp2_hd_deflate_hd2.rst \
|
||||
nghttp2_hd_deflate_hd_vec.rst \
|
||||
nghttp2_hd_deflate_hd_vec2.rst \
|
||||
nghttp2_hd_deflate_new.rst \
|
||||
nghttp2_hd_deflate_new2.rst \
|
||||
nghttp2_hd_inflate_change_table_size.rst \
|
||||
@@ -54,6 +56,7 @@ APIDOCS= \
|
||||
nghttp2_hd_inflate_get_table_entry.rst \
|
||||
nghttp2_hd_inflate_hd.rst \
|
||||
nghttp2_hd_inflate_hd2.rst \
|
||||
nghttp2_hd_inflate_hd3.rst \
|
||||
nghttp2_hd_inflate_new.rst \
|
||||
nghttp2_hd_inflate_new2.rst \
|
||||
nghttp2_http2_strerror.rst \
|
||||
@@ -78,6 +81,7 @@ APIDOCS= \
|
||||
nghttp2_option_set_max_settings.rst \
|
||||
nghttp2_option_set_stream_reset_rate_limit.rst \
|
||||
nghttp2_pack_settings_payload.rst \
|
||||
nghttp2_pack_settings_payload2.rst \
|
||||
nghttp2_priority_spec_check_default.rst \
|
||||
nghttp2_priority_spec_default_init.rst \
|
||||
nghttp2_priority_spec_init.rst \
|
||||
@@ -91,6 +95,7 @@ APIDOCS= \
|
||||
nghttp2_session_callbacks_new.rst \
|
||||
nghttp2_session_callbacks_set_before_frame_send_callback.rst \
|
||||
nghttp2_session_callbacks_set_data_source_read_length_callback.rst \
|
||||
nghttp2_session_callbacks_set_data_source_read_length_callback2.rst \
|
||||
nghttp2_session_callbacks_set_error_callback.rst \
|
||||
nghttp2_session_callbacks_set_error_callback2.rst \
|
||||
nghttp2_session_callbacks_set_on_begin_frame_callback.rst \
|
||||
@@ -107,9 +112,13 @@ APIDOCS= \
|
||||
nghttp2_session_callbacks_set_on_invalid_header_callback2.rst \
|
||||
nghttp2_session_callbacks_set_on_stream_close_callback.rst \
|
||||
nghttp2_session_callbacks_set_pack_extension_callback.rst \
|
||||
nghttp2_session_callbacks_set_pack_extension_callback2.rst \
|
||||
nghttp2_session_callbacks_set_recv_callback.rst \
|
||||
nghttp2_session_callbacks_set_recv_callback2.rst \
|
||||
nghttp2_session_callbacks_set_select_padding_callback.rst \
|
||||
nghttp2_session_callbacks_set_select_padding_callback2.rst \
|
||||
nghttp2_session_callbacks_set_send_callback.rst \
|
||||
nghttp2_session_callbacks_set_send_callback2.rst \
|
||||
nghttp2_session_callbacks_set_send_data_callback.rst \
|
||||
nghttp2_session_callbacks_set_unpack_extension_callback.rst \
|
||||
nghttp2_session_change_extpri_stream_priority.rst \
|
||||
@@ -146,7 +155,9 @@ APIDOCS= \
|
||||
nghttp2_session_get_stream_remote_window_size.rst \
|
||||
nghttp2_session_get_stream_user_data.rst \
|
||||
nghttp2_session_mem_recv.rst \
|
||||
nghttp2_session_mem_recv2.rst \
|
||||
nghttp2_session_mem_send.rst \
|
||||
nghttp2_session_mem_send2.rst \
|
||||
nghttp2_session_recv.rst \
|
||||
nghttp2_session_resume_data.rst \
|
||||
nghttp2_session_send.rst \
|
||||
@@ -174,6 +185,7 @@ APIDOCS= \
|
||||
nghttp2_strerror.rst \
|
||||
nghttp2_submit_altsvc.rst \
|
||||
nghttp2_submit_data.rst \
|
||||
nghttp2_submit_data2.rst \
|
||||
nghttp2_submit_extension.rst \
|
||||
nghttp2_submit_goaway.rst \
|
||||
nghttp2_submit_headers.rst \
|
||||
@@ -183,7 +195,9 @@ APIDOCS= \
|
||||
nghttp2_submit_priority_update.rst \
|
||||
nghttp2_submit_push_promise.rst \
|
||||
nghttp2_submit_request.rst \
|
||||
nghttp2_submit_request2.rst \
|
||||
nghttp2_submit_response.rst \
|
||||
nghttp2_submit_response2.rst \
|
||||
nghttp2_submit_rst_stream.rst \
|
||||
nghttp2_submit_settings.rst \
|
||||
nghttp2_submit_shutdown_notice.rst \
|
||||
@@ -212,7 +226,6 @@ EXTRA_DIST = \
|
||||
sources/h2load-howto.rst \
|
||||
sources/building-android-binary.rst \
|
||||
sources/contribute.rst \
|
||||
sources/security.rst \
|
||||
_exts/rubydomain/LICENSE.rubydomain \
|
||||
_exts/rubydomain/__init__.py \
|
||||
_exts/rubydomain/rubydomain.py \
|
||||
|
||||
@@ -68,7 +68,7 @@ The example follows::
|
||||
* Callback function invoked when |session| wants to send data to
|
||||
* remote peer.
|
||||
*/
|
||||
typedef ssize_t (*nghttp2_send_callback)
|
||||
typedef nghttp2_ssize (*nghttp2_send_callback2)
|
||||
(nghttp2_session *session,
|
||||
const uint8_t *data, size_t length, int flags, void *user_data);
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ _h2load()
|
||||
_get_comp_words_by_ref cur prev
|
||||
case $cur in
|
||||
-*)
|
||||
COMPREPLY=( $( compgen -W '--requests --clients --threads --input-file --max-concurrent-streams --max-frame-size --window-bits --connection-window-bits --header --ciphers --tls13-ciphers --no-tls-proto --data --rate --rate-period --duration --warm-up-time --connection-active-timeout --connection-inactivity-timeout --timing-script-file --base-uri --alpn-list --h1 --header-table-size --encoder-header-table-size --log-file --qlog-file-base --connect-to --rps --groups --no-udp-gso --max-udp-payload-size --ktls --verbose --version --help ' -- "$cur" ) )
|
||||
COMPREPLY=( $( compgen -W '--requests --clients --threads --input-file --max-concurrent-streams --max-frame-size --window-bits --connection-window-bits --header --ciphers --tls13-ciphers --no-tls-proto --data --rate --rate-period --duration --warm-up-time --connection-active-timeout --connection-inactivity-timeout --timing-script-file --base-uri --alpn-list --h1 --header-table-size --encoder-header-table-size --log-file --qlog-file-base --connect-to --rps --groups --no-udp-gso --max-udp-payload-size --ktls --sni --verbose --version --help ' -- "$cur" ) )
|
||||
;;
|
||||
*)
|
||||
_filedir
|
||||
|
||||
@@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
||||
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
||||
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
|
||||
..
|
||||
.TH "H2LOAD" "1" "Jan 21, 2024" "1.59.0" "nghttp2"
|
||||
.TH "H2LOAD" "1" "Mar 01, 2024" "1.60.0" "nghttp2"
|
||||
.SH NAME
|
||||
h2load \- HTTP/2 benchmarking tool
|
||||
.SH SYNOPSIS
|
||||
@@ -344,6 +344,12 @@ Enable ktls.
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \-\-sni=<DNSNAME>
|
||||
Send <DNSNAME> in TLS SNI, overriding the host name
|
||||
specified in URI.
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \-v, \-\-verbose
|
||||
Output debug information.
|
||||
.UNINDENT
|
||||
|
||||
@@ -290,6 +290,11 @@ OPTIONS
|
||||
|
||||
Enable ktls.
|
||||
|
||||
.. option:: --sni=<DNSNAME>
|
||||
|
||||
Send <DNSNAME> in TLS SNI, overriding the host name
|
||||
specified in URI.
|
||||
|
||||
.. option:: -v, --verbose
|
||||
|
||||
Output debug information.
|
||||
|
||||
@@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
||||
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
||||
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
|
||||
..
|
||||
.TH "NGHTTP" "1" "Jan 21, 2024" "1.59.0" "nghttp2"
|
||||
.TH "NGHTTP" "1" "Mar 01, 2024" "1.60.0" "nghttp2"
|
||||
.SH NAME
|
||||
nghttp \- HTTP/2 client
|
||||
.SH SYNOPSIS
|
||||
|
||||
@@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
||||
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
||||
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
|
||||
..
|
||||
.TH "NGHTTPD" "1" "Jan 21, 2024" "1.59.0" "nghttp2"
|
||||
.TH "NGHTTPD" "1" "Mar 01, 2024" "1.60.0" "nghttp2"
|
||||
.SH NAME
|
||||
nghttpd \- HTTP/2 server
|
||||
.SH SYNOPSIS
|
||||
|
||||
@@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
||||
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
||||
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
|
||||
..
|
||||
.TH "NGHTTPX" "1" "Jan 21, 2024" "1.59.0" "nghttp2"
|
||||
.TH "NGHTTPX" "1" "Mar 01, 2024" "1.60.0" "nghttp2"
|
||||
.SH NAME
|
||||
nghttpx \- HTTP/2 proxy
|
||||
.SH SYNOPSIS
|
||||
|
||||
@@ -40,28 +40,28 @@ most event-based architecture applications use is single thread per
|
||||
core, and handling one connection I/O is done by single thread.
|
||||
|
||||
To feed input to :type:`nghttp2_session` object, one can use
|
||||
`nghttp2_session_recv()` or `nghttp2_session_mem_recv()` functions.
|
||||
`nghttp2_session_recv()` or `nghttp2_session_mem_recv2()` functions.
|
||||
They behave similarly, and the difference is that
|
||||
`nghttp2_session_recv()` will use :type:`nghttp2_read_callback` to get
|
||||
input. On the other hand, `nghttp2_session_mem_recv()` will take
|
||||
input as its parameter. If in doubt, use `nghttp2_session_mem_recv()`
|
||||
since it is simpler, and could be faster since it avoids calling
|
||||
callback function.
|
||||
input. On the other hand, `nghttp2_session_mem_recv2()` will take
|
||||
input as its parameter. If in doubt, use
|
||||
`nghttp2_session_mem_recv2()` since it is simpler, and could be faster
|
||||
since it avoids calling callback function.
|
||||
|
||||
To get output from :type:`nghttp2_session` object, one can use
|
||||
`nghttp2_session_send()` or `nghttp2_session_mem_send()`. The
|
||||
`nghttp2_session_send()` or `nghttp2_session_mem_send2()`. The
|
||||
difference between them is that the former uses
|
||||
:type:`nghttp2_send_callback` to pass output to an application. On
|
||||
the other hand, the latter returns the output to the caller. If in
|
||||
doubt, use `nghttp2_session_mem_send()` since it is simpler. But
|
||||
doubt, use `nghttp2_session_mem_send2()` since it is simpler. But
|
||||
`nghttp2_session_send()` might be easier to use if the output buffer
|
||||
an application has is fixed sized.
|
||||
|
||||
In general, an application should call `nghttp2_session_mem_send()`
|
||||
In general, an application should call `nghttp2_session_mem_send2()`
|
||||
when it gets input from underlying connection. Since there is great
|
||||
chance to get something pushed into transmission queue while the call
|
||||
of `nghttp2_session_mem_send()`, it is recommended to call
|
||||
`nghttp2_session_mem_recv()` after `nghttp2_session_mem_send()`.
|
||||
of `nghttp2_session_mem_send2()`, it is recommended to call
|
||||
`nghttp2_session_mem_recv2()` after `nghttp2_session_mem_send2()`.
|
||||
|
||||
There is a question when we are safe to close HTTP/2 session without
|
||||
waiting for the closure of underlying connection. We offer 2 API
|
||||
@@ -70,7 +70,7 @@ calls for this: `nghttp2_session_want_read()` and
|
||||
can destroy :type:`nghttp2_session`, and then close the underlying
|
||||
connection. But make sure that the buffered output has been
|
||||
transmitted to the peer before closing the connection when
|
||||
`nghttp2_session_mem_send()` is used, since
|
||||
`nghttp2_session_mem_send2()` is used, since
|
||||
`nghttp2_session_want_write()` does not take into account the
|
||||
transmission of the buffered data outside of :type:`nghttp2_session`.
|
||||
|
||||
@@ -87,18 +87,18 @@ The header files are also available online: :doc:`nghttp2.h` and
|
||||
Remarks
|
||||
-------
|
||||
|
||||
Do not call `nghttp2_session_send()`, `nghttp2_session_mem_send()`,
|
||||
`nghttp2_session_recv()` or `nghttp2_session_mem_recv()` from the
|
||||
Do not call `nghttp2_session_send()`, `nghttp2_session_mem_send2()`,
|
||||
`nghttp2_session_recv()` or `nghttp2_session_mem_recv2()` from the
|
||||
nghttp2 callback functions directly or indirectly. It will lead to the
|
||||
crash. You can submit requests or frames in the callbacks then call
|
||||
these functions outside the callbacks.
|
||||
|
||||
`nghttp2_session_send()` and `nghttp2_session_mem_send()` send first
|
||||
`nghttp2_session_send()` and `nghttp2_session_mem_send2()` send first
|
||||
24 bytes of client magic string (MAGIC)
|
||||
(:macro:`NGHTTP2_CLIENT_MAGIC`) on client configuration. The
|
||||
applications are responsible to send SETTINGS frame as part of
|
||||
connection preface using `nghttp2_submit_settings()`. Similarly,
|
||||
`nghttp2_session_recv()` and `nghttp2_session_mem_recv()` consume
|
||||
`nghttp2_session_recv()` and `nghttp2_session_mem_recv2()` consume
|
||||
MAGIC on server configuration unless
|
||||
`nghttp2_option_set_no_recv_client_magic()` is used with nonzero
|
||||
option value.
|
||||
@@ -222,7 +222,7 @@ above, the following code does not work:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
nghttp2_submit_response(...)
|
||||
nghttp2_submit_response2(...)
|
||||
nghttp2_submit_rst_stream(...)
|
||||
|
||||
RST_STREAM cancels HEADERS (and DATA), and just RST_STREAM is sent.
|
||||
@@ -258,9 +258,9 @@ For example, we will illustrate how to send `ALTSVC
|
||||
const char *field;
|
||||
} alt_svc;
|
||||
|
||||
ssize_t pack_extension_callback(nghttp2_session *session, uint8_t *buf,
|
||||
size_t len, const nghttp2_frame *frame,
|
||||
void *user_data) {
|
||||
nghttp2_ssize pack_extension_callback(nghttp2_session *session, uint8_t *buf,
|
||||
size_t len, const nghttp2_frame *frame,
|
||||
void *user_data) {
|
||||
const alt_svc *altsvc = (const alt_svc *)frame->ext.payload;
|
||||
size_t originlen = strlen(altsvc->origin);
|
||||
size_t fieldlen = strlen(altsvc->field);
|
||||
@@ -497,8 +497,8 @@ order to receive and process PRIORITY_UPDATE frame, server has to call
|
||||
NGHTTP2_PRIORITY_UPDATE)`` (see the above section), and pass the
|
||||
option to `nghttp2_session_server_new2()` or
|
||||
`nghttp2_session_server_new3()` to create a server session. Client
|
||||
can send Priority header field via `nghttp2_submit_request()`. It can
|
||||
also send PRIORITY_UPDATE frame via
|
||||
can send Priority header field via `nghttp2_submit_request2()`. It
|
||||
can also send PRIORITY_UPDATE frame via
|
||||
`nghttp2_submit_priority_update()`. Server processes Priority header
|
||||
field in a request header field and updates the stream priority unless
|
||||
HTTP messaging rule enforcement is disabled (see
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
.. include:: ../doc/sources/security.rst
|
||||
@@ -18,7 +18,6 @@ Contents:
|
||||
|
||||
package_README
|
||||
contribute
|
||||
security
|
||||
building-android-binary
|
||||
tutorial-client
|
||||
tutorial-server
|
||||
|
||||
@@ -171,7 +171,7 @@ session object and several callbacks::
|
||||
|
||||
nghttp2_session_callbacks_new(&callbacks);
|
||||
|
||||
nghttp2_session_callbacks_set_send_callback(callbacks, send_callback);
|
||||
nghttp2_session_callbacks_set_send_callback2(callbacks, send_callback);
|
||||
|
||||
nghttp2_session_callbacks_set_on_frame_recv_callback(callbacks,
|
||||
on_frame_recv_callback);
|
||||
@@ -246,8 +246,8 @@ HTTP request in the ``submit_request()`` function::
|
||||
MAKE_NV(":path", stream_data->path, stream_data->pathlen)};
|
||||
fprintf(stderr, "Request headers:\n");
|
||||
print_headers(stderr, hdrs, ARRLEN(hdrs));
|
||||
stream_id = nghttp2_submit_request(session_data->session, NULL, hdrs,
|
||||
ARRLEN(hdrs), NULL, stream_data);
|
||||
stream_id = nghttp2_submit_request2(session_data->session, NULL, hdrs,
|
||||
ARRLEN(hdrs), NULL, stream_data);
|
||||
if (stream_id < 0) {
|
||||
errx(1, "Could not submit HTTP request: %s", nghttp2_strerror(stream_id));
|
||||
}
|
||||
@@ -258,11 +258,11 @@ HTTP request in the ``submit_request()`` function::
|
||||
We build the HTTP request header fields in ``hdrs``, which is an array
|
||||
of :type:`nghttp2_nv`. There are four header fields to be sent:
|
||||
``:method``, ``:scheme``, ``:authority``, and ``:path``. To queue the
|
||||
HTTP request, we call `nghttp2_submit_request()`. The ``stream_data``
|
||||
HTTP request, we call `nghttp2_submit_request2()`. The ``stream_data``
|
||||
is passed via the *stream_user_data* parameter, which is helpfully
|
||||
later passed back to callback functions.
|
||||
|
||||
`nghttp2_submit_request()` returns the newly assigned stream ID for
|
||||
`nghttp2_submit_request2()` returns the newly assigned stream ID for
|
||||
the request.
|
||||
|
||||
The next bufferevent callback is ``readcb()``, which is invoked when
|
||||
@@ -270,12 +270,12 @@ data is available to read from the bufferevent input buffer::
|
||||
|
||||
static void readcb(struct bufferevent *bev, void *ptr) {
|
||||
http2_session_data *session_data = (http2_session_data *)ptr;
|
||||
ssize_t readlen;
|
||||
nghttp2_ssize readlen;
|
||||
struct evbuffer *input = bufferevent_get_input(bev);
|
||||
size_t datalen = evbuffer_get_length(input);
|
||||
unsigned char *data = evbuffer_pullup(input, -1);
|
||||
|
||||
readlen = nghttp2_session_mem_recv(session_data->session, data, datalen);
|
||||
readlen = nghttp2_session_mem_recv2(session_data->session, data, datalen);
|
||||
if (readlen < 0) {
|
||||
warnx("Fatal error: %s", nghttp2_strerror((int)readlen));
|
||||
delete_http2_session_data(session_data);
|
||||
@@ -293,8 +293,8 @@ data is available to read from the bufferevent input buffer::
|
||||
}
|
||||
|
||||
In this function we feed all unprocessed, received data to the nghttp2
|
||||
session object using the `nghttp2_session_mem_recv()` function.
|
||||
`nghttp2_session_mem_recv()` processes the received data and may
|
||||
session object using the `nghttp2_session_mem_recv2()` function.
|
||||
`nghttp2_session_mem_recv2()` processes the received data and may
|
||||
invoke nghttp2 callbacks and queue frames for transmission. Since
|
||||
there may be pending frames for transmission, we call immediately
|
||||
``session_send()`` to send them. ``session_send()`` is defined as
|
||||
@@ -313,15 +313,16 @@ follows::
|
||||
|
||||
The `nghttp2_session_send()` function serializes pending frames into
|
||||
wire format and calls the ``send_callback()`` function to send them.
|
||||
``send_callback()`` has type :type:`nghttp2_send_callback` and is
|
||||
``send_callback()`` has type :type:`nghttp2_send_callback2` and is
|
||||
defined as::
|
||||
|
||||
static ssize_t send_callback(nghttp2_session *session _U_, const uint8_t *data,
|
||||
size_t length, int flags _U_, void *user_data) {
|
||||
static nghttp2_ssize send_callback(nghttp2_session *session _U_,
|
||||
const uint8_t *data, size_t length,
|
||||
int flags _U_, void *user_data) {
|
||||
http2_session_data *session_data = (http2_session_data *)user_data;
|
||||
struct bufferevent *bev = session_data->bev;
|
||||
bufferevent_write(bev, data, length);
|
||||
return (ssize_t)length;
|
||||
return (nghttp2_ssize)length;
|
||||
}
|
||||
|
||||
Since we use bufferevent to abstract network I/O, we just write the
|
||||
|
||||
@@ -24,11 +24,11 @@ deflater object for the dynamic header table. If in doubt, just
|
||||
specify 4096 here, which is the default upper bound of dynamic header
|
||||
table buffer size.
|
||||
|
||||
To encode header fields, use the `nghttp2_hd_deflate_hd()` function::
|
||||
To encode header fields, use the `nghttp2_hd_deflate_hd2()` function::
|
||||
|
||||
ssize_t nghttp2_hd_deflate_hd(nghttp2_hd_deflater *deflater,
|
||||
uint8_t *buf, size_t buflen,
|
||||
const nghttp2_nv *nva, size_t nvlen);
|
||||
nghttp2_ssize nghttp2_hd_deflate_hd2(nghttp2_hd_deflater *deflater,
|
||||
uint8_t *buf, size_t buflen,
|
||||
const nghttp2_nv *nva, size_t nvlen);
|
||||
|
||||
The *deflater* is the deflater object initialized by
|
||||
`nghttp2_hd_deflate_new()` described above. The encoded byte string is
|
||||
@@ -44,7 +44,7 @@ cookies), set the :macro:`NGHTTP2_NV_FLAG_NO_INDEX` flag in
|
||||
sensitive header fields by compression based attacks: This is achieved
|
||||
by not inserting the header field into the dynamic header table.
|
||||
|
||||
`nghttp2_hd_deflate_hd()` processes all headers given in *nva*. The
|
||||
`nghttp2_hd_deflate_hd2()` processes all headers given in *nva*. The
|
||||
*nva* must include all request or response header fields to be sent in
|
||||
one HEADERS (or optionally following (multiple) CONTINUATION
|
||||
frame(s)). The *buf* must have enough space to store the encoded
|
||||
@@ -55,13 +55,13 @@ of the encoded result length, use `nghttp2_hd_deflate_bound()`::
|
||||
const nghttp2_nv *nva, size_t nvlen);
|
||||
|
||||
Pass this function the same parameters (*deflater*, *nva*, and
|
||||
*nvlen*) which will be passed to `nghttp2_hd_deflate_hd()`.
|
||||
*nvlen*) which will be passed to `nghttp2_hd_deflate_hd2()`.
|
||||
|
||||
Subsequent calls to `nghttp2_hd_deflate_hd()` will use the current
|
||||
Subsequent calls to `nghttp2_hd_deflate_hd2()` will use the current
|
||||
encoder state and perform differential encoding, which yields HPAC's
|
||||
fundamental compression gain.
|
||||
|
||||
If `nghttp2_hd_deflate_hd()` fails, the failure is fatal and any
|
||||
If `nghttp2_hd_deflate_hd2()` fails, the failure is fatal and any
|
||||
further calls with the same deflater object will fail. Thus it's very
|
||||
important to use `nghttp2_hd_deflate_bound()` to determine the
|
||||
required size of the output buffer.
|
||||
@@ -78,14 +78,14 @@ header data. To initialize the object, use
|
||||
|
||||
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_hd3()`::
|
||||
|
||||
ssize_t nghttp2_hd_inflate_hd2(nghttp2_hd_inflater *inflater,
|
||||
nghttp2_nv *nv_out, int *inflate_flags,
|
||||
const uint8_t *in, size_t inlen,
|
||||
int in_final);
|
||||
nghttp2_ssize nghttp2_hd_inflate_hd3(nghttp2_hd_inflater *inflater,
|
||||
nghttp2_nv *nv_out, int *inflate_flags,
|
||||
const uint8_t *in, size_t inlen,
|
||||
int in_final);
|
||||
|
||||
`nghttp2_hd_inflate_hd2()` reads a stream of bytes and outputs a
|
||||
`nghttp2_hd_inflate_hd3()` reads a stream of bytes and outputs a
|
||||
single header field at a time. Multiple calls are normally required to
|
||||
read a full stream of bytes and output all of the header fields.
|
||||
|
||||
@@ -119,7 +119,7 @@ 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
|
||||
is required to pass additional data.
|
||||
|
||||
Example usage of `nghttp2_hd_inflate_hd2()` is shown in the
|
||||
Example usage of `nghttp2_hd_inflate_hd3()` is shown in the
|
||||
`inflate_header_block()` function in `deflate.c`_.
|
||||
|
||||
Finally, to delete a :type:`nghttp2_hd_inflater` object, use
|
||||
|
||||
@@ -220,7 +220,7 @@ session object and several callbacks::
|
||||
|
||||
nghttp2_session_callbacks_new(&callbacks);
|
||||
|
||||
nghttp2_session_callbacks_set_send_callback(callbacks, send_callback);
|
||||
nghttp2_session_callbacks_set_send_callback2(callbacks, send_callback);
|
||||
|
||||
nghttp2_session_callbacks_set_on_frame_recv_callback(callbacks,
|
||||
on_frame_recv_callback);
|
||||
@@ -275,12 +275,12 @@ this pending data. To process the received data, we call the
|
||||
``session_recv()`` function::
|
||||
|
||||
static int session_recv(http2_session_data *session_data) {
|
||||
ssize_t readlen;
|
||||
nghttp2_ssize readlen;
|
||||
struct evbuffer *input = bufferevent_get_input(session_data->bev);
|
||||
size_t datalen = evbuffer_get_length(input);
|
||||
unsigned char *data = evbuffer_pullup(input, -1);
|
||||
|
||||
readlen = nghttp2_session_mem_recv(session_data->session, data, datalen);
|
||||
readlen = nghttp2_session_mem_recv2(session_data->session, data, datalen);
|
||||
if (readlen < 0) {
|
||||
warnx("Fatal error: %s", nghttp2_strerror((int)readlen));
|
||||
return -1;
|
||||
@@ -296,9 +296,9 @@ this pending data. To process the received data, we call the
|
||||
}
|
||||
|
||||
In this function, we feed all unprocessed but already received data to
|
||||
the nghttp2 session object using the `nghttp2_session_mem_recv()`
|
||||
function. The `nghttp2_session_mem_recv()` function processes the data
|
||||
and may both invoke the previously setup callbacks and also queue
|
||||
the nghttp2 session object using the `nghttp2_session_mem_recv2()`
|
||||
function. The `nghttp2_session_mem_recv2()` function processes the
|
||||
data and may both invoke the previously setup callbacks and also queue
|
||||
outgoing frames. To send any pending outgoing frames, we immediately
|
||||
call ``session_send()``.
|
||||
|
||||
@@ -316,11 +316,12 @@ The ``session_send()`` function is defined as follows::
|
||||
|
||||
The `nghttp2_session_send()` function serializes the frame into wire
|
||||
format and calls the ``send_callback()``, which is of type
|
||||
:type:`nghttp2_send_callback`. The ``send_callback()`` is defined as
|
||||
:type:`nghttp2_send_callback2`. The ``send_callback()`` is defined as
|
||||
follows::
|
||||
|
||||
static ssize_t send_callback(nghttp2_session *session _U_, const uint8_t *data,
|
||||
size_t length, int flags _U_, void *user_data) {
|
||||
static nghttp2_ssize send_callback(nghttp2_session *session _U_,
|
||||
const uint8_t *data, size_t length,
|
||||
int flags _U_, void *user_data) {
|
||||
http2_session_data *session_data = (http2_session_data *)user_data;
|
||||
struct bufferevent *bev = session_data->bev;
|
||||
/* Avoid excessive buffering in server side. */
|
||||
@@ -329,7 +330,7 @@ follows::
|
||||
return NGHTTP2_ERR_WOULDBLOCK;
|
||||
}
|
||||
bufferevent_write(bev, data, length);
|
||||
return (ssize_t)length;
|
||||
return (nghttp2_ssize)length;
|
||||
}
|
||||
|
||||
Since we use bufferevent to abstract network I/O, we just write the
|
||||
@@ -509,11 +510,11 @@ Sending the file content is performed by the ``send_response()`` function::
|
||||
static int send_response(nghttp2_session *session, int32_t stream_id,
|
||||
nghttp2_nv *nva, size_t nvlen, int fd) {
|
||||
int rv;
|
||||
nghttp2_data_provider data_prd;
|
||||
nghttp2_data_provider2 data_prd;
|
||||
data_prd.source.fd = fd;
|
||||
data_prd.read_callback = file_read_callback;
|
||||
|
||||
rv = nghttp2_submit_response(session, stream_id, nva, nvlen, &data_prd);
|
||||
rv = nghttp2_submit_response2(session, stream_id, nva, nvlen, &data_prd);
|
||||
if (rv != 0) {
|
||||
warnx("Fatal error: %s", nghttp2_strerror(rv));
|
||||
return -1;
|
||||
@@ -521,7 +522,7 @@ Sending the file content is performed by the ``send_response()`` function::
|
||||
return 0;
|
||||
}
|
||||
|
||||
nghttp2 uses the :type:`nghttp2_data_provider` structure to send the
|
||||
nghttp2 uses the :type:`nghttp2_data_provider2` structure to send the
|
||||
entity body to the remote peer. The ``source`` member of this
|
||||
structure is a union, which can be either a void pointer or an int
|
||||
(which is intended to be used as file descriptor). In this example
|
||||
@@ -529,11 +530,11 @@ server, we use it as a file descriptor. We also set the
|
||||
``file_read_callback()`` callback function to read the contents of the
|
||||
file::
|
||||
|
||||
static ssize_t file_read_callback(nghttp2_session *session _U_,
|
||||
int32_t stream_id _U_, uint8_t *buf,
|
||||
size_t length, uint32_t *data_flags,
|
||||
nghttp2_data_source *source,
|
||||
void *user_data _U_) {
|
||||
static nghttp2_ssize file_read_callback(nghttp2_session *session _U_,
|
||||
int32_t stream_id _U_, uint8_t *buf,
|
||||
size_t length, uint32_t *data_flags,
|
||||
nghttp2_data_source *source,
|
||||
void *user_data _U_) {
|
||||
int fd = source->fd;
|
||||
ssize_t r;
|
||||
while ((r = read(fd, buf, length)) == -1 && errno == EINTR)
|
||||
@@ -544,7 +545,7 @@ file::
|
||||
if (r == 0) {
|
||||
*data_flags |= NGHTTP2_DATA_FLAG_EOF;
|
||||
}
|
||||
return r;
|
||||
return (nghttp2_ssize)r;
|
||||
}
|
||||
|
||||
If an error occurs while reading the file, we return
|
||||
@@ -553,8 +554,8 @@ library to send RST_STREAM to the stream. When all data has been
|
||||
read, the :macro:`NGHTTP2_DATA_FLAG_EOF` flag is set to signal nghttp2
|
||||
that we have finished reading the file.
|
||||
|
||||
The `nghttp2_submit_response()` function is used to send the response to the
|
||||
remote peer.
|
||||
The `nghttp2_submit_response2()` function is used to send the response
|
||||
to the remote peer.
|
||||
|
||||
The ``on_stream_close_callback()`` function is invoked when the stream
|
||||
is about to close::
|
||||
|
||||
@@ -1,22 +1,25 @@
|
||||
FROM debian:12 as build
|
||||
|
||||
ARG NGHTTP2_BRANCH=master
|
||||
|
||||
RUN apt-get update && \
|
||||
DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
|
||||
git clang make binutils autoconf automake autotools-dev libtool \
|
||||
pkg-config \
|
||||
pkg-config cmake cmake-data \
|
||||
zlib1g-dev libev-dev libjemalloc-dev ruby-dev libc-ares-dev bison \
|
||||
libelf-dev
|
||||
libelf-dev libbrotli-dev
|
||||
|
||||
RUN git clone --depth 1 -b OpenSSL_1_1_1w+quic https://github.com/quictls/openssl && \
|
||||
cd openssl && \
|
||||
./config --openssldir=/etc/ssl && \
|
||||
make -j$(nproc) && \
|
||||
make install_sw && \
|
||||
RUN git clone --depth 1 -b v1.21.0 https://github.com/aws/aws-lc && \
|
||||
cd aws-lc && \
|
||||
cmake -B build -DDISABLE_GO=ON && \
|
||||
make -j$(nproc) -C build && \
|
||||
cmake --install build && \
|
||||
cd .. && \
|
||||
rm -rf openssl
|
||||
rm -rf aws-lc
|
||||
|
||||
RUN git clone --depth 1 -b v1.1.0 https://github.com/ngtcp2/nghttp3 && \
|
||||
RUN git clone --depth 1 -b v1.2.0 https://github.com/ngtcp2/nghttp3 && \
|
||||
cd nghttp3 && \
|
||||
git submodule update --init --depth 1 && \
|
||||
autoreconf -i && \
|
||||
./configure --enable-lib-only && \
|
||||
make -j$(nproc) && \
|
||||
@@ -24,12 +27,13 @@ RUN git clone --depth 1 -b v1.1.0 https://github.com/ngtcp2/nghttp3 && \
|
||||
cd .. && \
|
||||
rm -rf nghttp3
|
||||
|
||||
RUN git clone --depth 1 -b v1.2.0 https://github.com/ngtcp2/ngtcp2 && \
|
||||
RUN git clone --depth 1 -b v1.3.0 https://github.com/ngtcp2/ngtcp2 && \
|
||||
cd ngtcp2 && \
|
||||
git submodule update --init --depth 1 && \
|
||||
autoreconf -i && \
|
||||
./configure --enable-lib-only \
|
||||
./configure --enable-lib-only --with-boringssl \
|
||||
LIBTOOL_LDFLAGS="-static-libtool-libs" \
|
||||
OPENSSL_LIBS="-l:libssl.a -l:libcrypto.a -ldl -lpthread" \
|
||||
BORINGSSL_LIBS="-l:libssl.a -l:libcrypto.a" \
|
||||
PKG_CONFIG_PATH="/usr/local/lib64/pkgconfig" && \
|
||||
make -j$(nproc) && \
|
||||
make install-strip && \
|
||||
@@ -42,21 +46,24 @@ RUN git clone --depth 1 -b v1.3.0 https://github.com/libbpf/libbpf && \
|
||||
cd .. && \
|
||||
rm -rf libbpf
|
||||
|
||||
RUN git clone --depth 1 https://github.com/nghttp2/nghttp2.git && \
|
||||
RUN git clone --depth 1 -b $NGHTTP2_BRANCH https://github.com/nghttp2/nghttp2 && \
|
||||
cd nghttp2 && \
|
||||
git submodule update --init && \
|
||||
git submodule update --init --depth 1 && \
|
||||
autoreconf -i && \
|
||||
./configure --disable-examples --disable-hpack-tools \
|
||||
--with-mruby --with-neverbleed \
|
||||
--with-mruby \
|
||||
--enable-http3 --with-libbpf \
|
||||
--with-libbrotlienc --with-libbrotlidec \
|
||||
CC=clang CXX=clang++ \
|
||||
LIBTOOL_LDFLAGS="-static-libtool-libs" \
|
||||
OPENSSL_LIBS="-l:libssl.a -l:libcrypto.a -ldl -pthread" \
|
||||
OPENSSL_LIBS="-l:libssl.a -l:libcrypto.a" \
|
||||
LIBEV_LIBS="-l:libev.a" \
|
||||
JEMALLOC_LIBS="-l:libjemalloc.a" \
|
||||
LIBCARES_LIBS="-l:libcares.a" \
|
||||
ZLIB_LIBS="-l:libz.a" \
|
||||
LIBBPF_LIBS="-L/usr/local/lib64 -l:libbpf.a -l:libelf.a" \
|
||||
LIBBROTLIENC_LIBS="-l:libbrotlienc.a -l:libbrotlicommon.a" \
|
||||
LIBBROTLIDEC_LIBS="-l:libbrotlidec.a -l:libbrotlicommon.a" \
|
||||
LDFLAGS="-static-libgcc -static-libstdc++" \
|
||||
PKG_CONFIG_PATH="/usr/local/lib64/pkgconfig" && \
|
||||
make -j$(nproc) install-strip && \
|
||||
|
||||
@@ -56,6 +56,7 @@
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#define NGHTTP2_NO_SSIZE_T
|
||||
#include <nghttp2/nghttp2.h>
|
||||
|
||||
#include <openssl/ssl.h>
|
||||
@@ -154,13 +155,14 @@ static void diec(const char *func, int error_code) {
|
||||
}
|
||||
|
||||
/*
|
||||
* The implementation of nghttp2_send_callback type. Here we write
|
||||
* The implementation of nghttp2_send_callback2 type. Here we write
|
||||
* |data| with size |length| to the network and return the number of
|
||||
* bytes actually written. See the documentation of
|
||||
* nghttp2_send_callback for the details.
|
||||
*/
|
||||
static ssize_t send_callback(nghttp2_session *session, const uint8_t *data,
|
||||
size_t length, int flags, void *user_data) {
|
||||
static nghttp2_ssize send_callback(nghttp2_session *session,
|
||||
const uint8_t *data, size_t length,
|
||||
int flags, void *user_data) {
|
||||
struct Connection *connection;
|
||||
int rv;
|
||||
(void)session;
|
||||
@@ -184,13 +186,14 @@ static ssize_t send_callback(nghttp2_session *session, const uint8_t *data,
|
||||
}
|
||||
|
||||
/*
|
||||
* The implementation of nghttp2_recv_callback type. Here we read data
|
||||
* from the network and write them in |buf|. The capacity of |buf| is
|
||||
* |length| bytes. Returns the number of bytes stored in |buf|. See
|
||||
* the documentation of nghttp2_recv_callback for the details.
|
||||
* The implementation of nghttp2_recv_callback2 type. Here we read
|
||||
* data from the network and write them in |buf|. The capacity of
|
||||
* |buf| is |length| bytes. Returns the number of bytes stored in
|
||||
* |buf|. See the documentation of nghttp2_recv_callback for the
|
||||
* details.
|
||||
*/
|
||||
static ssize_t recv_callback(nghttp2_session *session, uint8_t *buf,
|
||||
size_t length, int flags, void *user_data) {
|
||||
static nghttp2_ssize recv_callback(nghttp2_session *session, uint8_t *buf,
|
||||
size_t length, int flags, void *user_data) {
|
||||
struct Connection *connection;
|
||||
int rv;
|
||||
(void)session;
|
||||
@@ -328,9 +331,9 @@ static int on_data_chunk_recv_callback(nghttp2_session *session, uint8_t flags,
|
||||
* recv_callback is also required.
|
||||
*/
|
||||
static void setup_nghttp2_callbacks(nghttp2_session_callbacks *callbacks) {
|
||||
nghttp2_session_callbacks_set_send_callback(callbacks, send_callback);
|
||||
nghttp2_session_callbacks_set_send_callback2(callbacks, send_callback);
|
||||
|
||||
nghttp2_session_callbacks_set_recv_callback(callbacks, recv_callback);
|
||||
nghttp2_session_callbacks_set_recv_callback2(callbacks, recv_callback);
|
||||
|
||||
nghttp2_session_callbacks_set_on_frame_send_callback(callbacks,
|
||||
on_frame_send_callback);
|
||||
@@ -458,8 +461,8 @@ static void submit_request(struct Connection *connection, struct Request *req) {
|
||||
MAKE_NV("accept", "*/*"),
|
||||
MAKE_NV("user-agent", "nghttp2/" NGHTTP2_VERSION)};
|
||||
|
||||
stream_id = nghttp2_submit_request(connection->session, NULL, nva,
|
||||
sizeof(nva) / sizeof(nva[0]), NULL, req);
|
||||
stream_id = nghttp2_submit_request2(connection->session, NULL, nva,
|
||||
sizeof(nva) / sizeof(nva[0]), NULL, req);
|
||||
|
||||
if (stream_id < 0) {
|
||||
diec("nghttp2_submit_request", stream_id);
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#define NGHTTP2_NO_SSIZE_T
|
||||
#include <nghttp2/nghttp2.h>
|
||||
|
||||
#define MAKE_NV(K, V) \
|
||||
@@ -93,7 +94,7 @@ int main(void) {
|
||||
static void deflate(nghttp2_hd_deflater *deflater,
|
||||
nghttp2_hd_inflater *inflater, const nghttp2_nv *const nva,
|
||||
size_t nvlen) {
|
||||
ssize_t rv;
|
||||
nghttp2_ssize rv;
|
||||
uint8_t *buf;
|
||||
size_t buflen;
|
||||
size_t outlen;
|
||||
@@ -118,10 +119,10 @@ static void deflate(nghttp2_hd_deflater *deflater,
|
||||
buflen = nghttp2_hd_deflate_bound(deflater, nva, nvlen);
|
||||
buf = malloc(buflen);
|
||||
|
||||
rv = nghttp2_hd_deflate_hd(deflater, buf, buflen, nva, nvlen);
|
||||
rv = nghttp2_hd_deflate_hd2(deflater, buf, buflen, nva, nvlen);
|
||||
|
||||
if (rv < 0) {
|
||||
fprintf(stderr, "nghttp2_hd_deflate_hd() failed with error: %s\n",
|
||||
fprintf(stderr, "nghttp2_hd_deflate_hd2() failed with error: %s\n",
|
||||
nghttp2_strerror((int)rv));
|
||||
|
||||
free(buf);
|
||||
@@ -166,17 +167,18 @@ static void deflate(nghttp2_hd_deflater *deflater,
|
||||
|
||||
int inflate_header_block(nghttp2_hd_inflater *inflater, uint8_t *in,
|
||||
size_t inlen, int final) {
|
||||
ssize_t rv;
|
||||
nghttp2_ssize rv;
|
||||
|
||||
for (;;) {
|
||||
nghttp2_nv nv;
|
||||
int inflate_flags = 0;
|
||||
size_t proclen;
|
||||
|
||||
rv = nghttp2_hd_inflate_hd(inflater, &nv, &inflate_flags, in, inlen, final);
|
||||
rv =
|
||||
nghttp2_hd_inflate_hd3(inflater, &nv, &inflate_flags, in, inlen, final);
|
||||
|
||||
if (rv < 0) {
|
||||
fprintf(stderr, "inflate failed with error code %zd", rv);
|
||||
fprintf(stderr, "inflate failed with error code %td", rv);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
@@ -63,6 +63,7 @@ char *strndup(const char *s, size_t size);
|
||||
#include <event2/bufferevent_ssl.h>
|
||||
#include <event2/dns.h>
|
||||
|
||||
#define NGHTTP2_NO_SSIZE_T
|
||||
#include <nghttp2/nghttp2.h>
|
||||
|
||||
#include "url-parser/url_parser.h"
|
||||
@@ -196,18 +197,19 @@ static void print_headers(FILE *f, nghttp2_nv *nva, size_t nvlen) {
|
||||
fprintf(f, "\n");
|
||||
}
|
||||
|
||||
/* nghttp2_send_callback. Here we transmit the |data|, |length| bytes,
|
||||
to the network. Because we are using libevent bufferevent, we just
|
||||
write those bytes into bufferevent buffer. */
|
||||
static ssize_t send_callback(nghttp2_session *session, const uint8_t *data,
|
||||
size_t length, int flags, void *user_data) {
|
||||
/* nghttp2_send_callback2. Here we transmit the |data|, |length|
|
||||
bytes, to the network. Because we are using libevent bufferevent,
|
||||
we just write those bytes into bufferevent buffer. */
|
||||
static nghttp2_ssize send_callback(nghttp2_session *session,
|
||||
const uint8_t *data, size_t length,
|
||||
int flags, void *user_data) {
|
||||
http2_session_data *session_data = (http2_session_data *)user_data;
|
||||
struct bufferevent *bev = session_data->bev;
|
||||
(void)session;
|
||||
(void)flags;
|
||||
|
||||
bufferevent_write(bev, data, length);
|
||||
return (ssize_t)length;
|
||||
return (nghttp2_ssize)length;
|
||||
}
|
||||
|
||||
/* nghttp2_on_header_callback: Called when nghttp2 library emits
|
||||
@@ -342,7 +344,7 @@ static void initialize_nghttp2_session(http2_session_data *session_data) {
|
||||
|
||||
nghttp2_session_callbacks_new(&callbacks);
|
||||
|
||||
nghttp2_session_callbacks_set_send_callback(callbacks, send_callback);
|
||||
nghttp2_session_callbacks_set_send_callback2(callbacks, send_callback);
|
||||
|
||||
nghttp2_session_callbacks_set_on_frame_recv_callback(callbacks,
|
||||
on_frame_recv_callback);
|
||||
@@ -403,8 +405,8 @@ static void submit_request(http2_session_data *session_data) {
|
||||
MAKE_NV(":path", stream_data->path, stream_data->pathlen)};
|
||||
fprintf(stderr, "Request headers:\n");
|
||||
print_headers(stderr, hdrs, ARRLEN(hdrs));
|
||||
stream_id = nghttp2_submit_request(session_data->session, NULL, hdrs,
|
||||
ARRLEN(hdrs), NULL, stream_data);
|
||||
stream_id = nghttp2_submit_request2(session_data->session, NULL, hdrs,
|
||||
ARRLEN(hdrs), NULL, stream_data);
|
||||
if (stream_id < 0) {
|
||||
errx(1, "Could not submit HTTP request: %s", nghttp2_strerror(stream_id));
|
||||
}
|
||||
@@ -431,12 +433,12 @@ static int session_send(http2_session_data *session_data) {
|
||||
context. To send them, we call session_send() in the end. */
|
||||
static void readcb(struct bufferevent *bev, void *ptr) {
|
||||
http2_session_data *session_data = (http2_session_data *)ptr;
|
||||
ssize_t readlen;
|
||||
nghttp2_ssize readlen;
|
||||
struct evbuffer *input = bufferevent_get_input(bev);
|
||||
size_t datalen = evbuffer_get_length(input);
|
||||
unsigned char *data = evbuffer_pullup(input, -1);
|
||||
|
||||
readlen = nghttp2_session_mem_recv(session_data->session, data, datalen);
|
||||
readlen = nghttp2_session_mem_recv2(session_data->session, data, datalen);
|
||||
if (readlen < 0) {
|
||||
warnx("Fatal error: %s", nghttp2_strerror((int)readlen));
|
||||
delete_http2_session_data(session_data);
|
||||
|
||||
@@ -71,6 +71,7 @@
|
||||
#include <event2/bufferevent_ssl.h>
|
||||
#include <event2/listener.h>
|
||||
|
||||
#define NGHTTP2_NO_SSIZE_T
|
||||
#include <nghttp2/nghttp2.h>
|
||||
|
||||
#define OUTPUT_WOULDBLOCK_THRESHOLD (1 << 16)
|
||||
@@ -277,16 +278,16 @@ static int session_send(http2_session_data *session_data) {
|
||||
}
|
||||
|
||||
/* Read the data in the bufferevent and feed them into nghttp2 library
|
||||
function. Invocation of nghttp2_session_mem_recv() may make
|
||||
function. Invocation of nghttp2_session_mem_recv2() may make
|
||||
additional pending frames, so call session_send() at the end of the
|
||||
function. */
|
||||
static int session_recv(http2_session_data *session_data) {
|
||||
ssize_t readlen;
|
||||
nghttp2_ssize readlen;
|
||||
struct evbuffer *input = bufferevent_get_input(session_data->bev);
|
||||
size_t datalen = evbuffer_get_length(input);
|
||||
unsigned char *data = evbuffer_pullup(input, -1);
|
||||
|
||||
readlen = nghttp2_session_mem_recv(session_data->session, data, datalen);
|
||||
readlen = nghttp2_session_mem_recv2(session_data->session, data, datalen);
|
||||
if (readlen < 0) {
|
||||
warnx("Fatal error: %s", nghttp2_strerror((int)readlen));
|
||||
return -1;
|
||||
@@ -301,8 +302,9 @@ static int session_recv(http2_session_data *session_data) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t send_callback(nghttp2_session *session, const uint8_t *data,
|
||||
size_t length, int flags, void *user_data) {
|
||||
static nghttp2_ssize send_callback(nghttp2_session *session,
|
||||
const uint8_t *data, size_t length,
|
||||
int flags, void *user_data) {
|
||||
http2_session_data *session_data = (http2_session_data *)user_data;
|
||||
struct bufferevent *bev = session_data->bev;
|
||||
(void)session;
|
||||
@@ -314,7 +316,7 @@ static ssize_t send_callback(nghttp2_session *session, const uint8_t *data,
|
||||
return NGHTTP2_ERR_WOULDBLOCK;
|
||||
}
|
||||
bufferevent_write(bev, data, length);
|
||||
return (ssize_t)length;
|
||||
return (nghttp2_ssize)length;
|
||||
}
|
||||
|
||||
/* Returns nonzero if the string |s| ends with the substring |sub| */
|
||||
@@ -370,11 +372,11 @@ static char *percent_decode(const uint8_t *value, size_t valuelen) {
|
||||
return res;
|
||||
}
|
||||
|
||||
static ssize_t file_read_callback(nghttp2_session *session, int32_t stream_id,
|
||||
uint8_t *buf, size_t length,
|
||||
uint32_t *data_flags,
|
||||
nghttp2_data_source *source,
|
||||
void *user_data) {
|
||||
static nghttp2_ssize file_read_callback(nghttp2_session *session,
|
||||
int32_t stream_id, uint8_t *buf,
|
||||
size_t length, uint32_t *data_flags,
|
||||
nghttp2_data_source *source,
|
||||
void *user_data) {
|
||||
int fd = source->fd;
|
||||
ssize_t r;
|
||||
(void)session;
|
||||
@@ -389,17 +391,17 @@ static ssize_t file_read_callback(nghttp2_session *session, int32_t stream_id,
|
||||
if (r == 0) {
|
||||
*data_flags |= NGHTTP2_DATA_FLAG_EOF;
|
||||
}
|
||||
return r;
|
||||
return (nghttp2_ssize)r;
|
||||
}
|
||||
|
||||
static int send_response(nghttp2_session *session, int32_t stream_id,
|
||||
nghttp2_nv *nva, size_t nvlen, int fd) {
|
||||
int rv;
|
||||
nghttp2_data_provider data_prd;
|
||||
nghttp2_data_provider2 data_prd;
|
||||
data_prd.source.fd = fd;
|
||||
data_prd.read_callback = file_read_callback;
|
||||
|
||||
rv = nghttp2_submit_response(session, stream_id, nva, nvlen, &data_prd);
|
||||
rv = nghttp2_submit_response2(session, stream_id, nva, nvlen, &data_prd);
|
||||
if (rv != 0) {
|
||||
warnx("Fatal error: %s", nghttp2_strerror(rv));
|
||||
return -1;
|
||||
@@ -590,7 +592,7 @@ static void initialize_nghttp2_session(http2_session_data *session_data) {
|
||||
|
||||
nghttp2_session_callbacks_new(&callbacks);
|
||||
|
||||
nghttp2_session_callbacks_set_send_callback(callbacks, send_callback);
|
||||
nghttp2_session_callbacks_set_send_callback2(callbacks, send_callback);
|
||||
|
||||
nghttp2_session_callbacks_set_on_frame_recv_callback(callbacks,
|
||||
on_frame_recv_callback);
|
||||
|
||||
@@ -40,7 +40,7 @@ namespace {
|
||||
void send_pending(nghttp2_session *session) {
|
||||
for (;;) {
|
||||
const uint8_t *data;
|
||||
auto n = nghttp2_session_mem_send(session, &data);
|
||||
auto n = nghttp2_session_mem_send2(session, &data);
|
||||
if (n == 0) {
|
||||
return;
|
||||
}
|
||||
@@ -70,7 +70,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
|
||||
nghttp2_settings_entry iv{NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS, 100};
|
||||
nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, &iv, 1);
|
||||
send_pending(session);
|
||||
nghttp2_session_mem_recv(session, data, size);
|
||||
nghttp2_session_mem_recv2(session, data, size);
|
||||
send_pending(session);
|
||||
|
||||
nghttp2_session_del(session);
|
||||
|
||||
@@ -44,7 +44,7 @@ namespace {
|
||||
void send_pending(nghttp2_session *session) {
|
||||
for (;;) {
|
||||
const uint8_t *data;
|
||||
auto n = nghttp2_session_mem_send(session, &data);
|
||||
auto n = nghttp2_session_mem_send2(session, &data);
|
||||
if (n == 0) {
|
||||
return;
|
||||
}
|
||||
@@ -87,7 +87,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
|
||||
send_pending(session);
|
||||
|
||||
std::vector<uint8_t> d = data_provider.ConsumeRemainingBytes<uint8_t>();
|
||||
nghttp2_session_mem_recv(session, d.data(), d.size());
|
||||
nghttp2_session_mem_recv2(session, d.data(), d.size());
|
||||
|
||||
send_pending(session);
|
||||
|
||||
|
||||
6
go.mod
6
go.mod
@@ -6,7 +6,7 @@ require (
|
||||
github.com/bradfitz/gomemcache v0.0.0-20230905024940-24af94b03874
|
||||
github.com/quic-go/quic-go v0.41.0
|
||||
github.com/tatsuhiro-t/go-nghttp2 v0.0.0-20240121064059-46ccb0a462a8
|
||||
golang.org/x/net v0.20.0
|
||||
golang.org/x/net v0.21.0
|
||||
)
|
||||
|
||||
require (
|
||||
@@ -15,10 +15,10 @@ require (
|
||||
github.com/onsi/ginkgo/v2 v2.9.5 // indirect
|
||||
github.com/quic-go/qpack v0.4.0 // indirect
|
||||
go.uber.org/mock v0.3.0 // indirect
|
||||
golang.org/x/crypto v0.18.0 // indirect
|
||||
golang.org/x/crypto v0.19.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20221205204356-47842c84f3db // indirect
|
||||
golang.org/x/mod v0.11.0 // indirect
|
||||
golang.org/x/sys v0.16.0 // indirect
|
||||
golang.org/x/sys v0.17.0 // indirect
|
||||
golang.org/x/text v0.14.0 // indirect
|
||||
golang.org/x/tools v0.9.1 // indirect
|
||||
)
|
||||
|
||||
12
go.sum
12
go.sum
@@ -34,17 +34,17 @@ github.com/tatsuhiro-t/go-nghttp2 v0.0.0-20240121064059-46ccb0a462a8 h1:zKJxuRe+
|
||||
github.com/tatsuhiro-t/go-nghttp2 v0.0.0-20240121064059-46ccb0a462a8/go.mod h1:gTqc3Q4boc+cKRlSFywTYdX9t6VGRcsThlNIWwaL3Dc=
|
||||
go.uber.org/mock v0.3.0 h1:3mUxI1No2/60yUYax92Pt8eNOEecx2D3lcXZh2NEZJo=
|
||||
go.uber.org/mock v0.3.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc=
|
||||
golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc=
|
||||
golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg=
|
||||
golang.org/x/crypto v0.19.0 h1:ENy+Az/9Y1vSrlrvBSyna3PITt4tiZLf7sgCjZBX7Wo=
|
||||
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
|
||||
golang.org/x/exp v0.0.0-20221205204356-47842c84f3db h1:D/cFflL63o2KSLJIwjlcIt8PR064j/xsmdEJL/YvY/o=
|
||||
golang.org/x/exp v0.0.0-20221205204356-47842c84f3db/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc=
|
||||
golang.org/x/mod v0.11.0 h1:bUO06HqtnRcc/7l71XBe4WcqTZ+3AH1J59zWDDwLKgU=
|
||||
golang.org/x/mod v0.11.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo=
|
||||
golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY=
|
||||
golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4=
|
||||
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
|
||||
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU=
|
||||
golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y=
|
||||
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
|
||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/tools v0.9.1 h1:8WMNJAz3zrtPmnYC7ISf5dEn3MT0gY7jBJfw27yrrLo=
|
||||
|
||||
@@ -58,7 +58,7 @@ func TestH1H1PlainGETClose(t *testing.T) {
|
||||
// 501 status code
|
||||
func TestH1H1InvalidMethod(t *testing.T) {
|
||||
opts := options{
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
handler: func(http.ResponseWriter, *http.Request) {
|
||||
t.Errorf("server should not forward this request")
|
||||
},
|
||||
}
|
||||
@@ -82,7 +82,7 @@ func TestH1H1InvalidMethod(t *testing.T) {
|
||||
// contains multiple Content-Length header fields.
|
||||
func TestH1H1MultipleRequestCL(t *testing.T) {
|
||||
opts := options{
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
handler: func(http.ResponseWriter, *http.Request) {
|
||||
t.Errorf("server should not forward bad request")
|
||||
},
|
||||
}
|
||||
@@ -255,7 +255,7 @@ func TestH1H1HostRewrite(t *testing.T) {
|
||||
// characters in host header field.
|
||||
func TestH1H1BadHost(t *testing.T) {
|
||||
opts := options{
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
handler: func(http.ResponseWriter, *http.Request) {
|
||||
t.Errorf("server should not forward this request")
|
||||
},
|
||||
}
|
||||
@@ -281,7 +281,7 @@ func TestH1H1BadHost(t *testing.T) {
|
||||
// bad characters in authority component of requset URI.
|
||||
func TestH1H1BadAuthority(t *testing.T) {
|
||||
opts := options{
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
handler: func(http.ResponseWriter, *http.Request) {
|
||||
t.Errorf("server should not forward this request")
|
||||
},
|
||||
}
|
||||
@@ -307,7 +307,7 @@ func TestH1H1BadAuthority(t *testing.T) {
|
||||
// bad characters in scheme component of requset URI.
|
||||
func TestH1H1BadScheme(t *testing.T) {
|
||||
opts := options{
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
handler: func(http.ResponseWriter, *http.Request) {
|
||||
t.Errorf("server should not forward this request")
|
||||
},
|
||||
}
|
||||
@@ -394,7 +394,7 @@ func TestH1H1HTTP10NoHostRewrite(t *testing.T) {
|
||||
// backend.
|
||||
func TestH1H1RequestTrailer(t *testing.T) {
|
||||
opts := options{
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
handler: func(_ http.ResponseWriter, r *http.Request) {
|
||||
buf := make([]byte, 4096)
|
||||
for {
|
||||
_, err := r.Body.Read(buf)
|
||||
@@ -436,7 +436,7 @@ func TestH1H1HeaderFieldBufferPath(t *testing.T) {
|
||||
// limit.
|
||||
opts := options{
|
||||
args: []string{"--request-header-field-buffer=100"},
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
handler: func(http.ResponseWriter, *http.Request) {
|
||||
t.Fatal("execution path should not be here")
|
||||
},
|
||||
}
|
||||
@@ -460,7 +460,7 @@ func TestH1H1HeaderFieldBufferPath(t *testing.T) {
|
||||
func TestH1H1HeaderFieldBuffer(t *testing.T) {
|
||||
opts := options{
|
||||
args: []string{"--request-header-field-buffer=10"},
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
handler: func(http.ResponseWriter, *http.Request) {
|
||||
t.Fatal("execution path should not be here")
|
||||
},
|
||||
}
|
||||
@@ -483,7 +483,7 @@ func TestH1H1HeaderFieldBuffer(t *testing.T) {
|
||||
func TestH1H1HeaderFields(t *testing.T) {
|
||||
opts := options{
|
||||
args: []string{"--max-request-header-fields=1"},
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
handler: func(http.ResponseWriter, *http.Request) {
|
||||
t.Fatal("execution path should not be here")
|
||||
},
|
||||
}
|
||||
@@ -533,7 +533,7 @@ func TestH1H1Websocket(t *testing.T) {
|
||||
func TestH1H1ReqPhaseSetHeader(t *testing.T) {
|
||||
opts := options{
|
||||
args: []string{"--mruby-file=" + testDir + "/req-set-header.rb"},
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
handler: func(_ http.ResponseWriter, r *http.Request) {
|
||||
if got, want := r.Header.Get("User-Agent"), "mruby"; got != want {
|
||||
t.Errorf("User-Agent = %v; want %v", got, want)
|
||||
}
|
||||
@@ -559,7 +559,7 @@ func TestH1H1ReqPhaseSetHeader(t *testing.T) {
|
||||
func TestH1H1ReqPhaseReturn(t *testing.T) {
|
||||
opts := options{
|
||||
args: []string{"--mruby-file=" + testDir + "/req-return.rb"},
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
handler: func(http.ResponseWriter, *http.Request) {
|
||||
t.Fatalf("request should not be forwarded")
|
||||
},
|
||||
}
|
||||
@@ -599,7 +599,7 @@ func TestH1H1ReqPhaseReturn(t *testing.T) {
|
||||
func TestH1H1ReqPhaseReturnCONNECTMethod(t *testing.T) {
|
||||
opts := options{
|
||||
args: []string{"--mruby-file=" + testDir + "/req-return.rb"},
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
handler: func(http.ResponseWriter, *http.Request) {
|
||||
t.Fatalf("request should not be forwarded")
|
||||
},
|
||||
}
|
||||
@@ -884,7 +884,7 @@ func TestH1H1CONNECTMethodFailure(t *testing.T) {
|
||||
func TestH1H2NoHost(t *testing.T) {
|
||||
opts := options{
|
||||
args: []string{"--http2-bridge"},
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
handler: func(http.ResponseWriter, *http.Request) {
|
||||
t.Errorf("server should not forward bad request")
|
||||
},
|
||||
}
|
||||
@@ -978,7 +978,7 @@ func TestH1H2HTTP10NoHostRewrite(t *testing.T) {
|
||||
func TestH1H2CrumbleCookie(t *testing.T) {
|
||||
opts := options{
|
||||
args: []string{"--http2-bridge"},
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
handler: func(_ http.ResponseWriter, r *http.Request) {
|
||||
if got, want := r.Header.Get("Cookie"), "alpha; bravo; charlie"; got != want {
|
||||
t.Errorf("Cookie: %v; want %v", got, want)
|
||||
}
|
||||
@@ -1006,7 +1006,7 @@ func TestH1H2CrumbleCookie(t *testing.T) {
|
||||
func TestH1H2GenerateVia(t *testing.T) {
|
||||
opts := options{
|
||||
args: []string{"--http2-bridge"},
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
handler: func(_ http.ResponseWriter, r *http.Request) {
|
||||
if got, want := r.Header.Get("Via"), "1.1 nghttpx"; got != want {
|
||||
t.Errorf("Via: %v; want %v", got, want)
|
||||
}
|
||||
@@ -1092,7 +1092,7 @@ func TestH1H2ReqPhaseReturn(t *testing.T) {
|
||||
"--http2-bridge",
|
||||
"--mruby-file=" + testDir + "/req-return.rb",
|
||||
},
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
handler: func(http.ResponseWriter, *http.Request) {
|
||||
t.Fatalf("request should not be forwarded")
|
||||
},
|
||||
}
|
||||
@@ -1172,7 +1172,7 @@ func TestH1H2RespPhaseReturn(t *testing.T) {
|
||||
func TestH1H2TE(t *testing.T) {
|
||||
opts := options{
|
||||
args: []string{"--http2-bridge"},
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
handler: func(_ http.ResponseWriter, r *http.Request) {
|
||||
if got, want := r.Header.Get("te"), "trailers"; got != want {
|
||||
t.Errorf("te: %v; want %v", got, want)
|
||||
}
|
||||
@@ -1200,7 +1200,7 @@ func TestH1H2TE(t *testing.T) {
|
||||
func TestH1APIBackendconfig(t *testing.T) {
|
||||
opts := options{
|
||||
args: []string{"-f127.0.0.1,3010;api;no-tls"},
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
handler: func(http.ResponseWriter, *http.Request) {
|
||||
t.Fatalf("request should not be forwarded")
|
||||
},
|
||||
connectPort: 3010,
|
||||
@@ -1242,7 +1242,7 @@ backend=127.0.0.1,3011
|
||||
func TestH1APIBackendconfigQuery(t *testing.T) {
|
||||
opts := options{
|
||||
args: []string{"-f127.0.0.1,3010;api;no-tls"},
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
handler: func(http.ResponseWriter, *http.Request) {
|
||||
t.Fatalf("request should not be forwarded")
|
||||
},
|
||||
connectPort: 3010,
|
||||
@@ -1284,7 +1284,7 @@ backend=127.0.0.1,3011
|
||||
func TestH1APIBackendconfigBadMethod(t *testing.T) {
|
||||
opts := options{
|
||||
args: []string{"-f127.0.0.1,3010;api;no-tls"},
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
handler: func(http.ResponseWriter, *http.Request) {
|
||||
t.Fatalf("request should not be forwarded")
|
||||
},
|
||||
connectPort: 3010,
|
||||
@@ -1325,7 +1325,7 @@ backend=127.0.0.1,3011
|
||||
func TestH1APIConfigrevision(t *testing.T) {
|
||||
opts := options{
|
||||
args: []string{"-f127.0.0.1,3010;api;no-tls"},
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
handler: func(http.ResponseWriter, *http.Request) {
|
||||
t.Fatalf("request should not be forwarded")
|
||||
},
|
||||
connectPort: 3010,
|
||||
@@ -1368,7 +1368,7 @@ func TestH1APIConfigrevision(t *testing.T) {
|
||||
func TestH1APINotFound(t *testing.T) {
|
||||
opts := options{
|
||||
args: []string{"-f127.0.0.1,3010;api;no-tls"},
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
handler: func(http.ResponseWriter, *http.Request) {
|
||||
t.Fatalf("request should not be forwarded")
|
||||
},
|
||||
connectPort: 3010,
|
||||
@@ -1409,7 +1409,7 @@ backend=127.0.0.1,3011
|
||||
func TestH1Healthmon(t *testing.T) {
|
||||
opts := options{
|
||||
args: []string{"-f127.0.0.1,3011;healthmon;no-tls"},
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
handler: func(http.ResponseWriter, *http.Request) {
|
||||
t.Fatalf("request should not be forwarded")
|
||||
},
|
||||
connectPort: 3011,
|
||||
@@ -1434,7 +1434,7 @@ func TestH1Healthmon(t *testing.T) {
|
||||
func TestH1ResponseBeforeRequestEnd(t *testing.T) {
|
||||
opts := options{
|
||||
args: []string{"--mruby-file=" + testDir + "/req-return.rb"},
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
handler: func(http.ResponseWriter, *http.Request) {
|
||||
t.Fatal("request should not be forwarded")
|
||||
},
|
||||
}
|
||||
@@ -1462,7 +1462,7 @@ func TestH1ResponseBeforeRequestEnd(t *testing.T) {
|
||||
// if the backend chunked encoded response ends prematurely.
|
||||
func TestH1H1ChunkedEndsPrematurely(t *testing.T) {
|
||||
opts := options{
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
handler: func(w http.ResponseWriter, _ *http.Request) {
|
||||
hj, ok := w.(http.Hijacker)
|
||||
if !ok {
|
||||
http.Error(w, "Could not hijack the connection", http.StatusInternalServerError)
|
||||
@@ -1495,7 +1495,7 @@ func TestH1H1ChunkedEndsPrematurely(t *testing.T) {
|
||||
// request which contains malformed transfer-encoding.
|
||||
func TestH1H1RequestMalformedTransferEncoding(t *testing.T) {
|
||||
opts := options{
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
handler: func(http.ResponseWriter, *http.Request) {
|
||||
t.Errorf("server should not forward bad request")
|
||||
},
|
||||
}
|
||||
@@ -1523,7 +1523,7 @@ func TestH1H1RequestMalformedTransferEncoding(t *testing.T) {
|
||||
// its response contains malformed transfer-encoding.
|
||||
func TestH1H1ResponseMalformedTransferEncoding(t *testing.T) {
|
||||
opts := options{
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
handler: func(w http.ResponseWriter, _ *http.Request) {
|
||||
hj, ok := w.(http.Hijacker)
|
||||
if !ok {
|
||||
http.Error(w, "Could not hijack the connection", http.StatusInternalServerError)
|
||||
@@ -1559,7 +1559,7 @@ func TestH1H1ResponseMalformedTransferEncoding(t *testing.T) {
|
||||
// its response contains unknown transfer-encoding.
|
||||
func TestH1H1ResponseUnknownTransferEncoding(t *testing.T) {
|
||||
opts := options{
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
handler: func(w http.ResponseWriter, _ *http.Request) {
|
||||
hj, ok := w.(http.Hijacker)
|
||||
if !ok {
|
||||
http.Error(w, "Could not hijack the connection", http.StatusInternalServerError)
|
||||
@@ -1607,7 +1607,7 @@ func TestH1H1ResponseUnknownTransferEncoding(t *testing.T) {
|
||||
// HTTP/1.0 request which contains transfer-encoding.
|
||||
func TestH1H1RequestHTTP10TransferEncoding(t *testing.T) {
|
||||
opts := options{
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
handler: func(http.ResponseWriter, *http.Request) {
|
||||
t.Errorf("server should not forward bad request")
|
||||
},
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@ func TestH2H1PlainGET(t *testing.T) {
|
||||
func TestH2H1AddXfp(t *testing.T) {
|
||||
opts := options{
|
||||
args: []string{"--no-strip-incoming-x-forwarded-proto"},
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
handler: func(_ http.ResponseWriter, r *http.Request) {
|
||||
xfp := r.Header.Get("X-Forwarded-Proto")
|
||||
if got, want := xfp, "foo, http"; got != want {
|
||||
t.Errorf("X-Forwarded-Proto = %q; want %q", got, want)
|
||||
@@ -72,7 +72,7 @@ func TestH2H1NoAddXfp(t *testing.T) {
|
||||
"--no-add-x-forwarded-proto",
|
||||
"--no-strip-incoming-x-forwarded-proto",
|
||||
},
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
handler: func(_ http.ResponseWriter, r *http.Request) {
|
||||
xfp := r.Header.Get("X-Forwarded-Proto")
|
||||
if got, want := xfp, "foo"; got != want {
|
||||
t.Errorf("X-Forwarded-Proto = %q; want %q", got, want)
|
||||
@@ -100,7 +100,7 @@ func TestH2H1NoAddXfp(t *testing.T) {
|
||||
// x-forwarded-proto header field.
|
||||
func TestH2H1StripXfp(t *testing.T) {
|
||||
opts := options{
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
handler: func(_ http.ResponseWriter, r *http.Request) {
|
||||
xfp := r.Header.Get("X-Forwarded-Proto")
|
||||
if got, want := xfp, "http"; got != want {
|
||||
t.Errorf("X-Forwarded-Proto = %q; want %q", got, want)
|
||||
@@ -129,7 +129,7 @@ func TestH2H1StripXfp(t *testing.T) {
|
||||
func TestH2H1StripNoAddXfp(t *testing.T) {
|
||||
opts := options{
|
||||
args: []string{"--no-add-x-forwarded-proto"},
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
handler: func(_ http.ResponseWriter, r *http.Request) {
|
||||
if got, found := r.Header["X-Forwarded-Proto"]; found {
|
||||
t.Errorf("X-Forwarded-Proto = %q; want nothing", got)
|
||||
}
|
||||
@@ -157,7 +157,7 @@ func TestH2H1StripNoAddXfp(t *testing.T) {
|
||||
func TestH2H1AddXff(t *testing.T) {
|
||||
opts := options{
|
||||
args: []string{"--add-x-forwarded-for"},
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
handler: func(_ http.ResponseWriter, r *http.Request) {
|
||||
xff := r.Header.Get("X-Forwarded-For")
|
||||
want := "127.0.0.1"
|
||||
if xff != want {
|
||||
@@ -184,7 +184,7 @@ func TestH2H1AddXff(t *testing.T) {
|
||||
func TestH2H1AddXff2(t *testing.T) {
|
||||
opts := options{
|
||||
args: []string{"--add-x-forwarded-for"},
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
handler: func(_ http.ResponseWriter, r *http.Request) {
|
||||
xff := r.Header.Get("X-Forwarded-For")
|
||||
want := "host, 127.0.0.1"
|
||||
if xff != want {
|
||||
@@ -214,7 +214,7 @@ func TestH2H1AddXff2(t *testing.T) {
|
||||
func TestH2H1StripXff(t *testing.T) {
|
||||
opts := options{
|
||||
args: []string{"--strip-incoming-x-forwarded-for"},
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
handler: func(_ http.ResponseWriter, r *http.Request) {
|
||||
if xff, found := r.Header["X-Forwarded-For"]; found {
|
||||
t.Errorf("X-Forwarded-For = %v; want nothing", xff)
|
||||
}
|
||||
@@ -245,7 +245,7 @@ func TestH2H1StripAddXff(t *testing.T) {
|
||||
"--strip-incoming-x-forwarded-for",
|
||||
"--add-x-forwarded-for",
|
||||
},
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
handler: func(_ http.ResponseWriter, r *http.Request) {
|
||||
xff := r.Header.Get("X-Forwarded-For")
|
||||
want := "127.0.0.1"
|
||||
if xff != want {
|
||||
@@ -275,7 +275,7 @@ func TestH2H1StripAddXff(t *testing.T) {
|
||||
func TestH2H1AddForwardedObfuscated(t *testing.T) {
|
||||
opts := options{
|
||||
args: []string{"--add-forwarded=by,for,host,proto"},
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
handler: func(_ http.ResponseWriter, r *http.Request) {
|
||||
pattern := fmt.Sprintf(`by=_[^;]+;for=_[^;]+;host="127\.0\.0\.1:%v";proto=http`, serverPort)
|
||||
validFwd := regexp.MustCompile(pattern)
|
||||
got := r.Header.Get("Forwarded")
|
||||
@@ -304,7 +304,7 @@ func TestH2H1AddForwardedObfuscated(t *testing.T) {
|
||||
func TestH2H1AddForwardedByIP(t *testing.T) {
|
||||
opts := options{
|
||||
args: []string{"--add-forwarded=by,for", "--forwarded-by=ip"},
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
handler: func(_ http.ResponseWriter, r *http.Request) {
|
||||
pattern := fmt.Sprintf(`by="127\.0\.0\.1:%v";for=_[^;]+`, serverPort)
|
||||
validFwd := regexp.MustCompile(pattern)
|
||||
if got := r.Header.Get("Forwarded"); !validFwd.MatchString(got) {
|
||||
@@ -335,7 +335,7 @@ func TestH2H1AddForwardedForIP(t *testing.T) {
|
||||
"--forwarded-by=_alpha",
|
||||
"--forwarded-for=ip",
|
||||
},
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
handler: func(_ http.ResponseWriter, r *http.Request) {
|
||||
want := fmt.Sprintf(`by=_alpha;for=127.0.0.1;host="127.0.0.1:%v";proto=http`, serverPort)
|
||||
if got := r.Header.Get("Forwarded"); got != want {
|
||||
t.Errorf("Forwarded = %v; want %v", got, want)
|
||||
@@ -362,7 +362,7 @@ func TestH2H1AddForwardedForIP(t *testing.T) {
|
||||
func TestH2H1AddForwardedMerge(t *testing.T) {
|
||||
opts := options{
|
||||
args: []string{"--add-forwarded=proto"},
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
handler: func(_ http.ResponseWriter, r *http.Request) {
|
||||
if got, want := r.Header.Get("Forwarded"), `host=foo, proto=http`; got != want {
|
||||
t.Errorf("Forwarded = %v; want %v", got, want)
|
||||
}
|
||||
@@ -394,7 +394,7 @@ func TestH2H1AddForwardedStrip(t *testing.T) {
|
||||
"--strip-incoming-forwarded",
|
||||
"--add-forwarded=proto",
|
||||
},
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
handler: func(_ http.ResponseWriter, r *http.Request) {
|
||||
if got, want := r.Header.Get("Forwarded"), `proto=http`; got != want {
|
||||
t.Errorf("Forwarded = %v; want %v", got, want)
|
||||
}
|
||||
@@ -422,7 +422,7 @@ func TestH2H1AddForwardedStrip(t *testing.T) {
|
||||
func TestH2H1StripForwarded(t *testing.T) {
|
||||
opts := options{
|
||||
args: []string{"--strip-incoming-forwarded"},
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
handler: func(_ http.ResponseWriter, r *http.Request) {
|
||||
if got, found := r.Header["Forwarded"]; found {
|
||||
t.Errorf("Forwarded = %v; want nothing", got)
|
||||
}
|
||||
@@ -454,7 +454,7 @@ func TestH2H1AddForwardedStatic(t *testing.T) {
|
||||
"--add-forwarded=by,for",
|
||||
"--forwarded-by=_alpha",
|
||||
},
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
handler: func(_ http.ResponseWriter, r *http.Request) {
|
||||
pattern := `by=_alpha;for=_[^;]+`
|
||||
validFwd := regexp.MustCompile(pattern)
|
||||
if got := r.Header.Get("Forwarded"); !validFwd.MatchString(got) {
|
||||
@@ -480,7 +480,7 @@ func TestH2H1AddForwardedStatic(t *testing.T) {
|
||||
// from backend server.
|
||||
func TestH2H1GenerateVia(t *testing.T) {
|
||||
opts := options{
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
handler: func(_ http.ResponseWriter, r *http.Request) {
|
||||
if got, want := r.Header.Get("Via"), "2 nghttpx"; got != want {
|
||||
t.Errorf("Via: %v; want %v", got, want)
|
||||
}
|
||||
@@ -639,7 +639,7 @@ func TestH2H1BadRequestCL(t *testing.T) {
|
||||
// response body size.
|
||||
func TestH2H1BadResponseCL(t *testing.T) {
|
||||
opts := options{
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
handler: func(w http.ResponseWriter, _ *http.Request) {
|
||||
// we set content-length: 1024, but only send 3 bytes.
|
||||
w.Header().Add("Content-Length", "1024")
|
||||
if _, err := w.Write([]byte("foo")); err != nil {
|
||||
@@ -667,7 +667,7 @@ func TestH2H1BadResponseCL(t *testing.T) {
|
||||
// works.
|
||||
func TestH2H1LocationRewrite(t *testing.T) {
|
||||
opts := options{
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
handler: func(w http.ResponseWriter, _ *http.Request) {
|
||||
// TODO we cannot get st.ts's port number
|
||||
// here.. 8443 is just a place holder. We
|
||||
// ignore it on rewrite.
|
||||
@@ -693,7 +693,7 @@ func TestH2H1LocationRewrite(t *testing.T) {
|
||||
// TestH2H1ChunkedRequestBody tests that chunked request body works.
|
||||
func TestH2H1ChunkedRequestBody(t *testing.T) {
|
||||
opts := options{
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
handler: func(_ http.ResponseWriter, r *http.Request) {
|
||||
want := "[chunked]"
|
||||
if got := fmt.Sprint(r.TransferEncoding); got != want {
|
||||
t.Errorf("Transfer-Encoding: %v; want %v", got, want)
|
||||
@@ -728,7 +728,7 @@ func TestH2H1ChunkedRequestBody(t *testing.T) {
|
||||
// multiple Content-Length request header fields.
|
||||
func TestH2H1MultipleRequestCL(t *testing.T) {
|
||||
opts := options{
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
handler: func(http.ResponseWriter, *http.Request) {
|
||||
t.Errorf("server should not forward bad request")
|
||||
},
|
||||
}
|
||||
@@ -754,7 +754,7 @@ func TestH2H1MultipleRequestCL(t *testing.T) {
|
||||
// Content-Length which cannot be parsed as a number.
|
||||
func TestH2H1InvalidRequestCL(t *testing.T) {
|
||||
opts := options{
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
handler: func(http.ResponseWriter, *http.Request) {
|
||||
t.Errorf("server should not forward bad request")
|
||||
},
|
||||
}
|
||||
@@ -800,7 +800,7 @@ func TestH2H1InvalidRequestCL(t *testing.T) {
|
||||
// 501.
|
||||
func TestH2H1InvalidMethod(t *testing.T) {
|
||||
opts := options{
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
handler: func(http.ResponseWriter, *http.Request) {
|
||||
t.Errorf("server should not forward this request")
|
||||
},
|
||||
}
|
||||
@@ -823,7 +823,7 @@ func TestH2H1InvalidMethod(t *testing.T) {
|
||||
// bad characters in :authority header field.
|
||||
func TestH2H1BadAuthority(t *testing.T) {
|
||||
opts := options{
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
handler: func(http.ResponseWriter, *http.Request) {
|
||||
t.Errorf("server should not forward this request")
|
||||
},
|
||||
}
|
||||
@@ -846,7 +846,7 @@ func TestH2H1BadAuthority(t *testing.T) {
|
||||
// bad characters in :scheme header field.
|
||||
func TestH2H1BadScheme(t *testing.T) {
|
||||
opts := options{
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
handler: func(http.ResponseWriter, *http.Request) {
|
||||
t.Errorf("server should not forward this request")
|
||||
},
|
||||
}
|
||||
@@ -869,7 +869,7 @@ func TestH2H1BadScheme(t *testing.T) {
|
||||
// request is assembled into 1 when forwarding to HTTP/1 backend link.
|
||||
func TestH2H1AssembleCookies(t *testing.T) {
|
||||
opts := options{
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
handler: func(_ http.ResponseWriter, r *http.Request) {
|
||||
if got, want := r.Header.Get("Cookie"), "alpha; bravo; charlie"; got != want {
|
||||
t.Errorf("Cookie: %v; want %v", got, want)
|
||||
}
|
||||
@@ -918,7 +918,7 @@ func TestH2H1TETrailers(t *testing.T) {
|
||||
// field contains gzip.
|
||||
func TestH2H1TEGzip(t *testing.T) {
|
||||
opts := options{
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
handler: func(http.ResponseWriter, *http.Request) {
|
||||
t.Error("server should not forward bad request")
|
||||
},
|
||||
}
|
||||
@@ -967,7 +967,7 @@ func TestH2H1SNI(t *testing.T) {
|
||||
// connection is encrypted.
|
||||
func TestH2H1TLSXfp(t *testing.T) {
|
||||
opts := options{
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
handler: func(_ http.ResponseWriter, r *http.Request) {
|
||||
if got, want := r.Header.Get("x-forwarded-proto"), "http"; got != want {
|
||||
t.Errorf("x-forwarded-proto: want %v; got %v", want, got)
|
||||
}
|
||||
@@ -1028,7 +1028,7 @@ func TestH2H1ServerPush(t *testing.T) {
|
||||
// backend.
|
||||
func TestH2H1RequestTrailer(t *testing.T) {
|
||||
opts := options{
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
handler: func(_ http.ResponseWriter, r *http.Request) {
|
||||
buf := make([]byte, 4096)
|
||||
for {
|
||||
_, err := r.Body.Read(buf)
|
||||
@@ -1067,7 +1067,7 @@ func TestH2H1RequestTrailer(t *testing.T) {
|
||||
func TestH2H1HeaderFieldBuffer(t *testing.T) {
|
||||
opts := options{
|
||||
args: []string{"--request-header-field-buffer=10"},
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
handler: func(http.ResponseWriter, *http.Request) {
|
||||
t.Fatal("execution path should not be here")
|
||||
},
|
||||
}
|
||||
@@ -1090,7 +1090,7 @@ func TestH2H1HeaderFieldBuffer(t *testing.T) {
|
||||
func TestH2H1HeaderFields(t *testing.T) {
|
||||
opts := options{
|
||||
args: []string{"--max-request-header-fields=1"},
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
handler: func(http.ResponseWriter, *http.Request) {
|
||||
t.Fatal("execution path should not be here")
|
||||
},
|
||||
}
|
||||
@@ -1115,7 +1115,7 @@ func TestH2H1HeaderFields(t *testing.T) {
|
||||
func TestH2H1ReqPhaseSetHeader(t *testing.T) {
|
||||
opts := options{
|
||||
args: []string{"--mruby-file=" + testDir + "/req-set-header.rb"},
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
handler: func(_ http.ResponseWriter, r *http.Request) {
|
||||
if got, want := r.Header.Get("User-Agent"), "mruby"; got != want {
|
||||
t.Errorf("User-Agent = %v; want %v", got, want)
|
||||
}
|
||||
@@ -1141,7 +1141,7 @@ func TestH2H1ReqPhaseSetHeader(t *testing.T) {
|
||||
func TestH2H1ReqPhaseReturn(t *testing.T) {
|
||||
opts := options{
|
||||
args: []string{"--mruby-file=" + testDir + "/req-return.rb"},
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
handler: func(http.ResponseWriter, *http.Request) {
|
||||
t.Fatalf("request should not be forwarded")
|
||||
},
|
||||
}
|
||||
@@ -1284,7 +1284,7 @@ func TestH2H1ProxyProtocolV1ForwardedForObfuscated(t *testing.T) {
|
||||
"--add-forwarded=for",
|
||||
"--forwarded-for=obfuscated",
|
||||
},
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
handler: func(_ http.ResponseWriter, r *http.Request) {
|
||||
if got := r.Header.Get("Forwarded"); !validFwd.MatchString(got) {
|
||||
t.Errorf("Forwarded: %v; want pattern %v", got, pattern)
|
||||
}
|
||||
@@ -1321,7 +1321,7 @@ func TestH2H1ProxyProtocolV1TCP4(t *testing.T) {
|
||||
"--add-forwarded=for",
|
||||
"--forwarded-for=ip",
|
||||
},
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
handler: func(_ http.ResponseWriter, r *http.Request) {
|
||||
if got, want := r.Header.Get("X-Forwarded-For"), "192.168.0.2"; got != want {
|
||||
t.Errorf("X-Forwarded-For: %v; want %v", got, want)
|
||||
}
|
||||
@@ -1361,7 +1361,7 @@ func TestH2H1ProxyProtocolV1TCP6(t *testing.T) {
|
||||
"--add-forwarded=for",
|
||||
"--forwarded-for=ip",
|
||||
},
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
handler: func(_ http.ResponseWriter, r *http.Request) {
|
||||
if got, want := r.Header.Get("X-Forwarded-For"), "2001:0db8:85a3:0000:0000:8a2e:0370:7334"; got != want {
|
||||
t.Errorf("X-Forwarded-For: %v; want %v", got, want)
|
||||
}
|
||||
@@ -1401,7 +1401,7 @@ func TestH2H1ProxyProtocolV1TCP4TLS(t *testing.T) {
|
||||
"--add-forwarded=for",
|
||||
"--forwarded-for=ip",
|
||||
},
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
handler: func(_ http.ResponseWriter, r *http.Request) {
|
||||
if got, want := r.Header.Get("X-Forwarded-For"), "192.168.0.2"; got != want {
|
||||
t.Errorf("X-Forwarded-For: %v; want %v", got, want)
|
||||
}
|
||||
@@ -1439,7 +1439,7 @@ func TestH2H1ProxyProtocolV1TCP6TLS(t *testing.T) {
|
||||
"--add-forwarded=for",
|
||||
"--forwarded-for=ip",
|
||||
},
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
handler: func(_ http.ResponseWriter, r *http.Request) {
|
||||
if got, want := r.Header.Get("X-Forwarded-For"), "2001:0db8:85a3:0000:0000:8a2e:0370:7334"; got != want {
|
||||
t.Errorf("X-Forwarded-For: %v; want %v", got, want)
|
||||
}
|
||||
@@ -1476,7 +1476,7 @@ func TestH2H1ProxyProtocolV1Unknown(t *testing.T) {
|
||||
"--add-forwarded=for",
|
||||
"--forwarded-for=ip",
|
||||
},
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
handler: func(_ http.ResponseWriter, r *http.Request) {
|
||||
if got, notWant := r.Header.Get("X-Forwarded-For"), "192.168.0.2"; got == notWant {
|
||||
t.Errorf("X-Forwarded-For: %v; want something else", got)
|
||||
}
|
||||
@@ -1881,7 +1881,7 @@ func TestH2H1ProxyProtocolV2TCP4(t *testing.T) {
|
||||
"--add-forwarded=for",
|
||||
"--forwarded-for=ip",
|
||||
},
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
handler: func(_ http.ResponseWriter, r *http.Request) {
|
||||
if got, want := r.Header.Get("X-Forwarded-For"), "192.168.0.2"; got != want {
|
||||
t.Errorf("X-Forwarded-For: %v; want %v", got, want)
|
||||
}
|
||||
@@ -1937,7 +1937,7 @@ func TestH2H1ProxyProtocolV2TCP6(t *testing.T) {
|
||||
"--add-forwarded=for",
|
||||
"--forwarded-for=ip",
|
||||
},
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
handler: func(_ http.ResponseWriter, r *http.Request) {
|
||||
if got, want := r.Header.Get("X-Forwarded-For"), "2001:db8:85a3::8a2e:370:7334"; got != want {
|
||||
t.Errorf("X-Forwarded-For: %v; want %v", got, want)
|
||||
}
|
||||
@@ -2009,7 +2009,7 @@ func TestH2H1ProxyProtocolV2TCP4TLS(t *testing.T) {
|
||||
"--add-forwarded=for",
|
||||
"--forwarded-for=ip",
|
||||
},
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
handler: func(_ http.ResponseWriter, r *http.Request) {
|
||||
if got, want := r.Header.Get("X-Forwarded-For"), "192.168.0.2"; got != want {
|
||||
t.Errorf("X-Forwarded-For: %v; want %v", got, want)
|
||||
}
|
||||
@@ -2063,7 +2063,7 @@ func TestH2H1ProxyProtocolV2TCP6TLS(t *testing.T) {
|
||||
"--add-forwarded=for",
|
||||
"--forwarded-for=ip",
|
||||
},
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
handler: func(_ http.ResponseWriter, r *http.Request) {
|
||||
if got, want := r.Header.Get("X-Forwarded-For"), "2001:db8:85a3::8a2e:370:7334"; got != want {
|
||||
t.Errorf("X-Forwarded-For: %v; want %v", got, want)
|
||||
}
|
||||
@@ -2100,7 +2100,7 @@ func TestH2H1ProxyProtocolV2Local(t *testing.T) {
|
||||
"--add-forwarded=for",
|
||||
"--forwarded-for=ip",
|
||||
},
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
handler: func(_ http.ResponseWriter, r *http.Request) {
|
||||
if got, want := r.Header.Get("X-Forwarded-For"), "127.0.0.1"; got != want {
|
||||
t.Errorf("X-Forwarded-For: %v; want %v", got, want)
|
||||
}
|
||||
@@ -2193,7 +2193,7 @@ func TestH2H1ProxyProtocolV2Unix(t *testing.T) {
|
||||
"--add-forwarded=for",
|
||||
"--forwarded-for=ip",
|
||||
},
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
handler: func(_ http.ResponseWriter, r *http.Request) {
|
||||
if got, want := r.Header.Get("X-Forwarded-For"), "127.0.0.1"; got != want {
|
||||
t.Errorf("X-Forwarded-For: %v; want %v", got, want)
|
||||
}
|
||||
@@ -2248,7 +2248,7 @@ func TestH2H1ProxyProtocolV2Unspec(t *testing.T) {
|
||||
"--add-forwarded=for",
|
||||
"--forwarded-for=ip",
|
||||
},
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
handler: func(_ http.ResponseWriter, r *http.Request) {
|
||||
if got, want := r.Header.Get("X-Forwarded-For"), "127.0.0.1"; got != want {
|
||||
t.Errorf("X-Forwarded-For: %v; want %v", got, want)
|
||||
}
|
||||
@@ -2383,7 +2383,7 @@ func TestH2H1HTTPSRedirectPort(t *testing.T) {
|
||||
// transfer-encoding is valid.
|
||||
func TestH2H1Code204(t *testing.T) {
|
||||
opts := options{
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
handler: func(w http.ResponseWriter, _ *http.Request) {
|
||||
w.WriteHeader(http.StatusNoContent)
|
||||
},
|
||||
}
|
||||
@@ -2406,7 +2406,7 @@ func TestH2H1Code204(t *testing.T) {
|
||||
// is allowed.
|
||||
func TestH2H1Code204CL0(t *testing.T) {
|
||||
opts := options{
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
handler: func(w http.ResponseWriter, _ *http.Request) {
|
||||
hj, ok := w.(http.Hijacker)
|
||||
if !ok {
|
||||
http.Error(w, "Could not hijack the connection", http.StatusInternalServerError)
|
||||
@@ -2447,7 +2447,7 @@ func TestH2H1Code204CL0(t *testing.T) {
|
||||
// content-length is not allowed.
|
||||
func TestH2H1Code204CLNonzero(t *testing.T) {
|
||||
opts := options{
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
handler: func(w http.ResponseWriter, _ *http.Request) {
|
||||
hj, ok := w.(http.Hijacker)
|
||||
if !ok {
|
||||
http.Error(w, "Could not hijack the connection", http.StatusInternalServerError)
|
||||
@@ -2484,7 +2484,7 @@ func TestH2H1Code204CLNonzero(t *testing.T) {
|
||||
// not allowed.
|
||||
func TestH2H1Code204TE(t *testing.T) {
|
||||
opts := options{
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
handler: func(w http.ResponseWriter, _ *http.Request) {
|
||||
hj, ok := w.(http.Hijacker)
|
||||
if !ok {
|
||||
http.Error(w, "Could not hijack the connection", http.StatusInternalServerError)
|
||||
@@ -2659,7 +2659,7 @@ func TestH2H1GracefulShutdown(t *testing.T) {
|
||||
func TestH2H2MultipleResponseCL(t *testing.T) {
|
||||
opts := options{
|
||||
args: []string{"--http2-bridge"},
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
handler: func(w http.ResponseWriter, _ *http.Request) {
|
||||
w.Header().Add("content-length", "1")
|
||||
w.Header().Add("content-length", "1")
|
||||
},
|
||||
@@ -2684,7 +2684,7 @@ func TestH2H2MultipleResponseCL(t *testing.T) {
|
||||
func TestH2H2InvalidResponseCL(t *testing.T) {
|
||||
opts := options{
|
||||
args: []string{"--http2-bridge"},
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
handler: func(w http.ResponseWriter, _ *http.Request) {
|
||||
w.Header().Add("content-length", "")
|
||||
},
|
||||
}
|
||||
@@ -2783,7 +2783,7 @@ func TestH2H2NoHostRewrite(t *testing.T) {
|
||||
func TestH2H2TLSXfp(t *testing.T) {
|
||||
opts := options{
|
||||
args: []string{"--http2-bridge"},
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
handler: func(_ http.ResponseWriter, r *http.Request) {
|
||||
if got, want := r.Header.Get("x-forwarded-proto"), "http"; got != want {
|
||||
t.Errorf("x-forwarded-proto: want %v; got %v", want, got)
|
||||
}
|
||||
@@ -2812,7 +2812,7 @@ func TestH2H2AddXfp(t *testing.T) {
|
||||
"--http2-bridge",
|
||||
"--no-strip-incoming-x-forwarded-proto",
|
||||
},
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
handler: func(_ http.ResponseWriter, r *http.Request) {
|
||||
xfp := r.Header.Get("X-Forwarded-Proto")
|
||||
if got, want := xfp, "foo, http"; got != want {
|
||||
t.Errorf("X-Forwarded-Proto = %q; want %q", got, want)
|
||||
@@ -2846,7 +2846,7 @@ func TestH2H2NoAddXfp(t *testing.T) {
|
||||
"--no-add-x-forwarded-proto",
|
||||
"--no-strip-incoming-x-forwarded-proto",
|
||||
},
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
handler: func(_ http.ResponseWriter, r *http.Request) {
|
||||
xfp := r.Header.Get("X-Forwarded-Proto")
|
||||
if got, want := xfp, "foo"; got != want {
|
||||
t.Errorf("X-Forwarded-Proto = %q; want %q", got, want)
|
||||
@@ -2876,7 +2876,7 @@ func TestH2H2NoAddXfp(t *testing.T) {
|
||||
func TestH2H2StripXfp(t *testing.T) {
|
||||
opts := options{
|
||||
args: []string{"--http2-bridge"},
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
handler: func(_ http.ResponseWriter, r *http.Request) {
|
||||
xfp := r.Header.Get("X-Forwarded-Proto")
|
||||
if got, want := xfp, "http"; got != want {
|
||||
t.Errorf("X-Forwarded-Proto = %q; want %q", got, want)
|
||||
@@ -2906,7 +2906,7 @@ func TestH2H2StripXfp(t *testing.T) {
|
||||
func TestH2H2StripNoAddXfp(t *testing.T) {
|
||||
opts := options{
|
||||
args: []string{"--http2-bridge", "--no-add-x-forwarded-proto"},
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
handler: func(_ http.ResponseWriter, r *http.Request) {
|
||||
if got, found := r.Header["X-Forwarded-Proto"]; found {
|
||||
t.Errorf("X-Forwarded-Proto = %q; want nothing", got)
|
||||
}
|
||||
@@ -2935,7 +2935,7 @@ func TestH2H2StripNoAddXfp(t *testing.T) {
|
||||
func TestH2H2AddXff(t *testing.T) {
|
||||
opts := options{
|
||||
args: []string{"--http2-bridge", "--add-x-forwarded-for"},
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
handler: func(_ http.ResponseWriter, r *http.Request) {
|
||||
xff := r.Header.Get("X-Forwarded-For")
|
||||
want := "127.0.0.1"
|
||||
if xff != want {
|
||||
@@ -2963,7 +2963,7 @@ func TestH2H2AddXff(t *testing.T) {
|
||||
func TestH2H2AddXff2(t *testing.T) {
|
||||
opts := options{
|
||||
args: []string{"--http2-bridge", "--add-x-forwarded-for"},
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
handler: func(_ http.ResponseWriter, r *http.Request) {
|
||||
xff := r.Header.Get("X-Forwarded-For")
|
||||
want := "host, 127.0.0.1"
|
||||
if xff != want {
|
||||
@@ -2997,7 +2997,7 @@ func TestH2H2StripXff(t *testing.T) {
|
||||
"--http2-bridge",
|
||||
"--strip-incoming-x-forwarded-for",
|
||||
},
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
handler: func(_ http.ResponseWriter, r *http.Request) {
|
||||
if xff, found := r.Header["X-Forwarded-For"]; found {
|
||||
t.Errorf("X-Forwarded-For = %v; want nothing", xff)
|
||||
}
|
||||
@@ -3030,7 +3030,7 @@ func TestH2H2StripAddXff(t *testing.T) {
|
||||
"--strip-incoming-x-forwarded-for",
|
||||
"--add-x-forwarded-for",
|
||||
},
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
handler: func(_ http.ResponseWriter, r *http.Request) {
|
||||
xff := r.Header.Get("X-Forwarded-For")
|
||||
want := "127.0.0.1"
|
||||
if xff != want {
|
||||
@@ -3065,7 +3065,7 @@ func TestH2H2AddForwarded(t *testing.T) {
|
||||
"--add-forwarded=by,for,host,proto",
|
||||
"--forwarded-by=_alpha",
|
||||
},
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
handler: func(_ http.ResponseWriter, r *http.Request) {
|
||||
pattern := fmt.Sprintf(`by=_alpha;for=_[^;]+;host="127\.0\.0\.1:%v";proto=https`, serverPort)
|
||||
validFwd := regexp.MustCompile(pattern)
|
||||
if got := r.Header.Get("Forwarded"); !validFwd.MatchString(got) {
|
||||
@@ -3099,7 +3099,7 @@ func TestH2H2AddForwardedMerge(t *testing.T) {
|
||||
"--add-forwarded=by,host,proto",
|
||||
"--forwarded-by=_alpha",
|
||||
},
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
handler: func(_ http.ResponseWriter, r *http.Request) {
|
||||
want := fmt.Sprintf(`host=foo, by=_alpha;host="127.0.0.1:%v";proto=https`, serverPort)
|
||||
if got := r.Header.Get("Forwarded"); got != want {
|
||||
t.Errorf("Forwarded = %v; want %v", got, want)
|
||||
@@ -3136,7 +3136,7 @@ func TestH2H2AddForwardedStrip(t *testing.T) {
|
||||
"--add-forwarded=by,host,proto",
|
||||
"--forwarded-by=_alpha",
|
||||
},
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
handler: func(_ http.ResponseWriter, r *http.Request) {
|
||||
want := fmt.Sprintf(`by=_alpha;host="127.0.0.1:%v";proto=https`, serverPort)
|
||||
if got := r.Header.Get("Forwarded"); got != want {
|
||||
t.Errorf("Forwarded = %v; want %v", got, want)
|
||||
@@ -3167,7 +3167,7 @@ func TestH2H2AddForwardedStrip(t *testing.T) {
|
||||
func TestH2H2StripForwarded(t *testing.T) {
|
||||
opts := options{
|
||||
args: []string{"--http2-bridge", "--strip-incoming-forwarded"},
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
handler: func(_ http.ResponseWriter, r *http.Request) {
|
||||
if got, found := r.Header["Forwarded"]; found {
|
||||
t.Errorf("Forwarded = %v; want nothing", got)
|
||||
}
|
||||
@@ -3200,7 +3200,7 @@ func TestH2H2ReqPhaseReturn(t *testing.T) {
|
||||
"--http2-bridge",
|
||||
"--mruby-file=" + testDir + "/req-return.rb",
|
||||
},
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
handler: func(http.ResponseWriter, *http.Request) {
|
||||
t.Fatalf("request should not be forwarded")
|
||||
},
|
||||
}
|
||||
@@ -3322,7 +3322,7 @@ func TestH2H2DNS(t *testing.T) {
|
||||
func TestH2H2Code204(t *testing.T) {
|
||||
opts := options{
|
||||
args: []string{"--http2-bridge"},
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
handler: func(w http.ResponseWriter, _ *http.Request) {
|
||||
w.WriteHeader(http.StatusNoContent)
|
||||
},
|
||||
}
|
||||
@@ -3346,7 +3346,7 @@ func TestH2H2Code204(t *testing.T) {
|
||||
func TestH2APIBackendconfig(t *testing.T) {
|
||||
opts := options{
|
||||
args: []string{"-f127.0.0.1,3010;api;no-tls"},
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
handler: func(http.ResponseWriter, *http.Request) {
|
||||
t.Fatalf("request should not be forwarded")
|
||||
},
|
||||
connectPort: 3010,
|
||||
@@ -3388,7 +3388,7 @@ backend=127.0.0.1,3011
|
||||
func TestH2APIBackendconfigQuery(t *testing.T) {
|
||||
opts := options{
|
||||
args: []string{"-f127.0.0.1,3010;api;no-tls"},
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
handler: func(http.ResponseWriter, *http.Request) {
|
||||
t.Fatalf("request should not be forwarded")
|
||||
},
|
||||
connectPort: 3010,
|
||||
@@ -3430,7 +3430,7 @@ backend=127.0.0.1,3011
|
||||
func TestH2APIBackendconfigBadMethod(t *testing.T) {
|
||||
opts := options{
|
||||
args: []string{"-f127.0.0.1,3010;api;no-tls"},
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
handler: func(http.ResponseWriter, *http.Request) {
|
||||
t.Fatalf("request should not be forwarded")
|
||||
},
|
||||
connectPort: 3010,
|
||||
@@ -3471,7 +3471,7 @@ backend=127.0.0.1,3011
|
||||
func TestH2APIConfigrevision(t *testing.T) {
|
||||
opts := options{
|
||||
args: []string{"-f127.0.0.1,3010;api;no-tls"},
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
handler: func(http.ResponseWriter, *http.Request) {
|
||||
t.Fatalf("request should not be forwarded")
|
||||
},
|
||||
connectPort: 3010,
|
||||
@@ -3514,7 +3514,7 @@ func TestH2APIConfigrevision(t *testing.T) {
|
||||
func TestH2APINotFound(t *testing.T) {
|
||||
opts := options{
|
||||
args: []string{"-f127.0.0.1,3010;api;no-tls"},
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
handler: func(http.ResponseWriter, *http.Request) {
|
||||
t.Fatalf("request should not be forwarded")
|
||||
},
|
||||
connectPort: 3010,
|
||||
@@ -3555,7 +3555,7 @@ backend=127.0.0.1,3011
|
||||
func TestH2Healthmon(t *testing.T) {
|
||||
opts := options{
|
||||
args: []string{"-f127.0.0.1,3011;healthmon;no-tls"},
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
handler: func(http.ResponseWriter, *http.Request) {
|
||||
t.Fatalf("request should not be forwarded")
|
||||
},
|
||||
connectPort: 3011,
|
||||
@@ -3580,7 +3580,7 @@ func TestH2Healthmon(t *testing.T) {
|
||||
func TestH2ResponseBeforeRequestEnd(t *testing.T) {
|
||||
opts := options{
|
||||
args: []string{"--mruby-file=" + testDir + "/req-return.rb"},
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
handler: func(http.ResponseWriter, *http.Request) {
|
||||
t.Fatal("request should not be forwarded")
|
||||
},
|
||||
}
|
||||
@@ -3603,7 +3603,7 @@ func TestH2ResponseBeforeRequestEnd(t *testing.T) {
|
||||
// backend chunked encoded response ends prematurely.
|
||||
func TestH2H1ChunkedEndsPrematurely(t *testing.T) {
|
||||
opts := options{
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
handler: func(w http.ResponseWriter, _ *http.Request) {
|
||||
hj, ok := w.(http.Hijacker)
|
||||
if !ok {
|
||||
http.Error(w, "Could not hijack the connection", http.StatusInternalServerError)
|
||||
@@ -3641,7 +3641,7 @@ func TestH2H1ChunkedEndsPrematurely(t *testing.T) {
|
||||
func TestH2H1RequireHTTPSchemeHTTPSWithoutEncryption(t *testing.T) {
|
||||
opts := options{
|
||||
args: []string{"--require-http-scheme"},
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
handler: func(http.ResponseWriter, *http.Request) {
|
||||
t.Errorf("server should not forward this request")
|
||||
},
|
||||
}
|
||||
@@ -3666,7 +3666,7 @@ func TestH2H1RequireHTTPSchemeHTTPSWithoutEncryption(t *testing.T) {
|
||||
func TestH2H1RequireHTTPSchemeHTTPWithEncryption(t *testing.T) {
|
||||
opts := options{
|
||||
args: []string{"--require-http-scheme"},
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
handler: func(http.ResponseWriter, *http.Request) {
|
||||
t.Errorf("server should not forward this request")
|
||||
},
|
||||
tls: true,
|
||||
@@ -3693,7 +3693,7 @@ func TestH2H1RequireHTTPSchemeHTTPWithEncryption(t *testing.T) {
|
||||
func TestH2H1RequireHTTPSchemeUnknownSchemeWithoutEncryption(t *testing.T) {
|
||||
opts := options{
|
||||
args: []string{"--require-http-scheme"},
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
handler: func(http.ResponseWriter, *http.Request) {
|
||||
t.Errorf("server should not forward this request")
|
||||
},
|
||||
}
|
||||
@@ -3718,7 +3718,7 @@ func TestH2H1RequireHTTPSchemeUnknownSchemeWithoutEncryption(t *testing.T) {
|
||||
func TestH2H1RequireHTTPSchemeUnknownSchemeWithEncryption(t *testing.T) {
|
||||
opts := options{
|
||||
args: []string{"--require-http-scheme"},
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
handler: func(http.ResponseWriter, *http.Request) {
|
||||
t.Errorf("server should not forward this request")
|
||||
},
|
||||
tls: true,
|
||||
|
||||
@@ -41,7 +41,7 @@ func TestH3H1RequestBody(t *testing.T) {
|
||||
}
|
||||
|
||||
opts := options{
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
handler: func(_ http.ResponseWriter, r *http.Request) {
|
||||
buf := make([]byte, 4096)
|
||||
buflen := 0
|
||||
p := buf
|
||||
@@ -92,7 +92,7 @@ func TestH3H1RequestBody(t *testing.T) {
|
||||
// and from backend server.
|
||||
func TestH3H1GenerateVia(t *testing.T) {
|
||||
opts := options{
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
handler: func(_ http.ResponseWriter, r *http.Request) {
|
||||
if got, want := r.Header.Get("Via"), "3 nghttpx"; got != want {
|
||||
t.Errorf("Via: %v; want %v", got, want)
|
||||
}
|
||||
@@ -177,7 +177,7 @@ func TestH3H1NoVia(t *testing.T) {
|
||||
// response body size.
|
||||
func TestH3H1BadResponseCL(t *testing.T) {
|
||||
opts := options{
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
handler: func(w http.ResponseWriter, _ *http.Request) {
|
||||
// we set content-length: 1024, but only send 3 bytes.
|
||||
w.Header().Add("Content-Length", "1024")
|
||||
if _, err := w.Write([]byte("foo")); err != nil {
|
||||
@@ -256,7 +256,7 @@ func TestH3H2ReqPhaseReturn(t *testing.T) {
|
||||
"--http2-bridge",
|
||||
"--mruby-file=" + testDir + "/req-return.rb",
|
||||
},
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
handler: func(http.ResponseWriter, *http.Request) {
|
||||
t.Fatalf("request should not be forwarded")
|
||||
},
|
||||
quic: true,
|
||||
@@ -338,7 +338,7 @@ func TestH3H2RespPhaseReturn(t *testing.T) {
|
||||
func TestH3ResponseBeforeRequestEnd(t *testing.T) {
|
||||
opts := options{
|
||||
args: []string{"--mruby-file=" + testDir + "/req-return.rb"},
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
handler: func(http.ResponseWriter, *http.Request) {
|
||||
t.Fatal("request should not be forwarded")
|
||||
},
|
||||
quic: true,
|
||||
@@ -362,7 +362,7 @@ func TestH3ResponseBeforeRequestEnd(t *testing.T) {
|
||||
// backend chunked encoded response ends prematurely.
|
||||
func TestH3H1ChunkedEndsPrematurely(t *testing.T) {
|
||||
opts := options{
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
handler: func(w http.ResponseWriter, _ *http.Request) {
|
||||
hj, ok := w.(http.Hijacker)
|
||||
if !ok {
|
||||
http.Error(w, "Could not hijack the connection", http.StatusInternalServerError)
|
||||
|
||||
@@ -31,6 +31,8 @@ set(NGHTTP2_SOURCES
|
||||
)
|
||||
|
||||
set(NGHTTP2_RES "")
|
||||
set(STATIC_LIB "nghttp2_static")
|
||||
set(SHARED_LIB "nghttp2")
|
||||
|
||||
if(WIN32)
|
||||
configure_file(
|
||||
@@ -41,40 +43,61 @@ if(WIN32)
|
||||
set(NGHTTP2_RES ${CMAKE_CURRENT_BINARY_DIR}/version.rc)
|
||||
endif()
|
||||
|
||||
set(EXPORT_SET "${PROJECT_NAME}-targets")
|
||||
|
||||
# Public shared library
|
||||
if(ENABLE_SHARED_LIB)
|
||||
add_library(nghttp2 SHARED ${NGHTTP2_SOURCES} ${NGHTTP2_RES})
|
||||
set_target_properties(nghttp2 PROPERTIES
|
||||
if(BUILD_SHARED_LIBS)
|
||||
add_library(${SHARED_LIB} SHARED ${NGHTTP2_SOURCES} ${NGHTTP2_RES})
|
||||
|
||||
set_target_properties(${SHARED_LIB} PROPERTIES
|
||||
COMPILE_FLAGS "${WARNCFLAGS}"
|
||||
VERSION ${LT_VERSION} SOVERSION ${LT_SOVERSION}
|
||||
C_VISIBILITY_PRESET hidden
|
||||
)
|
||||
target_include_directories(nghttp2 INTERFACE
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/includes"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/includes"
|
||||
|
||||
target_include_directories(${SHARED_LIB} INTERFACE
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/includes>
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}/includes>
|
||||
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
|
||||
)
|
||||
|
||||
install(TARGETS nghttp2
|
||||
ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}"
|
||||
LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}"
|
||||
RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}")
|
||||
install(TARGETS ${SHARED_LIB} EXPORT ${EXPORT_SET})
|
||||
list(APPEND nghttp2_exports ${SHARED_LIB})
|
||||
endif()
|
||||
|
||||
if(HAVE_CUNIT OR ENABLE_STATIC_LIB)
|
||||
# Static library (for unittests because of symbol visibility)
|
||||
add_library(nghttp2_static STATIC ${NGHTTP2_SOURCES})
|
||||
set_target_properties(nghttp2_static PROPERTIES
|
||||
COMPILE_FLAGS "${WARNCFLAGS}"
|
||||
VERSION ${LT_VERSION} SOVERSION ${LT_SOVERSION}
|
||||
ARCHIVE_OUTPUT_NAME nghttp2${STATIC_LIB_SUFFIX}
|
||||
)
|
||||
target_compile_definitions(nghttp2_static PUBLIC "-DNGHTTP2_STATICLIB")
|
||||
if(ENABLE_STATIC_LIB)
|
||||
install(TARGETS nghttp2_static
|
||||
DESTINATION "${CMAKE_INSTALL_LIBDIR}")
|
||||
endif()
|
||||
# Static library (for unittests because of symbol visibility)
|
||||
add_library(${STATIC_LIB} STATIC ${NGHTTP2_SOURCES})
|
||||
|
||||
set_target_properties(${STATIC_LIB} PROPERTIES
|
||||
COMPILE_FLAGS "${WARNCFLAGS}"
|
||||
VERSION ${LT_VERSION} SOVERSION ${LT_SOVERSION}
|
||||
ARCHIVE_OUTPUT_NAME nghttp2${STATIC_LIB_SUFFIX}
|
||||
)
|
||||
|
||||
target_include_directories(${STATIC_LIB} INTERFACE
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/includes>
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}/includes>
|
||||
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
|
||||
)
|
||||
|
||||
target_compile_definitions(${STATIC_LIB} PUBLIC "-DNGHTTP2_STATICLIB")
|
||||
|
||||
if(BUILD_STATIC_LIBS)
|
||||
install(TARGETS ${STATIC_LIB} EXPORT ${EXPORT_SET})
|
||||
list(APPEND nghttp2_exports ${STATIC_LIB})
|
||||
endif()
|
||||
|
||||
if(BUILD_SHARED_LIBS)
|
||||
set(LIB_SELECTED ${SHARED_LIB})
|
||||
else()
|
||||
set(LIB_SELECTED ${STATIC_LIB})
|
||||
endif()
|
||||
|
||||
add_library(${PROJECT_NAME}::nghttp2 ALIAS ${LIB_SELECTED})
|
||||
|
||||
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/libnghttp2.pc"
|
||||
DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig")
|
||||
|
||||
install(EXPORT ${EXPORT_SET}
|
||||
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}
|
||||
NAMESPACE ${PROJECT_NAME}::)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -430,7 +430,7 @@ int nghttp2_bufs_orb_hold(nghttp2_bufs *bufs, uint8_t b) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
ssize_t nghttp2_bufs_remove(nghttp2_bufs *bufs, uint8_t **out) {
|
||||
nghttp2_ssize nghttp2_bufs_remove(nghttp2_bufs *bufs, uint8_t **out) {
|
||||
size_t len;
|
||||
nghttp2_buf_chain *chain;
|
||||
nghttp2_buf *buf;
|
||||
@@ -462,7 +462,7 @@ ssize_t nghttp2_bufs_remove(nghttp2_bufs *bufs, uint8_t **out) {
|
||||
|
||||
*out = res;
|
||||
|
||||
return (ssize_t)len;
|
||||
return (nghttp2_ssize)len;
|
||||
}
|
||||
|
||||
size_t nghttp2_bufs_remove_copy(nghttp2_bufs *bufs, uint8_t *out) {
|
||||
|
||||
@@ -349,7 +349,7 @@ int nghttp2_bufs_orb_hold(nghttp2_bufs *bufs, uint8_t b);
|
||||
* NGHTTP2_ERR_NOMEM
|
||||
* Out of memory
|
||||
*/
|
||||
ssize_t nghttp2_bufs_remove(nghttp2_bufs *bufs, uint8_t **out);
|
||||
nghttp2_ssize nghttp2_bufs_remove(nghttp2_bufs *bufs, uint8_t **out);
|
||||
|
||||
/*
|
||||
* Copies all data stored in |bufs| to |out|. This function assumes
|
||||
|
||||
@@ -45,11 +45,21 @@ void nghttp2_session_callbacks_set_send_callback(
|
||||
cbs->send_callback = send_callback;
|
||||
}
|
||||
|
||||
void nghttp2_session_callbacks_set_send_callback2(
|
||||
nghttp2_session_callbacks *cbs, nghttp2_send_callback2 send_callback) {
|
||||
cbs->send_callback2 = send_callback;
|
||||
}
|
||||
|
||||
void nghttp2_session_callbacks_set_recv_callback(
|
||||
nghttp2_session_callbacks *cbs, nghttp2_recv_callback recv_callback) {
|
||||
cbs->recv_callback = recv_callback;
|
||||
}
|
||||
|
||||
void nghttp2_session_callbacks_set_recv_callback2(
|
||||
nghttp2_session_callbacks *cbs, nghttp2_recv_callback2 recv_callback) {
|
||||
cbs->recv_callback2 = recv_callback;
|
||||
}
|
||||
|
||||
void nghttp2_session_callbacks_set_on_frame_recv_callback(
|
||||
nghttp2_session_callbacks *cbs,
|
||||
nghttp2_on_frame_recv_callback on_frame_recv_callback) {
|
||||
@@ -128,12 +138,24 @@ void nghttp2_session_callbacks_set_select_padding_callback(
|
||||
cbs->select_padding_callback = select_padding_callback;
|
||||
}
|
||||
|
||||
void nghttp2_session_callbacks_set_select_padding_callback2(
|
||||
nghttp2_session_callbacks *cbs,
|
||||
nghttp2_select_padding_callback2 select_padding_callback) {
|
||||
cbs->select_padding_callback2 = select_padding_callback;
|
||||
}
|
||||
|
||||
void nghttp2_session_callbacks_set_data_source_read_length_callback(
|
||||
nghttp2_session_callbacks *cbs,
|
||||
nghttp2_data_source_read_length_callback data_source_read_length_callback) {
|
||||
cbs->read_length_callback = data_source_read_length_callback;
|
||||
}
|
||||
|
||||
void nghttp2_session_callbacks_set_data_source_read_length_callback2(
|
||||
nghttp2_session_callbacks *cbs, nghttp2_data_source_read_length_callback2
|
||||
data_source_read_length_callback) {
|
||||
cbs->read_length_callback2 = data_source_read_length_callback;
|
||||
}
|
||||
|
||||
void nghttp2_session_callbacks_set_on_begin_frame_callback(
|
||||
nghttp2_session_callbacks *cbs,
|
||||
nghttp2_on_begin_frame_callback on_begin_frame_callback) {
|
||||
@@ -152,6 +174,12 @@ void nghttp2_session_callbacks_set_pack_extension_callback(
|
||||
cbs->pack_extension_callback = pack_extension_callback;
|
||||
}
|
||||
|
||||
void nghttp2_session_callbacks_set_pack_extension_callback2(
|
||||
nghttp2_session_callbacks *cbs,
|
||||
nghttp2_pack_extension_callback2 pack_extension_callback) {
|
||||
cbs->pack_extension_callback2 = pack_extension_callback;
|
||||
}
|
||||
|
||||
void nghttp2_session_callbacks_set_unpack_extension_callback(
|
||||
nghttp2_session_callbacks *cbs,
|
||||
nghttp2_unpack_extension_callback unpack_extension_callback) {
|
||||
|
||||
@@ -36,19 +36,33 @@
|
||||
*/
|
||||
struct nghttp2_session_callbacks {
|
||||
/**
|
||||
* Callback function invoked when the session wants to send data to
|
||||
* the remote peer. This callback is not necessary if the
|
||||
* application uses solely `nghttp2_session_mem_send()` to serialize
|
||||
* data to transmit.
|
||||
* Deprecated. Use send_callback2 instead. Callback function
|
||||
* invoked when the session wants to send data to the remote peer.
|
||||
* This callback is not necessary if the application uses solely
|
||||
* `nghttp2_session_mem_send()` to serialize data to transmit.
|
||||
*/
|
||||
nghttp2_send_callback send_callback;
|
||||
/**
|
||||
* Callback function invoked when the session wants to receive data
|
||||
* from the remote peer. This callback is not necessary if the
|
||||
* application uses solely `nghttp2_session_mem_recv()` to process
|
||||
* received data.
|
||||
* Callback function invoked when the session wants to send data to
|
||||
* the remote peer. This callback is not necessary if the
|
||||
* application uses solely `nghttp2_session_mem_send2()` to
|
||||
* serialize data to transmit.
|
||||
*/
|
||||
nghttp2_send_callback2 send_callback2;
|
||||
/**
|
||||
* Deprecated. Use recv_callback2 instead. Callback function
|
||||
* invoked when the session wants to receive data from the remote
|
||||
* peer. This callback is not necessary if the application uses
|
||||
* solely `nghttp2_session_mem_recv()` to process received data.
|
||||
*/
|
||||
nghttp2_recv_callback recv_callback;
|
||||
/**
|
||||
* Callback function invoked when the session wants to receive data
|
||||
* from the remote peer. This callback is not necessary if the
|
||||
* application uses solely `nghttp2_session_mem_recv2()` to process
|
||||
* received data.
|
||||
*/
|
||||
nghttp2_recv_callback2 recv_callback2;
|
||||
/**
|
||||
* Callback function invoked by `nghttp2_session_recv()` when a
|
||||
* frame is received.
|
||||
@@ -100,22 +114,39 @@ struct nghttp2_session_callbacks {
|
||||
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
|
||||
* many padding bytes are required for the transmission of the given
|
||||
* Deprecated. Use select_padding_callback2 instead. Callback
|
||||
* function invoked when the library asks application how many
|
||||
* padding bytes are required for the transmission of the given
|
||||
* frame.
|
||||
*/
|
||||
nghttp2_select_padding_callback select_padding_callback;
|
||||
/**
|
||||
* The callback function used to determine the length allowed in
|
||||
* Callback function invoked when the library asks application how
|
||||
* many padding bytes are required for the transmission of the given
|
||||
* frame.
|
||||
*/
|
||||
nghttp2_select_padding_callback2 select_padding_callback2;
|
||||
/**
|
||||
* Deprecated. Use read_length_callback2 instead. The callback
|
||||
* function used to determine the length allowed in
|
||||
* `nghttp2_data_source_read_callback()`
|
||||
*/
|
||||
nghttp2_data_source_read_length_callback read_length_callback;
|
||||
/**
|
||||
* The callback function used to determine the length allowed in
|
||||
* `nghttp2_data_source_read_callback2()`
|
||||
*/
|
||||
nghttp2_data_source_read_length_callback2 read_length_callback2;
|
||||
/**
|
||||
* Sets callback function invoked when a frame header is received.
|
||||
*/
|
||||
nghttp2_on_begin_frame_callback on_begin_frame_callback;
|
||||
nghttp2_send_data_callback send_data_callback;
|
||||
/**
|
||||
* Deprecated. Use pack_extension_callback2 instead.
|
||||
*/
|
||||
nghttp2_pack_extension_callback pack_extension_callback;
|
||||
nghttp2_pack_extension_callback2 pack_extension_callback2;
|
||||
nghttp2_unpack_extension_callback unpack_extension_callback;
|
||||
nghttp2_on_extension_chunk_recv_callback on_extension_chunk_recv_callback;
|
||||
nghttp2_error_callback error_callback;
|
||||
|
||||
114
lib/nghttp2_hd.c
114
lib/nghttp2_hd.c
@@ -850,9 +850,10 @@ static size_t encode_length(uint8_t *buf, size_t n, size_t prefix) {
|
||||
* in the next call will be stored in |*shift_ptr|) and returns number
|
||||
* of bytes processed, or returns -1, indicating decoding error.
|
||||
*/
|
||||
static ssize_t decode_length(uint32_t *res, size_t *shift_ptr, int *fin,
|
||||
uint32_t initial, size_t shift, const uint8_t *in,
|
||||
const uint8_t *last, size_t prefix) {
|
||||
static nghttp2_ssize decode_length(uint32_t *res, size_t *shift_ptr, int *fin,
|
||||
uint32_t initial, size_t shift,
|
||||
const uint8_t *in, const uint8_t *last,
|
||||
size_t prefix) {
|
||||
uint32_t k = (uint8_t)((1 << prefix) - 1);
|
||||
uint32_t n = initial;
|
||||
const uint8_t *start = in;
|
||||
@@ -871,7 +872,7 @@ static ssize_t decode_length(uint32_t *res, size_t *shift_ptr, int *fin,
|
||||
|
||||
if (++in == last) {
|
||||
*res = n;
|
||||
return (ssize_t)(in - start);
|
||||
return (nghttp2_ssize)(in - start);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -906,12 +907,12 @@ static ssize_t decode_length(uint32_t *res, size_t *shift_ptr, int *fin,
|
||||
|
||||
if (in == last) {
|
||||
*res = n;
|
||||
return (ssize_t)(in - start);
|
||||
return (nghttp2_ssize)(in - start);
|
||||
}
|
||||
|
||||
*res = n;
|
||||
*fin = 1;
|
||||
return (ssize_t)(in + 1 - start);
|
||||
return (nghttp2_ssize)(in + 1 - start);
|
||||
}
|
||||
|
||||
static int emit_table_size(nghttp2_bufs *bufs, size_t table_size) {
|
||||
@@ -1164,7 +1165,7 @@ static int add_hd_table_incremental(nghttp2_hd_context *context,
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
ssize_t index;
|
||||
nghttp2_ssize index;
|
||||
/* Nonzero if both name and value are matched. */
|
||||
int name_value_match;
|
||||
} search_result;
|
||||
@@ -1213,8 +1214,8 @@ static search_result search_hd_table(nghttp2_hd_context *context,
|
||||
return res;
|
||||
}
|
||||
|
||||
res.index =
|
||||
(ssize_t)(context->next_seq - 1 - ent->seq + NGHTTP2_STATIC_TABLE_LENGTH);
|
||||
res.index = (nghttp2_ssize)(context->next_seq - 1 - ent->seq +
|
||||
NGHTTP2_STATIC_TABLE_LENGTH);
|
||||
res.name_value_match = exact_match;
|
||||
|
||||
return res;
|
||||
@@ -1343,7 +1344,7 @@ static int deflate_nv(nghttp2_hd_deflater *deflater, nghttp2_bufs *bufs,
|
||||
const nghttp2_nv *nv) {
|
||||
int rv;
|
||||
search_result res;
|
||||
ssize_t idx;
|
||||
nghttp2_ssize idx;
|
||||
int indexing_mode;
|
||||
int32_t token;
|
||||
nghttp2_mem *mem;
|
||||
@@ -1379,7 +1380,7 @@ static int deflate_nv(nghttp2_hd_deflater *deflater, nghttp2_bufs *bufs,
|
||||
|
||||
if (res.name_value_match) {
|
||||
|
||||
DEBUGF("deflatehd: name/value match index=%zd\n", idx);
|
||||
DEBUGF("deflatehd: name/value match index=%td\n", idx);
|
||||
|
||||
rv = emit_indexed_block(bufs, (size_t)idx);
|
||||
if (rv != 0) {
|
||||
@@ -1390,7 +1391,7 @@ static int deflate_nv(nghttp2_hd_deflater *deflater, nghttp2_bufs *bufs,
|
||||
}
|
||||
|
||||
if (res.index != -1) {
|
||||
DEBUGF("deflatehd: name match index=%zd\n", res.index);
|
||||
DEBUGF("deflatehd: name match index=%td\n", res.index);
|
||||
}
|
||||
|
||||
if (indexing_mode == NGHTTP2_HD_WITH_INDEXING) {
|
||||
@@ -1491,6 +1492,12 @@ fail:
|
||||
ssize_t nghttp2_hd_deflate_hd(nghttp2_hd_deflater *deflater, uint8_t *buf,
|
||||
size_t buflen, const nghttp2_nv *nv,
|
||||
size_t nvlen) {
|
||||
return (ssize_t)nghttp2_hd_deflate_hd2(deflater, buf, buflen, nv, nvlen);
|
||||
}
|
||||
|
||||
nghttp2_ssize nghttp2_hd_deflate_hd2(nghttp2_hd_deflater *deflater,
|
||||
uint8_t *buf, size_t buflen,
|
||||
const nghttp2_nv *nv, size_t nvlen) {
|
||||
nghttp2_bufs bufs;
|
||||
int rv;
|
||||
nghttp2_mem *mem;
|
||||
@@ -1517,12 +1524,18 @@ ssize_t nghttp2_hd_deflate_hd(nghttp2_hd_deflater *deflater, uint8_t *buf,
|
||||
return rv;
|
||||
}
|
||||
|
||||
return (ssize_t)buflen;
|
||||
return (nghttp2_ssize)buflen;
|
||||
}
|
||||
|
||||
ssize_t nghttp2_hd_deflate_hd_vec(nghttp2_hd_deflater *deflater,
|
||||
const nghttp2_vec *vec, size_t veclen,
|
||||
const nghttp2_nv *nv, size_t nvlen) {
|
||||
return (ssize_t)nghttp2_hd_deflate_hd_vec2(deflater, vec, veclen, nv, nvlen);
|
||||
}
|
||||
|
||||
nghttp2_ssize nghttp2_hd_deflate_hd_vec2(nghttp2_hd_deflater *deflater,
|
||||
const nghttp2_vec *vec, size_t veclen,
|
||||
const nghttp2_nv *nv, size_t nvlen) {
|
||||
nghttp2_bufs bufs;
|
||||
int rv;
|
||||
nghttp2_mem *mem;
|
||||
@@ -1550,7 +1563,7 @@ ssize_t nghttp2_hd_deflate_hd_vec(nghttp2_hd_deflater *deflater,
|
||||
return rv;
|
||||
}
|
||||
|
||||
return (ssize_t)buflen;
|
||||
return (nghttp2_ssize)buflen;
|
||||
}
|
||||
|
||||
size_t nghttp2_hd_deflate_bound(nghttp2_hd_deflater *deflater,
|
||||
@@ -1643,10 +1656,11 @@ static void hd_inflate_set_huffman_encoded(nghttp2_hd_inflater *inflater,
|
||||
* NGHTTP2_ERR_HEADER_COMP
|
||||
* Integer decoding failed
|
||||
*/
|
||||
static ssize_t hd_inflate_read_len(nghttp2_hd_inflater *inflater, int *rfin,
|
||||
const uint8_t *in, const uint8_t *last,
|
||||
size_t prefix, size_t maxlen) {
|
||||
ssize_t rv;
|
||||
static nghttp2_ssize hd_inflate_read_len(nghttp2_hd_inflater *inflater,
|
||||
int *rfin, const uint8_t *in,
|
||||
const uint8_t *last, size_t prefix,
|
||||
size_t maxlen) {
|
||||
nghttp2_ssize rv;
|
||||
uint32_t out;
|
||||
|
||||
*rfin = 0;
|
||||
@@ -1684,10 +1698,10 @@ static ssize_t hd_inflate_read_len(nghttp2_hd_inflater *inflater, int *rfin,
|
||||
* NGHTTP2_ERR_HEADER_COMP
|
||||
* Huffman decoding failed
|
||||
*/
|
||||
static ssize_t hd_inflate_read_huff(nghttp2_hd_inflater *inflater,
|
||||
nghttp2_buf *buf, const uint8_t *in,
|
||||
const uint8_t *last) {
|
||||
ssize_t readlen;
|
||||
static nghttp2_ssize hd_inflate_read_huff(nghttp2_hd_inflater *inflater,
|
||||
nghttp2_buf *buf, const uint8_t *in,
|
||||
const uint8_t *last) {
|
||||
nghttp2_ssize readlen;
|
||||
int fin = 0;
|
||||
if ((size_t)(last - in) >= inflater->left) {
|
||||
last = in + inflater->left;
|
||||
@@ -1721,14 +1735,15 @@ static ssize_t hd_inflate_read_huff(nghttp2_hd_inflater *inflater,
|
||||
* NGHTTP2_ERR_HEADER_COMP
|
||||
* Header decompression failed
|
||||
*/
|
||||
static ssize_t hd_inflate_read(nghttp2_hd_inflater *inflater, nghttp2_buf *buf,
|
||||
const uint8_t *in, const uint8_t *last) {
|
||||
static nghttp2_ssize hd_inflate_read(nghttp2_hd_inflater *inflater,
|
||||
nghttp2_buf *buf, const uint8_t *in,
|
||||
const uint8_t *last) {
|
||||
size_t len = nghttp2_min((size_t)(last - in), inflater->left);
|
||||
|
||||
buf->last = nghttp2_cpymem(buf->last, in, len);
|
||||
|
||||
inflater->left -= len;
|
||||
return (ssize_t)len;
|
||||
return (nghttp2_ssize)len;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1843,7 +1858,15 @@ ssize_t nghttp2_hd_inflate_hd(nghttp2_hd_inflater *inflater, nghttp2_nv *nv_out,
|
||||
ssize_t nghttp2_hd_inflate_hd2(nghttp2_hd_inflater *inflater,
|
||||
nghttp2_nv *nv_out, int *inflate_flags,
|
||||
const uint8_t *in, size_t inlen, int in_final) {
|
||||
ssize_t rv;
|
||||
return (nghttp2_ssize)nghttp2_hd_inflate_hd3(inflater, nv_out, inflate_flags,
|
||||
in, inlen, in_final);
|
||||
}
|
||||
|
||||
nghttp2_ssize nghttp2_hd_inflate_hd3(nghttp2_hd_inflater *inflater,
|
||||
nghttp2_nv *nv_out, int *inflate_flags,
|
||||
const uint8_t *in, size_t inlen,
|
||||
int in_final) {
|
||||
nghttp2_ssize rv;
|
||||
nghttp2_hd_nv hd_nv;
|
||||
|
||||
rv = nghttp2_hd_inflate_hd_nv(inflater, &hd_nv, inflate_flags, in, inlen,
|
||||
@@ -1866,11 +1889,11 @@ ssize_t nghttp2_hd_inflate_hd2(nghttp2_hd_inflater *inflater,
|
||||
return rv;
|
||||
}
|
||||
|
||||
ssize_t nghttp2_hd_inflate_hd_nv(nghttp2_hd_inflater *inflater,
|
||||
nghttp2_hd_nv *nv_out, int *inflate_flags,
|
||||
const uint8_t *in, size_t inlen,
|
||||
int in_final) {
|
||||
ssize_t rv = 0;
|
||||
nghttp2_ssize nghttp2_hd_inflate_hd_nv(nghttp2_hd_inflater *inflater,
|
||||
nghttp2_hd_nv *nv_out,
|
||||
int *inflate_flags, const uint8_t *in,
|
||||
size_t inlen, int in_final) {
|
||||
nghttp2_ssize rv = 0;
|
||||
const uint8_t *first = in;
|
||||
const uint8_t *last = in + inlen;
|
||||
int rfin = 0;
|
||||
@@ -1992,7 +2015,7 @@ ssize_t nghttp2_hd_inflate_hd_nv(nghttp2_hd_inflater *inflater,
|
||||
|
||||
inflater->state = NGHTTP2_HD_STATE_OPCODE;
|
||||
*inflate_flags |= NGHTTP2_HD_INFLATE_EMIT;
|
||||
return (ssize_t)(in - first);
|
||||
return (nghttp2_ssize)(in - first);
|
||||
} else {
|
||||
inflater->index = inflater->left;
|
||||
--inflater->index;
|
||||
@@ -2050,7 +2073,7 @@ ssize_t nghttp2_hd_inflate_hd_nv(nghttp2_hd_inflater *inflater,
|
||||
|
||||
in += rv;
|
||||
|
||||
DEBUGF("inflatehd: %zd bytes read\n", rv);
|
||||
DEBUGF("inflatehd: %td bytes read\n", rv);
|
||||
|
||||
if (inflater->left) {
|
||||
DEBUGF("inflatehd: still %zu bytes to go\n", inflater->left);
|
||||
@@ -2072,7 +2095,7 @@ ssize_t nghttp2_hd_inflate_hd_nv(nghttp2_hd_inflater *inflater,
|
||||
|
||||
in += rv;
|
||||
|
||||
DEBUGF("inflatehd: %zd bytes read\n", rv);
|
||||
DEBUGF("inflatehd: %td bytes read\n", rv);
|
||||
if (inflater->left) {
|
||||
DEBUGF("inflatehd: still %zu bytes to go\n", inflater->left);
|
||||
|
||||
@@ -2138,7 +2161,7 @@ ssize_t nghttp2_hd_inflate_hd_nv(nghttp2_hd_inflater *inflater,
|
||||
|
||||
in += rv;
|
||||
|
||||
DEBUGF("inflatehd: %zd bytes read\n", rv);
|
||||
DEBUGF("inflatehd: %td bytes read\n", rv);
|
||||
|
||||
if (inflater->left) {
|
||||
DEBUGF("inflatehd: still %zu bytes to go\n", inflater->left);
|
||||
@@ -2162,18 +2185,18 @@ ssize_t nghttp2_hd_inflate_hd_nv(nghttp2_hd_inflater *inflater,
|
||||
inflater->state = NGHTTP2_HD_STATE_OPCODE;
|
||||
*inflate_flags |= NGHTTP2_HD_INFLATE_EMIT;
|
||||
|
||||
return (ssize_t)(in - first);
|
||||
return (nghttp2_ssize)(in - first);
|
||||
case NGHTTP2_HD_STATE_READ_VALUE:
|
||||
rv = hd_inflate_read(inflater, &inflater->valuebuf, in, last);
|
||||
if (rv < 0) {
|
||||
DEBUGF("inflatehd: value read failure %zd: %s\n", rv,
|
||||
DEBUGF("inflatehd: value read failure %td: %s\n", rv,
|
||||
nghttp2_strerror((int)rv));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
in += rv;
|
||||
|
||||
DEBUGF("inflatehd: %zd bytes read\n", rv);
|
||||
DEBUGF("inflatehd: %td bytes read\n", rv);
|
||||
|
||||
if (inflater->left) {
|
||||
DEBUGF("inflatehd: still %zu bytes to go\n", inflater->left);
|
||||
@@ -2196,7 +2219,7 @@ ssize_t nghttp2_hd_inflate_hd_nv(nghttp2_hd_inflater *inflater,
|
||||
inflater->state = NGHTTP2_HD_STATE_OPCODE;
|
||||
*inflate_flags |= NGHTTP2_HD_INFLATE_EMIT;
|
||||
|
||||
return (ssize_t)(in - first);
|
||||
return (nghttp2_ssize)(in - first);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2216,7 +2239,7 @@ ssize_t nghttp2_hd_inflate_hd_nv(nghttp2_hd_inflater *inflater,
|
||||
}
|
||||
*inflate_flags |= NGHTTP2_HD_INFLATE_FINAL;
|
||||
}
|
||||
return (ssize_t)(in - first);
|
||||
return (nghttp2_ssize)(in - first);
|
||||
|
||||
almost_ok:
|
||||
if (in_final) {
|
||||
@@ -2226,10 +2249,10 @@ almost_ok:
|
||||
|
||||
goto fail;
|
||||
}
|
||||
return (ssize_t)(in - first);
|
||||
return (nghttp2_ssize)(in - first);
|
||||
|
||||
fail:
|
||||
DEBUGF("inflatehd: error return %zd\n", rv);
|
||||
DEBUGF("inflatehd: error return %td\n", rv);
|
||||
|
||||
inflater->ctx.bad = 1;
|
||||
return rv;
|
||||
@@ -2297,9 +2320,10 @@ int nghttp2_hd_emit_table_size(nghttp2_bufs *bufs, size_t table_size) {
|
||||
return emit_table_size(bufs, table_size);
|
||||
}
|
||||
|
||||
ssize_t nghttp2_hd_decode_length(uint32_t *res, size_t *shift_ptr, int *fin,
|
||||
uint32_t initial, size_t shift, uint8_t *in,
|
||||
uint8_t *last, size_t prefix) {
|
||||
nghttp2_ssize nghttp2_hd_decode_length(uint32_t *res, size_t *shift_ptr,
|
||||
int *fin, uint32_t initial, size_t shift,
|
||||
uint8_t *in, uint8_t *last,
|
||||
size_t prefix) {
|
||||
return decode_length(res, shift_ptr, fin, initial, shift, in, last, prefix);
|
||||
}
|
||||
|
||||
|
||||
@@ -357,9 +357,10 @@ void nghttp2_hd_inflate_free(nghttp2_hd_inflater *inflater);
|
||||
* that return values and semantics are the same as
|
||||
* nghttp2_hd_inflate_hd().
|
||||
*/
|
||||
ssize_t nghttp2_hd_inflate_hd_nv(nghttp2_hd_inflater *inflater,
|
||||
nghttp2_hd_nv *nv_out, int *inflate_flags,
|
||||
const uint8_t *in, size_t inlen, int in_final);
|
||||
nghttp2_ssize nghttp2_hd_inflate_hd_nv(nghttp2_hd_inflater *inflater,
|
||||
nghttp2_hd_nv *nv_out,
|
||||
int *inflate_flags, const uint8_t *in,
|
||||
size_t inlen, int in_final);
|
||||
|
||||
/* For unittesting purpose */
|
||||
int nghttp2_hd_emit_indname_block(nghttp2_bufs *bufs, size_t index,
|
||||
@@ -376,9 +377,10 @@ 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);
|
||||
|
||||
/* For unittesting purpose */
|
||||
ssize_t nghttp2_hd_decode_length(uint32_t *res, size_t *shift_ptr, int *fin,
|
||||
uint32_t initial, size_t shift, uint8_t *in,
|
||||
uint8_t *last, size_t prefix);
|
||||
nghttp2_ssize nghttp2_hd_decode_length(uint32_t *res, size_t *shift_ptr,
|
||||
int *fin, uint32_t initial, size_t shift,
|
||||
uint8_t *in, uint8_t *last,
|
||||
size_t prefix);
|
||||
|
||||
/* Huffman encoding/decoding functions */
|
||||
|
||||
@@ -427,9 +429,9 @@ void nghttp2_hd_huff_decode_context_init(nghttp2_hd_huff_decode_context *ctx);
|
||||
* NGHTTP2_ERR_HEADER_COMP
|
||||
* Decoding process has failed.
|
||||
*/
|
||||
ssize_t nghttp2_hd_huff_decode(nghttp2_hd_huff_decode_context *ctx,
|
||||
nghttp2_buf *buf, const uint8_t *src,
|
||||
size_t srclen, int fin);
|
||||
nghttp2_ssize nghttp2_hd_huff_decode(nghttp2_hd_huff_decode_context *ctx,
|
||||
nghttp2_buf *buf, const uint8_t *src,
|
||||
size_t srclen, int fin);
|
||||
|
||||
/*
|
||||
* nghttp2_hd_huff_decode_failure_state returns nonzero if |ctx|
|
||||
|
||||
@@ -107,9 +107,9 @@ void nghttp2_hd_huff_decode_context_init(nghttp2_hd_huff_decode_context *ctx) {
|
||||
ctx->fstate = NGHTTP2_HUFF_ACCEPTED;
|
||||
}
|
||||
|
||||
ssize_t nghttp2_hd_huff_decode(nghttp2_hd_huff_decode_context *ctx,
|
||||
nghttp2_buf *buf, const uint8_t *src,
|
||||
size_t srclen, int final) {
|
||||
nghttp2_ssize nghttp2_hd_huff_decode(nghttp2_hd_huff_decode_context *ctx,
|
||||
nghttp2_buf *buf, const uint8_t *src,
|
||||
size_t srclen, int final) {
|
||||
const uint8_t *end = src + srclen;
|
||||
nghttp2_huff_decode node = {ctx->fstate, 0};
|
||||
const nghttp2_huff_decode *t = &node;
|
||||
@@ -136,7 +136,7 @@ ssize_t nghttp2_hd_huff_decode(nghttp2_hd_huff_decode_context *ctx,
|
||||
return NGHTTP2_ERR_HEADER_COMP;
|
||||
}
|
||||
|
||||
return (ssize_t)srclen;
|
||||
return (nghttp2_ssize)srclen;
|
||||
}
|
||||
|
||||
int nghttp2_hd_huff_decode_failure_state(nghttp2_hd_huff_decode_context *ctx) {
|
||||
|
||||
@@ -27,6 +27,32 @@
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
nghttp2_data_provider_wrap *
|
||||
nghttp2_data_provider_wrap_v1(nghttp2_data_provider_wrap *dpw,
|
||||
const nghttp2_data_provider *data_prd) {
|
||||
if (!data_prd) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
dpw->version = NGHTTP2_DATA_PROVIDER_V1;
|
||||
dpw->data_prd.v1 = *data_prd;
|
||||
|
||||
return dpw;
|
||||
}
|
||||
|
||||
nghttp2_data_provider_wrap *
|
||||
nghttp2_data_provider_wrap_v2(nghttp2_data_provider_wrap *dpw,
|
||||
const nghttp2_data_provider2 *data_prd) {
|
||||
if (!data_prd) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
dpw->version = NGHTTP2_DATA_PROVIDER_V2;
|
||||
dpw->data_prd.v2 = *data_prd;
|
||||
|
||||
return dpw;
|
||||
}
|
||||
|
||||
void nghttp2_outbound_item_init(nghttp2_outbound_item *item) {
|
||||
item->cycle = 0;
|
||||
item->qnext = NULL;
|
||||
|
||||
@@ -33,9 +33,32 @@
|
||||
#include "nghttp2_frame.h"
|
||||
#include "nghttp2_mem.h"
|
||||
|
||||
#define NGHTTP2_DATA_PROVIDER_V1 1
|
||||
#define NGHTTP2_DATA_PROVIDER_V2 2
|
||||
|
||||
typedef struct nghttp2_data_provider_wrap {
|
||||
int version;
|
||||
union {
|
||||
struct {
|
||||
nghttp2_data_source source;
|
||||
void *read_callback;
|
||||
};
|
||||
nghttp2_data_provider v1;
|
||||
nghttp2_data_provider2 v2;
|
||||
} data_prd;
|
||||
} nghttp2_data_provider_wrap;
|
||||
|
||||
nghttp2_data_provider_wrap *
|
||||
nghttp2_data_provider_wrap_v1(nghttp2_data_provider_wrap *dpw,
|
||||
const nghttp2_data_provider *data_prd);
|
||||
|
||||
nghttp2_data_provider_wrap *
|
||||
nghttp2_data_provider_wrap_v2(nghttp2_data_provider_wrap *dpw,
|
||||
const nghttp2_data_provider2 *data_prd);
|
||||
|
||||
/* struct used for HEADERS and PUSH_PROMISE frame */
|
||||
typedef struct {
|
||||
nghttp2_data_provider data_prd;
|
||||
nghttp2_data_provider_wrap dpw;
|
||||
void *stream_user_data;
|
||||
/* error code when request HEADERS is canceled by RST_STREAM while
|
||||
it is in queue. */
|
||||
@@ -50,7 +73,7 @@ typedef struct {
|
||||
/**
|
||||
* The data to be sent for this DATA frame.
|
||||
*/
|
||||
nghttp2_data_provider data_prd;
|
||||
nghttp2_data_provider_wrap dpw;
|
||||
/**
|
||||
* The flags of DATA frame. We use separate flags here and
|
||||
* nghttp2_data frame. The latter contains flags actually sent to
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
#include "nghttp2_extpri.h"
|
||||
#include "nghttp2_time.h"
|
||||
#include "nghttp2_debug.h"
|
||||
#include "nghttp2_submit.h"
|
||||
|
||||
/*
|
||||
* Returns non-zero if the number of outgoing opened streams is larger
|
||||
@@ -2103,10 +2104,9 @@ static int session_predicate_priority_update_send(nghttp2_session *session,
|
||||
|
||||
/* Take into account settings max frame size and both connection-level
|
||||
flow control here */
|
||||
static ssize_t
|
||||
nghttp2_session_enforce_flow_control_limits(nghttp2_session *session,
|
||||
nghttp2_stream *stream,
|
||||
ssize_t requested_window_size) {
|
||||
static nghttp2_ssize nghttp2_session_enforce_flow_control_limits(
|
||||
nghttp2_session *session, nghttp2_stream *stream,
|
||||
nghttp2_ssize requested_window_size) {
|
||||
DEBUGF("send: remote windowsize connection=%d, remote maxframsize=%u, "
|
||||
"stream(id %d)=%d\n",
|
||||
session->remote_window_size, session->remote_settings.max_frame_size,
|
||||
@@ -2126,12 +2126,12 @@ nghttp2_session_enforce_flow_control_limits(nghttp2_session *session,
|
||||
*/
|
||||
static size_t nghttp2_session_next_data_read(nghttp2_session *session,
|
||||
nghttp2_stream *stream) {
|
||||
ssize_t window_size;
|
||||
nghttp2_ssize window_size;
|
||||
|
||||
window_size = nghttp2_session_enforce_flow_control_limits(
|
||||
session, stream, NGHTTP2_DATA_PAYLOADLEN);
|
||||
|
||||
DEBUGF("send: available window=%zd\n", window_size);
|
||||
DEBUGF("send: available window=%td\n", window_size);
|
||||
|
||||
return window_size > 0 ? (size_t)window_size : 0;
|
||||
}
|
||||
@@ -2186,29 +2186,33 @@ static int nghttp2_session_predicate_data_send(nghttp2_session *session,
|
||||
return NGHTTP2_ERR_INVALID_STREAM_STATE;
|
||||
}
|
||||
|
||||
static ssize_t session_call_select_padding(nghttp2_session *session,
|
||||
const nghttp2_frame *frame,
|
||||
size_t max_payloadlen) {
|
||||
ssize_t rv;
|
||||
static nghttp2_ssize session_call_select_padding(nghttp2_session *session,
|
||||
const nghttp2_frame *frame,
|
||||
size_t max_payloadlen) {
|
||||
nghttp2_ssize rv;
|
||||
size_t max_paddedlen;
|
||||
|
||||
if (frame->hd.length >= max_payloadlen) {
|
||||
return (ssize_t)frame->hd.length;
|
||||
if (frame->hd.length >= max_payloadlen ||
|
||||
(!session->callbacks.select_padding_callback2 &&
|
||||
!session->callbacks.select_padding_callback)) {
|
||||
return (nghttp2_ssize)frame->hd.length;
|
||||
}
|
||||
|
||||
if (session->callbacks.select_padding_callback) {
|
||||
size_t max_paddedlen;
|
||||
max_paddedlen =
|
||||
nghttp2_min(frame->hd.length + NGHTTP2_MAX_PADLEN, max_payloadlen);
|
||||
|
||||
max_paddedlen =
|
||||
nghttp2_min(frame->hd.length + NGHTTP2_MAX_PADLEN, max_payloadlen);
|
||||
|
||||
rv = session->callbacks.select_padding_callback(
|
||||
if (session->callbacks.select_padding_callback2) {
|
||||
rv = session->callbacks.select_padding_callback2(
|
||||
session, frame, max_paddedlen, session->user_data);
|
||||
} else {
|
||||
rv = (nghttp2_ssize)session->callbacks.select_padding_callback(
|
||||
session, frame, max_paddedlen, session->user_data);
|
||||
if (rv < (ssize_t)frame->hd.length || rv > (ssize_t)max_paddedlen) {
|
||||
return NGHTTP2_ERR_CALLBACK_FAILURE;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
return (ssize_t)frame->hd.length;
|
||||
if (rv < (nghttp2_ssize)frame->hd.length ||
|
||||
rv > (nghttp2_ssize)max_paddedlen) {
|
||||
return NGHTTP2_ERR_CALLBACK_FAILURE;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
/* Add padding to HEADERS or PUSH_PROMISE. We use
|
||||
@@ -2216,7 +2220,7 @@ static ssize_t session_call_select_padding(nghttp2_session *session,
|
||||
frame->push_promise has also padlen in the same position. */
|
||||
static int session_headers_add_pad(nghttp2_session *session,
|
||||
nghttp2_frame *frame) {
|
||||
ssize_t padded_payloadlen;
|
||||
nghttp2_ssize padded_payloadlen;
|
||||
nghttp2_active_outbound_item *aob;
|
||||
nghttp2_bufs *framebufs;
|
||||
size_t padlen;
|
||||
@@ -2237,7 +2241,7 @@ static int session_headers_add_pad(nghttp2_session *session,
|
||||
|
||||
padlen = (size_t)padded_payloadlen - frame->hd.length;
|
||||
|
||||
DEBUGF("send: padding selected: payloadlen=%zd, padlen=%zu\n",
|
||||
DEBUGF("send: padding selected: payloadlen=%td, padlen=%zu\n",
|
||||
padded_payloadlen, padlen);
|
||||
|
||||
nghttp2_frame_add_pad(framebufs, &frame->hd, padlen, 0);
|
||||
@@ -2257,18 +2261,24 @@ static size_t session_estimate_headers_payload(nghttp2_session *session,
|
||||
|
||||
static int session_pack_extension(nghttp2_session *session, nghttp2_bufs *bufs,
|
||||
nghttp2_frame *frame) {
|
||||
ssize_t rv;
|
||||
nghttp2_ssize rv;
|
||||
nghttp2_buf *buf;
|
||||
size_t buflen;
|
||||
size_t framelen;
|
||||
|
||||
assert(session->callbacks.pack_extension_callback);
|
||||
assert(session->callbacks.pack_extension_callback2 ||
|
||||
session->callbacks.pack_extension_callback);
|
||||
|
||||
buf = &bufs->head->buf;
|
||||
buflen = nghttp2_min(nghttp2_buf_avail(buf), NGHTTP2_MAX_PAYLOADLEN);
|
||||
|
||||
rv = session->callbacks.pack_extension_callback(session, buf->last, buflen,
|
||||
frame, session->user_data);
|
||||
if (session->callbacks.pack_extension_callback2) {
|
||||
rv = session->callbacks.pack_extension_callback2(session, buf->last, buflen,
|
||||
frame, session->user_data);
|
||||
} else {
|
||||
rv = (nghttp2_ssize)session->callbacks.pack_extension_callback(
|
||||
session, buf->last, buflen, frame, session->user_data);
|
||||
}
|
||||
if (rv == NGHTTP2_ERR_CANCEL) {
|
||||
return (int)rv;
|
||||
}
|
||||
@@ -2451,7 +2461,7 @@ static int session_prep_frame(nghttp2_session *session,
|
||||
return rv;
|
||||
}
|
||||
|
||||
DEBUGF("send: before padding, HEADERS serialized in %zd bytes\n",
|
||||
DEBUGF("send: before padding, HEADERS serialized in %zu bytes\n",
|
||||
nghttp2_bufs_len(&session->aob.framebufs));
|
||||
|
||||
rv = session_headers_add_pad(session, frame);
|
||||
@@ -2460,7 +2470,7 @@ static int session_prep_frame(nghttp2_session *session,
|
||||
return rv;
|
||||
}
|
||||
|
||||
DEBUGF("send: HEADERS finally serialized in %zd bytes\n",
|
||||
DEBUGF("send: HEADERS finally serialized in %zu bytes\n",
|
||||
nghttp2_bufs_len(&session->aob.framebufs));
|
||||
|
||||
if (frame->headers.cat == NGHTTP2_HCAT_REQUEST) {
|
||||
@@ -2877,7 +2887,7 @@ static int session_after_frame_sent1(nghttp2_session *session) {
|
||||
|
||||
/* Call on_frame_send_callback after
|
||||
nghttp2_stream_detach_item(), so that application can issue
|
||||
nghttp2_submit_data() in the callback. */
|
||||
nghttp2_submit_data2() in the callback. */
|
||||
if (session->callbacks.on_frame_send_callback) {
|
||||
rv = session_call_on_frame_send(session, frame);
|
||||
if (nghttp2_is_fatal(rv)) {
|
||||
@@ -2949,15 +2959,17 @@ static int session_after_frame_sent1(nghttp2_session *session) {
|
||||
}
|
||||
/* We assume aux_data is a pointer to nghttp2_headers_aux_data */
|
||||
aux_data = &item->aux_data.headers;
|
||||
if (aux_data->data_prd.read_callback) {
|
||||
/* nghttp2_submit_data() makes a copy of aux_data->data_prd */
|
||||
rv = nghttp2_submit_data(session, NGHTTP2_FLAG_END_STREAM,
|
||||
frame->hd.stream_id, &aux_data->data_prd);
|
||||
if (aux_data->dpw.data_prd.read_callback) {
|
||||
/* nghttp2_submit_data_shared() makes a copy of
|
||||
aux_data->dpw */
|
||||
rv = nghttp2_submit_data_shared(session, NGHTTP2_FLAG_END_STREAM,
|
||||
frame->hd.stream_id, &aux_data->dpw);
|
||||
if (nghttp2_is_fatal(rv)) {
|
||||
return rv;
|
||||
}
|
||||
/* TODO nghttp2_submit_data() may fail if stream has already
|
||||
DATA frame item. We might have to handle it here. */
|
||||
/* TODO nghttp2_submit_data_shared() may fail if stream has
|
||||
already DATA frame item. We might have to handle it
|
||||
here. */
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -2978,14 +2990,15 @@ static int session_after_frame_sent1(nghttp2_session *session) {
|
||||
}
|
||||
/* We assume aux_data is a pointer to nghttp2_headers_aux_data */
|
||||
aux_data = &item->aux_data.headers;
|
||||
if (aux_data->data_prd.read_callback) {
|
||||
rv = nghttp2_submit_data(session, NGHTTP2_FLAG_END_STREAM,
|
||||
frame->hd.stream_id, &aux_data->data_prd);
|
||||
if (aux_data->dpw.data_prd.read_callback) {
|
||||
rv = nghttp2_submit_data_shared(session, NGHTTP2_FLAG_END_STREAM,
|
||||
frame->hd.stream_id, &aux_data->dpw);
|
||||
if (nghttp2_is_fatal(rv)) {
|
||||
return rv;
|
||||
}
|
||||
/* TODO nghttp2_submit_data() may fail if stream has already
|
||||
DATA frame item. We might have to handle it here. */
|
||||
/* TODO nghttp2_submit_data_shared() may fail if stream has
|
||||
already DATA frame item. We might have to handle it
|
||||
here. */
|
||||
}
|
||||
return 0;
|
||||
default:
|
||||
@@ -3144,7 +3157,7 @@ static void session_after_frame_sent2(nghttp2_session *session) {
|
||||
aux_data = &item->aux_data.data;
|
||||
|
||||
/* On EOF, we have already detached data. Please note that
|
||||
application may issue nghttp2_submit_data() in
|
||||
application may issue nghttp2_submit_data2() in
|
||||
on_frame_send_callback (call from session_after_frame_sent1),
|
||||
which attach data to stream. We don't want to detach it. */
|
||||
if (aux_data->eof) {
|
||||
@@ -3191,7 +3204,7 @@ static int session_call_send_data(nghttp2_session *session,
|
||||
aux_data = &item->aux_data.data;
|
||||
|
||||
rv = session->callbacks.send_data_callback(session, frame, buf->pos, length,
|
||||
&aux_data->data_prd.source,
|
||||
&aux_data->dpw.data_prd.source,
|
||||
session->user_data);
|
||||
|
||||
switch (rv) {
|
||||
@@ -3205,9 +3218,9 @@ static int session_call_send_data(nghttp2_session *session,
|
||||
}
|
||||
}
|
||||
|
||||
static ssize_t nghttp2_session_mem_send_internal(nghttp2_session *session,
|
||||
const uint8_t **data_ptr,
|
||||
int fast_cb) {
|
||||
static nghttp2_ssize nghttp2_session_mem_send_internal(nghttp2_session *session,
|
||||
const uint8_t **data_ptr,
|
||||
int fast_cb) {
|
||||
int rv;
|
||||
nghttp2_active_outbound_item *aob;
|
||||
nghttp2_bufs *framebufs;
|
||||
@@ -3385,7 +3398,7 @@ static ssize_t nghttp2_session_mem_send_internal(nghttp2_session *session,
|
||||
}
|
||||
}
|
||||
|
||||
DEBUGF("send: start transmitting frame type=%u, length=%zd\n",
|
||||
DEBUGF("send: start transmitting frame type=%u, length=%td\n",
|
||||
framebufs->cur->buf.pos[3],
|
||||
framebufs->cur->buf.last - framebufs->cur->buf.pos);
|
||||
|
||||
@@ -3425,7 +3438,7 @@ static ssize_t nghttp2_session_mem_send_internal(nghttp2_session *session,
|
||||
everything, we will adjust it. */
|
||||
buf->pos += datalen;
|
||||
|
||||
return (ssize_t)datalen;
|
||||
return (nghttp2_ssize)datalen;
|
||||
}
|
||||
case NGHTTP2_OB_SEND_NO_COPY: {
|
||||
nghttp2_stream *stream;
|
||||
@@ -3502,7 +3515,7 @@ static ssize_t nghttp2_session_mem_send_internal(nghttp2_session *session,
|
||||
|
||||
buf->pos += datalen;
|
||||
|
||||
return (ssize_t)datalen;
|
||||
return (nghttp2_ssize)datalen;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3510,8 +3523,13 @@ static ssize_t nghttp2_session_mem_send_internal(nghttp2_session *session,
|
||||
|
||||
ssize_t nghttp2_session_mem_send(nghttp2_session *session,
|
||||
const uint8_t **data_ptr) {
|
||||
return (ssize_t)nghttp2_session_mem_send2(session, data_ptr);
|
||||
}
|
||||
|
||||
nghttp2_ssize nghttp2_session_mem_send2(nghttp2_session *session,
|
||||
const uint8_t **data_ptr) {
|
||||
int rv;
|
||||
ssize_t len;
|
||||
nghttp2_ssize len;
|
||||
|
||||
*data_ptr = NULL;
|
||||
|
||||
@@ -3528,7 +3546,7 @@ ssize_t nghttp2_session_mem_send(nghttp2_session *session,
|
||||
rv = session_after_frame_sent1(session);
|
||||
if (rv < 0) {
|
||||
assert(nghttp2_is_fatal(rv));
|
||||
return (ssize_t)rv;
|
||||
return (nghttp2_ssize)rv;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3537,8 +3555,8 @@ ssize_t nghttp2_session_mem_send(nghttp2_session *session,
|
||||
|
||||
int nghttp2_session_send(nghttp2_session *session) {
|
||||
const uint8_t *data = NULL;
|
||||
ssize_t datalen;
|
||||
ssize_t sentlen;
|
||||
nghttp2_ssize datalen;
|
||||
nghttp2_ssize sentlen;
|
||||
nghttp2_bufs *framebufs;
|
||||
|
||||
framebufs = &session->aob.framebufs;
|
||||
@@ -3548,8 +3566,13 @@ int nghttp2_session_send(nghttp2_session *session) {
|
||||
if (datalen <= 0) {
|
||||
return (int)datalen;
|
||||
}
|
||||
sentlen = session->callbacks.send_callback(session, data, (size_t)datalen,
|
||||
0, session->user_data);
|
||||
if (session->callbacks.send_callback2) {
|
||||
sentlen = session->callbacks.send_callback2(
|
||||
session, data, (size_t)datalen, 0, session->user_data);
|
||||
} else {
|
||||
sentlen = (nghttp2_ssize)session->callbacks.send_callback(
|
||||
session, data, (size_t)datalen, 0, session->user_data);
|
||||
}
|
||||
if (sentlen < 0) {
|
||||
if (sentlen == NGHTTP2_ERR_WOULDBLOCK) {
|
||||
/* Transmission canceled. Rewind the offset */
|
||||
@@ -3564,11 +3587,17 @@ int nghttp2_session_send(nghttp2_session *session) {
|
||||
}
|
||||
}
|
||||
|
||||
static ssize_t session_recv(nghttp2_session *session, uint8_t *buf,
|
||||
size_t len) {
|
||||
ssize_t rv;
|
||||
rv = session->callbacks.recv_callback(session, buf, len, 0,
|
||||
session->user_data);
|
||||
static nghttp2_ssize session_recv(nghttp2_session *session, uint8_t *buf,
|
||||
size_t len) {
|
||||
nghttp2_ssize rv;
|
||||
|
||||
if (session->callbacks.recv_callback2) {
|
||||
rv = session->callbacks.recv_callback2(session, buf, len, 0,
|
||||
session->user_data);
|
||||
} else {
|
||||
rv = (nghttp2_ssize)session->callbacks.recv_callback(session, buf, len, 0,
|
||||
session->user_data);
|
||||
}
|
||||
if (rv > 0) {
|
||||
if ((size_t)rv > len) {
|
||||
return NGHTTP2_ERR_CALLBACK_FAILURE;
|
||||
@@ -3870,7 +3899,7 @@ static int session_inflate_handle_invalid_connection(nghttp2_session *session,
|
||||
static int inflate_header_block(nghttp2_session *session, nghttp2_frame *frame,
|
||||
size_t *readlen_ptr, uint8_t *in, size_t inlen,
|
||||
int final, int call_header_cb) {
|
||||
ssize_t proclen;
|
||||
nghttp2_ssize proclen;
|
||||
int rv;
|
||||
int inflate_flags;
|
||||
nghttp2_hd_nv nv;
|
||||
@@ -3923,7 +3952,7 @@ static int inflate_header_block(nghttp2_session *session, nghttp2_frame *frame,
|
||||
inlen -= (size_t)proclen;
|
||||
*readlen_ptr += (size_t)proclen;
|
||||
|
||||
DEBUGF("recv: proclen=%zd\n", proclen);
|
||||
DEBUGF("recv: proclen=%td\n", proclen);
|
||||
|
||||
if (call_header_cb && (inflate_flags & NGHTTP2_HD_INFLATE_EMIT)) {
|
||||
rv = 0;
|
||||
@@ -5763,7 +5792,7 @@ static int inbound_frame_handle_pad(nghttp2_inbound_frame *iframe,
|
||||
* Computes number of padding based on flags. This function returns
|
||||
* the calculated length if it succeeds, or -1.
|
||||
*/
|
||||
static ssize_t inbound_frame_compute_pad(nghttp2_inbound_frame *iframe) {
|
||||
static nghttp2_ssize inbound_frame_compute_pad(nghttp2_inbound_frame *iframe) {
|
||||
size_t padlen;
|
||||
|
||||
/* 1 for Pad Length field */
|
||||
@@ -5778,7 +5807,7 @@ static ssize_t inbound_frame_compute_pad(nghttp2_inbound_frame *iframe) {
|
||||
|
||||
iframe->padlen = padlen;
|
||||
|
||||
return (ssize_t)padlen;
|
||||
return (nghttp2_ssize)padlen;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -5787,9 +5816,9 @@ static ssize_t inbound_frame_compute_pad(nghttp2_inbound_frame *iframe) {
|
||||
* |payloadleft| does not include |readlen|. If padding was started
|
||||
* strictly before this data chunk, this function returns -1.
|
||||
*/
|
||||
static ssize_t inbound_frame_effective_readlen(nghttp2_inbound_frame *iframe,
|
||||
size_t payloadleft,
|
||||
size_t readlen) {
|
||||
static nghttp2_ssize
|
||||
inbound_frame_effective_readlen(nghttp2_inbound_frame *iframe,
|
||||
size_t payloadleft, size_t readlen) {
|
||||
size_t trail_padlen =
|
||||
nghttp2_frame_trail_padlen(&iframe->frame, iframe->padlen);
|
||||
|
||||
@@ -5799,19 +5828,24 @@ static ssize_t inbound_frame_effective_readlen(nghttp2_inbound_frame *iframe,
|
||||
if (readlen < padlen) {
|
||||
return -1;
|
||||
}
|
||||
return (ssize_t)(readlen - padlen);
|
||||
return (nghttp2_ssize)(readlen - padlen);
|
||||
}
|
||||
return (ssize_t)(readlen);
|
||||
return (nghttp2_ssize)(readlen);
|
||||
}
|
||||
|
||||
static const uint8_t static_in[] = {0};
|
||||
|
||||
ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
|
||||
size_t inlen) {
|
||||
return (ssize_t)nghttp2_session_mem_recv2(session, in, inlen);
|
||||
}
|
||||
|
||||
nghttp2_ssize nghttp2_session_mem_recv2(nghttp2_session *session,
|
||||
const uint8_t *in, size_t inlen) {
|
||||
const uint8_t *first, *last;
|
||||
nghttp2_inbound_frame *iframe = &session->iframe;
|
||||
size_t readlen;
|
||||
ssize_t padlen;
|
||||
nghttp2_ssize padlen;
|
||||
int rv;
|
||||
int busy = 0;
|
||||
nghttp2_frame_hd cont_hd;
|
||||
@@ -5841,7 +5875,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
|
||||
}
|
||||
|
||||
if (!nghttp2_session_want_read(session)) {
|
||||
return (ssize_t)inlen;
|
||||
return (nghttp2_ssize)inlen;
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
@@ -5871,7 +5905,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
|
||||
in += readlen;
|
||||
|
||||
if (nghttp2_buf_mark_avail(&iframe->sbuf)) {
|
||||
return (ssize_t)(in - first);
|
||||
return (nghttp2_ssize)(in - first);
|
||||
}
|
||||
|
||||
if (iframe->sbuf.pos[3] != NGHTTP2_SETTINGS ||
|
||||
@@ -5893,7 +5927,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
|
||||
return rv;
|
||||
}
|
||||
|
||||
return (ssize_t)inlen;
|
||||
return (nghttp2_ssize)inlen;
|
||||
}
|
||||
|
||||
iframe->state = NGHTTP2_IB_READ_HEAD;
|
||||
@@ -5908,7 +5942,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
|
||||
in += readlen;
|
||||
|
||||
if (nghttp2_buf_mark_avail(&iframe->sbuf)) {
|
||||
return (ssize_t)(in - first);
|
||||
return (nghttp2_ssize)(in - first);
|
||||
}
|
||||
|
||||
nghttp2_frame_unpack_frame_hd(&iframe->frame.hd, iframe->sbuf.pos);
|
||||
@@ -5929,7 +5963,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
|
||||
return rv;
|
||||
}
|
||||
|
||||
return (ssize_t)inlen;
|
||||
return (nghttp2_ssize)inlen;
|
||||
}
|
||||
|
||||
switch (iframe->frame.hd.type) {
|
||||
@@ -5944,7 +5978,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
|
||||
|
||||
rv = session_on_data_received_fail_fast(session);
|
||||
if (iframe->state == NGHTTP2_IB_IGN_ALL) {
|
||||
return (ssize_t)inlen;
|
||||
return (nghttp2_ssize)inlen;
|
||||
}
|
||||
if (rv == NGHTTP2_ERR_IGN_PAYLOAD) {
|
||||
DEBUGF("recv: DATA not allowed stream_id=%d\n",
|
||||
@@ -5966,7 +6000,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
|
||||
if (nghttp2_is_fatal(rv)) {
|
||||
return rv;
|
||||
}
|
||||
return (ssize_t)inlen;
|
||||
return (nghttp2_ssize)inlen;
|
||||
}
|
||||
|
||||
if (rv == 1) {
|
||||
@@ -5993,7 +6027,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
|
||||
if (nghttp2_is_fatal(rv)) {
|
||||
return rv;
|
||||
}
|
||||
return (ssize_t)inlen;
|
||||
return (nghttp2_ssize)inlen;
|
||||
}
|
||||
|
||||
if (rv == 1) {
|
||||
@@ -6036,7 +6070,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
|
||||
busy = 1;
|
||||
|
||||
if (iframe->state == NGHTTP2_IB_IGN_ALL) {
|
||||
return (ssize_t)inlen;
|
||||
return (nghttp2_ssize)inlen;
|
||||
}
|
||||
|
||||
if (rv == NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE) {
|
||||
@@ -6137,7 +6171,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
|
||||
if (nghttp2_is_fatal(rv)) {
|
||||
return rv;
|
||||
}
|
||||
return (ssize_t)inlen;
|
||||
return (nghttp2_ssize)inlen;
|
||||
}
|
||||
|
||||
iframe->iv = nghttp2_mem_malloc(mem, sizeof(nghttp2_settings_entry) *
|
||||
@@ -6175,7 +6209,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
|
||||
if (nghttp2_is_fatal(rv)) {
|
||||
return rv;
|
||||
}
|
||||
return (ssize_t)inlen;
|
||||
return (nghttp2_ssize)inlen;
|
||||
}
|
||||
|
||||
if (rv == 1) {
|
||||
@@ -6235,7 +6269,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
|
||||
return rv;
|
||||
}
|
||||
|
||||
return (ssize_t)inlen;
|
||||
return (nghttp2_ssize)inlen;
|
||||
default:
|
||||
DEBUGF("recv: extension frame\n");
|
||||
|
||||
@@ -6346,7 +6380,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
|
||||
if (nghttp2_is_fatal(rv)) {
|
||||
return rv;
|
||||
}
|
||||
return (ssize_t)inlen;
|
||||
return (nghttp2_ssize)inlen;
|
||||
}
|
||||
|
||||
if (iframe->payloadleft < 4) {
|
||||
@@ -6404,11 +6438,11 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
|
||||
in += readlen;
|
||||
iframe->payloadleft -= readlen;
|
||||
|
||||
DEBUGF("recv: readlen=%zu, payloadleft=%zu, left=%zd\n", readlen,
|
||||
DEBUGF("recv: readlen=%zu, payloadleft=%zu, left=%zu\n", readlen,
|
||||
iframe->payloadleft, nghttp2_buf_mark_avail(&iframe->sbuf));
|
||||
|
||||
if (nghttp2_buf_mark_avail(&iframe->sbuf)) {
|
||||
return (ssize_t)(in - first);
|
||||
return (nghttp2_ssize)(in - first);
|
||||
}
|
||||
|
||||
switch (iframe->frame.hd.type) {
|
||||
@@ -6424,7 +6458,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
|
||||
if (nghttp2_is_fatal(rv)) {
|
||||
return rv;
|
||||
}
|
||||
return (ssize_t)inlen;
|
||||
return (nghttp2_ssize)inlen;
|
||||
}
|
||||
iframe->frame.headers.padlen = (size_t)padlen;
|
||||
|
||||
@@ -6451,7 +6485,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
|
||||
busy = 1;
|
||||
|
||||
if (iframe->state == NGHTTP2_IB_IGN_ALL) {
|
||||
return (ssize_t)inlen;
|
||||
return (nghttp2_ssize)inlen;
|
||||
}
|
||||
|
||||
if (rv == NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE) {
|
||||
@@ -6481,7 +6515,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
|
||||
}
|
||||
|
||||
if (iframe->state == NGHTTP2_IB_IGN_ALL) {
|
||||
return (ssize_t)inlen;
|
||||
return (nghttp2_ssize)inlen;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6495,7 +6529,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
|
||||
}
|
||||
|
||||
if (iframe->state == NGHTTP2_IB_IGN_ALL) {
|
||||
return (ssize_t)inlen;
|
||||
return (nghttp2_ssize)inlen;
|
||||
}
|
||||
|
||||
session_inbound_frame_reset(session);
|
||||
@@ -6513,7 +6547,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
|
||||
if (nghttp2_is_fatal(rv)) {
|
||||
return rv;
|
||||
}
|
||||
return (ssize_t)inlen;
|
||||
return (nghttp2_ssize)inlen;
|
||||
}
|
||||
|
||||
iframe->frame.push_promise.padlen = (size_t)padlen;
|
||||
@@ -6539,7 +6573,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
|
||||
busy = 1;
|
||||
|
||||
if (iframe->state == NGHTTP2_IB_IGN_ALL) {
|
||||
return (ssize_t)inlen;
|
||||
return (nghttp2_ssize)inlen;
|
||||
}
|
||||
|
||||
if (rv == NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE) {
|
||||
@@ -6568,7 +6602,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
|
||||
}
|
||||
|
||||
if (iframe->state == NGHTTP2_IB_IGN_ALL) {
|
||||
return (ssize_t)inlen;
|
||||
return (nghttp2_ssize)inlen;
|
||||
}
|
||||
|
||||
session_inbound_frame_reset(session);
|
||||
@@ -6603,7 +6637,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
|
||||
}
|
||||
|
||||
if (iframe->state == NGHTTP2_IB_IGN_ALL) {
|
||||
return (ssize_t)inlen;
|
||||
return (nghttp2_ssize)inlen;
|
||||
}
|
||||
|
||||
session_inbound_frame_reset(session);
|
||||
@@ -6661,7 +6695,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
|
||||
break;
|
||||
case NGHTTP2_IB_READ_HEADER_BLOCK:
|
||||
case NGHTTP2_IB_IGN_HEADER_BLOCK: {
|
||||
ssize_t data_readlen;
|
||||
nghttp2_ssize data_readlen;
|
||||
size_t trail_padlen;
|
||||
int final;
|
||||
#ifdef DEBUGBUILD
|
||||
@@ -6705,14 +6739,14 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
|
||||
}
|
||||
|
||||
if (iframe->state == NGHTTP2_IB_IGN_ALL) {
|
||||
return (ssize_t)inlen;
|
||||
return (nghttp2_ssize)inlen;
|
||||
}
|
||||
|
||||
if (rv == NGHTTP2_ERR_PAUSE) {
|
||||
in += hd_proclen;
|
||||
iframe->payloadleft -= hd_proclen;
|
||||
|
||||
return (ssize_t)(in - first);
|
||||
return (nghttp2_ssize)(in - first);
|
||||
}
|
||||
|
||||
if (rv == NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE) {
|
||||
@@ -6819,7 +6853,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
|
||||
|
||||
assert(iframe->state == NGHTTP2_IB_IGN_ALL);
|
||||
|
||||
return (ssize_t)inlen;
|
||||
return (nghttp2_ssize)inlen;
|
||||
case NGHTTP2_IB_READ_SETTINGS:
|
||||
DEBUGF("recv: [IB_READ_SETTINGS]\n");
|
||||
|
||||
@@ -6849,7 +6883,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
|
||||
}
|
||||
|
||||
if (iframe->state == NGHTTP2_IB_IGN_ALL) {
|
||||
return (ssize_t)inlen;
|
||||
return (nghttp2_ssize)inlen;
|
||||
}
|
||||
|
||||
session_inbound_frame_reset(session);
|
||||
@@ -6883,7 +6917,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
|
||||
}
|
||||
|
||||
if (iframe->state == NGHTTP2_IB_IGN_ALL) {
|
||||
return (ssize_t)inlen;
|
||||
return (nghttp2_ssize)inlen;
|
||||
}
|
||||
|
||||
session_inbound_frame_reset(session);
|
||||
@@ -6903,7 +6937,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
|
||||
in += readlen;
|
||||
|
||||
if (nghttp2_buf_mark_avail(&iframe->sbuf)) {
|
||||
return (ssize_t)(in - first);
|
||||
return (nghttp2_ssize)(in - first);
|
||||
}
|
||||
|
||||
nghttp2_frame_unpack_frame_hd(&cont_hd, iframe->sbuf.pos);
|
||||
@@ -6925,7 +6959,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
|
||||
return rv;
|
||||
}
|
||||
|
||||
return (ssize_t)inlen;
|
||||
return (nghttp2_ssize)inlen;
|
||||
}
|
||||
|
||||
/* CONTINUATION won't bear NGHTTP2_PADDED flag */
|
||||
@@ -6961,7 +6995,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
|
||||
iframe->payloadleft, nghttp2_buf_mark_avail(&iframe->sbuf));
|
||||
|
||||
if (nghttp2_buf_mark_avail(&iframe->sbuf)) {
|
||||
return (ssize_t)(in - first);
|
||||
return (nghttp2_ssize)(in - first);
|
||||
}
|
||||
|
||||
/* Pad Length field is subject to flow control */
|
||||
@@ -6971,7 +7005,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
|
||||
}
|
||||
|
||||
if (iframe->state == NGHTTP2_IB_IGN_ALL) {
|
||||
return (ssize_t)inlen;
|
||||
return (nghttp2_ssize)inlen;
|
||||
}
|
||||
|
||||
/* Pad Length field is consumed immediately */
|
||||
@@ -6983,7 +7017,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
|
||||
}
|
||||
|
||||
if (iframe->state == NGHTTP2_IB_IGN_ALL) {
|
||||
return (ssize_t)inlen;
|
||||
return (nghttp2_ssize)inlen;
|
||||
}
|
||||
|
||||
stream = nghttp2_session_get_stream(session, iframe->frame.hd.stream_id);
|
||||
@@ -7006,7 +7040,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
|
||||
if (nghttp2_is_fatal(rv)) {
|
||||
return rv;
|
||||
}
|
||||
return (ssize_t)inlen;
|
||||
return (nghttp2_ssize)inlen;
|
||||
}
|
||||
|
||||
iframe->frame.data.padlen = (size_t)padlen;
|
||||
@@ -7033,7 +7067,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
|
||||
iframe->payloadleft);
|
||||
|
||||
if (readlen > 0) {
|
||||
ssize_t data_readlen;
|
||||
nghttp2_ssize data_readlen;
|
||||
|
||||
rv = nghttp2_session_update_recv_connection_window_size(session,
|
||||
readlen);
|
||||
@@ -7042,7 +7076,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
|
||||
}
|
||||
|
||||
if (iframe->state == NGHTTP2_IB_IGN_ALL) {
|
||||
return (ssize_t)inlen;
|
||||
return (nghttp2_ssize)inlen;
|
||||
}
|
||||
|
||||
rv = nghttp2_session_update_recv_stream_window_size(
|
||||
@@ -7061,7 +7095,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
|
||||
data_readlen = 0;
|
||||
}
|
||||
|
||||
padlen = (ssize_t)readlen - data_readlen;
|
||||
padlen = (nghttp2_ssize)readlen - data_readlen;
|
||||
|
||||
if (padlen > 0) {
|
||||
/* Padding is considered as "consumed" immediately */
|
||||
@@ -7073,11 +7107,11 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
|
||||
}
|
||||
|
||||
if (iframe->state == NGHTTP2_IB_IGN_ALL) {
|
||||
return (ssize_t)inlen;
|
||||
return (nghttp2_ssize)inlen;
|
||||
}
|
||||
}
|
||||
|
||||
DEBUGF("recv: data_readlen=%zd\n", data_readlen);
|
||||
DEBUGF("recv: data_readlen=%td\n", data_readlen);
|
||||
|
||||
if (data_readlen > 0) {
|
||||
if (session_enforce_http_messaging(session)) {
|
||||
@@ -7092,7 +7126,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
|
||||
}
|
||||
|
||||
if (iframe->state == NGHTTP2_IB_IGN_DATA) {
|
||||
return (ssize_t)inlen;
|
||||
return (nghttp2_ssize)inlen;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7111,7 +7145,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
|
||||
session, iframe->frame.hd.flags, iframe->frame.hd.stream_id,
|
||||
in - readlen, (size_t)data_readlen, session->user_data);
|
||||
if (rv == NGHTTP2_ERR_PAUSE) {
|
||||
return (ssize_t)(in - first);
|
||||
return (nghttp2_ssize)(in - first);
|
||||
}
|
||||
|
||||
if (nghttp2_is_fatal(rv)) {
|
||||
@@ -7153,7 +7187,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
|
||||
}
|
||||
|
||||
if (iframe->state == NGHTTP2_IB_IGN_ALL) {
|
||||
return (ssize_t)inlen;
|
||||
return (nghttp2_ssize)inlen;
|
||||
}
|
||||
|
||||
if (session->opt_flags & NGHTTP2_OPTMASK_NO_AUTO_WINDOW_UPDATE) {
|
||||
@@ -7166,7 +7200,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
|
||||
}
|
||||
|
||||
if (iframe->state == NGHTTP2_IB_IGN_ALL) {
|
||||
return (ssize_t)inlen;
|
||||
return (nghttp2_ssize)inlen;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7179,7 +7213,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
|
||||
|
||||
break;
|
||||
case NGHTTP2_IB_IGN_ALL:
|
||||
return (ssize_t)inlen;
|
||||
return (nghttp2_ssize)inlen;
|
||||
case NGHTTP2_IB_READ_EXTENSION_PAYLOAD:
|
||||
DEBUGF("recv: [IB_READ_EXTENSION_PAYLOAD]\n");
|
||||
|
||||
@@ -7274,7 +7308,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
|
||||
}
|
||||
|
||||
if (iframe->state == NGHTTP2_IB_IGN_ALL) {
|
||||
return (ssize_t)inlen;
|
||||
return (nghttp2_ssize)inlen;
|
||||
}
|
||||
|
||||
session_inbound_frame_reset(session);
|
||||
@@ -7291,16 +7325,17 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
|
||||
|
||||
assert(in == last);
|
||||
|
||||
return (ssize_t)(in - first);
|
||||
return (nghttp2_ssize)(in - first);
|
||||
}
|
||||
|
||||
int nghttp2_session_recv(nghttp2_session *session) {
|
||||
uint8_t buf[NGHTTP2_INBOUND_BUFFER_LENGTH];
|
||||
while (1) {
|
||||
ssize_t readlen;
|
||||
nghttp2_ssize readlen;
|
||||
readlen = session_recv(session, buf, sizeof(buf));
|
||||
if (readlen > 0) {
|
||||
ssize_t proclen = nghttp2_session_mem_recv(session, buf, (size_t)readlen);
|
||||
nghttp2_ssize proclen =
|
||||
nghttp2_session_mem_recv2(session, buf, (size_t)readlen);
|
||||
if (proclen < 0) {
|
||||
return (int)proclen;
|
||||
}
|
||||
@@ -7642,8 +7677,8 @@ int nghttp2_session_pack_data(nghttp2_session *session, nghttp2_bufs *bufs,
|
||||
nghttp2_stream *stream) {
|
||||
int rv;
|
||||
uint32_t data_flags;
|
||||
ssize_t payloadlen;
|
||||
ssize_t padded_payloadlen;
|
||||
nghttp2_ssize payloadlen;
|
||||
nghttp2_ssize padded_payloadlen;
|
||||
nghttp2_buf *buf;
|
||||
size_t max_payloadlen;
|
||||
|
||||
@@ -7651,19 +7686,26 @@ int nghttp2_session_pack_data(nghttp2_session *session, nghttp2_bufs *bufs,
|
||||
|
||||
buf = &bufs->cur->buf;
|
||||
|
||||
if (session->callbacks.read_length_callback) {
|
||||
if (session->callbacks.read_length_callback2 ||
|
||||
session->callbacks.read_length_callback) {
|
||||
if (session->callbacks.read_length_callback2) {
|
||||
payloadlen = session->callbacks.read_length_callback2(
|
||||
session, frame->hd.type, stream->stream_id,
|
||||
session->remote_window_size, stream->remote_window_size,
|
||||
session->remote_settings.max_frame_size, session->user_data);
|
||||
} else {
|
||||
payloadlen = (nghttp2_ssize)session->callbacks.read_length_callback(
|
||||
session, frame->hd.type, stream->stream_id,
|
||||
session->remote_window_size, stream->remote_window_size,
|
||||
session->remote_settings.max_frame_size, session->user_data);
|
||||
}
|
||||
|
||||
payloadlen = session->callbacks.read_length_callback(
|
||||
session, frame->hd.type, stream->stream_id, session->remote_window_size,
|
||||
stream->remote_window_size, session->remote_settings.max_frame_size,
|
||||
session->user_data);
|
||||
|
||||
DEBUGF("send: read_length_callback=%zd\n", payloadlen);
|
||||
DEBUGF("send: read_length_callback=%td\n", payloadlen);
|
||||
|
||||
payloadlen = nghttp2_session_enforce_flow_control_limits(session, stream,
|
||||
payloadlen);
|
||||
|
||||
DEBUGF("send: read_length_callback after flow control=%zd\n", payloadlen);
|
||||
DEBUGF("send: read_length_callback after flow control=%td\n", payloadlen);
|
||||
|
||||
if (payloadlen <= 0) {
|
||||
return NGHTTP2_ERR_CALLBACK_FAILURE;
|
||||
@@ -7679,9 +7721,9 @@ int nghttp2_session_pack_data(nghttp2_session *session, nghttp2_bufs *bufs,
|
||||
DEBUGF("send: realloc buffer failed rv=%d", rv);
|
||||
/* If reallocation failed, old buffers are still in tact. So
|
||||
use safe limit. */
|
||||
payloadlen = (ssize_t)datamax;
|
||||
payloadlen = (nghttp2_ssize)datamax;
|
||||
|
||||
DEBUGF("send: use safe limit payloadlen=%zd", payloadlen);
|
||||
DEBUGF("send: use safe limit payloadlen=%td", payloadlen);
|
||||
} else {
|
||||
assert(&session->aob.framebufs == bufs);
|
||||
|
||||
@@ -7695,9 +7737,23 @@ int nghttp2_session_pack_data(nghttp2_session *session, nghttp2_bufs *bufs,
|
||||
assert(nghttp2_buf_avail(buf) >= datamax);
|
||||
|
||||
data_flags = NGHTTP2_DATA_FLAG_NONE;
|
||||
payloadlen = aux_data->data_prd.read_callback(
|
||||
session, frame->hd.stream_id, buf->pos, datamax, &data_flags,
|
||||
&aux_data->data_prd.source, session->user_data);
|
||||
switch (aux_data->dpw.version) {
|
||||
case NGHTTP2_DATA_PROVIDER_V1:
|
||||
payloadlen = (nghttp2_ssize)aux_data->dpw.data_prd.v1.read_callback(
|
||||
session, frame->hd.stream_id, buf->pos, datamax, &data_flags,
|
||||
&aux_data->dpw.data_prd.source, session->user_data);
|
||||
|
||||
break;
|
||||
case NGHTTP2_DATA_PROVIDER_V2:
|
||||
payloadlen = aux_data->dpw.data_prd.v2.read_callback(
|
||||
session, frame->hd.stream_id, buf->pos, datamax, &data_flags,
|
||||
&aux_data->dpw.data_prd.source, session->user_data);
|
||||
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
abort();
|
||||
}
|
||||
|
||||
if (payloadlen == NGHTTP2_ERR_DEFERRED ||
|
||||
payloadlen == NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE ||
|
||||
@@ -8275,7 +8331,7 @@ int nghttp2_session_change_stream_priority(
|
||||
/* We don't intentionally call nghttp2_session_adjust_idle_stream()
|
||||
so that idle stream created by this function, and existing ones
|
||||
are kept for application. We will adjust number of idle stream
|
||||
in nghttp2_session_mem_send or nghttp2_session_mem_recv is
|
||||
in nghttp2_session_mem_send2 or nghttp2_session_mem_recv2 is
|
||||
called. */
|
||||
return 0;
|
||||
}
|
||||
@@ -8313,7 +8369,7 @@ int nghttp2_session_create_idle_stream(nghttp2_session *session,
|
||||
/* We don't intentionally call nghttp2_session_adjust_idle_stream()
|
||||
so that idle stream created by this function, and existing ones
|
||||
are kept for application. We will adjust number of idle stream
|
||||
in nghttp2_session_mem_send or nghttp2_session_mem_recv is
|
||||
in nghttp2_session_mem_send2 or nghttp2_session_mem_recv2 is
|
||||
called. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -68,7 +68,7 @@ static int32_t submit_headers_shared(nghttp2_session *session, uint8_t flags,
|
||||
int32_t stream_id,
|
||||
const nghttp2_priority_spec *pri_spec,
|
||||
nghttp2_nv *nva_copy, size_t nvlen,
|
||||
const nghttp2_data_provider *data_prd,
|
||||
const nghttp2_data_provider_wrap *dpw,
|
||||
void *stream_user_data) {
|
||||
int rv;
|
||||
uint8_t flags_copy;
|
||||
@@ -87,8 +87,8 @@ static int32_t submit_headers_shared(nghttp2_session *session, uint8_t flags,
|
||||
|
||||
nghttp2_outbound_item_init(item);
|
||||
|
||||
if (data_prd != NULL && data_prd->read_callback != NULL) {
|
||||
item->aux_data.headers.data_prd = *data_prd;
|
||||
if (dpw != NULL && dpw->data_prd.read_callback != NULL) {
|
||||
item->aux_data.headers.dpw = *dpw;
|
||||
}
|
||||
|
||||
item->aux_data.headers.stream_user_data = stream_user_data;
|
||||
@@ -143,7 +143,7 @@ static int32_t submit_headers_shared_nva(nghttp2_session *session,
|
||||
uint8_t flags, int32_t stream_id,
|
||||
const nghttp2_priority_spec *pri_spec,
|
||||
const nghttp2_nv *nva, size_t nvlen,
|
||||
const nghttp2_data_provider *data_prd,
|
||||
const nghttp2_data_provider_wrap *dpw,
|
||||
void *stream_user_data) {
|
||||
int rv;
|
||||
nghttp2_nv *nva_copy;
|
||||
@@ -165,7 +165,7 @@ static int32_t submit_headers_shared_nva(nghttp2_session *session,
|
||||
}
|
||||
|
||||
return submit_headers_shared(session, flags, stream_id, ©_pri_spec,
|
||||
nva_copy, nvlen, data_prd, stream_user_data);
|
||||
nva_copy, nvlen, dpw, stream_user_data);
|
||||
}
|
||||
|
||||
int nghttp2_submit_trailer(nghttp2_session *session, int32_t stream_id,
|
||||
@@ -740,9 +740,9 @@ fail_item_malloc:
|
||||
}
|
||||
|
||||
static uint8_t set_request_flags(const nghttp2_priority_spec *pri_spec,
|
||||
const nghttp2_data_provider *data_prd) {
|
||||
const nghttp2_data_provider_wrap *dpw) {
|
||||
uint8_t flags = NGHTTP2_FLAG_NONE;
|
||||
if (data_prd == NULL || data_prd->read_callback == NULL) {
|
||||
if (dpw == NULL || dpw->data_prd.read_callback == NULL) {
|
||||
flags |= NGHTTP2_FLAG_END_STREAM;
|
||||
}
|
||||
|
||||
@@ -753,11 +753,11 @@ static uint8_t set_request_flags(const nghttp2_priority_spec *pri_spec,
|
||||
return flags;
|
||||
}
|
||||
|
||||
int32_t nghttp2_submit_request(nghttp2_session *session,
|
||||
const nghttp2_priority_spec *pri_spec,
|
||||
const nghttp2_nv *nva, size_t nvlen,
|
||||
const nghttp2_data_provider *data_prd,
|
||||
void *stream_user_data) {
|
||||
static int32_t submit_request_shared(nghttp2_session *session,
|
||||
const nghttp2_priority_spec *pri_spec,
|
||||
const nghttp2_nv *nva, size_t nvlen,
|
||||
const nghttp2_data_provider_wrap *dpw,
|
||||
void *stream_user_data) {
|
||||
uint8_t flags;
|
||||
int rv;
|
||||
|
||||
@@ -775,23 +775,47 @@ int32_t nghttp2_submit_request(nghttp2_session *session,
|
||||
pri_spec = NULL;
|
||||
}
|
||||
|
||||
flags = set_request_flags(pri_spec, data_prd);
|
||||
flags = set_request_flags(pri_spec, dpw);
|
||||
|
||||
return submit_headers_shared_nva(session, flags, -1, pri_spec, nva, nvlen,
|
||||
data_prd, stream_user_data);
|
||||
dpw, stream_user_data);
|
||||
}
|
||||
|
||||
static uint8_t set_response_flags(const nghttp2_data_provider *data_prd) {
|
||||
int32_t nghttp2_submit_request(nghttp2_session *session,
|
||||
const nghttp2_priority_spec *pri_spec,
|
||||
const nghttp2_nv *nva, size_t nvlen,
|
||||
const nghttp2_data_provider *data_prd,
|
||||
void *stream_user_data) {
|
||||
nghttp2_data_provider_wrap dpw;
|
||||
|
||||
return submit_request_shared(session, pri_spec, nva, nvlen,
|
||||
nghttp2_data_provider_wrap_v1(&dpw, data_prd),
|
||||
stream_user_data);
|
||||
}
|
||||
|
||||
int32_t nghttp2_submit_request2(nghttp2_session *session,
|
||||
const nghttp2_priority_spec *pri_spec,
|
||||
const nghttp2_nv *nva, size_t nvlen,
|
||||
const nghttp2_data_provider2 *data_prd,
|
||||
void *stream_user_data) {
|
||||
nghttp2_data_provider_wrap dpw;
|
||||
|
||||
return submit_request_shared(session, pri_spec, nva, nvlen,
|
||||
nghttp2_data_provider_wrap_v2(&dpw, data_prd),
|
||||
stream_user_data);
|
||||
}
|
||||
|
||||
static uint8_t set_response_flags(const nghttp2_data_provider_wrap *dpw) {
|
||||
uint8_t flags = NGHTTP2_FLAG_NONE;
|
||||
if (data_prd == NULL || data_prd->read_callback == NULL) {
|
||||
if (dpw == NULL || dpw->data_prd.read_callback == NULL) {
|
||||
flags |= NGHTTP2_FLAG_END_STREAM;
|
||||
}
|
||||
return flags;
|
||||
}
|
||||
|
||||
int nghttp2_submit_response(nghttp2_session *session, int32_t stream_id,
|
||||
const nghttp2_nv *nva, size_t nvlen,
|
||||
const nghttp2_data_provider *data_prd) {
|
||||
static int submit_response_shared(nghttp2_session *session, int32_t stream_id,
|
||||
const nghttp2_nv *nva, size_t nvlen,
|
||||
const nghttp2_data_provider_wrap *dpw) {
|
||||
uint8_t flags;
|
||||
|
||||
if (stream_id <= 0) {
|
||||
@@ -802,14 +826,32 @@ int nghttp2_submit_response(nghttp2_session *session, int32_t stream_id,
|
||||
return NGHTTP2_ERR_PROTO;
|
||||
}
|
||||
|
||||
flags = set_response_flags(data_prd);
|
||||
flags = set_response_flags(dpw);
|
||||
return submit_headers_shared_nva(session, flags, stream_id, NULL, nva, nvlen,
|
||||
data_prd, NULL);
|
||||
dpw, NULL);
|
||||
}
|
||||
|
||||
int nghttp2_submit_data(nghttp2_session *session, uint8_t flags,
|
||||
int32_t stream_id,
|
||||
const nghttp2_data_provider *data_prd) {
|
||||
int nghttp2_submit_response(nghttp2_session *session, int32_t stream_id,
|
||||
const nghttp2_nv *nva, size_t nvlen,
|
||||
const nghttp2_data_provider *data_prd) {
|
||||
nghttp2_data_provider_wrap dpw;
|
||||
|
||||
return submit_response_shared(session, stream_id, nva, nvlen,
|
||||
nghttp2_data_provider_wrap_v1(&dpw, data_prd));
|
||||
}
|
||||
|
||||
int nghttp2_submit_response2(nghttp2_session *session, int32_t stream_id,
|
||||
const nghttp2_nv *nva, size_t nvlen,
|
||||
const nghttp2_data_provider2 *data_prd) {
|
||||
nghttp2_data_provider_wrap dpw;
|
||||
|
||||
return submit_response_shared(session, stream_id, nva, nvlen,
|
||||
nghttp2_data_provider_wrap_v2(&dpw, data_prd));
|
||||
}
|
||||
|
||||
int nghttp2_submit_data_shared(nghttp2_session *session, uint8_t flags,
|
||||
int32_t stream_id,
|
||||
const nghttp2_data_provider_wrap *dpw) {
|
||||
int rv;
|
||||
nghttp2_outbound_item *item;
|
||||
nghttp2_frame *frame;
|
||||
@@ -832,7 +874,7 @@ int nghttp2_submit_data(nghttp2_session *session, uint8_t flags,
|
||||
|
||||
frame = &item->frame;
|
||||
aux_data = &item->aux_data.data;
|
||||
aux_data->data_prd = *data_prd;
|
||||
aux_data->dpw = *dpw;
|
||||
aux_data->eof = 0;
|
||||
aux_data->flags = nflags;
|
||||
|
||||
@@ -848,9 +890,37 @@ int nghttp2_submit_data(nghttp2_session *session, uint8_t flags,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int nghttp2_submit_data(nghttp2_session *session, uint8_t flags,
|
||||
int32_t stream_id,
|
||||
const nghttp2_data_provider *data_prd) {
|
||||
nghttp2_data_provider_wrap dpw;
|
||||
|
||||
assert(data_prd);
|
||||
|
||||
return nghttp2_submit_data_shared(
|
||||
session, flags, stream_id, nghttp2_data_provider_wrap_v1(&dpw, data_prd));
|
||||
}
|
||||
|
||||
int nghttp2_submit_data2(nghttp2_session *session, uint8_t flags,
|
||||
int32_t stream_id,
|
||||
const nghttp2_data_provider2 *data_prd) {
|
||||
nghttp2_data_provider_wrap dpw;
|
||||
|
||||
assert(data_prd);
|
||||
|
||||
return nghttp2_submit_data_shared(
|
||||
session, flags, stream_id, nghttp2_data_provider_wrap_v2(&dpw, data_prd));
|
||||
}
|
||||
|
||||
ssize_t nghttp2_pack_settings_payload(uint8_t *buf, size_t buflen,
|
||||
const nghttp2_settings_entry *iv,
|
||||
size_t niv) {
|
||||
return (ssize_t)nghttp2_pack_settings_payload2(buf, buflen, iv, niv);
|
||||
}
|
||||
|
||||
nghttp2_ssize nghttp2_pack_settings_payload2(uint8_t *buf, size_t buflen,
|
||||
const nghttp2_settings_entry *iv,
|
||||
size_t niv) {
|
||||
if (!nghttp2_iv_check(iv, niv)) {
|
||||
return NGHTTP2_ERR_INVALID_ARGUMENT;
|
||||
}
|
||||
@@ -859,7 +929,7 @@ ssize_t nghttp2_pack_settings_payload(uint8_t *buf, size_t buflen,
|
||||
return NGHTTP2_ERR_INSUFF_BUFSIZE;
|
||||
}
|
||||
|
||||
return (ssize_t)nghttp2_frame_pack_settings_payload(buf, iv, niv);
|
||||
return (nghttp2_ssize)nghttp2_frame_pack_settings_payload(buf, iv, niv);
|
||||
}
|
||||
|
||||
int nghttp2_submit_extension(nghttp2_session *session, uint8_t type,
|
||||
@@ -875,7 +945,8 @@ int nghttp2_submit_extension(nghttp2_session *session, uint8_t type,
|
||||
return NGHTTP2_ERR_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
if (!session->callbacks.pack_extension_callback) {
|
||||
if (!session->callbacks.pack_extension_callback2 &&
|
||||
!session->callbacks.pack_extension_callback) {
|
||||
return NGHTTP2_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
|
||||
@@ -31,4 +31,10 @@
|
||||
|
||||
#include <nghttp2/nghttp2.h>
|
||||
|
||||
typedef struct nghttp2_data_provider_wrap nghttp2_data_provider_wrap;
|
||||
|
||||
int nghttp2_submit_data_shared(nghttp2_session *session, uint8_t flags,
|
||||
int32_t stream_id,
|
||||
const nghttp2_data_provider_wrap *dpw);
|
||||
|
||||
#endif /* NGHTTP2_SUBMIT_H */
|
||||
|
||||
@@ -6,7 +6,7 @@ PREV_TAG=$2
|
||||
git checkout refs/tags/$TAG
|
||||
git log --pretty=fuller --date=short refs/tags/$PREV_TAG..HEAD > ChangeLog
|
||||
|
||||
git submodule update --init
|
||||
git submodule update --init --depth 1
|
||||
|
||||
autoreconf -i
|
||||
./configure --with-mruby && \
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# nghttp2 - HTTP/2 C Library
|
||||
|
||||
@@ -21,6 +21,8 @@ include_directories(
|
||||
${JANSSON_INCLUDE_DIRS}
|
||||
${ZLIB_INCLUDE_DIRS}
|
||||
${LIBBPF_INCLUDE_DIRS}
|
||||
${LIBBROTLIENC_INCLUDE_DIRS}
|
||||
${LIBBROTLIDEC_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
# XXX per-target?
|
||||
@@ -38,6 +40,8 @@ link_libraries(
|
||||
${ZLIB_LIBRARIES}
|
||||
${APP_LIBRARIES}
|
||||
${LIBBPF_LIBRARIES}
|
||||
${LIBBROTLIENC_LIBRARIES}
|
||||
${LIBBROTLIDEC_LIBRARIES}
|
||||
)
|
||||
|
||||
if(ENABLE_APP)
|
||||
@@ -163,45 +167,45 @@ if(ENABLE_APP)
|
||||
target_link_libraries(nghttpx_static neverbleed)
|
||||
endif()
|
||||
|
||||
|
||||
if(HAVE_CUNIT)
|
||||
set(NGHTTPX_UNITTEST_SOURCES
|
||||
shrpx-unittest.cc
|
||||
shrpx_tls_test.cc
|
||||
shrpx_downstream_test.cc
|
||||
shrpx_config_test.cc
|
||||
shrpx_worker_test.cc
|
||||
shrpx_http_test.cc
|
||||
shrpx_router_test.cc
|
||||
http2_test.cc
|
||||
util_test.cc
|
||||
nghttp2_gzip_test.c
|
||||
nghttp2_gzip.c
|
||||
buffer_test.cc
|
||||
memchunk_test.cc
|
||||
template_test.cc
|
||||
base64_test.cc
|
||||
set(NGHTTPX_UNITTEST_SOURCES
|
||||
shrpx-unittest.cc
|
||||
shrpx_tls_test.cc
|
||||
shrpx_downstream_test.cc
|
||||
shrpx_config_test.cc
|
||||
shrpx_worker_test.cc
|
||||
shrpx_http_test.cc
|
||||
shrpx_router_test.cc
|
||||
http2_test.cc
|
||||
util_test.cc
|
||||
nghttp2_gzip_test.c
|
||||
nghttp2_gzip.c
|
||||
buffer_test.cc
|
||||
memchunk_test.cc
|
||||
template_test.cc
|
||||
base64_test.cc
|
||||
${CMAKE_SOURCE_DIR}/tests/munit/munit.c
|
||||
)
|
||||
add_executable(nghttpx-unittest EXCLUDE_FROM_ALL
|
||||
${NGHTTPX_UNITTEST_SOURCES}
|
||||
$<TARGET_OBJECTS:llhttp>
|
||||
$<TARGET_OBJECTS:url-parser>
|
||||
)
|
||||
add_executable(nghttpx-unittest EXCLUDE_FROM_ALL
|
||||
${NGHTTPX_UNITTEST_SOURCES}
|
||||
$<TARGET_OBJECTS:llhttp>
|
||||
$<TARGET_OBJECTS:url-parser>
|
||||
)
|
||||
target_include_directories(nghttpx-unittest PRIVATE ${CUNIT_INCLUDE_DIRS})
|
||||
target_compile_definitions(nghttpx-unittest
|
||||
PRIVATE "-DNGHTTP2_SRC_DIR=\"${CMAKE_SOURCE_DIR}/src\""
|
||||
)
|
||||
target_link_libraries(nghttpx-unittest nghttpx_static ${CUNIT_LIBRARIES})
|
||||
if(HAVE_MRUBY)
|
||||
target_link_libraries(nghttpx-unittest mruby-lib)
|
||||
endif()
|
||||
if(HAVE_NEVERBLEED)
|
||||
target_link_libraries(nghttpx-unittest neverbleed)
|
||||
endif()
|
||||
|
||||
add_test(nghttpx-unittest nghttpx-unittest)
|
||||
add_dependencies(check nghttpx-unittest)
|
||||
target_include_directories(nghttpx-unittest PRIVATE
|
||||
${CMAKE_SOURCE_DIR}/tests/munit
|
||||
)
|
||||
target_compile_definitions(nghttpx-unittest
|
||||
PRIVATE "-DNGHTTP2_SRC_DIR=\"${CMAKE_SOURCE_DIR}/src\""
|
||||
)
|
||||
target_link_libraries(nghttpx-unittest nghttpx_static)
|
||||
if(HAVE_MRUBY)
|
||||
target_link_libraries(nghttpx-unittest mruby-lib)
|
||||
endif()
|
||||
if(HAVE_NEVERBLEED)
|
||||
target_link_libraries(nghttpx-unittest neverbleed)
|
||||
endif()
|
||||
|
||||
add_test(nghttpx-unittest nghttpx-unittest)
|
||||
add_dependencies(check nghttpx-unittest)
|
||||
|
||||
add_executable(nghttp ${NGHTTP_SOURCES} $<TARGET_OBJECTS:llhttp>
|
||||
$<TARGET_OBJECTS:url-parser>
|
||||
@@ -221,8 +225,7 @@ if(ENABLE_APP)
|
||||
$<TARGET_OBJECTS:url-parser>
|
||||
)
|
||||
|
||||
install(TARGETS nghttp nghttpd nghttpx h2load
|
||||
RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}")
|
||||
install(TARGETS nghttp nghttpd nghttpx h2load)
|
||||
endif()
|
||||
|
||||
if(ENABLE_HPACK_TOOLS)
|
||||
@@ -238,6 +241,5 @@ if(ENABLE_HPACK_TOOLS)
|
||||
)
|
||||
add_executable(inflatehd ${inflatehd_SOURCES})
|
||||
add_executable(deflatehd ${deflatehd_SOURCES})
|
||||
install(TARGETS inflatehd deflatehd
|
||||
RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}")
|
||||
install(TARGETS inflatehd deflatehd)
|
||||
endif()
|
||||
|
||||
@@ -607,10 +607,10 @@ int Http2Handler::fill_wb() {
|
||||
|
||||
for (;;) {
|
||||
const uint8_t *data;
|
||||
auto datalen = nghttp2_session_mem_send(session_, &data);
|
||||
auto datalen = nghttp2_session_mem_send2(session_, &data);
|
||||
|
||||
if (datalen < 0) {
|
||||
std::cerr << "nghttp2_session_mem_send() returned error: "
|
||||
std::cerr << "nghttp2_session_mem_send2() returned error: "
|
||||
<< nghttp2_strerror(datalen) << std::endl;
|
||||
return -1;
|
||||
}
|
||||
@@ -648,10 +648,10 @@ int Http2Handler::read_clear() {
|
||||
util::hexdump(stdout, buf.data(), nread);
|
||||
}
|
||||
|
||||
rv = nghttp2_session_mem_recv(session_, buf.data(), nread);
|
||||
rv = nghttp2_session_mem_recv2(session_, buf.data(), nread);
|
||||
if (rv < 0) {
|
||||
if (rv != NGHTTP2_ERR_BAD_CLIENT_MAGIC) {
|
||||
std::cerr << "nghttp2_session_mem_recv() returned error: "
|
||||
std::cerr << "nghttp2_session_mem_recv2() returned error: "
|
||||
<< nghttp2_strerror(rv) << std::endl;
|
||||
}
|
||||
return -1;
|
||||
@@ -771,10 +771,10 @@ int Http2Handler::read_tls() {
|
||||
util::hexdump(stdout, buf.data(), nread);
|
||||
}
|
||||
|
||||
rv = nghttp2_session_mem_recv(session_, buf.data(), nread);
|
||||
rv = nghttp2_session_mem_recv2(session_, buf.data(), nread);
|
||||
if (rv < 0) {
|
||||
if (rv != NGHTTP2_ERR_BAD_CLIENT_MAGIC) {
|
||||
std::cerr << "nghttp2_session_mem_recv() returned error: "
|
||||
std::cerr << "nghttp2_session_mem_recv2() returned error: "
|
||||
<< nghttp2_strerror(rv) << std::endl;
|
||||
}
|
||||
return -1;
|
||||
@@ -917,7 +917,7 @@ int Http2Handler::verify_alpn_result() {
|
||||
int Http2Handler::submit_file_response(const StringRef &status, Stream *stream,
|
||||
time_t last_modified, off_t file_length,
|
||||
const std::string *content_type,
|
||||
nghttp2_data_provider *data_prd) {
|
||||
nghttp2_data_provider2 *data_prd) {
|
||||
std::string last_modified_str;
|
||||
auto nva = make_array(http2::make_nv_ls_nocopy(":status", status),
|
||||
http2::make_nv_ls_nocopy("server", NGHTTPD_SERVER),
|
||||
@@ -942,13 +942,13 @@ int Http2Handler::submit_file_response(const StringRef &status, Stream *stream,
|
||||
if (!trailer_names.empty()) {
|
||||
nva[nvlen++] = http2::make_nv_ls_nocopy("trailer", trailer_names);
|
||||
}
|
||||
return nghttp2_submit_response(session_, stream->stream_id, nva.data(), nvlen,
|
||||
data_prd);
|
||||
return nghttp2_submit_response2(session_, stream->stream_id, nva.data(),
|
||||
nvlen, data_prd);
|
||||
}
|
||||
|
||||
int Http2Handler::submit_response(const StringRef &status, int32_t stream_id,
|
||||
const HeaderRefs &headers,
|
||||
nghttp2_data_provider *data_prd) {
|
||||
nghttp2_data_provider2 *data_prd) {
|
||||
auto nva = std::vector<nghttp2_nv>();
|
||||
nva.reserve(4 + headers.size());
|
||||
nva.push_back(http2::make_nv_ls_nocopy(":status", status));
|
||||
@@ -965,13 +965,13 @@ int Http2Handler::submit_response(const StringRef &status, int32_t stream_id,
|
||||
for (auto &nv : headers) {
|
||||
nva.push_back(http2::make_nv_nocopy(nv.name, nv.value, nv.no_index));
|
||||
}
|
||||
int r = nghttp2_submit_response(session_, stream_id, nva.data(), nva.size(),
|
||||
data_prd);
|
||||
int r = nghttp2_submit_response2(session_, stream_id, nva.data(), nva.size(),
|
||||
data_prd);
|
||||
return r;
|
||||
}
|
||||
|
||||
int Http2Handler::submit_response(const StringRef &status, int32_t stream_id,
|
||||
nghttp2_data_provider *data_prd) {
|
||||
nghttp2_data_provider2 *data_prd) {
|
||||
auto nva = make_array(http2::make_nv_ls_nocopy(":status", status),
|
||||
http2::make_nv_ls_nocopy("server", NGHTTPD_SERVER),
|
||||
http2::make_nv_ls("date", sessions_->get_cached_date()),
|
||||
@@ -985,8 +985,8 @@ int Http2Handler::submit_response(const StringRef &status, int32_t stream_id,
|
||||
}
|
||||
}
|
||||
|
||||
return nghttp2_submit_response(session_, stream_id, nva.data(), nvlen,
|
||||
data_prd);
|
||||
return nghttp2_submit_response2(session_, stream_id, nva.data(), nvlen,
|
||||
data_prd);
|
||||
}
|
||||
|
||||
int Http2Handler::submit_non_final_response(const std::string &status,
|
||||
@@ -1076,9 +1076,10 @@ void Http2Handler::terminate_session(uint32_t error_code) {
|
||||
nghttp2_session_terminate_session(session_, error_code);
|
||||
}
|
||||
|
||||
ssize_t file_read_callback(nghttp2_session *session, int32_t stream_id,
|
||||
uint8_t *buf, size_t length, uint32_t *data_flags,
|
||||
nghttp2_data_source *source, void *user_data) {
|
||||
nghttp2_ssize file_read_callback(nghttp2_session *session, int32_t stream_id,
|
||||
uint8_t *buf, size_t length,
|
||||
uint32_t *data_flags,
|
||||
nghttp2_data_source *source, void *user_data) {
|
||||
int rv;
|
||||
auto hd = static_cast<Http2Handler *>(user_data);
|
||||
auto stream = hd->get_stream(stream_id);
|
||||
@@ -1127,7 +1128,7 @@ void prepare_status_response(Stream *stream, Http2Handler *hd, int status) {
|
||||
|
||||
// we don't set stream->file_ent since we don't want to expire it.
|
||||
stream->body_length = file_ent->length;
|
||||
nghttp2_data_provider data_prd;
|
||||
nghttp2_data_provider2 data_prd;
|
||||
data_prd.source.fd = file_ent->fd;
|
||||
data_prd.read_callback = file_read_callback;
|
||||
|
||||
@@ -1155,7 +1156,7 @@ void prepare_echo_response(Stream *stream, Http2Handler *hd) {
|
||||
hd->submit_rst_stream(stream, NGHTTP2_INTERNAL_ERROR);
|
||||
return;
|
||||
}
|
||||
nghttp2_data_provider data_prd;
|
||||
nghttp2_data_provider2 data_prd;
|
||||
data_prd.source.fd = stream->file_ent->fd;
|
||||
data_prd.read_callback = file_read_callback;
|
||||
|
||||
@@ -1378,7 +1379,7 @@ void prepare_response(Stream *stream, Http2Handler *hd,
|
||||
|
||||
stream->body_length = file_ent->length;
|
||||
|
||||
nghttp2_data_provider data_prd;
|
||||
nghttp2_data_provider2 data_prd;
|
||||
|
||||
data_prd.source.fd = file_ent->fd;
|
||||
data_prd.read_callback = file_read_callback;
|
||||
@@ -1676,9 +1677,9 @@ int send_data_callback(nghttp2_session *session, nghttp2_frame *frame,
|
||||
} // namespace
|
||||
|
||||
namespace {
|
||||
ssize_t select_padding_callback(nghttp2_session *session,
|
||||
const nghttp2_frame *frame, size_t max_payload,
|
||||
void *user_data) {
|
||||
nghttp2_ssize select_padding_callback(nghttp2_session *session,
|
||||
const nghttp2_frame *frame,
|
||||
size_t max_payload, void *user_data) {
|
||||
auto hd = static_cast<Http2Handler *>(user_data);
|
||||
return std::min(max_payload, frame->hd.length + hd->get_config()->padding);
|
||||
}
|
||||
@@ -1765,7 +1766,7 @@ void fill_callback(nghttp2_session_callbacks *callbacks, const Config *config) {
|
||||
send_data_callback);
|
||||
|
||||
if (config->padding) {
|
||||
nghttp2_session_callbacks_set_select_padding_callback(
|
||||
nghttp2_session_callbacks_set_select_padding_callback2(
|
||||
callbacks, select_padding_callback);
|
||||
}
|
||||
}
|
||||
@@ -2205,6 +2206,15 @@ int HttpServer::run() {
|
||||
|
||||
// ALPN selection callback
|
||||
SSL_CTX_set_alpn_select_cb(ssl_ctx, alpn_select_proto_cb, this);
|
||||
|
||||
#if defined(NGHTTP2_OPENSSL_IS_BORINGSSL) && defined(HAVE_LIBBROTLI)
|
||||
if (!SSL_CTX_add_cert_compression_alg(
|
||||
ssl_ctx, nghttp2::tls::CERTIFICATE_COMPRESSION_ALGO_BROTLI,
|
||||
nghttp2::tls::cert_compress, nghttp2::tls::cert_decompress)) {
|
||||
std::cerr << "SSL_CTX_add_cert_compression_alg failed." << std::endl;
|
||||
return -1;
|
||||
}
|
||||
#endif // NGHTTP2_OPENSSL_IS_BORINGSSL && HAVE_LIBBROTLI
|
||||
}
|
||||
|
||||
auto loop = EV_DEFAULT;
|
||||
|
||||
@@ -41,6 +41,7 @@
|
||||
|
||||
#include <ev.h>
|
||||
|
||||
#define NGHTTP2_NO_SSIZE_T
|
||||
#include <nghttp2/nghttp2.h>
|
||||
|
||||
#include "http2.h"
|
||||
@@ -172,14 +173,14 @@ public:
|
||||
int submit_file_response(const StringRef &status, Stream *stream,
|
||||
time_t last_modified, off_t file_length,
|
||||
const std::string *content_type,
|
||||
nghttp2_data_provider *data_prd);
|
||||
nghttp2_data_provider2 *data_prd);
|
||||
|
||||
int submit_response(const StringRef &status, int32_t stream_id,
|
||||
nghttp2_data_provider *data_prd);
|
||||
nghttp2_data_provider2 *data_prd);
|
||||
|
||||
int submit_response(const StringRef &status, int32_t stream_id,
|
||||
const HeaderRefs &headers,
|
||||
nghttp2_data_provider *data_prd);
|
||||
nghttp2_data_provider2 *data_prd);
|
||||
|
||||
int submit_non_final_response(const std::string &status, int32_t stream_id);
|
||||
|
||||
|
||||
@@ -53,6 +53,8 @@ AM_CPPFLAGS = \
|
||||
@JANSSON_CFLAGS@ \
|
||||
@LIBBPF_CFLAGS@ \
|
||||
@ZLIB_CFLAGS@ \
|
||||
@LIBBROTLIENC_CFLAGS@ \
|
||||
@LIBBROTLIDEC_CFLAGS@ \
|
||||
@EXTRA_DEFS@ \
|
||||
@DEFS@
|
||||
AM_LDFLAGS = @LIBTOOL_LDFLAGS@
|
||||
@@ -73,6 +75,8 @@ LDADD = $(top_builddir)/lib/libnghttp2.la \
|
||||
@JANSSON_LIBS@ \
|
||||
@LIBBPF_LIBS@ \
|
||||
@ZLIB_LIBS@ \
|
||||
@LIBBROTLIENC_LIBS@ \
|
||||
@LIBBROTLIDEC_LIBS@ \
|
||||
@APPLDFLAGS@
|
||||
|
||||
if ENABLE_APP
|
||||
@@ -203,7 +207,6 @@ libnghttpx_a_CPPFLAGS += -I${top_srcdir}/third-party/neverbleed
|
||||
nghttpx_LDADD += ${top_builddir}/third-party/libneverbleed.la
|
||||
endif # HAVE_NEVERBLEED
|
||||
|
||||
if HAVE_CUNIT
|
||||
check_PROGRAMS += nghttpx-unittest
|
||||
nghttpx_unittest_SOURCES = shrpx-unittest.cc \
|
||||
shrpx_tls_test.cc shrpx_tls_test.h \
|
||||
@@ -219,10 +222,13 @@ nghttpx_unittest_SOURCES = shrpx-unittest.cc \
|
||||
buffer_test.cc buffer_test.h \
|
||||
memchunk_test.cc memchunk_test.h \
|
||||
template_test.cc template_test.h \
|
||||
base64_test.cc base64_test.h
|
||||
base64_test.cc base64_test.h \
|
||||
$(top_srcdir)/tests/munit/munit.c $(top_srcdir)/tests/munit/munit.h \
|
||||
$(top_srcdir)/tests/munit/munitxx.h
|
||||
nghttpx_unittest_CPPFLAGS = ${AM_CPPFLAGS} \
|
||||
-I$(top_srcdir)/tests/munit \
|
||||
-DNGHTTP2_SRC_DIR=\"$(top_srcdir)/src\"
|
||||
nghttpx_unittest_LDADD = libnghttpx.a ${LDADD} @CUNIT_LIBS@ @TESTLDADD@
|
||||
nghttpx_unittest_LDADD = libnghttpx.a ${LDADD} @TESTLDADD@
|
||||
|
||||
if HAVE_MRUBY
|
||||
nghttpx_unittest_CPPFLAGS += \
|
||||
@@ -237,7 +243,6 @@ nghttpx_unittest_LDADD += ${top_builddir}/third-party/libneverbleed.la
|
||||
endif # HAVE_NEVERBLEED
|
||||
|
||||
TESTS += nghttpx-unittest
|
||||
endif # HAVE_CUNIT
|
||||
|
||||
endif # ENABLE_APP
|
||||
|
||||
|
||||
@@ -119,7 +119,7 @@ struct BlockAllocator {
|
||||
}
|
||||
|
||||
if (!head ||
|
||||
head->end - head->last < static_cast<ssize_t>(size + sizeof(size_t))) {
|
||||
static_cast<size_t>(head->end - head->last) < size + sizeof(size_t)) {
|
||||
head = alloc_mem_block(block_size);
|
||||
}
|
||||
|
||||
|
||||
@@ -53,8 +53,6 @@
|
||||
#include <iomanip>
|
||||
#include <fstream>
|
||||
|
||||
#include <zlib.h>
|
||||
|
||||
#include "app_helper.h"
|
||||
#include "util.h"
|
||||
#include "http2.h"
|
||||
@@ -477,42 +475,4 @@ std::chrono::steady_clock::time_point get_time() {
|
||||
return std::chrono::steady_clock::now();
|
||||
}
|
||||
|
||||
ssize_t deflate_data(uint8_t *out, size_t outlen, const uint8_t *in,
|
||||
size_t inlen) {
|
||||
int rv;
|
||||
z_stream zst{};
|
||||
uint8_t temp_out[8_k];
|
||||
auto temp_outlen = sizeof(temp_out);
|
||||
|
||||
rv = deflateInit2(&zst, Z_DEFAULT_COMPRESSION, Z_DEFLATED, 31, 9,
|
||||
Z_DEFAULT_STRATEGY);
|
||||
|
||||
if (rv != Z_OK) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
zst.avail_in = inlen;
|
||||
zst.next_in = (uint8_t *)in;
|
||||
zst.avail_out = temp_outlen;
|
||||
zst.next_out = temp_out;
|
||||
|
||||
rv = deflate(&zst, Z_FINISH);
|
||||
|
||||
deflateEnd(&zst);
|
||||
|
||||
if (rv != Z_STREAM_END) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
temp_outlen -= zst.avail_out;
|
||||
|
||||
if (temp_outlen > outlen) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
memcpy(out, temp_out, temp_outlen);
|
||||
|
||||
return temp_outlen;
|
||||
}
|
||||
|
||||
} // namespace nghttp2
|
||||
|
||||
@@ -90,9 +90,6 @@ void set_color_output(bool f);
|
||||
// used.
|
||||
void set_output(FILE *file);
|
||||
|
||||
ssize_t deflate_data(uint8_t *out, size_t outlen, const uint8_t *in,
|
||||
size_t inlen);
|
||||
|
||||
} // namespace nghttp2
|
||||
|
||||
#endif // APP_HELPER_H
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
#include <cstring>
|
||||
#include <iostream>
|
||||
|
||||
#include <CUnit/CUnit.h>
|
||||
#include "munitxx.h"
|
||||
|
||||
#include <nghttp2/nghttp2.h>
|
||||
|
||||
@@ -35,26 +35,38 @@
|
||||
|
||||
namespace nghttp2 {
|
||||
|
||||
namespace {
|
||||
const MunitTest tests[]{
|
||||
munit_void_test(test_base64_encode),
|
||||
munit_void_test(test_base64_decode),
|
||||
munit_test_end(),
|
||||
};
|
||||
} // namespace
|
||||
|
||||
const MunitSuite base64_suite{
|
||||
"/base64", tests, NULL, 1, MUNIT_SUITE_OPTION_NONE,
|
||||
};
|
||||
|
||||
void test_base64_encode(void) {
|
||||
{
|
||||
std::string in = "\xff";
|
||||
auto out = base64::encode(std::begin(in), std::end(in));
|
||||
CU_ASSERT("/w==" == out);
|
||||
assert_stdstring_equal("/w==", out);
|
||||
}
|
||||
{
|
||||
std::string in = "\xff\xfe";
|
||||
auto out = base64::encode(std::begin(in), std::end(in));
|
||||
CU_ASSERT("//4=" == out);
|
||||
assert_stdstring_equal("//4=", out);
|
||||
}
|
||||
{
|
||||
std::string in = "\xff\xfe\xfd";
|
||||
auto out = base64::encode(std::begin(in), std::end(in));
|
||||
CU_ASSERT("//79" == out);
|
||||
assert_stdstring_equal("//79", out);
|
||||
}
|
||||
{
|
||||
std::string in = "\xff\xfe\xfd\xfc";
|
||||
auto out = base64::encode(std::begin(in), std::end(in));
|
||||
CU_ASSERT("//79/A==" == out);
|
||||
assert_stdstring_equal("//79/A==", out);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,58 +75,65 @@ void test_base64_decode(void) {
|
||||
{
|
||||
std::string in = "/w==";
|
||||
auto out = base64::decode(std::begin(in), std::end(in));
|
||||
CU_ASSERT("\xff" == out);
|
||||
CU_ASSERT("\xff" == base64::decode(balloc, std::begin(in), std::end(in)));
|
||||
assert_stdstring_equal("\xff", out);
|
||||
assert_stdstring_equal(
|
||||
"\xff", base64::decode(balloc, std::begin(in), std::end(in)).str());
|
||||
}
|
||||
{
|
||||
std::string in = "//4=";
|
||||
auto out = base64::decode(std::begin(in), std::end(in));
|
||||
CU_ASSERT("\xff\xfe" == out);
|
||||
CU_ASSERT("\xff\xfe" ==
|
||||
base64::decode(balloc, std::begin(in), std::end(in)));
|
||||
assert_stdstring_equal("\xff\xfe", out);
|
||||
assert_stdstring_equal(
|
||||
"\xff\xfe", base64::decode(balloc, std::begin(in), std::end(in)).str());
|
||||
}
|
||||
{
|
||||
std::string in = "//79";
|
||||
auto out = base64::decode(std::begin(in), std::end(in));
|
||||
CU_ASSERT("\xff\xfe\xfd" == out);
|
||||
CU_ASSERT("\xff\xfe\xfd" ==
|
||||
base64::decode(balloc, std::begin(in), std::end(in)));
|
||||
assert_stdstring_equal("\xff\xfe\xfd", out);
|
||||
assert_stdstring_equal(
|
||||
"\xff\xfe\xfd",
|
||||
base64::decode(balloc, std::begin(in), std::end(in)).str());
|
||||
}
|
||||
{
|
||||
std::string in = "//79/A==";
|
||||
auto out = base64::decode(std::begin(in), std::end(in));
|
||||
CU_ASSERT("\xff\xfe\xfd\xfc" == out);
|
||||
CU_ASSERT("\xff\xfe\xfd\xfc" ==
|
||||
base64::decode(balloc, std::begin(in), std::end(in)));
|
||||
assert_stdstring_equal("\xff\xfe\xfd\xfc", out);
|
||||
assert_stdstring_equal(
|
||||
"\xff\xfe\xfd\xfc",
|
||||
base64::decode(balloc, std::begin(in), std::end(in)).str());
|
||||
}
|
||||
{
|
||||
// we check the number of valid input must be multiples of 4
|
||||
std::string in = "//79=";
|
||||
auto out = base64::decode(std::begin(in), std::end(in));
|
||||
CU_ASSERT("" == out);
|
||||
CU_ASSERT("" == base64::decode(balloc, std::begin(in), std::end(in)));
|
||||
assert_stdstring_equal("", out);
|
||||
assert_stdstring_equal(
|
||||
"", base64::decode(balloc, std::begin(in), std::end(in)).str());
|
||||
}
|
||||
{
|
||||
// ending invalid character at the boundary of multiples of 4 is
|
||||
// bad
|
||||
std::string in = "bmdodHRw\n";
|
||||
auto out = base64::decode(std::begin(in), std::end(in));
|
||||
CU_ASSERT("" == out);
|
||||
CU_ASSERT("" == base64::decode(balloc, std::begin(in), std::end(in)));
|
||||
assert_stdstring_equal("", out);
|
||||
assert_stdstring_equal(
|
||||
"", base64::decode(balloc, std::begin(in), std::end(in)).str());
|
||||
}
|
||||
{
|
||||
// after seeing '=', subsequent input must be also '='.
|
||||
std::string in = "//79/A=A";
|
||||
auto out = base64::decode(std::begin(in), std::end(in));
|
||||
CU_ASSERT("" == out);
|
||||
CU_ASSERT("" == base64::decode(balloc, std::begin(in), std::end(in)));
|
||||
assert_stdstring_equal("", out);
|
||||
assert_stdstring_equal(
|
||||
"", base64::decode(balloc, std::begin(in), std::end(in)).str());
|
||||
}
|
||||
{
|
||||
// additional '=' at the end is bad
|
||||
std::string in = "//79/A======";
|
||||
auto out = base64::decode(std::begin(in), std::end(in));
|
||||
CU_ASSERT("" == out);
|
||||
CU_ASSERT("" == base64::decode(balloc, std::begin(in), std::end(in)));
|
||||
assert_stdstring_equal("", out);
|
||||
assert_stdstring_equal(
|
||||
"", base64::decode(balloc, std::begin(in), std::end(in)).str());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -29,10 +29,16 @@
|
||||
# include <config.h>
|
||||
#endif // HAVE_CONFIG_H
|
||||
|
||||
#define MUNIT_ENABLE_ASSERT_ALIASES
|
||||
|
||||
#include "munit.h"
|
||||
|
||||
namespace nghttp2 {
|
||||
|
||||
void test_base64_encode(void);
|
||||
void test_base64_decode(void);
|
||||
extern const MunitSuite base64_suite;
|
||||
|
||||
munit_void_test_decl(test_base64_encode);
|
||||
munit_void_test_decl(test_base64_decode);
|
||||
|
||||
} // namespace nghttp2
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
#include <iostream>
|
||||
#include <tuple>
|
||||
|
||||
#include <CUnit/CUnit.h>
|
||||
#include "munitxx.h"
|
||||
|
||||
#include <nghttp2/nghttp2.h>
|
||||
|
||||
@@ -36,43 +36,54 @@
|
||||
|
||||
namespace nghttp2 {
|
||||
|
||||
namespace {
|
||||
const MunitTest tests[]{
|
||||
munit_void_test(test_buffer_write),
|
||||
munit_test_end(),
|
||||
};
|
||||
} // namespace
|
||||
|
||||
const MunitSuite buffer_suite{
|
||||
"/buffer", tests, NULL, 1, MUNIT_SUITE_OPTION_NONE,
|
||||
};
|
||||
|
||||
void test_buffer_write(void) {
|
||||
Buffer<16> b;
|
||||
CU_ASSERT(0 == b.rleft());
|
||||
CU_ASSERT(16 == b.wleft());
|
||||
assert_size(0, ==, b.rleft());
|
||||
assert_size(16, ==, b.wleft());
|
||||
|
||||
b.write("012", 3);
|
||||
|
||||
CU_ASSERT(3 == b.rleft());
|
||||
CU_ASSERT(13 == b.wleft());
|
||||
CU_ASSERT(b.pos == std::begin(b.buf));
|
||||
assert_size(3, ==, b.rleft());
|
||||
assert_size(13, ==, b.wleft());
|
||||
assert_ptr_equal(b.pos, std::begin(b.buf));
|
||||
|
||||
b.drain(3);
|
||||
|
||||
CU_ASSERT(0 == b.rleft());
|
||||
CU_ASSERT(13 == b.wleft());
|
||||
CU_ASSERT(3 == b.pos - std::begin(b.buf));
|
||||
assert_size(0, ==, b.rleft());
|
||||
assert_size(13, ==, b.wleft());
|
||||
assert_ptrdiff(3, ==, b.pos - std::begin(b.buf));
|
||||
|
||||
auto n = b.write("0123456789ABCDEF", 16);
|
||||
|
||||
CU_ASSERT(n == 13);
|
||||
assert_ssize(13, ==, n);
|
||||
|
||||
CU_ASSERT(13 == b.rleft());
|
||||
CU_ASSERT(0 == b.wleft());
|
||||
CU_ASSERT(3 == b.pos - std::begin(b.buf));
|
||||
CU_ASSERT(0 == memcmp(b.pos, "0123456789ABC", 13));
|
||||
assert_size(13, ==, b.rleft());
|
||||
assert_size(0, ==, b.wleft());
|
||||
assert_ptrdiff(3, ==, b.pos - std::begin(b.buf));
|
||||
assert_memory_equal(13, b.pos, "0123456789ABC");
|
||||
|
||||
b.reset();
|
||||
|
||||
CU_ASSERT(0 == b.rleft());
|
||||
CU_ASSERT(16 == b.wleft());
|
||||
CU_ASSERT(b.pos == std::begin(b.buf));
|
||||
assert_size(0, ==, b.rleft());
|
||||
assert_size(16, ==, b.wleft());
|
||||
assert_ptr_equal(b.pos, std::begin(b.buf));
|
||||
|
||||
b.write(5);
|
||||
|
||||
CU_ASSERT(5 == b.rleft());
|
||||
CU_ASSERT(11 == b.wleft());
|
||||
CU_ASSERT(b.pos == std::begin(b.buf));
|
||||
assert_size(5, ==, b.rleft());
|
||||
assert_size(11, ==, b.wleft());
|
||||
assert_ptr_equal(b.pos, std::begin(b.buf));
|
||||
}
|
||||
|
||||
} // namespace nghttp2
|
||||
|
||||
@@ -29,9 +29,15 @@
|
||||
# include <config.h>
|
||||
#endif // HAVE_CONFIG_H
|
||||
|
||||
#define MUNIT_ENABLE_ASSERT_ALIASES
|
||||
|
||||
#include "munit.h"
|
||||
|
||||
namespace nghttp2 {
|
||||
|
||||
void test_buffer_write(void);
|
||||
extern const MunitSuite buffer_suite;
|
||||
|
||||
munit_void_test_decl(test_buffer_write);
|
||||
|
||||
} // namespace nghttp2
|
||||
|
||||
|
||||
@@ -41,6 +41,7 @@
|
||||
|
||||
#include <jansson.h>
|
||||
|
||||
#define NGHTTP2_NO_SSIZE_T
|
||||
#include <nghttp2/nghttp2.h>
|
||||
|
||||
#include "template.h"
|
||||
@@ -113,11 +114,10 @@ static void output_to_json(nghttp2_hd_deflater *deflater, const uint8_t *buf,
|
||||
static void deflate_hd(nghttp2_hd_deflater *deflater,
|
||||
const std::vector<nghttp2_nv> &nva, size_t inputlen,
|
||||
int seq) {
|
||||
ssize_t rv;
|
||||
std::array<uint8_t, 64_k> buf;
|
||||
|
||||
rv = nghttp2_hd_deflate_hd(deflater, buf.data(), buf.size(),
|
||||
(nghttp2_nv *)nva.data(), nva.size());
|
||||
auto rv = nghttp2_hd_deflate_hd2(deflater, buf.data(), buf.size(),
|
||||
(nghttp2_nv *)nva.data(), nva.size());
|
||||
if (rv < 0) {
|
||||
fprintf(stderr, "deflate failed with error code %zd at %d\n", rv, seq);
|
||||
exit(EXIT_FAILURE);
|
||||
|
||||
@@ -410,7 +410,7 @@ namespace {
|
||||
void client_request_timeout_cb(struct ev_loop *loop, ev_timer *w, int revents) {
|
||||
auto client = static_cast<Client *>(w->data);
|
||||
|
||||
if (client->streams.size() >= (size_t)config.max_concurrent_streams) {
|
||||
if (client->streams.size() >= config.max_concurrent_streams) {
|
||||
ev_timer_stop(client->worker->loop, w);
|
||||
return;
|
||||
}
|
||||
@@ -582,8 +582,12 @@ int Client::make_socket(addrinfo *addr) {
|
||||
}
|
||||
}
|
||||
|
||||
if (ssl && !util::numeric_host(config.host.c_str())) {
|
||||
SSL_set_tlsext_host_name(ssl, config.host.c_str());
|
||||
if (ssl) {
|
||||
if (!config.sni.empty()) {
|
||||
SSL_set_tlsext_host_name(ssl, config.sni.c_str());
|
||||
} else if (!util::numeric_host(config.host.c_str())) {
|
||||
SSL_set_tlsext_host_name(ssl, config.host.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
if (config.is_quic()) {
|
||||
@@ -2301,6 +2305,9 @@ Options:
|
||||
--max-udp-payload-size=<SIZE>
|
||||
Specify the maximum outgoing UDP datagram payload size.
|
||||
--ktls Enable ktls.
|
||||
--sni=<DNSNAME>
|
||||
Send <DNSNAME> in TLS SNI, overriding the host name
|
||||
specified in URI.
|
||||
-v, --verbose
|
||||
Output debug information.
|
||||
--version Display version information and exit.
|
||||
@@ -2363,6 +2370,7 @@ int main(int argc, char **argv) {
|
||||
{"max-udp-payload-size", required_argument, &flag, 17},
|
||||
{"ktls", no_argument, &flag, 18},
|
||||
{"alpn-list", required_argument, &flag, 19},
|
||||
{"sni", required_argument, &flag, 20},
|
||||
{nullptr, 0, nullptr, 0}};
|
||||
int option_index = 0;
|
||||
auto c = getopt_long(argc, argv,
|
||||
@@ -2699,6 +2707,10 @@ int main(int argc, char **argv) {
|
||||
// alpn-list option
|
||||
config.alpn_list = util::parse_config_str_list(StringRef{optarg});
|
||||
break;
|
||||
case 20:
|
||||
// --sni
|
||||
config.sni = optarg;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@@ -2973,6 +2985,15 @@ int main(int argc, char **argv) {
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(NGHTTP2_OPENSSL_IS_BORINGSSL) && defined(HAVE_LIBBROTLI)
|
||||
if (!SSL_CTX_add_cert_compression_alg(
|
||||
ssl_ctx, nghttp2::tls::CERTIFICATE_COMPRESSION_ALGO_BROTLI,
|
||||
nghttp2::tls::cert_compress, nghttp2::tls::cert_decompress)) {
|
||||
std::cerr << "SSL_CTX_add_cert_compression_alg failed" << std::endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
#endif // NGHTTP2_OPENSSL_IS_BORINGSSL && HAVE_LIBBROTLI
|
||||
|
||||
std::string user_agent = "h2load nghttp2/" NGHTTP2_VERSION;
|
||||
Headers shared_nva;
|
||||
shared_nva.emplace_back(":scheme", config.scheme);
|
||||
@@ -3079,18 +3100,18 @@ int main(int argc, char **argv) {
|
||||
|
||||
#ifndef NOTHREADS
|
||||
size_t nreqs_per_thread = 0;
|
||||
ssize_t nreqs_rem = 0;
|
||||
size_t nreqs_rem = 0;
|
||||
|
||||
if (!config.timing_script) {
|
||||
nreqs_per_thread = config.nreqs / config.nthreads;
|
||||
nreqs_rem = config.nreqs % config.nthreads;
|
||||
}
|
||||
|
||||
size_t nclients_per_thread = config.nclients / config.nthreads;
|
||||
ssize_t nclients_rem = config.nclients % config.nthreads;
|
||||
auto nclients_per_thread = config.nclients / config.nthreads;
|
||||
auto nclients_rem = config.nclients % config.nthreads;
|
||||
|
||||
size_t rate_per_thread = config.rate / config.nthreads;
|
||||
ssize_t rate_per_thread_rem = config.rate % config.nthreads;
|
||||
auto rate_per_thread = config.rate / config.nthreads;
|
||||
auto rate_per_thread_rem = config.rate % config.nthreads;
|
||||
|
||||
size_t max_samples_per_thread =
|
||||
std::max(static_cast<size_t>(256), MAX_SAMPLES / config.nthreads);
|
||||
|
||||
@@ -43,6 +43,7 @@
|
||||
#include <chrono>
|
||||
#include <array>
|
||||
|
||||
#define NGHTTP2_NO_SSIZE_T
|
||||
#include <nghttp2/nghttp2.h>
|
||||
|
||||
#ifdef ENABLE_HTTP3
|
||||
@@ -92,7 +93,7 @@ struct Config {
|
||||
size_t nclients;
|
||||
size_t nthreads;
|
||||
// The maximum number of concurrent streams per session.
|
||||
ssize_t max_concurrent_streams;
|
||||
size_t max_concurrent_streams;
|
||||
size_t window_bits;
|
||||
size_t connection_window_bits;
|
||||
size_t max_frame_size;
|
||||
@@ -138,6 +139,9 @@ struct Config {
|
||||
size_t max_udp_payload_size;
|
||||
// Enable ktls.
|
||||
bool ktls;
|
||||
// sni is the value sent in TLS SNI, overriding DNS name of the
|
||||
// remote host.
|
||||
std::string sni;
|
||||
|
||||
Config();
|
||||
~Config();
|
||||
|
||||
@@ -124,9 +124,10 @@ int before_frame_send_callback(nghttp2_session *session,
|
||||
} // namespace
|
||||
|
||||
namespace {
|
||||
ssize_t file_read_callback(nghttp2_session *session, int32_t stream_id,
|
||||
uint8_t *buf, size_t length, uint32_t *data_flags,
|
||||
nghttp2_data_source *source, void *user_data) {
|
||||
nghttp2_ssize file_read_callback(nghttp2_session *session, int32_t stream_id,
|
||||
uint8_t *buf, size_t length,
|
||||
uint32_t *data_flags,
|
||||
nghttp2_data_source *source, void *user_data) {
|
||||
auto client = static_cast<Client *>(user_data);
|
||||
auto config = client->worker->config;
|
||||
auto req_stat = client->get_req_stat(stream_id);
|
||||
@@ -158,8 +159,8 @@ ssize_t file_read_callback(nghttp2_session *session, int32_t stream_id,
|
||||
} // namespace
|
||||
|
||||
namespace {
|
||||
ssize_t send_callback(nghttp2_session *session, const uint8_t *data,
|
||||
size_t length, int flags, void *user_data) {
|
||||
nghttp2_ssize send_callback(nghttp2_session *session, const uint8_t *data,
|
||||
size_t length, int flags, void *user_data) {
|
||||
auto client = static_cast<Client *>(user_data);
|
||||
auto &wb = client->wb;
|
||||
|
||||
@@ -198,7 +199,7 @@ void Http2Session::on_connect() {
|
||||
nghttp2_session_callbacks_set_before_frame_send_callback(
|
||||
callbacks, before_frame_send_callback);
|
||||
|
||||
nghttp2_session_callbacks_set_send_callback(callbacks, send_callback);
|
||||
nghttp2_session_callbacks_set_send_callback2(callbacks, send_callback);
|
||||
|
||||
nghttp2_option *opt;
|
||||
|
||||
@@ -257,11 +258,11 @@ int Http2Session::submit_request() {
|
||||
client_->reqidx = 0;
|
||||
}
|
||||
|
||||
nghttp2_data_provider prd{{0}, file_read_callback};
|
||||
nghttp2_data_provider2 prd{{0}, file_read_callback};
|
||||
|
||||
auto stream_id =
|
||||
nghttp2_submit_request(session_, nullptr, nva.data(), nva.size(),
|
||||
config->data_fd == -1 ? nullptr : &prd, nullptr);
|
||||
nghttp2_submit_request2(session_, nullptr, nva.data(), nva.size(),
|
||||
config->data_fd == -1 ? nullptr : &prd, nullptr);
|
||||
if (stream_id < 0) {
|
||||
return -1;
|
||||
}
|
||||
@@ -272,7 +273,7 @@ int Http2Session::submit_request() {
|
||||
}
|
||||
|
||||
int Http2Session::on_read(const uint8_t *data, size_t len) {
|
||||
auto rv = nghttp2_session_mem_recv(session_, data, len);
|
||||
auto rv = nghttp2_session_mem_recv2(session_, data, len);
|
||||
if (rv < 0) {
|
||||
return -1;
|
||||
}
|
||||
@@ -308,7 +309,7 @@ void Http2Session::terminate() {
|
||||
}
|
||||
|
||||
size_t Http2Session::max_concurrent_streams() {
|
||||
return (size_t)client_->worker->config->max_concurrent_streams;
|
||||
return client_->worker->config->max_concurrent_streams;
|
||||
}
|
||||
|
||||
} // namespace h2load
|
||||
|
||||
@@ -124,7 +124,7 @@ int Http3Session::on_write() { return -1; }
|
||||
void Http3Session::terminate() {}
|
||||
|
||||
size_t Http3Session::max_concurrent_streams() {
|
||||
return (size_t)client_->worker->config->max_concurrent_streams;
|
||||
return client_->worker->config->max_concurrent_streams;
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
@@ -654,7 +654,8 @@ int Client::write_quic() {
|
||||
ngtcp2_conn_get_path_max_tx_udp_payload_size(quic.conn);
|
||||
#endif // UDP_SEGMENT
|
||||
auto max_pktcnt =
|
||||
ngtcp2_conn_get_send_quantum(quic.conn) / max_udp_payload_size;
|
||||
std::max(ngtcp2_conn_get_send_quantum(quic.conn) / max_udp_payload_size,
|
||||
static_cast<size_t>(1));
|
||||
uint8_t *bufpos = quic.tx.data.get();
|
||||
ngtcp2_path_storage ps;
|
||||
size_t gso_size = 0;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -29,25 +29,31 @@
|
||||
# include <config.h>
|
||||
#endif // HAVE_CONFIG_H
|
||||
|
||||
#define MUNIT_ENABLE_ASSERT_ALIASES
|
||||
|
||||
#include "munit.h"
|
||||
|
||||
namespace shrpx {
|
||||
|
||||
void test_http2_add_header(void);
|
||||
void test_http2_get_header(void);
|
||||
void test_http2_copy_headers_to_nva(void);
|
||||
void test_http2_build_http1_headers_from_headers(void);
|
||||
void test_http2_lws(void);
|
||||
void test_http2_rewrite_location_uri(void);
|
||||
void test_http2_parse_http_status_code(void);
|
||||
void test_http2_index_header(void);
|
||||
void test_http2_lookup_token(void);
|
||||
void test_http2_parse_link_header(void);
|
||||
void test_http2_path_join(void);
|
||||
void test_http2_normalize_path(void);
|
||||
void test_http2_rewrite_clean_path(void);
|
||||
void test_http2_get_pure_path_component(void);
|
||||
void test_http2_construct_push_component(void);
|
||||
void test_http2_contains_trailers(void);
|
||||
void test_http2_check_transfer_encoding(void);
|
||||
extern const MunitSuite http2_suite;
|
||||
|
||||
munit_void_test_decl(test_http2_add_header);
|
||||
munit_void_test_decl(test_http2_get_header);
|
||||
munit_void_test_decl(test_http2_copy_headers_to_nva);
|
||||
munit_void_test_decl(test_http2_build_http1_headers_from_headers);
|
||||
munit_void_test_decl(test_http2_lws);
|
||||
munit_void_test_decl(test_http2_rewrite_location_uri);
|
||||
munit_void_test_decl(test_http2_parse_http_status_code);
|
||||
munit_void_test_decl(test_http2_index_header);
|
||||
munit_void_test_decl(test_http2_lookup_token);
|
||||
munit_void_test_decl(test_http2_parse_link_header);
|
||||
munit_void_test_decl(test_http2_path_join);
|
||||
munit_void_test_decl(test_http2_normalize_path);
|
||||
munit_void_test_decl(test_http2_rewrite_clean_path);
|
||||
munit_void_test_decl(test_http2_get_pure_path_component);
|
||||
munit_void_test_decl(test_http2_construct_push_component);
|
||||
munit_void_test_decl(test_http2_contains_trailers);
|
||||
munit_void_test_decl(test_http2_check_transfer_encoding);
|
||||
|
||||
} // namespace shrpx
|
||||
|
||||
|
||||
@@ -41,6 +41,7 @@
|
||||
|
||||
#include <jansson.h>
|
||||
|
||||
#define NGHTTP2_NO_SSIZE_T
|
||||
#include <nghttp2/nghttp2.h>
|
||||
|
||||
#include "template.h"
|
||||
@@ -93,7 +94,6 @@ static void to_json(nghttp2_hd_inflater *inflater, json_t *headers,
|
||||
}
|
||||
|
||||
static int inflate_hd(json_t *obj, nghttp2_hd_inflater *inflater, int seq) {
|
||||
ssize_t rv;
|
||||
nghttp2_nv nv;
|
||||
int inflate_flags;
|
||||
size_t old_settings_table_size =
|
||||
@@ -120,8 +120,8 @@ static int inflate_hd(json_t *obj, nghttp2_hd_inflater *inflater, int seq) {
|
||||
seq);
|
||||
return -1;
|
||||
}
|
||||
rv = nghttp2_hd_inflate_change_table_size(inflater,
|
||||
json_integer_value(table_size));
|
||||
auto rv = nghttp2_hd_inflate_change_table_size(
|
||||
inflater, json_integer_value(table_size));
|
||||
if (rv != 0) {
|
||||
fprintf(stderr,
|
||||
"nghttp2_hd_change_table_size() failed with error %s at %d\n",
|
||||
@@ -147,7 +147,8 @@ static int inflate_hd(json_t *obj, nghttp2_hd_inflater *inflater, int seq) {
|
||||
auto p = buf.data();
|
||||
for (;;) {
|
||||
inflate_flags = 0;
|
||||
rv = nghttp2_hd_inflate_hd(inflater, &nv, &inflate_flags, p, buflen, 1);
|
||||
auto rv =
|
||||
nghttp2_hd_inflate_hd3(inflater, &nv, &inflate_flags, p, buflen, 1);
|
||||
if (rv < 0) {
|
||||
fprintf(stderr, "inflate failed with error code %zd at %d\n", rv, seq);
|
||||
exit(EXIT_FAILURE);
|
||||
|
||||
@@ -1,162 +0,0 @@
|
||||
/*
|
||||
* nghttp2 - HTTP/2 C Library
|
||||
*
|
||||
* Copyright (c) 2014 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 "libevent_util.h"
|
||||
|
||||
#include <cstring>
|
||||
#include <algorithm>
|
||||
|
||||
namespace nghttp2 {
|
||||
|
||||
namespace util {
|
||||
|
||||
EvbufferBuffer::EvbufferBuffer()
|
||||
: evbuffer_(nullptr),
|
||||
bucket_(nullptr),
|
||||
buf_(nullptr),
|
||||
bufmax_(0),
|
||||
buflen_(0),
|
||||
limit_(0),
|
||||
writelen_(0) {}
|
||||
|
||||
EvbufferBuffer::EvbufferBuffer(evbuffer *evbuffer, uint8_t *buf, size_t bufmax,
|
||||
ssize_t limit)
|
||||
: evbuffer_(evbuffer),
|
||||
bucket_(limit == -1 ? nullptr : evbuffer_new()),
|
||||
buf_(buf),
|
||||
bufmax_(bufmax),
|
||||
buflen_(0),
|
||||
limit_(limit),
|
||||
writelen_(0) {}
|
||||
|
||||
void EvbufferBuffer::reset(evbuffer *evbuffer, uint8_t *buf, size_t bufmax,
|
||||
ssize_t limit) {
|
||||
evbuffer_ = evbuffer;
|
||||
buf_ = buf;
|
||||
if (limit != -1 && !bucket_) {
|
||||
bucket_ = evbuffer_new();
|
||||
}
|
||||
bufmax_ = bufmax;
|
||||
buflen_ = 0;
|
||||
limit_ = limit;
|
||||
writelen_ = 0;
|
||||
}
|
||||
|
||||
EvbufferBuffer::~EvbufferBuffer() {
|
||||
if (bucket_) {
|
||||
evbuffer_free(bucket_);
|
||||
}
|
||||
}
|
||||
|
||||
int EvbufferBuffer::write_buffer() {
|
||||
for (auto pos = buf_, end = buf_ + buflen_; pos < end;) {
|
||||
// To avoid merging chunks in evbuffer, we first add to temporal
|
||||
// buffer bucket_ and then move its chain to evbuffer_.
|
||||
auto nwrite = std::min(end - pos, limit_);
|
||||
auto rv = evbuffer_add(bucket_, pos, nwrite);
|
||||
if (rv == -1) {
|
||||
return -1;
|
||||
}
|
||||
rv = evbuffer_add_buffer(evbuffer_, bucket_);
|
||||
if (rv == -1) {
|
||||
return -1;
|
||||
}
|
||||
pos += nwrite;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int EvbufferBuffer::flush() {
|
||||
int rv;
|
||||
if (buflen_ > 0) {
|
||||
if (limit_ == -1) {
|
||||
rv = evbuffer_add(evbuffer_, buf_, buflen_);
|
||||
} else {
|
||||
rv = write_buffer();
|
||||
}
|
||||
if (rv == -1) {
|
||||
return -1;
|
||||
}
|
||||
writelen_ += buflen_;
|
||||
buflen_ = 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int EvbufferBuffer::add(const uint8_t *data, size_t datalen) {
|
||||
int rv;
|
||||
if (buflen_ + datalen > bufmax_) {
|
||||
if (buflen_ > 0) {
|
||||
if (limit_ == -1) {
|
||||
rv = evbuffer_add(evbuffer_, buf_, buflen_);
|
||||
} else {
|
||||
rv = write_buffer();
|
||||
}
|
||||
if (rv == -1) {
|
||||
return -1;
|
||||
}
|
||||
writelen_ += buflen_;
|
||||
buflen_ = 0;
|
||||
}
|
||||
if (datalen > bufmax_) {
|
||||
if (limit_ == -1) {
|
||||
rv = evbuffer_add(evbuffer_, data, datalen);
|
||||
} else {
|
||||
rv = write_buffer();
|
||||
}
|
||||
if (rv == -1) {
|
||||
return -1;
|
||||
}
|
||||
writelen_ += buflen_;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
memcpy(buf_ + buflen_, data, datalen);
|
||||
buflen_ += datalen;
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t EvbufferBuffer::get_buflen() const { return buflen_; }
|
||||
|
||||
size_t EvbufferBuffer::get_writelen() const { return writelen_; }
|
||||
|
||||
void bev_enable_unless(bufferevent *bev, int events) {
|
||||
if ((bufferevent_get_enabled(bev) & events) == events) {
|
||||
return;
|
||||
}
|
||||
|
||||
bufferevent_enable(bev, events);
|
||||
}
|
||||
|
||||
void bev_disable_unless(bufferevent *bev, int events) {
|
||||
if ((bufferevent_get_enabled(bev) & events) == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
bufferevent_disable(bev, events);
|
||||
}
|
||||
|
||||
} // namespace util
|
||||
|
||||
} // namespace nghttp2
|
||||
@@ -1,75 +0,0 @@
|
||||
/*
|
||||
* nghttp2 - HTTP/2 C Library
|
||||
*
|
||||
* Copyright (c) 2014 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 LIBEVENT_UTIL_H
|
||||
#define LIBEVENT_UTIL_H
|
||||
|
||||
#include "nghttp2_config.h"
|
||||
|
||||
#include <event2/buffer.h>
|
||||
#include <event2/bufferevent.h>
|
||||
|
||||
namespace nghttp2 {
|
||||
|
||||
namespace util {
|
||||
|
||||
class EvbufferBuffer {
|
||||
public:
|
||||
EvbufferBuffer();
|
||||
// If |limit| is not -1, at most min(limit, bufmax) size bytes are
|
||||
// added to evbuffer_.
|
||||
EvbufferBuffer(evbuffer *evbuffer, uint8_t *buf, size_t bufmax,
|
||||
ssize_t limit = -1);
|
||||
~EvbufferBuffer();
|
||||
void reset(evbuffer *evbuffer, uint8_t *buf, size_t bufmax,
|
||||
ssize_t limit = -1);
|
||||
int flush();
|
||||
int add(const uint8_t *data, size_t datalen);
|
||||
size_t get_buflen() const;
|
||||
int write_buffer();
|
||||
// Returns the number of written bytes to evbuffer_ so far. reset()
|
||||
// resets this value to 0.
|
||||
size_t get_writelen() const;
|
||||
|
||||
private:
|
||||
evbuffer *evbuffer_;
|
||||
evbuffer *bucket_;
|
||||
uint8_t *buf_;
|
||||
size_t bufmax_;
|
||||
size_t buflen_;
|
||||
ssize_t limit_;
|
||||
size_t writelen_;
|
||||
};
|
||||
|
||||
// These functions are provided to reduce epoll_ctl syscall. Avoid
|
||||
// calling bufferevent_enable/disable() unless it is required by
|
||||
// sniffing current enabled events.
|
||||
void bev_enable_unless(bufferevent *bev, int events);
|
||||
void bev_disable_unless(bufferevent *bev, int events);
|
||||
|
||||
} // namespace util
|
||||
|
||||
} // namespace nghttp2
|
||||
|
||||
#endif // LIBEVENT_UTIL_H
|
||||
@@ -24,7 +24,7 @@
|
||||
*/
|
||||
#include "memchunk_test.h"
|
||||
|
||||
#include <CUnit/CUnit.h>
|
||||
#include "munitxx.h"
|
||||
|
||||
#include <nghttp2/nghttp2.h>
|
||||
|
||||
@@ -33,52 +33,72 @@
|
||||
|
||||
namespace nghttp2 {
|
||||
|
||||
namespace {
|
||||
const MunitTest tests[]{
|
||||
munit_void_test(test_pool_recycle),
|
||||
munit_void_test(test_memchunks_append),
|
||||
munit_void_test(test_memchunks_drain),
|
||||
munit_void_test(test_memchunks_riovec),
|
||||
munit_void_test(test_memchunks_recycle),
|
||||
munit_void_test(test_memchunks_reset),
|
||||
munit_void_test(test_peek_memchunks_append),
|
||||
munit_void_test(test_peek_memchunks_disable_peek_drain),
|
||||
munit_void_test(test_peek_memchunks_disable_peek_no_drain),
|
||||
munit_void_test(test_peek_memchunks_reset),
|
||||
munit_test_end(),
|
||||
};
|
||||
} // namespace
|
||||
|
||||
const MunitSuite memchunk_suite{
|
||||
"/memchunk", tests, NULL, 1, MUNIT_SUITE_OPTION_NONE,
|
||||
};
|
||||
|
||||
void test_pool_recycle(void) {
|
||||
MemchunkPool pool;
|
||||
|
||||
CU_ASSERT(!pool.pool);
|
||||
CU_ASSERT(0 == pool.poolsize);
|
||||
CU_ASSERT(nullptr == pool.freelist);
|
||||
assert_null(pool.pool);
|
||||
assert_size(0, ==, pool.poolsize);
|
||||
assert_null(pool.freelist);
|
||||
|
||||
auto m1 = pool.get();
|
||||
|
||||
CU_ASSERT(m1 == pool.pool);
|
||||
CU_ASSERT(MemchunkPool::value_type::size == pool.poolsize);
|
||||
CU_ASSERT(nullptr == pool.freelist);
|
||||
assert_ptr_equal(m1, pool.pool);
|
||||
assert_size(MemchunkPool::value_type::size, ==, pool.poolsize);
|
||||
assert_null(pool.freelist);
|
||||
|
||||
auto m2 = pool.get();
|
||||
|
||||
CU_ASSERT(m2 == pool.pool);
|
||||
CU_ASSERT(2 * MemchunkPool::value_type::size == pool.poolsize);
|
||||
CU_ASSERT(nullptr == pool.freelist);
|
||||
CU_ASSERT(m1 == m2->knext);
|
||||
CU_ASSERT(nullptr == m1->knext);
|
||||
assert_ptr_equal(m2, pool.pool);
|
||||
assert_size(2 * MemchunkPool::value_type::size, ==, pool.poolsize);
|
||||
assert_null(pool.freelist);
|
||||
assert_ptr_equal(m1, m2->knext);
|
||||
assert_null(m1->knext);
|
||||
|
||||
auto m3 = pool.get();
|
||||
|
||||
CU_ASSERT(m3 == pool.pool);
|
||||
CU_ASSERT(3 * MemchunkPool::value_type::size == pool.poolsize);
|
||||
CU_ASSERT(nullptr == pool.freelist);
|
||||
assert_ptr_equal(m3, pool.pool);
|
||||
assert_size(3 * MemchunkPool::value_type::size, ==, pool.poolsize);
|
||||
assert_null(pool.freelist);
|
||||
|
||||
pool.recycle(m3);
|
||||
|
||||
CU_ASSERT(m3 == pool.pool);
|
||||
CU_ASSERT(3 * MemchunkPool::value_type::size == pool.poolsize);
|
||||
CU_ASSERT(m3 == pool.freelist);
|
||||
assert_ptr_equal(m3, pool.pool);
|
||||
assert_size(3 * MemchunkPool::value_type::size, ==, pool.poolsize);
|
||||
assert_ptr_equal(m3, pool.freelist);
|
||||
|
||||
auto m4 = pool.get();
|
||||
|
||||
CU_ASSERT(m3 == m4);
|
||||
CU_ASSERT(m4 == pool.pool);
|
||||
CU_ASSERT(3 * MemchunkPool::value_type::size == pool.poolsize);
|
||||
CU_ASSERT(nullptr == pool.freelist);
|
||||
assert_ptr_equal(m3, m4);
|
||||
assert_ptr_equal(m4, pool.pool);
|
||||
assert_size(3 * MemchunkPool::value_type::size, ==, pool.poolsize);
|
||||
assert_null(pool.freelist);
|
||||
|
||||
pool.recycle(m2);
|
||||
pool.recycle(m1);
|
||||
|
||||
CU_ASSERT(m1 == pool.freelist);
|
||||
CU_ASSERT(m2 == m1->next);
|
||||
CU_ASSERT(nullptr == m2->next);
|
||||
assert_ptr_equal(m1, pool.freelist);
|
||||
assert_ptr_equal(m2, m1->next);
|
||||
assert_null(m2->next);
|
||||
}
|
||||
|
||||
using Memchunk16 = Memchunk<16>;
|
||||
@@ -94,37 +114,37 @@ void test_memchunks_append(void) {
|
||||
|
||||
auto m = chunks.tail;
|
||||
|
||||
CU_ASSERT(3 == m->len());
|
||||
CU_ASSERT(13 == m->left());
|
||||
assert_size(3, ==, m->len());
|
||||
assert_size(13, ==, m->left());
|
||||
|
||||
chunks.append("3456789abcdef@");
|
||||
|
||||
CU_ASSERT(16 == m->len());
|
||||
CU_ASSERT(0 == m->left());
|
||||
assert_size(16, ==, m->len());
|
||||
assert_size(0, ==, m->left());
|
||||
|
||||
m = chunks.tail;
|
||||
|
||||
CU_ASSERT(1 == m->len());
|
||||
CU_ASSERT(15 == m->left());
|
||||
CU_ASSERT(17 == chunks.rleft());
|
||||
assert_size(1, ==, m->len());
|
||||
assert_size(15, ==, m->left());
|
||||
assert_size(17, ==, chunks.rleft());
|
||||
|
||||
char buf[16];
|
||||
size_t nread;
|
||||
|
||||
nread = chunks.remove(buf, 8);
|
||||
|
||||
CU_ASSERT(8 == nread);
|
||||
CU_ASSERT(0 == memcmp("01234567", buf, nread));
|
||||
CU_ASSERT(9 == chunks.rleft());
|
||||
assert_size(8, ==, nread);
|
||||
assert_memory_equal(nread, "01234567", buf);
|
||||
assert_size(9, ==, chunks.rleft());
|
||||
|
||||
nread = chunks.remove(buf, sizeof(buf));
|
||||
|
||||
CU_ASSERT(9 == nread);
|
||||
CU_ASSERT(0 == memcmp("89abcdef@", buf, nread));
|
||||
CU_ASSERT(0 == chunks.rleft());
|
||||
CU_ASSERT(nullptr == chunks.head);
|
||||
CU_ASSERT(nullptr == chunks.tail);
|
||||
CU_ASSERT(32 == pool.poolsize);
|
||||
assert_size(9, ==, nread);
|
||||
assert_memory_equal(nread, "89abcdef@", buf);
|
||||
assert_size(0, ==, chunks.rleft());
|
||||
assert_null(chunks.head);
|
||||
assert_null(chunks.tail);
|
||||
assert_size(32, ==, pool.poolsize);
|
||||
}
|
||||
|
||||
void test_memchunks_drain(void) {
|
||||
@@ -137,14 +157,14 @@ void test_memchunks_drain(void) {
|
||||
|
||||
nread = chunks.drain(3);
|
||||
|
||||
CU_ASSERT(3 == nread);
|
||||
assert_size(3, ==, nread);
|
||||
|
||||
char buf[16];
|
||||
|
||||
nread = chunks.remove(buf, sizeof(buf));
|
||||
|
||||
CU_ASSERT(7 == nread);
|
||||
CU_ASSERT(0 == memcmp("3456789", buf, nread));
|
||||
assert_size(7, ==, nread);
|
||||
assert_memory_equal(nread, "3456789", buf);
|
||||
}
|
||||
|
||||
void test_memchunks_riovec(void) {
|
||||
@@ -160,24 +180,24 @@ void test_memchunks_riovec(void) {
|
||||
|
||||
auto m = chunks.head;
|
||||
|
||||
CU_ASSERT(2 == iovcnt);
|
||||
CU_ASSERT(m->buf.data() == iov[0].iov_base);
|
||||
CU_ASSERT(m->len() == iov[0].iov_len);
|
||||
assert_int(2, ==, iovcnt);
|
||||
assert_ptr_equal(m->buf.data(), iov[0].iov_base);
|
||||
assert_size(m->len(), ==, iov[0].iov_len);
|
||||
|
||||
m = m->next;
|
||||
|
||||
CU_ASSERT(m->buf.data() == iov[1].iov_base);
|
||||
CU_ASSERT(m->len() == iov[1].iov_len);
|
||||
assert_ptr_equal(m->buf.data(), iov[1].iov_base);
|
||||
assert_size(m->len(), ==, iov[1].iov_len);
|
||||
|
||||
chunks.drain(2 * 16);
|
||||
|
||||
iovcnt = chunks.riovec(iov.data(), iov.size());
|
||||
|
||||
CU_ASSERT(1 == iovcnt);
|
||||
assert_int(1, ==, iovcnt);
|
||||
|
||||
m = chunks.head;
|
||||
CU_ASSERT(m->buf.data() == iov[0].iov_base);
|
||||
CU_ASSERT(m->len() == iov[0].iov_len);
|
||||
assert_ptr_equal(m->buf.data(), iov[0].iov_base);
|
||||
assert_size(m->len(), ==, iov[0].iov_len);
|
||||
}
|
||||
|
||||
void test_memchunks_recycle(void) {
|
||||
@@ -187,14 +207,14 @@ void test_memchunks_recycle(void) {
|
||||
std::array<char, 32> buf{};
|
||||
chunks.append(buf.data(), buf.size());
|
||||
}
|
||||
CU_ASSERT(32 == pool.poolsize);
|
||||
CU_ASSERT(nullptr != pool.freelist);
|
||||
assert_size(32, ==, pool.poolsize);
|
||||
assert_not_null(pool.freelist);
|
||||
|
||||
auto m = pool.freelist;
|
||||
m = m->next;
|
||||
|
||||
CU_ASSERT(nullptr != m);
|
||||
CU_ASSERT(nullptr == m->next);
|
||||
assert_not_null(m);
|
||||
assert_null(m->next);
|
||||
}
|
||||
|
||||
void test_memchunks_reset(void) {
|
||||
@@ -205,19 +225,19 @@ void test_memchunks_reset(void) {
|
||||
|
||||
chunks.append(b.data(), b.size());
|
||||
|
||||
CU_ASSERT(32 == chunks.rleft());
|
||||
assert_size(32, ==, chunks.rleft());
|
||||
|
||||
chunks.reset();
|
||||
|
||||
CU_ASSERT(0 == chunks.rleft());
|
||||
CU_ASSERT(nullptr == chunks.head);
|
||||
CU_ASSERT(nullptr == chunks.tail);
|
||||
assert_size(0, ==, chunks.rleft());
|
||||
assert_null(chunks.head);
|
||||
assert_null(chunks.tail);
|
||||
|
||||
auto m = pool.freelist;
|
||||
|
||||
CU_ASSERT(nullptr != m);
|
||||
CU_ASSERT(nullptr != m->next);
|
||||
CU_ASSERT(nullptr == m->next->next);
|
||||
assert_not_null(m);
|
||||
assert_not_null(m->next);
|
||||
assert_null(m->next->next);
|
||||
}
|
||||
|
||||
void test_peek_memchunks_append(void) {
|
||||
@@ -232,27 +252,27 @@ void test_peek_memchunks_append(void) {
|
||||
|
||||
pchunks.append(b.data(), b.size());
|
||||
|
||||
CU_ASSERT(32 == pchunks.rleft());
|
||||
CU_ASSERT(32 == pchunks.rleft_buffered());
|
||||
assert_size(32, ==, pchunks.rleft());
|
||||
assert_size(32, ==, pchunks.rleft_buffered());
|
||||
|
||||
CU_ASSERT(0 == pchunks.remove(nullptr, 0));
|
||||
assert_size(0, ==, pchunks.remove(nullptr, 0));
|
||||
|
||||
CU_ASSERT(32 == pchunks.rleft());
|
||||
CU_ASSERT(32 == pchunks.rleft_buffered());
|
||||
assert_size(32, ==, pchunks.rleft());
|
||||
assert_size(32, ==, pchunks.rleft_buffered());
|
||||
|
||||
CU_ASSERT(12 == pchunks.remove(d.data(), 12));
|
||||
assert_size(12, ==, pchunks.remove(d.data(), 12));
|
||||
|
||||
CU_ASSERT(std::equal(std::begin(b), std::begin(b) + 12, std::begin(d)));
|
||||
assert_true(std::equal(std::begin(b), std::begin(b) + 12, std::begin(d)));
|
||||
|
||||
CU_ASSERT(20 == pchunks.rleft());
|
||||
CU_ASSERT(32 == pchunks.rleft_buffered());
|
||||
assert_size(20, ==, pchunks.rleft());
|
||||
assert_size(32, ==, pchunks.rleft_buffered());
|
||||
|
||||
CU_ASSERT(20 == pchunks.remove(d.data(), d.size()));
|
||||
assert_size(20, ==, pchunks.remove(d.data(), d.size()));
|
||||
|
||||
CU_ASSERT(std::equal(std::begin(b) + 12, std::end(b), std::begin(d)));
|
||||
assert_true(std::equal(std::begin(b) + 12, std::end(b), std::begin(d)));
|
||||
|
||||
CU_ASSERT(0 == pchunks.rleft());
|
||||
CU_ASSERT(32 == pchunks.rleft_buffered());
|
||||
assert_size(0, ==, pchunks.rleft());
|
||||
assert_size(32, ==, pchunks.rleft_buffered());
|
||||
}
|
||||
|
||||
void test_peek_memchunks_disable_peek_drain(void) {
|
||||
@@ -267,20 +287,20 @@ void test_peek_memchunks_disable_peek_drain(void) {
|
||||
|
||||
pchunks.append(b.data(), b.size());
|
||||
|
||||
CU_ASSERT(12 == pchunks.remove(d.data(), 12));
|
||||
assert_size(12, ==, pchunks.remove(d.data(), 12));
|
||||
|
||||
pchunks.disable_peek(true);
|
||||
|
||||
CU_ASSERT(!pchunks.peeking);
|
||||
CU_ASSERT(20 == pchunks.rleft());
|
||||
CU_ASSERT(20 == pchunks.rleft_buffered());
|
||||
assert_false(pchunks.peeking);
|
||||
assert_size(20, ==, pchunks.rleft());
|
||||
assert_size(20, ==, pchunks.rleft_buffered());
|
||||
|
||||
CU_ASSERT(20 == pchunks.remove(d.data(), d.size()));
|
||||
assert_size(20, ==, pchunks.remove(d.data(), d.size()));
|
||||
|
||||
CU_ASSERT(std::equal(std::begin(b) + 12, std::end(b), std::begin(d)));
|
||||
assert_true(std::equal(std::begin(b) + 12, std::end(b), std::begin(d)));
|
||||
|
||||
CU_ASSERT(0 == pchunks.rleft());
|
||||
CU_ASSERT(0 == pchunks.rleft_buffered());
|
||||
assert_size(0, ==, pchunks.rleft());
|
||||
assert_size(0, ==, pchunks.rleft_buffered());
|
||||
}
|
||||
|
||||
void test_peek_memchunks_disable_peek_no_drain(void) {
|
||||
@@ -295,20 +315,20 @@ void test_peek_memchunks_disable_peek_no_drain(void) {
|
||||
|
||||
pchunks.append(b.data(), b.size());
|
||||
|
||||
CU_ASSERT(12 == pchunks.remove(d.data(), 12));
|
||||
assert_size(12, ==, pchunks.remove(d.data(), 12));
|
||||
|
||||
pchunks.disable_peek(false);
|
||||
|
||||
CU_ASSERT(!pchunks.peeking);
|
||||
CU_ASSERT(32 == pchunks.rleft());
|
||||
CU_ASSERT(32 == pchunks.rleft_buffered());
|
||||
assert_false(pchunks.peeking);
|
||||
assert_size(32, ==, pchunks.rleft());
|
||||
assert_size(32, ==, pchunks.rleft_buffered());
|
||||
|
||||
CU_ASSERT(32 == pchunks.remove(d.data(), d.size()));
|
||||
assert_size(32, ==, pchunks.remove(d.data(), d.size()));
|
||||
|
||||
CU_ASSERT(std::equal(std::begin(b), std::end(b), std::begin(d)));
|
||||
assert_true(std::equal(std::begin(b), std::end(b), std::begin(d)));
|
||||
|
||||
CU_ASSERT(0 == pchunks.rleft());
|
||||
CU_ASSERT(0 == pchunks.rleft_buffered());
|
||||
assert_size(0, ==, pchunks.rleft());
|
||||
assert_size(0, ==, pchunks.rleft_buffered());
|
||||
}
|
||||
|
||||
void test_peek_memchunks_reset(void) {
|
||||
@@ -323,18 +343,18 @@ void test_peek_memchunks_reset(void) {
|
||||
|
||||
pchunks.append(b.data(), b.size());
|
||||
|
||||
CU_ASSERT(12 == pchunks.remove(d.data(), 12));
|
||||
assert_size(12, ==, pchunks.remove(d.data(), 12));
|
||||
|
||||
pchunks.disable_peek(true);
|
||||
pchunks.reset();
|
||||
|
||||
CU_ASSERT(0 == pchunks.rleft());
|
||||
CU_ASSERT(0 == pchunks.rleft_buffered());
|
||||
assert_size(0, ==, pchunks.rleft());
|
||||
assert_size(0, ==, pchunks.rleft_buffered());
|
||||
|
||||
CU_ASSERT(nullptr == pchunks.cur);
|
||||
CU_ASSERT(nullptr == pchunks.cur_pos);
|
||||
CU_ASSERT(nullptr == pchunks.cur_last);
|
||||
CU_ASSERT(pchunks.peeking);
|
||||
assert_null(pchunks.cur);
|
||||
assert_null(pchunks.cur_pos);
|
||||
assert_null(pchunks.cur_last);
|
||||
assert_true(pchunks.peeking);
|
||||
}
|
||||
|
||||
} // namespace nghttp2
|
||||
|
||||
@@ -29,18 +29,24 @@
|
||||
# include <config.h>
|
||||
#endif // HAVE_CONFIG_H
|
||||
|
||||
#define MUNIT_ENABLE_ASSERT_ALIASES
|
||||
|
||||
#include "munit.h"
|
||||
|
||||
namespace nghttp2 {
|
||||
|
||||
void test_pool_recycle(void);
|
||||
void test_memchunks_append(void);
|
||||
void test_memchunks_drain(void);
|
||||
void test_memchunks_riovec(void);
|
||||
void test_memchunks_recycle(void);
|
||||
void test_memchunks_reset(void);
|
||||
void test_peek_memchunks_append(void);
|
||||
void test_peek_memchunks_disable_peek_drain(void);
|
||||
void test_peek_memchunks_disable_peek_no_drain(void);
|
||||
void test_peek_memchunks_reset(void);
|
||||
extern const MunitSuite memchunk_suite;
|
||||
|
||||
munit_void_test_decl(test_pool_recycle);
|
||||
munit_void_test_decl(test_memchunks_append);
|
||||
munit_void_test_decl(test_memchunks_drain);
|
||||
munit_void_test_decl(test_memchunks_riovec);
|
||||
munit_void_test_decl(test_memchunks_recycle);
|
||||
munit_void_test_decl(test_memchunks_reset);
|
||||
munit_void_test_decl(test_peek_memchunks_append);
|
||||
munit_void_test_decl(test_peek_memchunks_disable_peek_drain);
|
||||
munit_void_test_decl(test_peek_memchunks_disable_peek_no_drain);
|
||||
munit_void_test_decl(test_peek_memchunks_reset);
|
||||
|
||||
} // namespace nghttp2
|
||||
|
||||
|
||||
@@ -157,7 +157,7 @@ std::string strip_fragment(const char *raw_uri) {
|
||||
} // namespace
|
||||
|
||||
Request::Request(const std::string &uri, const http_parser_url &u,
|
||||
const nghttp2_data_provider *data_prd, int64_t data_length,
|
||||
const nghttp2_data_provider2 *data_prd, int64_t data_length,
|
||||
const nghttp2_priority_spec &pri_spec, int level)
|
||||
: uri(uri),
|
||||
u(u),
|
||||
@@ -370,11 +370,11 @@ void continue_timeout_cb(struct ev_loop *loop, ev_timer *w, int revents) {
|
||||
auto req = static_cast<Request *>(w->data);
|
||||
int error;
|
||||
|
||||
error = nghttp2_submit_data(client->session, NGHTTP2_FLAG_END_STREAM,
|
||||
req->stream_id, req->data_prd);
|
||||
error = nghttp2_submit_data2(client->session, NGHTTP2_FLAG_END_STREAM,
|
||||
req->stream_id, req->data_prd);
|
||||
|
||||
if (error) {
|
||||
std::cerr << "[ERROR] nghttp2_submit_data() returned error: "
|
||||
std::cerr << "[ERROR] nghttp2_submit_data2() returned error: "
|
||||
<< nghttp2_strerror(error) << std::endl;
|
||||
nghttp2_submit_rst_stream(client->session, NGHTTP2_FLAG_NONE,
|
||||
req->stream_id, NGHTTP2_INTERNAL_ERROR);
|
||||
@@ -525,13 +525,13 @@ int submit_request(HttpClient *client, const Headers &headers, Request *req) {
|
||||
nva.data(), nva.size(), req);
|
||||
} else {
|
||||
stream_id =
|
||||
nghttp2_submit_request(client->session, &req->pri_spec, nva.data(),
|
||||
nva.size(), req->data_prd, req);
|
||||
nghttp2_submit_request2(client->session, &req->pri_spec, nva.data(),
|
||||
nva.size(), req->data_prd, req);
|
||||
}
|
||||
|
||||
if (stream_id < 0) {
|
||||
std::cerr << "[ERROR] nghttp2_submit_"
|
||||
<< (expect_continue ? "headers" : "request")
|
||||
<< (expect_continue ? "headers" : "request2")
|
||||
<< "() returned error: " << nghttp2_strerror(stream_id)
|
||||
<< std::endl;
|
||||
return -1;
|
||||
@@ -953,14 +953,14 @@ size_t populate_settings(nghttp2_settings_entry *iv) {
|
||||
} // namespace
|
||||
|
||||
int HttpClient::on_upgrade_connect() {
|
||||
ssize_t rv;
|
||||
nghttp2_ssize rv;
|
||||
record_connect_end_time();
|
||||
assert(!reqvec.empty());
|
||||
std::array<nghttp2_settings_entry, 16> iv;
|
||||
size_t niv = populate_settings(iv.data());
|
||||
assert(settings_payload.size() >= 8 * niv);
|
||||
rv = nghttp2_pack_settings_payload(settings_payload.data(),
|
||||
settings_payload.size(), iv.data(), niv);
|
||||
rv = nghttp2_pack_settings_payload2(settings_payload.data(),
|
||||
settings_payload.size(), iv.data(), niv);
|
||||
if (rv < 0) {
|
||||
return -1;
|
||||
}
|
||||
@@ -1250,9 +1250,9 @@ int HttpClient::on_read(const uint8_t *data, size_t len) {
|
||||
util::hexdump(stdout, data, len);
|
||||
}
|
||||
|
||||
auto rv = nghttp2_session_mem_recv(session, data, len);
|
||||
auto rv = nghttp2_session_mem_recv2(session, data, len);
|
||||
if (rv < 0) {
|
||||
std::cerr << "[ERROR] nghttp2_session_mem_recv() returned error: "
|
||||
std::cerr << "[ERROR] nghttp2_session_mem_recv2() returned error: "
|
||||
<< nghttp2_strerror(rv) << std::endl;
|
||||
return -1;
|
||||
}
|
||||
@@ -1276,9 +1276,9 @@ int HttpClient::on_write() {
|
||||
}
|
||||
|
||||
const uint8_t *data;
|
||||
auto len = nghttp2_session_mem_send(session, &data);
|
||||
auto len = nghttp2_session_mem_send2(session, &data);
|
||||
if (len < 0) {
|
||||
std::cerr << "[ERROR] nghttp2_session_send() returned error: "
|
||||
std::cerr << "[ERROR] nghttp2_session_send2() returned error: "
|
||||
<< nghttp2_strerror(len) << std::endl;
|
||||
return -1;
|
||||
}
|
||||
@@ -1449,7 +1449,7 @@ void HttpClient::update_hostport() {
|
||||
}
|
||||
|
||||
bool HttpClient::add_request(const std::string &uri,
|
||||
const nghttp2_data_provider *data_prd,
|
||||
const nghttp2_data_provider2 *data_prd,
|
||||
int64_t data_length,
|
||||
const nghttp2_priority_spec &pri_spec, int level) {
|
||||
http_parser_url u{};
|
||||
@@ -1768,9 +1768,9 @@ int on_data_chunk_recv_callback(nghttp2_session *session, uint8_t flags,
|
||||
} // namespace
|
||||
|
||||
namespace {
|
||||
ssize_t select_padding_callback(nghttp2_session *session,
|
||||
const nghttp2_frame *frame, size_t max_payload,
|
||||
void *user_data) {
|
||||
nghttp2_ssize select_padding_callback(nghttp2_session *session,
|
||||
const nghttp2_frame *frame,
|
||||
size_t max_payload, void *user_data) {
|
||||
return std::min(max_payload, frame->hd.length + config.padding);
|
||||
}
|
||||
} // namespace
|
||||
@@ -2241,7 +2241,7 @@ namespace {
|
||||
int communicate(
|
||||
const std::string &scheme, const std::string &host, uint16_t port,
|
||||
std::vector<
|
||||
std::tuple<std::string, nghttp2_data_provider *, int64_t, int32_t>>
|
||||
std::tuple<std::string, nghttp2_data_provider2 *, int64_t, int32_t>>
|
||||
requests,
|
||||
const nghttp2_session_callbacks *callbacks) {
|
||||
int result = 0;
|
||||
@@ -2311,6 +2311,17 @@ int communicate(
|
||||
auto proto_list = util::get_default_alpn();
|
||||
|
||||
SSL_CTX_set_alpn_protos(ssl_ctx, proto_list.data(), proto_list.size());
|
||||
|
||||
#if defined(NGHTTP2_OPENSSL_IS_BORINGSSL) && defined(HAVE_LIBBROTLI)
|
||||
if (!SSL_CTX_add_cert_compression_alg(
|
||||
ssl_ctx, nghttp2::tls::CERTIFICATE_COMPRESSION_ALGO_BROTLI,
|
||||
nghttp2::tls::cert_compress, nghttp2::tls::cert_decompress)) {
|
||||
std::cerr << "[ERROR] SSL_CTX_add_cert_compression_alg failed."
|
||||
<< std::endl;
|
||||
result = -1;
|
||||
goto fin;
|
||||
}
|
||||
#endif // NGHTTP2_OPENSSL_IS_BORINGSSL && HAVE_LIBBROTLI
|
||||
}
|
||||
{
|
||||
HttpClient client{callbacks, loop, ssl_ctx};
|
||||
@@ -2391,9 +2402,10 @@ fin:
|
||||
} // namespace
|
||||
|
||||
namespace {
|
||||
ssize_t file_read_callback(nghttp2_session *session, int32_t stream_id,
|
||||
uint8_t *buf, size_t length, uint32_t *data_flags,
|
||||
nghttp2_data_source *source, void *user_data) {
|
||||
nghttp2_ssize file_read_callback(nghttp2_session *session, int32_t stream_id,
|
||||
uint8_t *buf, size_t length,
|
||||
uint32_t *data_flags,
|
||||
nghttp2_data_source *source, void *user_data) {
|
||||
int rv;
|
||||
auto req = static_cast<Request *>(
|
||||
nghttp2_session_get_stream_user_data(session, stream_id));
|
||||
@@ -2429,14 +2441,14 @@ ssize_t file_read_callback(nghttp2_session *session, int32_t stream_id,
|
||||
}
|
||||
}
|
||||
|
||||
return nread;
|
||||
return static_cast<nghttp2_ssize>(nread);
|
||||
}
|
||||
|
||||
if (req->data_offset > req->data_length || nread == 0) {
|
||||
return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
|
||||
}
|
||||
|
||||
return nread;
|
||||
return static_cast<nghttp2_ssize>(nread);
|
||||
}
|
||||
} // namespace
|
||||
|
||||
@@ -2480,7 +2492,7 @@ int run(char **uris, int n) {
|
||||
callbacks, on_frame_not_send_callback);
|
||||
|
||||
if (config.padding) {
|
||||
nghttp2_session_callbacks_set_select_padding_callback(
|
||||
nghttp2_session_callbacks_set_select_padding_callback2(
|
||||
callbacks, select_padding_callback);
|
||||
}
|
||||
|
||||
@@ -2489,7 +2501,7 @@ int run(char **uris, int n) {
|
||||
uint16_t prev_port = 0;
|
||||
int failures = 0;
|
||||
int data_fd = -1;
|
||||
nghttp2_data_provider data_prd;
|
||||
nghttp2_data_provider2 data_prd;
|
||||
struct stat data_stat;
|
||||
|
||||
if (!config.datafile.empty()) {
|
||||
@@ -2557,7 +2569,7 @@ int run(char **uris, int n) {
|
||||
data_prd.read_callback = file_read_callback;
|
||||
}
|
||||
std::vector<
|
||||
std::tuple<std::string, nghttp2_data_provider *, int64_t, int32_t>>
|
||||
std::tuple<std::string, nghttp2_data_provider2 *, int64_t, int32_t>>
|
||||
requests;
|
||||
|
||||
size_t next_weight_idx = 0;
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
|
||||
#include <ev.h>
|
||||
|
||||
#define NGHTTP2_NO_SSIZE_T
|
||||
#include <nghttp2/nghttp2.h>
|
||||
|
||||
#include "llhttp.h"
|
||||
@@ -77,7 +78,7 @@ struct Config {
|
||||
int64_t encoder_header_table_size;
|
||||
size_t padding;
|
||||
size_t max_concurrent_streams;
|
||||
ssize_t peer_max_concurrent_streams;
|
||||
size_t peer_max_concurrent_streams;
|
||||
int multiply;
|
||||
// milliseconds
|
||||
ev_tstamp timeout;
|
||||
@@ -137,7 +138,7 @@ struct ContinueTimer {
|
||||
struct Request {
|
||||
// For pushed request, |uri| is empty and |u| is zero-cleared.
|
||||
Request(const std::string &uri, const http_parser_url &u,
|
||||
const nghttp2_data_provider *data_prd, int64_t data_length,
|
||||
const nghttp2_data_provider2 *data_prd, int64_t data_length,
|
||||
const nghttp2_priority_spec &pri_spec, int level = 0);
|
||||
~Request();
|
||||
|
||||
@@ -180,7 +181,7 @@ struct Request {
|
||||
int64_t response_len;
|
||||
nghttp2_gzip *inflater;
|
||||
std::unique_ptr<HtmlParser> html_parser;
|
||||
const nghttp2_data_provider *data_prd;
|
||||
const nghttp2_data_provider2 *data_prd;
|
||||
size_t header_buffer_size;
|
||||
int32_t stream_id;
|
||||
int status;
|
||||
@@ -246,7 +247,7 @@ struct HttpClient {
|
||||
bool all_requests_processed() const;
|
||||
void update_hostport();
|
||||
bool add_request(const std::string &uri,
|
||||
const nghttp2_data_provider *data_prd, int64_t data_length,
|
||||
const nghttp2_data_provider2 *data_prd, int64_t data_length,
|
||||
const nghttp2_priority_spec &pri_spec, int level = 0);
|
||||
|
||||
void record_start_time();
|
||||
|
||||
@@ -27,26 +27,35 @@
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <CUnit/CUnit.h>
|
||||
#include "munit.h"
|
||||
|
||||
#include <zlib.h>
|
||||
|
||||
#include "nghttp2_gzip.h"
|
||||
|
||||
static const MunitTest tests[] = {
|
||||
munit_void_test(test_nghttp2_gzip_inflate),
|
||||
munit_test_end(),
|
||||
};
|
||||
|
||||
const MunitSuite gzip_suite = {
|
||||
"/gzip", tests, NULL, 1, MUNIT_SUITE_OPTION_NONE,
|
||||
};
|
||||
|
||||
static size_t deflate_data(uint8_t *out, size_t outlen, const uint8_t *in,
|
||||
size_t inlen) {
|
||||
int rv;
|
||||
z_stream zst = {0};
|
||||
|
||||
rv = deflateInit(&zst, Z_DEFAULT_COMPRESSION);
|
||||
CU_ASSERT(rv == Z_OK);
|
||||
assert_int(Z_OK, ==, rv);
|
||||
|
||||
zst.avail_in = (unsigned int)inlen;
|
||||
zst.next_in = (uint8_t *)in;
|
||||
zst.avail_out = (unsigned int)outlen;
|
||||
zst.next_out = out;
|
||||
rv = deflate(&zst, Z_SYNC_FLUSH);
|
||||
CU_ASSERT(rv == Z_OK);
|
||||
assert_int(Z_OK, ==, rv);
|
||||
|
||||
deflateEnd(&zst);
|
||||
|
||||
@@ -71,41 +80,44 @@ void test_nghttp2_gzip_inflate(void) {
|
||||
|
||||
inlen = deflate_data(in, inlen, (const uint8_t *)input, sizeof(input) - 1);
|
||||
|
||||
CU_ASSERT(0 == nghttp2_gzip_inflate_new(&inflater));
|
||||
assert_int(0, ==, nghttp2_gzip_inflate_new(&inflater));
|
||||
/* First 16 bytes */
|
||||
inptr = in;
|
||||
inproclen = inlen;
|
||||
outproclen = 16;
|
||||
CU_ASSERT(
|
||||
0 == nghttp2_gzip_inflate(inflater, out, &outproclen, inptr, &inproclen));
|
||||
CU_ASSERT(16 == outproclen);
|
||||
CU_ASSERT(inproclen > 0);
|
||||
CU_ASSERT(0 == memcmp(inputptr, out, outproclen));
|
||||
assert_int(
|
||||
0, ==,
|
||||
nghttp2_gzip_inflate(inflater, out, &outproclen, inptr, &inproclen));
|
||||
assert_size(16, ==, outproclen);
|
||||
assert_size(0, <, inproclen);
|
||||
assert_memory_equal(outproclen, inputptr, out);
|
||||
/* Next 32 bytes */
|
||||
inptr += inproclen;
|
||||
inlen -= inproclen;
|
||||
inproclen = inlen;
|
||||
inputptr += outproclen;
|
||||
outproclen = 32;
|
||||
CU_ASSERT(
|
||||
0 == nghttp2_gzip_inflate(inflater, out, &outproclen, inptr, &inproclen));
|
||||
CU_ASSERT(32 == outproclen);
|
||||
CU_ASSERT(inproclen > 0);
|
||||
CU_ASSERT(0 == memcmp(inputptr, out, outproclen));
|
||||
assert_int(
|
||||
0, ==,
|
||||
nghttp2_gzip_inflate(inflater, out, &outproclen, inptr, &inproclen));
|
||||
assert_size(32, ==, outproclen);
|
||||
assert_size(0, <, inproclen);
|
||||
assert_memory_equal(outproclen, inputptr, out);
|
||||
/* Rest */
|
||||
inptr += inproclen;
|
||||
inlen -= inproclen;
|
||||
inproclen = inlen;
|
||||
inputptr += outproclen;
|
||||
outproclen = sizeof(out);
|
||||
CU_ASSERT(
|
||||
0 == nghttp2_gzip_inflate(inflater, out, &outproclen, inptr, &inproclen));
|
||||
CU_ASSERT(sizeof(input) - 49 == outproclen);
|
||||
CU_ASSERT(inproclen > 0);
|
||||
CU_ASSERT(0 == memcmp(inputptr, out, outproclen));
|
||||
assert_int(
|
||||
0, ==,
|
||||
nghttp2_gzip_inflate(inflater, out, &outproclen, inptr, &inproclen));
|
||||
assert_size(sizeof(input) - 49, ==, outproclen);
|
||||
assert_size(0, <, inproclen);
|
||||
assert_memory_equal(outproclen, inputptr, out);
|
||||
|
||||
inlen -= inproclen;
|
||||
CU_ASSERT(0 == inlen);
|
||||
assert_size(0, ==, inlen);
|
||||
|
||||
nghttp2_gzip_inflate_del(inflater);
|
||||
}
|
||||
|
||||
@@ -33,7 +33,13 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void test_nghttp2_gzip_inflate(void);
|
||||
#define MUNIT_ENABLE_ASSERT_ALIASES
|
||||
|
||||
#include "munit.h"
|
||||
|
||||
extern const MunitSuite gzip_suite;
|
||||
|
||||
munit_void_test_decl(test_nghttp2_gzip_inflate);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -26,9 +26,8 @@
|
||||
# include <config.h>
|
||||
#endif // HAVE_CONFIG_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <CUnit/Basic.h>
|
||||
#include "munit.h"
|
||||
|
||||
// include test cases' include files here
|
||||
#include "shrpx_tls_test.h"
|
||||
#include "shrpx_downstream_test.h"
|
||||
@@ -47,200 +46,21 @@
|
||||
#include "shrpx_router_test.h"
|
||||
#include "shrpx_log.h"
|
||||
|
||||
static int init_suite1(void) { return 0; }
|
||||
|
||||
static int clean_suite1(void) { return 0; }
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
CU_pSuite pSuite = nullptr;
|
||||
unsigned int num_tests_failed;
|
||||
|
||||
shrpx::create_config();
|
||||
|
||||
// initialize the CUnit test registry
|
||||
if (CUE_SUCCESS != CU_initialize_registry())
|
||||
return CU_get_error();
|
||||
const MunitSuite suites[] = {
|
||||
shrpx::tls_suite, shrpx::downstream_suite,
|
||||
shrpx::config_suite, shrpx::worker_suite,
|
||||
shrpx::http_suite, shrpx::router_suite,
|
||||
shrpx::http2_suite, shrpx::util_suite,
|
||||
gzip_suite, buffer_suite,
|
||||
memchunk_suite, template_suite,
|
||||
base64_suite, {NULL, NULL, NULL, 0, MUNIT_SUITE_OPTION_NONE},
|
||||
};
|
||||
const MunitSuite suite = {
|
||||
"", NULL, suites, 1, MUNIT_SUITE_OPTION_NONE,
|
||||
};
|
||||
|
||||
// add a suite to the registry
|
||||
pSuite = CU_add_suite("shrpx_TestSuite", init_suite1, clean_suite1);
|
||||
if (nullptr == pSuite) {
|
||||
CU_cleanup_registry();
|
||||
return CU_get_error();
|
||||
}
|
||||
|
||||
// add the tests to the suite
|
||||
if (!CU_add_test(pSuite, "tls_create_lookup_tree",
|
||||
shrpx::test_shrpx_tls_create_lookup_tree) ||
|
||||
!CU_add_test(pSuite, "tls_cert_lookup_tree_add_ssl_ctx",
|
||||
shrpx::test_shrpx_tls_cert_lookup_tree_add_ssl_ctx) ||
|
||||
!CU_add_test(pSuite, "tls_tls_hostname_match",
|
||||
shrpx::test_shrpx_tls_tls_hostname_match) ||
|
||||
!CU_add_test(pSuite, "tls_tls_verify_numeric_hostname",
|
||||
shrpx::test_shrpx_tls_verify_numeric_hostname) ||
|
||||
!CU_add_test(pSuite, "tls_tls_verify_dns_hostname",
|
||||
shrpx::test_shrpx_tls_verify_dns_hostname) ||
|
||||
!CU_add_test(pSuite, "http2_add_header", shrpx::test_http2_add_header) ||
|
||||
!CU_add_test(pSuite, "http2_get_header", shrpx::test_http2_get_header) ||
|
||||
!CU_add_test(pSuite, "http2_copy_headers_to_nva",
|
||||
shrpx::test_http2_copy_headers_to_nva) ||
|
||||
!CU_add_test(pSuite, "http2_build_http1_headers_from_headers",
|
||||
shrpx::test_http2_build_http1_headers_from_headers) ||
|
||||
!CU_add_test(pSuite, "http2_lws", shrpx::test_http2_lws) ||
|
||||
!CU_add_test(pSuite, "http2_rewrite_location_uri",
|
||||
shrpx::test_http2_rewrite_location_uri) ||
|
||||
!CU_add_test(pSuite, "http2_parse_http_status_code",
|
||||
shrpx::test_http2_parse_http_status_code) ||
|
||||
!CU_add_test(pSuite, "http2_index_header",
|
||||
shrpx::test_http2_index_header) ||
|
||||
!CU_add_test(pSuite, "http2_lookup_token",
|
||||
shrpx::test_http2_lookup_token) ||
|
||||
!CU_add_test(pSuite, "http2_parse_link_header",
|
||||
shrpx::test_http2_parse_link_header) ||
|
||||
!CU_add_test(pSuite, "http2_path_join", shrpx::test_http2_path_join) ||
|
||||
!CU_add_test(pSuite, "http2_normalize_path",
|
||||
shrpx::test_http2_normalize_path) ||
|
||||
!CU_add_test(pSuite, "http2_rewrite_clean_path",
|
||||
shrpx::test_http2_rewrite_clean_path) ||
|
||||
!CU_add_test(pSuite, "http2_get_pure_path_component",
|
||||
shrpx::test_http2_get_pure_path_component) ||
|
||||
!CU_add_test(pSuite, "http2_construct_push_component",
|
||||
shrpx::test_http2_construct_push_component) ||
|
||||
!CU_add_test(pSuite, "http2_contains_trailers",
|
||||
shrpx::test_http2_contains_trailers) ||
|
||||
!CU_add_test(pSuite, "http2_check_transfer_encoding",
|
||||
shrpx::test_http2_check_transfer_encoding) ||
|
||||
!CU_add_test(pSuite, "downstream_field_store_append_last_header",
|
||||
shrpx::test_downstream_field_store_append_last_header) ||
|
||||
!CU_add_test(pSuite, "downstream_field_store_header",
|
||||
shrpx::test_downstream_field_store_header) ||
|
||||
!CU_add_test(pSuite, "downstream_crumble_request_cookie",
|
||||
shrpx::test_downstream_crumble_request_cookie) ||
|
||||
!CU_add_test(pSuite, "downstream_assemble_request_cookie",
|
||||
shrpx::test_downstream_assemble_request_cookie) ||
|
||||
!CU_add_test(pSuite, "downstream_rewrite_location_response_header",
|
||||
shrpx::test_downstream_rewrite_location_response_header) ||
|
||||
!CU_add_test(pSuite, "downstream_supports_non_final_response",
|
||||
shrpx::test_downstream_supports_non_final_response) ||
|
||||
!CU_add_test(pSuite, "downstream_find_affinity_cookie",
|
||||
shrpx::test_downstream_find_affinity_cookie) ||
|
||||
!CU_add_test(pSuite, "config_parse_header",
|
||||
shrpx::test_shrpx_config_parse_header) ||
|
||||
!CU_add_test(pSuite, "config_parse_log_format",
|
||||
shrpx::test_shrpx_config_parse_log_format) ||
|
||||
!CU_add_test(pSuite, "config_read_tls_ticket_key_file",
|
||||
shrpx::test_shrpx_config_read_tls_ticket_key_file) ||
|
||||
!CU_add_test(pSuite, "config_read_tls_ticket_key_file_aes_256",
|
||||
shrpx::test_shrpx_config_read_tls_ticket_key_file_aes_256) ||
|
||||
!CU_add_test(pSuite, "worker_match_downstream_addr_group",
|
||||
shrpx::test_shrpx_worker_match_downstream_addr_group) ||
|
||||
!CU_add_test(pSuite, "http_create_forwarded",
|
||||
shrpx::test_shrpx_http_create_forwarded) ||
|
||||
!CU_add_test(pSuite, "http_create_via_header_value",
|
||||
shrpx::test_shrpx_http_create_via_header_value) ||
|
||||
!CU_add_test(pSuite, "http_create_affinity_cookie",
|
||||
shrpx::test_shrpx_http_create_affinity_cookie) ||
|
||||
!CU_add_test(pSuite, "http_create_atlsvc_header_field_value",
|
||||
shrpx::test_shrpx_http_create_altsvc_header_value) ||
|
||||
!CU_add_test(pSuite, "http_check_http_scheme",
|
||||
shrpx::test_shrpx_http_check_http_scheme) ||
|
||||
!CU_add_test(pSuite, "router_match", shrpx::test_shrpx_router_match) ||
|
||||
!CU_add_test(pSuite, "router_match_wildcard",
|
||||
shrpx::test_shrpx_router_match_wildcard) ||
|
||||
!CU_add_test(pSuite, "router_match_prefix",
|
||||
shrpx::test_shrpx_router_match_prefix) ||
|
||||
!CU_add_test(pSuite, "util_streq", shrpx::test_util_streq) ||
|
||||
!CU_add_test(pSuite, "util_strieq", shrpx::test_util_strieq) ||
|
||||
!CU_add_test(pSuite, "util_inp_strlower",
|
||||
shrpx::test_util_inp_strlower) ||
|
||||
!CU_add_test(pSuite, "util_to_base64", shrpx::test_util_to_base64) ||
|
||||
!CU_add_test(pSuite, "util_to_token68", shrpx::test_util_to_token68) ||
|
||||
!CU_add_test(pSuite, "util_percent_encode_token",
|
||||
shrpx::test_util_percent_encode_token) ||
|
||||
!CU_add_test(pSuite, "util_percent_decode",
|
||||
shrpx::test_util_percent_decode) ||
|
||||
!CU_add_test(pSuite, "util_quote_string",
|
||||
shrpx::test_util_quote_string) ||
|
||||
!CU_add_test(pSuite, "util_utox", shrpx::test_util_utox) ||
|
||||
!CU_add_test(pSuite, "util_http_date", shrpx::test_util_http_date) ||
|
||||
!CU_add_test(pSuite, "util_select_h2", shrpx::test_util_select_h2) ||
|
||||
!CU_add_test(pSuite, "util_ipv6_numeric_addr",
|
||||
shrpx::test_util_ipv6_numeric_addr) ||
|
||||
!CU_add_test(pSuite, "util_utos", shrpx::test_util_utos) ||
|
||||
!CU_add_test(pSuite, "util_make_string_ref_uint",
|
||||
shrpx::test_util_make_string_ref_uint) ||
|
||||
!CU_add_test(pSuite, "util_utos_unit", shrpx::test_util_utos_unit) ||
|
||||
!CU_add_test(pSuite, "util_utos_funit", shrpx::test_util_utos_funit) ||
|
||||
!CU_add_test(pSuite, "util_parse_uint_with_unit",
|
||||
shrpx::test_util_parse_uint_with_unit) ||
|
||||
!CU_add_test(pSuite, "util_parse_uint", shrpx::test_util_parse_uint) ||
|
||||
!CU_add_test(pSuite, "util_parse_duration_with_unit",
|
||||
shrpx::test_util_parse_duration_with_unit) ||
|
||||
!CU_add_test(pSuite, "util_duration_str",
|
||||
shrpx::test_util_duration_str) ||
|
||||
!CU_add_test(pSuite, "util_format_duration",
|
||||
shrpx::test_util_format_duration) ||
|
||||
!CU_add_test(pSuite, "util_starts_with", shrpx::test_util_starts_with) ||
|
||||
!CU_add_test(pSuite, "util_ends_with", shrpx::test_util_ends_with) ||
|
||||
!CU_add_test(pSuite, "util_parse_http_date",
|
||||
shrpx::test_util_parse_http_date) ||
|
||||
!CU_add_test(pSuite, "util_localtime_date",
|
||||
shrpx::test_util_localtime_date) ||
|
||||
!CU_add_test(pSuite, "util_get_uint64", shrpx::test_util_get_uint64) ||
|
||||
!CU_add_test(pSuite, "util_parse_config_str_list",
|
||||
shrpx::test_util_parse_config_str_list) ||
|
||||
!CU_add_test(pSuite, "util_make_http_hostport",
|
||||
shrpx::test_util_make_http_hostport) ||
|
||||
!CU_add_test(pSuite, "util_make_hostport",
|
||||
shrpx::test_util_make_hostport) ||
|
||||
!CU_add_test(pSuite, "util_strifind", shrpx::test_util_strifind) ||
|
||||
!CU_add_test(pSuite, "util_random_alpha_digit",
|
||||
shrpx::test_util_random_alpha_digit) ||
|
||||
!CU_add_test(pSuite, "util_format_hex", shrpx::test_util_format_hex) ||
|
||||
!CU_add_test(pSuite, "util_is_hex_string",
|
||||
shrpx::test_util_is_hex_string) ||
|
||||
!CU_add_test(pSuite, "util_decode_hex", shrpx::test_util_decode_hex) ||
|
||||
!CU_add_test(pSuite, "util_extract_host",
|
||||
shrpx::test_util_extract_host) ||
|
||||
!CU_add_test(pSuite, "util_split_hostport",
|
||||
shrpx::test_util_split_hostport) ||
|
||||
!CU_add_test(pSuite, "util_split_str", shrpx::test_util_split_str) ||
|
||||
!CU_add_test(pSuite, "util_rstrip", shrpx::test_util_rstrip) ||
|
||||
!CU_add_test(pSuite, "gzip_inflate", test_nghttp2_gzip_inflate) ||
|
||||
!CU_add_test(pSuite, "buffer_write", nghttp2::test_buffer_write) ||
|
||||
!CU_add_test(pSuite, "pool_recycle", nghttp2::test_pool_recycle) ||
|
||||
!CU_add_test(pSuite, "memchunk_append", nghttp2::test_memchunks_append) ||
|
||||
!CU_add_test(pSuite, "memchunk_drain", nghttp2::test_memchunks_drain) ||
|
||||
!CU_add_test(pSuite, "memchunk_riovec", nghttp2::test_memchunks_riovec) ||
|
||||
!CU_add_test(pSuite, "memchunk_recycle",
|
||||
nghttp2::test_memchunks_recycle) ||
|
||||
!CU_add_test(pSuite, "memchunk_reset", nghttp2::test_memchunks_reset) ||
|
||||
!CU_add_test(pSuite, "peek_memchunk_append",
|
||||
nghttp2::test_peek_memchunks_append) ||
|
||||
!CU_add_test(pSuite, "peek_memchunk_disable_peek_drain",
|
||||
nghttp2::test_peek_memchunks_disable_peek_drain) ||
|
||||
!CU_add_test(pSuite, "peek_memchunk_disable_peek_no_drain",
|
||||
nghttp2::test_peek_memchunks_disable_peek_no_drain) ||
|
||||
!CU_add_test(pSuite, "peek_memchunk_reset",
|
||||
nghttp2::test_peek_memchunks_reset) ||
|
||||
!CU_add_test(pSuite, "template_immutable_string",
|
||||
nghttp2::test_template_immutable_string) ||
|
||||
!CU_add_test(pSuite, "template_string_ref",
|
||||
nghttp2::test_template_string_ref) ||
|
||||
!CU_add_test(pSuite, "base64_encode", nghttp2::test_base64_encode) ||
|
||||
!CU_add_test(pSuite, "base64_decode", nghttp2::test_base64_decode)) {
|
||||
CU_cleanup_registry();
|
||||
return CU_get_error();
|
||||
}
|
||||
|
||||
// Run all tests using the CUnit Basic interface
|
||||
CU_basic_set_mode(CU_BRM_VERBOSE);
|
||||
CU_basic_run_tests();
|
||||
num_tests_failed = CU_get_number_of_tests_failed();
|
||||
CU_cleanup_registry();
|
||||
if (CU_get_error() == CUE_SUCCESS) {
|
||||
return num_tests_failed;
|
||||
} else {
|
||||
printf("CUnit Error: %s\n", CU_get_error_msg());
|
||||
return CU_get_error();
|
||||
}
|
||||
return munit_suite_main(&suite, NULL, argc, argv);
|
||||
}
|
||||
|
||||
@@ -36,6 +36,8 @@
|
||||
|
||||
#include <cassert>
|
||||
|
||||
#define NGHTTP2_NO_SSIZE_T
|
||||
|
||||
#ifndef HAVE__EXIT
|
||||
# define nghttp2_Exit(status) _exit(status)
|
||||
#else // HAVE__EXIT
|
||||
|
||||
@@ -49,6 +49,8 @@
|
||||
#include <fstream>
|
||||
#include <unordered_map>
|
||||
|
||||
#include <openssl/evp.h>
|
||||
|
||||
#include <nghttp2/nghttp2.h>
|
||||
|
||||
#include "url-parser/url_parser.h"
|
||||
@@ -64,6 +66,10 @@
|
||||
#include "ssl_compat.h"
|
||||
#include "xsi_strerror.h"
|
||||
|
||||
#ifndef AI_NUMERICSERV
|
||||
# define AI_NUMERICSERV 0
|
||||
#endif
|
||||
|
||||
namespace shrpx {
|
||||
|
||||
namespace {
|
||||
@@ -4691,4 +4697,32 @@ int resolve_hostname(Address *addr, const char *hostname, uint16_t port,
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_HTTP3
|
||||
QUICKeyingMaterial::QUICKeyingMaterial(QUICKeyingMaterial &&other) noexcept
|
||||
: cid_encryption_ctx{std::exchange(other.cid_encryption_ctx, nullptr)},
|
||||
reserved{other.reserved},
|
||||
secret{other.secret},
|
||||
salt{other.salt},
|
||||
cid_encryption_key{other.cid_encryption_key},
|
||||
id{other.id} {}
|
||||
|
||||
QUICKeyingMaterial::~QUICKeyingMaterial() noexcept {
|
||||
if (cid_encryption_ctx) {
|
||||
EVP_CIPHER_CTX_free(cid_encryption_ctx);
|
||||
}
|
||||
}
|
||||
|
||||
QUICKeyingMaterial &
|
||||
QUICKeyingMaterial::operator=(QUICKeyingMaterial &&other) noexcept {
|
||||
cid_encryption_ctx = std::exchange(other.cid_encryption_ctx, nullptr);
|
||||
reserved = other.reserved;
|
||||
secret = other.secret;
|
||||
salt = other.salt;
|
||||
cid_encryption_key = other.cid_encryption_key;
|
||||
id = other.id;
|
||||
|
||||
return *this;
|
||||
}
|
||||
#endif // ENABLE_HTTP3
|
||||
|
||||
} // namespace shrpx
|
||||
|
||||
@@ -636,6 +636,11 @@ struct TLSCertificate {
|
||||
|
||||
#ifdef ENABLE_HTTP3
|
||||
struct QUICKeyingMaterial {
|
||||
QUICKeyingMaterial() noexcept = default;
|
||||
QUICKeyingMaterial(QUICKeyingMaterial &&other) noexcept;
|
||||
~QUICKeyingMaterial() noexcept;
|
||||
QUICKeyingMaterial &operator=(QUICKeyingMaterial &&other) noexcept;
|
||||
EVP_CIPHER_CTX *cid_encryption_ctx;
|
||||
std::array<uint8_t, SHRPX_QUIC_SECRET_RESERVEDLEN> reserved;
|
||||
std::array<uint8_t, SHRPX_QUIC_SECRETLEN> secret;
|
||||
std::array<uint8_t, SHRPX_QUIC_SALTLEN> salt;
|
||||
|
||||
@@ -30,43 +30,57 @@
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
#include <CUnit/CUnit.h>
|
||||
#include "munitxx.h"
|
||||
|
||||
#include "shrpx_config.h"
|
||||
#include "shrpx_log.h"
|
||||
|
||||
namespace shrpx {
|
||||
|
||||
namespace {
|
||||
const MunitTest tests[]{
|
||||
munit_void_test(test_shrpx_config_parse_header),
|
||||
munit_void_test(test_shrpx_config_parse_log_format),
|
||||
munit_void_test(test_shrpx_config_read_tls_ticket_key_file),
|
||||
munit_void_test(test_shrpx_config_read_tls_ticket_key_file_aes_256),
|
||||
munit_test_end(),
|
||||
};
|
||||
} // namespace
|
||||
|
||||
const MunitSuite config_suite{
|
||||
"/config_suite", tests, NULL, 1, MUNIT_SUITE_OPTION_NONE,
|
||||
};
|
||||
|
||||
void test_shrpx_config_parse_header(void) {
|
||||
BlockAllocator balloc(4096, 4096);
|
||||
|
||||
auto p = parse_header(balloc, StringRef::from_lit("a: b"));
|
||||
CU_ASSERT("a" == p.name);
|
||||
CU_ASSERT("b" == p.value);
|
||||
assert_stdstring_equal("a", p.name.str());
|
||||
assert_stdstring_equal("b", p.value.str());
|
||||
|
||||
p = parse_header(balloc, StringRef::from_lit("a: b"));
|
||||
CU_ASSERT("a" == p.name);
|
||||
CU_ASSERT("b" == p.value);
|
||||
assert_stdstring_equal("a", p.name.str());
|
||||
assert_stdstring_equal("b", p.value.str());
|
||||
|
||||
p = parse_header(balloc, StringRef::from_lit(":a: b"));
|
||||
CU_ASSERT(p.name.empty());
|
||||
assert_true(p.name.empty());
|
||||
|
||||
p = parse_header(balloc, StringRef::from_lit("a: :b"));
|
||||
CU_ASSERT("a" == p.name);
|
||||
CU_ASSERT(":b" == p.value);
|
||||
assert_stdstring_equal("a", p.name.str());
|
||||
assert_stdstring_equal(":b", p.value.str());
|
||||
|
||||
p = parse_header(balloc, StringRef::from_lit(": b"));
|
||||
CU_ASSERT(p.name.empty());
|
||||
assert_true(p.name.empty());
|
||||
|
||||
p = parse_header(balloc, StringRef::from_lit("alpha: bravo charlie"));
|
||||
CU_ASSERT("alpha" == p.name);
|
||||
CU_ASSERT("bravo charlie" == p.value);
|
||||
assert_stdstring_equal("alpha", p.name.str());
|
||||
assert_stdstring_equal("bravo charlie", p.value.str());
|
||||
|
||||
p = parse_header(balloc, StringRef::from_lit("a,: b"));
|
||||
CU_ASSERT(p.name.empty());
|
||||
assert_true(p.name.empty());
|
||||
|
||||
p = parse_header(balloc, StringRef::from_lit("a: b\x0a"));
|
||||
CU_ASSERT(p.name.empty());
|
||||
assert_true(p.name.empty());
|
||||
}
|
||||
|
||||
void test_shrpx_config_parse_log_format(void) {
|
||||
@@ -77,100 +91,102 @@ void test_shrpx_config_parse_log_format(void) {
|
||||
R"($remote_addr - $remote_user [$time_local] )"
|
||||
R"("$request" $status $body_bytes_sent )"
|
||||
R"("${http_referer}" $http_host "$http_user_agent")"));
|
||||
CU_ASSERT(16 == res.size());
|
||||
assert_size(16, ==, res.size());
|
||||
|
||||
CU_ASSERT(LogFragmentType::REMOTE_ADDR == res[0].type);
|
||||
assert_enum_class(LogFragmentType::REMOTE_ADDR, ==, res[0].type);
|
||||
|
||||
CU_ASSERT(LogFragmentType::LITERAL == res[1].type);
|
||||
CU_ASSERT(" - $remote_user [" == res[1].value);
|
||||
assert_enum_class(LogFragmentType::LITERAL, ==, res[1].type);
|
||||
assert_stdstring_equal(" - $remote_user [", res[1].value.str());
|
||||
|
||||
CU_ASSERT(LogFragmentType::TIME_LOCAL == res[2].type);
|
||||
assert_enum_class(LogFragmentType::TIME_LOCAL, ==, res[2].type);
|
||||
|
||||
CU_ASSERT(LogFragmentType::LITERAL == res[3].type);
|
||||
CU_ASSERT("] \"" == res[3].value);
|
||||
assert_enum_class(LogFragmentType::LITERAL, ==, res[3].type);
|
||||
assert_stdstring_equal("] \"", res[3].value.str());
|
||||
|
||||
CU_ASSERT(LogFragmentType::REQUEST == res[4].type);
|
||||
assert_enum_class(LogFragmentType::REQUEST, ==, res[4].type);
|
||||
|
||||
CU_ASSERT(LogFragmentType::LITERAL == res[5].type);
|
||||
CU_ASSERT("\" " == res[5].value);
|
||||
assert_enum_class(LogFragmentType::LITERAL, ==, res[5].type);
|
||||
assert_stdstring_equal("\" ", res[5].value.str());
|
||||
|
||||
CU_ASSERT(LogFragmentType::STATUS == res[6].type);
|
||||
assert_enum_class(LogFragmentType::STATUS, ==, res[6].type);
|
||||
|
||||
CU_ASSERT(LogFragmentType::LITERAL == res[7].type);
|
||||
CU_ASSERT(" " == res[7].value);
|
||||
assert_enum_class(LogFragmentType::LITERAL, ==, res[7].type);
|
||||
assert_stdstring_equal(" ", res[7].value.str());
|
||||
|
||||
CU_ASSERT(LogFragmentType::BODY_BYTES_SENT == res[8].type);
|
||||
assert_enum_class(LogFragmentType::BODY_BYTES_SENT, ==, res[8].type);
|
||||
|
||||
CU_ASSERT(LogFragmentType::LITERAL == res[9].type);
|
||||
CU_ASSERT(" \"" == res[9].value);
|
||||
assert_enum_class(LogFragmentType::LITERAL, ==, res[9].type);
|
||||
assert_stdstring_equal(" \"", res[9].value.str());
|
||||
|
||||
CU_ASSERT(LogFragmentType::HTTP == res[10].type);
|
||||
CU_ASSERT("referer" == res[10].value);
|
||||
assert_enum_class(LogFragmentType::HTTP, ==, res[10].type);
|
||||
assert_stdstring_equal("referer", res[10].value.str());
|
||||
|
||||
CU_ASSERT(LogFragmentType::LITERAL == res[11].type);
|
||||
CU_ASSERT("\" " == res[11].value);
|
||||
assert_enum_class(LogFragmentType::LITERAL, ==, res[11].type);
|
||||
assert_stdstring_equal("\" ", res[11].value.str());
|
||||
|
||||
CU_ASSERT(LogFragmentType::AUTHORITY == res[12].type);
|
||||
assert_enum_class(LogFragmentType::AUTHORITY, ==, res[12].type);
|
||||
|
||||
CU_ASSERT(LogFragmentType::LITERAL == res[13].type);
|
||||
CU_ASSERT(" \"" == res[13].value);
|
||||
assert_enum_class(LogFragmentType::LITERAL, ==, res[13].type);
|
||||
assert_stdstring_equal(" \"", res[13].value.str());
|
||||
|
||||
CU_ASSERT(LogFragmentType::HTTP == res[14].type);
|
||||
CU_ASSERT("user-agent" == res[14].value);
|
||||
assert_enum_class(LogFragmentType::HTTP, ==, res[14].type);
|
||||
assert_stdstring_equal("user-agent", res[14].value.str());
|
||||
|
||||
CU_ASSERT(LogFragmentType::LITERAL == res[15].type);
|
||||
CU_ASSERT("\"" == res[15].value);
|
||||
assert_enum_class(LogFragmentType::LITERAL, ==, res[15].type);
|
||||
assert_stdstring_equal("\"", res[15].value.str());
|
||||
|
||||
res = parse_log_format(balloc, StringRef::from_lit("$"));
|
||||
|
||||
CU_ASSERT(1 == res.size());
|
||||
assert_size(1, ==, res.size());
|
||||
|
||||
CU_ASSERT(LogFragmentType::LITERAL == res[0].type);
|
||||
CU_ASSERT("$" == res[0].value);
|
||||
assert_enum_class(LogFragmentType::LITERAL, ==, res[0].type);
|
||||
assert_stdstring_equal("$", res[0].value.str());
|
||||
|
||||
res = parse_log_format(balloc, StringRef::from_lit("${"));
|
||||
|
||||
CU_ASSERT(1 == res.size());
|
||||
assert_size(1, ==, res.size());
|
||||
|
||||
CU_ASSERT(LogFragmentType::LITERAL == res[0].type);
|
||||
CU_ASSERT("${" == res[0].value);
|
||||
assert_enum_class(LogFragmentType::LITERAL, ==, res[0].type);
|
||||
assert_stdstring_equal("${", res[0].value.str());
|
||||
|
||||
res = parse_log_format(balloc, StringRef::from_lit("${a"));
|
||||
|
||||
CU_ASSERT(1 == res.size());
|
||||
assert_size(1, ==, res.size());
|
||||
|
||||
CU_ASSERT(LogFragmentType::LITERAL == res[0].type);
|
||||
CU_ASSERT("${a" == res[0].value);
|
||||
assert_enum_class(LogFragmentType::LITERAL, ==, res[0].type);
|
||||
assert_stdstring_equal("${a", res[0].value.str());
|
||||
|
||||
res = parse_log_format(balloc, StringRef::from_lit("${a "));
|
||||
|
||||
CU_ASSERT(1 == res.size());
|
||||
assert_size(1, ==, res.size());
|
||||
|
||||
CU_ASSERT(LogFragmentType::LITERAL == res[0].type);
|
||||
CU_ASSERT("${a " == res[0].value);
|
||||
assert_enum_class(LogFragmentType::LITERAL, ==, res[0].type);
|
||||
assert_stdstring_equal("${a ", res[0].value.str());
|
||||
|
||||
res = parse_log_format(balloc, StringRef::from_lit("$$remote_addr"));
|
||||
|
||||
CU_ASSERT(2 == res.size());
|
||||
assert_size(2, ==, res.size());
|
||||
|
||||
CU_ASSERT(LogFragmentType::LITERAL == res[0].type);
|
||||
CU_ASSERT("$" == res[0].value);
|
||||
assert_enum_class(LogFragmentType::LITERAL, ==, res[0].type);
|
||||
assert_stdstring_equal("$", res[0].value.str());
|
||||
|
||||
CU_ASSERT(LogFragmentType::REMOTE_ADDR == res[1].type);
|
||||
CU_ASSERT("" == res[1].value);
|
||||
assert_enum_class(LogFragmentType::REMOTE_ADDR, ==, res[1].type);
|
||||
assert_stdstring_equal("", res[1].value.str());
|
||||
}
|
||||
|
||||
void test_shrpx_config_read_tls_ticket_key_file(void) {
|
||||
char file1[] = "/tmp/nghttpx-unittest.XXXXXX";
|
||||
auto fd1 = mkstemp(file1);
|
||||
CU_ASSERT(fd1 != -1);
|
||||
CU_ASSERT(48 ==
|
||||
write(fd1, "0..............12..............34..............5", 48));
|
||||
assert_int(-1, !=, fd1);
|
||||
assert_ssize(
|
||||
48, ==,
|
||||
write(fd1, "0..............12..............34..............5", 48));
|
||||
char file2[] = "/tmp/nghttpx-unittest.XXXXXX";
|
||||
auto fd2 = mkstemp(file2);
|
||||
CU_ASSERT(fd2 != -1);
|
||||
CU_ASSERT(48 ==
|
||||
write(fd2, "6..............78..............9a..............b", 48));
|
||||
assert_int(-1, !=, fd2);
|
||||
assert_ssize(
|
||||
48, ==,
|
||||
write(fd2, "6..............78..............9a..............b", 48));
|
||||
|
||||
close(fd1);
|
||||
close(fd2);
|
||||
@@ -178,44 +194,48 @@ void test_shrpx_config_read_tls_ticket_key_file(void) {
|
||||
{StringRef{file1}, StringRef{file2}}, EVP_aes_128_cbc(), EVP_sha256());
|
||||
unlink(file1);
|
||||
unlink(file2);
|
||||
CU_ASSERT(ticket_keys.get() != nullptr);
|
||||
CU_ASSERT(2 == ticket_keys->keys.size());
|
||||
assert_not_null(ticket_keys.get());
|
||||
assert_size(2, ==, ticket_keys->keys.size());
|
||||
auto key = &ticket_keys->keys[0];
|
||||
CU_ASSERT(std::equal(std::begin(key->data.name), std::end(key->data.name),
|
||||
"0..............1"));
|
||||
CU_ASSERT(std::equal(std::begin(key->data.enc_key),
|
||||
std::begin(key->data.enc_key) + 16, "2..............3"));
|
||||
CU_ASSERT(std::equal(std::begin(key->data.hmac_key),
|
||||
std::begin(key->data.hmac_key) + 16,
|
||||
"4..............5"));
|
||||
CU_ASSERT(16 == key->hmac_keylen);
|
||||
assert_true(std::equal(std::begin(key->data.name), std::end(key->data.name),
|
||||
"0..............1"));
|
||||
assert_true(std::equal(std::begin(key->data.enc_key),
|
||||
std::begin(key->data.enc_key) + 16,
|
||||
"2..............3"));
|
||||
assert_true(std::equal(std::begin(key->data.hmac_key),
|
||||
std::begin(key->data.hmac_key) + 16,
|
||||
"4..............5"));
|
||||
assert_size(16, ==, key->hmac_keylen);
|
||||
|
||||
key = &ticket_keys->keys[1];
|
||||
CU_ASSERT(std::equal(std::begin(key->data.name), std::end(key->data.name),
|
||||
"6..............7"));
|
||||
CU_ASSERT(std::equal(std::begin(key->data.enc_key),
|
||||
std::begin(key->data.enc_key) + 16, "8..............9"));
|
||||
CU_ASSERT(std::equal(std::begin(key->data.hmac_key),
|
||||
std::begin(key->data.hmac_key) + 16,
|
||||
"a..............b"));
|
||||
CU_ASSERT(16 == key->hmac_keylen);
|
||||
assert_true(std::equal(std::begin(key->data.name), std::end(key->data.name),
|
||||
"6..............7"));
|
||||
assert_true(std::equal(std::begin(key->data.enc_key),
|
||||
std::begin(key->data.enc_key) + 16,
|
||||
"8..............9"));
|
||||
assert_true(std::equal(std::begin(key->data.hmac_key),
|
||||
std::begin(key->data.hmac_key) + 16,
|
||||
"a..............b"));
|
||||
assert_size(16, ==, key->hmac_keylen);
|
||||
}
|
||||
|
||||
void test_shrpx_config_read_tls_ticket_key_file_aes_256(void) {
|
||||
char file1[] = "/tmp/nghttpx-unittest.XXXXXX";
|
||||
auto fd1 = mkstemp(file1);
|
||||
CU_ASSERT(fd1 != -1);
|
||||
CU_ASSERT(80 == write(fd1,
|
||||
"0..............12..............................34..."
|
||||
"...........................5",
|
||||
80));
|
||||
assert_int(-1, !=, fd1);
|
||||
assert_ssize(80, ==,
|
||||
write(fd1,
|
||||
"0..............12..............................34..."
|
||||
"...........................5",
|
||||
80));
|
||||
char file2[] = "/tmp/nghttpx-unittest.XXXXXX";
|
||||
auto fd2 = mkstemp(file2);
|
||||
CU_ASSERT(fd2 != -1);
|
||||
CU_ASSERT(80 == write(fd2,
|
||||
"6..............78..............................9a..."
|
||||
"...........................b",
|
||||
80));
|
||||
assert_int(-1, !=, fd2);
|
||||
assert_ssize(80, ==,
|
||||
write(fd2,
|
||||
"6..............78..............................9a..."
|
||||
"...........................b",
|
||||
80));
|
||||
|
||||
close(fd1);
|
||||
close(fd2);
|
||||
@@ -223,27 +243,27 @@ void test_shrpx_config_read_tls_ticket_key_file_aes_256(void) {
|
||||
{StringRef{file1}, StringRef{file2}}, EVP_aes_256_cbc(), EVP_sha256());
|
||||
unlink(file1);
|
||||
unlink(file2);
|
||||
CU_ASSERT(ticket_keys.get() != nullptr);
|
||||
CU_ASSERT(2 == ticket_keys->keys.size());
|
||||
assert_not_null(ticket_keys.get());
|
||||
assert_size(2, ==, ticket_keys->keys.size());
|
||||
auto key = &ticket_keys->keys[0];
|
||||
CU_ASSERT(std::equal(std::begin(key->data.name), std::end(key->data.name),
|
||||
"0..............1"));
|
||||
CU_ASSERT(std::equal(std::begin(key->data.enc_key),
|
||||
std::end(key->data.enc_key),
|
||||
"2..............................3"));
|
||||
CU_ASSERT(std::equal(std::begin(key->data.hmac_key),
|
||||
std::end(key->data.hmac_key),
|
||||
"4..............................5"));
|
||||
assert_true(std::equal(std::begin(key->data.name), std::end(key->data.name),
|
||||
"0..............1"));
|
||||
assert_true(std::equal(std::begin(key->data.enc_key),
|
||||
std::end(key->data.enc_key),
|
||||
"2..............................3"));
|
||||
assert_true(std::equal(std::begin(key->data.hmac_key),
|
||||
std::end(key->data.hmac_key),
|
||||
"4..............................5"));
|
||||
|
||||
key = &ticket_keys->keys[1];
|
||||
CU_ASSERT(std::equal(std::begin(key->data.name), std::end(key->data.name),
|
||||
"6..............7"));
|
||||
CU_ASSERT(std::equal(std::begin(key->data.enc_key),
|
||||
std::end(key->data.enc_key),
|
||||
"8..............................9"));
|
||||
CU_ASSERT(std::equal(std::begin(key->data.hmac_key),
|
||||
std::end(key->data.hmac_key),
|
||||
"a..............................b"));
|
||||
assert_true(std::equal(std::begin(key->data.name), std::end(key->data.name),
|
||||
"6..............7"));
|
||||
assert_true(std::equal(std::begin(key->data.enc_key),
|
||||
std::end(key->data.enc_key),
|
||||
"8..............................9"));
|
||||
assert_true(std::equal(std::begin(key->data.hmac_key),
|
||||
std::end(key->data.hmac_key),
|
||||
"a..............................b"));
|
||||
}
|
||||
|
||||
} // namespace shrpx
|
||||
|
||||
@@ -29,13 +29,18 @@
|
||||
# include <config.h>
|
||||
#endif // HAVE_CONFIG_H
|
||||
|
||||
#define MUNIT_ENABLE_ASSERT_ALIASES
|
||||
|
||||
#include "munit.h"
|
||||
|
||||
namespace shrpx {
|
||||
|
||||
void test_shrpx_config_parse_header(void);
|
||||
void test_shrpx_config_parse_log_format(void);
|
||||
void test_shrpx_config_read_tls_ticket_key_file(void);
|
||||
void test_shrpx_config_read_tls_ticket_key_file_aes_256(void);
|
||||
void test_shrpx_config_match_downstream_addr_group(void);
|
||||
extern const MunitSuite config_suite;
|
||||
|
||||
munit_void_test_decl(test_shrpx_config_parse_header);
|
||||
munit_void_test_decl(test_shrpx_config_parse_log_format);
|
||||
munit_void_test_decl(test_shrpx_config_read_tls_ticket_key_file);
|
||||
munit_void_test_decl(test_shrpx_config_read_tls_ticket_key_file_aes_256);
|
||||
|
||||
} // namespace shrpx
|
||||
|
||||
|
||||
@@ -863,7 +863,7 @@ void Connection::start_tls_write_idle() {
|
||||
}
|
||||
}
|
||||
|
||||
ssize_t Connection::write_tls(const void *data, size_t len) {
|
||||
nghttp2_ssize Connection::write_tls(const void *data, size_t len) {
|
||||
// SSL_write requires the same arguments (buf pointer and its
|
||||
// length) on SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE.
|
||||
// get_write_limit() may return smaller length than previously
|
||||
@@ -950,7 +950,7 @@ ssize_t Connection::write_tls(const void *data, size_t len) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
ssize_t Connection::read_tls(void *data, size_t len) {
|
||||
nghttp2_ssize Connection::read_tls(void *data, size_t len) {
|
||||
ERR_clear_error();
|
||||
|
||||
#if defined(NGHTTP2_GENUINE_OPENSSL) || defined(NGHTTP2_OPENSSL_IS_BORINGSSL)
|
||||
@@ -1061,7 +1061,7 @@ ssize_t Connection::read_tls(void *data, size_t len) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
ssize_t Connection::write_clear(const void *data, size_t len) {
|
||||
nghttp2_ssize Connection::write_clear(const void *data, size_t len) {
|
||||
len = std::min(len, wlimit.avail());
|
||||
if (len == 0) {
|
||||
return 0;
|
||||
@@ -1088,7 +1088,7 @@ ssize_t Connection::write_clear(const void *data, size_t len) {
|
||||
return nwrite;
|
||||
}
|
||||
|
||||
ssize_t Connection::writev_clear(struct iovec *iov, int iovcnt) {
|
||||
nghttp2_ssize Connection::writev_clear(struct iovec *iov, int iovcnt) {
|
||||
iovcnt = limit_iovec(iov, iovcnt, wlimit.avail());
|
||||
if (iovcnt == 0) {
|
||||
return 0;
|
||||
@@ -1115,7 +1115,7 @@ ssize_t Connection::writev_clear(struct iovec *iov, int iovcnt) {
|
||||
return nwrite;
|
||||
}
|
||||
|
||||
ssize_t Connection::read_clear(void *data, size_t len) {
|
||||
nghttp2_ssize Connection::read_clear(void *data, size_t len) {
|
||||
len = std::min(len, rlimit.avail());
|
||||
if (len == 0) {
|
||||
return 0;
|
||||
@@ -1140,7 +1140,7 @@ ssize_t Connection::read_clear(void *data, size_t len) {
|
||||
return nread;
|
||||
}
|
||||
|
||||
ssize_t Connection::read_nolim_clear(void *data, size_t len) {
|
||||
nghttp2_ssize Connection::read_nolim_clear(void *data, size_t len) {
|
||||
ssize_t nread;
|
||||
while ((nread = read(fd, data, len)) == -1 && errno == EINTR)
|
||||
;
|
||||
@@ -1158,7 +1158,7 @@ ssize_t Connection::read_nolim_clear(void *data, size_t len) {
|
||||
return nread;
|
||||
}
|
||||
|
||||
ssize_t Connection::peek_clear(void *data, size_t len) {
|
||||
nghttp2_ssize Connection::peek_clear(void *data, size_t len) {
|
||||
ssize_t nread;
|
||||
while ((nread = recv(fd, data, len, MSG_PEEK)) == -1 && errno == EINTR)
|
||||
;
|
||||
|
||||
@@ -33,6 +33,8 @@
|
||||
|
||||
#include <openssl/ssl.h>
|
||||
|
||||
#include <nghttp2/nghttp2.h>
|
||||
|
||||
#ifdef ENABLE_HTTP3
|
||||
# include <ngtcp2/ngtcp2_crypto.h>
|
||||
#endif // ENABLE_HTTP3
|
||||
@@ -128,8 +130,8 @@ struct Connection {
|
||||
// underlying connection blocks), return 0. SHRPX_ERR_EOF is
|
||||
// returned in case of EOF and no data was read. Otherwise
|
||||
// SHRPX_ERR_NETWORK is return in case of error.
|
||||
ssize_t write_tls(const void *data, size_t len);
|
||||
ssize_t read_tls(void *data, size_t len);
|
||||
nghttp2_ssize write_tls(const void *data, size_t len);
|
||||
nghttp2_ssize read_tls(void *data, size_t len);
|
||||
|
||||
size_t get_tls_write_limit();
|
||||
// Updates the number of bytes written in warm up period.
|
||||
@@ -138,13 +140,13 @@ struct Connection {
|
||||
// determine fallback to short record size mode.
|
||||
void start_tls_write_idle();
|
||||
|
||||
ssize_t write_clear(const void *data, size_t len);
|
||||
ssize_t writev_clear(struct iovec *iov, int iovcnt);
|
||||
ssize_t read_clear(void *data, size_t len);
|
||||
nghttp2_ssize write_clear(const void *data, size_t len);
|
||||
nghttp2_ssize writev_clear(struct iovec *iov, int iovcnt);
|
||||
nghttp2_ssize read_clear(void *data, size_t len);
|
||||
// Read at most |len| bytes of data from socket without rate limit.
|
||||
ssize_t read_nolim_clear(void *data, size_t len);
|
||||
nghttp2_ssize read_nolim_clear(void *data, size_t len);
|
||||
// Peek at most |len| bytes of data from socket without rate limit.
|
||||
ssize_t peek_clear(void *data, size_t len);
|
||||
nghttp2_ssize peek_clear(void *data, size_t len);
|
||||
|
||||
void handle_tls_pending_read();
|
||||
|
||||
|
||||
@@ -739,40 +739,31 @@ void ConnectionHandler::handle_ocsp_complete() {
|
||||
// that case we get nullptr.
|
||||
auto quic_ssl_ctx = quic_all_ssl_ctx_[ocsp_.next];
|
||||
if (quic_ssl_ctx) {
|
||||
# ifndef NGHTTP2_OPENSSL_IS_BORINGSSL
|
||||
auto quic_tls_ctx_data = static_cast<tls::TLSContextData *>(
|
||||
SSL_CTX_get_app_data(quic_ssl_ctx));
|
||||
# ifdef HAVE_ATOMIC_STD_SHARED_PTR
|
||||
# ifdef HAVE_ATOMIC_STD_SHARED_PTR
|
||||
std::atomic_store_explicit(
|
||||
&quic_tls_ctx_data->ocsp_data,
|
||||
std::make_shared<std::vector<uint8_t>>(ocsp_.resp),
|
||||
std::memory_order_release);
|
||||
# else // !HAVE_ATOMIC_STD_SHARED_PTR
|
||||
# else // !HAVE_ATOMIC_STD_SHARED_PTR
|
||||
std::lock_guard<std::mutex> g(quic_tls_ctx_data->mu);
|
||||
quic_tls_ctx_data->ocsp_data =
|
||||
std::make_shared<std::vector<uint8_t>>(ocsp_.resp);
|
||||
# endif // !HAVE_ATOMIC_STD_SHARED_PTR
|
||||
# else // NGHTTP2_OPENSSL_IS_BORINGSSL
|
||||
SSL_CTX_set_ocsp_response(quic_ssl_ctx, ocsp_.resp.data(),
|
||||
ocsp_.resp.size());
|
||||
# endif // NGHTTP2_OPENSSL_IS_BORINGSSL
|
||||
# endif // !HAVE_ATOMIC_STD_SHARED_PTR
|
||||
}
|
||||
#endif // ENABLE_HTTP3
|
||||
|
||||
#ifndef NGHTTP2_OPENSSL_IS_BORINGSSL
|
||||
# ifdef HAVE_ATOMIC_STD_SHARED_PTR
|
||||
#ifdef HAVE_ATOMIC_STD_SHARED_PTR
|
||||
std::atomic_store_explicit(
|
||||
&tls_ctx_data->ocsp_data,
|
||||
std::make_shared<std::vector<uint8_t>>(std::move(ocsp_.resp)),
|
||||
std::memory_order_release);
|
||||
# else // !HAVE_ATOMIC_STD_SHARED_PTR
|
||||
#else // !HAVE_ATOMIC_STD_SHARED_PTR
|
||||
std::lock_guard<std::mutex> g(tls_ctx_data->mu);
|
||||
tls_ctx_data->ocsp_data =
|
||||
std::make_shared<std::vector<uint8_t>>(std::move(ocsp_.resp));
|
||||
# endif // !HAVE_ATOMIC_STD_SHARED_PTR
|
||||
#else // NGHTTP2_OPENSSL_IS_BORINGSSL
|
||||
SSL_CTX_set_ocsp_response(ssl_ctx, ocsp_.resp.data(), ocsp_.resp.size());
|
||||
#endif // NGHTTP2_OPENSSL_IS_BORINGSSL
|
||||
#endif // !HAVE_ATOMIC_STD_SHARED_PTR
|
||||
}
|
||||
|
||||
++ocsp_.next;
|
||||
@@ -1288,7 +1279,7 @@ int ConnectionHandler::quic_ipc_read() {
|
||||
|
||||
if (decrypt_quic_connection_id(decrypted_dcid.data(),
|
||||
vc.dcid + SHRPX_QUIC_CID_PREFIX_OFFSET,
|
||||
qkm.cid_encryption_key.data()) != 0) {
|
||||
qkm.cid_encryption_ctx) != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
@@ -26,12 +26,29 @@
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include <CUnit/CUnit.h>
|
||||
#include "munitxx.h"
|
||||
|
||||
#include "shrpx_downstream.h"
|
||||
|
||||
namespace shrpx {
|
||||
|
||||
namespace {
|
||||
const MunitTest tests[]{
|
||||
munit_void_test(test_downstream_field_store_append_last_header),
|
||||
munit_void_test(test_downstream_field_store_header),
|
||||
munit_void_test(test_downstream_crumble_request_cookie),
|
||||
munit_void_test(test_downstream_assemble_request_cookie),
|
||||
munit_void_test(test_downstream_rewrite_location_response_header),
|
||||
munit_void_test(test_downstream_supports_non_final_response),
|
||||
munit_void_test(test_downstream_find_affinity_cookie),
|
||||
munit_test_end(),
|
||||
};
|
||||
} // namespace
|
||||
|
||||
const MunitSuite downstream_suite{
|
||||
"/downstream", tests, NULL, 1, MUNIT_SUITE_OPTION_NONE,
|
||||
};
|
||||
|
||||
void test_downstream_field_store_append_last_header(void) {
|
||||
BlockAllocator balloc(16, 16);
|
||||
FieldStore fs(balloc, 0);
|
||||
@@ -57,7 +74,7 @@ void test_downstream_field_store_append_last_header(void) {
|
||||
HeaderRefs{{StringRef::from_lit("alphabravogolf0123456789"),
|
||||
StringRef::from_lit("CharliedeltAecho0123456789")},
|
||||
{StringRef::from_lit("echo"), StringRef::from_lit("foxtrot")}};
|
||||
CU_ASSERT(ans == fs.headers());
|
||||
assert_true(ans == fs.headers());
|
||||
}
|
||||
|
||||
void test_downstream_field_store_header(void) {
|
||||
@@ -72,14 +89,14 @@ void test_downstream_field_store_header(void) {
|
||||
http2::HD_CONTENT_LENGTH);
|
||||
|
||||
// By token
|
||||
CU_ASSERT(HeaderRef(StringRef{":authority"}, StringRef{"1"}) ==
|
||||
*fs.header(http2::HD__AUTHORITY));
|
||||
CU_ASSERT(nullptr == fs.header(http2::HD__METHOD));
|
||||
assert_true(HeaderRef(StringRef{":authority"}, StringRef{"1"}) ==
|
||||
*fs.header(http2::HD__AUTHORITY));
|
||||
assert_null(fs.header(http2::HD__METHOD));
|
||||
|
||||
// By name
|
||||
CU_ASSERT(HeaderRef(StringRef{"alpha"}, StringRef{"0"}) ==
|
||||
*fs.header(StringRef::from_lit("alpha")));
|
||||
CU_ASSERT(nullptr == fs.header(StringRef::from_lit("bravo")));
|
||||
assert_true(HeaderRef(StringRef{"alpha"}, StringRef{"0"}) ==
|
||||
*fs.header(StringRef::from_lit("alpha")));
|
||||
assert_null(fs.header(StringRef::from_lit("bravo")));
|
||||
}
|
||||
|
||||
void test_downstream_crumble_request_cookie(void) {
|
||||
@@ -103,8 +120,8 @@ void test_downstream_crumble_request_cookie(void) {
|
||||
|
||||
auto num_cookies = d.count_crumble_request_cookie();
|
||||
|
||||
CU_ASSERT(5 == nva.size());
|
||||
CU_ASSERT(5 == num_cookies);
|
||||
assert_size(5, ==, nva.size());
|
||||
assert_size(5, ==, num_cookies);
|
||||
|
||||
HeaderRefs cookies;
|
||||
std::transform(std::begin(nva), std::end(nva), std::back_inserter(cookies),
|
||||
@@ -121,10 +138,10 @@ void test_downstream_crumble_request_cookie(void) {
|
||||
{StringRef::from_lit("cookie"), StringRef::from_lit("delta")},
|
||||
{StringRef::from_lit("cookie"), StringRef::from_lit("echo")}};
|
||||
|
||||
CU_ASSERT(ans == cookies);
|
||||
CU_ASSERT(cookies[0].no_index);
|
||||
CU_ASSERT(cookies[1].no_index);
|
||||
CU_ASSERT(cookies[2].no_index);
|
||||
assert_true(ans == cookies);
|
||||
assert_true(cookies[0].no_index);
|
||||
assert_true(cookies[1].no_index);
|
||||
assert_true(cookies[2].no_index);
|
||||
}
|
||||
|
||||
void test_downstream_assemble_request_cookie(void) {
|
||||
@@ -147,7 +164,8 @@ void test_downstream_assemble_request_cookie(void) {
|
||||
req.fs.add_header_token(StringRef::from_lit("cookie"),
|
||||
StringRef::from_lit("delta;;"), false,
|
||||
http2::HD_COOKIE);
|
||||
CU_ASSERT("alpha; bravo; charlie; delta" == d.assemble_request_cookie());
|
||||
assert_stdstring_equal("alpha; bravo; charlie; delta",
|
||||
d.assemble_request_cookie().str());
|
||||
}
|
||||
|
||||
void test_downstream_rewrite_location_response_header(void) {
|
||||
@@ -161,7 +179,7 @@ void test_downstream_rewrite_location_response_header(void) {
|
||||
false, http2::HD_LOCATION);
|
||||
d.rewrite_location_response_header(StringRef::from_lit("https"));
|
||||
auto location = resp.fs.header(http2::HD_LOCATION);
|
||||
CU_ASSERT("https://localhost:8443/" == (*location).value);
|
||||
assert_stdstring_equal("https://localhost:8443/", (*location).value.str());
|
||||
}
|
||||
|
||||
void test_downstream_supports_non_final_response(void) {
|
||||
@@ -171,27 +189,27 @@ void test_downstream_supports_non_final_response(void) {
|
||||
req.http_major = 3;
|
||||
req.http_minor = 0;
|
||||
|
||||
CU_ASSERT(d.supports_non_final_response());
|
||||
assert_true(d.supports_non_final_response());
|
||||
|
||||
req.http_major = 2;
|
||||
req.http_minor = 0;
|
||||
|
||||
CU_ASSERT(d.supports_non_final_response());
|
||||
assert_true(d.supports_non_final_response());
|
||||
|
||||
req.http_major = 1;
|
||||
req.http_minor = 1;
|
||||
|
||||
CU_ASSERT(d.supports_non_final_response());
|
||||
assert_true(d.supports_non_final_response());
|
||||
|
||||
req.http_major = 1;
|
||||
req.http_minor = 0;
|
||||
|
||||
CU_ASSERT(!d.supports_non_final_response());
|
||||
assert_false(d.supports_non_final_response());
|
||||
|
||||
req.http_major = 0;
|
||||
req.http_minor = 9;
|
||||
|
||||
CU_ASSERT(!d.supports_non_final_response());
|
||||
assert_false(d.supports_non_final_response());
|
||||
}
|
||||
|
||||
void test_downstream_find_affinity_cookie(void) {
|
||||
@@ -217,15 +235,15 @@ void test_downstream_find_affinity_cookie(void) {
|
||||
|
||||
aff = d.find_affinity_cookie(StringRef::from_lit("lb"));
|
||||
|
||||
CU_ASSERT(0xdeadbeef == aff);
|
||||
assert_uint32(0xdeadbeef, ==, aff);
|
||||
|
||||
aff = d.find_affinity_cookie(StringRef::from_lit("LB"));
|
||||
|
||||
CU_ASSERT(0xf1f2f3f4 == aff);
|
||||
assert_uint32(0xf1f2f3f4, ==, aff);
|
||||
|
||||
aff = d.find_affinity_cookie(StringRef::from_lit("short"));
|
||||
|
||||
CU_ASSERT(0 == aff);
|
||||
assert_uint32(0, ==, aff);
|
||||
}
|
||||
|
||||
} // namespace shrpx
|
||||
|
||||
@@ -29,15 +29,21 @@
|
||||
# include <config.h>
|
||||
#endif // HAVE_CONFIG_H
|
||||
|
||||
#define MUNIT_ENABLE_ASSERT_ALIASES
|
||||
|
||||
#include "munit.h"
|
||||
|
||||
namespace shrpx {
|
||||
|
||||
void test_downstream_field_store_append_last_header(void);
|
||||
void test_downstream_field_store_header(void);
|
||||
void test_downstream_crumble_request_cookie(void);
|
||||
void test_downstream_assemble_request_cookie(void);
|
||||
void test_downstream_rewrite_location_response_header(void);
|
||||
void test_downstream_supports_non_final_response(void);
|
||||
void test_downstream_find_affinity_cookie(void);
|
||||
extern const MunitSuite downstream_suite;
|
||||
|
||||
munit_void_test_decl(test_downstream_field_store_append_last_header);
|
||||
munit_void_test_decl(test_downstream_field_store_header);
|
||||
munit_void_test_decl(test_downstream_crumble_request_cookie);
|
||||
munit_void_test_decl(test_downstream_assemble_request_cookie);
|
||||
munit_void_test_decl(test_downstream_rewrite_location_response_header);
|
||||
munit_void_test_decl(test_downstream_supports_non_final_response);
|
||||
munit_void_test_decl(test_downstream_find_affinity_cookie);
|
||||
|
||||
} // namespace shrpx
|
||||
|
||||
|
||||
@@ -167,9 +167,9 @@ std::string colorizeHeaders(const char *hdrs) {
|
||||
return nhdrs;
|
||||
}
|
||||
|
||||
ssize_t select_padding_callback(nghttp2_session *session,
|
||||
const nghttp2_frame *frame, size_t max_payload,
|
||||
void *user_data) {
|
||||
nghttp2_ssize select_padding_callback(nghttp2_session *session,
|
||||
const nghttp2_frame *frame,
|
||||
size_t max_payload, void *user_data) {
|
||||
return std::min(max_payload, frame->hd.length + get_config()->padding);
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user