mirror of
https://github.com/nghttp2/nghttp2.git
synced 2025-12-07 18:48:54 +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
|
AcrossEmptyLines: false
|
||||||
AcrossComments: false
|
AcrossComments: false
|
||||||
AlignCompound: false
|
AlignCompound: false
|
||||||
AlignFunctionPointers: false
|
|
||||||
PadOperators: true
|
PadOperators: true
|
||||||
AlignConsecutiveBitFields:
|
AlignConsecutiveBitFields:
|
||||||
Enabled: false
|
Enabled: false
|
||||||
AcrossEmptyLines: false
|
AcrossEmptyLines: false
|
||||||
AcrossComments: false
|
AcrossComments: false
|
||||||
AlignCompound: false
|
AlignCompound: false
|
||||||
AlignFunctionPointers: false
|
|
||||||
PadOperators: true
|
PadOperators: true
|
||||||
AlignConsecutiveDeclarations:
|
AlignConsecutiveDeclarations:
|
||||||
Enabled: false
|
Enabled: false
|
||||||
AcrossEmptyLines: false
|
AcrossEmptyLines: false
|
||||||
AcrossComments: false
|
AcrossComments: false
|
||||||
AlignCompound: false
|
AlignCompound: false
|
||||||
AlignFunctionPointers: false
|
|
||||||
PadOperators: true
|
PadOperators: true
|
||||||
AlignConsecutiveMacros:
|
AlignConsecutiveMacros:
|
||||||
Enabled: false
|
Enabled: false
|
||||||
AcrossEmptyLines: false
|
AcrossEmptyLines: false
|
||||||
AcrossComments: false
|
AcrossComments: false
|
||||||
AlignCompound: false
|
AlignCompound: false
|
||||||
AlignFunctionPointers: false
|
|
||||||
PadOperators: true
|
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
|
AlignEscapedNewlines: Right
|
||||||
AlignOperands: Align
|
AlignOperands: Align
|
||||||
AlignTrailingComments:
|
AlignTrailingComments: true
|
||||||
Kind: Always
|
|
||||||
OverEmptyLines: 0
|
|
||||||
AllowAllArgumentsOnNextLine: true
|
AllowAllArgumentsOnNextLine: true
|
||||||
AllowAllParametersOfDeclarationOnNextLine: true
|
AllowAllParametersOfDeclarationOnNextLine: true
|
||||||
AllowBreakBeforeNoexceptSpecifier: Never
|
|
||||||
AllowShortBlocksOnASingleLine: Never
|
|
||||||
AllowShortCaseExpressionOnASingleLine: true
|
|
||||||
AllowShortCaseLabelsOnASingleLine: false
|
|
||||||
AllowShortCompoundRequirementOnASingleLine: true
|
|
||||||
AllowShortEnumsOnASingleLine: true
|
AllowShortEnumsOnASingleLine: true
|
||||||
|
AllowShortBlocksOnASingleLine: Never
|
||||||
|
AllowShortCaseLabelsOnASingleLine: false
|
||||||
AllowShortFunctionsOnASingleLine: All
|
AllowShortFunctionsOnASingleLine: All
|
||||||
AllowShortIfStatementsOnASingleLine: Never
|
|
||||||
AllowShortLambdasOnASingleLine: All
|
AllowShortLambdasOnASingleLine: All
|
||||||
|
AllowShortIfStatementsOnASingleLine: Never
|
||||||
AllowShortLoopsOnASingleLine: false
|
AllowShortLoopsOnASingleLine: false
|
||||||
AlwaysBreakAfterDefinitionReturnType: None
|
AlwaysBreakAfterDefinitionReturnType: None
|
||||||
|
AlwaysBreakAfterReturnType: None
|
||||||
AlwaysBreakBeforeMultilineStrings: false
|
AlwaysBreakBeforeMultilineStrings: false
|
||||||
|
AlwaysBreakTemplateDeclarations: MultiLine
|
||||||
AttributeMacros:
|
AttributeMacros:
|
||||||
- __capability
|
- __capability
|
||||||
BinPackArguments: true
|
BinPackArguments: true
|
||||||
BinPackParameters: true
|
BinPackParameters: true
|
||||||
BitFieldColonSpacing: Both
|
|
||||||
BraceWrapping:
|
BraceWrapping:
|
||||||
AfterCaseLabel: false
|
AfterCaseLabel: false
|
||||||
AfterClass: false
|
AfterClass: false
|
||||||
AfterControlStatement: Never
|
AfterControlStatement: Never
|
||||||
AfterEnum: false
|
AfterEnum: false
|
||||||
AfterExternBlock: false
|
|
||||||
AfterFunction: false
|
AfterFunction: false
|
||||||
AfterNamespace: false
|
AfterNamespace: false
|
||||||
AfterObjCDeclaration: false
|
AfterObjCDeclaration: false
|
||||||
AfterStruct: false
|
AfterStruct: false
|
||||||
AfterUnion: false
|
AfterUnion: false
|
||||||
|
AfterExternBlock: false
|
||||||
BeforeCatch: false
|
BeforeCatch: false
|
||||||
BeforeElse: false
|
BeforeElse: false
|
||||||
BeforeLambdaBody: false
|
BeforeLambdaBody: false
|
||||||
@@ -101,32 +66,33 @@ BraceWrapping:
|
|||||||
SplitEmptyFunction: true
|
SplitEmptyFunction: true
|
||||||
SplitEmptyRecord: true
|
SplitEmptyRecord: true
|
||||||
SplitEmptyNamespace: true
|
SplitEmptyNamespace: true
|
||||||
BreakAdjacentStringLiterals: true
|
|
||||||
BreakAfterAttributes: Leave
|
|
||||||
BreakAfterJavaFieldAnnotations: false
|
|
||||||
BreakAfterReturnType: None
|
|
||||||
BreakArrays: true
|
|
||||||
BreakBeforeBinaryOperators: None
|
BreakBeforeBinaryOperators: None
|
||||||
BreakBeforeConceptDeclarations: Always
|
BreakBeforeConceptDeclarations: Always
|
||||||
BreakBeforeBraces: Attach
|
BreakBeforeBraces: Attach
|
||||||
BreakBeforeInlineASMColon: OnlyMultiline
|
BreakBeforeInheritanceComma: false
|
||||||
BreakBeforeTernaryOperators: true
|
|
||||||
BreakConstructorInitializers: BeforeColon
|
|
||||||
BreakFunctionDefinitionParameters: false
|
|
||||||
BreakInheritanceList: BeforeColon
|
BreakInheritanceList: BeforeColon
|
||||||
|
BreakBeforeTernaryOperators: true
|
||||||
|
BreakConstructorInitializersBeforeComma: false
|
||||||
|
BreakConstructorInitializers: BeforeColon
|
||||||
|
BreakAfterJavaFieldAnnotations: false
|
||||||
BreakStringLiterals: true
|
BreakStringLiterals: true
|
||||||
BreakTemplateDeclarations: MultiLine
|
|
||||||
ColumnLimit: 80
|
ColumnLimit: 80
|
||||||
CommentPragmas: '^ IWYU pragma:'
|
CommentPragmas: '^ IWYU pragma:'
|
||||||
|
QualifierAlignment: Leave
|
||||||
CompactNamespaces: false
|
CompactNamespaces: false
|
||||||
ConstructorInitializerIndentWidth: 2
|
ConstructorInitializerIndentWidth: 4
|
||||||
ContinuationIndentWidth: 2
|
ContinuationIndentWidth: 4
|
||||||
Cpp11BracedListStyle: true
|
Cpp11BracedListStyle: true
|
||||||
|
DeriveLineEnding: true
|
||||||
DerivePointerAlignment: false
|
DerivePointerAlignment: false
|
||||||
DisableFormat: false
|
DisableFormat: false
|
||||||
EmptyLineAfterAccessModifier: Never
|
EmptyLineAfterAccessModifier: Never
|
||||||
EmptyLineBeforeAccessModifier: LogicalBlock
|
EmptyLineBeforeAccessModifier: LogicalBlock
|
||||||
ExperimentalAutoDetectBinPacking: false
|
ExperimentalAutoDetectBinPacking: false
|
||||||
|
PackConstructorInitializers: NextLine
|
||||||
|
BasedOnStyle: ''
|
||||||
|
ConstructorInitializerAllOnOneLineOrOnePerLine: false
|
||||||
|
AllowAllConstructorInitializersOnNextLine: true
|
||||||
FixNamespaceComments: true
|
FixNamespaceComments: true
|
||||||
ForEachMacros:
|
ForEachMacros:
|
||||||
- foreach
|
- foreach
|
||||||
@@ -151,35 +117,22 @@ IncludeCategories:
|
|||||||
IncludeIsMainRegex: '$'
|
IncludeIsMainRegex: '$'
|
||||||
IncludeIsMainSourceRegex: ''
|
IncludeIsMainSourceRegex: ''
|
||||||
IndentAccessModifiers: false
|
IndentAccessModifiers: false
|
||||||
IndentCaseBlocks: false
|
|
||||||
IndentCaseLabels: false
|
IndentCaseLabels: false
|
||||||
IndentExternBlock: AfterExternBlock
|
IndentCaseBlocks: false
|
||||||
IndentGotoLabels: true
|
IndentGotoLabels: true
|
||||||
IndentPPDirectives: AfterHash
|
IndentPPDirectives: AfterHash
|
||||||
|
IndentExternBlock: AfterExternBlock
|
||||||
IndentRequiresClause: false
|
IndentRequiresClause: false
|
||||||
IndentWidth: 2
|
IndentWidth: 2
|
||||||
IndentWrappedFunctionNames: false
|
IndentWrappedFunctionNames: false
|
||||||
InsertBraces: false
|
InsertBraces: false
|
||||||
InsertNewlineAtEOF: false
|
|
||||||
InsertTrailingCommas: None
|
InsertTrailingCommas: None
|
||||||
IntegerLiteralSeparator:
|
|
||||||
Binary: 0
|
|
||||||
BinaryMinDigits: 0
|
|
||||||
Decimal: 0
|
|
||||||
DecimalMinDigits: 0
|
|
||||||
Hex: 0
|
|
||||||
HexMinDigits: 0
|
|
||||||
JavaScriptQuotes: Leave
|
JavaScriptQuotes: Leave
|
||||||
JavaScriptWrapImports: true
|
JavaScriptWrapImports: true
|
||||||
KeepEmptyLines:
|
KeepEmptyLinesAtTheStartOfBlocks: true
|
||||||
AtEndOfFile: false
|
|
||||||
AtStartOfBlock: false
|
|
||||||
AtStartOfFile: true
|
|
||||||
LambdaBodyIndentation: Signature
|
LambdaBodyIndentation: Signature
|
||||||
LineEnding: DeriveLF
|
|
||||||
MacroBlockBegin: ''
|
MacroBlockBegin: ''
|
||||||
MacroBlockEnd: ''
|
MacroBlockEnd: ''
|
||||||
MainIncludeChar: Quote
|
|
||||||
MaxEmptyLinesToKeep: 1
|
MaxEmptyLinesToKeep: 1
|
||||||
NamespaceIndentation: None
|
NamespaceIndentation: None
|
||||||
ObjCBinPackProtocolList: Auto
|
ObjCBinPackProtocolList: Auto
|
||||||
@@ -187,44 +140,35 @@ ObjCBlockIndentWidth: 2
|
|||||||
ObjCBreakBeforeNestedBlockParam: true
|
ObjCBreakBeforeNestedBlockParam: true
|
||||||
ObjCSpaceAfterProperty: false
|
ObjCSpaceAfterProperty: false
|
||||||
ObjCSpaceBeforeProtocolList: true
|
ObjCSpaceBeforeProtocolList: true
|
||||||
PackConstructorInitializers: NextLine
|
|
||||||
PenaltyBreakAssignment: 2
|
PenaltyBreakAssignment: 2
|
||||||
PenaltyBreakBeforeFirstCallParameter: 19
|
PenaltyBreakBeforeFirstCallParameter: 19
|
||||||
PenaltyBreakComment: 300
|
PenaltyBreakComment: 300
|
||||||
PenaltyBreakFirstLessLess: 120
|
PenaltyBreakFirstLessLess: 120
|
||||||
PenaltyBreakOpenParenthesis: 0
|
PenaltyBreakOpenParenthesis: 0
|
||||||
PenaltyBreakScopeResolution: 500
|
|
||||||
PenaltyBreakString: 1000
|
PenaltyBreakString: 1000
|
||||||
PenaltyBreakTemplateDeclaration: 10
|
PenaltyBreakTemplateDeclaration: 10
|
||||||
PenaltyExcessCharacter: 1000000
|
PenaltyExcessCharacter: 1000000
|
||||||
PenaltyIndentedWhitespace: 0
|
|
||||||
PenaltyReturnTypeOnItsOwnLine: 60
|
PenaltyReturnTypeOnItsOwnLine: 60
|
||||||
|
PenaltyIndentedWhitespace: 0
|
||||||
PointerAlignment: Right
|
PointerAlignment: Right
|
||||||
PPIndentWidth: -1
|
PPIndentWidth: -1
|
||||||
QualifierAlignment: Leave
|
|
||||||
ReferenceAlignment: Pointer
|
ReferenceAlignment: Pointer
|
||||||
ReflowComments: true
|
ReflowComments: true
|
||||||
RemoveBracesLLVM: false
|
RemoveBracesLLVM: false
|
||||||
RemoveParentheses: Leave
|
|
||||||
RemoveSemicolon: false
|
|
||||||
RequiresClausePosition: OwnLine
|
RequiresClausePosition: OwnLine
|
||||||
RequiresExpressionIndentation: OuterScope
|
|
||||||
SeparateDefinitionBlocks: Leave
|
SeparateDefinitionBlocks: Leave
|
||||||
ShortNamespaceLines: 1
|
ShortNamespaceLines: 1
|
||||||
SkipMacroDefinitionBody: false
|
|
||||||
SortIncludes: Never
|
SortIncludes: Never
|
||||||
SortJavaStaticImport: Before
|
SortJavaStaticImport: Before
|
||||||
SortUsingDeclarations: LexicographicNumeric
|
SortUsingDeclarations: true
|
||||||
SpaceAfterCStyleCast: false
|
SpaceAfterCStyleCast: false
|
||||||
SpaceAfterLogicalNot: false
|
SpaceAfterLogicalNot: false
|
||||||
SpaceAfterTemplateKeyword: true
|
SpaceAfterTemplateKeyword: true
|
||||||
SpaceAroundPointerQualifiers: Default
|
|
||||||
SpaceBeforeAssignmentOperators: true
|
SpaceBeforeAssignmentOperators: true
|
||||||
SpaceBeforeCaseColon: false
|
SpaceBeforeCaseColon: false
|
||||||
SpaceBeforeCpp11BracedList: false
|
SpaceBeforeCpp11BracedList: false
|
||||||
SpaceBeforeCtorInitializerColon: true
|
SpaceBeforeCtorInitializerColon: true
|
||||||
SpaceBeforeInheritanceColon: true
|
SpaceBeforeInheritanceColon: true
|
||||||
SpaceBeforeJsonColon: false
|
|
||||||
SpaceBeforeParens: ControlStatements
|
SpaceBeforeParens: ControlStatements
|
||||||
SpaceBeforeParensOptions:
|
SpaceBeforeParensOptions:
|
||||||
AfterControlStatements: true
|
AfterControlStatements: true
|
||||||
@@ -233,40 +177,34 @@ SpaceBeforeParensOptions:
|
|||||||
AfterFunctionDeclarationName: false
|
AfterFunctionDeclarationName: false
|
||||||
AfterIfMacros: true
|
AfterIfMacros: true
|
||||||
AfterOverloadedOperator: false
|
AfterOverloadedOperator: false
|
||||||
AfterPlacementOperator: true
|
|
||||||
AfterRequiresInClause: false
|
AfterRequiresInClause: false
|
||||||
AfterRequiresInExpression: false
|
AfterRequiresInExpression: false
|
||||||
BeforeNonEmptyParentheses: false
|
BeforeNonEmptyParentheses: false
|
||||||
|
SpaceAroundPointerQualifiers: Default
|
||||||
SpaceBeforeRangeBasedForLoopColon: true
|
SpaceBeforeRangeBasedForLoopColon: true
|
||||||
SpaceBeforeSquareBrackets: false
|
|
||||||
SpaceInEmptyBlock: false
|
SpaceInEmptyBlock: false
|
||||||
|
SpaceInEmptyParentheses: false
|
||||||
SpacesBeforeTrailingComments: 1
|
SpacesBeforeTrailingComments: 1
|
||||||
SpacesInAngles: Never
|
SpacesInAngles: Never
|
||||||
|
SpacesInConditionalStatement: false
|
||||||
SpacesInContainerLiterals: true
|
SpacesInContainerLiterals: true
|
||||||
|
SpacesInCStyleCastParentheses: false
|
||||||
SpacesInLineCommentPrefix:
|
SpacesInLineCommentPrefix:
|
||||||
Minimum: 1
|
Minimum: 1
|
||||||
Maximum: -1
|
Maximum: -1
|
||||||
SpacesInParens: Never
|
SpacesInParentheses: false
|
||||||
SpacesInParensOptions:
|
|
||||||
ExceptDoubleParentheses: false
|
|
||||||
InCStyleCasts: false
|
|
||||||
InConditionalStatements: false
|
|
||||||
InEmptyParentheses: false
|
|
||||||
Other: false
|
|
||||||
SpacesInSquareBrackets: false
|
SpacesInSquareBrackets: false
|
||||||
|
SpaceBeforeSquareBrackets: false
|
||||||
|
BitFieldColonSpacing: Both
|
||||||
Standard: Latest
|
Standard: Latest
|
||||||
StatementAttributeLikeMacros:
|
StatementAttributeLikeMacros:
|
||||||
- Q_EMIT
|
- Q_EMIT
|
||||||
StatementMacros:
|
StatementMacros:
|
||||||
- Q_UNUSED
|
- Q_UNUSED
|
||||||
- QT_REQUIRE_VERSION
|
- QT_REQUIRE_VERSION
|
||||||
- munit_void_test_decl
|
|
||||||
- nghttp2_max_def
|
|
||||||
- nghttp2_min_def
|
|
||||||
TableGenBreakInsideDAGArg: DontBreak
|
|
||||||
TabWidth: 8
|
TabWidth: 8
|
||||||
|
UseCRLF: false
|
||||||
UseTab: Never
|
UseTab: Never
|
||||||
VerilogBreakBetweenInstancePorts: true
|
|
||||||
WhitespaceSensitiveMacros:
|
WhitespaceSensitiveMacros:
|
||||||
- STRINGIZE
|
- STRINGIZE
|
||||||
- PP_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
|
permissions: read-all
|
||||||
|
|
||||||
env:
|
env:
|
||||||
LIBBPF_VERSION: v1.6.2
|
LIBBPF_VERSION: v1.3.0
|
||||||
OPENSSL1_VERSION: 1_1_1w+quic
|
OPENSSL1_VERSION: 1_1_1w+quic
|
||||||
OPENSSL3_VERSION: 3.5.2
|
OPENSSL3_VERSION: 3.1.5+quic
|
||||||
BORINGSSL_VERSION: 729648fb79df7bc46c145e49b0dfd8d2a24232f1
|
BORINGSSL_VERSION: 6ab7c1482bf4cdc91c87bc512aaf68ffb18975ec
|
||||||
AWSLC_VERSION: v1.58.1
|
AWSLC_VERSION: v1.26.0
|
||||||
NGHTTP3_VERSION: v1.11.0
|
NGHTTP3_VERSION: v1.3.0
|
||||||
NGTCP2_VERSION: v1.15.1
|
NGTCP2_VERSION: v1.5.0
|
||||||
WOLFSSL_VERSION: v5.8.2-stable
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build-cache:
|
build-cache:
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
os: [ubuntu-24.04, macos-14, macos-15]
|
os: [ubuntu-22.04, macos-13, macos-14]
|
||||||
|
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v5
|
uses: actions/checkout@v4
|
||||||
- name: Restore libbpf cache
|
- name: Restore libbpf cache
|
||||||
id: cache-libbpf
|
id: cache-libbpf
|
||||||
uses: actions/cache@v4
|
uses: actions/cache@v4
|
||||||
@@ -49,8 +48,8 @@ jobs:
|
|||||||
uses: actions/cache@v4
|
uses: actions/cache@v4
|
||||||
with:
|
with:
|
||||||
path: |
|
path: |
|
||||||
boringssl/build/libcrypto.a
|
boringssl/build/crypto/libcrypto.a
|
||||||
boringssl/build/libssl.a
|
boringssl/build/ssl/libssl.a
|
||||||
boringssl/include
|
boringssl/include
|
||||||
key: ${{ matrix.os }}-boringssl-${{ env.BORINGSSL_VERSION }}
|
key: ${{ matrix.os }}-boringssl-${{ env.BORINGSSL_VERSION }}
|
||||||
- name: Restore aws-lc cache
|
- name: Restore aws-lc cache
|
||||||
@@ -62,12 +61,6 @@ jobs:
|
|||||||
aws-lc/build/ssl/libssl.a
|
aws-lc/build/ssl/libssl.a
|
||||||
aws-lc/include
|
aws-lc/include
|
||||||
key: ${{ matrix.os }}-awslc-${{ env.AWSLC_VERSION }}
|
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
|
- name: Restore nghttp3 cache
|
||||||
id: cache-nghttp3
|
id: cache-nghttp3
|
||||||
uses: actions/cache@v4
|
uses: actions/cache@v4
|
||||||
@@ -93,7 +86,6 @@ jobs:
|
|||||||
steps.cache-openssl3.outputs.cache-hit != 'true' ||
|
steps.cache-openssl3.outputs.cache-hit != 'true' ||
|
||||||
steps.cache-boringssl.outputs.cache-hit != 'true' ||
|
steps.cache-boringssl.outputs.cache-hit != 'true' ||
|
||||||
steps.cache-awslc.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-nghttp3.outputs.cache-hit != 'true' ||
|
||||||
steps.cache-ngtcp2-openssl1.outputs.cache-hit != 'true' ||
|
steps.cache-ngtcp2-openssl1.outputs.cache-hit != 'true' ||
|
||||||
steps.cache-ngtcp2-openssl3.outputs.cache-hit != 'true'
|
steps.cache-ngtcp2-openssl3.outputs.cache-hit != 'true'
|
||||||
@@ -104,6 +96,8 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
sudo apt-get update
|
sudo apt-get update
|
||||||
sudo apt-get install \
|
sudo apt-get install \
|
||||||
|
g++-12 \
|
||||||
|
clang-15 \
|
||||||
autoconf \
|
autoconf \
|
||||||
automake \
|
automake \
|
||||||
autotools-dev \
|
autotools-dev \
|
||||||
@@ -118,27 +112,28 @@ jobs:
|
|||||||
brew install \
|
brew install \
|
||||||
autoconf \
|
autoconf \
|
||||||
automake \
|
automake \
|
||||||
|
pkg-config \
|
||||||
libtool
|
libtool
|
||||||
- name: Build libbpf
|
- name: Build libbpf
|
||||||
if: steps.cache-libbpf.outputs.cache-hit != 'true' && runner.os == 'Linux'
|
if: steps.cache-libbpf.outputs.cache-hit != 'true' && runner.os == 'Linux'
|
||||||
run: |
|
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
|
cd libbpf
|
||||||
make -C src install PREFIX=$PWD/build
|
make -C src install PREFIX=$PWD/build
|
||||||
- name: Build quictls/openssl v1.1.1
|
- name: Build quictls/openssl v1.1.1
|
||||||
if: steps.cache-openssl1.outputs.cache-hit != 'true'
|
if: steps.cache-openssl1.outputs.cache-hit != 'true'
|
||||||
run: |
|
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
|
cd openssl1
|
||||||
./config --prefix=$PWD/build
|
./config --prefix=$PWD/build
|
||||||
make -j"$(nproc 2> /dev/null || sysctl -n hw.ncpu)"
|
make -j"$(nproc 2> /dev/null || sysctl -n hw.ncpu)"
|
||||||
make install_sw
|
make install_sw
|
||||||
- name: Build openssl/openssl v3.x
|
- name: Build quictls/openssl v3.x
|
||||||
if: steps.cache-openssl3.outputs.cache-hit != 'true'
|
if: steps.cache-openssl3.outputs.cache-hit != 'true'
|
||||||
run: |
|
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
|
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 -j"$(nproc 2> /dev/null || sysctl -n hw.ncpu)"
|
||||||
make install_sw
|
make install_sw
|
||||||
- name: Build BoringSSL
|
- name: Build BoringSSL
|
||||||
@@ -157,56 +152,42 @@ jobs:
|
|||||||
- name: Build aws-lc
|
- name: Build aws-lc
|
||||||
if: steps.cache-awslc.outputs.cache-hit != 'true'
|
if: steps.cache-awslc.outputs.cache-hit != 'true'
|
||||||
run: |
|
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
|
cd aws-lc
|
||||||
cmake -B build -DDISABLE_GO=ON
|
cmake -B build -DDISABLE_GO=ON
|
||||||
make -j"$(nproc 2> /dev/null || sysctl -n hw.ncpu)" -C build
|
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
|
- name: Build nghttp3
|
||||||
if: steps.cache-nghttp3.outputs.cache-hit != 'true'
|
if: steps.cache-nghttp3.outputs.cache-hit != 'true'
|
||||||
run: |
|
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
|
cd nghttp3
|
||||||
autoreconf -i
|
autoreconf -i
|
||||||
./configure --disable-dependency-tracking --prefix=$PWD/build \
|
./configure --prefix=$PWD/build --enable-lib-only
|
||||||
--enable-lib-only
|
|
||||||
make -j"$(nproc 2> /dev/null || sysctl -n hw.ncpu)" check
|
make -j"$(nproc 2> /dev/null || sysctl -n hw.ncpu)" check
|
||||||
make install
|
make install
|
||||||
- name: Build ngtcp2 + quictls/openssl v1.1.1 + BoringSSL
|
- name: Build ngtcp2 + quictls/openssl v1.1.1 + BoringSSL
|
||||||
if: steps.cache-ngtcp2-openssl1.outputs.cache-hit != 'true'
|
if: steps.cache-ngtcp2-openssl1.outputs.cache-hit != 'true'
|
||||||
run: |
|
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
|
cd ngtcp2-openssl1
|
||||||
autoreconf -i
|
autoreconf -i
|
||||||
./configure --prefix=$PWD/build --enable-lib-only \
|
./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_CFLAGS="-I$PWD/../boringssl/include/" \
|
||||||
BORINGSSL_LIBS="-L$PWD/../boringssl/build -lssl -lcrypto" \
|
BORINGSSL_LIBS="-L$PWD/../boringssl/build/ssl -lssl -L$PWD/../boringssl/build/crypto -lcrypto" \
|
||||||
--disable-dependency-tracking \
|
--with-boringssl
|
||||||
--with-boringssl \
|
|
||||||
--with-wolfssl
|
|
||||||
make -j"$(nproc 2> /dev/null || sysctl -n hw.ncpu)" check
|
make -j"$(nproc 2> /dev/null || sysctl -n hw.ncpu)" check
|
||||||
make install
|
make install
|
||||||
- name: Build ngtcp2 + quictls/openssl v3.x + aws-lc
|
- name: Build ngtcp2 + quictls/openssl v3.x + aws-lc
|
||||||
if: steps.cache-ngtcp2-openssl3.outputs.cache-hit != 'true'
|
if: steps.cache-ngtcp2-openssl3.outputs.cache-hit != 'true'
|
||||||
run: |
|
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
|
cd ngtcp2-openssl3
|
||||||
autoreconf -i
|
autoreconf -i
|
||||||
./configure --prefix=$PWD/build --enable-lib-only \
|
./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_CFLAGS="-I$PWD/../aws-lc/include/" \
|
||||||
BORINGSSL_LIBS="-L$PWD/../aws-lc/build/ssl -lssl -L$PWD/../aws-lc/build/crypto -lcrypto" \
|
BORINGSSL_LIBS="-L$PWD/../aws-lc/build/ssl -lssl -L$PWD/../aws-lc/build/crypto -lcrypto" \
|
||||||
--disable-dependency-tracking \
|
|
||||||
--with-boringssl
|
--with-boringssl
|
||||||
make -j"$(nproc 2> /dev/null || sysctl -n hw.ncpu)" check
|
make -j"$(nproc 2> /dev/null || sysctl -n hw.ncpu)" check
|
||||||
make install
|
make install
|
||||||
@@ -217,42 +198,46 @@ jobs:
|
|||||||
|
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
os: [ubuntu-24.04, macos-14, macos-15]
|
os: [ubuntu-22.04, macos-13, macos-14]
|
||||||
compiler: [gcc, clang]
|
compiler: [gcc, clang]
|
||||||
buildtool: [autotools, cmake]
|
buildtool: [autotools, cmake]
|
||||||
http3: [http3, no-http3]
|
http3: [http3, no-http3]
|
||||||
openssl: [openssl1, openssl3, boringssl, awslc, wolfssl]
|
openssl: [openssl1, openssl3, boringssl, awslc]
|
||||||
exclude:
|
exclude:
|
||||||
- http3: no-http3
|
- os: macos-13
|
||||||
openssl: openssl3
|
openssl: openssl3
|
||||||
- os: macos-14
|
- os: macos-14
|
||||||
|
openssl: openssl3
|
||||||
|
- http3: no-http3
|
||||||
|
openssl: openssl3
|
||||||
|
- os: macos-13
|
||||||
compiler: gcc
|
compiler: gcc
|
||||||
- os: macos-15
|
- os: macos-14
|
||||||
compiler: gcc
|
compiler: gcc
|
||||||
|
- # disable macos cmake because of include path issue
|
||||||
|
os: macos-13
|
||||||
|
buildtool: cmake
|
||||||
- # disable macos cmake because of include path issue
|
- # disable macos cmake because of include path issue
|
||||||
os: macos-14
|
os: macos-14
|
||||||
buildtool: cmake
|
buildtool: cmake
|
||||||
- # disable macos cmake because of include path issue
|
- os: macos-13
|
||||||
os: macos-15
|
|
||||||
buildtool: cmake
|
|
||||||
- os: macos-14
|
|
||||||
openssl: boringssl
|
openssl: boringssl
|
||||||
- os: macos-15
|
- os: macos-14
|
||||||
openssl: boringssl
|
openssl: boringssl
|
||||||
- openssl: boringssl
|
- openssl: boringssl
|
||||||
buildtool: cmake
|
buildtool: cmake
|
||||||
- openssl: boringssl
|
- openssl: boringssl
|
||||||
compiler: gcc
|
compiler: gcc
|
||||||
- os: macos-14
|
- os: macos-13
|
||||||
openssl: awslc
|
openssl: awslc
|
||||||
- os: macos-15
|
- os: macos-14
|
||||||
openssl: awslc
|
openssl: awslc
|
||||||
- openssl: awslc
|
- openssl: awslc
|
||||||
buildtool: cmake
|
buildtool: cmake
|
||||||
- openssl: awslc
|
- openssl: awslc
|
||||||
compiler: gcc
|
compiler: gcc
|
||||||
include:
|
include:
|
||||||
- os: ubuntu-24.04
|
- os: ubuntu-22.04
|
||||||
compiler: clang
|
compiler: clang
|
||||||
buildtool: distcheck
|
buildtool: distcheck
|
||||||
http3: http3
|
http3: http3
|
||||||
@@ -262,7 +247,7 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v5
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
submodules: recursive
|
submodules: recursive
|
||||||
- name: Linux setup
|
- name: Linux setup
|
||||||
@@ -270,8 +255,8 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
sudo apt-get update
|
sudo apt-get update
|
||||||
sudo apt-get install \
|
sudo apt-get install \
|
||||||
g++-14 \
|
g++-12 \
|
||||||
clang-19 \
|
clang-15 \
|
||||||
autoconf \
|
autoconf \
|
||||||
automake \
|
automake \
|
||||||
autotools-dev \
|
autotools-dev \
|
||||||
@@ -302,16 +287,20 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
brew install \
|
brew install \
|
||||||
libev \
|
libev \
|
||||||
|
libevent \
|
||||||
|
c-ares \
|
||||||
libressl \
|
libressl \
|
||||||
|
brotli \
|
||||||
autoconf \
|
autoconf \
|
||||||
automake \
|
automake \
|
||||||
|
pkg-config \
|
||||||
libtool
|
libtool
|
||||||
echo 'PKG_CONFIG_PATH=/usr/local/opt/libressl/lib/pkgconfig:/usr/local/opt/libxml2/lib/pkgconfig' >> $GITHUB_ENV
|
echo 'PKG_CONFIG_PATH=/usr/local/opt/libressl/lib/pkgconfig:/usr/local/opt/libxml2/lib/pkgconfig' >> $GITHUB_ENV
|
||||||
- name: Setup clang (Linux)
|
- name: Setup clang (Linux)
|
||||||
if: runner.os == 'Linux' && matrix.compiler == 'clang'
|
if: runner.os == 'Linux' && matrix.compiler == 'clang'
|
||||||
run: |
|
run: |
|
||||||
echo 'CC=clang-19' >> $GITHUB_ENV
|
echo 'CC=clang-15' >> $GITHUB_ENV
|
||||||
echo 'CXX=clang++-19' >> $GITHUB_ENV
|
echo 'CXX=clang++-15' >> $GITHUB_ENV
|
||||||
- name: Setup clang (MacOS)
|
- name: Setup clang (MacOS)
|
||||||
if: runner.os == 'macOS' && matrix.compiler == 'clang'
|
if: runner.os == 'macOS' && matrix.compiler == 'clang'
|
||||||
run: |
|
run: |
|
||||||
@@ -320,8 +309,8 @@ jobs:
|
|||||||
- name: Setup gcc (Linux)
|
- name: Setup gcc (Linux)
|
||||||
if: runner.os == 'Linux' && matrix.compiler == 'gcc'
|
if: runner.os == 'Linux' && matrix.compiler == 'gcc'
|
||||||
run: |
|
run: |
|
||||||
echo 'CC=gcc-14' >> $GITHUB_ENV
|
echo 'CC=gcc-12' >> $GITHUB_ENV
|
||||||
echo 'CXX=g++-14' >> $GITHUB_ENV
|
echo 'CXX=g++-12' >> $GITHUB_ENV
|
||||||
# g++-12 is known to produce false positive warnings.
|
# g++-12 is known to produce false positive warnings.
|
||||||
echo 'CXXFLAGS=-Wno-restrict' >> $GITHUB_ENV
|
echo 'CXXFLAGS=-Wno-restrict' >> $GITHUB_ENV
|
||||||
- name: Setup gcc (MacOS)
|
- name: Setup gcc (MacOS)
|
||||||
@@ -341,13 +330,13 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
cd libbpf
|
cd libbpf
|
||||||
|
|
||||||
EXTRA_AUTOTOOLS_OPTS="$EXTRA_AUTOTOOLS_OPTS --with-libbpf"
|
EXTRA_AUTOTOOLS_OPTS="--with-libbpf"
|
||||||
EXTRA_CMAKE_OPTS="$EXTRA_CMAKE_OPTS -DWITH_LIBBPF=1"
|
EXTRA_CMAKE_OPTS="-DWITH_LIBBPF=1"
|
||||||
|
|
||||||
echo 'EXTRA_AUTOTOOLS_OPTS='"$EXTRA_AUTOTOOLS_OPTS" >> $GITHUB_ENV
|
echo 'EXTRA_AUTOTOOLS_OPTS='"$EXTRA_AUTOTOOLS_OPTS" >> $GITHUB_ENV
|
||||||
echo 'EXTRA_CMAKE_OPTS='"$EXTRA_CMAKE_OPTS" >> $GITHUB_ENV
|
echo 'EXTRA_CMAKE_OPTS='"$EXTRA_CMAKE_OPTS" >> $GITHUB_ENV
|
||||||
- name: Setup libev variables
|
- name: Setup libev variables
|
||||||
if: runner.os == 'macOS'
|
if: matrix.os == 'macos-14'
|
||||||
run: |
|
run: |
|
||||||
LIBEV_CFLAGS="-I/opt/homebrew/Cellar/libev/4.33/include"
|
LIBEV_CFLAGS="-I/opt/homebrew/Cellar/libev/4.33/include"
|
||||||
LIBEV_LIBS="-L/opt/homebrew/Cellar/libev/4.33/lib -lev"
|
LIBEV_LIBS="-L/opt/homebrew/Cellar/libev/4.33/lib -lev"
|
||||||
@@ -361,7 +350,7 @@ jobs:
|
|||||||
path: openssl1/build
|
path: openssl1/build
|
||||||
key: ${{ matrix.os }}-openssl-${{ env.OPENSSL1_VERSION }}
|
key: ${{ matrix.os }}-openssl-${{ env.OPENSSL1_VERSION }}
|
||||||
fail-on-cache-miss: true
|
fail-on-cache-miss: true
|
||||||
- name: Restore openssl/openssl v3.x cache
|
- name: Restore quictls/openssl v3.x cache
|
||||||
uses: actions/cache/restore@v4
|
uses: actions/cache/restore@v4
|
||||||
if: matrix.openssl == 'openssl3'
|
if: matrix.openssl == 'openssl3'
|
||||||
with:
|
with:
|
||||||
@@ -373,8 +362,8 @@ jobs:
|
|||||||
if: matrix.openssl == 'boringssl'
|
if: matrix.openssl == 'boringssl'
|
||||||
with:
|
with:
|
||||||
path: |
|
path: |
|
||||||
boringssl/build/libcrypto.a
|
boringssl/build/crypto/libcrypto.a
|
||||||
boringssl/build/libssl.a
|
boringssl/build/ssl/libssl.a
|
||||||
boringssl/include
|
boringssl/include
|
||||||
key: ${{ matrix.os }}-boringssl-${{ env.BORINGSSL_VERSION }}
|
key: ${{ matrix.os }}-boringssl-${{ env.BORINGSSL_VERSION }}
|
||||||
fail-on-cache-miss: true
|
fail-on-cache-miss: true
|
||||||
@@ -394,7 +383,7 @@ jobs:
|
|||||||
cd boringssl
|
cd boringssl
|
||||||
|
|
||||||
OPENSSL_CFLAGS="-I$PWD/include/"
|
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"
|
EXTRA_AUTOTOOLS_OPTS="$EXTRA_AUTOTOOLS_OPTS --without-neverbleed --without-jemalloc --disable-examples"
|
||||||
|
|
||||||
echo 'OPENSSL_CFLAGS='"$OPENSSL_CFLAGS" >> $GITHUB_ENV
|
echo 'OPENSSL_CFLAGS='"$OPENSSL_CFLAGS" >> $GITHUB_ENV
|
||||||
@@ -416,21 +405,6 @@ jobs:
|
|||||||
echo 'BORINGSSL_CFLAGS='"$OPENSSL_CFLAGS" >> $GITHUB_ENV
|
echo 'BORINGSSL_CFLAGS='"$OPENSSL_CFLAGS" >> $GITHUB_ENV
|
||||||
echo 'BORINGSSL_LIBS='"$OPENSSL_LIBS" >> $GITHUB_ENV
|
echo 'BORINGSSL_LIBS='"$OPENSSL_LIBS" >> $GITHUB_ENV
|
||||||
echo 'EXTRA_AUTOTOOLS_OPTS='"$EXTRA_AUTOTOOLS_OPTS" >> $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
|
- name: Restore nghttp3 cache
|
||||||
uses: actions/cache/restore@v4
|
uses: actions/cache/restore@v4
|
||||||
if: matrix.http3 == 'http3'
|
if: matrix.http3 == 'http3'
|
||||||
@@ -440,7 +414,7 @@ jobs:
|
|||||||
fail-on-cache-miss: true
|
fail-on-cache-miss: true
|
||||||
- name: Restore ngtcp2 + quictls/openssl v1.1.1 cache + BoringSSL
|
- name: Restore ngtcp2 + quictls/openssl v1.1.1 cache + BoringSSL
|
||||||
uses: actions/cache/restore@v4
|
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:
|
with:
|
||||||
path: ngtcp2-openssl1/build
|
path: ngtcp2-openssl1/build
|
||||||
key: ${{ matrix.os }}-ngtcp2-${{ env.NGTCP2_VERSION }}-openssl-${{ env.OPENSSL1_VERSION }}
|
key: ${{ matrix.os }}-ngtcp2-${{ env.NGTCP2_VERSION }}-openssl-${{ env.OPENSSL1_VERSION }}
|
||||||
@@ -455,18 +429,18 @@ jobs:
|
|||||||
- name: Setup extra environment variables
|
- name: Setup extra environment variables
|
||||||
if: matrix.http3 == 'no-http3'
|
if: matrix.http3 == 'no-http3'
|
||||||
run: |
|
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"
|
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/lib64 -Wl,-rpath,$PWD/openssl3/build/lib"
|
LDFLAGS="$LDFLAGS -Wl,-rpath,$PWD/openssl1/build/lib -Wl,-rpath,$PWD/openssl3/build/lib"
|
||||||
|
|
||||||
echo 'PKG_CONFIG_PATH='"$PKG_CONFIG_PATH" >> $GITHUB_ENV
|
echo 'PKG_CONFIG_PATH='"$PKG_CONFIG_PATH" >> $GITHUB_ENV
|
||||||
echo 'LDFLAGS='"$LDFLAGS" >> $GITHUB_ENV
|
echo 'LDFLAGS='"$LDFLAGS" >> $GITHUB_ENV
|
||||||
- name: Setup extra environment variables for HTTP/3
|
- name: Setup extra environment variables for HTTP/3
|
||||||
if: matrix.http3 == 'http3'
|
if: matrix.http3 == 'http3'
|
||||||
run: |
|
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"
|
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/lib64 -Wl,-rpath,$PWD/openssl3/build/lib -Wl,-rpath,$PWD/libbpf/build/lib64"
|
LDFLAGS="$LDFLAGS -Wl,-rpath,$PWD/openssl1/build/lib -Wl,-rpath,$PWD/openssl3/build/lib -Wl,-rpath,$PWD/libbpf/build/lib64"
|
||||||
EXTRA_AUTOTOOLS_OPTS="$EXTRA_AUTOTOOLS_OPTS --enable-http3"
|
EXTRA_AUTOTOOLS_OPTS="--enable-http3 $EXTRA_AUTOTOOLS_OPTS"
|
||||||
EXTRA_CMAKE_OPTS="$EXTRA_CMAKE_OPTS -DENABLE_HTTP3=1"
|
EXTRA_CMAKE_OPTS="-DENABLE_HTTP3=1 $EXTRA_CMAKE_OPTS"
|
||||||
|
|
||||||
echo 'PKG_CONFIG_PATH='"$PKG_CONFIG_PATH" >> $GITHUB_ENV
|
echo 'PKG_CONFIG_PATH='"$PKG_CONFIG_PATH" >> $GITHUB_ENV
|
||||||
echo 'LDFLAGS='"$LDFLAGS" >> $GITHUB_ENV
|
echo 'LDFLAGS='"$LDFLAGS" >> $GITHUB_ENV
|
||||||
@@ -475,7 +449,7 @@ jobs:
|
|||||||
- name: Configure autotools
|
- name: Configure autotools
|
||||||
run: |
|
run: |
|
||||||
autoreconf -i
|
autoreconf -i
|
||||||
./configure --disable-dependency-tracking
|
./configure
|
||||||
- name: Make distribution and unpack
|
- name: Make distribution and unpack
|
||||||
if: matrix.buildtool != 'distcheck'
|
if: matrix.buildtool != 'distcheck'
|
||||||
run: |
|
run: |
|
||||||
@@ -504,14 +478,14 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
cd $NGHTTP2_BUILD_DIR
|
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
|
make -j"$(nproc)" check
|
||||||
- name: Build nghttp2 with autotools (MacOS)
|
- name: Build nghttp2 with autotools (MacOS)
|
||||||
if: matrix.buildtool == 'autotools' && runner.os == 'macOS'
|
if: matrix.buildtool == 'autotools' && runner.os == 'macOS'
|
||||||
run: |
|
run: |
|
||||||
cd $NGHTTP2_BUILD_DIR
|
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
|
make -j"$(sysctl -n hw.ncpu)" check
|
||||||
- name: Build nghttp2 with autotools (distcheck)
|
- name: Build nghttp2 with autotools (distcheck)
|
||||||
if: matrix.buildtool == 'distcheck'
|
if: matrix.buildtool == 'distcheck'
|
||||||
@@ -527,13 +501,12 @@ jobs:
|
|||||||
- uses: actions/setup-go@v5
|
- uses: actions/setup-go@v5
|
||||||
if: matrix.buildtool != 'distcheck'
|
if: matrix.buildtool != 'distcheck'
|
||||||
with:
|
with:
|
||||||
go-version: "1.24"
|
go-version-file: go.mod
|
||||||
- name: Integration test
|
- name: Integration test
|
||||||
# Integration tests for nghttpx; autotools erases build
|
# Integration tests for nghttpx; autotools erases build
|
||||||
# artifacts.
|
# artifacts.
|
||||||
if: matrix.buildtool != 'distcheck'
|
if: matrix.buildtool != 'distcheck'
|
||||||
run: |
|
run: |
|
||||||
sudo sh -c 'echo "127.0.0.1 127.0.0.1.nip.io" >> /etc/hosts'
|
|
||||||
cd $NGHTTP2_BUILD_DIR/integration-tests
|
cd $NGHTTP2_BUILD_DIR/integration-tests
|
||||||
make it
|
make it
|
||||||
|
|
||||||
@@ -542,22 +515,19 @@ jobs:
|
|||||||
matrix:
|
matrix:
|
||||||
host: [x86_64-w64-mingw32, i686-w64-mingw32]
|
host: [x86_64-w64-mingw32, i686-w64-mingw32]
|
||||||
|
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-22.04
|
||||||
|
|
||||||
env:
|
env:
|
||||||
HOST: ${{ matrix.host }}
|
HOST: ${{ matrix.host }}
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v5
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
submodules: recursive
|
submodules: recursive
|
||||||
- name: Prepare for i386
|
|
||||||
if: matrix.host == 'i686-w64-mingw32'
|
|
||||||
run: |
|
|
||||||
sudo dpkg --add-architecture i386
|
|
||||||
- name: Linux setup
|
- name: Linux setup
|
||||||
run: |
|
run: |
|
||||||
|
sudo dpkg --add-architecture i386
|
||||||
sudo apt-get update
|
sudo apt-get update
|
||||||
sudo apt-get install \
|
sudo apt-get install \
|
||||||
gcc-mingw-w64 \
|
gcc-mingw-w64 \
|
||||||
@@ -570,16 +540,16 @@ jobs:
|
|||||||
- name: Configure autotools
|
- name: Configure autotools
|
||||||
run: |
|
run: |
|
||||||
autoreconf -i && \
|
autoreconf -i && \
|
||||||
./configure --disable-dependency-tracking --enable-werror \
|
./configure --enable-werror --enable-lib-only --host="$HOST" \
|
||||||
--enable-lib-only --host="$HOST" \
|
|
||||||
CFLAGS="-g -O2 -D_WIN32_WINNT=0x0600" LIBS="-pthread"
|
CFLAGS="-g -O2 -D_WIN32_WINNT=0x0600" LIBS="-pthread"
|
||||||
- name: Build nghttp2
|
- name: Build nghttp2
|
||||||
run: |
|
run: |
|
||||||
make -j$(nproc)
|
make -j$(nproc)
|
||||||
make -j$(nproc) check TESTS=""
|
make -j$(nproc) check TESTS=""
|
||||||
- name: Run tests
|
- name: Run tests
|
||||||
|
if: matrix.host == 'x86_64-w64-mingw32'
|
||||||
run: |
|
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
|
cd tests
|
||||||
wine main.exe
|
wine main.exe
|
||||||
|
|
||||||
@@ -597,7 +567,7 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v5
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
submodules: recursive
|
submodules: recursive
|
||||||
- uses: microsoft/setup-msbuild@v2
|
- uses: microsoft/setup-msbuild@v2
|
||||||
@@ -619,10 +589,10 @@ jobs:
|
|||||||
permissions:
|
permissions:
|
||||||
contents: write
|
contents: write
|
||||||
|
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-22.04
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v5
|
- uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
submodules: recursive
|
submodules: recursive
|
||||||
|
|||||||
6
.github/workflows/docker.yaml
vendored
6
.github/workflows/docker.yaml
vendored
@@ -11,14 +11,14 @@ permissions: read-all
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-22.04
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v5
|
- uses: actions/checkout@v4
|
||||||
- name: Set up Docker Buildx
|
- name: Set up Docker Buildx
|
||||||
uses: docker/setup-buildx-action@v3
|
uses: docker/setup-buildx-action@v3
|
||||||
- name: Build
|
- name: Build
|
||||||
uses: docker/build-push-action@v6
|
uses: docker/build-push-action@v5
|
||||||
with:
|
with:
|
||||||
context: docker
|
context: docker
|
||||||
build-args: NGHTTP2_BRANCH=${{ github.ref_name }}
|
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:
|
permissions:
|
||||||
issues: write
|
issues: write
|
||||||
actions: write
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
stale:
|
stale:
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-22.04
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/stale@v9
|
- 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.'
|
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-stale: 30
|
||||||
days-before-close: 7
|
days-before-close: 7
|
||||||
days-before-pr-stale: -1
|
|
||||||
exempt-all-milestones: true
|
exempt-all-milestones: true
|
||||||
|
|||||||
3
.gitmodules
vendored
3
.gitmodules
vendored
@@ -8,6 +8,3 @@
|
|||||||
[submodule "tests/munit"]
|
[submodule "tests/munit"]
|
||||||
path = tests/munit
|
path = tests/munit
|
||||||
url = https://github.com/ngtcp2/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 Korczynski
|
||||||
David Weekly
|
David Weekly
|
||||||
Deel
|
Deel
|
||||||
Deep Chordia
|
|
||||||
Dimitris Apostolou
|
Dimitris Apostolou
|
||||||
Dmitri Tikhonov
|
Dmitri Tikhonov
|
||||||
Dmitriy Vetutnev
|
Dmitriy Vetutnev
|
||||||
@@ -80,7 +79,6 @@ Jonas Kvinge
|
|||||||
Josh Braegger
|
Josh Braegger
|
||||||
José F. Calcerrada
|
José F. Calcerrada
|
||||||
Kamil Dudka
|
Kamil Dudka
|
||||||
Karthik Dasari
|
|
||||||
Kazuho Oku
|
Kazuho Oku
|
||||||
Kenny (kang-yen) Peng
|
Kenny (kang-yen) Peng
|
||||||
Kenny Peng
|
Kenny Peng
|
||||||
@@ -90,11 +88,9 @@ LazyHamster
|
|||||||
Leo Neat
|
Leo Neat
|
||||||
Lorenz Nickel
|
Lorenz Nickel
|
||||||
Lucas Pardue
|
Lucas Pardue
|
||||||
Lukas Märdian
|
|
||||||
MATSUMOTO Ryosuke
|
MATSUMOTO Ryosuke
|
||||||
Marc Bachmann
|
Marc Bachmann
|
||||||
Marcelo Trylesinski
|
Marcelo Trylesinski
|
||||||
Mark Boddington
|
|
||||||
Matt Rudary
|
Matt Rudary
|
||||||
Matt Way
|
Matt Way
|
||||||
Michael Kaufmann
|
Michael Kaufmann
|
||||||
@@ -106,7 +102,6 @@ Nora Shoemaker
|
|||||||
Paweł Wegner
|
Paweł Wegner
|
||||||
Pedro Santos
|
Pedro Santos
|
||||||
Peeyush Aggarwal
|
Peeyush Aggarwal
|
||||||
Peng-Yu Chen
|
|
||||||
Peter Wu
|
Peter Wu
|
||||||
Piotr Sikora
|
Piotr Sikora
|
||||||
PufferOverflow
|
PufferOverflow
|
||||||
@@ -118,11 +113,9 @@ Richard Wolfert
|
|||||||
Rick Lei
|
Rick Lei
|
||||||
Ross Smith II
|
Ross Smith II
|
||||||
Rudi Heitbaum
|
Rudi Heitbaum
|
||||||
Ryan Carsten Schmidt
|
|
||||||
Ryo Ota
|
Ryo Ota
|
||||||
Scott Mitchell
|
Scott Mitchell
|
||||||
Sebastiaan Deckers
|
Sebastiaan Deckers
|
||||||
Sergei Trofimovich
|
|
||||||
Sergey Fedorov
|
Sergey Fedorov
|
||||||
Shelley Vohr
|
Shelley Vohr
|
||||||
Simon Frankenberger
|
Simon Frankenberger
|
||||||
@@ -136,7 +129,6 @@ Syohei YOSHIDA
|
|||||||
Tapanito
|
Tapanito
|
||||||
Tatsuhiko Kubo
|
Tatsuhiko Kubo
|
||||||
Tatsuhiro Tsujikawa
|
Tatsuhiro Tsujikawa
|
||||||
Thomas Devoogdt
|
|
||||||
Tobias Geerinckx-Rice
|
Tobias Geerinckx-Rice
|
||||||
Tom Harwood
|
Tom Harwood
|
||||||
Tomas Krizek
|
Tomas Krizek
|
||||||
@@ -146,22 +138,18 @@ Vernon Tang
|
|||||||
Viacheslav Biriukov
|
Viacheslav Biriukov
|
||||||
Viktor Szakats
|
Viktor Szakats
|
||||||
Viktor Szépe
|
Viktor Szépe
|
||||||
Ville Vesilehto
|
|
||||||
Wenfeng Liu
|
Wenfeng Liu
|
||||||
William A Rowe Jr
|
William A Rowe Jr
|
||||||
Xiaoguang Sun
|
Xiaoguang Sun
|
||||||
Zachary Turner
|
|
||||||
Zhuoyun Wei
|
Zhuoyun Wei
|
||||||
acesso
|
acesso
|
||||||
ayanamist
|
ayanamist
|
||||||
bmarques1995
|
|
||||||
bxshi
|
bxshi
|
||||||
clemahieu
|
clemahieu
|
||||||
dalf
|
dalf
|
||||||
dawg
|
dawg
|
||||||
es
|
es
|
||||||
fangdingjun
|
fangdingjun
|
||||||
feicong
|
|
||||||
hrxi
|
hrxi
|
||||||
jwchoi
|
jwchoi
|
||||||
kumagi
|
kumagi
|
||||||
|
|||||||
141
CMakeLists.txt
141
CMakeLists.txt
@@ -24,13 +24,13 @@
|
|||||||
|
|
||||||
cmake_minimum_required(VERSION 3.14)
|
cmake_minimum_required(VERSION 3.14)
|
||||||
# XXX using 1.8.90 instead of 1.9.0-DEV
|
# XXX using 1.8.90 instead of 1.9.0-DEV
|
||||||
project(nghttp2 VERSION 1.67.0 LANGUAGES C)
|
project(nghttp2 VERSION 1.62.1)
|
||||||
|
|
||||||
# See versioning rule:
|
# See versioning rule:
|
||||||
# https://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html
|
# https://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html
|
||||||
set(LT_CURRENT 43)
|
set(LT_CURRENT 42)
|
||||||
set(LT_REVISION 0)
|
set(LT_REVISION 1)
|
||||||
set(LT_AGE 29)
|
set(LT_AGE 28)
|
||||||
|
|
||||||
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH})
|
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH})
|
||||||
include(Version)
|
include(Version)
|
||||||
@@ -58,7 +58,6 @@ find_package(Python3 COMPONENTS Interpreter)
|
|||||||
|
|
||||||
# Auto-detection of features that can be toggled
|
# Auto-detection of features that can be toggled
|
||||||
if(NOT ENABLE_LIB_ONLY)
|
if(NOT ENABLE_LIB_ONLY)
|
||||||
enable_language(CXX)
|
|
||||||
find_package(Libev 4.11)
|
find_package(Libev 4.11)
|
||||||
find_package(Libcares 1.7.5)
|
find_package(Libcares 1.7.5)
|
||||||
find_package(ZLIB 1.2.3)
|
find_package(ZLIB 1.2.3)
|
||||||
@@ -66,20 +65,20 @@ if(NOT ENABLE_LIB_ONLY)
|
|||||||
find_package(Libbrotlidec 1.0.9)
|
find_package(Libbrotlidec 1.0.9)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(WITH_WOLFSSL)
|
find_package(OpenSSL 1.1.1)
|
||||||
find_package(WolfSSL 5.7.0)
|
find_package(Libngtcp2 1.0.0)
|
||||||
else()
|
find_package(Libngtcp2_crypto_quictls 1.0.0)
|
||||||
find_package(OpenSSL 1.1.1)
|
if(LIBNGTCP2_CRYPTO_QUICTLS_FOUND)
|
||||||
|
set(HAVE_LIBNGTCP2_CRYPTO_QUICTLS 1)
|
||||||
endif()
|
endif()
|
||||||
find_package(Libngtcp2 1.15.0)
|
find_package(Libnghttp3 1.1.0)
|
||||||
find_package(Libnghttp3 1.11.0)
|
|
||||||
if(WITH_LIBBPF)
|
if(WITH_LIBBPF)
|
||||||
find_package(Libbpf 0.7.0)
|
find_package(Libbpf 0.7.0)
|
||||||
if(NOT LIBBPF_FOUND)
|
if(NOT LIBBPF_FOUND)
|
||||||
message(FATAL_ERROR "libbpf was requested (WITH_LIBBPF=1) but not found.")
|
message(FATAL_ERROR "libbpf was requested (WITH_LIBBPF=1) but not found.")
|
||||||
endif()
|
endif()
|
||||||
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)
|
set(ENABLE_APP_DEFAULT ON)
|
||||||
else()
|
else()
|
||||||
set(ENABLE_APP_DEFAULT OFF)
|
set(ENABLE_APP_DEFAULT OFF)
|
||||||
@@ -124,31 +123,30 @@ else()
|
|||||||
set(HINT_NORETURN)
|
set(HINT_NORETURN)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(NOT ENABLE_LIB_ONLY)
|
include(ExtractValidFlags)
|
||||||
include(ExtractValidFlags)
|
foreach(_cxx1x_flag -std=c++20)
|
||||||
foreach(_cxx1x_flag -std=c++20)
|
extract_valid_cxx_flags(_cxx1x_flag_supported ${_cxx1x_flag})
|
||||||
extract_valid_cxx_flags(_cxx1x_flag_supported ${_cxx1x_flag})
|
if(_cxx1x_flag_supported)
|
||||||
if(_cxx1x_flag_supported)
|
set(CXX1XCXXFLAGS ${_cxx1x_flag})
|
||||||
set(CXX1XCXXFLAGS ${_cxx1x_flag})
|
break()
|
||||||
break()
|
endif()
|
||||||
endif()
|
endforeach()
|
||||||
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.
|
# Checks for libraries.
|
||||||
# Additional libraries required for programs under src directory.
|
# Additional libraries required for programs under src directory.
|
||||||
@@ -176,7 +174,7 @@ add_custom_target(check COMMAND ${CMAKE_CTEST_COMMAND})
|
|||||||
# openssl (for src)
|
# openssl (for src)
|
||||||
include(CheckSymbolExists)
|
include(CheckSymbolExists)
|
||||||
set(HAVE_OPENSSL ${OPENSSL_FOUND})
|
set(HAVE_OPENSSL ${OPENSSL_FOUND})
|
||||||
if(NOT ENABLE_LIB_ONLY AND OPENSSL_FOUND)
|
if(OPENSSL_FOUND)
|
||||||
set(OPENSSL_INCLUDE_DIRS ${OPENSSL_INCLUDE_DIR})
|
set(OPENSSL_INCLUDE_DIRS ${OPENSSL_INCLUDE_DIR})
|
||||||
cmake_push_check_state()
|
cmake_push_check_state()
|
||||||
set(CMAKE_REQUIRED_INCLUDES "${OPENSSL_INCLUDE_DIR}")
|
set(CMAKE_REQUIRED_INCLUDES "${OPENSSL_INCLUDE_DIR}")
|
||||||
@@ -184,14 +182,10 @@ if(NOT ENABLE_LIB_ONLY AND OPENSSL_FOUND)
|
|||||||
if(WIN32)
|
if(WIN32)
|
||||||
set(CMAKE_REQUIRED_LIBRARIES "${CMAKE_REQUIRED_LIBRARIES}" "ws2_32" "bcrypt")
|
set(CMAKE_REQUIRED_LIBRARIES "${CMAKE_REQUIRED_LIBRARIES}" "ws2_32" "bcrypt")
|
||||||
endif()
|
endif()
|
||||||
check_symbol_exists("LIBRESSL_VERSION_NUMBER" "openssl/opensslv.h" LIBRESSL_FOUND)
|
|
||||||
if(ENABLE_HTTP3)
|
if(ENABLE_HTTP3)
|
||||||
check_symbol_exists(SSL_provide_quic_data "openssl/ssl.h" HAVE_SSL_PROVIDE_QUIC_DATA)
|
check_symbol_exists(SSL_provide_quic_data "openssl/ssl.h" HAVE_SSL_PROVIDE_QUIC_DATA)
|
||||||
if(NOT 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)
|
message(WARNING "OpenSSL in ${OPENSSL_LIBRARIES} does not have SSL_provide_quic_data. HTTP/3 support cannot be enabled")
|
||||||
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()
|
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
cmake_pop_check_state()
|
cmake_pop_check_state()
|
||||||
@@ -199,22 +193,6 @@ else()
|
|||||||
set(OPENSSL_INCLUDE_DIRS "")
|
set(OPENSSL_INCLUDE_DIRS "")
|
||||||
set(OPENSSL_LIBRARIES "")
|
set(OPENSSL_LIBRARIES "")
|
||||||
endif()
|
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)
|
# libev (for src)
|
||||||
set(HAVE_LIBEV ${LIBEV_FOUND})
|
set(HAVE_LIBEV ${LIBEV_FOUND})
|
||||||
set(HAVE_ZLIB ${ZLIB_FOUND})
|
set(HAVE_ZLIB ${ZLIB_FOUND})
|
||||||
@@ -267,45 +245,13 @@ int main() { enum bpf_stats_type foo; (void)foo; }" HAVE_BPF_STATS_TYPE)
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
# The nghttp, nghttpd and nghttpx under src depend on zlib, OpenSSL and libev
|
# 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.")
|
message(FATAL_ERROR "Applications were requested (ENABLE_APP=1) but dependencies are not met.")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(ENABLE_HTTP3)
|
# HTTP/3 requires quictls/openssl, libngtcp2, libngtcp2_crypto_quictls
|
||||||
if(HAVE_SSL_PROVIDE_QUIC_DATA AND NOT LIBRESSL_FOUND)
|
# and libnghttp3.
|
||||||
find_package(Libngtcp2_crypto_quictls 1.15.0)
|
if(ENABLE_HTTP3 AND NOT (HAVE_SSL_PROVIDE_QUIC_DATA AND LIBNGTCP2_FOUND AND LIBNGTCP2_CRYPTO_QUICTLS_FOUND AND LIBNGHTTP3_FOUND))
|
||||||
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))))
|
|
||||||
message(FATAL_ERROR "HTTP/3 was requested (ENABLE_HTTP3=1) but dependencies are not met.")
|
message(FATAL_ERROR "HTTP/3 was requested (ENABLE_HTTP3=1) but dependencies are not met.")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
@@ -380,9 +326,8 @@ check_function_exists(_Exit HAVE__EXIT)
|
|||||||
check_function_exists(accept4 HAVE_ACCEPT4)
|
check_function_exists(accept4 HAVE_ACCEPT4)
|
||||||
check_function_exists(clock_gettime HAVE_CLOCK_GETTIME)
|
check_function_exists(clock_gettime HAVE_CLOCK_GETTIME)
|
||||||
check_function_exists(mkostemp HAVE_MKOSTEMP)
|
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)
|
include(CheckSymbolExists)
|
||||||
# XXX does this correctly detect initgroups (un)availability on cygwin?
|
# XXX does this correctly detect initgroups (un)availability on cygwin?
|
||||||
@@ -499,6 +444,7 @@ if(ENABLE_DOC)
|
|||||||
add_subdirectory(doc)
|
add_subdirectory(doc)
|
||||||
endif()
|
endif()
|
||||||
add_subdirectory(contrib)
|
add_subdirectory(contrib)
|
||||||
|
add_subdirectory(script)
|
||||||
add_subdirectory(bpf)
|
add_subdirectory(bpf)
|
||||||
|
|
||||||
|
|
||||||
@@ -526,14 +472,11 @@ message(STATUS "summary of build options:
|
|||||||
Build Test: ${BUILD_TESTING}
|
Build Test: ${BUILD_TESTING}
|
||||||
Libs:
|
Libs:
|
||||||
OpenSSL: ${HAVE_OPENSSL} (LIBS='${OPENSSL_LIBRARIES}')
|
OpenSSL: ${HAVE_OPENSSL} (LIBS='${OPENSSL_LIBRARIES}')
|
||||||
wolfSSL: ${HAVE_WOLFSSL} (LIBS='${WOLFSSL_LIBRARIES}')
|
|
||||||
Libxml2: ${HAVE_LIBXML2} (LIBS='${LIBXML2_LIBRARIES}')
|
Libxml2: ${HAVE_LIBXML2} (LIBS='${LIBXML2_LIBRARIES}')
|
||||||
Libev: ${HAVE_LIBEV} (LIBS='${LIBEV_LIBRARIES}')
|
Libev: ${HAVE_LIBEV} (LIBS='${LIBEV_LIBRARIES}')
|
||||||
Libc-ares: ${HAVE_LIBCARES} (LIBS='${LIBCARES_LIBRARIES}')
|
Libc-ares: ${HAVE_LIBCARES} (LIBS='${LIBCARES_LIBRARIES}')
|
||||||
Libngtcp2: ${HAVE_LIBNGTCP2} (LIBS='${LIBNGTCP2_LIBRARIES}')
|
Libngtcp2: ${HAVE_LIBNGTCP2} (LIBS='${LIBNGTCP2_LIBRARIES}')
|
||||||
Libngtcp2_crypto_quictls: ${HAVE_LIBNGTCP2_CRYPTO_QUICTLS} (LIBS='${LIBNGTCP2_CRYPTO_QUICTLS_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}')
|
Libnghttp3: ${HAVE_LIBNGHTTP3} (LIBS='${LIBNGHTTP3_LIBRARIES}')
|
||||||
Libbpf: ${HAVE_LIBBPF} (LIBS='${LIBBPF_LIBRARIES}')
|
Libbpf: ${HAVE_LIBBPF} (LIBS='${LIBBPF_LIBRARIES}')
|
||||||
Libevent(SSL): ${HAVE_LIBEVENT_OPENSSL} (LIBS='${LIBEVENT_OPENSSL_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_MRUBY "Use mruby")
|
||||||
option(WITH_NEVERBLEED "Use neverbleed")
|
option(WITH_NEVERBLEED "Use neverbleed")
|
||||||
option(WITH_LIBBPF "Use libbpf")
|
option(WITH_LIBBPF "Use libbpf")
|
||||||
option(WITH_WOLFSSL "Use wolfSSL")
|
|
||||||
|
|
||||||
# vim: ft=cmake:
|
# vim: ft=cmake:
|
||||||
|
|||||||
@@ -12,21 +12,21 @@
|
|||||||
|
|
||||||
|
|
||||||
# Only use standalone-toolchain for reduce size
|
# Only use standalone-toolchain for reduce size
|
||||||
FROM ubuntu:24.04
|
FROM ubuntu:22.04
|
||||||
LABEL org.opencontainers.image.authors="Tatsuhiro Tsujikawa"
|
MAINTAINER Tatsuhiro Tsujikawa
|
||||||
|
|
||||||
ARG NDK_VERSION=r27c
|
ENV NDK_VERSION r25b
|
||||||
ARG NDK=/root/android-ndk-$NDK_VERSION
|
ENV NDK /root/android-ndk-$NDK_VERSION
|
||||||
ARG TOOLCHAIN=$NDK/toolchains/llvm/prebuilt/linux-x86_64
|
ENV TOOLCHAIN $NDK/toolchains/llvm/prebuilt/linux-x86_64
|
||||||
ARG TARGET=aarch64-linux-android
|
ENV TARGET aarch64-linux-android
|
||||||
ARG API=33
|
ENV API 33
|
||||||
ARG AR=$TOOLCHAIN/bin/llvm-ar
|
ENV AR $TOOLCHAIN/bin/llvm-ar
|
||||||
ARG CC=$TOOLCHAIN/bin/$TARGET$API-clang
|
ENV CC $TOOLCHAIN/bin/$TARGET$API-clang
|
||||||
ARG CXX=$TOOLCHAIN/bin/$TARGET$API-clang++
|
ENV CXX $TOOLCHAIN/bin/$TARGET$API-clang++
|
||||||
ARG LD=$TOOLCHAIN/bin/ld
|
ENV LD $TOOLCHAIN/bin/ld
|
||||||
ARG RANDLIB=$TOOLCHAIN/bin/llvm-ranlib
|
ENV RANDLIB $TOOLCHAIN/bin/llvm-ranlib
|
||||||
ARG STRIP=$TOOLCHAIN/bin/llvm-strip
|
ENV STRIP $TOOLCHAIN/bin/llvm-strip
|
||||||
ARG PREFIX=/root/usr/local
|
ENV PREFIX /root/usr/local
|
||||||
|
|
||||||
WORKDIR /root
|
WORKDIR /root
|
||||||
RUN apt-get update && \
|
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
|
rm android-ndk-$NDK_VERSION-linux.zip
|
||||||
|
|
||||||
# Setup version of libraries
|
# Setup version of libraries
|
||||||
ARG OPENSSL_VERSION=1.1.1w
|
ENV OPENSSL_VERSION 1.1.1q
|
||||||
ARG LIBEV_VERSION=4.33
|
ENV LIBEV_VERSION 4.33
|
||||||
ARG ZLIB_VERSION=1.3.1
|
ENV ZLIB_VERSION 1.2.13
|
||||||
ARG CARES_VERSION=1.18.1
|
ENV CARES_VERSION 1.18.1
|
||||||
ARG NGHTTP2_VERSION=master
|
ENV NGHTTP2_VERSION master
|
||||||
|
|
||||||
WORKDIR /root/build
|
WORKDIR /root/build
|
||||||
RUN curl -L -O https://www.openssl.org/source/openssl-$OPENSSL_VERSION.tar.gz && \
|
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
|
WORKDIR /root/build/libev-$LIBEV_VERSION
|
||||||
RUN ./configure \
|
RUN ./configure \
|
||||||
--disable-dependency-tracking \
|
|
||||||
--host=$TARGET \
|
--host=$TARGET \
|
||||||
--build=`dpkg-architecture -qDEB_BUILD_GNU_TYPE` \
|
--build=`dpkg-architecture -qDEB_BUILD_GNU_TYPE` \
|
||||||
--prefix=$PREFIX \
|
--prefix=$PREFIX \
|
||||||
@@ -76,7 +75,7 @@ RUN ./configure \
|
|||||||
make install
|
make install
|
||||||
|
|
||||||
WORKDIR /root/build
|
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 && \
|
tar xf zlib-$ZLIB_VERSION.tar.gz && \
|
||||||
rm zlib-$ZLIB_VERSION.tar.gz
|
rm zlib-$ZLIB_VERSION.tar.gz
|
||||||
|
|
||||||
@@ -91,13 +90,12 @@ RUN HOST=$TARGET \
|
|||||||
|
|
||||||
|
|
||||||
WORKDIR /root/build
|
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 && \
|
tar xf c-ares-$CARES_VERSION.tar.gz && \
|
||||||
rm c-ares-$CARES_VERSION.tar.gz
|
rm c-ares-$CARES_VERSION.tar.gz
|
||||||
|
|
||||||
WORKDIR /root/build/c-ares-$CARES_VERSION
|
WORKDIR /root/build/c-ares-$CARES_VERSION
|
||||||
RUN ./configure \
|
RUN ./configure \
|
||||||
--disable-dependency-tracking \
|
|
||||||
--host=$TARGET \
|
--host=$TARGET \
|
||||||
--build=`dpkg-architecture -qDEB_BUILD_GNU_TYPE` \
|
--build=`dpkg-architecture -qDEB_BUILD_GNU_TYPE` \
|
||||||
--prefix=$PREFIX \
|
--prefix=$PREFIX \
|
||||||
@@ -105,11 +103,10 @@ RUN ./configure \
|
|||||||
make install
|
make install
|
||||||
|
|
||||||
WORKDIR /root/build
|
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
|
WORKDIR /root/build/nghttp2
|
||||||
RUN autoreconf -i && \
|
RUN autoreconf -i && \
|
||||||
./configure \
|
./configure \
|
||||||
--disable-dependency-tracking \
|
|
||||||
--enable-app \
|
--enable-app \
|
||||||
--disable-shared \
|
--disable-shared \
|
||||||
--host=$TARGET \
|
--host=$TARGET \
|
||||||
@@ -119,6 +116,6 @@ RUN autoreconf -i && \
|
|||||||
--disable-threads \
|
--disable-threads \
|
||||||
CPPFLAGS="-fPIE -I$PREFIX/include" \
|
CPPFLAGS="-fPIE -I$PREFIX/include" \
|
||||||
PKG_CONFIG_LIBDIR="$PREFIX/lib/pkgconfig" \
|
PKG_CONFIG_LIBDIR="$PREFIX/lib/pkgconfig" \
|
||||||
LDFLAGS="-static-libstdc++ -static-libgcc -fPIE -pie -L$PREFIX/lib" && \
|
LDFLAGS="-fPIE -pie -L$PREFIX/lib" && \
|
||||||
make && \
|
make && \
|
||||||
$STRIP src/nghttpx src/nghttpd src/nghttp
|
$STRIP src/nghttpx src/nghttpd src/nghttp
|
||||||
|
|||||||
@@ -20,8 +20,8 @@
|
|||||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
SUBDIRS = lib tests third-party src bpf examples integration-tests \
|
SUBDIRS = lib third-party src bpf examples tests integration-tests \
|
||||||
doc contrib
|
doc contrib script
|
||||||
|
|
||||||
ACLOCAL_AMFLAGS = -I m4
|
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/FindLibngtcp2_crypto_quictls.cmake \
|
||||||
cmake/FindLibbrotlienc.cmake \
|
cmake/FindLibbrotlienc.cmake \
|
||||||
cmake/FindLibbrotlidec.cmake \
|
cmake/FindLibbrotlidec.cmake \
|
||||||
cmake/FindLibngtcp2_crypto_wolfssl.cmake \
|
|
||||||
cmake/FindLibngtcp2_crypto_ossl.cmake \
|
|
||||||
cmake/FindWolfSSL.cmake \
|
|
||||||
cmake/PickyWarningsC.cmake \
|
cmake/PickyWarningsC.cmake \
|
||||||
cmake/PickyWarningsCXX.cmake
|
cmake/PickyWarningsCXX.cmake
|
||||||
|
|
||||||
|
|||||||
47
README.rst
47
README.rst
@@ -31,8 +31,9 @@ implementation.
|
|||||||
|
|
||||||
* https://nghttp2.org/ (TLS + ALPN and HTTP/3)
|
* https://nghttp2.org/ (TLS + ALPN and HTTP/3)
|
||||||
|
|
||||||
This endpoint supports ``h2`` and ``http/1.1`` via ALPN and requires
|
This endpoint supports ``h2``, ``h2-16``, ``h2-14``, and
|
||||||
TLSv1.2 for HTTP/2 connection.
|
``http/1.1`` via ALPN and requires TLSv1.2 for HTTP/2
|
||||||
|
connection.
|
||||||
|
|
||||||
It also supports HTTP/3.
|
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
|
``nghttpx`` and ``h2load``) in the ``src`` directory, the following packages
|
||||||
are required:
|
are required:
|
||||||
|
|
||||||
* OpenSSL >= 1.1.1; or wolfSSL >= 5.7.0; or LibreSSL >= 3.8.1; or
|
* OpenSSL >= 1.1.1; or LibreSSL >= 3.8.1; or aws-lc >= 1.19.0; or
|
||||||
aws-lc >= 1.19.0; or BoringSSL
|
BoringSSL
|
||||||
* libev >= 4.11
|
* libev >= 4.11
|
||||||
* zlib >= 1.2.3
|
* zlib >= 1.2.3
|
||||||
* libc-ares >= 1.7.5
|
* 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
|
To enable the experimental HTTP/3 support for h2load and nghttpx, the
|
||||||
following libraries are required:
|
following libraries are required:
|
||||||
|
|
||||||
* `quictls
|
* `OpenSSL with QUIC support
|
||||||
<https://github.com/quictls/openssl/tree/OpenSSL_1_1_1w+quic>`_; or
|
<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
|
`BoringSSL <https://boringssl.googlesource.com/boringssl/>`_ (commit
|
||||||
729648fb79df7bc46c145e49b0dfd8d2a24232f1); or OpenSSL >= 3.5.0
|
6ab7c1482bf4cdc91c87bc512aaf68ffb18975ec)
|
||||||
* `ngtcp2 <https://github.com/ngtcp2/ngtcp2>`_ >= 1.15.0
|
* `ngtcp2 <https://github.com/ngtcp2/ngtcp2>`_ >= 1.4.0
|
||||||
* `nghttp3 <https://github.com/ngtcp2/nghttp3>`_ >= 1.11.0
|
* `nghttp3 <https://github.com/ngtcp2/nghttp3>`_ >= 1.1.0
|
||||||
|
|
||||||
Use ``--enable-http3`` configure option to enable HTTP/3 feature for
|
Use ``--enable-http3`` configure option to enable HTTP/3 feature for
|
||||||
h2load and nghttpx.
|
h2load and nghttpx.
|
||||||
@@ -143,14 +144,14 @@ Use ``--with-libbpf`` configure option to build eBPF program.
|
|||||||
libelf-dev is needed to build libbpf.
|
libelf-dev is needed to build libbpf.
|
||||||
|
|
||||||
For Ubuntu 20.04, you can build libbpf from `the source code
|
For Ubuntu 20.04, you can build libbpf from `the source code
|
||||||
<https://github.com/libbpf/libbpf/releases>`_. nghttpx requires eBPF
|
<https://github.com/libbpf/libbpf/releases/tag/v1.3.0>`_. nghttpx
|
||||||
program for reloading its configuration and hot swapping its
|
requires eBPF program for reloading its configuration and hot swapping
|
||||||
executable.
|
its executable.
|
||||||
|
|
||||||
Compiling libnghttp2 C source code requires a C99 compiler. gcc 4.8
|
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,
|
is known to be adequate. In order to compile the C++ source code,
|
||||||
C++20 compliant compiler is required. At least g++ >= 12 and
|
C++20 compliant compiler is required. At least g++ >= 1.12 and
|
||||||
clang++ >= 18 are known to work.
|
clang++ >= 1.15 are known to work.
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|
|
||||||
@@ -340,7 +341,7 @@ Build aws-lc:
|
|||||||
|
|
||||||
.. code-block:: text
|
.. 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
|
$ cd aws-lc
|
||||||
$ cmake -B build -DDISABLE_GO=ON --install-prefix=$PWD/opt
|
$ cmake -B build -DDISABLE_GO=ON --install-prefix=$PWD/opt
|
||||||
$ make -j$(nproc) -C build
|
$ make -j$(nproc) -C build
|
||||||
@@ -351,7 +352,7 @@ Build nghttp3:
|
|||||||
|
|
||||||
.. code-block:: text
|
.. 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
|
$ cd nghttp3
|
||||||
$ git submodule update --init --depth 1
|
$ git submodule update --init --depth 1
|
||||||
$ autoreconf -i
|
$ autoreconf -i
|
||||||
@@ -364,7 +365,7 @@ Build ngtcp2:
|
|||||||
|
|
||||||
.. code-block:: text
|
.. 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
|
$ cd ngtcp2
|
||||||
$ git submodule update --init --depth 1
|
$ git submodule update --init --depth 1
|
||||||
$ autoreconf -i
|
$ autoreconf -i
|
||||||
@@ -380,7 +381,7 @@ from source:
|
|||||||
|
|
||||||
.. code-block:: text
|
.. 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
|
$ cd libbpf
|
||||||
$ PREFIX=$PWD/build make -C src install
|
$ PREFIX=$PWD/build make -C src install
|
||||||
$ cd ..
|
$ cd ..
|
||||||
@@ -394,7 +395,7 @@ Build nghttp2:
|
|||||||
$ git submodule update --init
|
$ git submodule update --init
|
||||||
$ autoreconf -i
|
$ autoreconf -i
|
||||||
$ ./configure --with-mruby --enable-http3 --with-libbpf \
|
$ ./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" \
|
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"
|
LDFLAGS="$LDFLAGS -Wl,-rpath,$PWD/../aws-lc/opt/lib -Wl,-rpath,$PWD/../libbpf/build/lib64"
|
||||||
$ make -j$(nproc)
|
$ make -j$(nproc)
|
||||||
@@ -846,10 +847,10 @@ to know how to migrate from earlier releases.
|
|||||||
|
|
||||||
``nghttpx`` implements `important performance-oriented features
|
``nghttpx`` implements `important performance-oriented features
|
||||||
<https://istlsfastyet.com/#server-performance>`_ in TLS, such as
|
<https://istlsfastyet.com/#server-performance>`_ in TLS, such as
|
||||||
session IDs, session tickets (with automatic key rotation), dynamic
|
session IDs, session tickets (with automatic key rotation), OCSP
|
||||||
record sizing, ALPN, forward secrecy and HTTP/2. ``nghttpx`` also
|
stapling, dynamic record sizing, ALPN, forward secrecy and HTTP/2.
|
||||||
offers the functionality to share ticket keys among multiple
|
``nghttpx`` also offers the functionality to share session cache and
|
||||||
``nghttpx`` instances via memcached.
|
ticket keys among multiple ``nghttpx`` instances via memcached.
|
||||||
|
|
||||||
``nghttpx`` has 2 operation modes:
|
``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)
|
dynamically trading ROM for RAM - This can be useful in (embedded)
|
||||||
bootloader applications, where ROM is often limited. */
|
bootloader applications, where ROM is often limited. */
|
||||||
static const __u8 rsbox[256] = {
|
static const __u8 rsbox[256] = {
|
||||||
0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81,
|
0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e,
|
||||||
0xf3, 0xd7, 0xfb, 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e,
|
0x81, 0xf3, 0xd7, 0xfb, 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87,
|
||||||
0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23,
|
0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, 0x54, 0x7b, 0x94, 0x32,
|
||||||
0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e, 0x08, 0x2e, 0xa1, 0x66,
|
0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e,
|
||||||
0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25, 0x72,
|
0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49,
|
||||||
0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65,
|
0x6d, 0x8b, 0xd1, 0x25, 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16,
|
||||||
0xb6, 0x92, 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46,
|
0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92, 0x6c, 0x70, 0x48, 0x50,
|
||||||
0x57, 0xa7, 0x8d, 0x9d, 0x84, 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a,
|
0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84,
|
||||||
0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06, 0xd0, 0x2c, 0x1e, 0x8f, 0xca,
|
0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05,
|
||||||
0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b, 0x3a, 0x91,
|
0xb8, 0xb3, 0x45, 0x06, 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02,
|
||||||
0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6,
|
0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b, 0x3a, 0x91, 0x11, 0x41,
|
||||||
0x73, 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8,
|
0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73,
|
||||||
0x1c, 0x75, 0xdf, 0x6e, 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f,
|
0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8,
|
||||||
0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b, 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2,
|
0x1c, 0x75, 0xdf, 0x6e, 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89,
|
||||||
0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4, 0x1f, 0xdd, 0xa8,
|
0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b, 0xfc, 0x56, 0x3e, 0x4b,
|
||||||
0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f,
|
0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4,
|
||||||
0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93,
|
0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59,
|
||||||
0xc9, 0x9c, 0xef, 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb,
|
0x27, 0x80, 0xec, 0x5f, 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d,
|
||||||
0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61, 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6,
|
0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef, 0xa0, 0xe0, 0x3b, 0x4d,
|
||||||
0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d};
|
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
|
/* This function adds the round key to state. The round key is added
|
||||||
to the state by an XOR function. */
|
to the state by an XOR function. */
|
||||||
|
|||||||
@@ -17,18 +17,12 @@ find_library(LIBCARES_LIBRARY
|
|||||||
)
|
)
|
||||||
|
|
||||||
if(LIBCARES_INCLUDE_DIR)
|
if(LIBCARES_INCLUDE_DIR)
|
||||||
file(READ "${LIBCARES_INCLUDE_DIR}/ares_version.h" _ares_version_h)
|
set(_version_regex "^#define[ \t]+ARES_VERSION_STR[ \t]+\"([^\"]+)\".*")
|
||||||
string(REGEX REPLACE ".*#define[ \t]+ARES_VERSION_MAJOR[ \t]+([0-9]+).*" "\\1"
|
file(STRINGS "${LIBCARES_INCLUDE_DIR}/ares_version.h"
|
||||||
_ares_version_major ${_ares_version_h})
|
LIBCARES_VERSION REGEX "${_version_regex}")
|
||||||
string(REGEX REPLACE ".*#define[ \t]+ARES_VERSION_MINOR[ \t]+([0-9]+).*" "\\1"
|
string(REGEX REPLACE "${_version_regex}" "\\1"
|
||||||
_ares_version_minor ${_ares_version_h})
|
LIBCARES_VERSION "${LIBCARES_VERSION}")
|
||||||
string(REGEX REPLACE ".*#define[ \t]+ARES_VERSION_PATCH[ \t]+([0-9]+).*" "\\1"
|
unset(_version_regex)
|
||||||
_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)
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
include(FindPackageHandleStandardArgs)
|
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
|
list(APPEND WPICKY_ENABLE
|
||||||
${WPICKY_COMMON_OLD}
|
${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
|
# Enable based on compiler version
|
||||||
if((CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 3.6) OR
|
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))
|
(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. */
|
/* Define to `int' if <sys/types.h> does not define. */
|
||||||
#cmakedefine ssize_t @ssize_t@
|
#cmakedefine ssize_t @ssize_t@
|
||||||
|
|
||||||
/* Define to 1 if you have the `std::chrono::time_zone`. */
|
/* Define to 1 if you have the `std::map::emplace`. */
|
||||||
#cmakedefine HAVE_STD_CHRONO_TIME_ZONE 1
|
#cmakedefine HAVE_STD_MAP_EMPLACE 1
|
||||||
|
|
||||||
/* Define to 1 if you have `libjansson` library. */
|
/* Define to 1 if you have `libjansson` library. */
|
||||||
#cmakedefine HAVE_JANSSON 1
|
#cmakedefine HAVE_JANSSON 1
|
||||||
@@ -31,9 +31,6 @@
|
|||||||
/* Define to 1 if you have the `mkostemp` function. */
|
/* Define to 1 if you have the `mkostemp` function. */
|
||||||
#cmakedefine HAVE_MKOSTEMP 1
|
#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. */
|
/* Define to 1 if you have the `GetTickCount64` function. */
|
||||||
#cmakedefine HAVE_GETTICKCOUNT64 1
|
#cmakedefine HAVE_GETTICKCOUNT64 1
|
||||||
|
|
||||||
@@ -100,17 +97,8 @@
|
|||||||
/* Define to 1 if you have `libngtcp2_crypto_quictls` library. */
|
/* Define to 1 if you have `libngtcp2_crypto_quictls` library. */
|
||||||
#cmakedefine HAVE_LIBNGTCP2_CRYPTO_QUICTLS
|
#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. */
|
/* Define to 1 if you have `libev` library. */
|
||||||
#cmakedefine HAVE_LIBEV 1
|
#cmakedefine HAVE_LIBEV 1
|
||||||
|
|
||||||
/* Define to 1 if you have `libbrotlienc` and `libbrotlidec` libraries. */
|
/* Define to 1 if you have `libbrotlienc` and `libbrotlidec` libraries. */
|
||||||
#cmakedefine HAVE_LIBBROTLI 1
|
#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
|
dnl https://www.gnu.org/software/automake/manual/html_node/Flag-Variables-Ordering.html
|
||||||
|
|
||||||
AC_PREREQ(2.61)
|
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_AUX_DIR([.])
|
||||||
AC_CONFIG_MACRO_DIR([m4])
|
AC_CONFIG_MACRO_DIR([m4])
|
||||||
AC_CONFIG_HEADERS([config.h])
|
AC_CONFIG_HEADERS([config.h])
|
||||||
@@ -44,9 +44,9 @@ m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
|
|||||||
|
|
||||||
dnl See versioning rule:
|
dnl See versioning rule:
|
||||||
dnl https://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html
|
dnl https://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html
|
||||||
AC_SUBST(LT_CURRENT, 43)
|
AC_SUBST(LT_CURRENT, 42)
|
||||||
AC_SUBST(LT_REVISION, 0)
|
AC_SUBST(LT_REVISION, 1)
|
||||||
AC_SUBST(LT_AGE, 29)
|
AC_SUBST(LT_AGE, 28)
|
||||||
|
|
||||||
major=`echo $PACKAGE_VERSION |cut -d. -f1 | sed -e "s/[^0-9]//g"`
|
major=`echo $PACKAGE_VERSION |cut -d. -f1 | sed -e "s/[^0-9]//g"`
|
||||||
minor=`echo $PACKAGE_VERSION |cut -d. -f2 | sed -e "s/[^0-9]//g"`
|
minor=`echo $PACKAGE_VERSION |cut -d. -f2 | sed -e "s/[^0-9]//g"`
|
||||||
@@ -127,11 +127,6 @@ AC_ARG_WITH([libcares],
|
|||||||
[Use libc-ares [default=check]])],
|
[Use libc-ares [default=check]])],
|
||||||
[request_libcares=$withval], [request_libcares=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],
|
AC_ARG_WITH([openssl],
|
||||||
[AS_HELP_STRING([--with-openssl],
|
[AS_HELP_STRING([--with-openssl],
|
||||||
[Use openssl [default=check]])],
|
[Use openssl [default=check]])],
|
||||||
@@ -272,6 +267,22 @@ std::vector<std::future<int>> v;
|
|||||||
[have_std_future=no
|
[have_std_future=no
|
||||||
AC_MSG_RESULT([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.
|
# Check that std::atomic<std::shared_ptr<T>> is supported.
|
||||||
AC_MSG_CHECKING([whether 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(
|
AC_COMPILE_IFELSE([AC_LANG_PROGRAM(
|
||||||
@@ -291,21 +302,19 @@ a.store(p);
|
|||||||
[have_atomic_std_shared_ptr=no
|
[have_atomic_std_shared_ptr=no
|
||||||
AC_MSG_RESULT([no])])
|
AC_MSG_RESULT([no])])
|
||||||
|
|
||||||
# Check that std::chrono::time_zone is available.
|
# Check that thread_local storage specifier is available
|
||||||
AC_MSG_CHECKING([whether std::chrono::time_zone is available])
|
AC_MSG_CHECKING([whether thread_local storage class specifier is available.])
|
||||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM(
|
AC_COMPILE_IFELSE([AC_LANG_PROGRAM(
|
||||||
|
,
|
||||||
[[
|
[[
|
||||||
#include <chrono>
|
thread_local int a = 0;
|
||||||
]],
|
(void)a;
|
||||||
[[
|
|
||||||
auto tz = std::chrono::current_zone();
|
|
||||||
(void)tz;
|
|
||||||
]])],
|
]])],
|
||||||
[AC_DEFINE([HAVE_STD_CHRONO_TIME_ZONE], [1],
|
[AC_DEFINE([HAVE_THREAD_LOCAL], [1],
|
||||||
[Define to 1 if you have the `std::chrono::time_zone`.])
|
[Define to 1 if you have thread_local storage specifier.])
|
||||||
have_std_chrono_time_zone=yes
|
have_thread_local=yes
|
||||||
AC_MSG_RESULT([yes])],
|
AC_MSG_RESULT([yes])],
|
||||||
[have_std_chrono_time_zone=no
|
[have_Thread_local=no
|
||||||
AC_MSG_RESULT([no])])
|
AC_MSG_RESULT([no])])
|
||||||
|
|
||||||
CXXFLAGS=$save_CXXFLAGS
|
CXXFLAGS=$save_CXXFLAGS
|
||||||
@@ -324,7 +333,7 @@ case "$host_os" in
|
|||||||
*android*)
|
*android*)
|
||||||
android_build=yes
|
android_build=yes
|
||||||
# android does not need -pthread, but needs following 2 libs for C++
|
# android does not need -pthread, but needs following 2 libs for C++
|
||||||
APPLDFLAGS="$APPLDFLAGS -latomic"
|
APPLDFLAGS="$APPLDFLAGS -lstdc++ -latomic"
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
PTHREAD_LDFLAGS="-pthread"
|
PTHREAD_LDFLAGS="-pthread"
|
||||||
@@ -402,15 +411,9 @@ if test "x${request_libev}" = "xyes" &&
|
|||||||
AC_MSG_ERROR([libev was requested (--with-libev) but not found])
|
AC_MSG_ERROR([libev was requested (--with-libev) but not found])
|
||||||
fi
|
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)
|
# openssl (for src)
|
||||||
have_openssl=no
|
have_openssl=no
|
||||||
if test "x${request_openssl}" != "xno" &&
|
if test "x${request_openssl}" != "xno"; then
|
||||||
test "x${request_wolfssl}" != "xyes"; then
|
|
||||||
PKG_CHECK_MODULES([OPENSSL], [openssl >= 1.1.1],
|
PKG_CHECK_MODULES([OPENSSL], [openssl >= 1.1.1],
|
||||||
[have_openssl=yes], [have_openssl=no])
|
[have_openssl=yes], [have_openssl=no])
|
||||||
if test "x${have_openssl}" = "xno"; then
|
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([yes]); have_ssl_provide_quic_data=yes],
|
||||||
[AC_MSG_RESULT([no]); have_ssl_provide_quic_data=no])
|
[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.
|
# boringssl has SSL_set_quic_early_data_context.
|
||||||
AC_MSG_CHECKING([for SSL_set_quic_early_data_context])
|
AC_MSG_CHECKING([for SSL_set_quic_early_data_context])
|
||||||
AC_LINK_IFELSE([AC_LANG_PROGRAM([[
|
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])
|
AC_MSG_ERROR([openssl was requested (--with-openssl) but not found])
|
||||||
fi
|
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)
|
# c-ares (for src)
|
||||||
have_libcares=no
|
have_libcares=no
|
||||||
if test "x${request_libcares}" != "xno"; then
|
if test "x${request_libcares}" != "xno"; then
|
||||||
@@ -532,7 +480,7 @@ fi
|
|||||||
# ngtcp2 (for src)
|
# ngtcp2 (for src)
|
||||||
have_libngtcp2=no
|
have_libngtcp2=no
|
||||||
if test "x${request_libngtcp2}" != "xno"; then
|
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])
|
[have_libngtcp2=no])
|
||||||
if test "x${have_libngtcp2}" = "xno"; then
|
if test "x${have_libngtcp2}" = "xno"; then
|
||||||
AC_MSG_NOTICE($LIBNGTCP2_PKG_ERRORS)
|
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])
|
AC_MSG_ERROR([libngtcp2 was requested (--with-libngtcp2) but not found])
|
||||||
fi
|
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)
|
# ngtcp2_crypto_quictls (for src)
|
||||||
have_libngtcp2_crypto_quictls=no
|
have_libngtcp2_crypto_quictls=no
|
||||||
if test "x${have_ssl_provide_quic_data}" = "xyes" &&
|
if test "x${have_ssl_provide_quic_data}" = "xyes" &&
|
||||||
test "x${have_libressl}" != "xyes" &&
|
|
||||||
test "x${have_boringssl_quic}" != "xyes" &&
|
test "x${have_boringssl_quic}" != "xyes" &&
|
||||||
test "x${request_libngtcp2}" != "xno"; then
|
test "x${request_libngtcp2}" != "xno"; then
|
||||||
PKG_CHECK_MODULES([LIBNGTCP2_CRYPTO_QUICTLS],
|
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=yes],
|
||||||
[have_libngtcp2_crypto_quictls=no])
|
[have_libngtcp2_crypto_quictls=no])
|
||||||
if test "x${have_libngtcp2_crypto_quictls}" = "xno"; then
|
if test "x${have_libngtcp2_crypto_quictls}" = "xno"; then
|
||||||
@@ -585,37 +510,12 @@ if test "x${have_ssl_provide_quic_data}" = "xyes" &&
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
if test "x${have_ssl_provide_quic_data}" = "xyes" &&
|
if test "x${have_ssl_provide_quic_data}" = "xyes" &&
|
||||||
test "x${have_libressl}" != "xyes" &&
|
|
||||||
test "x${have_boringssl_quic}" != "xyes" &&
|
test "x${have_boringssl_quic}" != "xyes" &&
|
||||||
test "x${request_libngtcp2}" = "xyes" &&
|
test "x${request_libngtcp2}" = "xyes" &&
|
||||||
test "x${have_libngtcp2_crypto_quictls}" != "xyes"; then
|
test "x${have_libngtcp2_crypto_quictls}" != "xyes"; then
|
||||||
AC_MSG_ERROR([libngtcp2_crypto_quictls was requested (--with-libngtcp2) but not found])
|
AC_MSG_ERROR([libngtcp2_crypto_quictls was requested (--with-libngtcp2) but not found])
|
||||||
fi
|
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)
|
# ngtcp2_crypto_boringssl (for src)
|
||||||
have_libngtcp2_crypto_boringssl=no
|
have_libngtcp2_crypto_boringssl=no
|
||||||
if test "x${have_boringssl_quic}" = "xyes" &&
|
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])
|
AC_MSG_ERROR([libngtcp2_crypto_boringssl was requested (--with-libngtcp2) but not found])
|
||||||
fi
|
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)
|
# nghttp3 (for src)
|
||||||
have_libnghttp3=no
|
have_libnghttp3=no
|
||||||
if test "x${request_libnghttp3}" != "xno"; then
|
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])
|
[have_libnghttp3=no])
|
||||||
if test "x${have_libnghttp3}" = "xno"; then
|
if test "x${have_libnghttp3}" = "xno"; then
|
||||||
AC_MSG_NOTICE($LIBNGHTTP3_PKG_ERRORS)
|
AC_MSG_NOTICE($LIBNGHTTP3_PKG_ERRORS)
|
||||||
@@ -873,7 +751,7 @@ fi
|
|||||||
enable_app=no
|
enable_app=no
|
||||||
if test "x${request_app}" != "xno" &&
|
if test "x${request_app}" != "xno" &&
|
||||||
test "x${have_zlib}" = "xyes" &&
|
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_libev}" = "xyes" &&
|
||||||
test "x${have_libcares}" = "xyes"; then
|
test "x${have_libcares}" = "xyes"; then
|
||||||
enable_app=yes
|
enable_app=yes
|
||||||
@@ -890,11 +768,8 @@ AM_CONDITIONAL([ENABLE_APP], [ test "x${enable_app}" = "xyes" ])
|
|||||||
enable_http3=no
|
enable_http3=no
|
||||||
if test "x${request_http3}" != "xno" &&
|
if test "x${request_http3}" != "xno" &&
|
||||||
test "x${have_libngtcp2}" = "xyes" &&
|
test "x${have_libngtcp2}" = "xyes" &&
|
||||||
(test "x${have_libngtcp2_crypto_wolfssl}" = "xyes" ||
|
(test "x${have_libngtcp2_crypto_quictls}" = "xyes" ||
|
||||||
test "x${have_libngtcp2_crypto_quictls}" = "xyes" ||
|
test "x${have_libngtcp2_crypto_boringssl}" = "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_libnghttp3}" = "xyes"; then
|
test "x${have_libnghttp3}" = "xyes"; then
|
||||||
enable_http3=yes
|
enable_http3=yes
|
||||||
AC_DEFINE([ENABLE_HTTP3], [1], [Define to 1 if HTTP/3 is enabled.])
|
AC_DEFINE([ENABLE_HTTP3], [1], [Define to 1 if HTTP/3 is enabled.])
|
||||||
@@ -1070,7 +945,6 @@ AC_CHECK_FUNCS([ \
|
|||||||
memmove \
|
memmove \
|
||||||
memset \
|
memset \
|
||||||
mkostemp \
|
mkostemp \
|
||||||
pipe2 \
|
|
||||||
socket \
|
socket \
|
||||||
sqrt \
|
sqrt \
|
||||||
strchr \
|
strchr \
|
||||||
@@ -1175,7 +1049,6 @@ if test "x$werror" != "xno"; then
|
|||||||
# Only work with Clang for the moment
|
# Only work with Clang for the moment
|
||||||
AX_CHECK_COMPILE_FLAG([-Wheader-guard], [CFLAGS="$CFLAGS -Wheader-guard"])
|
AX_CHECK_COMPILE_FLAG([-Wheader-guard], [CFLAGS="$CFLAGS -Wheader-guard"])
|
||||||
AX_CHECK_COMPILE_FLAG([-Wsometimes-uninitialized], [CFLAGS="$CFLAGS -Wsometimes-uninitialized"])
|
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*.
|
# This is required because we pass format string as "const char*.
|
||||||
AX_CHECK_COMPILE_FLAG([-Wno-format-nonliteral], [CFLAGS="$CFLAGS -Wno-format-nonliteral"])
|
AX_CHECK_COMPILE_FLAG([-Wno-format-nonliteral], [CFLAGS="$CFLAGS -Wno-format-nonliteral"])
|
||||||
@@ -1186,13 +1059,9 @@ if test "x$werror" != "xno"; then
|
|||||||
AX_CHECK_COMPILE_FLAG([-Werror], [CXXFLAGS="$CXXFLAGS -Werror"])
|
AX_CHECK_COMPILE_FLAG([-Werror], [CXXFLAGS="$CXXFLAGS -Werror"])
|
||||||
AX_CHECK_COMPILE_FLAG([-Wformat-security], [CXXFLAGS="$CXXFLAGS -Wformat-security"])
|
AX_CHECK_COMPILE_FLAG([-Wformat-security], [CXXFLAGS="$CXXFLAGS -Wformat-security"])
|
||||||
AX_CHECK_COMPILE_FLAG([-Wsometimes-uninitialized], [CXXFLAGS="$CXXFLAGS -Wsometimes-uninitialized"])
|
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
|
# Disable noexcept-type warning of g++-7. This is not harmful as
|
||||||
# long as all source files are compiled with the same compiler.
|
# long as all source files are compiled with the same compiler.
|
||||||
AX_CHECK_COMPILE_FLAG([-Wno-noexcept-type], [CXXFLAGS="$CXXFLAGS -Wno-noexcept-type"])
|
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()
|
AC_LANG_POP()
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -1259,6 +1128,7 @@ AC_CONFIG_FILES([
|
|||||||
doc/nghttp2ver.h.rst
|
doc/nghttp2ver.h.rst
|
||||||
doc/contribute.rst
|
doc/contribute.rst
|
||||||
contrib/Makefile
|
contrib/Makefile
|
||||||
|
script/Makefile
|
||||||
])
|
])
|
||||||
AC_OUTPUT
|
AC_OUTPUT
|
||||||
|
|
||||||
@@ -1300,16 +1170,13 @@ AC_MSG_NOTICE([summary of build options:
|
|||||||
Test:
|
Test:
|
||||||
Failmalloc: ${enable_failmalloc}
|
Failmalloc: ${enable_failmalloc}
|
||||||
Libs:
|
Libs:
|
||||||
wolfSSL: ${have_wolfssl} (CFLAGS='${WOLFSSL_CFLAGS}' LIBS='${WOLFSSL_LIBS}')
|
|
||||||
OpenSSL: ${have_openssl} (CFLAGS='${OPENSSL_CFLAGS}' LIBS='${OPENSSL_LIBS}')
|
OpenSSL: ${have_openssl} (CFLAGS='${OPENSSL_CFLAGS}' LIBS='${OPENSSL_LIBS}')
|
||||||
Libxml2: ${have_libxml2} (CFLAGS='${LIBXML2_CFLAGS}' LIBS='${LIBXML2_LIBS}')
|
Libxml2: ${have_libxml2} (CFLAGS='${LIBXML2_CFLAGS}' LIBS='${LIBXML2_LIBS}')
|
||||||
Libev: ${have_libev} (CFLAGS='${LIBEV_CFLAGS}' LIBS='${LIBEV_LIBS}')
|
Libev: ${have_libev} (CFLAGS='${LIBEV_CFLAGS}' LIBS='${LIBEV_LIBS}')
|
||||||
Libc-ares: ${have_libcares} (CFLAGS='${LIBCARES_CFLAGS}' LIBS='${LIBCARES_LIBS}')
|
Libc-ares: ${have_libcares} (CFLAGS='${LIBCARES_CFLAGS}' LIBS='${LIBCARES_LIBS}')
|
||||||
libngtcp2: ${have_libngtcp2} (CFLAGS='${LIBNGTCP2_CFLAGS}' LIBS='${LIBNGTCP2_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_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_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}')
|
libnghttp3: ${have_libnghttp3} (CFLAGS='${LIBNGHTTP3_CFLAGS}' LIBS='${LIBNGHTTP3_LIBS}')
|
||||||
libbpf: ${have_libbpf} (CFLAGS='${LIBBPF_CFLAGS}' LIBS='${LIBBPF_LIBS}')
|
libbpf: ${have_libbpf} (CFLAGS='${LIBBPF_CFLAGS}' LIBS='${LIBBPF_LIBS}')
|
||||||
Libevent(SSL): ${have_libevent_openssl} (CFLAGS='${LIBEVENT_OPENSSL_CFLAGS}' LIBS='${LIBEVENT_OPENSSL_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_outbound_ack.rst \
|
||||||
nghttp2_option_set_max_settings.rst \
|
nghttp2_option_set_max_settings.rst \
|
||||||
nghttp2_option_set_stream_reset_rate_limit.rst \
|
nghttp2_option_set_stream_reset_rate_limit.rst \
|
||||||
nghttp2_option_set_glitch_rate_limit.rst \
|
|
||||||
nghttp2_pack_settings_payload.rst \
|
nghttp2_pack_settings_payload.rst \
|
||||||
nghttp2_pack_settings_payload2.rst \
|
nghttp2_pack_settings_payload2.rst \
|
||||||
nghttp2_priority_spec_check_default.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_on_stream_close_callback.rst \
|
||||||
nghttp2_session_callbacks_set_pack_extension_callback.rst \
|
nghttp2_session_callbacks_set_pack_extension_callback.rst \
|
||||||
nghttp2_session_callbacks_set_pack_extension_callback2.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_callback.rst \
|
||||||
nghttp2_session_callbacks_set_recv_callback2.rst \
|
nghttp2_session_callbacks_set_recv_callback2.rst \
|
||||||
nghttp2_session_callbacks_set_select_padding_callback.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
|
_get_comp_words_by_ref cur prev
|
||||||
case $cur in
|
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
|
_filedir
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ _nghttpd()
|
|||||||
_get_comp_words_by_ref cur prev
|
_get_comp_words_by_ref cur prev
|
||||||
case $cur in
|
case $cur in
|
||||||
-*)
|
-*)
|
||||||
COMPREPLY=( $( compgen -W '--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
|
_filedir
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ _nghttpx()
|
|||||||
_get_comp_words_by_ref cur prev
|
_get_comp_words_by_ref cur prev
|
||||||
case $cur in
|
case $cur in
|
||||||
-*)
|
-*)
|
||||||
COMPREPLY=( $( compgen -W '--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
|
_filedir
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
|||||||
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
||||||
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
|
.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
|
.SH NAME
|
||||||
h2load \- HTTP/2 benchmarking tool
|
h2load \- HTTP/2 benchmarking tool
|
||||||
.SH SYNOPSIS
|
.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
|
by a single comma only and any white spaces are treated
|
||||||
as a part of protocol string.
|
as a part of protocol string.
|
||||||
.sp
|
.sp
|
||||||
Default: \fBh2,http/1.1\fP
|
Default: \fBh2,h2\-16,h2\-14,http/1.1\fP
|
||||||
.UNINDENT
|
.UNINDENT
|
||||||
.INDENT 0.0
|
.INDENT 0.0
|
||||||
.TP
|
.TP
|
||||||
|
|||||||
@@ -221,7 +221,7 @@ OPTIONS
|
|||||||
by a single comma only and any white spaces are treated
|
by a single comma only and any white spaces are treated
|
||||||
as a part of protocol string.
|
as a part of protocol string.
|
||||||
|
|
||||||
Default: ``h2,http/1.1``
|
Default: ``h2,h2-16,h2-14,http/1.1``
|
||||||
|
|
||||||
.. option:: --h1
|
.. 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]]
|
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
||||||
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
|
.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
|
.SH NAME
|
||||||
nghttp \- HTTP/2 client
|
nghttp \- HTTP/2 client
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
@@ -141,15 +141,14 @@ HTTP upgrade request is performed with OPTIONS method.
|
|||||||
.UNINDENT
|
.UNINDENT
|
||||||
.INDENT 0.0
|
.INDENT 0.0
|
||||||
.TP
|
.TP
|
||||||
.B \-\-extpri=<PRI>
|
.B \-p, \-\-weight=<WEIGHT>
|
||||||
Sets RFC 9218 priority of given URI. <PRI> must be the
|
Sets weight of given URI. This option can be used
|
||||||
wire format of priority header field (e.g., \(dqu=3,i\(dq).
|
multiple times, and N\-th \fI\%\-p\fP option sets weight of N\-th
|
||||||
This option can be used multiple times, and N\-th
|
URI in the command line. If the number of \fI\%\-p\fP option is
|
||||||
\fI\%\-\-extpri\fP option sets priority of N\-th URI in the command
|
less than the number of URI, the last \fI\%\-p\fP option value is
|
||||||
line. If the number of this option is less than the
|
repeated. If there is no \fI\%\-p\fP option, default weight, 16,
|
||||||
number of URI, the last option value is repeated. If
|
is assumed. The valid value range is
|
||||||
there is no \fI\%\-\-extpri\fP option, urgency is 3, and
|
[1, 256], inclusive.
|
||||||
incremental is false.
|
|
||||||
.UNINDENT
|
.UNINDENT
|
||||||
.INDENT 0.0
|
.INDENT 0.0
|
||||||
.TP
|
.TP
|
||||||
@@ -206,6 +205,11 @@ Don\(aqt send content\-length header field.
|
|||||||
.UNINDENT
|
.UNINDENT
|
||||||
.INDENT 0.0
|
.INDENT 0.0
|
||||||
.TP
|
.TP
|
||||||
|
.B \-\-no\-dep
|
||||||
|
Don\(aqt send dependency based priority hint to server.
|
||||||
|
.UNINDENT
|
||||||
|
.INDENT 0.0
|
||||||
|
.TP
|
||||||
.B \-\-hexdump
|
.B \-\-hexdump
|
||||||
Display the incoming traffic in hexadecimal (Canonical
|
Display the incoming traffic in hexadecimal (Canonical
|
||||||
hex+ASCII display). If SSL/TLS is used, decrypted data
|
hex+ASCII display). If SSL/TLS is used, decrypted data
|
||||||
@@ -243,6 +247,11 @@ Enable ktls.
|
|||||||
.UNINDENT
|
.UNINDENT
|
||||||
.INDENT 0.0
|
.INDENT 0.0
|
||||||
.TP
|
.TP
|
||||||
|
.B \-\-no\-rfc7540\-pri
|
||||||
|
Disable RFC7540 priorities.
|
||||||
|
.UNINDENT
|
||||||
|
.INDENT 0.0
|
||||||
|
.TP
|
||||||
.B \-\-version
|
.B \-\-version
|
||||||
Display version information and exit.
|
Display version information and exit.
|
||||||
.UNINDENT
|
.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
|
is 1 second and 500ms is 500 milliseconds). Units are h, m, s or ms
|
||||||
(hours, minutes, seconds and milliseconds, respectively). If a unit
|
(hours, minutes, seconds and milliseconds, respectively). If a unit
|
||||||
is omitted, a second is used as unit.
|
is omitted, a second is used as unit.
|
||||||
|
.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
|
.SH SEE ALSO
|
||||||
.sp
|
.sp
|
||||||
\fBnghttpd(1)\fP, \fBnghttpx(1)\fP, \fBh2load(1)\fP
|
\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
|
if the request URI has https scheme. If :option:`-d` is used, the
|
||||||
HTTP upgrade request is performed with OPTIONS method.
|
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
|
Sets weight of given URI. This option can be used
|
||||||
wire format of priority header field (e.g., "u=3,i").
|
multiple times, and N-th :option:`-p` option sets weight of N-th
|
||||||
This option can be used multiple times, and N-th
|
URI in the command line. If the number of :option:`-p` option is
|
||||||
:option:`--extpri` option sets priority of N-th URI in the command
|
less than the number of URI, the last :option:`-p` option value is
|
||||||
line. If the number of this option is less than the
|
repeated. If there is no :option:`-p` option, default weight, 16,
|
||||||
number of URI, the last option value is repeated. If
|
is assumed. The valid value range is
|
||||||
there is no :option:`--extpri` option, urgency is 3, and
|
[1, 256], inclusive.
|
||||||
incremental is false.
|
|
||||||
|
|
||||||
.. option:: -M, --peer-max-concurrent-streams=<N>
|
.. option:: -M, --peer-max-concurrent-streams=<N>
|
||||||
|
|
||||||
@@ -161,6 +160,10 @@ OPTIONS
|
|||||||
|
|
||||||
Don't send content-length header field.
|
Don't send content-length header field.
|
||||||
|
|
||||||
|
.. option:: --no-dep
|
||||||
|
|
||||||
|
Don't send dependency based priority hint to server.
|
||||||
|
|
||||||
.. option:: --hexdump
|
.. option:: --hexdump
|
||||||
|
|
||||||
Display the incoming traffic in hexadecimal (Canonical
|
Display the incoming traffic in hexadecimal (Canonical
|
||||||
@@ -192,6 +195,10 @@ OPTIONS
|
|||||||
|
|
||||||
Enable ktls.
|
Enable ktls.
|
||||||
|
|
||||||
|
.. option:: --no-rfc7540-pri
|
||||||
|
|
||||||
|
Disable RFC7540 priorities.
|
||||||
|
|
||||||
.. option:: --version
|
.. option:: --version
|
||||||
|
|
||||||
Display version information and exit.
|
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
|
(hours, minutes, seconds and milliseconds, respectively). If a unit
|
||||||
is omitted, a second is used as unit.
|
is omitted, a second is used as unit.
|
||||||
|
|
||||||
|
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
|
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
|
SEE ALSO
|
||||||
--------
|
--------
|
||||||
|
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
|||||||
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
||||||
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
|
.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
|
.SH NAME
|
||||||
nghttpd \- HTTP/2 server
|
nghttpd \- HTTP/2 server
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
@@ -209,6 +209,11 @@ Enable ktls.
|
|||||||
.UNINDENT
|
.UNINDENT
|
||||||
.INDENT 0.0
|
.INDENT 0.0
|
||||||
.TP
|
.TP
|
||||||
|
.B \-\-no\-rfc7540\-pri
|
||||||
|
Disable RFC7540 priorities.
|
||||||
|
.UNINDENT
|
||||||
|
.INDENT 0.0
|
||||||
|
.TP
|
||||||
.B \-\-version
|
.B \-\-version
|
||||||
Display version information and exit.
|
Display version information and exit.
|
||||||
.UNINDENT
|
.UNINDENT
|
||||||
|
|||||||
@@ -163,6 +163,10 @@ OPTIONS
|
|||||||
|
|
||||||
Enable ktls.
|
Enable ktls.
|
||||||
|
|
||||||
|
.. option:: --no-rfc7540-pri
|
||||||
|
|
||||||
|
Disable RFC7540 priorities.
|
||||||
|
|
||||||
.. option:: --version
|
.. option:: --version
|
||||||
|
|
||||||
Display version information and exit.
|
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]]
|
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
||||||
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
|
.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
|
.SH NAME
|
||||||
nghttpx \- HTTP/2 proxy
|
nghttpx \- HTTP/2 proxy
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
@@ -46,7 +46,8 @@ Set path to server\(aqs private key. Required unless
|
|||||||
.TP
|
.TP
|
||||||
.B <CERT>
|
.B <CERT>
|
||||||
Set path to server\(aqs certificate. Required unless
|
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
|
.UNINDENT
|
||||||
.SH OPTIONS
|
.SH OPTIONS
|
||||||
.sp
|
.sp
|
||||||
@@ -744,10 +745,12 @@ enabled for backend connections.
|
|||||||
.B \-\-cacert=<PATH>
|
.B \-\-cacert=<PATH>
|
||||||
Set path to trusted CA certificate file. It is used in
|
Set path to trusted CA certificate file. It is used in
|
||||||
backend TLS connections to verify peer\(aqs certificate.
|
backend TLS connections to verify peer\(aqs certificate.
|
||||||
The file must be in PEM format. It can contain multiple
|
It is also used to verify OCSP response from the script
|
||||||
certificates. If the linked OpenSSL is configured to
|
set by \fI\%\-\-fetch\-ocsp\-response\-file\fP\&. The file must be in
|
||||||
load system wide certificates, they are loaded at
|
PEM format. It can contain multiple certificates. If
|
||||||
startup regardless of this option.
|
the linked OpenSSL is configured to load system wide
|
||||||
|
certificates, they are loaded at startup regardless of
|
||||||
|
this option.
|
||||||
.UNINDENT
|
.UNINDENT
|
||||||
.INDENT 0.0
|
.INDENT 0.0
|
||||||
.TP
|
.TP
|
||||||
@@ -767,7 +770,8 @@ curves (e.g., P\-256) between client and server are also
|
|||||||
taken into consideration. This allows nghttpx to send
|
taken into consideration. This allows nghttpx to send
|
||||||
ECDSA certificate to modern clients, while sending RSA
|
ECDSA certificate to modern clients, while sending RSA
|
||||||
based certificate to older clients. This option can be
|
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
|
.sp
|
||||||
Additional parameter can be specified in <PARAM>. The
|
Additional parameter can be specified in <PARAM>. The
|
||||||
available <PARAM> is \(dqsct\-dir=<DIR>\(dq.
|
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
|
by a single comma only and any white spaces are treated
|
||||||
as a part of protocol string.
|
as a part of protocol string.
|
||||||
.sp
|
.sp
|
||||||
Default: \fBh2,http/1.1\fP
|
Default: \fBh2,h2\-16,h2\-14,http/1.1\fP
|
||||||
.UNINDENT
|
.UNINDENT
|
||||||
.INDENT 0.0
|
.INDENT 0.0
|
||||||
.TP
|
.TP
|
||||||
@@ -958,6 +962,72 @@ get TLS ticket keys.
|
|||||||
.UNINDENT
|
.UNINDENT
|
||||||
.INDENT 0.0
|
.INDENT 0.0
|
||||||
.TP
|
.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>
|
.B \-\-tls\-dyn\-rec\-warmup\-threshold=<SIZE>
|
||||||
Specify the threshold size for TLS dynamic record size
|
Specify the threshold size for TLS dynamic record size
|
||||||
behaviour. During a TLS session, after the threshold
|
behaviour. During a TLS session, after the threshold
|
||||||
@@ -1065,7 +1135,8 @@ Default: \fB16K\fP
|
|||||||
.INDENT 0.0
|
.INDENT 0.0
|
||||||
.TP
|
.TP
|
||||||
.B \-\-tls\-ktls
|
.B \-\-tls\-ktls
|
||||||
Enable ktls.
|
Enable ktls. For server, ktls is enable if
|
||||||
|
\fI\%\-\-tls\-session\-cache\-memcached\fP is not configured.
|
||||||
.UNINDENT
|
.UNINDENT
|
||||||
.SS HTTP/2
|
.SS HTTP/2
|
||||||
.INDENT 0.0
|
.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
|
server is given time based on this timeout, and it is
|
||||||
scaled linearly.
|
scaled linearly.
|
||||||
.sp
|
.sp
|
||||||
Default: \fB250ms\fP
|
Default: \fB5s\fP
|
||||||
.UNINDENT
|
.UNINDENT
|
||||||
.INDENT 0.0
|
.INDENT 0.0
|
||||||
.TP
|
.TP
|
||||||
@@ -1612,7 +1683,7 @@ Default: \fB250ms\fP
|
|||||||
Set the number of DNS query before nghttpx gives up name
|
Set the number of DNS query before nghttpx gives up name
|
||||||
lookup.
|
lookup.
|
||||||
.sp
|
.sp
|
||||||
Default: \fB3\fP
|
Default: \fB2\fP
|
||||||
.UNINDENT
|
.UNINDENT
|
||||||
.INDENT 0.0
|
.INDENT 0.0
|
||||||
.TP
|
.TP
|
||||||
@@ -1932,9 +2003,11 @@ request header field, do this:
|
|||||||
.INDENT 7.0
|
.INDENT 7.0
|
||||||
.INDENT 3.5
|
.INDENT 3.5
|
||||||
.sp
|
.sp
|
||||||
.EX
|
.nf
|
||||||
|
.ft C
|
||||||
add\-request\-header=foo: bar
|
add\-request\-header=foo: bar
|
||||||
.EE
|
.ft P
|
||||||
|
.fi
|
||||||
.UNINDENT
|
.UNINDENT
|
||||||
.UNINDENT
|
.UNINDENT
|
||||||
.sp
|
.sp
|
||||||
@@ -1942,9 +2015,11 @@ instead of:
|
|||||||
.INDENT 7.0
|
.INDENT 7.0
|
||||||
.INDENT 3.5
|
.INDENT 3.5
|
||||||
.sp
|
.sp
|
||||||
.EX
|
.nf
|
||||||
|
.ft C
|
||||||
add\-request\-header=\(dqfoo: bar\(dq
|
add\-request\-header=\(dqfoo: bar\(dq
|
||||||
.EE
|
.ft P
|
||||||
|
.fi
|
||||||
.UNINDENT
|
.UNINDENT
|
||||||
.UNINDENT
|
.UNINDENT
|
||||||
.sp
|
.sp
|
||||||
@@ -2049,10 +2124,12 @@ header field to initiate server push:
|
|||||||
.INDENT 0.0
|
.INDENT 0.0
|
||||||
.INDENT 3.5
|
.INDENT 3.5
|
||||||
.sp
|
.sp
|
||||||
.EX
|
.nf
|
||||||
|
.ft C
|
||||||
Link: </fonts/font.woff>; rel=preload
|
Link: </fonts/font.woff>; rel=preload
|
||||||
Link: </css/theme.css>; rel=preload
|
Link: </css/theme.css>; rel=preload
|
||||||
.EE
|
.ft P
|
||||||
|
.fi
|
||||||
.UNINDENT
|
.UNINDENT
|
||||||
.UNINDENT
|
.UNINDENT
|
||||||
.sp
|
.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
|
deletes it. However, if SIGUSR2 is used to execute new binary and
|
||||||
both old and new configurations use same filename, new binary does not
|
both old and new configurations use same filename, new binary does not
|
||||||
delete the socket and continues to use it.
|
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
|
.SH TLS SESSION RESUMPTION
|
||||||
.sp
|
.sp
|
||||||
nghttpx supports TLS session resumption through both session ID and
|
nghttpx supports TLS session resumption through both session ID and
|
||||||
@@ -2090,6 +2196,16 @@ session ticket.
|
|||||||
.SS SESSION ID RESUMPTION
|
.SS SESSION ID RESUMPTION
|
||||||
.sp
|
.sp
|
||||||
By default, session ID is shared by all worker threads.
|
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
|
.SS TLS SESSION TICKET RESUMPTION
|
||||||
.sp
|
.sp
|
||||||
By default, session ticket is shared by all worker threads. The
|
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 0.0
|
||||||
.INDENT 3.5
|
.INDENT 3.5
|
||||||
.sp
|
.sp
|
||||||
.EX
|
.nf
|
||||||
|
.ft C
|
||||||
+\-\-\-\-\-\-\-\-\-\-\-\-\-\-+\-\-\-\-\-\-\-+\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-+
|
+\-\-\-\-\-\-\-\-\-\-\-\-\-\-+\-\-\-\-\-\-\-+\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-+
|
||||||
| VERSION (4) |LEN (2)|KEY(48 or 80) ...
|
| 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
|
(LEN, KEY) pair can be repeated
|
||||||
.EE
|
.ft P
|
||||||
|
.fi
|
||||||
.UNINDENT
|
.UNINDENT
|
||||||
.UNINDENT
|
.UNINDENT
|
||||||
.sp
|
.sp
|
||||||
@@ -2533,7 +2651,8 @@ Modify request path:
|
|||||||
.INDENT 0.0
|
.INDENT 0.0
|
||||||
.INDENT 3.5
|
.INDENT 3.5
|
||||||
.sp
|
.sp
|
||||||
.EX
|
.nf
|
||||||
|
.ft C
|
||||||
class App
|
class App
|
||||||
def on_req(env)
|
def on_req(env)
|
||||||
env.req.path = \(dq/apps#{env.req.path}\(dq
|
env.req.path = \(dq/apps#{env.req.path}\(dq
|
||||||
@@ -2541,7 +2660,8 @@ class App
|
|||||||
end
|
end
|
||||||
|
|
||||||
App.new
|
App.new
|
||||||
.EE
|
.ft P
|
||||||
|
.fi
|
||||||
.UNINDENT
|
.UNINDENT
|
||||||
.UNINDENT
|
.UNINDENT
|
||||||
.sp
|
.sp
|
||||||
@@ -2552,7 +2672,8 @@ addresses:
|
|||||||
.INDENT 0.0
|
.INDENT 0.0
|
||||||
.INDENT 3.5
|
.INDENT 3.5
|
||||||
.sp
|
.sp
|
||||||
.EX
|
.nf
|
||||||
|
.ft C
|
||||||
class App
|
class App
|
||||||
def on_req(env)
|
def on_req(env)
|
||||||
allowed_clients = [\(dq127.0.0.1\(dq, \(dq::1\(dq]
|
allowed_clients = [\(dq127.0.0.1\(dq, \(dq::1\(dq]
|
||||||
@@ -2566,7 +2687,8 @@ class App
|
|||||||
end
|
end
|
||||||
|
|
||||||
App.new
|
App.new
|
||||||
.EE
|
.ft P
|
||||||
|
.fi
|
||||||
.UNINDENT
|
.UNINDENT
|
||||||
.UNINDENT
|
.UNINDENT
|
||||||
.SH API ENDPOINTS
|
.SH API ENDPOINTS
|
||||||
|
|||||||
@@ -25,7 +25,8 @@ A reverse proxy for HTTP/3, HTTP/2, and HTTP/1.
|
|||||||
.. describe:: <CERT>
|
.. describe:: <CERT>
|
||||||
|
|
||||||
Set path to server's certificate. Required unless
|
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
|
OPTIONS
|
||||||
@@ -694,10 +695,12 @@ SSL/TLS
|
|||||||
|
|
||||||
Set path to trusted CA certificate file. It is used in
|
Set path to trusted CA certificate file. It is used in
|
||||||
backend TLS connections to verify peer's certificate.
|
backend TLS connections to verify peer's certificate.
|
||||||
The file must be in PEM format. It can contain multiple
|
It is also used to verify OCSP response from the script
|
||||||
certificates. If the linked OpenSSL is configured to
|
set by :option:`--fetch-ocsp-response-file`\. The file must be in
|
||||||
load system wide certificates, they are loaded at
|
PEM format. It can contain multiple certificates. If
|
||||||
startup regardless of this option.
|
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>
|
.. option:: --private-key-passwd-file=<PATH>
|
||||||
|
|
||||||
@@ -715,7 +718,8 @@ SSL/TLS
|
|||||||
taken into consideration. This allows nghttpx to send
|
taken into consideration. This allows nghttpx to send
|
||||||
ECDSA certificate to modern clients, while sending RSA
|
ECDSA certificate to modern clients, while sending RSA
|
||||||
based certificate to older clients. This option can be
|
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
|
Additional parameter can be specified in <PARAM>. The
|
||||||
available <PARAM> is "sct-dir=<DIR>".
|
available <PARAM> is "sct-dir=<DIR>".
|
||||||
@@ -740,7 +744,7 @@ SSL/TLS
|
|||||||
by a single comma only and any white spaces are treated
|
by a single comma only and any white spaces are treated
|
||||||
as a part of protocol string.
|
as a part of protocol string.
|
||||||
|
|
||||||
Default: ``h2,http/1.1``
|
Default: ``h2,h2-16,h2-14,http/1.1``
|
||||||
|
|
||||||
.. option:: --verify-client
|
.. option:: --verify-client
|
||||||
|
|
||||||
@@ -886,6 +890,63 @@ SSL/TLS
|
|||||||
Path to client private key for memcached connections to
|
Path to client private key for memcached connections to
|
||||||
get TLS ticket keys.
|
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>
|
.. option:: --tls-dyn-rec-warmup-threshold=<SIZE>
|
||||||
|
|
||||||
Specify the threshold size for TLS dynamic record size
|
Specify the threshold size for TLS dynamic record size
|
||||||
@@ -985,7 +1046,8 @@ SSL/TLS
|
|||||||
|
|
||||||
.. option:: --tls-ktls
|
.. option:: --tls-ktls
|
||||||
|
|
||||||
Enable ktls.
|
Enable ktls. For server, ktls is enable if
|
||||||
|
:option:`--tls-session-cache-memcached` is not configured.
|
||||||
|
|
||||||
|
|
||||||
HTTP/2
|
HTTP/2
|
||||||
@@ -1462,14 +1524,14 @@ DNS
|
|||||||
server is given time based on this timeout, and it is
|
server is given time based on this timeout, and it is
|
||||||
scaled linearly.
|
scaled linearly.
|
||||||
|
|
||||||
Default: ``250ms``
|
Default: ``5s``
|
||||||
|
|
||||||
.. option:: --dns-max-try=<N>
|
.. option:: --dns-max-try=<N>
|
||||||
|
|
||||||
Set the number of DNS query before nghttpx gives up name
|
Set the number of DNS query before nghttpx gives up name
|
||||||
lookup.
|
lookup.
|
||||||
|
|
||||||
Default: ``3``
|
Default: ``2``
|
||||||
|
|
||||||
.. option:: --frontend-max-requests=<N>
|
.. 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
|
both old and new configurations use same filename, new binary does not
|
||||||
delete the socket and continues to use it.
|
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
|
TLS SESSION RESUMPTION
|
||||||
----------------------
|
----------------------
|
||||||
|
|
||||||
@@ -1920,6 +2013,16 @@ SESSION ID RESUMPTION
|
|||||||
|
|
||||||
By default, session ID is shared by all worker threads.
|
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
|
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
|
both old and new configurations use same filename, new binary does not
|
||||||
delete the socket and continues to use it.
|
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
|
TLS SESSION RESUMPTION
|
||||||
----------------------
|
----------------------
|
||||||
|
|
||||||
@@ -167,6 +198,16 @@ SESSION ID RESUMPTION
|
|||||||
|
|
||||||
By default, session ID is shared by all worker threads.
|
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
|
TLS SESSION TICKET RESUMPTION
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
|||||||
@@ -482,22 +482,20 @@ be called as usual.
|
|||||||
Stream priorities
|
Stream priorities
|
||||||
-----------------
|
-----------------
|
||||||
|
|
||||||
The stream prioritization scheme described in :rfc:`7540`, which has
|
By default, the stream prioritization scheme described in :rfc:`7540`
|
||||||
been formally deprecated by :rfc:`9113`, has been removed. An
|
is used. This scheme has been formally deprecated by :rfc:`9113`. In
|
||||||
application is advised to send
|
order to disable it, send
|
||||||
:enum:`nghttp2_settings_id.NGHTTP2_SETTINGS_NO_RFC7540_PRIORITIES` of
|
:enum:`nghttp2_settings_id.NGHTTP2_SETTINGS_NO_RFC7540_PRIORITIES` of
|
||||||
value of 1 via `nghttp2_submit_settings()`, and migrate to
|
value of 1 via `nghttp2_submit_settings()`. This settings ID is
|
||||||
:rfc:`9218`.
|
defined by :rfc:`9218`. The sender of this settings value disables
|
||||||
|
RFC 7540 priorities, and instead it enables RFC 9218 Extensible
|
||||||
The sender of this settings value disables :rfc:`7540` priorities, and
|
Prioritization Scheme. This new prioritization scheme has 2 methods
|
||||||
instead it enables :rfc:`9218` Extensible Prioritization Scheme. This
|
to convey the stream priorities to a remote endpoint: Priority header
|
||||||
new prioritization scheme has 2 methods to convey the stream
|
field and PRIORITY_UPDATE frame. nghttp2 supports both methods. In
|
||||||
priorities to a remote endpoint: Priority header field and
|
order to receive and process PRIORITY_UPDATE frame, server has to call
|
||||||
PRIORITY_UPDATE frame. nghttp2 supports both methods. In order to
|
``nghttp2_option_set_builtin_recv_extension_type(option,
|
||||||
receive and process PRIORITY_UPDATE frame, server has to call
|
NGHTTP2_PRIORITY_UPDATE)`` (see the above section), and pass the
|
||||||
`nghttp2_option_set_builtin_recv_extension_type()` with
|
option to `nghttp2_session_server_new2()` or
|
||||||
NGHTTP2_PRIORITY_UPDATE as type argument (see the above section), and
|
|
||||||
pass the option to `nghttp2_session_server_new2()` or
|
|
||||||
`nghttp2_session_server_new3()` to create a server session. Client
|
`nghttp2_session_server_new3()` to create a server session. Client
|
||||||
can send Priority header field via `nghttp2_submit_request2()`. It
|
can send Priority header field via `nghttp2_submit_request2()`. It
|
||||||
can also send PRIORITY_UPDATE frame via
|
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
|
field in a request header field and updates the stream priority unless
|
||||||
HTTP messaging rule enforcement is disabled (see
|
HTTP messaging rule enforcement is disabled (see
|
||||||
`nghttp2_option_set_no_http_messaging()`).
|
`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
|
We use clang-format to format source code consistently. The
|
||||||
clang-format configuration file .clang-format is located at the root
|
clang-format configuration file .clang-format is located at the root
|
||||||
directory. Since clang-format produces slightly different results
|
directory. Since clang-format produces slightly different results
|
||||||
between versions, we currently use clang-format-19.
|
between versions, we currently use clang-format-15.
|
||||||
|
|
||||||
To detect any violation to the coding style, we recommend to setup git
|
To detect any violation to the coding style, we recommend to setup git
|
||||||
pre-commit hook to check coding style of the changes you introduced.
|
pre-commit hook to check coding style of the changes you introduced.
|
||||||
@@ -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
|
.git/hooks and make sure that it is executable. The pre-commit script
|
||||||
uses clang-format-diff.py to detect any style errors. If it is not in
|
uses clang-format-diff.py to detect any style errors. If it is not in
|
||||||
your PATH or it exists under different name (e.g.,
|
your PATH or it exists under different name (e.g.,
|
||||||
clang-format-diff-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.
|
git option ``clangformatdiff.binary`` to point to the script.
|
||||||
|
|
||||||
For emacs users, integrating clang-format to emacs is very easy.
|
For emacs users, integrating clang-format to emacs is very easy.
|
||||||
|
|||||||
@@ -167,7 +167,8 @@ Enable SSL/TLS on memcached connection
|
|||||||
|
|
||||||
By default, memcached connection is not encrypted. To enable
|
By default, memcached connection is not encrypted. To enable
|
||||||
encryption, use ``tls`` keyword in
|
encryption, use ``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
|
Specifying additional server certificates
|
||||||
-----------------------------------------
|
-----------------------------------------
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ structure is defined as follows::
|
|||||||
/* The NULL-terminated URI string to retrieve. */
|
/* The NULL-terminated URI string to retrieve. */
|
||||||
const char *uri;
|
const char *uri;
|
||||||
/* Parsed result of the |uri| */
|
/* Parsed result of the |uri| */
|
||||||
urlparse_url *u;
|
struct http_parser_url *u;
|
||||||
/* The authority portion of the |uri|, not NULL-terminated */
|
/* The authority portion of the |uri|, not NULL-terminated */
|
||||||
char *authority;
|
char *authority;
|
||||||
/* The path portion of the |uri|, including query, not
|
/* The path portion of the |uri|, including query, not
|
||||||
@@ -237,11 +237,11 @@ HTTP request in the ``submit_request()`` function::
|
|||||||
int32_t stream_id;
|
int32_t stream_id;
|
||||||
http2_stream_data *stream_data = session_data->stream_data;
|
http2_stream_data *stream_data = session_data->stream_data;
|
||||||
const char *uri = stream_data->uri;
|
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[] = {
|
nghttp2_nv hdrs[] = {
|
||||||
MAKE_NV2(":method", "GET"),
|
MAKE_NV2(":method", "GET"),
|
||||||
MAKE_NV(":scheme", &uri[u->field_data[URLPARSE_SCHEMA].off],
|
MAKE_NV(":scheme", &uri[u->field_data[UF_SCHEMA].off],
|
||||||
u->field_data[URLPARSE_SCHEMA].len),
|
u->field_data[UF_SCHEMA].len),
|
||||||
MAKE_NV(":authority", stream_data->authority, stream_data->authoritylen),
|
MAKE_NV(":authority", stream_data->authority, stream_data->authoritylen),
|
||||||
MAKE_NV(":path", stream_data->path, stream_data->pathlen)};
|
MAKE_NV(":path", stream_data->path, stream_data->pathlen)};
|
||||||
fprintf(stderr, "Request headers:\n");
|
fprintf(stderr, "Request headers:\n");
|
||||||
|
|||||||
@@ -4,36 +4,32 @@ ARG NGHTTP2_BRANCH=master
|
|||||||
|
|
||||||
RUN apt-get update && \
|
RUN apt-get update && \
|
||||||
DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
|
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 \
|
pkg-config cmake cmake-data \
|
||||||
zlib1g-dev libev-dev libjemalloc-dev ruby-dev libc-ares-dev bison \
|
zlib1g-dev libev-dev libjemalloc-dev ruby-dev libc-ares-dev bison \
|
||||||
libelf-dev libbrotli-dev
|
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 && \
|
cd aws-lc && \
|
||||||
export CC=clang-19 CXX=clang++-19 && \
|
|
||||||
cmake -B build -DDISABLE_GO=ON && \
|
cmake -B build -DDISABLE_GO=ON && \
|
||||||
make -j$(nproc) -C build && \
|
make -j$(nproc) -C build && \
|
||||||
cmake --install build && \
|
cmake --install build && \
|
||||||
cd .. && \
|
cd .. && \
|
||||||
rm -rf aws-lc
|
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 && \
|
cd nghttp3 && \
|
||||||
autoreconf -i && \
|
autoreconf -i && \
|
||||||
./configure --disable-dependency-tracking --enable-lib-only \
|
./configure --enable-lib-only && \
|
||||||
CC=clang-19 CXX=clang++-19 && \
|
|
||||||
make -j$(nproc) && \
|
make -j$(nproc) && \
|
||||||
make install-strip && \
|
make install-strip && \
|
||||||
cd .. && \
|
cd .. && \
|
||||||
rm -rf nghttp3
|
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 && \
|
cd ngtcp2 && \
|
||||||
autoreconf -i && \
|
autoreconf -i && \
|
||||||
./configure --disable-dependency-tracking --enable-lib-only \
|
./configure --enable-lib-only --with-boringssl \
|
||||||
--with-boringssl \
|
|
||||||
CC=clang-19 CXX=clang++-19 \
|
|
||||||
LIBTOOL_LDFLAGS="-static-libtool-libs" \
|
LIBTOOL_LDFLAGS="-static-libtool-libs" \
|
||||||
BORINGSSL_LIBS="-l:libssl.a -l:libcrypto.a" \
|
BORINGSSL_LIBS="-l:libssl.a -l:libcrypto.a" \
|
||||||
PKG_CONFIG_PATH="/usr/local/lib64/pkgconfig" && \
|
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 .. && \
|
cd .. && \
|
||||||
rm -rf ngtcp2
|
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 && \
|
cd libbpf && \
|
||||||
CC=clang-19 PREFIX=/usr/local make -C src install && \
|
PREFIX=/usr/local make -C src install && \
|
||||||
cd .. && \
|
cd .. && \
|
||||||
rm -rf libbpf
|
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 && \
|
cd nghttp2 && \
|
||||||
autoreconf -i && \
|
autoreconf -i && \
|
||||||
./configure --disable-dependency-tracking --disable-examples \
|
./configure --disable-examples --disable-hpack-tools \
|
||||||
--disable-hpack-tools \
|
|
||||||
--with-mruby \
|
--with-mruby \
|
||||||
--enable-http3 --with-libbpf \
|
--enable-http3 --with-libbpf \
|
||||||
--with-libbrotlienc --with-libbrotlidec \
|
--with-libbrotlienc --with-libbrotlidec \
|
||||||
CC=clang-19 CXX=clang++-19 \
|
CC=clang CXX=clang++ \
|
||||||
LIBTOOL_LDFLAGS="-static-libtool-libs" \
|
LIBTOOL_LDFLAGS="-static-libtool-libs" \
|
||||||
OPENSSL_LIBS="-l:libssl.a -l:libcrypto.a" \
|
OPENSSL_LIBS="-l:libssl.a -l:libcrypto.a" \
|
||||||
LIBEV_LIBS="-l:libev.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
|
FROM gcr.io/distroless/base-nossl-debian12
|
||||||
|
|
||||||
|
COPY --from=build --link \
|
||||||
|
/usr/local/share/nghttp2/ \
|
||||||
|
/usr/local/share/nghttp2/
|
||||||
COPY --from=build --link \
|
COPY --from=build --link \
|
||||||
/usr/local/bin/h2load \
|
/usr/local/bin/h2load \
|
||||||
/usr/local/bin/nghttpx \
|
/usr/local/bin/nghttpx \
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ if(ENABLE_EXAMPLES)
|
|||||||
|
|
||||||
include_directories(
|
include_directories(
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}
|
${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"
|
"${CMAKE_CURRENT_SOURCE_DIR}/../third-party/llhttp/include"
|
||||||
|
|
||||||
${LIBEVENT_INCLUDE_DIRS}
|
${LIBEVENT_INCLUDE_DIRS}
|
||||||
@@ -23,15 +23,15 @@ if(ENABLE_EXAMPLES)
|
|||||||
)
|
)
|
||||||
|
|
||||||
add_executable(client client.c $<TARGET_OBJECTS:llhttp>
|
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>
|
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>
|
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>
|
add_executable(deflate deflate.c $<TARGET_OBJECTS:llhttp>
|
||||||
$<TARGET_OBJECTS:urlparse>
|
$<TARGET_OBJECTS:url-parser>
|
||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|||||||
@@ -30,13 +30,13 @@ AM_CXXFLAGS = $(WARNCXXFLAGS) $(CXX1XCXXFLAGS)
|
|||||||
AM_CPPFLAGS = \
|
AM_CPPFLAGS = \
|
||||||
-I$(top_srcdir)/lib/includes \
|
-I$(top_srcdir)/lib/includes \
|
||||||
-I$(top_builddir)/lib/includes \
|
-I$(top_builddir)/lib/includes \
|
||||||
-I$(top_srcdir)/third-party/urlparse \
|
-I$(top_srcdir)/third-party \
|
||||||
@LIBEVENT_OPENSSL_CFLAGS@ \
|
@LIBEVENT_OPENSSL_CFLAGS@ \
|
||||||
@OPENSSL_CFLAGS@ \
|
@OPENSSL_CFLAGS@ \
|
||||||
@DEFS@
|
@DEFS@
|
||||||
AM_LDFLAGS = @LIBTOOL_LDFLAGS@
|
AM_LDFLAGS = @LIBTOOL_LDFLAGS@
|
||||||
LDADD = $(top_builddir)/lib/libnghttp2.la \
|
LDADD = $(top_builddir)/lib/libnghttp2.la \
|
||||||
$(top_builddir)/third-party/liburlparse.la \
|
$(top_builddir)/third-party/liburl-parser.la \
|
||||||
@LIBEVENT_OPENSSL_LIBS@ \
|
@LIBEVENT_OPENSSL_LIBS@ \
|
||||||
@OPENSSL_LIBS@ \
|
@OPENSSL_LIBS@ \
|
||||||
@APPLDFLAGS@
|
@APPLDFLAGS@
|
||||||
|
|||||||
@@ -67,14 +67,14 @@ enum { IO_NONE, WANT_READ, WANT_WRITE };
|
|||||||
|
|
||||||
#define MAKE_NV(NAME, VALUE) \
|
#define MAKE_NV(NAME, VALUE) \
|
||||||
{ \
|
{ \
|
||||||
(uint8_t *)NAME, (uint8_t *)VALUE, sizeof(NAME) - 1, \
|
(uint8_t *)NAME, (uint8_t *)VALUE, sizeof(NAME) - 1, sizeof(VALUE) - 1, \
|
||||||
sizeof(VALUE) - 1, NGHTTP2_NV_FLAG_NONE, \
|
NGHTTP2_NV_FLAG_NONE \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define MAKE_NV_CS(NAME, VALUE) \
|
#define MAKE_NV_CS(NAME, VALUE) \
|
||||||
{ \
|
{ \
|
||||||
(uint8_t *)NAME, (uint8_t *)VALUE, sizeof(NAME) - 1, \
|
(uint8_t *)NAME, (uint8_t *)VALUE, sizeof(NAME) - 1, strlen(VALUE), \
|
||||||
strlen(VALUE), NGHTTP2_NV_FLAG_NONE, \
|
NGHTTP2_NV_FLAG_NONE \
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Connection {
|
struct Connection {
|
||||||
@@ -176,7 +176,7 @@ static nghttp2_ssize send_callback(nghttp2_session *session,
|
|||||||
int err = SSL_get_error(connection->ssl, rv);
|
int err = SSL_get_error(connection->ssl, rv);
|
||||||
if (err == SSL_ERROR_WANT_WRITE || err == SSL_ERROR_WANT_READ) {
|
if (err == SSL_ERROR_WANT_WRITE || err == SSL_ERROR_WANT_READ) {
|
||||||
connection->want_io =
|
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;
|
rv = NGHTTP2_ERR_WOULDBLOCK;
|
||||||
} else {
|
} else {
|
||||||
rv = NGHTTP2_ERR_CALLBACK_FAILURE;
|
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);
|
int err = SSL_get_error(connection->ssl, rv);
|
||||||
if (err == SSL_ERROR_WANT_WRITE || err == SSL_ERROR_WANT_READ) {
|
if (err == SSL_ERROR_WANT_WRITE || err == SSL_ERROR_WANT_READ) {
|
||||||
connection->want_io =
|
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;
|
rv = NGHTTP2_ERR_WOULDBLOCK;
|
||||||
} else {
|
} else {
|
||||||
rv = NGHTTP2_ERR_CALLBACK_FAILURE;
|
rv = NGHTTP2_ERR_CALLBACK_FAILURE;
|
||||||
@@ -342,10 +342,10 @@ static void setup_nghttp2_callbacks(nghttp2_session_callbacks *callbacks) {
|
|||||||
on_frame_recv_callback);
|
on_frame_recv_callback);
|
||||||
|
|
||||||
nghttp2_session_callbacks_set_on_stream_close_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(
|
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) \
|
#define MAKE_NV(K, V) \
|
||||||
{ \
|
{ \
|
||||||
(uint8_t *)K, (uint8_t *)V, sizeof(K) - 1, \
|
(uint8_t *)K, (uint8_t *)V, sizeof(K) - 1, sizeof(V) - 1, \
|
||||||
sizeof(V) - 1, NGHTTP2_NV_FLAG_NONE, \
|
NGHTTP2_NV_FLAG_NONE \
|
||||||
}
|
}
|
||||||
|
|
||||||
static void deflate(nghttp2_hd_deflater *deflater,
|
static void deflate(nghttp2_hd_deflater *deflater,
|
||||||
@@ -51,9 +51,9 @@ int main(void) {
|
|||||||
nghttp2_hd_inflater *inflater;
|
nghttp2_hd_inflater *inflater;
|
||||||
/* Define 1st header set. This is looks like a HTTP request. */
|
/* Define 1st header set. This is looks like a HTTP request. */
|
||||||
nghttp2_nv nva1[] = {
|
nghttp2_nv nva1[] = {
|
||||||
MAKE_NV(":scheme", "https"), MAKE_NV(":authority", "example.org"),
|
MAKE_NV(":scheme", "https"), MAKE_NV(":authority", "example.org"),
|
||||||
MAKE_NV(":path", "/"), MAKE_NV("user-agent", "libnghttp2"),
|
MAKE_NV(":path", "/"), MAKE_NV("user-agent", "libnghttp2"),
|
||||||
MAKE_NV("accept-encoding", "gzip, deflate")};
|
MAKE_NV("accept-encoding", "gzip, deflate")};
|
||||||
/* Define 2nd header set */
|
/* Define 2nd header set */
|
||||||
nghttp2_nv nva2[] = {MAKE_NV(":scheme", "https"),
|
nghttp2_nv nva2[] = {MAKE_NV(":scheme", "https"),
|
||||||
MAKE_NV(":authority", "example.org"),
|
MAKE_NV(":authority", "example.org"),
|
||||||
@@ -175,7 +175,7 @@ int inflate_header_block(nghttp2_hd_inflater *inflater, uint8_t *in,
|
|||||||
size_t proclen;
|
size_t proclen;
|
||||||
|
|
||||||
rv =
|
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) {
|
if (rv < 0) {
|
||||||
fprintf(stderr, "inflate failed with error code %td", rv);
|
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
|
#define NGHTTP2_NO_SSIZE_T
|
||||||
#include <nghttp2/nghttp2.h>
|
#include <nghttp2/nghttp2.h>
|
||||||
|
|
||||||
#include "urlparse.h"
|
#include "url-parser/url_parser.h"
|
||||||
|
|
||||||
#define ARRLEN(x) (sizeof(x) / sizeof(x[0]))
|
#define ARRLEN(x) (sizeof(x) / sizeof(x[0]))
|
||||||
|
|
||||||
@@ -74,7 +74,7 @@ typedef struct {
|
|||||||
/* The NULL-terminated URI string to retrieve. */
|
/* The NULL-terminated URI string to retrieve. */
|
||||||
const char *uri;
|
const char *uri;
|
||||||
/* Parsed result of the |uri| */
|
/* Parsed result of the |uri| */
|
||||||
urlparse_url *u;
|
struct http_parser_url *u;
|
||||||
/* The authority portion of the |uri|, not NULL-terminated */
|
/* The authority portion of the |uri|, not NULL-terminated */
|
||||||
char *authority;
|
char *authority;
|
||||||
/* The path portion of the |uri|, including query, not
|
/* The path portion of the |uri|, including query, not
|
||||||
@@ -96,7 +96,7 @@ typedef struct {
|
|||||||
} http2_session_data;
|
} http2_session_data;
|
||||||
|
|
||||||
static http2_stream_data *create_http2_stream_data(const char *uri,
|
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) */
|
/* MAX 5 digits (max 65535) + 1 ':' + 1 NULL (because of snprintf) */
|
||||||
size_t extra = 7;
|
size_t extra = 7;
|
||||||
http2_stream_data *stream_data = malloc(sizeof(http2_stream_data));
|
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->u = u;
|
||||||
stream_data->stream_id = -1;
|
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);
|
stream_data->authority = malloc(stream_data->authoritylen + extra);
|
||||||
memcpy(stream_data->authority, &uri[u->field_data[URLPARSE_HOST].off],
|
memcpy(stream_data->authority, &uri[u->field_data[UF_HOST].off],
|
||||||
u->field_data[URLPARSE_HOST].len);
|
u->field_data[UF_HOST].len);
|
||||||
if (u->field_set & (1 << URLPARSE_PORT)) {
|
if (u->field_set & (1 << UF_PORT)) {
|
||||||
stream_data->authoritylen += (size_t)snprintf(
|
stream_data->authoritylen +=
|
||||||
stream_data->authority + u->field_data[URLPARSE_HOST].len, extra, ":%u",
|
(size_t)snprintf(stream_data->authority + u->field_data[UF_HOST].len,
|
||||||
u->port);
|
extra, ":%u", u->port);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If we don't have path in URI, we use "/" as path. */
|
/* If we don't have path in URI, we use "/" as path. */
|
||||||
stream_data->pathlen = 1;
|
stream_data->pathlen = 1;
|
||||||
if (u->field_set & (1 << URLPARSE_PATH)) {
|
if (u->field_set & (1 << UF_PATH)) {
|
||||||
stream_data->pathlen = u->field_data[URLPARSE_PATH].len;
|
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 */
|
/* +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);
|
stream_data->path = malloc(stream_data->pathlen);
|
||||||
if (u->field_set & (1 << URLPARSE_PATH)) {
|
if (u->field_set & (1 << UF_PATH)) {
|
||||||
memcpy(stream_data->path, &uri[u->field_data[URLPARSE_PATH].off],
|
memcpy(stream_data->path, &uri[u->field_data[UF_PATH].off],
|
||||||
u->field_data[URLPARSE_PATH].len);
|
u->field_data[UF_PATH].len);
|
||||||
} else {
|
} else {
|
||||||
stream_data->path[0] = '/';
|
stream_data->path[0] = '/';
|
||||||
}
|
}
|
||||||
if (u->field_set & (1 << URLPARSE_QUERY)) {
|
if (u->field_set & (1 << UF_QUERY)) {
|
||||||
stream_data
|
stream_data->path[stream_data->pathlen - u->field_data[UF_QUERY].len - 1] =
|
||||||
->path[stream_data->pathlen - u->field_data[URLPARSE_QUERY].len - 1] =
|
'?';
|
||||||
'?';
|
|
||||||
memcpy(stream_data->path + stream_data->pathlen -
|
memcpy(stream_data->path + stream_data->pathlen -
|
||||||
u->field_data[URLPARSE_QUERY].len,
|
u->field_data[UF_QUERY].len,
|
||||||
&uri[u->field_data[URLPARSE_QUERY].off],
|
&uri[u->field_data[UF_QUERY].off], u->field_data[UF_QUERY].len);
|
||||||
u->field_data[URLPARSE_QUERY].len);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return stream_data;
|
return stream_data;
|
||||||
@@ -320,9 +318,10 @@ static SSL_CTX *create_ssl_ctx(void) {
|
|||||||
errx(1, "Could not create SSL/TLS context: %s",
|
errx(1, "Could not create SSL/TLS context: %s",
|
||||||
ERR_error_string(ERR_get_error(), NULL));
|
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_CTX_set_options(ssl_ctx,
|
||||||
SSL_OP_NO_COMPRESSION |
|
SSL_OP_ALL | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 |
|
||||||
SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION);
|
SSL_OP_NO_COMPRESSION |
|
||||||
|
SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION);
|
||||||
|
|
||||||
SSL_CTX_set_alpn_protos(ssl_ctx, (const unsigned char *)"\x02h2", 3);
|
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);
|
on_frame_recv_callback);
|
||||||
|
|
||||||
nghttp2_session_callbacks_set_on_data_chunk_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(
|
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,
|
nghttp2_session_callbacks_set_on_header_callback(callbacks,
|
||||||
on_header_callback);
|
on_header_callback);
|
||||||
|
|
||||||
nghttp2_session_callbacks_set_on_begin_headers_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);
|
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) {
|
static void send_client_connection_header(http2_session_data *session_data) {
|
||||||
nghttp2_settings_entry iv[1] = {
|
nghttp2_settings_entry iv[1] = {
|
||||||
{NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS, 100}};
|
{NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS, 100}};
|
||||||
int rv;
|
int rv;
|
||||||
|
|
||||||
/* client 24 bytes magic string will be sent by nghttp2 library */
|
/* 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) \
|
#define MAKE_NV(NAME, VALUE, VALUELEN) \
|
||||||
{ \
|
{ \
|
||||||
(uint8_t *)NAME, (uint8_t *)VALUE, sizeof(NAME) - 1, \
|
(uint8_t *)NAME, (uint8_t *)VALUE, sizeof(NAME) - 1, VALUELEN, \
|
||||||
VALUELEN, NGHTTP2_NV_FLAG_NONE, \
|
NGHTTP2_NV_FLAG_NONE \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define MAKE_NV2(NAME, VALUE) \
|
#define MAKE_NV2(NAME, VALUE) \
|
||||||
{ \
|
{ \
|
||||||
(uint8_t *)NAME, (uint8_t *)VALUE, sizeof(NAME) - 1, \
|
(uint8_t *)NAME, (uint8_t *)VALUE, sizeof(NAME) - 1, sizeof(VALUE) - 1, \
|
||||||
sizeof(VALUE) - 1, NGHTTP2_NV_FLAG_NONE, \
|
NGHTTP2_NV_FLAG_NONE \
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Send HTTP request to the remote peer */
|
/* Send HTTP request to the remote peer */
|
||||||
@@ -397,13 +396,13 @@ static void submit_request(http2_session_data *session_data) {
|
|||||||
int32_t stream_id;
|
int32_t stream_id;
|
||||||
http2_stream_data *stream_data = session_data->stream_data;
|
http2_stream_data *stream_data = session_data->stream_data;
|
||||||
const char *uri = stream_data->uri;
|
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[] = {
|
nghttp2_nv hdrs[] = {
|
||||||
MAKE_NV2(":method", "GET"),
|
MAKE_NV2(":method", "GET"),
|
||||||
MAKE_NV(":scheme", &uri[u->field_data[URLPARSE_SCHEMA].off],
|
MAKE_NV(":scheme", &uri[u->field_data[UF_SCHEMA].off],
|
||||||
u->field_data[URLPARSE_SCHEMA].len),
|
u->field_data[UF_SCHEMA].len),
|
||||||
MAKE_NV(":authority", stream_data->authority, stream_data->authoritylen),
|
MAKE_NV(":authority", stream_data->authority, stream_data->authoritylen),
|
||||||
MAKE_NV(":path", stream_data->path, stream_data->pathlen)};
|
MAKE_NV(":path", stream_data->path, stream_data->pathlen)};
|
||||||
fprintf(stderr, "Request headers:\n");
|
fprintf(stderr, "Request headers:\n");
|
||||||
print_headers(stderr, hdrs, ARRLEN(hdrs));
|
print_headers(stderr, hdrs, ARRLEN(hdrs));
|
||||||
stream_id = nghttp2_submit_request2(session_data->session, NULL, 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);
|
ssl = create_ssl(ssl_ctx);
|
||||||
bev = bufferevent_openssl_socket_new(
|
bev = bufferevent_openssl_socket_new(
|
||||||
evbase, -1, ssl, BUFFEREVENT_SSL_CONNECTING,
|
evbase, -1, ssl, BUFFEREVENT_SSL_CONNECTING,
|
||||||
BEV_OPT_DEFER_CALLBACKS | BEV_OPT_CLOSE_ON_FREE);
|
BEV_OPT_DEFER_CALLBACKS | BEV_OPT_CLOSE_ON_FREE);
|
||||||
bufferevent_enable(bev, EV_READ | EV_WRITE);
|
bufferevent_enable(bev, EV_READ | EV_WRITE);
|
||||||
bufferevent_setcb(bev, readcb, writecb, eventcb, session_data);
|
bufferevent_setcb(bev, readcb, writecb, eventcb, session_data);
|
||||||
rv = bufferevent_socket_connect_hostname(bev, session_data->dnsbase,
|
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
|
/* Get resource denoted by the |uri|. The debug and error messages are
|
||||||
printed in stderr, while the response body is printed in stdout. */
|
printed in stderr, while the response body is printed in stdout. */
|
||||||
static void run(const char *uri) {
|
static void run(const char *uri) {
|
||||||
urlparse_url u;
|
struct http_parser_url u;
|
||||||
char *host;
|
char *host;
|
||||||
uint16_t port;
|
uint16_t port;
|
||||||
int rv;
|
int rv;
|
||||||
@@ -553,13 +552,12 @@ static void run(const char *uri) {
|
|||||||
http2_session_data *session_data;
|
http2_session_data *session_data;
|
||||||
|
|
||||||
/* Parse the |uri| and stores its components in |u| */
|
/* 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) {
|
if (rv != 0) {
|
||||||
errx(1, "Could not parse URI %s", uri);
|
errx(1, "Could not parse URI %s", uri);
|
||||||
}
|
}
|
||||||
host = strndup(&uri[u.field_data[URLPARSE_HOST].off],
|
host = strndup(&uri[u.field_data[UF_HOST].off], u.field_data[UF_HOST].len);
|
||||||
u.field_data[URLPARSE_HOST].len);
|
if (!(u.field_set & (1 << UF_PORT))) {
|
||||||
if (!(u.field_set & (1 << URLPARSE_PORT))) {
|
|
||||||
port = 443;
|
port = 443;
|
||||||
} else {
|
} else {
|
||||||
port = u.port;
|
port = u.port;
|
||||||
|
|||||||
@@ -80,8 +80,8 @@
|
|||||||
|
|
||||||
#define MAKE_NV(NAME, VALUE) \
|
#define MAKE_NV(NAME, VALUE) \
|
||||||
{ \
|
{ \
|
||||||
(uint8_t *)NAME, (uint8_t *)VALUE, sizeof(NAME) - 1, \
|
(uint8_t *)NAME, (uint8_t *)VALUE, sizeof(NAME) - 1, sizeof(VALUE) - 1, \
|
||||||
sizeof(VALUE) - 1, NGHTTP2_NV_FLAG_NONE, \
|
NGHTTP2_NV_FLAG_NONE \
|
||||||
}
|
}
|
||||||
|
|
||||||
struct app_context;
|
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",
|
errx(1, "Could not create SSL/TLS context: %s",
|
||||||
ERR_error_string(ERR_get_error(), NULL));
|
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_CTX_set_options(ssl_ctx,
|
||||||
SSL_OP_NO_COMPRESSION |
|
SSL_OP_ALL | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 |
|
||||||
SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION);
|
SSL_OP_NO_COMPRESSION |
|
||||||
|
SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION);
|
||||||
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
|
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
|
||||||
if (SSL_CTX_set1_curves_list(ssl_ctx, "P-256") != 1) {
|
if (SSL_CTX_set1_curves_list(ssl_ctx, "P-256") != 1) {
|
||||||
errx(1, "SSL_CTX_set1_curves_list failed: %s",
|
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;
|
session_data->app_ctx = app_ctx;
|
||||||
setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char *)&val, sizeof(val));
|
setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char *)&val, sizeof(val));
|
||||||
session_data->bev = bufferevent_openssl_socket_new(
|
session_data->bev = bufferevent_openssl_socket_new(
|
||||||
app_ctx->evbase, fd, ssl, BUFFEREVENT_SSL_ACCEPTING,
|
app_ctx->evbase, fd, ssl, BUFFEREVENT_SSL_ACCEPTING,
|
||||||
BEV_OPT_CLOSE_ON_FREE | BEV_OPT_DEFER_CALLBACKS);
|
BEV_OPT_CLOSE_ON_FREE | BEV_OPT_DEFER_CALLBACKS);
|
||||||
bufferevent_enable(session_data->bev, EV_READ | EV_WRITE);
|
bufferevent_enable(session_data->bev, EV_READ | EV_WRITE);
|
||||||
rv = getnameinfo(addr, (socklen_t)addrlen, host, sizeof(host), NULL, 0,
|
rv = getnameinfo(addr, (socklen_t)addrlen, host, sizeof(host), NULL, 0,
|
||||||
NI_NUMERICHOST);
|
NI_NUMERICHOST);
|
||||||
@@ -359,7 +360,7 @@ static char *percent_decode(const uint8_t *value, size_t valuelen) {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
res[j++] =
|
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;
|
i += 3;
|
||||||
}
|
}
|
||||||
memcpy(&res[j], &value[i], 2);
|
memcpy(&res[j], &value[i], 2);
|
||||||
@@ -421,9 +422,9 @@ static int error_reply(nghttp2_session *session,
|
|||||||
rv = pipe(pipefd);
|
rv = pipe(pipefd);
|
||||||
if (rv != 0) {
|
if (rv != 0) {
|
||||||
warn("Could not create pipe");
|
warn("Could not create pipe");
|
||||||
rv =
|
rv = nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE,
|
||||||
nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE,
|
stream_data->stream_id,
|
||||||
stream_data->stream_id, NGHTTP2_INTERNAL_ERROR);
|
NGHTTP2_INTERNAL_ERROR);
|
||||||
if (rv != 0) {
|
if (rv != 0) {
|
||||||
warnx("Fatal error: %s", nghttp2_strerror(rv));
|
warnx("Fatal error: %s", nghttp2_strerror(rv));
|
||||||
return -1;
|
return -1;
|
||||||
@@ -466,7 +467,7 @@ static int on_header_callback(nghttp2_session *session,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
stream_data =
|
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) {
|
if (!stream_data || stream_data->request_path) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -556,7 +557,7 @@ static int on_frame_recv_callback(nghttp2_session *session,
|
|||||||
/* Check that the client request has finished */
|
/* Check that the client request has finished */
|
||||||
if (frame->hd.flags & NGHTTP2_FLAG_END_STREAM) {
|
if (frame->hd.flags & NGHTTP2_FLAG_END_STREAM) {
|
||||||
stream_data =
|
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
|
/* For DATA and HEADERS frame, this callback may be called after
|
||||||
on_stream_close_callback. Check that stream still alive. */
|
on_stream_close_callback. Check that stream still alive. */
|
||||||
if (!stream_data) {
|
if (!stream_data) {
|
||||||
@@ -597,13 +598,13 @@ static void initialize_nghttp2_session(http2_session_data *session_data) {
|
|||||||
on_frame_recv_callback);
|
on_frame_recv_callback);
|
||||||
|
|
||||||
nghttp2_session_callbacks_set_on_stream_close_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,
|
nghttp2_session_callbacks_set_on_header_callback(callbacks,
|
||||||
on_header_callback);
|
on_header_callback);
|
||||||
|
|
||||||
nghttp2_session_callbacks_set_on_begin_headers_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);
|
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 */
|
magic octets and SETTINGS frame */
|
||||||
static int send_server_connection_header(http2_session_data *session_data) {
|
static int send_server_connection_header(http2_session_data *session_data) {
|
||||||
nghttp2_settings_entry iv[1] = {
|
nghttp2_settings_entry iv[1] = {
|
||||||
{NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS, 100}};
|
{NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS, 100}};
|
||||||
int rv;
|
int rv;
|
||||||
|
|
||||||
rv = nghttp2_submit_settings(session_data->session, NGHTTP2_FLAG_NONE, iv,
|
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) {
|
for (rp = res; rp; rp = rp->ai_next) {
|
||||||
struct evconnlistener *listener;
|
struct evconnlistener *listener;
|
||||||
listener = evconnlistener_new_bind(
|
listener = evconnlistener_new_bind(
|
||||||
evbase, acceptcb, app_ctx, LEV_OPT_CLOSE_ON_FREE | LEV_OPT_REUSEABLE, 16,
|
evbase, acceptcb, app_ctx, LEV_OPT_CLOSE_ON_FREE | LEV_OPT_REUSEABLE,
|
||||||
rp->ai_addr, (int)rp->ai_addrlen);
|
16, rp->ai_addr, (int)rp->ai_addrlen);
|
||||||
if (listener) {
|
if (listener) {
|
||||||
freeaddrinfo(res);
|
freeaddrinfo(res);
|
||||||
|
|
||||||
|
|||||||
@@ -62,8 +62,8 @@ void check_frame_pack_headers(FuzzedDataProvider *data_provider) {
|
|||||||
nvlen = HEADERS_LENGTH;
|
nvlen = HEADERS_LENGTH;
|
||||||
nghttp2_priority_spec_default_init(&pri_spec);
|
nghttp2_priority_spec_default_init(&pri_spec);
|
||||||
nghttp2_frame_headers_init(
|
nghttp2_frame_headers_init(
|
||||||
&frame, NGHTTP2_FLAG_END_STREAM | NGHTTP2_FLAG_END_HEADERS, 1000000007,
|
&frame, NGHTTP2_FLAG_END_STREAM | NGHTTP2_FLAG_END_HEADERS, 1000000007,
|
||||||
NGHTTP2_HCAT_REQUEST, &pri_spec, nva, nvlen);
|
NGHTTP2_HCAT_REQUEST, &pri_spec, nva, nvlen);
|
||||||
|
|
||||||
/* Perform a set of operations with the fuzz data */
|
/* Perform a set of operations with the fuzz data */
|
||||||
rv = nghttp2_frame_pack_headers(&bufs, &frame, &deflater);
|
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,
|
nghttp2_session_callbacks_set_on_frame_recv_callback(callbacks,
|
||||||
on_frame_recv_callback);
|
on_frame_recv_callback);
|
||||||
nghttp2_session_callbacks_set_on_begin_headers_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,
|
nghttp2_session_callbacks_set_on_header_callback2(callbacks,
|
||||||
on_header_callback2);
|
on_header_callback2);
|
||||||
nghttp2_session_callbacks_set_before_frame_send_callback(
|
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,
|
nghttp2_session_callbacks_set_on_frame_send_callback(callbacks,
|
||||||
on_frame_send_callback);
|
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,
|
nghttp2_session_callbacks_set_on_frame_recv_callback(callbacks,
|
||||||
on_frame_recv_callback);
|
on_frame_recv_callback);
|
||||||
nghttp2_session_callbacks_set_on_begin_headers_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,
|
nghttp2_session_callbacks_set_on_header_callback2(callbacks,
|
||||||
on_header_callback2);
|
on_header_callback2);
|
||||||
nghttp2_session_callbacks_set_before_frame_send_callback(
|
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,
|
nghttp2_session_callbacks_set_on_frame_send_callback(callbacks,
|
||||||
on_frame_send_callback);
|
on_frame_send_callback);
|
||||||
|
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ enum {''')
|
|||||||
|
|
||||||
def gen_index_header(tokens, prefix, comp_fun, return_type, fail_value):
|
def gen_index_header(tokens, prefix, comp_fun, return_type, fail_value):
|
||||||
print('''\
|
print('''\
|
||||||
{} lookup_token(const std::string_view &name) {{
|
{} lookup_token(const StringRef &name) {{
|
||||||
switch (name.size()) {{'''.format(return_type))
|
switch (name.size()) {{'''.format(return_type))
|
||||||
b = build_header(tokens)
|
b = build_header(tokens)
|
||||||
for size in sorted(b.keys()):
|
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))
|
case '{}':'''.format(c))
|
||||||
for k in headers:
|
for k in headers:
|
||||||
print('''\
|
print('''\
|
||||||
if ({}("{}"sv, name.substr(0, {}))) {{
|
if ({}("{}"_sr, name, {})) {{
|
||||||
return {};
|
return {};
|
||||||
}}'''.format(comp_fun, k[:-1], size - 1, to_enum_hd(k, prefix)))
|
}}'''.format(comp_fun, k[:-1], size - 1, to_enum_hd(k, prefix)))
|
||||||
print('''\
|
print('''\
|
||||||
|
|||||||
25
go.mod
25
go.mod
@@ -1,21 +1,24 @@
|
|||||||
module github.com/nghttp2/nghttp2
|
module github.com/nghttp2/nghttp2
|
||||||
|
|
||||||
go 1.24.0
|
go 1.21.1
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/bradfitz/gomemcache v0.0.0-20230905024940-24af94b03874
|
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
|
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 (
|
require (
|
||||||
github.com/quic-go/qpack v0.5.1 // indirect
|
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect
|
||||||
go.uber.org/mock v0.5.0 // indirect
|
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 // indirect
|
||||||
golang.org/x/crypto v0.41.0 // indirect
|
github.com/onsi/ginkgo/v2 v2.9.5 // indirect
|
||||||
golang.org/x/mod v0.26.0 // indirect
|
github.com/quic-go/qpack v0.4.0 // indirect
|
||||||
golang.org/x/sync v0.16.0 // indirect
|
go.uber.org/mock v0.4.0 // indirect
|
||||||
golang.org/x/sys v0.35.0 // indirect
|
golang.org/x/crypto v0.22.0 // indirect
|
||||||
golang.org/x/text v0.28.0 // indirect
|
golang.org/x/exp v0.0.0-20221205204356-47842c84f3db // indirect
|
||||||
golang.org/x/tools v0.35.0 // 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 h1:N7oVaKyGp8bttX0bfZGmcGkjz7DLQXhAn3DNd3T0ous=
|
||||||
github.com/bradfitz/gomemcache v0.0.0-20230905024940-24af94b03874/go.mod h1:r5xuitiExdLAJ09PR7vBVENGvp4ZuTBeWTGtxuX3K+c=
|
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 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
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/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ=
|
||||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
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 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
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.4.0 h1:Cr9BXA1sQS2SmDUWjSofMPNKmvF6IiIfDRmgU0w1ZCo=
|
||||||
github.com/quic-go/qpack v0.5.1/go.mod h1:+PC4XFrEskIVkcLzpEkbLqq1uCoxPhQuvK5rH1ZgaEg=
|
github.com/quic-go/qpack v0.4.0/go.mod h1:UZVnYIfi5GRk+zI9UMaCPsmZ2xKJP7XBUvVyT1Knj9A=
|
||||||
github.com/quic-go/quic-go v0.54.0 h1:6s1YB9QotYI6Ospeiguknbp2Znb/jZYjZLRXn9kMQBg=
|
github.com/quic-go/quic-go v0.43.1 h1:fLiMNfQVe9q2JvSsiXo4fXOEguXHGGl9+6gLp4RPeZQ=
|
||||||
github.com/quic-go/quic-go v0.54.0/go.mod h1:e68ZEaCdyviluZmy44P6Iey98v/Wfz6HCjQEm+l8zTY=
|
github.com/quic-go/quic-go v0.43.1/go.mod h1:132kz4kL3F9vxhW3CtQJLDVwcFe5wdWeJXXijhsO57M=
|
||||||
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
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 h1:zKJxuRe+a0O34V81GAZWOrotuU6mveT30QLjJ7OPMMg=
|
||||||
github.com/tatsuhiro-t/go-nghttp2 v0.0.0-20240121064059-46ccb0a462a8/go.mod h1:gTqc3Q4boc+cKRlSFywTYdX9t6VGRcsThlNIWwaL3Dc=
|
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.4.0 h1:VcM4ZOtdbR4f6VXfiOpwpVJDL6lCReaZ6mw31wqh7KU=
|
||||||
go.uber.org/mock v0.5.0/go.mod h1:ge71pBPLYDk7QIi1LupWxdAykm7KIEFchiOqd6z7qMM=
|
go.uber.org/mock v0.4.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc=
|
||||||
golang.org/x/crypto v0.41.0 h1:WKYxWedPGCTVVl5+WHSSrOBT0O8lx32+zxmHxijgXp4=
|
golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30=
|
||||||
golang.org/x/crypto v0.41.0/go.mod h1:pO5AFd7FA68rFak7rOAGVuygIISepHftHnr8dr6+sUc=
|
golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M=
|
||||||
golang.org/x/mod v0.26.0 h1:EGMPT//Ezu+ylkCijjPc+f4Aih7sZvaAr+O3EHBxvZg=
|
golang.org/x/exp v0.0.0-20221205204356-47842c84f3db h1:D/cFflL63o2KSLJIwjlcIt8PR064j/xsmdEJL/YvY/o=
|
||||||
golang.org/x/mod v0.26.0/go.mod h1:/j6NAhSk8iQ723BGAUyoAcn7SlD7s15Dp9Nd/SfeaFQ=
|
golang.org/x/exp v0.0.0-20221205204356-47842c84f3db/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc=
|
||||||
golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE=
|
golang.org/x/mod v0.11.0 h1:bUO06HqtnRcc/7l71XBe4WcqTZ+3AH1J59zWDDwLKgU=
|
||||||
golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg=
|
golang.org/x/mod v0.11.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||||
golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw=
|
golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w=
|
||||||
golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8=
|
||||||
golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI=
|
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o=
|
||||||
golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng=
|
golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU=
|
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
|
||||||
golang.org/x/tools v0.35.0 h1:mBffYraMEf7aa0sB+NuKnuCy8qI/9Bughn8dC2Gu5r0=
|
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||||
golang.org/x/tools v0.35.0/go.mod h1:NKdj5HkL/73byiZSJjqJgKn3ep7KjFkBOkR/Hps3VPw=
|
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 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import (
|
|||||||
"bufio"
|
"bufio"
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
@@ -63,7 +62,6 @@ func TestH1H1InvalidMethod(t *testing.T) {
|
|||||||
t.Errorf("server should not forward this request")
|
t.Errorf("server should not forward this request")
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
st := newServerTester(t, opts)
|
st := newServerTester(t, opts)
|
||||||
defer st.Close()
|
defer st.Close()
|
||||||
|
|
||||||
@@ -88,7 +86,6 @@ func TestH1H1MultipleRequestCL(t *testing.T) {
|
|||||||
t.Errorf("server should not forward bad request")
|
t.Errorf("server should not forward bad request")
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
st := newServerTester(t, opts)
|
st := newServerTester(t, opts)
|
||||||
defer st.Close()
|
defer st.Close()
|
||||||
|
|
||||||
@@ -136,7 +133,6 @@ func TestH1H1AffinityCookie(t *testing.T) {
|
|||||||
opts := options{
|
opts := options{
|
||||||
args: []string{"--affinity-cookie"},
|
args: []string{"--affinity-cookie"},
|
||||||
}
|
}
|
||||||
|
|
||||||
st := newServerTester(t, opts)
|
st := newServerTester(t, opts)
|
||||||
defer st.Close()
|
defer st.Close()
|
||||||
|
|
||||||
@@ -153,7 +149,6 @@ func TestH1H1AffinityCookie(t *testing.T) {
|
|||||||
|
|
||||||
const pattern = `affinity=[0-9a-f]{8}; Path=/foo/bar`
|
const pattern = `affinity=[0-9a-f]{8}; Path=/foo/bar`
|
||||||
validCookie := regexp.MustCompile(pattern)
|
validCookie := regexp.MustCompile(pattern)
|
||||||
|
|
||||||
if got := res.header.Get("Set-Cookie"); !validCookie.MatchString(got) {
|
if got := res.header.Get("Set-Cookie"); !validCookie.MatchString(got) {
|
||||||
t.Errorf("Set-Cookie: %v; want pattern %v", got, pattern)
|
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"},
|
args: []string{"--alpn-h1", "--affinity-cookie"},
|
||||||
tls: true,
|
tls: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
st := newServerTester(t, opts)
|
st := newServerTester(t, opts)
|
||||||
defer st.Close()
|
defer st.Close()
|
||||||
|
|
||||||
@@ -183,7 +177,6 @@ func TestH1H1AffinityCookieTLS(t *testing.T) {
|
|||||||
|
|
||||||
const pattern = `affinity=[0-9a-f]{8}; Path=/foo/bar; Secure`
|
const pattern = `affinity=[0-9a-f]{8}; Path=/foo/bar; Secure`
|
||||||
validCookie := regexp.MustCompile(pattern)
|
validCookie := regexp.MustCompile(pattern)
|
||||||
|
|
||||||
if got := res.header.Get("Set-Cookie"); !validCookie.MatchString(got) {
|
if got := res.header.Get("Set-Cookie"); !validCookie.MatchString(got) {
|
||||||
t.Errorf("Set-Cookie: %v; want pattern %v", got, pattern)
|
t.Errorf("Set-Cookie: %v; want pattern %v", got, pattern)
|
||||||
}
|
}
|
||||||
@@ -228,8 +221,7 @@ func TestH1H1GracefulShutdown(t *testing.T) {
|
|||||||
|
|
||||||
want := io.EOF
|
want := io.EOF
|
||||||
b := make([]byte, 256)
|
b := make([]byte, 256)
|
||||||
|
if _, err := st.conn.Read(b); err == nil || err != want {
|
||||||
if _, err := st.conn.Read(b); !errors.Is(err, want) {
|
|
||||||
t.Errorf("st.conn.Read(): %v; want %v", 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)
|
w.Header().Add("request-host", r.Host)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
st := newServerTester(t, opts)
|
st := newServerTester(t, opts)
|
||||||
defer st.Close()
|
defer st.Close()
|
||||||
|
|
||||||
@@ -252,11 +243,9 @@ func TestH1H1HostRewrite(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Error st.http1() = %v", err)
|
t.Fatalf("Error st.http1() = %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if got, want := res.status, http.StatusOK; got != want {
|
if got, want := res.status, http.StatusOK; got != want {
|
||||||
t.Errorf("status: %v; want %v", got, want)
|
t.Errorf("status: %v; want %v", got, want)
|
||||||
}
|
}
|
||||||
|
|
||||||
if got, want := res.header.Get("request-host"), st.backendHost; got != want {
|
if got, want := res.header.Get("request-host"), st.backendHost; got != want {
|
||||||
t.Errorf("request-host: %v; want %v", 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")
|
t.Errorf("server should not forward this request")
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
st := newServerTester(t, opts)
|
st := newServerTester(t, opts)
|
||||||
defer st.Close()
|
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 {
|
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)
|
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 {
|
if err != nil {
|
||||||
t.Fatalf("Error http.ReadResponse() = %v", err)
|
t.Fatalf("Error http.ReadResponse() = %v", err)
|
||||||
@@ -298,14 +285,12 @@ func TestH1H1BadAuthority(t *testing.T) {
|
|||||||
t.Errorf("server should not forward this request")
|
t.Errorf("server should not forward this request")
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
st := newServerTester(t, opts)
|
st := newServerTester(t, opts)
|
||||||
defer st.Close()
|
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 {
|
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)
|
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 {
|
if err != nil {
|
||||||
t.Fatalf("Error http.ReadResponse() = %v", err)
|
t.Fatalf("Error http.ReadResponse() = %v", err)
|
||||||
@@ -326,14 +311,12 @@ func TestH1H1BadScheme(t *testing.T) {
|
|||||||
t.Errorf("server should not forward this request")
|
t.Errorf("server should not forward this request")
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
st := newServerTester(t, opts)
|
st := newServerTester(t, opts)
|
||||||
defer st.Close()
|
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 {
|
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)
|
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 {
|
if err != nil {
|
||||||
t.Fatalf("Error http.ReadResponse() = %v", err)
|
t.Fatalf("Error http.ReadResponse() = %v", err)
|
||||||
@@ -354,7 +337,6 @@ func TestH1H1HTTP10(t *testing.T) {
|
|||||||
w.Header().Add("request-host", r.Host)
|
w.Header().Add("request-host", r.Host)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
st := newServerTester(t, opts)
|
st := newServerTester(t, opts)
|
||||||
defer st.Close()
|
defer st.Close()
|
||||||
|
|
||||||
@@ -372,7 +354,6 @@ func TestH1H1HTTP10(t *testing.T) {
|
|||||||
if got, want := resp.StatusCode, http.StatusOK; got != want {
|
if got, want := resp.StatusCode, http.StatusOK; got != want {
|
||||||
t.Errorf("status: %v; want %v", got, want)
|
t.Errorf("status: %v; want %v", got, want)
|
||||||
}
|
}
|
||||||
|
|
||||||
if got, want := resp.Header.Get("request-host"), st.backendHost; got != want {
|
if got, want := resp.Header.Get("request-host"), st.backendHost; got != want {
|
||||||
t.Errorf("request-host: %v; want %v", 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)
|
w.Header().Add("request-host", r.Host)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
st := newServerTester(t, opts)
|
st := newServerTester(t, opts)
|
||||||
defer st.Close()
|
defer st.Close()
|
||||||
|
|
||||||
@@ -405,7 +385,6 @@ func TestH1H1HTTP10NoHostRewrite(t *testing.T) {
|
|||||||
if got, want := resp.StatusCode, http.StatusOK; got != want {
|
if got, want := resp.StatusCode, http.StatusOK; got != want {
|
||||||
t.Errorf("status: %v; want %v", got, want)
|
t.Errorf("status: %v; want %v", got, want)
|
||||||
}
|
}
|
||||||
|
|
||||||
if got, want := resp.Header.Get("request-host"), st.backendHost; got != want {
|
if got, want := resp.Header.Get("request-host"), st.backendHost; got != want {
|
||||||
t.Errorf("request-host: %v; want %v", got, want)
|
t.Errorf("request-host: %v; want %v", got, want)
|
||||||
}
|
}
|
||||||
@@ -419,11 +398,10 @@ func TestH1H1RequestTrailer(t *testing.T) {
|
|||||||
buf := make([]byte, 4096)
|
buf := make([]byte, 4096)
|
||||||
for {
|
for {
|
||||||
_, err := r.Body.Read(buf)
|
_, err := r.Body.Read(buf)
|
||||||
|
if err == io.EOF {
|
||||||
|
break
|
||||||
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Is(err, io.EOF) {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
t.Fatalf("r.Body.Read() = %v", err)
|
t.Fatalf("r.Body.Read() = %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -432,7 +410,6 @@ func TestH1H1RequestTrailer(t *testing.T) {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
st := newServerTester(t, opts)
|
st := newServerTester(t, opts)
|
||||||
defer st.Close()
|
defer st.Close()
|
||||||
|
|
||||||
@@ -446,7 +423,6 @@ func TestH1H1RequestTrailer(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Error st.http1() = %v", err)
|
t.Fatalf("Error st.http1() = %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if got, want := res.status, http.StatusOK; got != want {
|
if got, want := res.status, http.StatusOK; got != want {
|
||||||
t.Errorf("res.status: %v; want %v", 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")
|
t.Fatal("execution path should not be here")
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
st := newServerTester(t, opts)
|
st := newServerTester(t, opts)
|
||||||
defer st.Close()
|
defer st.Close()
|
||||||
|
|
||||||
@@ -475,7 +450,6 @@ func TestH1H1HeaderFieldBufferPath(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Error st.http1() = %v", err)
|
t.Fatalf("Error st.http1() = %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if got, want := res.status, http.StatusRequestHeaderFieldsTooLarge; got != want {
|
if got, want := res.status, http.StatusRequestHeaderFieldsTooLarge; got != want {
|
||||||
t.Errorf("status: %v; want %v", 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")
|
t.Fatal("execution path should not be here")
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
st := newServerTester(t, opts)
|
st := newServerTester(t, opts)
|
||||||
defer st.Close()
|
defer st.Close()
|
||||||
|
|
||||||
@@ -500,7 +473,6 @@ func TestH1H1HeaderFieldBuffer(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Error st.http1() = %v", err)
|
t.Fatalf("Error st.http1() = %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if got, want := res.status, http.StatusRequestHeaderFieldsTooLarge; got != want {
|
if got, want := res.status, http.StatusRequestHeaderFieldsTooLarge; got != want {
|
||||||
t.Errorf("status: %v; want %v", 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")
|
t.Fatal("execution path should not be here")
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
st := newServerTester(t, opts)
|
st := newServerTester(t, opts)
|
||||||
defer st.Close()
|
defer st.Close()
|
||||||
|
|
||||||
@@ -530,7 +501,6 @@ func TestH1H1HeaderFields(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Error st.http1() = %v", err)
|
t.Fatalf("Error st.http1() = %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if got, want := res.status, http.StatusRequestHeaderFieldsTooLarge; got != want {
|
if got, want := res.status, http.StatusRequestHeaderFieldsTooLarge; got != want {
|
||||||
t.Errorf("status: %v; want %v", got, want)
|
t.Errorf("status: %v; want %v", got, want)
|
||||||
}
|
}
|
||||||
@@ -545,7 +515,6 @@ func TestH1H1Websocket(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}).ServeHTTP,
|
}).ServeHTTP,
|
||||||
}
|
}
|
||||||
|
|
||||||
st := newServerTester(t, opts)
|
st := newServerTester(t, opts)
|
||||||
defer st.Close()
|
defer st.Close()
|
||||||
|
|
||||||
@@ -554,7 +523,6 @@ func TestH1H1Websocket(t *testing.T) {
|
|||||||
name: "TestH1H1Websocket",
|
name: "TestH1H1Websocket",
|
||||||
body: content,
|
body: content,
|
||||||
})
|
})
|
||||||
|
|
||||||
if got, want := res.body, content; !bytes.Equal(got, want) {
|
if got, want := res.body, content; !bytes.Equal(got, want) {
|
||||||
t.Errorf("echo: %q; want %q", got, want)
|
t.Errorf("echo: %q; want %q", got, want)
|
||||||
}
|
}
|
||||||
@@ -571,7 +539,6 @@ func TestH1H1ReqPhaseSetHeader(t *testing.T) {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
st := newServerTester(t, opts)
|
st := newServerTester(t, opts)
|
||||||
defer st.Close()
|
defer st.Close()
|
||||||
|
|
||||||
@@ -596,7 +563,6 @@ func TestH1H1ReqPhaseReturn(t *testing.T) {
|
|||||||
t.Fatalf("request should not be forwarded")
|
t.Fatalf("request should not be forwarded")
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
st := newServerTester(t, opts)
|
st := newServerTester(t, opts)
|
||||||
defer st.Close()
|
defer st.Close()
|
||||||
|
|
||||||
@@ -637,7 +603,6 @@ func TestH1H1ReqPhaseReturnCONNECTMethod(t *testing.T) {
|
|||||||
t.Fatalf("request should not be forwarded")
|
t.Fatalf("request should not be forwarded")
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
st := newServerTester(t, opts)
|
st := newServerTester(t, opts)
|
||||||
defer st.Close()
|
defer st.Close()
|
||||||
|
|
||||||
@@ -705,7 +670,6 @@ func TestH1H1RespPhaseSetHeader(t *testing.T) {
|
|||||||
opts := options{
|
opts := options{
|
||||||
args: []string{"--mruby-file=" + testDir + "/resp-set-header.rb"},
|
args: []string{"--mruby-file=" + testDir + "/resp-set-header.rb"},
|
||||||
}
|
}
|
||||||
|
|
||||||
st := newServerTester(t, opts)
|
st := newServerTester(t, opts)
|
||||||
defer st.Close()
|
defer st.Close()
|
||||||
|
|
||||||
@@ -731,7 +695,6 @@ func TestH1H1RespPhaseReturn(t *testing.T) {
|
|||||||
opts := options{
|
opts := options{
|
||||||
args: []string{"--mruby-file=" + testDir + "/resp-return.rb"},
|
args: []string{"--mruby-file=" + testDir + "/resp-return.rb"},
|
||||||
}
|
}
|
||||||
|
|
||||||
st := newServerTester(t, opts)
|
st := newServerTester(t, opts)
|
||||||
defer st.Close()
|
defer st.Close()
|
||||||
|
|
||||||
@@ -769,7 +732,6 @@ func TestH1H1HTTPSRedirect(t *testing.T) {
|
|||||||
opts := options{
|
opts := options{
|
||||||
args: []string{"--redirect-if-not-tls"},
|
args: []string{"--redirect-if-not-tls"},
|
||||||
}
|
}
|
||||||
|
|
||||||
st := newServerTester(t, opts)
|
st := newServerTester(t, opts)
|
||||||
defer st.Close()
|
defer st.Close()
|
||||||
|
|
||||||
@@ -783,7 +745,6 @@ func TestH1H1HTTPSRedirect(t *testing.T) {
|
|||||||
if got, want := res.status, http.StatusPermanentRedirect; got != want {
|
if got, want := res.status, http.StatusPermanentRedirect; got != want {
|
||||||
t.Errorf("status = %v; want %v", got, want)
|
t.Errorf("status = %v; want %v", got, want)
|
||||||
}
|
}
|
||||||
|
|
||||||
if got, want := res.header.Get("location"), "https://127.0.0.1/"; got != want {
|
if got, want := res.header.Get("location"), "https://127.0.0.1/"; got != want {
|
||||||
t.Errorf("location: %v; want %v", got, want)
|
t.Errorf("location: %v; want %v", got, want)
|
||||||
}
|
}
|
||||||
@@ -798,7 +759,6 @@ func TestH1H1HTTPSRedirectPort(t *testing.T) {
|
|||||||
"--redirect-https-port=8443",
|
"--redirect-https-port=8443",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
st := newServerTester(t, opts)
|
st := newServerTester(t, opts)
|
||||||
defer st.Close()
|
defer st.Close()
|
||||||
|
|
||||||
@@ -813,7 +773,6 @@ func TestH1H1HTTPSRedirectPort(t *testing.T) {
|
|||||||
if got, want := res.status, http.StatusPermanentRedirect; got != want {
|
if got, want := res.status, http.StatusPermanentRedirect; got != want {
|
||||||
t.Errorf("status = %v; want %v", 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 {
|
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)
|
t.Errorf("location: %v; want %v", got, want)
|
||||||
}
|
}
|
||||||
@@ -832,7 +791,6 @@ func TestH1H1POSTRequests(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Error st.http1() = %v", err)
|
t.Fatalf("Error st.http1() = %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if got, want := res.status, http.StatusOK; got != want {
|
if got, want := res.status, http.StatusOK; got != want {
|
||||||
t.Errorf("res.status: %v; want %v", got, want)
|
t.Errorf("res.status: %v; want %v", got, want)
|
||||||
}
|
}
|
||||||
@@ -844,7 +802,6 @@ func TestH1H1POSTRequests(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Error st.http1() = %v", err)
|
t.Fatalf("Error st.http1() = %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if got, want := res.status, http.StatusOK; got != want {
|
if got, want := res.status, http.StatusOK; got != want {
|
||||||
t.Errorf("res.status: %v; want %v", got, want)
|
t.Errorf("res.status: %v; want %v", got, want)
|
||||||
}
|
}
|
||||||
@@ -860,7 +817,6 @@ func TestH1H1CONNECTMethodFailure(t *testing.T) {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
st := newServerTester(t, opts)
|
st := newServerTester(t, opts)
|
||||||
defer st.Close()
|
defer st.Close()
|
||||||
|
|
||||||
@@ -882,39 +838,12 @@ func TestH1H1CONNECTMethodFailure(t *testing.T) {
|
|||||||
if _, err := io.ReadAll(resp.Body); err != nil {
|
if _, err := io.ReadAll(resp.Body); err != nil {
|
||||||
t.Fatalf("Error io.ReadAll() = %v", err)
|
t.Fatalf("Error io.ReadAll() = %v", err)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// TestH1H1CONNECTMethod tests that CONNECT request succeeds.
|
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 {
|
||||||
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 {
|
|
||||||
t.Fatalf("Error io.WriteString() = %v", err)
|
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 {
|
if err != nil {
|
||||||
t.Fatalf("Error http.ReadResponse() = %v", err)
|
t.Fatalf("Error http.ReadResponse() = %v", err)
|
||||||
}
|
}
|
||||||
@@ -959,7 +888,6 @@ func TestH1H2NoHost(t *testing.T) {
|
|||||||
t.Errorf("server should not forward bad request")
|
t.Errorf("server should not forward bad request")
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
st := newServerTester(t, opts)
|
st := newServerTester(t, opts)
|
||||||
defer st.Close()
|
defer st.Close()
|
||||||
|
|
||||||
@@ -989,7 +917,6 @@ func TestH1H2HTTP10(t *testing.T) {
|
|||||||
w.Header().Add("request-host", r.Host)
|
w.Header().Add("request-host", r.Host)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
st := newServerTester(t, opts)
|
st := newServerTester(t, opts)
|
||||||
defer st.Close()
|
defer st.Close()
|
||||||
|
|
||||||
@@ -1007,7 +934,6 @@ func TestH1H2HTTP10(t *testing.T) {
|
|||||||
if got, want := resp.StatusCode, http.StatusOK; got != want {
|
if got, want := resp.StatusCode, http.StatusOK; got != want {
|
||||||
t.Errorf("status: %v; want %v", got, want)
|
t.Errorf("status: %v; want %v", got, want)
|
||||||
}
|
}
|
||||||
|
|
||||||
if got, want := resp.Header.Get("request-host"), st.backendHost; got != want {
|
if got, want := resp.Header.Get("request-host"), st.backendHost; got != want {
|
||||||
t.Errorf("request-host: %v; want %v", 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)
|
w.Header().Add("request-host", r.Host)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
st := newServerTester(t, opts)
|
st := newServerTester(t, opts)
|
||||||
defer st.Close()
|
defer st.Close()
|
||||||
|
|
||||||
@@ -1041,7 +966,6 @@ func TestH1H2HTTP10NoHostRewrite(t *testing.T) {
|
|||||||
if got, want := resp.StatusCode, http.StatusOK; got != want {
|
if got, want := resp.StatusCode, http.StatusOK; got != want {
|
||||||
t.Errorf("status: %v; want %v", got, want)
|
t.Errorf("status: %v; want %v", got, want)
|
||||||
}
|
}
|
||||||
|
|
||||||
if got, want := resp.Header.Get("request-host"), st.backendHost; got != want {
|
if got, want := resp.Header.Get("request-host"), st.backendHost; got != want {
|
||||||
t.Errorf("request-host: %v; want %v", got, want)
|
t.Errorf("request-host: %v; want %v", got, want)
|
||||||
}
|
}
|
||||||
@@ -1060,7 +984,6 @@ func TestH1H2CrumbleCookie(t *testing.T) {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
st := newServerTester(t, opts)
|
st := newServerTester(t, opts)
|
||||||
defer st.Close()
|
defer st.Close()
|
||||||
|
|
||||||
@@ -1073,7 +996,6 @@ func TestH1H2CrumbleCookie(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Error st.http1() = %v", err)
|
t.Fatalf("Error st.http1() = %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if got, want := res.status, http.StatusOK; got != want {
|
if got, want := res.status, http.StatusOK; got != want {
|
||||||
t.Errorf("status: %v; want %v", got, want)
|
t.Errorf("status: %v; want %v", got, want)
|
||||||
}
|
}
|
||||||
@@ -1090,7 +1012,6 @@ func TestH1H2GenerateVia(t *testing.T) {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
st := newServerTester(t, opts)
|
st := newServerTester(t, opts)
|
||||||
defer st.Close()
|
defer st.Close()
|
||||||
|
|
||||||
@@ -1100,7 +1021,6 @@ func TestH1H2GenerateVia(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Error st.http1() = %v", err)
|
t.Fatalf("Error st.http1() = %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if got, want := res.header.Get("Via"), "2 nghttpx"; got != want {
|
if got, want := res.header.Get("Via"), "2 nghttpx"; got != want {
|
||||||
t.Errorf("Via: %v; want %v", got, want)
|
t.Errorf("Via: %v; want %v", got, want)
|
||||||
}
|
}
|
||||||
@@ -1118,7 +1038,6 @@ func TestH1H2AppendVia(t *testing.T) {
|
|||||||
w.Header().Add("Via", "bar")
|
w.Header().Add("Via", "bar")
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
st := newServerTester(t, opts)
|
st := newServerTester(t, opts)
|
||||||
defer st.Close()
|
defer st.Close()
|
||||||
|
|
||||||
@@ -1131,7 +1050,6 @@ func TestH1H2AppendVia(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Error st.http1() = %v", err)
|
t.Fatalf("Error st.http1() = %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if got, want := res.header.Get("Via"), "bar, 2 nghttpx"; got != want {
|
if got, want := res.header.Get("Via"), "bar, 2 nghttpx"; got != want {
|
||||||
t.Errorf("Via: %v; want %v", got, want)
|
t.Errorf("Via: %v; want %v", got, want)
|
||||||
}
|
}
|
||||||
@@ -1149,7 +1067,6 @@ func TestH1H2NoVia(t *testing.T) {
|
|||||||
w.Header().Add("Via", "bar")
|
w.Header().Add("Via", "bar")
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
st := newServerTester(t, opts)
|
st := newServerTester(t, opts)
|
||||||
defer st.Close()
|
defer st.Close()
|
||||||
|
|
||||||
@@ -1162,7 +1079,6 @@ func TestH1H2NoVia(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Error st.http1() = %v", err)
|
t.Fatalf("Error st.http1() = %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if got, want := res.header.Get("Via"), "bar"; got != want {
|
if got, want := res.header.Get("Via"), "bar"; got != want {
|
||||||
t.Errorf("Via: %v; want %v", 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")
|
t.Fatalf("request should not be forwarded")
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
st := newServerTester(t, opts)
|
st := newServerTester(t, opts)
|
||||||
defer st.Close()
|
defer st.Close()
|
||||||
|
|
||||||
@@ -1221,7 +1136,6 @@ func TestH1H2RespPhaseReturn(t *testing.T) {
|
|||||||
"--mruby-file=" + testDir + "/resp-return.rb",
|
"--mruby-file=" + testDir + "/resp-return.rb",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
st := newServerTester(t, opts)
|
st := newServerTester(t, opts)
|
||||||
defer st.Close()
|
defer st.Close()
|
||||||
|
|
||||||
@@ -1264,7 +1178,6 @@ func TestH1H2TE(t *testing.T) {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
st := newServerTester(t, opts)
|
st := newServerTester(t, opts)
|
||||||
defer st.Close()
|
defer st.Close()
|
||||||
|
|
||||||
@@ -1277,7 +1190,6 @@ func TestH1H2TE(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Error st.http1() = %v", err)
|
t.Fatalf("Error st.http1() = %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if got, want := res.status, http.StatusOK; got != want {
|
if got, want := res.status, http.StatusOK; got != want {
|
||||||
t.Errorf("status: %v; want %v", got, want)
|
t.Errorf("status: %v; want %v", got, want)
|
||||||
}
|
}
|
||||||
@@ -1293,7 +1205,6 @@ func TestH1APIBackendconfig(t *testing.T) {
|
|||||||
},
|
},
|
||||||
connectPort: 3010,
|
connectPort: 3010,
|
||||||
}
|
}
|
||||||
|
|
||||||
st := newServerTester(t, opts)
|
st := newServerTester(t, opts)
|
||||||
defer st.Close()
|
defer st.Close()
|
||||||
|
|
||||||
@@ -1309,21 +1220,18 @@ backend=127.0.0.1,3011
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Error st.http1() = %v", err)
|
t.Fatalf("Error st.http1() = %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if got, want := res.status, http.StatusOK; got != want {
|
if got, want := res.status, http.StatusOK; got != want {
|
||||||
t.Errorf("res.status: %v; want %v", got, want)
|
t.Errorf("res.status: %v; want %v", got, want)
|
||||||
}
|
}
|
||||||
|
|
||||||
var apiResp APIResponse
|
var apiResp APIResponse
|
||||||
|
err = json.Unmarshal(res.body, &apiResp)
|
||||||
if err := json.Unmarshal(res.body, &apiResp); err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Error unmarshaling API response: %v", err)
|
t.Fatalf("Error unmarshaling API response: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if got, want := apiResp.Status, "Success"; got != want {
|
if got, want := apiResp.Status, "Success"; got != want {
|
||||||
t.Errorf("apiResp.Status: %v; want %v", got, want)
|
t.Errorf("apiResp.Status: %v; want %v", got, want)
|
||||||
}
|
}
|
||||||
|
|
||||||
if got, want := apiResp.Code, 200; got != want {
|
if got, want := apiResp.Code, 200; got != want {
|
||||||
t.Errorf("apiResp.Status: %v; want %v", got, want)
|
t.Errorf("apiResp.Status: %v; want %v", got, want)
|
||||||
}
|
}
|
||||||
@@ -1339,7 +1247,6 @@ func TestH1APIBackendconfigQuery(t *testing.T) {
|
|||||||
},
|
},
|
||||||
connectPort: 3010,
|
connectPort: 3010,
|
||||||
}
|
}
|
||||||
|
|
||||||
st := newServerTester(t, opts)
|
st := newServerTester(t, opts)
|
||||||
defer st.Close()
|
defer st.Close()
|
||||||
|
|
||||||
@@ -1355,21 +1262,18 @@ backend=127.0.0.1,3011
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Error st.http1() = %v", err)
|
t.Fatalf("Error st.http1() = %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if got, want := res.status, http.StatusOK; got != want {
|
if got, want := res.status, http.StatusOK; got != want {
|
||||||
t.Errorf("res.status: %v; want %v", got, want)
|
t.Errorf("res.status: %v; want %v", got, want)
|
||||||
}
|
}
|
||||||
|
|
||||||
var apiResp APIResponse
|
var apiResp APIResponse
|
||||||
|
err = json.Unmarshal(res.body, &apiResp)
|
||||||
if err := json.Unmarshal(res.body, &apiResp); err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Error unmarshaling API response: %v", err)
|
t.Fatalf("Error unmarshaling API response: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if got, want := apiResp.Status, "Success"; got != want {
|
if got, want := apiResp.Status, "Success"; got != want {
|
||||||
t.Errorf("apiResp.Status: %v; want %v", got, want)
|
t.Errorf("apiResp.Status: %v; want %v", got, want)
|
||||||
}
|
}
|
||||||
|
|
||||||
if got, want := apiResp.Code, 200; got != want {
|
if got, want := apiResp.Code, 200; got != want {
|
||||||
t.Errorf("apiResp.Status: %v; want %v", got, want)
|
t.Errorf("apiResp.Status: %v; want %v", got, want)
|
||||||
}
|
}
|
||||||
@@ -1385,7 +1289,6 @@ func TestH1APIBackendconfigBadMethod(t *testing.T) {
|
|||||||
},
|
},
|
||||||
connectPort: 3010,
|
connectPort: 3010,
|
||||||
}
|
}
|
||||||
|
|
||||||
st := newServerTester(t, opts)
|
st := newServerTester(t, opts)
|
||||||
defer st.Close()
|
defer st.Close()
|
||||||
|
|
||||||
@@ -1401,21 +1304,18 @@ backend=127.0.0.1,3011
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Error st.http1() = %v", err)
|
t.Fatalf("Error st.http1() = %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if got, want := res.status, http.StatusMethodNotAllowed; got != want {
|
if got, want := res.status, http.StatusMethodNotAllowed; got != want {
|
||||||
t.Errorf("res.status: %v; want %v", got, want)
|
t.Errorf("res.status: %v; want %v", got, want)
|
||||||
}
|
}
|
||||||
|
|
||||||
var apiResp APIResponse
|
var apiResp APIResponse
|
||||||
|
err = json.Unmarshal(res.body, &apiResp)
|
||||||
if err := json.Unmarshal(res.body, &apiResp); err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Error unmarshaling API response: %v", err)
|
t.Fatalf("Error unmarshaling API response: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if got, want := apiResp.Status, "Failure"; got != want {
|
if got, want := apiResp.Status, "Failure"; got != want {
|
||||||
t.Errorf("apiResp.Status: %v; want %v", got, want)
|
t.Errorf("apiResp.Status: %v; want %v", got, want)
|
||||||
}
|
}
|
||||||
|
|
||||||
if got, want := apiResp.Code, 405; got != want {
|
if got, want := apiResp.Code, 405; got != want {
|
||||||
t.Errorf("apiResp.Status: %v; want %v", got, want)
|
t.Errorf("apiResp.Status: %v; want %v", got, want)
|
||||||
}
|
}
|
||||||
@@ -1430,7 +1330,6 @@ func TestH1APIConfigrevision(t *testing.T) {
|
|||||||
},
|
},
|
||||||
connectPort: 3010,
|
connectPort: 3010,
|
||||||
}
|
}
|
||||||
|
|
||||||
st := newServerTester(t, opts)
|
st := newServerTester(t, opts)
|
||||||
defer st.Close()
|
defer st.Close()
|
||||||
|
|
||||||
@@ -1442,28 +1341,23 @@ func TestH1APIConfigrevision(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Error st.http1() = %v", err)
|
t.Fatalf("Error st.http1() = %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if got, want := res.status, http.StatusOK; got != want {
|
if got, want := res.status, http.StatusOK; got != want {
|
||||||
t.Errorf("res.status: %v; want = %v", got, want)
|
t.Errorf("res.status: %v; want = %v", got, want)
|
||||||
}
|
}
|
||||||
|
|
||||||
var apiResp APIResponse
|
var apiResp APIResponse
|
||||||
|
|
||||||
d := json.NewDecoder(bytes.NewBuffer(res.body))
|
d := json.NewDecoder(bytes.NewBuffer(res.body))
|
||||||
d.UseNumber()
|
d.UseNumber()
|
||||||
|
err = d.Decode(&apiResp)
|
||||||
if err := d.Decode(&apiResp); err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Error unmarshalling API response: %v", err)
|
t.Fatalf("Error unmarshalling API response: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if got, want := apiResp.Status, "Success"; got != want {
|
if got, want := apiResp.Status, "Success"; got != want {
|
||||||
t.Errorf("apiResp.Status: %v; want %v", got, want)
|
t.Errorf("apiResp.Status: %v; want %v", got, want)
|
||||||
}
|
}
|
||||||
|
|
||||||
if got, want := apiResp.Code, 200; got != want {
|
if got, want := apiResp.Code, 200; got != want {
|
||||||
t.Errorf("apiResp.Status: %v; want %v", got, want)
|
t.Errorf("apiResp.Status: %v; want %v", got, want)
|
||||||
}
|
}
|
||||||
|
|
||||||
if got, want := apiResp.Data["configRevision"], json.Number("0"); 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)
|
t.Errorf(`apiResp.Data["configRevision"]: %v %t; want %v`, got, got, want)
|
||||||
}
|
}
|
||||||
@@ -1479,7 +1373,6 @@ func TestH1APINotFound(t *testing.T) {
|
|||||||
},
|
},
|
||||||
connectPort: 3010,
|
connectPort: 3010,
|
||||||
}
|
}
|
||||||
|
|
||||||
st := newServerTester(t, opts)
|
st := newServerTester(t, opts)
|
||||||
defer st.Close()
|
defer st.Close()
|
||||||
|
|
||||||
@@ -1495,21 +1388,18 @@ backend=127.0.0.1,3011
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Error st.http1() = %v", err)
|
t.Fatalf("Error st.http1() = %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if got, want := res.status, http.StatusNotFound; got != want {
|
if got, want := res.status, http.StatusNotFound; got != want {
|
||||||
t.Errorf("res.status: %v; want %v", got, want)
|
t.Errorf("res.status: %v; want %v", got, want)
|
||||||
}
|
}
|
||||||
|
|
||||||
var apiResp APIResponse
|
var apiResp APIResponse
|
||||||
|
err = json.Unmarshal(res.body, &apiResp)
|
||||||
if err := json.Unmarshal(res.body, &apiResp); err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Error unmarshaling API response: %v", err)
|
t.Fatalf("Error unmarshaling API response: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if got, want := apiResp.Status, "Failure"; got != want {
|
if got, want := apiResp.Status, "Failure"; got != want {
|
||||||
t.Errorf("apiResp.Status: %v; want %v", got, want)
|
t.Errorf("apiResp.Status: %v; want %v", got, want)
|
||||||
}
|
}
|
||||||
|
|
||||||
if got, want := apiResp.Code, 404; got != want {
|
if got, want := apiResp.Code, 404; got != want {
|
||||||
t.Errorf("apiResp.Status: %v; want %v", got, want)
|
t.Errorf("apiResp.Status: %v; want %v", got, want)
|
||||||
}
|
}
|
||||||
@@ -1524,7 +1414,6 @@ func TestH1Healthmon(t *testing.T) {
|
|||||||
},
|
},
|
||||||
connectPort: 3011,
|
connectPort: 3011,
|
||||||
}
|
}
|
||||||
|
|
||||||
st := newServerTester(t, opts)
|
st := newServerTester(t, opts)
|
||||||
defer st.Close()
|
defer st.Close()
|
||||||
|
|
||||||
@@ -1535,7 +1424,6 @@ func TestH1Healthmon(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Error st.http1() = %v", err)
|
t.Fatalf("Error st.http1() = %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if got, want := res.status, http.StatusOK; got != want {
|
if got, want := res.status, http.StatusOK; got != want {
|
||||||
t.Errorf("res.status: %v; want %v", 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")
|
t.Fatal("request should not be forwarded")
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
st := newServerTester(t, opts)
|
st := newServerTester(t, opts)
|
||||||
defer st.Close()
|
defer st.Close()
|
||||||
|
|
||||||
@@ -1593,7 +1480,6 @@ func TestH1H1ChunkedEndsPrematurely(t *testing.T) {
|
|||||||
bufrw.Flush()
|
bufrw.Flush()
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
st := newServerTester(t, opts)
|
st := newServerTester(t, opts)
|
||||||
defer st.Close()
|
defer st.Close()
|
||||||
|
|
||||||
@@ -1613,7 +1499,6 @@ func TestH1H1RequestMalformedTransferEncoding(t *testing.T) {
|
|||||||
t.Errorf("server should not forward bad request")
|
t.Errorf("server should not forward bad request")
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
st := newServerTester(t, opts)
|
st := newServerTester(t, opts)
|
||||||
defer st.Close()
|
defer st.Close()
|
||||||
|
|
||||||
@@ -1656,7 +1541,6 @@ func TestH1H1ResponseMalformedTransferEncoding(t *testing.T) {
|
|||||||
bufrw.Flush()
|
bufrw.Flush()
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
st := newServerTester(t, opts)
|
st := newServerTester(t, opts)
|
||||||
defer st.Close()
|
defer st.Close()
|
||||||
|
|
||||||
@@ -1666,7 +1550,6 @@ func TestH1H1ResponseMalformedTransferEncoding(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Error st.http1() = %v", err)
|
t.Fatalf("Error st.http1() = %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if got, want := res.status, http.StatusBadGateway; got != want {
|
if got, want := res.status, http.StatusBadGateway; got != want {
|
||||||
t.Errorf("res.status: %v; want %v", got, want)
|
t.Errorf("res.status: %v; want %v", got, want)
|
||||||
}
|
}
|
||||||
@@ -1694,7 +1577,6 @@ func TestH1H1ResponseUnknownTransferEncoding(t *testing.T) {
|
|||||||
bufrw.Flush()
|
bufrw.Flush()
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
st := newServerTester(t, opts)
|
st := newServerTester(t, opts)
|
||||||
defer st.Close()
|
defer st.Close()
|
||||||
|
|
||||||
@@ -1729,7 +1611,6 @@ func TestH1H1RequestHTTP10TransferEncoding(t *testing.T) {
|
|||||||
t.Errorf("server should not forward bad request")
|
t.Errorf("server should not forward bad request")
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
st := newServerTester(t, opts)
|
st := newServerTester(t, opts)
|
||||||
defer st.Close()
|
defer st.Close()
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -5,7 +5,6 @@ package nghttp2
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"errors"
|
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"regexp"
|
"regexp"
|
||||||
@@ -36,7 +35,6 @@ func TestH3H1PlainGET(t *testing.T) {
|
|||||||
// TestH3H1RequestBody tests HTTP/3 request with body works.
|
// TestH3H1RequestBody tests HTTP/3 request with body works.
|
||||||
func TestH3H1RequestBody(t *testing.T) {
|
func TestH3H1RequestBody(t *testing.T) {
|
||||||
body := make([]byte, 3333)
|
body := make([]byte, 3333)
|
||||||
|
|
||||||
_, err := rand.Read(body)
|
_, err := rand.Read(body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Unable to create request body: %v", err)
|
t.Fatalf("Unable to create request body: %v", err)
|
||||||
@@ -59,7 +57,7 @@ func TestH3H1RequestBody(t *testing.T) {
|
|||||||
buflen += n
|
buflen += n
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Is(err, io.EOF) {
|
if err == io.EOF {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -75,7 +73,6 @@ func TestH3H1RequestBody(t *testing.T) {
|
|||||||
},
|
},
|
||||||
quic: true,
|
quic: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
st := newServerTester(t, opts)
|
st := newServerTester(t, opts)
|
||||||
defer st.Close()
|
defer st.Close()
|
||||||
|
|
||||||
@@ -86,7 +83,6 @@ func TestH3H1RequestBody(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Error st.http3() = %v", err)
|
t.Fatalf("Error st.http3() = %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if got, want := res.status, http.StatusOK; got != want {
|
if got, want := res.status, http.StatusOK; got != want {
|
||||||
t.Errorf("res.status: %v; want %v", got, want)
|
t.Errorf("res.status: %v; want %v", got, want)
|
||||||
}
|
}
|
||||||
@@ -103,7 +99,6 @@ func TestH3H1GenerateVia(t *testing.T) {
|
|||||||
},
|
},
|
||||||
quic: true,
|
quic: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
st := newServerTester(t, opts)
|
st := newServerTester(t, opts)
|
||||||
defer st.Close()
|
defer st.Close()
|
||||||
|
|
||||||
@@ -113,7 +108,6 @@ func TestH3H1GenerateVia(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Error st.http3() = %v", err)
|
t.Fatalf("Error st.http3() = %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if got, want := res.header.Get("Via"), "1.1 nghttpx"; got != want {
|
if got, want := res.header.Get("Via"), "1.1 nghttpx"; got != want {
|
||||||
t.Errorf("Via: %v; want %v", got, want)
|
t.Errorf("Via: %v; want %v", got, want)
|
||||||
}
|
}
|
||||||
@@ -131,7 +125,6 @@ func TestH3H1AppendVia(t *testing.T) {
|
|||||||
},
|
},
|
||||||
quic: true,
|
quic: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
st := newServerTester(t, opts)
|
st := newServerTester(t, opts)
|
||||||
defer st.Close()
|
defer st.Close()
|
||||||
|
|
||||||
@@ -144,7 +137,6 @@ func TestH3H1AppendVia(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Error st.http3() = %v", err)
|
t.Fatalf("Error st.http3() = %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if got, want := res.header.Get("Via"), "bar, 1.1 nghttpx"; got != want {
|
if got, want := res.header.Get("Via"), "bar, 1.1 nghttpx"; got != want {
|
||||||
t.Errorf("Via: %v; want %v", got, want)
|
t.Errorf("Via: %v; want %v", got, want)
|
||||||
}
|
}
|
||||||
@@ -163,7 +155,6 @@ func TestH3H1NoVia(t *testing.T) {
|
|||||||
},
|
},
|
||||||
quic: true,
|
quic: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
st := newServerTester(t, opts)
|
st := newServerTester(t, opts)
|
||||||
defer st.Close()
|
defer st.Close()
|
||||||
|
|
||||||
@@ -176,7 +167,6 @@ func TestH3H1NoVia(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Error st.http3() = %v", err)
|
t.Fatalf("Error st.http3() = %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if got, want := res.header.Get("Via"), "bar"; got != want {
|
if got, want := res.header.Get("Via"), "bar"; got != want {
|
||||||
t.Errorf("Via: %v; want %v", got, want)
|
t.Errorf("Via: %v; want %v", got, want)
|
||||||
}
|
}
|
||||||
@@ -196,7 +186,6 @@ func TestH3H1BadResponseCL(t *testing.T) {
|
|||||||
},
|
},
|
||||||
quic: true,
|
quic: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
st := newServerTester(t, opts)
|
st := newServerTester(t, opts)
|
||||||
defer st.Close()
|
defer st.Close()
|
||||||
|
|
||||||
@@ -215,7 +204,6 @@ func TestH3H1HTTPSRedirect(t *testing.T) {
|
|||||||
args: []string{"--redirect-if-not-tls"},
|
args: []string{"--redirect-if-not-tls"},
|
||||||
quic: true,
|
quic: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
st := newServerTester(t, opts)
|
st := newServerTester(t, opts)
|
||||||
defer st.Close()
|
defer st.Close()
|
||||||
|
|
||||||
@@ -238,7 +226,6 @@ func TestH3H1AffinityCookieTLS(t *testing.T) {
|
|||||||
args: []string{"--affinity-cookie"},
|
args: []string{"--affinity-cookie"},
|
||||||
quic: true,
|
quic: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
st := newServerTester(t, opts)
|
st := newServerTester(t, opts)
|
||||||
defer st.Close()
|
defer st.Close()
|
||||||
|
|
||||||
@@ -256,7 +243,6 @@ func TestH3H1AffinityCookieTLS(t *testing.T) {
|
|||||||
|
|
||||||
const pattern = `affinity=[0-9a-f]{8}; Path=/foo/bar; Secure`
|
const pattern = `affinity=[0-9a-f]{8}; Path=/foo/bar; Secure`
|
||||||
validCookie := regexp.MustCompile(pattern)
|
validCookie := regexp.MustCompile(pattern)
|
||||||
|
|
||||||
if got := res.header.Get("Set-Cookie"); !validCookie.MatchString(got) {
|
if got := res.header.Get("Set-Cookie"); !validCookie.MatchString(got) {
|
||||||
t.Errorf("Set-Cookie: %v; want pattern %v", got, pattern)
|
t.Errorf("Set-Cookie: %v; want pattern %v", got, pattern)
|
||||||
}
|
}
|
||||||
@@ -275,7 +261,6 @@ func TestH3H2ReqPhaseReturn(t *testing.T) {
|
|||||||
},
|
},
|
||||||
quic: true,
|
quic: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
st := newServerTester(t, opts)
|
st := newServerTester(t, opts)
|
||||||
defer st.Close()
|
defer st.Close()
|
||||||
|
|
||||||
@@ -317,7 +302,6 @@ func TestH3H2RespPhaseReturn(t *testing.T) {
|
|||||||
},
|
},
|
||||||
quic: true,
|
quic: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
st := newServerTester(t, opts)
|
st := newServerTester(t, opts)
|
||||||
defer st.Close()
|
defer st.Close()
|
||||||
|
|
||||||
@@ -359,7 +343,6 @@ func TestH3ResponseBeforeRequestEnd(t *testing.T) {
|
|||||||
},
|
},
|
||||||
quic: true,
|
quic: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
st := newServerTester(t, opts)
|
st := newServerTester(t, opts)
|
||||||
defer st.Close()
|
defer st.Close()
|
||||||
|
|
||||||
@@ -370,7 +353,6 @@ func TestH3ResponseBeforeRequestEnd(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Error st.http3() = %v", err)
|
t.Fatalf("Error st.http3() = %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if got, want := res.status, http.StatusNotFound; got != want {
|
if got, want := res.status, http.StatusNotFound; got != want {
|
||||||
t.Errorf("res.status: %v; want %v", got, want)
|
t.Errorf("res.status: %v; want %v", got, want)
|
||||||
}
|
}
|
||||||
@@ -399,7 +381,6 @@ func TestH3H1ChunkedEndsPrematurely(t *testing.T) {
|
|||||||
},
|
},
|
||||||
quic: true,
|
quic: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
st := newServerTester(t, opts)
|
st := newServerTester(t, opts)
|
||||||
defer st.Close()
|
defer st.Close()
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ package nghttp2
|
|||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"bytes"
|
"bytes"
|
||||||
"cmp"
|
|
||||||
"context"
|
"context"
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
@@ -16,7 +15,7 @@ import (
|
|||||||
"net/url"
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"slices"
|
"sort"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"syscall"
|
"syscall"
|
||||||
@@ -95,17 +94,14 @@ func newServerTester(t *testing.T, opts options) *serverTester {
|
|||||||
if opts.handler == nil {
|
if opts.handler == nil {
|
||||||
opts.handler = noopHandler
|
opts.handler = noopHandler
|
||||||
}
|
}
|
||||||
|
|
||||||
if opts.connectPort == 0 {
|
if opts.connectPort == 0 {
|
||||||
opts.connectPort = serverPort
|
opts.connectPort = serverPort
|
||||||
}
|
}
|
||||||
|
|
||||||
ts := httptest.NewUnstartedServer(opts.handler)
|
ts := httptest.NewUnstartedServer(opts.handler)
|
||||||
|
|
||||||
var (
|
var args []string
|
||||||
args []string
|
var backendTLS, dns, externalDNS, acceptProxyProtocol, redirectIfNotTLS, affinityCookie, alpnH1 bool
|
||||||
backendTLS, dns, externalDNS, acceptProxyProtocol, redirectIfNotTLS, affinityCookie, alpnH1 bool
|
|
||||||
)
|
|
||||||
|
|
||||||
for _, k := range opts.args {
|
for _, k := range opts.args {
|
||||||
switch k {
|
switch k {
|
||||||
@@ -128,7 +124,6 @@ func newServerTester(t *testing.T, opts options) *serverTester {
|
|||||||
args = append(args, k)
|
args = append(args, k)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if backendTLS {
|
if backendTLS {
|
||||||
nghttp2.ConfigureServer(ts.Config, &nghttp2.Server{})
|
nghttp2.ConfigureServer(ts.Config, &nghttp2.Server{})
|
||||||
// According to httptest/server.go, we have to set
|
// 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 = new(tls.Config)
|
||||||
ts.TLS.NextProtos = append(ts.TLS.NextProtos, "h2")
|
ts.TLS.NextProtos = append(ts.TLS.NextProtos, "h2")
|
||||||
ts.StartTLS()
|
ts.StartTLS()
|
||||||
|
|
||||||
args = append(args, "-k")
|
args = append(args, "-k")
|
||||||
} else {
|
} else {
|
||||||
ts.Start()
|
ts.Start()
|
||||||
}
|
}
|
||||||
|
|
||||||
scheme := "http"
|
scheme := "http"
|
||||||
|
|
||||||
if opts.tls {
|
if opts.tls {
|
||||||
scheme = "https"
|
scheme = "https"
|
||||||
|
|
||||||
args = append(args, testDir+"/server.key", testDir+"/server.crt")
|
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
|
// URL.Host looks like "127.0.0.1:8080", but we want
|
||||||
// "127.0.0.1,8080"
|
// "127.0.0.1,8080"
|
||||||
b := "-b"
|
b := "-b"
|
||||||
|
|
||||||
if !externalDNS {
|
if !externalDNS {
|
||||||
b += fmt.Sprintf("%v;", strings.ReplaceAll(backendURL.Host, ":", ","))
|
b += fmt.Sprintf("%v;", strings.Replace(backendURL.Host, ":", ",", -1))
|
||||||
} else {
|
} else {
|
||||||
sep := strings.LastIndex(backendURL.Host, ":")
|
sep := strings.LastIndex(backendURL.Host, ":")
|
||||||
if sep == -1 {
|
if sep == -1 {
|
||||||
t.Fatalf("backendURL.Host %v does not contain separator ':'", backendURL.Host)
|
t.Fatalf("backendURL.Host %v does not contain separator ':'", backendURL.Host)
|
||||||
}
|
}
|
||||||
|
|
||||||
// We use awesome service nip.io.
|
// We use awesome service nip.io.
|
||||||
b += fmt.Sprintf("%v.nip.io,%v;", backendURL.Host[:sep], backendURL.Host[sep+1:])
|
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 {
|
if backendTLS {
|
||||||
b += ";proto=h2;tls"
|
b += ";proto=h2;tls"
|
||||||
}
|
}
|
||||||
|
|
||||||
if dns {
|
if dns {
|
||||||
b += ";dns"
|
b += ";dns"
|
||||||
}
|
}
|
||||||
@@ -191,13 +177,11 @@ func newServerTester(t *testing.T, opts options) *serverTester {
|
|||||||
}
|
}
|
||||||
|
|
||||||
noTLS := ";no-tls"
|
noTLS := ";no-tls"
|
||||||
|
|
||||||
if opts.tls {
|
if opts.tls {
|
||||||
noTLS = ""
|
noTLS = ""
|
||||||
}
|
}
|
||||||
|
|
||||||
var proxyProto string
|
var proxyProto string
|
||||||
|
|
||||||
if acceptProxyProtocol {
|
if acceptProxyProtocol {
|
||||||
proxyProto = ";proxyproto"
|
proxyProto = ";proxyproto"
|
||||||
}
|
}
|
||||||
@@ -208,19 +192,7 @@ func newServerTester(t *testing.T, opts options) *serverTester {
|
|||||||
if opts.quic {
|
if opts.quic {
|
||||||
args = append(args,
|
args = append(args,
|
||||||
fmt.Sprintf("-f127.0.0.1,%v;quic", serverPort),
|
fmt.Sprintf("-f127.0.0.1,%v;quic", serverPort),
|
||||||
"--no-quic-bpf",
|
"--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",
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
authority := fmt.Sprintf("127.0.0.1:%v", opts.connectPort)
|
authority := fmt.Sprintf("127.0.0.1:%v", opts.connectPort)
|
||||||
@@ -246,7 +218,6 @@ func newServerTester(t *testing.T, opts options) *serverTester {
|
|||||||
}
|
}
|
||||||
|
|
||||||
retry := 0
|
retry := 0
|
||||||
|
|
||||||
for {
|
for {
|
||||||
time.Sleep(50 * time.Millisecond)
|
time.Sleep(50 * time.Millisecond)
|
||||||
|
|
||||||
@@ -260,41 +231,32 @@ func newServerTester(t *testing.T, opts options) *serverTester {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var tlsConfig *tls.Config
|
var tlsConfig *tls.Config
|
||||||
|
|
||||||
if opts.tlsConfig == nil {
|
if opts.tlsConfig == nil {
|
||||||
tlsConfig = new(tls.Config)
|
tlsConfig = new(tls.Config)
|
||||||
} else {
|
} else {
|
||||||
tlsConfig = opts.tlsConfig.Clone()
|
tlsConfig = opts.tlsConfig.Clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
tlsConfig.InsecureSkipVerify = true
|
tlsConfig.InsecureSkipVerify = true
|
||||||
|
|
||||||
if alpnH1 {
|
if alpnH1 {
|
||||||
tlsConfig.NextProtos = []string{"http/1.1"}
|
tlsConfig.NextProtos = []string{"http/1.1"}
|
||||||
} else {
|
} else {
|
||||||
tlsConfig.NextProtos = []string{"h2"}
|
tlsConfig.NextProtos = []string{"h2"}
|
||||||
}
|
}
|
||||||
|
|
||||||
tlsConn := tls.Client(conn, tlsConfig)
|
tlsConn := tls.Client(conn, tlsConfig)
|
||||||
|
|
||||||
err = tlsConn.Handshake()
|
err = tlsConn.Handshake()
|
||||||
if err == nil {
|
if err == nil {
|
||||||
conn = tlsConn
|
conn = tlsConn
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
retry++
|
retry++
|
||||||
if retry >= 100 {
|
if retry >= 100 {
|
||||||
st.Close()
|
st.Close()
|
||||||
st.t.Fatalf("Error server is not responding too long; server command-line arguments may be invalid")
|
st.t.Fatalf("Error server is not responding too long; server command-line arguments may be invalid")
|
||||||
}
|
}
|
||||||
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
st.conn = conn
|
st.conn = conn
|
||||||
|
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -311,15 +273,12 @@ func (st *serverTester) Close() {
|
|||||||
if st.conn != nil {
|
if st.conn != nil {
|
||||||
st.conn.Close()
|
st.conn.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
if st.cmd != nil {
|
if st.cmd != nil {
|
||||||
done := make(chan struct{})
|
done := make(chan struct{})
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
if err := st.cmd.Wait(); err != nil {
|
if err := st.cmd.Wait(); err != nil {
|
||||||
st.t.Errorf("Error st.cmd.Wait() = %v", err)
|
st.t.Errorf("Error st.cmd.Wait() = %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
close(done)
|
close(done)
|
||||||
}()
|
}()
|
||||||
|
|
||||||
@@ -333,11 +292,9 @@ func (st *serverTester) Close() {
|
|||||||
if err := st.cmd.Process.Kill(); err != nil {
|
if err := st.cmd.Process.Kill(); err != nil {
|
||||||
st.t.Errorf("Error st.cmd.Process.Kill() = %v", err)
|
st.t.Errorf("Error st.cmd.Process.Kill() = %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
<-done
|
<-done
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if st.ts != nil {
|
if st.ts != nil {
|
||||||
st.ts.Close()
|
st.ts.Close()
|
||||||
}
|
}
|
||||||
@@ -350,7 +307,6 @@ func (st *serverTester) readFrame() (http2.Frame, error) {
|
|||||||
st.errCh <- err
|
st.errCh <- err
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
st.frCh <- f
|
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.
|
// after request was sent and before body returns EOF.
|
||||||
if !cbr.trailerWritten {
|
if !cbr.trailerWritten {
|
||||||
cbr.trailerWritten = true
|
cbr.trailerWritten = true
|
||||||
|
|
||||||
for _, h := range cbr.trailer {
|
for _, h := range cbr.trailer {
|
||||||
cbr.req.Trailer.Set(h.Name, h.Value)
|
cbr.req.Trailer.Set(h.Name, h.Value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return cbr.body.Read(p)
|
return cbr.body.Read(p)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -409,7 +363,6 @@ func (st *serverTester) websocket(rp requestParam) *serverResponse {
|
|||||||
}
|
}
|
||||||
|
|
||||||
config.Header.Add("Test-Case", rp.name)
|
config.Header.Add("Test-Case", rp.name)
|
||||||
|
|
||||||
for _, h := range rp.header {
|
for _, h := range rp.header {
|
||||||
config.Header.Add(h.Name, h.Value)
|
config.Header.Add(h.Name, h.Value)
|
||||||
}
|
}
|
||||||
@@ -424,9 +377,7 @@ func (st *serverTester) websocket(rp requestParam) *serverResponse {
|
|||||||
}
|
}
|
||||||
|
|
||||||
msg := make([]byte, 1024)
|
msg := make([]byte, 1024)
|
||||||
|
|
||||||
var n int
|
var n int
|
||||||
|
|
||||||
if n, err = ws.Read(msg); err != nil {
|
if n, err = ws.Read(msg); err != nil {
|
||||||
st.t.Fatalf("ws.Read() returned error: %v", err)
|
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) {
|
func (st *serverTester) http1(rp requestParam) (*serverResponse, error) {
|
||||||
method := "GET"
|
method := "GET"
|
||||||
|
|
||||||
if rp.method != "" {
|
if rp.method != "" {
|
||||||
method = rp.method
|
method = rp.method
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var body io.Reader
|
||||||
body io.Reader
|
var cbr *chunkedBodyReader
|
||||||
cbr *chunkedBodyReader
|
|
||||||
)
|
|
||||||
|
|
||||||
if rp.body != nil {
|
if rp.body != nil {
|
||||||
body = bytes.NewBuffer(rp.body)
|
body = bytes.NewBuffer(rp.body)
|
||||||
|
|
||||||
if len(rp.trailer) != 0 {
|
if len(rp.trailer) != 0 {
|
||||||
cbr = &chunkedBodyReader{
|
cbr = &chunkedBodyReader{
|
||||||
trailer: rp.trailer,
|
trailer: rp.trailer,
|
||||||
body: body,
|
body: body,
|
||||||
}
|
}
|
||||||
|
|
||||||
body = cbr
|
body = cbr
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -470,7 +415,6 @@ func (st *serverTester) http1(rp requestParam) (*serverResponse, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
st.t.Fatalf("Error parsing URL from st.url %v: %v", st.url, err)
|
st.t.Fatalf("Error parsing URL from st.url %v: %v", st.url, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
u.Path = ""
|
u.Path = ""
|
||||||
u.RawQuery = ""
|
u.RawQuery = ""
|
||||||
reqURL = u.String() + rp.path
|
reqURL = u.String() + rp.path
|
||||||
@@ -483,38 +427,30 @@ func (st *serverTester) http1(rp requestParam) (*serverResponse, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, h := range rp.header {
|
for _, h := range rp.header {
|
||||||
req.Header.Add(h.Name, h.Value)
|
req.Header.Add(h.Name, h.Value)
|
||||||
}
|
}
|
||||||
|
|
||||||
req.Header.Add("Test-Case", rp.name)
|
req.Header.Add("Test-Case", rp.name)
|
||||||
|
|
||||||
if cbr != nil {
|
if cbr != nil {
|
||||||
cbr.req = req
|
cbr.req = req
|
||||||
// this makes request use chunked encoding
|
// this makes request use chunked encoding
|
||||||
req.ContentLength = -1
|
req.ContentLength = -1
|
||||||
req.Trailer = make(http.Header)
|
req.Trailer = make(http.Header)
|
||||||
|
|
||||||
for _, h := range cbr.trailer {
|
for _, h := range cbr.trailer {
|
||||||
req.Trailer.Set(h.Name, "")
|
req.Trailer.Set(h.Name, "")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := req.Write(st.conn); err != nil {
|
if err := req.Write(st.conn); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
resp, err := http.ReadResponse(bufio.NewReader(st.conn), req)
|
resp, err := http.ReadResponse(bufio.NewReader(st.conn), req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
respBody, err := io.ReadAll(resp.Body)
|
respBody, err := io.ReadAll(resp.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
resp.Body.Close()
|
resp.Body.Close()
|
||||||
|
|
||||||
res := &serverResponse{
|
res := &serverResponse{
|
||||||
@@ -532,7 +468,6 @@ func (st *serverTester) http2(rp requestParam) (*serverResponse, error) {
|
|||||||
st.header = make(http.Header)
|
st.header = make(http.Header)
|
||||||
|
|
||||||
var id uint32
|
var id uint32
|
||||||
|
|
||||||
if rp.streamID != 0 {
|
if rp.streamID != 0 {
|
||||||
id = rp.streamID
|
id = rp.streamID
|
||||||
if id >= st.nextStreamID && id%2 == 1 {
|
if id >= st.nextStreamID && id%2 == 1 {
|
||||||
@@ -546,7 +481,6 @@ func (st *serverTester) http2(rp requestParam) (*serverResponse, error) {
|
|||||||
if !st.h2PrefaceSent {
|
if !st.h2PrefaceSent {
|
||||||
st.h2PrefaceSent = true
|
st.h2PrefaceSent = true
|
||||||
fmt.Fprint(st.conn, "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n")
|
fmt.Fprint(st.conn, "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n")
|
||||||
|
|
||||||
if err := st.fr.WriteSettings(); err != nil {
|
if err := st.fr.WriteSettings(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -564,32 +498,26 @@ func (st *serverTester) http2(rp requestParam) (*serverResponse, error) {
|
|||||||
if rp.method != "" {
|
if rp.method != "" {
|
||||||
method = rp.method
|
method = rp.method
|
||||||
}
|
}
|
||||||
|
|
||||||
_ = st.enc.WriteField(pair(":method", method))
|
_ = st.enc.WriteField(pair(":method", method))
|
||||||
|
|
||||||
scheme := "http"
|
scheme := "http"
|
||||||
|
|
||||||
if rp.scheme != "" {
|
if rp.scheme != "" {
|
||||||
scheme = rp.scheme
|
scheme = rp.scheme
|
||||||
}
|
}
|
||||||
|
|
||||||
_ = st.enc.WriteField(pair(":scheme", scheme))
|
_ = st.enc.WriteField(pair(":scheme", scheme))
|
||||||
|
|
||||||
authority := st.authority
|
authority := st.authority
|
||||||
|
|
||||||
if rp.authority != "" {
|
if rp.authority != "" {
|
||||||
authority = rp.authority
|
authority = rp.authority
|
||||||
}
|
}
|
||||||
|
|
||||||
_ = st.enc.WriteField(pair(":authority", authority))
|
_ = st.enc.WriteField(pair(":authority", authority))
|
||||||
|
|
||||||
path := "/"
|
path := "/"
|
||||||
|
|
||||||
if rp.path != "" {
|
if rp.path != "" {
|
||||||
path = rp.path
|
path = rp.path
|
||||||
}
|
}
|
||||||
|
|
||||||
_ = st.enc.WriteField(pair(":path", path))
|
_ = st.enc.WriteField(pair(":path", path))
|
||||||
|
|
||||||
_ = st.enc.WriteField(pair("test-case", rp.name))
|
_ = st.enc.WriteField(pair("test-case", rp.name))
|
||||||
|
|
||||||
for _, h := range rp.header {
|
for _, h := range rp.header {
|
||||||
@@ -615,11 +543,9 @@ func (st *serverTester) http2(rp requestParam) (*serverResponse, error) {
|
|||||||
|
|
||||||
if len(rp.trailer) != 0 {
|
if len(rp.trailer) != 0 {
|
||||||
st.headerBlkBuf.Reset()
|
st.headerBlkBuf.Reset()
|
||||||
|
|
||||||
for _, h := range rp.trailer {
|
for _, h := range rp.trailer {
|
||||||
_ = st.enc.WriteField(h)
|
_ = st.enc.WriteField(h)
|
||||||
}
|
}
|
||||||
|
|
||||||
err := st.fr.WriteHeaders(http2.HeadersFrameParam{
|
err := st.fr.WriteHeaders(http2.HeadersFrameParam{
|
||||||
StreamID: id,
|
StreamID: id,
|
||||||
EndStream: true,
|
EndStream: true,
|
||||||
@@ -637,65 +563,56 @@ loop:
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return res, err
|
return res, err
|
||||||
}
|
}
|
||||||
|
|
||||||
switch f := fr.(type) {
|
switch f := fr.(type) {
|
||||||
case *http2.HeadersFrame:
|
case *http2.HeadersFrame:
|
||||||
_, err := st.dec.Write(f.HeaderBlockFragment())
|
_, err := st.dec.Write(f.HeaderBlockFragment())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return res, err
|
return res, err
|
||||||
}
|
}
|
||||||
|
sr, ok := streams[f.FrameHeader.StreamID]
|
||||||
sr, ok := streams[f.StreamID]
|
|
||||||
if !ok {
|
if !ok {
|
||||||
st.header = make(http.Header)
|
st.header = make(http.Header)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
sr.header = cloneHeader(st.header)
|
sr.header = cloneHeader(st.header)
|
||||||
|
|
||||||
var status int
|
var status int
|
||||||
|
|
||||||
status, err = strconv.Atoi(sr.header.Get(":status"))
|
status, err = strconv.Atoi(sr.header.Get(":status"))
|
||||||
if err != nil {
|
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
|
sr.status = status
|
||||||
|
if f.StreamEnded() {
|
||||||
if f.StreamEnded() && streamEnded(res, streams, sr) {
|
if streamEnded(res, streams, sr) {
|
||||||
break loop
|
break loop
|
||||||
|
}
|
||||||
}
|
}
|
||||||
case *http2.PushPromiseFrame:
|
case *http2.PushPromiseFrame:
|
||||||
_, err := st.dec.Write(f.HeaderBlockFragment())
|
_, err := st.dec.Write(f.HeaderBlockFragment())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return res, err
|
return res, err
|
||||||
}
|
}
|
||||||
|
|
||||||
sr := &serverResponse{
|
sr := &serverResponse{
|
||||||
streamID: f.PromiseID,
|
streamID: f.PromiseID,
|
||||||
reqHeader: cloneHeader(st.header),
|
reqHeader: cloneHeader(st.header),
|
||||||
}
|
}
|
||||||
|
|
||||||
streams[sr.streamID] = sr
|
streams[sr.streamID] = sr
|
||||||
case *http2.DataFrame:
|
case *http2.DataFrame:
|
||||||
sr, ok := streams[f.StreamID]
|
sr, ok := streams[f.FrameHeader.StreamID]
|
||||||
if !ok {
|
if !ok {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
sr.body = append(sr.body, f.Data()...)
|
sr.body = append(sr.body, f.Data()...)
|
||||||
|
if f.StreamEnded() {
|
||||||
if f.StreamEnded() && streamEnded(res, streams, sr) {
|
if streamEnded(res, streams, sr) {
|
||||||
break loop
|
break loop
|
||||||
|
}
|
||||||
}
|
}
|
||||||
case *http2.RSTStreamFrame:
|
case *http2.RSTStreamFrame:
|
||||||
sr, ok := streams[f.StreamID]
|
sr, ok := streams[f.FrameHeader.StreamID]
|
||||||
if !ok {
|
if !ok {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
sr.errCode = f.ErrCode
|
sr.errCode = f.ErrCode
|
||||||
|
|
||||||
if streamEnded(res, streams, sr) {
|
if streamEnded(res, streams, sr) {
|
||||||
break loop
|
break loop
|
||||||
}
|
}
|
||||||
@@ -703,36 +620,27 @@ loop:
|
|||||||
if f.ErrCode == http2.ErrCodeNo {
|
if f.ErrCode == http2.ErrCodeNo {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
res.errCode = f.ErrCode
|
res.errCode = f.ErrCode
|
||||||
res.connErr = true
|
res.connErr = true
|
||||||
|
|
||||||
break loop
|
break loop
|
||||||
case *http2.SettingsFrame:
|
case *http2.SettingsFrame:
|
||||||
if f.IsAck() {
|
if f.IsAck() {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := st.fr.WriteSettingsAck(); err != nil {
|
if err := st.fr.WriteSettingsAck(); err != nil {
|
||||||
return res, err
|
return res, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
sort.Sort(ByStreamID(res.pushResponse))
|
||||||
slices.SortFunc(res.pushResponse, func(a, b *serverResponse) int {
|
|
||||||
return cmp.Compare(a.streamID, b.streamID)
|
|
||||||
})
|
|
||||||
|
|
||||||
return res, nil
|
return res, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func streamEnded(mainSr *serverResponse, streams map[uint32]*serverResponse, sr *serverResponse) bool {
|
func streamEnded(mainSr *serverResponse, streams map[uint32]*serverResponse, sr *serverResponse) bool {
|
||||||
delete(streams, sr.streamID)
|
delete(streams, sr.streamID)
|
||||||
|
|
||||||
if mainSr.streamID != sr.streamID {
|
if mainSr.streamID != sr.streamID {
|
||||||
mainSr.pushResponse = append(mainSr.pushResponse, sr)
|
mainSr.pushResponse = append(mainSr.pushResponse, sr)
|
||||||
}
|
}
|
||||||
|
|
||||||
return len(streams) == 0
|
return len(streams) == 0
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -748,15 +656,27 @@ type serverResponse struct {
|
|||||||
pushResponse []*serverResponse // pushed response
|
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 {
|
func cloneHeader(h http.Header) http.Header {
|
||||||
h2 := make(http.Header, len(h))
|
h2 := make(http.Header, len(h))
|
||||||
|
|
||||||
for k, vv := range h {
|
for k, vv := range h {
|
||||||
vv2 := make([]string, len(vv))
|
vv2 := make([]string, len(vv))
|
||||||
copy(vv2, vv)
|
copy(vv2, vv)
|
||||||
h2[k] = vv2
|
h2[k] = vv2
|
||||||
}
|
}
|
||||||
|
|
||||||
return h2
|
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 {
|
if _, err := w.Write([]byte{0x0D, 0x0A, 0x0D, 0x0A, 0x00, 0x0D, 0x0A, 0x51, 0x55, 0x49, 0x54, 0x0A}); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err := w.Write([]byte{byte(0x20 | hdr.command)}); err != nil {
|
if _, err := w.Write([]byte{byte(0x20 | hdr.command)}); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -815,59 +734,44 @@ func writeProxyProtocolV2(w io.Writer, hdr proxyProtocolV2) error {
|
|||||||
switch srcAddr := hdr.sourceAddress.(type) {
|
switch srcAddr := hdr.sourceAddress.(type) {
|
||||||
case *net.TCPAddr:
|
case *net.TCPAddr:
|
||||||
dstAddr := hdr.destinationAddress.(*net.TCPAddr)
|
dstAddr := hdr.destinationAddress.(*net.TCPAddr)
|
||||||
|
|
||||||
if len(srcAddr.IP) != len(dstAddr.IP) {
|
if len(srcAddr.IP) != len(dstAddr.IP) {
|
||||||
panic("len(srcAddr.IP) != len(dstAddr.IP)")
|
panic("len(srcAddr.IP) != len(dstAddr.IP)")
|
||||||
}
|
}
|
||||||
|
|
||||||
var fam byte
|
var fam byte
|
||||||
|
|
||||||
if len(srcAddr.IP) == 4 {
|
if len(srcAddr.IP) == 4 {
|
||||||
fam = byte(proxyProtocolV2FamilyInet << 4)
|
fam = byte(proxyProtocolV2FamilyInet << 4)
|
||||||
} else {
|
} else {
|
||||||
fam = byte(proxyProtocolV2FamilyInet6 << 4)
|
fam = byte(proxyProtocolV2FamilyInet6 << 4)
|
||||||
}
|
}
|
||||||
|
|
||||||
fam |= byte(proxyProtocolV2ProtocolStream)
|
fam |= byte(proxyProtocolV2ProtocolStream)
|
||||||
|
|
||||||
if _, err := w.Write([]byte{fam}); err != nil {
|
if _, err := w.Write([]byte{fam}); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
length := uint16(len(srcAddr.IP)*2 + 4 + len(hdr.additionalData))
|
length := uint16(len(srcAddr.IP)*2 + 4 + len(hdr.additionalData))
|
||||||
|
|
||||||
if err := binary.Write(w, binary.BigEndian, length); err != nil {
|
if err := binary.Write(w, binary.BigEndian, length); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err := w.Write(srcAddr.IP); err != nil {
|
if _, err := w.Write(srcAddr.IP); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err := w.Write(dstAddr.IP); err != nil {
|
if _, err := w.Write(dstAddr.IP); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := binary.Write(w, binary.BigEndian, uint16(srcAddr.Port)); err != nil {
|
if err := binary.Write(w, binary.BigEndian, uint16(srcAddr.Port)); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := binary.Write(w, binary.BigEndian, uint16(dstAddr.Port)); err != nil {
|
if err := binary.Write(w, binary.BigEndian, uint16(dstAddr.Port)); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
case *net.UnixAddr:
|
case *net.UnixAddr:
|
||||||
dstAddr := hdr.destinationAddress.(*net.UnixAddr)
|
dstAddr := hdr.destinationAddress.(*net.UnixAddr)
|
||||||
|
|
||||||
if len(srcAddr.Name) > 108 {
|
if len(srcAddr.Name) > 108 {
|
||||||
panic("too long Unix source address")
|
panic("too long Unix source address")
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(dstAddr.Name) > 108 {
|
if len(dstAddr.Name) > 108 {
|
||||||
panic("too long Unix destination address")
|
panic("too long Unix destination address")
|
||||||
}
|
}
|
||||||
|
|
||||||
fam := byte(proxyProtocolV2FamilyUnix << 4)
|
fam := byte(proxyProtocolV2FamilyUnix << 4)
|
||||||
|
|
||||||
switch srcAddr.Net {
|
switch srcAddr.Net {
|
||||||
case "unix":
|
case "unix":
|
||||||
fam |= byte(proxyProtocolV2ProtocolStream)
|
fam |= byte(proxyProtocolV2ProtocolStream)
|
||||||
@@ -876,43 +780,32 @@ func writeProxyProtocolV2(w io.Writer, hdr proxyProtocolV2) error {
|
|||||||
default:
|
default:
|
||||||
fam |= byte(proxyProtocolV2ProtocolUnspec)
|
fam |= byte(proxyProtocolV2ProtocolUnspec)
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err := w.Write([]byte{fam}); err != nil {
|
if _, err := w.Write([]byte{fam}); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
length := uint16(216 + len(hdr.additionalData))
|
length := uint16(216 + len(hdr.additionalData))
|
||||||
|
|
||||||
if err := binary.Write(w, binary.BigEndian, length); err != nil {
|
if err := binary.Write(w, binary.BigEndian, length); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
zeros := make([]byte, 108)
|
zeros := make([]byte, 108)
|
||||||
|
|
||||||
if _, err := w.Write([]byte(srcAddr.Name)); err != nil {
|
if _, err := w.Write([]byte(srcAddr.Name)); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err := w.Write(zeros[:108-len(srcAddr.Name)]); err != nil {
|
if _, err := w.Write(zeros[:108-len(srcAddr.Name)]); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err := w.Write([]byte(dstAddr.Name)); err != nil {
|
if _, err := w.Write([]byte(dstAddr.Name)); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err := w.Write(zeros[:108-len(dstAddr.Name)]); err != nil {
|
if _, err := w.Write(zeros[:108-len(dstAddr.Name)]); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
fam := byte(proxyProtocolV2FamilyUnspec<<4) | byte(proxyProtocolV2ProtocolUnspec)
|
fam := byte(proxyProtocolV2FamilyUnspec<<4) | byte(proxyProtocolV2ProtocolUnspec)
|
||||||
|
|
||||||
if _, err := w.Write([]byte{fam}); err != nil {
|
if _, err := w.Write([]byte{fam}); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
length := uint16(len(hdr.additionalData))
|
length := uint16(len(hdr.additionalData))
|
||||||
|
|
||||||
if err := binary.Write(w, binary.BigEndian, length); err != nil {
|
if err := binary.Write(w, binary.BigEndian, length); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func (st *serverTester) http3(rp requestParam) (*serverResponse, error) {
|
func (st *serverTester) http3(rp requestParam) (*serverResponse, error) {
|
||||||
rt := &http3.Transport{
|
rt := &http3.RoundTripper{
|
||||||
TLSClientConfig: &tls.Config{
|
TLSClientConfig: &tls.Config{
|
||||||
InsecureSkipVerify: true,
|
InsecureSkipVerify: true,
|
||||||
},
|
},
|
||||||
@@ -45,7 +45,6 @@ func (st *serverTester) http3(rp requestParam) (*serverResponse, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
st.t.Fatalf("Error parsing URL from st.url %v: %v", st.url, err)
|
st.t.Fatalf("Error parsing URL from st.url %v: %v", st.url, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
u.Path = ""
|
u.Path = ""
|
||||||
u.RawQuery = ""
|
u.RawQuery = ""
|
||||||
reqURL = u.String() + rp.path
|
reqURL = u.String() + rp.path
|
||||||
|
|||||||
@@ -47,29 +47,7 @@ if(WIN32)
|
|||||||
set(NGHTTP2_RES ${CMAKE_CURRENT_BINARY_DIR}/version.rc)
|
set(NGHTTP2_RES ${CMAKE_CURRENT_BINARY_DIR}/version.rc)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
set(NGHTTP2_GENERATED_DIR "${CMAKE_CURRENT_BINARY_DIR}/generated")
|
set(EXPORT_SET "${PROJECT_NAME}-targets")
|
||||||
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}")
|
|
||||||
|
|
||||||
# Public shared library
|
# Public shared library
|
||||||
if(BUILD_SHARED_LIBS)
|
if(BUILD_SHARED_LIBS)
|
||||||
@@ -87,11 +65,7 @@ if(BUILD_SHARED_LIBS)
|
|||||||
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
|
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
|
||||||
)
|
)
|
||||||
|
|
||||||
install(TARGETS ${SHARED_LIB}
|
install(TARGETS ${SHARED_LIB} EXPORT ${EXPORT_SET})
|
||||||
EXPORT ${NGHTTP2_TARGETS_EXPORT_NAME}
|
|
||||||
ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}"
|
|
||||||
LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}"
|
|
||||||
RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}")
|
|
||||||
list(APPEND nghttp2_exports ${SHARED_LIB})
|
list(APPEND nghttp2_exports ${SHARED_LIB})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
@@ -113,9 +87,7 @@ if(BUILD_STATIC_LIBS)
|
|||||||
|
|
||||||
target_compile_definitions(${STATIC_LIB} PUBLIC "-DNGHTTP2_STATICLIB")
|
target_compile_definitions(${STATIC_LIB} PUBLIC "-DNGHTTP2_STATICLIB")
|
||||||
|
|
||||||
install(TARGETS ${STATIC_LIB}
|
install(TARGETS ${STATIC_LIB} EXPORT ${EXPORT_SET})
|
||||||
EXPORT ${NGHTTP2_TARGETS_EXPORT_NAME}
|
|
||||||
ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}")
|
|
||||||
list(APPEND nghttp2_exports ${STATIC_LIB})
|
list(APPEND nghttp2_exports ${STATIC_LIB})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
@@ -125,7 +97,11 @@ else()
|
|||||||
set(LIB_SELECTED ${STATIC_LIB})
|
set(LIB_SELECTED ${STATIC_LIB})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
add_library(nghttp2 ALIAS ${LIB_SELECTED})
|
add_library(${PROJECT_NAME}::nghttp2 ALIAS ${LIB_SELECTED})
|
||||||
|
|
||||||
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/libnghttp2.pc"
|
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/libnghttp2.pc"
|
||||||
DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig")
|
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.
|
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
SUBDIRS = includes
|
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_CFLAGS = $(WARNCFLAGS) $(EXTRACFLAG)
|
||||||
AM_CPPFLAGS = -I$(srcdir)/includes -I$(builddir)/includes -DBUILDING_NGHTTP2 \
|
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(
|
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;
|
cbs->send_callback = send_callback;
|
||||||
}
|
}
|
||||||
|
|
||||||
void nghttp2_session_callbacks_set_send_callback2(
|
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;
|
cbs->send_callback2 = send_callback;
|
||||||
}
|
}
|
||||||
|
|
||||||
void nghttp2_session_callbacks_set_recv_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;
|
cbs->recv_callback = recv_callback;
|
||||||
}
|
}
|
||||||
|
|
||||||
void nghttp2_session_callbacks_set_recv_callback2(
|
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;
|
cbs->recv_callback2 = recv_callback;
|
||||||
}
|
}
|
||||||
|
|
||||||
void nghttp2_session_callbacks_set_on_frame_recv_callback(
|
void nghttp2_session_callbacks_set_on_frame_recv_callback(
|
||||||
nghttp2_session_callbacks *cbs,
|
nghttp2_session_callbacks *cbs,
|
||||||
nghttp2_on_frame_recv_callback on_frame_recv_callback) {
|
nghttp2_on_frame_recv_callback on_frame_recv_callback) {
|
||||||
cbs->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(
|
void nghttp2_session_callbacks_set_on_invalid_frame_recv_callback(
|
||||||
nghttp2_session_callbacks *cbs,
|
nghttp2_session_callbacks *cbs,
|
||||||
nghttp2_on_invalid_frame_recv_callback on_invalid_frame_recv_callback) {
|
nghttp2_on_invalid_frame_recv_callback on_invalid_frame_recv_callback) {
|
||||||
cbs->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(
|
void nghttp2_session_callbacks_set_on_data_chunk_recv_callback(
|
||||||
nghttp2_session_callbacks *cbs,
|
nghttp2_session_callbacks *cbs,
|
||||||
nghttp2_on_data_chunk_recv_callback on_data_chunk_recv_callback) {
|
nghttp2_on_data_chunk_recv_callback on_data_chunk_recv_callback) {
|
||||||
cbs->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(
|
void nghttp2_session_callbacks_set_before_frame_send_callback(
|
||||||
nghttp2_session_callbacks *cbs,
|
nghttp2_session_callbacks *cbs,
|
||||||
nghttp2_before_frame_send_callback before_frame_send_callback) {
|
nghttp2_before_frame_send_callback before_frame_send_callback) {
|
||||||
cbs->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(
|
void nghttp2_session_callbacks_set_on_frame_send_callback(
|
||||||
nghttp2_session_callbacks *cbs,
|
nghttp2_session_callbacks *cbs,
|
||||||
nghttp2_on_frame_send_callback on_frame_send_callback) {
|
nghttp2_on_frame_send_callback on_frame_send_callback) {
|
||||||
cbs->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(
|
void nghttp2_session_callbacks_set_on_frame_not_send_callback(
|
||||||
nghttp2_session_callbacks *cbs,
|
nghttp2_session_callbacks *cbs,
|
||||||
nghttp2_on_frame_not_send_callback on_frame_not_send_callback) {
|
nghttp2_on_frame_not_send_callback on_frame_not_send_callback) {
|
||||||
cbs->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(
|
void nghttp2_session_callbacks_set_on_stream_close_callback(
|
||||||
nghttp2_session_callbacks *cbs,
|
nghttp2_session_callbacks *cbs,
|
||||||
nghttp2_on_stream_close_callback on_stream_close_callback) {
|
nghttp2_on_stream_close_callback on_stream_close_callback) {
|
||||||
cbs->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(
|
void nghttp2_session_callbacks_set_on_begin_headers_callback(
|
||||||
nghttp2_session_callbacks *cbs,
|
nghttp2_session_callbacks *cbs,
|
||||||
nghttp2_on_begin_headers_callback on_begin_headers_callback) {
|
nghttp2_on_begin_headers_callback on_begin_headers_callback) {
|
||||||
cbs->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(
|
void nghttp2_session_callbacks_set_on_header_callback(
|
||||||
nghttp2_session_callbacks *cbs,
|
nghttp2_session_callbacks *cbs,
|
||||||
nghttp2_on_header_callback on_header_callback) {
|
nghttp2_on_header_callback on_header_callback) {
|
||||||
cbs->on_header_callback = on_header_callback;
|
cbs->on_header_callback = on_header_callback;
|
||||||
}
|
}
|
||||||
|
|
||||||
void nghttp2_session_callbacks_set_on_header_callback2(
|
void nghttp2_session_callbacks_set_on_header_callback2(
|
||||||
nghttp2_session_callbacks *cbs,
|
nghttp2_session_callbacks *cbs,
|
||||||
nghttp2_on_header_callback2 on_header_callback2) {
|
nghttp2_on_header_callback2 on_header_callback2) {
|
||||||
cbs->on_header_callback2 = on_header_callback2;
|
cbs->on_header_callback2 = on_header_callback2;
|
||||||
}
|
}
|
||||||
|
|
||||||
void nghttp2_session_callbacks_set_on_invalid_header_callback(
|
void nghttp2_session_callbacks_set_on_invalid_header_callback(
|
||||||
nghttp2_session_callbacks *cbs,
|
nghttp2_session_callbacks *cbs,
|
||||||
nghttp2_on_invalid_header_callback on_invalid_header_callback) {
|
nghttp2_on_invalid_header_callback on_invalid_header_callback) {
|
||||||
cbs->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(
|
void nghttp2_session_callbacks_set_on_invalid_header_callback2(
|
||||||
nghttp2_session_callbacks *cbs,
|
nghttp2_session_callbacks *cbs,
|
||||||
nghttp2_on_invalid_header_callback2 on_invalid_header_callback2) {
|
nghttp2_on_invalid_header_callback2 on_invalid_header_callback2) {
|
||||||
cbs->on_invalid_header_callback2 = on_invalid_header_callback2;
|
cbs->on_invalid_header_callback2 = on_invalid_header_callback2;
|
||||||
}
|
}
|
||||||
|
|
||||||
void nghttp2_session_callbacks_set_select_padding_callback(
|
void nghttp2_session_callbacks_set_select_padding_callback(
|
||||||
nghttp2_session_callbacks *cbs,
|
nghttp2_session_callbacks *cbs,
|
||||||
nghttp2_select_padding_callback select_padding_callback) {
|
nghttp2_select_padding_callback select_padding_callback) {
|
||||||
cbs->select_padding_callback = select_padding_callback;
|
cbs->select_padding_callback = select_padding_callback;
|
||||||
}
|
}
|
||||||
|
|
||||||
void nghttp2_session_callbacks_set_select_padding_callback2(
|
void nghttp2_session_callbacks_set_select_padding_callback2(
|
||||||
nghttp2_session_callbacks *cbs,
|
nghttp2_session_callbacks *cbs,
|
||||||
nghttp2_select_padding_callback2 select_padding_callback) {
|
nghttp2_select_padding_callback2 select_padding_callback) {
|
||||||
cbs->select_padding_callback2 = select_padding_callback;
|
cbs->select_padding_callback2 = select_padding_callback;
|
||||||
}
|
}
|
||||||
|
|
||||||
void nghttp2_session_callbacks_set_data_source_read_length_callback(
|
void nghttp2_session_callbacks_set_data_source_read_length_callback(
|
||||||
nghttp2_session_callbacks *cbs,
|
nghttp2_session_callbacks *cbs,
|
||||||
nghttp2_data_source_read_length_callback data_source_read_length_callback) {
|
nghttp2_data_source_read_length_callback data_source_read_length_callback) {
|
||||||
cbs->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(
|
void nghttp2_session_callbacks_set_data_source_read_length_callback2(
|
||||||
nghttp2_session_callbacks *cbs,
|
nghttp2_session_callbacks *cbs, nghttp2_data_source_read_length_callback2
|
||||||
nghttp2_data_source_read_length_callback2 data_source_read_length_callback) {
|
data_source_read_length_callback) {
|
||||||
cbs->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(
|
void nghttp2_session_callbacks_set_on_begin_frame_callback(
|
||||||
nghttp2_session_callbacks *cbs,
|
nghttp2_session_callbacks *cbs,
|
||||||
nghttp2_on_begin_frame_callback on_begin_frame_callback) {
|
nghttp2_on_begin_frame_callback on_begin_frame_callback) {
|
||||||
cbs->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(
|
void nghttp2_session_callbacks_set_send_data_callback(
|
||||||
nghttp2_session_callbacks *cbs,
|
nghttp2_session_callbacks *cbs,
|
||||||
nghttp2_send_data_callback send_data_callback) {
|
nghttp2_send_data_callback send_data_callback) {
|
||||||
cbs->send_data_callback = send_data_callback;
|
cbs->send_data_callback = send_data_callback;
|
||||||
}
|
}
|
||||||
|
|
||||||
void nghttp2_session_callbacks_set_pack_extension_callback(
|
void nghttp2_session_callbacks_set_pack_extension_callback(
|
||||||
nghttp2_session_callbacks *cbs,
|
nghttp2_session_callbacks *cbs,
|
||||||
nghttp2_pack_extension_callback pack_extension_callback) {
|
nghttp2_pack_extension_callback pack_extension_callback) {
|
||||||
cbs->pack_extension_callback = pack_extension_callback;
|
cbs->pack_extension_callback = pack_extension_callback;
|
||||||
}
|
}
|
||||||
|
|
||||||
void nghttp2_session_callbacks_set_pack_extension_callback2(
|
void nghttp2_session_callbacks_set_pack_extension_callback2(
|
||||||
nghttp2_session_callbacks *cbs,
|
nghttp2_session_callbacks *cbs,
|
||||||
nghttp2_pack_extension_callback2 pack_extension_callback) {
|
nghttp2_pack_extension_callback2 pack_extension_callback) {
|
||||||
cbs->pack_extension_callback2 = pack_extension_callback;
|
cbs->pack_extension_callback2 = pack_extension_callback;
|
||||||
}
|
}
|
||||||
|
|
||||||
void nghttp2_session_callbacks_set_unpack_extension_callback(
|
void nghttp2_session_callbacks_set_unpack_extension_callback(
|
||||||
nghttp2_session_callbacks *cbs,
|
nghttp2_session_callbacks *cbs,
|
||||||
nghttp2_unpack_extension_callback unpack_extension_callback) {
|
nghttp2_unpack_extension_callback unpack_extension_callback) {
|
||||||
cbs->unpack_extension_callback = unpack_extension_callback;
|
cbs->unpack_extension_callback = unpack_extension_callback;
|
||||||
}
|
}
|
||||||
|
|
||||||
void nghttp2_session_callbacks_set_on_extension_chunk_recv_callback(
|
void nghttp2_session_callbacks_set_on_extension_chunk_recv_callback(
|
||||||
nghttp2_session_callbacks *cbs,
|
nghttp2_session_callbacks *cbs,
|
||||||
nghttp2_on_extension_chunk_recv_callback on_extension_chunk_recv_callback) {
|
nghttp2_on_extension_chunk_recv_callback on_extension_chunk_recv_callback) {
|
||||||
cbs->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(
|
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;
|
cbs->error_callback = error_callback;
|
||||||
}
|
}
|
||||||
|
|
||||||
void nghttp2_session_callbacks_set_error_callback2(
|
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;
|
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_on_extension_chunk_recv_callback on_extension_chunk_recv_callback;
|
||||||
nghttp2_error_callback error_callback;
|
nghttp2_error_callback error_callback;
|
||||||
nghttp2_error_callback2 error_callback2;
|
nghttp2_error_callback2 error_callback2;
|
||||||
nghttp2_rand_callback rand_callback;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* NGHTTP2_CALLBACKS_H */
|
#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 =
|
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, ...) {
|
void nghttp2_debug_vprintf(const char *format, ...) {
|
||||||
if (static_debug_vprintf_callback) {
|
if (static_debug_vprintf_callback) {
|
||||||
@@ -46,14 +46,14 @@ void nghttp2_debug_vprintf(const char *format, ...) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void nghttp2_set_debug_vprintf_callback(
|
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;
|
static_debug_vprintf_callback = debug_vprintf_callback;
|
||||||
}
|
}
|
||||||
|
|
||||||
#else /* !DEBUGBUILD */
|
#else /* !DEBUGBUILD */
|
||||||
|
|
||||||
void nghttp2_set_debug_vprintf_callback(
|
void nghttp2_set_debug_vprintf_callback(
|
||||||
nghttp2_debug_vprintf_callback debug_vprintf_callback) {
|
nghttp2_debug_vprintf_callback debug_vprintf_callback) {
|
||||||
(void)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
|
* nghttp2_extpri_uint8_inc extracts inc from |PRI| which is supposed to
|
||||||
* be constructed by nghttp2_extpri_to_uint8.
|
* 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 */
|
#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);
|
nghttp2_frame_pack_frame_hd(buf->pos, &frame->hd);
|
||||||
|
|
||||||
buf->last +=
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -537,7 +537,7 @@ int nghttp2_frame_unpack_settings_payload2(nghttp2_settings_entry **iv_ptr,
|
|||||||
}
|
}
|
||||||
|
|
||||||
*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) {
|
if (*iv_ptr == NULL) {
|
||||||
return NGHTTP2_ERR_NOMEM;
|
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,
|
void nghttp2_frame_unpack_push_promise_payload(nghttp2_push_promise *frame,
|
||||||
const uint8_t *payload) {
|
const uint8_t *payload) {
|
||||||
frame->promised_stream_id =
|
frame->promised_stream_id =
|
||||||
nghttp2_get_uint32(payload) & NGHTTP2_STREAM_ID_MASK;
|
nghttp2_get_uint32(payload) & NGHTTP2_STREAM_ID_MASK;
|
||||||
frame->nva = NULL;
|
frame->nva = NULL;
|
||||||
frame->nvlen = 0;
|
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);
|
nghttp2_frame_pack_frame_hd(buf->pos, &frame->hd);
|
||||||
|
|
||||||
buf->last =
|
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,
|
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,
|
void nghttp2_frame_unpack_window_update_payload(nghttp2_window_update *frame,
|
||||||
const uint8_t *payload) {
|
const uint8_t *payload) {
|
||||||
frame->window_size_increment =
|
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) {
|
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 = frame->payload;
|
||||||
|
|
||||||
priority_update->stream_id =
|
priority_update->stream_id =
|
||||||
nghttp2_get_uint32(payload) & NGHTTP2_STREAM_ID_MASK;
|
nghttp2_get_uint32(payload) & NGHTTP2_STREAM_ID_MASK;
|
||||||
|
|
||||||
if (payloadlen > 4) {
|
if (payloadlen > 4) {
|
||||||
priority_update->field_value = payload + 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) \
|
#define MAKE_STATIC_ENT(N, V, T, H) \
|
||||||
{ \
|
{ \
|
||||||
{NULL, NULL, (uint8_t *)(N), sizeof((N)) - 1, -1}, \
|
{NULL, NULL, (uint8_t *)(N), sizeof((N)) - 1, -1}, \
|
||||||
{NULL, NULL, (uint8_t *)(V), sizeof((V)) - 1, -1}, \
|
{NULL, NULL, (uint8_t *)(V), sizeof((V)) - 1, -1}, \
|
||||||
{(uint8_t *)(N), (uint8_t *)(V), sizeof((N)) - 1, sizeof((V)) - 1, 0}, \
|
{(uint8_t *)(N), (uint8_t *)(V), sizeof((N)) - 1, sizeof((V)) - 1, 0}, \
|
||||||
T, \
|
T, H \
|
||||||
H, \
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Generated by mkstatictbl.py */
|
/* Generated by mkstatictbl.py */
|
||||||
@@ -47,67 +46,67 @@
|
|||||||
first enum value if same header names are repeated (e.g.,
|
first enum value if same header names are repeated (e.g.,
|
||||||
:status). */
|
:status). */
|
||||||
static const nghttp2_hd_static_entry static_table[] = {
|
static const nghttp2_hd_static_entry static_table[] = {
|
||||||
MAKE_STATIC_ENT(":authority", "", 0, 3153725150u),
|
MAKE_STATIC_ENT(":authority", "", 0, 3153725150u),
|
||||||
MAKE_STATIC_ENT(":method", "GET", 1, 695666056u),
|
MAKE_STATIC_ENT(":method", "GET", 1, 695666056u),
|
||||||
MAKE_STATIC_ENT(":method", "POST", 1, 695666056u),
|
MAKE_STATIC_ENT(":method", "POST", 1, 695666056u),
|
||||||
MAKE_STATIC_ENT(":path", "/", 3, 3292848686u),
|
MAKE_STATIC_ENT(":path", "/", 3, 3292848686u),
|
||||||
MAKE_STATIC_ENT(":path", "/index.html", 3, 3292848686u),
|
MAKE_STATIC_ENT(":path", "/index.html", 3, 3292848686u),
|
||||||
MAKE_STATIC_ENT(":scheme", "http", 5, 2510477674u),
|
MAKE_STATIC_ENT(":scheme", "http", 5, 2510477674u),
|
||||||
MAKE_STATIC_ENT(":scheme", "https", 5, 2510477674u),
|
MAKE_STATIC_ENT(":scheme", "https", 5, 2510477674u),
|
||||||
MAKE_STATIC_ENT(":status", "200", 7, 4000288983u),
|
MAKE_STATIC_ENT(":status", "200", 7, 4000288983u),
|
||||||
MAKE_STATIC_ENT(":status", "204", 7, 4000288983u),
|
MAKE_STATIC_ENT(":status", "204", 7, 4000288983u),
|
||||||
MAKE_STATIC_ENT(":status", "206", 7, 4000288983u),
|
MAKE_STATIC_ENT(":status", "206", 7, 4000288983u),
|
||||||
MAKE_STATIC_ENT(":status", "304", 7, 4000288983u),
|
MAKE_STATIC_ENT(":status", "304", 7, 4000288983u),
|
||||||
MAKE_STATIC_ENT(":status", "400", 7, 4000288983u),
|
MAKE_STATIC_ENT(":status", "400", 7, 4000288983u),
|
||||||
MAKE_STATIC_ENT(":status", "404", 7, 4000288983u),
|
MAKE_STATIC_ENT(":status", "404", 7, 4000288983u),
|
||||||
MAKE_STATIC_ENT(":status", "500", 7, 4000288983u),
|
MAKE_STATIC_ENT(":status", "500", 7, 4000288983u),
|
||||||
MAKE_STATIC_ENT("accept-charset", "", 14, 3664010344u),
|
MAKE_STATIC_ENT("accept-charset", "", 14, 3664010344u),
|
||||||
MAKE_STATIC_ENT("accept-encoding", "gzip, deflate", 15, 3379649177u),
|
MAKE_STATIC_ENT("accept-encoding", "gzip, deflate", 15, 3379649177u),
|
||||||
MAKE_STATIC_ENT("accept-language", "", 16, 1979086614u),
|
MAKE_STATIC_ENT("accept-language", "", 16, 1979086614u),
|
||||||
MAKE_STATIC_ENT("accept-ranges", "", 17, 1713753958u),
|
MAKE_STATIC_ENT("accept-ranges", "", 17, 1713753958u),
|
||||||
MAKE_STATIC_ENT("accept", "", 18, 136609321u),
|
MAKE_STATIC_ENT("accept", "", 18, 136609321u),
|
||||||
MAKE_STATIC_ENT("access-control-allow-origin", "", 19, 2710797292u),
|
MAKE_STATIC_ENT("access-control-allow-origin", "", 19, 2710797292u),
|
||||||
MAKE_STATIC_ENT("age", "", 20, 742476188u),
|
MAKE_STATIC_ENT("age", "", 20, 742476188u),
|
||||||
MAKE_STATIC_ENT("allow", "", 21, 2930878514u),
|
MAKE_STATIC_ENT("allow", "", 21, 2930878514u),
|
||||||
MAKE_STATIC_ENT("authorization", "", 22, 2436257726u),
|
MAKE_STATIC_ENT("authorization", "", 22, 2436257726u),
|
||||||
MAKE_STATIC_ENT("cache-control", "", 23, 1355326669u),
|
MAKE_STATIC_ENT("cache-control", "", 23, 1355326669u),
|
||||||
MAKE_STATIC_ENT("content-disposition", "", 24, 3889184348u),
|
MAKE_STATIC_ENT("content-disposition", "", 24, 3889184348u),
|
||||||
MAKE_STATIC_ENT("content-encoding", "", 25, 65203592u),
|
MAKE_STATIC_ENT("content-encoding", "", 25, 65203592u),
|
||||||
MAKE_STATIC_ENT("content-language", "", 26, 24973587u),
|
MAKE_STATIC_ENT("content-language", "", 26, 24973587u),
|
||||||
MAKE_STATIC_ENT("content-length", "", 27, 1308181789u),
|
MAKE_STATIC_ENT("content-length", "", 27, 1308181789u),
|
||||||
MAKE_STATIC_ENT("content-location", "", 28, 2302364718u),
|
MAKE_STATIC_ENT("content-location", "", 28, 2302364718u),
|
||||||
MAKE_STATIC_ENT("content-range", "", 29, 3555523146u),
|
MAKE_STATIC_ENT("content-range", "", 29, 3555523146u),
|
||||||
MAKE_STATIC_ENT("content-type", "", 30, 4244048277u),
|
MAKE_STATIC_ENT("content-type", "", 30, 4244048277u),
|
||||||
MAKE_STATIC_ENT("cookie", "", 31, 2007449791u),
|
MAKE_STATIC_ENT("cookie", "", 31, 2007449791u),
|
||||||
MAKE_STATIC_ENT("date", "", 32, 3564297305u),
|
MAKE_STATIC_ENT("date", "", 32, 3564297305u),
|
||||||
MAKE_STATIC_ENT("etag", "", 33, 113792960u),
|
MAKE_STATIC_ENT("etag", "", 33, 113792960u),
|
||||||
MAKE_STATIC_ENT("expect", "", 34, 2530896728u),
|
MAKE_STATIC_ENT("expect", "", 34, 2530896728u),
|
||||||
MAKE_STATIC_ENT("expires", "", 35, 1049544579u),
|
MAKE_STATIC_ENT("expires", "", 35, 1049544579u),
|
||||||
MAKE_STATIC_ENT("from", "", 36, 2513272949u),
|
MAKE_STATIC_ENT("from", "", 36, 2513272949u),
|
||||||
MAKE_STATIC_ENT("host", "", 37, 2952701295u),
|
MAKE_STATIC_ENT("host", "", 37, 2952701295u),
|
||||||
MAKE_STATIC_ENT("if-match", "", 38, 3597694698u),
|
MAKE_STATIC_ENT("if-match", "", 38, 3597694698u),
|
||||||
MAKE_STATIC_ENT("if-modified-since", "", 39, 2213050793u),
|
MAKE_STATIC_ENT("if-modified-since", "", 39, 2213050793u),
|
||||||
MAKE_STATIC_ENT("if-none-match", "", 40, 2536202615u),
|
MAKE_STATIC_ENT("if-none-match", "", 40, 2536202615u),
|
||||||
MAKE_STATIC_ENT("if-range", "", 41, 2340978238u),
|
MAKE_STATIC_ENT("if-range", "", 41, 2340978238u),
|
||||||
MAKE_STATIC_ENT("if-unmodified-since", "", 42, 3794814858u),
|
MAKE_STATIC_ENT("if-unmodified-since", "", 42, 3794814858u),
|
||||||
MAKE_STATIC_ENT("last-modified", "", 43, 3226950251u),
|
MAKE_STATIC_ENT("last-modified", "", 43, 3226950251u),
|
||||||
MAKE_STATIC_ENT("link", "", 44, 232457833u),
|
MAKE_STATIC_ENT("link", "", 44, 232457833u),
|
||||||
MAKE_STATIC_ENT("location", "", 45, 200649126u),
|
MAKE_STATIC_ENT("location", "", 45, 200649126u),
|
||||||
MAKE_STATIC_ENT("max-forwards", "", 46, 1826162134u),
|
MAKE_STATIC_ENT("max-forwards", "", 46, 1826162134u),
|
||||||
MAKE_STATIC_ENT("proxy-authenticate", "", 47, 2709445359u),
|
MAKE_STATIC_ENT("proxy-authenticate", "", 47, 2709445359u),
|
||||||
MAKE_STATIC_ENT("proxy-authorization", "", 48, 2686392507u),
|
MAKE_STATIC_ENT("proxy-authorization", "", 48, 2686392507u),
|
||||||
MAKE_STATIC_ENT("range", "", 49, 4208725202u),
|
MAKE_STATIC_ENT("range", "", 49, 4208725202u),
|
||||||
MAKE_STATIC_ENT("referer", "", 50, 3969579366u),
|
MAKE_STATIC_ENT("referer", "", 50, 3969579366u),
|
||||||
MAKE_STATIC_ENT("refresh", "", 51, 3572655668u),
|
MAKE_STATIC_ENT("refresh", "", 51, 3572655668u),
|
||||||
MAKE_STATIC_ENT("retry-after", "", 52, 3336180598u),
|
MAKE_STATIC_ENT("retry-after", "", 52, 3336180598u),
|
||||||
MAKE_STATIC_ENT("server", "", 53, 1085029842u),
|
MAKE_STATIC_ENT("server", "", 53, 1085029842u),
|
||||||
MAKE_STATIC_ENT("set-cookie", "", 54, 1848371000u),
|
MAKE_STATIC_ENT("set-cookie", "", 54, 1848371000u),
|
||||||
MAKE_STATIC_ENT("strict-transport-security", "", 55, 4138147361u),
|
MAKE_STATIC_ENT("strict-transport-security", "", 55, 4138147361u),
|
||||||
MAKE_STATIC_ENT("transfer-encoding", "", 56, 3719590988u),
|
MAKE_STATIC_ENT("transfer-encoding", "", 56, 3719590988u),
|
||||||
MAKE_STATIC_ENT("user-agent", "", 57, 606444526u),
|
MAKE_STATIC_ENT("user-agent", "", 57, 606444526u),
|
||||||
MAKE_STATIC_ENT("vary", "", 58, 1085005381u),
|
MAKE_STATIC_ENT("vary", "", 58, 1085005381u),
|
||||||
MAKE_STATIC_ENT("via", "", 59, 1762798611u),
|
MAKE_STATIC_ENT("via", "", 59, 1762798611u),
|
||||||
MAKE_STATIC_ENT("www-authenticate", "", 60, 779865858u),
|
MAKE_STATIC_ENT("www-authenticate", "", 60, 779865858u),
|
||||||
};
|
};
|
||||||
|
|
||||||
static int memeq(const void *s1, const void *s2, size_t n) {
|
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,
|
static int hd_ringbuf_init(nghttp2_hd_ringbuf *ringbuf, size_t bufsize,
|
||||||
nghttp2_mem *mem) {
|
nghttp2_mem *mem) {
|
||||||
size_t size;
|
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)
|
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);
|
ringbuf->buffer = nghttp2_mem_malloc(mem, sizeof(nghttp2_hd_entry *) * size);
|
||||||
if (ringbuf->buffer == NULL) {
|
if (ringbuf->buffer == NULL) {
|
||||||
return NGHTTP2_ERR_NOMEM;
|
return NGHTTP2_ERR_NOMEM;
|
||||||
@@ -689,8 +677,8 @@ static int hd_context_init(nghttp2_hd_context *context, nghttp2_mem *mem) {
|
|||||||
context->bad = 0;
|
context->bad = 0;
|
||||||
context->hd_table_bufsize_max = NGHTTP2_HD_DEFAULT_MAX_BUFFER_SIZE;
|
context->hd_table_bufsize_max = NGHTTP2_HD_DEFAULT_MAX_BUFFER_SIZE;
|
||||||
rv = hd_ringbuf_init(
|
rv = hd_ringbuf_init(
|
||||||
&context->hd_table,
|
&context->hd_table,
|
||||||
context->hd_table_bufsize_max / NGHTTP2_HD_ENTRY_OVERHEAD, mem);
|
context->hd_table_bufsize_max / NGHTTP2_HD_ENTRY_OVERHEAD, mem);
|
||||||
if (rv != 0) {
|
if (rv != 0) {
|
||||||
return rv;
|
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) {
|
int nghttp2_hd_deflate_init(nghttp2_hd_deflater *deflater, nghttp2_mem *mem) {
|
||||||
return nghttp2_hd_deflate_init2(
|
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,
|
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;
|
int rv;
|
||||||
|
|
||||||
DEBUGF(
|
DEBUGF(
|
||||||
"deflatehd: emit newname namelen=%zu, valuelen=%zu, indexing_mode=%d\n",
|
"deflatehd: emit newname namelen=%zu, valuelen=%zu, indexing_mode=%d\n",
|
||||||
nv->namelen, nv->valuelen, indexing_mode);
|
nv->namelen, nv->valuelen, indexing_mode);
|
||||||
|
|
||||||
rv = nghttp2_bufs_addb(bufs, pack_first_byte(indexing_mode));
|
rv = nghttp2_bufs_addb(bufs, pack_first_byte(indexing_mode));
|
||||||
if (rv != 0) {
|
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 &&
|
while (context->hd_table_bufsize + room > context->hd_table_bufsize_max &&
|
||||||
context->hd_table.len > 0) {
|
context->hd_table.len > 0) {
|
||||||
|
|
||||||
size_t idx = context->hd_table.len - 1;
|
size_t idx = context->hd_table.len - 1;
|
||||||
nghttp2_hd_entry *ent = hd_ringbuf_get(&context->hd_table, idx);
|
nghttp2_hd_entry *ent = hd_ringbuf_get(&context->hd_table, idx);
|
||||||
|
|
||||||
context->hd_table_bufsize -=
|
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",
|
DEBUGF("hpack: remove item from header table: %s: %s\n",
|
||||||
(char *)ent->nv.name->base, (char *)ent->nv.value->base);
|
(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;
|
size_t idx = context->hd_table.len - 1;
|
||||||
nghttp2_hd_entry *ent = hd_ringbuf_get(&context->hd_table, idx);
|
nghttp2_hd_entry *ent = hd_ringbuf_get(&context->hd_table, idx);
|
||||||
context->hd_table_bufsize -=
|
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);
|
hd_ringbuf_pop_back(&context->hd_table);
|
||||||
if (map) {
|
if (map) {
|
||||||
hd_map_remove(map, ent);
|
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(
|
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(
|
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->ctx.hd_table_bufsize_max = next_bufsize;
|
||||||
|
|
||||||
deflater->min_hd_table_bufsize_max =
|
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;
|
deflater->notify_table_size_change = 1;
|
||||||
|
|
||||||
@@ -1271,7 +1260,7 @@ int nghttp2_hd_deflate_change_table_size(
|
|||||||
}
|
}
|
||||||
|
|
||||||
int nghttp2_hd_inflate_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) {
|
switch (inflater->state) {
|
||||||
case NGHTTP2_HD_STATE_EXPECT_TABLE_SIZE:
|
case NGHTTP2_HD_STATE_EXPECT_TABLE_SIZE:
|
||||||
case NGHTTP2_HD_STATE_INFLATE_START:
|
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));
|
assert(INDEX_RANGE_VALID(context, idx));
|
||||||
if (idx >= NGHTTP2_STATIC_TABLE_LENGTH) {
|
if (idx >= NGHTTP2_STATIC_TABLE_LENGTH) {
|
||||||
return hd_ringbuf_get(&context->hd_table, idx - NGHTTP2_STATIC_TABLE_LENGTH)
|
return hd_ringbuf_get(&context->hd_table, idx - NGHTTP2_STATIC_TABLE_LENGTH)
|
||||||
->nv;
|
->nv;
|
||||||
} else {
|
} else {
|
||||||
const nghttp2_hd_static_entry *ent = &static_table[idx];
|
const nghttp2_hd_static_entry *ent = &static_table[idx];
|
||||||
nghttp2_hd_nv nv = {(nghttp2_rcbuf *)&ent->name,
|
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) {
|
if (idx >= NGHTTP2_STATIC_TABLE_LENGTH) {
|
||||||
return &hd_ringbuf_get(&context->hd_table,
|
return &hd_ringbuf_get(&context->hd_table,
|
||||||
idx - NGHTTP2_STATIC_TABLE_LENGTH)
|
idx - NGHTTP2_STATIC_TABLE_LENGTH)
|
||||||
->cnv;
|
->cnv;
|
||||||
}
|
}
|
||||||
|
|
||||||
return &static_table[idx].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_IF_NONE_MATCH || token == NGHTTP2_TOKEN_LOCATION ||
|
||||||
token == NGHTTP2_TOKEN_SET_COOKIE ||
|
token == NGHTTP2_TOKEN_SET_COOKIE ||
|
||||||
entry_room(nv->namelen, nv->valuelen) >
|
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;
|
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
|
entropy secret data (e.g., id/password). Also cookie header
|
||||||
field with less than 20 bytes value is also never indexed. This
|
field with less than 20 bytes value is also never indexed. This
|
||||||
is the same criteria used in Firefox codebase. */
|
is the same criteria used in Firefox codebase. */
|
||||||
indexing_mode = token == NGHTTP2_TOKEN_AUTHORIZATION ||
|
indexing_mode =
|
||||||
(token == NGHTTP2_TOKEN_COOKIE && nv->valuelen < 20) ||
|
token == NGHTTP2_TOKEN_AUTHORIZATION ||
|
||||||
(nv->flags & NGHTTP2_NV_FLAG_NO_INDEX)
|
(token == NGHTTP2_TOKEN_COOKIE && nv->valuelen < 20) ||
|
||||||
? NGHTTP2_HD_NEVER_INDEXING
|
(nv->flags & NGHTTP2_NV_FLAG_NO_INDEX)
|
||||||
: hd_deflate_decide_indexing(deflater, nv, token);
|
? NGHTTP2_HD_NEVER_INDEXING
|
||||||
|
: hd_deflate_decide_indexing(deflater, nv, token);
|
||||||
|
|
||||||
res = search_hd_table(&deflater->ctx, nv, token, indexing_mode,
|
res = search_hd_table(&deflater->ctx, nv, token, indexing_mode,
|
||||||
&deflater->map, hash);
|
&deflater->map, hash);
|
||||||
@@ -1389,6 +1379,7 @@ static int deflate_nv(nghttp2_hd_deflater *deflater, nghttp2_bufs *bufs,
|
|||||||
idx = res.index;
|
idx = res.index;
|
||||||
|
|
||||||
if (res.name_value_match) {
|
if (res.name_value_match) {
|
||||||
|
|
||||||
DEBUGF("deflatehd: name/value match index=%td\n", idx);
|
DEBUGF("deflatehd: name/value match index=%td\n", idx);
|
||||||
|
|
||||||
rv = emit_indexed_block(bufs, (size_t)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;
|
deflater->min_hd_table_bufsize_max = UINT32_MAX;
|
||||||
|
|
||||||
if (deflater->ctx.hd_table_bufsize_max > min_hd_table_bufsize_max) {
|
if (deflater->ctx.hd_table_bufsize_max > min_hd_table_bufsize_max) {
|
||||||
|
|
||||||
rv = emit_table_size(bufs, min_hd_table_bufsize_max);
|
rv = emit_table_size(bufs, min_hd_table_bufsize_max);
|
||||||
|
|
||||||
if (rv != 0) {
|
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:
|
case NGHTTP2_HD_STATE_READ_TABLE_SIZE:
|
||||||
rfin = 0;
|
rfin = 0;
|
||||||
rv = hd_inflate_read_len(
|
rv = hd_inflate_read_len(
|
||||||
inflater, &rfin, in, last, 5,
|
inflater, &rfin, in, last, 5,
|
||||||
nghttp2_min_size(inflater->min_hd_table_bufsize_max,
|
nghttp2_min_size(inflater->min_hd_table_bufsize_max,
|
||||||
inflater->settings_hd_table_bufsize_max));
|
inflater->settings_hd_table_bufsize_max));
|
||||||
if (rv < 0) {
|
if (rv < 0) {
|
||||||
goto fail;
|
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;
|
inflater->state = NGHTTP2_HD_STATE_NEWNAME_READ_NAMEHUFF;
|
||||||
|
|
||||||
rv =
|
rv = nghttp2_rcbuf_new(&inflater->namercbuf, inflater->left * 2 + 1,
|
||||||
nghttp2_rcbuf_new(&inflater->namercbuf, inflater->left * 2 + 1, mem);
|
mem);
|
||||||
} else {
|
} else {
|
||||||
inflater->state = NGHTTP2_HD_STATE_NEWNAME_READ_NAME;
|
inflater->state = NGHTTP2_HD_STATE_NEWNAME_READ_NAME;
|
||||||
rv = nghttp2_rcbuf_new(&inflater->namercbuf, inflater->left + 1, mem);
|
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;
|
inflater->state = NGHTTP2_HD_STATE_READ_VALUEHUFF;
|
||||||
|
|
||||||
rv =
|
rv = nghttp2_rcbuf_new(&inflater->valuercbuf, inflater->left * 2 + 1,
|
||||||
nghttp2_rcbuf_new(&inflater->valuercbuf, inflater->left * 2 + 1, mem);
|
mem);
|
||||||
} else {
|
} else {
|
||||||
inflater->state = NGHTTP2_HD_STATE_READ_VALUE;
|
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,
|
int nghttp2_hd_emit_indname_block(nghttp2_bufs *bufs, size_t idx,
|
||||||
nghttp2_nv *nv, int indexing_mode) {
|
nghttp2_nv *nv, int indexing_mode) {
|
||||||
|
|
||||||
return emit_indname_block(bufs, idx, nv, 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) {
|
if (nbits) {
|
||||||
rv = nghttp2_bufs_addb(
|
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) {
|
if (rv != 0) {
|
||||||
return rv;
|
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 */
|
/* Generated by gendowncasetbl.py */
|
||||||
static const uint8_t DOWNCASE_TBL[] = {
|
static const uint8_t DOWNCASE_TBL[] = {
|
||||||
0 /* NUL */, 1 /* SOH */, 2 /* STX */, 3 /* ETX */,
|
0 /* NUL */, 1 /* SOH */, 2 /* STX */, 3 /* ETX */,
|
||||||
4 /* EOT */, 5 /* ENQ */, 6 /* ACK */, 7 /* BEL */,
|
4 /* EOT */, 5 /* ENQ */, 6 /* ACK */, 7 /* BEL */,
|
||||||
8 /* BS */, 9 /* HT */, 10 /* LF */, 11 /* VT */,
|
8 /* BS */, 9 /* HT */, 10 /* LF */, 11 /* VT */,
|
||||||
12 /* FF */, 13 /* CR */, 14 /* SO */, 15 /* SI */,
|
12 /* FF */, 13 /* CR */, 14 /* SO */, 15 /* SI */,
|
||||||
16 /* DLE */, 17 /* DC1 */, 18 /* DC2 */, 19 /* DC3 */,
|
16 /* DLE */, 17 /* DC1 */, 18 /* DC2 */, 19 /* DC3 */,
|
||||||
20 /* DC4 */, 21 /* NAK */, 22 /* SYN */, 23 /* ETB */,
|
20 /* DC4 */, 21 /* NAK */, 22 /* SYN */, 23 /* ETB */,
|
||||||
24 /* CAN */, 25 /* EM */, 26 /* SUB */, 27 /* ESC */,
|
24 /* CAN */, 25 /* EM */, 26 /* SUB */, 27 /* ESC */,
|
||||||
28 /* FS */, 29 /* GS */, 30 /* RS */, 31 /* US */,
|
28 /* FS */, 29 /* GS */, 30 /* RS */, 31 /* US */,
|
||||||
32 /* SPC */, 33 /* ! */, 34 /* " */, 35 /* # */,
|
32 /* SPC */, 33 /* ! */, 34 /* " */, 35 /* # */,
|
||||||
36 /* $ */, 37 /* % */, 38 /* & */, 39 /* ' */,
|
36 /* $ */, 37 /* % */, 38 /* & */, 39 /* ' */,
|
||||||
40 /* ( */, 41 /* ) */, 42 /* * */, 43 /* + */,
|
40 /* ( */, 41 /* ) */, 42 /* * */, 43 /* + */,
|
||||||
44 /* , */, 45 /* - */, 46 /* . */, 47 /* / */,
|
44 /* , */, 45 /* - */, 46 /* . */, 47 /* / */,
|
||||||
48 /* 0 */, 49 /* 1 */, 50 /* 2 */, 51 /* 3 */,
|
48 /* 0 */, 49 /* 1 */, 50 /* 2 */, 51 /* 3 */,
|
||||||
52 /* 4 */, 53 /* 5 */, 54 /* 6 */, 55 /* 7 */,
|
52 /* 4 */, 53 /* 5 */, 54 /* 6 */, 55 /* 7 */,
|
||||||
56 /* 8 */, 57 /* 9 */, 58 /* : */, 59 /* ; */,
|
56 /* 8 */, 57 /* 9 */, 58 /* : */, 59 /* ; */,
|
||||||
60 /* < */, 61 /* = */, 62 /* > */, 63 /* ? */,
|
60 /* < */, 61 /* = */, 62 /* > */, 63 /* ? */,
|
||||||
64 /* @ */, 97 /* A */, 98 /* B */, 99 /* C */,
|
64 /* @ */, 97 /* A */, 98 /* B */, 99 /* C */,
|
||||||
100 /* D */, 101 /* E */, 102 /* F */, 103 /* G */,
|
100 /* D */, 101 /* E */, 102 /* F */, 103 /* G */,
|
||||||
104 /* H */, 105 /* I */, 106 /* J */, 107 /* K */,
|
104 /* H */, 105 /* I */, 106 /* J */, 107 /* K */,
|
||||||
108 /* L */, 109 /* M */, 110 /* N */, 111 /* O */,
|
108 /* L */, 109 /* M */, 110 /* N */, 111 /* O */,
|
||||||
112 /* P */, 113 /* Q */, 114 /* R */, 115 /* S */,
|
112 /* P */, 113 /* Q */, 114 /* R */, 115 /* S */,
|
||||||
116 /* T */, 117 /* U */, 118 /* V */, 119 /* W */,
|
116 /* T */, 117 /* U */, 118 /* V */, 119 /* W */,
|
||||||
120 /* X */, 121 /* Y */, 122 /* Z */, 91 /* [ */,
|
120 /* X */, 121 /* Y */, 122 /* Z */, 91 /* [ */,
|
||||||
92 /* \ */, 93 /* ] */, 94 /* ^ */, 95 /* _ */,
|
92 /* \ */, 93 /* ] */, 94 /* ^ */, 95 /* _ */,
|
||||||
96 /* ` */, 97 /* a */, 98 /* b */, 99 /* c */,
|
96 /* ` */, 97 /* a */, 98 /* b */, 99 /* c */,
|
||||||
100 /* d */, 101 /* e */, 102 /* f */, 103 /* g */,
|
100 /* d */, 101 /* e */, 102 /* f */, 103 /* g */,
|
||||||
104 /* h */, 105 /* i */, 106 /* j */, 107 /* k */,
|
104 /* h */, 105 /* i */, 106 /* j */, 107 /* k */,
|
||||||
108 /* l */, 109 /* m */, 110 /* n */, 111 /* o */,
|
108 /* l */, 109 /* m */, 110 /* n */, 111 /* o */,
|
||||||
112 /* p */, 113 /* q */, 114 /* r */, 115 /* s */,
|
112 /* p */, 113 /* q */, 114 /* r */, 115 /* s */,
|
||||||
116 /* t */, 117 /* u */, 118 /* v */, 119 /* w */,
|
116 /* t */, 117 /* u */, 118 /* v */, 119 /* w */,
|
||||||
120 /* x */, 121 /* y */, 122 /* z */, 123 /* { */,
|
120 /* x */, 121 /* y */, 122 /* z */, 123 /* { */,
|
||||||
124 /* | */, 125 /* } */, 126 /* ~ */, 127 /* DEL */,
|
124 /* | */, 125 /* } */, 126 /* ~ */, 127 /* DEL */,
|
||||||
128 /* 0x80 */, 129 /* 0x81 */, 130 /* 0x82 */, 131 /* 0x83 */,
|
128 /* 0x80 */, 129 /* 0x81 */, 130 /* 0x82 */, 131 /* 0x83 */,
|
||||||
132 /* 0x84 */, 133 /* 0x85 */, 134 /* 0x86 */, 135 /* 0x87 */,
|
132 /* 0x84 */, 133 /* 0x85 */, 134 /* 0x86 */, 135 /* 0x87 */,
|
||||||
136 /* 0x88 */, 137 /* 0x89 */, 138 /* 0x8a */, 139 /* 0x8b */,
|
136 /* 0x88 */, 137 /* 0x89 */, 138 /* 0x8a */, 139 /* 0x8b */,
|
||||||
140 /* 0x8c */, 141 /* 0x8d */, 142 /* 0x8e */, 143 /* 0x8f */,
|
140 /* 0x8c */, 141 /* 0x8d */, 142 /* 0x8e */, 143 /* 0x8f */,
|
||||||
144 /* 0x90 */, 145 /* 0x91 */, 146 /* 0x92 */, 147 /* 0x93 */,
|
144 /* 0x90 */, 145 /* 0x91 */, 146 /* 0x92 */, 147 /* 0x93 */,
|
||||||
148 /* 0x94 */, 149 /* 0x95 */, 150 /* 0x96 */, 151 /* 0x97 */,
|
148 /* 0x94 */, 149 /* 0x95 */, 150 /* 0x96 */, 151 /* 0x97 */,
|
||||||
152 /* 0x98 */, 153 /* 0x99 */, 154 /* 0x9a */, 155 /* 0x9b */,
|
152 /* 0x98 */, 153 /* 0x99 */, 154 /* 0x9a */, 155 /* 0x9b */,
|
||||||
156 /* 0x9c */, 157 /* 0x9d */, 158 /* 0x9e */, 159 /* 0x9f */,
|
156 /* 0x9c */, 157 /* 0x9d */, 158 /* 0x9e */, 159 /* 0x9f */,
|
||||||
160 /* 0xa0 */, 161 /* 0xa1 */, 162 /* 0xa2 */, 163 /* 0xa3 */,
|
160 /* 0xa0 */, 161 /* 0xa1 */, 162 /* 0xa2 */, 163 /* 0xa3 */,
|
||||||
164 /* 0xa4 */, 165 /* 0xa5 */, 166 /* 0xa6 */, 167 /* 0xa7 */,
|
164 /* 0xa4 */, 165 /* 0xa5 */, 166 /* 0xa6 */, 167 /* 0xa7 */,
|
||||||
168 /* 0xa8 */, 169 /* 0xa9 */, 170 /* 0xaa */, 171 /* 0xab */,
|
168 /* 0xa8 */, 169 /* 0xa9 */, 170 /* 0xaa */, 171 /* 0xab */,
|
||||||
172 /* 0xac */, 173 /* 0xad */, 174 /* 0xae */, 175 /* 0xaf */,
|
172 /* 0xac */, 173 /* 0xad */, 174 /* 0xae */, 175 /* 0xaf */,
|
||||||
176 /* 0xb0 */, 177 /* 0xb1 */, 178 /* 0xb2 */, 179 /* 0xb3 */,
|
176 /* 0xb0 */, 177 /* 0xb1 */, 178 /* 0xb2 */, 179 /* 0xb3 */,
|
||||||
180 /* 0xb4 */, 181 /* 0xb5 */, 182 /* 0xb6 */, 183 /* 0xb7 */,
|
180 /* 0xb4 */, 181 /* 0xb5 */, 182 /* 0xb6 */, 183 /* 0xb7 */,
|
||||||
184 /* 0xb8 */, 185 /* 0xb9 */, 186 /* 0xba */, 187 /* 0xbb */,
|
184 /* 0xb8 */, 185 /* 0xb9 */, 186 /* 0xba */, 187 /* 0xbb */,
|
||||||
188 /* 0xbc */, 189 /* 0xbd */, 190 /* 0xbe */, 191 /* 0xbf */,
|
188 /* 0xbc */, 189 /* 0xbd */, 190 /* 0xbe */, 191 /* 0xbf */,
|
||||||
192 /* 0xc0 */, 193 /* 0xc1 */, 194 /* 0xc2 */, 195 /* 0xc3 */,
|
192 /* 0xc0 */, 193 /* 0xc1 */, 194 /* 0xc2 */, 195 /* 0xc3 */,
|
||||||
196 /* 0xc4 */, 197 /* 0xc5 */, 198 /* 0xc6 */, 199 /* 0xc7 */,
|
196 /* 0xc4 */, 197 /* 0xc5 */, 198 /* 0xc6 */, 199 /* 0xc7 */,
|
||||||
200 /* 0xc8 */, 201 /* 0xc9 */, 202 /* 0xca */, 203 /* 0xcb */,
|
200 /* 0xc8 */, 201 /* 0xc9 */, 202 /* 0xca */, 203 /* 0xcb */,
|
||||||
204 /* 0xcc */, 205 /* 0xcd */, 206 /* 0xce */, 207 /* 0xcf */,
|
204 /* 0xcc */, 205 /* 0xcd */, 206 /* 0xce */, 207 /* 0xcf */,
|
||||||
208 /* 0xd0 */, 209 /* 0xd1 */, 210 /* 0xd2 */, 211 /* 0xd3 */,
|
208 /* 0xd0 */, 209 /* 0xd1 */, 210 /* 0xd2 */, 211 /* 0xd3 */,
|
||||||
212 /* 0xd4 */, 213 /* 0xd5 */, 214 /* 0xd6 */, 215 /* 0xd7 */,
|
212 /* 0xd4 */, 213 /* 0xd5 */, 214 /* 0xd6 */, 215 /* 0xd7 */,
|
||||||
216 /* 0xd8 */, 217 /* 0xd9 */, 218 /* 0xda */, 219 /* 0xdb */,
|
216 /* 0xd8 */, 217 /* 0xd9 */, 218 /* 0xda */, 219 /* 0xdb */,
|
||||||
220 /* 0xdc */, 221 /* 0xdd */, 222 /* 0xde */, 223 /* 0xdf */,
|
220 /* 0xdc */, 221 /* 0xdd */, 222 /* 0xde */, 223 /* 0xdf */,
|
||||||
224 /* 0xe0 */, 225 /* 0xe1 */, 226 /* 0xe2 */, 227 /* 0xe3 */,
|
224 /* 0xe0 */, 225 /* 0xe1 */, 226 /* 0xe2 */, 227 /* 0xe3 */,
|
||||||
228 /* 0xe4 */, 229 /* 0xe5 */, 230 /* 0xe6 */, 231 /* 0xe7 */,
|
228 /* 0xe4 */, 229 /* 0xe5 */, 230 /* 0xe6 */, 231 /* 0xe7 */,
|
||||||
232 /* 0xe8 */, 233 /* 0xe9 */, 234 /* 0xea */, 235 /* 0xeb */,
|
232 /* 0xe8 */, 233 /* 0xe9 */, 234 /* 0xea */, 235 /* 0xeb */,
|
||||||
236 /* 0xec */, 237 /* 0xed */, 238 /* 0xee */, 239 /* 0xef */,
|
236 /* 0xec */, 237 /* 0xed */, 238 /* 0xee */, 239 /* 0xef */,
|
||||||
240 /* 0xf0 */, 241 /* 0xf1 */, 242 /* 0xf2 */, 243 /* 0xf3 */,
|
240 /* 0xf0 */, 241 /* 0xf1 */, 242 /* 0xf2 */, 243 /* 0xf3 */,
|
||||||
244 /* 0xf4 */, 245 /* 0xf5 */, 246 /* 0xf6 */, 247 /* 0xf7 */,
|
244 /* 0xf4 */, 245 /* 0xf5 */, 246 /* 0xf6 */, 247 /* 0xf7 */,
|
||||||
248 /* 0xf8 */, 249 /* 0xf9 */, 250 /* 0xfa */, 251 /* 0xfb */,
|
248 /* 0xf8 */, 249 /* 0xf9 */, 250 /* 0xfa */, 251 /* 0xfb */,
|
||||||
252 /* 0xfc */, 253 /* 0xfd */, 254 /* 0xfe */, 255 /* 0xff */,
|
252 /* 0xfc */, 253 /* 0xfd */, 254 /* 0xfe */, 255 /* 0xff */,
|
||||||
};
|
};
|
||||||
|
|
||||||
void nghttp2_downcase(uint8_t *s, size_t len) {
|
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 recv_reduction_delta;
|
||||||
int32_t delta;
|
int32_t delta;
|
||||||
int32_t new_recv_window_size =
|
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) {
|
if (new_recv_window_size >= 0) {
|
||||||
*recv_window_size_ptr = new_recv_window_size;
|
*recv_window_size_ptr = new_recv_window_size;
|
||||||
@@ -345,70 +345,70 @@ const char *nghttp2_strerror(int error_code) {
|
|||||||
|
|
||||||
/* Generated by gennmchartbl.py */
|
/* Generated by gennmchartbl.py */
|
||||||
static const int VALID_HD_NAME_CHARS[] = {
|
static const int VALID_HD_NAME_CHARS[] = {
|
||||||
0 /* NUL */, 0 /* SOH */, 0 /* STX */, 0 /* ETX */,
|
0 /* NUL */, 0 /* SOH */, 0 /* STX */, 0 /* ETX */,
|
||||||
0 /* EOT */, 0 /* ENQ */, 0 /* ACK */, 0 /* BEL */,
|
0 /* EOT */, 0 /* ENQ */, 0 /* ACK */, 0 /* BEL */,
|
||||||
0 /* BS */, 0 /* HT */, 0 /* LF */, 0 /* VT */,
|
0 /* BS */, 0 /* HT */, 0 /* LF */, 0 /* VT */,
|
||||||
0 /* FF */, 0 /* CR */, 0 /* SO */, 0 /* SI */,
|
0 /* FF */, 0 /* CR */, 0 /* SO */, 0 /* SI */,
|
||||||
0 /* DLE */, 0 /* DC1 */, 0 /* DC2 */, 0 /* DC3 */,
|
0 /* DLE */, 0 /* DC1 */, 0 /* DC2 */, 0 /* DC3 */,
|
||||||
0 /* DC4 */, 0 /* NAK */, 0 /* SYN */, 0 /* ETB */,
|
0 /* DC4 */, 0 /* NAK */, 0 /* SYN */, 0 /* ETB */,
|
||||||
0 /* CAN */, 0 /* EM */, 0 /* SUB */, 0 /* ESC */,
|
0 /* CAN */, 0 /* EM */, 0 /* SUB */, 0 /* ESC */,
|
||||||
0 /* FS */, 0 /* GS */, 0 /* RS */, 0 /* US */,
|
0 /* FS */, 0 /* GS */, 0 /* RS */, 0 /* US */,
|
||||||
0 /* SPC */, 1 /* ! */, 0 /* " */, 1 /* # */,
|
0 /* SPC */, 1 /* ! */, 0 /* " */, 1 /* # */,
|
||||||
1 /* $ */, 1 /* % */, 1 /* & */, 1 /* ' */,
|
1 /* $ */, 1 /* % */, 1 /* & */, 1 /* ' */,
|
||||||
0 /* ( */, 0 /* ) */, 1 /* * */, 1 /* + */,
|
0 /* ( */, 0 /* ) */, 1 /* * */, 1 /* + */,
|
||||||
0 /* , */, 1 /* - */, 1 /* . */, 0 /* / */,
|
0 /* , */, 1 /* - */, 1 /* . */, 0 /* / */,
|
||||||
1 /* 0 */, 1 /* 1 */, 1 /* 2 */, 1 /* 3 */,
|
1 /* 0 */, 1 /* 1 */, 1 /* 2 */, 1 /* 3 */,
|
||||||
1 /* 4 */, 1 /* 5 */, 1 /* 6 */, 1 /* 7 */,
|
1 /* 4 */, 1 /* 5 */, 1 /* 6 */, 1 /* 7 */,
|
||||||
1 /* 8 */, 1 /* 9 */, 0 /* : */, 0 /* ; */,
|
1 /* 8 */, 1 /* 9 */, 0 /* : */, 0 /* ; */,
|
||||||
0 /* < */, 0 /* = */, 0 /* > */, 0 /* ? */,
|
0 /* < */, 0 /* = */, 0 /* > */, 0 /* ? */,
|
||||||
0 /* @ */, 0 /* A */, 0 /* B */, 0 /* C */,
|
0 /* @ */, 0 /* A */, 0 /* B */, 0 /* C */,
|
||||||
0 /* D */, 0 /* E */, 0 /* F */, 0 /* G */,
|
0 /* D */, 0 /* E */, 0 /* F */, 0 /* G */,
|
||||||
0 /* H */, 0 /* I */, 0 /* J */, 0 /* K */,
|
0 /* H */, 0 /* I */, 0 /* J */, 0 /* K */,
|
||||||
0 /* L */, 0 /* M */, 0 /* N */, 0 /* O */,
|
0 /* L */, 0 /* M */, 0 /* N */, 0 /* O */,
|
||||||
0 /* P */, 0 /* Q */, 0 /* R */, 0 /* S */,
|
0 /* P */, 0 /* Q */, 0 /* R */, 0 /* S */,
|
||||||
0 /* T */, 0 /* U */, 0 /* V */, 0 /* W */,
|
0 /* T */, 0 /* U */, 0 /* V */, 0 /* W */,
|
||||||
0 /* X */, 0 /* Y */, 0 /* Z */, 0 /* [ */,
|
0 /* X */, 0 /* Y */, 0 /* Z */, 0 /* [ */,
|
||||||
0 /* \ */, 0 /* ] */, 1 /* ^ */, 1 /* _ */,
|
0 /* \ */, 0 /* ] */, 1 /* ^ */, 1 /* _ */,
|
||||||
1 /* ` */, 1 /* a */, 1 /* b */, 1 /* c */,
|
1 /* ` */, 1 /* a */, 1 /* b */, 1 /* c */,
|
||||||
1 /* d */, 1 /* e */, 1 /* f */, 1 /* g */,
|
1 /* d */, 1 /* e */, 1 /* f */, 1 /* g */,
|
||||||
1 /* h */, 1 /* i */, 1 /* j */, 1 /* k */,
|
1 /* h */, 1 /* i */, 1 /* j */, 1 /* k */,
|
||||||
1 /* l */, 1 /* m */, 1 /* n */, 1 /* o */,
|
1 /* l */, 1 /* m */, 1 /* n */, 1 /* o */,
|
||||||
1 /* p */, 1 /* q */, 1 /* r */, 1 /* s */,
|
1 /* p */, 1 /* q */, 1 /* r */, 1 /* s */,
|
||||||
1 /* t */, 1 /* u */, 1 /* v */, 1 /* w */,
|
1 /* t */, 1 /* u */, 1 /* v */, 1 /* w */,
|
||||||
1 /* x */, 1 /* y */, 1 /* z */, 0 /* { */,
|
1 /* x */, 1 /* y */, 1 /* z */, 0 /* { */,
|
||||||
1 /* | */, 0 /* } */, 1 /* ~ */, 0 /* DEL */,
|
1 /* | */, 0 /* } */, 1 /* ~ */, 0 /* DEL */,
|
||||||
0 /* 0x80 */, 0 /* 0x81 */, 0 /* 0x82 */, 0 /* 0x83 */,
|
0 /* 0x80 */, 0 /* 0x81 */, 0 /* 0x82 */, 0 /* 0x83 */,
|
||||||
0 /* 0x84 */, 0 /* 0x85 */, 0 /* 0x86 */, 0 /* 0x87 */,
|
0 /* 0x84 */, 0 /* 0x85 */, 0 /* 0x86 */, 0 /* 0x87 */,
|
||||||
0 /* 0x88 */, 0 /* 0x89 */, 0 /* 0x8a */, 0 /* 0x8b */,
|
0 /* 0x88 */, 0 /* 0x89 */, 0 /* 0x8a */, 0 /* 0x8b */,
|
||||||
0 /* 0x8c */, 0 /* 0x8d */, 0 /* 0x8e */, 0 /* 0x8f */,
|
0 /* 0x8c */, 0 /* 0x8d */, 0 /* 0x8e */, 0 /* 0x8f */,
|
||||||
0 /* 0x90 */, 0 /* 0x91 */, 0 /* 0x92 */, 0 /* 0x93 */,
|
0 /* 0x90 */, 0 /* 0x91 */, 0 /* 0x92 */, 0 /* 0x93 */,
|
||||||
0 /* 0x94 */, 0 /* 0x95 */, 0 /* 0x96 */, 0 /* 0x97 */,
|
0 /* 0x94 */, 0 /* 0x95 */, 0 /* 0x96 */, 0 /* 0x97 */,
|
||||||
0 /* 0x98 */, 0 /* 0x99 */, 0 /* 0x9a */, 0 /* 0x9b */,
|
0 /* 0x98 */, 0 /* 0x99 */, 0 /* 0x9a */, 0 /* 0x9b */,
|
||||||
0 /* 0x9c */, 0 /* 0x9d */, 0 /* 0x9e */, 0 /* 0x9f */,
|
0 /* 0x9c */, 0 /* 0x9d */, 0 /* 0x9e */, 0 /* 0x9f */,
|
||||||
0 /* 0xa0 */, 0 /* 0xa1 */, 0 /* 0xa2 */, 0 /* 0xa3 */,
|
0 /* 0xa0 */, 0 /* 0xa1 */, 0 /* 0xa2 */, 0 /* 0xa3 */,
|
||||||
0 /* 0xa4 */, 0 /* 0xa5 */, 0 /* 0xa6 */, 0 /* 0xa7 */,
|
0 /* 0xa4 */, 0 /* 0xa5 */, 0 /* 0xa6 */, 0 /* 0xa7 */,
|
||||||
0 /* 0xa8 */, 0 /* 0xa9 */, 0 /* 0xaa */, 0 /* 0xab */,
|
0 /* 0xa8 */, 0 /* 0xa9 */, 0 /* 0xaa */, 0 /* 0xab */,
|
||||||
0 /* 0xac */, 0 /* 0xad */, 0 /* 0xae */, 0 /* 0xaf */,
|
0 /* 0xac */, 0 /* 0xad */, 0 /* 0xae */, 0 /* 0xaf */,
|
||||||
0 /* 0xb0 */, 0 /* 0xb1 */, 0 /* 0xb2 */, 0 /* 0xb3 */,
|
0 /* 0xb0 */, 0 /* 0xb1 */, 0 /* 0xb2 */, 0 /* 0xb3 */,
|
||||||
0 /* 0xb4 */, 0 /* 0xb5 */, 0 /* 0xb6 */, 0 /* 0xb7 */,
|
0 /* 0xb4 */, 0 /* 0xb5 */, 0 /* 0xb6 */, 0 /* 0xb7 */,
|
||||||
0 /* 0xb8 */, 0 /* 0xb9 */, 0 /* 0xba */, 0 /* 0xbb */,
|
0 /* 0xb8 */, 0 /* 0xb9 */, 0 /* 0xba */, 0 /* 0xbb */,
|
||||||
0 /* 0xbc */, 0 /* 0xbd */, 0 /* 0xbe */, 0 /* 0xbf */,
|
0 /* 0xbc */, 0 /* 0xbd */, 0 /* 0xbe */, 0 /* 0xbf */,
|
||||||
0 /* 0xc0 */, 0 /* 0xc1 */, 0 /* 0xc2 */, 0 /* 0xc3 */,
|
0 /* 0xc0 */, 0 /* 0xc1 */, 0 /* 0xc2 */, 0 /* 0xc3 */,
|
||||||
0 /* 0xc4 */, 0 /* 0xc5 */, 0 /* 0xc6 */, 0 /* 0xc7 */,
|
0 /* 0xc4 */, 0 /* 0xc5 */, 0 /* 0xc6 */, 0 /* 0xc7 */,
|
||||||
0 /* 0xc8 */, 0 /* 0xc9 */, 0 /* 0xca */, 0 /* 0xcb */,
|
0 /* 0xc8 */, 0 /* 0xc9 */, 0 /* 0xca */, 0 /* 0xcb */,
|
||||||
0 /* 0xcc */, 0 /* 0xcd */, 0 /* 0xce */, 0 /* 0xcf */,
|
0 /* 0xcc */, 0 /* 0xcd */, 0 /* 0xce */, 0 /* 0xcf */,
|
||||||
0 /* 0xd0 */, 0 /* 0xd1 */, 0 /* 0xd2 */, 0 /* 0xd3 */,
|
0 /* 0xd0 */, 0 /* 0xd1 */, 0 /* 0xd2 */, 0 /* 0xd3 */,
|
||||||
0 /* 0xd4 */, 0 /* 0xd5 */, 0 /* 0xd6 */, 0 /* 0xd7 */,
|
0 /* 0xd4 */, 0 /* 0xd5 */, 0 /* 0xd6 */, 0 /* 0xd7 */,
|
||||||
0 /* 0xd8 */, 0 /* 0xd9 */, 0 /* 0xda */, 0 /* 0xdb */,
|
0 /* 0xd8 */, 0 /* 0xd9 */, 0 /* 0xda */, 0 /* 0xdb */,
|
||||||
0 /* 0xdc */, 0 /* 0xdd */, 0 /* 0xde */, 0 /* 0xdf */,
|
0 /* 0xdc */, 0 /* 0xdd */, 0 /* 0xde */, 0 /* 0xdf */,
|
||||||
0 /* 0xe0 */, 0 /* 0xe1 */, 0 /* 0xe2 */, 0 /* 0xe3 */,
|
0 /* 0xe0 */, 0 /* 0xe1 */, 0 /* 0xe2 */, 0 /* 0xe3 */,
|
||||||
0 /* 0xe4 */, 0 /* 0xe5 */, 0 /* 0xe6 */, 0 /* 0xe7 */,
|
0 /* 0xe4 */, 0 /* 0xe5 */, 0 /* 0xe6 */, 0 /* 0xe7 */,
|
||||||
0 /* 0xe8 */, 0 /* 0xe9 */, 0 /* 0xea */, 0 /* 0xeb */,
|
0 /* 0xe8 */, 0 /* 0xe9 */, 0 /* 0xea */, 0 /* 0xeb */,
|
||||||
0 /* 0xec */, 0 /* 0xed */, 0 /* 0xee */, 0 /* 0xef */,
|
0 /* 0xec */, 0 /* 0xed */, 0 /* 0xee */, 0 /* 0xef */,
|
||||||
0 /* 0xf0 */, 0 /* 0xf1 */, 0 /* 0xf2 */, 0 /* 0xf3 */,
|
0 /* 0xf0 */, 0 /* 0xf1 */, 0 /* 0xf2 */, 0 /* 0xf3 */,
|
||||||
0 /* 0xf4 */, 0 /* 0xf5 */, 0 /* 0xf6 */, 0 /* 0xf7 */,
|
0 /* 0xf4 */, 0 /* 0xf5 */, 0 /* 0xf6 */, 0 /* 0xf7 */,
|
||||||
0 /* 0xf8 */, 0 /* 0xf9 */, 0 /* 0xfa */, 0 /* 0xfb */,
|
0 /* 0xf8 */, 0 /* 0xf9 */, 0 /* 0xfa */, 0 /* 0xfb */,
|
||||||
0 /* 0xfc */, 0 /* 0xfd */, 0 /* 0xfe */, 0 /* 0xff */
|
0 /* 0xfc */, 0 /* 0xfd */, 0 /* 0xfe */, 0 /* 0xff */
|
||||||
};
|
};
|
||||||
|
|
||||||
int nghttp2_check_header_name(const uint8_t *name, size_t len) {
|
int nghttp2_check_header_name(const uint8_t *name, size_t len) {
|
||||||
@@ -433,70 +433,70 @@ int nghttp2_check_header_name(const uint8_t *name, size_t len) {
|
|||||||
|
|
||||||
/* Generated by genvchartbl.py */
|
/* Generated by genvchartbl.py */
|
||||||
static const int VALID_HD_VALUE_CHARS[] = {
|
static const int VALID_HD_VALUE_CHARS[] = {
|
||||||
0 /* NUL */, 0 /* SOH */, 0 /* STX */, 0 /* ETX */,
|
0 /* NUL */, 0 /* SOH */, 0 /* STX */, 0 /* ETX */,
|
||||||
0 /* EOT */, 0 /* ENQ */, 0 /* ACK */, 0 /* BEL */,
|
0 /* EOT */, 0 /* ENQ */, 0 /* ACK */, 0 /* BEL */,
|
||||||
0 /* BS */, 1 /* HT */, 0 /* LF */, 0 /* VT */,
|
0 /* BS */, 1 /* HT */, 0 /* LF */, 0 /* VT */,
|
||||||
0 /* FF */, 0 /* CR */, 0 /* SO */, 0 /* SI */,
|
0 /* FF */, 0 /* CR */, 0 /* SO */, 0 /* SI */,
|
||||||
0 /* DLE */, 0 /* DC1 */, 0 /* DC2 */, 0 /* DC3 */,
|
0 /* DLE */, 0 /* DC1 */, 0 /* DC2 */, 0 /* DC3 */,
|
||||||
0 /* DC4 */, 0 /* NAK */, 0 /* SYN */, 0 /* ETB */,
|
0 /* DC4 */, 0 /* NAK */, 0 /* SYN */, 0 /* ETB */,
|
||||||
0 /* CAN */, 0 /* EM */, 0 /* SUB */, 0 /* ESC */,
|
0 /* CAN */, 0 /* EM */, 0 /* SUB */, 0 /* ESC */,
|
||||||
0 /* FS */, 0 /* GS */, 0 /* RS */, 0 /* US */,
|
0 /* FS */, 0 /* GS */, 0 /* RS */, 0 /* US */,
|
||||||
1 /* SPC */, 1 /* ! */, 1 /* " */, 1 /* # */,
|
1 /* SPC */, 1 /* ! */, 1 /* " */, 1 /* # */,
|
||||||
1 /* $ */, 1 /* % */, 1 /* & */, 1 /* ' */,
|
1 /* $ */, 1 /* % */, 1 /* & */, 1 /* ' */,
|
||||||
1 /* ( */, 1 /* ) */, 1 /* * */, 1 /* + */,
|
1 /* ( */, 1 /* ) */, 1 /* * */, 1 /* + */,
|
||||||
1 /* , */, 1 /* - */, 1 /* . */, 1 /* / */,
|
1 /* , */, 1 /* - */, 1 /* . */, 1 /* / */,
|
||||||
1 /* 0 */, 1 /* 1 */, 1 /* 2 */, 1 /* 3 */,
|
1 /* 0 */, 1 /* 1 */, 1 /* 2 */, 1 /* 3 */,
|
||||||
1 /* 4 */, 1 /* 5 */, 1 /* 6 */, 1 /* 7 */,
|
1 /* 4 */, 1 /* 5 */, 1 /* 6 */, 1 /* 7 */,
|
||||||
1 /* 8 */, 1 /* 9 */, 1 /* : */, 1 /* ; */,
|
1 /* 8 */, 1 /* 9 */, 1 /* : */, 1 /* ; */,
|
||||||
1 /* < */, 1 /* = */, 1 /* > */, 1 /* ? */,
|
1 /* < */, 1 /* = */, 1 /* > */, 1 /* ? */,
|
||||||
1 /* @ */, 1 /* A */, 1 /* B */, 1 /* C */,
|
1 /* @ */, 1 /* A */, 1 /* B */, 1 /* C */,
|
||||||
1 /* D */, 1 /* E */, 1 /* F */, 1 /* G */,
|
1 /* D */, 1 /* E */, 1 /* F */, 1 /* G */,
|
||||||
1 /* H */, 1 /* I */, 1 /* J */, 1 /* K */,
|
1 /* H */, 1 /* I */, 1 /* J */, 1 /* K */,
|
||||||
1 /* L */, 1 /* M */, 1 /* N */, 1 /* O */,
|
1 /* L */, 1 /* M */, 1 /* N */, 1 /* O */,
|
||||||
1 /* P */, 1 /* Q */, 1 /* R */, 1 /* S */,
|
1 /* P */, 1 /* Q */, 1 /* R */, 1 /* S */,
|
||||||
1 /* T */, 1 /* U */, 1 /* V */, 1 /* W */,
|
1 /* T */, 1 /* U */, 1 /* V */, 1 /* W */,
|
||||||
1 /* X */, 1 /* Y */, 1 /* Z */, 1 /* [ */,
|
1 /* X */, 1 /* Y */, 1 /* Z */, 1 /* [ */,
|
||||||
1 /* \ */, 1 /* ] */, 1 /* ^ */, 1 /* _ */,
|
1 /* \ */, 1 /* ] */, 1 /* ^ */, 1 /* _ */,
|
||||||
1 /* ` */, 1 /* a */, 1 /* b */, 1 /* c */,
|
1 /* ` */, 1 /* a */, 1 /* b */, 1 /* c */,
|
||||||
1 /* d */, 1 /* e */, 1 /* f */, 1 /* g */,
|
1 /* d */, 1 /* e */, 1 /* f */, 1 /* g */,
|
||||||
1 /* h */, 1 /* i */, 1 /* j */, 1 /* k */,
|
1 /* h */, 1 /* i */, 1 /* j */, 1 /* k */,
|
||||||
1 /* l */, 1 /* m */, 1 /* n */, 1 /* o */,
|
1 /* l */, 1 /* m */, 1 /* n */, 1 /* o */,
|
||||||
1 /* p */, 1 /* q */, 1 /* r */, 1 /* s */,
|
1 /* p */, 1 /* q */, 1 /* r */, 1 /* s */,
|
||||||
1 /* t */, 1 /* u */, 1 /* v */, 1 /* w */,
|
1 /* t */, 1 /* u */, 1 /* v */, 1 /* w */,
|
||||||
1 /* x */, 1 /* y */, 1 /* z */, 1 /* { */,
|
1 /* x */, 1 /* y */, 1 /* z */, 1 /* { */,
|
||||||
1 /* | */, 1 /* } */, 1 /* ~ */, 0 /* DEL */,
|
1 /* | */, 1 /* } */, 1 /* ~ */, 0 /* DEL */,
|
||||||
1 /* 0x80 */, 1 /* 0x81 */, 1 /* 0x82 */, 1 /* 0x83 */,
|
1 /* 0x80 */, 1 /* 0x81 */, 1 /* 0x82 */, 1 /* 0x83 */,
|
||||||
1 /* 0x84 */, 1 /* 0x85 */, 1 /* 0x86 */, 1 /* 0x87 */,
|
1 /* 0x84 */, 1 /* 0x85 */, 1 /* 0x86 */, 1 /* 0x87 */,
|
||||||
1 /* 0x88 */, 1 /* 0x89 */, 1 /* 0x8a */, 1 /* 0x8b */,
|
1 /* 0x88 */, 1 /* 0x89 */, 1 /* 0x8a */, 1 /* 0x8b */,
|
||||||
1 /* 0x8c */, 1 /* 0x8d */, 1 /* 0x8e */, 1 /* 0x8f */,
|
1 /* 0x8c */, 1 /* 0x8d */, 1 /* 0x8e */, 1 /* 0x8f */,
|
||||||
1 /* 0x90 */, 1 /* 0x91 */, 1 /* 0x92 */, 1 /* 0x93 */,
|
1 /* 0x90 */, 1 /* 0x91 */, 1 /* 0x92 */, 1 /* 0x93 */,
|
||||||
1 /* 0x94 */, 1 /* 0x95 */, 1 /* 0x96 */, 1 /* 0x97 */,
|
1 /* 0x94 */, 1 /* 0x95 */, 1 /* 0x96 */, 1 /* 0x97 */,
|
||||||
1 /* 0x98 */, 1 /* 0x99 */, 1 /* 0x9a */, 1 /* 0x9b */,
|
1 /* 0x98 */, 1 /* 0x99 */, 1 /* 0x9a */, 1 /* 0x9b */,
|
||||||
1 /* 0x9c */, 1 /* 0x9d */, 1 /* 0x9e */, 1 /* 0x9f */,
|
1 /* 0x9c */, 1 /* 0x9d */, 1 /* 0x9e */, 1 /* 0x9f */,
|
||||||
1 /* 0xa0 */, 1 /* 0xa1 */, 1 /* 0xa2 */, 1 /* 0xa3 */,
|
1 /* 0xa0 */, 1 /* 0xa1 */, 1 /* 0xa2 */, 1 /* 0xa3 */,
|
||||||
1 /* 0xa4 */, 1 /* 0xa5 */, 1 /* 0xa6 */, 1 /* 0xa7 */,
|
1 /* 0xa4 */, 1 /* 0xa5 */, 1 /* 0xa6 */, 1 /* 0xa7 */,
|
||||||
1 /* 0xa8 */, 1 /* 0xa9 */, 1 /* 0xaa */, 1 /* 0xab */,
|
1 /* 0xa8 */, 1 /* 0xa9 */, 1 /* 0xaa */, 1 /* 0xab */,
|
||||||
1 /* 0xac */, 1 /* 0xad */, 1 /* 0xae */, 1 /* 0xaf */,
|
1 /* 0xac */, 1 /* 0xad */, 1 /* 0xae */, 1 /* 0xaf */,
|
||||||
1 /* 0xb0 */, 1 /* 0xb1 */, 1 /* 0xb2 */, 1 /* 0xb3 */,
|
1 /* 0xb0 */, 1 /* 0xb1 */, 1 /* 0xb2 */, 1 /* 0xb3 */,
|
||||||
1 /* 0xb4 */, 1 /* 0xb5 */, 1 /* 0xb6 */, 1 /* 0xb7 */,
|
1 /* 0xb4 */, 1 /* 0xb5 */, 1 /* 0xb6 */, 1 /* 0xb7 */,
|
||||||
1 /* 0xb8 */, 1 /* 0xb9 */, 1 /* 0xba */, 1 /* 0xbb */,
|
1 /* 0xb8 */, 1 /* 0xb9 */, 1 /* 0xba */, 1 /* 0xbb */,
|
||||||
1 /* 0xbc */, 1 /* 0xbd */, 1 /* 0xbe */, 1 /* 0xbf */,
|
1 /* 0xbc */, 1 /* 0xbd */, 1 /* 0xbe */, 1 /* 0xbf */,
|
||||||
1 /* 0xc0 */, 1 /* 0xc1 */, 1 /* 0xc2 */, 1 /* 0xc3 */,
|
1 /* 0xc0 */, 1 /* 0xc1 */, 1 /* 0xc2 */, 1 /* 0xc3 */,
|
||||||
1 /* 0xc4 */, 1 /* 0xc5 */, 1 /* 0xc6 */, 1 /* 0xc7 */,
|
1 /* 0xc4 */, 1 /* 0xc5 */, 1 /* 0xc6 */, 1 /* 0xc7 */,
|
||||||
1 /* 0xc8 */, 1 /* 0xc9 */, 1 /* 0xca */, 1 /* 0xcb */,
|
1 /* 0xc8 */, 1 /* 0xc9 */, 1 /* 0xca */, 1 /* 0xcb */,
|
||||||
1 /* 0xcc */, 1 /* 0xcd */, 1 /* 0xce */, 1 /* 0xcf */,
|
1 /* 0xcc */, 1 /* 0xcd */, 1 /* 0xce */, 1 /* 0xcf */,
|
||||||
1 /* 0xd0 */, 1 /* 0xd1 */, 1 /* 0xd2 */, 1 /* 0xd3 */,
|
1 /* 0xd0 */, 1 /* 0xd1 */, 1 /* 0xd2 */, 1 /* 0xd3 */,
|
||||||
1 /* 0xd4 */, 1 /* 0xd5 */, 1 /* 0xd6 */, 1 /* 0xd7 */,
|
1 /* 0xd4 */, 1 /* 0xd5 */, 1 /* 0xd6 */, 1 /* 0xd7 */,
|
||||||
1 /* 0xd8 */, 1 /* 0xd9 */, 1 /* 0xda */, 1 /* 0xdb */,
|
1 /* 0xd8 */, 1 /* 0xd9 */, 1 /* 0xda */, 1 /* 0xdb */,
|
||||||
1 /* 0xdc */, 1 /* 0xdd */, 1 /* 0xde */, 1 /* 0xdf */,
|
1 /* 0xdc */, 1 /* 0xdd */, 1 /* 0xde */, 1 /* 0xdf */,
|
||||||
1 /* 0xe0 */, 1 /* 0xe1 */, 1 /* 0xe2 */, 1 /* 0xe3 */,
|
1 /* 0xe0 */, 1 /* 0xe1 */, 1 /* 0xe2 */, 1 /* 0xe3 */,
|
||||||
1 /* 0xe4 */, 1 /* 0xe5 */, 1 /* 0xe6 */, 1 /* 0xe7 */,
|
1 /* 0xe4 */, 1 /* 0xe5 */, 1 /* 0xe6 */, 1 /* 0xe7 */,
|
||||||
1 /* 0xe8 */, 1 /* 0xe9 */, 1 /* 0xea */, 1 /* 0xeb */,
|
1 /* 0xe8 */, 1 /* 0xe9 */, 1 /* 0xea */, 1 /* 0xeb */,
|
||||||
1 /* 0xec */, 1 /* 0xed */, 1 /* 0xee */, 1 /* 0xef */,
|
1 /* 0xec */, 1 /* 0xed */, 1 /* 0xee */, 1 /* 0xef */,
|
||||||
1 /* 0xf0 */, 1 /* 0xf1 */, 1 /* 0xf2 */, 1 /* 0xf3 */,
|
1 /* 0xf0 */, 1 /* 0xf1 */, 1 /* 0xf2 */, 1 /* 0xf3 */,
|
||||||
1 /* 0xf4 */, 1 /* 0xf5 */, 1 /* 0xf6 */, 1 /* 0xf7 */,
|
1 /* 0xf4 */, 1 /* 0xf5 */, 1 /* 0xf6 */, 1 /* 0xf7 */,
|
||||||
1 /* 0xf8 */, 1 /* 0xf9 */, 1 /* 0xfa */, 1 /* 0xfb */,
|
1 /* 0xf8 */, 1 /* 0xf9 */, 1 /* 0xfa */, 1 /* 0xfb */,
|
||||||
1 /* 0xfc */, 1 /* 0xfd */, 1 /* 0xfe */, 1 /* 0xff */
|
1 /* 0xfc */, 1 /* 0xfd */, 1 /* 0xfe */, 1 /* 0xff */
|
||||||
};
|
};
|
||||||
|
|
||||||
int nghttp2_check_header_value(const uint8_t *value, size_t len) {
|
int nghttp2_check_header_value(const uint8_t *value, size_t len) {
|
||||||
@@ -524,70 +524,70 @@ int nghttp2_check_header_value_rfc9113(const uint8_t *value, size_t len) {
|
|||||||
|
|
||||||
/* Generated by genmethodchartbl.py */
|
/* Generated by genmethodchartbl.py */
|
||||||
static char VALID_METHOD_CHARS[] = {
|
static char VALID_METHOD_CHARS[] = {
|
||||||
0 /* NUL */, 0 /* SOH */, 0 /* STX */, 0 /* ETX */,
|
0 /* NUL */, 0 /* SOH */, 0 /* STX */, 0 /* ETX */,
|
||||||
0 /* EOT */, 0 /* ENQ */, 0 /* ACK */, 0 /* BEL */,
|
0 /* EOT */, 0 /* ENQ */, 0 /* ACK */, 0 /* BEL */,
|
||||||
0 /* BS */, 0 /* HT */, 0 /* LF */, 0 /* VT */,
|
0 /* BS */, 0 /* HT */, 0 /* LF */, 0 /* VT */,
|
||||||
0 /* FF */, 0 /* CR */, 0 /* SO */, 0 /* SI */,
|
0 /* FF */, 0 /* CR */, 0 /* SO */, 0 /* SI */,
|
||||||
0 /* DLE */, 0 /* DC1 */, 0 /* DC2 */, 0 /* DC3 */,
|
0 /* DLE */, 0 /* DC1 */, 0 /* DC2 */, 0 /* DC3 */,
|
||||||
0 /* DC4 */, 0 /* NAK */, 0 /* SYN */, 0 /* ETB */,
|
0 /* DC4 */, 0 /* NAK */, 0 /* SYN */, 0 /* ETB */,
|
||||||
0 /* CAN */, 0 /* EM */, 0 /* SUB */, 0 /* ESC */,
|
0 /* CAN */, 0 /* EM */, 0 /* SUB */, 0 /* ESC */,
|
||||||
0 /* FS */, 0 /* GS */, 0 /* RS */, 0 /* US */,
|
0 /* FS */, 0 /* GS */, 0 /* RS */, 0 /* US */,
|
||||||
0 /* SPC */, 1 /* ! */, 0 /* " */, 1 /* # */,
|
0 /* SPC */, 1 /* ! */, 0 /* " */, 1 /* # */,
|
||||||
1 /* $ */, 1 /* % */, 1 /* & */, 1 /* ' */,
|
1 /* $ */, 1 /* % */, 1 /* & */, 1 /* ' */,
|
||||||
0 /* ( */, 0 /* ) */, 1 /* * */, 1 /* + */,
|
0 /* ( */, 0 /* ) */, 1 /* * */, 1 /* + */,
|
||||||
0 /* , */, 1 /* - */, 1 /* . */, 0 /* / */,
|
0 /* , */, 1 /* - */, 1 /* . */, 0 /* / */,
|
||||||
1 /* 0 */, 1 /* 1 */, 1 /* 2 */, 1 /* 3 */,
|
1 /* 0 */, 1 /* 1 */, 1 /* 2 */, 1 /* 3 */,
|
||||||
1 /* 4 */, 1 /* 5 */, 1 /* 6 */, 1 /* 7 */,
|
1 /* 4 */, 1 /* 5 */, 1 /* 6 */, 1 /* 7 */,
|
||||||
1 /* 8 */, 1 /* 9 */, 0 /* : */, 0 /* ; */,
|
1 /* 8 */, 1 /* 9 */, 0 /* : */, 0 /* ; */,
|
||||||
0 /* < */, 0 /* = */, 0 /* > */, 0 /* ? */,
|
0 /* < */, 0 /* = */, 0 /* > */, 0 /* ? */,
|
||||||
0 /* @ */, 1 /* A */, 1 /* B */, 1 /* C */,
|
0 /* @ */, 1 /* A */, 1 /* B */, 1 /* C */,
|
||||||
1 /* D */, 1 /* E */, 1 /* F */, 1 /* G */,
|
1 /* D */, 1 /* E */, 1 /* F */, 1 /* G */,
|
||||||
1 /* H */, 1 /* I */, 1 /* J */, 1 /* K */,
|
1 /* H */, 1 /* I */, 1 /* J */, 1 /* K */,
|
||||||
1 /* L */, 1 /* M */, 1 /* N */, 1 /* O */,
|
1 /* L */, 1 /* M */, 1 /* N */, 1 /* O */,
|
||||||
1 /* P */, 1 /* Q */, 1 /* R */, 1 /* S */,
|
1 /* P */, 1 /* Q */, 1 /* R */, 1 /* S */,
|
||||||
1 /* T */, 1 /* U */, 1 /* V */, 1 /* W */,
|
1 /* T */, 1 /* U */, 1 /* V */, 1 /* W */,
|
||||||
1 /* X */, 1 /* Y */, 1 /* Z */, 0 /* [ */,
|
1 /* X */, 1 /* Y */, 1 /* Z */, 0 /* [ */,
|
||||||
0 /* \ */, 0 /* ] */, 1 /* ^ */, 1 /* _ */,
|
0 /* \ */, 0 /* ] */, 1 /* ^ */, 1 /* _ */,
|
||||||
1 /* ` */, 1 /* a */, 1 /* b */, 1 /* c */,
|
1 /* ` */, 1 /* a */, 1 /* b */, 1 /* c */,
|
||||||
1 /* d */, 1 /* e */, 1 /* f */, 1 /* g */,
|
1 /* d */, 1 /* e */, 1 /* f */, 1 /* g */,
|
||||||
1 /* h */, 1 /* i */, 1 /* j */, 1 /* k */,
|
1 /* h */, 1 /* i */, 1 /* j */, 1 /* k */,
|
||||||
1 /* l */, 1 /* m */, 1 /* n */, 1 /* o */,
|
1 /* l */, 1 /* m */, 1 /* n */, 1 /* o */,
|
||||||
1 /* p */, 1 /* q */, 1 /* r */, 1 /* s */,
|
1 /* p */, 1 /* q */, 1 /* r */, 1 /* s */,
|
||||||
1 /* t */, 1 /* u */, 1 /* v */, 1 /* w */,
|
1 /* t */, 1 /* u */, 1 /* v */, 1 /* w */,
|
||||||
1 /* x */, 1 /* y */, 1 /* z */, 0 /* { */,
|
1 /* x */, 1 /* y */, 1 /* z */, 0 /* { */,
|
||||||
1 /* | */, 0 /* } */, 1 /* ~ */, 0 /* DEL */,
|
1 /* | */, 0 /* } */, 1 /* ~ */, 0 /* DEL */,
|
||||||
0 /* 0x80 */, 0 /* 0x81 */, 0 /* 0x82 */, 0 /* 0x83 */,
|
0 /* 0x80 */, 0 /* 0x81 */, 0 /* 0x82 */, 0 /* 0x83 */,
|
||||||
0 /* 0x84 */, 0 /* 0x85 */, 0 /* 0x86 */, 0 /* 0x87 */,
|
0 /* 0x84 */, 0 /* 0x85 */, 0 /* 0x86 */, 0 /* 0x87 */,
|
||||||
0 /* 0x88 */, 0 /* 0x89 */, 0 /* 0x8a */, 0 /* 0x8b */,
|
0 /* 0x88 */, 0 /* 0x89 */, 0 /* 0x8a */, 0 /* 0x8b */,
|
||||||
0 /* 0x8c */, 0 /* 0x8d */, 0 /* 0x8e */, 0 /* 0x8f */,
|
0 /* 0x8c */, 0 /* 0x8d */, 0 /* 0x8e */, 0 /* 0x8f */,
|
||||||
0 /* 0x90 */, 0 /* 0x91 */, 0 /* 0x92 */, 0 /* 0x93 */,
|
0 /* 0x90 */, 0 /* 0x91 */, 0 /* 0x92 */, 0 /* 0x93 */,
|
||||||
0 /* 0x94 */, 0 /* 0x95 */, 0 /* 0x96 */, 0 /* 0x97 */,
|
0 /* 0x94 */, 0 /* 0x95 */, 0 /* 0x96 */, 0 /* 0x97 */,
|
||||||
0 /* 0x98 */, 0 /* 0x99 */, 0 /* 0x9a */, 0 /* 0x9b */,
|
0 /* 0x98 */, 0 /* 0x99 */, 0 /* 0x9a */, 0 /* 0x9b */,
|
||||||
0 /* 0x9c */, 0 /* 0x9d */, 0 /* 0x9e */, 0 /* 0x9f */,
|
0 /* 0x9c */, 0 /* 0x9d */, 0 /* 0x9e */, 0 /* 0x9f */,
|
||||||
0 /* 0xa0 */, 0 /* 0xa1 */, 0 /* 0xa2 */, 0 /* 0xa3 */,
|
0 /* 0xa0 */, 0 /* 0xa1 */, 0 /* 0xa2 */, 0 /* 0xa3 */,
|
||||||
0 /* 0xa4 */, 0 /* 0xa5 */, 0 /* 0xa6 */, 0 /* 0xa7 */,
|
0 /* 0xa4 */, 0 /* 0xa5 */, 0 /* 0xa6 */, 0 /* 0xa7 */,
|
||||||
0 /* 0xa8 */, 0 /* 0xa9 */, 0 /* 0xaa */, 0 /* 0xab */,
|
0 /* 0xa8 */, 0 /* 0xa9 */, 0 /* 0xaa */, 0 /* 0xab */,
|
||||||
0 /* 0xac */, 0 /* 0xad */, 0 /* 0xae */, 0 /* 0xaf */,
|
0 /* 0xac */, 0 /* 0xad */, 0 /* 0xae */, 0 /* 0xaf */,
|
||||||
0 /* 0xb0 */, 0 /* 0xb1 */, 0 /* 0xb2 */, 0 /* 0xb3 */,
|
0 /* 0xb0 */, 0 /* 0xb1 */, 0 /* 0xb2 */, 0 /* 0xb3 */,
|
||||||
0 /* 0xb4 */, 0 /* 0xb5 */, 0 /* 0xb6 */, 0 /* 0xb7 */,
|
0 /* 0xb4 */, 0 /* 0xb5 */, 0 /* 0xb6 */, 0 /* 0xb7 */,
|
||||||
0 /* 0xb8 */, 0 /* 0xb9 */, 0 /* 0xba */, 0 /* 0xbb */,
|
0 /* 0xb8 */, 0 /* 0xb9 */, 0 /* 0xba */, 0 /* 0xbb */,
|
||||||
0 /* 0xbc */, 0 /* 0xbd */, 0 /* 0xbe */, 0 /* 0xbf */,
|
0 /* 0xbc */, 0 /* 0xbd */, 0 /* 0xbe */, 0 /* 0xbf */,
|
||||||
0 /* 0xc0 */, 0 /* 0xc1 */, 0 /* 0xc2 */, 0 /* 0xc3 */,
|
0 /* 0xc0 */, 0 /* 0xc1 */, 0 /* 0xc2 */, 0 /* 0xc3 */,
|
||||||
0 /* 0xc4 */, 0 /* 0xc5 */, 0 /* 0xc6 */, 0 /* 0xc7 */,
|
0 /* 0xc4 */, 0 /* 0xc5 */, 0 /* 0xc6 */, 0 /* 0xc7 */,
|
||||||
0 /* 0xc8 */, 0 /* 0xc9 */, 0 /* 0xca */, 0 /* 0xcb */,
|
0 /* 0xc8 */, 0 /* 0xc9 */, 0 /* 0xca */, 0 /* 0xcb */,
|
||||||
0 /* 0xcc */, 0 /* 0xcd */, 0 /* 0xce */, 0 /* 0xcf */,
|
0 /* 0xcc */, 0 /* 0xcd */, 0 /* 0xce */, 0 /* 0xcf */,
|
||||||
0 /* 0xd0 */, 0 /* 0xd1 */, 0 /* 0xd2 */, 0 /* 0xd3 */,
|
0 /* 0xd0 */, 0 /* 0xd1 */, 0 /* 0xd2 */, 0 /* 0xd3 */,
|
||||||
0 /* 0xd4 */, 0 /* 0xd5 */, 0 /* 0xd6 */, 0 /* 0xd7 */,
|
0 /* 0xd4 */, 0 /* 0xd5 */, 0 /* 0xd6 */, 0 /* 0xd7 */,
|
||||||
0 /* 0xd8 */, 0 /* 0xd9 */, 0 /* 0xda */, 0 /* 0xdb */,
|
0 /* 0xd8 */, 0 /* 0xd9 */, 0 /* 0xda */, 0 /* 0xdb */,
|
||||||
0 /* 0xdc */, 0 /* 0xdd */, 0 /* 0xde */, 0 /* 0xdf */,
|
0 /* 0xdc */, 0 /* 0xdd */, 0 /* 0xde */, 0 /* 0xdf */,
|
||||||
0 /* 0xe0 */, 0 /* 0xe1 */, 0 /* 0xe2 */, 0 /* 0xe3 */,
|
0 /* 0xe0 */, 0 /* 0xe1 */, 0 /* 0xe2 */, 0 /* 0xe3 */,
|
||||||
0 /* 0xe4 */, 0 /* 0xe5 */, 0 /* 0xe6 */, 0 /* 0xe7 */,
|
0 /* 0xe4 */, 0 /* 0xe5 */, 0 /* 0xe6 */, 0 /* 0xe7 */,
|
||||||
0 /* 0xe8 */, 0 /* 0xe9 */, 0 /* 0xea */, 0 /* 0xeb */,
|
0 /* 0xe8 */, 0 /* 0xe9 */, 0 /* 0xea */, 0 /* 0xeb */,
|
||||||
0 /* 0xec */, 0 /* 0xed */, 0 /* 0xee */, 0 /* 0xef */,
|
0 /* 0xec */, 0 /* 0xed */, 0 /* 0xee */, 0 /* 0xef */,
|
||||||
0 /* 0xf0 */, 0 /* 0xf1 */, 0 /* 0xf2 */, 0 /* 0xf3 */,
|
0 /* 0xf0 */, 0 /* 0xf1 */, 0 /* 0xf2 */, 0 /* 0xf3 */,
|
||||||
0 /* 0xf4 */, 0 /* 0xf5 */, 0 /* 0xf6 */, 0 /* 0xf7 */,
|
0 /* 0xf4 */, 0 /* 0xf5 */, 0 /* 0xf6 */, 0 /* 0xf7 */,
|
||||||
0 /* 0xf8 */, 0 /* 0xf9 */, 0 /* 0xfa */, 0 /* 0xfb */,
|
0 /* 0xf8 */, 0 /* 0xf9 */, 0 /* 0xfa */, 0 /* 0xfb */,
|
||||||
0 /* 0xfc */, 0 /* 0xfd */, 0 /* 0xfe */, 0 /* 0xff */
|
0 /* 0xfc */, 0 /* 0xfd */, 0 /* 0xfe */, 0 /* 0xff */
|
||||||
};
|
};
|
||||||
|
|
||||||
int nghttp2_check_method(const uint8_t *value, size_t len) {
|
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 */
|
/* Generated by genpathchartbl.py */
|
||||||
static char VALID_PATH_CHARS[] = {
|
static char VALID_PATH_CHARS[] = {
|
||||||
0 /* NUL */, 0 /* SOH */, 0 /* STX */, 0 /* ETX */,
|
0 /* NUL */, 0 /* SOH */, 0 /* STX */, 0 /* ETX */,
|
||||||
0 /* EOT */, 0 /* ENQ */, 0 /* ACK */, 0 /* BEL */,
|
0 /* EOT */, 0 /* ENQ */, 0 /* ACK */, 0 /* BEL */,
|
||||||
0 /* BS */, 0 /* HT */, 0 /* LF */, 0 /* VT */,
|
0 /* BS */, 0 /* HT */, 0 /* LF */, 0 /* VT */,
|
||||||
0 /* FF */, 0 /* CR */, 0 /* SO */, 0 /* SI */,
|
0 /* FF */, 0 /* CR */, 0 /* SO */, 0 /* SI */,
|
||||||
0 /* DLE */, 0 /* DC1 */, 0 /* DC2 */, 0 /* DC3 */,
|
0 /* DLE */, 0 /* DC1 */, 0 /* DC2 */, 0 /* DC3 */,
|
||||||
0 /* DC4 */, 0 /* NAK */, 0 /* SYN */, 0 /* ETB */,
|
0 /* DC4 */, 0 /* NAK */, 0 /* SYN */, 0 /* ETB */,
|
||||||
0 /* CAN */, 0 /* EM */, 0 /* SUB */, 0 /* ESC */,
|
0 /* CAN */, 0 /* EM */, 0 /* SUB */, 0 /* ESC */,
|
||||||
0 /* FS */, 0 /* GS */, 0 /* RS */, 0 /* US */,
|
0 /* FS */, 0 /* GS */, 0 /* RS */, 0 /* US */,
|
||||||
0 /* SPC */, 1 /* ! */, 1 /* " */, 1 /* # */,
|
0 /* SPC */, 1 /* ! */, 1 /* " */, 1 /* # */,
|
||||||
1 /* $ */, 1 /* % */, 1 /* & */, 1 /* ' */,
|
1 /* $ */, 1 /* % */, 1 /* & */, 1 /* ' */,
|
||||||
1 /* ( */, 1 /* ) */, 1 /* * */, 1 /* + */,
|
1 /* ( */, 1 /* ) */, 1 /* * */, 1 /* + */,
|
||||||
1 /* , */, 1 /* - */, 1 /* . */, 1 /* / */,
|
1 /* , */, 1 /* - */, 1 /* . */, 1 /* / */,
|
||||||
1 /* 0 */, 1 /* 1 */, 1 /* 2 */, 1 /* 3 */,
|
1 /* 0 */, 1 /* 1 */, 1 /* 2 */, 1 /* 3 */,
|
||||||
1 /* 4 */, 1 /* 5 */, 1 /* 6 */, 1 /* 7 */,
|
1 /* 4 */, 1 /* 5 */, 1 /* 6 */, 1 /* 7 */,
|
||||||
1 /* 8 */, 1 /* 9 */, 1 /* : */, 1 /* ; */,
|
1 /* 8 */, 1 /* 9 */, 1 /* : */, 1 /* ; */,
|
||||||
1 /* < */, 1 /* = */, 1 /* > */, 1 /* ? */,
|
1 /* < */, 1 /* = */, 1 /* > */, 1 /* ? */,
|
||||||
1 /* @ */, 1 /* A */, 1 /* B */, 1 /* C */,
|
1 /* @ */, 1 /* A */, 1 /* B */, 1 /* C */,
|
||||||
1 /* D */, 1 /* E */, 1 /* F */, 1 /* G */,
|
1 /* D */, 1 /* E */, 1 /* F */, 1 /* G */,
|
||||||
1 /* H */, 1 /* I */, 1 /* J */, 1 /* K */,
|
1 /* H */, 1 /* I */, 1 /* J */, 1 /* K */,
|
||||||
1 /* L */, 1 /* M */, 1 /* N */, 1 /* O */,
|
1 /* L */, 1 /* M */, 1 /* N */, 1 /* O */,
|
||||||
1 /* P */, 1 /* Q */, 1 /* R */, 1 /* S */,
|
1 /* P */, 1 /* Q */, 1 /* R */, 1 /* S */,
|
||||||
1 /* T */, 1 /* U */, 1 /* V */, 1 /* W */,
|
1 /* T */, 1 /* U */, 1 /* V */, 1 /* W */,
|
||||||
1 /* X */, 1 /* Y */, 1 /* Z */, 1 /* [ */,
|
1 /* X */, 1 /* Y */, 1 /* Z */, 1 /* [ */,
|
||||||
1 /* \ */, 1 /* ] */, 1 /* ^ */, 1 /* _ */,
|
1 /* \ */, 1 /* ] */, 1 /* ^ */, 1 /* _ */,
|
||||||
1 /* ` */, 1 /* a */, 1 /* b */, 1 /* c */,
|
1 /* ` */, 1 /* a */, 1 /* b */, 1 /* c */,
|
||||||
1 /* d */, 1 /* e */, 1 /* f */, 1 /* g */,
|
1 /* d */, 1 /* e */, 1 /* f */, 1 /* g */,
|
||||||
1 /* h */, 1 /* i */, 1 /* j */, 1 /* k */,
|
1 /* h */, 1 /* i */, 1 /* j */, 1 /* k */,
|
||||||
1 /* l */, 1 /* m */, 1 /* n */, 1 /* o */,
|
1 /* l */, 1 /* m */, 1 /* n */, 1 /* o */,
|
||||||
1 /* p */, 1 /* q */, 1 /* r */, 1 /* s */,
|
1 /* p */, 1 /* q */, 1 /* r */, 1 /* s */,
|
||||||
1 /* t */, 1 /* u */, 1 /* v */, 1 /* w */,
|
1 /* t */, 1 /* u */, 1 /* v */, 1 /* w */,
|
||||||
1 /* x */, 1 /* y */, 1 /* z */, 1 /* { */,
|
1 /* x */, 1 /* y */, 1 /* z */, 1 /* { */,
|
||||||
1 /* | */, 1 /* } */, 1 /* ~ */, 0 /* DEL */,
|
1 /* | */, 1 /* } */, 1 /* ~ */, 0 /* DEL */,
|
||||||
1 /* 0x80 */, 1 /* 0x81 */, 1 /* 0x82 */, 1 /* 0x83 */,
|
1 /* 0x80 */, 1 /* 0x81 */, 1 /* 0x82 */, 1 /* 0x83 */,
|
||||||
1 /* 0x84 */, 1 /* 0x85 */, 1 /* 0x86 */, 1 /* 0x87 */,
|
1 /* 0x84 */, 1 /* 0x85 */, 1 /* 0x86 */, 1 /* 0x87 */,
|
||||||
1 /* 0x88 */, 1 /* 0x89 */, 1 /* 0x8a */, 1 /* 0x8b */,
|
1 /* 0x88 */, 1 /* 0x89 */, 1 /* 0x8a */, 1 /* 0x8b */,
|
||||||
1 /* 0x8c */, 1 /* 0x8d */, 1 /* 0x8e */, 1 /* 0x8f */,
|
1 /* 0x8c */, 1 /* 0x8d */, 1 /* 0x8e */, 1 /* 0x8f */,
|
||||||
1 /* 0x90 */, 1 /* 0x91 */, 1 /* 0x92 */, 1 /* 0x93 */,
|
1 /* 0x90 */, 1 /* 0x91 */, 1 /* 0x92 */, 1 /* 0x93 */,
|
||||||
1 /* 0x94 */, 1 /* 0x95 */, 1 /* 0x96 */, 1 /* 0x97 */,
|
1 /* 0x94 */, 1 /* 0x95 */, 1 /* 0x96 */, 1 /* 0x97 */,
|
||||||
1 /* 0x98 */, 1 /* 0x99 */, 1 /* 0x9a */, 1 /* 0x9b */,
|
1 /* 0x98 */, 1 /* 0x99 */, 1 /* 0x9a */, 1 /* 0x9b */,
|
||||||
1 /* 0x9c */, 1 /* 0x9d */, 1 /* 0x9e */, 1 /* 0x9f */,
|
1 /* 0x9c */, 1 /* 0x9d */, 1 /* 0x9e */, 1 /* 0x9f */,
|
||||||
1 /* 0xa0 */, 1 /* 0xa1 */, 1 /* 0xa2 */, 1 /* 0xa3 */,
|
1 /* 0xa0 */, 1 /* 0xa1 */, 1 /* 0xa2 */, 1 /* 0xa3 */,
|
||||||
1 /* 0xa4 */, 1 /* 0xa5 */, 1 /* 0xa6 */, 1 /* 0xa7 */,
|
1 /* 0xa4 */, 1 /* 0xa5 */, 1 /* 0xa6 */, 1 /* 0xa7 */,
|
||||||
1 /* 0xa8 */, 1 /* 0xa9 */, 1 /* 0xaa */, 1 /* 0xab */,
|
1 /* 0xa8 */, 1 /* 0xa9 */, 1 /* 0xaa */, 1 /* 0xab */,
|
||||||
1 /* 0xac */, 1 /* 0xad */, 1 /* 0xae */, 1 /* 0xaf */,
|
1 /* 0xac */, 1 /* 0xad */, 1 /* 0xae */, 1 /* 0xaf */,
|
||||||
1 /* 0xb0 */, 1 /* 0xb1 */, 1 /* 0xb2 */, 1 /* 0xb3 */,
|
1 /* 0xb0 */, 1 /* 0xb1 */, 1 /* 0xb2 */, 1 /* 0xb3 */,
|
||||||
1 /* 0xb4 */, 1 /* 0xb5 */, 1 /* 0xb6 */, 1 /* 0xb7 */,
|
1 /* 0xb4 */, 1 /* 0xb5 */, 1 /* 0xb6 */, 1 /* 0xb7 */,
|
||||||
1 /* 0xb8 */, 1 /* 0xb9 */, 1 /* 0xba */, 1 /* 0xbb */,
|
1 /* 0xb8 */, 1 /* 0xb9 */, 1 /* 0xba */, 1 /* 0xbb */,
|
||||||
1 /* 0xbc */, 1 /* 0xbd */, 1 /* 0xbe */, 1 /* 0xbf */,
|
1 /* 0xbc */, 1 /* 0xbd */, 1 /* 0xbe */, 1 /* 0xbf */,
|
||||||
1 /* 0xc0 */, 1 /* 0xc1 */, 1 /* 0xc2 */, 1 /* 0xc3 */,
|
1 /* 0xc0 */, 1 /* 0xc1 */, 1 /* 0xc2 */, 1 /* 0xc3 */,
|
||||||
1 /* 0xc4 */, 1 /* 0xc5 */, 1 /* 0xc6 */, 1 /* 0xc7 */,
|
1 /* 0xc4 */, 1 /* 0xc5 */, 1 /* 0xc6 */, 1 /* 0xc7 */,
|
||||||
1 /* 0xc8 */, 1 /* 0xc9 */, 1 /* 0xca */, 1 /* 0xcb */,
|
1 /* 0xc8 */, 1 /* 0xc9 */, 1 /* 0xca */, 1 /* 0xcb */,
|
||||||
1 /* 0xcc */, 1 /* 0xcd */, 1 /* 0xce */, 1 /* 0xcf */,
|
1 /* 0xcc */, 1 /* 0xcd */, 1 /* 0xce */, 1 /* 0xcf */,
|
||||||
1 /* 0xd0 */, 1 /* 0xd1 */, 1 /* 0xd2 */, 1 /* 0xd3 */,
|
1 /* 0xd0 */, 1 /* 0xd1 */, 1 /* 0xd2 */, 1 /* 0xd3 */,
|
||||||
1 /* 0xd4 */, 1 /* 0xd5 */, 1 /* 0xd6 */, 1 /* 0xd7 */,
|
1 /* 0xd4 */, 1 /* 0xd5 */, 1 /* 0xd6 */, 1 /* 0xd7 */,
|
||||||
1 /* 0xd8 */, 1 /* 0xd9 */, 1 /* 0xda */, 1 /* 0xdb */,
|
1 /* 0xd8 */, 1 /* 0xd9 */, 1 /* 0xda */, 1 /* 0xdb */,
|
||||||
1 /* 0xdc */, 1 /* 0xdd */, 1 /* 0xde */, 1 /* 0xdf */,
|
1 /* 0xdc */, 1 /* 0xdd */, 1 /* 0xde */, 1 /* 0xdf */,
|
||||||
1 /* 0xe0 */, 1 /* 0xe1 */, 1 /* 0xe2 */, 1 /* 0xe3 */,
|
1 /* 0xe0 */, 1 /* 0xe1 */, 1 /* 0xe2 */, 1 /* 0xe3 */,
|
||||||
1 /* 0xe4 */, 1 /* 0xe5 */, 1 /* 0xe6 */, 1 /* 0xe7 */,
|
1 /* 0xe4 */, 1 /* 0xe5 */, 1 /* 0xe6 */, 1 /* 0xe7 */,
|
||||||
1 /* 0xe8 */, 1 /* 0xe9 */, 1 /* 0xea */, 1 /* 0xeb */,
|
1 /* 0xe8 */, 1 /* 0xe9 */, 1 /* 0xea */, 1 /* 0xeb */,
|
||||||
1 /* 0xec */, 1 /* 0xed */, 1 /* 0xee */, 1 /* 0xef */,
|
1 /* 0xec */, 1 /* 0xed */, 1 /* 0xee */, 1 /* 0xef */,
|
||||||
1 /* 0xf0 */, 1 /* 0xf1 */, 1 /* 0xf2 */, 1 /* 0xf3 */,
|
1 /* 0xf0 */, 1 /* 0xf1 */, 1 /* 0xf2 */, 1 /* 0xf3 */,
|
||||||
1 /* 0xf4 */, 1 /* 0xf5 */, 1 /* 0xf6 */, 1 /* 0xf7 */,
|
1 /* 0xf4 */, 1 /* 0xf5 */, 1 /* 0xf6 */, 1 /* 0xf7 */,
|
||||||
1 /* 0xf8 */, 1 /* 0xf9 */, 1 /* 0xfa */, 1 /* 0xfb */,
|
1 /* 0xf8 */, 1 /* 0xf9 */, 1 /* 0xfa */, 1 /* 0xfb */,
|
||||||
1 /* 0xfc */, 1 /* 0xfd */, 1 /* 0xfe */, 1 /* 0xff */
|
1 /* 0xfc */, 1 /* 0xfd */, 1 /* 0xfe */, 1 /* 0xff */
|
||||||
};
|
};
|
||||||
|
|
||||||
int nghttp2_check_path(const uint8_t *value, size_t len) {
|
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 */
|
/* Generated by genauthoritychartbl.py */
|
||||||
static char VALID_AUTHORITY_CHARS[] = {
|
static char VALID_AUTHORITY_CHARS[] = {
|
||||||
0 /* NUL */, 0 /* SOH */, 0 /* STX */, 0 /* ETX */,
|
0 /* NUL */, 0 /* SOH */, 0 /* STX */, 0 /* ETX */,
|
||||||
0 /* EOT */, 0 /* ENQ */, 0 /* ACK */, 0 /* BEL */,
|
0 /* EOT */, 0 /* ENQ */, 0 /* ACK */, 0 /* BEL */,
|
||||||
0 /* BS */, 0 /* HT */, 0 /* LF */, 0 /* VT */,
|
0 /* BS */, 0 /* HT */, 0 /* LF */, 0 /* VT */,
|
||||||
0 /* FF */, 0 /* CR */, 0 /* SO */, 0 /* SI */,
|
0 /* FF */, 0 /* CR */, 0 /* SO */, 0 /* SI */,
|
||||||
0 /* DLE */, 0 /* DC1 */, 0 /* DC2 */, 0 /* DC3 */,
|
0 /* DLE */, 0 /* DC1 */, 0 /* DC2 */, 0 /* DC3 */,
|
||||||
0 /* DC4 */, 0 /* NAK */, 0 /* SYN */, 0 /* ETB */,
|
0 /* DC4 */, 0 /* NAK */, 0 /* SYN */, 0 /* ETB */,
|
||||||
0 /* CAN */, 0 /* EM */, 0 /* SUB */, 0 /* ESC */,
|
0 /* CAN */, 0 /* EM */, 0 /* SUB */, 0 /* ESC */,
|
||||||
0 /* FS */, 0 /* GS */, 0 /* RS */, 0 /* US */,
|
0 /* FS */, 0 /* GS */, 0 /* RS */, 0 /* US */,
|
||||||
0 /* SPC */, 1 /* ! */, 0 /* " */, 0 /* # */,
|
0 /* SPC */, 1 /* ! */, 0 /* " */, 0 /* # */,
|
||||||
1 /* $ */, 1 /* % */, 1 /* & */, 1 /* ' */,
|
1 /* $ */, 1 /* % */, 1 /* & */, 1 /* ' */,
|
||||||
1 /* ( */, 1 /* ) */, 1 /* * */, 1 /* + */,
|
1 /* ( */, 1 /* ) */, 1 /* * */, 1 /* + */,
|
||||||
1 /* , */, 1 /* - */, 1 /* . */, 0 /* / */,
|
1 /* , */, 1 /* - */, 1 /* . */, 0 /* / */,
|
||||||
1 /* 0 */, 1 /* 1 */, 1 /* 2 */, 1 /* 3 */,
|
1 /* 0 */, 1 /* 1 */, 1 /* 2 */, 1 /* 3 */,
|
||||||
1 /* 4 */, 1 /* 5 */, 1 /* 6 */, 1 /* 7 */,
|
1 /* 4 */, 1 /* 5 */, 1 /* 6 */, 1 /* 7 */,
|
||||||
1 /* 8 */, 1 /* 9 */, 1 /* : */, 1 /* ; */,
|
1 /* 8 */, 1 /* 9 */, 1 /* : */, 1 /* ; */,
|
||||||
0 /* < */, 1 /* = */, 0 /* > */, 0 /* ? */,
|
0 /* < */, 1 /* = */, 0 /* > */, 0 /* ? */,
|
||||||
1 /* @ */, 1 /* A */, 1 /* B */, 1 /* C */,
|
1 /* @ */, 1 /* A */, 1 /* B */, 1 /* C */,
|
||||||
1 /* D */, 1 /* E */, 1 /* F */, 1 /* G */,
|
1 /* D */, 1 /* E */, 1 /* F */, 1 /* G */,
|
||||||
1 /* H */, 1 /* I */, 1 /* J */, 1 /* K */,
|
1 /* H */, 1 /* I */, 1 /* J */, 1 /* K */,
|
||||||
1 /* L */, 1 /* M */, 1 /* N */, 1 /* O */,
|
1 /* L */, 1 /* M */, 1 /* N */, 1 /* O */,
|
||||||
1 /* P */, 1 /* Q */, 1 /* R */, 1 /* S */,
|
1 /* P */, 1 /* Q */, 1 /* R */, 1 /* S */,
|
||||||
1 /* T */, 1 /* U */, 1 /* V */, 1 /* W */,
|
1 /* T */, 1 /* U */, 1 /* V */, 1 /* W */,
|
||||||
1 /* X */, 1 /* Y */, 1 /* Z */, 1 /* [ */,
|
1 /* X */, 1 /* Y */, 1 /* Z */, 1 /* [ */,
|
||||||
0 /* \ */, 1 /* ] */, 0 /* ^ */, 1 /* _ */,
|
0 /* \ */, 1 /* ] */, 0 /* ^ */, 1 /* _ */,
|
||||||
0 /* ` */, 1 /* a */, 1 /* b */, 1 /* c */,
|
0 /* ` */, 1 /* a */, 1 /* b */, 1 /* c */,
|
||||||
1 /* d */, 1 /* e */, 1 /* f */, 1 /* g */,
|
1 /* d */, 1 /* e */, 1 /* f */, 1 /* g */,
|
||||||
1 /* h */, 1 /* i */, 1 /* j */, 1 /* k */,
|
1 /* h */, 1 /* i */, 1 /* j */, 1 /* k */,
|
||||||
1 /* l */, 1 /* m */, 1 /* n */, 1 /* o */,
|
1 /* l */, 1 /* m */, 1 /* n */, 1 /* o */,
|
||||||
1 /* p */, 1 /* q */, 1 /* r */, 1 /* s */,
|
1 /* p */, 1 /* q */, 1 /* r */, 1 /* s */,
|
||||||
1 /* t */, 1 /* u */, 1 /* v */, 1 /* w */,
|
1 /* t */, 1 /* u */, 1 /* v */, 1 /* w */,
|
||||||
1 /* x */, 1 /* y */, 1 /* z */, 0 /* { */,
|
1 /* x */, 1 /* y */, 1 /* z */, 0 /* { */,
|
||||||
0 /* | */, 0 /* } */, 1 /* ~ */, 0 /* DEL */,
|
0 /* | */, 0 /* } */, 1 /* ~ */, 0 /* DEL */,
|
||||||
0 /* 0x80 */, 0 /* 0x81 */, 0 /* 0x82 */, 0 /* 0x83 */,
|
0 /* 0x80 */, 0 /* 0x81 */, 0 /* 0x82 */, 0 /* 0x83 */,
|
||||||
0 /* 0x84 */, 0 /* 0x85 */, 0 /* 0x86 */, 0 /* 0x87 */,
|
0 /* 0x84 */, 0 /* 0x85 */, 0 /* 0x86 */, 0 /* 0x87 */,
|
||||||
0 /* 0x88 */, 0 /* 0x89 */, 0 /* 0x8a */, 0 /* 0x8b */,
|
0 /* 0x88 */, 0 /* 0x89 */, 0 /* 0x8a */, 0 /* 0x8b */,
|
||||||
0 /* 0x8c */, 0 /* 0x8d */, 0 /* 0x8e */, 0 /* 0x8f */,
|
0 /* 0x8c */, 0 /* 0x8d */, 0 /* 0x8e */, 0 /* 0x8f */,
|
||||||
0 /* 0x90 */, 0 /* 0x91 */, 0 /* 0x92 */, 0 /* 0x93 */,
|
0 /* 0x90 */, 0 /* 0x91 */, 0 /* 0x92 */, 0 /* 0x93 */,
|
||||||
0 /* 0x94 */, 0 /* 0x95 */, 0 /* 0x96 */, 0 /* 0x97 */,
|
0 /* 0x94 */, 0 /* 0x95 */, 0 /* 0x96 */, 0 /* 0x97 */,
|
||||||
0 /* 0x98 */, 0 /* 0x99 */, 0 /* 0x9a */, 0 /* 0x9b */,
|
0 /* 0x98 */, 0 /* 0x99 */, 0 /* 0x9a */, 0 /* 0x9b */,
|
||||||
0 /* 0x9c */, 0 /* 0x9d */, 0 /* 0x9e */, 0 /* 0x9f */,
|
0 /* 0x9c */, 0 /* 0x9d */, 0 /* 0x9e */, 0 /* 0x9f */,
|
||||||
0 /* 0xa0 */, 0 /* 0xa1 */, 0 /* 0xa2 */, 0 /* 0xa3 */,
|
0 /* 0xa0 */, 0 /* 0xa1 */, 0 /* 0xa2 */, 0 /* 0xa3 */,
|
||||||
0 /* 0xa4 */, 0 /* 0xa5 */, 0 /* 0xa6 */, 0 /* 0xa7 */,
|
0 /* 0xa4 */, 0 /* 0xa5 */, 0 /* 0xa6 */, 0 /* 0xa7 */,
|
||||||
0 /* 0xa8 */, 0 /* 0xa9 */, 0 /* 0xaa */, 0 /* 0xab */,
|
0 /* 0xa8 */, 0 /* 0xa9 */, 0 /* 0xaa */, 0 /* 0xab */,
|
||||||
0 /* 0xac */, 0 /* 0xad */, 0 /* 0xae */, 0 /* 0xaf */,
|
0 /* 0xac */, 0 /* 0xad */, 0 /* 0xae */, 0 /* 0xaf */,
|
||||||
0 /* 0xb0 */, 0 /* 0xb1 */, 0 /* 0xb2 */, 0 /* 0xb3 */,
|
0 /* 0xb0 */, 0 /* 0xb1 */, 0 /* 0xb2 */, 0 /* 0xb3 */,
|
||||||
0 /* 0xb4 */, 0 /* 0xb5 */, 0 /* 0xb6 */, 0 /* 0xb7 */,
|
0 /* 0xb4 */, 0 /* 0xb5 */, 0 /* 0xb6 */, 0 /* 0xb7 */,
|
||||||
0 /* 0xb8 */, 0 /* 0xb9 */, 0 /* 0xba */, 0 /* 0xbb */,
|
0 /* 0xb8 */, 0 /* 0xb9 */, 0 /* 0xba */, 0 /* 0xbb */,
|
||||||
0 /* 0xbc */, 0 /* 0xbd */, 0 /* 0xbe */, 0 /* 0xbf */,
|
0 /* 0xbc */, 0 /* 0xbd */, 0 /* 0xbe */, 0 /* 0xbf */,
|
||||||
0 /* 0xc0 */, 0 /* 0xc1 */, 0 /* 0xc2 */, 0 /* 0xc3 */,
|
0 /* 0xc0 */, 0 /* 0xc1 */, 0 /* 0xc2 */, 0 /* 0xc3 */,
|
||||||
0 /* 0xc4 */, 0 /* 0xc5 */, 0 /* 0xc6 */, 0 /* 0xc7 */,
|
0 /* 0xc4 */, 0 /* 0xc5 */, 0 /* 0xc6 */, 0 /* 0xc7 */,
|
||||||
0 /* 0xc8 */, 0 /* 0xc9 */, 0 /* 0xca */, 0 /* 0xcb */,
|
0 /* 0xc8 */, 0 /* 0xc9 */, 0 /* 0xca */, 0 /* 0xcb */,
|
||||||
0 /* 0xcc */, 0 /* 0xcd */, 0 /* 0xce */, 0 /* 0xcf */,
|
0 /* 0xcc */, 0 /* 0xcd */, 0 /* 0xce */, 0 /* 0xcf */,
|
||||||
0 /* 0xd0 */, 0 /* 0xd1 */, 0 /* 0xd2 */, 0 /* 0xd3 */,
|
0 /* 0xd0 */, 0 /* 0xd1 */, 0 /* 0xd2 */, 0 /* 0xd3 */,
|
||||||
0 /* 0xd4 */, 0 /* 0xd5 */, 0 /* 0xd6 */, 0 /* 0xd7 */,
|
0 /* 0xd4 */, 0 /* 0xd5 */, 0 /* 0xd6 */, 0 /* 0xd7 */,
|
||||||
0 /* 0xd8 */, 0 /* 0xd9 */, 0 /* 0xda */, 0 /* 0xdb */,
|
0 /* 0xd8 */, 0 /* 0xd9 */, 0 /* 0xda */, 0 /* 0xdb */,
|
||||||
0 /* 0xdc */, 0 /* 0xdd */, 0 /* 0xde */, 0 /* 0xdf */,
|
0 /* 0xdc */, 0 /* 0xdd */, 0 /* 0xde */, 0 /* 0xdf */,
|
||||||
0 /* 0xe0 */, 0 /* 0xe1 */, 0 /* 0xe2 */, 0 /* 0xe3 */,
|
0 /* 0xe0 */, 0 /* 0xe1 */, 0 /* 0xe2 */, 0 /* 0xe3 */,
|
||||||
0 /* 0xe4 */, 0 /* 0xe5 */, 0 /* 0xe6 */, 0 /* 0xe7 */,
|
0 /* 0xe4 */, 0 /* 0xe5 */, 0 /* 0xe6 */, 0 /* 0xe7 */,
|
||||||
0 /* 0xe8 */, 0 /* 0xe9 */, 0 /* 0xea */, 0 /* 0xeb */,
|
0 /* 0xe8 */, 0 /* 0xe9 */, 0 /* 0xea */, 0 /* 0xeb */,
|
||||||
0 /* 0xec */, 0 /* 0xed */, 0 /* 0xee */, 0 /* 0xef */,
|
0 /* 0xec */, 0 /* 0xed */, 0 /* 0xee */, 0 /* 0xef */,
|
||||||
0 /* 0xf0 */, 0 /* 0xf1 */, 0 /* 0xf2 */, 0 /* 0xf3 */,
|
0 /* 0xf0 */, 0 /* 0xf1 */, 0 /* 0xf2 */, 0 /* 0xf3 */,
|
||||||
0 /* 0xf4 */, 0 /* 0xf5 */, 0 /* 0xf6 */, 0 /* 0xf7 */,
|
0 /* 0xf4 */, 0 /* 0xf5 */, 0 /* 0xf6 */, 0 /* 0xf7 */,
|
||||||
0 /* 0xf8 */, 0 /* 0xf9 */, 0 /* 0xfa */, 0 /* 0xfb */,
|
0 /* 0xf8 */, 0 /* 0xf9 */, 0 /* 0xfa */, 0 /* 0xfb */,
|
||||||
0 /* 0xfc */, 0 /* 0xfd */, 0 /* 0xfe */, 0 /* 0xff */
|
0 /* 0xfc */, 0 /* 0xfd */, 0 /* 0xfe */, 0 /* 0xff */
|
||||||
};
|
};
|
||||||
|
|
||||||
int nghttp2_check_authority(const uint8_t *value, size_t len) {
|
int nghttp2_check_authority(const uint8_t *value, size_t len) {
|
||||||
|
|||||||
@@ -38,33 +38,33 @@
|
|||||||
#define nghttp2_max_def(SUFFIX, T) \
|
#define nghttp2_max_def(SUFFIX, T) \
|
||||||
static inline T nghttp2_max_##SUFFIX(T a, T b) { return a < b ? b : a; }
|
static inline T nghttp2_max_##SUFFIX(T a, T b) { return a < b ? b : a; }
|
||||||
|
|
||||||
nghttp2_max_def(int8, int8_t)
|
nghttp2_max_def(int8, int8_t);
|
||||||
nghttp2_max_def(int16, int16_t)
|
nghttp2_max_def(int16, int16_t);
|
||||||
nghttp2_max_def(int32, int32_t)
|
nghttp2_max_def(int32, int32_t);
|
||||||
nghttp2_max_def(int64, int64_t)
|
nghttp2_max_def(int64, int64_t);
|
||||||
nghttp2_max_def(uint8, uint8_t)
|
nghttp2_max_def(uint8, uint8_t);
|
||||||
nghttp2_max_def(uint16, uint16_t)
|
nghttp2_max_def(uint16, uint16_t);
|
||||||
nghttp2_max_def(uint32, uint32_t)
|
nghttp2_max_def(uint32, uint32_t);
|
||||||
nghttp2_max_def(uint64, uint64_t)
|
nghttp2_max_def(uint64, uint64_t);
|
||||||
nghttp2_max_def(size, size_t)
|
nghttp2_max_def(size, size_t);
|
||||||
|
|
||||||
#define nghttp2_min_def(SUFFIX, T) \
|
#define nghttp2_min_def(SUFFIX, T) \
|
||||||
static inline T nghttp2_min_##SUFFIX(T a, T b) { return a < b ? a : b; }
|
static inline T nghttp2_min_##SUFFIX(T a, T b) { return a < b ? a : b; }
|
||||||
|
|
||||||
nghttp2_min_def(int8, int8_t)
|
nghttp2_min_def(int8, int8_t);
|
||||||
nghttp2_min_def(int16, int16_t)
|
nghttp2_min_def(int16, int16_t);
|
||||||
nghttp2_min_def(int32, int32_t)
|
nghttp2_min_def(int32, int32_t);
|
||||||
nghttp2_min_def(int64, int64_t)
|
nghttp2_min_def(int64, int64_t);
|
||||||
nghttp2_min_def(uint8, uint8_t)
|
nghttp2_min_def(uint8, uint8_t);
|
||||||
nghttp2_min_def(uint16, uint16_t)
|
nghttp2_min_def(uint16, uint16_t);
|
||||||
nghttp2_min_def(uint32, uint32_t)
|
nghttp2_min_def(uint32, uint32_t);
|
||||||
nghttp2_min_def(uint64, uint64_t)
|
nghttp2_min_def(uint64, uint64_t);
|
||||||
nghttp2_min_def(size, size_t)
|
nghttp2_min_def(size, size_t);
|
||||||
|
|
||||||
#define lstreq(A, B, N) ((sizeof((A)) - 1) == (N) && memcmp((A), (B), (N)) == 0)
|
#define lstreq(A, B, N) ((sizeof((A)) - 1) == (N) && memcmp((A), (B), (N)) == 0)
|
||||||
|
|
||||||
#define nghttp2_struct_of(ptr, type, member) \
|
#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
|
* 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 &&
|
if (!trailer &&
|
||||||
/* Do not parse the header field in PUSH_PROMISE. */
|
/* Do not parse the header field in PUSH_PROMISE. */
|
||||||
(stream->stream_id & 1) &&
|
(stream->stream_id & 1) &&
|
||||||
|
(stream->flags & NGHTTP2_STREAM_FLAG_NO_RFC7540_PRIORITIES) &&
|
||||||
!(stream->http_flags & NGHTTP2_HTTP_FLAG_BAD_PRIORITY)) {
|
!(stream->http_flags & NGHTTP2_HTTP_FLAG_BAD_PRIORITY)) {
|
||||||
nghttp2_extpri_from_uint8(&extpri, stream->http_extpri);
|
nghttp2_extpri_from_uint8(&extpri, stream->http_extpri);
|
||||||
if (nghttp2_http_parse_priority(&extpri, nv->value->base,
|
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;
|
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,
|
int nghttp2_http_on_header(nghttp2_session *session, nghttp2_stream *stream,
|
||||||
nghttp2_frame *frame, nghttp2_hd_nv *nv,
|
nghttp2_frame *frame, nghttp2_hd_nv *nv,
|
||||||
int trailer) {
|
int trailer) {
|
||||||
@@ -465,10 +388,10 @@ int nghttp2_http_on_header(nghttp2_session *session, nghttp2_stream *stream,
|
|||||||
case NGHTTP2_TOKEN__AUTHORITY:
|
case NGHTTP2_TOKEN__AUTHORITY:
|
||||||
case NGHTTP2_TOKEN_HOST:
|
case NGHTTP2_TOKEN_HOST:
|
||||||
if (session->server || frame->hd.type == NGHTTP2_PUSH_PROMISE) {
|
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 (
|
} else if (
|
||||||
stream->flags &
|
stream->flags &
|
||||||
NGHTTP2_STREAM_FLAG_NO_RFC9113_LEADING_AND_TRAILING_WS_VALIDATION) {
|
NGHTTP2_STREAM_FLAG_NO_RFC9113_LEADING_AND_TRAILING_WS_VALIDATION) {
|
||||||
rv = nghttp2_check_header_value(nv->value->base, nv->value->len);
|
rv = nghttp2_check_header_value(nv->value->base, nv->value->len);
|
||||||
} else {
|
} else {
|
||||||
rv = nghttp2_check_header_value_rfc9113(nv->value->base, nv->value->len);
|
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) {
|
if (session->server || frame->hd.type == NGHTTP2_PUSH_PROMISE) {
|
||||||
return http_request_on_header(stream, nv, trailer,
|
return http_request_on_header(stream, nv, trailer,
|
||||||
session->server &&
|
session->server &&
|
||||||
session->pending_enable_connect_protocol);
|
session->pending_enable_connect_protocol);
|
||||||
}
|
}
|
||||||
|
|
||||||
return http_response_on_header(stream, nv, trailer);
|
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;
|
stream->content_length = -1;
|
||||||
} else {
|
} else {
|
||||||
if ((stream->http_flags & NGHTTP2_HTTP_FLAG_REQ_HEADERS) !=
|
if ((stream->http_flags & NGHTTP2_HTTP_FLAG_REQ_HEADERS) !=
|
||||||
NGHTTP2_HTTP_FLAG_REQ_HEADERS ||
|
NGHTTP2_HTTP_FLAG_REQ_HEADERS ||
|
||||||
(stream->http_flags &
|
(stream->http_flags &
|
||||||
(NGHTTP2_HTTP_FLAG__AUTHORITY | NGHTTP2_HTTP_FLAG_HOST)) == 0) {
|
(NGHTTP2_HTTP_FLAG__AUTHORITY | NGHTTP2_HTTP_FLAG_HOST)) == 0) {
|
||||||
return -1;
|
return -1;
|
||||||
@@ -570,7 +493,7 @@ int nghttp2_http_on_response_headers(nghttp2_stream *stream) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
stream->http_flags =
|
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)) {
|
if (!expect_response_body(stream)) {
|
||||||
stream->content_length = 0;
|
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,
|
int nghttp2_http_parse_priority(nghttp2_extpri *dest, const uint8_t *value,
|
||||||
size_t valuelen) {
|
size_t valuelen) {
|
||||||
nghttp2_extpri pri = *dest;
|
nghttp2_extpri pri = *dest;
|
||||||
sfparse_parser sfp;
|
sf_parser sfp;
|
||||||
sfparse_vec key;
|
sf_vec key;
|
||||||
sfparse_value val;
|
sf_value val;
|
||||||
int rv;
|
int rv;
|
||||||
|
|
||||||
sfparse_parser_init(&sfp, value, valuelen);
|
sf_parser_init(&sfp, value, valuelen);
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
rv = sfparse_parser_dict(&sfp, &key, &val);
|
rv = sf_parser_dict(&sfp, &key, &val);
|
||||||
if (rv != 0) {
|
if (rv != 0) {
|
||||||
if (rv == SFPARSE_ERR_EOF) {
|
if (rv == SF_ERR_EOF) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -682,7 +605,7 @@ int nghttp2_http_parse_priority(nghttp2_extpri *dest, const uint8_t *value,
|
|||||||
|
|
||||||
switch (key.base[0]) {
|
switch (key.base[0]) {
|
||||||
case 'i':
|
case 'i':
|
||||||
if (val.type != SFPARSE_TYPE_BOOLEAN) {
|
if (val.type != SF_TYPE_BOOLEAN) {
|
||||||
return NGHTTP2_ERR_INVALID_ARGUMENT;
|
return NGHTTP2_ERR_INVALID_ARGUMENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -690,7 +613,7 @@ int nghttp2_http_parse_priority(nghttp2_extpri *dest, const uint8_t *value,
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
case 'u':
|
case 'u':
|
||||||
if (val.type != SFPARSE_TYPE_INTEGER ||
|
if (val.type != SF_TYPE_INTEGER ||
|
||||||
val.integer < NGHTTP2_EXTPRI_URGENCY_HIGH ||
|
val.integer < NGHTTP2_EXTPRI_URGENCY_HIGH ||
|
||||||
NGHTTP2_EXTPRI_URGENCY_LOW < val.integer) {
|
NGHTTP2_EXTPRI_URGENCY_LOW < val.integer) {
|
||||||
return NGHTTP2_ERR_INVALID_ARGUMENT;
|
return NGHTTP2_ERR_INVALID_ARGUMENT;
|
||||||
|
|||||||
@@ -52,11 +52,7 @@ typedef enum {
|
|||||||
* Unlike NGHTTP2_ERR_IGN_HTTP_HEADER, this does not invoke
|
* Unlike NGHTTP2_ERR_IGN_HTTP_HEADER, this does not invoke
|
||||||
* nghttp2_on_invalid_header_callback.
|
* nghttp2_on_invalid_header_callback.
|
||||||
*/
|
*/
|
||||||
NGHTTP2_ERR_REMOVE_HTTP_HEADER = -106,
|
NGHTTP2_ERR_REMOVE_HTTP_HEADER = -106
|
||||||
/*
|
|
||||||
* Cancel pushed stream.
|
|
||||||
*/
|
|
||||||
NGHTTP2_ERR_PUSH_CANCEL = -107,
|
|
||||||
} nghttp2_internal_error;
|
} nghttp2_internal_error;
|
||||||
|
|
||||||
#endif /* NGHTTP2_INT_H */
|
#endif /* NGHTTP2_INT_H */
|
||||||
|
|||||||
@@ -31,13 +31,13 @@
|
|||||||
|
|
||||||
#include "nghttp2_helper.h"
|
#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->mem = mem;
|
||||||
map->hashbits = 0;
|
map->tablelen = 0;
|
||||||
|
map->tablelenbits = 0;
|
||||||
map->table = NULL;
|
map->table = NULL;
|
||||||
map->seed = seed;
|
|
||||||
map->size = 0;
|
map->size = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -49,20 +49,33 @@ void nghttp2_map_free(nghttp2_map *map) {
|
|||||||
nghttp2_mem_free(map->mem, map->table);
|
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) {
|
void *ptr) {
|
||||||
int rv;
|
int rv;
|
||||||
size_t i;
|
uint32_t i;
|
||||||
nghttp2_map_bucket *bkt;
|
nghttp2_map_bucket *bkt;
|
||||||
size_t tablelen;
|
|
||||||
|
|
||||||
if (map->size == 0) {
|
if (map->size == 0) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
tablelen = 1u << map->hashbits;
|
for (i = 0; i < map->tablelen; ++i) {
|
||||||
|
|
||||||
for (i = 0; i < tablelen; ++i) {
|
|
||||||
bkt = &map->table[i];
|
bkt = &map->table[i];
|
||||||
|
|
||||||
if (bkt->data == NULL) {
|
if (bkt->data == NULL) {
|
||||||
@@ -78,70 +91,82 @@ int nghttp2_map_each(const nghttp2_map *map, int (*func)(void *data, void *ptr),
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static size_t map_hash(const nghttp2_map *map, nghttp2_map_key_type key) {
|
static uint32_t hash(nghttp2_map_key_type key) {
|
||||||
/* hasher from
|
return (uint32_t)key * 2654435769u;
|
||||||
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 void map_bucket_swap(nghttp2_map_bucket *a, nghttp2_map_bucket *b) {
|
static size_t h2idx(uint32_t hash, uint32_t bits) {
|
||||||
nghttp2_map_bucket c = *a;
|
return hash >> (32 - bits);
|
||||||
|
}
|
||||||
|
|
||||||
*a = *b;
|
static size_t distance(uint32_t tablelen, uint32_t tablelenbits,
|
||||||
*b = c;
|
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
|
#ifndef WIN32
|
||||||
void nghttp2_map_print_distance(const nghttp2_map *map) {
|
void nghttp2_map_print_distance(nghttp2_map *map) {
|
||||||
size_t i;
|
uint32_t i;
|
||||||
size_t idx;
|
size_t idx;
|
||||||
nghttp2_map_bucket *bkt;
|
nghttp2_map_bucket *bkt;
|
||||||
size_t tablelen;
|
|
||||||
|
|
||||||
if (map->size == 0) {
|
for (i = 0; i < map->tablelen; ++i) {
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
tablelen = 1u << map->hashbits;
|
|
||||||
|
|
||||||
for (i = 0; i < tablelen; ++i) {
|
|
||||||
bkt = &map->table[i];
|
bkt = &map->table[i];
|
||||||
|
|
||||||
if (bkt->data == NULL) {
|
if (bkt->data == NULL) {
|
||||||
fprintf(stderr, "@%zu <EMPTY>\n", i);
|
fprintf(stderr, "@%u <EMPTY>\n", i);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
idx = map_hash(map, bkt->key);
|
idx = h2idx(bkt->hash, map->tablelenbits);
|
||||||
fprintf(stderr, "@%zu hash=%zu key=%d base=%zu distance=%u\n", i,
|
fprintf(stderr, "@%u hash=%08x key=%d base=%zu distance=%zu\n", i,
|
||||||
map_hash(map, bkt->key), bkt->key, idx, bkt->psl);
|
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) {
|
static int insert(nghttp2_map_bucket *table, uint32_t tablelen,
|
||||||
size_t idx = map_hash(map, key);
|
uint32_t tablelenbits, uint32_t hash,
|
||||||
nghttp2_map_bucket b = {
|
nghttp2_map_key_type key, void *data) {
|
||||||
.key = key,
|
size_t idx = h2idx(hash, tablelenbits);
|
||||||
.data = data,
|
size_t d = 0, dd;
|
||||||
};
|
|
||||||
nghttp2_map_bucket *bkt;
|
nghttp2_map_bucket *bkt;
|
||||||
size_t mask = (1u << map->hashbits) - 1;
|
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
bkt = &map->table[idx];
|
bkt = &table[idx];
|
||||||
|
|
||||||
if (bkt->data == NULL) {
|
if (bkt->data == NULL) {
|
||||||
*bkt = b;
|
map_bucket_set_data(bkt, hash, key, data);
|
||||||
++map->size;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (b.psl > bkt->psl) {
|
dd = distance(tablelen, tablelenbits, bkt, idx);
|
||||||
map_bucket_swap(bkt, &b);
|
if (d > dd) {
|
||||||
|
map_bucket_swap(bkt, &hash, &key, &data);
|
||||||
|
d = dd;
|
||||||
} else if (bkt->key == key) {
|
} else if (bkt->key == key) {
|
||||||
/* TODO This check is just a waste after first swap or if this
|
/* TODO This check is just a waste after first swap or if this
|
||||||
function is called from map_resize. That said, there is no
|
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;
|
return NGHTTP2_ERR_INVALID_ARGUMENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
++b.psl;
|
++d;
|
||||||
idx = (idx + 1) & mask;
|
idx = (idx + 1) & (tablelen - 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int map_resize(nghttp2_map *map, size_t new_hashbits) {
|
/* new_tablelen must be power of 2 and new_tablelen == (1 <<
|
||||||
size_t i;
|
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;
|
nghttp2_map_bucket *bkt;
|
||||||
size_t tablelen;
|
|
||||||
int rv;
|
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;
|
(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;
|
return NGHTTP2_ERR_NOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (map->size) {
|
for (i = 0; i < map->tablelen; ++i) {
|
||||||
tablelen = 1u << map->hashbits;
|
bkt = &map->table[i];
|
||||||
|
if (bkt->data == NULL) {
|
||||||
for (i = 0; i < tablelen; ++i) {
|
continue;
|
||||||
bkt = &map->table[i];
|
|
||||||
if (bkt->data == NULL) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
rv = map_insert(&new_map, bkt->key, bkt->data);
|
|
||||||
|
|
||||||
assert(0 == rv);
|
|
||||||
}
|
}
|
||||||
|
rv = insert(new_table, new_tablelen, new_tablelenbits, bkt->hash, bkt->key,
|
||||||
|
bkt->data);
|
||||||
|
|
||||||
|
assert(0 == rv);
|
||||||
}
|
}
|
||||||
|
|
||||||
nghttp2_mem_free(map->mem, map->table);
|
nghttp2_mem_free(map->mem, map->table);
|
||||||
map->table = new_map.table;
|
map->tablelen = new_tablelen;
|
||||||
map->hashbits = new_hashbits;
|
map->tablelenbits = new_tablelenbits;
|
||||||
|
map->table = new_table;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -200,48 +220,49 @@ int nghttp2_map_insert(nghttp2_map *map, nghttp2_map_key_type key, void *data) {
|
|||||||
|
|
||||||
assert(data);
|
assert(data);
|
||||||
|
|
||||||
/* Load factor is 7/8 */
|
/* Load factor is 0.75 */
|
||||||
/* Under the very initial condition, that is map->size == 0 and
|
if ((map->size + 1) * 4 > map->tablelen * 3) {
|
||||||
map->hashbits == 0, 8 > 7 still holds nicely. */
|
if (map->tablelen) {
|
||||||
if ((map->size + 1) * 8 > (1u << map->hashbits) * 7) {
|
rv = map_resize(map, map->tablelen * 2, map->tablelenbits + 1);
|
||||||
if (map->hashbits) {
|
|
||||||
rv = map_resize(map, map->hashbits + 1);
|
|
||||||
if (rv != 0) {
|
if (rv != 0) {
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
rv = map_resize(map, NGHTTP2_INITIAL_HASHBITS);
|
rv = map_resize(map, 1 << NGHTTP2_INITIAL_TABLE_LENBITS,
|
||||||
|
NGHTTP2_INITIAL_TABLE_LENBITS);
|
||||||
if (rv != 0) {
|
if (rv != 0) {
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rv = map_insert(map, key, data);
|
rv = insert(map->table, map->tablelen, map->tablelenbits, hash(key), key,
|
||||||
|
data);
|
||||||
if (rv != 0) {
|
if (rv != 0) {
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
++map->size;
|
||||||
return 0;
|
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;
|
size_t idx;
|
||||||
nghttp2_map_bucket *bkt;
|
nghttp2_map_bucket *bkt;
|
||||||
size_t psl = 0;
|
size_t d = 0;
|
||||||
size_t mask;
|
|
||||||
|
|
||||||
if (map->size == 0) {
|
if (map->size == 0) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
idx = map_hash(map, key);
|
h = hash(key);
|
||||||
mask = (1u << map->hashbits) - 1;
|
idx = h2idx(h, map->tablelenbits);
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
bkt = &map->table[idx];
|
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;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -249,47 +270,50 @@ void *nghttp2_map_find(const nghttp2_map *map, nghttp2_map_key_type key) {
|
|||||||
return bkt->data;
|
return bkt->data;
|
||||||
}
|
}
|
||||||
|
|
||||||
++psl;
|
++d;
|
||||||
idx = (idx + 1) & mask;
|
idx = (idx + 1) & (map->tablelen - 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int nghttp2_map_remove(nghttp2_map *map, nghttp2_map_key_type key) {
|
int nghttp2_map_remove(nghttp2_map *map, nghttp2_map_key_type key) {
|
||||||
size_t idx;
|
uint32_t h;
|
||||||
nghttp2_map_bucket *b, *bkt;
|
size_t idx, didx;
|
||||||
size_t psl = 0;
|
nghttp2_map_bucket *bkt;
|
||||||
size_t mask;
|
size_t d = 0;
|
||||||
|
|
||||||
if (map->size == 0) {
|
if (map->size == 0) {
|
||||||
return NGHTTP2_ERR_INVALID_ARGUMENT;
|
return NGHTTP2_ERR_INVALID_ARGUMENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
idx = map_hash(map, key);
|
h = hash(key);
|
||||||
mask = (1u << map->hashbits) - 1;
|
idx = h2idx(h, map->tablelenbits);
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
bkt = &map->table[idx];
|
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;
|
return NGHTTP2_ERR_INVALID_ARGUMENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bkt->key == key) {
|
if (bkt->key == key) {
|
||||||
b = bkt;
|
map_bucket_set_data(bkt, 0, 0, NULL);
|
||||||
idx = (idx + 1) & mask;
|
|
||||||
|
didx = idx;
|
||||||
|
idx = (idx + 1) & (map->tablelen - 1);
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
bkt = &map->table[idx];
|
bkt = &map->table[idx];
|
||||||
if (bkt->data == NULL || bkt->psl == 0) {
|
if (bkt->data == NULL ||
|
||||||
b->data = NULL;
|
distance(map->tablelen, map->tablelenbits, bkt, idx) == 0) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
--bkt->psl;
|
map->table[didx] = *bkt;
|
||||||
*b = *bkt;
|
map_bucket_set_data(bkt, 0, 0, NULL);
|
||||||
b = bkt;
|
didx = idx;
|
||||||
|
|
||||||
idx = (idx + 1) & mask;
|
idx = (idx + 1) & (map->tablelen - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
--map->size;
|
--map->size;
|
||||||
@@ -297,18 +321,18 @@ int nghttp2_map_remove(nghttp2_map *map, nghttp2_map_key_type key) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
++psl;
|
++d;
|
||||||
idx = (idx + 1) & mask;
|
idx = (idx + 1) & (map->tablelen - 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void nghttp2_map_clear(nghttp2_map *map) {
|
void nghttp2_map_clear(nghttp2_map *map) {
|
||||||
if (map->size == 0) {
|
if (map->tablelen == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(map->table, 0, sizeof(*map->table) * (1u << map->hashbits));
|
memset(map->table, 0, sizeof(*map->table) * map->tablelen);
|
||||||
map->size = 0;
|
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
|
#ifdef HAVE_CONFIG_H
|
||||||
# include <config.h>
|
# include <config.h>
|
||||||
#endif /* defined(HAVE_CONFIG_H) */
|
#endif /* HAVE_CONFIG_H */
|
||||||
|
|
||||||
#include <nghttp2/nghttp2.h>
|
#include <nghttp2/nghttp2.h>
|
||||||
|
|
||||||
@@ -39,7 +39,7 @@
|
|||||||
typedef int32_t nghttp2_map_key_type;
|
typedef int32_t nghttp2_map_key_type;
|
||||||
|
|
||||||
typedef struct nghttp2_map_bucket {
|
typedef struct nghttp2_map_bucket {
|
||||||
uint32_t psl;
|
uint32_t hash;
|
||||||
nghttp2_map_key_type key;
|
nghttp2_map_key_type key;
|
||||||
void *data;
|
void *data;
|
||||||
} nghttp2_map_bucket;
|
} nghttp2_map_bucket;
|
||||||
@@ -47,26 +47,34 @@ typedef struct nghttp2_map_bucket {
|
|||||||
typedef struct nghttp2_map {
|
typedef struct nghttp2_map {
|
||||||
nghttp2_map_bucket *table;
|
nghttp2_map_bucket *table;
|
||||||
nghttp2_mem *mem;
|
nghttp2_mem *mem;
|
||||||
uint32_t seed;
|
|
||||||
size_t size;
|
size_t size;
|
||||||
size_t hashbits;
|
uint32_t tablelen;
|
||||||
|
uint32_t tablelenbits;
|
||||||
} nghttp2_map;
|
} 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|.
|
* Deallocates any resources allocated for |map|. The stored entries
|
||||||
* The stored entries are not freed by this function. Use
|
* are not freed by this function. Use nghttp2_map_each_free() to free
|
||||||
* nghttp2_map_each() to free each entry.
|
* each entries.
|
||||||
*/
|
*/
|
||||||
void nghttp2_map_free(nghttp2_map *map);
|
void nghttp2_map_free(nghttp2_map *map);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* nghttp2_map_insert inserts the new |data| with the |key| to the map
|
* Deallocates each entries using |func| function and any resources
|
||||||
* |map|.
|
* 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
|
* This function returns 0 if it succeeds, or one of the following
|
||||||
* negative error codes:
|
* negative error codes:
|
||||||
@@ -74,56 +82,57 @@ void nghttp2_map_free(nghttp2_map *map);
|
|||||||
* NGHTTP2_ERR_INVALID_ARGUMENT
|
* NGHTTP2_ERR_INVALID_ARGUMENT
|
||||||
* The item associated by |key| already exists.
|
* The item associated by |key| already exists.
|
||||||
* NGHTTP2_ERR_NOMEM
|
* NGHTTP2_ERR_NOMEM
|
||||||
* Out of memory
|
* Out of memory
|
||||||
*/
|
*/
|
||||||
int nghttp2_map_insert(nghttp2_map *map, nghttp2_map_key_type key, void *data);
|
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
|
* Returns the data associated by the key |key|. If there is no such
|
||||||
* there is no such entry, this function returns NULL.
|
* 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|
|
* Removes the data associated by the key |key| from the |map|. The
|
||||||
* from the |map|. The removed entry is not freed by this function.
|
* removed data is not freed by this function.
|
||||||
*
|
*
|
||||||
* This function returns 0 if it succeeds, or one of the following
|
* This function returns 0 if it succeeds, or one of the following
|
||||||
* negative error codes:
|
* negative error codes:
|
||||||
*
|
*
|
||||||
* NGHTTP2_ERR_INVALID_ARGUMENT
|
* 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);
|
int nghttp2_map_remove(nghttp2_map *map, nghttp2_map_key_type key);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* nghttp2_map_clear removes all entries from |map|. The removed
|
* Removes all entries from |map|.
|
||||||
* entry is not freed by this function.
|
|
||||||
*/
|
*/
|
||||||
void nghttp2_map_clear(nghttp2_map *map);
|
void nghttp2_map_clear(nghttp2_map *map);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* nghttp2_map_size returns the number of items stored in the map
|
* Returns the number of items stored in the map |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
|
* Applies the function |func| to each data in the |map| with the
|
||||||
* |map| with the optional user supplied pointer |ptr|.
|
* optional user supplied pointer |ptr|.
|
||||||
*
|
*
|
||||||
* If the |func| returns 0, this function calls the |func| with the
|
* 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| for further entries and return the return value of the
|
||||||
* |func| immediately. Thus, this function returns 0 if all the
|
* |func| immediately. Thus, this function returns 0 if all the
|
||||||
* invocations of the |func| return 0, or nonzero value which the last
|
* invocations of the |func| return 0, or nonzero value which the last
|
||||||
* invocation of |func| returns.
|
* 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);
|
void *ptr);
|
||||||
|
|
||||||
#ifndef WIN32
|
#ifndef WIN32
|
||||||
void nghttp2_map_print_distance(const nghttp2_map *map);
|
void nghttp2_map_print_distance(nghttp2_map *map);
|
||||||
#endif /* !defined(WIN32) */
|
#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(
|
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->opt_set_mask |= NGHTTP2_OPT_SERVER_FALLBACK_RFC7540_PRIORITIES;
|
||||||
option->server_fallback_rfc7540_priorities = val;
|
option->server_fallback_rfc7540_priorities = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
void nghttp2_option_set_no_rfc9113_leading_and_trailing_ws_validation(
|
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 |=
|
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;
|
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->opt_set_mask |= NGHTTP2_OPT_MAX_CONTINUATIONS;
|
||||||
option->max_continuations = val;
|
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_NO_RFC9113_LEADING_AND_TRAILING_WS_VALIDATION = 1 << 14,
|
||||||
NGHTTP2_OPT_STREAM_RESET_RATE_LIMIT = 1 << 15,
|
NGHTTP2_OPT_STREAM_RESET_RATE_LIMIT = 1 << 15,
|
||||||
NGHTTP2_OPT_MAX_CONTINUATIONS = 1 << 16,
|
NGHTTP2_OPT_MAX_CONTINUATIONS = 1 << 16,
|
||||||
NGHTTP2_OPT_GLITCH_RATE_LIMIT = 1 << 17,
|
|
||||||
} nghttp2_option_flag;
|
} nghttp2_option_flag;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -84,11 +83,6 @@ struct nghttp2_option {
|
|||||||
*/
|
*/
|
||||||
uint64_t stream_reset_burst;
|
uint64_t stream_reset_burst;
|
||||||
uint64_t stream_reset_rate;
|
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
|
* 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) {
|
int nghttp2_queue_push(nghttp2_queue *queue, void *data) {
|
||||||
nghttp2_queue_cell *new_cell =
|
nghttp2_queue_cell *new_cell =
|
||||||
(nghttp2_queue_cell *)malloc(sizeof(nghttp2_queue_cell));
|
(nghttp2_queue_cell *)malloc(sizeof(nghttp2_queue_cell));
|
||||||
if (!new_cell) {
|
if (!new_cell) {
|
||||||
return NGHTTP2_ERR_NOMEM;
|
return NGHTTP2_ERR_NOMEM;
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -45,8 +45,6 @@
|
|||||||
preface handling. */
|
preface handling. */
|
||||||
extern int nghttp2_enable_strict_preface;
|
extern int nghttp2_enable_strict_preface;
|
||||||
|
|
||||||
extern nghttp2_stream nghttp2_stream_root;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Option flags.
|
* Option flags.
|
||||||
*/
|
*/
|
||||||
@@ -55,6 +53,8 @@ typedef enum {
|
|||||||
NGHTTP2_OPTMASK_NO_RECV_CLIENT_MAGIC = 1 << 1,
|
NGHTTP2_OPTMASK_NO_RECV_CLIENT_MAGIC = 1 << 1,
|
||||||
NGHTTP2_OPTMASK_NO_HTTP_MESSAGING = 1 << 2,
|
NGHTTP2_OPTMASK_NO_HTTP_MESSAGING = 1 << 2,
|
||||||
NGHTTP2_OPTMASK_NO_AUTO_PING_ACK = 1 << 3,
|
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_NO_RFC9113_LEADING_AND_TRAILING_WS_VALIDATION = 1 << 6,
|
||||||
} nghttp2_optmask;
|
} nghttp2_optmask;
|
||||||
|
|
||||||
@@ -89,6 +89,10 @@ typedef struct {
|
|||||||
/* The default maximum number of incoming reserved streams */
|
/* The default maximum number of incoming reserved streams */
|
||||||
#define NGHTTP2_MAX_INCOMING_RESERVED_STREAMS 200
|
#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
|
/* The maximum number of items in outbound queue, which is considered
|
||||||
as flooding caused by peer. All frames are not considered here.
|
as flooding caused by peer. All frames are not considered here.
|
||||||
We only consider PING + ACK and SETTINGS + ACK. This is because
|
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_BURST 1000
|
||||||
#define NGHTTP2_DEFAULT_STREAM_RESET_RATE 33
|
#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
|
/* The default max number of CONTINUATION frames following an incoming
|
||||||
HEADER frame. */
|
HEADER frame. */
|
||||||
#define NGHTTP2_DEFAULT_MAX_CONTINUATIONS 8
|
#define NGHTTP2_DEFAULT_MAX_CONTINUATIONS 8
|
||||||
@@ -205,6 +205,8 @@ typedef struct nghttp2_inflight_settings nghttp2_inflight_settings;
|
|||||||
|
|
||||||
struct nghttp2_session {
|
struct nghttp2_session {
|
||||||
nghttp2_map /* <nghttp2_stream*> */ streams;
|
nghttp2_map /* <nghttp2_stream*> */ streams;
|
||||||
|
/* root of dependency tree*/
|
||||||
|
nghttp2_stream root;
|
||||||
/* Queue for outbound urgent frames (PING and SETTINGS) */
|
/* Queue for outbound urgent frames (PING and SETTINGS) */
|
||||||
nghttp2_outbound_queue ob_urgent;
|
nghttp2_outbound_queue ob_urgent;
|
||||||
/* Queue for non-DATA frames */
|
/* Queue for non-DATA frames */
|
||||||
@@ -227,14 +229,26 @@ struct nghttp2_session {
|
|||||||
/* Memory allocator */
|
/* Memory allocator */
|
||||||
nghttp2_mem mem;
|
nghttp2_mem mem;
|
||||||
void *user_data;
|
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
|
/* Queue of In-flight SETTINGS values. SETTINGS bearing ACK is not
|
||||||
considered as in-flight. */
|
considered as in-flight. */
|
||||||
nghttp2_inflight_settings *inflight_settings_head;
|
nghttp2_inflight_settings *inflight_settings_head;
|
||||||
/* Stream reset rate limiter. If receiving excessive amount of
|
/* Stream reset rate limiter. If receiving excessive amount of
|
||||||
stream resets, GOAWAY will be sent. */
|
stream resets, GOAWAY will be sent. */
|
||||||
nghttp2_ratelim stream_reset_ratelim;
|
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
|
/* Sequential number across all streams to process streams in
|
||||||
FIFO. */
|
FIFO. */
|
||||||
uint64_t stream_seq;
|
uint64_t stream_seq;
|
||||||
@@ -262,9 +276,10 @@ struct nghttp2_session {
|
|||||||
|closed_stream_head|. The current implementation only keeps
|
|closed_stream_head|. The current implementation only keeps
|
||||||
incoming streams and session is initialized as server. */
|
incoming streams and session is initialized as server. */
|
||||||
size_t num_closed_streams;
|
size_t num_closed_streams;
|
||||||
/* The number of idle streams kept in |streams| hash. The current
|
/* The number of idle streams kept in |streams| hash. The idle
|
||||||
implementation only keeps idle streams if session is initialized
|
streams can be accessed through doubly linked list
|
||||||
as server. */
|
|idle_stream_head|. The current implementation only keeps idle
|
||||||
|
streams if session is initialized as server. */
|
||||||
size_t num_idle_streams;
|
size_t num_idle_streams;
|
||||||
/* The number of bytes allocated for nvbuf */
|
/* The number of bytes allocated for nvbuf */
|
||||||
size_t nvbuflen;
|
size_t nvbuflen;
|
||||||
@@ -347,6 +362,8 @@ struct nghttp2_session {
|
|||||||
/* Unacked local SETTINGS_NO_RFC7540_PRIORITIES value, which is
|
/* Unacked local SETTINGS_NO_RFC7540_PRIORITIES value, which is
|
||||||
effective before it is acknowledged. */
|
effective before it is acknowledged. */
|
||||||
uint8_t pending_no_rfc7540_priorities;
|
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. */
|
/* Nonzero if the session is server side. */
|
||||||
uint8_t server;
|
uint8_t server;
|
||||||
/* Flags indicating GOAWAY is sent and/or received. The flags are
|
/* 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,
|
int nghttp2_session_add_item(nghttp2_session *session,
|
||||||
nghttp2_outbound_item *item);
|
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
|
* Adds RST_STREAM frame for the stream |stream_id| with the error
|
||||||
* code |error_code|. This is a convenient function built on top of
|
* 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
|
* This function simply returns 0 without adding RST_STREAM frame if
|
||||||
* given stream is in NGHTTP2_STREAM_CLOSING state, because multiple
|
* given stream is in NGHTTP2_STREAM_CLOSING state, because multiple
|
||||||
* RST_STREAM for a stream is redundant. It also returns 0 without
|
* RST_STREAM for a stream is redundant.
|
||||||
* adding the frame if |continue_without_stream| is nonzero, and
|
|
||||||
* stream was already gone.
|
|
||||||
*
|
*
|
||||||
* This function returns 0 if it succeeds, or one of the following
|
* This function returns 0 if it succeeds, or one of the following
|
||||||
* negative error codes:
|
* negative error codes:
|
||||||
@@ -432,10 +440,8 @@ int nghttp2_session_add_rst_stream(nghttp2_session *session, int32_t stream_id,
|
|||||||
* NGHTTP2_ERR_NOMEM
|
* NGHTTP2_ERR_NOMEM
|
||||||
* Out of memory.
|
* Out of memory.
|
||||||
*/
|
*/
|
||||||
int nghttp2_session_add_rst_stream_continue(nghttp2_session *session,
|
int nghttp2_session_add_rst_stream(nghttp2_session *session, int32_t stream_id,
|
||||||
int32_t stream_id,
|
uint32_t error_code);
|
||||||
uint32_t error_code,
|
|
||||||
int continue_without_stream);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Adds PING frame. This is a convenient function built on top of
|
* 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
|
* This function returns a pointer to created new stream object, or
|
||||||
* NULL.
|
* 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,
|
nghttp2_stream *nghttp2_session_open_stream(nghttp2_session *session,
|
||||||
int32_t stream_id, uint8_t flags,
|
int32_t stream_id, uint8_t flags,
|
||||||
|
nghttp2_priority_spec *pri_spec,
|
||||||
nghttp2_stream_state initial_state,
|
nghttp2_stream_state initial_state,
|
||||||
void *stream_user_data);
|
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,
|
* is indicated by the |error_code|. When closing the stream,
|
||||||
* on_stream_close_callback will be called.
|
* 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
|
* This function returns 0 if it succeeds, or one the following
|
||||||
* negative error codes:
|
* 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
|
* Deletes |stream| from memory. After this function returns, stream
|
||||||
* cannot be accessed.
|
* 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,
|
int nghttp2_session_destroy_stream(nghttp2_session *session,
|
||||||
nghttp2_stream *stream);
|
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|
|
* 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,
|
nghttp2_settings_entry *iv,
|
||||||
size_t niv);
|
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|
|
* Terminates current |session| with the |error_code|. The |reason|
|
||||||
* is NULL-terminated debug string.
|
* is NULL-terminated debug string.
|
||||||
|
|||||||
@@ -25,17 +25,45 @@
|
|||||||
#include "nghttp2_stream.h"
|
#include "nghttp2_stream.h"
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
#include "nghttp2_session.h"
|
#include "nghttp2_session.h"
|
||||||
#include "nghttp2_helper.h"
|
#include "nghttp2_helper.h"
|
||||||
#include "nghttp2_debug.h"
|
#include "nghttp2_debug.h"
|
||||||
#include "nghttp2_frame.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,
|
void nghttp2_stream_init(nghttp2_stream *stream, int32_t stream_id,
|
||||||
uint8_t flags, nghttp2_stream_state initial_state,
|
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,
|
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->stream_id = stream_id;
|
||||||
stream->flags = flags;
|
stream->flags = flags;
|
||||||
stream->state = initial_state;
|
stream->state = initial_state;
|
||||||
@@ -49,36 +77,428 @@ void nghttp2_stream_init(nghttp2_stream *stream, int32_t stream_id,
|
|||||||
stream->recv_reduction = 0;
|
stream->recv_reduction = 0;
|
||||||
stream->window_update_queued = 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->closed_next = NULL;
|
||||||
|
|
||||||
|
stream->weight = weight;
|
||||||
|
stream->sum_dep_weight = 0;
|
||||||
|
|
||||||
stream->http_flags = NGHTTP2_HTTP_FLAG_NONE;
|
stream->http_flags = NGHTTP2_HTTP_FLAG_NONE;
|
||||||
stream->content_length = -1;
|
stream->content_length = -1;
|
||||||
stream->recv_content_length = 0;
|
stream->recv_content_length = 0;
|
||||||
stream->status_code = -1;
|
stream->status_code = -1;
|
||||||
|
|
||||||
stream->queued = 0;
|
stream->queued = 0;
|
||||||
|
stream->descendant_last_cycle = 0;
|
||||||
stream->cycle = 0;
|
stream->cycle = 0;
|
||||||
stream->pending_penalty = 0;
|
stream->pending_penalty = 0;
|
||||||
|
stream->descendant_next_seq = 0;
|
||||||
stream->seq = 0;
|
stream->seq = 0;
|
||||||
stream->last_writelen = 0;
|
stream->last_writelen = 0;
|
||||||
|
|
||||||
stream->extpri = stream->http_extpri = NGHTTP2_EXTPRI_DEFAULT_URGENCY;
|
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) {
|
void nghttp2_stream_shutdown(nghttp2_stream *stream, nghttp2_shut_flag flag) {
|
||||||
stream->shut_flags = (uint8_t)(stream->shut_flags | 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->flags & NGHTTP2_STREAM_FLAG_DEFERRED_ALL) == 0);
|
||||||
assert(stream->item == NULL);
|
assert(stream->item == NULL);
|
||||||
|
|
||||||
DEBUGF("stream: stream=%d attach item=%p\n", stream->stream_id, item);
|
DEBUGF("stream: stream=%d attach item=%p\n", stream->stream_id, item);
|
||||||
|
|
||||||
stream->item = 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) {
|
void nghttp2_stream_detach_item(nghttp2_stream *stream) {
|
||||||
@@ -86,6 +506,12 @@ void nghttp2_stream_detach_item(nghttp2_stream *stream) {
|
|||||||
|
|
||||||
stream->item = NULL;
|
stream->item = NULL;
|
||||||
stream->flags = (uint8_t)(stream->flags & ~NGHTTP2_STREAM_FLAG_DEFERRED_ALL);
|
stream->flags = (uint8_t)(stream->flags & ~NGHTTP2_STREAM_FLAG_DEFERRED_ALL);
|
||||||
|
|
||||||
|
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) {
|
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->item, flags);
|
||||||
|
|
||||||
stream->flags |= 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,
|
int nghttp2_stream_resume_deferred_item(nghttp2_stream *stream, uint8_t flags) {
|
||||||
uint8_t flags) {
|
|
||||||
assert(stream->item);
|
assert(stream->item);
|
||||||
|
|
||||||
DEBUGF("stream: stream=%d resume item=%p flags=%02x\n", stream->stream_id,
|
DEBUGF("stream: stream=%d resume item=%p flags=%02x\n", stream->stream_id,
|
||||||
stream->item, flags);
|
stream->item, flags);
|
||||||
|
|
||||||
stream->flags = (uint8_t)(stream->flags & ~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) {
|
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(
|
int nghttp2_stream_update_remote_initial_window_size(
|
||||||
nghttp2_stream *stream, int32_t new_initial_window_size,
|
nghttp2_stream *stream, int32_t new_initial_window_size,
|
||||||
int32_t old_initial_window_size) {
|
int32_t old_initial_window_size) {
|
||||||
return update_initial_window_size(&stream->remote_window_size,
|
return update_initial_window_size(&stream->remote_window_size,
|
||||||
new_initial_window_size,
|
new_initial_window_size,
|
||||||
old_initial_window_size);
|
old_initial_window_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
int nghttp2_stream_update_local_initial_window_size(
|
int nghttp2_stream_update_local_initial_window_size(
|
||||||
nghttp2_stream *stream, int32_t new_initial_window_size,
|
nghttp2_stream *stream, int32_t new_initial_window_size,
|
||||||
int32_t old_initial_window_size) {
|
int32_t old_initial_window_size) {
|
||||||
return update_initial_window_size(&stream->local_window_size,
|
return update_initial_window_size(&stream->local_window_size,
|
||||||
new_initial_window_size,
|
new_initial_window_size,
|
||||||
old_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);
|
stream->flags = (uint8_t)(stream->flags & ~NGHTTP2_STREAM_FLAG_PUSH);
|
||||||
}
|
}
|
||||||
|
|
||||||
nghttp2_stream_proto_state nghttp2_stream_get_state(nghttp2_stream *stream) {
|
int nghttp2_stream_dep_find_ancestor(nghttp2_stream *stream,
|
||||||
if (stream == &nghttp2_stream_root) {
|
nghttp2_stream *target) {
|
||||||
return NGHTTP2_STREAM_STATE_IDLE;
|
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) {
|
if (stream->flags & NGHTTP2_STREAM_FLAG_CLOSED) {
|
||||||
return NGHTTP2_STREAM_STATE_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) {
|
nghttp2_stream *nghttp2_stream_get_parent(nghttp2_stream *stream) {
|
||||||
(void)stream;
|
return stream->dep_prev;
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
nghttp2_stream *nghttp2_stream_get_next_sibling(nghttp2_stream *stream) {
|
nghttp2_stream *nghttp2_stream_get_next_sibling(nghttp2_stream *stream) {
|
||||||
(void)stream;
|
return stream->sib_next;
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
nghttp2_stream *nghttp2_stream_get_previous_sibling(nghttp2_stream *stream) {
|
nghttp2_stream *nghttp2_stream_get_previous_sibling(nghttp2_stream *stream) {
|
||||||
(void)stream;
|
return stream->sib_prev;
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
nghttp2_stream *nghttp2_stream_get_first_child(nghttp2_stream *stream) {
|
nghttp2_stream *nghttp2_stream_get_first_child(nghttp2_stream *stream) {
|
||||||
(void)stream;
|
return stream->dep_next;
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t nghttp2_stream_get_weight(nghttp2_stream *stream) {
|
int32_t nghttp2_stream_get_weight(nghttp2_stream *stream) {
|
||||||
(void)stream;
|
return stream->weight;
|
||||||
|
|
||||||
return NGHTTP2_DEFAULT_WEIGHT;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t nghttp2_stream_get_sum_dependency_weight(nghttp2_stream *stream) {
|
int32_t nghttp2_stream_get_sum_dependency_weight(nghttp2_stream *stream) {
|
||||||
(void)stream;
|
return stream->sum_dep_weight;
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t nghttp2_stream_get_stream_id(nghttp2_stream *stream) {
|
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
|
/* bitwise OR of NGHTTP2_STREAM_FLAG_DEFERRED_FLOW_CONTROL and
|
||||||
NGHTTP2_STREAM_FLAG_DEFERRED_USER. */
|
NGHTTP2_STREAM_FLAG_DEFERRED_USER. */
|
||||||
NGHTTP2_STREAM_FLAG_DEFERRED_ALL = 0x0c,
|
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. */
|
/* Ignore client RFC 9218 priority signal. */
|
||||||
NGHTTP2_STREAM_FLAG_IGNORE_CLIENT_PRIORITIES = 0x20,
|
NGHTTP2_STREAM_FLAG_IGNORE_CLIENT_PRIORITIES = 0x20,
|
||||||
/* Indicates that RFC 9113 leading and trailing white spaces
|
/* 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_HEAD = 1 << 8,
|
||||||
NGHTTP2_HTTP_FLAG_METH_OPTIONS = 1 << 9,
|
NGHTTP2_HTTP_FLAG_METH_OPTIONS = 1 << 9,
|
||||||
NGHTTP2_HTTP_FLAG_METH_UPGRADE_WORKAROUND = 1 << 10,
|
NGHTTP2_HTTP_FLAG_METH_UPGRADE_WORKAROUND = 1 << 10,
|
||||||
NGHTTP2_HTTP_FLAG_METH_ALL =
|
NGHTTP2_HTTP_FLAG_METH_ALL = NGHTTP2_HTTP_FLAG_METH_CONNECT |
|
||||||
NGHTTP2_HTTP_FLAG_METH_CONNECT | NGHTTP2_HTTP_FLAG_METH_HEAD |
|
NGHTTP2_HTTP_FLAG_METH_HEAD |
|
||||||
NGHTTP2_HTTP_FLAG_METH_OPTIONS | NGHTTP2_HTTP_FLAG_METH_UPGRADE_WORKAROUND,
|
NGHTTP2_HTTP_FLAG_METH_OPTIONS |
|
||||||
|
NGHTTP2_HTTP_FLAG_METH_UPGRADE_WORKAROUND,
|
||||||
/* :path category */
|
/* :path category */
|
||||||
/* path starts with "/" */
|
/* path starts with "/" */
|
||||||
NGHTTP2_HTTP_FLAG_PATH_REGULAR = 1 << 11,
|
NGHTTP2_HTTP_FLAG_PATH_REGULAR = 1 << 11,
|
||||||
@@ -143,18 +147,39 @@ typedef enum {
|
|||||||
} nghttp2_http_flag;
|
} nghttp2_http_flag;
|
||||||
|
|
||||||
struct nghttp2_stream {
|
struct nghttp2_stream {
|
||||||
nghttp2_stream_state state;
|
/* Entry for dep_prev->obq */
|
||||||
nghttp2_pq_entry pq_entry;
|
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. */
|
/* Content-Length of request/response body. -1 if unknown. */
|
||||||
int64_t content_length;
|
int64_t content_length;
|
||||||
/* Received body so far */
|
/* Received body so far */
|
||||||
int64_t recv_content_length;
|
int64_t recv_content_length;
|
||||||
|
/* Base last_cycle for direct descendent streams. */
|
||||||
|
uint64_t descendant_last_cycle;
|
||||||
/* Next scheduled time to sent item */
|
/* Next scheduled time to sent item */
|
||||||
uint64_t cycle;
|
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
|
/* Secondary key for prioritization to break a tie for cycle. This
|
||||||
value is monotonically increased for single parent stream. */
|
value is monotonically increased for single parent stream. */
|
||||||
uint64_t seq;
|
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. */
|
/* The arbitrary data provided by user for this stream. */
|
||||||
void *stream_user_data;
|
void *stream_user_data;
|
||||||
/* Item to send */
|
/* Item to send */
|
||||||
@@ -181,8 +206,13 @@ struct nghttp2_stream {
|
|||||||
NGHTTP2_INITIAL_WINDOW_SIZE and could be increased/decreased by
|
NGHTTP2_INITIAL_WINDOW_SIZE and could be increased/decreased by
|
||||||
submitting WINDOW_UPDATE. See nghttp2_submit_window_update(). */
|
submitting WINDOW_UPDATE. See nghttp2_submit_window_update(). */
|
||||||
int32_t local_window_size;
|
int32_t local_window_size;
|
||||||
|
/* weight of this stream */
|
||||||
|
int32_t weight;
|
||||||
/* This is unpaid penalty (offset) when calculating cycle. */
|
/* This is unpaid penalty (offset) when calculating cycle. */
|
||||||
uint32_t pending_penalty;
|
uint32_t pending_penalty;
|
||||||
|
/* sum of weight of direct descendants */
|
||||||
|
int32_t sum_dep_weight;
|
||||||
|
nghttp2_stream_state state;
|
||||||
/* status code from remote server */
|
/* status code from remote server */
|
||||||
int16_t status_code;
|
int16_t status_code;
|
||||||
/* Bitwise OR of zero or more nghttp2_http_flag values */
|
/* 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,
|
void nghttp2_stream_init(nghttp2_stream *stream, int32_t stream_id,
|
||||||
uint8_t flags, nghttp2_stream_state initial_state,
|
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,
|
int32_t local_initial_window_size,
|
||||||
void *stream_user_data);
|
void *stream_user_data, nghttp2_mem *mem);
|
||||||
|
|
||||||
void nghttp2_stream_free(nghttp2_stream *stream);
|
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
|
* NGHTTP2_STREAM_FLAG_DEFERRED_FLOW_CONTROL and given masks are
|
||||||
* cleared if they are set. So even if this function is called, if
|
* cleared if they are set. So even if this function is called, if
|
||||||
* one of flag is still set, data does not become active.
|
* 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.
|
* 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.
|
* overflow.
|
||||||
*/
|
*/
|
||||||
int nghttp2_stream_update_remote_initial_window_size(
|
int nghttp2_stream_update_remote_initial_window_size(
|
||||||
nghttp2_stream *stream, int32_t new_initial_window_size,
|
nghttp2_stream *stream, int32_t new_initial_window_size,
|
||||||
int32_t old_initial_window_size);
|
int32_t old_initial_window_size);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Updates the local window size with the new value
|
* Updates the local window size with the new value
|
||||||
@@ -272,8 +308,8 @@ int nghttp2_stream_update_remote_initial_window_size(
|
|||||||
* overflow.
|
* overflow.
|
||||||
*/
|
*/
|
||||||
int nghttp2_stream_update_local_initial_window_size(
|
int nghttp2_stream_update_local_initial_window_size(
|
||||||
nghttp2_stream *stream, int32_t new_initial_window_size,
|
nghttp2_stream *stream, int32_t new_initial_window_size,
|
||||||
int32_t old_initial_window_size);
|
int32_t old_initial_window_size);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Call this function if promised stream |stream| is replied with
|
* 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);
|
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,
|
int nghttp2_stream_dep_find_ancestor(nghttp2_stream *stream,
|
||||||
nghttp2_outbound_item *item);
|
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
|
* 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);
|
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 */
|
#endif /* NGHTTP2_STREAM */
|
||||||
|
|||||||
@@ -32,12 +32,42 @@
|
|||||||
#include "nghttp2_helper.h"
|
#include "nghttp2_helper.h"
|
||||||
#include "nghttp2_priority_spec.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
|
/* This function takes ownership of |nva_copy|. Regardless of the
|
||||||
return value, the caller must not free |nva_copy| after this
|
return value, the caller must not free |nva_copy| after this
|
||||||
function returns. */
|
function returns. */
|
||||||
static int32_t submit_headers_shared(nghttp2_session *session, uint8_t flags,
|
static int32_t submit_headers_shared(nghttp2_session *session, uint8_t flags,
|
||||||
int32_t stream_id, nghttp2_nv *nva_copy,
|
int32_t stream_id,
|
||||||
size_t nvlen,
|
const nghttp2_priority_spec *pri_spec,
|
||||||
|
nghttp2_nv *nva_copy, size_t nvlen,
|
||||||
const nghttp2_data_provider_wrap *dpw,
|
const nghttp2_data_provider_wrap *dpw,
|
||||||
void *stream_user_data) {
|
void *stream_user_data) {
|
||||||
int rv;
|
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;
|
item->aux_data.headers.stream_user_data = stream_user_data;
|
||||||
|
|
||||||
flags_copy =
|
flags_copy =
|
||||||
(uint8_t)((flags & (NGHTTP2_FLAG_END_STREAM | NGHTTP2_FLAG_PRIORITY)) |
|
(uint8_t)((flags & (NGHTTP2_FLAG_END_STREAM | NGHTTP2_FLAG_PRIORITY)) |
|
||||||
NGHTTP2_FLAG_END_HEADERS);
|
NGHTTP2_FLAG_END_HEADERS);
|
||||||
|
|
||||||
if (stream_id == -1) {
|
if (stream_id == -1) {
|
||||||
if (session->next_stream_id > INT32_MAX) {
|
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;
|
frame = &item->frame;
|
||||||
|
|
||||||
nghttp2_frame_headers_init(&frame->headers, flags_copy, stream_id, hcat, NULL,
|
nghttp2_frame_headers_init(&frame->headers, flags_copy, stream_id, hcat,
|
||||||
nva_copy, nvlen);
|
pri_spec, nva_copy, nvlen);
|
||||||
|
|
||||||
rv = nghttp2_session_add_item(session, item);
|
rv = nghttp2_session_add_item(session, item);
|
||||||
|
|
||||||
@@ -111,22 +141,31 @@ fail2:
|
|||||||
|
|
||||||
static int32_t submit_headers_shared_nva(nghttp2_session *session,
|
static int32_t submit_headers_shared_nva(nghttp2_session *session,
|
||||||
uint8_t flags, int32_t stream_id,
|
uint8_t flags, int32_t stream_id,
|
||||||
|
const nghttp2_priority_spec *pri_spec,
|
||||||
const nghttp2_nv *nva, size_t nvlen,
|
const nghttp2_nv *nva, size_t nvlen,
|
||||||
const nghttp2_data_provider_wrap *dpw,
|
const nghttp2_data_provider_wrap *dpw,
|
||||||
void *stream_user_data) {
|
void *stream_user_data) {
|
||||||
int rv;
|
int rv;
|
||||||
nghttp2_nv *nva_copy;
|
nghttp2_nv *nva_copy;
|
||||||
|
nghttp2_priority_spec copy_pri_spec;
|
||||||
nghttp2_mem *mem;
|
nghttp2_mem *mem;
|
||||||
|
|
||||||
mem = &session->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);
|
rv = nghttp2_nv_array_copy(&nva_copy, nva, nvlen, mem);
|
||||||
if (rv < 0) {
|
if (rv < 0) {
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
return submit_headers_shared(session, flags, stream_id, nva_copy, nvlen, dpw,
|
return submit_headers_shared(session, flags, stream_id, ©_pri_spec,
|
||||||
stream_user_data);
|
nva_copy, nvlen, dpw, stream_user_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
int nghttp2_submit_trailer(nghttp2_session *session, int32_t stream_id,
|
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,
|
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,
|
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_priority_spec *pri_spec,
|
||||||
const nghttp2_nv *nva, size_t nvlen,
|
const nghttp2_nv *nva, size_t nvlen,
|
||||||
void *stream_user_data) {
|
void *stream_user_data) {
|
||||||
(void)pri_spec;
|
int rv;
|
||||||
|
|
||||||
if (stream_id == -1) {
|
if (stream_id == -1) {
|
||||||
if (session->server) {
|
if (session->server) {
|
||||||
@@ -156,8 +196,20 @@ int32_t nghttp2_submit_headers(nghttp2_session *session, uint8_t flags,
|
|||||||
|
|
||||||
flags &= NGHTTP2_FLAG_END_STREAM;
|
flags &= NGHTTP2_FLAG_END_STREAM;
|
||||||
|
|
||||||
return submit_headers_shared_nva(session, flags, stream_id, nva, nvlen, NULL,
|
if (pri_spec && !nghttp2_priority_spec_check_default(pri_spec) &&
|
||||||
stream_user_data);
|
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,
|
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,
|
int nghttp2_submit_priority(nghttp2_session *session, uint8_t flags,
|
||||||
int32_t stream_id,
|
int32_t stream_id,
|
||||||
const nghttp2_priority_spec *pri_spec) {
|
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)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;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -185,8 +278,7 @@ int nghttp2_submit_rst_stream(nghttp2_session *session, uint8_t flags,
|
|||||||
return NGHTTP2_ERR_INVALID_ARGUMENT;
|
return NGHTTP2_ERR_INVALID_ARGUMENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
return nghttp2_session_add_rst_stream_continue(
|
return nghttp2_session_add_rst_stream(session, stream_id, error_code);
|
||||||
session, stream_id, error_code, /* continue_without_stream = */ 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int nghttp2_submit_goaway(nghttp2_session *session, uint8_t flags,
|
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) {
|
if (stream_id == 0) {
|
||||||
rv = nghttp2_adjust_local_window_size(
|
rv = nghttp2_adjust_local_window_size(
|
||||||
&session->local_window_size, &session->recv_window_size,
|
&session->local_window_size, &session->recv_window_size,
|
||||||
&session->recv_reduction, &window_size_increment);
|
&session->recv_reduction, &window_size_increment);
|
||||||
if (rv != 0) {
|
if (rv != 0) {
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
@@ -309,8 +401,8 @@ int nghttp2_submit_window_update(nghttp2_session *session, uint8_t flags,
|
|||||||
}
|
}
|
||||||
|
|
||||||
rv = nghttp2_adjust_local_window_size(
|
rv = nghttp2_adjust_local_window_size(
|
||||||
&stream->local_window_size, &stream->recv_window_size,
|
&stream->local_window_size, &stream->recv_window_size,
|
||||||
&stream->recv_reduction, &window_size_increment);
|
&stream->recv_reduction, &window_size_increment);
|
||||||
if (rv != 0) {
|
if (rv != 0) {
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
@@ -319,10 +411,10 @@ int nghttp2_submit_window_update(nghttp2_session *session, uint8_t flags,
|
|||||||
if (window_size_increment > 0) {
|
if (window_size_increment > 0) {
|
||||||
if (stream_id == 0) {
|
if (stream_id == 0) {
|
||||||
session->consumed_size =
|
session->consumed_size =
|
||||||
nghttp2_max_int32(0, session->consumed_size - window_size_increment);
|
nghttp2_max_int32(0, session->consumed_size - window_size_increment);
|
||||||
} else {
|
} else {
|
||||||
stream->consumed_size =
|
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,
|
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) {
|
if (window_size_increment < 0) {
|
||||||
return nghttp2_adjust_local_window_size(
|
return nghttp2_adjust_local_window_size(
|
||||||
&session->local_window_size, &session->recv_window_size,
|
&session->local_window_size, &session->recv_window_size,
|
||||||
&session->recv_reduction, &window_size_increment);
|
&session->recv_reduction, &window_size_increment);
|
||||||
}
|
}
|
||||||
|
|
||||||
rv = nghttp2_increase_local_window_size(
|
rv = nghttp2_increase_local_window_size(
|
||||||
&session->local_window_size, &session->recv_window_size,
|
&session->local_window_size, &session->recv_window_size,
|
||||||
&session->recv_reduction, &window_size_increment);
|
&session->recv_reduction, &window_size_increment);
|
||||||
|
|
||||||
if (rv != 0) {
|
if (rv != 0) {
|
||||||
return rv;
|
return rv;
|
||||||
@@ -385,13 +477,13 @@ int nghttp2_session_set_local_window_size(nghttp2_session *session,
|
|||||||
|
|
||||||
if (window_size_increment < 0) {
|
if (window_size_increment < 0) {
|
||||||
return nghttp2_adjust_local_window_size(
|
return nghttp2_adjust_local_window_size(
|
||||||
&stream->local_window_size, &stream->recv_window_size,
|
&stream->local_window_size, &stream->recv_window_size,
|
||||||
&stream->recv_reduction, &window_size_increment);
|
&stream->recv_reduction, &window_size_increment);
|
||||||
}
|
}
|
||||||
|
|
||||||
rv = nghttp2_increase_local_window_size(
|
rv = nghttp2_increase_local_window_size(
|
||||||
&stream->local_window_size, &stream->recv_window_size,
|
&stream->local_window_size, &stream->recv_window_size,
|
||||||
&stream->recv_reduction, &window_size_increment);
|
&stream->recv_reduction, &window_size_increment);
|
||||||
|
|
||||||
if (rv != 0) {
|
if (rv != 0) {
|
||||||
return rv;
|
return rv;
|
||||||
@@ -487,7 +579,7 @@ int nghttp2_submit_altsvc(nghttp2_session *session, uint8_t flags,
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
fail_item_malloc:
|
fail_item_malloc:
|
||||||
nghttp2_mem_free(mem, buf);
|
free(buf);
|
||||||
|
|
||||||
return rv;
|
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. */
|
/* The last nov is added for terminal NULL character. */
|
||||||
ov_copy =
|
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) {
|
if (ov_copy == NULL) {
|
||||||
return NGHTTP2_ERR_NOMEM;
|
return NGHTTP2_ERR_NOMEM;
|
||||||
}
|
}
|
||||||
@@ -570,7 +662,7 @@ int nghttp2_submit_origin(nghttp2_session *session, uint8_t flags,
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
fail_item_malloc:
|
fail_item_malloc:
|
||||||
nghttp2_mem_free(mem, ov_copy);
|
free(ov_copy);
|
||||||
|
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
@@ -642,34 +734,51 @@ int nghttp2_submit_priority_update(nghttp2_session *session, uint8_t flags,
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
fail_item_malloc:
|
fail_item_malloc:
|
||||||
nghttp2_mem_free(mem, buf);
|
free(buf);
|
||||||
|
|
||||||
return rv;
|
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;
|
uint8_t flags = NGHTTP2_FLAG_NONE;
|
||||||
if (dpw == NULL || dpw->data_prd.read_callback == NULL) {
|
if (dpw == NULL || dpw->data_prd.read_callback == NULL) {
|
||||||
flags |= NGHTTP2_FLAG_END_STREAM;
|
flags |= NGHTTP2_FLAG_END_STREAM;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (pri_spec) {
|
||||||
|
flags |= NGHTTP2_FLAG_PRIORITY;
|
||||||
|
}
|
||||||
|
|
||||||
return flags;
|
return flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int32_t submit_request_shared(nghttp2_session *session,
|
static int32_t submit_request_shared(nghttp2_session *session,
|
||||||
|
const nghttp2_priority_spec *pri_spec,
|
||||||
const nghttp2_nv *nva, size_t nvlen,
|
const nghttp2_nv *nva, size_t nvlen,
|
||||||
const nghttp2_data_provider_wrap *dpw,
|
const nghttp2_data_provider_wrap *dpw,
|
||||||
void *stream_user_data) {
|
void *stream_user_data) {
|
||||||
uint8_t flags;
|
uint8_t flags;
|
||||||
|
int rv;
|
||||||
|
|
||||||
if (session->server) {
|
if (session->server) {
|
||||||
return NGHTTP2_ERR_PROTO;
|
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,
|
flags = set_request_flags(pri_spec, dpw);
|
||||||
stream_user_data);
|
|
||||||
|
return submit_headers_shared_nva(session, flags, -1, pri_spec, nva, nvlen,
|
||||||
|
dpw, stream_user_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t nghttp2_submit_request(nghttp2_session *session,
|
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,
|
const nghttp2_data_provider *data_prd,
|
||||||
void *stream_user_data) {
|
void *stream_user_data) {
|
||||||
nghttp2_data_provider_wrap dpw;
|
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),
|
nghttp2_data_provider_wrap_v1(&dpw, data_prd),
|
||||||
stream_user_data);
|
stream_user_data);
|
||||||
}
|
}
|
||||||
@@ -691,9 +799,8 @@ int32_t nghttp2_submit_request2(nghttp2_session *session,
|
|||||||
const nghttp2_data_provider2 *data_prd,
|
const nghttp2_data_provider2 *data_prd,
|
||||||
void *stream_user_data) {
|
void *stream_user_data) {
|
||||||
nghttp2_data_provider_wrap dpw;
|
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),
|
nghttp2_data_provider_wrap_v2(&dpw, data_prd),
|
||||||
stream_user_data);
|
stream_user_data);
|
||||||
}
|
}
|
||||||
@@ -720,8 +827,8 @@ static int submit_response_shared(nghttp2_session *session, int32_t stream_id,
|
|||||||
}
|
}
|
||||||
|
|
||||||
flags = set_response_flags(dpw);
|
flags = set_response_flags(dpw);
|
||||||
return submit_headers_shared_nva(session, flags, stream_id, nva, nvlen, dpw,
|
return submit_headers_shared_nva(session, flags, stream_id, NULL, nva, nvlen,
|
||||||
NULL);
|
dpw, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
int nghttp2_submit_response(nghttp2_session *session, int32_t stream_id,
|
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);
|
assert(data_prd);
|
||||||
|
|
||||||
return nghttp2_submit_data_shared(
|
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,
|
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);
|
assert(data_prd);
|
||||||
|
|
||||||
return nghttp2_submit_data_shared(
|
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,
|
ssize_t nghttp2_pack_settings_payload(uint8_t *buf, size_t buflen,
|
||||||
|
|||||||
@@ -31,7 +31,7 @@
|
|||||||
|
|
||||||
#include <nghttp2/nghttp2.h>
|
#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,
|
int nghttp2_submit_data_shared(nghttp2_session *session, uint8_t flags,
|
||||||
int32_t stream_id,
|
int32_t stream_id,
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ static uint64_t time_now_sec(void) {
|
|||||||
#if defined(HAVE_GETTICKCOUNT64) && !defined(__CYGWIN__)
|
#if defined(HAVE_GETTICKCOUNT64) && !defined(__CYGWIN__)
|
||||||
uint64_t nghttp2_time_now_sec(void) { return GetTickCount64() / 1000; }
|
uint64_t nghttp2_time_now_sec(void) { return GetTickCount64() / 1000; }
|
||||||
#elif defined(HAVE_CLOCK_GETTIME) && defined(HAVE_DECL_CLOCK_MONOTONIC) && \
|
#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) {
|
uint64_t nghttp2_time_now_sec(void) {
|
||||||
struct timespec tp;
|
struct timespec tp;
|
||||||
int rv = clock_gettime(CLOCK_MONOTONIC, &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) */
|
libcurl) */
|
||||||
#if (defined(_WIN32) || defined(__WIN32__)) && !defined(WIN32)
|
#if (defined(_WIN32) || defined(__WIN32__)) && !defined(WIN32)
|
||||||
# define WIN32
|
# define WIN32
|
||||||
#endif /* (defined(_WIN32) || defined(__WIN32__)) && !defined(WIN32) */
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif /* defined(__cplusplus) */
|
#endif
|
||||||
|
|
||||||
#if defined(_MSC_VER) && (_MSC_VER < 1800)
|
#if defined(_MSC_VER) && (_MSC_VER < 1800)
|
||||||
/* MSVC < 2013 does not have inttypes.h because it is not C99
|
/* MSVC < 2013 does not have inttypes.h because it is not C99
|
||||||
compliant. See compiler macros and version number in
|
compliant. See compiler macros and version number in
|
||||||
https://sourceforge.net/p/predef/wiki/Compilers/ */
|
https://sourceforge.net/p/predef/wiki/Compilers/ */
|
||||||
# include <stdint.h>
|
# include <stdint.h>
|
||||||
#else /* !(defined(_MSC_VER) && (_MSC_VER < 1800)) */
|
#else /* !defined(_MSC_VER) || (_MSC_VER >= 1800) */
|
||||||
# include <inttypes.h>
|
# include <inttypes.h>
|
||||||
#endif /* !(defined(_MSC_VER) && (_MSC_VER < 1800)) */
|
#endif /* !defined(_MSC_VER) || (_MSC_VER >= 1800) */
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @enum
|
* @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,
|
SF_TYPE_DATE
|
||||||
/**
|
} sf_type;
|
||||||
* :enum:`SFPARSE_TYPE_DISPSTRING` indicates display string type.
|
|
||||||
*/
|
|
||||||
SFPARSE_TYPE_DISPSTRING
|
|
||||||
} sfparse_type;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @macro
|
* @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.
|
* occurred, and it is not possible to continue the processing.
|
||||||
*/
|
*/
|
||||||
#define SFPARSE_ERR_PARSE -1
|
#define SF_ERR_PARSE_ERROR -1
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @macro
|
* @macro
|
||||||
*
|
*
|
||||||
* :macro:`SFPARSE_ERR_EOF` indicates that there is nothing left to
|
* :macro:`SF_ERR_EOF` indicates that there is nothing left to read.
|
||||||
* read. The context of this error varies depending on the function
|
* The context of this error varies depending on the function that
|
||||||
* that returns this error code.
|
* returns this error code.
|
||||||
*/
|
*/
|
||||||
#define SFPARSE_ERR_EOF -2
|
#define SF_ERR_EOF -2
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @struct
|
* @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.
|
* :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.
|
* :member:`len` is the number of bytes contained in this sequence.
|
||||||
*/
|
*/
|
||||||
size_t len;
|
size_t len;
|
||||||
} sfparse_vec;
|
} sf_vec;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @macro
|
* @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
|
||||||
*
|
*
|
||||||
* :macro:`SFPARSE_VALUE_FLAG_ESCAPED_STRING` indicates that a string
|
* :macro:`SF_VALUE_FLAG_ESCAPED_STRING` indicates that a string
|
||||||
* contains escaped character(s).
|
* contains escaped character(s).
|
||||||
*/
|
*/
|
||||||
#define SFPARSE_VALUE_FLAG_ESCAPED_STRING 0x1u
|
#define SF_VALUE_FLAG_ESCAPED_STRING 0x1u
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @struct
|
* @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.
|
* :member:`numer` contains numerator of the decimal value.
|
||||||
*/
|
*/
|
||||||
@@ -154,289 +150,260 @@ typedef struct sfparse_decimal {
|
|||||||
* :member:`denom` contains denominator of the decimal value.
|
* :member:`denom` contains denominator of the decimal value.
|
||||||
*/
|
*/
|
||||||
int64_t denom;
|
int64_t denom;
|
||||||
} sfparse_decimal;
|
} sf_decimal;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @struct
|
* @struct
|
||||||
*
|
*
|
||||||
* :type:`sfparse_value` stores a Structured Field item. For Inner
|
* :type:`sf_value` stores a Structured Field item. For Inner List,
|
||||||
* List, only type is set to
|
* only type is set to :enum:`sf_type.SF_TYPE_INNER_LIST`. In order
|
||||||
* :enum:`sfparse_type.SFPARSE_TYPE_INNER_LIST`. In order to read the
|
* to read the items contained in an inner list, call
|
||||||
* items contained in an inner list, call `sfparse_parser_inner_list`.
|
* `sf_parser_inner_list`.
|
||||||
*/
|
*/
|
||||||
typedef struct sfparse_value {
|
typedef struct sf_value {
|
||||||
/**
|
/**
|
||||||
* :member:`type` is the type of the value contained in this
|
* :member:`type` is the type of the value contained in this
|
||||||
* particular object.
|
* particular object.
|
||||||
*/
|
*/
|
||||||
sfparse_type type;
|
sf_type type;
|
||||||
/**
|
/**
|
||||||
* :member:`flags` is bitwise OR of one or more of
|
* :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;
|
uint32_t flags;
|
||||||
/**
|
/**
|
||||||
* @anonunion_start
|
* @anonunion_start
|
||||||
*
|
*
|
||||||
* @sfparse_value_value
|
* @sf_value_value
|
||||||
*/
|
*/
|
||||||
union {
|
union {
|
||||||
/**
|
/**
|
||||||
* :member:`boolean` contains boolean value if :member:`type` ==
|
* :member:`boolean` contains boolean value if :member:`type` ==
|
||||||
* :enum:`sfparse_type.SFPARSE_TYPE_BOOLEAN`. 1 indicates true,
|
* :enum:`sf_type.SF_TYPE_BOOLEAN`. 1 indicates true, and 0
|
||||||
* and 0 indicates false.
|
* indicates false.
|
||||||
*/
|
*/
|
||||||
int boolean;
|
int boolean;
|
||||||
/**
|
/**
|
||||||
* :member:`integer` contains integer value if :member:`type` is
|
* :member:`integer` contains integer value if :member:`type` is
|
||||||
* either :enum:`sfparse_type.SFPARSE_TYPE_INTEGER` or
|
* either :enum:`sf_type.SF_TYPE_INTEGER` or
|
||||||
* :enum:`sfparse_type.SFPARSE_TYPE_DATE`.
|
* :enum:`sf_type.SF_TYPE_DATE`.
|
||||||
*/
|
*/
|
||||||
int64_t integer;
|
int64_t integer;
|
||||||
/**
|
/**
|
||||||
* :member:`decimal` contains decimal value if :member:`type` ==
|
* :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
|
* :member:`vec` contains sequence of bytes if :member:`type` is
|
||||||
* either :enum:`sfparse_type.SFPARSE_TYPE_STRING`,
|
* either :enum:`sf_type.SF_TYPE_STRING`,
|
||||||
* :enum:`sfparse_type.SFPARSE_TYPE_TOKEN`,
|
* :enum:`sf_type.SF_TYPE_TOKEN`, or
|
||||||
* :enum:`sfparse_type.SFPARSE_TYPE_BYTESEQ`, or
|
* :enum:`sf_type.SF_TYPE_BYTESEQ`.
|
||||||
* :enum:`sfparse_type.SFPARSE_TYPE_DISPSTRING`.
|
|
||||||
*
|
*
|
||||||
* For :enum:`sfparse_type.SFPARSE_TYPE_STRING`, this field
|
* For :enum:`sf_type.SF_TYPE_STRING`, this field contains one or
|
||||||
* contains one or more escaped characters if :member:`flags` has
|
* more escaped characters if :member:`flags` has
|
||||||
* :macro:`SFPARSE_VALUE_FLAG_ESCAPED_STRING` set. To unescape
|
* :macro:`SF_VALUE_FLAG_ESCAPED_STRING` set. To unescape the
|
||||||
* the string, use `sfparse_unescape`.
|
* string, use `sf_unescape`.
|
||||||
*
|
*
|
||||||
* For :enum:`sfparse_type.SFPARSE_TYPE_BYTESEQ`, this field
|
* For :enum:`sf_type.SF_TYPE_BYTESEQ`, this field contains base64
|
||||||
* contains base64 encoded string. To decode this byte string,
|
* encoded string. To decode this byte string, use
|
||||||
* use `sfparse_base64decode`.
|
* `sf_base64decode`.
|
||||||
*
|
*
|
||||||
* For :enum:`sfparse_type.SFPARSE_TYPE_DISPSTRING`, this field
|
* If :member:`vec.len <sf_vec.len>` == 0, :member:`vec.base
|
||||||
* may contain percent-encoded UTF-8 byte sequences. To decode
|
* <sf_vec.base>` is guaranteed to be NULL.
|
||||||
* it, use `sfparse_pctdecode`.
|
|
||||||
*
|
|
||||||
* If :member:`vec.len <sfparse_vec.len>` == 0, :member:`vec.base
|
|
||||||
* <sfparse_vec.base>` is guaranteed to be NULL.
|
|
||||||
*/
|
*/
|
||||||
sfparse_vec vec;
|
sf_vec vec;
|
||||||
/**
|
/**
|
||||||
* @anonunion_end
|
* @anonunion_end
|
||||||
*/
|
*/
|
||||||
};
|
};
|
||||||
} sfparse_value;
|
} sf_value;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @struct
|
* @struct
|
||||||
*
|
*
|
||||||
* :type:`sfparse_parser` is the Structured Field Values parser. Use
|
* :type:`sf_parser` is the Structured Field Values parser. Use
|
||||||
* `sfparse_parser_init` to initialize it.
|
* `sf_parser_init` to initialize it.
|
||||||
*/
|
*/
|
||||||
typedef struct sfparse_parser {
|
typedef struct sf_parser {
|
||||||
/* all fields are private */
|
/* all fields are private */
|
||||||
const uint8_t *pos;
|
const uint8_t *pos;
|
||||||
const uint8_t *end;
|
const uint8_t *end;
|
||||||
uint32_t state;
|
uint32_t state;
|
||||||
} sfparse_parser;
|
} sf_parser;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @function
|
* @function
|
||||||
*
|
*
|
||||||
* `sfparse_parser_init` initializes |sfp| with the given data encoded
|
* `sf_parser_init` initializes |sfp| with the given buffer pointed by
|
||||||
* in Structured Field Values pointed by |data| of length |datalen|.
|
* |data| of length |datalen|.
|
||||||
*/
|
*/
|
||||||
void sfparse_parser_init(sfparse_parser *sfp, const uint8_t *data,
|
void sf_parser_init(sf_parser *sfp, const uint8_t *data, size_t datalen);
|
||||||
size_t datalen);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @function
|
* @function
|
||||||
*
|
*
|
||||||
* `sfparse_parser_param` reads a parameter. If this function returns
|
* `sf_parser_param` reads a parameter. If this function returns 0,
|
||||||
* 0, it stores parameter key and value in |dest_key| and |dest_value|
|
* it stores parameter key and value in |dest_key| and |dest_value|
|
||||||
* respectively, if they are not NULL.
|
* respectively, if they are not NULL.
|
||||||
*
|
*
|
||||||
* This function does no effort to find duplicated keys. Same key may
|
* This function does no effort to find duplicated keys. Same key may
|
||||||
* be reported more than once.
|
* be reported more than once.
|
||||||
*
|
*
|
||||||
* Caller should keep calling this function until it returns negative
|
* Caller should keep calling this function until it returns negative
|
||||||
* error code. If it returns :macro:`SFPARSE_ERR_EOF`, all parameters
|
* error code. If it returns :macro:`SF_ERR_EOF`, all parameters have
|
||||||
* have read, and caller can continue to read rest of the values. If
|
* read, and caller can continue to read rest of the values. If it
|
||||||
* it returns :macro:`SFPARSE_ERR_PARSE`, it encountered fatal error
|
* returns :macro:`SF_ERR_PARSE_ERROR`, it encountered fatal error
|
||||||
* while parsing field value.
|
* while parsing field value.
|
||||||
*/
|
*/
|
||||||
int sfparse_parser_param(sfparse_parser *sfp, sfparse_vec *dest_key,
|
int sf_parser_param(sf_parser *sfp, sf_vec *dest_key, sf_value *dest_value);
|
||||||
sfparse_value *dest_value);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @function
|
* @function
|
||||||
*
|
*
|
||||||
* `sfparse_parser_dict` reads the next dictionary key and value pair.
|
* `sf_parser_dict` reads the next dictionary key and value pair. If
|
||||||
* If this function returns 0, it stores the key and value in
|
* this function returns 0, it stores the key and value in |dest_key|
|
||||||
* |dest_key| and |dest_value| respectively, if they are not NULL.
|
* and |dest_value| respectively, if they are not NULL.
|
||||||
*
|
*
|
||||||
* Caller can optionally read parameters attached to the pair by
|
* 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
|
* This function does no effort to find duplicated keys. Same key may
|
||||||
* be reported more than once.
|
* be reported more than once.
|
||||||
*
|
*
|
||||||
* Caller should keep calling this function until it returns negative
|
* Caller should keep calling this function until it returns negative
|
||||||
* error code. If it returns :macro:`SFPARSE_ERR_EOF`, all key and
|
* error code. If it returns :macro:`SF_ERR_EOF`, all key and value
|
||||||
* value pairs have been read, and there is nothing left to read.
|
* pairs have been read, and there is nothing left to read.
|
||||||
*
|
*
|
||||||
* This function returns 0 if it succeeds, or one of the following
|
* This function returns 0 if it succeeds, or one of the following
|
||||||
* negative error codes:
|
* negative error codes:
|
||||||
*
|
*
|
||||||
* :macro:`SFPARSE_ERR_EOF`
|
* :macro:`SF_ERR_EOF`
|
||||||
* All values in the dictionary have read.
|
* All values in the dictionary have read.
|
||||||
* :macro:`SFPARSE_ERR_PARSE`
|
* :macro:`SF_ERR_PARSE_ERROR`
|
||||||
* It encountered fatal error while parsing field value.
|
* It encountered fatal error while parsing field value.
|
||||||
*/
|
*/
|
||||||
int sfparse_parser_dict(sfparse_parser *sfp, sfparse_vec *dest_key,
|
int sf_parser_dict(sf_parser *sfp, sf_vec *dest_key, sf_value *dest_value);
|
||||||
sfparse_value *dest_value);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @function
|
* @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.
|
* returns 0, it stores the item in |dest| if it is not NULL.
|
||||||
*
|
*
|
||||||
* Caller can optionally read parameters attached to the item by
|
* 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
|
* Caller should keep calling this function until it returns negative
|
||||||
* error code. If it returns :macro:`SFPARSE_ERR_EOF`, all values in
|
* error code. If it returns :macro:`SF_ERR_EOF`, all values in the
|
||||||
* the list have been read, and there is nothing left to read.
|
* list have been read, and there is nothing left to read.
|
||||||
*
|
*
|
||||||
* This function returns 0 if it succeeds, or one of the following
|
* This function returns 0 if it succeeds, or one of the following
|
||||||
* negative error codes:
|
* negative error codes:
|
||||||
*
|
*
|
||||||
* :macro:`SFPARSE_ERR_EOF`
|
* :macro:`SF_ERR_EOF`
|
||||||
* All values in the list have read.
|
* All values in the list have read.
|
||||||
* :macro:`SFPARSE_ERR_PARSE`
|
* :macro:`SF_ERR_PARSE_ERROR`
|
||||||
* It encountered fatal error while parsing field value.
|
* 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
|
* @function
|
||||||
*
|
*
|
||||||
* `sfparse_parser_item` reads a single item. If this function
|
* `sf_parser_item` reads a single item. If this function returns 0,
|
||||||
* returns 0, it stores the item in |dest| if it is not NULL.
|
* it stores the item in |dest| if it is not NULL.
|
||||||
*
|
*
|
||||||
* This function is only used for the field value that consists of a
|
* This function is only used for the field value that consists of a
|
||||||
* single item.
|
* single item.
|
||||||
*
|
*
|
||||||
* Caller can optionally read parameters attached to the item by
|
* 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
|
* Caller should call this function again to make sure that there is
|
||||||
* nothing left to read. If this 2nd function call returns
|
* nothing left to read. If this 2nd function call returns
|
||||||
* :macro:`SFPARSE_ERR_EOF`, all data have been processed
|
* :macro:`SF_ERR_EOF`, all data have been processed successfully.
|
||||||
* successfully.
|
|
||||||
*
|
*
|
||||||
* This function returns 0 if it succeeds, or one of the following
|
* This function returns 0 if it succeeds, or one of the following
|
||||||
* negative error codes:
|
* negative error codes:
|
||||||
*
|
*
|
||||||
* :macro:`SFPARSE_ERR_EOF`
|
* :macro:`SF_ERR_EOF`
|
||||||
* There is nothing left to read.
|
* There is nothing left to read.
|
||||||
* :macro:`SFPARSE_ERR_PARSE`
|
* :macro:`SF_ERR_PARSE_ERROR`
|
||||||
* It encountered fatal error while parsing field value.
|
* 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
|
* @function
|
||||||
*
|
*
|
||||||
* `sfparse_parser_inner_list` reads the next inner list item. If
|
* `sf_parser_inner_list` reads the next inner list item. If this
|
||||||
* this function returns 0, it stores the item in |dest| if it is not
|
* function returns 0, it stores the item in |dest| if it is not NULL.
|
||||||
* NULL.
|
|
||||||
*
|
*
|
||||||
* Caller can optionally read parameters attached to the item by
|
* 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
|
* Caller should keep calling this function until it returns negative
|
||||||
* error code. If it returns :macro:`SFPARSE_ERR_EOF`, all values in
|
* error code. If it returns :macro:`SF_ERR_EOF`, all values in this
|
||||||
* this inner list have been read, and caller can optionally read
|
* inner list have been read, and caller can optionally read
|
||||||
* parameters attached to this inner list by calling
|
* parameters attached to this inner list by calling
|
||||||
* `sfparse_parser_param`. Then caller can continue to read rest of
|
* `sf_parser_param`. Then caller can continue to read rest of the
|
||||||
* the values.
|
* values.
|
||||||
*
|
*
|
||||||
* This function returns 0 if it succeeds, or one of the following
|
* This function returns 0 if it succeeds, or one of the following
|
||||||
* negative error codes:
|
* negative error codes:
|
||||||
*
|
*
|
||||||
* :macro:`SFPARSE_ERR_EOF`
|
* :macro:`SF_ERR_EOF`
|
||||||
* All values in the inner list have read.
|
* 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.
|
* 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
|
* @function
|
||||||
*
|
*
|
||||||
* `sfparse_unescape` copies |src| to |dest| by removing escapes
|
* `sf_unescape` copies |src| to |dest| by removing escapes (``\``).
|
||||||
* (``\``). |src| should be the pointer to
|
* |src| should be the pointer to :member:`sf_value.vec` of type
|
||||||
* :member:`sfparse_value.vec` of type
|
* :enum:`sf_type.SF_TYPE_STRING` produced by either `sf_parser_dict`,
|
||||||
* :enum:`sfparse_type.SFPARSE_TYPE_STRING` produced by either
|
* `sf_parser_list`, `sf_parser_inner_list`, `sf_parser_item`, or
|
||||||
* `sfparse_parser_dict`, `sfparse_parser_list`,
|
* `sf_parser_param`, otherwise the behavior is undefined.
|
||||||
* `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
|
* :member:`dest->base <sf_vec.base>` must point to the buffer that
|
||||||
* that has sufficient space to store the unescaped string. The
|
* has sufficient space to store the unescaped string.
|
||||||
* memory areas pointed by :member:`dest->base <sfparse_vec.base>` and
|
*
|
||||||
* :member:`src->base <sfparse_vec.base>` must not overlap.
|
* 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
|
* 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
|
* @function
|
||||||
*
|
*
|
||||||
* `sfparse_base64decode` decodes Base64 encoded string |src| and
|
* `sf_base64decode` decodes Base64 encoded string |src| and writes
|
||||||
* 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
|
|
||||||
* the result into |dest|. |src| should be the pointer to
|
* the result into |dest|. |src| should be the pointer to
|
||||||
* :member:`sfparse_value.vec` of type
|
* :member:`sf_value.vec` of type :enum:`sf_type.SF_TYPE_BYTESEQ`
|
||||||
* :enum:`sfparse_type.SFPARSE_TYPE_DISPSTRING` produced by either
|
* produced by either `sf_parser_dict`, `sf_parser_list`,
|
||||||
* `sfparse_parser_dict`, `sfparse_parser_list`,
|
* `sf_parser_inner_list`, `sf_parser_item`, or `sf_parser_param`,
|
||||||
* `sfparse_parser_inner_list`, `sfparse_parser_item`, or
|
* otherwise the behavior is undefined.
|
||||||
* `sfparse_parser_param`, otherwise the behavior is undefined.
|
|
||||||
*
|
*
|
||||||
* :member:`dest->base <sfparse_vec.base>` must point to the buffer
|
* :member:`dest->base <sf_vec.base>` must point to the buffer that
|
||||||
* that has sufficient space to store the decoded byte string. The
|
* has sufficient space to store the decoded byte string.
|
||||||
* memory areas pointed by :member:`dest->base <sfparse_vec.base>` and
|
*
|
||||||
* :member:`src->base <sfparse_vec.base>` must not overlap.
|
* If :member:`src->len <sf_vec.len>` == 0, |*src| is assigned to
|
||||||
|
* |*dest|.
|
||||||
*
|
*
|
||||||
* This function sets the length of decoded byte string to
|
* 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
|
#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(
|
include_directories(
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/includes"
|
"${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"
|
"${CMAKE_CURRENT_SOURCE_DIR}/../third-party/llhttp/include"
|
||||||
|
|
||||||
${JEMALLOC_INCLUDE_DIRS}
|
${JEMALLOC_INCLUDE_DIRS}
|
||||||
@@ -16,11 +16,7 @@ include_directories(
|
|||||||
${LIBNGHTTP3_INCLUDE_DIRS}
|
${LIBNGHTTP3_INCLUDE_DIRS}
|
||||||
${LIBNGTCP2_INCLUDE_DIRS}
|
${LIBNGTCP2_INCLUDE_DIRS}
|
||||||
${LIBNGTCP2_CRYPTO_QUICTLS_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}
|
${OPENSSL_INCLUDE_DIRS}
|
||||||
${WOLFSSL_INCLUDE_DIRS}
|
|
||||||
${LIBCARES_INCLUDE_DIRS}
|
${LIBCARES_INCLUDE_DIRS}
|
||||||
${JANSSON_INCLUDE_DIRS}
|
${JANSSON_INCLUDE_DIRS}
|
||||||
${ZLIB_INCLUDE_DIRS}
|
${ZLIB_INCLUDE_DIRS}
|
||||||
@@ -38,11 +34,7 @@ link_libraries(
|
|||||||
${LIBNGHTTP3_LIBRARIES}
|
${LIBNGHTTP3_LIBRARIES}
|
||||||
${LIBNGTCP2_LIBRARIES}
|
${LIBNGTCP2_LIBRARIES}
|
||||||
${LIBNGTCP2_CRYPTO_QUICTLS_LIBRARIES}
|
${LIBNGTCP2_CRYPTO_QUICTLS_LIBRARIES}
|
||||||
${LIBNGTCP2_CRYPTO_LIBRESSL_LIBRARIES}
|
|
||||||
${LIBNGTCP2_CRYPTO_WOLFSSL_LIBRARIES}
|
|
||||||
${LIBNGTCP2_CRYPTO_OSSL_LIBRARIES}
|
|
||||||
${OPENSSL_LIBRARIES}
|
${OPENSSL_LIBRARIES}
|
||||||
${WOLFSSL_LIBRARIES}
|
|
||||||
${LIBCARES_LIBRARIES}
|
${LIBCARES_LIBRARIES}
|
||||||
${JANSSON_LIBRARIES}
|
${JANSSON_LIBRARIES}
|
||||||
${ZLIB_LIBRARIES}
|
${ZLIB_LIBRARIES}
|
||||||
@@ -89,6 +81,7 @@ if(ENABLE_APP)
|
|||||||
list(APPEND H2LOAD_SOURCES
|
list(APPEND H2LOAD_SOURCES
|
||||||
h2load_http3_session.cc
|
h2load_http3_session.cc
|
||||||
h2load_quic.cc
|
h2load_quic.cc
|
||||||
|
quic.cc
|
||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
@@ -128,6 +121,7 @@ if(ENABLE_APP)
|
|||||||
shrpx_api_downstream_connection.cc
|
shrpx_api_downstream_connection.cc
|
||||||
shrpx_health_monitor_downstream_connection.cc
|
shrpx_health_monitor_downstream_connection.cc
|
||||||
shrpx_null_downstream_connection.cc
|
shrpx_null_downstream_connection.cc
|
||||||
|
shrpx_exec.cc
|
||||||
shrpx_dns_resolver.cc
|
shrpx_dns_resolver.cc
|
||||||
shrpx_dual_dns_resolver.cc
|
shrpx_dual_dns_resolver.cc
|
||||||
shrpx_dns_tracker.cc
|
shrpx_dns_tracker.cc
|
||||||
@@ -149,7 +143,7 @@ if(ENABLE_APP)
|
|||||||
shrpx_quic_connection_handler.cc
|
shrpx_quic_connection_handler.cc
|
||||||
shrpx_http3_upstream.cc
|
shrpx_http3_upstream.cc
|
||||||
http3.cc
|
http3.cc
|
||||||
siphash.cc
|
quic.cc
|
||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
add_library(nghttpx_static STATIC ${NGHTTPX_SRCS})
|
add_library(nghttpx_static STATIC ${NGHTTPX_SRCS})
|
||||||
@@ -173,59 +167,54 @@ if(ENABLE_APP)
|
|||||||
target_link_libraries(nghttpx_static neverbleed)
|
target_link_libraries(nghttpx_static neverbleed)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME AND BUILD_TESTING)
|
set(NGHTTPX_UNITTEST_SOURCES
|
||||||
set(NGHTTPX_UNITTEST_SOURCES
|
shrpx-unittest.cc
|
||||||
shrpx-unittest.cc
|
shrpx_tls_test.cc
|
||||||
shrpx_tls_test.cc
|
shrpx_downstream_test.cc
|
||||||
shrpx_downstream_test.cc
|
shrpx_config_test.cc
|
||||||
shrpx_config_test.cc
|
shrpx_worker_test.cc
|
||||||
shrpx_worker_test.cc
|
shrpx_http_test.cc
|
||||||
shrpx_http_test.cc
|
shrpx_router_test.cc
|
||||||
shrpx_router_test.cc
|
http2_test.cc
|
||||||
http2_test.cc
|
util_test.cc
|
||||||
util_test.cc
|
nghttp2_gzip_test.c
|
||||||
nghttp2_gzip_test.c
|
nghttp2_gzip.c
|
||||||
nghttp2_gzip.c
|
buffer_test.cc
|
||||||
buffer_test.cc
|
memchunk_test.cc
|
||||||
memchunk_test.cc
|
template_test.cc
|
||||||
template_test.cc
|
base64_test.cc
|
||||||
base64_test.cc
|
${CMAKE_SOURCE_DIR}/tests/munit/munit.c
|
||||||
${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)
|
target_include_directories(nghttpx-unittest PRIVATE
|
||||||
list(APPEND NGHTTPX_UNITTEST_SOURCES siphash_test.cc)
|
${CMAKE_SOURCE_DIR}/tests/munit
|
||||||
endif()
|
)
|
||||||
add_executable(nghttpx-unittest EXCLUDE_FROM_ALL
|
target_compile_definitions(nghttpx-unittest
|
||||||
${NGHTTPX_UNITTEST_SOURCES}
|
PRIVATE "-DNGHTTP2_SRC_DIR=\"${CMAKE_SOURCE_DIR}/src\""
|
||||||
$<TARGET_OBJECTS:llhttp>
|
)
|
||||||
$<TARGET_OBJECTS:urlparse>
|
target_link_libraries(nghttpx-unittest nghttpx_static)
|
||||||
)
|
if(HAVE_MRUBY)
|
||||||
target_include_directories(nghttpx-unittest PRIVATE
|
target_link_libraries(nghttpx-unittest mruby-lib)
|
||||||
${CMAKE_SOURCE_DIR}/tests/munit
|
endif()
|
||||||
)
|
if(HAVE_NEVERBLEED)
|
||||||
target_compile_definitions(nghttpx-unittest
|
target_link_libraries(nghttpx-unittest neverbleed)
|
||||||
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)
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
add_test(nghttpx-unittest nghttpx-unittest)
|
||||||
|
add_dependencies(check nghttpx-unittest)
|
||||||
|
|
||||||
add_executable(nghttp ${NGHTTP_SOURCES} $<TARGET_OBJECTS:llhttp>
|
add_executable(nghttp ${NGHTTP_SOURCES} $<TARGET_OBJECTS:llhttp>
|
||||||
$<TARGET_OBJECTS:urlparse>
|
$<TARGET_OBJECTS:url-parser>
|
||||||
)
|
)
|
||||||
add_executable(nghttpd ${NGHTTPD_SOURCES} $<TARGET_OBJECTS:llhttp>
|
add_executable(nghttpd ${NGHTTPD_SOURCES} $<TARGET_OBJECTS:llhttp>
|
||||||
$<TARGET_OBJECTS:urlparse>
|
$<TARGET_OBJECTS:url-parser>
|
||||||
)
|
)
|
||||||
add_executable(nghttpx ${NGHTTPX-bin_SOURCES} $<TARGET_OBJECTS:llhttp>
|
add_executable(nghttpx ${NGHTTPX-bin_SOURCES} $<TARGET_OBJECTS:llhttp>
|
||||||
$<TARGET_OBJECTS:urlparse>
|
$<TARGET_OBJECTS:url-parser>
|
||||||
)
|
)
|
||||||
target_compile_definitions(nghttpx PRIVATE
|
target_compile_definitions(nghttpx PRIVATE
|
||||||
"-DPKGDATADIR=\"${PKGDATADIR}\""
|
"-DPKGDATADIR=\"${PKGDATADIR}\""
|
||||||
@@ -233,7 +222,7 @@ if(ENABLE_APP)
|
|||||||
)
|
)
|
||||||
target_link_libraries(nghttpx nghttpx_static)
|
target_link_libraries(nghttpx nghttpx_static)
|
||||||
add_executable(h2load ${H2LOAD_SOURCES} $<TARGET_OBJECTS:llhttp>
|
add_executable(h2load ${H2LOAD_SOURCES} $<TARGET_OBJECTS:llhttp>
|
||||||
$<TARGET_OBJECTS:urlparse>
|
$<TARGET_OBJECTS:url-parser>
|
||||||
)
|
)
|
||||||
|
|
||||||
install(TARGETS nghttp nghttpd nghttpx h2load)
|
install(TARGETS nghttp nghttpd nghttpx h2load)
|
||||||
|
|||||||
@@ -31,36 +31,38 @@
|
|||||||
namespace nghttp2 {
|
namespace nghttp2 {
|
||||||
|
|
||||||
ParserData::ParserData(const std::string &base_uri)
|
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)
|
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_); }
|
HtmlParser::~HtmlParser() { htmlFreeParserCtxt(parser_ctx_); }
|
||||||
|
|
||||||
namespace {
|
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) {
|
if (attrs == nullptr) {
|
||||||
return ""sv;
|
return StringRef{};
|
||||||
}
|
}
|
||||||
for (; *attrs; attrs += 2) {
|
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)) {
|
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
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
ResourceType
|
ResourceType
|
||||||
get_resource_type_for_preload_as(const std::string_view &attribute_value) {
|
get_resource_type_for_preload_as(const StringRef &attribute_value) {
|
||||||
if (util::strieq("image"sv, attribute_value)) {
|
if (util::strieq("image"_sr, attribute_value)) {
|
||||||
return REQ_IMG;
|
return REQ_IMG;
|
||||||
} else if (util::strieq("style"sv, attribute_value)) {
|
} else if (util::strieq("style"_sr, attribute_value)) {
|
||||||
return REQ_CSS;
|
return REQ_CSS;
|
||||||
} else if (util::strieq("script"sv, attribute_value)) {
|
} else if (util::strieq("script"_sr, attribute_value)) {
|
||||||
return REQ_UNBLOCK_JS;
|
return REQ_UNBLOCK_JS;
|
||||||
} else {
|
} else {
|
||||||
return REQ_OTHERS;
|
return REQ_OTHERS;
|
||||||
@@ -69,15 +71,15 @@ get_resource_type_for_preload_as(const std::string_view &attribute_value) {
|
|||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
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) {
|
ResourceType res_type) {
|
||||||
auto u = xmlBuildURI(
|
auto u = xmlBuildURI(
|
||||||
reinterpret_cast<const xmlChar *>(uri.data()),
|
reinterpret_cast<const xmlChar *>(uri.data()),
|
||||||
reinterpret_cast<const xmlChar *>(parser_data->base_uri.c_str()));
|
reinterpret_cast<const xmlChar *>(parser_data->base_uri.c_str()));
|
||||||
if (u) {
|
if (u) {
|
||||||
parser_data->links.push_back(
|
parser_data->links.push_back(
|
||||||
std::make_pair(reinterpret_cast<char *>(u), res_type));
|
std::make_pair(reinterpret_cast<char *>(u), res_type));
|
||||||
xmlFree(u);
|
free(u);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
@@ -86,36 +88,37 @@ namespace {
|
|||||||
void start_element_func(void *user_data, const xmlChar *src_name,
|
void start_element_func(void *user_data, const xmlChar *src_name,
|
||||||
const xmlChar **attrs) {
|
const xmlChar **attrs) {
|
||||||
auto parser_data = static_cast<ParserData *>(user_data);
|
auto parser_data = static_cast<ParserData *>(user_data);
|
||||||
auto name = std::string_view{reinterpret_cast<const char *>(src_name)};
|
auto name =
|
||||||
if (util::strieq("head"sv, name)) {
|
StringRef{src_name, strlen(reinterpret_cast<const char *>(src_name))};
|
||||||
|
if (util::strieq("head"_sr, name)) {
|
||||||
++parser_data->inside_head;
|
++parser_data->inside_head;
|
||||||
}
|
}
|
||||||
if (util::strieq("link"sv, name)) {
|
if (util::strieq("link"_sr, name)) {
|
||||||
auto rel_attr = get_attr(attrs, "rel"sv);
|
auto rel_attr = get_attr(attrs, "rel"_sr);
|
||||||
auto href_attr = get_attr(attrs, "href"sv);
|
auto href_attr = get_attr(attrs, "href"_sr);
|
||||||
if (rel_attr.empty() || href_attr.empty()) {
|
if (rel_attr.empty() || href_attr.empty()) {
|
||||||
return;
|
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);
|
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);
|
add_link(parser_data, href_attr, REQ_CSS);
|
||||||
} else if (util::strieq("preload"sv, rel_attr)) {
|
} else if (util::strieq("preload"_sr, rel_attr)) {
|
||||||
auto as_attr = get_attr(attrs, "as"sv);
|
auto as_attr = get_attr(attrs, "as"_sr);
|
||||||
if (as_attr.empty()) {
|
if (as_attr.empty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
add_link(parser_data, href_attr,
|
add_link(parser_data, href_attr,
|
||||||
get_resource_type_for_preload_as(as_attr));
|
get_resource_type_for_preload_as(as_attr));
|
||||||
}
|
}
|
||||||
} else if (util::strieq("img"sv, name)) {
|
} else if (util::strieq("img"_sr, name)) {
|
||||||
auto src_attr = get_attr(attrs, "src"sv);
|
auto src_attr = get_attr(attrs, "src"_sr);
|
||||||
if (src_attr.empty()) {
|
if (src_attr.empty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
add_link(parser_data, src_attr, REQ_IMG);
|
add_link(parser_data, src_attr, REQ_IMG);
|
||||||
} else if (util::strieq("script"sv, name)) {
|
} else if (util::strieq("script"_sr, name)) {
|
||||||
auto src_attr = get_attr(attrs, "src"sv);
|
auto src_attr = get_attr(attrs, "src"_sr);
|
||||||
if (src_attr.empty()) {
|
if (src_attr.empty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -131,8 +134,9 @@ void start_element_func(void *user_data, const xmlChar *src_name,
|
|||||||
namespace {
|
namespace {
|
||||||
void end_element_func(void *user_data, const xmlChar *name) {
|
void end_element_func(void *user_data, const xmlChar *name) {
|
||||||
auto parser_data = static_cast<ParserData *>(user_data);
|
auto parser_data = static_cast<ParserData *>(user_data);
|
||||||
if (util::strieq("head"sv,
|
if (util::strieq(
|
||||||
std::string_view{reinterpret_cast<const char *>(name)})) {
|
"head"_sr,
|
||||||
|
StringRef{name, strlen(reinterpret_cast<const char *>(name))})) {
|
||||||
--parser_data->inside_head;
|
--parser_data->inside_head;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -140,46 +144,46 @@ void end_element_func(void *user_data, const xmlChar *name) {
|
|||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
xmlSAXHandler saxHandler = {
|
xmlSAXHandler saxHandler = {
|
||||||
nullptr, // internalSubsetSAXFunc
|
nullptr, // internalSubsetSAXFunc
|
||||||
nullptr, // isStandaloneSAXFunc
|
nullptr, // isStandaloneSAXFunc
|
||||||
nullptr, // hasInternalSubsetSAXFunc
|
nullptr, // hasInternalSubsetSAXFunc
|
||||||
nullptr, // hasExternalSubsetSAXFunc
|
nullptr, // hasExternalSubsetSAXFunc
|
||||||
nullptr, // resolveEntitySAXFunc
|
nullptr, // resolveEntitySAXFunc
|
||||||
nullptr, // getEntitySAXFunc
|
nullptr, // getEntitySAXFunc
|
||||||
nullptr, // entityDeclSAXFunc
|
nullptr, // entityDeclSAXFunc
|
||||||
nullptr, // notationDeclSAXFunc
|
nullptr, // notationDeclSAXFunc
|
||||||
nullptr, // attributeDeclSAXFunc
|
nullptr, // attributeDeclSAXFunc
|
||||||
nullptr, // elementDeclSAXFunc
|
nullptr, // elementDeclSAXFunc
|
||||||
nullptr, // unparsedEntityDeclSAXFunc
|
nullptr, // unparsedEntityDeclSAXFunc
|
||||||
nullptr, // setDocumentLocatorSAXFunc
|
nullptr, // setDocumentLocatorSAXFunc
|
||||||
nullptr, // startDocumentSAXFunc
|
nullptr, // startDocumentSAXFunc
|
||||||
nullptr, // endDocumentSAXFunc
|
nullptr, // endDocumentSAXFunc
|
||||||
&start_element_func, // startElementSAXFunc
|
&start_element_func, // startElementSAXFunc
|
||||||
&end_element_func, // endElementSAXFunc
|
&end_element_func, // endElementSAXFunc
|
||||||
nullptr, // referenceSAXFunc
|
nullptr, // referenceSAXFunc
|
||||||
nullptr, // charactersSAXFunc
|
nullptr, // charactersSAXFunc
|
||||||
nullptr, // ignorableWhitespaceSAXFunc
|
nullptr, // ignorableWhitespaceSAXFunc
|
||||||
nullptr, // processingInstructionSAXFunc
|
nullptr, // processingInstructionSAXFunc
|
||||||
nullptr, // commentSAXFunc
|
nullptr, // commentSAXFunc
|
||||||
nullptr, // warningSAXFunc
|
nullptr, // warningSAXFunc
|
||||||
nullptr, // errorSAXFunc
|
nullptr, // errorSAXFunc
|
||||||
nullptr, // fatalErrorSAXFunc
|
nullptr, // fatalErrorSAXFunc
|
||||||
nullptr, // getParameterEntitySAXFunc
|
nullptr, // getParameterEntitySAXFunc
|
||||||
nullptr, // cdataBlockSAXFunc
|
nullptr, // cdataBlockSAXFunc
|
||||||
nullptr, // externalSubsetSAXFunc
|
nullptr, // externalSubsetSAXFunc
|
||||||
0, // unsigned int initialized
|
0, // unsigned int initialized
|
||||||
nullptr, // void * _private
|
nullptr, // void * _private
|
||||||
nullptr, // startElementNsSAX2Func
|
nullptr, // startElementNsSAX2Func
|
||||||
nullptr, // endElementNsSAX2Func
|
nullptr, // endElementNsSAX2Func
|
||||||
nullptr, // xmlStructuredErrorFunc
|
nullptr, // xmlStructuredErrorFunc
|
||||||
};
|
};
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
int HtmlParser::parse_chunk(const char *chunk, size_t size, int fin) {
|
int HtmlParser::parse_chunk(const char *chunk, size_t size, int fin) {
|
||||||
if (!parser_ctx_) {
|
if (!parser_ctx_) {
|
||||||
parser_ctx_ = htmlCreatePushParserCtxt(
|
parser_ctx_ =
|
||||||
&saxHandler, &parser_data_, chunk, static_cast<int>(size),
|
htmlCreatePushParserCtxt(&saxHandler, &parser_data_, chunk, size,
|
||||||
base_uri_.c_str(), XML_CHAR_ENCODING_NONE);
|
base_uri_.c_str(), XML_CHAR_ENCODING_NONE);
|
||||||
if (!parser_ctx_) {
|
if (!parser_ctx_) {
|
||||||
return -1;
|
return -1;
|
||||||
} else {
|
} 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 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) {
|
if (rv == 0) {
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -34,17 +34,10 @@
|
|||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <unordered_map>
|
#include <map>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
#include "ssl_compat.h"
|
#include <openssl/ssl.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 <ev.h>
|
#include <ev.h>
|
||||||
|
|
||||||
@@ -59,8 +52,8 @@
|
|||||||
namespace nghttp2 {
|
namespace nghttp2 {
|
||||||
|
|
||||||
struct Config {
|
struct Config {
|
||||||
std::unordered_map<std::string, std::vector<std::string>> push;
|
std::map<std::string, std::vector<std::string>> push;
|
||||||
std::unordered_map<std::string, std::string> mime_types;
|
std::map<std::string, std::string> mime_types;
|
||||||
Headers trailer;
|
Headers trailer;
|
||||||
std::string trailer_names;
|
std::string trailer_names;
|
||||||
std::string htdocs;
|
std::string htdocs;
|
||||||
@@ -91,6 +84,7 @@ struct Config {
|
|||||||
bool echo_upload;
|
bool echo_upload;
|
||||||
bool no_content_length;
|
bool no_content_length;
|
||||||
bool ktls;
|
bool ktls;
|
||||||
|
bool no_rfc7540_pri;
|
||||||
Config();
|
Config();
|
||||||
~Config();
|
~Config();
|
||||||
};
|
};
|
||||||
@@ -102,18 +96,18 @@ struct FileEntry {
|
|||||||
const std::string *content_type,
|
const std::string *content_type,
|
||||||
const std::chrono::steady_clock::time_point &last_valid,
|
const std::chrono::steady_clock::time_point &last_valid,
|
||||||
bool stale = false)
|
bool stale = false)
|
||||||
: path(std::move(path)),
|
: path(std::move(path)),
|
||||||
length(length),
|
length(length),
|
||||||
mtime(mtime),
|
mtime(mtime),
|
||||||
last_valid(last_valid),
|
last_valid(last_valid),
|
||||||
content_type(content_type),
|
content_type(content_type),
|
||||||
dlnext(nullptr),
|
dlnext(nullptr),
|
||||||
dlprev(nullptr),
|
dlprev(nullptr),
|
||||||
fd(fd),
|
fd(fd),
|
||||||
usecount(1),
|
usecount(1),
|
||||||
stale(stale) {}
|
stale(stale) {}
|
||||||
std::string path;
|
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 length;
|
||||||
int64_t mtime;
|
int64_t mtime;
|
||||||
std::chrono::steady_clock::time_point last_valid;
|
std::chrono::steady_clock::time_point last_valid;
|
||||||
@@ -125,13 +119,13 @@ struct FileEntry {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct RequestHeader {
|
struct RequestHeader {
|
||||||
std::string_view method;
|
StringRef method;
|
||||||
std::string_view scheme;
|
StringRef scheme;
|
||||||
std::string_view authority;
|
StringRef authority;
|
||||||
std::string_view host;
|
StringRef host;
|
||||||
std::string_view path;
|
StringRef path;
|
||||||
std::string_view ims;
|
StringRef ims;
|
||||||
std::string_view expect;
|
StringRef expect;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
nghttp2_rcbuf *method;
|
nghttp2_rcbuf *method;
|
||||||
@@ -176,21 +170,21 @@ public:
|
|||||||
int connection_made();
|
int connection_made();
|
||||||
int verify_alpn_result();
|
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,
|
time_t last_modified, off_t file_length,
|
||||||
const std::string *content_type,
|
const std::string *content_type,
|
||||||
nghttp2_data_provider2 *data_prd);
|
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);
|
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,
|
const HeaderRefs &headers,
|
||||||
nghttp2_data_provider2 *data_prd);
|
nghttp2_data_provider2 *data_prd);
|
||||||
|
|
||||||
int submit_non_final_response(const std::string &status, int32_t stream_id);
|
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);
|
int submit_rst_stream(Stream *stream, uint32_t error_code);
|
||||||
|
|
||||||
@@ -221,7 +215,7 @@ private:
|
|||||||
ev_io wev_;
|
ev_io wev_;
|
||||||
ev_io rev_;
|
ev_io rev_;
|
||||||
ev_timer settings_timerev_;
|
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_;
|
WriteBuf wb_;
|
||||||
std::function<int(Http2Handler &)> read_, write_;
|
std::function<int(Http2Handler &)> read_, write_;
|
||||||
int64_t session_id_;
|
int64_t session_id_;
|
||||||
|
|||||||
@@ -39,19 +39,15 @@ AM_CPPFLAGS = \
|
|||||||
-I$(top_srcdir)/lib/includes \
|
-I$(top_srcdir)/lib/includes \
|
||||||
-I$(top_builddir)/lib/includes \
|
-I$(top_builddir)/lib/includes \
|
||||||
-I$(top_srcdir)/lib \
|
-I$(top_srcdir)/lib \
|
||||||
-I$(top_srcdir)/third-party/urlparse \
|
-I$(top_srcdir)/third-party \
|
||||||
-I$(top_srcdir)/third-party/llhttp/include \
|
-I$(top_srcdir)/third-party/llhttp/include \
|
||||||
@JEMALLOC_CFLAGS@ \
|
@JEMALLOC_CFLAGS@ \
|
||||||
@LIBXML2_CFLAGS@ \
|
@LIBXML2_CFLAGS@ \
|
||||||
@LIBEV_CFLAGS@ \
|
@LIBEV_CFLAGS@ \
|
||||||
@LIBNGHTTP3_CFLAGS@ \
|
@LIBNGHTTP3_CFLAGS@ \
|
||||||
@LIBNGTCP2_CRYPTO_WOLFSSL_CFLAGS@ \
|
|
||||||
@LIBNGTCP2_CRYPTO_QUICTLS_CFLAGS@ \
|
@LIBNGTCP2_CRYPTO_QUICTLS_CFLAGS@ \
|
||||||
@LIBNGTCP2_CRYPTO_LIBRESSL_CFLAGS@ \
|
|
||||||
@LIBNGTCP2_CRYPTO_BORINGSSL_CFLAGS@ \
|
@LIBNGTCP2_CRYPTO_BORINGSSL_CFLAGS@ \
|
||||||
@LIBNGTCP2_CRYPTO_OSSL_CFLAGS@ \
|
|
||||||
@LIBNGTCP2_CFLAGS@ \
|
@LIBNGTCP2_CFLAGS@ \
|
||||||
@WOLFSSL_CFLAGS@ \
|
|
||||||
@OPENSSL_CFLAGS@ \
|
@OPENSSL_CFLAGS@ \
|
||||||
@LIBCARES_CFLAGS@ \
|
@LIBCARES_CFLAGS@ \
|
||||||
@JANSSON_CFLAGS@ \
|
@JANSSON_CFLAGS@ \
|
||||||
@@ -64,19 +60,15 @@ AM_CPPFLAGS = \
|
|||||||
AM_LDFLAGS = @LIBTOOL_LDFLAGS@
|
AM_LDFLAGS = @LIBTOOL_LDFLAGS@
|
||||||
|
|
||||||
LDADD = $(top_builddir)/lib/libnghttp2.la \
|
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 \
|
$(top_builddir)/third-party/libllhttp.la \
|
||||||
@JEMALLOC_LIBS@ \
|
@JEMALLOC_LIBS@ \
|
||||||
@LIBXML2_LIBS@ \
|
@LIBXML2_LIBS@ \
|
||||||
@LIBEV_LIBS@ \
|
@LIBEV_LIBS@ \
|
||||||
@LIBNGHTTP3_LIBS@ \
|
@LIBNGHTTP3_LIBS@ \
|
||||||
@LIBNGTCP2_CRYPTO_WOLFSSL_LIBS@ \
|
|
||||||
@LIBNGTCP2_CRYPTO_QUICTLS_LIBS@ \
|
@LIBNGTCP2_CRYPTO_QUICTLS_LIBS@ \
|
||||||
@LIBNGTCP2_CRYPTO_LIBRESSL_LIBS@ \
|
|
||||||
@LIBNGTCP2_CRYPTO_BORINGSSL_LIBS@ \
|
@LIBNGTCP2_CRYPTO_BORINGSSL_LIBS@ \
|
||||||
@LIBNGTCP2_CRYPTO_OSSL_LIBS@ \
|
|
||||||
@LIBNGTCP2_LIBS@ \
|
@LIBNGTCP2_LIBS@ \
|
||||||
@WOLFSSL_LIBS@ \
|
|
||||||
@OPENSSL_LIBS@ \
|
@OPENSSL_LIBS@ \
|
||||||
@LIBCARES_LIBS@ \
|
@LIBCARES_LIBS@ \
|
||||||
@SYSTEMD_LIBS@ \
|
@SYSTEMD_LIBS@ \
|
||||||
@@ -125,7 +117,8 @@ h2load_SOURCES = util.cc util.h \
|
|||||||
if ENABLE_HTTP3
|
if ENABLE_HTTP3
|
||||||
h2load_SOURCES += \
|
h2load_SOURCES += \
|
||||||
h2load_http3_session.cc h2load_http3_session.h \
|
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
|
endif # ENABLE_HTTP3
|
||||||
|
|
||||||
NGHTTPX_SRCS = \
|
NGHTTPX_SRCS = \
|
||||||
@@ -169,6 +162,7 @@ NGHTTPX_SRCS = \
|
|||||||
shrpx_health_monitor_downstream_connection.cc \
|
shrpx_health_monitor_downstream_connection.cc \
|
||||||
shrpx_health_monitor_downstream_connection.h \
|
shrpx_health_monitor_downstream_connection.h \
|
||||||
shrpx_null_downstream_connection.cc shrpx_null_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_dns_resolver.cc shrpx_dns_resolver.h \
|
||||||
shrpx_dual_dns_resolver.cc shrpx_dual_dns_resolver.h \
|
shrpx_dual_dns_resolver.cc shrpx_dual_dns_resolver.h \
|
||||||
shrpx_dns_tracker.cc shrpx_dns_tracker.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_quic_connection_handler.cc shrpx_quic_connection_handler.h \
|
||||||
shrpx_http3_upstream.cc shrpx_http3_upstream.h \
|
shrpx_http3_upstream.cc shrpx_http3_upstream.h \
|
||||||
http3.cc http3.h \
|
http3.cc http3.h \
|
||||||
siphash.cc siphash.h
|
quic.cc quic.h
|
||||||
endif # ENABLE_HTTP3
|
endif # ENABLE_HTTP3
|
||||||
|
|
||||||
noinst_LIBRARIES = libnghttpx.a
|
noinst_LIBRARIES = libnghttpx.a
|
||||||
@@ -231,9 +225,6 @@ nghttpx_unittest_SOURCES = shrpx-unittest.cc \
|
|||||||
base64_test.cc base64_test.h \
|
base64_test.cc base64_test.h \
|
||||||
$(top_srcdir)/tests/munit/munit.c $(top_srcdir)/tests/munit/munit.h \
|
$(top_srcdir)/tests/munit/munit.c $(top_srcdir)/tests/munit/munit.h \
|
||||||
$(top_srcdir)/tests/munit/munitxx.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} \
|
nghttpx_unittest_CPPFLAGS = ${AM_CPPFLAGS} \
|
||||||
-I$(top_srcdir)/tests/munit \
|
-I$(top_srcdir)/tests/munit \
|
||||||
-DNGHTTP2_SRC_DIR=\"$(top_srcdir)/src\"
|
-DNGHTTP2_SRC_DIR=\"$(top_srcdir)/src\"
|
||||||
|
|||||||
@@ -34,7 +34,6 @@
|
|||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <span>
|
#include <span>
|
||||||
#include <algorithm>
|
|
||||||
|
|
||||||
#include "template.h"
|
#include "template.h"
|
||||||
|
|
||||||
@@ -70,20 +69,20 @@ static_assert(sizeof(ChunkHead) == 16);
|
|||||||
// |block_size|.
|
// |block_size|.
|
||||||
struct BlockAllocator {
|
struct BlockAllocator {
|
||||||
BlockAllocator(size_t block_size, size_t isolation_threshold)
|
BlockAllocator(size_t block_size, size_t isolation_threshold)
|
||||||
: retain(nullptr),
|
: retain(nullptr),
|
||||||
head(nullptr),
|
head(nullptr),
|
||||||
block_size(block_size),
|
block_size(block_size),
|
||||||
isolation_threshold(std::min(block_size, isolation_threshold)) {
|
isolation_threshold(std::min(block_size, isolation_threshold)) {
|
||||||
assert(isolation_threshold <= block_size);
|
assert(isolation_threshold <= block_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
~BlockAllocator() { reset(); }
|
~BlockAllocator() { reset(); }
|
||||||
|
|
||||||
BlockAllocator(BlockAllocator &&other) noexcept
|
BlockAllocator(BlockAllocator &&other) noexcept
|
||||||
: retain{std::exchange(other.retain, nullptr)},
|
: retain{std::exchange(other.retain, nullptr)},
|
||||||
head{std::exchange(other.head, nullptr)},
|
head{std::exchange(other.head, nullptr)},
|
||||||
block_size(other.block_size),
|
block_size(other.block_size),
|
||||||
isolation_threshold(other.isolation_threshold) {}
|
isolation_threshold(other.isolation_threshold) {}
|
||||||
|
|
||||||
BlockAllocator &operator=(BlockAllocator &&other) noexcept {
|
BlockAllocator &operator=(BlockAllocator &&other) noexcept {
|
||||||
reset();
|
reset();
|
||||||
@@ -116,7 +115,7 @@ struct BlockAllocator {
|
|||||||
|
|
||||||
mb->next = retain;
|
mb->next = retain;
|
||||||
mb->begin = mb->last = reinterpret_cast<uint8_t *>(
|
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;
|
mb->end = mb->begin + size;
|
||||||
retain = mb;
|
retain = mb;
|
||||||
return mb;
|
return mb;
|
||||||
@@ -147,7 +146,7 @@ struct BlockAllocator {
|
|||||||
ch->size = size;
|
ch->size = size;
|
||||||
|
|
||||||
head->last = reinterpret_cast<uint8_t *>(
|
head->last = reinterpret_cast<uint8_t *>(
|
||||||
(reinterpret_cast<intptr_t>(res + size) + 0xf) & ~0xf);
|
(reinterpret_cast<intptr_t>(res + size) + 0xf) & ~0xf);
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
@@ -157,7 +156,7 @@ struct BlockAllocator {
|
|||||||
size_t get_alloc_length(void *ptr) {
|
size_t get_alloc_length(void *ptr) {
|
||||||
return reinterpret_cast<ChunkHead *>(static_cast<uint8_t *>(ptr) -
|
return reinterpret_cast<ChunkHead *>(static_cast<uint8_t *>(ptr) -
|
||||||
sizeof(ChunkHead))
|
sizeof(ChunkHead))
|
||||||
->size;
|
->size;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Allocates memory of at least |size| bytes. If |ptr| is nullptr,
|
// 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 nalloclen = std::max(size + 1, alloclen * 2);
|
||||||
|
|
||||||
auto res = alloc(nalloclen);
|
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;
|
return res;
|
||||||
}
|
}
|
||||||
@@ -196,37 +195,29 @@ struct BlockAllocator {
|
|||||||
size_t isolation_threshold;
|
size_t isolation_threshold;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Makes a copy of a range [|first|, |last|). The resulting string
|
// Makes a copy of |src|. The resulting string will be
|
||||||
// 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
|
|
||||||
// NULL-terminated.
|
// NULL-terminated.
|
||||||
template <std::ranges::input_range R>
|
template <typename BlockAllocator>
|
||||||
requires(!std::is_array_v<std::remove_cvref_t<R>>)
|
StringRef make_string_ref(BlockAllocator &alloc, const StringRef &src) {
|
||||||
std::string_view make_string_ref(BlockAllocator &alloc, R &&r) {
|
auto dst = static_cast<uint8_t *>(alloc.alloc(src.size() + 1));
|
||||||
return make_string_ref(alloc, std::ranges::begin(r), std::ranges::end(r));
|
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
|
// private function used in concat_string_ref. this is the base
|
||||||
// function of concat_string_ref_count().
|
// 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
|
// private function used in concat_string_ref. This function counts
|
||||||
// the sum of length of given arguments. The calculated length is
|
// the sum of length of given arguments. The calculated length is
|
||||||
// accumulated, and passed to the next function.
|
// accumulated, and passed to the next function.
|
||||||
template <std::ranges::input_range R, std::ranges::input_range... Args>
|
template <typename... Args>
|
||||||
requires(!std::is_array_v<std::remove_cvref_t<R>>)
|
constexpr size_t concat_string_ref_count(size_t acc, const StringRef &value,
|
||||||
constexpr size_t concat_string_ref_count(size_t acc, R &&r, Args &&...args) {
|
Args &&...args) {
|
||||||
return concat_string_ref_count(acc + std::ranges::size(r), args...);
|
return concat_string_ref_count(acc + value.size(),
|
||||||
|
std::forward<Args>(args)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
// private function used in concat_string_ref. this is the base
|
// 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,
|
// given strings into |p|. |p| is incremented by the copied length,
|
||||||
// and returned. In the end, return value points to the location one
|
// and returned. In the end, return value points to the location one
|
||||||
// beyond the last byte written.
|
// beyond the last byte written.
|
||||||
template <std::ranges::input_range R, std::ranges::input_range... Args>
|
template <typename... Args>
|
||||||
requires(!std::is_array_v<std::remove_cvref_t<R>>)
|
uint8_t *concat_string_ref_copy(uint8_t *p, const StringRef &value,
|
||||||
uint8_t *concat_string_ref_copy(uint8_t *p, R &&r, Args &&...args) {
|
Args &&...args) {
|
||||||
return concat_string_ref_copy(std::ranges::copy(std::forward<R>(r), p).out,
|
p = std::copy(std::begin(value), std::end(value), p);
|
||||||
std::forward<Args>(args)...);
|
return concat_string_ref_copy(p, std::forward<Args>(args)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the string which is the concatenation of |args| in the
|
// Returns the string which is the concatenation of |args| in the
|
||||||
// given order. The resulting string will be NULL-terminated.
|
// given order. The resulting string will be NULL-terminated.
|
||||||
template <std::ranges::input_range... Args>
|
template <typename BlockAllocator, typename... Args>
|
||||||
std::string_view concat_string_ref(BlockAllocator &alloc, Args &&...args) {
|
StringRef concat_string_ref(BlockAllocator &alloc, Args &&...args) {
|
||||||
auto len = concat_string_ref_count(0, args...);
|
size_t len = concat_string_ref_count(0, std::forward<Args>(args)...);
|
||||||
auto dst = static_cast<uint8_t *>(alloc.alloc(len + 1));
|
auto dst = static_cast<uint8_t *>(alloc.alloc(len + 1));
|
||||||
auto p = dst;
|
auto p = dst;
|
||||||
p = concat_string_ref_copy(p, std::forward<Args>(args)...);
|
p = concat_string_ref_copy(p, std::forward<Args>(args)...);
|
||||||
*p = '\0';
|
*p = '\0';
|
||||||
return as_string_view(dst, p);
|
return StringRef{dst, len};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the string which is the concatenation of |value| and |args|
|
// 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
|
// obtained from alloc.alloc() or alloc.realloc(), and attempts to use
|
||||||
// unused memory region by using alloc.realloc(). If value is empty,
|
// unused memory region by using alloc.realloc(). If value is empty,
|
||||||
// then just call concat_string_ref().
|
// then just call concat_string_ref().
|
||||||
template <std::ranges::input_range... Args>
|
template <typename BlockAllocator, typename... Args>
|
||||||
std::string_view realloc_concat_string_ref(BlockAllocator &alloc,
|
StringRef realloc_concat_string_ref(BlockAllocator &alloc,
|
||||||
const std::string_view &value,
|
const StringRef &value, Args &&...args) {
|
||||||
Args &&...args) {
|
|
||||||
if (value.empty()) {
|
if (value.empty()) {
|
||||||
return concat_string_ref(alloc, std::forward<Args>(args)...);
|
return concat_string_ref(alloc, std::forward<Args>(args)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto len = value.size() + concat_string_ref_count(0, args...);
|
auto len =
|
||||||
auto dst = static_cast<uint8_t *>(alloc.realloc(
|
value.size() + concat_string_ref_count(0, std::forward<Args>(args)...);
|
||||||
const_cast<uint8_t *>(reinterpret_cast<const uint8_t *>(value.data())),
|
auto dst = static_cast<uint8_t *>(
|
||||||
len + 1));
|
alloc.realloc(const_cast<uint8_t *>(value.byte()), len + 1));
|
||||||
auto p = dst + value.size();
|
auto p = dst + value.size();
|
||||||
p = concat_string_ref_copy(p, std::forward<Args>(args)...);
|
p = concat_string_ref_copy(p, std::forward<Args>(args)...);
|
||||||
*p = '\0';
|
*p = '\0';
|
||||||
|
|
||||||
return as_string_view(dst, p);
|
return StringRef{dst, len};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Makes an uninitialized buffer with given size.
|
// 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};
|
return {static_cast<uint8_t *>(alloc.alloc(size)), size};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -49,6 +49,7 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <set>
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
|
||||||
@@ -118,7 +119,7 @@ std::string strframetype(uint8_t type) {
|
|||||||
s += ')';
|
s += ')';
|
||||||
|
|
||||||
return s;
|
return s;
|
||||||
}
|
};
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
@@ -328,20 +329,20 @@ void print_frame(print_type ptype, const nghttp2_frame *frame) {
|
|||||||
case NGHTTP2_PING:
|
case NGHTTP2_PING:
|
||||||
print_frame_attr_indent();
|
print_frame_attr_indent();
|
||||||
fprintf(outfile, "(opaque_data=%s)\n",
|
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;
|
break;
|
||||||
case NGHTTP2_GOAWAY:
|
case NGHTTP2_GOAWAY:
|
||||||
print_frame_attr_indent();
|
print_frame_attr_indent();
|
||||||
fprintf(
|
fprintf(outfile,
|
||||||
outfile,
|
"(last_stream_id=%d, error_code=%s(0x%02x), "
|
||||||
"(last_stream_id=%d, error_code=%s(0x%02x), "
|
"opaque_data(%u)=[%s])\n",
|
||||||
"opaque_data(%u)=[%s])\n",
|
frame->goaway.last_stream_id,
|
||||||
frame->goaway.last_stream_id,
|
nghttp2_http2_strerror(frame->goaway.error_code),
|
||||||
nghttp2_http2_strerror(frame->goaway.error_code),
|
frame->goaway.error_code,
|
||||||
frame->goaway.error_code,
|
static_cast<unsigned int>(frame->goaway.opaque_data_len),
|
||||||
static_cast<unsigned int>(frame->goaway.opaque_data_len),
|
util::ascii_dump(frame->goaway.opaque_data,
|
||||||
util::ascii_dump(frame->goaway.opaque_data, frame->goaway.opaque_data_len)
|
frame->goaway.opaque_data_len)
|
||||||
.c_str());
|
.c_str());
|
||||||
break;
|
break;
|
||||||
case NGHTTP2_WINDOW_UPDATE:
|
case NGHTTP2_WINDOW_UPDATE:
|
||||||
print_frame_attr_indent();
|
print_frame_attr_indent();
|
||||||
@@ -367,7 +368,7 @@ void print_frame(print_type ptype, const nghttp2_frame *frame) {
|
|||||||
}
|
}
|
||||||
case NGHTTP2_PRIORITY_UPDATE: {
|
case NGHTTP2_PRIORITY_UPDATE: {
|
||||||
auto 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();
|
print_frame_attr_indent();
|
||||||
fprintf(outfile,
|
fprintf(outfile,
|
||||||
"(prioritized_stream_id=%d, priority_field_value=[%.*s])\n",
|
"(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) {
|
size_t len, void *user_data) {
|
||||||
print_timer();
|
print_timer();
|
||||||
auto srecv =
|
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);
|
auto crecv = nghttp2_session_get_effective_recv_data_length(session);
|
||||||
|
|
||||||
fprintf(outfile,
|
fprintf(outfile,
|
||||||
|
|||||||
@@ -34,6 +34,7 @@
|
|||||||
#endif // HAVE_SYS_TIME_H
|
#endif // HAVE_SYS_TIME_H
|
||||||
#include <poll.h>
|
#include <poll.h>
|
||||||
|
|
||||||
|
#include <map>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
|
|
||||||
#include <nghttp2/nghttp2.h>
|
#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