mirror of
https://github.com/nghttp2/nghttp2.git
synced 2025-12-07 10:38:53 +08:00
Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d13a575837 | ||
|
|
001833c5a4 | ||
|
|
38fb5c2b3f |
128
.clang-format
128
.clang-format
@@ -8,91 +8,56 @@ AlignConsecutiveAssignments:
|
||||
AcrossEmptyLines: false
|
||||
AcrossComments: false
|
||||
AlignCompound: false
|
||||
AlignFunctionPointers: false
|
||||
PadOperators: true
|
||||
AlignConsecutiveBitFields:
|
||||
Enabled: false
|
||||
AcrossEmptyLines: false
|
||||
AcrossComments: false
|
||||
AlignCompound: false
|
||||
AlignFunctionPointers: false
|
||||
PadOperators: true
|
||||
AlignConsecutiveDeclarations:
|
||||
Enabled: false
|
||||
AcrossEmptyLines: false
|
||||
AcrossComments: false
|
||||
AlignCompound: false
|
||||
AlignFunctionPointers: false
|
||||
PadOperators: true
|
||||
AlignConsecutiveMacros:
|
||||
Enabled: false
|
||||
AcrossEmptyLines: false
|
||||
AcrossComments: false
|
||||
AlignCompound: false
|
||||
AlignFunctionPointers: false
|
||||
PadOperators: true
|
||||
AlignConsecutiveShortCaseStatements:
|
||||
Enabled: false
|
||||
AcrossEmptyLines: false
|
||||
AcrossComments: false
|
||||
AlignCaseArrows: false
|
||||
AlignCaseColons: false
|
||||
AlignConsecutiveTableGenBreakingDAGArgColons:
|
||||
Enabled: false
|
||||
AcrossEmptyLines: false
|
||||
AcrossComments: false
|
||||
AlignCompound: false
|
||||
AlignFunctionPointers: false
|
||||
PadOperators: false
|
||||
AlignConsecutiveTableGenCondOperatorColons:
|
||||
Enabled: false
|
||||
AcrossEmptyLines: false
|
||||
AcrossComments: false
|
||||
AlignCompound: false
|
||||
AlignFunctionPointers: false
|
||||
PadOperators: false
|
||||
AlignConsecutiveTableGenDefinitionColons:
|
||||
Enabled: false
|
||||
AcrossEmptyLines: false
|
||||
AcrossComments: false
|
||||
AlignCompound: false
|
||||
AlignFunctionPointers: false
|
||||
PadOperators: false
|
||||
AlignEscapedNewlines: Right
|
||||
AlignOperands: Align
|
||||
AlignTrailingComments:
|
||||
Kind: Always
|
||||
OverEmptyLines: 0
|
||||
AlignTrailingComments: true
|
||||
AllowAllArgumentsOnNextLine: true
|
||||
AllowAllParametersOfDeclarationOnNextLine: true
|
||||
AllowBreakBeforeNoexceptSpecifier: Never
|
||||
AllowShortBlocksOnASingleLine: Never
|
||||
AllowShortCaseExpressionOnASingleLine: true
|
||||
AllowShortCaseLabelsOnASingleLine: false
|
||||
AllowShortCompoundRequirementOnASingleLine: true
|
||||
AllowShortEnumsOnASingleLine: true
|
||||
AllowShortBlocksOnASingleLine: Never
|
||||
AllowShortCaseLabelsOnASingleLine: false
|
||||
AllowShortFunctionsOnASingleLine: All
|
||||
AllowShortIfStatementsOnASingleLine: Never
|
||||
AllowShortLambdasOnASingleLine: All
|
||||
AllowShortIfStatementsOnASingleLine: Never
|
||||
AllowShortLoopsOnASingleLine: false
|
||||
AlwaysBreakAfterDefinitionReturnType: None
|
||||
AlwaysBreakAfterReturnType: None
|
||||
AlwaysBreakBeforeMultilineStrings: false
|
||||
AlwaysBreakTemplateDeclarations: MultiLine
|
||||
AttributeMacros:
|
||||
- __capability
|
||||
BinPackArguments: true
|
||||
BinPackParameters: true
|
||||
BitFieldColonSpacing: Both
|
||||
BraceWrapping:
|
||||
AfterCaseLabel: false
|
||||
AfterClass: false
|
||||
AfterControlStatement: Never
|
||||
AfterEnum: false
|
||||
AfterExternBlock: false
|
||||
AfterFunction: false
|
||||
AfterNamespace: false
|
||||
AfterObjCDeclaration: false
|
||||
AfterStruct: false
|
||||
AfterUnion: false
|
||||
AfterExternBlock: false
|
||||
BeforeCatch: false
|
||||
BeforeElse: false
|
||||
BeforeLambdaBody: false
|
||||
@@ -101,32 +66,33 @@ BraceWrapping:
|
||||
SplitEmptyFunction: true
|
||||
SplitEmptyRecord: true
|
||||
SplitEmptyNamespace: true
|
||||
BreakAdjacentStringLiterals: true
|
||||
BreakAfterAttributes: Leave
|
||||
BreakAfterJavaFieldAnnotations: false
|
||||
BreakAfterReturnType: None
|
||||
BreakArrays: true
|
||||
BreakBeforeBinaryOperators: None
|
||||
BreakBeforeConceptDeclarations: Always
|
||||
BreakBeforeBraces: Attach
|
||||
BreakBeforeInlineASMColon: OnlyMultiline
|
||||
BreakBeforeTernaryOperators: true
|
||||
BreakConstructorInitializers: BeforeColon
|
||||
BreakFunctionDefinitionParameters: false
|
||||
BreakBeforeInheritanceComma: false
|
||||
BreakInheritanceList: BeforeColon
|
||||
BreakBeforeTernaryOperators: true
|
||||
BreakConstructorInitializersBeforeComma: false
|
||||
BreakConstructorInitializers: BeforeColon
|
||||
BreakAfterJavaFieldAnnotations: false
|
||||
BreakStringLiterals: true
|
||||
BreakTemplateDeclarations: MultiLine
|
||||
ColumnLimit: 80
|
||||
CommentPragmas: '^ IWYU pragma:'
|
||||
QualifierAlignment: Leave
|
||||
CompactNamespaces: false
|
||||
ConstructorInitializerIndentWidth: 2
|
||||
ContinuationIndentWidth: 2
|
||||
ConstructorInitializerIndentWidth: 4
|
||||
ContinuationIndentWidth: 4
|
||||
Cpp11BracedListStyle: true
|
||||
DeriveLineEnding: true
|
||||
DerivePointerAlignment: false
|
||||
DisableFormat: false
|
||||
EmptyLineAfterAccessModifier: Never
|
||||
EmptyLineBeforeAccessModifier: LogicalBlock
|
||||
ExperimentalAutoDetectBinPacking: false
|
||||
PackConstructorInitializers: NextLine
|
||||
BasedOnStyle: ''
|
||||
ConstructorInitializerAllOnOneLineOrOnePerLine: false
|
||||
AllowAllConstructorInitializersOnNextLine: true
|
||||
FixNamespaceComments: true
|
||||
ForEachMacros:
|
||||
- foreach
|
||||
@@ -151,35 +117,22 @@ IncludeCategories:
|
||||
IncludeIsMainRegex: '$'
|
||||
IncludeIsMainSourceRegex: ''
|
||||
IndentAccessModifiers: false
|
||||
IndentCaseBlocks: false
|
||||
IndentCaseLabels: false
|
||||
IndentExternBlock: AfterExternBlock
|
||||
IndentCaseBlocks: false
|
||||
IndentGotoLabels: true
|
||||
IndentPPDirectives: AfterHash
|
||||
IndentExternBlock: AfterExternBlock
|
||||
IndentRequiresClause: false
|
||||
IndentWidth: 2
|
||||
IndentWrappedFunctionNames: false
|
||||
InsertBraces: false
|
||||
InsertNewlineAtEOF: false
|
||||
InsertTrailingCommas: None
|
||||
IntegerLiteralSeparator:
|
||||
Binary: 0
|
||||
BinaryMinDigits: 0
|
||||
Decimal: 0
|
||||
DecimalMinDigits: 0
|
||||
Hex: 0
|
||||
HexMinDigits: 0
|
||||
JavaScriptQuotes: Leave
|
||||
JavaScriptWrapImports: true
|
||||
KeepEmptyLines:
|
||||
AtEndOfFile: false
|
||||
AtStartOfBlock: false
|
||||
AtStartOfFile: true
|
||||
KeepEmptyLinesAtTheStartOfBlocks: true
|
||||
LambdaBodyIndentation: Signature
|
||||
LineEnding: DeriveLF
|
||||
MacroBlockBegin: ''
|
||||
MacroBlockEnd: ''
|
||||
MainIncludeChar: Quote
|
||||
MaxEmptyLinesToKeep: 1
|
||||
NamespaceIndentation: None
|
||||
ObjCBinPackProtocolList: Auto
|
||||
@@ -187,44 +140,35 @@ ObjCBlockIndentWidth: 2
|
||||
ObjCBreakBeforeNestedBlockParam: true
|
||||
ObjCSpaceAfterProperty: false
|
||||
ObjCSpaceBeforeProtocolList: true
|
||||
PackConstructorInitializers: NextLine
|
||||
PenaltyBreakAssignment: 2
|
||||
PenaltyBreakBeforeFirstCallParameter: 19
|
||||
PenaltyBreakComment: 300
|
||||
PenaltyBreakFirstLessLess: 120
|
||||
PenaltyBreakOpenParenthesis: 0
|
||||
PenaltyBreakScopeResolution: 500
|
||||
PenaltyBreakString: 1000
|
||||
PenaltyBreakTemplateDeclaration: 10
|
||||
PenaltyExcessCharacter: 1000000
|
||||
PenaltyIndentedWhitespace: 0
|
||||
PenaltyReturnTypeOnItsOwnLine: 60
|
||||
PenaltyIndentedWhitespace: 0
|
||||
PointerAlignment: Right
|
||||
PPIndentWidth: -1
|
||||
QualifierAlignment: Leave
|
||||
ReferenceAlignment: Pointer
|
||||
ReflowComments: true
|
||||
RemoveBracesLLVM: false
|
||||
RemoveParentheses: Leave
|
||||
RemoveSemicolon: false
|
||||
RequiresClausePosition: OwnLine
|
||||
RequiresExpressionIndentation: OuterScope
|
||||
SeparateDefinitionBlocks: Leave
|
||||
ShortNamespaceLines: 1
|
||||
SkipMacroDefinitionBody: false
|
||||
SortIncludes: Never
|
||||
SortJavaStaticImport: Before
|
||||
SortUsingDeclarations: LexicographicNumeric
|
||||
SortUsingDeclarations: true
|
||||
SpaceAfterCStyleCast: false
|
||||
SpaceAfterLogicalNot: false
|
||||
SpaceAfterTemplateKeyword: true
|
||||
SpaceAroundPointerQualifiers: Default
|
||||
SpaceBeforeAssignmentOperators: true
|
||||
SpaceBeforeCaseColon: false
|
||||
SpaceBeforeCpp11BracedList: false
|
||||
SpaceBeforeCtorInitializerColon: true
|
||||
SpaceBeforeInheritanceColon: true
|
||||
SpaceBeforeJsonColon: false
|
||||
SpaceBeforeParens: ControlStatements
|
||||
SpaceBeforeParensOptions:
|
||||
AfterControlStatements: true
|
||||
@@ -233,40 +177,34 @@ SpaceBeforeParensOptions:
|
||||
AfterFunctionDeclarationName: false
|
||||
AfterIfMacros: true
|
||||
AfterOverloadedOperator: false
|
||||
AfterPlacementOperator: true
|
||||
AfterRequiresInClause: false
|
||||
AfterRequiresInExpression: false
|
||||
BeforeNonEmptyParentheses: false
|
||||
SpaceAroundPointerQualifiers: Default
|
||||
SpaceBeforeRangeBasedForLoopColon: true
|
||||
SpaceBeforeSquareBrackets: false
|
||||
SpaceInEmptyBlock: false
|
||||
SpaceInEmptyParentheses: false
|
||||
SpacesBeforeTrailingComments: 1
|
||||
SpacesInAngles: Never
|
||||
SpacesInConditionalStatement: false
|
||||
SpacesInContainerLiterals: true
|
||||
SpacesInCStyleCastParentheses: false
|
||||
SpacesInLineCommentPrefix:
|
||||
Minimum: 1
|
||||
Maximum: -1
|
||||
SpacesInParens: Never
|
||||
SpacesInParensOptions:
|
||||
ExceptDoubleParentheses: false
|
||||
InCStyleCasts: false
|
||||
InConditionalStatements: false
|
||||
InEmptyParentheses: false
|
||||
Other: false
|
||||
SpacesInParentheses: false
|
||||
SpacesInSquareBrackets: false
|
||||
SpaceBeforeSquareBrackets: false
|
||||
BitFieldColonSpacing: Both
|
||||
Standard: Latest
|
||||
StatementAttributeLikeMacros:
|
||||
- Q_EMIT
|
||||
StatementMacros:
|
||||
- Q_UNUSED
|
||||
- QT_REQUIRE_VERSION
|
||||
- munit_void_test_decl
|
||||
- nghttp2_max_def
|
||||
- nghttp2_min_def
|
||||
TableGenBreakInsideDAGArg: DontBreak
|
||||
TabWidth: 8
|
||||
UseCRLF: false
|
||||
UseTab: Never
|
||||
VerilogBreakBetweenInstancePorts: true
|
||||
WhitespaceSensitiveMacros:
|
||||
- STRINGIZE
|
||||
- PP_STRINGIZE
|
||||
|
||||
24
.github/workflows/android.yml
vendored
24
.github/workflows/android.yml
vendored
@@ -1,24 +0,0 @@
|
||||
name: android
|
||||
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- Dockerfile.android
|
||||
- .github/workflows/android.yml
|
||||
branches:
|
||||
- '**'
|
||||
|
||||
permissions: read-all
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-24.04
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
- name: Build
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
file: Dockerfile.android
|
||||
192
.github/workflows/build.yml
vendored
192
.github/workflows/build.yml
vendored
@@ -5,26 +5,25 @@ on: [push, pull_request]
|
||||
permissions: read-all
|
||||
|
||||
env:
|
||||
LIBBPF_VERSION: v1.6.2
|
||||
LIBBPF_VERSION: v1.3.0
|
||||
OPENSSL1_VERSION: 1_1_1w+quic
|
||||
OPENSSL3_VERSION: 3.5.2
|
||||
BORINGSSL_VERSION: 729648fb79df7bc46c145e49b0dfd8d2a24232f1
|
||||
AWSLC_VERSION: v1.58.1
|
||||
NGHTTP3_VERSION: v1.11.0
|
||||
NGTCP2_VERSION: v1.15.1
|
||||
WOLFSSL_VERSION: v5.8.2-stable
|
||||
OPENSSL3_VERSION: 3.1.5+quic
|
||||
BORINGSSL_VERSION: 6ab7c1482bf4cdc91c87bc512aaf68ffb18975ec
|
||||
AWSLC_VERSION: v1.26.0
|
||||
NGHTTP3_VERSION: v1.3.0
|
||||
NGTCP2_VERSION: v1.5.0
|
||||
|
||||
jobs:
|
||||
build-cache:
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-24.04, macos-14, macos-15]
|
||||
os: [ubuntu-22.04, macos-13, macos-14]
|
||||
|
||||
runs-on: ${{ matrix.os }}
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v4
|
||||
- name: Restore libbpf cache
|
||||
id: cache-libbpf
|
||||
uses: actions/cache@v4
|
||||
@@ -49,8 +48,8 @@ jobs:
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
boringssl/build/libcrypto.a
|
||||
boringssl/build/libssl.a
|
||||
boringssl/build/crypto/libcrypto.a
|
||||
boringssl/build/ssl/libssl.a
|
||||
boringssl/include
|
||||
key: ${{ matrix.os }}-boringssl-${{ env.BORINGSSL_VERSION }}
|
||||
- name: Restore aws-lc cache
|
||||
@@ -62,12 +61,6 @@ jobs:
|
||||
aws-lc/build/ssl/libssl.a
|
||||
aws-lc/include
|
||||
key: ${{ matrix.os }}-awslc-${{ env.AWSLC_VERSION }}
|
||||
- name: Restore wolfSSL cache
|
||||
id: cache-wolfssl
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: wolfssl/build
|
||||
key: ${{ matrix.os }}-wolfssl-${{ env.WOLFSSL_VERSION }}
|
||||
- name: Restore nghttp3 cache
|
||||
id: cache-nghttp3
|
||||
uses: actions/cache@v4
|
||||
@@ -93,7 +86,6 @@ jobs:
|
||||
steps.cache-openssl3.outputs.cache-hit != 'true' ||
|
||||
steps.cache-boringssl.outputs.cache-hit != 'true' ||
|
||||
steps.cache-awslc.outputs.cache-hit != 'true' ||
|
||||
steps.cache-wolfssl.outputs.cache-hit != 'true' ||
|
||||
steps.cache-nghttp3.outputs.cache-hit != 'true' ||
|
||||
steps.cache-ngtcp2-openssl1.outputs.cache-hit != 'true' ||
|
||||
steps.cache-ngtcp2-openssl3.outputs.cache-hit != 'true'
|
||||
@@ -104,6 +96,8 @@ jobs:
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install \
|
||||
g++-12 \
|
||||
clang-15 \
|
||||
autoconf \
|
||||
automake \
|
||||
autotools-dev \
|
||||
@@ -118,27 +112,28 @@ jobs:
|
||||
brew install \
|
||||
autoconf \
|
||||
automake \
|
||||
pkg-config \
|
||||
libtool
|
||||
- name: Build libbpf
|
||||
if: steps.cache-libbpf.outputs.cache-hit != 'true' && runner.os == 'Linux'
|
||||
run: |
|
||||
git clone --recursive --shallow-submodules -b ${{ env.LIBBPF_VERSION }} https://github.com/libbpf/libbpf
|
||||
git clone --recursive -b ${{ env.LIBBPF_VERSION }} https://github.com/libbpf/libbpf
|
||||
cd libbpf
|
||||
make -C src install PREFIX=$PWD/build
|
||||
- name: Build quictls/openssl v1.1.1
|
||||
if: steps.cache-openssl1.outputs.cache-hit != 'true'
|
||||
run: |
|
||||
git clone --recursive --shallow-submodules --depth 1 -b OpenSSL_${{ env.OPENSSL1_VERSION }} https://github.com/quictls/openssl openssl1
|
||||
git clone --recursive --depth 1 -b OpenSSL_${{ env.OPENSSL1_VERSION }} https://github.com/quictls/openssl openssl1
|
||||
cd openssl1
|
||||
./config --prefix=$PWD/build
|
||||
make -j"$(nproc 2> /dev/null || sysctl -n hw.ncpu)"
|
||||
make install_sw
|
||||
- name: Build openssl/openssl v3.x
|
||||
- name: Build quictls/openssl v3.x
|
||||
if: steps.cache-openssl3.outputs.cache-hit != 'true'
|
||||
run: |
|
||||
git clone --recursive --shallow-submodules --depth 1 -b openssl-${{ env.OPENSSL3_VERSION }} https://github.com/openssl/openssl openssl3
|
||||
git clone --recursive --depth 1 -b openssl-${{ env.OPENSSL3_VERSION }} https://github.com/quictls/openssl openssl3
|
||||
cd openssl3
|
||||
./config enable-ktls --prefix=$PWD/build
|
||||
./config enable-ktls --prefix=$PWD/build --libdir=$PWD/build/lib
|
||||
make -j"$(nproc 2> /dev/null || sysctl -n hw.ncpu)"
|
||||
make install_sw
|
||||
- name: Build BoringSSL
|
||||
@@ -157,56 +152,42 @@ jobs:
|
||||
- name: Build aws-lc
|
||||
if: steps.cache-awslc.outputs.cache-hit != 'true'
|
||||
run: |
|
||||
git clone --recursive --shallow-submodules --depth 1 -b "${AWSLC_VERSION}" https://github.com/aws/aws-lc
|
||||
git clone --recursive --depth 1 -b "${AWSLC_VERSION}" https://github.com/aws/aws-lc
|
||||
cd aws-lc
|
||||
cmake -B build -DDISABLE_GO=ON
|
||||
make -j"$(nproc 2> /dev/null || sysctl -n hw.ncpu)" -C build
|
||||
- name: Build wolfSSL
|
||||
if: steps.cache-wolfssl.outputs.cache-hit != 'true'
|
||||
run: |
|
||||
git clone --depth 1 -b ${{ env.WOLFSSL_VERSION }} https://github.com/wolfSSL/wolfssl
|
||||
cd wolfssl
|
||||
autoreconf -i
|
||||
./configure --disable-dependency-tracking --prefix=$PWD/build \
|
||||
--enable-all --enable-harden --disable-ech
|
||||
make -j"$(nproc 2> /dev/null || sysctl -n hw.ncpu)"
|
||||
make install
|
||||
- name: Build nghttp3
|
||||
if: steps.cache-nghttp3.outputs.cache-hit != 'true'
|
||||
run: |
|
||||
git clone --recursive --shallow-submodules --depth 1 -b ${{ env.NGHTTP3_VERSION}} https://github.com/ngtcp2/nghttp3
|
||||
git clone --recursive --depth 1 -b ${{ env.NGHTTP3_VERSION}} https://github.com/ngtcp2/nghttp3
|
||||
cd nghttp3
|
||||
autoreconf -i
|
||||
./configure --disable-dependency-tracking --prefix=$PWD/build \
|
||||
--enable-lib-only
|
||||
./configure --prefix=$PWD/build --enable-lib-only
|
||||
make -j"$(nproc 2> /dev/null || sysctl -n hw.ncpu)" check
|
||||
make install
|
||||
- name: Build ngtcp2 + quictls/openssl v1.1.1 + BoringSSL
|
||||
if: steps.cache-ngtcp2-openssl1.outputs.cache-hit != 'true'
|
||||
run: |
|
||||
git clone --recursive --shallow-submodules --depth 1 -b ${{ env.NGTCP2_VERSION }} https://github.com/ngtcp2/ngtcp2 ngtcp2-openssl1
|
||||
git clone --recursive --depth 1 -b ${{ env.NGTCP2_VERSION }} https://github.com/ngtcp2/ngtcp2 ngtcp2-openssl1
|
||||
cd ngtcp2-openssl1
|
||||
autoreconf -i
|
||||
./configure --prefix=$PWD/build --enable-lib-only \
|
||||
PKG_CONFIG_PATH="../openssl1/build/lib/pkgconfig:../wolfssl/build/lib/pkgconfig" \
|
||||
PKG_CONFIG_PATH="../openssl1/build/lib/pkgconfig" \
|
||||
BORINGSSL_CFLAGS="-I$PWD/../boringssl/include/" \
|
||||
BORINGSSL_LIBS="-L$PWD/../boringssl/build -lssl -lcrypto" \
|
||||
--disable-dependency-tracking \
|
||||
--with-boringssl \
|
||||
--with-wolfssl
|
||||
BORINGSSL_LIBS="-L$PWD/../boringssl/build/ssl -lssl -L$PWD/../boringssl/build/crypto -lcrypto" \
|
||||
--with-boringssl
|
||||
make -j"$(nproc 2> /dev/null || sysctl -n hw.ncpu)" check
|
||||
make install
|
||||
- name: Build ngtcp2 + quictls/openssl v3.x + aws-lc
|
||||
if: steps.cache-ngtcp2-openssl3.outputs.cache-hit != 'true'
|
||||
run: |
|
||||
git clone --recursive --shallow-submodules --depth 1 -b ${{ env.NGTCP2_VERSION }} https://github.com/ngtcp2/ngtcp2 ngtcp2-openssl3
|
||||
git clone --recursive --depth 1 -b ${{ env.NGTCP2_VERSION }} https://github.com/ngtcp2/ngtcp2 ngtcp2-openssl3
|
||||
cd ngtcp2-openssl3
|
||||
autoreconf -i
|
||||
./configure --prefix=$PWD/build --enable-lib-only \
|
||||
PKG_CONFIG_PATH="../openssl3/build/lib64/pkgconfig:../openssl3/build/lib/pkgconfig" \
|
||||
PKG_CONFIG_PATH="../openssl3/build/lib/pkgconfig" \
|
||||
BORINGSSL_CFLAGS="-I$PWD/../aws-lc/include/" \
|
||||
BORINGSSL_LIBS="-L$PWD/../aws-lc/build/ssl -lssl -L$PWD/../aws-lc/build/crypto -lcrypto" \
|
||||
--disable-dependency-tracking \
|
||||
--with-boringssl
|
||||
make -j"$(nproc 2> /dev/null || sysctl -n hw.ncpu)" check
|
||||
make install
|
||||
@@ -217,42 +198,46 @@ jobs:
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-24.04, macos-14, macos-15]
|
||||
os: [ubuntu-22.04, macos-13, macos-14]
|
||||
compiler: [gcc, clang]
|
||||
buildtool: [autotools, cmake]
|
||||
http3: [http3, no-http3]
|
||||
openssl: [openssl1, openssl3, boringssl, awslc, wolfssl]
|
||||
openssl: [openssl1, openssl3, boringssl, awslc]
|
||||
exclude:
|
||||
- http3: no-http3
|
||||
- os: macos-13
|
||||
openssl: openssl3
|
||||
- os: macos-14
|
||||
openssl: openssl3
|
||||
- http3: no-http3
|
||||
openssl: openssl3
|
||||
- os: macos-13
|
||||
compiler: gcc
|
||||
- os: macos-15
|
||||
- os: macos-14
|
||||
compiler: gcc
|
||||
- # disable macos cmake because of include path issue
|
||||
os: macos-13
|
||||
buildtool: cmake
|
||||
- # disable macos cmake because of include path issue
|
||||
os: macos-14
|
||||
buildtool: cmake
|
||||
- # disable macos cmake because of include path issue
|
||||
os: macos-15
|
||||
buildtool: cmake
|
||||
- os: macos-14
|
||||
- os: macos-13
|
||||
openssl: boringssl
|
||||
- os: macos-15
|
||||
- os: macos-14
|
||||
openssl: boringssl
|
||||
- openssl: boringssl
|
||||
buildtool: cmake
|
||||
- openssl: boringssl
|
||||
compiler: gcc
|
||||
- os: macos-14
|
||||
- os: macos-13
|
||||
openssl: awslc
|
||||
- os: macos-15
|
||||
- os: macos-14
|
||||
openssl: awslc
|
||||
- openssl: awslc
|
||||
buildtool: cmake
|
||||
- openssl: awslc
|
||||
compiler: gcc
|
||||
include:
|
||||
- os: ubuntu-24.04
|
||||
- os: ubuntu-22.04
|
||||
compiler: clang
|
||||
buildtool: distcheck
|
||||
http3: http3
|
||||
@@ -262,7 +247,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
- name: Linux setup
|
||||
@@ -270,8 +255,8 @@ jobs:
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install \
|
||||
g++-14 \
|
||||
clang-19 \
|
||||
g++-12 \
|
||||
clang-15 \
|
||||
autoconf \
|
||||
automake \
|
||||
autotools-dev \
|
||||
@@ -302,16 +287,20 @@ jobs:
|
||||
run: |
|
||||
brew install \
|
||||
libev \
|
||||
libevent \
|
||||
c-ares \
|
||||
libressl \
|
||||
brotli \
|
||||
autoconf \
|
||||
automake \
|
||||
pkg-config \
|
||||
libtool
|
||||
echo 'PKG_CONFIG_PATH=/usr/local/opt/libressl/lib/pkgconfig:/usr/local/opt/libxml2/lib/pkgconfig' >> $GITHUB_ENV
|
||||
- name: Setup clang (Linux)
|
||||
if: runner.os == 'Linux' && matrix.compiler == 'clang'
|
||||
run: |
|
||||
echo 'CC=clang-19' >> $GITHUB_ENV
|
||||
echo 'CXX=clang++-19' >> $GITHUB_ENV
|
||||
echo 'CC=clang-15' >> $GITHUB_ENV
|
||||
echo 'CXX=clang++-15' >> $GITHUB_ENV
|
||||
- name: Setup clang (MacOS)
|
||||
if: runner.os == 'macOS' && matrix.compiler == 'clang'
|
||||
run: |
|
||||
@@ -320,8 +309,8 @@ jobs:
|
||||
- name: Setup gcc (Linux)
|
||||
if: runner.os == 'Linux' && matrix.compiler == 'gcc'
|
||||
run: |
|
||||
echo 'CC=gcc-14' >> $GITHUB_ENV
|
||||
echo 'CXX=g++-14' >> $GITHUB_ENV
|
||||
echo 'CC=gcc-12' >> $GITHUB_ENV
|
||||
echo 'CXX=g++-12' >> $GITHUB_ENV
|
||||
# g++-12 is known to produce false positive warnings.
|
||||
echo 'CXXFLAGS=-Wno-restrict' >> $GITHUB_ENV
|
||||
- name: Setup gcc (MacOS)
|
||||
@@ -341,13 +330,13 @@ jobs:
|
||||
run: |
|
||||
cd libbpf
|
||||
|
||||
EXTRA_AUTOTOOLS_OPTS="$EXTRA_AUTOTOOLS_OPTS --with-libbpf"
|
||||
EXTRA_CMAKE_OPTS="$EXTRA_CMAKE_OPTS -DWITH_LIBBPF=1"
|
||||
EXTRA_AUTOTOOLS_OPTS="--with-libbpf"
|
||||
EXTRA_CMAKE_OPTS="-DWITH_LIBBPF=1"
|
||||
|
||||
echo 'EXTRA_AUTOTOOLS_OPTS='"$EXTRA_AUTOTOOLS_OPTS" >> $GITHUB_ENV
|
||||
echo 'EXTRA_CMAKE_OPTS='"$EXTRA_CMAKE_OPTS" >> $GITHUB_ENV
|
||||
- name: Setup libev variables
|
||||
if: runner.os == 'macOS'
|
||||
if: matrix.os == 'macos-14'
|
||||
run: |
|
||||
LIBEV_CFLAGS="-I/opt/homebrew/Cellar/libev/4.33/include"
|
||||
LIBEV_LIBS="-L/opt/homebrew/Cellar/libev/4.33/lib -lev"
|
||||
@@ -361,7 +350,7 @@ jobs:
|
||||
path: openssl1/build
|
||||
key: ${{ matrix.os }}-openssl-${{ env.OPENSSL1_VERSION }}
|
||||
fail-on-cache-miss: true
|
||||
- name: Restore openssl/openssl v3.x cache
|
||||
- name: Restore quictls/openssl v3.x cache
|
||||
uses: actions/cache/restore@v4
|
||||
if: matrix.openssl == 'openssl3'
|
||||
with:
|
||||
@@ -373,8 +362,8 @@ jobs:
|
||||
if: matrix.openssl == 'boringssl'
|
||||
with:
|
||||
path: |
|
||||
boringssl/build/libcrypto.a
|
||||
boringssl/build/libssl.a
|
||||
boringssl/build/crypto/libcrypto.a
|
||||
boringssl/build/ssl/libssl.a
|
||||
boringssl/include
|
||||
key: ${{ matrix.os }}-boringssl-${{ env.BORINGSSL_VERSION }}
|
||||
fail-on-cache-miss: true
|
||||
@@ -394,7 +383,7 @@ jobs:
|
||||
cd boringssl
|
||||
|
||||
OPENSSL_CFLAGS="-I$PWD/include/"
|
||||
OPENSSL_LIBS="-L$PWD/build -lssl -lcrypto -pthread"
|
||||
OPENSSL_LIBS="-L$PWD/build/ssl -lssl -L$PWD/build/crypto -lcrypto -pthread"
|
||||
EXTRA_AUTOTOOLS_OPTS="$EXTRA_AUTOTOOLS_OPTS --without-neverbleed --without-jemalloc --disable-examples"
|
||||
|
||||
echo 'OPENSSL_CFLAGS='"$OPENSSL_CFLAGS" >> $GITHUB_ENV
|
||||
@@ -416,21 +405,6 @@ jobs:
|
||||
echo 'BORINGSSL_CFLAGS='"$OPENSSL_CFLAGS" >> $GITHUB_ENV
|
||||
echo 'BORINGSSL_LIBS='"$OPENSSL_LIBS" >> $GITHUB_ENV
|
||||
echo 'EXTRA_AUTOTOOLS_OPTS='"$EXTRA_AUTOTOOLS_OPTS" >> $GITHUB_ENV
|
||||
- name: Restore wolfSSL cache
|
||||
uses: actions/cache/restore@v4
|
||||
if: matrix.openssl == 'wolfssl'
|
||||
with:
|
||||
path: wolfssl/build
|
||||
key: ${{ matrix.os }}-wolfssl-${{ env.WOLFSSL_VERSION }}
|
||||
fail-on-cache-miss: true
|
||||
- name: Set wolfSSL variables
|
||||
if: matrix.openssl == 'wolfssl'
|
||||
run: |
|
||||
EXTRA_AUTOTOOLS_OPTS="$EXTRA_AUTOTOOLS_OPTS --with-wolfssl --without-neverbleed"
|
||||
EXTRA_CMAKE_OPTS="$EXTRA_CMAKE_OPTS -DWITH_WOLFSSL=1 -DWITH_NEVERBLEED=0 -DENABLE_EXAMPLES=0"
|
||||
|
||||
echo 'EXTRA_AUTOTOOLS_OPTS='"$EXTRA_AUTOTOOLS_OPTS" >> $GITHUB_ENV
|
||||
echo 'EXTRA_CMAKE_OPTS='"$EXTRA_CMAKE_OPTS" >> $GITHUB_ENV
|
||||
- name: Restore nghttp3 cache
|
||||
uses: actions/cache/restore@v4
|
||||
if: matrix.http3 == 'http3'
|
||||
@@ -440,7 +414,7 @@ jobs:
|
||||
fail-on-cache-miss: true
|
||||
- name: Restore ngtcp2 + quictls/openssl v1.1.1 cache + BoringSSL
|
||||
uses: actions/cache/restore@v4
|
||||
if: matrix.http3 == 'http3' && (matrix.openssl == 'openssl1' || matrix.openssl == 'boringssl' || matrix.openssl == 'wolfssl')
|
||||
if: matrix.http3 == 'http3' && (matrix.openssl == 'openssl1' || matrix.openssl == 'boringssl')
|
||||
with:
|
||||
path: ngtcp2-openssl1/build
|
||||
key: ${{ matrix.os }}-ngtcp2-${{ env.NGTCP2_VERSION }}-openssl-${{ env.OPENSSL1_VERSION }}
|
||||
@@ -455,18 +429,18 @@ jobs:
|
||||
- name: Setup extra environment variables
|
||||
if: matrix.http3 == 'no-http3'
|
||||
run: |
|
||||
PKG_CONFIG_PATH="$PWD/openssl1/build/lib/pkgconfig:$PWD/openssl3/build/lib64/pkgconfig:$PWD/openssl3/build/lib/pkgconfig:$PWD/wolfssl/build/lib/pkgconfig:$PKG_CONFIG_PATH"
|
||||
LDFLAGS="$LDFLAGS -Wl,-rpath,$PWD/openssl1/build/lib -Wl,-rpath,$PWD/openssl3/build/lib64 -Wl,-rpath,$PWD/openssl3/build/lib"
|
||||
PKG_CONFIG_PATH="$PWD/openssl1/build/lib/pkgconfig:$PWD/openssl3/build/lib/pkgconfig"
|
||||
LDFLAGS="$LDFLAGS -Wl,-rpath,$PWD/openssl1/build/lib -Wl,-rpath,$PWD/openssl3/build/lib"
|
||||
|
||||
echo 'PKG_CONFIG_PATH='"$PKG_CONFIG_PATH" >> $GITHUB_ENV
|
||||
echo 'LDFLAGS='"$LDFLAGS" >> $GITHUB_ENV
|
||||
- name: Setup extra environment variables for HTTP/3
|
||||
if: matrix.http3 == 'http3'
|
||||
run: |
|
||||
PKG_CONFIG_PATH="$PWD/openssl1/build/lib/pkgconfig:$PWD/openssl3/build/lib64/pkgconfig:$PWD/openssl3/build/lib/pkgconfig:$PWD/wolfssl/build/lib/pkgconfig:$PWD/nghttp3/build/lib/pkgconfig:$PWD/ngtcp2-openssl1/build/lib/pkgconfig:$PWD/ngtcp2-openssl3/build/lib/pkgconfig:$PWD/libbpf/build/lib64/pkgconfig:$PKG_CONFIG_PATH"
|
||||
LDFLAGS="$LDFLAGS -Wl,-rpath,$PWD/openssl1/build/lib -Wl,-rpath,$PWD/openssl3/build/lib64 -Wl,-rpath,$PWD/openssl3/build/lib -Wl,-rpath,$PWD/libbpf/build/lib64"
|
||||
EXTRA_AUTOTOOLS_OPTS="$EXTRA_AUTOTOOLS_OPTS --enable-http3"
|
||||
EXTRA_CMAKE_OPTS="$EXTRA_CMAKE_OPTS -DENABLE_HTTP3=1"
|
||||
PKG_CONFIG_PATH="$PWD/openssl1/build/lib/pkgconfig:$PWD/openssl3/build/lib/pkgconfig:$PWD/nghttp3/build/lib/pkgconfig:$PWD/ngtcp2-openssl1/build/lib/pkgconfig:$PWD/ngtcp2-openssl3/build/lib/pkgconfig:$PWD/libbpf/build/lib64/pkgconfig:$PKG_CONFIG_PATH"
|
||||
LDFLAGS="$LDFLAGS -Wl,-rpath,$PWD/openssl1/build/lib -Wl,-rpath,$PWD/openssl3/build/lib -Wl,-rpath,$PWD/libbpf/build/lib64"
|
||||
EXTRA_AUTOTOOLS_OPTS="--enable-http3 $EXTRA_AUTOTOOLS_OPTS"
|
||||
EXTRA_CMAKE_OPTS="-DENABLE_HTTP3=1 $EXTRA_CMAKE_OPTS"
|
||||
|
||||
echo 'PKG_CONFIG_PATH='"$PKG_CONFIG_PATH" >> $GITHUB_ENV
|
||||
echo 'LDFLAGS='"$LDFLAGS" >> $GITHUB_ENV
|
||||
@@ -475,7 +449,7 @@ jobs:
|
||||
- name: Configure autotools
|
||||
run: |
|
||||
autoreconf -i
|
||||
./configure --disable-dependency-tracking
|
||||
./configure
|
||||
- name: Make distribution and unpack
|
||||
if: matrix.buildtool != 'distcheck'
|
||||
run: |
|
||||
@@ -504,14 +478,14 @@ jobs:
|
||||
run: |
|
||||
cd $NGHTTP2_BUILD_DIR
|
||||
|
||||
./configure --disable-dependency-tracking --with-mruby --with-neverbleed --with-libev --with-libbrotlienc --with-libbrotlidec --enable-werror $EXTRA_AUTOTOOLS_OPTS
|
||||
./configure --with-mruby --with-neverbleed --with-libev --with-libbrotlienc --with-libbrotlidec --enable-werror $EXTRA_AUTOTOOLS_OPTS
|
||||
make -j"$(nproc)" check
|
||||
- name: Build nghttp2 with autotools (MacOS)
|
||||
if: matrix.buildtool == 'autotools' && runner.os == 'macOS'
|
||||
run: |
|
||||
cd $NGHTTP2_BUILD_DIR
|
||||
|
||||
./configure --disable-dependency-tracking --with-mruby --with-libev --with-libbrotlienc --with-libbrotlidec --enable-werror $EXTRA_AUTOTOOLS_OPTS
|
||||
./configure --with-mruby --with-libev --with-libbrotlienc --with-libbrotlidec --enable-werror $EXTRA_AUTOTOOLS_OPTS
|
||||
make -j"$(sysctl -n hw.ncpu)" check
|
||||
- name: Build nghttp2 with autotools (distcheck)
|
||||
if: matrix.buildtool == 'distcheck'
|
||||
@@ -527,13 +501,12 @@ jobs:
|
||||
- uses: actions/setup-go@v5
|
||||
if: matrix.buildtool != 'distcheck'
|
||||
with:
|
||||
go-version: "1.24"
|
||||
go-version-file: go.mod
|
||||
- name: Integration test
|
||||
# Integration tests for nghttpx; autotools erases build
|
||||
# artifacts.
|
||||
if: matrix.buildtool != 'distcheck'
|
||||
run: |
|
||||
sudo sh -c 'echo "127.0.0.1 127.0.0.1.nip.io" >> /etc/hosts'
|
||||
cd $NGHTTP2_BUILD_DIR/integration-tests
|
||||
make it
|
||||
|
||||
@@ -542,22 +515,19 @@ jobs:
|
||||
matrix:
|
||||
host: [x86_64-w64-mingw32, i686-w64-mingw32]
|
||||
|
||||
runs-on: ubuntu-24.04
|
||||
runs-on: ubuntu-22.04
|
||||
|
||||
env:
|
||||
HOST: ${{ matrix.host }}
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
- name: Prepare for i386
|
||||
if: matrix.host == 'i686-w64-mingw32'
|
||||
run: |
|
||||
sudo dpkg --add-architecture i386
|
||||
- name: Linux setup
|
||||
run: |
|
||||
sudo dpkg --add-architecture i386
|
||||
sudo apt-get update
|
||||
sudo apt-get install \
|
||||
gcc-mingw-w64 \
|
||||
@@ -570,16 +540,16 @@ jobs:
|
||||
- name: Configure autotools
|
||||
run: |
|
||||
autoreconf -i && \
|
||||
./configure --disable-dependency-tracking --enable-werror \
|
||||
--enable-lib-only --host="$HOST" \
|
||||
./configure --enable-werror --enable-lib-only --host="$HOST" \
|
||||
CFLAGS="-g -O2 -D_WIN32_WINNT=0x0600" LIBS="-pthread"
|
||||
- name: Build nghttp2
|
||||
run: |
|
||||
make -j$(nproc)
|
||||
make -j$(nproc) check TESTS=""
|
||||
- name: Run tests
|
||||
if: matrix.host == 'x86_64-w64-mingw32'
|
||||
run: |
|
||||
export WINEPATH="/usr/${{ matrix.host }}/lib;$(winepath -w /usr/lib/x86_64-linux-gnu/wine/x86_64-windows)"
|
||||
export WINEPATH=/usr/x86_64-w64-mingw32/lib
|
||||
cd tests
|
||||
wine main.exe
|
||||
|
||||
@@ -597,7 +567,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
- uses: microsoft/setup-msbuild@v2
|
||||
@@ -619,10 +589,10 @@ jobs:
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
runs-on: ubuntu-24.04
|
||||
runs-on: ubuntu-22.04
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
submodules: recursive
|
||||
|
||||
6
.github/workflows/docker.yaml
vendored
6
.github/workflows/docker.yaml
vendored
@@ -11,14 +11,14 @@ permissions: read-all
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-24.04
|
||||
runs-on: ubuntu-22.04
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@v4
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
- name: Build
|
||||
uses: docker/build-push-action@v6
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
context: docker
|
||||
build-args: NGHTTP2_BRANCH=${{ github.ref_name }}
|
||||
|
||||
4
.github/workflows/stale.yaml
vendored
4
.github/workflows/stale.yaml
vendored
@@ -6,11 +6,10 @@ on:
|
||||
|
||||
permissions:
|
||||
issues: write
|
||||
actions: write
|
||||
|
||||
jobs:
|
||||
stale:
|
||||
runs-on: ubuntu-24.04
|
||||
runs-on: ubuntu-22.04
|
||||
|
||||
steps:
|
||||
- uses: actions/stale@v9
|
||||
@@ -18,5 +17,4 @@ jobs:
|
||||
stale-issue-message: 'This issue is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 7 days.'
|
||||
days-before-stale: 30
|
||||
days-before-close: 7
|
||||
days-before-pr-stale: -1
|
||||
exempt-all-milestones: true
|
||||
|
||||
3
.gitmodules
vendored
3
.gitmodules
vendored
@@ -8,6 +8,3 @@
|
||||
[submodule "tests/munit"]
|
||||
path = tests/munit
|
||||
url = https://github.com/ngtcp2/munit
|
||||
[submodule "third-party/urlparse"]
|
||||
path = third-party/urlparse
|
||||
url = https://github.com/ngtcp2/urlparse
|
||||
|
||||
12
AUTHORS
12
AUTHORS
@@ -47,7 +47,6 @@ David Beitey
|
||||
David Korczynski
|
||||
David Weekly
|
||||
Deel
|
||||
Deep Chordia
|
||||
Dimitris Apostolou
|
||||
Dmitri Tikhonov
|
||||
Dmitriy Vetutnev
|
||||
@@ -80,7 +79,6 @@ Jonas Kvinge
|
||||
Josh Braegger
|
||||
José F. Calcerrada
|
||||
Kamil Dudka
|
||||
Karthik Dasari
|
||||
Kazuho Oku
|
||||
Kenny (kang-yen) Peng
|
||||
Kenny Peng
|
||||
@@ -90,11 +88,9 @@ LazyHamster
|
||||
Leo Neat
|
||||
Lorenz Nickel
|
||||
Lucas Pardue
|
||||
Lukas Märdian
|
||||
MATSUMOTO Ryosuke
|
||||
Marc Bachmann
|
||||
Marcelo Trylesinski
|
||||
Mark Boddington
|
||||
Matt Rudary
|
||||
Matt Way
|
||||
Michael Kaufmann
|
||||
@@ -106,7 +102,6 @@ Nora Shoemaker
|
||||
Paweł Wegner
|
||||
Pedro Santos
|
||||
Peeyush Aggarwal
|
||||
Peng-Yu Chen
|
||||
Peter Wu
|
||||
Piotr Sikora
|
||||
PufferOverflow
|
||||
@@ -118,11 +113,9 @@ Richard Wolfert
|
||||
Rick Lei
|
||||
Ross Smith II
|
||||
Rudi Heitbaum
|
||||
Ryan Carsten Schmidt
|
||||
Ryo Ota
|
||||
Scott Mitchell
|
||||
Sebastiaan Deckers
|
||||
Sergei Trofimovich
|
||||
Sergey Fedorov
|
||||
Shelley Vohr
|
||||
Simon Frankenberger
|
||||
@@ -136,7 +129,6 @@ Syohei YOSHIDA
|
||||
Tapanito
|
||||
Tatsuhiko Kubo
|
||||
Tatsuhiro Tsujikawa
|
||||
Thomas Devoogdt
|
||||
Tobias Geerinckx-Rice
|
||||
Tom Harwood
|
||||
Tomas Krizek
|
||||
@@ -146,22 +138,18 @@ Vernon Tang
|
||||
Viacheslav Biriukov
|
||||
Viktor Szakats
|
||||
Viktor Szépe
|
||||
Ville Vesilehto
|
||||
Wenfeng Liu
|
||||
William A Rowe Jr
|
||||
Xiaoguang Sun
|
||||
Zachary Turner
|
||||
Zhuoyun Wei
|
||||
acesso
|
||||
ayanamist
|
||||
bmarques1995
|
||||
bxshi
|
||||
clemahieu
|
||||
dalf
|
||||
dawg
|
||||
es
|
||||
fangdingjun
|
||||
feicong
|
||||
hrxi
|
||||
jwchoi
|
||||
kumagi
|
||||
|
||||
141
CMakeLists.txt
141
CMakeLists.txt
@@ -24,13 +24,13 @@
|
||||
|
||||
cmake_minimum_required(VERSION 3.14)
|
||||
# XXX using 1.8.90 instead of 1.9.0-DEV
|
||||
project(nghttp2 VERSION 1.67.0 LANGUAGES C)
|
||||
project(nghttp2 VERSION 1.62.1)
|
||||
|
||||
# See versioning rule:
|
||||
# https://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html
|
||||
set(LT_CURRENT 43)
|
||||
set(LT_REVISION 0)
|
||||
set(LT_AGE 29)
|
||||
set(LT_CURRENT 42)
|
||||
set(LT_REVISION 1)
|
||||
set(LT_AGE 28)
|
||||
|
||||
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH})
|
||||
include(Version)
|
||||
@@ -58,7 +58,6 @@ find_package(Python3 COMPONENTS Interpreter)
|
||||
|
||||
# Auto-detection of features that can be toggled
|
||||
if(NOT ENABLE_LIB_ONLY)
|
||||
enable_language(CXX)
|
||||
find_package(Libev 4.11)
|
||||
find_package(Libcares 1.7.5)
|
||||
find_package(ZLIB 1.2.3)
|
||||
@@ -66,20 +65,20 @@ if(NOT ENABLE_LIB_ONLY)
|
||||
find_package(Libbrotlidec 1.0.9)
|
||||
endif()
|
||||
|
||||
if(WITH_WOLFSSL)
|
||||
find_package(WolfSSL 5.7.0)
|
||||
else()
|
||||
find_package(OpenSSL 1.1.1)
|
||||
find_package(OpenSSL 1.1.1)
|
||||
find_package(Libngtcp2 1.0.0)
|
||||
find_package(Libngtcp2_crypto_quictls 1.0.0)
|
||||
if(LIBNGTCP2_CRYPTO_QUICTLS_FOUND)
|
||||
set(HAVE_LIBNGTCP2_CRYPTO_QUICTLS 1)
|
||||
endif()
|
||||
find_package(Libngtcp2 1.15.0)
|
||||
find_package(Libnghttp3 1.11.0)
|
||||
find_package(Libnghttp3 1.1.0)
|
||||
if(WITH_LIBBPF)
|
||||
find_package(Libbpf 0.7.0)
|
||||
if(NOT LIBBPF_FOUND)
|
||||
message(FATAL_ERROR "libbpf was requested (WITH_LIBBPF=1) but not found.")
|
||||
endif()
|
||||
endif()
|
||||
if((OPENSSL_FOUND OR WOLFSSL_FOUND) AND LIBEV_FOUND AND ZLIB_FOUND)
|
||||
if(OPENSSL_FOUND AND LIBEV_FOUND AND ZLIB_FOUND)
|
||||
set(ENABLE_APP_DEFAULT ON)
|
||||
else()
|
||||
set(ENABLE_APP_DEFAULT OFF)
|
||||
@@ -124,31 +123,30 @@ else()
|
||||
set(HINT_NORETURN)
|
||||
endif()
|
||||
|
||||
if(NOT ENABLE_LIB_ONLY)
|
||||
include(ExtractValidFlags)
|
||||
foreach(_cxx1x_flag -std=c++20)
|
||||
extract_valid_cxx_flags(_cxx1x_flag_supported ${_cxx1x_flag})
|
||||
if(_cxx1x_flag_supported)
|
||||
set(CXX1XCXXFLAGS ${_cxx1x_flag})
|
||||
break()
|
||||
endif()
|
||||
endforeach()
|
||||
include(ExtractValidFlags)
|
||||
foreach(_cxx1x_flag -std=c++20)
|
||||
extract_valid_cxx_flags(_cxx1x_flag_supported ${_cxx1x_flag})
|
||||
if(_cxx1x_flag_supported)
|
||||
set(CXX1XCXXFLAGS ${_cxx1x_flag})
|
||||
break()
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
include(CMakePushCheckState)
|
||||
include(CheckCXXSourceCompiles)
|
||||
cmake_push_check_state()
|
||||
set(CMAKE_REQUIRED_DEFINITIONS "${CXX1XCXXFLAGS}")
|
||||
# Check that std::future is available.
|
||||
check_cxx_source_compiles("
|
||||
#include <vector>
|
||||
#include <future>
|
||||
int main() { std::vector<std::future<int>> v; }" HAVE_STD_FUTURE)
|
||||
# Check that std::map::emplace is available for g++-4.7.
|
||||
check_cxx_source_compiles("
|
||||
#include <map>
|
||||
int main() { std::map<int, int>().emplace(1, 2); }" HAVE_STD_MAP_EMPLACE)
|
||||
cmake_pop_check_state()
|
||||
|
||||
include(CMakePushCheckState)
|
||||
include(CheckCXXSourceCompiles)
|
||||
cmake_push_check_state()
|
||||
set(CMAKE_REQUIRED_DEFINITIONS "${CXX1XCXXFLAGS}")
|
||||
# Check that std::future is available.
|
||||
check_cxx_source_compiles("
|
||||
#include <vector>
|
||||
#include <future>
|
||||
int main() { std::vector<std::future<int>> v; }" HAVE_STD_FUTURE)
|
||||
# Check that std::chrono::time_zone is available.
|
||||
check_cxx_source_compiles("
|
||||
#include <chrono>
|
||||
int main() { auto tz = std::chrono::current_zone(); (void)tz; }" HAVE_STD_CHRONO_TIME_ZONE)
|
||||
cmake_pop_check_state()
|
||||
endif()
|
||||
|
||||
# Checks for libraries.
|
||||
# Additional libraries required for programs under src directory.
|
||||
@@ -176,7 +174,7 @@ add_custom_target(check COMMAND ${CMAKE_CTEST_COMMAND})
|
||||
# openssl (for src)
|
||||
include(CheckSymbolExists)
|
||||
set(HAVE_OPENSSL ${OPENSSL_FOUND})
|
||||
if(NOT ENABLE_LIB_ONLY AND OPENSSL_FOUND)
|
||||
if(OPENSSL_FOUND)
|
||||
set(OPENSSL_INCLUDE_DIRS ${OPENSSL_INCLUDE_DIR})
|
||||
cmake_push_check_state()
|
||||
set(CMAKE_REQUIRED_INCLUDES "${OPENSSL_INCLUDE_DIR}")
|
||||
@@ -184,14 +182,10 @@ if(NOT ENABLE_LIB_ONLY AND OPENSSL_FOUND)
|
||||
if(WIN32)
|
||||
set(CMAKE_REQUIRED_LIBRARIES "${CMAKE_REQUIRED_LIBRARIES}" "ws2_32" "bcrypt")
|
||||
endif()
|
||||
check_symbol_exists("LIBRESSL_VERSION_NUMBER" "openssl/opensslv.h" LIBRESSL_FOUND)
|
||||
if(ENABLE_HTTP3)
|
||||
check_symbol_exists(SSL_provide_quic_data "openssl/ssl.h" HAVE_SSL_PROVIDE_QUIC_DATA)
|
||||
if(NOT HAVE_SSL_PROVIDE_QUIC_DATA)
|
||||
check_symbol_exists(SSL_set_quic_tls_cbs "openssl/ssl.h" HAVE_SSL_SET_QUIC_TLS_CBS)
|
||||
if(NOT HAVE_SSL_SET_QUIC_TLS_CBS)
|
||||
message(WARNING "OpenSSL in ${OPENSSL_LIBRARIES} has neither SSL_provide_quic_data nor SSL_set_quic_tls_cbs. HTTP/3 support cannot be enabled")
|
||||
endif()
|
||||
message(WARNING "OpenSSL in ${OPENSSL_LIBRARIES} does not have SSL_provide_quic_data. HTTP/3 support cannot be enabled")
|
||||
endif()
|
||||
endif()
|
||||
cmake_pop_check_state()
|
||||
@@ -199,22 +193,6 @@ else()
|
||||
set(OPENSSL_INCLUDE_DIRS "")
|
||||
set(OPENSSL_LIBRARIES "")
|
||||
endif()
|
||||
# wolfSSL (for src)
|
||||
set(HAVE_WOLFSSL ${WOLFSSL_FOUND})
|
||||
if(WOLFSSL_FOUND)
|
||||
set(WOLFSSL_INCLUDE_DIRS ${WOLFSSL_INCLUDE_DIR})
|
||||
cmake_push_check_state()
|
||||
set(CMAKE_REQUIRED_INCLUDES "${WOLFSSL_INCLUDE_DIR}")
|
||||
set(CMAKE_REQUIRED_LIBRARIES "${WOLFSSL_LIBRARIES}")
|
||||
check_symbol_exists(SSL_provide_quic_data "wolfssl/options.h;wolfssl/ssl.h" HAVE_WOLFSSL_SSL_PROVIDE_QUIC_DATA)
|
||||
if(NOT HAVE_WOLFSSL_SSL_PROVIDE_QUIC_DATA)
|
||||
message(WARNING "wolfSSL in ${WOLFSSL_LIBRARIES} does not have SSL_provide_quic_data. HTTP/3 support cannot be enabled")
|
||||
endif()
|
||||
cmake_pop_check_state()
|
||||
else()
|
||||
set(WOLFSSL_INCLUDE_DIRS "")
|
||||
set(WOLFSSL_LIBRARIES "")
|
||||
endif()
|
||||
# libev (for src)
|
||||
set(HAVE_LIBEV ${LIBEV_FOUND})
|
||||
set(HAVE_ZLIB ${ZLIB_FOUND})
|
||||
@@ -267,45 +245,13 @@ int main() { enum bpf_stats_type foo; (void)foo; }" HAVE_BPF_STATS_TYPE)
|
||||
endif()
|
||||
|
||||
# The nghttp, nghttpd and nghttpx under src depend on zlib, OpenSSL and libev
|
||||
if(ENABLE_APP AND NOT (ZLIB_FOUND AND (OPENSSL_FOUND OR WOLFSSL_FOUND) AND LIBEV_FOUND))
|
||||
if(ENABLE_APP AND NOT (ZLIB_FOUND AND OPENSSL_FOUND AND LIBEV_FOUND))
|
||||
message(FATAL_ERROR "Applications were requested (ENABLE_APP=1) but dependencies are not met.")
|
||||
endif()
|
||||
|
||||
if(ENABLE_HTTP3)
|
||||
if(HAVE_SSL_PROVIDE_QUIC_DATA AND NOT LIBRESSL_FOUND)
|
||||
find_package(Libngtcp2_crypto_quictls 1.15.0)
|
||||
if(LIBNGTCP2_CRYPTO_QUICTLS_FOUND)
|
||||
set(HAVE_LIBNGTCP2_CRYPTO_QUICTLS 1)
|
||||
endif()
|
||||
elseif(HAVE_SSL_PROVIDE_QUIC_DATA AND LIBRESSL_FOUND)
|
||||
find_package(Libngtcp2_crypto_libressl 1.15.0)
|
||||
if(LIBNGTCP2_CRYPTO_LIBRESSL_FOUND)
|
||||
set(HAVE_LIBNGTCP2_CRYPTO_LIBRESSL 1)
|
||||
endif()
|
||||
elseif(HAVE_WOLFSSL_SSL_PROVIDE_QUIC_DATA)
|
||||
find_package(Libngtcp2_crypto_wolfssl 1.15.0)
|
||||
if(LIBNGTCP2_CRYPTO_WOLFSSL_FOUND)
|
||||
set(HAVE_LIBNGTCP2_CRYPTO_WOLFSSL 1)
|
||||
endif()
|
||||
elseif(HAVE_SSL_SET_QUIC_TLS_CBS)
|
||||
find_package(Libngtcp2_crypto_ossl 1.15.0)
|
||||
if(LIBNGTCP2_CRYPTO_OSSL_FOUND)
|
||||
set(HAVE_LIBNGTCP2_CRYPTO_OSSL 1)
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# HTTP/3 requires libngtcp2 + nghttp3 + one of:
|
||||
#
|
||||
# - quictls/openssl + libngtcp2_crypto_quictls
|
||||
# - libressl + libngtcp2_crypto_libressl
|
||||
# - wolfSSL + libngtcp2_crypto_wolfssl
|
||||
# - openssl/openssl + libngtcp2_crypto_ossl
|
||||
if(ENABLE_HTTP3 AND NOT (LIBNGTCP2_FOUND AND LIBNGHTTP3_FOUND AND
|
||||
((HAVE_SSL_PROVIDE_QUIC_DATA AND NOT LIBRESSL_FOUND AND LIBNGTCP2_CRYPTO_QUICTLS_FOUND) OR
|
||||
(HAVE_SSL_PROVIDE_QUIC_DATA AND LIBRESSL_FOUND AND LIBNGTCP2_CRYPTO_LIBRESSL_FOUND) OR
|
||||
(HAVE_WOLFSSL_SSL_PROVIDE_QUIC_DATA AND LIBNGTCP2_CRYPTO_WOLFSSL_FOUND) OR
|
||||
(HAVE_SSL_SET_QUIC_TLS_CBS AND LIBNGTCP2_CRYPTO_OSSL_FOUND))))
|
||||
# HTTP/3 requires quictls/openssl, libngtcp2, libngtcp2_crypto_quictls
|
||||
# and libnghttp3.
|
||||
if(ENABLE_HTTP3 AND NOT (HAVE_SSL_PROVIDE_QUIC_DATA AND LIBNGTCP2_FOUND AND LIBNGTCP2_CRYPTO_QUICTLS_FOUND AND LIBNGHTTP3_FOUND))
|
||||
message(FATAL_ERROR "HTTP/3 was requested (ENABLE_HTTP3=1) but dependencies are not met.")
|
||||
endif()
|
||||
|
||||
@@ -380,9 +326,8 @@ check_function_exists(_Exit HAVE__EXIT)
|
||||
check_function_exists(accept4 HAVE_ACCEPT4)
|
||||
check_function_exists(clock_gettime HAVE_CLOCK_GETTIME)
|
||||
check_function_exists(mkostemp HAVE_MKOSTEMP)
|
||||
check_function_exists(pipe2 HAVE_PIPE2)
|
||||
|
||||
check_symbol_exists(GetTickCount64 "windows.h;sysinfoapi.h" HAVE_GETTICKCOUNT64)
|
||||
check_symbol_exists(GetTickCount64 sysinfoapi.h HAVE_GETTICKCOUNT64)
|
||||
|
||||
include(CheckSymbolExists)
|
||||
# XXX does this correctly detect initgroups (un)availability on cygwin?
|
||||
@@ -499,6 +444,7 @@ if(ENABLE_DOC)
|
||||
add_subdirectory(doc)
|
||||
endif()
|
||||
add_subdirectory(contrib)
|
||||
add_subdirectory(script)
|
||||
add_subdirectory(bpf)
|
||||
|
||||
|
||||
@@ -526,14 +472,11 @@ message(STATUS "summary of build options:
|
||||
Build Test: ${BUILD_TESTING}
|
||||
Libs:
|
||||
OpenSSL: ${HAVE_OPENSSL} (LIBS='${OPENSSL_LIBRARIES}')
|
||||
wolfSSL: ${HAVE_WOLFSSL} (LIBS='${WOLFSSL_LIBRARIES}')
|
||||
Libxml2: ${HAVE_LIBXML2} (LIBS='${LIBXML2_LIBRARIES}')
|
||||
Libev: ${HAVE_LIBEV} (LIBS='${LIBEV_LIBRARIES}')
|
||||
Libc-ares: ${HAVE_LIBCARES} (LIBS='${LIBCARES_LIBRARIES}')
|
||||
Libngtcp2: ${HAVE_LIBNGTCP2} (LIBS='${LIBNGTCP2_LIBRARIES}')
|
||||
Libngtcp2_crypto_quictls: ${HAVE_LIBNGTCP2_CRYPTO_QUICTLS} (LIBS='${LIBNGTCP2_CRYPTO_QUICTLS_LIBRARIES}')
|
||||
Libngtcp2_crypto_libressl: ${HAVE_LIBNGTCP2_CRYPTO_LIBRESSL} (LIBS='${LIBNGTCP2_CRYPTO_LIBRESSL_LIBRARIES}')
|
||||
Libngtcp2_crypto_wolfssl: ${HAVE_LIBNGTCP2_CRYPTO_WOLFSSL} (LIBS='${LIBNGTCP2_CRYPTO_WOLFSSL_LIBRARIES}')
|
||||
Libnghttp3: ${HAVE_LIBNGHTTP3} (LIBS='${LIBNGHTTP3_LIBRARIES}')
|
||||
Libbpf: ${HAVE_LIBBPF} (LIBS='${LIBBPF_LIBRARIES}')
|
||||
Libevent(SSL): ${HAVE_LIBEVENT_OPENSSL} (LIBS='${LIBEVENT_OPENSSL_LIBRARIES}')
|
||||
|
||||
@@ -25,6 +25,5 @@ option(WITH_JEMALLOC "Use jemalloc"
|
||||
option(WITH_MRUBY "Use mruby")
|
||||
option(WITH_NEVERBLEED "Use neverbleed")
|
||||
option(WITH_LIBBPF "Use libbpf")
|
||||
option(WITH_WOLFSSL "Use wolfSSL")
|
||||
|
||||
# vim: ft=cmake:
|
||||
|
||||
@@ -12,21 +12,21 @@
|
||||
|
||||
|
||||
# Only use standalone-toolchain for reduce size
|
||||
FROM ubuntu:24.04
|
||||
LABEL org.opencontainers.image.authors="Tatsuhiro Tsujikawa"
|
||||
FROM ubuntu:22.04
|
||||
MAINTAINER Tatsuhiro Tsujikawa
|
||||
|
||||
ARG NDK_VERSION=r27c
|
||||
ARG NDK=/root/android-ndk-$NDK_VERSION
|
||||
ARG TOOLCHAIN=$NDK/toolchains/llvm/prebuilt/linux-x86_64
|
||||
ARG TARGET=aarch64-linux-android
|
||||
ARG API=33
|
||||
ARG AR=$TOOLCHAIN/bin/llvm-ar
|
||||
ARG CC=$TOOLCHAIN/bin/$TARGET$API-clang
|
||||
ARG CXX=$TOOLCHAIN/bin/$TARGET$API-clang++
|
||||
ARG LD=$TOOLCHAIN/bin/ld
|
||||
ARG RANDLIB=$TOOLCHAIN/bin/llvm-ranlib
|
||||
ARG STRIP=$TOOLCHAIN/bin/llvm-strip
|
||||
ARG PREFIX=/root/usr/local
|
||||
ENV NDK_VERSION r25b
|
||||
ENV NDK /root/android-ndk-$NDK_VERSION
|
||||
ENV TOOLCHAIN $NDK/toolchains/llvm/prebuilt/linux-x86_64
|
||||
ENV TARGET aarch64-linux-android
|
||||
ENV API 33
|
||||
ENV AR $TOOLCHAIN/bin/llvm-ar
|
||||
ENV CC $TOOLCHAIN/bin/$TARGET$API-clang
|
||||
ENV CXX $TOOLCHAIN/bin/$TARGET$API-clang++
|
||||
ENV LD $TOOLCHAIN/bin/ld
|
||||
ENV RANDLIB $TOOLCHAIN/bin/llvm-ranlib
|
||||
ENV STRIP $TOOLCHAIN/bin/llvm-strip
|
||||
ENV PREFIX /root/usr/local
|
||||
|
||||
WORKDIR /root
|
||||
RUN apt-get update && \
|
||||
@@ -42,11 +42,11 @@ RUN curl -L -O https://dl.google.com/android/repository/android-ndk-$NDK_VERSION
|
||||
rm android-ndk-$NDK_VERSION-linux.zip
|
||||
|
||||
# Setup version of libraries
|
||||
ARG OPENSSL_VERSION=1.1.1w
|
||||
ARG LIBEV_VERSION=4.33
|
||||
ARG ZLIB_VERSION=1.3.1
|
||||
ARG CARES_VERSION=1.18.1
|
||||
ARG NGHTTP2_VERSION=master
|
||||
ENV OPENSSL_VERSION 1.1.1q
|
||||
ENV LIBEV_VERSION 4.33
|
||||
ENV ZLIB_VERSION 1.2.13
|
||||
ENV CARES_VERSION 1.18.1
|
||||
ENV NGHTTP2_VERSION master
|
||||
|
||||
WORKDIR /root/build
|
||||
RUN curl -L -O https://www.openssl.org/source/openssl-$OPENSSL_VERSION.tar.gz && \
|
||||
@@ -65,7 +65,6 @@ RUN curl -L -O http://dist.schmorp.de/libev/Attic/libev-$LIBEV_VERSION.tar.gz &&
|
||||
|
||||
WORKDIR /root/build/libev-$LIBEV_VERSION
|
||||
RUN ./configure \
|
||||
--disable-dependency-tracking \
|
||||
--host=$TARGET \
|
||||
--build=`dpkg-architecture -qDEB_BUILD_GNU_TYPE` \
|
||||
--prefix=$PREFIX \
|
||||
@@ -76,7 +75,7 @@ RUN ./configure \
|
||||
make install
|
||||
|
||||
WORKDIR /root/build
|
||||
RUN curl -L -O https://github.com/madler/zlib/releases/download/v$ZLIB_VERSION/zlib-$ZLIB_VERSION.tar.gz && \
|
||||
RUN curl -L -O https://zlib.net/zlib-$ZLIB_VERSION.tar.gz && \
|
||||
tar xf zlib-$ZLIB_VERSION.tar.gz && \
|
||||
rm zlib-$ZLIB_VERSION.tar.gz
|
||||
|
||||
@@ -91,13 +90,12 @@ RUN HOST=$TARGET \
|
||||
|
||||
|
||||
WORKDIR /root/build
|
||||
RUN curl -L -O https://github.com/c-ares/c-ares/releases/download/cares-1_18_1/c-ares-$CARES_VERSION.tar.gz && \
|
||||
RUN curl -L -O https://c-ares.haxx.se/download/c-ares-$CARES_VERSION.tar.gz && \
|
||||
tar xf c-ares-$CARES_VERSION.tar.gz && \
|
||||
rm c-ares-$CARES_VERSION.tar.gz
|
||||
|
||||
WORKDIR /root/build/c-ares-$CARES_VERSION
|
||||
RUN ./configure \
|
||||
--disable-dependency-tracking \
|
||||
--host=$TARGET \
|
||||
--build=`dpkg-architecture -qDEB_BUILD_GNU_TYPE` \
|
||||
--prefix=$PREFIX \
|
||||
@@ -105,11 +103,10 @@ RUN ./configure \
|
||||
make install
|
||||
|
||||
WORKDIR /root/build
|
||||
RUN git clone --recursive --shallow-submodules https://github.com/nghttp2/nghttp2 -b $NGHTTP2_VERSION --depth 1
|
||||
RUN git clone https://github.com/nghttp2/nghttp2 -b $NGHTTP2_VERSION --depth 1
|
||||
WORKDIR /root/build/nghttp2
|
||||
RUN autoreconf -i && \
|
||||
./configure \
|
||||
--disable-dependency-tracking \
|
||||
--enable-app \
|
||||
--disable-shared \
|
||||
--host=$TARGET \
|
||||
@@ -119,6 +116,6 @@ RUN autoreconf -i && \
|
||||
--disable-threads \
|
||||
CPPFLAGS="-fPIE -I$PREFIX/include" \
|
||||
PKG_CONFIG_LIBDIR="$PREFIX/lib/pkgconfig" \
|
||||
LDFLAGS="-static-libstdc++ -static-libgcc -fPIE -pie -L$PREFIX/lib" && \
|
||||
LDFLAGS="-fPIE -pie -L$PREFIX/lib" && \
|
||||
make && \
|
||||
$STRIP src/nghttpx src/nghttpd src/nghttp
|
||||
|
||||
@@ -20,8 +20,8 @@
|
||||
# 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.
|
||||
SUBDIRS = lib tests third-party src bpf examples integration-tests \
|
||||
doc contrib
|
||||
SUBDIRS = lib third-party src bpf examples tests integration-tests \
|
||||
doc contrib script
|
||||
|
||||
ACLOCAL_AMFLAGS = -I m4
|
||||
|
||||
@@ -46,9 +46,6 @@ EXTRA_DIST = nghttpx.conf.sample proxy.pac.sample android-config android-env \
|
||||
cmake/FindLibngtcp2_crypto_quictls.cmake \
|
||||
cmake/FindLibbrotlienc.cmake \
|
||||
cmake/FindLibbrotlidec.cmake \
|
||||
cmake/FindLibngtcp2_crypto_wolfssl.cmake \
|
||||
cmake/FindLibngtcp2_crypto_ossl.cmake \
|
||||
cmake/FindWolfSSL.cmake \
|
||||
cmake/PickyWarningsC.cmake \
|
||||
cmake/PickyWarningsCXX.cmake
|
||||
|
||||
|
||||
47
README.rst
47
README.rst
@@ -31,8 +31,9 @@ implementation.
|
||||
|
||||
* https://nghttp2.org/ (TLS + ALPN and HTTP/3)
|
||||
|
||||
This endpoint supports ``h2`` and ``http/1.1`` via ALPN and requires
|
||||
TLSv1.2 for HTTP/2 connection.
|
||||
This endpoint supports ``h2``, ``h2-16``, ``h2-14``, and
|
||||
``http/1.1`` via ALPN and requires TLSv1.2 for HTTP/2
|
||||
connection.
|
||||
|
||||
It also supports HTTP/3.
|
||||
|
||||
@@ -60,8 +61,8 @@ To build and run the application programs (``nghttp``, ``nghttpd``,
|
||||
``nghttpx`` and ``h2load``) in the ``src`` directory, the following packages
|
||||
are required:
|
||||
|
||||
* OpenSSL >= 1.1.1; or wolfSSL >= 5.7.0; or LibreSSL >= 3.8.1; or
|
||||
aws-lc >= 1.19.0; or BoringSSL
|
||||
* OpenSSL >= 1.1.1; or LibreSSL >= 3.8.1; or aws-lc >= 1.19.0; or
|
||||
BoringSSL
|
||||
* libev >= 4.11
|
||||
* zlib >= 1.2.3
|
||||
* libc-ares >= 1.7.5
|
||||
@@ -122,13 +123,13 @@ exploited. The neverbleed is disabled by default. To enable it, use
|
||||
To enable the experimental HTTP/3 support for h2load and nghttpx, the
|
||||
following libraries are required:
|
||||
|
||||
* `quictls
|
||||
* `OpenSSL with QUIC support
|
||||
<https://github.com/quictls/openssl/tree/OpenSSL_1_1_1w+quic>`_; or
|
||||
wolfSSL; or LibreSSL (does not support 0RTT); or aws-lc; or
|
||||
LibreSSL (does not support 0RTT); or aws-lc; or
|
||||
`BoringSSL <https://boringssl.googlesource.com/boringssl/>`_ (commit
|
||||
729648fb79df7bc46c145e49b0dfd8d2a24232f1); or OpenSSL >= 3.5.0
|
||||
* `ngtcp2 <https://github.com/ngtcp2/ngtcp2>`_ >= 1.15.0
|
||||
* `nghttp3 <https://github.com/ngtcp2/nghttp3>`_ >= 1.11.0
|
||||
6ab7c1482bf4cdc91c87bc512aaf68ffb18975ec)
|
||||
* `ngtcp2 <https://github.com/ngtcp2/ngtcp2>`_ >= 1.4.0
|
||||
* `nghttp3 <https://github.com/ngtcp2/nghttp3>`_ >= 1.1.0
|
||||
|
||||
Use ``--enable-http3`` configure option to enable HTTP/3 feature for
|
||||
h2load and nghttpx.
|
||||
@@ -143,14 +144,14 @@ Use ``--with-libbpf`` configure option to build eBPF program.
|
||||
libelf-dev is needed to build libbpf.
|
||||
|
||||
For Ubuntu 20.04, you can build libbpf from `the source code
|
||||
<https://github.com/libbpf/libbpf/releases>`_. nghttpx requires eBPF
|
||||
program for reloading its configuration and hot swapping its
|
||||
executable.
|
||||
<https://github.com/libbpf/libbpf/releases/tag/v1.3.0>`_. nghttpx
|
||||
requires eBPF program for reloading its configuration and hot swapping
|
||||
its executable.
|
||||
|
||||
Compiling libnghttp2 C source code requires a C99 compiler. gcc 4.8
|
||||
is known to be adequate. In order to compile the C++ source code,
|
||||
C++20 compliant compiler is required. At least g++ >= 12 and
|
||||
clang++ >= 18 are known to work.
|
||||
C++20 compliant compiler is required. At least g++ >= 1.12 and
|
||||
clang++ >= 1.15 are known to work.
|
||||
|
||||
.. note::
|
||||
|
||||
@@ -340,7 +341,7 @@ Build aws-lc:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
$ git clone --depth 1 -b v1.58.1 https://github.com/aws/aws-lc
|
||||
$ git clone --depth 1 -b v1.26.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
|
||||
@@ -351,7 +352,7 @@ Build nghttp3:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
$ git clone --depth 1 -b v1.11.0 https://github.com/ngtcp2/nghttp3
|
||||
$ git clone --depth 1 -b v1.3.0 https://github.com/ngtcp2/nghttp3
|
||||
$ cd nghttp3
|
||||
$ git submodule update --init --depth 1
|
||||
$ autoreconf -i
|
||||
@@ -364,7 +365,7 @@ Build ngtcp2:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
$ git clone --depth 1 -b v1.15.1 https://github.com/ngtcp2/ngtcp2
|
||||
$ git clone --depth 1 -b v1.5.0 https://github.com/ngtcp2/ngtcp2
|
||||
$ cd ngtcp2
|
||||
$ git submodule update --init --depth 1
|
||||
$ autoreconf -i
|
||||
@@ -380,7 +381,7 @@ from source:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
$ git clone --depth 1 -b v1.6.2 https://github.com/libbpf/libbpf
|
||||
$ git clone --depth 1 -b v1.3.0 https://github.com/libbpf/libbpf
|
||||
$ cd libbpf
|
||||
$ PREFIX=$PWD/build make -C src install
|
||||
$ cd ..
|
||||
@@ -394,7 +395,7 @@ Build nghttp2:
|
||||
$ git submodule update --init
|
||||
$ autoreconf -i
|
||||
$ ./configure --with-mruby --enable-http3 --with-libbpf \
|
||||
CC=clang-19 CXX=clang++-19 \
|
||||
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)
|
||||
@@ -846,10 +847,10 @@ to know how to migrate from earlier releases.
|
||||
|
||||
``nghttpx`` implements `important performance-oriented features
|
||||
<https://istlsfastyet.com/#server-performance>`_ in TLS, such as
|
||||
session IDs, session tickets (with automatic key rotation), dynamic
|
||||
record sizing, ALPN, forward secrecy and HTTP/2. ``nghttpx`` also
|
||||
offers the functionality to share ticket keys among multiple
|
||||
``nghttpx`` instances via memcached.
|
||||
session IDs, session tickets (with automatic key rotation), OCSP
|
||||
stapling, dynamic record sizing, ALPN, forward secrecy and HTTP/2.
|
||||
``nghttpx`` also offers the functionality to share session cache and
|
||||
ticket keys among multiple ``nghttpx`` instances via memcached.
|
||||
|
||||
``nghttpx`` has 2 operation modes:
|
||||
|
||||
|
||||
@@ -63,26 +63,28 @@ typedef __u8 state_t[4][4];
|
||||
dynamically trading ROM for RAM - This can be useful in (embedded)
|
||||
bootloader applications, where ROM is often limited. */
|
||||
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, 0x34, 0x8e,
|
||||
0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23,
|
||||
0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e, 0x08, 0x2e, 0xa1, 0x66,
|
||||
0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25, 0x72,
|
||||
0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65,
|
||||
0xb6, 0x92, 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46,
|
||||
0x57, 0xa7, 0x8d, 0x9d, 0x84, 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a,
|
||||
0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06, 0xd0, 0x2c, 0x1e, 0x8f, 0xca,
|
||||
0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b, 0x3a, 0x91,
|
||||
0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6,
|
||||
0x73, 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8,
|
||||
0x1c, 0x75, 0xdf, 0x6e, 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f,
|
||||
0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b, 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2,
|
||||
0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4, 0x1f, 0xdd, 0xa8,
|
||||
0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f,
|
||||
0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93,
|
||||
0xc9, 0x9c, 0xef, 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb,
|
||||
0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61, 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6,
|
||||
0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d};
|
||||
0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e,
|
||||
0x81, 0xf3, 0xd7, 0xfb, 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87,
|
||||
0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, 0x54, 0x7b, 0x94, 0x32,
|
||||
0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e,
|
||||
0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49,
|
||||
0x6d, 0x8b, 0xd1, 0x25, 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16,
|
||||
0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92, 0x6c, 0x70, 0x48, 0x50,
|
||||
0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84,
|
||||
0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05,
|
||||
0xb8, 0xb3, 0x45, 0x06, 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02,
|
||||
0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b, 0x3a, 0x91, 0x11, 0x41,
|
||||
0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73,
|
||||
0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8,
|
||||
0x1c, 0x75, 0xdf, 0x6e, 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89,
|
||||
0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b, 0xfc, 0x56, 0x3e, 0x4b,
|
||||
0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4,
|
||||
0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59,
|
||||
0x27, 0x80, 0xec, 0x5f, 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d,
|
||||
0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef, 0xa0, 0xe0, 0x3b, 0x4d,
|
||||
0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,
|
||||
0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63,
|
||||
0x55, 0x21, 0x0c, 0x7d};
|
||||
|
||||
/* This function adds the round key to state. The round key is added
|
||||
to the state by an XOR function. */
|
||||
|
||||
@@ -17,18 +17,12 @@ find_library(LIBCARES_LIBRARY
|
||||
)
|
||||
|
||||
if(LIBCARES_INCLUDE_DIR)
|
||||
file(READ "${LIBCARES_INCLUDE_DIR}/ares_version.h" _ares_version_h)
|
||||
string(REGEX REPLACE ".*#define[ \t]+ARES_VERSION_MAJOR[ \t]+([0-9]+).*" "\\1"
|
||||
_ares_version_major ${_ares_version_h})
|
||||
string(REGEX REPLACE ".*#define[ \t]+ARES_VERSION_MINOR[ \t]+([0-9]+).*" "\\1"
|
||||
_ares_version_minor ${_ares_version_h})
|
||||
string(REGEX REPLACE ".*#define[ \t]+ARES_VERSION_PATCH[ \t]+([0-9]+).*" "\\1"
|
||||
_ares_version_patch ${_ares_version_h})
|
||||
set(LIBCARES_VERSION "${_ares_version_major}.${_ares_version_minor}.${_ares_version_patch}")
|
||||
unset(_ares_version_patch)
|
||||
unset(_ares_version_minor)
|
||||
unset(_ares_version_major)
|
||||
unset(_ares_version_h)
|
||||
set(_version_regex "^#define[ \t]+ARES_VERSION_STR[ \t]+\"([^\"]+)\".*")
|
||||
file(STRINGS "${LIBCARES_INCLUDE_DIR}/ares_version.h"
|
||||
LIBCARES_VERSION REGEX "${_version_regex}")
|
||||
string(REGEX REPLACE "${_version_regex}" "\\1"
|
||||
LIBCARES_VERSION "${LIBCARES_VERSION}")
|
||||
unset(_version_regex)
|
||||
endif()
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
|
||||
@@ -1,43 +0,0 @@
|
||||
# - Try to find libngtcp2_crypto_libressl
|
||||
# Once done this will define
|
||||
# LIBNGTCP2_CRYPTO_LIBRESSL_FOUND - System has libngtcp2_crypto_libressl
|
||||
# LIBNGTCP2_CRYPTO_LIBRESSL_INCLUDE_DIRS - The libngtcp2_crypto_libressl include directories
|
||||
# LIBNGTCP2_CRYPTO_LIBRESSL_LIBRARIES - The libraries needed to use libngtcp2_crypto_libressl
|
||||
|
||||
find_package(PkgConfig QUIET)
|
||||
pkg_check_modules(PC_LIBNGTCP2_CRYPTO_LIBRESSL QUIET libngtcp2_crypto_libressl)
|
||||
|
||||
find_path(LIBNGTCP2_CRYPTO_LIBRESSL_INCLUDE_DIR
|
||||
NAMES ngtcp2/ngtcp2_crypto_quictls.h
|
||||
HINTS ${PC_LIBNGTCP2_CRYPTO_LIBRESSL_INCLUDE_DIRS}
|
||||
)
|
||||
find_library(LIBNGTCP2_CRYPTO_LIBRESSL_LIBRARY
|
||||
NAMES ngtcp2_crypto_libressl
|
||||
HINTS ${PC_LIBNGTCP2_CRYPTO_LIBRESSL_LIBRARY_DIRS}
|
||||
)
|
||||
|
||||
if(LIBNGTCP2_CRYPTO_LIBRESSL_INCLUDE_DIR)
|
||||
set(_version_regex "^#define[ \t]+NGTCP2_VERSION[ \t]+\"([^\"]+)\".*")
|
||||
file(STRINGS "${LIBNGTCP2_CRYPTO_LIBRESSL_INCLUDE_DIR}/ngtcp2/version.h"
|
||||
LIBNGTCP2_CRYPTO_LIBRESSL_VERSION REGEX "${_version_regex}")
|
||||
string(REGEX REPLACE "${_version_regex}" "\\1"
|
||||
LIBNGTCP2_CRYPTO_LIBRESSL_VERSION "${LIBNGTCP2_CRYPTO_LIBRESSL_VERSION}")
|
||||
unset(_version_regex)
|
||||
endif()
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
# handle the QUIETLY and REQUIRED arguments and set
|
||||
# LIBNGTCP2_CRYPTO_LIBRESSL_FOUND to TRUE if all listed variables are
|
||||
# TRUE and the requested version matches.
|
||||
find_package_handle_standard_args(Libngtcp2_crypto_libressl REQUIRED_VARS
|
||||
LIBNGTCP2_CRYPTO_LIBRESSL_LIBRARY
|
||||
LIBNGTCP2_CRYPTO_LIBRESSL_INCLUDE_DIR
|
||||
VERSION_VAR LIBNGTCP2_CRYPTO_LIBRESSL_VERSION)
|
||||
|
||||
if(LIBNGTCP2_CRYPTO_LIBRESSL_FOUND)
|
||||
set(LIBNGTCP2_CRYPTO_LIBRESSL_LIBRARIES ${LIBNGTCP2_CRYPTO_LIBRESSL_LIBRARY})
|
||||
set(LIBNGTCP2_CRYPTO_LIBRESSL_INCLUDE_DIRS ${LIBNGTCP2_CRYPTO_LIBRESSL_INCLUDE_DIR})
|
||||
endif()
|
||||
|
||||
mark_as_advanced(LIBNGTCP2_CRYPTO_LIBRESSL_INCLUDE_DIR
|
||||
LIBNGTCP2_CRYPTO_LIBRESSL_LIBRARY)
|
||||
@@ -1,43 +0,0 @@
|
||||
# - Try to find libngtcp2_crypto_ossl
|
||||
# Once done this will define
|
||||
# LIBNGTCP2_CRYPTO_OSSL_FOUND - System has libngtcp2_crypto_ossl
|
||||
# LIBNGTCP2_CRYPTO_OSSL_INCLUDE_DIRS - The libngtcp2_crypto_ossl include directories
|
||||
# LIBNGTCP2_CRYPTO_OSSL_LIBRARIES - The libraries needed to use libngtcp2_crypto_ossl
|
||||
|
||||
find_package(PkgConfig QUIET)
|
||||
pkg_check_modules(PC_LIBNGTCP2_CRYPTO_OSSL QUIET libngtcp2_crypto_ossl)
|
||||
|
||||
find_path(LIBNGTCP2_CRYPTO_OSSL_INCLUDE_DIR
|
||||
NAMES ngtcp2/ngtcp2_crypto_ossl.h
|
||||
HINTS ${PC_LIBNGTCP2_CRYPTO_OSSL_INCLUDE_DIRS}
|
||||
)
|
||||
find_library(LIBNGTCP2_CRYPTO_OSSL_LIBRARY
|
||||
NAMES ngtcp2_crypto_ossl
|
||||
HINTS ${PC_LIBNGTCP2_CRYPTO_OSSL_LIBRARY_DIRS}
|
||||
)
|
||||
|
||||
if(LIBNGTCP2_CRYPTO_OSSL_INCLUDE_DIR)
|
||||
set(_version_regex "^#define[ \t]+NGTCP2_VERSION[ \t]+\"([^\"]+)\".*")
|
||||
file(STRINGS "${LIBNGTCP2_CRYPTO_OSSL_INCLUDE_DIR}/ngtcp2/version.h"
|
||||
LIBNGTCP2_CRYPTO_OSSL_VERSION REGEX "${_version_regex}")
|
||||
string(REGEX REPLACE "${_version_regex}" "\\1"
|
||||
LIBNGTCP2_CRYPTO_OSSL_VERSION "${LIBNGTCP2_CRYPTO_OSSL_VERSION}")
|
||||
unset(_version_regex)
|
||||
endif()
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
# handle the QUIETLY and REQUIRED arguments and set
|
||||
# LIBNGTCP2_CRYPTO_OSSL_FOUND to TRUE if all listed variables are
|
||||
# TRUE and the requested version matches.
|
||||
find_package_handle_standard_args(Libngtcp2_crypto_ossl REQUIRED_VARS
|
||||
LIBNGTCP2_CRYPTO_OSSL_LIBRARY
|
||||
LIBNGTCP2_CRYPTO_OSSL_INCLUDE_DIR
|
||||
VERSION_VAR LIBNGTCP2_CRYPTO_OSSL_VERSION)
|
||||
|
||||
if(LIBNGTCP2_CRYPTO_OSSL_FOUND)
|
||||
set(LIBNGTCP2_CRYPTO_OSSL_LIBRARIES ${LIBNGTCP2_CRYPTO_OSSL_LIBRARY})
|
||||
set(LIBNGTCP2_CRYPTO_OSSL_INCLUDE_DIRS ${LIBNGTCP2_CRYPTO_OSSL_INCLUDE_DIR})
|
||||
endif()
|
||||
|
||||
mark_as_advanced(LIBNGTCP2_CRYPTO_OSSL_INCLUDE_DIR
|
||||
LIBNGTCP2_CRYPTO_OSSL_LIBRARY)
|
||||
@@ -1,43 +0,0 @@
|
||||
# - Try to find libngtcp2_crypto_wolfssl
|
||||
# Once done this will define
|
||||
# LIBNGTCP2_CRYPTO_WOLFSSL_FOUND - System has libngtcp2_crypto_wolfssl
|
||||
# LIBNGTCP2_CRYPTO_WOLFSSL_INCLUDE_DIRS - The libngtcp2_crypto_wolfssl include directories
|
||||
# LIBNGTCP2_CRYPTO_WOLFSSL_LIBRARIES - The libraries needed to use libngtcp2_crypto_wolfssl
|
||||
|
||||
find_package(PkgConfig QUIET)
|
||||
pkg_check_modules(PC_LIBNGTCP2_CRYPTO_WOLFSSL QUIET libngtcp2_crypto_wolfssl)
|
||||
|
||||
find_path(LIBNGTCP2_CRYPTO_WOLFSSL_INCLUDE_DIR
|
||||
NAMES ngtcp2/ngtcp2_crypto_wolfssl.h
|
||||
HINTS ${PC_LIBNGTCP2_CRYPTO_WOLFSSL_INCLUDE_DIRS}
|
||||
)
|
||||
find_library(LIBNGTCP2_CRYPTO_WOLFSSL_LIBRARY
|
||||
NAMES ngtcp2_crypto_wolfssl
|
||||
HINTS ${PC_LIBNGTCP2_CRYPTO_WOLFSSL_LIBRARY_DIRS}
|
||||
)
|
||||
|
||||
if(LIBNGTCP2_CRYPTO_WOLFSSL_INCLUDE_DIR)
|
||||
set(_version_regex "^#define[ \t]+NGTCP2_VERSION[ \t]+\"([^\"]+)\".*")
|
||||
file(STRINGS "${LIBNGTCP2_CRYPTO_WOLFSSL_INCLUDE_DIR}/ngtcp2/version.h"
|
||||
LIBNGTCP2_CRYPTO_WOLFSSL_VERSION REGEX "${_version_regex}")
|
||||
string(REGEX REPLACE "${_version_regex}" "\\1"
|
||||
LIBNGTCP2_CRYPTO_WOLFSSL_VERSION "${LIBNGTCP2_CRYPTO_WOLFSSL_VERSION}")
|
||||
unset(_version_regex)
|
||||
endif()
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
# handle the QUIETLY and REQUIRED arguments and set
|
||||
# LIBNGTCP2_CRYPTO_WOLFSSL_FOUND to TRUE if all listed variables are
|
||||
# TRUE and the requested version matches.
|
||||
find_package_handle_standard_args(Libngtcp2_crypto_wolfssl REQUIRED_VARS
|
||||
LIBNGTCP2_CRYPTO_WOLFSSL_LIBRARY
|
||||
LIBNGTCP2_CRYPTO_WOLFSSL_INCLUDE_DIR
|
||||
VERSION_VAR LIBNGTCP2_CRYPTO_WOLFSSL_VERSION)
|
||||
|
||||
if(LIBNGTCP2_CRYPTO_WOLFSSL_FOUND)
|
||||
set(LIBNGTCP2_CRYPTO_WOLFSSL_LIBRARIES ${LIBNGTCP2_CRYPTO_WOLFSSL_LIBRARY})
|
||||
set(LIBNGTCP2_CRYPTO_WOLFSSL_INCLUDE_DIRS ${LIBNGTCP2_CRYPTO_WOLFSSL_INCLUDE_DIR})
|
||||
endif()
|
||||
|
||||
mark_as_advanced(LIBNGTCP2_CRYPTO_WOLFSSL_INCLUDE_DIR
|
||||
LIBNGTCP2_CRYPTO_WOLFSSL_LIBRARY)
|
||||
@@ -1,41 +0,0 @@
|
||||
# - Try to find wolfssl
|
||||
# Once done this will define
|
||||
# WOLFSSL_FOUND - System has wolfssl
|
||||
# WOLFSSL_INCLUDE_DIRS - The wolfssl include directories
|
||||
# WOLFSSL_LIBRARIES - The libraries needed to use wolfssl
|
||||
|
||||
find_package(PkgConfig QUIET)
|
||||
pkg_check_modules(PC_WOLFSSL QUIET wolfssl)
|
||||
|
||||
find_path(WOLFSSL_INCLUDE_DIR
|
||||
NAMES wolfssl/ssl.h
|
||||
HINTS ${PC_WOLFSSL_INCLUDE_DIRS}
|
||||
)
|
||||
find_library(WOLFSSL_LIBRARY
|
||||
NAMES wolfssl
|
||||
HINTS ${PC_WOLFSSL_LIBRARY_DIRS}
|
||||
)
|
||||
|
||||
if(WOLFSSL_INCLUDE_DIR)
|
||||
set(_version_regex "^#define[ \t]+LIBWOLFSSL_VERSION_STRING[ \t]+\"([^\"]+)\".*")
|
||||
file(STRINGS "${WOLFSSL_INCLUDE_DIR}/wolfssl/version.h"
|
||||
WOLFSSL_VERSION REGEX "${_version_regex}")
|
||||
string(REGEX REPLACE "${_version_regex}" "\\1"
|
||||
WOLFSSL_VERSION "${WOLFSSL_VERSION}")
|
||||
unset(_version_regex)
|
||||
endif()
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
# handle the QUIETLY and REQUIRED arguments and set WOLFSSL_FOUND
|
||||
# to TRUE if all listed variables are TRUE and the requested version
|
||||
# matches.
|
||||
find_package_handle_standard_args(WolfSSL REQUIRED_VARS
|
||||
WOLFSSL_LIBRARY WOLFSSL_INCLUDE_DIR
|
||||
VERSION_VAR WOLFSSL_VERSION)
|
||||
|
||||
if(WOLFSSL_FOUND)
|
||||
set(WOLFSSL_LIBRARIES ${WOLFSSL_LIBRARY})
|
||||
set(WOLFSSL_INCLUDE_DIRS ${WOLFSSL_INCLUDE_DIR})
|
||||
endif()
|
||||
|
||||
mark_as_advanced(WOLFSSL_INCLUDE_DIR WOLFSSL_LIBRARY)
|
||||
@@ -58,10 +58,6 @@ if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID
|
||||
list(APPEND WPICKY_ENABLE
|
||||
${WPICKY_COMMON_OLD}
|
||||
)
|
||||
list(APPEND WPICKY_ENABLE
|
||||
# clang++-18 warns this when building with wolfSSL >= v5.7.6-stable.
|
||||
-Wno-extern-c-compat
|
||||
)
|
||||
# Enable based on compiler version
|
||||
if((CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 3.6) OR
|
||||
(CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang" AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 6.3))
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
/* Define to `int' if <sys/types.h> does not define. */
|
||||
#cmakedefine ssize_t @ssize_t@
|
||||
|
||||
/* Define to 1 if you have the `std::chrono::time_zone`. */
|
||||
#cmakedefine HAVE_STD_CHRONO_TIME_ZONE 1
|
||||
/* Define to 1 if you have the `std::map::emplace`. */
|
||||
#cmakedefine HAVE_STD_MAP_EMPLACE 1
|
||||
|
||||
/* Define to 1 if you have `libjansson` library. */
|
||||
#cmakedefine HAVE_JANSSON 1
|
||||
@@ -31,9 +31,6 @@
|
||||
/* Define to 1 if you have the `mkostemp` function. */
|
||||
#cmakedefine HAVE_MKOSTEMP 1
|
||||
|
||||
/* Define to 1 if you have the `pipe2` function. */
|
||||
#cmakedefine HAVE_PIPE2 1
|
||||
|
||||
/* Define to 1 if you have the `GetTickCount64` function. */
|
||||
#cmakedefine HAVE_GETTICKCOUNT64 1
|
||||
|
||||
@@ -100,17 +97,8 @@
|
||||
/* Define to 1 if you have `libngtcp2_crypto_quictls` library. */
|
||||
#cmakedefine HAVE_LIBNGTCP2_CRYPTO_QUICTLS
|
||||
|
||||
/* Define to 1 if you have `libngtcp2_crypto_libressl` library. */
|
||||
#cmakedefine HAVE_LIBNGTCP2_CRYPTO_LIBRESSL
|
||||
|
||||
/* Define to 1 if you have `libngtcp2_crypto_wolfssl` library. */
|
||||
#cmakedefine HAVE_LIBNGTCP2_CRYPTO_WOLFSSL 1
|
||||
|
||||
/* 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
|
||||
|
||||
/* Define to 1 if you have `wolfssl` library. */
|
||||
#cmakedefine HAVE_WOLFSSL 1
|
||||
|
||||
209
configure.ac
209
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.67.0], [t-tujikawa@users.sourceforge.net])
|
||||
AC_INIT([nghttp2], [1.62.1], [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, 43)
|
||||
AC_SUBST(LT_REVISION, 0)
|
||||
AC_SUBST(LT_AGE, 29)
|
||||
AC_SUBST(LT_CURRENT, 42)
|
||||
AC_SUBST(LT_REVISION, 1)
|
||||
AC_SUBST(LT_AGE, 28)
|
||||
|
||||
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"`
|
||||
@@ -127,11 +127,6 @@ AC_ARG_WITH([libcares],
|
||||
[Use libc-ares [default=check]])],
|
||||
[request_libcares=$withval], [request_libcares=check])
|
||||
|
||||
AC_ARG_WITH([wolfssl],
|
||||
[AS_HELP_STRING([--with-wolfssl],
|
||||
[Use wolfSSL [default=check]])],
|
||||
[request_wolfssl=$withval], [request_wolfssl=check])
|
||||
|
||||
AC_ARG_WITH([openssl],
|
||||
[AS_HELP_STRING([--with-openssl],
|
||||
[Use openssl [default=check]])],
|
||||
@@ -272,6 +267,22 @@ std::vector<std::future<int>> v;
|
||||
[have_std_future=no
|
||||
AC_MSG_RESULT([no])])
|
||||
|
||||
# Check that std::map::emplace is available for g++-4.7.
|
||||
AC_MSG_CHECKING([whether std::map::emplace is available])
|
||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM(
|
||||
[[
|
||||
#include <map>
|
||||
]],
|
||||
[[
|
||||
std::map<int, int>().emplace(1, 2);
|
||||
]])],
|
||||
[AC_DEFINE([HAVE_STD_MAP_EMPLACE], [1],
|
||||
[Define to 1 if you have the `std::map::emplace`.])
|
||||
have_std_map_emplace=yes
|
||||
AC_MSG_RESULT([yes])],
|
||||
[have_std_map_emplace=no
|
||||
AC_MSG_RESULT([no])])
|
||||
|
||||
# Check that std::atomic<std::shared_ptr<T>> is supported.
|
||||
AC_MSG_CHECKING([whether std::atomic<std::shared_ptr<T>> is supported])
|
||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM(
|
||||
@@ -291,21 +302,19 @@ a.store(p);
|
||||
[have_atomic_std_shared_ptr=no
|
||||
AC_MSG_RESULT([no])])
|
||||
|
||||
# Check that std::chrono::time_zone is available.
|
||||
AC_MSG_CHECKING([whether std::chrono::time_zone is available])
|
||||
# Check that thread_local storage specifier is available
|
||||
AC_MSG_CHECKING([whether thread_local storage class specifier is available.])
|
||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM(
|
||||
,
|
||||
[[
|
||||
#include <chrono>
|
||||
]],
|
||||
[[
|
||||
auto tz = std::chrono::current_zone();
|
||||
(void)tz;
|
||||
thread_local int a = 0;
|
||||
(void)a;
|
||||
]])],
|
||||
[AC_DEFINE([HAVE_STD_CHRONO_TIME_ZONE], [1],
|
||||
[Define to 1 if you have the `std::chrono::time_zone`.])
|
||||
have_std_chrono_time_zone=yes
|
||||
[AC_DEFINE([HAVE_THREAD_LOCAL], [1],
|
||||
[Define to 1 if you have thread_local storage specifier.])
|
||||
have_thread_local=yes
|
||||
AC_MSG_RESULT([yes])],
|
||||
[have_std_chrono_time_zone=no
|
||||
[have_Thread_local=no
|
||||
AC_MSG_RESULT([no])])
|
||||
|
||||
CXXFLAGS=$save_CXXFLAGS
|
||||
@@ -324,7 +333,7 @@ case "$host_os" in
|
||||
*android*)
|
||||
android_build=yes
|
||||
# android does not need -pthread, but needs following 2 libs for C++
|
||||
APPLDFLAGS="$APPLDFLAGS -latomic"
|
||||
APPLDFLAGS="$APPLDFLAGS -lstdc++ -latomic"
|
||||
;;
|
||||
*)
|
||||
PTHREAD_LDFLAGS="-pthread"
|
||||
@@ -402,15 +411,9 @@ if test "x${request_libev}" = "xyes" &&
|
||||
AC_MSG_ERROR([libev was requested (--with-libev) but not found])
|
||||
fi
|
||||
|
||||
if test "x${request_openssl}" = "xyes" &&
|
||||
test "x${request_wolfssl}" = "xyes"; then
|
||||
AC_MSG_ERROR([Requesting both OpenSSL and wolfSSL is not allowed])
|
||||
fi
|
||||
|
||||
# openssl (for src)
|
||||
have_openssl=no
|
||||
if test "x${request_openssl}" != "xno" &&
|
||||
test "x${request_wolfssl}" != "xyes"; then
|
||||
if test "x${request_openssl}" != "xno"; then
|
||||
PKG_CHECK_MODULES([OPENSSL], [openssl >= 1.1.1],
|
||||
[have_openssl=yes], [have_openssl=no])
|
||||
if test "x${have_openssl}" = "xno"; then
|
||||
@@ -436,22 +439,6 @@ if test "x${request_openssl}" != "xno" &&
|
||||
[AC_MSG_RESULT([yes]); have_ssl_provide_quic_data=yes],
|
||||
[AC_MSG_RESULT([no]); have_ssl_provide_quic_data=no])
|
||||
|
||||
# Check whether this is libressl or not
|
||||
AC_CHECK_DECLS([LIBRESSL_VERSION_NUMBER],
|
||||
[have_libressl=yes], [have_libressl=no],
|
||||
[[
|
||||
#include <openssl/opensslv.h>
|
||||
]])
|
||||
|
||||
AC_MSG_CHECKING([for SSL_set_quic_tls_cbs])
|
||||
AC_LINK_IFELSE([AC_LANG_PROGRAM([[
|
||||
#include <openssl/ssl.h>
|
||||
]], [[
|
||||
SSL_set_quic_tls_cbs(NULL, NULL, NULL);
|
||||
]])],
|
||||
[AC_MSG_RESULT([yes]); have_ossl_quic=yes],
|
||||
[AC_MSG_RESULT([no]); have_ossl_quic=no])
|
||||
|
||||
# boringssl has SSL_set_quic_early_data_context.
|
||||
AC_MSG_CHECKING([for SSL_set_quic_early_data_context])
|
||||
AC_LINK_IFELSE([AC_LANG_PROGRAM([[
|
||||
@@ -475,45 +462,6 @@ if test "x${request_openssl}" = "xyes" &&
|
||||
AC_MSG_ERROR([openssl was requested (--with-openssl) but not found])
|
||||
fi
|
||||
|
||||
# wolfSSL (for src)
|
||||
have_wolfssl=no
|
||||
if test "x${request_wolfssl}" != "xno" &&
|
||||
test "x${request_openssl}" != "xyes" &&
|
||||
test "x${have_openssl}" != "xyes"; then
|
||||
PKG_CHECK_MODULES([WOLFSSL], [wolfssl >= 5.7.0],
|
||||
[have_wolfssl=yes], [have_wolfssl=no])
|
||||
if test "x${have_wolfssl}" = "xno"; then
|
||||
AC_MSG_NOTICE($WOLFSSL_PKG_ERRORS)
|
||||
else
|
||||
AC_DEFINE([HAVE_WOLFSSL], [1],
|
||||
[Define to 1 if you have 'wolfssl' library.])
|
||||
|
||||
save_CFLAGS="$CFLAGS"
|
||||
save_LIBS="$LIBS"
|
||||
CFLAGS="$WOLFSSL_CFLAGS $CFLAGS"
|
||||
LIBS="$WOLFSSL_LIBS $LIBS"
|
||||
|
||||
have_wolfssl_quic=no
|
||||
AC_MSG_CHECKING([for wolfSSL QUIC])
|
||||
AC_LINK_IFELSE([AC_LANG_PROGRAM([[
|
||||
#include <wolfssl/options.h>
|
||||
#include <wolfssl/openssl/ssl.h>
|
||||
]], [[
|
||||
SSL_provide_quic_data(NULL, 0, NULL, 0);
|
||||
]])],
|
||||
[AC_MSG_RESULT([yes]); have_wolfssl_quic=yes],
|
||||
[AC_MSG_RESULT([no]); have_wolfssl_quic=no])
|
||||
|
||||
CFLAGS="$save_CFLAGS"
|
||||
LIBS="$save_LIBS"
|
||||
fi
|
||||
fi
|
||||
|
||||
if test "x${request_wolfssl}" = "xyes" &&
|
||||
test "x${have_wolfssl}" != "xyes"; then
|
||||
AC_MSG_ERROR([wolfSSL was requested (--with-wolfssl) but not found])
|
||||
fi
|
||||
|
||||
# c-ares (for src)
|
||||
have_libcares=no
|
||||
if test "x${request_libcares}" != "xno"; then
|
||||
@@ -532,7 +480,7 @@ fi
|
||||
# ngtcp2 (for src)
|
||||
have_libngtcp2=no
|
||||
if test "x${request_libngtcp2}" != "xno"; then
|
||||
PKG_CHECK_MODULES([LIBNGTCP2], [libngtcp2 >= 1.15.0], [have_libngtcp2=yes],
|
||||
PKG_CHECK_MODULES([LIBNGTCP2], [libngtcp2 >= 1.4.0], [have_libngtcp2=yes],
|
||||
[have_libngtcp2=no])
|
||||
if test "x${have_libngtcp2}" = "xno"; then
|
||||
AC_MSG_NOTICE($LIBNGTCP2_PKG_ERRORS)
|
||||
@@ -544,36 +492,13 @@ if test "x${request_libngtcp2}" = "xyes" &&
|
||||
AC_MSG_ERROR([libngtcp2 was requested (--with-libngtcp2) but not found])
|
||||
fi
|
||||
|
||||
# ngtcp2_crypto_wolfssl (for src)
|
||||
have_libngtcp2_crypto_wolfssl=no
|
||||
if test "x${have_wolfssl_quic}" = "xyes" &&
|
||||
test "x${request_libngtcp2}" != "xno"; then
|
||||
PKG_CHECK_MODULES([LIBNGTCP2_CRYPTO_WOLFSSL],
|
||||
[libngtcp2_crypto_wolfssl >= 1.15.0],
|
||||
[have_libngtcp2_crypto_wolfssl=yes],
|
||||
[have_libngtcp2_crypto_wolfssl=no])
|
||||
if test "x${have_libngtcp2_crypto_wolfssl}" = "xno"; then
|
||||
AC_MSG_NOTICE($LIBNGTCP2_CRYPTO_WOLFSSL_PKG_ERRORS)
|
||||
else
|
||||
AC_DEFINE([HAVE_LIBNGTCP2_CRYPTO_WOLFSSL], [1],
|
||||
[Define to 1 if you have `libngtcp2_crypto_wolfssl` library.])
|
||||
fi
|
||||
fi
|
||||
|
||||
if test "x${have_wolfssl_quic}" = "xyes" &&
|
||||
test "x${request_libngtcp2}" = "xyes" &&
|
||||
test "x${have_libngtcp2_crypto_wolfssl}" != "xyes"; then
|
||||
AC_MSG_ERROR([libngtcp2_crypto_wolfssl was requested (--with-libngtcp2) but not found])
|
||||
fi
|
||||
|
||||
# ngtcp2_crypto_quictls (for src)
|
||||
have_libngtcp2_crypto_quictls=no
|
||||
if test "x${have_ssl_provide_quic_data}" = "xyes" &&
|
||||
test "x${have_libressl}" != "xyes" &&
|
||||
test "x${have_boringssl_quic}" != "xyes" &&
|
||||
test "x${request_libngtcp2}" != "xno"; then
|
||||
PKG_CHECK_MODULES([LIBNGTCP2_CRYPTO_QUICTLS],
|
||||
[libngtcp2_crypto_quictls >= 1.15.0],
|
||||
[libngtcp2_crypto_quictls >= 1.0.0],
|
||||
[have_libngtcp2_crypto_quictls=yes],
|
||||
[have_libngtcp2_crypto_quictls=no])
|
||||
if test "x${have_libngtcp2_crypto_quictls}" = "xno"; then
|
||||
@@ -585,37 +510,12 @@ if test "x${have_ssl_provide_quic_data}" = "xyes" &&
|
||||
fi
|
||||
|
||||
if test "x${have_ssl_provide_quic_data}" = "xyes" &&
|
||||
test "x${have_libressl}" != "xyes" &&
|
||||
test "x${have_boringssl_quic}" != "xyes" &&
|
||||
test "x${request_libngtcp2}" = "xyes" &&
|
||||
test "x${have_libngtcp2_crypto_quictls}" != "xyes"; then
|
||||
AC_MSG_ERROR([libngtcp2_crypto_quictls was requested (--with-libngtcp2) but not found])
|
||||
fi
|
||||
|
||||
# ngtcp2_crypto_libressl (for src)
|
||||
have_libngtcp2_crypto_libressl=no
|
||||
if test "x${have_ssl_provide_quic_data}" = "xyes" &&
|
||||
test "x${have_libressl}" = "xyes" &&
|
||||
test "x${request_libngtcp2}" != "xno"; then
|
||||
PKG_CHECK_MODULES([LIBNGTCP2_CRYPTO_LIBRESSL],
|
||||
[libngtcp2_crypto_libressl >= 1.15.0],
|
||||
[have_libngtcp2_crypto_libressl=yes],
|
||||
[have_libngtcp2_crypto_libressl=no])
|
||||
if test "x${have_libngtcp2_crypto_libressl}" = "xno"; then
|
||||
AC_MSG_NOTICE($LIBNGTCP2_CRYPTO_LIBRESSL_PKG_ERRORS)
|
||||
else
|
||||
AC_DEFINE([HAVE_LIBNGTCP2_CRYPTO_LIBRESSL], [1],
|
||||
[Define to 1 if you have `libngtcp2_crypto_libressl` library.])
|
||||
fi
|
||||
fi
|
||||
|
||||
if test "x${have_ssl_provide_quic_data}" = "xyes" &&
|
||||
test "x${have_libressl}" = "xyes" &&
|
||||
test "x${request_libngtcp2}" = "xyes" &&
|
||||
test "x${have_libngtcp2_crypto_libressl}" != "xyes"; then
|
||||
AC_MSG_ERROR([libngtcp2_crypto_libressl was requested (--with-libngtcp2) but not found])
|
||||
fi
|
||||
|
||||
# ngtcp2_crypto_boringssl (for src)
|
||||
have_libngtcp2_crypto_boringssl=no
|
||||
if test "x${have_boringssl_quic}" = "xyes" &&
|
||||
@@ -638,32 +538,10 @@ if test "x${have_boringssl_quic}" = "xyes" &&
|
||||
AC_MSG_ERROR([libngtcp2_crypto_boringssl was requested (--with-libngtcp2) but not found])
|
||||
fi
|
||||
|
||||
# ngtcp2_crypto_ossl (for src)
|
||||
have_libngtcp2_crypto_ossl=no
|
||||
if test "x${have_ossl_quic}" = "xyes" &&
|
||||
test "x${request_libngtcp2}" != "xno"; then
|
||||
PKG_CHECK_MODULES([LIBNGTCP2_CRYPTO_OSSL],
|
||||
[libngtcp2_crypto_ossl >= 1.15.0],
|
||||
[have_libngtcp2_crypto_ossl=yes],
|
||||
[have_libngtcp2_crypto_ossl=no])
|
||||
if test "x${have_libngtcp2_crypto_ossl}" = "xno"; then
|
||||
AC_MSG_NOTICE($LIBNGTCP2_CRYPTO_OSSL_PKG_ERRORS)
|
||||
else
|
||||
AC_DEFINE([HAVE_LIBNGTCP2_CRYPTO_OSSL], [1],
|
||||
[Define to 1 if you have `libngtcp2_crypto_ossl` library.])
|
||||
fi
|
||||
fi
|
||||
|
||||
if test "x${have_ossl_quic}" = "xyes" &&
|
||||
test "x${request_libngtcp2}" = "xyes" &&
|
||||
test "x${have_libngtcp2_crypto_ossl}" != "xyes"; then
|
||||
AC_MSG_ERROR([libngtcp2_crypto_ossl was requested (--with-libngtcp2) but not found])
|
||||
fi
|
||||
|
||||
# nghttp3 (for src)
|
||||
have_libnghttp3=no
|
||||
if test "x${request_libnghttp3}" != "xno"; then
|
||||
PKG_CHECK_MODULES([LIBNGHTTP3], [libnghttp3 >= 1.11.0], [have_libnghttp3=yes],
|
||||
PKG_CHECK_MODULES([LIBNGHTTP3], [libnghttp3 >= 1.1.0], [have_libnghttp3=yes],
|
||||
[have_libnghttp3=no])
|
||||
if test "x${have_libnghttp3}" = "xno"; then
|
||||
AC_MSG_NOTICE($LIBNGHTTP3_PKG_ERRORS)
|
||||
@@ -873,7 +751,7 @@ fi
|
||||
enable_app=no
|
||||
if test "x${request_app}" != "xno" &&
|
||||
test "x${have_zlib}" = "xyes" &&
|
||||
(test "x${have_openssl}" = "xyes" || test "x${have_wolfssl}" = "xyes") &&
|
||||
test "x${have_openssl}" = "xyes" &&
|
||||
test "x${have_libev}" = "xyes" &&
|
||||
test "x${have_libcares}" = "xyes"; then
|
||||
enable_app=yes
|
||||
@@ -890,11 +768,8 @@ AM_CONDITIONAL([ENABLE_APP], [ test "x${enable_app}" = "xyes" ])
|
||||
enable_http3=no
|
||||
if test "x${request_http3}" != "xno" &&
|
||||
test "x${have_libngtcp2}" = "xyes" &&
|
||||
(test "x${have_libngtcp2_crypto_wolfssl}" = "xyes" ||
|
||||
test "x${have_libngtcp2_crypto_quictls}" = "xyes" ||
|
||||
test "x${have_libngtcp2_crypto_libressl}" = "xyes" ||
|
||||
test "x${have_libngtcp2_crypto_boringssl}" = "xyes" ||
|
||||
test "x${have_libngtcp2_crypto_ossl}" = "xyes") &&
|
||||
(test "x${have_libngtcp2_crypto_quictls}" = "xyes" ||
|
||||
test "x${have_libngtcp2_crypto_boringssl}" = "xyes") &&
|
||||
test "x${have_libnghttp3}" = "xyes"; then
|
||||
enable_http3=yes
|
||||
AC_DEFINE([ENABLE_HTTP3], [1], [Define to 1 if HTTP/3 is enabled.])
|
||||
@@ -1070,7 +945,6 @@ AC_CHECK_FUNCS([ \
|
||||
memmove \
|
||||
memset \
|
||||
mkostemp \
|
||||
pipe2 \
|
||||
socket \
|
||||
sqrt \
|
||||
strchr \
|
||||
@@ -1175,7 +1049,6 @@ if test "x$werror" != "xno"; then
|
||||
# Only work with Clang for the moment
|
||||
AX_CHECK_COMPILE_FLAG([-Wheader-guard], [CFLAGS="$CFLAGS -Wheader-guard"])
|
||||
AX_CHECK_COMPILE_FLAG([-Wsometimes-uninitialized], [CFLAGS="$CFLAGS -Wsometimes-uninitialized"])
|
||||
AX_CHECK_COMPILE_FLAG([-Wextra-semi], [CFLAGS="$CFLAGS -Wextra-semi"])
|
||||
|
||||
# This is required because we pass format string as "const char*.
|
||||
AX_CHECK_COMPILE_FLAG([-Wno-format-nonliteral], [CFLAGS="$CFLAGS -Wno-format-nonliteral"])
|
||||
@@ -1186,13 +1059,9 @@ if test "x$werror" != "xno"; then
|
||||
AX_CHECK_COMPILE_FLAG([-Werror], [CXXFLAGS="$CXXFLAGS -Werror"])
|
||||
AX_CHECK_COMPILE_FLAG([-Wformat-security], [CXXFLAGS="$CXXFLAGS -Wformat-security"])
|
||||
AX_CHECK_COMPILE_FLAG([-Wsometimes-uninitialized], [CXXFLAGS="$CXXFLAGS -Wsometimes-uninitialized"])
|
||||
AX_CHECK_COMPILE_FLAG([-Wextra-semi], [CXXFLAGS="$CXXFLAGS -Wextra-semi"])
|
||||
AX_CHECK_COMPILE_FLAG([-Wconversion], [CXXFLAGS="$CXXFLAGS -Wconversion"])
|
||||
# Disable noexcept-type warning of g++-7. This is not harmful as
|
||||
# long as all source files are compiled with the same compiler.
|
||||
AX_CHECK_COMPILE_FLAG([-Wno-noexcept-type], [CXXFLAGS="$CXXFLAGS -Wno-noexcept-type"])
|
||||
# clang++-18 warns this when building with wolfSSL >= v5.7.6-stable.
|
||||
AX_CHECK_COMPILE_FLAG([-Wno-extern-c-compat], [CXXFLAGS="$CXXFLAGS -Wno-extern-c-compat"])
|
||||
AC_LANG_POP()
|
||||
fi
|
||||
|
||||
@@ -1259,6 +1128,7 @@ AC_CONFIG_FILES([
|
||||
doc/nghttp2ver.h.rst
|
||||
doc/contribute.rst
|
||||
contrib/Makefile
|
||||
script/Makefile
|
||||
])
|
||||
AC_OUTPUT
|
||||
|
||||
@@ -1300,16 +1170,13 @@ AC_MSG_NOTICE([summary of build options:
|
||||
Test:
|
||||
Failmalloc: ${enable_failmalloc}
|
||||
Libs:
|
||||
wolfSSL: ${have_wolfssl} (CFLAGS='${WOLFSSL_CFLAGS}' LIBS='${WOLFSSL_LIBS}')
|
||||
OpenSSL: ${have_openssl} (CFLAGS='${OPENSSL_CFLAGS}' LIBS='${OPENSSL_LIBS}')
|
||||
Libxml2: ${have_libxml2} (CFLAGS='${LIBXML2_CFLAGS}' LIBS='${LIBXML2_LIBS}')
|
||||
Libev: ${have_libev} (CFLAGS='${LIBEV_CFLAGS}' LIBS='${LIBEV_LIBS}')
|
||||
Libc-ares: ${have_libcares} (CFLAGS='${LIBCARES_CFLAGS}' LIBS='${LIBCARES_LIBS}')
|
||||
libngtcp2: ${have_libngtcp2} (CFLAGS='${LIBNGTCP2_CFLAGS}' LIBS='${LIBNGTCP2_LIBS}')
|
||||
libngtcp2_crypto_quictls: ${have_libngtcp2_crypto_quictls} (CFLAGS='${LIBNGTCP2_CRYPTO_QUICTLS_CFLAGS}' LIBS='${LIBNGTCP2_CRYPTO_QUICTLS_LIBS}')
|
||||
libngtcp2_crypto_libressl: ${have_libngtcp2_crypto_libressl} (CFLAGS='${LIBNGTCP2_CRYPTO_LIBRESSL_CFLAGS}' LIBS='${LIBNGTCP2_CRYPTO_LIBRESSL_LIBS}')
|
||||
libngtcp2_crypto_boringssl: ${have_libngtcp2_crypto_boringssl} (CFLAGS='${LIBNGTCP2_CRYPTO_BORINGSSL_CFLAGS}' LIBS='${LIBNGTCP2_CRYPTO_BORINGSSL_LIBS}')
|
||||
libngtcp2_crypto_ossl: ${have_libngtcp2_crypto_ossl} (CFLAGS='${LIBNGTCP2_CRYPTO_OSSL_CFLAGS}' LIBS='${LIBNGTCP2_CRYPTO_OSSL_LIBS}')
|
||||
libnghttp3: ${have_libnghttp3} (CFLAGS='${LIBNGHTTP3_CFLAGS}' LIBS='${LIBNGHTTP3_LIBS}')
|
||||
libbpf: ${have_libbpf} (CFLAGS='${LIBBPF_CFLAGS}' LIBS='${LIBBPF_LIBS}')
|
||||
Libevent(SSL): ${have_libevent_openssl} (CFLAGS='${LIBEVENT_OPENSSL_CFLAGS}' LIBS='${LIBEVENT_OPENSSL_LIBS}')
|
||||
|
||||
@@ -81,7 +81,6 @@ APIDOCS= \
|
||||
nghttp2_option_set_max_outbound_ack.rst \
|
||||
nghttp2_option_set_max_settings.rst \
|
||||
nghttp2_option_set_stream_reset_rate_limit.rst \
|
||||
nghttp2_option_set_glitch_rate_limit.rst \
|
||||
nghttp2_pack_settings_payload.rst \
|
||||
nghttp2_pack_settings_payload2.rst \
|
||||
nghttp2_priority_spec_check_default.rst \
|
||||
@@ -115,7 +114,6 @@ APIDOCS= \
|
||||
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_rand_callback.rst \
|
||||
nghttp2_session_callbacks_set_recv_callback.rst \
|
||||
nghttp2_session_callbacks_set_recv_callback2.rst \
|
||||
nghttp2_session_callbacks_set_select_padding_callback.rst \
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
sphinxcontrib
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
This package is a namespace package that contains all extensions
|
||||
distributed in the ``sphinx-contrib`` distribution.
|
||||
|
||||
:copyright: Copyright 2007-2009 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
|
||||
__import__('pkg_resources').declare_namespace(__name__)
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ _nghttp()
|
||||
_get_comp_words_by_ref cur prev
|
||||
case $cur in
|
||||
-*)
|
||||
COMPREPLY=( $( compgen -W '--verbose --null-out --remote-name --timeout --window-bits --connection-window-bits --get-assets --stat --header --trailer --cert --key --data --multiply --upgrade --extpri --peer-max-concurrent-streams --header-table-size --encoder-header-table-size --padding --har --color --continuation --no-content-length --hexdump --no-push --max-concurrent-streams --expect-continue --no-verify-peer --ktls --version --help ' -- "$cur" ) )
|
||||
COMPREPLY=( $( compgen -W '--verbose --null-out --remote-name --timeout --window-bits --connection-window-bits --get-assets --stat --header --trailer --cert --key --data --multiply --upgrade --weight --peer-max-concurrent-streams --header-table-size --encoder-header-table-size --padding --har --color --continuation --no-content-length --no-dep --hexdump --no-push --max-concurrent-streams --expect-continue --no-verify-peer --ktls --no-rfc7540-pri --version --help ' -- "$cur" ) )
|
||||
;;
|
||||
*)
|
||||
_filedir
|
||||
|
||||
@@ -8,7 +8,7 @@ _nghttpd()
|
||||
_get_comp_words_by_ref cur prev
|
||||
case $cur in
|
||||
-*)
|
||||
COMPREPLY=( $( compgen -W '--address --daemon --verify-client --htdocs --verbose --no-tls --header-table-size --encoder-header-table-size --color --push --padding --max-concurrent-streams --workers --error-gzip --window-bits --connection-window-bits --dh-param-file --early-response --trailer --hexdump --echo-upload --mime-types-file --no-content-length --ktls --version --help ' -- "$cur" ) )
|
||||
COMPREPLY=( $( compgen -W '--address --daemon --verify-client --htdocs --verbose --no-tls --header-table-size --encoder-header-table-size --color --push --padding --max-concurrent-streams --workers --error-gzip --window-bits --connection-window-bits --dh-param-file --early-response --trailer --hexdump --echo-upload --mime-types-file --no-content-length --ktls --no-rfc7540-pri --version --help ' -- "$cur" ) )
|
||||
;;
|
||||
*)
|
||||
_filedir
|
||||
|
||||
@@ -8,7 +8,7 @@ _nghttpx()
|
||||
_get_comp_words_by_ref cur prev
|
||||
case $cur in
|
||||
-*)
|
||||
COMPREPLY=( $( compgen -W '--backend --frontend --backlog --backend-address-family --backend-http-proxy-uri --workers --single-thread --read-rate --read-burst --write-rate --write-burst --worker-read-rate --worker-read-burst --worker-write-rate --worker-write-burst --worker-frontend-connections --backend-connections-per-host --backend-connections-per-frontend --rlimit-nofile --rlimit-memlock --backend-request-buffer --backend-response-buffer --fastopen --no-kqueue --frontend-http2-idle-timeout --frontend-http3-idle-timeout --frontend-write-timeout --frontend-keep-alive-timeout --frontend-header-timeout --stream-read-timeout --stream-write-timeout --backend-read-timeout --backend-write-timeout --backend-connect-timeout --backend-keep-alive-timeout --listener-disable-timeout --frontend-http2-setting-timeout --backend-http2-settings-timeout --backend-max-backoff --ciphers --tls13-ciphers --client-ciphers --tls13-client-ciphers --ecdh-curves --insecure --cacert --private-key-passwd-file --subcert --dh-param-file --alpn-list --verify-client --verify-client-cacert --verify-client-tolerate-expired --client-private-key-file --client-cert-file --tls-min-proto-version --tls-max-proto-version --tls-ticket-key-file --tls-ticket-key-memcached --tls-ticket-key-memcached-address-family --tls-ticket-key-memcached-interval --tls-ticket-key-memcached-max-retry --tls-ticket-key-memcached-max-fail --tls-ticket-key-cipher --tls-ticket-key-memcached-cert-file --tls-ticket-key-memcached-private-key-file --tls-dyn-rec-warmup-threshold --tls-dyn-rec-idle-timeout --no-http2-cipher-block-list --client-no-http2-cipher-block-list --tls-sct-dir --psk-secrets --client-psk-secrets --tls-no-postpone-early-data --tls-max-early-data --tls-ktls --frontend-http2-max-concurrent-streams --backend-http2-max-concurrent-streams --frontend-http2-window-size --frontend-http2-connection-window-size --backend-http2-window-size --backend-http2-connection-window-size --http2-no-cookie-crumbling --padding --no-server-push --frontend-http2-optimize-write-buffer-size --frontend-http2-optimize-window-size --frontend-http2-encoder-dynamic-table-size --frontend-http2-decoder-dynamic-table-size --backend-http2-encoder-dynamic-table-size --backend-http2-decoder-dynamic-table-size --http2-proxy --log-level --accesslog-file --accesslog-syslog --accesslog-format --accesslog-write-early --errorlog-file --errorlog-syslog --syslog-facility --add-x-forwarded-for --strip-incoming-x-forwarded-for --no-add-x-forwarded-proto --no-strip-incoming-x-forwarded-proto --add-forwarded --strip-incoming-forwarded --forwarded-by --forwarded-for --no-via --no-strip-incoming-early-data --no-location-rewrite --host-rewrite --altsvc --http2-altsvc --add-request-header --add-response-header --request-header-field-buffer --max-request-header-fields --response-header-field-buffer --max-response-header-fields --error-page --server-name --no-server-rewrite --redirect-https-port --require-http-scheme --api-max-request-body --dns-cache-timeout --dns-lookup-timeout --dns-max-try --frontend-max-requests --frontend-http2-dump-request-header --frontend-http2-dump-response-header --frontend-frame-debug --daemon --pid-file --user --single-process --max-worker-processes --worker-process-grace-shutdown-period --mruby-file --ignore-per-pattern-mruby-error --frontend-quic-idle-timeout --frontend-quic-debug-log --quic-bpf-program-file --frontend-quic-early-data --frontend-quic-qlog-dir --frontend-quic-require-token --frontend-quic-congestion-controller --frontend-quic-secret-file --quic-server-id --frontend-quic-initial-rtt --no-quic-bpf --frontend-http3-window-size --frontend-http3-connection-window-size --frontend-http3-max-window-size --frontend-http3-max-connection-window-size --frontend-http3-max-concurrent-streams --conf --include --version --help ' -- "$cur" ) )
|
||||
COMPREPLY=( $( compgen -W '--backend --frontend --backlog --backend-address-family --backend-http-proxy-uri --workers --single-thread --read-rate --read-burst --write-rate --write-burst --worker-read-rate --worker-read-burst --worker-write-rate --worker-write-burst --worker-frontend-connections --backend-connections-per-host --backend-connections-per-frontend --rlimit-nofile --rlimit-memlock --backend-request-buffer --backend-response-buffer --fastopen --no-kqueue --frontend-http2-idle-timeout --frontend-http3-idle-timeout --frontend-write-timeout --frontend-keep-alive-timeout --frontend-header-timeout --stream-read-timeout --stream-write-timeout --backend-read-timeout --backend-write-timeout --backend-connect-timeout --backend-keep-alive-timeout --listener-disable-timeout --frontend-http2-setting-timeout --backend-http2-settings-timeout --backend-max-backoff --ciphers --tls13-ciphers --client-ciphers --tls13-client-ciphers --ecdh-curves --insecure --cacert --private-key-passwd-file --subcert --dh-param-file --alpn-list --verify-client --verify-client-cacert --verify-client-tolerate-expired --client-private-key-file --client-cert-file --tls-min-proto-version --tls-max-proto-version --tls-ticket-key-file --tls-ticket-key-memcached --tls-ticket-key-memcached-address-family --tls-ticket-key-memcached-interval --tls-ticket-key-memcached-max-retry --tls-ticket-key-memcached-max-fail --tls-ticket-key-cipher --tls-ticket-key-memcached-cert-file --tls-ticket-key-memcached-private-key-file --fetch-ocsp-response-file --ocsp-update-interval --ocsp-startup --no-verify-ocsp --no-ocsp --tls-session-cache-memcached --tls-session-cache-memcached-address-family --tls-session-cache-memcached-cert-file --tls-session-cache-memcached-private-key-file --tls-dyn-rec-warmup-threshold --tls-dyn-rec-idle-timeout --no-http2-cipher-block-list --client-no-http2-cipher-block-list --tls-sct-dir --psk-secrets --client-psk-secrets --tls-no-postpone-early-data --tls-max-early-data --tls-ktls --frontend-http2-max-concurrent-streams --backend-http2-max-concurrent-streams --frontend-http2-window-size --frontend-http2-connection-window-size --backend-http2-window-size --backend-http2-connection-window-size --http2-no-cookie-crumbling --padding --no-server-push --frontend-http2-optimize-write-buffer-size --frontend-http2-optimize-window-size --frontend-http2-encoder-dynamic-table-size --frontend-http2-decoder-dynamic-table-size --backend-http2-encoder-dynamic-table-size --backend-http2-decoder-dynamic-table-size --http2-proxy --log-level --accesslog-file --accesslog-syslog --accesslog-format --accesslog-write-early --errorlog-file --errorlog-syslog --syslog-facility --add-x-forwarded-for --strip-incoming-x-forwarded-for --no-add-x-forwarded-proto --no-strip-incoming-x-forwarded-proto --add-forwarded --strip-incoming-forwarded --forwarded-by --forwarded-for --no-via --no-strip-incoming-early-data --no-location-rewrite --host-rewrite --altsvc --http2-altsvc --add-request-header --add-response-header --request-header-field-buffer --max-request-header-fields --response-header-field-buffer --max-response-header-fields --error-page --server-name --no-server-rewrite --redirect-https-port --require-http-scheme --api-max-request-body --dns-cache-timeout --dns-lookup-timeout --dns-max-try --frontend-max-requests --frontend-http2-dump-request-header --frontend-http2-dump-response-header --frontend-frame-debug --daemon --pid-file --user --single-process --max-worker-processes --worker-process-grace-shutdown-period --mruby-file --ignore-per-pattern-mruby-error --frontend-quic-idle-timeout --frontend-quic-debug-log --quic-bpf-program-file --frontend-quic-early-data --frontend-quic-qlog-dir --frontend-quic-require-token --frontend-quic-congestion-controller --frontend-quic-secret-file --quic-server-id --frontend-quic-initial-rtt --no-quic-bpf --frontend-http3-window-size --frontend-http3-connection-window-size --frontend-http3-max-window-size --frontend-http3-max-connection-window-size --frontend-http3-max-concurrent-streams --conf --include --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" "Sep 02, 2025" "1.67.0" "nghttp2"
|
||||
.TH "H2LOAD" "1" "May 19, 2024" "1.62.1" "nghttp2"
|
||||
.SH NAME
|
||||
h2load \- HTTP/2 benchmarking tool
|
||||
.SH SYNOPSIS
|
||||
@@ -262,7 +262,7 @@ protocol comes first. The parameter must be delimited
|
||||
by a single comma only and any white spaces are treated
|
||||
as a part of protocol string.
|
||||
.sp
|
||||
Default: \fBh2,http/1.1\fP
|
||||
Default: \fBh2,h2\-16,h2\-14,http/1.1\fP
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
|
||||
@@ -221,7 +221,7 @@ OPTIONS
|
||||
by a single comma only and any white spaces are treated
|
||||
as a part of protocol string.
|
||||
|
||||
Default: ``h2,http/1.1``
|
||||
Default: ``h2,h2-16,h2-14,http/1.1``
|
||||
|
||||
.. option:: --h1
|
||||
|
||||
|
||||
86
doc/nghttp.1
86
doc/nghttp.1
@@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
||||
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
||||
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
|
||||
..
|
||||
.TH "NGHTTP" "1" "Sep 02, 2025" "1.67.0" "nghttp2"
|
||||
.TH "NGHTTP" "1" "May 19, 2024" "1.62.1" "nghttp2"
|
||||
.SH NAME
|
||||
nghttp \- HTTP/2 client
|
||||
.SH SYNOPSIS
|
||||
@@ -141,15 +141,14 @@ HTTP upgrade request is performed with OPTIONS method.
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \-\-extpri=<PRI>
|
||||
Sets RFC 9218 priority of given URI. <PRI> must be the
|
||||
wire format of priority header field (e.g., \(dqu=3,i\(dq).
|
||||
This option can be used multiple times, and N\-th
|
||||
\fI\%\-\-extpri\fP option sets priority of N\-th URI in the command
|
||||
line. If the number of this option is less than the
|
||||
number of URI, the last option value is repeated. If
|
||||
there is no \fI\%\-\-extpri\fP option, urgency is 3, and
|
||||
incremental is false.
|
||||
.B \-p, \-\-weight=<WEIGHT>
|
||||
Sets weight of given URI. This option can be used
|
||||
multiple times, and N\-th \fI\%\-p\fP option sets weight of N\-th
|
||||
URI in the command line. If the number of \fI\%\-p\fP option is
|
||||
less than the number of URI, the last \fI\%\-p\fP option value is
|
||||
repeated. If there is no \fI\%\-p\fP option, default weight, 16,
|
||||
is assumed. The valid value range is
|
||||
[1, 256], inclusive.
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
@@ -206,6 +205,11 @@ Don\(aqt send content\-length header field.
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \-\-no\-dep
|
||||
Don\(aqt send dependency based priority hint to server.
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \-\-hexdump
|
||||
Display the incoming traffic in hexadecimal (Canonical
|
||||
hex+ASCII display). If SSL/TLS is used, decrypted data
|
||||
@@ -243,6 +247,11 @@ Enable ktls.
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \-\-no\-rfc7540\-pri
|
||||
Disable RFC7540 priorities.
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \-\-version
|
||||
Display version information and exit.
|
||||
.UNINDENT
|
||||
@@ -259,6 +268,63 @@ The <DURATION> argument is an integer and an optional unit (e.g., 1s
|
||||
is 1 second and 500ms is 500 milliseconds). Units are h, m, s or ms
|
||||
(hours, minutes, seconds and milliseconds, respectively). If a unit
|
||||
is omitted, a second is used as unit.
|
||||
.SH DEPENDENCY BASED PRIORITY
|
||||
.sp
|
||||
nghttp sends priority hints to server by default unless
|
||||
\fI\%\-\-no\-dep\fP is used. nghttp mimics the way Firefox employs to
|
||||
manages dependency using idle streams. We follows the behaviour of
|
||||
Firefox Nightly as of April, 2015, and nghttp\(aqs behaviour is very
|
||||
static and could be different from Firefox in detail. But reproducing
|
||||
the same behaviour of Firefox is not our goal. The goal is provide
|
||||
the easy way to test out the dependency priority in server
|
||||
implementation.
|
||||
.sp
|
||||
When connection is established, nghttp sends 5 PRIORITY frames to idle
|
||||
streams 3, 5, 7, 9 and 11 to create \(dqanchor\(dq nodes in dependency
|
||||
tree:
|
||||
.INDENT 0.0
|
||||
.INDENT 3.5
|
||||
.sp
|
||||
.nf
|
||||
.ft C
|
||||
+\-\-\-\-\-+
|
||||
|id=0 |
|
||||
+\-\-\-\-\-+
|
||||
^ ^ ^
|
||||
w=201 / | \e w=1
|
||||
/ | \e
|
||||
/ w=101| \e
|
||||
+\-\-\-\-\-+ +\-\-\-\-\-+ +\-\-\-\-\-+
|
||||
|id=3 | |id=5 | |id=7 |
|
||||
+\-\-\-\-\-+ +\-\-\-\-\-+ +\-\-\-\-\-+
|
||||
^ ^
|
||||
w=1 | w=1 |
|
||||
| |
|
||||
+\-\-\-\-\-+ +\-\-\-\-\-+
|
||||
|id=11| |id=9 |
|
||||
+\-\-\-\-\-+ +\-\-\-\-\-+
|
||||
.ft P
|
||||
.fi
|
||||
.UNINDENT
|
||||
.UNINDENT
|
||||
.sp
|
||||
In the above figure, \fBid\fP means stream ID, and \fBw\fP means weight.
|
||||
The stream 0 is non\-existence stream, and forms the root of the tree.
|
||||
The stream 7 and 9 are not used for now.
|
||||
.sp
|
||||
The URIs given in the command\-line depend on stream 11 with the weight
|
||||
given in \fI\%\-p\fP option, which defaults to 16.
|
||||
.sp
|
||||
If \fI\%\-a\fP option is used, nghttp parses the resource pointed by
|
||||
URI given in command\-line as html, and extracts resource links from
|
||||
it. When requesting those resources, nghttp uses dependency according
|
||||
to its resource type.
|
||||
.sp
|
||||
For CSS, and Javascript files inside \(dqhead\(dq element, they depend on
|
||||
stream 3 with the weight 2. The Javascript files outside \(dqhead\(dq
|
||||
element depend on stream 5 with the weight 2. The mages depend on
|
||||
stream 11 with the weight 12. The other resources (e.g., icon) depend
|
||||
on stream 11 with the weight 2.
|
||||
.SH SEE ALSO
|
||||
.sp
|
||||
\fBnghttpd(1)\fP, \fBnghttpx(1)\fP, \fBh2load(1)\fP
|
||||
|
||||
@@ -105,16 +105,15 @@ OPTIONS
|
||||
if the request URI has https scheme. If :option:`-d` is used, the
|
||||
HTTP upgrade request is performed with OPTIONS method.
|
||||
|
||||
.. option:: --extpri=<PRI>
|
||||
.. option:: -p, --weight=<WEIGHT>
|
||||
|
||||
Sets RFC 9218 priority of given URI. <PRI> must be the
|
||||
wire format of priority header field (e.g., "u=3,i").
|
||||
This option can be used multiple times, and N-th
|
||||
:option:`--extpri` option sets priority of N-th URI in the command
|
||||
line. If the number of this option is less than the
|
||||
number of URI, the last option value is repeated. If
|
||||
there is no :option:`--extpri` option, urgency is 3, and
|
||||
incremental is false.
|
||||
Sets weight of given URI. This option can be used
|
||||
multiple times, and N-th :option:`-p` option sets weight of N-th
|
||||
URI in the command line. If the number of :option:`-p` option is
|
||||
less than the number of URI, the last :option:`-p` option value is
|
||||
repeated. If there is no :option:`-p` option, default weight, 16,
|
||||
is assumed. The valid value range is
|
||||
[1, 256], inclusive.
|
||||
|
||||
.. option:: -M, --peer-max-concurrent-streams=<N>
|
||||
|
||||
@@ -161,6 +160,10 @@ OPTIONS
|
||||
|
||||
Don't send content-length header field.
|
||||
|
||||
.. option:: --no-dep
|
||||
|
||||
Don't send dependency based priority hint to server.
|
||||
|
||||
.. option:: --hexdump
|
||||
|
||||
Display the incoming traffic in hexadecimal (Canonical
|
||||
@@ -192,6 +195,10 @@ OPTIONS
|
||||
|
||||
Enable ktls.
|
||||
|
||||
.. option:: --no-rfc7540-pri
|
||||
|
||||
Disable RFC7540 priorities.
|
||||
|
||||
.. option:: --version
|
||||
|
||||
Display version information and exit.
|
||||
@@ -210,6 +217,59 @@ is 1 second and 500ms is 500 milliseconds). Units are h, m, s or ms
|
||||
(hours, minutes, seconds and milliseconds, respectively). If a unit
|
||||
is omitted, a second is used as unit.
|
||||
|
||||
DEPENDENCY BASED PRIORITY
|
||||
-------------------------
|
||||
|
||||
nghttp sends priority hints to server by default unless
|
||||
:option:`--no-dep` is used. nghttp mimics the way Firefox employs to
|
||||
manages dependency using idle streams. We follows the behaviour of
|
||||
Firefox Nightly as of April, 2015, and nghttp's behaviour is very
|
||||
static and could be different from Firefox in detail. But reproducing
|
||||
the same behaviour of Firefox is not our goal. The goal is provide
|
||||
the easy way to test out the dependency priority in server
|
||||
implementation.
|
||||
|
||||
When connection is established, nghttp sends 5 PRIORITY frames to idle
|
||||
streams 3, 5, 7, 9 and 11 to create "anchor" nodes in dependency
|
||||
tree:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
+-----+
|
||||
|id=0 |
|
||||
+-----+
|
||||
^ ^ ^
|
||||
w=201 / | \ w=1
|
||||
/ | \
|
||||
/ w=101| \
|
||||
+-----+ +-----+ +-----+
|
||||
|id=3 | |id=5 | |id=7 |
|
||||
+-----+ +-----+ +-----+
|
||||
^ ^
|
||||
w=1 | w=1 |
|
||||
| |
|
||||
+-----+ +-----+
|
||||
|id=11| |id=9 |
|
||||
+-----+ +-----+
|
||||
|
||||
In the above figure, ``id`` means stream ID, and ``w`` means weight.
|
||||
The stream 0 is non-existence stream, and forms the root of the tree.
|
||||
The stream 7 and 9 are not used for now.
|
||||
|
||||
The URIs given in the command-line depend on stream 11 with the weight
|
||||
given in :option:`-p` option, which defaults to 16.
|
||||
|
||||
If :option:`-a` option is used, nghttp parses the resource pointed by
|
||||
URI given in command-line as html, and extracts resource links from
|
||||
it. When requesting those resources, nghttp uses dependency according
|
||||
to its resource type.
|
||||
|
||||
For CSS, and Javascript files inside "head" element, they depend on
|
||||
stream 3 with the weight 2. The Javascript files outside "head"
|
||||
element depend on stream 5 with the weight 2. The mages depend on
|
||||
stream 11 with the weight 12. The other resources (e.g., icon) depend
|
||||
on stream 11 with the weight 2.
|
||||
|
||||
SEE ALSO
|
||||
--------
|
||||
|
||||
|
||||
@@ -1,3 +1,56 @@
|
||||
DEPENDENCY BASED PRIORITY
|
||||
-------------------------
|
||||
|
||||
nghttp sends priority hints to server by default unless
|
||||
:option:`--no-dep` is used. nghttp mimics the way Firefox employs to
|
||||
manages dependency using idle streams. We follows the behaviour of
|
||||
Firefox Nightly as of April, 2015, and nghttp's behaviour is very
|
||||
static and could be different from Firefox in detail. But reproducing
|
||||
the same behaviour of Firefox is not our goal. The goal is provide
|
||||
the easy way to test out the dependency priority in server
|
||||
implementation.
|
||||
|
||||
When connection is established, nghttp sends 5 PRIORITY frames to idle
|
||||
streams 3, 5, 7, 9 and 11 to create "anchor" nodes in dependency
|
||||
tree:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
+-----+
|
||||
|id=0 |
|
||||
+-----+
|
||||
^ ^ ^
|
||||
w=201 / | \ w=1
|
||||
/ | \
|
||||
/ w=101| \
|
||||
+-----+ +-----+ +-----+
|
||||
|id=3 | |id=5 | |id=7 |
|
||||
+-----+ +-----+ +-----+
|
||||
^ ^
|
||||
w=1 | w=1 |
|
||||
| |
|
||||
+-----+ +-----+
|
||||
|id=11| |id=9 |
|
||||
+-----+ +-----+
|
||||
|
||||
In the above figure, ``id`` means stream ID, and ``w`` means weight.
|
||||
The stream 0 is non-existence stream, and forms the root of the tree.
|
||||
The stream 7 and 9 are not used for now.
|
||||
|
||||
The URIs given in the command-line depend on stream 11 with the weight
|
||||
given in :option:`-p` option, which defaults to 16.
|
||||
|
||||
If :option:`-a` option is used, nghttp parses the resource pointed by
|
||||
URI given in command-line as html, and extracts resource links from
|
||||
it. When requesting those resources, nghttp uses dependency according
|
||||
to its resource type.
|
||||
|
||||
For CSS, and Javascript files inside "head" element, they depend on
|
||||
stream 3 with the weight 2. The Javascript files outside "head"
|
||||
element depend on stream 5 with the weight 2. The mages depend on
|
||||
stream 11 with the weight 12. The other resources (e.g., icon) depend
|
||||
on stream 11 with the weight 2.
|
||||
|
||||
SEE ALSO
|
||||
--------
|
||||
|
||||
|
||||
@@ -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" "Sep 02, 2025" "1.67.0" "nghttp2"
|
||||
.TH "NGHTTPD" "1" "May 19, 2024" "1.62.1" "nghttp2"
|
||||
.SH NAME
|
||||
nghttpd \- HTTP/2 server
|
||||
.SH SYNOPSIS
|
||||
@@ -209,6 +209,11 @@ Enable ktls.
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \-\-no\-rfc7540\-pri
|
||||
Disable RFC7540 priorities.
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \-\-version
|
||||
Display version information and exit.
|
||||
.UNINDENT
|
||||
|
||||
@@ -163,6 +163,10 @@ OPTIONS
|
||||
|
||||
Enable ktls.
|
||||
|
||||
.. option:: --no-rfc7540-pri
|
||||
|
||||
Disable RFC7540 priorities.
|
||||
|
||||
.. option:: --version
|
||||
|
||||
Display version information and exit.
|
||||
|
||||
168
doc/nghttpx.1
168
doc/nghttpx.1
@@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
||||
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
||||
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
|
||||
..
|
||||
.TH "NGHTTPX" "1" "Sep 02, 2025" "1.67.0" "nghttp2"
|
||||
.TH "NGHTTPX" "1" "May 19, 2024" "1.62.1" "nghttp2"
|
||||
.SH NAME
|
||||
nghttpx \- HTTP/2 proxy
|
||||
.SH SYNOPSIS
|
||||
@@ -46,7 +46,8 @@ Set path to server\(aqs private key. Required unless
|
||||
.TP
|
||||
.B <CERT>
|
||||
Set path to server\(aqs certificate. Required unless
|
||||
\(dqno\-tls\(dq parameter is used in \fI\%\-\-frontend\fP option.
|
||||
\(dqno\-tls\(dq parameter is used in \fI\%\-\-frontend\fP option. To
|
||||
make OCSP stapling work, this must be an absolute path.
|
||||
.UNINDENT
|
||||
.SH OPTIONS
|
||||
.sp
|
||||
@@ -744,10 +745,12 @@ enabled for backend connections.
|
||||
.B \-\-cacert=<PATH>
|
||||
Set path to trusted CA certificate file. It is used in
|
||||
backend TLS connections to verify peer\(aqs certificate.
|
||||
The file must be in PEM format. It can contain multiple
|
||||
certificates. If the linked OpenSSL is configured to
|
||||
load system wide certificates, they are loaded at
|
||||
startup regardless of this option.
|
||||
It is also used to verify OCSP response from the script
|
||||
set by \fI\%\-\-fetch\-ocsp\-response\-file\fP\&. The file must be in
|
||||
PEM format. It can contain multiple certificates. If
|
||||
the linked OpenSSL is configured to load system wide
|
||||
certificates, they are loaded at startup regardless of
|
||||
this option.
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
@@ -767,7 +770,8 @@ curves (e.g., P\-256) between client and server are also
|
||||
taken into consideration. This allows nghttpx to send
|
||||
ECDSA certificate to modern clients, while sending RSA
|
||||
based certificate to older clients. This option can be
|
||||
used multiple times.
|
||||
used multiple times. To make OCSP stapling work,
|
||||
<CERTPATH> must be absolute path.
|
||||
.sp
|
||||
Additional parameter can be specified in <PARAM>. The
|
||||
available <PARAM> is \(dqsct\-dir=<DIR>\(dq.
|
||||
@@ -794,7 +798,7 @@ protocol comes first. The parameter must be delimited
|
||||
by a single comma only and any white spaces are treated
|
||||
as a part of protocol string.
|
||||
.sp
|
||||
Default: \fBh2,http/1.1\fP
|
||||
Default: \fBh2,h2\-16,h2\-14,http/1.1\fP
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
@@ -958,6 +962,72 @@ get TLS ticket keys.
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \-\-fetch\-ocsp\-response\-file=<PATH>
|
||||
Path to fetch\-ocsp\-response script file. It should be
|
||||
absolute path.
|
||||
.sp
|
||||
Default: \fB/usr/local/share/nghttp2/fetch\-ocsp\-response\fP
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \-\-ocsp\-update\-interval=<DURATION>
|
||||
Set interval to update OCSP response cache.
|
||||
.sp
|
||||
Default: \fB4h\fP
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \-\-ocsp\-startup
|
||||
Start accepting connections after initial attempts to
|
||||
get OCSP responses finish. It does not matter some of
|
||||
the attempts fail. This feature is useful if OCSP
|
||||
responses must be available before accepting
|
||||
connections.
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \-\-no\-verify\-ocsp
|
||||
nghttpx does not verify OCSP response.
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \-\-no\-ocsp
|
||||
Disable OCSP stapling.
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \-\-tls\-session\-cache\-memcached=<HOST>,<PORT>[;tls]
|
||||
Specify address of memcached server to store session
|
||||
cache. This enables shared session cache between
|
||||
multiple nghttpx instances. Optionally, memcached
|
||||
connection can be encrypted with TLS by specifying \(dqtls\(dq
|
||||
parameter.
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \-\-tls\-session\-cache\-memcached\-address\-family=(auto|IPv4|IPv6)
|
||||
Specify address family of memcached connections to store
|
||||
session cache. If \(dqauto\(dq is given, both IPv4 and IPv6
|
||||
are considered. If \(dqIPv4\(dq is given, only IPv4 address
|
||||
is considered. If \(dqIPv6\(dq is given, only IPv6 address is
|
||||
considered.
|
||||
.sp
|
||||
Default: \fBauto\fP
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \-\-tls\-session\-cache\-memcached\-cert\-file=<PATH>
|
||||
Path to client certificate for memcached connections to
|
||||
store session cache.
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \-\-tls\-session\-cache\-memcached\-private\-key\-file=<PATH>
|
||||
Path to client private key for memcached connections to
|
||||
store session cache.
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \-\-tls\-dyn\-rec\-warmup\-threshold=<SIZE>
|
||||
Specify the threshold size for TLS dynamic record size
|
||||
behaviour. During a TLS session, after the threshold
|
||||
@@ -1065,7 +1135,8 @@ Default: \fB16K\fP
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \-\-tls\-ktls
|
||||
Enable ktls.
|
||||
Enable ktls. For server, ktls is enable if
|
||||
\fI\%\-\-tls\-session\-cache\-memcached\fP is not configured.
|
||||
.UNINDENT
|
||||
.SS HTTP/2
|
||||
.INDENT 0.0
|
||||
@@ -1604,7 +1675,7 @@ initial DNS query. For the 2nd and later queries,
|
||||
server is given time based on this timeout, and it is
|
||||
scaled linearly.
|
||||
.sp
|
||||
Default: \fB250ms\fP
|
||||
Default: \fB5s\fP
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
@@ -1612,7 +1683,7 @@ Default: \fB250ms\fP
|
||||
Set the number of DNS query before nghttpx gives up name
|
||||
lookup.
|
||||
.sp
|
||||
Default: \fB3\fP
|
||||
Default: \fB2\fP
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
@@ -1932,9 +2003,11 @@ request header field, do this:
|
||||
.INDENT 7.0
|
||||
.INDENT 3.5
|
||||
.sp
|
||||
.EX
|
||||
.nf
|
||||
.ft C
|
||||
add\-request\-header=foo: bar
|
||||
.EE
|
||||
.ft P
|
||||
.fi
|
||||
.UNINDENT
|
||||
.UNINDENT
|
||||
.sp
|
||||
@@ -1942,9 +2015,11 @@ instead of:
|
||||
.INDENT 7.0
|
||||
.INDENT 3.5
|
||||
.sp
|
||||
.EX
|
||||
.nf
|
||||
.ft C
|
||||
add\-request\-header=\(dqfoo: bar\(dq
|
||||
.EE
|
||||
.ft P
|
||||
.fi
|
||||
.UNINDENT
|
||||
.UNINDENT
|
||||
.sp
|
||||
@@ -2049,10 +2124,12 @@ header field to initiate server push:
|
||||
.INDENT 0.0
|
||||
.INDENT 3.5
|
||||
.sp
|
||||
.EX
|
||||
.nf
|
||||
.ft C
|
||||
Link: </fonts/font.woff>; rel=preload
|
||||
Link: </css/theme.css>; rel=preload
|
||||
.EE
|
||||
.ft P
|
||||
.fi
|
||||
.UNINDENT
|
||||
.UNINDENT
|
||||
.sp
|
||||
@@ -2083,6 +2160,35 @@ specified socket already exists in the file system, nghttpx first
|
||||
deletes it. However, if SIGUSR2 is used to execute new binary and
|
||||
both old and new configurations use same filename, new binary does not
|
||||
delete the socket and continues to use it.
|
||||
.SH OCSP STAPLING
|
||||
.sp
|
||||
OCSP query is done using external Python script
|
||||
\fBfetch\-ocsp\-response\fP, which has been originally developed in Perl
|
||||
as part of h2o project (\X'tty: link https://github.com/h2o/h2o'\fI\%https://github.com/h2o/h2o\fP\X'tty: link'), and was
|
||||
translated into Python.
|
||||
.sp
|
||||
The script file is usually installed under
|
||||
\fB$(prefix)/share/nghttp2/\fP directory. The actual path to script can
|
||||
be customized using \fI\%\-\-fetch\-ocsp\-response\-file\fP option.
|
||||
.sp
|
||||
If OCSP query is failed, previous OCSP response, if any, is continued
|
||||
to be used.
|
||||
.sp
|
||||
\fI\%\-\-fetch\-ocsp\-response\-file\fP option provides wide range of
|
||||
possibility to manage OCSP response. It can take an arbitrary script
|
||||
or executable. The requirement is that it supports the command\-line
|
||||
interface of \fBfetch\-ocsp\-response\fP script, and it must return a
|
||||
valid DER encoded OCSP response on success. It must return exit code
|
||||
0 on success, and 75 for temporary error, and the other error code for
|
||||
generic failure. For large cluster of servers, it is not efficient
|
||||
for each server to perform OCSP query using \fBfetch\-ocsp\-response\fP\&.
|
||||
Instead, you can retrieve OCSP response in some way, and store it in a
|
||||
disk or a shared database. Then specify a program in
|
||||
\fI\%\-\-fetch\-ocsp\-response\-file\fP to fetch it from those stores.
|
||||
This could provide a way to share the OCSP response between fleet of
|
||||
servers, and also any OCSP query strategy can be applied which may be
|
||||
beyond the ability of nghttpx itself or \fBfetch\-ocsp\-response\fP
|
||||
script.
|
||||
.SH TLS SESSION RESUMPTION
|
||||
.sp
|
||||
nghttpx supports TLS session resumption through both session ID and
|
||||
@@ -2090,6 +2196,16 @@ session ticket.
|
||||
.SS SESSION ID RESUMPTION
|
||||
.sp
|
||||
By default, session ID is shared by all worker threads.
|
||||
.sp
|
||||
If \fI\%\-\-tls\-session\-cache\-memcached\fP is given, nghttpx will
|
||||
insert serialized session data to memcached with
|
||||
\fBnghttpx:tls\-session\-cache:\fP + lowercase hex string of session ID
|
||||
as a memcached entry key, with expiry time 12 hours. Session timeout
|
||||
is set to 12 hours.
|
||||
.sp
|
||||
By default, connections to memcached server are not encrypted. To
|
||||
enable encryption, use \fBtls\fP keyword in
|
||||
\fI\%\-\-tls\-session\-cache\-memcached\fP option.
|
||||
.SS TLS SESSION TICKET RESUMPTION
|
||||
.sp
|
||||
By default, session ticket is shared by all worker threads. The
|
||||
@@ -2108,7 +2224,8 @@ memcached is the binary format described below:
|
||||
.INDENT 0.0
|
||||
.INDENT 3.5
|
||||
.sp
|
||||
.EX
|
||||
.nf
|
||||
.ft C
|
||||
+\-\-\-\-\-\-\-\-\-\-\-\-\-\-+\-\-\-\-\-\-\-+\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-+
|
||||
| VERSION (4) |LEN (2)|KEY(48 or 80) ...
|
||||
+\-\-\-\-\-\-\-\-\-\-\-\-\-\-+\-\-\-\-\-\-\-+\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-+
|
||||
@@ -2116,7 +2233,8 @@ memcached is the binary format described below:
|
||||
| |
|
||||
+\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-+
|
||||
(LEN, KEY) pair can be repeated
|
||||
.EE
|
||||
.ft P
|
||||
.fi
|
||||
.UNINDENT
|
||||
.UNINDENT
|
||||
.sp
|
||||
@@ -2533,7 +2651,8 @@ Modify request path:
|
||||
.INDENT 0.0
|
||||
.INDENT 3.5
|
||||
.sp
|
||||
.EX
|
||||
.nf
|
||||
.ft C
|
||||
class App
|
||||
def on_req(env)
|
||||
env.req.path = \(dq/apps#{env.req.path}\(dq
|
||||
@@ -2541,7 +2660,8 @@ class App
|
||||
end
|
||||
|
||||
App.new
|
||||
.EE
|
||||
.ft P
|
||||
.fi
|
||||
.UNINDENT
|
||||
.UNINDENT
|
||||
.sp
|
||||
@@ -2552,7 +2672,8 @@ addresses:
|
||||
.INDENT 0.0
|
||||
.INDENT 3.5
|
||||
.sp
|
||||
.EX
|
||||
.nf
|
||||
.ft C
|
||||
class App
|
||||
def on_req(env)
|
||||
allowed_clients = [\(dq127.0.0.1\(dq, \(dq::1\(dq]
|
||||
@@ -2566,7 +2687,8 @@ class App
|
||||
end
|
||||
|
||||
App.new
|
||||
.EE
|
||||
.ft P
|
||||
.fi
|
||||
.UNINDENT
|
||||
.UNINDENT
|
||||
.SH API ENDPOINTS
|
||||
|
||||
@@ -25,7 +25,8 @@ A reverse proxy for HTTP/3, HTTP/2, and HTTP/1.
|
||||
.. describe:: <CERT>
|
||||
|
||||
Set path to server's certificate. Required unless
|
||||
"no-tls" parameter is used in :option:`--frontend` option.
|
||||
"no-tls" parameter is used in :option:`--frontend` option. To
|
||||
make OCSP stapling work, this must be an absolute path.
|
||||
|
||||
|
||||
OPTIONS
|
||||
@@ -694,10 +695,12 @@ SSL/TLS
|
||||
|
||||
Set path to trusted CA certificate file. It is used in
|
||||
backend TLS connections to verify peer's certificate.
|
||||
The file must be in PEM format. It can contain multiple
|
||||
certificates. If the linked OpenSSL is configured to
|
||||
load system wide certificates, they are loaded at
|
||||
startup regardless of this option.
|
||||
It is also used to verify OCSP response from the script
|
||||
set by :option:`--fetch-ocsp-response-file`\. The file must be in
|
||||
PEM format. It can contain multiple certificates. If
|
||||
the linked OpenSSL is configured to load system wide
|
||||
certificates, they are loaded at startup regardless of
|
||||
this option.
|
||||
|
||||
.. option:: --private-key-passwd-file=<PATH>
|
||||
|
||||
@@ -715,7 +718,8 @@ SSL/TLS
|
||||
taken into consideration. This allows nghttpx to send
|
||||
ECDSA certificate to modern clients, while sending RSA
|
||||
based certificate to older clients. This option can be
|
||||
used multiple times.
|
||||
used multiple times. To make OCSP stapling work,
|
||||
<CERTPATH> must be absolute path.
|
||||
|
||||
Additional parameter can be specified in <PARAM>. The
|
||||
available <PARAM> is "sct-dir=<DIR>".
|
||||
@@ -740,7 +744,7 @@ SSL/TLS
|
||||
by a single comma only and any white spaces are treated
|
||||
as a part of protocol string.
|
||||
|
||||
Default: ``h2,http/1.1``
|
||||
Default: ``h2,h2-16,h2-14,http/1.1``
|
||||
|
||||
.. option:: --verify-client
|
||||
|
||||
@@ -886,6 +890,63 @@ SSL/TLS
|
||||
Path to client private key for memcached connections to
|
||||
get TLS ticket keys.
|
||||
|
||||
.. option:: --fetch-ocsp-response-file=<PATH>
|
||||
|
||||
Path to fetch-ocsp-response script file. It should be
|
||||
absolute path.
|
||||
|
||||
Default: ``/usr/local/share/nghttp2/fetch-ocsp-response``
|
||||
|
||||
.. option:: --ocsp-update-interval=<DURATION>
|
||||
|
||||
Set interval to update OCSP response cache.
|
||||
|
||||
Default: ``4h``
|
||||
|
||||
.. option:: --ocsp-startup
|
||||
|
||||
Start accepting connections after initial attempts to
|
||||
get OCSP responses finish. It does not matter some of
|
||||
the attempts fail. This feature is useful if OCSP
|
||||
responses must be available before accepting
|
||||
connections.
|
||||
|
||||
.. option:: --no-verify-ocsp
|
||||
|
||||
nghttpx does not verify OCSP response.
|
||||
|
||||
.. option:: --no-ocsp
|
||||
|
||||
Disable OCSP stapling.
|
||||
|
||||
.. option:: --tls-session-cache-memcached=<HOST>,<PORT>[;tls]
|
||||
|
||||
Specify address of memcached server to store session
|
||||
cache. This enables shared session cache between
|
||||
multiple nghttpx instances. Optionally, memcached
|
||||
connection can be encrypted with TLS by specifying "tls"
|
||||
parameter.
|
||||
|
||||
.. option:: --tls-session-cache-memcached-address-family=(auto|IPv4|IPv6)
|
||||
|
||||
Specify address family of memcached connections to store
|
||||
session cache. If "auto" is given, both IPv4 and IPv6
|
||||
are considered. If "IPv4" is given, only IPv4 address
|
||||
is considered. If "IPv6" is given, only IPv6 address is
|
||||
considered.
|
||||
|
||||
Default: ``auto``
|
||||
|
||||
.. option:: --tls-session-cache-memcached-cert-file=<PATH>
|
||||
|
||||
Path to client certificate for memcached connections to
|
||||
store session cache.
|
||||
|
||||
.. option:: --tls-session-cache-memcached-private-key-file=<PATH>
|
||||
|
||||
Path to client private key for memcached connections to
|
||||
store session cache.
|
||||
|
||||
.. option:: --tls-dyn-rec-warmup-threshold=<SIZE>
|
||||
|
||||
Specify the threshold size for TLS dynamic record size
|
||||
@@ -985,7 +1046,8 @@ SSL/TLS
|
||||
|
||||
.. option:: --tls-ktls
|
||||
|
||||
Enable ktls.
|
||||
Enable ktls. For server, ktls is enable if
|
||||
:option:`--tls-session-cache-memcached` is not configured.
|
||||
|
||||
|
||||
HTTP/2
|
||||
@@ -1462,14 +1524,14 @@ DNS
|
||||
server is given time based on this timeout, and it is
|
||||
scaled linearly.
|
||||
|
||||
Default: ``250ms``
|
||||
Default: ``5s``
|
||||
|
||||
.. option:: --dns-max-try=<N>
|
||||
|
||||
Set the number of DNS query before nghttpx gives up name
|
||||
lookup.
|
||||
|
||||
Default: ``3``
|
||||
Default: ``2``
|
||||
|
||||
.. option:: --frontend-max-requests=<N>
|
||||
|
||||
@@ -1909,6 +1971,37 @@ deletes it. However, if SIGUSR2 is used to execute new binary and
|
||||
both old and new configurations use same filename, new binary does not
|
||||
delete the socket and continues to use it.
|
||||
|
||||
OCSP STAPLING
|
||||
-------------
|
||||
|
||||
OCSP query is done using external Python script
|
||||
``fetch-ocsp-response``, which has been originally developed in Perl
|
||||
as part of h2o project (https://github.com/h2o/h2o), and was
|
||||
translated into Python.
|
||||
|
||||
The script file is usually installed under
|
||||
``$(prefix)/share/nghttp2/`` directory. The actual path to script can
|
||||
be customized using :option:`--fetch-ocsp-response-file` option.
|
||||
|
||||
If OCSP query is failed, previous OCSP response, if any, is continued
|
||||
to be used.
|
||||
|
||||
:option:`--fetch-ocsp-response-file` option provides wide range of
|
||||
possibility to manage OCSP response. It can take an arbitrary script
|
||||
or executable. The requirement is that it supports the command-line
|
||||
interface of ``fetch-ocsp-response`` script, and it must return a
|
||||
valid DER encoded OCSP response on success. It must return exit code
|
||||
0 on success, and 75 for temporary error, and the other error code for
|
||||
generic failure. For large cluster of servers, it is not efficient
|
||||
for each server to perform OCSP query using ``fetch-ocsp-response``.
|
||||
Instead, you can retrieve OCSP response in some way, and store it in a
|
||||
disk or a shared database. Then specify a program in
|
||||
:option:`--fetch-ocsp-response-file` to fetch it from those stores.
|
||||
This could provide a way to share the OCSP response between fleet of
|
||||
servers, and also any OCSP query strategy can be applied which may be
|
||||
beyond the ability of nghttpx itself or ``fetch-ocsp-response``
|
||||
script.
|
||||
|
||||
TLS SESSION RESUMPTION
|
||||
----------------------
|
||||
|
||||
@@ -1920,6 +2013,16 @@ SESSION ID RESUMPTION
|
||||
|
||||
By default, session ID is shared by all worker threads.
|
||||
|
||||
If :option:`--tls-session-cache-memcached` is given, nghttpx will
|
||||
insert serialized session data to memcached with
|
||||
``nghttpx:tls-session-cache:`` + lowercase hex string of session ID
|
||||
as a memcached entry key, with expiry time 12 hours. Session timeout
|
||||
is set to 12 hours.
|
||||
|
||||
By default, connections to memcached server are not encrypted. To
|
||||
enable encryption, use ``tls`` keyword in
|
||||
:option:`--tls-session-cache-memcached` option.
|
||||
|
||||
TLS SESSION TICKET RESUMPTION
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
||||
@@ -156,6 +156,37 @@ deletes it. However, if SIGUSR2 is used to execute new binary and
|
||||
both old and new configurations use same filename, new binary does not
|
||||
delete the socket and continues to use it.
|
||||
|
||||
OCSP STAPLING
|
||||
-------------
|
||||
|
||||
OCSP query is done using external Python script
|
||||
``fetch-ocsp-response``, which has been originally developed in Perl
|
||||
as part of h2o project (https://github.com/h2o/h2o), and was
|
||||
translated into Python.
|
||||
|
||||
The script file is usually installed under
|
||||
``$(prefix)/share/nghttp2/`` directory. The actual path to script can
|
||||
be customized using :option:`--fetch-ocsp-response-file` option.
|
||||
|
||||
If OCSP query is failed, previous OCSP response, if any, is continued
|
||||
to be used.
|
||||
|
||||
:option:`--fetch-ocsp-response-file` option provides wide range of
|
||||
possibility to manage OCSP response. It can take an arbitrary script
|
||||
or executable. The requirement is that it supports the command-line
|
||||
interface of ``fetch-ocsp-response`` script, and it must return a
|
||||
valid DER encoded OCSP response on success. It must return exit code
|
||||
0 on success, and 75 for temporary error, and the other error code for
|
||||
generic failure. For large cluster of servers, it is not efficient
|
||||
for each server to perform OCSP query using ``fetch-ocsp-response``.
|
||||
Instead, you can retrieve OCSP response in some way, and store it in a
|
||||
disk or a shared database. Then specify a program in
|
||||
:option:`--fetch-ocsp-response-file` to fetch it from those stores.
|
||||
This could provide a way to share the OCSP response between fleet of
|
||||
servers, and also any OCSP query strategy can be applied which may be
|
||||
beyond the ability of nghttpx itself or ``fetch-ocsp-response``
|
||||
script.
|
||||
|
||||
TLS SESSION RESUMPTION
|
||||
----------------------
|
||||
|
||||
@@ -167,6 +198,16 @@ SESSION ID RESUMPTION
|
||||
|
||||
By default, session ID is shared by all worker threads.
|
||||
|
||||
If :option:`--tls-session-cache-memcached` is given, nghttpx will
|
||||
insert serialized session data to memcached with
|
||||
``nghttpx:tls-session-cache:`` + lowercase hex string of session ID
|
||||
as a memcached entry key, with expiry time 12 hours. Session timeout
|
||||
is set to 12 hours.
|
||||
|
||||
By default, connections to memcached server are not encrypted. To
|
||||
enable encryption, use ``tls`` keyword in
|
||||
:option:`--tls-session-cache-memcached` option.
|
||||
|
||||
TLS SESSION TICKET RESUMPTION
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
||||
@@ -482,22 +482,20 @@ be called as usual.
|
||||
Stream priorities
|
||||
-----------------
|
||||
|
||||
The stream prioritization scheme described in :rfc:`7540`, which has
|
||||
been formally deprecated by :rfc:`9113`, has been removed. An
|
||||
application is advised to send
|
||||
By default, the stream prioritization scheme described in :rfc:`7540`
|
||||
is used. This scheme has been formally deprecated by :rfc:`9113`. In
|
||||
order to disable it, send
|
||||
:enum:`nghttp2_settings_id.NGHTTP2_SETTINGS_NO_RFC7540_PRIORITIES` of
|
||||
value of 1 via `nghttp2_submit_settings()`, and migrate to
|
||||
:rfc:`9218`.
|
||||
|
||||
The sender of this settings value disables :rfc:`7540` priorities, and
|
||||
instead it enables :rfc:`9218` Extensible Prioritization Scheme. This
|
||||
new prioritization scheme has 2 methods to convey the stream
|
||||
priorities to a remote endpoint: Priority header field and
|
||||
PRIORITY_UPDATE frame. nghttp2 supports both methods. In order to
|
||||
receive and process PRIORITY_UPDATE frame, server has to call
|
||||
`nghttp2_option_set_builtin_recv_extension_type()` with
|
||||
NGHTTP2_PRIORITY_UPDATE as type argument (see the above section), and
|
||||
pass the option to `nghttp2_session_server_new2()` or
|
||||
value of 1 via `nghttp2_submit_settings()`. This settings ID is
|
||||
defined by :rfc:`9218`. The sender of this settings value disables
|
||||
RFC 7540 priorities, and instead it enables RFC 9218 Extensible
|
||||
Prioritization Scheme. This new prioritization scheme has 2 methods
|
||||
to convey the stream priorities to a remote endpoint: Priority header
|
||||
field and PRIORITY_UPDATE frame. nghttp2 supports both methods. In
|
||||
order to receive and process PRIORITY_UPDATE frame, server has to call
|
||||
``nghttp2_option_set_builtin_recv_extension_type(option,
|
||||
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_request2()`. It
|
||||
can also send PRIORITY_UPDATE frame via
|
||||
@@ -505,3 +503,24 @@ can also send PRIORITY_UPDATE frame via
|
||||
field in a request header field and updates the stream priority unless
|
||||
HTTP messaging rule enforcement is disabled (see
|
||||
`nghttp2_option_set_no_http_messaging()`).
|
||||
|
||||
For the purpose of smooth migration from RFC 7540 priorities, client
|
||||
is advised to send
|
||||
:enum:`nghttp2_settings_id.NGHTTP2_SETTINGS_NO_RFC7540_PRIORITIES` of
|
||||
value of 1. Until it receives the first server SETTINGS frame, it can
|
||||
send both RFC 7540 and RFC 9128 priority signals. If client receives
|
||||
SETTINGS_NO_RFC7540_PRIORITIES of value of 0, or it is omitted ,
|
||||
client stops sending PRIORITY_UPDATE frame. Priority header field
|
||||
will be sent in anyway since it is an end-to-end signal. If
|
||||
SETTINGS_NO_RFC7540_PRIORITIES of value of 1 is received, client stops
|
||||
sending RFC 7540 priority signals. This is the advice described in
|
||||
:rfc:`9218#section-2.1.1`.
|
||||
|
||||
Server has an optional mechanism to fallback to RFC 7540 priorities.
|
||||
By default, if server sends SETTINGS_NO_RFC7540_PRIORITIES of value of
|
||||
1, it completely disables RFC 7540 priorities and no fallback. By
|
||||
setting nonzero value to
|
||||
`nghttp2_option_set_server_fallback_rfc7540_priorities()`, server
|
||||
falls back to RFC 7540 priorities if it sends
|
||||
SETTINGS_NO_RFC7540_PRIORITIES value of value of 1, and client omits
|
||||
SETTINGS_NO_RFC7540_PRIORITIES in its SETTINGS frame.
|
||||
|
||||
@@ -26,7 +26,7 @@ Coding style
|
||||
We use clang-format to format source code consistently. The
|
||||
clang-format configuration file .clang-format is located at the root
|
||||
directory. Since clang-format produces slightly different results
|
||||
between versions, we currently use clang-format-19.
|
||||
between versions, we currently use clang-format-15.
|
||||
|
||||
To detect any violation to the coding style, we recommend to setup git
|
||||
pre-commit hook to check coding style of the changes you introduced.
|
||||
@@ -34,7 +34,7 @@ The pre-commit file is located at the root directory. Copy it under
|
||||
.git/hooks and make sure that it is executable. The pre-commit script
|
||||
uses clang-format-diff.py to detect any style errors. If it is not in
|
||||
your PATH or it exists under different name (e.g.,
|
||||
clang-format-diff-18 in debian), either add it to PATH variable or add
|
||||
clang-format-diff-14 in debian), either add it to PATH variable or add
|
||||
git option ``clangformatdiff.binary`` to point to the script.
|
||||
|
||||
For emacs users, integrating clang-format to emacs is very easy.
|
||||
|
||||
@@ -167,7 +167,8 @@ Enable SSL/TLS on memcached connection
|
||||
|
||||
By default, memcached connection is not encrypted. To enable
|
||||
encryption, use ``tls`` keyword in
|
||||
:option:`--tls-ticket-key-memcached`.
|
||||
:option:`--tls-ticket-key-memcached` for TLS ticket key, and
|
||||
:option:`--tls-session-cache-memcached` for TLS session cache.
|
||||
|
||||
Specifying additional server certificates
|
||||
-----------------------------------------
|
||||
|
||||
@@ -63,7 +63,7 @@ structure is defined as follows::
|
||||
/* The NULL-terminated URI string to retrieve. */
|
||||
const char *uri;
|
||||
/* Parsed result of the |uri| */
|
||||
urlparse_url *u;
|
||||
struct http_parser_url *u;
|
||||
/* The authority portion of the |uri|, not NULL-terminated */
|
||||
char *authority;
|
||||
/* The path portion of the |uri|, including query, not
|
||||
@@ -237,11 +237,11 @@ HTTP request in the ``submit_request()`` function::
|
||||
int32_t stream_id;
|
||||
http2_stream_data *stream_data = session_data->stream_data;
|
||||
const char *uri = stream_data->uri;
|
||||
const urlparse_url *u = stream_data->u;
|
||||
const struct http_parser_url *u = stream_data->u;
|
||||
nghttp2_nv hdrs[] = {
|
||||
MAKE_NV2(":method", "GET"),
|
||||
MAKE_NV(":scheme", &uri[u->field_data[URLPARSE_SCHEMA].off],
|
||||
u->field_data[URLPARSE_SCHEMA].len),
|
||||
MAKE_NV(":scheme", &uri[u->field_data[UF_SCHEMA].off],
|
||||
u->field_data[UF_SCHEMA].len),
|
||||
MAKE_NV(":authority", stream_data->authority, stream_data->authoritylen),
|
||||
MAKE_NV(":path", stream_data->path, stream_data->pathlen)};
|
||||
fprintf(stderr, "Request headers:\n");
|
||||
|
||||
@@ -4,36 +4,32 @@ ARG NGHTTP2_BRANCH=master
|
||||
|
||||
RUN apt-get update && \
|
||||
DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
|
||||
git clang-19 make binutils autoconf automake autotools-dev libtool \
|
||||
git clang make binutils autoconf automake autotools-dev libtool \
|
||||
pkg-config cmake cmake-data \
|
||||
zlib1g-dev libev-dev libjemalloc-dev ruby-dev libc-ares-dev bison \
|
||||
libelf-dev libbrotli-dev
|
||||
|
||||
RUN git clone --recursive --shallow-submodules --depth 1 -b v1.58.1 https://github.com/aws/aws-lc && \
|
||||
RUN git clone --recursive --depth 1 -b v1.26.0 https://github.com/aws/aws-lc && \
|
||||
cd aws-lc && \
|
||||
export CC=clang-19 CXX=clang++-19 && \
|
||||
cmake -B build -DDISABLE_GO=ON && \
|
||||
make -j$(nproc) -C build && \
|
||||
cmake --install build && \
|
||||
cd .. && \
|
||||
rm -rf aws-lc
|
||||
|
||||
RUN git clone --recursive --shallow-submodules --depth 1 -b v1.11.0 https://github.com/ngtcp2/nghttp3 && \
|
||||
RUN git clone --recursive --depth 1 -b v1.3.0 https://github.com/ngtcp2/nghttp3 && \
|
||||
cd nghttp3 && \
|
||||
autoreconf -i && \
|
||||
./configure --disable-dependency-tracking --enable-lib-only \
|
||||
CC=clang-19 CXX=clang++-19 && \
|
||||
./configure --enable-lib-only && \
|
||||
make -j$(nproc) && \
|
||||
make install-strip && \
|
||||
cd .. && \
|
||||
rm -rf nghttp3
|
||||
|
||||
RUN git clone --recursive --shallow-submodules --depth 1 -b v1.15.1 https://github.com/ngtcp2/ngtcp2 && \
|
||||
RUN git clone --recursive --depth 1 -b v1.5.0 https://github.com/ngtcp2/ngtcp2 && \
|
||||
cd ngtcp2 && \
|
||||
autoreconf -i && \
|
||||
./configure --disable-dependency-tracking --enable-lib-only \
|
||||
--with-boringssl \
|
||||
CC=clang-19 CXX=clang++-19 \
|
||||
./configure --enable-lib-only --with-boringssl \
|
||||
LIBTOOL_LDFLAGS="-static-libtool-libs" \
|
||||
BORINGSSL_LIBS="-l:libssl.a -l:libcrypto.a" \
|
||||
PKG_CONFIG_PATH="/usr/local/lib64/pkgconfig" && \
|
||||
@@ -42,21 +38,20 @@ RUN git clone --recursive --shallow-submodules --depth 1 -b v1.15.1 https://gith
|
||||
cd .. && \
|
||||
rm -rf ngtcp2
|
||||
|
||||
RUN git clone --depth 1 -b v1.6.2 https://github.com/libbpf/libbpf && \
|
||||
RUN git clone --depth 1 -b v1.3.0 https://github.com/libbpf/libbpf && \
|
||||
cd libbpf && \
|
||||
CC=clang-19 PREFIX=/usr/local make -C src install && \
|
||||
PREFIX=/usr/local make -C src install && \
|
||||
cd .. && \
|
||||
rm -rf libbpf
|
||||
|
||||
RUN git clone --recursive --shallow-submodules --depth 1 -b $NGHTTP2_BRANCH https://github.com/nghttp2/nghttp2 && \
|
||||
RUN git clone --recursive --depth 1 -b $NGHTTP2_BRANCH https://github.com/nghttp2/nghttp2 && \
|
||||
cd nghttp2 && \
|
||||
autoreconf -i && \
|
||||
./configure --disable-dependency-tracking --disable-examples \
|
||||
--disable-hpack-tools \
|
||||
./configure --disable-examples --disable-hpack-tools \
|
||||
--with-mruby \
|
||||
--enable-http3 --with-libbpf \
|
||||
--with-libbrotlienc --with-libbrotlidec \
|
||||
CC=clang-19 CXX=clang++-19 \
|
||||
CC=clang CXX=clang++ \
|
||||
LIBTOOL_LDFLAGS="-static-libtool-libs" \
|
||||
OPENSSL_LIBS="-l:libssl.a -l:libcrypto.a" \
|
||||
LIBEV_LIBS="-l:libev.a" \
|
||||
@@ -74,6 +69,9 @@ RUN git clone --recursive --shallow-submodules --depth 1 -b $NGHTTP2_BRANCH http
|
||||
|
||||
FROM gcr.io/distroless/base-nossl-debian12
|
||||
|
||||
COPY --from=build --link \
|
||||
/usr/local/share/nghttp2/ \
|
||||
/usr/local/share/nghttp2/
|
||||
COPY --from=build --link \
|
||||
/usr/local/bin/h2load \
|
||||
/usr/local/bin/nghttpx \
|
||||
|
||||
@@ -8,7 +8,7 @@ if(ENABLE_EXAMPLES)
|
||||
|
||||
include_directories(
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/../third-party/urlparse"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/../third-party"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/../third-party/llhttp/include"
|
||||
|
||||
${LIBEVENT_INCLUDE_DIRS}
|
||||
@@ -23,15 +23,15 @@ if(ENABLE_EXAMPLES)
|
||||
)
|
||||
|
||||
add_executable(client client.c $<TARGET_OBJECTS:llhttp>
|
||||
$<TARGET_OBJECTS:urlparse>
|
||||
$<TARGET_OBJECTS:url-parser>
|
||||
)
|
||||
add_executable(libevent-client libevent-client.c $<TARGET_OBJECTS:llhttp>
|
||||
$<TARGET_OBJECTS:urlparse>
|
||||
$<TARGET_OBJECTS:url-parser>
|
||||
)
|
||||
add_executable(libevent-server libevent-server.c $<TARGET_OBJECTS:llhttp>
|
||||
$<TARGET_OBJECTS:urlparse>
|
||||
$<TARGET_OBJECTS:url-parser>
|
||||
)
|
||||
add_executable(deflate deflate.c $<TARGET_OBJECTS:llhttp>
|
||||
$<TARGET_OBJECTS:urlparse>
|
||||
$<TARGET_OBJECTS:url-parser>
|
||||
)
|
||||
endif()
|
||||
|
||||
@@ -30,13 +30,13 @@ AM_CXXFLAGS = $(WARNCXXFLAGS) $(CXX1XCXXFLAGS)
|
||||
AM_CPPFLAGS = \
|
||||
-I$(top_srcdir)/lib/includes \
|
||||
-I$(top_builddir)/lib/includes \
|
||||
-I$(top_srcdir)/third-party/urlparse \
|
||||
-I$(top_srcdir)/third-party \
|
||||
@LIBEVENT_OPENSSL_CFLAGS@ \
|
||||
@OPENSSL_CFLAGS@ \
|
||||
@DEFS@
|
||||
AM_LDFLAGS = @LIBTOOL_LDFLAGS@
|
||||
LDADD = $(top_builddir)/lib/libnghttp2.la \
|
||||
$(top_builddir)/third-party/liburlparse.la \
|
||||
$(top_builddir)/third-party/liburl-parser.la \
|
||||
@LIBEVENT_OPENSSL_LIBS@ \
|
||||
@OPENSSL_LIBS@ \
|
||||
@APPLDFLAGS@
|
||||
|
||||
@@ -67,14 +67,14 @@ enum { IO_NONE, WANT_READ, WANT_WRITE };
|
||||
|
||||
#define MAKE_NV(NAME, VALUE) \
|
||||
{ \
|
||||
(uint8_t *)NAME, (uint8_t *)VALUE, sizeof(NAME) - 1, \
|
||||
sizeof(VALUE) - 1, NGHTTP2_NV_FLAG_NONE, \
|
||||
(uint8_t *)NAME, (uint8_t *)VALUE, sizeof(NAME) - 1, sizeof(VALUE) - 1, \
|
||||
NGHTTP2_NV_FLAG_NONE \
|
||||
}
|
||||
|
||||
#define MAKE_NV_CS(NAME, VALUE) \
|
||||
{ \
|
||||
(uint8_t *)NAME, (uint8_t *)VALUE, sizeof(NAME) - 1, \
|
||||
strlen(VALUE), NGHTTP2_NV_FLAG_NONE, \
|
||||
(uint8_t *)NAME, (uint8_t *)VALUE, sizeof(NAME) - 1, strlen(VALUE), \
|
||||
NGHTTP2_NV_FLAG_NONE \
|
||||
}
|
||||
|
||||
struct Connection {
|
||||
@@ -176,7 +176,7 @@ static nghttp2_ssize send_callback(nghttp2_session *session,
|
||||
int err = SSL_get_error(connection->ssl, rv);
|
||||
if (err == SSL_ERROR_WANT_WRITE || err == SSL_ERROR_WANT_READ) {
|
||||
connection->want_io =
|
||||
(err == SSL_ERROR_WANT_READ ? WANT_READ : WANT_WRITE);
|
||||
(err == SSL_ERROR_WANT_READ ? WANT_READ : WANT_WRITE);
|
||||
rv = NGHTTP2_ERR_WOULDBLOCK;
|
||||
} else {
|
||||
rv = NGHTTP2_ERR_CALLBACK_FAILURE;
|
||||
@@ -207,7 +207,7 @@ static nghttp2_ssize recv_callback(nghttp2_session *session, uint8_t *buf,
|
||||
int err = SSL_get_error(connection->ssl, rv);
|
||||
if (err == SSL_ERROR_WANT_WRITE || err == SSL_ERROR_WANT_READ) {
|
||||
connection->want_io =
|
||||
(err == SSL_ERROR_WANT_READ ? WANT_READ : WANT_WRITE);
|
||||
(err == SSL_ERROR_WANT_READ ? WANT_READ : WANT_WRITE);
|
||||
rv = NGHTTP2_ERR_WOULDBLOCK;
|
||||
} else {
|
||||
rv = NGHTTP2_ERR_CALLBACK_FAILURE;
|
||||
@@ -342,10 +342,10 @@ static void setup_nghttp2_callbacks(nghttp2_session_callbacks *callbacks) {
|
||||
on_frame_recv_callback);
|
||||
|
||||
nghttp2_session_callbacks_set_on_stream_close_callback(
|
||||
callbacks, on_stream_close_callback);
|
||||
callbacks, on_stream_close_callback);
|
||||
|
||||
nghttp2_session_callbacks_set_on_data_chunk_recv_callback(
|
||||
callbacks, on_data_chunk_recv_callback);
|
||||
callbacks, on_data_chunk_recv_callback);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -34,8 +34,8 @@
|
||||
|
||||
#define MAKE_NV(K, V) \
|
||||
{ \
|
||||
(uint8_t *)K, (uint8_t *)V, sizeof(K) - 1, \
|
||||
sizeof(V) - 1, NGHTTP2_NV_FLAG_NONE, \
|
||||
(uint8_t *)K, (uint8_t *)V, sizeof(K) - 1, sizeof(V) - 1, \
|
||||
NGHTTP2_NV_FLAG_NONE \
|
||||
}
|
||||
|
||||
static void deflate(nghttp2_hd_deflater *deflater,
|
||||
@@ -51,9 +51,9 @@ int main(void) {
|
||||
nghttp2_hd_inflater *inflater;
|
||||
/* Define 1st header set. This is looks like a HTTP request. */
|
||||
nghttp2_nv nva1[] = {
|
||||
MAKE_NV(":scheme", "https"), MAKE_NV(":authority", "example.org"),
|
||||
MAKE_NV(":path", "/"), MAKE_NV("user-agent", "libnghttp2"),
|
||||
MAKE_NV("accept-encoding", "gzip, deflate")};
|
||||
MAKE_NV(":scheme", "https"), MAKE_NV(":authority", "example.org"),
|
||||
MAKE_NV(":path", "/"), MAKE_NV("user-agent", "libnghttp2"),
|
||||
MAKE_NV("accept-encoding", "gzip, deflate")};
|
||||
/* Define 2nd header set */
|
||||
nghttp2_nv nva2[] = {MAKE_NV(":scheme", "https"),
|
||||
MAKE_NV(":authority", "example.org"),
|
||||
@@ -175,7 +175,7 @@ int inflate_header_block(nghttp2_hd_inflater *inflater, uint8_t *in,
|
||||
size_t proclen;
|
||||
|
||||
rv =
|
||||
nghttp2_hd_inflate_hd3(inflater, &nv, &inflate_flags, in, inlen, final);
|
||||
nghttp2_hd_inflate_hd3(inflater, &nv, &inflate_flags, in, inlen, final);
|
||||
|
||||
if (rv < 0) {
|
||||
fprintf(stderr, "inflate failed with error code %td", rv);
|
||||
|
||||
@@ -66,7 +66,7 @@ char *strndup(const char *s, size_t size);
|
||||
#define NGHTTP2_NO_SSIZE_T
|
||||
#include <nghttp2/nghttp2.h>
|
||||
|
||||
#include "urlparse.h"
|
||||
#include "url-parser/url_parser.h"
|
||||
|
||||
#define ARRLEN(x) (sizeof(x) / sizeof(x[0]))
|
||||
|
||||
@@ -74,7 +74,7 @@ typedef struct {
|
||||
/* The NULL-terminated URI string to retrieve. */
|
||||
const char *uri;
|
||||
/* Parsed result of the |uri| */
|
||||
urlparse_url *u;
|
||||
struct http_parser_url *u;
|
||||
/* The authority portion of the |uri|, not NULL-terminated */
|
||||
char *authority;
|
||||
/* The path portion of the |uri|, including query, not
|
||||
@@ -96,7 +96,7 @@ typedef struct {
|
||||
} http2_session_data;
|
||||
|
||||
static http2_stream_data *create_http2_stream_data(const char *uri,
|
||||
urlparse_url *u) {
|
||||
struct http_parser_url *u) {
|
||||
/* MAX 5 digits (max 65535) + 1 ':' + 1 NULL (because of snprintf) */
|
||||
size_t extra = 7;
|
||||
http2_stream_data *stream_data = malloc(sizeof(http2_stream_data));
|
||||
@@ -105,41 +105,39 @@ static http2_stream_data *create_http2_stream_data(const char *uri,
|
||||
stream_data->u = u;
|
||||
stream_data->stream_id = -1;
|
||||
|
||||
stream_data->authoritylen = u->field_data[URLPARSE_HOST].len;
|
||||
stream_data->authoritylen = u->field_data[UF_HOST].len;
|
||||
stream_data->authority = malloc(stream_data->authoritylen + extra);
|
||||
memcpy(stream_data->authority, &uri[u->field_data[URLPARSE_HOST].off],
|
||||
u->field_data[URLPARSE_HOST].len);
|
||||
if (u->field_set & (1 << URLPARSE_PORT)) {
|
||||
stream_data->authoritylen += (size_t)snprintf(
|
||||
stream_data->authority + u->field_data[URLPARSE_HOST].len, extra, ":%u",
|
||||
u->port);
|
||||
memcpy(stream_data->authority, &uri[u->field_data[UF_HOST].off],
|
||||
u->field_data[UF_HOST].len);
|
||||
if (u->field_set & (1 << UF_PORT)) {
|
||||
stream_data->authoritylen +=
|
||||
(size_t)snprintf(stream_data->authority + u->field_data[UF_HOST].len,
|
||||
extra, ":%u", u->port);
|
||||
}
|
||||
|
||||
/* If we don't have path in URI, we use "/" as path. */
|
||||
stream_data->pathlen = 1;
|
||||
if (u->field_set & (1 << URLPARSE_PATH)) {
|
||||
stream_data->pathlen = u->field_data[URLPARSE_PATH].len;
|
||||
if (u->field_set & (1 << UF_PATH)) {
|
||||
stream_data->pathlen = u->field_data[UF_PATH].len;
|
||||
}
|
||||
if (u->field_set & (1 << URLPARSE_QUERY)) {
|
||||
if (u->field_set & (1 << UF_QUERY)) {
|
||||
/* +1 for '?' character */
|
||||
stream_data->pathlen += (size_t)(u->field_data[URLPARSE_QUERY].len + 1);
|
||||
stream_data->pathlen += (size_t)(u->field_data[UF_QUERY].len + 1);
|
||||
}
|
||||
|
||||
stream_data->path = malloc(stream_data->pathlen);
|
||||
if (u->field_set & (1 << URLPARSE_PATH)) {
|
||||
memcpy(stream_data->path, &uri[u->field_data[URLPARSE_PATH].off],
|
||||
u->field_data[URLPARSE_PATH].len);
|
||||
if (u->field_set & (1 << UF_PATH)) {
|
||||
memcpy(stream_data->path, &uri[u->field_data[UF_PATH].off],
|
||||
u->field_data[UF_PATH].len);
|
||||
} else {
|
||||
stream_data->path[0] = '/';
|
||||
}
|
||||
if (u->field_set & (1 << URLPARSE_QUERY)) {
|
||||
stream_data
|
||||
->path[stream_data->pathlen - u->field_data[URLPARSE_QUERY].len - 1] =
|
||||
'?';
|
||||
if (u->field_set & (1 << UF_QUERY)) {
|
||||
stream_data->path[stream_data->pathlen - u->field_data[UF_QUERY].len - 1] =
|
||||
'?';
|
||||
memcpy(stream_data->path + stream_data->pathlen -
|
||||
u->field_data[URLPARSE_QUERY].len,
|
||||
&uri[u->field_data[URLPARSE_QUERY].off],
|
||||
u->field_data[URLPARSE_QUERY].len);
|
||||
u->field_data[UF_QUERY].len,
|
||||
&uri[u->field_data[UF_QUERY].off], u->field_data[UF_QUERY].len);
|
||||
}
|
||||
|
||||
return stream_data;
|
||||
@@ -320,9 +318,10 @@ static SSL_CTX *create_ssl_ctx(void) {
|
||||
errx(1, "Could not create SSL/TLS context: %s",
|
||||
ERR_error_string(ERR_get_error(), NULL));
|
||||
}
|
||||
SSL_CTX_set_options(ssl_ctx, SSL_OP_ALL | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 |
|
||||
SSL_OP_NO_COMPRESSION |
|
||||
SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION);
|
||||
SSL_CTX_set_options(ssl_ctx,
|
||||
SSL_OP_ALL | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 |
|
||||
SSL_OP_NO_COMPRESSION |
|
||||
SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION);
|
||||
|
||||
SSL_CTX_set_alpn_protos(ssl_ctx, (const unsigned char *)"\x02h2", 3);
|
||||
|
||||
@@ -351,16 +350,16 @@ static void initialize_nghttp2_session(http2_session_data *session_data) {
|
||||
on_frame_recv_callback);
|
||||
|
||||
nghttp2_session_callbacks_set_on_data_chunk_recv_callback(
|
||||
callbacks, on_data_chunk_recv_callback);
|
||||
callbacks, on_data_chunk_recv_callback);
|
||||
|
||||
nghttp2_session_callbacks_set_on_stream_close_callback(
|
||||
callbacks, on_stream_close_callback);
|
||||
callbacks, on_stream_close_callback);
|
||||
|
||||
nghttp2_session_callbacks_set_on_header_callback(callbacks,
|
||||
on_header_callback);
|
||||
|
||||
nghttp2_session_callbacks_set_on_begin_headers_callback(
|
||||
callbacks, on_begin_headers_callback);
|
||||
callbacks, on_begin_headers_callback);
|
||||
|
||||
nghttp2_session_client_new(&session_data->session, callbacks, session_data);
|
||||
|
||||
@@ -369,7 +368,7 @@ static void initialize_nghttp2_session(http2_session_data *session_data) {
|
||||
|
||||
static void send_client_connection_header(http2_session_data *session_data) {
|
||||
nghttp2_settings_entry iv[1] = {
|
||||
{NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS, 100}};
|
||||
{NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS, 100}};
|
||||
int rv;
|
||||
|
||||
/* client 24 bytes magic string will be sent by nghttp2 library */
|
||||
@@ -382,14 +381,14 @@ static void send_client_connection_header(http2_session_data *session_data) {
|
||||
|
||||
#define MAKE_NV(NAME, VALUE, VALUELEN) \
|
||||
{ \
|
||||
(uint8_t *)NAME, (uint8_t *)VALUE, sizeof(NAME) - 1, \
|
||||
VALUELEN, NGHTTP2_NV_FLAG_NONE, \
|
||||
(uint8_t *)NAME, (uint8_t *)VALUE, sizeof(NAME) - 1, VALUELEN, \
|
||||
NGHTTP2_NV_FLAG_NONE \
|
||||
}
|
||||
|
||||
#define MAKE_NV2(NAME, VALUE) \
|
||||
{ \
|
||||
(uint8_t *)NAME, (uint8_t *)VALUE, sizeof(NAME) - 1, \
|
||||
sizeof(VALUE) - 1, NGHTTP2_NV_FLAG_NONE, \
|
||||
(uint8_t *)NAME, (uint8_t *)VALUE, sizeof(NAME) - 1, sizeof(VALUE) - 1, \
|
||||
NGHTTP2_NV_FLAG_NONE \
|
||||
}
|
||||
|
||||
/* Send HTTP request to the remote peer */
|
||||
@@ -397,13 +396,13 @@ static void submit_request(http2_session_data *session_data) {
|
||||
int32_t stream_id;
|
||||
http2_stream_data *stream_data = session_data->stream_data;
|
||||
const char *uri = stream_data->uri;
|
||||
const urlparse_url *u = stream_data->u;
|
||||
const struct http_parser_url *u = stream_data->u;
|
||||
nghttp2_nv hdrs[] = {
|
||||
MAKE_NV2(":method", "GET"),
|
||||
MAKE_NV(":scheme", &uri[u->field_data[URLPARSE_SCHEMA].off],
|
||||
u->field_data[URLPARSE_SCHEMA].len),
|
||||
MAKE_NV(":authority", stream_data->authority, stream_data->authoritylen),
|
||||
MAKE_NV(":path", stream_data->path, stream_data->pathlen)};
|
||||
MAKE_NV2(":method", "GET"),
|
||||
MAKE_NV(":scheme", &uri[u->field_data[UF_SCHEMA].off],
|
||||
u->field_data[UF_SCHEMA].len),
|
||||
MAKE_NV(":authority", stream_data->authority, stream_data->authoritylen),
|
||||
MAKE_NV(":path", stream_data->path, stream_data->pathlen)};
|
||||
fprintf(stderr, "Request headers:\n");
|
||||
print_headers(stderr, hdrs, ARRLEN(hdrs));
|
||||
stream_id = nghttp2_submit_request2(session_data->session, NULL, hdrs,
|
||||
@@ -528,8 +527,8 @@ static void initiate_connection(struct event_base *evbase, SSL_CTX *ssl_ctx,
|
||||
|
||||
ssl = create_ssl(ssl_ctx);
|
||||
bev = bufferevent_openssl_socket_new(
|
||||
evbase, -1, ssl, BUFFEREVENT_SSL_CONNECTING,
|
||||
BEV_OPT_DEFER_CALLBACKS | BEV_OPT_CLOSE_ON_FREE);
|
||||
evbase, -1, ssl, BUFFEREVENT_SSL_CONNECTING,
|
||||
BEV_OPT_DEFER_CALLBACKS | BEV_OPT_CLOSE_ON_FREE);
|
||||
bufferevent_enable(bev, EV_READ | EV_WRITE);
|
||||
bufferevent_setcb(bev, readcb, writecb, eventcb, session_data);
|
||||
rv = bufferevent_socket_connect_hostname(bev, session_data->dnsbase,
|
||||
@@ -544,7 +543,7 @@ static void initiate_connection(struct event_base *evbase, SSL_CTX *ssl_ctx,
|
||||
/* Get resource denoted by the |uri|. The debug and error messages are
|
||||
printed in stderr, while the response body is printed in stdout. */
|
||||
static void run(const char *uri) {
|
||||
urlparse_url u;
|
||||
struct http_parser_url u;
|
||||
char *host;
|
||||
uint16_t port;
|
||||
int rv;
|
||||
@@ -553,13 +552,12 @@ static void run(const char *uri) {
|
||||
http2_session_data *session_data;
|
||||
|
||||
/* Parse the |uri| and stores its components in |u| */
|
||||
rv = urlparse_parse_url(uri, strlen(uri), 0, &u);
|
||||
rv = http_parser_parse_url(uri, strlen(uri), 0, &u);
|
||||
if (rv != 0) {
|
||||
errx(1, "Could not parse URI %s", uri);
|
||||
}
|
||||
host = strndup(&uri[u.field_data[URLPARSE_HOST].off],
|
||||
u.field_data[URLPARSE_HOST].len);
|
||||
if (!(u.field_set & (1 << URLPARSE_PORT))) {
|
||||
host = strndup(&uri[u.field_data[UF_HOST].off], u.field_data[UF_HOST].len);
|
||||
if (!(u.field_set & (1 << UF_PORT))) {
|
||||
port = 443;
|
||||
} else {
|
||||
port = u.port;
|
||||
|
||||
@@ -80,8 +80,8 @@
|
||||
|
||||
#define MAKE_NV(NAME, VALUE) \
|
||||
{ \
|
||||
(uint8_t *)NAME, (uint8_t *)VALUE, sizeof(NAME) - 1, \
|
||||
sizeof(VALUE) - 1, NGHTTP2_NV_FLAG_NONE, \
|
||||
(uint8_t *)NAME, (uint8_t *)VALUE, sizeof(NAME) - 1, sizeof(VALUE) - 1, \
|
||||
NGHTTP2_NV_FLAG_NONE \
|
||||
}
|
||||
|
||||
struct app_context;
|
||||
@@ -132,9 +132,10 @@ static SSL_CTX *create_ssl_ctx(const char *key_file, const char *cert_file) {
|
||||
errx(1, "Could not create SSL/TLS context: %s",
|
||||
ERR_error_string(ERR_get_error(), NULL));
|
||||
}
|
||||
SSL_CTX_set_options(ssl_ctx, SSL_OP_ALL | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 |
|
||||
SSL_OP_NO_COMPRESSION |
|
||||
SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION);
|
||||
SSL_CTX_set_options(ssl_ctx,
|
||||
SSL_OP_ALL | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 |
|
||||
SSL_OP_NO_COMPRESSION |
|
||||
SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION);
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
|
||||
if (SSL_CTX_set1_curves_list(ssl_ctx, "P-256") != 1) {
|
||||
errx(1, "SSL_CTX_set1_curves_list failed: %s",
|
||||
@@ -232,8 +233,8 @@ static http2_session_data *create_http2_session_data(app_context *app_ctx,
|
||||
session_data->app_ctx = app_ctx;
|
||||
setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char *)&val, sizeof(val));
|
||||
session_data->bev = bufferevent_openssl_socket_new(
|
||||
app_ctx->evbase, fd, ssl, BUFFEREVENT_SSL_ACCEPTING,
|
||||
BEV_OPT_CLOSE_ON_FREE | BEV_OPT_DEFER_CALLBACKS);
|
||||
app_ctx->evbase, fd, ssl, BUFFEREVENT_SSL_ACCEPTING,
|
||||
BEV_OPT_CLOSE_ON_FREE | BEV_OPT_DEFER_CALLBACKS);
|
||||
bufferevent_enable(session_data->bev, EV_READ | EV_WRITE);
|
||||
rv = getnameinfo(addr, (socklen_t)addrlen, host, sizeof(host), NULL, 0,
|
||||
NI_NUMERICHOST);
|
||||
@@ -359,7 +360,7 @@ static char *percent_decode(const uint8_t *value, size_t valuelen) {
|
||||
continue;
|
||||
}
|
||||
res[j++] =
|
||||
(char)((hex_to_uint(value[i + 1]) << 4) + hex_to_uint(value[i + 2]));
|
||||
(char)((hex_to_uint(value[i + 1]) << 4) + hex_to_uint(value[i + 2]));
|
||||
i += 3;
|
||||
}
|
||||
memcpy(&res[j], &value[i], 2);
|
||||
@@ -421,9 +422,9 @@ static int error_reply(nghttp2_session *session,
|
||||
rv = pipe(pipefd);
|
||||
if (rv != 0) {
|
||||
warn("Could not create pipe");
|
||||
rv =
|
||||
nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE,
|
||||
stream_data->stream_id, NGHTTP2_INTERNAL_ERROR);
|
||||
rv = nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE,
|
||||
stream_data->stream_id,
|
||||
NGHTTP2_INTERNAL_ERROR);
|
||||
if (rv != 0) {
|
||||
warnx("Fatal error: %s", nghttp2_strerror(rv));
|
||||
return -1;
|
||||
@@ -466,7 +467,7 @@ static int on_header_callback(nghttp2_session *session,
|
||||
break;
|
||||
}
|
||||
stream_data =
|
||||
nghttp2_session_get_stream_user_data(session, frame->hd.stream_id);
|
||||
nghttp2_session_get_stream_user_data(session, frame->hd.stream_id);
|
||||
if (!stream_data || stream_data->request_path) {
|
||||
break;
|
||||
}
|
||||
@@ -556,7 +557,7 @@ static int on_frame_recv_callback(nghttp2_session *session,
|
||||
/* Check that the client request has finished */
|
||||
if (frame->hd.flags & NGHTTP2_FLAG_END_STREAM) {
|
||||
stream_data =
|
||||
nghttp2_session_get_stream_user_data(session, frame->hd.stream_id);
|
||||
nghttp2_session_get_stream_user_data(session, frame->hd.stream_id);
|
||||
/* For DATA and HEADERS frame, this callback may be called after
|
||||
on_stream_close_callback. Check that stream still alive. */
|
||||
if (!stream_data) {
|
||||
@@ -597,13 +598,13 @@ static void initialize_nghttp2_session(http2_session_data *session_data) {
|
||||
on_frame_recv_callback);
|
||||
|
||||
nghttp2_session_callbacks_set_on_stream_close_callback(
|
||||
callbacks, on_stream_close_callback);
|
||||
callbacks, on_stream_close_callback);
|
||||
|
||||
nghttp2_session_callbacks_set_on_header_callback(callbacks,
|
||||
on_header_callback);
|
||||
|
||||
nghttp2_session_callbacks_set_on_begin_headers_callback(
|
||||
callbacks, on_begin_headers_callback);
|
||||
callbacks, on_begin_headers_callback);
|
||||
|
||||
nghttp2_session_server_new(&session_data->session, callbacks, session_data);
|
||||
|
||||
@@ -614,7 +615,7 @@ static void initialize_nghttp2_session(http2_session_data *session_data) {
|
||||
magic octets and SETTINGS frame */
|
||||
static int send_server_connection_header(http2_session_data *session_data) {
|
||||
nghttp2_settings_entry iv[1] = {
|
||||
{NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS, 100}};
|
||||
{NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS, 100}};
|
||||
int rv;
|
||||
|
||||
rv = nghttp2_submit_settings(session_data->session, NGHTTP2_FLAG_NONE, iv,
|
||||
@@ -736,8 +737,8 @@ static void start_listen(struct event_base *evbase, const char *service,
|
||||
for (rp = res; rp; rp = rp->ai_next) {
|
||||
struct evconnlistener *listener;
|
||||
listener = evconnlistener_new_bind(
|
||||
evbase, acceptcb, app_ctx, LEV_OPT_CLOSE_ON_FREE | LEV_OPT_REUSEABLE, 16,
|
||||
rp->ai_addr, (int)rp->ai_addrlen);
|
||||
evbase, acceptcb, app_ctx, LEV_OPT_CLOSE_ON_FREE | LEV_OPT_REUSEABLE,
|
||||
16, rp->ai_addr, (int)rp->ai_addrlen);
|
||||
if (listener) {
|
||||
freeaddrinfo(res);
|
||||
|
||||
|
||||
@@ -62,8 +62,8 @@ void check_frame_pack_headers(FuzzedDataProvider *data_provider) {
|
||||
nvlen = HEADERS_LENGTH;
|
||||
nghttp2_priority_spec_default_init(&pri_spec);
|
||||
nghttp2_frame_headers_init(
|
||||
&frame, NGHTTP2_FLAG_END_STREAM | NGHTTP2_FLAG_END_HEADERS, 1000000007,
|
||||
NGHTTP2_HCAT_REQUEST, &pri_spec, nva, nvlen);
|
||||
&frame, NGHTTP2_FLAG_END_STREAM | NGHTTP2_FLAG_END_HEADERS, 1000000007,
|
||||
NGHTTP2_HCAT_REQUEST, &pri_spec, nva, nvlen);
|
||||
|
||||
/* Perform a set of operations with the fuzz data */
|
||||
rv = nghttp2_frame_pack_headers(&bufs, &frame, &deflater);
|
||||
|
||||
@@ -56,11 +56,11 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
|
||||
nghttp2_session_callbacks_set_on_frame_recv_callback(callbacks,
|
||||
on_frame_recv_callback);
|
||||
nghttp2_session_callbacks_set_on_begin_headers_callback(
|
||||
callbacks, on_begin_headers_callback);
|
||||
callbacks, on_begin_headers_callback);
|
||||
nghttp2_session_callbacks_set_on_header_callback2(callbacks,
|
||||
on_header_callback2);
|
||||
nghttp2_session_callbacks_set_before_frame_send_callback(
|
||||
callbacks, before_frame_send_callback);
|
||||
callbacks, before_frame_send_callback);
|
||||
nghttp2_session_callbacks_set_on_frame_send_callback(callbacks,
|
||||
on_frame_send_callback);
|
||||
|
||||
|
||||
@@ -60,11 +60,11 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
|
||||
nghttp2_session_callbacks_set_on_frame_recv_callback(callbacks,
|
||||
on_frame_recv_callback);
|
||||
nghttp2_session_callbacks_set_on_begin_headers_callback(
|
||||
callbacks, on_begin_headers_callback);
|
||||
callbacks, on_begin_headers_callback);
|
||||
nghttp2_session_callbacks_set_on_header_callback2(callbacks,
|
||||
on_header_callback2);
|
||||
nghttp2_session_callbacks_set_before_frame_send_callback(
|
||||
callbacks, before_frame_send_callback);
|
||||
callbacks, before_frame_send_callback);
|
||||
nghttp2_session_callbacks_set_on_frame_send_callback(callbacks,
|
||||
on_frame_send_callback);
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ enum {''')
|
||||
|
||||
def gen_index_header(tokens, prefix, comp_fun, return_type, fail_value):
|
||||
print('''\
|
||||
{} lookup_token(const std::string_view &name) {{
|
||||
{} lookup_token(const StringRef &name) {{
|
||||
switch (name.size()) {{'''.format(return_type))
|
||||
b = build_header(tokens)
|
||||
for size in sorted(b.keys()):
|
||||
@@ -50,7 +50,7 @@ def gen_index_header(tokens, prefix, comp_fun, return_type, fail_value):
|
||||
case '{}':'''.format(c))
|
||||
for k in headers:
|
||||
print('''\
|
||||
if ({}("{}"sv, name.substr(0, {}))) {{
|
||||
if ({}("{}"_sr, name, {})) {{
|
||||
return {};
|
||||
}}'''.format(comp_fun, k[:-1], size - 1, to_enum_hd(k, prefix)))
|
||||
print('''\
|
||||
|
||||
25
go.mod
25
go.mod
@@ -1,21 +1,24 @@
|
||||
module github.com/nghttp2/nghttp2
|
||||
|
||||
go 1.24.0
|
||||
go 1.21.1
|
||||
|
||||
require (
|
||||
github.com/bradfitz/gomemcache v0.0.0-20230905024940-24af94b03874
|
||||
github.com/quic-go/quic-go v0.54.0
|
||||
github.com/quic-go/quic-go v0.43.1
|
||||
github.com/tatsuhiro-t/go-nghttp2 v0.0.0-20240121064059-46ccb0a462a8
|
||||
golang.org/x/net v0.43.0
|
||||
golang.org/x/net v0.24.0
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/quic-go/qpack v0.5.1 // indirect
|
||||
go.uber.org/mock v0.5.0 // indirect
|
||||
golang.org/x/crypto v0.41.0 // indirect
|
||||
golang.org/x/mod v0.26.0 // indirect
|
||||
golang.org/x/sync v0.16.0 // indirect
|
||||
golang.org/x/sys v0.35.0 // indirect
|
||||
golang.org/x/text v0.28.0 // indirect
|
||||
golang.org/x/tools v0.35.0 // indirect
|
||||
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect
|
||||
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 // indirect
|
||||
github.com/onsi/ginkgo/v2 v2.9.5 // indirect
|
||||
github.com/quic-go/qpack v0.4.0 // indirect
|
||||
go.uber.org/mock v0.4.0 // indirect
|
||||
golang.org/x/crypto v0.22.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.19.0 // indirect
|
||||
golang.org/x/text v0.14.0 // indirect
|
||||
golang.org/x/tools v0.9.1 // indirect
|
||||
)
|
||||
|
||||
73
go.sum
73
go.sum
@@ -1,34 +1,59 @@
|
||||
github.com/bradfitz/gomemcache v0.0.0-20230905024940-24af94b03874 h1:N7oVaKyGp8bttX0bfZGmcGkjz7DLQXhAn3DNd3T0ous=
|
||||
github.com/bradfitz/gomemcache v0.0.0-20230905024940-24af94b03874/go.mod h1:r5xuitiExdLAJ09PR7vBVENGvp4ZuTBeWTGtxuX3K+c=
|
||||
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
||||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
|
||||
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ=
|
||||
github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI=
|
||||
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls=
|
||||
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
|
||||
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
||||
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 h1:yAJXTCF9TqKcTiHJAE8dj7HMvPfh66eeA2JYW7eFpSE=
|
||||
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||
github.com/onsi/ginkgo/v2 v2.9.5 h1:+6Hr4uxzP4XIUyAkg61dWBw8lb/gc4/X5luuxN/EC+Q=
|
||||
github.com/onsi/ginkgo/v2 v2.9.5/go.mod h1:tvAoo1QUJwNEU2ITftXTpR7R1RbCzoZUOs3RonqW57k=
|
||||
github.com/onsi/gomega v1.27.6 h1:ENqfyGeS5AX/rlXDd/ETokDz93u0YufY1Pgxuy/PvWE=
|
||||
github.com/onsi/gomega v1.27.6/go.mod h1:PIQNjfQwkP3aQAH7lf7j87O/5FiNr+ZR8+ipb+qQlhg=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/quic-go/qpack v0.5.1 h1:giqksBPnT/HDtZ6VhtFKgoLOWmlyo9Ei6u9PqzIMbhI=
|
||||
github.com/quic-go/qpack v0.5.1/go.mod h1:+PC4XFrEskIVkcLzpEkbLqq1uCoxPhQuvK5rH1ZgaEg=
|
||||
github.com/quic-go/quic-go v0.54.0 h1:6s1YB9QotYI6Ospeiguknbp2Znb/jZYjZLRXn9kMQBg=
|
||||
github.com/quic-go/quic-go v0.54.0/go.mod h1:e68ZEaCdyviluZmy44P6Iey98v/Wfz6HCjQEm+l8zTY=
|
||||
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
||||
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/quic-go/qpack v0.4.0 h1:Cr9BXA1sQS2SmDUWjSofMPNKmvF6IiIfDRmgU0w1ZCo=
|
||||
github.com/quic-go/qpack v0.4.0/go.mod h1:UZVnYIfi5GRk+zI9UMaCPsmZ2xKJP7XBUvVyT1Knj9A=
|
||||
github.com/quic-go/quic-go v0.43.1 h1:fLiMNfQVe9q2JvSsiXo4fXOEguXHGGl9+6gLp4RPeZQ=
|
||||
github.com/quic-go/quic-go v0.43.1/go.mod h1:132kz4kL3F9vxhW3CtQJLDVwcFe5wdWeJXXijhsO57M=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
|
||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/tatsuhiro-t/go-nghttp2 v0.0.0-20240121064059-46ccb0a462a8 h1:zKJxuRe+a0O34V81GAZWOrotuU6mveT30QLjJ7OPMMg=
|
||||
github.com/tatsuhiro-t/go-nghttp2 v0.0.0-20240121064059-46ccb0a462a8/go.mod h1:gTqc3Q4boc+cKRlSFywTYdX9t6VGRcsThlNIWwaL3Dc=
|
||||
go.uber.org/mock v0.5.0 h1:KAMbZvZPyBPWgD14IrIQ38QCyjwpvVVV6K/bHl1IwQU=
|
||||
go.uber.org/mock v0.5.0/go.mod h1:ge71pBPLYDk7QIi1LupWxdAykm7KIEFchiOqd6z7qMM=
|
||||
golang.org/x/crypto v0.41.0 h1:WKYxWedPGCTVVl5+WHSSrOBT0O8lx32+zxmHxijgXp4=
|
||||
golang.org/x/crypto v0.41.0/go.mod h1:pO5AFd7FA68rFak7rOAGVuygIISepHftHnr8dr6+sUc=
|
||||
golang.org/x/mod v0.26.0 h1:EGMPT//Ezu+ylkCijjPc+f4Aih7sZvaAr+O3EHBxvZg=
|
||||
golang.org/x/mod v0.26.0/go.mod h1:/j6NAhSk8iQ723BGAUyoAcn7SlD7s15Dp9Nd/SfeaFQ=
|
||||
golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE=
|
||||
golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg=
|
||||
golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw=
|
||||
golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
||||
golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI=
|
||||
golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng=
|
||||
golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU=
|
||||
golang.org/x/tools v0.35.0 h1:mBffYraMEf7aa0sB+NuKnuCy8qI/9Bughn8dC2Gu5r0=
|
||||
golang.org/x/tools v0.35.0/go.mod h1:NKdj5HkL/73byiZSJjqJgKn3ep7KjFkBOkR/Hps3VPw=
|
||||
go.uber.org/mock v0.4.0 h1:VcM4ZOtdbR4f6VXfiOpwpVJDL6lCReaZ6mw31wqh7KU=
|
||||
go.uber.org/mock v0.4.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc=
|
||||
golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30=
|
||||
golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M=
|
||||
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.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w=
|
||||
golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8=
|
||||
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o=
|
||||
golang.org/x/sys v0.19.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/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
|
||||
golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
||||
golang.org/x/tools v0.9.1 h1:8WMNJAz3zrtPmnYC7ISf5dEn3MT0gY7jBJfw27yrrLo=
|
||||
golang.org/x/tools v0.9.1/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc=
|
||||
google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw=
|
||||
google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
|
||||
@@ -4,7 +4,6 @@ import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
@@ -63,7 +62,6 @@ func TestH1H1InvalidMethod(t *testing.T) {
|
||||
t.Errorf("server should not forward this request")
|
||||
},
|
||||
}
|
||||
|
||||
st := newServerTester(t, opts)
|
||||
defer st.Close()
|
||||
|
||||
@@ -88,7 +86,6 @@ func TestH1H1MultipleRequestCL(t *testing.T) {
|
||||
t.Errorf("server should not forward bad request")
|
||||
},
|
||||
}
|
||||
|
||||
st := newServerTester(t, opts)
|
||||
defer st.Close()
|
||||
|
||||
@@ -136,7 +133,6 @@ func TestH1H1AffinityCookie(t *testing.T) {
|
||||
opts := options{
|
||||
args: []string{"--affinity-cookie"},
|
||||
}
|
||||
|
||||
st := newServerTester(t, opts)
|
||||
defer st.Close()
|
||||
|
||||
@@ -153,7 +149,6 @@ func TestH1H1AffinityCookie(t *testing.T) {
|
||||
|
||||
const pattern = `affinity=[0-9a-f]{8}; Path=/foo/bar`
|
||||
validCookie := regexp.MustCompile(pattern)
|
||||
|
||||
if got := res.header.Get("Set-Cookie"); !validCookie.MatchString(got) {
|
||||
t.Errorf("Set-Cookie: %v; want pattern %v", got, pattern)
|
||||
}
|
||||
@@ -166,7 +161,6 @@ func TestH1H1AffinityCookieTLS(t *testing.T) {
|
||||
args: []string{"--alpn-h1", "--affinity-cookie"},
|
||||
tls: true,
|
||||
}
|
||||
|
||||
st := newServerTester(t, opts)
|
||||
defer st.Close()
|
||||
|
||||
@@ -183,7 +177,6 @@ func TestH1H1AffinityCookieTLS(t *testing.T) {
|
||||
|
||||
const pattern = `affinity=[0-9a-f]{8}; Path=/foo/bar; Secure`
|
||||
validCookie := regexp.MustCompile(pattern)
|
||||
|
||||
if got := res.header.Get("Set-Cookie"); !validCookie.MatchString(got) {
|
||||
t.Errorf("Set-Cookie: %v; want pattern %v", got, pattern)
|
||||
}
|
||||
@@ -228,8 +221,7 @@ func TestH1H1GracefulShutdown(t *testing.T) {
|
||||
|
||||
want := io.EOF
|
||||
b := make([]byte, 256)
|
||||
|
||||
if _, err := st.conn.Read(b); !errors.Is(err, want) {
|
||||
if _, err := st.conn.Read(b); err == nil || err != want {
|
||||
t.Errorf("st.conn.Read(): %v; want %v", err, want)
|
||||
}
|
||||
}
|
||||
@@ -242,7 +234,6 @@ func TestH1H1HostRewrite(t *testing.T) {
|
||||
w.Header().Add("request-host", r.Host)
|
||||
},
|
||||
}
|
||||
|
||||
st := newServerTester(t, opts)
|
||||
defer st.Close()
|
||||
|
||||
@@ -252,11 +243,9 @@ func TestH1H1HostRewrite(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatalf("Error st.http1() = %v", err)
|
||||
}
|
||||
|
||||
if got, want := res.status, http.StatusOK; got != want {
|
||||
t.Errorf("status: %v; want %v", got, want)
|
||||
}
|
||||
|
||||
if got, want := res.header.Get("request-host"), st.backendHost; got != want {
|
||||
t.Errorf("request-host: %v; want %v", got, want)
|
||||
}
|
||||
@@ -270,14 +259,12 @@ func TestH1H1BadHost(t *testing.T) {
|
||||
t.Errorf("server should not forward this request")
|
||||
},
|
||||
}
|
||||
|
||||
st := newServerTester(t, opts)
|
||||
defer st.Close()
|
||||
|
||||
if _, err := io.WriteString(st.conn, "GET / HTTP/1.1\r\nTest-Case: TestH1H1HBadHost\r\nHost: foo\"bar\r\n\r\n"); err != nil {
|
||||
t.Fatalf("Error io.WriteString() = %v", err)
|
||||
}
|
||||
|
||||
resp, err := http.ReadResponse(bufio.NewReader(st.conn), nil)
|
||||
if err != nil {
|
||||
t.Fatalf("Error http.ReadResponse() = %v", err)
|
||||
@@ -298,14 +285,12 @@ func TestH1H1BadAuthority(t *testing.T) {
|
||||
t.Errorf("server should not forward this request")
|
||||
},
|
||||
}
|
||||
|
||||
st := newServerTester(t, opts)
|
||||
defer st.Close()
|
||||
|
||||
if _, err := io.WriteString(st.conn, "GET http://foo\"bar/ HTTP/1.1\r\nTest-Case: TestH1H1HBadAuthority\r\nHost: foobar\r\n\r\n"); err != nil {
|
||||
t.Fatalf("Error io.WriteString() = %v", err)
|
||||
}
|
||||
|
||||
resp, err := http.ReadResponse(bufio.NewReader(st.conn), nil)
|
||||
if err != nil {
|
||||
t.Fatalf("Error http.ReadResponse() = %v", err)
|
||||
@@ -326,14 +311,12 @@ func TestH1H1BadScheme(t *testing.T) {
|
||||
t.Errorf("server should not forward this request")
|
||||
},
|
||||
}
|
||||
|
||||
st := newServerTester(t, opts)
|
||||
defer st.Close()
|
||||
|
||||
if _, err := io.WriteString(st.conn, "GET http*://example.com/ HTTP/1.1\r\nTest-Case: TestH1H1HBadScheme\r\nHost: example.com\r\n\r\n"); err != nil {
|
||||
t.Fatalf("Error io.WriteString() = %v", err)
|
||||
}
|
||||
|
||||
resp, err := http.ReadResponse(bufio.NewReader(st.conn), nil)
|
||||
if err != nil {
|
||||
t.Fatalf("Error http.ReadResponse() = %v", err)
|
||||
@@ -354,7 +337,6 @@ func TestH1H1HTTP10(t *testing.T) {
|
||||
w.Header().Add("request-host", r.Host)
|
||||
},
|
||||
}
|
||||
|
||||
st := newServerTester(t, opts)
|
||||
defer st.Close()
|
||||
|
||||
@@ -372,7 +354,6 @@ func TestH1H1HTTP10(t *testing.T) {
|
||||
if got, want := resp.StatusCode, http.StatusOK; got != want {
|
||||
t.Errorf("status: %v; want %v", got, want)
|
||||
}
|
||||
|
||||
if got, want := resp.Header.Get("request-host"), st.backendHost; got != want {
|
||||
t.Errorf("request-host: %v; want %v", got, want)
|
||||
}
|
||||
@@ -387,7 +368,6 @@ func TestH1H1HTTP10NoHostRewrite(t *testing.T) {
|
||||
w.Header().Add("request-host", r.Host)
|
||||
},
|
||||
}
|
||||
|
||||
st := newServerTester(t, opts)
|
||||
defer st.Close()
|
||||
|
||||
@@ -405,7 +385,6 @@ func TestH1H1HTTP10NoHostRewrite(t *testing.T) {
|
||||
if got, want := resp.StatusCode, http.StatusOK; got != want {
|
||||
t.Errorf("status: %v; want %v", got, want)
|
||||
}
|
||||
|
||||
if got, want := resp.Header.Get("request-host"), st.backendHost; got != want {
|
||||
t.Errorf("request-host: %v; want %v", got, want)
|
||||
}
|
||||
@@ -419,11 +398,10 @@ func TestH1H1RequestTrailer(t *testing.T) {
|
||||
buf := make([]byte, 4096)
|
||||
for {
|
||||
_, err := r.Body.Read(buf)
|
||||
if err == io.EOF {
|
||||
break
|
||||
}
|
||||
if err != nil {
|
||||
if errors.Is(err, io.EOF) {
|
||||
break
|
||||
}
|
||||
|
||||
t.Fatalf("r.Body.Read() = %v", err)
|
||||
}
|
||||
}
|
||||
@@ -432,7 +410,6 @@ func TestH1H1RequestTrailer(t *testing.T) {
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
st := newServerTester(t, opts)
|
||||
defer st.Close()
|
||||
|
||||
@@ -446,7 +423,6 @@ func TestH1H1RequestTrailer(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatalf("Error st.http1() = %v", err)
|
||||
}
|
||||
|
||||
if got, want := res.status, http.StatusOK; got != want {
|
||||
t.Errorf("res.status: %v; want %v", got, want)
|
||||
}
|
||||
@@ -464,7 +440,6 @@ func TestH1H1HeaderFieldBufferPath(t *testing.T) {
|
||||
t.Fatal("execution path should not be here")
|
||||
},
|
||||
}
|
||||
|
||||
st := newServerTester(t, opts)
|
||||
defer st.Close()
|
||||
|
||||
@@ -475,7 +450,6 @@ func TestH1H1HeaderFieldBufferPath(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatalf("Error st.http1() = %v", err)
|
||||
}
|
||||
|
||||
if got, want := res.status, http.StatusRequestHeaderFieldsTooLarge; got != want {
|
||||
t.Errorf("status: %v; want %v", got, want)
|
||||
}
|
||||
@@ -490,7 +464,6 @@ func TestH1H1HeaderFieldBuffer(t *testing.T) {
|
||||
t.Fatal("execution path should not be here")
|
||||
},
|
||||
}
|
||||
|
||||
st := newServerTester(t, opts)
|
||||
defer st.Close()
|
||||
|
||||
@@ -500,7 +473,6 @@ func TestH1H1HeaderFieldBuffer(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatalf("Error st.http1() = %v", err)
|
||||
}
|
||||
|
||||
if got, want := res.status, http.StatusRequestHeaderFieldsTooLarge; got != want {
|
||||
t.Errorf("status: %v; want %v", got, want)
|
||||
}
|
||||
@@ -515,7 +487,6 @@ func TestH1H1HeaderFields(t *testing.T) {
|
||||
t.Fatal("execution path should not be here")
|
||||
},
|
||||
}
|
||||
|
||||
st := newServerTester(t, opts)
|
||||
defer st.Close()
|
||||
|
||||
@@ -530,7 +501,6 @@ func TestH1H1HeaderFields(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatalf("Error st.http1() = %v", err)
|
||||
}
|
||||
|
||||
if got, want := res.status, http.StatusRequestHeaderFieldsTooLarge; got != want {
|
||||
t.Errorf("status: %v; want %v", got, want)
|
||||
}
|
||||
@@ -545,7 +515,6 @@ func TestH1H1Websocket(t *testing.T) {
|
||||
}
|
||||
}).ServeHTTP,
|
||||
}
|
||||
|
||||
st := newServerTester(t, opts)
|
||||
defer st.Close()
|
||||
|
||||
@@ -554,7 +523,6 @@ func TestH1H1Websocket(t *testing.T) {
|
||||
name: "TestH1H1Websocket",
|
||||
body: content,
|
||||
})
|
||||
|
||||
if got, want := res.body, content; !bytes.Equal(got, want) {
|
||||
t.Errorf("echo: %q; want %q", got, want)
|
||||
}
|
||||
@@ -571,7 +539,6 @@ func TestH1H1ReqPhaseSetHeader(t *testing.T) {
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
st := newServerTester(t, opts)
|
||||
defer st.Close()
|
||||
|
||||
@@ -596,7 +563,6 @@ func TestH1H1ReqPhaseReturn(t *testing.T) {
|
||||
t.Fatalf("request should not be forwarded")
|
||||
},
|
||||
}
|
||||
|
||||
st := newServerTester(t, opts)
|
||||
defer st.Close()
|
||||
|
||||
@@ -637,7 +603,6 @@ func TestH1H1ReqPhaseReturnCONNECTMethod(t *testing.T) {
|
||||
t.Fatalf("request should not be forwarded")
|
||||
},
|
||||
}
|
||||
|
||||
st := newServerTester(t, opts)
|
||||
defer st.Close()
|
||||
|
||||
@@ -705,7 +670,6 @@ func TestH1H1RespPhaseSetHeader(t *testing.T) {
|
||||
opts := options{
|
||||
args: []string{"--mruby-file=" + testDir + "/resp-set-header.rb"},
|
||||
}
|
||||
|
||||
st := newServerTester(t, opts)
|
||||
defer st.Close()
|
||||
|
||||
@@ -731,7 +695,6 @@ func TestH1H1RespPhaseReturn(t *testing.T) {
|
||||
opts := options{
|
||||
args: []string{"--mruby-file=" + testDir + "/resp-return.rb"},
|
||||
}
|
||||
|
||||
st := newServerTester(t, opts)
|
||||
defer st.Close()
|
||||
|
||||
@@ -769,7 +732,6 @@ func TestH1H1HTTPSRedirect(t *testing.T) {
|
||||
opts := options{
|
||||
args: []string{"--redirect-if-not-tls"},
|
||||
}
|
||||
|
||||
st := newServerTester(t, opts)
|
||||
defer st.Close()
|
||||
|
||||
@@ -783,7 +745,6 @@ func TestH1H1HTTPSRedirect(t *testing.T) {
|
||||
if got, want := res.status, http.StatusPermanentRedirect; got != want {
|
||||
t.Errorf("status = %v; want %v", got, want)
|
||||
}
|
||||
|
||||
if got, want := res.header.Get("location"), "https://127.0.0.1/"; got != want {
|
||||
t.Errorf("location: %v; want %v", got, want)
|
||||
}
|
||||
@@ -798,7 +759,6 @@ func TestH1H1HTTPSRedirectPort(t *testing.T) {
|
||||
"--redirect-https-port=8443",
|
||||
},
|
||||
}
|
||||
|
||||
st := newServerTester(t, opts)
|
||||
defer st.Close()
|
||||
|
||||
@@ -813,7 +773,6 @@ func TestH1H1HTTPSRedirectPort(t *testing.T) {
|
||||
if got, want := res.status, http.StatusPermanentRedirect; got != want {
|
||||
t.Errorf("status = %v; want %v", got, want)
|
||||
}
|
||||
|
||||
if got, want := res.header.Get("location"), "https://127.0.0.1:8443/foo?bar"; got != want {
|
||||
t.Errorf("location: %v; want %v", got, want)
|
||||
}
|
||||
@@ -832,7 +791,6 @@ func TestH1H1POSTRequests(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatalf("Error st.http1() = %v", err)
|
||||
}
|
||||
|
||||
if got, want := res.status, http.StatusOK; got != want {
|
||||
t.Errorf("res.status: %v; want %v", got, want)
|
||||
}
|
||||
@@ -844,7 +802,6 @@ func TestH1H1POSTRequests(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatalf("Error st.http1() = %v", err)
|
||||
}
|
||||
|
||||
if got, want := res.status, http.StatusOK; got != want {
|
||||
t.Errorf("res.status: %v; want %v", got, want)
|
||||
}
|
||||
@@ -860,7 +817,6 @@ func TestH1H1CONNECTMethodFailure(t *testing.T) {
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
st := newServerTester(t, opts)
|
||||
defer st.Close()
|
||||
|
||||
@@ -882,39 +838,12 @@ func TestH1H1CONNECTMethodFailure(t *testing.T) {
|
||||
if _, err := io.ReadAll(resp.Body); err != nil {
|
||||
t.Fatalf("Error io.ReadAll() = %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// TestH1H1CONNECTMethod tests that CONNECT request succeeds.
|
||||
func TestH1H1CONNECTMethod(t *testing.T) {
|
||||
opts := options{
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
hj, ok := w.(http.Hijacker)
|
||||
if !ok {
|
||||
http.Error(w, "Could not hijack the connection", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
_, bufrw, err := hj.Hijack()
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
if _, err := bufrw.WriteString("HTTP/1.1 200\r\n\r\n"); err != nil {
|
||||
t.Fatalf("Error bufrw.WriteString() = %v", err)
|
||||
}
|
||||
|
||||
bufrw.Flush()
|
||||
},
|
||||
}
|
||||
|
||||
st := newServerTester(t, opts)
|
||||
defer st.Close()
|
||||
|
||||
if _, err := io.WriteString(st.conn, "CONNECT 127.0.0.1:443 HTTP/1.1\r\nTest-Case: TestH1H1CONNECTMethod\r\nHost: 127.0.0.1:443\r\n\r\n"); err != nil {
|
||||
if _, err := io.WriteString(st.conn, "CONNECT 127.0.0.1:443 HTTP/1.1\r\nTest-Case: TestH1H1CONNECTMethodFailure\r\nHost: 127.0.0.1:443\r\nrequired-header: foo\r\n\r\n"); err != nil {
|
||||
t.Fatalf("Error io.WriteString() = %v", err)
|
||||
}
|
||||
|
||||
resp, err := http.ReadResponse(bufio.NewReader(st.conn), nil)
|
||||
resp, err = http.ReadResponse(bufio.NewReader(st.conn), nil)
|
||||
if err != nil {
|
||||
t.Fatalf("Error http.ReadResponse() = %v", err)
|
||||
}
|
||||
@@ -959,7 +888,6 @@ func TestH1H2NoHost(t *testing.T) {
|
||||
t.Errorf("server should not forward bad request")
|
||||
},
|
||||
}
|
||||
|
||||
st := newServerTester(t, opts)
|
||||
defer st.Close()
|
||||
|
||||
@@ -989,7 +917,6 @@ func TestH1H2HTTP10(t *testing.T) {
|
||||
w.Header().Add("request-host", r.Host)
|
||||
},
|
||||
}
|
||||
|
||||
st := newServerTester(t, opts)
|
||||
defer st.Close()
|
||||
|
||||
@@ -1007,7 +934,6 @@ func TestH1H2HTTP10(t *testing.T) {
|
||||
if got, want := resp.StatusCode, http.StatusOK; got != want {
|
||||
t.Errorf("status: %v; want %v", got, want)
|
||||
}
|
||||
|
||||
if got, want := resp.Header.Get("request-host"), st.backendHost; got != want {
|
||||
t.Errorf("request-host: %v; want %v", got, want)
|
||||
}
|
||||
@@ -1023,7 +949,6 @@ func TestH1H2HTTP10NoHostRewrite(t *testing.T) {
|
||||
w.Header().Add("request-host", r.Host)
|
||||
},
|
||||
}
|
||||
|
||||
st := newServerTester(t, opts)
|
||||
defer st.Close()
|
||||
|
||||
@@ -1041,7 +966,6 @@ func TestH1H2HTTP10NoHostRewrite(t *testing.T) {
|
||||
if got, want := resp.StatusCode, http.StatusOK; got != want {
|
||||
t.Errorf("status: %v; want %v", got, want)
|
||||
}
|
||||
|
||||
if got, want := resp.Header.Get("request-host"), st.backendHost; got != want {
|
||||
t.Errorf("request-host: %v; want %v", got, want)
|
||||
}
|
||||
@@ -1060,7 +984,6 @@ func TestH1H2CrumbleCookie(t *testing.T) {
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
st := newServerTester(t, opts)
|
||||
defer st.Close()
|
||||
|
||||
@@ -1073,7 +996,6 @@ func TestH1H2CrumbleCookie(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatalf("Error st.http1() = %v", err)
|
||||
}
|
||||
|
||||
if got, want := res.status, http.StatusOK; got != want {
|
||||
t.Errorf("status: %v; want %v", got, want)
|
||||
}
|
||||
@@ -1090,7 +1012,6 @@ func TestH1H2GenerateVia(t *testing.T) {
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
st := newServerTester(t, opts)
|
||||
defer st.Close()
|
||||
|
||||
@@ -1100,7 +1021,6 @@ func TestH1H2GenerateVia(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatalf("Error st.http1() = %v", err)
|
||||
}
|
||||
|
||||
if got, want := res.header.Get("Via"), "2 nghttpx"; got != want {
|
||||
t.Errorf("Via: %v; want %v", got, want)
|
||||
}
|
||||
@@ -1118,7 +1038,6 @@ func TestH1H2AppendVia(t *testing.T) {
|
||||
w.Header().Add("Via", "bar")
|
||||
},
|
||||
}
|
||||
|
||||
st := newServerTester(t, opts)
|
||||
defer st.Close()
|
||||
|
||||
@@ -1131,7 +1050,6 @@ func TestH1H2AppendVia(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatalf("Error st.http1() = %v", err)
|
||||
}
|
||||
|
||||
if got, want := res.header.Get("Via"), "bar, 2 nghttpx"; got != want {
|
||||
t.Errorf("Via: %v; want %v", got, want)
|
||||
}
|
||||
@@ -1149,7 +1067,6 @@ func TestH1H2NoVia(t *testing.T) {
|
||||
w.Header().Add("Via", "bar")
|
||||
},
|
||||
}
|
||||
|
||||
st := newServerTester(t, opts)
|
||||
defer st.Close()
|
||||
|
||||
@@ -1162,7 +1079,6 @@ func TestH1H2NoVia(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatalf("Error st.http1() = %v", err)
|
||||
}
|
||||
|
||||
if got, want := res.header.Get("Via"), "bar"; got != want {
|
||||
t.Errorf("Via: %v; want %v", got, want)
|
||||
}
|
||||
@@ -1180,7 +1096,6 @@ func TestH1H2ReqPhaseReturn(t *testing.T) {
|
||||
t.Fatalf("request should not be forwarded")
|
||||
},
|
||||
}
|
||||
|
||||
st := newServerTester(t, opts)
|
||||
defer st.Close()
|
||||
|
||||
@@ -1221,7 +1136,6 @@ func TestH1H2RespPhaseReturn(t *testing.T) {
|
||||
"--mruby-file=" + testDir + "/resp-return.rb",
|
||||
},
|
||||
}
|
||||
|
||||
st := newServerTester(t, opts)
|
||||
defer st.Close()
|
||||
|
||||
@@ -1264,7 +1178,6 @@ func TestH1H2TE(t *testing.T) {
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
st := newServerTester(t, opts)
|
||||
defer st.Close()
|
||||
|
||||
@@ -1277,7 +1190,6 @@ func TestH1H2TE(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatalf("Error st.http1() = %v", err)
|
||||
}
|
||||
|
||||
if got, want := res.status, http.StatusOK; got != want {
|
||||
t.Errorf("status: %v; want %v", got, want)
|
||||
}
|
||||
@@ -1293,7 +1205,6 @@ func TestH1APIBackendconfig(t *testing.T) {
|
||||
},
|
||||
connectPort: 3010,
|
||||
}
|
||||
|
||||
st := newServerTester(t, opts)
|
||||
defer st.Close()
|
||||
|
||||
@@ -1309,21 +1220,18 @@ backend=127.0.0.1,3011
|
||||
if err != nil {
|
||||
t.Fatalf("Error st.http1() = %v", err)
|
||||
}
|
||||
|
||||
if got, want := res.status, http.StatusOK; got != want {
|
||||
t.Errorf("res.status: %v; want %v", got, want)
|
||||
}
|
||||
|
||||
var apiResp APIResponse
|
||||
|
||||
if err := json.Unmarshal(res.body, &apiResp); err != nil {
|
||||
err = json.Unmarshal(res.body, &apiResp)
|
||||
if err != nil {
|
||||
t.Fatalf("Error unmarshaling API response: %v", err)
|
||||
}
|
||||
|
||||
if got, want := apiResp.Status, "Success"; got != want {
|
||||
t.Errorf("apiResp.Status: %v; want %v", got, want)
|
||||
}
|
||||
|
||||
if got, want := apiResp.Code, 200; got != want {
|
||||
t.Errorf("apiResp.Status: %v; want %v", got, want)
|
||||
}
|
||||
@@ -1339,7 +1247,6 @@ func TestH1APIBackendconfigQuery(t *testing.T) {
|
||||
},
|
||||
connectPort: 3010,
|
||||
}
|
||||
|
||||
st := newServerTester(t, opts)
|
||||
defer st.Close()
|
||||
|
||||
@@ -1355,21 +1262,18 @@ backend=127.0.0.1,3011
|
||||
if err != nil {
|
||||
t.Fatalf("Error st.http1() = %v", err)
|
||||
}
|
||||
|
||||
if got, want := res.status, http.StatusOK; got != want {
|
||||
t.Errorf("res.status: %v; want %v", got, want)
|
||||
}
|
||||
|
||||
var apiResp APIResponse
|
||||
|
||||
if err := json.Unmarshal(res.body, &apiResp); err != nil {
|
||||
err = json.Unmarshal(res.body, &apiResp)
|
||||
if err != nil {
|
||||
t.Fatalf("Error unmarshaling API response: %v", err)
|
||||
}
|
||||
|
||||
if got, want := apiResp.Status, "Success"; got != want {
|
||||
t.Errorf("apiResp.Status: %v; want %v", got, want)
|
||||
}
|
||||
|
||||
if got, want := apiResp.Code, 200; got != want {
|
||||
t.Errorf("apiResp.Status: %v; want %v", got, want)
|
||||
}
|
||||
@@ -1385,7 +1289,6 @@ func TestH1APIBackendconfigBadMethod(t *testing.T) {
|
||||
},
|
||||
connectPort: 3010,
|
||||
}
|
||||
|
||||
st := newServerTester(t, opts)
|
||||
defer st.Close()
|
||||
|
||||
@@ -1401,21 +1304,18 @@ backend=127.0.0.1,3011
|
||||
if err != nil {
|
||||
t.Fatalf("Error st.http1() = %v", err)
|
||||
}
|
||||
|
||||
if got, want := res.status, http.StatusMethodNotAllowed; got != want {
|
||||
t.Errorf("res.status: %v; want %v", got, want)
|
||||
}
|
||||
|
||||
var apiResp APIResponse
|
||||
|
||||
if err := json.Unmarshal(res.body, &apiResp); err != nil {
|
||||
err = json.Unmarshal(res.body, &apiResp)
|
||||
if err != nil {
|
||||
t.Fatalf("Error unmarshaling API response: %v", err)
|
||||
}
|
||||
|
||||
if got, want := apiResp.Status, "Failure"; got != want {
|
||||
t.Errorf("apiResp.Status: %v; want %v", got, want)
|
||||
}
|
||||
|
||||
if got, want := apiResp.Code, 405; got != want {
|
||||
t.Errorf("apiResp.Status: %v; want %v", got, want)
|
||||
}
|
||||
@@ -1430,7 +1330,6 @@ func TestH1APIConfigrevision(t *testing.T) {
|
||||
},
|
||||
connectPort: 3010,
|
||||
}
|
||||
|
||||
st := newServerTester(t, opts)
|
||||
defer st.Close()
|
||||
|
||||
@@ -1442,28 +1341,23 @@ func TestH1APIConfigrevision(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatalf("Error st.http1() = %v", err)
|
||||
}
|
||||
|
||||
if got, want := res.status, http.StatusOK; got != want {
|
||||
t.Errorf("res.status: %v; want = %v", got, want)
|
||||
}
|
||||
|
||||
var apiResp APIResponse
|
||||
|
||||
d := json.NewDecoder(bytes.NewBuffer(res.body))
|
||||
d.UseNumber()
|
||||
|
||||
if err := d.Decode(&apiResp); err != nil {
|
||||
err = d.Decode(&apiResp)
|
||||
if err != nil {
|
||||
t.Fatalf("Error unmarshalling API response: %v", err)
|
||||
}
|
||||
|
||||
if got, want := apiResp.Status, "Success"; got != want {
|
||||
t.Errorf("apiResp.Status: %v; want %v", got, want)
|
||||
}
|
||||
|
||||
if got, want := apiResp.Code, 200; got != want {
|
||||
t.Errorf("apiResp.Status: %v; want %v", got, want)
|
||||
}
|
||||
|
||||
if got, want := apiResp.Data["configRevision"], json.Number("0"); got != want {
|
||||
t.Errorf(`apiResp.Data["configRevision"]: %v %t; want %v`, got, got, want)
|
||||
}
|
||||
@@ -1479,7 +1373,6 @@ func TestH1APINotFound(t *testing.T) {
|
||||
},
|
||||
connectPort: 3010,
|
||||
}
|
||||
|
||||
st := newServerTester(t, opts)
|
||||
defer st.Close()
|
||||
|
||||
@@ -1495,21 +1388,18 @@ backend=127.0.0.1,3011
|
||||
if err != nil {
|
||||
t.Fatalf("Error st.http1() = %v", err)
|
||||
}
|
||||
|
||||
if got, want := res.status, http.StatusNotFound; got != want {
|
||||
t.Errorf("res.status: %v; want %v", got, want)
|
||||
}
|
||||
|
||||
var apiResp APIResponse
|
||||
|
||||
if err := json.Unmarshal(res.body, &apiResp); err != nil {
|
||||
err = json.Unmarshal(res.body, &apiResp)
|
||||
if err != nil {
|
||||
t.Fatalf("Error unmarshaling API response: %v", err)
|
||||
}
|
||||
|
||||
if got, want := apiResp.Status, "Failure"; got != want {
|
||||
t.Errorf("apiResp.Status: %v; want %v", got, want)
|
||||
}
|
||||
|
||||
if got, want := apiResp.Code, 404; got != want {
|
||||
t.Errorf("apiResp.Status: %v; want %v", got, want)
|
||||
}
|
||||
@@ -1524,7 +1414,6 @@ func TestH1Healthmon(t *testing.T) {
|
||||
},
|
||||
connectPort: 3011,
|
||||
}
|
||||
|
||||
st := newServerTester(t, opts)
|
||||
defer st.Close()
|
||||
|
||||
@@ -1535,7 +1424,6 @@ func TestH1Healthmon(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatalf("Error st.http1() = %v", err)
|
||||
}
|
||||
|
||||
if got, want := res.status, http.StatusOK; got != want {
|
||||
t.Errorf("res.status: %v; want %v", got, want)
|
||||
}
|
||||
@@ -1550,7 +1438,6 @@ func TestH1ResponseBeforeRequestEnd(t *testing.T) {
|
||||
t.Fatal("request should not be forwarded")
|
||||
},
|
||||
}
|
||||
|
||||
st := newServerTester(t, opts)
|
||||
defer st.Close()
|
||||
|
||||
@@ -1593,7 +1480,6 @@ func TestH1H1ChunkedEndsPrematurely(t *testing.T) {
|
||||
bufrw.Flush()
|
||||
},
|
||||
}
|
||||
|
||||
st := newServerTester(t, opts)
|
||||
defer st.Close()
|
||||
|
||||
@@ -1613,7 +1499,6 @@ func TestH1H1RequestMalformedTransferEncoding(t *testing.T) {
|
||||
t.Errorf("server should not forward bad request")
|
||||
},
|
||||
}
|
||||
|
||||
st := newServerTester(t, opts)
|
||||
defer st.Close()
|
||||
|
||||
@@ -1656,7 +1541,6 @@ func TestH1H1ResponseMalformedTransferEncoding(t *testing.T) {
|
||||
bufrw.Flush()
|
||||
},
|
||||
}
|
||||
|
||||
st := newServerTester(t, opts)
|
||||
defer st.Close()
|
||||
|
||||
@@ -1666,7 +1550,6 @@ func TestH1H1ResponseMalformedTransferEncoding(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatalf("Error st.http1() = %v", err)
|
||||
}
|
||||
|
||||
if got, want := res.status, http.StatusBadGateway; got != want {
|
||||
t.Errorf("res.status: %v; want %v", got, want)
|
||||
}
|
||||
@@ -1694,7 +1577,6 @@ func TestH1H1ResponseUnknownTransferEncoding(t *testing.T) {
|
||||
bufrw.Flush()
|
||||
},
|
||||
}
|
||||
|
||||
st := newServerTester(t, opts)
|
||||
defer st.Close()
|
||||
|
||||
@@ -1729,7 +1611,6 @@ func TestH1H1RequestHTTP10TransferEncoding(t *testing.T) {
|
||||
t.Errorf("server should not forward bad request")
|
||||
},
|
||||
}
|
||||
|
||||
st := newServerTester(t, opts)
|
||||
defer st.Close()
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -5,7 +5,6 @@ package nghttp2
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/rand"
|
||||
"errors"
|
||||
"io"
|
||||
"net/http"
|
||||
"regexp"
|
||||
@@ -36,7 +35,6 @@ func TestH3H1PlainGET(t *testing.T) {
|
||||
// TestH3H1RequestBody tests HTTP/3 request with body works.
|
||||
func TestH3H1RequestBody(t *testing.T) {
|
||||
body := make([]byte, 3333)
|
||||
|
||||
_, err := rand.Read(body)
|
||||
if err != nil {
|
||||
t.Fatalf("Unable to create request body: %v", err)
|
||||
@@ -59,7 +57,7 @@ func TestH3H1RequestBody(t *testing.T) {
|
||||
buflen += n
|
||||
|
||||
if err != nil {
|
||||
if errors.Is(err, io.EOF) {
|
||||
if err == io.EOF {
|
||||
break
|
||||
}
|
||||
|
||||
@@ -75,7 +73,6 @@ func TestH3H1RequestBody(t *testing.T) {
|
||||
},
|
||||
quic: true,
|
||||
}
|
||||
|
||||
st := newServerTester(t, opts)
|
||||
defer st.Close()
|
||||
|
||||
@@ -86,7 +83,6 @@ func TestH3H1RequestBody(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatalf("Error st.http3() = %v", err)
|
||||
}
|
||||
|
||||
if got, want := res.status, http.StatusOK; got != want {
|
||||
t.Errorf("res.status: %v; want %v", got, want)
|
||||
}
|
||||
@@ -103,7 +99,6 @@ func TestH3H1GenerateVia(t *testing.T) {
|
||||
},
|
||||
quic: true,
|
||||
}
|
||||
|
||||
st := newServerTester(t, opts)
|
||||
defer st.Close()
|
||||
|
||||
@@ -113,7 +108,6 @@ func TestH3H1GenerateVia(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatalf("Error st.http3() = %v", err)
|
||||
}
|
||||
|
||||
if got, want := res.header.Get("Via"), "1.1 nghttpx"; got != want {
|
||||
t.Errorf("Via: %v; want %v", got, want)
|
||||
}
|
||||
@@ -131,7 +125,6 @@ func TestH3H1AppendVia(t *testing.T) {
|
||||
},
|
||||
quic: true,
|
||||
}
|
||||
|
||||
st := newServerTester(t, opts)
|
||||
defer st.Close()
|
||||
|
||||
@@ -144,7 +137,6 @@ func TestH3H1AppendVia(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatalf("Error st.http3() = %v", err)
|
||||
}
|
||||
|
||||
if got, want := res.header.Get("Via"), "bar, 1.1 nghttpx"; got != want {
|
||||
t.Errorf("Via: %v; want %v", got, want)
|
||||
}
|
||||
@@ -163,7 +155,6 @@ func TestH3H1NoVia(t *testing.T) {
|
||||
},
|
||||
quic: true,
|
||||
}
|
||||
|
||||
st := newServerTester(t, opts)
|
||||
defer st.Close()
|
||||
|
||||
@@ -176,7 +167,6 @@ func TestH3H1NoVia(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatalf("Error st.http3() = %v", err)
|
||||
}
|
||||
|
||||
if got, want := res.header.Get("Via"), "bar"; got != want {
|
||||
t.Errorf("Via: %v; want %v", got, want)
|
||||
}
|
||||
@@ -196,7 +186,6 @@ func TestH3H1BadResponseCL(t *testing.T) {
|
||||
},
|
||||
quic: true,
|
||||
}
|
||||
|
||||
st := newServerTester(t, opts)
|
||||
defer st.Close()
|
||||
|
||||
@@ -215,7 +204,6 @@ func TestH3H1HTTPSRedirect(t *testing.T) {
|
||||
args: []string{"--redirect-if-not-tls"},
|
||||
quic: true,
|
||||
}
|
||||
|
||||
st := newServerTester(t, opts)
|
||||
defer st.Close()
|
||||
|
||||
@@ -238,7 +226,6 @@ func TestH3H1AffinityCookieTLS(t *testing.T) {
|
||||
args: []string{"--affinity-cookie"},
|
||||
quic: true,
|
||||
}
|
||||
|
||||
st := newServerTester(t, opts)
|
||||
defer st.Close()
|
||||
|
||||
@@ -256,7 +243,6 @@ func TestH3H1AffinityCookieTLS(t *testing.T) {
|
||||
|
||||
const pattern = `affinity=[0-9a-f]{8}; Path=/foo/bar; Secure`
|
||||
validCookie := regexp.MustCompile(pattern)
|
||||
|
||||
if got := res.header.Get("Set-Cookie"); !validCookie.MatchString(got) {
|
||||
t.Errorf("Set-Cookie: %v; want pattern %v", got, pattern)
|
||||
}
|
||||
@@ -275,7 +261,6 @@ func TestH3H2ReqPhaseReturn(t *testing.T) {
|
||||
},
|
||||
quic: true,
|
||||
}
|
||||
|
||||
st := newServerTester(t, opts)
|
||||
defer st.Close()
|
||||
|
||||
@@ -317,7 +302,6 @@ func TestH3H2RespPhaseReturn(t *testing.T) {
|
||||
},
|
||||
quic: true,
|
||||
}
|
||||
|
||||
st := newServerTester(t, opts)
|
||||
defer st.Close()
|
||||
|
||||
@@ -359,7 +343,6 @@ func TestH3ResponseBeforeRequestEnd(t *testing.T) {
|
||||
},
|
||||
quic: true,
|
||||
}
|
||||
|
||||
st := newServerTester(t, opts)
|
||||
defer st.Close()
|
||||
|
||||
@@ -370,7 +353,6 @@ func TestH3ResponseBeforeRequestEnd(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatalf("Error st.http3() = %v", err)
|
||||
}
|
||||
|
||||
if got, want := res.status, http.StatusNotFound; got != want {
|
||||
t.Errorf("res.status: %v; want %v", got, want)
|
||||
}
|
||||
@@ -399,7 +381,6 @@ func TestH3H1ChunkedEndsPrematurely(t *testing.T) {
|
||||
},
|
||||
quic: true,
|
||||
}
|
||||
|
||||
st := newServerTester(t, opts)
|
||||
defer st.Close()
|
||||
|
||||
|
||||
@@ -3,7 +3,6 @@ package nghttp2
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"cmp"
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"encoding/binary"
|
||||
@@ -16,7 +15,7 @@ import (
|
||||
"net/url"
|
||||
"os"
|
||||
"os/exec"
|
||||
"slices"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"syscall"
|
||||
@@ -95,17 +94,14 @@ func newServerTester(t *testing.T, opts options) *serverTester {
|
||||
if opts.handler == nil {
|
||||
opts.handler = noopHandler
|
||||
}
|
||||
|
||||
if opts.connectPort == 0 {
|
||||
opts.connectPort = serverPort
|
||||
}
|
||||
|
||||
ts := httptest.NewUnstartedServer(opts.handler)
|
||||
|
||||
var (
|
||||
args []string
|
||||
backendTLS, dns, externalDNS, acceptProxyProtocol, redirectIfNotTLS, affinityCookie, alpnH1 bool
|
||||
)
|
||||
var args []string
|
||||
var backendTLS, dns, externalDNS, acceptProxyProtocol, redirectIfNotTLS, affinityCookie, alpnH1 bool
|
||||
|
||||
for _, k := range opts.args {
|
||||
switch k {
|
||||
@@ -128,7 +124,6 @@ func newServerTester(t *testing.T, opts options) *serverTester {
|
||||
args = append(args, k)
|
||||
}
|
||||
}
|
||||
|
||||
if backendTLS {
|
||||
nghttp2.ConfigureServer(ts.Config, &nghttp2.Server{})
|
||||
// According to httptest/server.go, we have to set
|
||||
@@ -137,17 +132,13 @@ func newServerTester(t *testing.T, opts options) *serverTester {
|
||||
ts.TLS = new(tls.Config)
|
||||
ts.TLS.NextProtos = append(ts.TLS.NextProtos, "h2")
|
||||
ts.StartTLS()
|
||||
|
||||
args = append(args, "-k")
|
||||
} else {
|
||||
ts.Start()
|
||||
}
|
||||
|
||||
scheme := "http"
|
||||
|
||||
if opts.tls {
|
||||
scheme = "https"
|
||||
|
||||
args = append(args, testDir+"/server.key", testDir+"/server.crt")
|
||||
}
|
||||
|
||||
@@ -159,25 +150,20 @@ func newServerTester(t *testing.T, opts options) *serverTester {
|
||||
// URL.Host looks like "127.0.0.1:8080", but we want
|
||||
// "127.0.0.1,8080"
|
||||
b := "-b"
|
||||
|
||||
if !externalDNS {
|
||||
b += fmt.Sprintf("%v;", strings.ReplaceAll(backendURL.Host, ":", ","))
|
||||
b += fmt.Sprintf("%v;", strings.Replace(backendURL.Host, ":", ",", -1))
|
||||
} else {
|
||||
sep := strings.LastIndex(backendURL.Host, ":")
|
||||
if sep == -1 {
|
||||
t.Fatalf("backendURL.Host %v does not contain separator ':'", backendURL.Host)
|
||||
}
|
||||
|
||||
// We use awesome service nip.io.
|
||||
b += fmt.Sprintf("%v.nip.io,%v;", backendURL.Host[:sep], backendURL.Host[sep+1:])
|
||||
// Make external DNS tests less flaky.
|
||||
args = append(args, "--backend-address-family=IPv4")
|
||||
}
|
||||
|
||||
if backendTLS {
|
||||
b += ";proto=h2;tls"
|
||||
}
|
||||
|
||||
if dns {
|
||||
b += ";dns"
|
||||
}
|
||||
@@ -191,13 +177,11 @@ func newServerTester(t *testing.T, opts options) *serverTester {
|
||||
}
|
||||
|
||||
noTLS := ";no-tls"
|
||||
|
||||
if opts.tls {
|
||||
noTLS = ""
|
||||
}
|
||||
|
||||
var proxyProto string
|
||||
|
||||
if acceptProxyProtocol {
|
||||
proxyProto = ";proxyproto"
|
||||
}
|
||||
@@ -208,19 +192,7 @@ func newServerTester(t *testing.T, opts options) *serverTester {
|
||||
if opts.quic {
|
||||
args = append(args,
|
||||
fmt.Sprintf("-f127.0.0.1,%v;quic", serverPort),
|
||||
"--no-quic-bpf",
|
||||
// quic-go client just closes connection after
|
||||
// receiving the first GOAWAY without any
|
||||
// indication like sending CONNECTION_CLOSE if
|
||||
// there is no active stream. If that
|
||||
// happens, server keeps resending 2nd GOAWAY
|
||||
// until idle timeout passes. If that happens
|
||||
// during Close(), the process will be killed
|
||||
// because the default idle timeout is longer
|
||||
// than the close timeout. Shorten the idle
|
||||
// timeout to prevent it from happening.
|
||||
"--frontend-quic-idle-timeout=5",
|
||||
)
|
||||
"--no-quic-bpf")
|
||||
}
|
||||
|
||||
authority := fmt.Sprintf("127.0.0.1:%v", opts.connectPort)
|
||||
@@ -246,7 +218,6 @@ func newServerTester(t *testing.T, opts options) *serverTester {
|
||||
}
|
||||
|
||||
retry := 0
|
||||
|
||||
for {
|
||||
time.Sleep(50 * time.Millisecond)
|
||||
|
||||
@@ -260,41 +231,32 @@ func newServerTester(t *testing.T, opts options) *serverTester {
|
||||
}
|
||||
|
||||
var tlsConfig *tls.Config
|
||||
|
||||
if opts.tlsConfig == nil {
|
||||
tlsConfig = new(tls.Config)
|
||||
} else {
|
||||
tlsConfig = opts.tlsConfig.Clone()
|
||||
}
|
||||
|
||||
tlsConfig.InsecureSkipVerify = true
|
||||
|
||||
if alpnH1 {
|
||||
tlsConfig.NextProtos = []string{"http/1.1"}
|
||||
} else {
|
||||
tlsConfig.NextProtos = []string{"h2"}
|
||||
}
|
||||
|
||||
tlsConn := tls.Client(conn, tlsConfig)
|
||||
|
||||
err = tlsConn.Handshake()
|
||||
if err == nil {
|
||||
conn = tlsConn
|
||||
}
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
retry++
|
||||
if retry >= 100 {
|
||||
st.Close()
|
||||
st.t.Fatalf("Error server is not responding too long; server command-line arguments may be invalid")
|
||||
}
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
st.conn = conn
|
||||
|
||||
break
|
||||
}
|
||||
|
||||
@@ -311,15 +273,12 @@ func (st *serverTester) Close() {
|
||||
if st.conn != nil {
|
||||
st.conn.Close()
|
||||
}
|
||||
|
||||
if st.cmd != nil {
|
||||
done := make(chan struct{})
|
||||
|
||||
go func() {
|
||||
if err := st.cmd.Wait(); err != nil {
|
||||
st.t.Errorf("Error st.cmd.Wait() = %v", err)
|
||||
}
|
||||
|
||||
close(done)
|
||||
}()
|
||||
|
||||
@@ -333,11 +292,9 @@ func (st *serverTester) Close() {
|
||||
if err := st.cmd.Process.Kill(); err != nil {
|
||||
st.t.Errorf("Error st.cmd.Process.Kill() = %v", err)
|
||||
}
|
||||
|
||||
<-done
|
||||
}
|
||||
}
|
||||
|
||||
if st.ts != nil {
|
||||
st.ts.Close()
|
||||
}
|
||||
@@ -350,7 +307,6 @@ func (st *serverTester) readFrame() (http2.Frame, error) {
|
||||
st.errCh <- err
|
||||
return
|
||||
}
|
||||
|
||||
st.frCh <- f
|
||||
}()
|
||||
|
||||
@@ -391,12 +347,10 @@ func (cbr *chunkedBodyReader) Read(p []byte) (n int, err error) {
|
||||
// after request was sent and before body returns EOF.
|
||||
if !cbr.trailerWritten {
|
||||
cbr.trailerWritten = true
|
||||
|
||||
for _, h := range cbr.trailer {
|
||||
cbr.req.Trailer.Set(h.Name, h.Value)
|
||||
}
|
||||
}
|
||||
|
||||
return cbr.body.Read(p)
|
||||
}
|
||||
|
||||
@@ -409,7 +363,6 @@ func (st *serverTester) websocket(rp requestParam) *serverResponse {
|
||||
}
|
||||
|
||||
config.Header.Add("Test-Case", rp.name)
|
||||
|
||||
for _, h := range rp.header {
|
||||
config.Header.Add(h.Name, h.Value)
|
||||
}
|
||||
@@ -424,9 +377,7 @@ func (st *serverTester) websocket(rp requestParam) *serverResponse {
|
||||
}
|
||||
|
||||
msg := make([]byte, 1024)
|
||||
|
||||
var n int
|
||||
|
||||
if n, err = ws.Read(msg); err != nil {
|
||||
st.t.Fatalf("ws.Read() returned error: %v", err)
|
||||
}
|
||||
@@ -440,25 +391,19 @@ func (st *serverTester) websocket(rp requestParam) *serverResponse {
|
||||
|
||||
func (st *serverTester) http1(rp requestParam) (*serverResponse, error) {
|
||||
method := "GET"
|
||||
|
||||
if rp.method != "" {
|
||||
method = rp.method
|
||||
}
|
||||
|
||||
var (
|
||||
body io.Reader
|
||||
cbr *chunkedBodyReader
|
||||
)
|
||||
|
||||
var body io.Reader
|
||||
var cbr *chunkedBodyReader
|
||||
if rp.body != nil {
|
||||
body = bytes.NewBuffer(rp.body)
|
||||
|
||||
if len(rp.trailer) != 0 {
|
||||
cbr = &chunkedBodyReader{
|
||||
trailer: rp.trailer,
|
||||
body: body,
|
||||
}
|
||||
|
||||
body = cbr
|
||||
}
|
||||
}
|
||||
@@ -470,7 +415,6 @@ func (st *serverTester) http1(rp requestParam) (*serverResponse, error) {
|
||||
if err != nil {
|
||||
st.t.Fatalf("Error parsing URL from st.url %v: %v", st.url, err)
|
||||
}
|
||||
|
||||
u.Path = ""
|
||||
u.RawQuery = ""
|
||||
reqURL = u.String() + rp.path
|
||||
@@ -483,38 +427,30 @@ func (st *serverTester) http1(rp requestParam) (*serverResponse, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, h := range rp.header {
|
||||
req.Header.Add(h.Name, h.Value)
|
||||
}
|
||||
|
||||
req.Header.Add("Test-Case", rp.name)
|
||||
|
||||
if cbr != nil {
|
||||
cbr.req = req
|
||||
// this makes request use chunked encoding
|
||||
req.ContentLength = -1
|
||||
req.Trailer = make(http.Header)
|
||||
|
||||
for _, h := range cbr.trailer {
|
||||
req.Trailer.Set(h.Name, "")
|
||||
}
|
||||
}
|
||||
|
||||
if err := req.Write(st.conn); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resp, err := http.ReadResponse(bufio.NewReader(st.conn), req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
respBody, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resp.Body.Close()
|
||||
|
||||
res := &serverResponse{
|
||||
@@ -532,7 +468,6 @@ func (st *serverTester) http2(rp requestParam) (*serverResponse, error) {
|
||||
st.header = make(http.Header)
|
||||
|
||||
var id uint32
|
||||
|
||||
if rp.streamID != 0 {
|
||||
id = rp.streamID
|
||||
if id >= st.nextStreamID && id%2 == 1 {
|
||||
@@ -546,7 +481,6 @@ func (st *serverTester) http2(rp requestParam) (*serverResponse, error) {
|
||||
if !st.h2PrefaceSent {
|
||||
st.h2PrefaceSent = true
|
||||
fmt.Fprint(st.conn, "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n")
|
||||
|
||||
if err := st.fr.WriteSettings(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -564,32 +498,26 @@ func (st *serverTester) http2(rp requestParam) (*serverResponse, error) {
|
||||
if rp.method != "" {
|
||||
method = rp.method
|
||||
}
|
||||
|
||||
_ = st.enc.WriteField(pair(":method", method))
|
||||
|
||||
scheme := "http"
|
||||
|
||||
if rp.scheme != "" {
|
||||
scheme = rp.scheme
|
||||
}
|
||||
|
||||
_ = st.enc.WriteField(pair(":scheme", scheme))
|
||||
|
||||
authority := st.authority
|
||||
|
||||
if rp.authority != "" {
|
||||
authority = rp.authority
|
||||
}
|
||||
|
||||
_ = st.enc.WriteField(pair(":authority", authority))
|
||||
|
||||
path := "/"
|
||||
|
||||
if rp.path != "" {
|
||||
path = rp.path
|
||||
}
|
||||
|
||||
_ = st.enc.WriteField(pair(":path", path))
|
||||
|
||||
_ = st.enc.WriteField(pair("test-case", rp.name))
|
||||
|
||||
for _, h := range rp.header {
|
||||
@@ -615,11 +543,9 @@ func (st *serverTester) http2(rp requestParam) (*serverResponse, error) {
|
||||
|
||||
if len(rp.trailer) != 0 {
|
||||
st.headerBlkBuf.Reset()
|
||||
|
||||
for _, h := range rp.trailer {
|
||||
_ = st.enc.WriteField(h)
|
||||
}
|
||||
|
||||
err := st.fr.WriteHeaders(http2.HeadersFrameParam{
|
||||
StreamID: id,
|
||||
EndStream: true,
|
||||
@@ -637,65 +563,56 @@ loop:
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
||||
switch f := fr.(type) {
|
||||
case *http2.HeadersFrame:
|
||||
_, err := st.dec.Write(f.HeaderBlockFragment())
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
||||
sr, ok := streams[f.StreamID]
|
||||
sr, ok := streams[f.FrameHeader.StreamID]
|
||||
if !ok {
|
||||
st.header = make(http.Header)
|
||||
break
|
||||
}
|
||||
|
||||
sr.header = cloneHeader(st.header)
|
||||
|
||||
var status int
|
||||
|
||||
status, err = strconv.Atoi(sr.header.Get(":status"))
|
||||
if err != nil {
|
||||
return res, fmt.Errorf("could not parse :status: %w", err)
|
||||
return res, fmt.Errorf("Error parsing status code: %w", err)
|
||||
}
|
||||
|
||||
sr.status = status
|
||||
|
||||
if f.StreamEnded() && streamEnded(res, streams, sr) {
|
||||
break loop
|
||||
if f.StreamEnded() {
|
||||
if streamEnded(res, streams, sr) {
|
||||
break loop
|
||||
}
|
||||
}
|
||||
case *http2.PushPromiseFrame:
|
||||
_, err := st.dec.Write(f.HeaderBlockFragment())
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
||||
sr := &serverResponse{
|
||||
streamID: f.PromiseID,
|
||||
reqHeader: cloneHeader(st.header),
|
||||
}
|
||||
|
||||
streams[sr.streamID] = sr
|
||||
case *http2.DataFrame:
|
||||
sr, ok := streams[f.StreamID]
|
||||
sr, ok := streams[f.FrameHeader.StreamID]
|
||||
if !ok {
|
||||
break
|
||||
}
|
||||
|
||||
sr.body = append(sr.body, f.Data()...)
|
||||
|
||||
if f.StreamEnded() && streamEnded(res, streams, sr) {
|
||||
break loop
|
||||
if f.StreamEnded() {
|
||||
if streamEnded(res, streams, sr) {
|
||||
break loop
|
||||
}
|
||||
}
|
||||
case *http2.RSTStreamFrame:
|
||||
sr, ok := streams[f.StreamID]
|
||||
sr, ok := streams[f.FrameHeader.StreamID]
|
||||
if !ok {
|
||||
break
|
||||
}
|
||||
|
||||
sr.errCode = f.ErrCode
|
||||
|
||||
if streamEnded(res, streams, sr) {
|
||||
break loop
|
||||
}
|
||||
@@ -703,36 +620,27 @@ loop:
|
||||
if f.ErrCode == http2.ErrCodeNo {
|
||||
break
|
||||
}
|
||||
|
||||
res.errCode = f.ErrCode
|
||||
res.connErr = true
|
||||
|
||||
break loop
|
||||
case *http2.SettingsFrame:
|
||||
if f.IsAck() {
|
||||
break
|
||||
}
|
||||
|
||||
if err := st.fr.WriteSettingsAck(); err != nil {
|
||||
return res, err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
slices.SortFunc(res.pushResponse, func(a, b *serverResponse) int {
|
||||
return cmp.Compare(a.streamID, b.streamID)
|
||||
})
|
||||
|
||||
sort.Sort(ByStreamID(res.pushResponse))
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func streamEnded(mainSr *serverResponse, streams map[uint32]*serverResponse, sr *serverResponse) bool {
|
||||
delete(streams, sr.streamID)
|
||||
|
||||
if mainSr.streamID != sr.streamID {
|
||||
mainSr.pushResponse = append(mainSr.pushResponse, sr)
|
||||
}
|
||||
|
||||
return len(streams) == 0
|
||||
}
|
||||
|
||||
@@ -748,15 +656,27 @@ type serverResponse struct {
|
||||
pushResponse []*serverResponse // pushed response
|
||||
}
|
||||
|
||||
type ByStreamID []*serverResponse
|
||||
|
||||
func (b ByStreamID) Len() int {
|
||||
return len(b)
|
||||
}
|
||||
|
||||
func (b ByStreamID) Swap(i, j int) {
|
||||
b[i], b[j] = b[j], b[i]
|
||||
}
|
||||
|
||||
func (b ByStreamID) Less(i, j int) bool {
|
||||
return b[i].streamID < b[j].streamID
|
||||
}
|
||||
|
||||
func cloneHeader(h http.Header) http.Header {
|
||||
h2 := make(http.Header, len(h))
|
||||
|
||||
for k, vv := range h {
|
||||
vv2 := make([]string, len(vv))
|
||||
copy(vv2, vv)
|
||||
h2[k] = vv2
|
||||
}
|
||||
|
||||
return h2
|
||||
}
|
||||
|
||||
@@ -807,7 +727,6 @@ func writeProxyProtocolV2(w io.Writer, hdr proxyProtocolV2) error {
|
||||
if _, err := w.Write([]byte{0x0D, 0x0A, 0x0D, 0x0A, 0x00, 0x0D, 0x0A, 0x51, 0x55, 0x49, 0x54, 0x0A}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err := w.Write([]byte{byte(0x20 | hdr.command)}); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -815,59 +734,44 @@ func writeProxyProtocolV2(w io.Writer, hdr proxyProtocolV2) error {
|
||||
switch srcAddr := hdr.sourceAddress.(type) {
|
||||
case *net.TCPAddr:
|
||||
dstAddr := hdr.destinationAddress.(*net.TCPAddr)
|
||||
|
||||
if len(srcAddr.IP) != len(dstAddr.IP) {
|
||||
panic("len(srcAddr.IP) != len(dstAddr.IP)")
|
||||
}
|
||||
|
||||
var fam byte
|
||||
|
||||
if len(srcAddr.IP) == 4 {
|
||||
fam = byte(proxyProtocolV2FamilyInet << 4)
|
||||
} else {
|
||||
fam = byte(proxyProtocolV2FamilyInet6 << 4)
|
||||
}
|
||||
|
||||
fam |= byte(proxyProtocolV2ProtocolStream)
|
||||
|
||||
if _, err := w.Write([]byte{fam}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
length := uint16(len(srcAddr.IP)*2 + 4 + len(hdr.additionalData))
|
||||
|
||||
if err := binary.Write(w, binary.BigEndian, length); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err := w.Write(srcAddr.IP); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err := w.Write(dstAddr.IP); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := binary.Write(w, binary.BigEndian, uint16(srcAddr.Port)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := binary.Write(w, binary.BigEndian, uint16(dstAddr.Port)); err != nil {
|
||||
return err
|
||||
}
|
||||
case *net.UnixAddr:
|
||||
dstAddr := hdr.destinationAddress.(*net.UnixAddr)
|
||||
|
||||
if len(srcAddr.Name) > 108 {
|
||||
panic("too long Unix source address")
|
||||
}
|
||||
|
||||
if len(dstAddr.Name) > 108 {
|
||||
panic("too long Unix destination address")
|
||||
}
|
||||
|
||||
fam := byte(proxyProtocolV2FamilyUnix << 4)
|
||||
|
||||
switch srcAddr.Net {
|
||||
case "unix":
|
||||
fam |= byte(proxyProtocolV2ProtocolStream)
|
||||
@@ -876,43 +780,32 @@ func writeProxyProtocolV2(w io.Writer, hdr proxyProtocolV2) error {
|
||||
default:
|
||||
fam |= byte(proxyProtocolV2ProtocolUnspec)
|
||||
}
|
||||
|
||||
if _, err := w.Write([]byte{fam}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
length := uint16(216 + len(hdr.additionalData))
|
||||
|
||||
if err := binary.Write(w, binary.BigEndian, length); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
zeros := make([]byte, 108)
|
||||
|
||||
if _, err := w.Write([]byte(srcAddr.Name)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err := w.Write(zeros[:108-len(srcAddr.Name)]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err := w.Write([]byte(dstAddr.Name)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err := w.Write(zeros[:108-len(dstAddr.Name)]); err != nil {
|
||||
return err
|
||||
}
|
||||
default:
|
||||
fam := byte(proxyProtocolV2FamilyUnspec<<4) | byte(proxyProtocolV2ProtocolUnspec)
|
||||
|
||||
if _, err := w.Write([]byte{fam}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
length := uint16(len(hdr.additionalData))
|
||||
|
||||
if err := binary.Write(w, binary.BigEndian, length); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ import (
|
||||
)
|
||||
|
||||
func (st *serverTester) http3(rp requestParam) (*serverResponse, error) {
|
||||
rt := &http3.Transport{
|
||||
rt := &http3.RoundTripper{
|
||||
TLSClientConfig: &tls.Config{
|
||||
InsecureSkipVerify: true,
|
||||
},
|
||||
@@ -45,7 +45,6 @@ func (st *serverTester) http3(rp requestParam) (*serverResponse, error) {
|
||||
if err != nil {
|
||||
st.t.Fatalf("Error parsing URL from st.url %v: %v", st.url, err)
|
||||
}
|
||||
|
||||
u.Path = ""
|
||||
u.RawQuery = ""
|
||||
reqURL = u.String() + rp.path
|
||||
|
||||
@@ -47,29 +47,7 @@ if(WIN32)
|
||||
set(NGHTTP2_RES ${CMAKE_CURRENT_BINARY_DIR}/version.rc)
|
||||
endif()
|
||||
|
||||
set(NGHTTP2_GENERATED_DIR "${CMAKE_CURRENT_BINARY_DIR}/generated")
|
||||
set(NGHTTP2_VERSION_CONFIG "${NGHTTP2_GENERATED_DIR}/${PROJECT_NAME}ConfigVersion.cmake")
|
||||
set(NGHTTP2_PROJECT_CONFIG "${NGHTTP2_GENERATED_DIR}/${PROJECT_NAME}Config.cmake")
|
||||
set(NGHTTP2_TARGETS_EXPORT_NAME "${PROJECT_NAME}Targets")
|
||||
set(NGHTTP2_CONFIG_INSTALL_DIR "lib/cmake/${PROJECT_NAME}")
|
||||
set(NGHTTP2_NAMESPACE "${PROJECT_NAME}::")
|
||||
set(NGHTTP2_VERSION ${PROJECT_VERSION})
|
||||
|
||||
include(CMakePackageConfigHelpers)
|
||||
write_basic_package_version_file(
|
||||
"${NGHTTP2_VERSION_CONFIG}" VERSION ${NGHTTP2_VERSION} COMPATIBILITY SameMajorVersion
|
||||
)
|
||||
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/config.cmake.in" "${NGHTTP2_PROJECT_CONFIG}" @ONLY)
|
||||
|
||||
# Install cmake config files
|
||||
install(
|
||||
FILES "${NGHTTP2_PROJECT_CONFIG}" "${NGHTTP2_VERSION_CONFIG}"
|
||||
DESTINATION "${NGHTTP2_CONFIG_INSTALL_DIR}")
|
||||
|
||||
install(
|
||||
EXPORT "${NGHTTP2_TARGETS_EXPORT_NAME}"
|
||||
NAMESPACE "${NGHTTP2_NAMESPACE}"
|
||||
DESTINATION "${NGHTTP2_CONFIG_INSTALL_DIR}")
|
||||
set(EXPORT_SET "${PROJECT_NAME}-targets")
|
||||
|
||||
# Public shared library
|
||||
if(BUILD_SHARED_LIBS)
|
||||
@@ -87,11 +65,7 @@ if(BUILD_SHARED_LIBS)
|
||||
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
|
||||
)
|
||||
|
||||
install(TARGETS ${SHARED_LIB}
|
||||
EXPORT ${NGHTTP2_TARGETS_EXPORT_NAME}
|
||||
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()
|
||||
|
||||
@@ -113,9 +87,7 @@ if(BUILD_STATIC_LIBS)
|
||||
|
||||
target_compile_definitions(${STATIC_LIB} PUBLIC "-DNGHTTP2_STATICLIB")
|
||||
|
||||
install(TARGETS ${STATIC_LIB}
|
||||
EXPORT ${NGHTTP2_TARGETS_EXPORT_NAME}
|
||||
ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}")
|
||||
install(TARGETS ${STATIC_LIB} EXPORT ${EXPORT_SET})
|
||||
list(APPEND nghttp2_exports ${STATIC_LIB})
|
||||
endif()
|
||||
|
||||
@@ -125,7 +97,11 @@ else()
|
||||
set(LIB_SELECTED ${STATIC_LIB})
|
||||
endif()
|
||||
|
||||
add_library(nghttp2 ALIAS ${LIB_SELECTED})
|
||||
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}::)
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
SUBDIRS = includes
|
||||
|
||||
EXTRA_DIST = Makefile.msvc CMakeLists.txt version.rc.in config.cmake.in
|
||||
EXTRA_DIST = Makefile.msvc CMakeLists.txt version.rc.in
|
||||
|
||||
AM_CFLAGS = $(WARNCFLAGS) $(EXTRACFLAG)
|
||||
AM_CPPFLAGS = -I$(srcdir)/includes -I$(builddir)/includes -DBUILDING_NGHTTP2 \
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
include(CMakeFindDependencyMacro)
|
||||
|
||||
include("${CMAKE_CURRENT_LIST_DIR}/@NGHTTP2_TARGETS_EXPORT_NAME@.cmake")
|
||||
File diff suppressed because it is too large
Load Diff
@@ -41,168 +41,163 @@ void nghttp2_session_callbacks_del(nghttp2_session_callbacks *callbacks) {
|
||||
}
|
||||
|
||||
void nghttp2_session_callbacks_set_send_callback(
|
||||
nghttp2_session_callbacks *cbs, nghttp2_send_callback send_callback) {
|
||||
nghttp2_session_callbacks *cbs, nghttp2_send_callback send_callback) {
|
||||
cbs->send_callback = send_callback;
|
||||
}
|
||||
|
||||
void nghttp2_session_callbacks_set_send_callback2(
|
||||
nghttp2_session_callbacks *cbs, nghttp2_send_callback2 send_callback) {
|
||||
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) {
|
||||
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) {
|
||||
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) {
|
||||
nghttp2_session_callbacks *cbs,
|
||||
nghttp2_on_frame_recv_callback on_frame_recv_callback) {
|
||||
cbs->on_frame_recv_callback = on_frame_recv_callback;
|
||||
}
|
||||
|
||||
void nghttp2_session_callbacks_set_on_invalid_frame_recv_callback(
|
||||
nghttp2_session_callbacks *cbs,
|
||||
nghttp2_on_invalid_frame_recv_callback on_invalid_frame_recv_callback) {
|
||||
nghttp2_session_callbacks *cbs,
|
||||
nghttp2_on_invalid_frame_recv_callback on_invalid_frame_recv_callback) {
|
||||
cbs->on_invalid_frame_recv_callback = on_invalid_frame_recv_callback;
|
||||
}
|
||||
|
||||
void nghttp2_session_callbacks_set_on_data_chunk_recv_callback(
|
||||
nghttp2_session_callbacks *cbs,
|
||||
nghttp2_on_data_chunk_recv_callback on_data_chunk_recv_callback) {
|
||||
nghttp2_session_callbacks *cbs,
|
||||
nghttp2_on_data_chunk_recv_callback on_data_chunk_recv_callback) {
|
||||
cbs->on_data_chunk_recv_callback = on_data_chunk_recv_callback;
|
||||
}
|
||||
|
||||
void nghttp2_session_callbacks_set_before_frame_send_callback(
|
||||
nghttp2_session_callbacks *cbs,
|
||||
nghttp2_before_frame_send_callback before_frame_send_callback) {
|
||||
nghttp2_session_callbacks *cbs,
|
||||
nghttp2_before_frame_send_callback before_frame_send_callback) {
|
||||
cbs->before_frame_send_callback = before_frame_send_callback;
|
||||
}
|
||||
|
||||
void nghttp2_session_callbacks_set_on_frame_send_callback(
|
||||
nghttp2_session_callbacks *cbs,
|
||||
nghttp2_on_frame_send_callback on_frame_send_callback) {
|
||||
nghttp2_session_callbacks *cbs,
|
||||
nghttp2_on_frame_send_callback on_frame_send_callback) {
|
||||
cbs->on_frame_send_callback = on_frame_send_callback;
|
||||
}
|
||||
|
||||
void nghttp2_session_callbacks_set_on_frame_not_send_callback(
|
||||
nghttp2_session_callbacks *cbs,
|
||||
nghttp2_on_frame_not_send_callback on_frame_not_send_callback) {
|
||||
nghttp2_session_callbacks *cbs,
|
||||
nghttp2_on_frame_not_send_callback on_frame_not_send_callback) {
|
||||
cbs->on_frame_not_send_callback = on_frame_not_send_callback;
|
||||
}
|
||||
|
||||
void nghttp2_session_callbacks_set_on_stream_close_callback(
|
||||
nghttp2_session_callbacks *cbs,
|
||||
nghttp2_on_stream_close_callback on_stream_close_callback) {
|
||||
nghttp2_session_callbacks *cbs,
|
||||
nghttp2_on_stream_close_callback on_stream_close_callback) {
|
||||
cbs->on_stream_close_callback = on_stream_close_callback;
|
||||
}
|
||||
|
||||
void nghttp2_session_callbacks_set_on_begin_headers_callback(
|
||||
nghttp2_session_callbacks *cbs,
|
||||
nghttp2_on_begin_headers_callback on_begin_headers_callback) {
|
||||
nghttp2_session_callbacks *cbs,
|
||||
nghttp2_on_begin_headers_callback on_begin_headers_callback) {
|
||||
cbs->on_begin_headers_callback = on_begin_headers_callback;
|
||||
}
|
||||
|
||||
void nghttp2_session_callbacks_set_on_header_callback(
|
||||
nghttp2_session_callbacks *cbs,
|
||||
nghttp2_on_header_callback on_header_callback) {
|
||||
nghttp2_session_callbacks *cbs,
|
||||
nghttp2_on_header_callback on_header_callback) {
|
||||
cbs->on_header_callback = on_header_callback;
|
||||
}
|
||||
|
||||
void nghttp2_session_callbacks_set_on_header_callback2(
|
||||
nghttp2_session_callbacks *cbs,
|
||||
nghttp2_on_header_callback2 on_header_callback2) {
|
||||
nghttp2_session_callbacks *cbs,
|
||||
nghttp2_on_header_callback2 on_header_callback2) {
|
||||
cbs->on_header_callback2 = on_header_callback2;
|
||||
}
|
||||
|
||||
void nghttp2_session_callbacks_set_on_invalid_header_callback(
|
||||
nghttp2_session_callbacks *cbs,
|
||||
nghttp2_on_invalid_header_callback on_invalid_header_callback) {
|
||||
nghttp2_session_callbacks *cbs,
|
||||
nghttp2_on_invalid_header_callback on_invalid_header_callback) {
|
||||
cbs->on_invalid_header_callback = on_invalid_header_callback;
|
||||
}
|
||||
|
||||
void nghttp2_session_callbacks_set_on_invalid_header_callback2(
|
||||
nghttp2_session_callbacks *cbs,
|
||||
nghttp2_on_invalid_header_callback2 on_invalid_header_callback2) {
|
||||
nghttp2_session_callbacks *cbs,
|
||||
nghttp2_on_invalid_header_callback2 on_invalid_header_callback2) {
|
||||
cbs->on_invalid_header_callback2 = on_invalid_header_callback2;
|
||||
}
|
||||
|
||||
void nghttp2_session_callbacks_set_select_padding_callback(
|
||||
nghttp2_session_callbacks *cbs,
|
||||
nghttp2_select_padding_callback select_padding_callback) {
|
||||
nghttp2_session_callbacks *cbs,
|
||||
nghttp2_select_padding_callback 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) {
|
||||
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) {
|
||||
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) {
|
||||
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) {
|
||||
nghttp2_session_callbacks *cbs,
|
||||
nghttp2_on_begin_frame_callback on_begin_frame_callback) {
|
||||
cbs->on_begin_frame_callback = on_begin_frame_callback;
|
||||
}
|
||||
|
||||
void nghttp2_session_callbacks_set_send_data_callback(
|
||||
nghttp2_session_callbacks *cbs,
|
||||
nghttp2_send_data_callback send_data_callback) {
|
||||
nghttp2_session_callbacks *cbs,
|
||||
nghttp2_send_data_callback send_data_callback) {
|
||||
cbs->send_data_callback = send_data_callback;
|
||||
}
|
||||
|
||||
void nghttp2_session_callbacks_set_pack_extension_callback(
|
||||
nghttp2_session_callbacks *cbs,
|
||||
nghttp2_pack_extension_callback pack_extension_callback) {
|
||||
nghttp2_session_callbacks *cbs,
|
||||
nghttp2_pack_extension_callback 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) {
|
||||
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) {
|
||||
nghttp2_session_callbacks *cbs,
|
||||
nghttp2_unpack_extension_callback unpack_extension_callback) {
|
||||
cbs->unpack_extension_callback = unpack_extension_callback;
|
||||
}
|
||||
|
||||
void nghttp2_session_callbacks_set_on_extension_chunk_recv_callback(
|
||||
nghttp2_session_callbacks *cbs,
|
||||
nghttp2_on_extension_chunk_recv_callback on_extension_chunk_recv_callback) {
|
||||
nghttp2_session_callbacks *cbs,
|
||||
nghttp2_on_extension_chunk_recv_callback on_extension_chunk_recv_callback) {
|
||||
cbs->on_extension_chunk_recv_callback = on_extension_chunk_recv_callback;
|
||||
}
|
||||
|
||||
void nghttp2_session_callbacks_set_error_callback(
|
||||
nghttp2_session_callbacks *cbs, nghttp2_error_callback error_callback) {
|
||||
nghttp2_session_callbacks *cbs, nghttp2_error_callback error_callback) {
|
||||
cbs->error_callback = error_callback;
|
||||
}
|
||||
|
||||
void nghttp2_session_callbacks_set_error_callback2(
|
||||
nghttp2_session_callbacks *cbs, nghttp2_error_callback2 error_callback2) {
|
||||
nghttp2_session_callbacks *cbs, nghttp2_error_callback2 error_callback2) {
|
||||
cbs->error_callback2 = error_callback2;
|
||||
}
|
||||
|
||||
void nghttp2_session_callbacks_set_rand_callback(
|
||||
nghttp2_session_callbacks *cbs, nghttp2_rand_callback rand_callback) {
|
||||
cbs->rand_callback = rand_callback;
|
||||
}
|
||||
|
||||
@@ -151,7 +151,6 @@ struct nghttp2_session_callbacks {
|
||||
nghttp2_on_extension_chunk_recv_callback on_extension_chunk_recv_callback;
|
||||
nghttp2_error_callback error_callback;
|
||||
nghttp2_error_callback2 error_callback2;
|
||||
nghttp2_rand_callback rand_callback;
|
||||
};
|
||||
|
||||
#endif /* NGHTTP2_CALLBACKS_H */
|
||||
|
||||
@@ -34,7 +34,7 @@ static void nghttp2_default_debug_vfprintf_callback(const char *fmt,
|
||||
}
|
||||
|
||||
static nghttp2_debug_vprintf_callback static_debug_vprintf_callback =
|
||||
nghttp2_default_debug_vfprintf_callback;
|
||||
nghttp2_default_debug_vfprintf_callback;
|
||||
|
||||
void nghttp2_debug_vprintf(const char *format, ...) {
|
||||
if (static_debug_vprintf_callback) {
|
||||
@@ -46,14 +46,14 @@ void nghttp2_debug_vprintf(const char *format, ...) {
|
||||
}
|
||||
|
||||
void nghttp2_set_debug_vprintf_callback(
|
||||
nghttp2_debug_vprintf_callback debug_vprintf_callback) {
|
||||
nghttp2_debug_vprintf_callback debug_vprintf_callback) {
|
||||
static_debug_vprintf_callback = debug_vprintf_callback;
|
||||
}
|
||||
|
||||
#else /* !DEBUGBUILD */
|
||||
|
||||
void nghttp2_set_debug_vprintf_callback(
|
||||
nghttp2_debug_vprintf_callback debug_vprintf_callback) {
|
||||
nghttp2_debug_vprintf_callback debug_vprintf_callback) {
|
||||
(void)debug_vprintf_callback;
|
||||
}
|
||||
|
||||
|
||||
@@ -60,6 +60,6 @@ void nghttp2_extpri_from_uint8(nghttp2_extpri *extpri, uint8_t u8extpri);
|
||||
* nghttp2_extpri_uint8_inc extracts inc from |PRI| which is supposed to
|
||||
* be constructed by nghttp2_extpri_to_uint8.
|
||||
*/
|
||||
#define nghttp2_extpri_uint8_inc(PRI) (((PRI) & NGHTTP2_EXTPRI_INC_MASK) != 0)
|
||||
#define nghttp2_extpri_uint8_inc(PRI) (((PRI)&NGHTTP2_EXTPRI_INC_MASK) != 0)
|
||||
|
||||
#endif /* NGHTTP2_EXTPRI_H */
|
||||
|
||||
@@ -492,7 +492,7 @@ int nghttp2_frame_pack_settings(nghttp2_bufs *bufs, nghttp2_settings *frame) {
|
||||
nghttp2_frame_pack_frame_hd(buf->pos, &frame->hd);
|
||||
|
||||
buf->last +=
|
||||
nghttp2_frame_pack_settings_payload(buf->last, frame->iv, frame->niv);
|
||||
nghttp2_frame_pack_settings_payload(buf->last, frame->iv, frame->niv);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -537,7 +537,7 @@ int nghttp2_frame_unpack_settings_payload2(nghttp2_settings_entry **iv_ptr,
|
||||
}
|
||||
|
||||
*iv_ptr =
|
||||
nghttp2_mem_malloc(mem, (*niv_ptr) * sizeof(nghttp2_settings_entry));
|
||||
nghttp2_mem_malloc(mem, (*niv_ptr) * sizeof(nghttp2_settings_entry));
|
||||
|
||||
if (*iv_ptr == NULL) {
|
||||
return NGHTTP2_ERR_NOMEM;
|
||||
@@ -589,7 +589,7 @@ int nghttp2_frame_pack_push_promise(nghttp2_bufs *bufs,
|
||||
void nghttp2_frame_unpack_push_promise_payload(nghttp2_push_promise *frame,
|
||||
const uint8_t *payload) {
|
||||
frame->promised_stream_id =
|
||||
nghttp2_get_uint32(payload) & NGHTTP2_STREAM_ID_MASK;
|
||||
nghttp2_get_uint32(payload) & NGHTTP2_STREAM_ID_MASK;
|
||||
frame->nva = NULL;
|
||||
frame->nvlen = 0;
|
||||
}
|
||||
@@ -608,7 +608,7 @@ void nghttp2_frame_pack_ping(nghttp2_bufs *bufs, nghttp2_ping *frame) {
|
||||
nghttp2_frame_pack_frame_hd(buf->pos, &frame->hd);
|
||||
|
||||
buf->last =
|
||||
nghttp2_cpymem(buf->last, frame->opaque_data, sizeof(frame->opaque_data));
|
||||
nghttp2_cpymem(buf->last, frame->opaque_data, sizeof(frame->opaque_data));
|
||||
}
|
||||
|
||||
void nghttp2_frame_unpack_ping_payload(nghttp2_ping *frame,
|
||||
@@ -709,7 +709,7 @@ void nghttp2_frame_pack_window_update(nghttp2_bufs *bufs,
|
||||
void nghttp2_frame_unpack_window_update_payload(nghttp2_window_update *frame,
|
||||
const uint8_t *payload) {
|
||||
frame->window_size_increment =
|
||||
nghttp2_get_uint32(payload) & NGHTTP2_WINDOW_SIZE_INCREMENT_MASK;
|
||||
nghttp2_get_uint32(payload) & NGHTTP2_WINDOW_SIZE_INCREMENT_MASK;
|
||||
}
|
||||
|
||||
void nghttp2_frame_pack_altsvc(nghttp2_bufs *bufs, nghttp2_extension *frame) {
|
||||
@@ -926,7 +926,7 @@ void nghttp2_frame_unpack_priority_update_payload(nghttp2_extension *frame,
|
||||
priority_update = frame->payload;
|
||||
|
||||
priority_update->stream_id =
|
||||
nghttp2_get_uint32(payload) & NGHTTP2_STREAM_ID_MASK;
|
||||
nghttp2_get_uint32(payload) & NGHTTP2_STREAM_ID_MASK;
|
||||
|
||||
if (payloadlen > 4) {
|
||||
priority_update->field_value = payload + 4;
|
||||
|
||||
197
lib/nghttp2_hd.c
197
lib/nghttp2_hd.c
@@ -36,10 +36,9 @@
|
||||
#define MAKE_STATIC_ENT(N, V, T, H) \
|
||||
{ \
|
||||
{NULL, NULL, (uint8_t *)(N), sizeof((N)) - 1, -1}, \
|
||||
{NULL, NULL, (uint8_t *)(V), sizeof((V)) - 1, -1}, \
|
||||
{(uint8_t *)(N), (uint8_t *)(V), sizeof((N)) - 1, sizeof((V)) - 1, 0}, \
|
||||
T, \
|
||||
H, \
|
||||
{NULL, NULL, (uint8_t *)(V), sizeof((V)) - 1, -1}, \
|
||||
{(uint8_t *)(N), (uint8_t *)(V), sizeof((N)) - 1, sizeof((V)) - 1, 0}, \
|
||||
T, H \
|
||||
}
|
||||
|
||||
/* Generated by mkstatictbl.py */
|
||||
@@ -47,67 +46,67 @@
|
||||
first enum value if same header names are repeated (e.g.,
|
||||
:status). */
|
||||
static const nghttp2_hd_static_entry static_table[] = {
|
||||
MAKE_STATIC_ENT(":authority", "", 0, 3153725150u),
|
||||
MAKE_STATIC_ENT(":method", "GET", 1, 695666056u),
|
||||
MAKE_STATIC_ENT(":method", "POST", 1, 695666056u),
|
||||
MAKE_STATIC_ENT(":path", "/", 3, 3292848686u),
|
||||
MAKE_STATIC_ENT(":path", "/index.html", 3, 3292848686u),
|
||||
MAKE_STATIC_ENT(":scheme", "http", 5, 2510477674u),
|
||||
MAKE_STATIC_ENT(":scheme", "https", 5, 2510477674u),
|
||||
MAKE_STATIC_ENT(":status", "200", 7, 4000288983u),
|
||||
MAKE_STATIC_ENT(":status", "204", 7, 4000288983u),
|
||||
MAKE_STATIC_ENT(":status", "206", 7, 4000288983u),
|
||||
MAKE_STATIC_ENT(":status", "304", 7, 4000288983u),
|
||||
MAKE_STATIC_ENT(":status", "400", 7, 4000288983u),
|
||||
MAKE_STATIC_ENT(":status", "404", 7, 4000288983u),
|
||||
MAKE_STATIC_ENT(":status", "500", 7, 4000288983u),
|
||||
MAKE_STATIC_ENT("accept-charset", "", 14, 3664010344u),
|
||||
MAKE_STATIC_ENT("accept-encoding", "gzip, deflate", 15, 3379649177u),
|
||||
MAKE_STATIC_ENT("accept-language", "", 16, 1979086614u),
|
||||
MAKE_STATIC_ENT("accept-ranges", "", 17, 1713753958u),
|
||||
MAKE_STATIC_ENT("accept", "", 18, 136609321u),
|
||||
MAKE_STATIC_ENT("access-control-allow-origin", "", 19, 2710797292u),
|
||||
MAKE_STATIC_ENT("age", "", 20, 742476188u),
|
||||
MAKE_STATIC_ENT("allow", "", 21, 2930878514u),
|
||||
MAKE_STATIC_ENT("authorization", "", 22, 2436257726u),
|
||||
MAKE_STATIC_ENT("cache-control", "", 23, 1355326669u),
|
||||
MAKE_STATIC_ENT("content-disposition", "", 24, 3889184348u),
|
||||
MAKE_STATIC_ENT("content-encoding", "", 25, 65203592u),
|
||||
MAKE_STATIC_ENT("content-language", "", 26, 24973587u),
|
||||
MAKE_STATIC_ENT("content-length", "", 27, 1308181789u),
|
||||
MAKE_STATIC_ENT("content-location", "", 28, 2302364718u),
|
||||
MAKE_STATIC_ENT("content-range", "", 29, 3555523146u),
|
||||
MAKE_STATIC_ENT("content-type", "", 30, 4244048277u),
|
||||
MAKE_STATIC_ENT("cookie", "", 31, 2007449791u),
|
||||
MAKE_STATIC_ENT("date", "", 32, 3564297305u),
|
||||
MAKE_STATIC_ENT("etag", "", 33, 113792960u),
|
||||
MAKE_STATIC_ENT("expect", "", 34, 2530896728u),
|
||||
MAKE_STATIC_ENT("expires", "", 35, 1049544579u),
|
||||
MAKE_STATIC_ENT("from", "", 36, 2513272949u),
|
||||
MAKE_STATIC_ENT("host", "", 37, 2952701295u),
|
||||
MAKE_STATIC_ENT("if-match", "", 38, 3597694698u),
|
||||
MAKE_STATIC_ENT("if-modified-since", "", 39, 2213050793u),
|
||||
MAKE_STATIC_ENT("if-none-match", "", 40, 2536202615u),
|
||||
MAKE_STATIC_ENT("if-range", "", 41, 2340978238u),
|
||||
MAKE_STATIC_ENT("if-unmodified-since", "", 42, 3794814858u),
|
||||
MAKE_STATIC_ENT("last-modified", "", 43, 3226950251u),
|
||||
MAKE_STATIC_ENT("link", "", 44, 232457833u),
|
||||
MAKE_STATIC_ENT("location", "", 45, 200649126u),
|
||||
MAKE_STATIC_ENT("max-forwards", "", 46, 1826162134u),
|
||||
MAKE_STATIC_ENT("proxy-authenticate", "", 47, 2709445359u),
|
||||
MAKE_STATIC_ENT("proxy-authorization", "", 48, 2686392507u),
|
||||
MAKE_STATIC_ENT("range", "", 49, 4208725202u),
|
||||
MAKE_STATIC_ENT("referer", "", 50, 3969579366u),
|
||||
MAKE_STATIC_ENT("refresh", "", 51, 3572655668u),
|
||||
MAKE_STATIC_ENT("retry-after", "", 52, 3336180598u),
|
||||
MAKE_STATIC_ENT("server", "", 53, 1085029842u),
|
||||
MAKE_STATIC_ENT("set-cookie", "", 54, 1848371000u),
|
||||
MAKE_STATIC_ENT("strict-transport-security", "", 55, 4138147361u),
|
||||
MAKE_STATIC_ENT("transfer-encoding", "", 56, 3719590988u),
|
||||
MAKE_STATIC_ENT("user-agent", "", 57, 606444526u),
|
||||
MAKE_STATIC_ENT("vary", "", 58, 1085005381u),
|
||||
MAKE_STATIC_ENT("via", "", 59, 1762798611u),
|
||||
MAKE_STATIC_ENT("www-authenticate", "", 60, 779865858u),
|
||||
MAKE_STATIC_ENT(":authority", "", 0, 3153725150u),
|
||||
MAKE_STATIC_ENT(":method", "GET", 1, 695666056u),
|
||||
MAKE_STATIC_ENT(":method", "POST", 1, 695666056u),
|
||||
MAKE_STATIC_ENT(":path", "/", 3, 3292848686u),
|
||||
MAKE_STATIC_ENT(":path", "/index.html", 3, 3292848686u),
|
||||
MAKE_STATIC_ENT(":scheme", "http", 5, 2510477674u),
|
||||
MAKE_STATIC_ENT(":scheme", "https", 5, 2510477674u),
|
||||
MAKE_STATIC_ENT(":status", "200", 7, 4000288983u),
|
||||
MAKE_STATIC_ENT(":status", "204", 7, 4000288983u),
|
||||
MAKE_STATIC_ENT(":status", "206", 7, 4000288983u),
|
||||
MAKE_STATIC_ENT(":status", "304", 7, 4000288983u),
|
||||
MAKE_STATIC_ENT(":status", "400", 7, 4000288983u),
|
||||
MAKE_STATIC_ENT(":status", "404", 7, 4000288983u),
|
||||
MAKE_STATIC_ENT(":status", "500", 7, 4000288983u),
|
||||
MAKE_STATIC_ENT("accept-charset", "", 14, 3664010344u),
|
||||
MAKE_STATIC_ENT("accept-encoding", "gzip, deflate", 15, 3379649177u),
|
||||
MAKE_STATIC_ENT("accept-language", "", 16, 1979086614u),
|
||||
MAKE_STATIC_ENT("accept-ranges", "", 17, 1713753958u),
|
||||
MAKE_STATIC_ENT("accept", "", 18, 136609321u),
|
||||
MAKE_STATIC_ENT("access-control-allow-origin", "", 19, 2710797292u),
|
||||
MAKE_STATIC_ENT("age", "", 20, 742476188u),
|
||||
MAKE_STATIC_ENT("allow", "", 21, 2930878514u),
|
||||
MAKE_STATIC_ENT("authorization", "", 22, 2436257726u),
|
||||
MAKE_STATIC_ENT("cache-control", "", 23, 1355326669u),
|
||||
MAKE_STATIC_ENT("content-disposition", "", 24, 3889184348u),
|
||||
MAKE_STATIC_ENT("content-encoding", "", 25, 65203592u),
|
||||
MAKE_STATIC_ENT("content-language", "", 26, 24973587u),
|
||||
MAKE_STATIC_ENT("content-length", "", 27, 1308181789u),
|
||||
MAKE_STATIC_ENT("content-location", "", 28, 2302364718u),
|
||||
MAKE_STATIC_ENT("content-range", "", 29, 3555523146u),
|
||||
MAKE_STATIC_ENT("content-type", "", 30, 4244048277u),
|
||||
MAKE_STATIC_ENT("cookie", "", 31, 2007449791u),
|
||||
MAKE_STATIC_ENT("date", "", 32, 3564297305u),
|
||||
MAKE_STATIC_ENT("etag", "", 33, 113792960u),
|
||||
MAKE_STATIC_ENT("expect", "", 34, 2530896728u),
|
||||
MAKE_STATIC_ENT("expires", "", 35, 1049544579u),
|
||||
MAKE_STATIC_ENT("from", "", 36, 2513272949u),
|
||||
MAKE_STATIC_ENT("host", "", 37, 2952701295u),
|
||||
MAKE_STATIC_ENT("if-match", "", 38, 3597694698u),
|
||||
MAKE_STATIC_ENT("if-modified-since", "", 39, 2213050793u),
|
||||
MAKE_STATIC_ENT("if-none-match", "", 40, 2536202615u),
|
||||
MAKE_STATIC_ENT("if-range", "", 41, 2340978238u),
|
||||
MAKE_STATIC_ENT("if-unmodified-since", "", 42, 3794814858u),
|
||||
MAKE_STATIC_ENT("last-modified", "", 43, 3226950251u),
|
||||
MAKE_STATIC_ENT("link", "", 44, 232457833u),
|
||||
MAKE_STATIC_ENT("location", "", 45, 200649126u),
|
||||
MAKE_STATIC_ENT("max-forwards", "", 46, 1826162134u),
|
||||
MAKE_STATIC_ENT("proxy-authenticate", "", 47, 2709445359u),
|
||||
MAKE_STATIC_ENT("proxy-authorization", "", 48, 2686392507u),
|
||||
MAKE_STATIC_ENT("range", "", 49, 4208725202u),
|
||||
MAKE_STATIC_ENT("referer", "", 50, 3969579366u),
|
||||
MAKE_STATIC_ENT("refresh", "", 51, 3572655668u),
|
||||
MAKE_STATIC_ENT("retry-after", "", 52, 3336180598u),
|
||||
MAKE_STATIC_ENT("server", "", 53, 1085029842u),
|
||||
MAKE_STATIC_ENT("set-cookie", "", 54, 1848371000u),
|
||||
MAKE_STATIC_ENT("strict-transport-security", "", 55, 4138147361u),
|
||||
MAKE_STATIC_ENT("transfer-encoding", "", 56, 3719590988u),
|
||||
MAKE_STATIC_ENT("user-agent", "", 57, 606444526u),
|
||||
MAKE_STATIC_ENT("vary", "", 58, 1085005381u),
|
||||
MAKE_STATIC_ENT("via", "", 59, 1762798611u),
|
||||
MAKE_STATIC_ENT("www-authenticate", "", 60, 779865858u),
|
||||
};
|
||||
|
||||
static int memeq(const void *s1, const void *s2, size_t n) {
|
||||
@@ -594,19 +593,8 @@ static void hd_map_remove(nghttp2_hd_map *map, nghttp2_hd_entry *ent) {
|
||||
static int hd_ringbuf_init(nghttp2_hd_ringbuf *ringbuf, size_t bufsize,
|
||||
nghttp2_mem *mem) {
|
||||
size_t size;
|
||||
const size_t max_size = SIZE_MAX / sizeof(nghttp2_hd_entry *);
|
||||
|
||||
if (bufsize > max_size) {
|
||||
return NGHTTP2_ERR_NOMEM;
|
||||
}
|
||||
|
||||
for (size = 1; size < bufsize; size <<= 1)
|
||||
;
|
||||
|
||||
if (size > max_size) {
|
||||
return NGHTTP2_ERR_NOMEM;
|
||||
}
|
||||
|
||||
ringbuf->buffer = nghttp2_mem_malloc(mem, sizeof(nghttp2_hd_entry *) * size);
|
||||
if (ringbuf->buffer == NULL) {
|
||||
return NGHTTP2_ERR_NOMEM;
|
||||
@@ -689,8 +677,8 @@ static int hd_context_init(nghttp2_hd_context *context, nghttp2_mem *mem) {
|
||||
context->bad = 0;
|
||||
context->hd_table_bufsize_max = NGHTTP2_HD_DEFAULT_MAX_BUFFER_SIZE;
|
||||
rv = hd_ringbuf_init(
|
||||
&context->hd_table,
|
||||
context->hd_table_bufsize_max / NGHTTP2_HD_ENTRY_OVERHEAD, mem);
|
||||
&context->hd_table,
|
||||
context->hd_table_bufsize_max / NGHTTP2_HD_ENTRY_OVERHEAD, mem);
|
||||
if (rv != 0) {
|
||||
return rv;
|
||||
}
|
||||
@@ -707,7 +695,7 @@ static void hd_context_free(nghttp2_hd_context *context) {
|
||||
|
||||
int nghttp2_hd_deflate_init(nghttp2_hd_deflater *deflater, nghttp2_mem *mem) {
|
||||
return nghttp2_hd_deflate_init2(
|
||||
deflater, NGHTTP2_HD_DEFAULT_MAX_DEFLATE_BUFFER_SIZE, mem);
|
||||
deflater, NGHTTP2_HD_DEFAULT_MAX_DEFLATE_BUFFER_SIZE, mem);
|
||||
}
|
||||
|
||||
int nghttp2_hd_deflate_init2(nghttp2_hd_deflater *deflater,
|
||||
@@ -1089,8 +1077,8 @@ static int emit_newname_block(nghttp2_bufs *bufs, const nghttp2_nv *nv,
|
||||
int rv;
|
||||
|
||||
DEBUGF(
|
||||
"deflatehd: emit newname namelen=%zu, valuelen=%zu, indexing_mode=%d\n",
|
||||
nv->namelen, nv->valuelen, indexing_mode);
|
||||
"deflatehd: emit newname namelen=%zu, valuelen=%zu, indexing_mode=%d\n",
|
||||
nv->namelen, nv->valuelen, indexing_mode);
|
||||
|
||||
rv = nghttp2_bufs_addb(bufs, pack_first_byte(indexing_mode));
|
||||
if (rv != 0) {
|
||||
@@ -1123,11 +1111,12 @@ static int add_hd_table_incremental(nghttp2_hd_context *context,
|
||||
|
||||
while (context->hd_table_bufsize + room > context->hd_table_bufsize_max &&
|
||||
context->hd_table.len > 0) {
|
||||
|
||||
size_t idx = context->hd_table.len - 1;
|
||||
nghttp2_hd_entry *ent = hd_ringbuf_get(&context->hd_table, idx);
|
||||
|
||||
context->hd_table_bufsize -=
|
||||
entry_room(ent->nv.name->len, ent->nv.value->len);
|
||||
entry_room(ent->nv.name->len, ent->nv.value->len);
|
||||
|
||||
DEBUGF("hpack: remove item from header table: %s: %s\n",
|
||||
(char *)ent->nv.name->base, (char *)ent->nv.value->base);
|
||||
@@ -1243,7 +1232,7 @@ static void hd_context_shrink_table_size(nghttp2_hd_context *context,
|
||||
size_t idx = context->hd_table.len - 1;
|
||||
nghttp2_hd_entry *ent = hd_ringbuf_get(&context->hd_table, idx);
|
||||
context->hd_table_bufsize -=
|
||||
entry_room(ent->nv.name->len, ent->nv.value->len);
|
||||
entry_room(ent->nv.name->len, ent->nv.value->len);
|
||||
hd_ringbuf_pop_back(&context->hd_table);
|
||||
if (map) {
|
||||
hd_map_remove(map, ent);
|
||||
@@ -1255,14 +1244,14 @@ static void hd_context_shrink_table_size(nghttp2_hd_context *context,
|
||||
}
|
||||
|
||||
int nghttp2_hd_deflate_change_table_size(
|
||||
nghttp2_hd_deflater *deflater, size_t settings_max_dynamic_table_size) {
|
||||
nghttp2_hd_deflater *deflater, size_t settings_max_dynamic_table_size) {
|
||||
size_t next_bufsize = nghttp2_min_size(
|
||||
settings_max_dynamic_table_size, deflater->deflate_hd_table_bufsize_max);
|
||||
settings_max_dynamic_table_size, deflater->deflate_hd_table_bufsize_max);
|
||||
|
||||
deflater->ctx.hd_table_bufsize_max = next_bufsize;
|
||||
|
||||
deflater->min_hd_table_bufsize_max =
|
||||
nghttp2_min_size(deflater->min_hd_table_bufsize_max, next_bufsize);
|
||||
nghttp2_min_size(deflater->min_hd_table_bufsize_max, next_bufsize);
|
||||
|
||||
deflater->notify_table_size_change = 1;
|
||||
|
||||
@@ -1271,7 +1260,7 @@ int nghttp2_hd_deflate_change_table_size(
|
||||
}
|
||||
|
||||
int nghttp2_hd_inflate_change_table_size(
|
||||
nghttp2_hd_inflater *inflater, size_t settings_max_dynamic_table_size) {
|
||||
nghttp2_hd_inflater *inflater, size_t settings_max_dynamic_table_size) {
|
||||
switch (inflater->state) {
|
||||
case NGHTTP2_HD_STATE_EXPECT_TABLE_SIZE:
|
||||
case NGHTTP2_HD_STATE_INFLATE_START:
|
||||
@@ -1314,7 +1303,7 @@ nghttp2_hd_nv nghttp2_hd_table_get(nghttp2_hd_context *context, size_t idx) {
|
||||
assert(INDEX_RANGE_VALID(context, idx));
|
||||
if (idx >= NGHTTP2_STATIC_TABLE_LENGTH) {
|
||||
return hd_ringbuf_get(&context->hd_table, idx - NGHTTP2_STATIC_TABLE_LENGTH)
|
||||
->nv;
|
||||
->nv;
|
||||
} else {
|
||||
const nghttp2_hd_static_entry *ent = &static_table[idx];
|
||||
nghttp2_hd_nv nv = {(nghttp2_rcbuf *)&ent->name,
|
||||
@@ -1330,7 +1319,7 @@ static const nghttp2_nv *nghttp2_hd_table_get2(nghttp2_hd_context *context,
|
||||
if (idx >= NGHTTP2_STATIC_TABLE_LENGTH) {
|
||||
return &hd_ringbuf_get(&context->hd_table,
|
||||
idx - NGHTTP2_STATIC_TABLE_LENGTH)
|
||||
->cnv;
|
||||
->cnv;
|
||||
}
|
||||
|
||||
return &static_table[idx].cnv;
|
||||
@@ -1344,7 +1333,7 @@ static int hd_deflate_decide_indexing(nghttp2_hd_deflater *deflater,
|
||||
token == NGHTTP2_TOKEN_IF_NONE_MATCH || token == NGHTTP2_TOKEN_LOCATION ||
|
||||
token == NGHTTP2_TOKEN_SET_COOKIE ||
|
||||
entry_room(nv->namelen, nv->valuelen) >
|
||||
deflater->ctx.hd_table_bufsize_max * 3 / 4) {
|
||||
deflater->ctx.hd_table_bufsize_max * 3 / 4) {
|
||||
return NGHTTP2_HD_WITHOUT_INDEXING;
|
||||
}
|
||||
|
||||
@@ -1377,11 +1366,12 @@ static int deflate_nv(nghttp2_hd_deflater *deflater, nghttp2_bufs *bufs,
|
||||
entropy secret data (e.g., id/password). Also cookie header
|
||||
field with less than 20 bytes value is also never indexed. This
|
||||
is the same criteria used in Firefox codebase. */
|
||||
indexing_mode = token == NGHTTP2_TOKEN_AUTHORIZATION ||
|
||||
(token == NGHTTP2_TOKEN_COOKIE && nv->valuelen < 20) ||
|
||||
(nv->flags & NGHTTP2_NV_FLAG_NO_INDEX)
|
||||
? NGHTTP2_HD_NEVER_INDEXING
|
||||
: hd_deflate_decide_indexing(deflater, nv, token);
|
||||
indexing_mode =
|
||||
token == NGHTTP2_TOKEN_AUTHORIZATION ||
|
||||
(token == NGHTTP2_TOKEN_COOKIE && nv->valuelen < 20) ||
|
||||
(nv->flags & NGHTTP2_NV_FLAG_NO_INDEX)
|
||||
? NGHTTP2_HD_NEVER_INDEXING
|
||||
: hd_deflate_decide_indexing(deflater, nv, token);
|
||||
|
||||
res = search_hd_table(&deflater->ctx, nv, token, indexing_mode,
|
||||
&deflater->map, hash);
|
||||
@@ -1389,6 +1379,7 @@ static int deflate_nv(nghttp2_hd_deflater *deflater, nghttp2_bufs *bufs,
|
||||
idx = res.index;
|
||||
|
||||
if (res.name_value_match) {
|
||||
|
||||
DEBUGF("deflatehd: name/value match index=%td\n", idx);
|
||||
|
||||
rv = emit_indexed_block(bufs, (size_t)idx);
|
||||
@@ -1466,6 +1457,7 @@ int nghttp2_hd_deflate_hd_bufs(nghttp2_hd_deflater *deflater,
|
||||
deflater->min_hd_table_bufsize_max = UINT32_MAX;
|
||||
|
||||
if (deflater->ctx.hd_table_bufsize_max > min_hd_table_bufsize_max) {
|
||||
|
||||
rv = emit_table_size(bufs, min_hd_table_bufsize_max);
|
||||
|
||||
if (rv != 0) {
|
||||
@@ -1969,9 +1961,9 @@ nghttp2_ssize nghttp2_hd_inflate_hd_nv(nghttp2_hd_inflater *inflater,
|
||||
case NGHTTP2_HD_STATE_READ_TABLE_SIZE:
|
||||
rfin = 0;
|
||||
rv = hd_inflate_read_len(
|
||||
inflater, &rfin, in, last, 5,
|
||||
nghttp2_min_size(inflater->min_hd_table_bufsize_max,
|
||||
inflater->settings_hd_table_bufsize_max));
|
||||
inflater, &rfin, in, last, 5,
|
||||
nghttp2_min_size(inflater->min_hd_table_bufsize_max,
|
||||
inflater->settings_hd_table_bufsize_max));
|
||||
if (rv < 0) {
|
||||
goto fail;
|
||||
}
|
||||
@@ -2058,8 +2050,8 @@ nghttp2_ssize nghttp2_hd_inflate_hd_nv(nghttp2_hd_inflater *inflater,
|
||||
|
||||
inflater->state = NGHTTP2_HD_STATE_NEWNAME_READ_NAMEHUFF;
|
||||
|
||||
rv =
|
||||
nghttp2_rcbuf_new(&inflater->namercbuf, inflater->left * 2 + 1, mem);
|
||||
rv = nghttp2_rcbuf_new(&inflater->namercbuf, inflater->left * 2 + 1,
|
||||
mem);
|
||||
} else {
|
||||
inflater->state = NGHTTP2_HD_STATE_NEWNAME_READ_NAME;
|
||||
rv = nghttp2_rcbuf_new(&inflater->namercbuf, inflater->left + 1, mem);
|
||||
@@ -2143,8 +2135,8 @@ nghttp2_ssize nghttp2_hd_inflate_hd_nv(nghttp2_hd_inflater *inflater,
|
||||
|
||||
inflater->state = NGHTTP2_HD_STATE_READ_VALUEHUFF;
|
||||
|
||||
rv =
|
||||
nghttp2_rcbuf_new(&inflater->valuercbuf, inflater->left * 2 + 1, mem);
|
||||
rv = nghttp2_rcbuf_new(&inflater->valuercbuf, inflater->left * 2 + 1,
|
||||
mem);
|
||||
} else {
|
||||
inflater->state = NGHTTP2_HD_STATE_READ_VALUE;
|
||||
|
||||
@@ -2315,6 +2307,7 @@ void nghttp2_hd_inflate_del(nghttp2_hd_inflater *inflater) {
|
||||
|
||||
int nghttp2_hd_emit_indname_block(nghttp2_bufs *bufs, size_t idx,
|
||||
nghttp2_nv *nv, int indexing_mode) {
|
||||
|
||||
return emit_indname_block(bufs, idx, nv, indexing_mode);
|
||||
}
|
||||
|
||||
|
||||
@@ -94,7 +94,7 @@ int nghttp2_hd_huff_encode(nghttp2_bufs *bufs, const uint8_t *src,
|
||||
|
||||
if (nbits) {
|
||||
rv = nghttp2_bufs_addb(
|
||||
bufs, (uint8_t)((uint8_t)(code >> 56) | ((1 << (8 - nbits)) - 1)));
|
||||
bufs, (uint8_t)((uint8_t)(code >> 56) | ((1 << (8 - nbits)) - 1)));
|
||||
if (rv != 0) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -53,70 +53,70 @@ uint32_t nghttp2_get_uint32(const uint8_t *data) {
|
||||
|
||||
/* Generated by gendowncasetbl.py */
|
||||
static const uint8_t DOWNCASE_TBL[] = {
|
||||
0 /* NUL */, 1 /* SOH */, 2 /* STX */, 3 /* ETX */,
|
||||
4 /* EOT */, 5 /* ENQ */, 6 /* ACK */, 7 /* BEL */,
|
||||
8 /* BS */, 9 /* HT */, 10 /* LF */, 11 /* VT */,
|
||||
12 /* FF */, 13 /* CR */, 14 /* SO */, 15 /* SI */,
|
||||
16 /* DLE */, 17 /* DC1 */, 18 /* DC2 */, 19 /* DC3 */,
|
||||
20 /* DC4 */, 21 /* NAK */, 22 /* SYN */, 23 /* ETB */,
|
||||
24 /* CAN */, 25 /* EM */, 26 /* SUB */, 27 /* ESC */,
|
||||
28 /* FS */, 29 /* GS */, 30 /* RS */, 31 /* US */,
|
||||
32 /* SPC */, 33 /* ! */, 34 /* " */, 35 /* # */,
|
||||
36 /* $ */, 37 /* % */, 38 /* & */, 39 /* ' */,
|
||||
40 /* ( */, 41 /* ) */, 42 /* * */, 43 /* + */,
|
||||
44 /* , */, 45 /* - */, 46 /* . */, 47 /* / */,
|
||||
48 /* 0 */, 49 /* 1 */, 50 /* 2 */, 51 /* 3 */,
|
||||
52 /* 4 */, 53 /* 5 */, 54 /* 6 */, 55 /* 7 */,
|
||||
56 /* 8 */, 57 /* 9 */, 58 /* : */, 59 /* ; */,
|
||||
60 /* < */, 61 /* = */, 62 /* > */, 63 /* ? */,
|
||||
64 /* @ */, 97 /* A */, 98 /* B */, 99 /* C */,
|
||||
100 /* D */, 101 /* E */, 102 /* F */, 103 /* G */,
|
||||
104 /* H */, 105 /* I */, 106 /* J */, 107 /* K */,
|
||||
108 /* L */, 109 /* M */, 110 /* N */, 111 /* O */,
|
||||
112 /* P */, 113 /* Q */, 114 /* R */, 115 /* S */,
|
||||
116 /* T */, 117 /* U */, 118 /* V */, 119 /* W */,
|
||||
120 /* X */, 121 /* Y */, 122 /* Z */, 91 /* [ */,
|
||||
92 /* \ */, 93 /* ] */, 94 /* ^ */, 95 /* _ */,
|
||||
96 /* ` */, 97 /* a */, 98 /* b */, 99 /* c */,
|
||||
100 /* d */, 101 /* e */, 102 /* f */, 103 /* g */,
|
||||
104 /* h */, 105 /* i */, 106 /* j */, 107 /* k */,
|
||||
108 /* l */, 109 /* m */, 110 /* n */, 111 /* o */,
|
||||
112 /* p */, 113 /* q */, 114 /* r */, 115 /* s */,
|
||||
116 /* t */, 117 /* u */, 118 /* v */, 119 /* w */,
|
||||
120 /* x */, 121 /* y */, 122 /* z */, 123 /* { */,
|
||||
124 /* | */, 125 /* } */, 126 /* ~ */, 127 /* DEL */,
|
||||
128 /* 0x80 */, 129 /* 0x81 */, 130 /* 0x82 */, 131 /* 0x83 */,
|
||||
132 /* 0x84 */, 133 /* 0x85 */, 134 /* 0x86 */, 135 /* 0x87 */,
|
||||
136 /* 0x88 */, 137 /* 0x89 */, 138 /* 0x8a */, 139 /* 0x8b */,
|
||||
140 /* 0x8c */, 141 /* 0x8d */, 142 /* 0x8e */, 143 /* 0x8f */,
|
||||
144 /* 0x90 */, 145 /* 0x91 */, 146 /* 0x92 */, 147 /* 0x93 */,
|
||||
148 /* 0x94 */, 149 /* 0x95 */, 150 /* 0x96 */, 151 /* 0x97 */,
|
||||
152 /* 0x98 */, 153 /* 0x99 */, 154 /* 0x9a */, 155 /* 0x9b */,
|
||||
156 /* 0x9c */, 157 /* 0x9d */, 158 /* 0x9e */, 159 /* 0x9f */,
|
||||
160 /* 0xa0 */, 161 /* 0xa1 */, 162 /* 0xa2 */, 163 /* 0xa3 */,
|
||||
164 /* 0xa4 */, 165 /* 0xa5 */, 166 /* 0xa6 */, 167 /* 0xa7 */,
|
||||
168 /* 0xa8 */, 169 /* 0xa9 */, 170 /* 0xaa */, 171 /* 0xab */,
|
||||
172 /* 0xac */, 173 /* 0xad */, 174 /* 0xae */, 175 /* 0xaf */,
|
||||
176 /* 0xb0 */, 177 /* 0xb1 */, 178 /* 0xb2 */, 179 /* 0xb3 */,
|
||||
180 /* 0xb4 */, 181 /* 0xb5 */, 182 /* 0xb6 */, 183 /* 0xb7 */,
|
||||
184 /* 0xb8 */, 185 /* 0xb9 */, 186 /* 0xba */, 187 /* 0xbb */,
|
||||
188 /* 0xbc */, 189 /* 0xbd */, 190 /* 0xbe */, 191 /* 0xbf */,
|
||||
192 /* 0xc0 */, 193 /* 0xc1 */, 194 /* 0xc2 */, 195 /* 0xc3 */,
|
||||
196 /* 0xc4 */, 197 /* 0xc5 */, 198 /* 0xc6 */, 199 /* 0xc7 */,
|
||||
200 /* 0xc8 */, 201 /* 0xc9 */, 202 /* 0xca */, 203 /* 0xcb */,
|
||||
204 /* 0xcc */, 205 /* 0xcd */, 206 /* 0xce */, 207 /* 0xcf */,
|
||||
208 /* 0xd0 */, 209 /* 0xd1 */, 210 /* 0xd2 */, 211 /* 0xd3 */,
|
||||
212 /* 0xd4 */, 213 /* 0xd5 */, 214 /* 0xd6 */, 215 /* 0xd7 */,
|
||||
216 /* 0xd8 */, 217 /* 0xd9 */, 218 /* 0xda */, 219 /* 0xdb */,
|
||||
220 /* 0xdc */, 221 /* 0xdd */, 222 /* 0xde */, 223 /* 0xdf */,
|
||||
224 /* 0xe0 */, 225 /* 0xe1 */, 226 /* 0xe2 */, 227 /* 0xe3 */,
|
||||
228 /* 0xe4 */, 229 /* 0xe5 */, 230 /* 0xe6 */, 231 /* 0xe7 */,
|
||||
232 /* 0xe8 */, 233 /* 0xe9 */, 234 /* 0xea */, 235 /* 0xeb */,
|
||||
236 /* 0xec */, 237 /* 0xed */, 238 /* 0xee */, 239 /* 0xef */,
|
||||
240 /* 0xf0 */, 241 /* 0xf1 */, 242 /* 0xf2 */, 243 /* 0xf3 */,
|
||||
244 /* 0xf4 */, 245 /* 0xf5 */, 246 /* 0xf6 */, 247 /* 0xf7 */,
|
||||
248 /* 0xf8 */, 249 /* 0xf9 */, 250 /* 0xfa */, 251 /* 0xfb */,
|
||||
252 /* 0xfc */, 253 /* 0xfd */, 254 /* 0xfe */, 255 /* 0xff */,
|
||||
0 /* NUL */, 1 /* SOH */, 2 /* STX */, 3 /* ETX */,
|
||||
4 /* EOT */, 5 /* ENQ */, 6 /* ACK */, 7 /* BEL */,
|
||||
8 /* BS */, 9 /* HT */, 10 /* LF */, 11 /* VT */,
|
||||
12 /* FF */, 13 /* CR */, 14 /* SO */, 15 /* SI */,
|
||||
16 /* DLE */, 17 /* DC1 */, 18 /* DC2 */, 19 /* DC3 */,
|
||||
20 /* DC4 */, 21 /* NAK */, 22 /* SYN */, 23 /* ETB */,
|
||||
24 /* CAN */, 25 /* EM */, 26 /* SUB */, 27 /* ESC */,
|
||||
28 /* FS */, 29 /* GS */, 30 /* RS */, 31 /* US */,
|
||||
32 /* SPC */, 33 /* ! */, 34 /* " */, 35 /* # */,
|
||||
36 /* $ */, 37 /* % */, 38 /* & */, 39 /* ' */,
|
||||
40 /* ( */, 41 /* ) */, 42 /* * */, 43 /* + */,
|
||||
44 /* , */, 45 /* - */, 46 /* . */, 47 /* / */,
|
||||
48 /* 0 */, 49 /* 1 */, 50 /* 2 */, 51 /* 3 */,
|
||||
52 /* 4 */, 53 /* 5 */, 54 /* 6 */, 55 /* 7 */,
|
||||
56 /* 8 */, 57 /* 9 */, 58 /* : */, 59 /* ; */,
|
||||
60 /* < */, 61 /* = */, 62 /* > */, 63 /* ? */,
|
||||
64 /* @ */, 97 /* A */, 98 /* B */, 99 /* C */,
|
||||
100 /* D */, 101 /* E */, 102 /* F */, 103 /* G */,
|
||||
104 /* H */, 105 /* I */, 106 /* J */, 107 /* K */,
|
||||
108 /* L */, 109 /* M */, 110 /* N */, 111 /* O */,
|
||||
112 /* P */, 113 /* Q */, 114 /* R */, 115 /* S */,
|
||||
116 /* T */, 117 /* U */, 118 /* V */, 119 /* W */,
|
||||
120 /* X */, 121 /* Y */, 122 /* Z */, 91 /* [ */,
|
||||
92 /* \ */, 93 /* ] */, 94 /* ^ */, 95 /* _ */,
|
||||
96 /* ` */, 97 /* a */, 98 /* b */, 99 /* c */,
|
||||
100 /* d */, 101 /* e */, 102 /* f */, 103 /* g */,
|
||||
104 /* h */, 105 /* i */, 106 /* j */, 107 /* k */,
|
||||
108 /* l */, 109 /* m */, 110 /* n */, 111 /* o */,
|
||||
112 /* p */, 113 /* q */, 114 /* r */, 115 /* s */,
|
||||
116 /* t */, 117 /* u */, 118 /* v */, 119 /* w */,
|
||||
120 /* x */, 121 /* y */, 122 /* z */, 123 /* { */,
|
||||
124 /* | */, 125 /* } */, 126 /* ~ */, 127 /* DEL */,
|
||||
128 /* 0x80 */, 129 /* 0x81 */, 130 /* 0x82 */, 131 /* 0x83 */,
|
||||
132 /* 0x84 */, 133 /* 0x85 */, 134 /* 0x86 */, 135 /* 0x87 */,
|
||||
136 /* 0x88 */, 137 /* 0x89 */, 138 /* 0x8a */, 139 /* 0x8b */,
|
||||
140 /* 0x8c */, 141 /* 0x8d */, 142 /* 0x8e */, 143 /* 0x8f */,
|
||||
144 /* 0x90 */, 145 /* 0x91 */, 146 /* 0x92 */, 147 /* 0x93 */,
|
||||
148 /* 0x94 */, 149 /* 0x95 */, 150 /* 0x96 */, 151 /* 0x97 */,
|
||||
152 /* 0x98 */, 153 /* 0x99 */, 154 /* 0x9a */, 155 /* 0x9b */,
|
||||
156 /* 0x9c */, 157 /* 0x9d */, 158 /* 0x9e */, 159 /* 0x9f */,
|
||||
160 /* 0xa0 */, 161 /* 0xa1 */, 162 /* 0xa2 */, 163 /* 0xa3 */,
|
||||
164 /* 0xa4 */, 165 /* 0xa5 */, 166 /* 0xa6 */, 167 /* 0xa7 */,
|
||||
168 /* 0xa8 */, 169 /* 0xa9 */, 170 /* 0xaa */, 171 /* 0xab */,
|
||||
172 /* 0xac */, 173 /* 0xad */, 174 /* 0xae */, 175 /* 0xaf */,
|
||||
176 /* 0xb0 */, 177 /* 0xb1 */, 178 /* 0xb2 */, 179 /* 0xb3 */,
|
||||
180 /* 0xb4 */, 181 /* 0xb5 */, 182 /* 0xb6 */, 183 /* 0xb7 */,
|
||||
184 /* 0xb8 */, 185 /* 0xb9 */, 186 /* 0xba */, 187 /* 0xbb */,
|
||||
188 /* 0xbc */, 189 /* 0xbd */, 190 /* 0xbe */, 191 /* 0xbf */,
|
||||
192 /* 0xc0 */, 193 /* 0xc1 */, 194 /* 0xc2 */, 195 /* 0xc3 */,
|
||||
196 /* 0xc4 */, 197 /* 0xc5 */, 198 /* 0xc6 */, 199 /* 0xc7 */,
|
||||
200 /* 0xc8 */, 201 /* 0xc9 */, 202 /* 0xca */, 203 /* 0xcb */,
|
||||
204 /* 0xcc */, 205 /* 0xcd */, 206 /* 0xce */, 207 /* 0xcf */,
|
||||
208 /* 0xd0 */, 209 /* 0xd1 */, 210 /* 0xd2 */, 211 /* 0xd3 */,
|
||||
212 /* 0xd4 */, 213 /* 0xd5 */, 214 /* 0xd6 */, 215 /* 0xd7 */,
|
||||
216 /* 0xd8 */, 217 /* 0xd9 */, 218 /* 0xda */, 219 /* 0xdb */,
|
||||
220 /* 0xdc */, 221 /* 0xdd */, 222 /* 0xde */, 223 /* 0xdf */,
|
||||
224 /* 0xe0 */, 225 /* 0xe1 */, 226 /* 0xe2 */, 227 /* 0xe3 */,
|
||||
228 /* 0xe4 */, 229 /* 0xe5 */, 230 /* 0xe6 */, 231 /* 0xe7 */,
|
||||
232 /* 0xe8 */, 233 /* 0xe9 */, 234 /* 0xea */, 235 /* 0xeb */,
|
||||
236 /* 0xec */, 237 /* 0xed */, 238 /* 0xee */, 239 /* 0xef */,
|
||||
240 /* 0xf0 */, 241 /* 0xf1 */, 242 /* 0xf2 */, 243 /* 0xf3 */,
|
||||
244 /* 0xf4 */, 245 /* 0xf5 */, 246 /* 0xf6 */, 247 /* 0xf7 */,
|
||||
248 /* 0xf8 */, 249 /* 0xf9 */, 250 /* 0xfa */, 251 /* 0xfb */,
|
||||
252 /* 0xfc */, 253 /* 0xfd */, 254 /* 0xfe */, 255 /* 0xff */,
|
||||
};
|
||||
|
||||
void nghttp2_downcase(uint8_t *s, size_t len) {
|
||||
@@ -160,7 +160,7 @@ int nghttp2_adjust_local_window_size(int32_t *local_window_size_ptr,
|
||||
int32_t recv_reduction_delta;
|
||||
int32_t delta;
|
||||
int32_t new_recv_window_size =
|
||||
nghttp2_max_int32(0, *recv_window_size_ptr) - *delta_ptr;
|
||||
nghttp2_max_int32(0, *recv_window_size_ptr) - *delta_ptr;
|
||||
|
||||
if (new_recv_window_size >= 0) {
|
||||
*recv_window_size_ptr = new_recv_window_size;
|
||||
@@ -345,70 +345,70 @@ const char *nghttp2_strerror(int error_code) {
|
||||
|
||||
/* Generated by gennmchartbl.py */
|
||||
static const int VALID_HD_NAME_CHARS[] = {
|
||||
0 /* NUL */, 0 /* SOH */, 0 /* STX */, 0 /* ETX */,
|
||||
0 /* EOT */, 0 /* ENQ */, 0 /* ACK */, 0 /* BEL */,
|
||||
0 /* BS */, 0 /* HT */, 0 /* LF */, 0 /* VT */,
|
||||
0 /* FF */, 0 /* CR */, 0 /* SO */, 0 /* SI */,
|
||||
0 /* DLE */, 0 /* DC1 */, 0 /* DC2 */, 0 /* DC3 */,
|
||||
0 /* DC4 */, 0 /* NAK */, 0 /* SYN */, 0 /* ETB */,
|
||||
0 /* CAN */, 0 /* EM */, 0 /* SUB */, 0 /* ESC */,
|
||||
0 /* FS */, 0 /* GS */, 0 /* RS */, 0 /* US */,
|
||||
0 /* SPC */, 1 /* ! */, 0 /* " */, 1 /* # */,
|
||||
1 /* $ */, 1 /* % */, 1 /* & */, 1 /* ' */,
|
||||
0 /* ( */, 0 /* ) */, 1 /* * */, 1 /* + */,
|
||||
0 /* , */, 1 /* - */, 1 /* . */, 0 /* / */,
|
||||
1 /* 0 */, 1 /* 1 */, 1 /* 2 */, 1 /* 3 */,
|
||||
1 /* 4 */, 1 /* 5 */, 1 /* 6 */, 1 /* 7 */,
|
||||
1 /* 8 */, 1 /* 9 */, 0 /* : */, 0 /* ; */,
|
||||
0 /* < */, 0 /* = */, 0 /* > */, 0 /* ? */,
|
||||
0 /* @ */, 0 /* A */, 0 /* B */, 0 /* C */,
|
||||
0 /* D */, 0 /* E */, 0 /* F */, 0 /* G */,
|
||||
0 /* H */, 0 /* I */, 0 /* J */, 0 /* K */,
|
||||
0 /* L */, 0 /* M */, 0 /* N */, 0 /* O */,
|
||||
0 /* P */, 0 /* Q */, 0 /* R */, 0 /* S */,
|
||||
0 /* T */, 0 /* U */, 0 /* V */, 0 /* W */,
|
||||
0 /* X */, 0 /* Y */, 0 /* Z */, 0 /* [ */,
|
||||
0 /* \ */, 0 /* ] */, 1 /* ^ */, 1 /* _ */,
|
||||
1 /* ` */, 1 /* a */, 1 /* b */, 1 /* c */,
|
||||
1 /* d */, 1 /* e */, 1 /* f */, 1 /* g */,
|
||||
1 /* h */, 1 /* i */, 1 /* j */, 1 /* k */,
|
||||
1 /* l */, 1 /* m */, 1 /* n */, 1 /* o */,
|
||||
1 /* p */, 1 /* q */, 1 /* r */, 1 /* s */,
|
||||
1 /* t */, 1 /* u */, 1 /* v */, 1 /* w */,
|
||||
1 /* x */, 1 /* y */, 1 /* z */, 0 /* { */,
|
||||
1 /* | */, 0 /* } */, 1 /* ~ */, 0 /* DEL */,
|
||||
0 /* 0x80 */, 0 /* 0x81 */, 0 /* 0x82 */, 0 /* 0x83 */,
|
||||
0 /* 0x84 */, 0 /* 0x85 */, 0 /* 0x86 */, 0 /* 0x87 */,
|
||||
0 /* 0x88 */, 0 /* 0x89 */, 0 /* 0x8a */, 0 /* 0x8b */,
|
||||
0 /* 0x8c */, 0 /* 0x8d */, 0 /* 0x8e */, 0 /* 0x8f */,
|
||||
0 /* 0x90 */, 0 /* 0x91 */, 0 /* 0x92 */, 0 /* 0x93 */,
|
||||
0 /* 0x94 */, 0 /* 0x95 */, 0 /* 0x96 */, 0 /* 0x97 */,
|
||||
0 /* 0x98 */, 0 /* 0x99 */, 0 /* 0x9a */, 0 /* 0x9b */,
|
||||
0 /* 0x9c */, 0 /* 0x9d */, 0 /* 0x9e */, 0 /* 0x9f */,
|
||||
0 /* 0xa0 */, 0 /* 0xa1 */, 0 /* 0xa2 */, 0 /* 0xa3 */,
|
||||
0 /* 0xa4 */, 0 /* 0xa5 */, 0 /* 0xa6 */, 0 /* 0xa7 */,
|
||||
0 /* 0xa8 */, 0 /* 0xa9 */, 0 /* 0xaa */, 0 /* 0xab */,
|
||||
0 /* 0xac */, 0 /* 0xad */, 0 /* 0xae */, 0 /* 0xaf */,
|
||||
0 /* 0xb0 */, 0 /* 0xb1 */, 0 /* 0xb2 */, 0 /* 0xb3 */,
|
||||
0 /* 0xb4 */, 0 /* 0xb5 */, 0 /* 0xb6 */, 0 /* 0xb7 */,
|
||||
0 /* 0xb8 */, 0 /* 0xb9 */, 0 /* 0xba */, 0 /* 0xbb */,
|
||||
0 /* 0xbc */, 0 /* 0xbd */, 0 /* 0xbe */, 0 /* 0xbf */,
|
||||
0 /* 0xc0 */, 0 /* 0xc1 */, 0 /* 0xc2 */, 0 /* 0xc3 */,
|
||||
0 /* 0xc4 */, 0 /* 0xc5 */, 0 /* 0xc6 */, 0 /* 0xc7 */,
|
||||
0 /* 0xc8 */, 0 /* 0xc9 */, 0 /* 0xca */, 0 /* 0xcb */,
|
||||
0 /* 0xcc */, 0 /* 0xcd */, 0 /* 0xce */, 0 /* 0xcf */,
|
||||
0 /* 0xd0 */, 0 /* 0xd1 */, 0 /* 0xd2 */, 0 /* 0xd3 */,
|
||||
0 /* 0xd4 */, 0 /* 0xd5 */, 0 /* 0xd6 */, 0 /* 0xd7 */,
|
||||
0 /* 0xd8 */, 0 /* 0xd9 */, 0 /* 0xda */, 0 /* 0xdb */,
|
||||
0 /* 0xdc */, 0 /* 0xdd */, 0 /* 0xde */, 0 /* 0xdf */,
|
||||
0 /* 0xe0 */, 0 /* 0xe1 */, 0 /* 0xe2 */, 0 /* 0xe3 */,
|
||||
0 /* 0xe4 */, 0 /* 0xe5 */, 0 /* 0xe6 */, 0 /* 0xe7 */,
|
||||
0 /* 0xe8 */, 0 /* 0xe9 */, 0 /* 0xea */, 0 /* 0xeb */,
|
||||
0 /* 0xec */, 0 /* 0xed */, 0 /* 0xee */, 0 /* 0xef */,
|
||||
0 /* 0xf0 */, 0 /* 0xf1 */, 0 /* 0xf2 */, 0 /* 0xf3 */,
|
||||
0 /* 0xf4 */, 0 /* 0xf5 */, 0 /* 0xf6 */, 0 /* 0xf7 */,
|
||||
0 /* 0xf8 */, 0 /* 0xf9 */, 0 /* 0xfa */, 0 /* 0xfb */,
|
||||
0 /* 0xfc */, 0 /* 0xfd */, 0 /* 0xfe */, 0 /* 0xff */
|
||||
0 /* NUL */, 0 /* SOH */, 0 /* STX */, 0 /* ETX */,
|
||||
0 /* EOT */, 0 /* ENQ */, 0 /* ACK */, 0 /* BEL */,
|
||||
0 /* BS */, 0 /* HT */, 0 /* LF */, 0 /* VT */,
|
||||
0 /* FF */, 0 /* CR */, 0 /* SO */, 0 /* SI */,
|
||||
0 /* DLE */, 0 /* DC1 */, 0 /* DC2 */, 0 /* DC3 */,
|
||||
0 /* DC4 */, 0 /* NAK */, 0 /* SYN */, 0 /* ETB */,
|
||||
0 /* CAN */, 0 /* EM */, 0 /* SUB */, 0 /* ESC */,
|
||||
0 /* FS */, 0 /* GS */, 0 /* RS */, 0 /* US */,
|
||||
0 /* SPC */, 1 /* ! */, 0 /* " */, 1 /* # */,
|
||||
1 /* $ */, 1 /* % */, 1 /* & */, 1 /* ' */,
|
||||
0 /* ( */, 0 /* ) */, 1 /* * */, 1 /* + */,
|
||||
0 /* , */, 1 /* - */, 1 /* . */, 0 /* / */,
|
||||
1 /* 0 */, 1 /* 1 */, 1 /* 2 */, 1 /* 3 */,
|
||||
1 /* 4 */, 1 /* 5 */, 1 /* 6 */, 1 /* 7 */,
|
||||
1 /* 8 */, 1 /* 9 */, 0 /* : */, 0 /* ; */,
|
||||
0 /* < */, 0 /* = */, 0 /* > */, 0 /* ? */,
|
||||
0 /* @ */, 0 /* A */, 0 /* B */, 0 /* C */,
|
||||
0 /* D */, 0 /* E */, 0 /* F */, 0 /* G */,
|
||||
0 /* H */, 0 /* I */, 0 /* J */, 0 /* K */,
|
||||
0 /* L */, 0 /* M */, 0 /* N */, 0 /* O */,
|
||||
0 /* P */, 0 /* Q */, 0 /* R */, 0 /* S */,
|
||||
0 /* T */, 0 /* U */, 0 /* V */, 0 /* W */,
|
||||
0 /* X */, 0 /* Y */, 0 /* Z */, 0 /* [ */,
|
||||
0 /* \ */, 0 /* ] */, 1 /* ^ */, 1 /* _ */,
|
||||
1 /* ` */, 1 /* a */, 1 /* b */, 1 /* c */,
|
||||
1 /* d */, 1 /* e */, 1 /* f */, 1 /* g */,
|
||||
1 /* h */, 1 /* i */, 1 /* j */, 1 /* k */,
|
||||
1 /* l */, 1 /* m */, 1 /* n */, 1 /* o */,
|
||||
1 /* p */, 1 /* q */, 1 /* r */, 1 /* s */,
|
||||
1 /* t */, 1 /* u */, 1 /* v */, 1 /* w */,
|
||||
1 /* x */, 1 /* y */, 1 /* z */, 0 /* { */,
|
||||
1 /* | */, 0 /* } */, 1 /* ~ */, 0 /* DEL */,
|
||||
0 /* 0x80 */, 0 /* 0x81 */, 0 /* 0x82 */, 0 /* 0x83 */,
|
||||
0 /* 0x84 */, 0 /* 0x85 */, 0 /* 0x86 */, 0 /* 0x87 */,
|
||||
0 /* 0x88 */, 0 /* 0x89 */, 0 /* 0x8a */, 0 /* 0x8b */,
|
||||
0 /* 0x8c */, 0 /* 0x8d */, 0 /* 0x8e */, 0 /* 0x8f */,
|
||||
0 /* 0x90 */, 0 /* 0x91 */, 0 /* 0x92 */, 0 /* 0x93 */,
|
||||
0 /* 0x94 */, 0 /* 0x95 */, 0 /* 0x96 */, 0 /* 0x97 */,
|
||||
0 /* 0x98 */, 0 /* 0x99 */, 0 /* 0x9a */, 0 /* 0x9b */,
|
||||
0 /* 0x9c */, 0 /* 0x9d */, 0 /* 0x9e */, 0 /* 0x9f */,
|
||||
0 /* 0xa0 */, 0 /* 0xa1 */, 0 /* 0xa2 */, 0 /* 0xa3 */,
|
||||
0 /* 0xa4 */, 0 /* 0xa5 */, 0 /* 0xa6 */, 0 /* 0xa7 */,
|
||||
0 /* 0xa8 */, 0 /* 0xa9 */, 0 /* 0xaa */, 0 /* 0xab */,
|
||||
0 /* 0xac */, 0 /* 0xad */, 0 /* 0xae */, 0 /* 0xaf */,
|
||||
0 /* 0xb0 */, 0 /* 0xb1 */, 0 /* 0xb2 */, 0 /* 0xb3 */,
|
||||
0 /* 0xb4 */, 0 /* 0xb5 */, 0 /* 0xb6 */, 0 /* 0xb7 */,
|
||||
0 /* 0xb8 */, 0 /* 0xb9 */, 0 /* 0xba */, 0 /* 0xbb */,
|
||||
0 /* 0xbc */, 0 /* 0xbd */, 0 /* 0xbe */, 0 /* 0xbf */,
|
||||
0 /* 0xc0 */, 0 /* 0xc1 */, 0 /* 0xc2 */, 0 /* 0xc3 */,
|
||||
0 /* 0xc4 */, 0 /* 0xc5 */, 0 /* 0xc6 */, 0 /* 0xc7 */,
|
||||
0 /* 0xc8 */, 0 /* 0xc9 */, 0 /* 0xca */, 0 /* 0xcb */,
|
||||
0 /* 0xcc */, 0 /* 0xcd */, 0 /* 0xce */, 0 /* 0xcf */,
|
||||
0 /* 0xd0 */, 0 /* 0xd1 */, 0 /* 0xd2 */, 0 /* 0xd3 */,
|
||||
0 /* 0xd4 */, 0 /* 0xd5 */, 0 /* 0xd6 */, 0 /* 0xd7 */,
|
||||
0 /* 0xd8 */, 0 /* 0xd9 */, 0 /* 0xda */, 0 /* 0xdb */,
|
||||
0 /* 0xdc */, 0 /* 0xdd */, 0 /* 0xde */, 0 /* 0xdf */,
|
||||
0 /* 0xe0 */, 0 /* 0xe1 */, 0 /* 0xe2 */, 0 /* 0xe3 */,
|
||||
0 /* 0xe4 */, 0 /* 0xe5 */, 0 /* 0xe6 */, 0 /* 0xe7 */,
|
||||
0 /* 0xe8 */, 0 /* 0xe9 */, 0 /* 0xea */, 0 /* 0xeb */,
|
||||
0 /* 0xec */, 0 /* 0xed */, 0 /* 0xee */, 0 /* 0xef */,
|
||||
0 /* 0xf0 */, 0 /* 0xf1 */, 0 /* 0xf2 */, 0 /* 0xf3 */,
|
||||
0 /* 0xf4 */, 0 /* 0xf5 */, 0 /* 0xf6 */, 0 /* 0xf7 */,
|
||||
0 /* 0xf8 */, 0 /* 0xf9 */, 0 /* 0xfa */, 0 /* 0xfb */,
|
||||
0 /* 0xfc */, 0 /* 0xfd */, 0 /* 0xfe */, 0 /* 0xff */
|
||||
};
|
||||
|
||||
int nghttp2_check_header_name(const uint8_t *name, size_t len) {
|
||||
@@ -433,70 +433,70 @@ int nghttp2_check_header_name(const uint8_t *name, size_t len) {
|
||||
|
||||
/* Generated by genvchartbl.py */
|
||||
static const int VALID_HD_VALUE_CHARS[] = {
|
||||
0 /* NUL */, 0 /* SOH */, 0 /* STX */, 0 /* ETX */,
|
||||
0 /* EOT */, 0 /* ENQ */, 0 /* ACK */, 0 /* BEL */,
|
||||
0 /* BS */, 1 /* HT */, 0 /* LF */, 0 /* VT */,
|
||||
0 /* FF */, 0 /* CR */, 0 /* SO */, 0 /* SI */,
|
||||
0 /* DLE */, 0 /* DC1 */, 0 /* DC2 */, 0 /* DC3 */,
|
||||
0 /* DC4 */, 0 /* NAK */, 0 /* SYN */, 0 /* ETB */,
|
||||
0 /* CAN */, 0 /* EM */, 0 /* SUB */, 0 /* ESC */,
|
||||
0 /* FS */, 0 /* GS */, 0 /* RS */, 0 /* US */,
|
||||
1 /* SPC */, 1 /* ! */, 1 /* " */, 1 /* # */,
|
||||
1 /* $ */, 1 /* % */, 1 /* & */, 1 /* ' */,
|
||||
1 /* ( */, 1 /* ) */, 1 /* * */, 1 /* + */,
|
||||
1 /* , */, 1 /* - */, 1 /* . */, 1 /* / */,
|
||||
1 /* 0 */, 1 /* 1 */, 1 /* 2 */, 1 /* 3 */,
|
||||
1 /* 4 */, 1 /* 5 */, 1 /* 6 */, 1 /* 7 */,
|
||||
1 /* 8 */, 1 /* 9 */, 1 /* : */, 1 /* ; */,
|
||||
1 /* < */, 1 /* = */, 1 /* > */, 1 /* ? */,
|
||||
1 /* @ */, 1 /* A */, 1 /* B */, 1 /* C */,
|
||||
1 /* D */, 1 /* E */, 1 /* F */, 1 /* G */,
|
||||
1 /* H */, 1 /* I */, 1 /* J */, 1 /* K */,
|
||||
1 /* L */, 1 /* M */, 1 /* N */, 1 /* O */,
|
||||
1 /* P */, 1 /* Q */, 1 /* R */, 1 /* S */,
|
||||
1 /* T */, 1 /* U */, 1 /* V */, 1 /* W */,
|
||||
1 /* X */, 1 /* Y */, 1 /* Z */, 1 /* [ */,
|
||||
1 /* \ */, 1 /* ] */, 1 /* ^ */, 1 /* _ */,
|
||||
1 /* ` */, 1 /* a */, 1 /* b */, 1 /* c */,
|
||||
1 /* d */, 1 /* e */, 1 /* f */, 1 /* g */,
|
||||
1 /* h */, 1 /* i */, 1 /* j */, 1 /* k */,
|
||||
1 /* l */, 1 /* m */, 1 /* n */, 1 /* o */,
|
||||
1 /* p */, 1 /* q */, 1 /* r */, 1 /* s */,
|
||||
1 /* t */, 1 /* u */, 1 /* v */, 1 /* w */,
|
||||
1 /* x */, 1 /* y */, 1 /* z */, 1 /* { */,
|
||||
1 /* | */, 1 /* } */, 1 /* ~ */, 0 /* DEL */,
|
||||
1 /* 0x80 */, 1 /* 0x81 */, 1 /* 0x82 */, 1 /* 0x83 */,
|
||||
1 /* 0x84 */, 1 /* 0x85 */, 1 /* 0x86 */, 1 /* 0x87 */,
|
||||
1 /* 0x88 */, 1 /* 0x89 */, 1 /* 0x8a */, 1 /* 0x8b */,
|
||||
1 /* 0x8c */, 1 /* 0x8d */, 1 /* 0x8e */, 1 /* 0x8f */,
|
||||
1 /* 0x90 */, 1 /* 0x91 */, 1 /* 0x92 */, 1 /* 0x93 */,
|
||||
1 /* 0x94 */, 1 /* 0x95 */, 1 /* 0x96 */, 1 /* 0x97 */,
|
||||
1 /* 0x98 */, 1 /* 0x99 */, 1 /* 0x9a */, 1 /* 0x9b */,
|
||||
1 /* 0x9c */, 1 /* 0x9d */, 1 /* 0x9e */, 1 /* 0x9f */,
|
||||
1 /* 0xa0 */, 1 /* 0xa1 */, 1 /* 0xa2 */, 1 /* 0xa3 */,
|
||||
1 /* 0xa4 */, 1 /* 0xa5 */, 1 /* 0xa6 */, 1 /* 0xa7 */,
|
||||
1 /* 0xa8 */, 1 /* 0xa9 */, 1 /* 0xaa */, 1 /* 0xab */,
|
||||
1 /* 0xac */, 1 /* 0xad */, 1 /* 0xae */, 1 /* 0xaf */,
|
||||
1 /* 0xb0 */, 1 /* 0xb1 */, 1 /* 0xb2 */, 1 /* 0xb3 */,
|
||||
1 /* 0xb4 */, 1 /* 0xb5 */, 1 /* 0xb6 */, 1 /* 0xb7 */,
|
||||
1 /* 0xb8 */, 1 /* 0xb9 */, 1 /* 0xba */, 1 /* 0xbb */,
|
||||
1 /* 0xbc */, 1 /* 0xbd */, 1 /* 0xbe */, 1 /* 0xbf */,
|
||||
1 /* 0xc0 */, 1 /* 0xc1 */, 1 /* 0xc2 */, 1 /* 0xc3 */,
|
||||
1 /* 0xc4 */, 1 /* 0xc5 */, 1 /* 0xc6 */, 1 /* 0xc7 */,
|
||||
1 /* 0xc8 */, 1 /* 0xc9 */, 1 /* 0xca */, 1 /* 0xcb */,
|
||||
1 /* 0xcc */, 1 /* 0xcd */, 1 /* 0xce */, 1 /* 0xcf */,
|
||||
1 /* 0xd0 */, 1 /* 0xd1 */, 1 /* 0xd2 */, 1 /* 0xd3 */,
|
||||
1 /* 0xd4 */, 1 /* 0xd5 */, 1 /* 0xd6 */, 1 /* 0xd7 */,
|
||||
1 /* 0xd8 */, 1 /* 0xd9 */, 1 /* 0xda */, 1 /* 0xdb */,
|
||||
1 /* 0xdc */, 1 /* 0xdd */, 1 /* 0xde */, 1 /* 0xdf */,
|
||||
1 /* 0xe0 */, 1 /* 0xe1 */, 1 /* 0xe2 */, 1 /* 0xe3 */,
|
||||
1 /* 0xe4 */, 1 /* 0xe5 */, 1 /* 0xe6 */, 1 /* 0xe7 */,
|
||||
1 /* 0xe8 */, 1 /* 0xe9 */, 1 /* 0xea */, 1 /* 0xeb */,
|
||||
1 /* 0xec */, 1 /* 0xed */, 1 /* 0xee */, 1 /* 0xef */,
|
||||
1 /* 0xf0 */, 1 /* 0xf1 */, 1 /* 0xf2 */, 1 /* 0xf3 */,
|
||||
1 /* 0xf4 */, 1 /* 0xf5 */, 1 /* 0xf6 */, 1 /* 0xf7 */,
|
||||
1 /* 0xf8 */, 1 /* 0xf9 */, 1 /* 0xfa */, 1 /* 0xfb */,
|
||||
1 /* 0xfc */, 1 /* 0xfd */, 1 /* 0xfe */, 1 /* 0xff */
|
||||
0 /* NUL */, 0 /* SOH */, 0 /* STX */, 0 /* ETX */,
|
||||
0 /* EOT */, 0 /* ENQ */, 0 /* ACK */, 0 /* BEL */,
|
||||
0 /* BS */, 1 /* HT */, 0 /* LF */, 0 /* VT */,
|
||||
0 /* FF */, 0 /* CR */, 0 /* SO */, 0 /* SI */,
|
||||
0 /* DLE */, 0 /* DC1 */, 0 /* DC2 */, 0 /* DC3 */,
|
||||
0 /* DC4 */, 0 /* NAK */, 0 /* SYN */, 0 /* ETB */,
|
||||
0 /* CAN */, 0 /* EM */, 0 /* SUB */, 0 /* ESC */,
|
||||
0 /* FS */, 0 /* GS */, 0 /* RS */, 0 /* US */,
|
||||
1 /* SPC */, 1 /* ! */, 1 /* " */, 1 /* # */,
|
||||
1 /* $ */, 1 /* % */, 1 /* & */, 1 /* ' */,
|
||||
1 /* ( */, 1 /* ) */, 1 /* * */, 1 /* + */,
|
||||
1 /* , */, 1 /* - */, 1 /* . */, 1 /* / */,
|
||||
1 /* 0 */, 1 /* 1 */, 1 /* 2 */, 1 /* 3 */,
|
||||
1 /* 4 */, 1 /* 5 */, 1 /* 6 */, 1 /* 7 */,
|
||||
1 /* 8 */, 1 /* 9 */, 1 /* : */, 1 /* ; */,
|
||||
1 /* < */, 1 /* = */, 1 /* > */, 1 /* ? */,
|
||||
1 /* @ */, 1 /* A */, 1 /* B */, 1 /* C */,
|
||||
1 /* D */, 1 /* E */, 1 /* F */, 1 /* G */,
|
||||
1 /* H */, 1 /* I */, 1 /* J */, 1 /* K */,
|
||||
1 /* L */, 1 /* M */, 1 /* N */, 1 /* O */,
|
||||
1 /* P */, 1 /* Q */, 1 /* R */, 1 /* S */,
|
||||
1 /* T */, 1 /* U */, 1 /* V */, 1 /* W */,
|
||||
1 /* X */, 1 /* Y */, 1 /* Z */, 1 /* [ */,
|
||||
1 /* \ */, 1 /* ] */, 1 /* ^ */, 1 /* _ */,
|
||||
1 /* ` */, 1 /* a */, 1 /* b */, 1 /* c */,
|
||||
1 /* d */, 1 /* e */, 1 /* f */, 1 /* g */,
|
||||
1 /* h */, 1 /* i */, 1 /* j */, 1 /* k */,
|
||||
1 /* l */, 1 /* m */, 1 /* n */, 1 /* o */,
|
||||
1 /* p */, 1 /* q */, 1 /* r */, 1 /* s */,
|
||||
1 /* t */, 1 /* u */, 1 /* v */, 1 /* w */,
|
||||
1 /* x */, 1 /* y */, 1 /* z */, 1 /* { */,
|
||||
1 /* | */, 1 /* } */, 1 /* ~ */, 0 /* DEL */,
|
||||
1 /* 0x80 */, 1 /* 0x81 */, 1 /* 0x82 */, 1 /* 0x83 */,
|
||||
1 /* 0x84 */, 1 /* 0x85 */, 1 /* 0x86 */, 1 /* 0x87 */,
|
||||
1 /* 0x88 */, 1 /* 0x89 */, 1 /* 0x8a */, 1 /* 0x8b */,
|
||||
1 /* 0x8c */, 1 /* 0x8d */, 1 /* 0x8e */, 1 /* 0x8f */,
|
||||
1 /* 0x90 */, 1 /* 0x91 */, 1 /* 0x92 */, 1 /* 0x93 */,
|
||||
1 /* 0x94 */, 1 /* 0x95 */, 1 /* 0x96 */, 1 /* 0x97 */,
|
||||
1 /* 0x98 */, 1 /* 0x99 */, 1 /* 0x9a */, 1 /* 0x9b */,
|
||||
1 /* 0x9c */, 1 /* 0x9d */, 1 /* 0x9e */, 1 /* 0x9f */,
|
||||
1 /* 0xa0 */, 1 /* 0xa1 */, 1 /* 0xa2 */, 1 /* 0xa3 */,
|
||||
1 /* 0xa4 */, 1 /* 0xa5 */, 1 /* 0xa6 */, 1 /* 0xa7 */,
|
||||
1 /* 0xa8 */, 1 /* 0xa9 */, 1 /* 0xaa */, 1 /* 0xab */,
|
||||
1 /* 0xac */, 1 /* 0xad */, 1 /* 0xae */, 1 /* 0xaf */,
|
||||
1 /* 0xb0 */, 1 /* 0xb1 */, 1 /* 0xb2 */, 1 /* 0xb3 */,
|
||||
1 /* 0xb4 */, 1 /* 0xb5 */, 1 /* 0xb6 */, 1 /* 0xb7 */,
|
||||
1 /* 0xb8 */, 1 /* 0xb9 */, 1 /* 0xba */, 1 /* 0xbb */,
|
||||
1 /* 0xbc */, 1 /* 0xbd */, 1 /* 0xbe */, 1 /* 0xbf */,
|
||||
1 /* 0xc0 */, 1 /* 0xc1 */, 1 /* 0xc2 */, 1 /* 0xc3 */,
|
||||
1 /* 0xc4 */, 1 /* 0xc5 */, 1 /* 0xc6 */, 1 /* 0xc7 */,
|
||||
1 /* 0xc8 */, 1 /* 0xc9 */, 1 /* 0xca */, 1 /* 0xcb */,
|
||||
1 /* 0xcc */, 1 /* 0xcd */, 1 /* 0xce */, 1 /* 0xcf */,
|
||||
1 /* 0xd0 */, 1 /* 0xd1 */, 1 /* 0xd2 */, 1 /* 0xd3 */,
|
||||
1 /* 0xd4 */, 1 /* 0xd5 */, 1 /* 0xd6 */, 1 /* 0xd7 */,
|
||||
1 /* 0xd8 */, 1 /* 0xd9 */, 1 /* 0xda */, 1 /* 0xdb */,
|
||||
1 /* 0xdc */, 1 /* 0xdd */, 1 /* 0xde */, 1 /* 0xdf */,
|
||||
1 /* 0xe0 */, 1 /* 0xe1 */, 1 /* 0xe2 */, 1 /* 0xe3 */,
|
||||
1 /* 0xe4 */, 1 /* 0xe5 */, 1 /* 0xe6 */, 1 /* 0xe7 */,
|
||||
1 /* 0xe8 */, 1 /* 0xe9 */, 1 /* 0xea */, 1 /* 0xeb */,
|
||||
1 /* 0xec */, 1 /* 0xed */, 1 /* 0xee */, 1 /* 0xef */,
|
||||
1 /* 0xf0 */, 1 /* 0xf1 */, 1 /* 0xf2 */, 1 /* 0xf3 */,
|
||||
1 /* 0xf4 */, 1 /* 0xf5 */, 1 /* 0xf6 */, 1 /* 0xf7 */,
|
||||
1 /* 0xf8 */, 1 /* 0xf9 */, 1 /* 0xfa */, 1 /* 0xfb */,
|
||||
1 /* 0xfc */, 1 /* 0xfd */, 1 /* 0xfe */, 1 /* 0xff */
|
||||
};
|
||||
|
||||
int nghttp2_check_header_value(const uint8_t *value, size_t len) {
|
||||
@@ -524,70 +524,70 @@ int nghttp2_check_header_value_rfc9113(const uint8_t *value, size_t len) {
|
||||
|
||||
/* Generated by genmethodchartbl.py */
|
||||
static char VALID_METHOD_CHARS[] = {
|
||||
0 /* NUL */, 0 /* SOH */, 0 /* STX */, 0 /* ETX */,
|
||||
0 /* EOT */, 0 /* ENQ */, 0 /* ACK */, 0 /* BEL */,
|
||||
0 /* BS */, 0 /* HT */, 0 /* LF */, 0 /* VT */,
|
||||
0 /* FF */, 0 /* CR */, 0 /* SO */, 0 /* SI */,
|
||||
0 /* DLE */, 0 /* DC1 */, 0 /* DC2 */, 0 /* DC3 */,
|
||||
0 /* DC4 */, 0 /* NAK */, 0 /* SYN */, 0 /* ETB */,
|
||||
0 /* CAN */, 0 /* EM */, 0 /* SUB */, 0 /* ESC */,
|
||||
0 /* FS */, 0 /* GS */, 0 /* RS */, 0 /* US */,
|
||||
0 /* SPC */, 1 /* ! */, 0 /* " */, 1 /* # */,
|
||||
1 /* $ */, 1 /* % */, 1 /* & */, 1 /* ' */,
|
||||
0 /* ( */, 0 /* ) */, 1 /* * */, 1 /* + */,
|
||||
0 /* , */, 1 /* - */, 1 /* . */, 0 /* / */,
|
||||
1 /* 0 */, 1 /* 1 */, 1 /* 2 */, 1 /* 3 */,
|
||||
1 /* 4 */, 1 /* 5 */, 1 /* 6 */, 1 /* 7 */,
|
||||
1 /* 8 */, 1 /* 9 */, 0 /* : */, 0 /* ; */,
|
||||
0 /* < */, 0 /* = */, 0 /* > */, 0 /* ? */,
|
||||
0 /* @ */, 1 /* A */, 1 /* B */, 1 /* C */,
|
||||
1 /* D */, 1 /* E */, 1 /* F */, 1 /* G */,
|
||||
1 /* H */, 1 /* I */, 1 /* J */, 1 /* K */,
|
||||
1 /* L */, 1 /* M */, 1 /* N */, 1 /* O */,
|
||||
1 /* P */, 1 /* Q */, 1 /* R */, 1 /* S */,
|
||||
1 /* T */, 1 /* U */, 1 /* V */, 1 /* W */,
|
||||
1 /* X */, 1 /* Y */, 1 /* Z */, 0 /* [ */,
|
||||
0 /* \ */, 0 /* ] */, 1 /* ^ */, 1 /* _ */,
|
||||
1 /* ` */, 1 /* a */, 1 /* b */, 1 /* c */,
|
||||
1 /* d */, 1 /* e */, 1 /* f */, 1 /* g */,
|
||||
1 /* h */, 1 /* i */, 1 /* j */, 1 /* k */,
|
||||
1 /* l */, 1 /* m */, 1 /* n */, 1 /* o */,
|
||||
1 /* p */, 1 /* q */, 1 /* r */, 1 /* s */,
|
||||
1 /* t */, 1 /* u */, 1 /* v */, 1 /* w */,
|
||||
1 /* x */, 1 /* y */, 1 /* z */, 0 /* { */,
|
||||
1 /* | */, 0 /* } */, 1 /* ~ */, 0 /* DEL */,
|
||||
0 /* 0x80 */, 0 /* 0x81 */, 0 /* 0x82 */, 0 /* 0x83 */,
|
||||
0 /* 0x84 */, 0 /* 0x85 */, 0 /* 0x86 */, 0 /* 0x87 */,
|
||||
0 /* 0x88 */, 0 /* 0x89 */, 0 /* 0x8a */, 0 /* 0x8b */,
|
||||
0 /* 0x8c */, 0 /* 0x8d */, 0 /* 0x8e */, 0 /* 0x8f */,
|
||||
0 /* 0x90 */, 0 /* 0x91 */, 0 /* 0x92 */, 0 /* 0x93 */,
|
||||
0 /* 0x94 */, 0 /* 0x95 */, 0 /* 0x96 */, 0 /* 0x97 */,
|
||||
0 /* 0x98 */, 0 /* 0x99 */, 0 /* 0x9a */, 0 /* 0x9b */,
|
||||
0 /* 0x9c */, 0 /* 0x9d */, 0 /* 0x9e */, 0 /* 0x9f */,
|
||||
0 /* 0xa0 */, 0 /* 0xa1 */, 0 /* 0xa2 */, 0 /* 0xa3 */,
|
||||
0 /* 0xa4 */, 0 /* 0xa5 */, 0 /* 0xa6 */, 0 /* 0xa7 */,
|
||||
0 /* 0xa8 */, 0 /* 0xa9 */, 0 /* 0xaa */, 0 /* 0xab */,
|
||||
0 /* 0xac */, 0 /* 0xad */, 0 /* 0xae */, 0 /* 0xaf */,
|
||||
0 /* 0xb0 */, 0 /* 0xb1 */, 0 /* 0xb2 */, 0 /* 0xb3 */,
|
||||
0 /* 0xb4 */, 0 /* 0xb5 */, 0 /* 0xb6 */, 0 /* 0xb7 */,
|
||||
0 /* 0xb8 */, 0 /* 0xb9 */, 0 /* 0xba */, 0 /* 0xbb */,
|
||||
0 /* 0xbc */, 0 /* 0xbd */, 0 /* 0xbe */, 0 /* 0xbf */,
|
||||
0 /* 0xc0 */, 0 /* 0xc1 */, 0 /* 0xc2 */, 0 /* 0xc3 */,
|
||||
0 /* 0xc4 */, 0 /* 0xc5 */, 0 /* 0xc6 */, 0 /* 0xc7 */,
|
||||
0 /* 0xc8 */, 0 /* 0xc9 */, 0 /* 0xca */, 0 /* 0xcb */,
|
||||
0 /* 0xcc */, 0 /* 0xcd */, 0 /* 0xce */, 0 /* 0xcf */,
|
||||
0 /* 0xd0 */, 0 /* 0xd1 */, 0 /* 0xd2 */, 0 /* 0xd3 */,
|
||||
0 /* 0xd4 */, 0 /* 0xd5 */, 0 /* 0xd6 */, 0 /* 0xd7 */,
|
||||
0 /* 0xd8 */, 0 /* 0xd9 */, 0 /* 0xda */, 0 /* 0xdb */,
|
||||
0 /* 0xdc */, 0 /* 0xdd */, 0 /* 0xde */, 0 /* 0xdf */,
|
||||
0 /* 0xe0 */, 0 /* 0xe1 */, 0 /* 0xe2 */, 0 /* 0xe3 */,
|
||||
0 /* 0xe4 */, 0 /* 0xe5 */, 0 /* 0xe6 */, 0 /* 0xe7 */,
|
||||
0 /* 0xe8 */, 0 /* 0xe9 */, 0 /* 0xea */, 0 /* 0xeb */,
|
||||
0 /* 0xec */, 0 /* 0xed */, 0 /* 0xee */, 0 /* 0xef */,
|
||||
0 /* 0xf0 */, 0 /* 0xf1 */, 0 /* 0xf2 */, 0 /* 0xf3 */,
|
||||
0 /* 0xf4 */, 0 /* 0xf5 */, 0 /* 0xf6 */, 0 /* 0xf7 */,
|
||||
0 /* 0xf8 */, 0 /* 0xf9 */, 0 /* 0xfa */, 0 /* 0xfb */,
|
||||
0 /* 0xfc */, 0 /* 0xfd */, 0 /* 0xfe */, 0 /* 0xff */
|
||||
0 /* NUL */, 0 /* SOH */, 0 /* STX */, 0 /* ETX */,
|
||||
0 /* EOT */, 0 /* ENQ */, 0 /* ACK */, 0 /* BEL */,
|
||||
0 /* BS */, 0 /* HT */, 0 /* LF */, 0 /* VT */,
|
||||
0 /* FF */, 0 /* CR */, 0 /* SO */, 0 /* SI */,
|
||||
0 /* DLE */, 0 /* DC1 */, 0 /* DC2 */, 0 /* DC3 */,
|
||||
0 /* DC4 */, 0 /* NAK */, 0 /* SYN */, 0 /* ETB */,
|
||||
0 /* CAN */, 0 /* EM */, 0 /* SUB */, 0 /* ESC */,
|
||||
0 /* FS */, 0 /* GS */, 0 /* RS */, 0 /* US */,
|
||||
0 /* SPC */, 1 /* ! */, 0 /* " */, 1 /* # */,
|
||||
1 /* $ */, 1 /* % */, 1 /* & */, 1 /* ' */,
|
||||
0 /* ( */, 0 /* ) */, 1 /* * */, 1 /* + */,
|
||||
0 /* , */, 1 /* - */, 1 /* . */, 0 /* / */,
|
||||
1 /* 0 */, 1 /* 1 */, 1 /* 2 */, 1 /* 3 */,
|
||||
1 /* 4 */, 1 /* 5 */, 1 /* 6 */, 1 /* 7 */,
|
||||
1 /* 8 */, 1 /* 9 */, 0 /* : */, 0 /* ; */,
|
||||
0 /* < */, 0 /* = */, 0 /* > */, 0 /* ? */,
|
||||
0 /* @ */, 1 /* A */, 1 /* B */, 1 /* C */,
|
||||
1 /* D */, 1 /* E */, 1 /* F */, 1 /* G */,
|
||||
1 /* H */, 1 /* I */, 1 /* J */, 1 /* K */,
|
||||
1 /* L */, 1 /* M */, 1 /* N */, 1 /* O */,
|
||||
1 /* P */, 1 /* Q */, 1 /* R */, 1 /* S */,
|
||||
1 /* T */, 1 /* U */, 1 /* V */, 1 /* W */,
|
||||
1 /* X */, 1 /* Y */, 1 /* Z */, 0 /* [ */,
|
||||
0 /* \ */, 0 /* ] */, 1 /* ^ */, 1 /* _ */,
|
||||
1 /* ` */, 1 /* a */, 1 /* b */, 1 /* c */,
|
||||
1 /* d */, 1 /* e */, 1 /* f */, 1 /* g */,
|
||||
1 /* h */, 1 /* i */, 1 /* j */, 1 /* k */,
|
||||
1 /* l */, 1 /* m */, 1 /* n */, 1 /* o */,
|
||||
1 /* p */, 1 /* q */, 1 /* r */, 1 /* s */,
|
||||
1 /* t */, 1 /* u */, 1 /* v */, 1 /* w */,
|
||||
1 /* x */, 1 /* y */, 1 /* z */, 0 /* { */,
|
||||
1 /* | */, 0 /* } */, 1 /* ~ */, 0 /* DEL */,
|
||||
0 /* 0x80 */, 0 /* 0x81 */, 0 /* 0x82 */, 0 /* 0x83 */,
|
||||
0 /* 0x84 */, 0 /* 0x85 */, 0 /* 0x86 */, 0 /* 0x87 */,
|
||||
0 /* 0x88 */, 0 /* 0x89 */, 0 /* 0x8a */, 0 /* 0x8b */,
|
||||
0 /* 0x8c */, 0 /* 0x8d */, 0 /* 0x8e */, 0 /* 0x8f */,
|
||||
0 /* 0x90 */, 0 /* 0x91 */, 0 /* 0x92 */, 0 /* 0x93 */,
|
||||
0 /* 0x94 */, 0 /* 0x95 */, 0 /* 0x96 */, 0 /* 0x97 */,
|
||||
0 /* 0x98 */, 0 /* 0x99 */, 0 /* 0x9a */, 0 /* 0x9b */,
|
||||
0 /* 0x9c */, 0 /* 0x9d */, 0 /* 0x9e */, 0 /* 0x9f */,
|
||||
0 /* 0xa0 */, 0 /* 0xa1 */, 0 /* 0xa2 */, 0 /* 0xa3 */,
|
||||
0 /* 0xa4 */, 0 /* 0xa5 */, 0 /* 0xa6 */, 0 /* 0xa7 */,
|
||||
0 /* 0xa8 */, 0 /* 0xa9 */, 0 /* 0xaa */, 0 /* 0xab */,
|
||||
0 /* 0xac */, 0 /* 0xad */, 0 /* 0xae */, 0 /* 0xaf */,
|
||||
0 /* 0xb0 */, 0 /* 0xb1 */, 0 /* 0xb2 */, 0 /* 0xb3 */,
|
||||
0 /* 0xb4 */, 0 /* 0xb5 */, 0 /* 0xb6 */, 0 /* 0xb7 */,
|
||||
0 /* 0xb8 */, 0 /* 0xb9 */, 0 /* 0xba */, 0 /* 0xbb */,
|
||||
0 /* 0xbc */, 0 /* 0xbd */, 0 /* 0xbe */, 0 /* 0xbf */,
|
||||
0 /* 0xc0 */, 0 /* 0xc1 */, 0 /* 0xc2 */, 0 /* 0xc3 */,
|
||||
0 /* 0xc4 */, 0 /* 0xc5 */, 0 /* 0xc6 */, 0 /* 0xc7 */,
|
||||
0 /* 0xc8 */, 0 /* 0xc9 */, 0 /* 0xca */, 0 /* 0xcb */,
|
||||
0 /* 0xcc */, 0 /* 0xcd */, 0 /* 0xce */, 0 /* 0xcf */,
|
||||
0 /* 0xd0 */, 0 /* 0xd1 */, 0 /* 0xd2 */, 0 /* 0xd3 */,
|
||||
0 /* 0xd4 */, 0 /* 0xd5 */, 0 /* 0xd6 */, 0 /* 0xd7 */,
|
||||
0 /* 0xd8 */, 0 /* 0xd9 */, 0 /* 0xda */, 0 /* 0xdb */,
|
||||
0 /* 0xdc */, 0 /* 0xdd */, 0 /* 0xde */, 0 /* 0xdf */,
|
||||
0 /* 0xe0 */, 0 /* 0xe1 */, 0 /* 0xe2 */, 0 /* 0xe3 */,
|
||||
0 /* 0xe4 */, 0 /* 0xe5 */, 0 /* 0xe6 */, 0 /* 0xe7 */,
|
||||
0 /* 0xe8 */, 0 /* 0xe9 */, 0 /* 0xea */, 0 /* 0xeb */,
|
||||
0 /* 0xec */, 0 /* 0xed */, 0 /* 0xee */, 0 /* 0xef */,
|
||||
0 /* 0xf0 */, 0 /* 0xf1 */, 0 /* 0xf2 */, 0 /* 0xf3 */,
|
||||
0 /* 0xf4 */, 0 /* 0xf5 */, 0 /* 0xf6 */, 0 /* 0xf7 */,
|
||||
0 /* 0xf8 */, 0 /* 0xf9 */, 0 /* 0xfa */, 0 /* 0xfb */,
|
||||
0 /* 0xfc */, 0 /* 0xfd */, 0 /* 0xfe */, 0 /* 0xff */
|
||||
};
|
||||
|
||||
int nghttp2_check_method(const uint8_t *value, size_t len) {
|
||||
@@ -605,70 +605,70 @@ int nghttp2_check_method(const uint8_t *value, size_t len) {
|
||||
|
||||
/* Generated by genpathchartbl.py */
|
||||
static char VALID_PATH_CHARS[] = {
|
||||
0 /* NUL */, 0 /* SOH */, 0 /* STX */, 0 /* ETX */,
|
||||
0 /* EOT */, 0 /* ENQ */, 0 /* ACK */, 0 /* BEL */,
|
||||
0 /* BS */, 0 /* HT */, 0 /* LF */, 0 /* VT */,
|
||||
0 /* FF */, 0 /* CR */, 0 /* SO */, 0 /* SI */,
|
||||
0 /* DLE */, 0 /* DC1 */, 0 /* DC2 */, 0 /* DC3 */,
|
||||
0 /* DC4 */, 0 /* NAK */, 0 /* SYN */, 0 /* ETB */,
|
||||
0 /* CAN */, 0 /* EM */, 0 /* SUB */, 0 /* ESC */,
|
||||
0 /* FS */, 0 /* GS */, 0 /* RS */, 0 /* US */,
|
||||
0 /* SPC */, 1 /* ! */, 1 /* " */, 1 /* # */,
|
||||
1 /* $ */, 1 /* % */, 1 /* & */, 1 /* ' */,
|
||||
1 /* ( */, 1 /* ) */, 1 /* * */, 1 /* + */,
|
||||
1 /* , */, 1 /* - */, 1 /* . */, 1 /* / */,
|
||||
1 /* 0 */, 1 /* 1 */, 1 /* 2 */, 1 /* 3 */,
|
||||
1 /* 4 */, 1 /* 5 */, 1 /* 6 */, 1 /* 7 */,
|
||||
1 /* 8 */, 1 /* 9 */, 1 /* : */, 1 /* ; */,
|
||||
1 /* < */, 1 /* = */, 1 /* > */, 1 /* ? */,
|
||||
1 /* @ */, 1 /* A */, 1 /* B */, 1 /* C */,
|
||||
1 /* D */, 1 /* E */, 1 /* F */, 1 /* G */,
|
||||
1 /* H */, 1 /* I */, 1 /* J */, 1 /* K */,
|
||||
1 /* L */, 1 /* M */, 1 /* N */, 1 /* O */,
|
||||
1 /* P */, 1 /* Q */, 1 /* R */, 1 /* S */,
|
||||
1 /* T */, 1 /* U */, 1 /* V */, 1 /* W */,
|
||||
1 /* X */, 1 /* Y */, 1 /* Z */, 1 /* [ */,
|
||||
1 /* \ */, 1 /* ] */, 1 /* ^ */, 1 /* _ */,
|
||||
1 /* ` */, 1 /* a */, 1 /* b */, 1 /* c */,
|
||||
1 /* d */, 1 /* e */, 1 /* f */, 1 /* g */,
|
||||
1 /* h */, 1 /* i */, 1 /* j */, 1 /* k */,
|
||||
1 /* l */, 1 /* m */, 1 /* n */, 1 /* o */,
|
||||
1 /* p */, 1 /* q */, 1 /* r */, 1 /* s */,
|
||||
1 /* t */, 1 /* u */, 1 /* v */, 1 /* w */,
|
||||
1 /* x */, 1 /* y */, 1 /* z */, 1 /* { */,
|
||||
1 /* | */, 1 /* } */, 1 /* ~ */, 0 /* DEL */,
|
||||
1 /* 0x80 */, 1 /* 0x81 */, 1 /* 0x82 */, 1 /* 0x83 */,
|
||||
1 /* 0x84 */, 1 /* 0x85 */, 1 /* 0x86 */, 1 /* 0x87 */,
|
||||
1 /* 0x88 */, 1 /* 0x89 */, 1 /* 0x8a */, 1 /* 0x8b */,
|
||||
1 /* 0x8c */, 1 /* 0x8d */, 1 /* 0x8e */, 1 /* 0x8f */,
|
||||
1 /* 0x90 */, 1 /* 0x91 */, 1 /* 0x92 */, 1 /* 0x93 */,
|
||||
1 /* 0x94 */, 1 /* 0x95 */, 1 /* 0x96 */, 1 /* 0x97 */,
|
||||
1 /* 0x98 */, 1 /* 0x99 */, 1 /* 0x9a */, 1 /* 0x9b */,
|
||||
1 /* 0x9c */, 1 /* 0x9d */, 1 /* 0x9e */, 1 /* 0x9f */,
|
||||
1 /* 0xa0 */, 1 /* 0xa1 */, 1 /* 0xa2 */, 1 /* 0xa3 */,
|
||||
1 /* 0xa4 */, 1 /* 0xa5 */, 1 /* 0xa6 */, 1 /* 0xa7 */,
|
||||
1 /* 0xa8 */, 1 /* 0xa9 */, 1 /* 0xaa */, 1 /* 0xab */,
|
||||
1 /* 0xac */, 1 /* 0xad */, 1 /* 0xae */, 1 /* 0xaf */,
|
||||
1 /* 0xb0 */, 1 /* 0xb1 */, 1 /* 0xb2 */, 1 /* 0xb3 */,
|
||||
1 /* 0xb4 */, 1 /* 0xb5 */, 1 /* 0xb6 */, 1 /* 0xb7 */,
|
||||
1 /* 0xb8 */, 1 /* 0xb9 */, 1 /* 0xba */, 1 /* 0xbb */,
|
||||
1 /* 0xbc */, 1 /* 0xbd */, 1 /* 0xbe */, 1 /* 0xbf */,
|
||||
1 /* 0xc0 */, 1 /* 0xc1 */, 1 /* 0xc2 */, 1 /* 0xc3 */,
|
||||
1 /* 0xc4 */, 1 /* 0xc5 */, 1 /* 0xc6 */, 1 /* 0xc7 */,
|
||||
1 /* 0xc8 */, 1 /* 0xc9 */, 1 /* 0xca */, 1 /* 0xcb */,
|
||||
1 /* 0xcc */, 1 /* 0xcd */, 1 /* 0xce */, 1 /* 0xcf */,
|
||||
1 /* 0xd0 */, 1 /* 0xd1 */, 1 /* 0xd2 */, 1 /* 0xd3 */,
|
||||
1 /* 0xd4 */, 1 /* 0xd5 */, 1 /* 0xd6 */, 1 /* 0xd7 */,
|
||||
1 /* 0xd8 */, 1 /* 0xd9 */, 1 /* 0xda */, 1 /* 0xdb */,
|
||||
1 /* 0xdc */, 1 /* 0xdd */, 1 /* 0xde */, 1 /* 0xdf */,
|
||||
1 /* 0xe0 */, 1 /* 0xe1 */, 1 /* 0xe2 */, 1 /* 0xe3 */,
|
||||
1 /* 0xe4 */, 1 /* 0xe5 */, 1 /* 0xe6 */, 1 /* 0xe7 */,
|
||||
1 /* 0xe8 */, 1 /* 0xe9 */, 1 /* 0xea */, 1 /* 0xeb */,
|
||||
1 /* 0xec */, 1 /* 0xed */, 1 /* 0xee */, 1 /* 0xef */,
|
||||
1 /* 0xf0 */, 1 /* 0xf1 */, 1 /* 0xf2 */, 1 /* 0xf3 */,
|
||||
1 /* 0xf4 */, 1 /* 0xf5 */, 1 /* 0xf6 */, 1 /* 0xf7 */,
|
||||
1 /* 0xf8 */, 1 /* 0xf9 */, 1 /* 0xfa */, 1 /* 0xfb */,
|
||||
1 /* 0xfc */, 1 /* 0xfd */, 1 /* 0xfe */, 1 /* 0xff */
|
||||
0 /* NUL */, 0 /* SOH */, 0 /* STX */, 0 /* ETX */,
|
||||
0 /* EOT */, 0 /* ENQ */, 0 /* ACK */, 0 /* BEL */,
|
||||
0 /* BS */, 0 /* HT */, 0 /* LF */, 0 /* VT */,
|
||||
0 /* FF */, 0 /* CR */, 0 /* SO */, 0 /* SI */,
|
||||
0 /* DLE */, 0 /* DC1 */, 0 /* DC2 */, 0 /* DC3 */,
|
||||
0 /* DC4 */, 0 /* NAK */, 0 /* SYN */, 0 /* ETB */,
|
||||
0 /* CAN */, 0 /* EM */, 0 /* SUB */, 0 /* ESC */,
|
||||
0 /* FS */, 0 /* GS */, 0 /* RS */, 0 /* US */,
|
||||
0 /* SPC */, 1 /* ! */, 1 /* " */, 1 /* # */,
|
||||
1 /* $ */, 1 /* % */, 1 /* & */, 1 /* ' */,
|
||||
1 /* ( */, 1 /* ) */, 1 /* * */, 1 /* + */,
|
||||
1 /* , */, 1 /* - */, 1 /* . */, 1 /* / */,
|
||||
1 /* 0 */, 1 /* 1 */, 1 /* 2 */, 1 /* 3 */,
|
||||
1 /* 4 */, 1 /* 5 */, 1 /* 6 */, 1 /* 7 */,
|
||||
1 /* 8 */, 1 /* 9 */, 1 /* : */, 1 /* ; */,
|
||||
1 /* < */, 1 /* = */, 1 /* > */, 1 /* ? */,
|
||||
1 /* @ */, 1 /* A */, 1 /* B */, 1 /* C */,
|
||||
1 /* D */, 1 /* E */, 1 /* F */, 1 /* G */,
|
||||
1 /* H */, 1 /* I */, 1 /* J */, 1 /* K */,
|
||||
1 /* L */, 1 /* M */, 1 /* N */, 1 /* O */,
|
||||
1 /* P */, 1 /* Q */, 1 /* R */, 1 /* S */,
|
||||
1 /* T */, 1 /* U */, 1 /* V */, 1 /* W */,
|
||||
1 /* X */, 1 /* Y */, 1 /* Z */, 1 /* [ */,
|
||||
1 /* \ */, 1 /* ] */, 1 /* ^ */, 1 /* _ */,
|
||||
1 /* ` */, 1 /* a */, 1 /* b */, 1 /* c */,
|
||||
1 /* d */, 1 /* e */, 1 /* f */, 1 /* g */,
|
||||
1 /* h */, 1 /* i */, 1 /* j */, 1 /* k */,
|
||||
1 /* l */, 1 /* m */, 1 /* n */, 1 /* o */,
|
||||
1 /* p */, 1 /* q */, 1 /* r */, 1 /* s */,
|
||||
1 /* t */, 1 /* u */, 1 /* v */, 1 /* w */,
|
||||
1 /* x */, 1 /* y */, 1 /* z */, 1 /* { */,
|
||||
1 /* | */, 1 /* } */, 1 /* ~ */, 0 /* DEL */,
|
||||
1 /* 0x80 */, 1 /* 0x81 */, 1 /* 0x82 */, 1 /* 0x83 */,
|
||||
1 /* 0x84 */, 1 /* 0x85 */, 1 /* 0x86 */, 1 /* 0x87 */,
|
||||
1 /* 0x88 */, 1 /* 0x89 */, 1 /* 0x8a */, 1 /* 0x8b */,
|
||||
1 /* 0x8c */, 1 /* 0x8d */, 1 /* 0x8e */, 1 /* 0x8f */,
|
||||
1 /* 0x90 */, 1 /* 0x91 */, 1 /* 0x92 */, 1 /* 0x93 */,
|
||||
1 /* 0x94 */, 1 /* 0x95 */, 1 /* 0x96 */, 1 /* 0x97 */,
|
||||
1 /* 0x98 */, 1 /* 0x99 */, 1 /* 0x9a */, 1 /* 0x9b */,
|
||||
1 /* 0x9c */, 1 /* 0x9d */, 1 /* 0x9e */, 1 /* 0x9f */,
|
||||
1 /* 0xa0 */, 1 /* 0xa1 */, 1 /* 0xa2 */, 1 /* 0xa3 */,
|
||||
1 /* 0xa4 */, 1 /* 0xa5 */, 1 /* 0xa6 */, 1 /* 0xa7 */,
|
||||
1 /* 0xa8 */, 1 /* 0xa9 */, 1 /* 0xaa */, 1 /* 0xab */,
|
||||
1 /* 0xac */, 1 /* 0xad */, 1 /* 0xae */, 1 /* 0xaf */,
|
||||
1 /* 0xb0 */, 1 /* 0xb1 */, 1 /* 0xb2 */, 1 /* 0xb3 */,
|
||||
1 /* 0xb4 */, 1 /* 0xb5 */, 1 /* 0xb6 */, 1 /* 0xb7 */,
|
||||
1 /* 0xb8 */, 1 /* 0xb9 */, 1 /* 0xba */, 1 /* 0xbb */,
|
||||
1 /* 0xbc */, 1 /* 0xbd */, 1 /* 0xbe */, 1 /* 0xbf */,
|
||||
1 /* 0xc0 */, 1 /* 0xc1 */, 1 /* 0xc2 */, 1 /* 0xc3 */,
|
||||
1 /* 0xc4 */, 1 /* 0xc5 */, 1 /* 0xc6 */, 1 /* 0xc7 */,
|
||||
1 /* 0xc8 */, 1 /* 0xc9 */, 1 /* 0xca */, 1 /* 0xcb */,
|
||||
1 /* 0xcc */, 1 /* 0xcd */, 1 /* 0xce */, 1 /* 0xcf */,
|
||||
1 /* 0xd0 */, 1 /* 0xd1 */, 1 /* 0xd2 */, 1 /* 0xd3 */,
|
||||
1 /* 0xd4 */, 1 /* 0xd5 */, 1 /* 0xd6 */, 1 /* 0xd7 */,
|
||||
1 /* 0xd8 */, 1 /* 0xd9 */, 1 /* 0xda */, 1 /* 0xdb */,
|
||||
1 /* 0xdc */, 1 /* 0xdd */, 1 /* 0xde */, 1 /* 0xdf */,
|
||||
1 /* 0xe0 */, 1 /* 0xe1 */, 1 /* 0xe2 */, 1 /* 0xe3 */,
|
||||
1 /* 0xe4 */, 1 /* 0xe5 */, 1 /* 0xe6 */, 1 /* 0xe7 */,
|
||||
1 /* 0xe8 */, 1 /* 0xe9 */, 1 /* 0xea */, 1 /* 0xeb */,
|
||||
1 /* 0xec */, 1 /* 0xed */, 1 /* 0xee */, 1 /* 0xef */,
|
||||
1 /* 0xf0 */, 1 /* 0xf1 */, 1 /* 0xf2 */, 1 /* 0xf3 */,
|
||||
1 /* 0xf4 */, 1 /* 0xf5 */, 1 /* 0xf6 */, 1 /* 0xf7 */,
|
||||
1 /* 0xf8 */, 1 /* 0xf9 */, 1 /* 0xfa */, 1 /* 0xfb */,
|
||||
1 /* 0xfc */, 1 /* 0xfd */, 1 /* 0xfe */, 1 /* 0xff */
|
||||
};
|
||||
|
||||
int nghttp2_check_path(const uint8_t *value, size_t len) {
|
||||
@@ -683,70 +683,70 @@ int nghttp2_check_path(const uint8_t *value, size_t len) {
|
||||
|
||||
/* Generated by genauthoritychartbl.py */
|
||||
static char VALID_AUTHORITY_CHARS[] = {
|
||||
0 /* NUL */, 0 /* SOH */, 0 /* STX */, 0 /* ETX */,
|
||||
0 /* EOT */, 0 /* ENQ */, 0 /* ACK */, 0 /* BEL */,
|
||||
0 /* BS */, 0 /* HT */, 0 /* LF */, 0 /* VT */,
|
||||
0 /* FF */, 0 /* CR */, 0 /* SO */, 0 /* SI */,
|
||||
0 /* DLE */, 0 /* DC1 */, 0 /* DC2 */, 0 /* DC3 */,
|
||||
0 /* DC4 */, 0 /* NAK */, 0 /* SYN */, 0 /* ETB */,
|
||||
0 /* CAN */, 0 /* EM */, 0 /* SUB */, 0 /* ESC */,
|
||||
0 /* FS */, 0 /* GS */, 0 /* RS */, 0 /* US */,
|
||||
0 /* SPC */, 1 /* ! */, 0 /* " */, 0 /* # */,
|
||||
1 /* $ */, 1 /* % */, 1 /* & */, 1 /* ' */,
|
||||
1 /* ( */, 1 /* ) */, 1 /* * */, 1 /* + */,
|
||||
1 /* , */, 1 /* - */, 1 /* . */, 0 /* / */,
|
||||
1 /* 0 */, 1 /* 1 */, 1 /* 2 */, 1 /* 3 */,
|
||||
1 /* 4 */, 1 /* 5 */, 1 /* 6 */, 1 /* 7 */,
|
||||
1 /* 8 */, 1 /* 9 */, 1 /* : */, 1 /* ; */,
|
||||
0 /* < */, 1 /* = */, 0 /* > */, 0 /* ? */,
|
||||
1 /* @ */, 1 /* A */, 1 /* B */, 1 /* C */,
|
||||
1 /* D */, 1 /* E */, 1 /* F */, 1 /* G */,
|
||||
1 /* H */, 1 /* I */, 1 /* J */, 1 /* K */,
|
||||
1 /* L */, 1 /* M */, 1 /* N */, 1 /* O */,
|
||||
1 /* P */, 1 /* Q */, 1 /* R */, 1 /* S */,
|
||||
1 /* T */, 1 /* U */, 1 /* V */, 1 /* W */,
|
||||
1 /* X */, 1 /* Y */, 1 /* Z */, 1 /* [ */,
|
||||
0 /* \ */, 1 /* ] */, 0 /* ^ */, 1 /* _ */,
|
||||
0 /* ` */, 1 /* a */, 1 /* b */, 1 /* c */,
|
||||
1 /* d */, 1 /* e */, 1 /* f */, 1 /* g */,
|
||||
1 /* h */, 1 /* i */, 1 /* j */, 1 /* k */,
|
||||
1 /* l */, 1 /* m */, 1 /* n */, 1 /* o */,
|
||||
1 /* p */, 1 /* q */, 1 /* r */, 1 /* s */,
|
||||
1 /* t */, 1 /* u */, 1 /* v */, 1 /* w */,
|
||||
1 /* x */, 1 /* y */, 1 /* z */, 0 /* { */,
|
||||
0 /* | */, 0 /* } */, 1 /* ~ */, 0 /* DEL */,
|
||||
0 /* 0x80 */, 0 /* 0x81 */, 0 /* 0x82 */, 0 /* 0x83 */,
|
||||
0 /* 0x84 */, 0 /* 0x85 */, 0 /* 0x86 */, 0 /* 0x87 */,
|
||||
0 /* 0x88 */, 0 /* 0x89 */, 0 /* 0x8a */, 0 /* 0x8b */,
|
||||
0 /* 0x8c */, 0 /* 0x8d */, 0 /* 0x8e */, 0 /* 0x8f */,
|
||||
0 /* 0x90 */, 0 /* 0x91 */, 0 /* 0x92 */, 0 /* 0x93 */,
|
||||
0 /* 0x94 */, 0 /* 0x95 */, 0 /* 0x96 */, 0 /* 0x97 */,
|
||||
0 /* 0x98 */, 0 /* 0x99 */, 0 /* 0x9a */, 0 /* 0x9b */,
|
||||
0 /* 0x9c */, 0 /* 0x9d */, 0 /* 0x9e */, 0 /* 0x9f */,
|
||||
0 /* 0xa0 */, 0 /* 0xa1 */, 0 /* 0xa2 */, 0 /* 0xa3 */,
|
||||
0 /* 0xa4 */, 0 /* 0xa5 */, 0 /* 0xa6 */, 0 /* 0xa7 */,
|
||||
0 /* 0xa8 */, 0 /* 0xa9 */, 0 /* 0xaa */, 0 /* 0xab */,
|
||||
0 /* 0xac */, 0 /* 0xad */, 0 /* 0xae */, 0 /* 0xaf */,
|
||||
0 /* 0xb0 */, 0 /* 0xb1 */, 0 /* 0xb2 */, 0 /* 0xb3 */,
|
||||
0 /* 0xb4 */, 0 /* 0xb5 */, 0 /* 0xb6 */, 0 /* 0xb7 */,
|
||||
0 /* 0xb8 */, 0 /* 0xb9 */, 0 /* 0xba */, 0 /* 0xbb */,
|
||||
0 /* 0xbc */, 0 /* 0xbd */, 0 /* 0xbe */, 0 /* 0xbf */,
|
||||
0 /* 0xc0 */, 0 /* 0xc1 */, 0 /* 0xc2 */, 0 /* 0xc3 */,
|
||||
0 /* 0xc4 */, 0 /* 0xc5 */, 0 /* 0xc6 */, 0 /* 0xc7 */,
|
||||
0 /* 0xc8 */, 0 /* 0xc9 */, 0 /* 0xca */, 0 /* 0xcb */,
|
||||
0 /* 0xcc */, 0 /* 0xcd */, 0 /* 0xce */, 0 /* 0xcf */,
|
||||
0 /* 0xd0 */, 0 /* 0xd1 */, 0 /* 0xd2 */, 0 /* 0xd3 */,
|
||||
0 /* 0xd4 */, 0 /* 0xd5 */, 0 /* 0xd6 */, 0 /* 0xd7 */,
|
||||
0 /* 0xd8 */, 0 /* 0xd9 */, 0 /* 0xda */, 0 /* 0xdb */,
|
||||
0 /* 0xdc */, 0 /* 0xdd */, 0 /* 0xde */, 0 /* 0xdf */,
|
||||
0 /* 0xe0 */, 0 /* 0xe1 */, 0 /* 0xe2 */, 0 /* 0xe3 */,
|
||||
0 /* 0xe4 */, 0 /* 0xe5 */, 0 /* 0xe6 */, 0 /* 0xe7 */,
|
||||
0 /* 0xe8 */, 0 /* 0xe9 */, 0 /* 0xea */, 0 /* 0xeb */,
|
||||
0 /* 0xec */, 0 /* 0xed */, 0 /* 0xee */, 0 /* 0xef */,
|
||||
0 /* 0xf0 */, 0 /* 0xf1 */, 0 /* 0xf2 */, 0 /* 0xf3 */,
|
||||
0 /* 0xf4 */, 0 /* 0xf5 */, 0 /* 0xf6 */, 0 /* 0xf7 */,
|
||||
0 /* 0xf8 */, 0 /* 0xf9 */, 0 /* 0xfa */, 0 /* 0xfb */,
|
||||
0 /* 0xfc */, 0 /* 0xfd */, 0 /* 0xfe */, 0 /* 0xff */
|
||||
0 /* NUL */, 0 /* SOH */, 0 /* STX */, 0 /* ETX */,
|
||||
0 /* EOT */, 0 /* ENQ */, 0 /* ACK */, 0 /* BEL */,
|
||||
0 /* BS */, 0 /* HT */, 0 /* LF */, 0 /* VT */,
|
||||
0 /* FF */, 0 /* CR */, 0 /* SO */, 0 /* SI */,
|
||||
0 /* DLE */, 0 /* DC1 */, 0 /* DC2 */, 0 /* DC3 */,
|
||||
0 /* DC4 */, 0 /* NAK */, 0 /* SYN */, 0 /* ETB */,
|
||||
0 /* CAN */, 0 /* EM */, 0 /* SUB */, 0 /* ESC */,
|
||||
0 /* FS */, 0 /* GS */, 0 /* RS */, 0 /* US */,
|
||||
0 /* SPC */, 1 /* ! */, 0 /* " */, 0 /* # */,
|
||||
1 /* $ */, 1 /* % */, 1 /* & */, 1 /* ' */,
|
||||
1 /* ( */, 1 /* ) */, 1 /* * */, 1 /* + */,
|
||||
1 /* , */, 1 /* - */, 1 /* . */, 0 /* / */,
|
||||
1 /* 0 */, 1 /* 1 */, 1 /* 2 */, 1 /* 3 */,
|
||||
1 /* 4 */, 1 /* 5 */, 1 /* 6 */, 1 /* 7 */,
|
||||
1 /* 8 */, 1 /* 9 */, 1 /* : */, 1 /* ; */,
|
||||
0 /* < */, 1 /* = */, 0 /* > */, 0 /* ? */,
|
||||
1 /* @ */, 1 /* A */, 1 /* B */, 1 /* C */,
|
||||
1 /* D */, 1 /* E */, 1 /* F */, 1 /* G */,
|
||||
1 /* H */, 1 /* I */, 1 /* J */, 1 /* K */,
|
||||
1 /* L */, 1 /* M */, 1 /* N */, 1 /* O */,
|
||||
1 /* P */, 1 /* Q */, 1 /* R */, 1 /* S */,
|
||||
1 /* T */, 1 /* U */, 1 /* V */, 1 /* W */,
|
||||
1 /* X */, 1 /* Y */, 1 /* Z */, 1 /* [ */,
|
||||
0 /* \ */, 1 /* ] */, 0 /* ^ */, 1 /* _ */,
|
||||
0 /* ` */, 1 /* a */, 1 /* b */, 1 /* c */,
|
||||
1 /* d */, 1 /* e */, 1 /* f */, 1 /* g */,
|
||||
1 /* h */, 1 /* i */, 1 /* j */, 1 /* k */,
|
||||
1 /* l */, 1 /* m */, 1 /* n */, 1 /* o */,
|
||||
1 /* p */, 1 /* q */, 1 /* r */, 1 /* s */,
|
||||
1 /* t */, 1 /* u */, 1 /* v */, 1 /* w */,
|
||||
1 /* x */, 1 /* y */, 1 /* z */, 0 /* { */,
|
||||
0 /* | */, 0 /* } */, 1 /* ~ */, 0 /* DEL */,
|
||||
0 /* 0x80 */, 0 /* 0x81 */, 0 /* 0x82 */, 0 /* 0x83 */,
|
||||
0 /* 0x84 */, 0 /* 0x85 */, 0 /* 0x86 */, 0 /* 0x87 */,
|
||||
0 /* 0x88 */, 0 /* 0x89 */, 0 /* 0x8a */, 0 /* 0x8b */,
|
||||
0 /* 0x8c */, 0 /* 0x8d */, 0 /* 0x8e */, 0 /* 0x8f */,
|
||||
0 /* 0x90 */, 0 /* 0x91 */, 0 /* 0x92 */, 0 /* 0x93 */,
|
||||
0 /* 0x94 */, 0 /* 0x95 */, 0 /* 0x96 */, 0 /* 0x97 */,
|
||||
0 /* 0x98 */, 0 /* 0x99 */, 0 /* 0x9a */, 0 /* 0x9b */,
|
||||
0 /* 0x9c */, 0 /* 0x9d */, 0 /* 0x9e */, 0 /* 0x9f */,
|
||||
0 /* 0xa0 */, 0 /* 0xa1 */, 0 /* 0xa2 */, 0 /* 0xa3 */,
|
||||
0 /* 0xa4 */, 0 /* 0xa5 */, 0 /* 0xa6 */, 0 /* 0xa7 */,
|
||||
0 /* 0xa8 */, 0 /* 0xa9 */, 0 /* 0xaa */, 0 /* 0xab */,
|
||||
0 /* 0xac */, 0 /* 0xad */, 0 /* 0xae */, 0 /* 0xaf */,
|
||||
0 /* 0xb0 */, 0 /* 0xb1 */, 0 /* 0xb2 */, 0 /* 0xb3 */,
|
||||
0 /* 0xb4 */, 0 /* 0xb5 */, 0 /* 0xb6 */, 0 /* 0xb7 */,
|
||||
0 /* 0xb8 */, 0 /* 0xb9 */, 0 /* 0xba */, 0 /* 0xbb */,
|
||||
0 /* 0xbc */, 0 /* 0xbd */, 0 /* 0xbe */, 0 /* 0xbf */,
|
||||
0 /* 0xc0 */, 0 /* 0xc1 */, 0 /* 0xc2 */, 0 /* 0xc3 */,
|
||||
0 /* 0xc4 */, 0 /* 0xc5 */, 0 /* 0xc6 */, 0 /* 0xc7 */,
|
||||
0 /* 0xc8 */, 0 /* 0xc9 */, 0 /* 0xca */, 0 /* 0xcb */,
|
||||
0 /* 0xcc */, 0 /* 0xcd */, 0 /* 0xce */, 0 /* 0xcf */,
|
||||
0 /* 0xd0 */, 0 /* 0xd1 */, 0 /* 0xd2 */, 0 /* 0xd3 */,
|
||||
0 /* 0xd4 */, 0 /* 0xd5 */, 0 /* 0xd6 */, 0 /* 0xd7 */,
|
||||
0 /* 0xd8 */, 0 /* 0xd9 */, 0 /* 0xda */, 0 /* 0xdb */,
|
||||
0 /* 0xdc */, 0 /* 0xdd */, 0 /* 0xde */, 0 /* 0xdf */,
|
||||
0 /* 0xe0 */, 0 /* 0xe1 */, 0 /* 0xe2 */, 0 /* 0xe3 */,
|
||||
0 /* 0xe4 */, 0 /* 0xe5 */, 0 /* 0xe6 */, 0 /* 0xe7 */,
|
||||
0 /* 0xe8 */, 0 /* 0xe9 */, 0 /* 0xea */, 0 /* 0xeb */,
|
||||
0 /* 0xec */, 0 /* 0xed */, 0 /* 0xee */, 0 /* 0xef */,
|
||||
0 /* 0xf0 */, 0 /* 0xf1 */, 0 /* 0xf2 */, 0 /* 0xf3 */,
|
||||
0 /* 0xf4 */, 0 /* 0xf5 */, 0 /* 0xf6 */, 0 /* 0xf7 */,
|
||||
0 /* 0xf8 */, 0 /* 0xf9 */, 0 /* 0xfa */, 0 /* 0xfb */,
|
||||
0 /* 0xfc */, 0 /* 0xfd */, 0 /* 0xfe */, 0 /* 0xff */
|
||||
};
|
||||
|
||||
int nghttp2_check_authority(const uint8_t *value, size_t len) {
|
||||
|
||||
@@ -38,33 +38,33 @@
|
||||
#define nghttp2_max_def(SUFFIX, T) \
|
||||
static inline T nghttp2_max_##SUFFIX(T a, T b) { return a < b ? b : a; }
|
||||
|
||||
nghttp2_max_def(int8, int8_t)
|
||||
nghttp2_max_def(int16, int16_t)
|
||||
nghttp2_max_def(int32, int32_t)
|
||||
nghttp2_max_def(int64, int64_t)
|
||||
nghttp2_max_def(uint8, uint8_t)
|
||||
nghttp2_max_def(uint16, uint16_t)
|
||||
nghttp2_max_def(uint32, uint32_t)
|
||||
nghttp2_max_def(uint64, uint64_t)
|
||||
nghttp2_max_def(size, size_t)
|
||||
nghttp2_max_def(int8, int8_t);
|
||||
nghttp2_max_def(int16, int16_t);
|
||||
nghttp2_max_def(int32, int32_t);
|
||||
nghttp2_max_def(int64, int64_t);
|
||||
nghttp2_max_def(uint8, uint8_t);
|
||||
nghttp2_max_def(uint16, uint16_t);
|
||||
nghttp2_max_def(uint32, uint32_t);
|
||||
nghttp2_max_def(uint64, uint64_t);
|
||||
nghttp2_max_def(size, size_t);
|
||||
|
||||
#define nghttp2_min_def(SUFFIX, T) \
|
||||
static inline T nghttp2_min_##SUFFIX(T a, T b) { return a < b ? a : b; }
|
||||
|
||||
nghttp2_min_def(int8, int8_t)
|
||||
nghttp2_min_def(int16, int16_t)
|
||||
nghttp2_min_def(int32, int32_t)
|
||||
nghttp2_min_def(int64, int64_t)
|
||||
nghttp2_min_def(uint8, uint8_t)
|
||||
nghttp2_min_def(uint16, uint16_t)
|
||||
nghttp2_min_def(uint32, uint32_t)
|
||||
nghttp2_min_def(uint64, uint64_t)
|
||||
nghttp2_min_def(size, size_t)
|
||||
nghttp2_min_def(int8, int8_t);
|
||||
nghttp2_min_def(int16, int16_t);
|
||||
nghttp2_min_def(int32, int32_t);
|
||||
nghttp2_min_def(int64, int64_t);
|
||||
nghttp2_min_def(uint8, uint8_t);
|
||||
nghttp2_min_def(uint16, uint16_t);
|
||||
nghttp2_min_def(uint32, uint32_t);
|
||||
nghttp2_min_def(uint64, uint64_t);
|
||||
nghttp2_min_def(size, size_t);
|
||||
|
||||
#define lstreq(A, B, N) ((sizeof((A)) - 1) == (N) && memcmp((A), (B), (N)) == 0)
|
||||
|
||||
#define nghttp2_struct_of(ptr, type, member) \
|
||||
((type *)(void *)((char *)(ptr) - offsetof(type, member)))
|
||||
((type *)(void *)((char *)(ptr)-offsetof(type, member)))
|
||||
|
||||
/*
|
||||
* Copies 2 byte unsigned integer |n| in host byte order to |buf| in
|
||||
|
||||
@@ -207,6 +207,7 @@ static int http_request_on_header(nghttp2_stream *stream, nghttp2_hd_nv *nv,
|
||||
if (!trailer &&
|
||||
/* Do not parse the header field in PUSH_PROMISE. */
|
||||
(stream->stream_id & 1) &&
|
||||
(stream->flags & NGHTTP2_STREAM_FLAG_NO_RFC7540_PRIORITIES) &&
|
||||
!(stream->http_flags & NGHTTP2_HTTP_FLAG_BAD_PRIORITY)) {
|
||||
nghttp2_extpri_from_uint8(&extpri, stream->http_extpri);
|
||||
if (nghttp2_http_parse_priority(&extpri, nv->value->base,
|
||||
@@ -346,84 +347,6 @@ static int lws(const uint8_t *s, size_t n) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Generated by genauthoritychartbl.py, but '@' is not allowed */
|
||||
static char VALID_AUTHORITY_CHARS[] = {
|
||||
0 /* NUL */, 0 /* SOH */, 0 /* STX */, 0 /* ETX */,
|
||||
0 /* EOT */, 0 /* ENQ */, 0 /* ACK */, 0 /* BEL */,
|
||||
0 /* BS */, 0 /* HT */, 0 /* LF */, 0 /* VT */,
|
||||
0 /* FF */, 0 /* CR */, 0 /* SO */, 0 /* SI */,
|
||||
0 /* DLE */, 0 /* DC1 */, 0 /* DC2 */, 0 /* DC3 */,
|
||||
0 /* DC4 */, 0 /* NAK */, 0 /* SYN */, 0 /* ETB */,
|
||||
0 /* CAN */, 0 /* EM */, 0 /* SUB */, 0 /* ESC */,
|
||||
0 /* FS */, 0 /* GS */, 0 /* RS */, 0 /* US */,
|
||||
0 /* SPC */, 1 /* ! */, 0 /* " */, 0 /* # */,
|
||||
1 /* $ */, 1 /* % */, 1 /* & */, 1 /* ' */,
|
||||
1 /* ( */, 1 /* ) */, 1 /* * */, 1 /* + */,
|
||||
1 /* , */, 1 /* - */, 1 /* . */, 0 /* / */,
|
||||
1 /* 0 */, 1 /* 1 */, 1 /* 2 */, 1 /* 3 */,
|
||||
1 /* 4 */, 1 /* 5 */, 1 /* 6 */, 1 /* 7 */,
|
||||
1 /* 8 */, 1 /* 9 */, 1 /* : */, 1 /* ; */,
|
||||
0 /* < */, 1 /* = */, 0 /* > */, 0 /* ? */,
|
||||
0 /* @ */, 1 /* A */, 1 /* B */, 1 /* C */,
|
||||
1 /* D */, 1 /* E */, 1 /* F */, 1 /* G */,
|
||||
1 /* H */, 1 /* I */, 1 /* J */, 1 /* K */,
|
||||
1 /* L */, 1 /* M */, 1 /* N */, 1 /* O */,
|
||||
1 /* P */, 1 /* Q */, 1 /* R */, 1 /* S */,
|
||||
1 /* T */, 1 /* U */, 1 /* V */, 1 /* W */,
|
||||
1 /* X */, 1 /* Y */, 1 /* Z */, 1 /* [ */,
|
||||
0 /* \ */, 1 /* ] */, 0 /* ^ */, 1 /* _ */,
|
||||
0 /* ` */, 1 /* a */, 1 /* b */, 1 /* c */,
|
||||
1 /* d */, 1 /* e */, 1 /* f */, 1 /* g */,
|
||||
1 /* h */, 1 /* i */, 1 /* j */, 1 /* k */,
|
||||
1 /* l */, 1 /* m */, 1 /* n */, 1 /* o */,
|
||||
1 /* p */, 1 /* q */, 1 /* r */, 1 /* s */,
|
||||
1 /* t */, 1 /* u */, 1 /* v */, 1 /* w */,
|
||||
1 /* x */, 1 /* y */, 1 /* z */, 0 /* { */,
|
||||
0 /* | */, 0 /* } */, 1 /* ~ */, 0 /* DEL */,
|
||||
0 /* 0x80 */, 0 /* 0x81 */, 0 /* 0x82 */, 0 /* 0x83 */,
|
||||
0 /* 0x84 */, 0 /* 0x85 */, 0 /* 0x86 */, 0 /* 0x87 */,
|
||||
0 /* 0x88 */, 0 /* 0x89 */, 0 /* 0x8a */, 0 /* 0x8b */,
|
||||
0 /* 0x8c */, 0 /* 0x8d */, 0 /* 0x8e */, 0 /* 0x8f */,
|
||||
0 /* 0x90 */, 0 /* 0x91 */, 0 /* 0x92 */, 0 /* 0x93 */,
|
||||
0 /* 0x94 */, 0 /* 0x95 */, 0 /* 0x96 */, 0 /* 0x97 */,
|
||||
0 /* 0x98 */, 0 /* 0x99 */, 0 /* 0x9a */, 0 /* 0x9b */,
|
||||
0 /* 0x9c */, 0 /* 0x9d */, 0 /* 0x9e */, 0 /* 0x9f */,
|
||||
0 /* 0xa0 */, 0 /* 0xa1 */, 0 /* 0xa2 */, 0 /* 0xa3 */,
|
||||
0 /* 0xa4 */, 0 /* 0xa5 */, 0 /* 0xa6 */, 0 /* 0xa7 */,
|
||||
0 /* 0xa8 */, 0 /* 0xa9 */, 0 /* 0xaa */, 0 /* 0xab */,
|
||||
0 /* 0xac */, 0 /* 0xad */, 0 /* 0xae */, 0 /* 0xaf */,
|
||||
0 /* 0xb0 */, 0 /* 0xb1 */, 0 /* 0xb2 */, 0 /* 0xb3 */,
|
||||
0 /* 0xb4 */, 0 /* 0xb5 */, 0 /* 0xb6 */, 0 /* 0xb7 */,
|
||||
0 /* 0xb8 */, 0 /* 0xb9 */, 0 /* 0xba */, 0 /* 0xbb */,
|
||||
0 /* 0xbc */, 0 /* 0xbd */, 0 /* 0xbe */, 0 /* 0xbf */,
|
||||
0 /* 0xc0 */, 0 /* 0xc1 */, 0 /* 0xc2 */, 0 /* 0xc3 */,
|
||||
0 /* 0xc4 */, 0 /* 0xc5 */, 0 /* 0xc6 */, 0 /* 0xc7 */,
|
||||
0 /* 0xc8 */, 0 /* 0xc9 */, 0 /* 0xca */, 0 /* 0xcb */,
|
||||
0 /* 0xcc */, 0 /* 0xcd */, 0 /* 0xce */, 0 /* 0xcf */,
|
||||
0 /* 0xd0 */, 0 /* 0xd1 */, 0 /* 0xd2 */, 0 /* 0xd3 */,
|
||||
0 /* 0xd4 */, 0 /* 0xd5 */, 0 /* 0xd6 */, 0 /* 0xd7 */,
|
||||
0 /* 0xd8 */, 0 /* 0xd9 */, 0 /* 0xda */, 0 /* 0xdb */,
|
||||
0 /* 0xdc */, 0 /* 0xdd */, 0 /* 0xde */, 0 /* 0xdf */,
|
||||
0 /* 0xe0 */, 0 /* 0xe1 */, 0 /* 0xe2 */, 0 /* 0xe3 */,
|
||||
0 /* 0xe4 */, 0 /* 0xe5 */, 0 /* 0xe6 */, 0 /* 0xe7 */,
|
||||
0 /* 0xe8 */, 0 /* 0xe9 */, 0 /* 0xea */, 0 /* 0xeb */,
|
||||
0 /* 0xec */, 0 /* 0xed */, 0 /* 0xee */, 0 /* 0xef */,
|
||||
0 /* 0xf0 */, 0 /* 0xf1 */, 0 /* 0xf2 */, 0 /* 0xf3 */,
|
||||
0 /* 0xf4 */, 0 /* 0xf5 */, 0 /* 0xf6 */, 0 /* 0xf7 */,
|
||||
0 /* 0xf8 */, 0 /* 0xf9 */, 0 /* 0xfa */, 0 /* 0xfb */,
|
||||
0 /* 0xfc */, 0 /* 0xfd */, 0 /* 0xfe */, 0 /* 0xff */
|
||||
};
|
||||
|
||||
static int check_authority(const uint8_t *value, size_t len) {
|
||||
const uint8_t *last;
|
||||
for (last = value + len; value != last; ++value) {
|
||||
if (!VALID_AUTHORITY_CHARS[*value]) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int nghttp2_http_on_header(nghttp2_session *session, nghttp2_stream *stream,
|
||||
nghttp2_frame *frame, nghttp2_hd_nv *nv,
|
||||
int trailer) {
|
||||
@@ -465,10 +388,10 @@ int nghttp2_http_on_header(nghttp2_session *session, nghttp2_stream *stream,
|
||||
case NGHTTP2_TOKEN__AUTHORITY:
|
||||
case NGHTTP2_TOKEN_HOST:
|
||||
if (session->server || frame->hd.type == NGHTTP2_PUSH_PROMISE) {
|
||||
rv = check_authority(nv->value->base, nv->value->len);
|
||||
rv = nghttp2_check_authority(nv->value->base, nv->value->len);
|
||||
} else if (
|
||||
stream->flags &
|
||||
NGHTTP2_STREAM_FLAG_NO_RFC9113_LEADING_AND_TRAILING_WS_VALIDATION) {
|
||||
stream->flags &
|
||||
NGHTTP2_STREAM_FLAG_NO_RFC9113_LEADING_AND_TRAILING_WS_VALIDATION) {
|
||||
rv = nghttp2_check_header_value(nv->value->base, nv->value->len);
|
||||
} else {
|
||||
rv = nghttp2_check_header_value_rfc9113(nv->value->base, nv->value->len);
|
||||
@@ -512,7 +435,7 @@ int nghttp2_http_on_header(nghttp2_session *session, nghttp2_stream *stream,
|
||||
if (session->server || frame->hd.type == NGHTTP2_PUSH_PROMISE) {
|
||||
return http_request_on_header(stream, nv, trailer,
|
||||
session->server &&
|
||||
session->pending_enable_connect_protocol);
|
||||
session->pending_enable_connect_protocol);
|
||||
}
|
||||
|
||||
return http_response_on_header(stream, nv, trailer);
|
||||
@@ -530,7 +453,7 @@ int nghttp2_http_on_request_headers(nghttp2_stream *stream,
|
||||
stream->content_length = -1;
|
||||
} else {
|
||||
if ((stream->http_flags & NGHTTP2_HTTP_FLAG_REQ_HEADERS) !=
|
||||
NGHTTP2_HTTP_FLAG_REQ_HEADERS ||
|
||||
NGHTTP2_HTTP_FLAG_REQ_HEADERS ||
|
||||
(stream->http_flags &
|
||||
(NGHTTP2_HTTP_FLAG__AUTHORITY | NGHTTP2_HTTP_FLAG_HOST)) == 0) {
|
||||
return -1;
|
||||
@@ -570,7 +493,7 @@ int nghttp2_http_on_response_headers(nghttp2_stream *stream) {
|
||||
}
|
||||
|
||||
stream->http_flags =
|
||||
stream->http_flags & (uint32_t)~NGHTTP2_HTTP_FLAG_EXPECT_FINAL_RESPONSE;
|
||||
stream->http_flags & (uint32_t)~NGHTTP2_HTTP_FLAG_EXPECT_FINAL_RESPONSE;
|
||||
|
||||
if (!expect_response_body(stream)) {
|
||||
stream->content_length = 0;
|
||||
@@ -659,17 +582,17 @@ void nghttp2_http_record_request_method(nghttp2_stream *stream,
|
||||
int nghttp2_http_parse_priority(nghttp2_extpri *dest, const uint8_t *value,
|
||||
size_t valuelen) {
|
||||
nghttp2_extpri pri = *dest;
|
||||
sfparse_parser sfp;
|
||||
sfparse_vec key;
|
||||
sfparse_value val;
|
||||
sf_parser sfp;
|
||||
sf_vec key;
|
||||
sf_value val;
|
||||
int rv;
|
||||
|
||||
sfparse_parser_init(&sfp, value, valuelen);
|
||||
sf_parser_init(&sfp, value, valuelen);
|
||||
|
||||
for (;;) {
|
||||
rv = sfparse_parser_dict(&sfp, &key, &val);
|
||||
rv = sf_parser_dict(&sfp, &key, &val);
|
||||
if (rv != 0) {
|
||||
if (rv == SFPARSE_ERR_EOF) {
|
||||
if (rv == SF_ERR_EOF) {
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -682,7 +605,7 @@ int nghttp2_http_parse_priority(nghttp2_extpri *dest, const uint8_t *value,
|
||||
|
||||
switch (key.base[0]) {
|
||||
case 'i':
|
||||
if (val.type != SFPARSE_TYPE_BOOLEAN) {
|
||||
if (val.type != SF_TYPE_BOOLEAN) {
|
||||
return NGHTTP2_ERR_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
@@ -690,7 +613,7 @@ int nghttp2_http_parse_priority(nghttp2_extpri *dest, const uint8_t *value,
|
||||
|
||||
break;
|
||||
case 'u':
|
||||
if (val.type != SFPARSE_TYPE_INTEGER ||
|
||||
if (val.type != SF_TYPE_INTEGER ||
|
||||
val.integer < NGHTTP2_EXTPRI_URGENCY_HIGH ||
|
||||
NGHTTP2_EXTPRI_URGENCY_LOW < val.integer) {
|
||||
return NGHTTP2_ERR_INVALID_ARGUMENT;
|
||||
|
||||
@@ -52,11 +52,7 @@ typedef enum {
|
||||
* Unlike NGHTTP2_ERR_IGN_HTTP_HEADER, this does not invoke
|
||||
* nghttp2_on_invalid_header_callback.
|
||||
*/
|
||||
NGHTTP2_ERR_REMOVE_HTTP_HEADER = -106,
|
||||
/*
|
||||
* Cancel pushed stream.
|
||||
*/
|
||||
NGHTTP2_ERR_PUSH_CANCEL = -107,
|
||||
NGHTTP2_ERR_REMOVE_HTTP_HEADER = -106
|
||||
} nghttp2_internal_error;
|
||||
|
||||
#endif /* NGHTTP2_INT_H */
|
||||
|
||||
@@ -31,13 +31,13 @@
|
||||
|
||||
#include "nghttp2_helper.h"
|
||||
|
||||
#define NGHTTP2_INITIAL_HASHBITS 4
|
||||
#define NGHTTP2_INITIAL_TABLE_LENBITS 4
|
||||
|
||||
void nghttp2_map_init(nghttp2_map *map, uint32_t seed, nghttp2_mem *mem) {
|
||||
void nghttp2_map_init(nghttp2_map *map, nghttp2_mem *mem) {
|
||||
map->mem = mem;
|
||||
map->hashbits = 0;
|
||||
map->tablelen = 0;
|
||||
map->tablelenbits = 0;
|
||||
map->table = NULL;
|
||||
map->seed = seed;
|
||||
map->size = 0;
|
||||
}
|
||||
|
||||
@@ -49,20 +49,33 @@ void nghttp2_map_free(nghttp2_map *map) {
|
||||
nghttp2_mem_free(map->mem, map->table);
|
||||
}
|
||||
|
||||
int nghttp2_map_each(const nghttp2_map *map, int (*func)(void *data, void *ptr),
|
||||
void nghttp2_map_each_free(nghttp2_map *map, int (*func)(void *data, void *ptr),
|
||||
void *ptr) {
|
||||
uint32_t i;
|
||||
nghttp2_map_bucket *bkt;
|
||||
|
||||
for (i = 0; i < map->tablelen; ++i) {
|
||||
bkt = &map->table[i];
|
||||
|
||||
if (bkt->data == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
func(bkt->data, ptr);
|
||||
}
|
||||
}
|
||||
|
||||
int nghttp2_map_each(nghttp2_map *map, int (*func)(void *data, void *ptr),
|
||||
void *ptr) {
|
||||
int rv;
|
||||
size_t i;
|
||||
uint32_t i;
|
||||
nghttp2_map_bucket *bkt;
|
||||
size_t tablelen;
|
||||
|
||||
if (map->size == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
tablelen = 1u << map->hashbits;
|
||||
|
||||
for (i = 0; i < tablelen; ++i) {
|
||||
for (i = 0; i < map->tablelen; ++i) {
|
||||
bkt = &map->table[i];
|
||||
|
||||
if (bkt->data == NULL) {
|
||||
@@ -78,70 +91,82 @@ int nghttp2_map_each(const nghttp2_map *map, int (*func)(void *data, void *ptr),
|
||||
return 0;
|
||||
}
|
||||
|
||||
static size_t map_hash(const nghttp2_map *map, nghttp2_map_key_type key) {
|
||||
/* hasher from
|
||||
https://github.com/rust-lang/rustc-hash/blob/dc5c33f1283de2da64d8d7a06401d91aded03ad4/src/lib.rs
|
||||
We do not perform finalization here because we use top bits
|
||||
anyway. */
|
||||
uint32_t h = ((uint32_t)key + map->seed) * 0x93d765dd;
|
||||
return (size_t)((h * 2654435769u) >> (32 - map->hashbits));
|
||||
static uint32_t hash(nghttp2_map_key_type key) {
|
||||
return (uint32_t)key * 2654435769u;
|
||||
}
|
||||
|
||||
static void map_bucket_swap(nghttp2_map_bucket *a, nghttp2_map_bucket *b) {
|
||||
nghttp2_map_bucket c = *a;
|
||||
static size_t h2idx(uint32_t hash, uint32_t bits) {
|
||||
return hash >> (32 - bits);
|
||||
}
|
||||
|
||||
*a = *b;
|
||||
*b = c;
|
||||
static size_t distance(uint32_t tablelen, uint32_t tablelenbits,
|
||||
nghttp2_map_bucket *bkt, size_t idx) {
|
||||
return (idx - h2idx(bkt->hash, tablelenbits)) & (tablelen - 1);
|
||||
}
|
||||
|
||||
static void map_bucket_swap(nghttp2_map_bucket *bkt, uint32_t *phash,
|
||||
nghttp2_map_key_type *pkey, void **pdata) {
|
||||
uint32_t h = bkt->hash;
|
||||
nghttp2_map_key_type key = bkt->key;
|
||||
void *data = bkt->data;
|
||||
|
||||
bkt->hash = *phash;
|
||||
bkt->key = *pkey;
|
||||
bkt->data = *pdata;
|
||||
|
||||
*phash = h;
|
||||
*pkey = key;
|
||||
*pdata = data;
|
||||
}
|
||||
|
||||
static void map_bucket_set_data(nghttp2_map_bucket *bkt, uint32_t hash,
|
||||
nghttp2_map_key_type key, void *data) {
|
||||
bkt->hash = hash;
|
||||
bkt->key = key;
|
||||
bkt->data = data;
|
||||
}
|
||||
|
||||
#ifndef WIN32
|
||||
void nghttp2_map_print_distance(const nghttp2_map *map) {
|
||||
size_t i;
|
||||
void nghttp2_map_print_distance(nghttp2_map *map) {
|
||||
uint32_t i;
|
||||
size_t idx;
|
||||
nghttp2_map_bucket *bkt;
|
||||
size_t tablelen;
|
||||
|
||||
if (map->size == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
tablelen = 1u << map->hashbits;
|
||||
|
||||
for (i = 0; i < tablelen; ++i) {
|
||||
for (i = 0; i < map->tablelen; ++i) {
|
||||
bkt = &map->table[i];
|
||||
|
||||
if (bkt->data == NULL) {
|
||||
fprintf(stderr, "@%zu <EMPTY>\n", i);
|
||||
fprintf(stderr, "@%u <EMPTY>\n", i);
|
||||
continue;
|
||||
}
|
||||
|
||||
idx = map_hash(map, bkt->key);
|
||||
fprintf(stderr, "@%zu hash=%zu key=%d base=%zu distance=%u\n", i,
|
||||
map_hash(map, bkt->key), bkt->key, idx, bkt->psl);
|
||||
idx = h2idx(bkt->hash, map->tablelenbits);
|
||||
fprintf(stderr, "@%u hash=%08x key=%d base=%zu distance=%zu\n", i,
|
||||
bkt->hash, bkt->key, idx,
|
||||
distance(map->tablelen, map->tablelenbits, bkt, idx));
|
||||
}
|
||||
}
|
||||
#endif /* !defined(WIN32) */
|
||||
#endif /* !WIN32 */
|
||||
|
||||
static int map_insert(nghttp2_map *map, nghttp2_map_key_type key, void *data) {
|
||||
size_t idx = map_hash(map, key);
|
||||
nghttp2_map_bucket b = {
|
||||
.key = key,
|
||||
.data = data,
|
||||
};
|
||||
static int insert(nghttp2_map_bucket *table, uint32_t tablelen,
|
||||
uint32_t tablelenbits, uint32_t hash,
|
||||
nghttp2_map_key_type key, void *data) {
|
||||
size_t idx = h2idx(hash, tablelenbits);
|
||||
size_t d = 0, dd;
|
||||
nghttp2_map_bucket *bkt;
|
||||
size_t mask = (1u << map->hashbits) - 1;
|
||||
|
||||
for (;;) {
|
||||
bkt = &map->table[idx];
|
||||
bkt = &table[idx];
|
||||
|
||||
if (bkt->data == NULL) {
|
||||
*bkt = b;
|
||||
++map->size;
|
||||
map_bucket_set_data(bkt, hash, key, data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (b.psl > bkt->psl) {
|
||||
map_bucket_swap(bkt, &b);
|
||||
dd = distance(tablelen, tablelenbits, bkt, idx);
|
||||
if (d > dd) {
|
||||
map_bucket_swap(bkt, &hash, &key, &data);
|
||||
d = dd;
|
||||
} else if (bkt->key == key) {
|
||||
/* TODO This check is just a waste after first swap or if this
|
||||
function is called from map_resize. That said, there is no
|
||||
@@ -150,47 +175,42 @@ static int map_insert(nghttp2_map *map, nghttp2_map_key_type key, void *data) {
|
||||
return NGHTTP2_ERR_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
++b.psl;
|
||||
idx = (idx + 1) & mask;
|
||||
++d;
|
||||
idx = (idx + 1) & (tablelen - 1);
|
||||
}
|
||||
}
|
||||
|
||||
static int map_resize(nghttp2_map *map, size_t new_hashbits) {
|
||||
size_t i;
|
||||
/* new_tablelen must be power of 2 and new_tablelen == (1 <<
|
||||
new_tablelenbits) must hold. */
|
||||
static int map_resize(nghttp2_map *map, uint32_t new_tablelen,
|
||||
uint32_t new_tablelenbits) {
|
||||
uint32_t i;
|
||||
nghttp2_map_bucket *new_table;
|
||||
nghttp2_map_bucket *bkt;
|
||||
size_t tablelen;
|
||||
int rv;
|
||||
nghttp2_map new_map = {
|
||||
.table = nghttp2_mem_calloc(map->mem, 1u << new_hashbits,
|
||||
sizeof(nghttp2_map_bucket)),
|
||||
.mem = map->mem,
|
||||
.seed = map->seed,
|
||||
.hashbits = new_hashbits,
|
||||
};
|
||||
(void)rv;
|
||||
|
||||
if (new_map.table == NULL) {
|
||||
new_table =
|
||||
nghttp2_mem_calloc(map->mem, new_tablelen, sizeof(nghttp2_map_bucket));
|
||||
if (new_table == NULL) {
|
||||
return NGHTTP2_ERR_NOMEM;
|
||||
}
|
||||
|
||||
if (map->size) {
|
||||
tablelen = 1u << map->hashbits;
|
||||
|
||||
for (i = 0; i < tablelen; ++i) {
|
||||
bkt = &map->table[i];
|
||||
if (bkt->data == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
rv = map_insert(&new_map, bkt->key, bkt->data);
|
||||
|
||||
assert(0 == rv);
|
||||
for (i = 0; i < map->tablelen; ++i) {
|
||||
bkt = &map->table[i];
|
||||
if (bkt->data == NULL) {
|
||||
continue;
|
||||
}
|
||||
rv = insert(new_table, new_tablelen, new_tablelenbits, bkt->hash, bkt->key,
|
||||
bkt->data);
|
||||
|
||||
assert(0 == rv);
|
||||
}
|
||||
|
||||
nghttp2_mem_free(map->mem, map->table);
|
||||
map->table = new_map.table;
|
||||
map->hashbits = new_hashbits;
|
||||
map->tablelen = new_tablelen;
|
||||
map->tablelenbits = new_tablelenbits;
|
||||
map->table = new_table;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -200,48 +220,49 @@ int nghttp2_map_insert(nghttp2_map *map, nghttp2_map_key_type key, void *data) {
|
||||
|
||||
assert(data);
|
||||
|
||||
/* Load factor is 7/8 */
|
||||
/* Under the very initial condition, that is map->size == 0 and
|
||||
map->hashbits == 0, 8 > 7 still holds nicely. */
|
||||
if ((map->size + 1) * 8 > (1u << map->hashbits) * 7) {
|
||||
if (map->hashbits) {
|
||||
rv = map_resize(map, map->hashbits + 1);
|
||||
/* Load factor is 0.75 */
|
||||
if ((map->size + 1) * 4 > map->tablelen * 3) {
|
||||
if (map->tablelen) {
|
||||
rv = map_resize(map, map->tablelen * 2, map->tablelenbits + 1);
|
||||
if (rv != 0) {
|
||||
return rv;
|
||||
}
|
||||
} else {
|
||||
rv = map_resize(map, NGHTTP2_INITIAL_HASHBITS);
|
||||
rv = map_resize(map, 1 << NGHTTP2_INITIAL_TABLE_LENBITS,
|
||||
NGHTTP2_INITIAL_TABLE_LENBITS);
|
||||
if (rv != 0) {
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rv = map_insert(map, key, data);
|
||||
rv = insert(map->table, map->tablelen, map->tablelenbits, hash(key), key,
|
||||
data);
|
||||
if (rv != 0) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
++map->size;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void *nghttp2_map_find(const nghttp2_map *map, nghttp2_map_key_type key) {
|
||||
void *nghttp2_map_find(nghttp2_map *map, nghttp2_map_key_type key) {
|
||||
uint32_t h;
|
||||
size_t idx;
|
||||
nghttp2_map_bucket *bkt;
|
||||
size_t psl = 0;
|
||||
size_t mask;
|
||||
size_t d = 0;
|
||||
|
||||
if (map->size == 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
idx = map_hash(map, key);
|
||||
mask = (1u << map->hashbits) - 1;
|
||||
h = hash(key);
|
||||
idx = h2idx(h, map->tablelenbits);
|
||||
|
||||
for (;;) {
|
||||
bkt = &map->table[idx];
|
||||
|
||||
if (bkt->data == NULL || psl > bkt->psl) {
|
||||
if (bkt->data == NULL ||
|
||||
d > distance(map->tablelen, map->tablelenbits, bkt, idx)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -249,47 +270,50 @@ void *nghttp2_map_find(const nghttp2_map *map, nghttp2_map_key_type key) {
|
||||
return bkt->data;
|
||||
}
|
||||
|
||||
++psl;
|
||||
idx = (idx + 1) & mask;
|
||||
++d;
|
||||
idx = (idx + 1) & (map->tablelen - 1);
|
||||
}
|
||||
}
|
||||
|
||||
int nghttp2_map_remove(nghttp2_map *map, nghttp2_map_key_type key) {
|
||||
size_t idx;
|
||||
nghttp2_map_bucket *b, *bkt;
|
||||
size_t psl = 0;
|
||||
size_t mask;
|
||||
uint32_t h;
|
||||
size_t idx, didx;
|
||||
nghttp2_map_bucket *bkt;
|
||||
size_t d = 0;
|
||||
|
||||
if (map->size == 0) {
|
||||
return NGHTTP2_ERR_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
idx = map_hash(map, key);
|
||||
mask = (1u << map->hashbits) - 1;
|
||||
h = hash(key);
|
||||
idx = h2idx(h, map->tablelenbits);
|
||||
|
||||
for (;;) {
|
||||
bkt = &map->table[idx];
|
||||
|
||||
if (bkt->data == NULL || psl > bkt->psl) {
|
||||
if (bkt->data == NULL ||
|
||||
d > distance(map->tablelen, map->tablelenbits, bkt, idx)) {
|
||||
return NGHTTP2_ERR_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
if (bkt->key == key) {
|
||||
b = bkt;
|
||||
idx = (idx + 1) & mask;
|
||||
map_bucket_set_data(bkt, 0, 0, NULL);
|
||||
|
||||
didx = idx;
|
||||
idx = (idx + 1) & (map->tablelen - 1);
|
||||
|
||||
for (;;) {
|
||||
bkt = &map->table[idx];
|
||||
if (bkt->data == NULL || bkt->psl == 0) {
|
||||
b->data = NULL;
|
||||
if (bkt->data == NULL ||
|
||||
distance(map->tablelen, map->tablelenbits, bkt, idx) == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
--bkt->psl;
|
||||
*b = *bkt;
|
||||
b = bkt;
|
||||
map->table[didx] = *bkt;
|
||||
map_bucket_set_data(bkt, 0, 0, NULL);
|
||||
didx = idx;
|
||||
|
||||
idx = (idx + 1) & mask;
|
||||
idx = (idx + 1) & (map->tablelen - 1);
|
||||
}
|
||||
|
||||
--map->size;
|
||||
@@ -297,18 +321,18 @@ int nghttp2_map_remove(nghttp2_map *map, nghttp2_map_key_type key) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
++psl;
|
||||
idx = (idx + 1) & mask;
|
||||
++d;
|
||||
idx = (idx + 1) & (map->tablelen - 1);
|
||||
}
|
||||
}
|
||||
|
||||
void nghttp2_map_clear(nghttp2_map *map) {
|
||||
if (map->size == 0) {
|
||||
if (map->tablelen == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
memset(map->table, 0, sizeof(*map->table) * (1u << map->hashbits));
|
||||
memset(map->table, 0, sizeof(*map->table) * map->tablelen);
|
||||
map->size = 0;
|
||||
}
|
||||
|
||||
size_t nghttp2_map_size(const nghttp2_map *map) { return map->size; }
|
||||
size_t nghttp2_map_size(nghttp2_map *map) { return map->size; }
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif /* defined(HAVE_CONFIG_H) */
|
||||
#endif /* HAVE_CONFIG_H */
|
||||
|
||||
#include <nghttp2/nghttp2.h>
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
typedef int32_t nghttp2_map_key_type;
|
||||
|
||||
typedef struct nghttp2_map_bucket {
|
||||
uint32_t psl;
|
||||
uint32_t hash;
|
||||
nghttp2_map_key_type key;
|
||||
void *data;
|
||||
} nghttp2_map_bucket;
|
||||
@@ -47,26 +47,34 @@ typedef struct nghttp2_map_bucket {
|
||||
typedef struct nghttp2_map {
|
||||
nghttp2_map_bucket *table;
|
||||
nghttp2_mem *mem;
|
||||
uint32_t seed;
|
||||
size_t size;
|
||||
size_t hashbits;
|
||||
uint32_t tablelen;
|
||||
uint32_t tablelenbits;
|
||||
} nghttp2_map;
|
||||
|
||||
/*
|
||||
* nghttp2_map_init initializes the map |map|.
|
||||
* Initializes the map |map|.
|
||||
*/
|
||||
void nghttp2_map_init(nghttp2_map *map, uint32_t seed, nghttp2_mem *mem);
|
||||
void nghttp2_map_init(nghttp2_map *map, nghttp2_mem *mem);
|
||||
|
||||
/*
|
||||
* nghttp2_map_free deallocates any resources allocated for |map|.
|
||||
* The stored entries are not freed by this function. Use
|
||||
* nghttp2_map_each() to free each entry.
|
||||
* Deallocates any resources allocated for |map|. The stored entries
|
||||
* are not freed by this function. Use nghttp2_map_each_free() to free
|
||||
* each entries.
|
||||
*/
|
||||
void nghttp2_map_free(nghttp2_map *map);
|
||||
|
||||
/*
|
||||
* nghttp2_map_insert inserts the new |data| with the |key| to the map
|
||||
* |map|.
|
||||
* Deallocates each entries using |func| function and any resources
|
||||
* allocated for |map|. The |func| function is responsible for freeing
|
||||
* given the |data| object. The |ptr| will be passed to the |func| as
|
||||
* send argument. The return value of the |func| will be ignored.
|
||||
*/
|
||||
void nghttp2_map_each_free(nghttp2_map *map, int (*func)(void *data, void *ptr),
|
||||
void *ptr);
|
||||
|
||||
/*
|
||||
* Inserts the new |data| with the |key| to the map |map|.
|
||||
*
|
||||
* This function returns 0 if it succeeds, or one of the following
|
||||
* negative error codes:
|
||||
@@ -74,56 +82,57 @@ void nghttp2_map_free(nghttp2_map *map);
|
||||
* NGHTTP2_ERR_INVALID_ARGUMENT
|
||||
* The item associated by |key| already exists.
|
||||
* NGHTTP2_ERR_NOMEM
|
||||
* Out of memory
|
||||
* Out of memory
|
||||
*/
|
||||
int nghttp2_map_insert(nghttp2_map *map, nghttp2_map_key_type key, void *data);
|
||||
|
||||
/*
|
||||
* nghttp2_map_find returns the entry associated by the key |key|. If
|
||||
* there is no such entry, this function returns NULL.
|
||||
* Returns the data associated by the key |key|. If there is no such
|
||||
* data, this function returns NULL.
|
||||
*/
|
||||
void *nghttp2_map_find(const nghttp2_map *map, nghttp2_map_key_type key);
|
||||
void *nghttp2_map_find(nghttp2_map *map, nghttp2_map_key_type key);
|
||||
|
||||
/*
|
||||
* nghttp2_map_remove removes the entry associated by the key |key|
|
||||
* from the |map|. The removed entry is not freed by this function.
|
||||
* Removes the data associated by the key |key| from the |map|. The
|
||||
* removed data is not freed by this function.
|
||||
*
|
||||
* This function returns 0 if it succeeds, or one of the following
|
||||
* negative error codes:
|
||||
*
|
||||
* NGHTTP2_ERR_INVALID_ARGUMENT
|
||||
* The entry associated by |key| does not exist.
|
||||
* The data associated by |key| does not exist.
|
||||
*/
|
||||
int nghttp2_map_remove(nghttp2_map *map, nghttp2_map_key_type key);
|
||||
|
||||
/*
|
||||
* nghttp2_map_clear removes all entries from |map|. The removed
|
||||
* entry is not freed by this function.
|
||||
* Removes all entries from |map|.
|
||||
*/
|
||||
void nghttp2_map_clear(nghttp2_map *map);
|
||||
|
||||
/*
|
||||
* nghttp2_map_size returns the number of items stored in the map
|
||||
* |map|.
|
||||
* Returns the number of items stored in the map |map|.
|
||||
*/
|
||||
size_t nghttp2_map_size(const nghttp2_map *map);
|
||||
size_t nghttp2_map_size(nghttp2_map *map);
|
||||
|
||||
/*
|
||||
* nghttp2_map_each applies the function |func| to each entry in the
|
||||
* |map| with the optional user supplied pointer |ptr|.
|
||||
* Applies the function |func| to each data in the |map| with the
|
||||
* optional user supplied pointer |ptr|.
|
||||
*
|
||||
* If the |func| returns 0, this function calls the |func| with the
|
||||
* next entry. If the |func| returns nonzero, it will not call the
|
||||
* next data. If the |func| returns nonzero, it will not call the
|
||||
* |func| for further entries and return the return value of the
|
||||
* |func| immediately. Thus, this function returns 0 if all the
|
||||
* invocations of the |func| return 0, or nonzero value which the last
|
||||
* invocation of |func| returns.
|
||||
*
|
||||
* Don't use this function to free each data. Use
|
||||
* nghttp2_map_each_free() instead.
|
||||
*/
|
||||
int nghttp2_map_each(const nghttp2_map *map, int (*func)(void *data, void *ptr),
|
||||
int nghttp2_map_each(nghttp2_map *map, int (*func)(void *data, void *ptr),
|
||||
void *ptr);
|
||||
|
||||
#ifndef WIN32
|
||||
void nghttp2_map_print_distance(const nghttp2_map *map);
|
||||
#endif /* !defined(WIN32) */
|
||||
void nghttp2_map_print_distance(nghttp2_map *map);
|
||||
#endif /* !WIN32 */
|
||||
|
||||
#endif /* !defined(NGHTTP2_MAP_H) */
|
||||
#endif /* NGHTTP2_MAP_H */
|
||||
|
||||
@@ -132,15 +132,15 @@ void nghttp2_option_set_max_settings(nghttp2_option *option, size_t val) {
|
||||
}
|
||||
|
||||
void nghttp2_option_set_server_fallback_rfc7540_priorities(
|
||||
nghttp2_option *option, int val) {
|
||||
nghttp2_option *option, int val) {
|
||||
option->opt_set_mask |= NGHTTP2_OPT_SERVER_FALLBACK_RFC7540_PRIORITIES;
|
||||
option->server_fallback_rfc7540_priorities = val;
|
||||
}
|
||||
|
||||
void nghttp2_option_set_no_rfc9113_leading_and_trailing_ws_validation(
|
||||
nghttp2_option *option, int val) {
|
||||
nghttp2_option *option, int val) {
|
||||
option->opt_set_mask |=
|
||||
NGHTTP2_OPT_NO_RFC9113_LEADING_AND_TRAILING_WS_VALIDATION;
|
||||
NGHTTP2_OPT_NO_RFC9113_LEADING_AND_TRAILING_WS_VALIDATION;
|
||||
option->no_rfc9113_leading_and_trailing_ws_validation = val;
|
||||
}
|
||||
|
||||
@@ -155,10 +155,3 @@ void nghttp2_option_set_max_continuations(nghttp2_option *option, size_t val) {
|
||||
option->opt_set_mask |= NGHTTP2_OPT_MAX_CONTINUATIONS;
|
||||
option->max_continuations = val;
|
||||
}
|
||||
|
||||
void nghttp2_option_set_glitch_rate_limit(nghttp2_option *option,
|
||||
uint64_t burst, uint64_t rate) {
|
||||
option->opt_set_mask |= NGHTTP2_OPT_GLITCH_RATE_LIMIT;
|
||||
option->glitch_burst = burst;
|
||||
option->glitch_rate = rate;
|
||||
}
|
||||
|
||||
@@ -72,7 +72,6 @@ typedef enum {
|
||||
NGHTTP2_OPT_NO_RFC9113_LEADING_AND_TRAILING_WS_VALIDATION = 1 << 14,
|
||||
NGHTTP2_OPT_STREAM_RESET_RATE_LIMIT = 1 << 15,
|
||||
NGHTTP2_OPT_MAX_CONTINUATIONS = 1 << 16,
|
||||
NGHTTP2_OPT_GLITCH_RATE_LIMIT = 1 << 17,
|
||||
} nghttp2_option_flag;
|
||||
|
||||
/**
|
||||
@@ -84,11 +83,6 @@ struct nghttp2_option {
|
||||
*/
|
||||
uint64_t stream_reset_burst;
|
||||
uint64_t stream_reset_rate;
|
||||
/**
|
||||
* NGHTTP2_OPT_GLITCH_RATE_LIMIT
|
||||
*/
|
||||
uint64_t glitch_burst;
|
||||
uint64_t glitch_rate;
|
||||
/**
|
||||
* NGHTTP2_OPT_MAX_SEND_HEADER_BLOCK_LENGTH
|
||||
*/
|
||||
|
||||
@@ -46,7 +46,7 @@ void nghttp2_queue_free(nghttp2_queue *queue) {
|
||||
|
||||
int nghttp2_queue_push(nghttp2_queue *queue, void *data) {
|
||||
nghttp2_queue_cell *new_cell =
|
||||
(nghttp2_queue_cell *)malloc(sizeof(nghttp2_queue_cell));
|
||||
(nghttp2_queue_cell *)malloc(sizeof(nghttp2_queue_cell));
|
||||
if (!new_cell) {
|
||||
return NGHTTP2_ERR_NOMEM;
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -45,8 +45,6 @@
|
||||
preface handling. */
|
||||
extern int nghttp2_enable_strict_preface;
|
||||
|
||||
extern nghttp2_stream nghttp2_stream_root;
|
||||
|
||||
/*
|
||||
* Option flags.
|
||||
*/
|
||||
@@ -55,6 +53,8 @@ typedef enum {
|
||||
NGHTTP2_OPTMASK_NO_RECV_CLIENT_MAGIC = 1 << 1,
|
||||
NGHTTP2_OPTMASK_NO_HTTP_MESSAGING = 1 << 2,
|
||||
NGHTTP2_OPTMASK_NO_AUTO_PING_ACK = 1 << 3,
|
||||
NGHTTP2_OPTMASK_NO_CLOSED_STREAMS = 1 << 4,
|
||||
NGHTTP2_OPTMASK_SERVER_FALLBACK_RFC7540_PRIORITIES = 1 << 5,
|
||||
NGHTTP2_OPTMASK_NO_RFC9113_LEADING_AND_TRAILING_WS_VALIDATION = 1 << 6,
|
||||
} nghttp2_optmask;
|
||||
|
||||
@@ -89,6 +89,10 @@ typedef struct {
|
||||
/* The default maximum number of incoming reserved streams */
|
||||
#define NGHTTP2_MAX_INCOMING_RESERVED_STREAMS 200
|
||||
|
||||
/* Even if we have less SETTINGS_MAX_CONCURRENT_STREAMS than this
|
||||
number, we keep NGHTTP2_MIN_IDLE_STREAMS streams in idle state */
|
||||
#define NGHTTP2_MIN_IDLE_STREAMS 16
|
||||
|
||||
/* The maximum number of items in outbound queue, which is considered
|
||||
as flooding caused by peer. All frames are not considered here.
|
||||
We only consider PING + ACK and SETTINGS + ACK. This is because
|
||||
@@ -106,10 +110,6 @@ typedef struct {
|
||||
#define NGHTTP2_DEFAULT_STREAM_RESET_BURST 1000
|
||||
#define NGHTTP2_DEFAULT_STREAM_RESET_RATE 33
|
||||
|
||||
/* The default values for glitch rate limiter. */
|
||||
#define NGHTTP2_DEFAULT_GLITCH_BURST 1000
|
||||
#define NGHTTP2_DEFAULT_GLITCH_RATE 33
|
||||
|
||||
/* The default max number of CONTINUATION frames following an incoming
|
||||
HEADER frame. */
|
||||
#define NGHTTP2_DEFAULT_MAX_CONTINUATIONS 8
|
||||
@@ -205,6 +205,8 @@ typedef struct nghttp2_inflight_settings nghttp2_inflight_settings;
|
||||
|
||||
struct nghttp2_session {
|
||||
nghttp2_map /* <nghttp2_stream*> */ streams;
|
||||
/* root of dependency tree*/
|
||||
nghttp2_stream root;
|
||||
/* Queue for outbound urgent frames (PING and SETTINGS) */
|
||||
nghttp2_outbound_queue ob_urgent;
|
||||
/* Queue for non-DATA frames */
|
||||
@@ -227,14 +229,26 @@ struct nghttp2_session {
|
||||
/* Memory allocator */
|
||||
nghttp2_mem mem;
|
||||
void *user_data;
|
||||
/* Points to the latest incoming closed stream. NULL if there is no
|
||||
closed stream. Only used when session is initialized as
|
||||
server. */
|
||||
nghttp2_stream *closed_stream_head;
|
||||
/* Points to the oldest incoming closed stream. NULL if there is no
|
||||
closed stream. Only used when session is initialized as
|
||||
server. */
|
||||
nghttp2_stream *closed_stream_tail;
|
||||
/* Points to the latest idle stream. NULL if there is no idle
|
||||
stream. Only used when session is initialized as server .*/
|
||||
nghttp2_stream *idle_stream_head;
|
||||
/* Points to the oldest idle stream. NULL if there is no idle
|
||||
stream. Only used when session is initialized as erver. */
|
||||
nghttp2_stream *idle_stream_tail;
|
||||
/* Queue of In-flight SETTINGS values. SETTINGS bearing ACK is not
|
||||
considered as in-flight. */
|
||||
nghttp2_inflight_settings *inflight_settings_head;
|
||||
/* Stream reset rate limiter. If receiving excessive amount of
|
||||
stream resets, GOAWAY will be sent. */
|
||||
nghttp2_ratelim stream_reset_ratelim;
|
||||
/* Rate limiter for all kinds of glitches. */
|
||||
nghttp2_ratelim glitch_ratelim;
|
||||
/* Sequential number across all streams to process streams in
|
||||
FIFO. */
|
||||
uint64_t stream_seq;
|
||||
@@ -262,9 +276,10 @@ struct nghttp2_session {
|
||||
|closed_stream_head|. The current implementation only keeps
|
||||
incoming streams and session is initialized as server. */
|
||||
size_t num_closed_streams;
|
||||
/* The number of idle streams kept in |streams| hash. The current
|
||||
implementation only keeps idle streams if session is initialized
|
||||
as server. */
|
||||
/* The number of idle streams kept in |streams| hash. The idle
|
||||
streams can be accessed through doubly linked list
|
||||
|idle_stream_head|. The current implementation only keeps idle
|
||||
streams if session is initialized as server. */
|
||||
size_t num_idle_streams;
|
||||
/* The number of bytes allocated for nvbuf */
|
||||
size_t nvbuflen;
|
||||
@@ -347,6 +362,8 @@ struct nghttp2_session {
|
||||
/* Unacked local SETTINGS_NO_RFC7540_PRIORITIES value, which is
|
||||
effective before it is acknowledged. */
|
||||
uint8_t pending_no_rfc7540_priorities;
|
||||
/* Turn on fallback to RFC 7540 priorities; for server use only. */
|
||||
uint8_t fallback_rfc7540_priorities;
|
||||
/* Nonzero if the session is server side. */
|
||||
uint8_t server;
|
||||
/* Flags indicating GOAWAY is sent and/or received. The flags are
|
||||
@@ -408,13 +425,6 @@ int nghttp2_session_is_my_stream_id(nghttp2_session *session,
|
||||
int nghttp2_session_add_item(nghttp2_session *session,
|
||||
nghttp2_outbound_item *item);
|
||||
|
||||
/*
|
||||
* This function wraps around nghttp2_session_add_rst_stream_continue
|
||||
* with continue_without_stream = 1.
|
||||
*/
|
||||
int nghttp2_session_add_rst_stream(nghttp2_session *session, int32_t stream_id,
|
||||
uint32_t error_code);
|
||||
|
||||
/*
|
||||
* Adds RST_STREAM frame for the stream |stream_id| with the error
|
||||
* code |error_code|. This is a convenient function built on top of
|
||||
@@ -422,9 +432,7 @@ int nghttp2_session_add_rst_stream(nghttp2_session *session, int32_t stream_id,
|
||||
*
|
||||
* This function simply returns 0 without adding RST_STREAM frame if
|
||||
* given stream is in NGHTTP2_STREAM_CLOSING state, because multiple
|
||||
* RST_STREAM for a stream is redundant. It also returns 0 without
|
||||
* adding the frame if |continue_without_stream| is nonzero, and
|
||||
* stream was already gone.
|
||||
* RST_STREAM for a stream is redundant.
|
||||
*
|
||||
* This function returns 0 if it succeeds, or one of the following
|
||||
* negative error codes:
|
||||
@@ -432,10 +440,8 @@ int nghttp2_session_add_rst_stream(nghttp2_session *session, int32_t stream_id,
|
||||
* NGHTTP2_ERR_NOMEM
|
||||
* Out of memory.
|
||||
*/
|
||||
int nghttp2_session_add_rst_stream_continue(nghttp2_session *session,
|
||||
int32_t stream_id,
|
||||
uint32_t error_code,
|
||||
int continue_without_stream);
|
||||
int nghttp2_session_add_rst_stream(nghttp2_session *session, int32_t stream_id,
|
||||
uint32_t error_code);
|
||||
|
||||
/*
|
||||
* Adds PING frame. This is a convenient function built on top of
|
||||
@@ -521,9 +527,15 @@ int nghttp2_session_add_settings(nghttp2_session *session, uint8_t flags,
|
||||
*
|
||||
* This function returns a pointer to created new stream object, or
|
||||
* NULL.
|
||||
*
|
||||
* This function adjusts neither the number of closed streams or idle
|
||||
* streams. The caller should manually call
|
||||
* nghttp2_session_adjust_closed_stream() or
|
||||
* nghttp2_session_adjust_idle_stream() respectively.
|
||||
*/
|
||||
nghttp2_stream *nghttp2_session_open_stream(nghttp2_session *session,
|
||||
int32_t stream_id, uint8_t flags,
|
||||
nghttp2_priority_spec *pri_spec,
|
||||
nghttp2_stream_state initial_state,
|
||||
void *stream_user_data);
|
||||
|
||||
@@ -532,6 +544,11 @@ nghttp2_stream *nghttp2_session_open_stream(nghttp2_session *session,
|
||||
* is indicated by the |error_code|. When closing the stream,
|
||||
* on_stream_close_callback will be called.
|
||||
*
|
||||
* If the session is initialized as server and |stream| is incoming
|
||||
* stream, stream is just marked closed and this function calls
|
||||
* nghttp2_session_keep_closed_stream() with |stream|. Otherwise,
|
||||
* |stream| will be deleted from memory.
|
||||
*
|
||||
* This function returns 0 if it succeeds, or one the following
|
||||
* negative error codes:
|
||||
*
|
||||
@@ -548,9 +565,63 @@ int nghttp2_session_close_stream(nghttp2_session *session, int32_t stream_id,
|
||||
/*
|
||||
* Deletes |stream| from memory. After this function returns, stream
|
||||
* cannot be accessed.
|
||||
*
|
||||
* This function returns 0 if it succeeds, or one the following
|
||||
* negative error codes:
|
||||
*
|
||||
* NGHTTP2_ERR_NOMEM
|
||||
* Out of memory
|
||||
*/
|
||||
void nghttp2_session_destroy_stream(nghttp2_session *session,
|
||||
nghttp2_stream *stream);
|
||||
int nghttp2_session_destroy_stream(nghttp2_session *session,
|
||||
nghttp2_stream *stream);
|
||||
|
||||
/*
|
||||
* Tries to keep incoming closed stream |stream|. Due to the
|
||||
* limitation of maximum number of streams in memory, |stream| is not
|
||||
* closed and just deleted from memory (see
|
||||
* nghttp2_session_destroy_stream).
|
||||
*/
|
||||
void nghttp2_session_keep_closed_stream(nghttp2_session *session,
|
||||
nghttp2_stream *stream);
|
||||
|
||||
/*
|
||||
* Appends |stream| to linked list |session->idle_stream_head|. We
|
||||
* apply fixed limit for list size. To fit into that limit, one or
|
||||
* more oldest streams are removed from list as necessary.
|
||||
*/
|
||||
void nghttp2_session_keep_idle_stream(nghttp2_session *session,
|
||||
nghttp2_stream *stream);
|
||||
|
||||
/*
|
||||
* Detaches |stream| from idle streams linked list.
|
||||
*/
|
||||
void nghttp2_session_detach_idle_stream(nghttp2_session *session,
|
||||
nghttp2_stream *stream);
|
||||
|
||||
/*
|
||||
* Deletes closed stream to ensure that number of incoming streams
|
||||
* including active and closed is in the maximum number of allowed
|
||||
* stream.
|
||||
*
|
||||
* This function returns 0 if it succeeds, or one the following
|
||||
* negative error codes:
|
||||
*
|
||||
* NGHTTP2_ERR_NOMEM
|
||||
* Out of memory
|
||||
*/
|
||||
int nghttp2_session_adjust_closed_stream(nghttp2_session *session);
|
||||
|
||||
/*
|
||||
* Deletes idle stream to ensure that number of idle streams is in
|
||||
* certain limit.
|
||||
*
|
||||
* This function returns 0 if it succeeds, or one the following
|
||||
* negative error codes:
|
||||
*
|
||||
* NGHTTP2_ERR_NOMEM
|
||||
* Out of memory
|
||||
*/
|
||||
int nghttp2_session_adjust_idle_stream(nghttp2_session *session);
|
||||
|
||||
/*
|
||||
* If further receptions and transmissions over the stream |stream_id|
|
||||
@@ -844,6 +915,24 @@ int nghttp2_session_update_local_settings(nghttp2_session *session,
|
||||
nghttp2_settings_entry *iv,
|
||||
size_t niv);
|
||||
|
||||
/*
|
||||
* Re-prioritize |stream|. The new priority specification is
|
||||
* |pri_spec|. Caller must ensure that stream->hd.stream_id !=
|
||||
* pri_spec->stream_id.
|
||||
*
|
||||
* This function does not adjust the number of idle streams. The
|
||||
* caller should call nghttp2_session_adjust_idle_stream() later.
|
||||
*
|
||||
* This function returns 0 if it succeeds, or one of the following
|
||||
* negative error codes:
|
||||
*
|
||||
* NGHTTP2_ERR_NOMEM
|
||||
* Out of memory
|
||||
*/
|
||||
int nghttp2_session_reprioritize_stream(nghttp2_session *session,
|
||||
nghttp2_stream *stream,
|
||||
const nghttp2_priority_spec *pri_spec);
|
||||
|
||||
/*
|
||||
* Terminates current |session| with the |error_code|. The |reason|
|
||||
* is NULL-terminated debug string.
|
||||
|
||||
@@ -25,17 +25,45 @@
|
||||
#include "nghttp2_stream.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "nghttp2_session.h"
|
||||
#include "nghttp2_helper.h"
|
||||
#include "nghttp2_debug.h"
|
||||
#include "nghttp2_frame.h"
|
||||
|
||||
/* Maximum distance between any two stream's cycle in the same
|
||||
priority queue. Imagine stream A's cycle is A, and stream B's
|
||||
cycle is B, and A < B. The cycle is unsigned 32 bit integer, it
|
||||
may get overflow. Because of how we calculate the next cycle
|
||||
value, if B - A is less than or equals to
|
||||
NGHTTP2_MAX_CYCLE_DISTANCE, A and B are in the same scale, in other
|
||||
words, B is really greater than or equal to A. Otherwise, A is a
|
||||
result of overflow, and it is actually A > B if we consider that
|
||||
fact. */
|
||||
#define NGHTTP2_MAX_CYCLE_DISTANCE \
|
||||
((uint64_t)NGHTTP2_MAX_FRAME_SIZE_MAX * 256 + 255)
|
||||
|
||||
static int stream_less(const void *lhsx, const void *rhsx) {
|
||||
const nghttp2_stream *lhs, *rhs;
|
||||
|
||||
lhs = nghttp2_struct_of(lhsx, nghttp2_stream, pq_entry);
|
||||
rhs = nghttp2_struct_of(rhsx, nghttp2_stream, pq_entry);
|
||||
|
||||
if (lhs->cycle == rhs->cycle) {
|
||||
return lhs->seq < rhs->seq;
|
||||
}
|
||||
|
||||
return rhs->cycle - lhs->cycle <= NGHTTP2_MAX_CYCLE_DISTANCE;
|
||||
}
|
||||
|
||||
void nghttp2_stream_init(nghttp2_stream *stream, int32_t stream_id,
|
||||
uint8_t flags, nghttp2_stream_state initial_state,
|
||||
int32_t remote_initial_window_size,
|
||||
int32_t weight, int32_t remote_initial_window_size,
|
||||
int32_t local_initial_window_size,
|
||||
void *stream_user_data) {
|
||||
void *stream_user_data, nghttp2_mem *mem) {
|
||||
nghttp2_pq_init(&stream->obq, stream_less, mem);
|
||||
|
||||
stream->stream_id = stream_id;
|
||||
stream->flags = flags;
|
||||
stream->state = initial_state;
|
||||
@@ -49,36 +77,428 @@ void nghttp2_stream_init(nghttp2_stream *stream, int32_t stream_id,
|
||||
stream->recv_reduction = 0;
|
||||
stream->window_update_queued = 0;
|
||||
|
||||
stream->dep_prev = NULL;
|
||||
stream->dep_next = NULL;
|
||||
stream->sib_prev = NULL;
|
||||
stream->sib_next = NULL;
|
||||
|
||||
stream->closed_prev = NULL;
|
||||
stream->closed_next = NULL;
|
||||
|
||||
stream->weight = weight;
|
||||
stream->sum_dep_weight = 0;
|
||||
|
||||
stream->http_flags = NGHTTP2_HTTP_FLAG_NONE;
|
||||
stream->content_length = -1;
|
||||
stream->recv_content_length = 0;
|
||||
stream->status_code = -1;
|
||||
|
||||
stream->queued = 0;
|
||||
stream->descendant_last_cycle = 0;
|
||||
stream->cycle = 0;
|
||||
stream->pending_penalty = 0;
|
||||
stream->descendant_next_seq = 0;
|
||||
stream->seq = 0;
|
||||
stream->last_writelen = 0;
|
||||
|
||||
stream->extpri = stream->http_extpri = NGHTTP2_EXTPRI_DEFAULT_URGENCY;
|
||||
}
|
||||
|
||||
void nghttp2_stream_free(nghttp2_stream *stream) { (void)stream; }
|
||||
void nghttp2_stream_free(nghttp2_stream *stream) {
|
||||
nghttp2_pq_free(&stream->obq);
|
||||
/* We don't free stream->item. If it is assigned to aob, then
|
||||
active_outbound_item_reset() will delete it. Otherwise,
|
||||
nghttp2_stream_close() or session_del() will delete it. */
|
||||
}
|
||||
|
||||
void nghttp2_stream_shutdown(nghttp2_stream *stream, nghttp2_shut_flag flag) {
|
||||
stream->shut_flags = (uint8_t)(stream->shut_flags | flag);
|
||||
}
|
||||
|
||||
void nghttp2_stream_attach_item(nghttp2_stream *stream,
|
||||
nghttp2_outbound_item *item) {
|
||||
/*
|
||||
* Returns nonzero if |stream| is active. This function does not take
|
||||
* into account its descendants.
|
||||
*/
|
||||
static int stream_active(nghttp2_stream *stream) {
|
||||
return stream->item &&
|
||||
(stream->flags & NGHTTP2_STREAM_FLAG_DEFERRED_ALL) == 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns nonzero if |stream| or one of its descendants is active
|
||||
*/
|
||||
static int stream_subtree_active(nghttp2_stream *stream) {
|
||||
return stream_active(stream) || !nghttp2_pq_empty(&stream->obq);
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns next cycle for |stream|.
|
||||
*/
|
||||
static void stream_next_cycle(nghttp2_stream *stream, uint64_t last_cycle) {
|
||||
uint64_t penalty;
|
||||
|
||||
penalty = (uint64_t)stream->last_writelen * NGHTTP2_MAX_WEIGHT +
|
||||
stream->pending_penalty;
|
||||
|
||||
stream->cycle = last_cycle + penalty / (uint32_t)stream->weight;
|
||||
stream->pending_penalty = (uint32_t)(penalty % (uint32_t)stream->weight);
|
||||
}
|
||||
|
||||
static int stream_obq_push(nghttp2_stream *dep_stream, nghttp2_stream *stream) {
|
||||
int rv;
|
||||
|
||||
for (; dep_stream && !stream->queued;
|
||||
stream = dep_stream, dep_stream = dep_stream->dep_prev) {
|
||||
stream_next_cycle(stream, dep_stream->descendant_last_cycle);
|
||||
stream->seq = dep_stream->descendant_next_seq++;
|
||||
|
||||
DEBUGF("stream: stream=%d obq push cycle=%lu\n", stream->stream_id,
|
||||
stream->cycle);
|
||||
|
||||
DEBUGF("stream: push stream %d to stream %d\n", stream->stream_id,
|
||||
dep_stream->stream_id);
|
||||
|
||||
rv = nghttp2_pq_push(&dep_stream->obq, &stream->pq_entry);
|
||||
if (rv != 0) {
|
||||
return rv;
|
||||
}
|
||||
stream->queued = 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Removes |stream| from parent's obq. If removal of |stream| makes
|
||||
* parent's obq empty, and parent is not active, then parent is also
|
||||
* removed. This process is repeated recursively.
|
||||
*/
|
||||
static void stream_obq_remove(nghttp2_stream *stream) {
|
||||
nghttp2_stream *dep_stream;
|
||||
|
||||
dep_stream = stream->dep_prev;
|
||||
|
||||
if (!stream->queued) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (; dep_stream; stream = dep_stream, dep_stream = dep_stream->dep_prev) {
|
||||
DEBUGF("stream: remove stream %d from stream %d\n", stream->stream_id,
|
||||
dep_stream->stream_id);
|
||||
|
||||
nghttp2_pq_remove(&dep_stream->obq, &stream->pq_entry);
|
||||
|
||||
assert(stream->queued);
|
||||
|
||||
stream->queued = 0;
|
||||
stream->cycle = 0;
|
||||
stream->pending_penalty = 0;
|
||||
stream->descendant_last_cycle = 0;
|
||||
stream->last_writelen = 0;
|
||||
|
||||
if (stream_subtree_active(dep_stream)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Moves |stream| from |src|'s obq to |dest|'s obq. Removal from
|
||||
* |src|'s obq is just done calling nghttp2_pq_remove(), so it does
|
||||
* not recursively remove |src| and ancestors, like
|
||||
* stream_obq_remove().
|
||||
*/
|
||||
static int stream_obq_move(nghttp2_stream *dest, nghttp2_stream *src,
|
||||
nghttp2_stream *stream) {
|
||||
if (!stream->queued) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEBUGF("stream: remove stream %d from stream %d (move)\n", stream->stream_id,
|
||||
src->stream_id);
|
||||
|
||||
nghttp2_pq_remove(&src->obq, &stream->pq_entry);
|
||||
stream->queued = 0;
|
||||
|
||||
return stream_obq_push(dest, stream);
|
||||
}
|
||||
|
||||
void nghttp2_stream_reschedule(nghttp2_stream *stream) {
|
||||
nghttp2_stream *dep_stream;
|
||||
|
||||
assert(stream->queued);
|
||||
|
||||
dep_stream = stream->dep_prev;
|
||||
|
||||
for (; dep_stream; stream = dep_stream, dep_stream = dep_stream->dep_prev) {
|
||||
nghttp2_pq_remove(&dep_stream->obq, &stream->pq_entry);
|
||||
|
||||
stream_next_cycle(stream, dep_stream->descendant_last_cycle);
|
||||
stream->seq = dep_stream->descendant_next_seq++;
|
||||
|
||||
nghttp2_pq_push(&dep_stream->obq, &stream->pq_entry);
|
||||
|
||||
DEBUGF("stream: stream=%d obq resched cycle=%lu\n", stream->stream_id,
|
||||
stream->cycle);
|
||||
|
||||
dep_stream->last_writelen = stream->last_writelen;
|
||||
}
|
||||
}
|
||||
|
||||
void nghttp2_stream_change_weight(nghttp2_stream *stream, int32_t weight) {
|
||||
nghttp2_stream *dep_stream;
|
||||
uint64_t last_cycle;
|
||||
int32_t old_weight;
|
||||
uint64_t wlen_penalty;
|
||||
|
||||
if (stream->weight == weight) {
|
||||
return;
|
||||
}
|
||||
|
||||
old_weight = stream->weight;
|
||||
stream->weight = weight;
|
||||
|
||||
dep_stream = stream->dep_prev;
|
||||
|
||||
if (!dep_stream) {
|
||||
return;
|
||||
}
|
||||
|
||||
dep_stream->sum_dep_weight += weight - old_weight;
|
||||
|
||||
if (!stream->queued) {
|
||||
return;
|
||||
}
|
||||
|
||||
nghttp2_pq_remove(&dep_stream->obq, &stream->pq_entry);
|
||||
|
||||
wlen_penalty = (uint64_t)stream->last_writelen * NGHTTP2_MAX_WEIGHT;
|
||||
|
||||
/* Compute old stream->pending_penalty we used to calculate
|
||||
stream->cycle */
|
||||
stream->pending_penalty =
|
||||
(uint32_t)((stream->pending_penalty + (uint32_t)old_weight -
|
||||
(wlen_penalty % (uint32_t)old_weight)) %
|
||||
(uint32_t)old_weight);
|
||||
|
||||
last_cycle = stream->cycle -
|
||||
(wlen_penalty + stream->pending_penalty) / (uint32_t)old_weight;
|
||||
|
||||
/* Now we have old stream->pending_penalty and new stream->weight in
|
||||
place */
|
||||
stream_next_cycle(stream, last_cycle);
|
||||
|
||||
if (dep_stream->descendant_last_cycle - stream->cycle <=
|
||||
NGHTTP2_MAX_CYCLE_DISTANCE) {
|
||||
stream->cycle = dep_stream->descendant_last_cycle;
|
||||
}
|
||||
|
||||
/* Continue to use same stream->seq */
|
||||
|
||||
nghttp2_pq_push(&dep_stream->obq, &stream->pq_entry);
|
||||
|
||||
DEBUGF("stream: stream=%d obq resched cycle=%lu\n", stream->stream_id,
|
||||
stream->cycle);
|
||||
}
|
||||
|
||||
static nghttp2_stream *stream_last_sib(nghttp2_stream *stream) {
|
||||
for (; stream->sib_next; stream = stream->sib_next)
|
||||
;
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
||||
int32_t nghttp2_stream_dep_distributed_weight(nghttp2_stream *stream,
|
||||
int32_t weight) {
|
||||
weight = stream->weight * weight / stream->sum_dep_weight;
|
||||
|
||||
return nghttp2_max_int32(1, weight);
|
||||
}
|
||||
|
||||
#ifdef STREAM_DEP_DEBUG
|
||||
|
||||
static void ensure_inactive(nghttp2_stream *stream) {
|
||||
nghttp2_stream *si;
|
||||
|
||||
if (stream->queued) {
|
||||
fprintf(stderr, "stream(%p)=%d, stream->queued = 1; want 0\n", stream,
|
||||
stream->stream_id);
|
||||
assert(0);
|
||||
}
|
||||
|
||||
if (stream_active(stream)) {
|
||||
fprintf(stderr, "stream(%p)=%d, stream_active(stream) = 1; want 0\n",
|
||||
stream, stream->stream_id);
|
||||
assert(0);
|
||||
}
|
||||
|
||||
if (!nghttp2_pq_empty(&stream->obq)) {
|
||||
fprintf(stderr, "stream(%p)=%d, nghttp2_pq_size() = %zu; want 0\n", stream,
|
||||
stream->stream_id, nghttp2_pq_size(&stream->obq));
|
||||
assert(0);
|
||||
}
|
||||
|
||||
for (si = stream->dep_next; si; si = si->sib_next) {
|
||||
ensure_inactive(si);
|
||||
}
|
||||
}
|
||||
|
||||
static void check_queued(nghttp2_stream *stream) {
|
||||
nghttp2_stream *si;
|
||||
int queued;
|
||||
|
||||
if (stream->queued) {
|
||||
if (!stream_subtree_active(stream)) {
|
||||
fprintf(stderr,
|
||||
"stream(%p)=%d, stream->queued == 1, but "
|
||||
"stream_active() == %d and nghttp2_pq_size(&stream->obq) = %zu\n",
|
||||
stream, stream->stream_id, stream_active(stream),
|
||||
nghttp2_pq_size(&stream->obq));
|
||||
assert(0);
|
||||
}
|
||||
if (!stream_active(stream)) {
|
||||
queued = 0;
|
||||
for (si = stream->dep_next; si; si = si->sib_next) {
|
||||
if (si->queued) {
|
||||
++queued;
|
||||
}
|
||||
}
|
||||
if (queued == 0) {
|
||||
fprintf(stderr,
|
||||
"stream(%p)=%d, stream->queued == 1, and "
|
||||
"!stream_active(), but no descendants is queued\n",
|
||||
stream, stream->stream_id);
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
for (si = stream->dep_next; si; si = si->sib_next) {
|
||||
check_queued(si);
|
||||
}
|
||||
} else {
|
||||
if (stream_active(stream) || !nghttp2_pq_empty(&stream->obq)) {
|
||||
fprintf(stderr,
|
||||
"stream(%p) = %d, stream->queued == 0, but "
|
||||
"stream_active(stream) == %d and "
|
||||
"nghttp2_pq_size(&stream->obq) = %zu\n",
|
||||
stream, stream->stream_id, stream_active(stream),
|
||||
nghttp2_pq_size(&stream->obq));
|
||||
assert(0);
|
||||
}
|
||||
for (si = stream->dep_next; si; si = si->sib_next) {
|
||||
ensure_inactive(si);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void check_sum_dep(nghttp2_stream *stream) {
|
||||
nghttp2_stream *si;
|
||||
int32_t n = 0;
|
||||
for (si = stream->dep_next; si; si = si->sib_next) {
|
||||
n += si->weight;
|
||||
}
|
||||
if (n != stream->sum_dep_weight) {
|
||||
fprintf(stderr, "stream(%p)=%d, sum_dep_weight = %d; want %d\n", stream,
|
||||
stream->stream_id, n, stream->sum_dep_weight);
|
||||
assert(0);
|
||||
}
|
||||
for (si = stream->dep_next; si; si = si->sib_next) {
|
||||
check_sum_dep(si);
|
||||
}
|
||||
}
|
||||
|
||||
static void check_dep_prev(nghttp2_stream *stream) {
|
||||
nghttp2_stream *si;
|
||||
for (si = stream->dep_next; si; si = si->sib_next) {
|
||||
if (si->dep_prev != stream) {
|
||||
fprintf(stderr, "si->dep_prev = %p; want %p\n", si->dep_prev, stream);
|
||||
assert(0);
|
||||
}
|
||||
check_dep_prev(si);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* STREAM_DEP_DEBUG */
|
||||
|
||||
#ifdef STREAM_DEP_DEBUG
|
||||
static void validate_tree(nghttp2_stream *stream) {
|
||||
nghttp2_stream *si;
|
||||
|
||||
if (!stream) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (; stream->dep_prev; stream = stream->dep_prev)
|
||||
;
|
||||
|
||||
assert(stream->stream_id == 0);
|
||||
assert(!stream->queued);
|
||||
|
||||
fprintf(stderr, "checking...\n");
|
||||
if (nghttp2_pq_empty(&stream->obq)) {
|
||||
fprintf(stderr, "root obq empty\n");
|
||||
for (si = stream->dep_next; si; si = si->sib_next) {
|
||||
ensure_inactive(si);
|
||||
}
|
||||
} else {
|
||||
for (si = stream->dep_next; si; si = si->sib_next) {
|
||||
check_queued(si);
|
||||
}
|
||||
}
|
||||
|
||||
check_sum_dep(stream);
|
||||
check_dep_prev(stream);
|
||||
}
|
||||
#else /* !STREAM_DEP_DEBUG */
|
||||
static void validate_tree(nghttp2_stream *stream) { (void)stream; }
|
||||
#endif /* !STREAM_DEP_DEBUG*/
|
||||
|
||||
static int stream_update_dep_on_attach_item(nghttp2_stream *stream) {
|
||||
int rv;
|
||||
|
||||
rv = stream_obq_push(stream->dep_prev, stream);
|
||||
if (rv != 0) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
validate_tree(stream);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void stream_update_dep_on_detach_item(nghttp2_stream *stream) {
|
||||
if (nghttp2_pq_empty(&stream->obq)) {
|
||||
stream_obq_remove(stream);
|
||||
}
|
||||
|
||||
validate_tree(stream);
|
||||
}
|
||||
|
||||
int nghttp2_stream_attach_item(nghttp2_stream *stream,
|
||||
nghttp2_outbound_item *item) {
|
||||
int rv;
|
||||
|
||||
assert((stream->flags & NGHTTP2_STREAM_FLAG_DEFERRED_ALL) == 0);
|
||||
assert(stream->item == NULL);
|
||||
|
||||
DEBUGF("stream: stream=%d attach item=%p\n", stream->stream_id, item);
|
||||
|
||||
stream->item = item;
|
||||
|
||||
if (stream->flags & NGHTTP2_STREAM_FLAG_NO_RFC7540_PRIORITIES) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
rv = stream_update_dep_on_attach_item(stream);
|
||||
if (rv != 0) {
|
||||
/* This may relave stream->queued == 1, but stream->item == NULL.
|
||||
But only consequence of this error is fatal one, and session
|
||||
destruction. In that execution path, these inconsistency does
|
||||
not matter. */
|
||||
stream->item = NULL;
|
||||
return rv;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void nghttp2_stream_detach_item(nghttp2_stream *stream) {
|
||||
@@ -86,6 +506,12 @@ void nghttp2_stream_detach_item(nghttp2_stream *stream) {
|
||||
|
||||
stream->item = NULL;
|
||||
stream->flags = (uint8_t)(stream->flags & ~NGHTTP2_STREAM_FLAG_DEFERRED_ALL);
|
||||
|
||||
if (stream->flags & NGHTTP2_STREAM_FLAG_NO_RFC7540_PRIORITIES) {
|
||||
return;
|
||||
}
|
||||
|
||||
stream_update_dep_on_detach_item(stream);
|
||||
}
|
||||
|
||||
void nghttp2_stream_defer_item(nghttp2_stream *stream, uint8_t flags) {
|
||||
@@ -95,16 +521,31 @@ void nghttp2_stream_defer_item(nghttp2_stream *stream, uint8_t flags) {
|
||||
stream->item, flags);
|
||||
|
||||
stream->flags |= flags;
|
||||
|
||||
if (stream->flags & NGHTTP2_STREAM_FLAG_NO_RFC7540_PRIORITIES) {
|
||||
return;
|
||||
}
|
||||
|
||||
stream_update_dep_on_detach_item(stream);
|
||||
}
|
||||
|
||||
void nghttp2_stream_resume_deferred_item(nghttp2_stream *stream,
|
||||
uint8_t flags) {
|
||||
int nghttp2_stream_resume_deferred_item(nghttp2_stream *stream, uint8_t flags) {
|
||||
assert(stream->item);
|
||||
|
||||
DEBUGF("stream: stream=%d resume item=%p flags=%02x\n", stream->stream_id,
|
||||
stream->item, flags);
|
||||
|
||||
stream->flags = (uint8_t)(stream->flags & ~flags);
|
||||
|
||||
if (stream->flags & NGHTTP2_STREAM_FLAG_DEFERRED_ALL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (stream->flags & NGHTTP2_STREAM_FLAG_NO_RFC7540_PRIORITIES) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return stream_update_dep_on_attach_item(stream);
|
||||
}
|
||||
|
||||
int nghttp2_stream_check_deferred_item(nghttp2_stream *stream) {
|
||||
@@ -130,16 +571,16 @@ static int update_initial_window_size(int32_t *window_size_ptr,
|
||||
}
|
||||
|
||||
int nghttp2_stream_update_remote_initial_window_size(
|
||||
nghttp2_stream *stream, int32_t new_initial_window_size,
|
||||
int32_t old_initial_window_size) {
|
||||
nghttp2_stream *stream, int32_t new_initial_window_size,
|
||||
int32_t old_initial_window_size) {
|
||||
return update_initial_window_size(&stream->remote_window_size,
|
||||
new_initial_window_size,
|
||||
old_initial_window_size);
|
||||
}
|
||||
|
||||
int nghttp2_stream_update_local_initial_window_size(
|
||||
nghttp2_stream *stream, int32_t new_initial_window_size,
|
||||
int32_t old_initial_window_size) {
|
||||
nghttp2_stream *stream, int32_t new_initial_window_size,
|
||||
int32_t old_initial_window_size) {
|
||||
return update_initial_window_size(&stream->local_window_size,
|
||||
new_initial_window_size,
|
||||
old_initial_window_size);
|
||||
@@ -150,11 +591,373 @@ void nghttp2_stream_promise_fulfilled(nghttp2_stream *stream) {
|
||||
stream->flags = (uint8_t)(stream->flags & ~NGHTTP2_STREAM_FLAG_PUSH);
|
||||
}
|
||||
|
||||
nghttp2_stream_proto_state nghttp2_stream_get_state(nghttp2_stream *stream) {
|
||||
if (stream == &nghttp2_stream_root) {
|
||||
return NGHTTP2_STREAM_STATE_IDLE;
|
||||
int nghttp2_stream_dep_find_ancestor(nghttp2_stream *stream,
|
||||
nghttp2_stream *target) {
|
||||
for (; stream; stream = stream->dep_prev) {
|
||||
if (stream == target) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int nghttp2_stream_dep_insert(nghttp2_stream *dep_stream,
|
||||
nghttp2_stream *stream) {
|
||||
nghttp2_stream *si;
|
||||
int rv;
|
||||
|
||||
DEBUGF("stream: dep_insert dep_stream(%p)=%d, stream(%p)=%d\n", dep_stream,
|
||||
dep_stream->stream_id, stream, stream->stream_id);
|
||||
|
||||
stream->sum_dep_weight = dep_stream->sum_dep_weight;
|
||||
dep_stream->sum_dep_weight = stream->weight;
|
||||
|
||||
if (dep_stream->dep_next) {
|
||||
for (si = dep_stream->dep_next; si; si = si->sib_next) {
|
||||
si->dep_prev = stream;
|
||||
if (si->queued) {
|
||||
rv = stream_obq_move(stream, dep_stream, si);
|
||||
if (rv != 0) {
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (stream_subtree_active(stream)) {
|
||||
rv = stream_obq_push(dep_stream, stream);
|
||||
if (rv != 0) {
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
|
||||
stream->dep_next = dep_stream->dep_next;
|
||||
}
|
||||
|
||||
dep_stream->dep_next = stream;
|
||||
stream->dep_prev = dep_stream;
|
||||
|
||||
validate_tree(stream);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void set_dep_prev(nghttp2_stream *stream, nghttp2_stream *dep) {
|
||||
for (; stream; stream = stream->sib_next) {
|
||||
stream->dep_prev = dep;
|
||||
}
|
||||
}
|
||||
|
||||
static void link_dep(nghttp2_stream *dep_stream, nghttp2_stream *stream) {
|
||||
dep_stream->dep_next = stream;
|
||||
if (stream) {
|
||||
stream->dep_prev = dep_stream;
|
||||
}
|
||||
}
|
||||
|
||||
static void link_sib(nghttp2_stream *a, nghttp2_stream *b) {
|
||||
a->sib_next = b;
|
||||
if (b) {
|
||||
b->sib_prev = a;
|
||||
}
|
||||
}
|
||||
|
||||
static void insert_link_dep(nghttp2_stream *dep_stream,
|
||||
nghttp2_stream *stream) {
|
||||
nghttp2_stream *sib_next;
|
||||
|
||||
assert(stream->sib_prev == NULL);
|
||||
|
||||
sib_next = dep_stream->dep_next;
|
||||
|
||||
link_sib(stream, sib_next);
|
||||
|
||||
link_dep(dep_stream, stream);
|
||||
}
|
||||
|
||||
static void unlink_sib(nghttp2_stream *stream) {
|
||||
nghttp2_stream *prev, *next, *dep_next;
|
||||
|
||||
prev = stream->sib_prev;
|
||||
dep_next = stream->dep_next;
|
||||
|
||||
assert(prev);
|
||||
|
||||
if (dep_next) {
|
||||
/*
|
||||
* prev--stream(--sib_next--...)
|
||||
* |
|
||||
* dep_next
|
||||
*/
|
||||
|
||||
link_sib(prev, dep_next);
|
||||
|
||||
set_dep_prev(dep_next, stream->dep_prev);
|
||||
|
||||
if (stream->sib_next) {
|
||||
link_sib(stream_last_sib(dep_next), stream->sib_next);
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* prev--stream(--sib_next--...)
|
||||
*/
|
||||
next = stream->sib_next;
|
||||
|
||||
prev->sib_next = next;
|
||||
|
||||
if (next) {
|
||||
next->sib_prev = prev;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void unlink_dep(nghttp2_stream *stream) {
|
||||
nghttp2_stream *prev, *next, *dep_next;
|
||||
|
||||
prev = stream->dep_prev;
|
||||
dep_next = stream->dep_next;
|
||||
|
||||
assert(prev);
|
||||
|
||||
if (dep_next) {
|
||||
/*
|
||||
* prev
|
||||
* |
|
||||
* stream(--sib_next--...)
|
||||
* |
|
||||
* dep_next
|
||||
*/
|
||||
link_dep(prev, dep_next);
|
||||
|
||||
set_dep_prev(dep_next, stream->dep_prev);
|
||||
|
||||
if (stream->sib_next) {
|
||||
link_sib(stream_last_sib(dep_next), stream->sib_next);
|
||||
}
|
||||
|
||||
} else if (stream->sib_next) {
|
||||
/*
|
||||
* prev
|
||||
* |
|
||||
* stream--sib_next
|
||||
*/
|
||||
next = stream->sib_next;
|
||||
|
||||
next->sib_prev = NULL;
|
||||
|
||||
link_dep(prev, next);
|
||||
} else {
|
||||
prev->dep_next = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void nghttp2_stream_dep_add(nghttp2_stream *dep_stream,
|
||||
nghttp2_stream *stream) {
|
||||
DEBUGF("stream: dep_add dep_stream(%p)=%d, stream(%p)=%d\n", dep_stream,
|
||||
dep_stream->stream_id, stream, stream->stream_id);
|
||||
|
||||
dep_stream->sum_dep_weight += stream->weight;
|
||||
|
||||
if (dep_stream->dep_next == NULL) {
|
||||
link_dep(dep_stream, stream);
|
||||
} else {
|
||||
insert_link_dep(dep_stream, stream);
|
||||
}
|
||||
|
||||
validate_tree(stream);
|
||||
}
|
||||
|
||||
int nghttp2_stream_dep_remove(nghttp2_stream *stream) {
|
||||
nghttp2_stream *dep_prev, *si;
|
||||
int32_t sum_dep_weight_delta;
|
||||
int rv;
|
||||
|
||||
DEBUGF("stream: dep_remove stream(%p)=%d\n", stream, stream->stream_id);
|
||||
|
||||
/* Distribute weight of |stream| to direct descendants */
|
||||
sum_dep_weight_delta = -stream->weight;
|
||||
|
||||
for (si = stream->dep_next; si; si = si->sib_next) {
|
||||
si->weight = nghttp2_stream_dep_distributed_weight(stream, si->weight);
|
||||
|
||||
sum_dep_weight_delta += si->weight;
|
||||
|
||||
if (si->queued) {
|
||||
rv = stream_obq_move(stream->dep_prev, stream, si);
|
||||
if (rv != 0) {
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
assert(stream->dep_prev);
|
||||
|
||||
dep_prev = stream->dep_prev;
|
||||
|
||||
dep_prev->sum_dep_weight += sum_dep_weight_delta;
|
||||
|
||||
if (stream->queued) {
|
||||
stream_obq_remove(stream);
|
||||
}
|
||||
|
||||
if (stream->sib_prev) {
|
||||
unlink_sib(stream);
|
||||
} else {
|
||||
unlink_dep(stream);
|
||||
}
|
||||
|
||||
stream->sum_dep_weight = 0;
|
||||
|
||||
stream->dep_prev = NULL;
|
||||
stream->dep_next = NULL;
|
||||
stream->sib_prev = NULL;
|
||||
stream->sib_next = NULL;
|
||||
|
||||
validate_tree(dep_prev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int nghttp2_stream_dep_insert_subtree(nghttp2_stream *dep_stream,
|
||||
nghttp2_stream *stream) {
|
||||
nghttp2_stream *last_sib;
|
||||
nghttp2_stream *dep_next;
|
||||
nghttp2_stream *si;
|
||||
int rv;
|
||||
|
||||
DEBUGF("stream: dep_insert_subtree dep_stream(%p)=%d stream(%p)=%d\n",
|
||||
dep_stream, dep_stream->stream_id, stream, stream->stream_id);
|
||||
|
||||
stream->sum_dep_weight += dep_stream->sum_dep_weight;
|
||||
dep_stream->sum_dep_weight = stream->weight;
|
||||
|
||||
if (dep_stream->dep_next) {
|
||||
dep_next = dep_stream->dep_next;
|
||||
|
||||
link_dep(dep_stream, stream);
|
||||
|
||||
if (stream->dep_next) {
|
||||
last_sib = stream_last_sib(stream->dep_next);
|
||||
|
||||
link_sib(last_sib, dep_next);
|
||||
} else {
|
||||
link_dep(stream, dep_next);
|
||||
}
|
||||
|
||||
for (si = dep_next; si; si = si->sib_next) {
|
||||
si->dep_prev = stream;
|
||||
if (si->queued) {
|
||||
rv = stream_obq_move(stream, dep_stream, si);
|
||||
if (rv != 0) {
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
link_dep(dep_stream, stream);
|
||||
}
|
||||
|
||||
if (stream_subtree_active(stream)) {
|
||||
rv = stream_obq_push(dep_stream, stream);
|
||||
if (rv != 0) {
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
|
||||
validate_tree(dep_stream);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int nghttp2_stream_dep_add_subtree(nghttp2_stream *dep_stream,
|
||||
nghttp2_stream *stream) {
|
||||
int rv;
|
||||
|
||||
DEBUGF("stream: dep_add_subtree dep_stream(%p)=%d stream(%p)=%d\n",
|
||||
dep_stream, dep_stream->stream_id, stream, stream->stream_id);
|
||||
|
||||
dep_stream->sum_dep_weight += stream->weight;
|
||||
|
||||
if (dep_stream->dep_next) {
|
||||
insert_link_dep(dep_stream, stream);
|
||||
} else {
|
||||
link_dep(dep_stream, stream);
|
||||
}
|
||||
|
||||
if (stream_subtree_active(stream)) {
|
||||
rv = stream_obq_push(dep_stream, stream);
|
||||
if (rv != 0) {
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
|
||||
validate_tree(dep_stream);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void nghttp2_stream_dep_remove_subtree(nghttp2_stream *stream) {
|
||||
nghttp2_stream *next, *dep_prev;
|
||||
|
||||
DEBUGF("stream: dep_remove_subtree stream(%p)=%d\n", stream,
|
||||
stream->stream_id);
|
||||
|
||||
assert(stream->dep_prev);
|
||||
|
||||
dep_prev = stream->dep_prev;
|
||||
|
||||
if (stream->sib_prev) {
|
||||
link_sib(stream->sib_prev, stream->sib_next);
|
||||
} else {
|
||||
next = stream->sib_next;
|
||||
|
||||
link_dep(dep_prev, next);
|
||||
|
||||
if (next) {
|
||||
next->sib_prev = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
dep_prev->sum_dep_weight -= stream->weight;
|
||||
|
||||
if (stream->queued) {
|
||||
stream_obq_remove(stream);
|
||||
}
|
||||
|
||||
validate_tree(dep_prev);
|
||||
|
||||
stream->sib_prev = NULL;
|
||||
stream->sib_next = NULL;
|
||||
stream->dep_prev = NULL;
|
||||
}
|
||||
|
||||
int nghttp2_stream_in_dep_tree(nghttp2_stream *stream) {
|
||||
return stream->dep_prev || stream->dep_next || stream->sib_prev ||
|
||||
stream->sib_next;
|
||||
}
|
||||
|
||||
nghttp2_outbound_item *
|
||||
nghttp2_stream_next_outbound_item(nghttp2_stream *stream) {
|
||||
nghttp2_pq_entry *ent;
|
||||
nghttp2_stream *si;
|
||||
|
||||
for (;;) {
|
||||
if (stream_active(stream)) {
|
||||
/* Update ascendant's descendant_last_cycle here, so that we can
|
||||
assure that new stream is scheduled based on it. */
|
||||
for (si = stream; si->dep_prev; si = si->dep_prev) {
|
||||
si->dep_prev->descendant_last_cycle = si->cycle;
|
||||
}
|
||||
return stream->item;
|
||||
}
|
||||
ent = nghttp2_pq_top(&stream->obq);
|
||||
if (!ent) {
|
||||
return NULL;
|
||||
}
|
||||
stream = nghttp2_struct_of(ent, nghttp2_stream, pq_entry);
|
||||
}
|
||||
}
|
||||
|
||||
nghttp2_stream_proto_state nghttp2_stream_get_state(nghttp2_stream *stream) {
|
||||
if (stream->flags & NGHTTP2_STREAM_FLAG_CLOSED) {
|
||||
return NGHTTP2_STREAM_STATE_CLOSED;
|
||||
}
|
||||
@@ -185,39 +988,27 @@ nghttp2_stream_proto_state nghttp2_stream_get_state(nghttp2_stream *stream) {
|
||||
}
|
||||
|
||||
nghttp2_stream *nghttp2_stream_get_parent(nghttp2_stream *stream) {
|
||||
(void)stream;
|
||||
|
||||
return NULL;
|
||||
return stream->dep_prev;
|
||||
}
|
||||
|
||||
nghttp2_stream *nghttp2_stream_get_next_sibling(nghttp2_stream *stream) {
|
||||
(void)stream;
|
||||
|
||||
return NULL;
|
||||
return stream->sib_next;
|
||||
}
|
||||
|
||||
nghttp2_stream *nghttp2_stream_get_previous_sibling(nghttp2_stream *stream) {
|
||||
(void)stream;
|
||||
|
||||
return NULL;
|
||||
return stream->sib_prev;
|
||||
}
|
||||
|
||||
nghttp2_stream *nghttp2_stream_get_first_child(nghttp2_stream *stream) {
|
||||
(void)stream;
|
||||
|
||||
return NULL;
|
||||
return stream->dep_next;
|
||||
}
|
||||
|
||||
int32_t nghttp2_stream_get_weight(nghttp2_stream *stream) {
|
||||
(void)stream;
|
||||
|
||||
return NGHTTP2_DEFAULT_WEIGHT;
|
||||
return stream->weight;
|
||||
}
|
||||
|
||||
int32_t nghttp2_stream_get_sum_dependency_weight(nghttp2_stream *stream) {
|
||||
(void)stream;
|
||||
|
||||
return 0;
|
||||
return stream->sum_dep_weight;
|
||||
}
|
||||
|
||||
int32_t nghttp2_stream_get_stream_id(nghttp2_stream *stream) {
|
||||
|
||||
@@ -91,6 +91,9 @@ typedef enum {
|
||||
/* bitwise OR of NGHTTP2_STREAM_FLAG_DEFERRED_FLOW_CONTROL and
|
||||
NGHTTP2_STREAM_FLAG_DEFERRED_USER. */
|
||||
NGHTTP2_STREAM_FLAG_DEFERRED_ALL = 0x0c,
|
||||
/* Indicates that this stream is not subject to RFC7540
|
||||
priorities scheme. */
|
||||
NGHTTP2_STREAM_FLAG_NO_RFC7540_PRIORITIES = 0x10,
|
||||
/* Ignore client RFC 9218 priority signal. */
|
||||
NGHTTP2_STREAM_FLAG_IGNORE_CLIENT_PRIORITIES = 0x20,
|
||||
/* Indicates that RFC 9113 leading and trailing white spaces
|
||||
@@ -121,9 +124,10 @@ typedef enum {
|
||||
NGHTTP2_HTTP_FLAG_METH_HEAD = 1 << 8,
|
||||
NGHTTP2_HTTP_FLAG_METH_OPTIONS = 1 << 9,
|
||||
NGHTTP2_HTTP_FLAG_METH_UPGRADE_WORKAROUND = 1 << 10,
|
||||
NGHTTP2_HTTP_FLAG_METH_ALL =
|
||||
NGHTTP2_HTTP_FLAG_METH_CONNECT | NGHTTP2_HTTP_FLAG_METH_HEAD |
|
||||
NGHTTP2_HTTP_FLAG_METH_OPTIONS | NGHTTP2_HTTP_FLAG_METH_UPGRADE_WORKAROUND,
|
||||
NGHTTP2_HTTP_FLAG_METH_ALL = NGHTTP2_HTTP_FLAG_METH_CONNECT |
|
||||
NGHTTP2_HTTP_FLAG_METH_HEAD |
|
||||
NGHTTP2_HTTP_FLAG_METH_OPTIONS |
|
||||
NGHTTP2_HTTP_FLAG_METH_UPGRADE_WORKAROUND,
|
||||
/* :path category */
|
||||
/* path starts with "/" */
|
||||
NGHTTP2_HTTP_FLAG_PATH_REGULAR = 1 << 11,
|
||||
@@ -143,18 +147,39 @@ typedef enum {
|
||||
} nghttp2_http_flag;
|
||||
|
||||
struct nghttp2_stream {
|
||||
nghttp2_stream_state state;
|
||||
/* Entry for dep_prev->obq */
|
||||
nghttp2_pq_entry pq_entry;
|
||||
/* Priority Queue storing direct descendant (nghttp2_stream). Only
|
||||
streams which itself has some data to send, or has a descendant
|
||||
which has some data to sent. */
|
||||
nghttp2_pq obq;
|
||||
/* Content-Length of request/response body. -1 if unknown. */
|
||||
int64_t content_length;
|
||||
/* Received body so far */
|
||||
int64_t recv_content_length;
|
||||
/* Base last_cycle for direct descendent streams. */
|
||||
uint64_t descendant_last_cycle;
|
||||
/* Next scheduled time to sent item */
|
||||
uint64_t cycle;
|
||||
/* Next seq used for direct descendant streams */
|
||||
uint64_t descendant_next_seq;
|
||||
/* Secondary key for prioritization to break a tie for cycle. This
|
||||
value is monotonically increased for single parent stream. */
|
||||
uint64_t seq;
|
||||
nghttp2_stream *closed_next;
|
||||
/* pointers to form dependency tree. If multiple streams depend on
|
||||
a stream, only one stream (left most) has non-NULL dep_prev which
|
||||
points to the stream it depends on. The remaining streams are
|
||||
linked using sib_prev and sib_next. The stream which has
|
||||
non-NULL dep_prev always NULL sib_prev. The right most stream
|
||||
has NULL sib_next. If this stream is a root of dependency tree,
|
||||
dep_prev and sib_prev are NULL. */
|
||||
nghttp2_stream *dep_prev, *dep_next;
|
||||
nghttp2_stream *sib_prev, *sib_next;
|
||||
/* When stream is kept after closure, it may be kept in doubly
|
||||
linked list pointed by nghttp2_session closed_stream_head.
|
||||
closed_next points to the next stream object if it is the element
|
||||
of the list. */
|
||||
nghttp2_stream *closed_prev, *closed_next;
|
||||
/* The arbitrary data provided by user for this stream. */
|
||||
void *stream_user_data;
|
||||
/* Item to send */
|
||||
@@ -181,8 +206,13 @@ struct nghttp2_stream {
|
||||
NGHTTP2_INITIAL_WINDOW_SIZE and could be increased/decreased by
|
||||
submitting WINDOW_UPDATE. See nghttp2_submit_window_update(). */
|
||||
int32_t local_window_size;
|
||||
/* weight of this stream */
|
||||
int32_t weight;
|
||||
/* This is unpaid penalty (offset) when calculating cycle. */
|
||||
uint32_t pending_penalty;
|
||||
/* sum of weight of direct descendants */
|
||||
int32_t sum_dep_weight;
|
||||
nghttp2_stream_state state;
|
||||
/* status code from remote server */
|
||||
int16_t status_code;
|
||||
/* Bitwise OR of zero or more nghttp2_http_flag values */
|
||||
@@ -210,9 +240,9 @@ struct nghttp2_stream {
|
||||
|
||||
void nghttp2_stream_init(nghttp2_stream *stream, int32_t stream_id,
|
||||
uint8_t flags, nghttp2_stream_state initial_state,
|
||||
int32_t remote_initial_window_size,
|
||||
int32_t weight, int32_t remote_initial_window_size,
|
||||
int32_t local_initial_window_size,
|
||||
void *stream_user_data);
|
||||
void *stream_user_data, nghttp2_mem *mem);
|
||||
|
||||
void nghttp2_stream_free(nghttp2_stream *stream);
|
||||
|
||||
@@ -238,8 +268,14 @@ void nghttp2_stream_defer_item(nghttp2_stream *stream, uint8_t flags);
|
||||
* NGHTTP2_STREAM_FLAG_DEFERRED_FLOW_CONTROL and given masks are
|
||||
* cleared if they are set. So even if this function is called, if
|
||||
* one of flag is still set, data does not become active.
|
||||
*
|
||||
* This function returns 0 if it succeeds, or one of the following
|
||||
* negative error codes:
|
||||
*
|
||||
* NGHTTP2_ERR_NOMEM
|
||||
* Out of memory
|
||||
*/
|
||||
void nghttp2_stream_resume_deferred_item(nghttp2_stream *stream, uint8_t flags);
|
||||
int nghttp2_stream_resume_deferred_item(nghttp2_stream *stream, uint8_t flags);
|
||||
|
||||
/*
|
||||
* Returns nonzero if item is deferred by whatever reason.
|
||||
@@ -260,8 +296,8 @@ int nghttp2_stream_check_deferred_by_flow_control(nghttp2_stream *stream);
|
||||
* overflow.
|
||||
*/
|
||||
int nghttp2_stream_update_remote_initial_window_size(
|
||||
nghttp2_stream *stream, int32_t new_initial_window_size,
|
||||
int32_t old_initial_window_size);
|
||||
nghttp2_stream *stream, int32_t new_initial_window_size,
|
||||
int32_t old_initial_window_size);
|
||||
|
||||
/*
|
||||
* Updates the local window size with the new value
|
||||
@@ -272,8 +308,8 @@ int nghttp2_stream_update_remote_initial_window_size(
|
||||
* overflow.
|
||||
*/
|
||||
int nghttp2_stream_update_local_initial_window_size(
|
||||
nghttp2_stream *stream, int32_t new_initial_window_size,
|
||||
int32_t old_initial_window_size);
|
||||
nghttp2_stream *stream, int32_t new_initial_window_size,
|
||||
int32_t old_initial_window_size);
|
||||
|
||||
/*
|
||||
* Call this function if promised stream |stream| is replied with
|
||||
@@ -283,10 +319,56 @@ int nghttp2_stream_update_local_initial_window_size(
|
||||
void nghttp2_stream_promise_fulfilled(nghttp2_stream *stream);
|
||||
|
||||
/*
|
||||
* Attaches |item| to |stream|.
|
||||
* Returns nonzero if |target| is an ancestor of |stream|.
|
||||
*/
|
||||
void nghttp2_stream_attach_item(nghttp2_stream *stream,
|
||||
nghttp2_outbound_item *item);
|
||||
int nghttp2_stream_dep_find_ancestor(nghttp2_stream *stream,
|
||||
nghttp2_stream *target);
|
||||
|
||||
/*
|
||||
* Computes distributed weight of a stream of the |weight| under the
|
||||
* |stream| if |stream| is removed from a dependency tree.
|
||||
*/
|
||||
int32_t nghttp2_stream_dep_distributed_weight(nghttp2_stream *stream,
|
||||
int32_t weight);
|
||||
|
||||
/*
|
||||
* Makes the |stream| depend on the |dep_stream|. This dependency is
|
||||
* exclusive. All existing direct descendants of |dep_stream| become
|
||||
* the descendants of the |stream|. This function assumes
|
||||
* |stream->item| is NULL.
|
||||
*
|
||||
* This function returns 0 if it succeeds, or one of the following
|
||||
* negative error codes:
|
||||
*
|
||||
* NGHTTP2_ERR_NOMEM
|
||||
* Out of memory
|
||||
*/
|
||||
int nghttp2_stream_dep_insert(nghttp2_stream *dep_stream,
|
||||
nghttp2_stream *stream);
|
||||
|
||||
/*
|
||||
* Makes the |stream| depend on the |dep_stream|. This dependency is
|
||||
* not exclusive. This function assumes |stream->item| is NULL.
|
||||
*/
|
||||
void nghttp2_stream_dep_add(nghttp2_stream *dep_stream, nghttp2_stream *stream);
|
||||
|
||||
/*
|
||||
* Removes the |stream| from the current dependency tree. This
|
||||
* function assumes |stream->item| is NULL.
|
||||
*/
|
||||
int nghttp2_stream_dep_remove(nghttp2_stream *stream);
|
||||
|
||||
/*
|
||||
* Attaches |item| to |stream|.
|
||||
*
|
||||
* This function returns 0 if it succeeds, or one of the following
|
||||
* negative error codes:
|
||||
*
|
||||
* NGHTTP2_ERR_NOMEM
|
||||
* Out of memory
|
||||
*/
|
||||
int nghttp2_stream_attach_item(nghttp2_stream *stream,
|
||||
nghttp2_outbound_item *item);
|
||||
|
||||
/*
|
||||
* Detaches |stream->item|. This function does not free
|
||||
@@ -294,4 +376,66 @@ void nghttp2_stream_attach_item(nghttp2_stream *stream,
|
||||
*/
|
||||
void nghttp2_stream_detach_item(nghttp2_stream *stream);
|
||||
|
||||
/*
|
||||
* Makes the |stream| depend on the |dep_stream|. This dependency is
|
||||
* exclusive.
|
||||
*
|
||||
* This function returns 0 if it succeeds, or one of the following
|
||||
* negative error codes:
|
||||
*
|
||||
* NGHTTP2_ERR_NOMEM
|
||||
* Out of memory
|
||||
*/
|
||||
int nghttp2_stream_dep_insert_subtree(nghttp2_stream *dep_stream,
|
||||
nghttp2_stream *stream);
|
||||
|
||||
/*
|
||||
* Makes the |stream| depend on the |dep_stream|. This dependency is
|
||||
* not exclusive.
|
||||
*
|
||||
* This function returns 0 if it succeeds, or one of the following
|
||||
* negative error codes:
|
||||
*
|
||||
* NGHTTP2_ERR_NOMEM
|
||||
* Out of memory
|
||||
*/
|
||||
int nghttp2_stream_dep_add_subtree(nghttp2_stream *dep_stream,
|
||||
nghttp2_stream *stream);
|
||||
|
||||
/*
|
||||
* Removes subtree whose root stream is |stream|. The
|
||||
* effective_weight of streams in removed subtree is not updated.
|
||||
*
|
||||
* This function returns 0 if it succeeds, or one of the following
|
||||
* negative error codes:
|
||||
*
|
||||
* NGHTTP2_ERR_NOMEM
|
||||
* Out of memory
|
||||
*/
|
||||
void nghttp2_stream_dep_remove_subtree(nghttp2_stream *stream);
|
||||
|
||||
/*
|
||||
* Returns nonzero if |stream| is in any dependency tree.
|
||||
*/
|
||||
int nghttp2_stream_in_dep_tree(nghttp2_stream *stream);
|
||||
|
||||
/*
|
||||
* Schedules transmission of |stream|'s item, assuming stream->item is
|
||||
* attached, and stream->last_writelen was updated.
|
||||
*/
|
||||
void nghttp2_stream_reschedule(nghttp2_stream *stream);
|
||||
|
||||
/*
|
||||
* Changes |stream|'s weight to |weight|. If |stream| is queued, it
|
||||
* will be rescheduled based on new weight.
|
||||
*/
|
||||
void nghttp2_stream_change_weight(nghttp2_stream *stream, int32_t weight);
|
||||
|
||||
/*
|
||||
* Returns a stream which has highest priority, updating
|
||||
* descendant_last_cycle of selected stream's ancestors.
|
||||
*/
|
||||
nghttp2_outbound_item *
|
||||
nghttp2_stream_next_outbound_item(nghttp2_stream *stream);
|
||||
|
||||
#endif /* NGHTTP2_STREAM */
|
||||
|
||||
@@ -32,12 +32,42 @@
|
||||
#include "nghttp2_helper.h"
|
||||
#include "nghttp2_priority_spec.h"
|
||||
|
||||
/*
|
||||
* Detects the dependency error, that is stream attempted to depend on
|
||||
* itself. If |stream_id| is -1, we use session->next_stream_id as
|
||||
* stream ID.
|
||||
*
|
||||
* This function returns 0 if it succeeds, or one of the following
|
||||
* error codes:
|
||||
*
|
||||
* NGHTTP2_ERR_INVALID_ARGUMENT
|
||||
* Stream attempted to depend on itself.
|
||||
*/
|
||||
static int detect_self_dependency(nghttp2_session *session, int32_t stream_id,
|
||||
const nghttp2_priority_spec *pri_spec) {
|
||||
assert(pri_spec);
|
||||
|
||||
if (stream_id == -1) {
|
||||
if ((int32_t)session->next_stream_id == pri_spec->stream_id) {
|
||||
return NGHTTP2_ERR_INVALID_ARGUMENT;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (stream_id == pri_spec->stream_id) {
|
||||
return NGHTTP2_ERR_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* This function takes ownership of |nva_copy|. Regardless of the
|
||||
return value, the caller must not free |nva_copy| after this
|
||||
function returns. */
|
||||
static int32_t submit_headers_shared(nghttp2_session *session, uint8_t flags,
|
||||
int32_t stream_id, nghttp2_nv *nva_copy,
|
||||
size_t nvlen,
|
||||
int32_t stream_id,
|
||||
const nghttp2_priority_spec *pri_spec,
|
||||
nghttp2_nv *nva_copy, size_t nvlen,
|
||||
const nghttp2_data_provider_wrap *dpw,
|
||||
void *stream_user_data) {
|
||||
int rv;
|
||||
@@ -64,8 +94,8 @@ static int32_t submit_headers_shared(nghttp2_session *session, uint8_t flags,
|
||||
item->aux_data.headers.stream_user_data = stream_user_data;
|
||||
|
||||
flags_copy =
|
||||
(uint8_t)((flags & (NGHTTP2_FLAG_END_STREAM | NGHTTP2_FLAG_PRIORITY)) |
|
||||
NGHTTP2_FLAG_END_HEADERS);
|
||||
(uint8_t)((flags & (NGHTTP2_FLAG_END_STREAM | NGHTTP2_FLAG_PRIORITY)) |
|
||||
NGHTTP2_FLAG_END_HEADERS);
|
||||
|
||||
if (stream_id == -1) {
|
||||
if (session->next_stream_id > INT32_MAX) {
|
||||
@@ -84,8 +114,8 @@ static int32_t submit_headers_shared(nghttp2_session *session, uint8_t flags,
|
||||
|
||||
frame = &item->frame;
|
||||
|
||||
nghttp2_frame_headers_init(&frame->headers, flags_copy, stream_id, hcat, NULL,
|
||||
nva_copy, nvlen);
|
||||
nghttp2_frame_headers_init(&frame->headers, flags_copy, stream_id, hcat,
|
||||
pri_spec, nva_copy, nvlen);
|
||||
|
||||
rv = nghttp2_session_add_item(session, item);
|
||||
|
||||
@@ -111,22 +141,31 @@ fail2:
|
||||
|
||||
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_wrap *dpw,
|
||||
void *stream_user_data) {
|
||||
int rv;
|
||||
nghttp2_nv *nva_copy;
|
||||
nghttp2_priority_spec copy_pri_spec;
|
||||
nghttp2_mem *mem;
|
||||
|
||||
mem = &session->mem;
|
||||
|
||||
if (pri_spec) {
|
||||
copy_pri_spec = *pri_spec;
|
||||
nghttp2_priority_spec_normalize_weight(©_pri_spec);
|
||||
} else {
|
||||
nghttp2_priority_spec_default_init(©_pri_spec);
|
||||
}
|
||||
|
||||
rv = nghttp2_nv_array_copy(&nva_copy, nva, nvlen, mem);
|
||||
if (rv < 0) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
return submit_headers_shared(session, flags, stream_id, nva_copy, nvlen, dpw,
|
||||
stream_user_data);
|
||||
return submit_headers_shared(session, flags, stream_id, ©_pri_spec,
|
||||
nva_copy, nvlen, dpw, stream_user_data);
|
||||
}
|
||||
|
||||
int nghttp2_submit_trailer(nghttp2_session *session, int32_t stream_id,
|
||||
@@ -136,7 +175,8 @@ int nghttp2_submit_trailer(nghttp2_session *session, int32_t stream_id,
|
||||
}
|
||||
|
||||
return (int)submit_headers_shared_nva(session, NGHTTP2_FLAG_END_STREAM,
|
||||
stream_id, nva, nvlen, NULL, NULL);
|
||||
stream_id, NULL, nva, nvlen, NULL,
|
||||
NULL);
|
||||
}
|
||||
|
||||
int32_t nghttp2_submit_headers(nghttp2_session *session, uint8_t flags,
|
||||
@@ -144,7 +184,7 @@ int32_t nghttp2_submit_headers(nghttp2_session *session, uint8_t flags,
|
||||
const nghttp2_priority_spec *pri_spec,
|
||||
const nghttp2_nv *nva, size_t nvlen,
|
||||
void *stream_user_data) {
|
||||
(void)pri_spec;
|
||||
int rv;
|
||||
|
||||
if (stream_id == -1) {
|
||||
if (session->server) {
|
||||
@@ -156,8 +196,20 @@ int32_t nghttp2_submit_headers(nghttp2_session *session, uint8_t flags,
|
||||
|
||||
flags &= NGHTTP2_FLAG_END_STREAM;
|
||||
|
||||
return submit_headers_shared_nva(session, flags, stream_id, nva, nvlen, NULL,
|
||||
stream_user_data);
|
||||
if (pri_spec && !nghttp2_priority_spec_check_default(pri_spec) &&
|
||||
session->remote_settings.no_rfc7540_priorities != 1) {
|
||||
rv = detect_self_dependency(session, stream_id, pri_spec);
|
||||
if (rv != 0) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
flags |= NGHTTP2_FLAG_PRIORITY;
|
||||
} else {
|
||||
pri_spec = NULL;
|
||||
}
|
||||
|
||||
return submit_headers_shared_nva(session, flags, stream_id, pri_spec, nva,
|
||||
nvlen, NULL, stream_user_data);
|
||||
}
|
||||
|
||||
int nghttp2_submit_ping(nghttp2_session *session, uint8_t flags,
|
||||
@@ -169,10 +221,51 @@ int nghttp2_submit_ping(nghttp2_session *session, uint8_t flags,
|
||||
int nghttp2_submit_priority(nghttp2_session *session, uint8_t flags,
|
||||
int32_t stream_id,
|
||||
const nghttp2_priority_spec *pri_spec) {
|
||||
(void)session;
|
||||
int rv;
|
||||
nghttp2_outbound_item *item;
|
||||
nghttp2_frame *frame;
|
||||
nghttp2_priority_spec copy_pri_spec;
|
||||
nghttp2_mem *mem;
|
||||
(void)flags;
|
||||
(void)stream_id;
|
||||
(void)pri_spec;
|
||||
|
||||
mem = &session->mem;
|
||||
|
||||
if (session->remote_settings.no_rfc7540_priorities == 1) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (stream_id == 0 || pri_spec == NULL) {
|
||||
return NGHTTP2_ERR_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
if (stream_id == pri_spec->stream_id) {
|
||||
return NGHTTP2_ERR_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
copy_pri_spec = *pri_spec;
|
||||
|
||||
nghttp2_priority_spec_normalize_weight(©_pri_spec);
|
||||
|
||||
item = nghttp2_mem_malloc(mem, sizeof(nghttp2_outbound_item));
|
||||
|
||||
if (item == NULL) {
|
||||
return NGHTTP2_ERR_NOMEM;
|
||||
}
|
||||
|
||||
nghttp2_outbound_item_init(item);
|
||||
|
||||
frame = &item->frame;
|
||||
|
||||
nghttp2_frame_priority_init(&frame->priority, stream_id, ©_pri_spec);
|
||||
|
||||
rv = nghttp2_session_add_item(session, item);
|
||||
|
||||
if (rv != 0) {
|
||||
nghttp2_frame_priority_free(&frame->priority);
|
||||
nghttp2_mem_free(mem, item);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -185,8 +278,7 @@ int nghttp2_submit_rst_stream(nghttp2_session *session, uint8_t flags,
|
||||
return NGHTTP2_ERR_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
return nghttp2_session_add_rst_stream_continue(
|
||||
session, stream_id, error_code, /* continue_without_stream = */ 0);
|
||||
return nghttp2_session_add_rst_stream(session, stream_id, error_code);
|
||||
}
|
||||
|
||||
int nghttp2_submit_goaway(nghttp2_session *session, uint8_t flags,
|
||||
@@ -297,8 +389,8 @@ int nghttp2_submit_window_update(nghttp2_session *session, uint8_t flags,
|
||||
}
|
||||
if (stream_id == 0) {
|
||||
rv = nghttp2_adjust_local_window_size(
|
||||
&session->local_window_size, &session->recv_window_size,
|
||||
&session->recv_reduction, &window_size_increment);
|
||||
&session->local_window_size, &session->recv_window_size,
|
||||
&session->recv_reduction, &window_size_increment);
|
||||
if (rv != 0) {
|
||||
return rv;
|
||||
}
|
||||
@@ -309,8 +401,8 @@ int nghttp2_submit_window_update(nghttp2_session *session, uint8_t flags,
|
||||
}
|
||||
|
||||
rv = nghttp2_adjust_local_window_size(
|
||||
&stream->local_window_size, &stream->recv_window_size,
|
||||
&stream->recv_reduction, &window_size_increment);
|
||||
&stream->local_window_size, &stream->recv_window_size,
|
||||
&stream->recv_reduction, &window_size_increment);
|
||||
if (rv != 0) {
|
||||
return rv;
|
||||
}
|
||||
@@ -319,10 +411,10 @@ int nghttp2_submit_window_update(nghttp2_session *session, uint8_t flags,
|
||||
if (window_size_increment > 0) {
|
||||
if (stream_id == 0) {
|
||||
session->consumed_size =
|
||||
nghttp2_max_int32(0, session->consumed_size - window_size_increment);
|
||||
nghttp2_max_int32(0, session->consumed_size - window_size_increment);
|
||||
} else {
|
||||
stream->consumed_size =
|
||||
nghttp2_max_int32(0, stream->consumed_size - window_size_increment);
|
||||
nghttp2_max_int32(0, stream->consumed_size - window_size_increment);
|
||||
}
|
||||
|
||||
return nghttp2_session_add_window_update(session, 0, stream_id,
|
||||
@@ -352,13 +444,13 @@ int nghttp2_session_set_local_window_size(nghttp2_session *session,
|
||||
|
||||
if (window_size_increment < 0) {
|
||||
return nghttp2_adjust_local_window_size(
|
||||
&session->local_window_size, &session->recv_window_size,
|
||||
&session->recv_reduction, &window_size_increment);
|
||||
&session->local_window_size, &session->recv_window_size,
|
||||
&session->recv_reduction, &window_size_increment);
|
||||
}
|
||||
|
||||
rv = nghttp2_increase_local_window_size(
|
||||
&session->local_window_size, &session->recv_window_size,
|
||||
&session->recv_reduction, &window_size_increment);
|
||||
&session->local_window_size, &session->recv_window_size,
|
||||
&session->recv_reduction, &window_size_increment);
|
||||
|
||||
if (rv != 0) {
|
||||
return rv;
|
||||
@@ -385,13 +477,13 @@ int nghttp2_session_set_local_window_size(nghttp2_session *session,
|
||||
|
||||
if (window_size_increment < 0) {
|
||||
return nghttp2_adjust_local_window_size(
|
||||
&stream->local_window_size, &stream->recv_window_size,
|
||||
&stream->recv_reduction, &window_size_increment);
|
||||
&stream->local_window_size, &stream->recv_window_size,
|
||||
&stream->recv_reduction, &window_size_increment);
|
||||
}
|
||||
|
||||
rv = nghttp2_increase_local_window_size(
|
||||
&stream->local_window_size, &stream->recv_window_size,
|
||||
&stream->recv_reduction, &window_size_increment);
|
||||
&stream->local_window_size, &stream->recv_window_size,
|
||||
&stream->recv_reduction, &window_size_increment);
|
||||
|
||||
if (rv != 0) {
|
||||
return rv;
|
||||
@@ -487,7 +579,7 @@ int nghttp2_submit_altsvc(nghttp2_session *session, uint8_t flags,
|
||||
return 0;
|
||||
|
||||
fail_item_malloc:
|
||||
nghttp2_mem_free(mem, buf);
|
||||
free(buf);
|
||||
|
||||
return rv;
|
||||
}
|
||||
@@ -522,7 +614,7 @@ int nghttp2_submit_origin(nghttp2_session *session, uint8_t flags,
|
||||
|
||||
/* The last nov is added for terminal NULL character. */
|
||||
ov_copy =
|
||||
nghttp2_mem_malloc(mem, nov * sizeof(nghttp2_origin_entry) + len + nov);
|
||||
nghttp2_mem_malloc(mem, nov * sizeof(nghttp2_origin_entry) + len + nov);
|
||||
if (ov_copy == NULL) {
|
||||
return NGHTTP2_ERR_NOMEM;
|
||||
}
|
||||
@@ -570,7 +662,7 @@ int nghttp2_submit_origin(nghttp2_session *session, uint8_t flags,
|
||||
return 0;
|
||||
|
||||
fail_item_malloc:
|
||||
nghttp2_mem_free(mem, ov_copy);
|
||||
free(ov_copy);
|
||||
|
||||
return rv;
|
||||
}
|
||||
@@ -642,34 +734,51 @@ int nghttp2_submit_priority_update(nghttp2_session *session, uint8_t flags,
|
||||
return 0;
|
||||
|
||||
fail_item_malloc:
|
||||
nghttp2_mem_free(mem, buf);
|
||||
free(buf);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
static uint8_t set_request_flags(const nghttp2_data_provider_wrap *dpw) {
|
||||
static uint8_t set_request_flags(const nghttp2_priority_spec *pri_spec,
|
||||
const nghttp2_data_provider_wrap *dpw) {
|
||||
uint8_t flags = NGHTTP2_FLAG_NONE;
|
||||
if (dpw == NULL || dpw->data_prd.read_callback == NULL) {
|
||||
flags |= NGHTTP2_FLAG_END_STREAM;
|
||||
}
|
||||
|
||||
if (pri_spec) {
|
||||
flags |= NGHTTP2_FLAG_PRIORITY;
|
||||
}
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
if (session->server) {
|
||||
return NGHTTP2_ERR_PROTO;
|
||||
}
|
||||
|
||||
flags = set_request_flags(dpw);
|
||||
if (pri_spec && !nghttp2_priority_spec_check_default(pri_spec) &&
|
||||
session->remote_settings.no_rfc7540_priorities != 1) {
|
||||
rv = detect_self_dependency(session, -1, pri_spec);
|
||||
if (rv != 0) {
|
||||
return rv;
|
||||
}
|
||||
} else {
|
||||
pri_spec = NULL;
|
||||
}
|
||||
|
||||
return submit_headers_shared_nva(session, flags, -1, nva, nvlen, dpw,
|
||||
stream_user_data);
|
||||
flags = set_request_flags(pri_spec, dpw);
|
||||
|
||||
return submit_headers_shared_nva(session, flags, -1, pri_spec, nva, nvlen,
|
||||
dpw, stream_user_data);
|
||||
}
|
||||
|
||||
int32_t nghttp2_submit_request(nghttp2_session *session,
|
||||
@@ -678,9 +787,8 @@ int32_t nghttp2_submit_request(nghttp2_session *session,
|
||||
const nghttp2_data_provider *data_prd,
|
||||
void *stream_user_data) {
|
||||
nghttp2_data_provider_wrap dpw;
|
||||
(void)pri_spec;
|
||||
|
||||
return submit_request_shared(session, nva, nvlen,
|
||||
return submit_request_shared(session, pri_spec, nva, nvlen,
|
||||
nghttp2_data_provider_wrap_v1(&dpw, data_prd),
|
||||
stream_user_data);
|
||||
}
|
||||
@@ -691,9 +799,8 @@ int32_t nghttp2_submit_request2(nghttp2_session *session,
|
||||
const nghttp2_data_provider2 *data_prd,
|
||||
void *stream_user_data) {
|
||||
nghttp2_data_provider_wrap dpw;
|
||||
(void)pri_spec;
|
||||
|
||||
return submit_request_shared(session, nva, nvlen,
|
||||
return submit_request_shared(session, pri_spec, nva, nvlen,
|
||||
nghttp2_data_provider_wrap_v2(&dpw, data_prd),
|
||||
stream_user_data);
|
||||
}
|
||||
@@ -720,8 +827,8 @@ static int submit_response_shared(nghttp2_session *session, int32_t stream_id,
|
||||
}
|
||||
|
||||
flags = set_response_flags(dpw);
|
||||
return submit_headers_shared_nva(session, flags, stream_id, nva, nvlen, dpw,
|
||||
NULL);
|
||||
return submit_headers_shared_nva(session, flags, stream_id, NULL, nva, nvlen,
|
||||
dpw, NULL);
|
||||
}
|
||||
|
||||
int nghttp2_submit_response(nghttp2_session *session, int32_t stream_id,
|
||||
@@ -791,7 +898,7 @@ int nghttp2_submit_data(nghttp2_session *session, uint8_t flags,
|
||||
assert(data_prd);
|
||||
|
||||
return nghttp2_submit_data_shared(
|
||||
session, flags, stream_id, nghttp2_data_provider_wrap_v1(&dpw, data_prd));
|
||||
session, flags, stream_id, nghttp2_data_provider_wrap_v1(&dpw, data_prd));
|
||||
}
|
||||
|
||||
int nghttp2_submit_data2(nghttp2_session *session, uint8_t flags,
|
||||
@@ -802,7 +909,7 @@ int nghttp2_submit_data2(nghttp2_session *session, uint8_t flags,
|
||||
assert(data_prd);
|
||||
|
||||
return nghttp2_submit_data_shared(
|
||||
session, flags, stream_id, nghttp2_data_provider_wrap_v2(&dpw, data_prd));
|
||||
session, flags, stream_id, nghttp2_data_provider_wrap_v2(&dpw, data_prd));
|
||||
}
|
||||
|
||||
ssize_t nghttp2_pack_settings_payload(uint8_t *buf, size_t buflen,
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
|
||||
#include <nghttp2/nghttp2.h>
|
||||
|
||||
#include "nghttp2_outbound_item.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,
|
||||
|
||||
@@ -45,7 +45,7 @@ static uint64_t time_now_sec(void) {
|
||||
#if defined(HAVE_GETTICKCOUNT64) && !defined(__CYGWIN__)
|
||||
uint64_t nghttp2_time_now_sec(void) { return GetTickCount64() / 1000; }
|
||||
#elif defined(HAVE_CLOCK_GETTIME) && defined(HAVE_DECL_CLOCK_MONOTONIC) && \
|
||||
HAVE_DECL_CLOCK_MONOTONIC
|
||||
HAVE_DECL_CLOCK_MONOTONIC
|
||||
uint64_t nghttp2_time_now_sec(void) {
|
||||
struct timespec tp;
|
||||
int rv = clock_gettime(CLOCK_MONOTONIC, &tp);
|
||||
|
||||
1177
lib/sfparse.c
1177
lib/sfparse.c
File diff suppressed because it is too large
Load Diff
313
lib/sfparse.h
313
lib/sfparse.h
@@ -31,90 +31,86 @@
|
||||
libcurl) */
|
||||
#if (defined(_WIN32) || defined(__WIN32__)) && !defined(WIN32)
|
||||
# define WIN32
|
||||
#endif /* (defined(_WIN32) || defined(__WIN32__)) && !defined(WIN32) */
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* defined(__cplusplus) */
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER < 1800)
|
||||
/* MSVC < 2013 does not have inttypes.h because it is not C99
|
||||
compliant. See compiler macros and version number in
|
||||
https://sourceforge.net/p/predef/wiki/Compilers/ */
|
||||
# include <stdint.h>
|
||||
#else /* !(defined(_MSC_VER) && (_MSC_VER < 1800)) */
|
||||
#else /* !defined(_MSC_VER) || (_MSC_VER >= 1800) */
|
||||
# include <inttypes.h>
|
||||
#endif /* !(defined(_MSC_VER) && (_MSC_VER < 1800)) */
|
||||
#endif /* !defined(_MSC_VER) || (_MSC_VER >= 1800) */
|
||||
#include <sys/types.h>
|
||||
#include <stddef.h>
|
||||
|
||||
/**
|
||||
* @enum
|
||||
*
|
||||
* :type:`sfparse_type` defines value type.
|
||||
* :type:`sf_type` defines value type.
|
||||
*/
|
||||
typedef enum sfparse_type {
|
||||
typedef enum sf_type {
|
||||
/**
|
||||
* :enum:`SFPARSE_TYPE_BOOLEAN` indicates boolean type.
|
||||
* :enum:`SF_TYPE_BOOLEAN` indicates boolean type.
|
||||
*/
|
||||
SFPARSE_TYPE_BOOLEAN,
|
||||
SF_TYPE_BOOLEAN,
|
||||
/**
|
||||
* :enum:`SFPARSE_TYPE_INTEGER` indicates integer type.
|
||||
* :enum:`SF_TYPE_INTEGER` indicates integer type.
|
||||
*/
|
||||
SFPARSE_TYPE_INTEGER,
|
||||
SF_TYPE_INTEGER,
|
||||
/**
|
||||
* :enum:`SFPARSE_TYPE_DECIMAL` indicates decimal type.
|
||||
* :enum:`SF_TYPE_DECIMAL` indicates decimal type.
|
||||
*/
|
||||
SFPARSE_TYPE_DECIMAL,
|
||||
SF_TYPE_DECIMAL,
|
||||
/**
|
||||
* :enum:`SFPARSE_TYPE_STRING` indicates string type.
|
||||
* :enum:`SF_TYPE_STRING` indicates string type.
|
||||
*/
|
||||
SFPARSE_TYPE_STRING,
|
||||
SF_TYPE_STRING,
|
||||
/**
|
||||
* :enum:`SFPARSE_TYPE_TOKEN` indicates token type.
|
||||
* :enum:`SF_TYPE_TOKEN` indicates token type.
|
||||
*/
|
||||
SFPARSE_TYPE_TOKEN,
|
||||
SF_TYPE_TOKEN,
|
||||
/**
|
||||
* :enum:`SFPARSE_TYPE_BYTESEQ` indicates byte sequence type.
|
||||
* :enum:`SF_TYPE_BYTESEQ` indicates byte sequence type.
|
||||
*/
|
||||
SFPARSE_TYPE_BYTESEQ,
|
||||
SF_TYPE_BYTESEQ,
|
||||
/**
|
||||
* :enum:`SFPARSE_TYPE_INNER_LIST` indicates inner list type.
|
||||
* :enum:`SF_TYPE_INNER_LIST` indicates inner list type.
|
||||
*/
|
||||
SFPARSE_TYPE_INNER_LIST,
|
||||
SF_TYPE_INNER_LIST,
|
||||
/**
|
||||
* :enum:`SFPARSE_TYPE_DATE` indicates date type.
|
||||
* :enum:`SF_TYPE_DATE` indicates date type.
|
||||
*/
|
||||
SFPARSE_TYPE_DATE,
|
||||
/**
|
||||
* :enum:`SFPARSE_TYPE_DISPSTRING` indicates display string type.
|
||||
*/
|
||||
SFPARSE_TYPE_DISPSTRING
|
||||
} sfparse_type;
|
||||
SF_TYPE_DATE
|
||||
} sf_type;
|
||||
|
||||
/**
|
||||
* @macro
|
||||
*
|
||||
* :macro:`SFPARSE_ERR_PARSE` indicates fatal parse error has
|
||||
* :macro:`SF_ERR_PARSE_ERROR` indicates fatal parse error has
|
||||
* occurred, and it is not possible to continue the processing.
|
||||
*/
|
||||
#define SFPARSE_ERR_PARSE -1
|
||||
#define SF_ERR_PARSE_ERROR -1
|
||||
|
||||
/**
|
||||
* @macro
|
||||
*
|
||||
* :macro:`SFPARSE_ERR_EOF` indicates that there is nothing left to
|
||||
* read. The context of this error varies depending on the function
|
||||
* that returns this error code.
|
||||
* :macro:`SF_ERR_EOF` indicates that there is nothing left to read.
|
||||
* The context of this error varies depending on the function that
|
||||
* returns this error code.
|
||||
*/
|
||||
#define SFPARSE_ERR_EOF -2
|
||||
#define SF_ERR_EOF -2
|
||||
|
||||
/**
|
||||
* @struct
|
||||
*
|
||||
* :type:`sfparse_vec` stores sequence of bytes.
|
||||
* :type:`sf_vec` stores sequence of bytes.
|
||||
*/
|
||||
typedef struct sfparse_vec {
|
||||
typedef struct sf_vec {
|
||||
/**
|
||||
* :member:`base` points to the beginning of the sequence of bytes.
|
||||
*/
|
||||
@@ -123,29 +119,29 @@ typedef struct sfparse_vec {
|
||||
* :member:`len` is the number of bytes contained in this sequence.
|
||||
*/
|
||||
size_t len;
|
||||
} sfparse_vec;
|
||||
} sf_vec;
|
||||
|
||||
/**
|
||||
* @macro
|
||||
*
|
||||
* :macro:`SFPARSE_VALUE_FLAG_NONE` indicates no flag set.
|
||||
* :macro:`SF_VALUE_FLAG_NONE` indicates no flag set.
|
||||
*/
|
||||
#define SFPARSE_VALUE_FLAG_NONE 0x0u
|
||||
#define SF_VALUE_FLAG_NONE 0x0u
|
||||
|
||||
/**
|
||||
* @macro
|
||||
*
|
||||
* :macro:`SFPARSE_VALUE_FLAG_ESCAPED_STRING` indicates that a string
|
||||
* :macro:`SF_VALUE_FLAG_ESCAPED_STRING` indicates that a string
|
||||
* contains escaped character(s).
|
||||
*/
|
||||
#define SFPARSE_VALUE_FLAG_ESCAPED_STRING 0x1u
|
||||
#define SF_VALUE_FLAG_ESCAPED_STRING 0x1u
|
||||
|
||||
/**
|
||||
* @struct
|
||||
*
|
||||
* :type:`sfparse_decimal` contains decimal value.
|
||||
* :type:`sf_decimal` contains decimal value.
|
||||
*/
|
||||
typedef struct sfparse_decimal {
|
||||
typedef struct sf_decimal {
|
||||
/**
|
||||
* :member:`numer` contains numerator of the decimal value.
|
||||
*/
|
||||
@@ -154,289 +150,260 @@ typedef struct sfparse_decimal {
|
||||
* :member:`denom` contains denominator of the decimal value.
|
||||
*/
|
||||
int64_t denom;
|
||||
} sfparse_decimal;
|
||||
} sf_decimal;
|
||||
|
||||
/**
|
||||
* @struct
|
||||
*
|
||||
* :type:`sfparse_value` stores a Structured Field item. For Inner
|
||||
* List, only type is set to
|
||||
* :enum:`sfparse_type.SFPARSE_TYPE_INNER_LIST`. In order to read the
|
||||
* items contained in an inner list, call `sfparse_parser_inner_list`.
|
||||
* :type:`sf_value` stores a Structured Field item. For Inner List,
|
||||
* only type is set to :enum:`sf_type.SF_TYPE_INNER_LIST`. In order
|
||||
* to read the items contained in an inner list, call
|
||||
* `sf_parser_inner_list`.
|
||||
*/
|
||||
typedef struct sfparse_value {
|
||||
typedef struct sf_value {
|
||||
/**
|
||||
* :member:`type` is the type of the value contained in this
|
||||
* particular object.
|
||||
*/
|
||||
sfparse_type type;
|
||||
sf_type type;
|
||||
/**
|
||||
* :member:`flags` is bitwise OR of one or more of
|
||||
* :macro:`SFPARSE_VALUE_FLAG_* <SFPARSE_VALUE_FLAG_NONE>`.
|
||||
* :macro:`SF_VALUE_FLAG_* <SF_VALUE_FLAG_NONE>`.
|
||||
*/
|
||||
uint32_t flags;
|
||||
/**
|
||||
* @anonunion_start
|
||||
*
|
||||
* @sfparse_value_value
|
||||
* @sf_value_value
|
||||
*/
|
||||
union {
|
||||
/**
|
||||
* :member:`boolean` contains boolean value if :member:`type` ==
|
||||
* :enum:`sfparse_type.SFPARSE_TYPE_BOOLEAN`. 1 indicates true,
|
||||
* and 0 indicates false.
|
||||
* :enum:`sf_type.SF_TYPE_BOOLEAN`. 1 indicates true, and 0
|
||||
* indicates false.
|
||||
*/
|
||||
int boolean;
|
||||
/**
|
||||
* :member:`integer` contains integer value if :member:`type` is
|
||||
* either :enum:`sfparse_type.SFPARSE_TYPE_INTEGER` or
|
||||
* :enum:`sfparse_type.SFPARSE_TYPE_DATE`.
|
||||
* either :enum:`sf_type.SF_TYPE_INTEGER` or
|
||||
* :enum:`sf_type.SF_TYPE_DATE`.
|
||||
*/
|
||||
int64_t integer;
|
||||
/**
|
||||
* :member:`decimal` contains decimal value if :member:`type` ==
|
||||
* :enum:`sfparse_type.SFPARSE_TYPE_DECIMAL`.
|
||||
* :enum:`sf_type.SF_TYPE_DECIMAL`.
|
||||
*/
|
||||
sfparse_decimal decimal;
|
||||
sf_decimal decimal;
|
||||
/**
|
||||
* :member:`vec` contains sequence of bytes if :member:`type` is
|
||||
* either :enum:`sfparse_type.SFPARSE_TYPE_STRING`,
|
||||
* :enum:`sfparse_type.SFPARSE_TYPE_TOKEN`,
|
||||
* :enum:`sfparse_type.SFPARSE_TYPE_BYTESEQ`, or
|
||||
* :enum:`sfparse_type.SFPARSE_TYPE_DISPSTRING`.
|
||||
* either :enum:`sf_type.SF_TYPE_STRING`,
|
||||
* :enum:`sf_type.SF_TYPE_TOKEN`, or
|
||||
* :enum:`sf_type.SF_TYPE_BYTESEQ`.
|
||||
*
|
||||
* For :enum:`sfparse_type.SFPARSE_TYPE_STRING`, this field
|
||||
* contains one or more escaped characters if :member:`flags` has
|
||||
* :macro:`SFPARSE_VALUE_FLAG_ESCAPED_STRING` set. To unescape
|
||||
* the string, use `sfparse_unescape`.
|
||||
* For :enum:`sf_type.SF_TYPE_STRING`, this field contains one or
|
||||
* more escaped characters if :member:`flags` has
|
||||
* :macro:`SF_VALUE_FLAG_ESCAPED_STRING` set. To unescape the
|
||||
* string, use `sf_unescape`.
|
||||
*
|
||||
* For :enum:`sfparse_type.SFPARSE_TYPE_BYTESEQ`, this field
|
||||
* contains base64 encoded string. To decode this byte string,
|
||||
* use `sfparse_base64decode`.
|
||||
* For :enum:`sf_type.SF_TYPE_BYTESEQ`, this field contains base64
|
||||
* encoded string. To decode this byte string, use
|
||||
* `sf_base64decode`.
|
||||
*
|
||||
* For :enum:`sfparse_type.SFPARSE_TYPE_DISPSTRING`, this field
|
||||
* may contain percent-encoded UTF-8 byte sequences. To decode
|
||||
* it, use `sfparse_pctdecode`.
|
||||
*
|
||||
* If :member:`vec.len <sfparse_vec.len>` == 0, :member:`vec.base
|
||||
* <sfparse_vec.base>` is guaranteed to be NULL.
|
||||
* If :member:`vec.len <sf_vec.len>` == 0, :member:`vec.base
|
||||
* <sf_vec.base>` is guaranteed to be NULL.
|
||||
*/
|
||||
sfparse_vec vec;
|
||||
sf_vec vec;
|
||||
/**
|
||||
* @anonunion_end
|
||||
*/
|
||||
};
|
||||
} sfparse_value;
|
||||
} sf_value;
|
||||
|
||||
/**
|
||||
* @struct
|
||||
*
|
||||
* :type:`sfparse_parser` is the Structured Field Values parser. Use
|
||||
* `sfparse_parser_init` to initialize it.
|
||||
* :type:`sf_parser` is the Structured Field Values parser. Use
|
||||
* `sf_parser_init` to initialize it.
|
||||
*/
|
||||
typedef struct sfparse_parser {
|
||||
typedef struct sf_parser {
|
||||
/* all fields are private */
|
||||
const uint8_t *pos;
|
||||
const uint8_t *end;
|
||||
uint32_t state;
|
||||
} sfparse_parser;
|
||||
} sf_parser;
|
||||
|
||||
/**
|
||||
* @function
|
||||
*
|
||||
* `sfparse_parser_init` initializes |sfp| with the given data encoded
|
||||
* in Structured Field Values pointed by |data| of length |datalen|.
|
||||
* `sf_parser_init` initializes |sfp| with the given buffer pointed by
|
||||
* |data| of length |datalen|.
|
||||
*/
|
||||
void sfparse_parser_init(sfparse_parser *sfp, const uint8_t *data,
|
||||
size_t datalen);
|
||||
void sf_parser_init(sf_parser *sfp, const uint8_t *data, size_t datalen);
|
||||
|
||||
/**
|
||||
* @function
|
||||
*
|
||||
* `sfparse_parser_param` reads a parameter. If this function returns
|
||||
* 0, it stores parameter key and value in |dest_key| and |dest_value|
|
||||
* `sf_parser_param` reads a parameter. If this function returns 0,
|
||||
* it stores parameter key and value in |dest_key| and |dest_value|
|
||||
* respectively, if they are not NULL.
|
||||
*
|
||||
* This function does no effort to find duplicated keys. Same key may
|
||||
* be reported more than once.
|
||||
*
|
||||
* Caller should keep calling this function until it returns negative
|
||||
* error code. If it returns :macro:`SFPARSE_ERR_EOF`, all parameters
|
||||
* have read, and caller can continue to read rest of the values. If
|
||||
* it returns :macro:`SFPARSE_ERR_PARSE`, it encountered fatal error
|
||||
* error code. If it returns :macro:`SF_ERR_EOF`, all parameters have
|
||||
* read, and caller can continue to read rest of the values. If it
|
||||
* returns :macro:`SF_ERR_PARSE_ERROR`, it encountered fatal error
|
||||
* while parsing field value.
|
||||
*/
|
||||
int sfparse_parser_param(sfparse_parser *sfp, sfparse_vec *dest_key,
|
||||
sfparse_value *dest_value);
|
||||
int sf_parser_param(sf_parser *sfp, sf_vec *dest_key, sf_value *dest_value);
|
||||
|
||||
/**
|
||||
* @function
|
||||
*
|
||||
* `sfparse_parser_dict` reads the next dictionary key and value pair.
|
||||
* If this function returns 0, it stores the key and value in
|
||||
* |dest_key| and |dest_value| respectively, if they are not NULL.
|
||||
* `sf_parser_dict` reads the next dictionary key and value pair. If
|
||||
* this function returns 0, it stores the key and value in |dest_key|
|
||||
* and |dest_value| respectively, if they are not NULL.
|
||||
*
|
||||
* Caller can optionally read parameters attached to the pair by
|
||||
* calling `sfparse_parser_param`.
|
||||
* calling `sf_parser_param`.
|
||||
*
|
||||
* This function does no effort to find duplicated keys. Same key may
|
||||
* be reported more than once.
|
||||
*
|
||||
* Caller should keep calling this function until it returns negative
|
||||
* error code. If it returns :macro:`SFPARSE_ERR_EOF`, all key and
|
||||
* value pairs have been read, and there is nothing left to read.
|
||||
* error code. If it returns :macro:`SF_ERR_EOF`, all key and value
|
||||
* pairs have been read, and there is nothing left to read.
|
||||
*
|
||||
* This function returns 0 if it succeeds, or one of the following
|
||||
* negative error codes:
|
||||
*
|
||||
* :macro:`SFPARSE_ERR_EOF`
|
||||
* :macro:`SF_ERR_EOF`
|
||||
* All values in the dictionary have read.
|
||||
* :macro:`SFPARSE_ERR_PARSE`
|
||||
* :macro:`SF_ERR_PARSE_ERROR`
|
||||
* It encountered fatal error while parsing field value.
|
||||
*/
|
||||
int sfparse_parser_dict(sfparse_parser *sfp, sfparse_vec *dest_key,
|
||||
sfparse_value *dest_value);
|
||||
int sf_parser_dict(sf_parser *sfp, sf_vec *dest_key, sf_value *dest_value);
|
||||
|
||||
/**
|
||||
* @function
|
||||
*
|
||||
* `sfparse_parser_list` reads the next list item. If this function
|
||||
* `sf_parser_list` reads the next list item. If this function
|
||||
* returns 0, it stores the item in |dest| if it is not NULL.
|
||||
*
|
||||
* Caller can optionally read parameters attached to the item by
|
||||
* calling `sfparse_parser_param`.
|
||||
* calling `sf_parser_param`.
|
||||
*
|
||||
* Caller should keep calling this function until it returns negative
|
||||
* error code. If it returns :macro:`SFPARSE_ERR_EOF`, all values in
|
||||
* the list have been read, and there is nothing left to read.
|
||||
* error code. If it returns :macro:`SF_ERR_EOF`, all values in the
|
||||
* list have been read, and there is nothing left to read.
|
||||
*
|
||||
* This function returns 0 if it succeeds, or one of the following
|
||||
* negative error codes:
|
||||
*
|
||||
* :macro:`SFPARSE_ERR_EOF`
|
||||
* :macro:`SF_ERR_EOF`
|
||||
* All values in the list have read.
|
||||
* :macro:`SFPARSE_ERR_PARSE`
|
||||
* :macro:`SF_ERR_PARSE_ERROR`
|
||||
* It encountered fatal error while parsing field value.
|
||||
*/
|
||||
int sfparse_parser_list(sfparse_parser *sfp, sfparse_value *dest);
|
||||
int sf_parser_list(sf_parser *sfp, sf_value *dest);
|
||||
|
||||
/**
|
||||
* @function
|
||||
*
|
||||
* `sfparse_parser_item` reads a single item. If this function
|
||||
* returns 0, it stores the item in |dest| if it is not NULL.
|
||||
* `sf_parser_item` reads a single item. If this function returns 0,
|
||||
* it stores the item in |dest| if it is not NULL.
|
||||
*
|
||||
* This function is only used for the field value that consists of a
|
||||
* single item.
|
||||
*
|
||||
* Caller can optionally read parameters attached to the item by
|
||||
* calling `sfparse_parser_param`.
|
||||
* calling `sf_parser_param`.
|
||||
*
|
||||
* Caller should call this function again to make sure that there is
|
||||
* nothing left to read. If this 2nd function call returns
|
||||
* :macro:`SFPARSE_ERR_EOF`, all data have been processed
|
||||
* successfully.
|
||||
* :macro:`SF_ERR_EOF`, all data have been processed successfully.
|
||||
*
|
||||
* This function returns 0 if it succeeds, or one of the following
|
||||
* negative error codes:
|
||||
*
|
||||
* :macro:`SFPARSE_ERR_EOF`
|
||||
* :macro:`SF_ERR_EOF`
|
||||
* There is nothing left to read.
|
||||
* :macro:`SFPARSE_ERR_PARSE`
|
||||
* :macro:`SF_ERR_PARSE_ERROR`
|
||||
* It encountered fatal error while parsing field value.
|
||||
*/
|
||||
int sfparse_parser_item(sfparse_parser *sfp, sfparse_value *dest);
|
||||
int sf_parser_item(sf_parser *sfp, sf_value *dest);
|
||||
|
||||
/**
|
||||
* @function
|
||||
*
|
||||
* `sfparse_parser_inner_list` reads the next inner list item. If
|
||||
* this function returns 0, it stores the item in |dest| if it is not
|
||||
* NULL.
|
||||
* `sf_parser_inner_list` reads the next inner list item. If this
|
||||
* function returns 0, it stores the item in |dest| if it is not NULL.
|
||||
*
|
||||
* Caller can optionally read parameters attached to the item by
|
||||
* calling `sfparse_parser_param`.
|
||||
* calling `sf_parser_param`.
|
||||
*
|
||||
* Caller should keep calling this function until it returns negative
|
||||
* error code. If it returns :macro:`SFPARSE_ERR_EOF`, all values in
|
||||
* this inner list have been read, and caller can optionally read
|
||||
* error code. If it returns :macro:`SF_ERR_EOF`, all values in this
|
||||
* inner list have been read, and caller can optionally read
|
||||
* parameters attached to this inner list by calling
|
||||
* `sfparse_parser_param`. Then caller can continue to read rest of
|
||||
* the values.
|
||||
* `sf_parser_param`. Then caller can continue to read rest of the
|
||||
* values.
|
||||
*
|
||||
* This function returns 0 if it succeeds, or one of the following
|
||||
* negative error codes:
|
||||
*
|
||||
* :macro:`SFPARSE_ERR_EOF`
|
||||
* :macro:`SF_ERR_EOF`
|
||||
* All values in the inner list have read.
|
||||
* :macro:`SFPARSE_ERR_PARSE`
|
||||
* :macro:`SF_ERR_PARSE_ERROR`
|
||||
* It encountered fatal error while parsing field value.
|
||||
*/
|
||||
int sfparse_parser_inner_list(sfparse_parser *sfp, sfparse_value *dest);
|
||||
int sf_parser_inner_list(sf_parser *sfp, sf_value *dest);
|
||||
|
||||
/**
|
||||
* @function
|
||||
*
|
||||
* `sfparse_unescape` copies |src| to |dest| by removing escapes
|
||||
* (``\``). |src| should be the pointer to
|
||||
* :member:`sfparse_value.vec` of type
|
||||
* :enum:`sfparse_type.SFPARSE_TYPE_STRING` produced by either
|
||||
* `sfparse_parser_dict`, `sfparse_parser_list`,
|
||||
* `sfparse_parser_inner_list`, `sfparse_parser_item`, or
|
||||
* `sfparse_parser_param`, otherwise the behavior is undefined.
|
||||
* `sf_unescape` copies |src| to |dest| by removing escapes (``\``).
|
||||
* |src| should be the pointer to :member:`sf_value.vec` of type
|
||||
* :enum:`sf_type.SF_TYPE_STRING` produced by either `sf_parser_dict`,
|
||||
* `sf_parser_list`, `sf_parser_inner_list`, `sf_parser_item`, or
|
||||
* `sf_parser_param`, otherwise the behavior is undefined.
|
||||
*
|
||||
* :member:`dest->base <sfparse_vec.base>` must point to the buffer
|
||||
* that has sufficient space to store the unescaped string. The
|
||||
* memory areas pointed by :member:`dest->base <sfparse_vec.base>` and
|
||||
* :member:`src->base <sfparse_vec.base>` must not overlap.
|
||||
* :member:`dest->base <sf_vec.base>` must point to the buffer that
|
||||
* has sufficient space to store the unescaped string.
|
||||
*
|
||||
* If there is no escape character in |src|, |*src| is assigned to
|
||||
* |*dest|. This includes the case that :member:`src->len
|
||||
* <sf_vec.len>` == 0.
|
||||
*
|
||||
* This function sets the length of unescaped string to
|
||||
* :member:`dest->len <sfparse_vec.len>`.
|
||||
* :member:`dest->len <sf_vec.len>`.
|
||||
*/
|
||||
void sfparse_unescape(sfparse_vec *dest, const sfparse_vec *src);
|
||||
void sf_unescape(sf_vec *dest, const sf_vec *src);
|
||||
|
||||
/**
|
||||
* @function
|
||||
*
|
||||
* `sfparse_base64decode` decodes Base64 encoded string |src| and
|
||||
* writes the result into |dest|. |src| should be the pointer to
|
||||
* :member:`sfparse_value.vec` of type
|
||||
* :enum:`sfparse_type.SFPARSE_TYPE_BYTESEQ` produced by either
|
||||
* `sfparse_parser_dict`, `sfparse_parser_list`,
|
||||
* `sfparse_parser_inner_list`, `sfparse_parser_item`, or
|
||||
* `sfparse_parser_param`, otherwise the behavior is undefined.
|
||||
*
|
||||
* :member:`dest->base <sfparse_vec.base>` must point to the buffer
|
||||
* that has sufficient space to store the decoded byte string.
|
||||
*
|
||||
* This function sets the length of decoded byte string to
|
||||
* :member:`dest->len <sfparse_vec.len>`.
|
||||
*/
|
||||
void sfparse_base64decode(sfparse_vec *dest, const sfparse_vec *src);
|
||||
|
||||
/**
|
||||
* @function
|
||||
*
|
||||
* `sfparse_pctdecode` decodes percent-encoded string |src| and writes
|
||||
* `sf_base64decode` decodes Base64 encoded string |src| and writes
|
||||
* the result into |dest|. |src| should be the pointer to
|
||||
* :member:`sfparse_value.vec` of type
|
||||
* :enum:`sfparse_type.SFPARSE_TYPE_DISPSTRING` produced by either
|
||||
* `sfparse_parser_dict`, `sfparse_parser_list`,
|
||||
* `sfparse_parser_inner_list`, `sfparse_parser_item`, or
|
||||
* `sfparse_parser_param`, otherwise the behavior is undefined.
|
||||
* :member:`sf_value.vec` of type :enum:`sf_type.SF_TYPE_BYTESEQ`
|
||||
* produced by either `sf_parser_dict`, `sf_parser_list`,
|
||||
* `sf_parser_inner_list`, `sf_parser_item`, or `sf_parser_param`,
|
||||
* otherwise the behavior is undefined.
|
||||
*
|
||||
* :member:`dest->base <sfparse_vec.base>` must point to the buffer
|
||||
* that has sufficient space to store the decoded byte string. The
|
||||
* memory areas pointed by :member:`dest->base <sfparse_vec.base>` and
|
||||
* :member:`src->base <sfparse_vec.base>` must not overlap.
|
||||
* :member:`dest->base <sf_vec.base>` must point to the buffer that
|
||||
* has sufficient space to store the decoded byte string.
|
||||
*
|
||||
* If :member:`src->len <sf_vec.len>` == 0, |*src| is assigned to
|
||||
* |*dest|.
|
||||
*
|
||||
* This function sets the length of decoded byte string to
|
||||
* :member:`dest->len <sfparse_vec.len>`.
|
||||
* :member:`dest->len <sf_vec.len>`.
|
||||
*/
|
||||
void sfparse_pctdecode(sfparse_vec *dest, const sfparse_vec *src);
|
||||
void sf_base64decode(sf_vec *dest, const sf_vec *src);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* defined(__cplusplus) */
|
||||
#endif
|
||||
|
||||
#endif /* !defined(SFPARSE_H) */
|
||||
#endif /* SFPARSE_H */
|
||||
|
||||
5
script/CMakeLists.txt
Normal file
5
script/CMakeLists.txt
Normal file
@@ -0,0 +1,5 @@
|
||||
# EXTRA_DIST = README.rst
|
||||
install(
|
||||
PROGRAMS fetch-ocsp-response
|
||||
DESTINATION "${CMAKE_INSTALL_DATADIR}/${CMAKE_PROJECT_NAME}"
|
||||
)
|
||||
25
script/Makefile.am
Normal file
25
script/Makefile.am
Normal file
@@ -0,0 +1,25 @@
|
||||
# nghttp2 - HTTP/2 C Library
|
||||
|
||||
# Copyright (c) 2015 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.
|
||||
|
||||
EXTRA_DIST = README.rst CMakeLists.txt
|
||||
dist_pkgdata_SCRIPTS = fetch-ocsp-response
|
||||
10
script/README.rst
Normal file
10
script/README.rst
Normal file
@@ -0,0 +1,10 @@
|
||||
fetch-ocsp-response is a Python script which performs OCSP query and
|
||||
get response. It uses openssl command under the hood. nghttpx uses
|
||||
it to enable OCSP stapling feature.
|
||||
|
||||
fetch-ocsp-response is a translation from original fetch-ocsp-response
|
||||
written in Perl and which has been developed as part of h2o project
|
||||
(https://github.com/h2o/h2o).
|
||||
|
||||
fetch-ocsp-response is usually installed under $(pkgdatadir), which is
|
||||
$(prefix)/share/nghttp2.
|
||||
253
script/fetch-ocsp-response
Executable file
253
script/fetch-ocsp-response
Executable file
@@ -0,0 +1,253 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# nghttp2 - HTTP/2 C Library
|
||||
|
||||
# Copyright (c) 2015 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.
|
||||
|
||||
# This program was translated from the program originally developed by
|
||||
# h2o project (https://github.com/h2o/h2o), written in Perl. It had
|
||||
# the following copyright notice:
|
||||
|
||||
# Copyright (c) 2015 DeNA Co., Ltd.
|
||||
#
|
||||
# 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.
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import argparse
|
||||
import io
|
||||
import os
|
||||
import os.path
|
||||
import re
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
import tempfile
|
||||
|
||||
# make this program work for both Python 3 and Python 2.
|
||||
try:
|
||||
from urllib.parse import urlparse
|
||||
stdout_bwrite = sys.stdout.buffer.write
|
||||
except ImportError:
|
||||
from urlparse import urlparse
|
||||
stdout_bwrite = sys.stdout.write
|
||||
|
||||
|
||||
def die(msg):
|
||||
sys.stderr.write(msg)
|
||||
sys.stderr.write('\n')
|
||||
sys.exit(255)
|
||||
|
||||
|
||||
def tempfail(msg):
|
||||
sys.stderr.write(msg)
|
||||
sys.stderr.write('\n')
|
||||
sys.exit(os.EX_TEMPFAIL)
|
||||
|
||||
|
||||
def run_openssl(args, allow_tempfail=False):
|
||||
buf = io.BytesIO()
|
||||
try:
|
||||
p = subprocess.Popen(args, stdout=subprocess.PIPE)
|
||||
except Exception as e:
|
||||
die('failed to invoke {}:{}'.format(args, e))
|
||||
try:
|
||||
while True:
|
||||
data = p.stdout.read()
|
||||
if len(data) == 0:
|
||||
break
|
||||
buf.write(data)
|
||||
if p.wait() != 0:
|
||||
raise Exception('nonzero return code {}'.format(p.returncode))
|
||||
return buf.getvalue()
|
||||
except Exception as e:
|
||||
msg = 'OpenSSL exited abnormally: {}:{}'.format(args, e)
|
||||
tempfail(msg) if allow_tempfail else die(msg)
|
||||
|
||||
|
||||
def read_file(path):
|
||||
with open(path, 'rb') as f:
|
||||
return f.read()
|
||||
|
||||
|
||||
def write_file(path, data):
|
||||
with open(path, 'wb') as f:
|
||||
f.write(data)
|
||||
|
||||
|
||||
def detect_openssl_version(cmd):
|
||||
return run_openssl([cmd, 'version']).decode('utf-8').strip()
|
||||
|
||||
|
||||
def extract_ocsp_uri(cmd, cert_fn):
|
||||
# obtain ocsp uri
|
||||
ocsp_uri = run_openssl(
|
||||
[cmd, 'x509', '-in', cert_fn, '-noout',
|
||||
'-ocsp_uri']).decode('utf-8').strip()
|
||||
|
||||
if not re.match(r'^https?://', ocsp_uri):
|
||||
die('failed to extract ocsp URI from {}'.format(cert_fn))
|
||||
|
||||
return ocsp_uri
|
||||
|
||||
|
||||
def save_issuer_certificate(issuer_fn, cert_fn):
|
||||
# save issuer certificate
|
||||
chain = read_file(cert_fn).decode('utf-8')
|
||||
m = re.match(
|
||||
r'.*?-----END CERTIFICATE-----.*?(-----BEGIN CERTIFICATE-----.*?-----END CERTIFICATE-----)',
|
||||
chain, re.DOTALL)
|
||||
if not m:
|
||||
die('--issuer option was not used, and failed to extract issuer certificate from the certificate')
|
||||
write_file(issuer_fn, (m.group(1) + '\n').encode('utf-8'))
|
||||
|
||||
|
||||
def send_and_receive_ocsp(respder_fn, cmd, cert_fn, issuer_fn, ocsp_uri,
|
||||
ocsp_host, openssl_version):
|
||||
# obtain response (without verification)
|
||||
sys.stderr.write('sending OCSP request to {}\n'.format(ocsp_uri))
|
||||
args = [
|
||||
cmd, 'ocsp', '-issuer', issuer_fn, '-cert', cert_fn, '-url', ocsp_uri,
|
||||
'-noverify', '-respout', respder_fn
|
||||
]
|
||||
ver = openssl_version.lower()
|
||||
if ver.startswith('openssl 1.0.') or ver.startswith('libressl '):
|
||||
args.extend(['-header', 'Host', ocsp_host])
|
||||
resp = run_openssl(args, allow_tempfail=True)
|
||||
return resp.decode('utf-8')
|
||||
|
||||
|
||||
def verify_response(cmd, tempdir, issuer_fn, respder_fn):
|
||||
# verify the response
|
||||
sys.stderr.write('verifying the response signature\n')
|
||||
|
||||
verify_fn = os.path.join(tempdir, 'verify.out')
|
||||
|
||||
# try from exotic options
|
||||
allextra = [
|
||||
# for comodo
|
||||
['-VAfile', issuer_fn],
|
||||
# these options are only available in OpenSSL >= 1.0.2
|
||||
['-partial_chain', '-trusted_first', '-CAfile', issuer_fn],
|
||||
# for OpenSSL <= 1.0.1
|
||||
['-CAfile', issuer_fn],
|
||||
]
|
||||
|
||||
for extra in allextra:
|
||||
with open(verify_fn, 'w+b') as f:
|
||||
args = [cmd, 'ocsp', '-respin', respder_fn]
|
||||
args.extend(extra)
|
||||
p = subprocess.Popen(args, stdout=f, stderr=f)
|
||||
if p.wait() == 0:
|
||||
# OpenSSL <= 1.0.1, openssl ocsp still returns exit
|
||||
# code 0 even if verification was failed. So check
|
||||
# the error message in stderr output.
|
||||
f.seek(0)
|
||||
if f.read().decode('utf-8').find(
|
||||
'Response Verify Failure') != -1:
|
||||
continue
|
||||
sys.stderr.write('verify OK (used: {})\n'.format(extra))
|
||||
return True
|
||||
|
||||
sys.stderr.write(read_file(verify_fn).decode('utf-8'))
|
||||
return False
|
||||
|
||||
|
||||
def fetch_ocsp_response(cmd, cert_fn, tempdir, issuer_fn=None):
|
||||
openssl_version = detect_openssl_version(cmd)
|
||||
|
||||
sys.stderr.write(
|
||||
'fetch-ocsp-response (using {})\n'.format(openssl_version))
|
||||
|
||||
ocsp_uri = extract_ocsp_uri(cmd, cert_fn)
|
||||
ocsp_host = urlparse(ocsp_uri).netloc
|
||||
|
||||
if not issuer_fn:
|
||||
issuer_fn = os.path.join(tempdir, 'issuer.crt')
|
||||
save_issuer_certificate(issuer_fn, cert_fn)
|
||||
|
||||
respder_fn = os.path.join(tempdir, 'resp.der')
|
||||
resp = send_and_receive_ocsp(
|
||||
respder_fn, cmd, cert_fn, issuer_fn, ocsp_uri, ocsp_host,
|
||||
openssl_version)
|
||||
|
||||
sys.stderr.write('{}\n'.format(resp))
|
||||
|
||||
# OpenSSL 1.0.2 still returns exit code 0 even if ocsp responder
|
||||
# returned error status (e.g., trylater(3))
|
||||
if resp.find('Responder Error:') != -1:
|
||||
raise Exception('responder returned error')
|
||||
|
||||
if not verify_response(cmd, tempdir, issuer_fn, respder_fn):
|
||||
tempfail('failed to verify the response')
|
||||
|
||||
# success
|
||||
res = read_file(respder_fn)
|
||||
stdout_bwrite(res)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
parser = argparse.ArgumentParser(
|
||||
description=
|
||||
'''The command issues an OCSP request for given server certificate, verifies the response and prints the resulting DER.''',
|
||||
epilog=
|
||||
'''The command exits 0 if successful, or 75 (EX_TEMPFAIL) on temporary error. Other exit codes may be returned in case of hard errors.''')
|
||||
parser.add_argument(
|
||||
'--issuer',
|
||||
metavar='FILE',
|
||||
help=
|
||||
'issuer certificate (if omitted, is extracted from the certificate chain)')
|
||||
parser.add_argument('--openssl',
|
||||
metavar='CMD',
|
||||
help='openssl command to use (default: "openssl")',
|
||||
default='openssl')
|
||||
parser.add_argument('certificate',
|
||||
help='path to certificate file to validate')
|
||||
args = parser.parse_args()
|
||||
|
||||
tempdir = None
|
||||
try:
|
||||
# Python3.2 has tempfile.TemporaryDirectory, which has nice
|
||||
# feature to delete its tree by cleanup() function. We have
|
||||
# to support Python2.7, so we have to do this manually.
|
||||
tempdir = tempfile.mkdtemp()
|
||||
fetch_ocsp_response(args.openssl, args.certificate, tempdir,
|
||||
args.issuer)
|
||||
finally:
|
||||
if tempdir:
|
||||
shutil.rmtree(tempdir)
|
||||
@@ -7,7 +7,7 @@ set_source_files_properties(${cxx_sources} PROPERTIES
|
||||
|
||||
include_directories(
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/includes"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/../third-party/urlparse"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/../third-party"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/../third-party/llhttp/include"
|
||||
|
||||
${JEMALLOC_INCLUDE_DIRS}
|
||||
@@ -16,11 +16,7 @@ include_directories(
|
||||
${LIBNGHTTP3_INCLUDE_DIRS}
|
||||
${LIBNGTCP2_INCLUDE_DIRS}
|
||||
${LIBNGTCP2_CRYPTO_QUICTLS_INCLUDE_DIRS}
|
||||
${LIBNGTCP2_CRYPTO_LIBRESSL_INCLUDE_DIRS}
|
||||
${LIBNGTCP2_CRYPTO_WOLFSSL_INCLUDE_DIRS}
|
||||
${LIBNGTCP2_CRYPTO_OSSL_INCLUDE_DIRS}
|
||||
${OPENSSL_INCLUDE_DIRS}
|
||||
${WOLFSSL_INCLUDE_DIRS}
|
||||
${LIBCARES_INCLUDE_DIRS}
|
||||
${JANSSON_INCLUDE_DIRS}
|
||||
${ZLIB_INCLUDE_DIRS}
|
||||
@@ -38,11 +34,7 @@ link_libraries(
|
||||
${LIBNGHTTP3_LIBRARIES}
|
||||
${LIBNGTCP2_LIBRARIES}
|
||||
${LIBNGTCP2_CRYPTO_QUICTLS_LIBRARIES}
|
||||
${LIBNGTCP2_CRYPTO_LIBRESSL_LIBRARIES}
|
||||
${LIBNGTCP2_CRYPTO_WOLFSSL_LIBRARIES}
|
||||
${LIBNGTCP2_CRYPTO_OSSL_LIBRARIES}
|
||||
${OPENSSL_LIBRARIES}
|
||||
${WOLFSSL_LIBRARIES}
|
||||
${LIBCARES_LIBRARIES}
|
||||
${JANSSON_LIBRARIES}
|
||||
${ZLIB_LIBRARIES}
|
||||
@@ -89,6 +81,7 @@ if(ENABLE_APP)
|
||||
list(APPEND H2LOAD_SOURCES
|
||||
h2load_http3_session.cc
|
||||
h2load_quic.cc
|
||||
quic.cc
|
||||
)
|
||||
endif()
|
||||
|
||||
@@ -128,6 +121,7 @@ if(ENABLE_APP)
|
||||
shrpx_api_downstream_connection.cc
|
||||
shrpx_health_monitor_downstream_connection.cc
|
||||
shrpx_null_downstream_connection.cc
|
||||
shrpx_exec.cc
|
||||
shrpx_dns_resolver.cc
|
||||
shrpx_dual_dns_resolver.cc
|
||||
shrpx_dns_tracker.cc
|
||||
@@ -149,7 +143,7 @@ if(ENABLE_APP)
|
||||
shrpx_quic_connection_handler.cc
|
||||
shrpx_http3_upstream.cc
|
||||
http3.cc
|
||||
siphash.cc
|
||||
quic.cc
|
||||
)
|
||||
endif()
|
||||
add_library(nghttpx_static STATIC ${NGHTTPX_SRCS})
|
||||
@@ -173,59 +167,54 @@ if(ENABLE_APP)
|
||||
target_link_libraries(nghttpx_static neverbleed)
|
||||
endif()
|
||||
|
||||
if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME AND BUILD_TESTING)
|
||||
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
|
||||
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>
|
||||
)
|
||||
if(ENABLE_HTTP3)
|
||||
list(APPEND NGHTTPX_UNITTEST_SOURCES siphash_test.cc)
|
||||
endif()
|
||||
add_executable(nghttpx-unittest EXCLUDE_FROM_ALL
|
||||
${NGHTTPX_UNITTEST_SOURCES}
|
||||
$<TARGET_OBJECTS:llhttp>
|
||||
$<TARGET_OBJECTS:urlparse>
|
||||
)
|
||||
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)
|
||||
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:urlparse>
|
||||
$<TARGET_OBJECTS:url-parser>
|
||||
)
|
||||
add_executable(nghttpd ${NGHTTPD_SOURCES} $<TARGET_OBJECTS:llhttp>
|
||||
$<TARGET_OBJECTS:urlparse>
|
||||
$<TARGET_OBJECTS:url-parser>
|
||||
)
|
||||
add_executable(nghttpx ${NGHTTPX-bin_SOURCES} $<TARGET_OBJECTS:llhttp>
|
||||
$<TARGET_OBJECTS:urlparse>
|
||||
$<TARGET_OBJECTS:url-parser>
|
||||
)
|
||||
target_compile_definitions(nghttpx PRIVATE
|
||||
"-DPKGDATADIR=\"${PKGDATADIR}\""
|
||||
@@ -233,7 +222,7 @@ if(ENABLE_APP)
|
||||
)
|
||||
target_link_libraries(nghttpx nghttpx_static)
|
||||
add_executable(h2load ${H2LOAD_SOURCES} $<TARGET_OBJECTS:llhttp>
|
||||
$<TARGET_OBJECTS:urlparse>
|
||||
$<TARGET_OBJECTS:url-parser>
|
||||
)
|
||||
|
||||
install(TARGETS nghttp nghttpd nghttpx h2load)
|
||||
|
||||
@@ -31,36 +31,38 @@
|
||||
namespace nghttp2 {
|
||||
|
||||
ParserData::ParserData(const std::string &base_uri)
|
||||
: base_uri(base_uri), inside_head(0) {}
|
||||
: base_uri(base_uri), inside_head(0) {}
|
||||
|
||||
HtmlParser::HtmlParser(const std::string &base_uri)
|
||||
: base_uri_(base_uri), parser_ctx_(nullptr), parser_data_(base_uri) {}
|
||||
: base_uri_(base_uri), parser_ctx_(nullptr), parser_data_(base_uri) {}
|
||||
|
||||
HtmlParser::~HtmlParser() { htmlFreeParserCtxt(parser_ctx_); }
|
||||
|
||||
namespace {
|
||||
std::string_view get_attr(const xmlChar **attrs, const std::string_view &name) {
|
||||
StringRef get_attr(const xmlChar **attrs, const StringRef &name) {
|
||||
if (attrs == nullptr) {
|
||||
return ""sv;
|
||||
return StringRef{};
|
||||
}
|
||||
for (; *attrs; attrs += 2) {
|
||||
if (util::strieq(std::string_view{reinterpret_cast<const char *>(attrs[0])},
|
||||
if (util::strieq(StringRef{attrs[0], strlen(reinterpret_cast<const char *>(
|
||||
attrs[0]))},
|
||||
name)) {
|
||||
return std::string_view{reinterpret_cast<const char *>(attrs[1])};
|
||||
return StringRef{attrs[1],
|
||||
strlen(reinterpret_cast<const char *>(attrs[1]))};
|
||||
}
|
||||
}
|
||||
return ""sv;
|
||||
return StringRef{};
|
||||
}
|
||||
} // namespace
|
||||
|
||||
namespace {
|
||||
ResourceType
|
||||
get_resource_type_for_preload_as(const std::string_view &attribute_value) {
|
||||
if (util::strieq("image"sv, attribute_value)) {
|
||||
get_resource_type_for_preload_as(const StringRef &attribute_value) {
|
||||
if (util::strieq("image"_sr, attribute_value)) {
|
||||
return REQ_IMG;
|
||||
} else if (util::strieq("style"sv, attribute_value)) {
|
||||
} else if (util::strieq("style"_sr, attribute_value)) {
|
||||
return REQ_CSS;
|
||||
} else if (util::strieq("script"sv, attribute_value)) {
|
||||
} else if (util::strieq("script"_sr, attribute_value)) {
|
||||
return REQ_UNBLOCK_JS;
|
||||
} else {
|
||||
return REQ_OTHERS;
|
||||
@@ -69,15 +71,15 @@ get_resource_type_for_preload_as(const std::string_view &attribute_value) {
|
||||
} // namespace
|
||||
|
||||
namespace {
|
||||
void add_link(ParserData *parser_data, const std::string_view &uri,
|
||||
void add_link(ParserData *parser_data, const StringRef &uri,
|
||||
ResourceType res_type) {
|
||||
auto u = xmlBuildURI(
|
||||
reinterpret_cast<const xmlChar *>(uri.data()),
|
||||
reinterpret_cast<const xmlChar *>(parser_data->base_uri.c_str()));
|
||||
reinterpret_cast<const xmlChar *>(uri.data()),
|
||||
reinterpret_cast<const xmlChar *>(parser_data->base_uri.c_str()));
|
||||
if (u) {
|
||||
parser_data->links.push_back(
|
||||
std::make_pair(reinterpret_cast<char *>(u), res_type));
|
||||
xmlFree(u);
|
||||
std::make_pair(reinterpret_cast<char *>(u), res_type));
|
||||
free(u);
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
@@ -86,36 +88,37 @@ namespace {
|
||||
void start_element_func(void *user_data, const xmlChar *src_name,
|
||||
const xmlChar **attrs) {
|
||||
auto parser_data = static_cast<ParserData *>(user_data);
|
||||
auto name = std::string_view{reinterpret_cast<const char *>(src_name)};
|
||||
if (util::strieq("head"sv, name)) {
|
||||
auto name =
|
||||
StringRef{src_name, strlen(reinterpret_cast<const char *>(src_name))};
|
||||
if (util::strieq("head"_sr, name)) {
|
||||
++parser_data->inside_head;
|
||||
}
|
||||
if (util::strieq("link"sv, name)) {
|
||||
auto rel_attr = get_attr(attrs, "rel"sv);
|
||||
auto href_attr = get_attr(attrs, "href"sv);
|
||||
if (util::strieq("link"_sr, name)) {
|
||||
auto rel_attr = get_attr(attrs, "rel"_sr);
|
||||
auto href_attr = get_attr(attrs, "href"_sr);
|
||||
if (rel_attr.empty() || href_attr.empty()) {
|
||||
return;
|
||||
}
|
||||
if (util::strieq("shortcut icon"sv, rel_attr)) {
|
||||
if (util::strieq("shortcut icon"_sr, rel_attr)) {
|
||||
add_link(parser_data, href_attr, REQ_OTHERS);
|
||||
} else if (util::strieq("stylesheet"sv, rel_attr)) {
|
||||
} else if (util::strieq("stylesheet"_sr, rel_attr)) {
|
||||
add_link(parser_data, href_attr, REQ_CSS);
|
||||
} else if (util::strieq("preload"sv, rel_attr)) {
|
||||
auto as_attr = get_attr(attrs, "as"sv);
|
||||
} else if (util::strieq("preload"_sr, rel_attr)) {
|
||||
auto as_attr = get_attr(attrs, "as"_sr);
|
||||
if (as_attr.empty()) {
|
||||
return;
|
||||
}
|
||||
add_link(parser_data, href_attr,
|
||||
get_resource_type_for_preload_as(as_attr));
|
||||
}
|
||||
} else if (util::strieq("img"sv, name)) {
|
||||
auto src_attr = get_attr(attrs, "src"sv);
|
||||
} else if (util::strieq("img"_sr, name)) {
|
||||
auto src_attr = get_attr(attrs, "src"_sr);
|
||||
if (src_attr.empty()) {
|
||||
return;
|
||||
}
|
||||
add_link(parser_data, src_attr, REQ_IMG);
|
||||
} else if (util::strieq("script"sv, name)) {
|
||||
auto src_attr = get_attr(attrs, "src"sv);
|
||||
} else if (util::strieq("script"_sr, name)) {
|
||||
auto src_attr = get_attr(attrs, "src"_sr);
|
||||
if (src_attr.empty()) {
|
||||
return;
|
||||
}
|
||||
@@ -131,8 +134,9 @@ void start_element_func(void *user_data, const xmlChar *src_name,
|
||||
namespace {
|
||||
void end_element_func(void *user_data, const xmlChar *name) {
|
||||
auto parser_data = static_cast<ParserData *>(user_data);
|
||||
if (util::strieq("head"sv,
|
||||
std::string_view{reinterpret_cast<const char *>(name)})) {
|
||||
if (util::strieq(
|
||||
"head"_sr,
|
||||
StringRef{name, strlen(reinterpret_cast<const char *>(name))})) {
|
||||
--parser_data->inside_head;
|
||||
}
|
||||
}
|
||||
@@ -140,46 +144,46 @@ void end_element_func(void *user_data, const xmlChar *name) {
|
||||
|
||||
namespace {
|
||||
xmlSAXHandler saxHandler = {
|
||||
nullptr, // internalSubsetSAXFunc
|
||||
nullptr, // isStandaloneSAXFunc
|
||||
nullptr, // hasInternalSubsetSAXFunc
|
||||
nullptr, // hasExternalSubsetSAXFunc
|
||||
nullptr, // resolveEntitySAXFunc
|
||||
nullptr, // getEntitySAXFunc
|
||||
nullptr, // entityDeclSAXFunc
|
||||
nullptr, // notationDeclSAXFunc
|
||||
nullptr, // attributeDeclSAXFunc
|
||||
nullptr, // elementDeclSAXFunc
|
||||
nullptr, // unparsedEntityDeclSAXFunc
|
||||
nullptr, // setDocumentLocatorSAXFunc
|
||||
nullptr, // startDocumentSAXFunc
|
||||
nullptr, // endDocumentSAXFunc
|
||||
&start_element_func, // startElementSAXFunc
|
||||
&end_element_func, // endElementSAXFunc
|
||||
nullptr, // referenceSAXFunc
|
||||
nullptr, // charactersSAXFunc
|
||||
nullptr, // ignorableWhitespaceSAXFunc
|
||||
nullptr, // processingInstructionSAXFunc
|
||||
nullptr, // commentSAXFunc
|
||||
nullptr, // warningSAXFunc
|
||||
nullptr, // errorSAXFunc
|
||||
nullptr, // fatalErrorSAXFunc
|
||||
nullptr, // getParameterEntitySAXFunc
|
||||
nullptr, // cdataBlockSAXFunc
|
||||
nullptr, // externalSubsetSAXFunc
|
||||
0, // unsigned int initialized
|
||||
nullptr, // void * _private
|
||||
nullptr, // startElementNsSAX2Func
|
||||
nullptr, // endElementNsSAX2Func
|
||||
nullptr, // xmlStructuredErrorFunc
|
||||
nullptr, // internalSubsetSAXFunc
|
||||
nullptr, // isStandaloneSAXFunc
|
||||
nullptr, // hasInternalSubsetSAXFunc
|
||||
nullptr, // hasExternalSubsetSAXFunc
|
||||
nullptr, // resolveEntitySAXFunc
|
||||
nullptr, // getEntitySAXFunc
|
||||
nullptr, // entityDeclSAXFunc
|
||||
nullptr, // notationDeclSAXFunc
|
||||
nullptr, // attributeDeclSAXFunc
|
||||
nullptr, // elementDeclSAXFunc
|
||||
nullptr, // unparsedEntityDeclSAXFunc
|
||||
nullptr, // setDocumentLocatorSAXFunc
|
||||
nullptr, // startDocumentSAXFunc
|
||||
nullptr, // endDocumentSAXFunc
|
||||
&start_element_func, // startElementSAXFunc
|
||||
&end_element_func, // endElementSAXFunc
|
||||
nullptr, // referenceSAXFunc
|
||||
nullptr, // charactersSAXFunc
|
||||
nullptr, // ignorableWhitespaceSAXFunc
|
||||
nullptr, // processingInstructionSAXFunc
|
||||
nullptr, // commentSAXFunc
|
||||
nullptr, // warningSAXFunc
|
||||
nullptr, // errorSAXFunc
|
||||
nullptr, // fatalErrorSAXFunc
|
||||
nullptr, // getParameterEntitySAXFunc
|
||||
nullptr, // cdataBlockSAXFunc
|
||||
nullptr, // externalSubsetSAXFunc
|
||||
0, // unsigned int initialized
|
||||
nullptr, // void * _private
|
||||
nullptr, // startElementNsSAX2Func
|
||||
nullptr, // endElementNsSAX2Func
|
||||
nullptr, // xmlStructuredErrorFunc
|
||||
};
|
||||
} // namespace
|
||||
|
||||
int HtmlParser::parse_chunk(const char *chunk, size_t size, int fin) {
|
||||
if (!parser_ctx_) {
|
||||
parser_ctx_ = htmlCreatePushParserCtxt(
|
||||
&saxHandler, &parser_data_, chunk, static_cast<int>(size),
|
||||
base_uri_.c_str(), XML_CHAR_ENCODING_NONE);
|
||||
parser_ctx_ =
|
||||
htmlCreatePushParserCtxt(&saxHandler, &parser_data_, chunk, size,
|
||||
base_uri_.c_str(), XML_CHAR_ENCODING_NONE);
|
||||
if (!parser_ctx_) {
|
||||
return -1;
|
||||
} else {
|
||||
@@ -195,7 +199,7 @@ int HtmlParser::parse_chunk(const char *chunk, size_t size, int fin) {
|
||||
}
|
||||
|
||||
int HtmlParser::parse_chunk_internal(const char *chunk, size_t size, int fin) {
|
||||
int rv = htmlParseChunk(parser_ctx_, chunk, static_cast<int>(size), fin);
|
||||
int rv = htmlParseChunk(parser_ctx_, chunk, size, fin);
|
||||
if (rv == 0) {
|
||||
return 0;
|
||||
} else {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -34,17 +34,10 @@
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <unordered_map>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
|
||||
#include "ssl_compat.h"
|
||||
|
||||
#ifdef NGHTTP2_OPENSSL_IS_WOLFSSL
|
||||
# include <wolfssl/options.h>
|
||||
# include <wolfssl/openssl/ssl.h>
|
||||
#else // !NGHTTP2_OPENSSL_IS_WOLFSSL
|
||||
# include <openssl/ssl.h>
|
||||
#endif // !NGHTTP2_OPENSSL_IS_WOLFSSL
|
||||
#include <openssl/ssl.h>
|
||||
|
||||
#include <ev.h>
|
||||
|
||||
@@ -59,8 +52,8 @@
|
||||
namespace nghttp2 {
|
||||
|
||||
struct Config {
|
||||
std::unordered_map<std::string, std::vector<std::string>> push;
|
||||
std::unordered_map<std::string, std::string> mime_types;
|
||||
std::map<std::string, std::vector<std::string>> push;
|
||||
std::map<std::string, std::string> mime_types;
|
||||
Headers trailer;
|
||||
std::string trailer_names;
|
||||
std::string htdocs;
|
||||
@@ -91,6 +84,7 @@ struct Config {
|
||||
bool echo_upload;
|
||||
bool no_content_length;
|
||||
bool ktls;
|
||||
bool no_rfc7540_pri;
|
||||
Config();
|
||||
~Config();
|
||||
};
|
||||
@@ -102,18 +96,18 @@ struct FileEntry {
|
||||
const std::string *content_type,
|
||||
const std::chrono::steady_clock::time_point &last_valid,
|
||||
bool stale = false)
|
||||
: path(std::move(path)),
|
||||
length(length),
|
||||
mtime(mtime),
|
||||
last_valid(last_valid),
|
||||
content_type(content_type),
|
||||
dlnext(nullptr),
|
||||
dlprev(nullptr),
|
||||
fd(fd),
|
||||
usecount(1),
|
||||
stale(stale) {}
|
||||
: path(std::move(path)),
|
||||
length(length),
|
||||
mtime(mtime),
|
||||
last_valid(last_valid),
|
||||
content_type(content_type),
|
||||
dlnext(nullptr),
|
||||
dlprev(nullptr),
|
||||
fd(fd),
|
||||
usecount(1),
|
||||
stale(stale) {}
|
||||
std::string path;
|
||||
std::unordered_multimap<std::string, std::unique_ptr<FileEntry>>::iterator it;
|
||||
std::multimap<std::string, std::unique_ptr<FileEntry>>::iterator it;
|
||||
int64_t length;
|
||||
int64_t mtime;
|
||||
std::chrono::steady_clock::time_point last_valid;
|
||||
@@ -125,13 +119,13 @@ struct FileEntry {
|
||||
};
|
||||
|
||||
struct RequestHeader {
|
||||
std::string_view method;
|
||||
std::string_view scheme;
|
||||
std::string_view authority;
|
||||
std::string_view host;
|
||||
std::string_view path;
|
||||
std::string_view ims;
|
||||
std::string_view expect;
|
||||
StringRef method;
|
||||
StringRef scheme;
|
||||
StringRef authority;
|
||||
StringRef host;
|
||||
StringRef path;
|
||||
StringRef ims;
|
||||
StringRef expect;
|
||||
|
||||
struct {
|
||||
nghttp2_rcbuf *method;
|
||||
@@ -176,21 +170,21 @@ public:
|
||||
int connection_made();
|
||||
int verify_alpn_result();
|
||||
|
||||
int submit_file_response(const std::string_view &status, Stream *stream,
|
||||
int submit_file_response(const StringRef &status, Stream *stream,
|
||||
time_t last_modified, off_t file_length,
|
||||
const std::string *content_type,
|
||||
nghttp2_data_provider2 *data_prd);
|
||||
|
||||
int submit_response(const std::string_view &status, int32_t stream_id,
|
||||
int submit_response(const StringRef &status, int32_t stream_id,
|
||||
nghttp2_data_provider2 *data_prd);
|
||||
|
||||
int submit_response(const std::string_view &status, int32_t stream_id,
|
||||
int submit_response(const StringRef &status, int32_t stream_id,
|
||||
const HeaderRefs &headers,
|
||||
nghttp2_data_provider2 *data_prd);
|
||||
|
||||
int submit_non_final_response(const std::string &status, int32_t stream_id);
|
||||
|
||||
int submit_push_promise(Stream *stream, const std::string_view &push_path);
|
||||
int submit_push_promise(Stream *stream, const StringRef &push_path);
|
||||
|
||||
int submit_rst_stream(Stream *stream, uint32_t error_code);
|
||||
|
||||
@@ -221,7 +215,7 @@ private:
|
||||
ev_io wev_;
|
||||
ev_io rev_;
|
||||
ev_timer settings_timerev_;
|
||||
std::unordered_map<int32_t, std::unique_ptr<Stream>> id2stream_;
|
||||
std::map<int32_t, std::unique_ptr<Stream>> id2stream_;
|
||||
WriteBuf wb_;
|
||||
std::function<int(Http2Handler &)> read_, write_;
|
||||
int64_t session_id_;
|
||||
|
||||
@@ -39,19 +39,15 @@ AM_CPPFLAGS = \
|
||||
-I$(top_srcdir)/lib/includes \
|
||||
-I$(top_builddir)/lib/includes \
|
||||
-I$(top_srcdir)/lib \
|
||||
-I$(top_srcdir)/third-party/urlparse \
|
||||
-I$(top_srcdir)/third-party \
|
||||
-I$(top_srcdir)/third-party/llhttp/include \
|
||||
@JEMALLOC_CFLAGS@ \
|
||||
@LIBXML2_CFLAGS@ \
|
||||
@LIBEV_CFLAGS@ \
|
||||
@LIBNGHTTP3_CFLAGS@ \
|
||||
@LIBNGTCP2_CRYPTO_WOLFSSL_CFLAGS@ \
|
||||
@LIBNGTCP2_CRYPTO_QUICTLS_CFLAGS@ \
|
||||
@LIBNGTCP2_CRYPTO_LIBRESSL_CFLAGS@ \
|
||||
@LIBNGTCP2_CRYPTO_BORINGSSL_CFLAGS@ \
|
||||
@LIBNGTCP2_CRYPTO_OSSL_CFLAGS@ \
|
||||
@LIBNGTCP2_CFLAGS@ \
|
||||
@WOLFSSL_CFLAGS@ \
|
||||
@OPENSSL_CFLAGS@ \
|
||||
@LIBCARES_CFLAGS@ \
|
||||
@JANSSON_CFLAGS@ \
|
||||
@@ -64,19 +60,15 @@ AM_CPPFLAGS = \
|
||||
AM_LDFLAGS = @LIBTOOL_LDFLAGS@
|
||||
|
||||
LDADD = $(top_builddir)/lib/libnghttp2.la \
|
||||
$(top_builddir)/third-party/liburlparse.la \
|
||||
$(top_builddir)/third-party/liburl-parser.la \
|
||||
$(top_builddir)/third-party/libllhttp.la \
|
||||
@JEMALLOC_LIBS@ \
|
||||
@LIBXML2_LIBS@ \
|
||||
@LIBEV_LIBS@ \
|
||||
@LIBNGHTTP3_LIBS@ \
|
||||
@LIBNGTCP2_CRYPTO_WOLFSSL_LIBS@ \
|
||||
@LIBNGTCP2_CRYPTO_QUICTLS_LIBS@ \
|
||||
@LIBNGTCP2_CRYPTO_LIBRESSL_LIBS@ \
|
||||
@LIBNGTCP2_CRYPTO_BORINGSSL_LIBS@ \
|
||||
@LIBNGTCP2_CRYPTO_OSSL_LIBS@ \
|
||||
@LIBNGTCP2_LIBS@ \
|
||||
@WOLFSSL_LIBS@ \
|
||||
@OPENSSL_LIBS@ \
|
||||
@LIBCARES_LIBS@ \
|
||||
@SYSTEMD_LIBS@ \
|
||||
@@ -125,7 +117,8 @@ h2load_SOURCES = util.cc util.h \
|
||||
if ENABLE_HTTP3
|
||||
h2load_SOURCES += \
|
||||
h2load_http3_session.cc h2load_http3_session.h \
|
||||
h2load_quic.cc h2load_quic.h
|
||||
h2load_quic.cc h2load_quic.h \
|
||||
quic.cc quic.h
|
||||
endif # ENABLE_HTTP3
|
||||
|
||||
NGHTTPX_SRCS = \
|
||||
@@ -169,6 +162,7 @@ NGHTTPX_SRCS = \
|
||||
shrpx_health_monitor_downstream_connection.cc \
|
||||
shrpx_health_monitor_downstream_connection.h \
|
||||
shrpx_null_downstream_connection.cc shrpx_null_downstream_connection.h \
|
||||
shrpx_exec.cc shrpx_exec.h \
|
||||
shrpx_dns_resolver.cc shrpx_dns_resolver.h \
|
||||
shrpx_dual_dns_resolver.cc shrpx_dual_dns_resolver.h \
|
||||
shrpx_dns_tracker.cc shrpx_dns_tracker.h \
|
||||
@@ -191,7 +185,7 @@ NGHTTPX_SRCS += \
|
||||
shrpx_quic_connection_handler.cc shrpx_quic_connection_handler.h \
|
||||
shrpx_http3_upstream.cc shrpx_http3_upstream.h \
|
||||
http3.cc http3.h \
|
||||
siphash.cc siphash.h
|
||||
quic.cc quic.h
|
||||
endif # ENABLE_HTTP3
|
||||
|
||||
noinst_LIBRARIES = libnghttpx.a
|
||||
@@ -231,9 +225,6 @@ nghttpx_unittest_SOURCES = shrpx-unittest.cc \
|
||||
base64_test.cc base64_test.h \
|
||||
$(top_srcdir)/tests/munit/munit.c $(top_srcdir)/tests/munit/munit.h \
|
||||
$(top_srcdir)/tests/munit/munitxx.h
|
||||
if ENABLE_HTTP3
|
||||
nghttpx_unittest_SOURCES += siphash_test.cc siphash_test.h
|
||||
endif # ENABLE_HTTP3
|
||||
nghttpx_unittest_CPPFLAGS = ${AM_CPPFLAGS} \
|
||||
-I$(top_srcdir)/tests/munit \
|
||||
-DNGHTTP2_SRC_DIR=\"$(top_srcdir)/src\"
|
||||
|
||||
@@ -34,7 +34,6 @@
|
||||
#include <cassert>
|
||||
#include <utility>
|
||||
#include <span>
|
||||
#include <algorithm>
|
||||
|
||||
#include "template.h"
|
||||
|
||||
@@ -70,20 +69,20 @@ static_assert(sizeof(ChunkHead) == 16);
|
||||
// |block_size|.
|
||||
struct BlockAllocator {
|
||||
BlockAllocator(size_t block_size, size_t isolation_threshold)
|
||||
: retain(nullptr),
|
||||
head(nullptr),
|
||||
block_size(block_size),
|
||||
isolation_threshold(std::min(block_size, isolation_threshold)) {
|
||||
: retain(nullptr),
|
||||
head(nullptr),
|
||||
block_size(block_size),
|
||||
isolation_threshold(std::min(block_size, isolation_threshold)) {
|
||||
assert(isolation_threshold <= block_size);
|
||||
}
|
||||
|
||||
~BlockAllocator() { reset(); }
|
||||
|
||||
BlockAllocator(BlockAllocator &&other) noexcept
|
||||
: retain{std::exchange(other.retain, nullptr)},
|
||||
head{std::exchange(other.head, nullptr)},
|
||||
block_size(other.block_size),
|
||||
isolation_threshold(other.isolation_threshold) {}
|
||||
: retain{std::exchange(other.retain, nullptr)},
|
||||
head{std::exchange(other.head, nullptr)},
|
||||
block_size(other.block_size),
|
||||
isolation_threshold(other.isolation_threshold) {}
|
||||
|
||||
BlockAllocator &operator=(BlockAllocator &&other) noexcept {
|
||||
reset();
|
||||
@@ -116,7 +115,7 @@ struct BlockAllocator {
|
||||
|
||||
mb->next = retain;
|
||||
mb->begin = mb->last = reinterpret_cast<uint8_t *>(
|
||||
(reinterpret_cast<intptr_t>(block + sizeof(MemBlock)) + 0xf) & ~0xf);
|
||||
(reinterpret_cast<intptr_t>(block + sizeof(MemBlock)) + 0xf) & ~0xf);
|
||||
mb->end = mb->begin + size;
|
||||
retain = mb;
|
||||
return mb;
|
||||
@@ -147,7 +146,7 @@ struct BlockAllocator {
|
||||
ch->size = size;
|
||||
|
||||
head->last = reinterpret_cast<uint8_t *>(
|
||||
(reinterpret_cast<intptr_t>(res + size) + 0xf) & ~0xf);
|
||||
(reinterpret_cast<intptr_t>(res + size) + 0xf) & ~0xf);
|
||||
|
||||
return res;
|
||||
}
|
||||
@@ -157,7 +156,7 @@ struct BlockAllocator {
|
||||
size_t get_alloc_length(void *ptr) {
|
||||
return reinterpret_cast<ChunkHead *>(static_cast<uint8_t *>(ptr) -
|
||||
sizeof(ChunkHead))
|
||||
->size;
|
||||
->size;
|
||||
}
|
||||
|
||||
// Allocates memory of at least |size| bytes. If |ptr| is nullptr,
|
||||
@@ -180,7 +179,7 @@ struct BlockAllocator {
|
||||
auto nalloclen = std::max(size + 1, alloclen * 2);
|
||||
|
||||
auto res = alloc(nalloclen);
|
||||
std::ranges::copy_n(p, as_signed(alloclen), static_cast<uint8_t *>(res));
|
||||
std::copy_n(p, alloclen, static_cast<uint8_t *>(res));
|
||||
|
||||
return res;
|
||||
}
|
||||
@@ -196,37 +195,29 @@ struct BlockAllocator {
|
||||
size_t isolation_threshold;
|
||||
};
|
||||
|
||||
// Makes a copy of a range [|first|, |last|). The resulting string
|
||||
// will be NULL-terminated.
|
||||
template <std::input_iterator I>
|
||||
std::string_view make_string_ref(BlockAllocator &alloc, I first, I last) {
|
||||
auto dst = static_cast<char *>(
|
||||
alloc.alloc(static_cast<size_t>(std::ranges::distance(first, last) + 1)));
|
||||
auto p = std::ranges::copy(first, last, dst).out;
|
||||
*p = '\0';
|
||||
|
||||
return std::string_view{dst, p};
|
||||
}
|
||||
|
||||
// Makes a copy of |r| as std::string_view. The resulting string will be
|
||||
// Makes a copy of |src|. The resulting string will be
|
||||
// NULL-terminated.
|
||||
template <std::ranges::input_range R>
|
||||
requires(!std::is_array_v<std::remove_cvref_t<R>>)
|
||||
std::string_view make_string_ref(BlockAllocator &alloc, R &&r) {
|
||||
return make_string_ref(alloc, std::ranges::begin(r), std::ranges::end(r));
|
||||
template <typename BlockAllocator>
|
||||
StringRef make_string_ref(BlockAllocator &alloc, const StringRef &src) {
|
||||
auto dst = static_cast<uint8_t *>(alloc.alloc(src.size() + 1));
|
||||
auto p = dst;
|
||||
p = std::copy(std::begin(src), std::end(src), p);
|
||||
*p = '\0';
|
||||
return StringRef{dst, src.size()};
|
||||
}
|
||||
|
||||
// private function used in concat_string_ref. this is the base
|
||||
// function of concat_string_ref_count().
|
||||
constexpr size_t concat_string_ref_count(size_t acc) { return acc; }
|
||||
inline constexpr size_t concat_string_ref_count(size_t acc) { return acc; }
|
||||
|
||||
// private function used in concat_string_ref. This function counts
|
||||
// the sum of length of given arguments. The calculated length is
|
||||
// accumulated, and passed to the next function.
|
||||
template <std::ranges::input_range R, std::ranges::input_range... Args>
|
||||
requires(!std::is_array_v<std::remove_cvref_t<R>>)
|
||||
constexpr size_t concat_string_ref_count(size_t acc, R &&r, Args &&...args) {
|
||||
return concat_string_ref_count(acc + std::ranges::size(r), args...);
|
||||
template <typename... Args>
|
||||
constexpr size_t concat_string_ref_count(size_t acc, const StringRef &value,
|
||||
Args &&...args) {
|
||||
return concat_string_ref_count(acc + value.size(),
|
||||
std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
// private function used in concat_string_ref. this is the base
|
||||
@@ -237,23 +228,23 @@ inline uint8_t *concat_string_ref_copy(uint8_t *p) { return p; }
|
||||
// given strings into |p|. |p| is incremented by the copied length,
|
||||
// and returned. In the end, return value points to the location one
|
||||
// beyond the last byte written.
|
||||
template <std::ranges::input_range R, std::ranges::input_range... Args>
|
||||
requires(!std::is_array_v<std::remove_cvref_t<R>>)
|
||||
uint8_t *concat_string_ref_copy(uint8_t *p, R &&r, Args &&...args) {
|
||||
return concat_string_ref_copy(std::ranges::copy(std::forward<R>(r), p).out,
|
||||
std::forward<Args>(args)...);
|
||||
template <typename... Args>
|
||||
uint8_t *concat_string_ref_copy(uint8_t *p, const StringRef &value,
|
||||
Args &&...args) {
|
||||
p = std::copy(std::begin(value), std::end(value), p);
|
||||
return concat_string_ref_copy(p, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
// Returns the string which is the concatenation of |args| in the
|
||||
// given order. The resulting string will be NULL-terminated.
|
||||
template <std::ranges::input_range... Args>
|
||||
std::string_view concat_string_ref(BlockAllocator &alloc, Args &&...args) {
|
||||
auto len = concat_string_ref_count(0, args...);
|
||||
template <typename BlockAllocator, typename... Args>
|
||||
StringRef concat_string_ref(BlockAllocator &alloc, Args &&...args) {
|
||||
size_t len = concat_string_ref_count(0, std::forward<Args>(args)...);
|
||||
auto dst = static_cast<uint8_t *>(alloc.alloc(len + 1));
|
||||
auto p = dst;
|
||||
p = concat_string_ref_copy(p, std::forward<Args>(args)...);
|
||||
*p = '\0';
|
||||
return as_string_view(dst, p);
|
||||
return StringRef{dst, len};
|
||||
}
|
||||
|
||||
// Returns the string which is the concatenation of |value| and |args|
|
||||
@@ -262,27 +253,27 @@ std::string_view concat_string_ref(BlockAllocator &alloc, Args &&...args) {
|
||||
// obtained from alloc.alloc() or alloc.realloc(), and attempts to use
|
||||
// unused memory region by using alloc.realloc(). If value is empty,
|
||||
// then just call concat_string_ref().
|
||||
template <std::ranges::input_range... Args>
|
||||
std::string_view realloc_concat_string_ref(BlockAllocator &alloc,
|
||||
const std::string_view &value,
|
||||
Args &&...args) {
|
||||
template <typename BlockAllocator, typename... Args>
|
||||
StringRef realloc_concat_string_ref(BlockAllocator &alloc,
|
||||
const StringRef &value, Args &&...args) {
|
||||
if (value.empty()) {
|
||||
return concat_string_ref(alloc, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
auto len = value.size() + concat_string_ref_count(0, args...);
|
||||
auto dst = static_cast<uint8_t *>(alloc.realloc(
|
||||
const_cast<uint8_t *>(reinterpret_cast<const uint8_t *>(value.data())),
|
||||
len + 1));
|
||||
auto len =
|
||||
value.size() + concat_string_ref_count(0, std::forward<Args>(args)...);
|
||||
auto dst = static_cast<uint8_t *>(
|
||||
alloc.realloc(const_cast<uint8_t *>(value.byte()), len + 1));
|
||||
auto p = dst + value.size();
|
||||
p = concat_string_ref_copy(p, std::forward<Args>(args)...);
|
||||
*p = '\0';
|
||||
|
||||
return as_string_view(dst, p);
|
||||
return StringRef{dst, len};
|
||||
}
|
||||
|
||||
// Makes an uninitialized buffer with given size.
|
||||
inline std::span<uint8_t> make_byte_ref(BlockAllocator &alloc, size_t size) {
|
||||
template <typename BlockAllocator>
|
||||
std::span<uint8_t> make_byte_ref(BlockAllocator &alloc, size_t size) {
|
||||
return {static_cast<uint8_t *>(alloc.alloc(size)), size};
|
||||
}
|
||||
|
||||
|
||||
@@ -49,6 +49,7 @@
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <set>
|
||||
#include <iomanip>
|
||||
#include <fstream>
|
||||
|
||||
@@ -118,7 +119,7 @@ std::string strframetype(uint8_t type) {
|
||||
s += ')';
|
||||
|
||||
return s;
|
||||
}
|
||||
};
|
||||
} // namespace
|
||||
|
||||
namespace {
|
||||
@@ -328,20 +329,20 @@ void print_frame(print_type ptype, const nghttp2_frame *frame) {
|
||||
case NGHTTP2_PING:
|
||||
print_frame_attr_indent();
|
||||
fprintf(outfile, "(opaque_data=%s)\n",
|
||||
util::format_hex(std::span{frame->ping.opaque_data}).c_str());
|
||||
util::format_hex(frame->ping.opaque_data).c_str());
|
||||
break;
|
||||
case NGHTTP2_GOAWAY:
|
||||
print_frame_attr_indent();
|
||||
fprintf(
|
||||
outfile,
|
||||
"(last_stream_id=%d, error_code=%s(0x%02x), "
|
||||
"opaque_data(%u)=[%s])\n",
|
||||
frame->goaway.last_stream_id,
|
||||
nghttp2_http2_strerror(frame->goaway.error_code),
|
||||
frame->goaway.error_code,
|
||||
static_cast<unsigned int>(frame->goaway.opaque_data_len),
|
||||
util::ascii_dump(frame->goaway.opaque_data, frame->goaway.opaque_data_len)
|
||||
.c_str());
|
||||
fprintf(outfile,
|
||||
"(last_stream_id=%d, error_code=%s(0x%02x), "
|
||||
"opaque_data(%u)=[%s])\n",
|
||||
frame->goaway.last_stream_id,
|
||||
nghttp2_http2_strerror(frame->goaway.error_code),
|
||||
frame->goaway.error_code,
|
||||
static_cast<unsigned int>(frame->goaway.opaque_data_len),
|
||||
util::ascii_dump(frame->goaway.opaque_data,
|
||||
frame->goaway.opaque_data_len)
|
||||
.c_str());
|
||||
break;
|
||||
case NGHTTP2_WINDOW_UPDATE:
|
||||
print_frame_attr_indent();
|
||||
@@ -367,7 +368,7 @@ void print_frame(print_type ptype, const nghttp2_frame *frame) {
|
||||
}
|
||||
case NGHTTP2_PRIORITY_UPDATE: {
|
||||
auto priority_update =
|
||||
static_cast<nghttp2_ext_priority_update *>(frame->ext.payload);
|
||||
static_cast<nghttp2_ext_priority_update *>(frame->ext.payload);
|
||||
print_frame_attr_indent();
|
||||
fprintf(outfile,
|
||||
"(prioritized_stream_id=%d, priority_field_value=[%.*s])\n",
|
||||
@@ -440,7 +441,7 @@ int verbose_on_data_chunk_recv_callback(nghttp2_session *session, uint8_t flags,
|
||||
size_t len, void *user_data) {
|
||||
print_timer();
|
||||
auto srecv =
|
||||
nghttp2_session_get_stream_effective_recv_data_length(session, stream_id);
|
||||
nghttp2_session_get_stream_effective_recv_data_length(session, stream_id);
|
||||
auto crecv = nghttp2_session_get_effective_recv_data_length(session);
|
||||
|
||||
fprintf(outfile,
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#endif // HAVE_SYS_TIME_H
|
||||
#include <poll.h>
|
||||
|
||||
#include <map>
|
||||
#include <chrono>
|
||||
|
||||
#include <nghttp2/nghttp2.h>
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user