mirror of
https://github.com/nghttp2/nghttp2.git
synced 2025-12-08 02:58:53 +08:00
Compare commits
435 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4a9d200554 | ||
|
|
acf6a9229d | ||
|
|
4ff4582132 | ||
|
|
42dce01ec1 | ||
|
|
a35059e3f1 | ||
|
|
5a30fafdda | ||
|
|
dce91ad37c | ||
|
|
2cff8b43cf | ||
|
|
be96654d56 | ||
|
|
ce962c3fdf | ||
|
|
f931504e1c | ||
|
|
d978f351da | ||
|
|
ec519f22dc | ||
|
|
e8b213e367 | ||
|
|
cfb47d30a5 | ||
|
|
dbbe4e017a | ||
|
|
371bc3a8f7 | ||
|
|
5e7889c5ef | ||
|
|
b1b2ad5017 | ||
|
|
e043ca83c5 | ||
|
|
c2434dfbbc | ||
|
|
816ad2102f | ||
|
|
f5feb16ef4 | ||
|
|
adf09f2124 | ||
|
|
2591960e2f | ||
|
|
d93842db3e | ||
|
|
8dc2b263ba | ||
|
|
8d842701b5 | ||
|
|
de85b0fda5 | ||
|
|
5d6beed590 | ||
|
|
1ff9de4c87 | ||
|
|
34482ed4df | ||
|
|
9b6ced66f3 | ||
|
|
e7e8ee5fe6 | ||
|
|
b3b4e33535 | ||
|
|
bd93d90a89 | ||
|
|
ea69c84b33 | ||
|
|
783b649bb1 | ||
|
|
eb21e6f8f7 | ||
|
|
ab2aa5672b | ||
|
|
ff87a54202 | ||
|
|
439dbce679 | ||
|
|
e9c9838cdc | ||
|
|
803d4ba948 | ||
|
|
732245e562 | ||
|
|
9e8d5433e7 | ||
|
|
fdcdb21c38 | ||
|
|
11d0533cfc | ||
|
|
dbb5f00d68 | ||
|
|
9cc412e2fd | ||
|
|
5b2efc0a12 | ||
|
|
7e4c48a461 | ||
|
|
082e162f3c | ||
|
|
7cc7c06c7b | ||
|
|
12ebeb30d0 | ||
|
|
c78abbe1d2 | ||
|
|
124c7848c0 | ||
|
|
ce9667c4f5 | ||
|
|
f3f40840b3 | ||
|
|
2c1570595e | ||
|
|
302abf1b46 | ||
|
|
089a03be42 | ||
|
|
de4fe72861 | ||
|
|
d1b3a83f59 | ||
|
|
eb6792533d | ||
|
|
6800d317e7 | ||
|
|
c98362eab1 | ||
|
|
e520469b3e | ||
|
|
54067256eb | ||
|
|
c4d2eeeec7 | ||
|
|
f51e696e4a | ||
|
|
a433b132fc | ||
|
|
cf48a56d2e | ||
|
|
6cad1b243b | ||
|
|
3c393dca58 | ||
|
|
172924457f | ||
|
|
f6644a92af | ||
|
|
48998f7239 | ||
|
|
15ff52f9fb | ||
|
|
6c03bb142b | ||
|
|
524b439221 | ||
|
|
859bf2bc41 | ||
|
|
b5619fb156 | ||
|
|
dcbe0c690f | ||
|
|
2996c28456 | ||
|
|
42e8ceb656 | ||
|
|
1daf9ce8b7 | ||
|
|
d68edf56c0 | ||
|
|
0c4e9fef29 | ||
|
|
571404c6e8 | ||
|
|
4d562b773b | ||
|
|
e62258713e | ||
|
|
4bd075defd | ||
|
|
b46a324943 | ||
|
|
4bd44b9cdf | ||
|
|
1b42110d4f | ||
|
|
0735ec55f3 | ||
|
|
00554779e1 | ||
|
|
0963f38935 | ||
|
|
1abfa3ca5f | ||
|
|
f2159bc2c1 | ||
|
|
b0eb68ee9e | ||
|
|
e7b7b037f6 | ||
|
|
5e4f434fd8 | ||
|
|
20ea964f2f | ||
|
|
d105619bc3 | ||
|
|
ec5729b1fa | ||
|
|
6c9196953e | ||
|
|
46576178a3 | ||
|
|
5e925f873e | ||
|
|
153531d4d0 | ||
|
|
f7287df03f | ||
|
|
2b085815b7 | ||
|
|
986fa30264 | ||
|
|
7c8cb3a0ce | ||
|
|
334c439ce0 | ||
|
|
6c17ed7e61 | ||
|
|
6700626c30 | ||
|
|
15162addc4 | ||
|
|
9327077741 | ||
|
|
aeb92bbbe2 | ||
|
|
fc7489e044 | ||
|
|
87ac872fdc | ||
|
|
c278adde7a | ||
|
|
f94d720909 | ||
|
|
9b9baa6bd9 | ||
|
|
02566ee383 | ||
|
|
3002f31b1f | ||
|
|
d2a594a753 | ||
|
|
651e147711 | ||
|
|
a42faf1cc2 | ||
|
|
4aac05e193 | ||
|
|
b80dfaa8a0 | ||
|
|
a19d8f5d31 | ||
|
|
33f6e90a56 | ||
|
|
ed7fabcbc2 | ||
|
|
8753b6da14 | ||
|
|
f2de733bdf | ||
|
|
88ff8c69a0 | ||
|
|
a63558a1eb | ||
|
|
3575a1325e | ||
|
|
e2de2fee69 | ||
|
|
9f415979fb | ||
|
|
4bfc0cd196 | ||
|
|
9c824b87fe | ||
|
|
a1ea1696be | ||
|
|
dfc0f248c6 | ||
|
|
ed7c9db2a6 | ||
|
|
5b42815afb | ||
|
|
cfe7fa9a75 | ||
|
|
cb8a9d58fd | ||
|
|
023b94480b | ||
|
|
9b03c64f68 | ||
|
|
b8eccec62d | ||
|
|
9f21258720 | ||
|
|
47f6012407 | ||
|
|
770e44de4d | ||
|
|
2ab319c137 | ||
|
|
3992302432 | ||
|
|
b30f312a70 | ||
|
|
c5cdb78a95 | ||
|
|
d82811303b | ||
|
|
f79a58120e | ||
|
|
9d843334d6 | ||
|
|
23cb3f38a6 | ||
|
|
1d682dcdae | ||
|
|
601fbbb4ae | ||
|
|
f44aa2466f | ||
|
|
dd74a6dd34 | ||
|
|
e959e7338e | ||
|
|
fb9a204de2 | ||
|
|
cd096802bd | ||
|
|
7417fd71a4 | ||
|
|
2d1a981c81 | ||
|
|
45acc922eb | ||
|
|
214d089910 | ||
|
|
31fd707d0c | ||
|
|
9a2e38e058 | ||
|
|
d24527e7e6 | ||
|
|
6195d747ce | ||
|
|
fb97f596e1 | ||
|
|
0ccc7a770d | ||
|
|
32826466f5 | ||
|
|
0422f8a844 | ||
|
|
e329479a99 | ||
|
|
f80a7873ba | ||
|
|
866ac6ab27 | ||
|
|
b574ae6aa2 | ||
|
|
de4fd7cd35 | ||
|
|
32d7883c47 | ||
|
|
9b24e19763 | ||
|
|
13ffece12d | ||
|
|
9d5b781df6 | ||
|
|
11d822c2a7 | ||
|
|
4098512b5d | ||
|
|
7e06ac1072 | ||
|
|
c6d8c4013c | ||
|
|
e5b3f9addd | ||
|
|
880f948684 | ||
|
|
bda7e079e2 | ||
|
|
fc94018b97 | ||
|
|
159c5e446a | ||
|
|
bfd4d8b052 | ||
|
|
388e785822 | ||
|
|
2ba1389993 | ||
|
|
d65a417306 | ||
|
|
575bc309b9 | ||
|
|
00909d0742 | ||
|
|
a7e38724e7 | ||
|
|
325612bcde | ||
|
|
8034221525 | ||
|
|
2e6593e5a5 | ||
|
|
572735e496 | ||
|
|
e8d693c395 | ||
|
|
f44dfcd9dc | ||
|
|
1f1b0d93d4 | ||
|
|
ce8c749b77 | ||
|
|
3e4f257b91 | ||
|
|
86fab997b4 | ||
|
|
c3ecd44592 | ||
|
|
c65ca20a49 | ||
|
|
a5c408c5e3 | ||
|
|
06379b2861 | ||
|
|
e04de48ed9 | ||
|
|
009646421c | ||
|
|
8d0b4544f8 | ||
|
|
d8a34131e1 | ||
|
|
5db17d0af9 | ||
|
|
1bf69b5662 | ||
|
|
3febaef1fa | ||
|
|
b1bd6035e8 | ||
|
|
b48bcb214a | ||
|
|
6f3ce2c72d | ||
|
|
2f9121cf44 | ||
|
|
e65e7711ca | ||
|
|
636ef51b0f | ||
|
|
400934e5a3 | ||
|
|
4c3a3acf9b | ||
|
|
9aa6002c37 | ||
|
|
f342260bfe | ||
|
|
a6dd497016 | ||
|
|
842509dab6 | ||
|
|
4add618a3f | ||
|
|
6e74466231 | ||
|
|
478eac099f | ||
|
|
88e2029e37 | ||
|
|
45d76cf501 | ||
|
|
54573f28a8 | ||
|
|
17793e99dc | ||
|
|
5eac3c9025 | ||
|
|
e70195ae91 | ||
|
|
fe51e7fa1a | ||
|
|
eb951c2ce4 | ||
|
|
39f0ce7c25 | ||
|
|
65157811d4 | ||
|
|
e8af7afc65 | ||
|
|
38abfd1863 | ||
|
|
ff3edc09ed | ||
|
|
0bb1540682 | ||
|
|
f0836c7e39 | ||
|
|
25db178b7d | ||
|
|
1b6713e6ec | ||
|
|
c1a496cf4e | ||
|
|
e098a21132 | ||
|
|
0ba4bf51e4 | ||
|
|
6deee2037d | ||
|
|
6761a933fe | ||
|
|
5cc3d159e1 | ||
|
|
652f57e79d | ||
|
|
acd6b40e4c | ||
|
|
0fbb46edd6 | ||
|
|
6ad629de47 | ||
|
|
74754982f1 | ||
|
|
a31a2e3b2c | ||
|
|
a776b0dbcc | ||
|
|
cfd926f09b | ||
|
|
72f52716ae | ||
|
|
439b9b6c6a | ||
|
|
4849845292 | ||
|
|
d30f38163c | ||
|
|
cff9ebe1dd | ||
|
|
4d1139f653 | ||
|
|
48f574076c | ||
|
|
c1f14d73c7 | ||
|
|
216f4dad83 | ||
|
|
a4e27d766b | ||
|
|
96df14d2ec | ||
|
|
2365f12e39 | ||
|
|
96ea9cdaf7 | ||
|
|
03f7ec0f60 | ||
|
|
a941699962 | ||
|
|
2056e812bd | ||
|
|
04348ff20e | ||
|
|
d8e378fea9 | ||
|
|
1ebb6810a1 | ||
|
|
2a694b270a | ||
|
|
a3ebeeafba | ||
|
|
422ad1be32 | ||
|
|
97f1735cf5 | ||
|
|
939ad5ddbe | ||
|
|
24d92b979d | ||
|
|
4c92ff1843 | ||
|
|
280db5c6ba | ||
|
|
7fbcb2d005 | ||
|
|
53aeb2c3d7 | ||
|
|
ff200bfcf3 | ||
|
|
fee3151fd2 | ||
|
|
99a85159ae | ||
|
|
2a981a3f56 | ||
|
|
0028275d7b | ||
|
|
ee8bfddfc9 | ||
|
|
194acb1f2c | ||
|
|
43a2a70ae7 | ||
|
|
73344ae9aa | ||
|
|
c479f6122f | ||
|
|
eca0a3025b | ||
|
|
4720c5cb3d | ||
|
|
cd55ab28ab | ||
|
|
d402cfdf16 | ||
|
|
22502182d0 | ||
|
|
05e1fd5e77 | ||
|
|
943d7923f9 | ||
|
|
568ecbfb28 | ||
|
|
f5ddd7f43b | ||
|
|
88abbce7e7 | ||
|
|
16e9036568 | ||
|
|
fa7945c627 | ||
|
|
daca43f0dd | ||
|
|
16bc11e670 | ||
|
|
6f7e94cdba | ||
|
|
61efa15a14 | ||
|
|
8c0ea56bb8 | ||
|
|
549053710b | ||
|
|
6010d39325 | ||
|
|
be5c39a1cf | ||
|
|
b8fda6808b | ||
|
|
e29b9c1261 | ||
|
|
539e27812b | ||
|
|
7008afd40e | ||
|
|
77a41756db | ||
|
|
b15045d60e | ||
|
|
03084f7517 | ||
|
|
60baca27e4 | ||
|
|
86990db236 | ||
|
|
cb376bcd80 | ||
|
|
f2b8edd1e2 | ||
|
|
c4f8afcfde | ||
|
|
1a1a216d5a | ||
|
|
9f80a82c1a | ||
|
|
c573c80bd3 | ||
|
|
3cd6817e21 | ||
|
|
d4a69658a1 | ||
|
|
8e06fe4971 | ||
|
|
aaeeec8f1c | ||
|
|
66d5e24606 | ||
|
|
e8907a073f | ||
|
|
9656ac0254 | ||
|
|
75624617ce | ||
|
|
1a8f6578b3 | ||
|
|
4f0548b018 | ||
|
|
5119e82b93 | ||
|
|
3be5856c82 | ||
|
|
a319143901 | ||
|
|
17c88d60c7 | ||
|
|
7601511fdf | ||
|
|
f507b5eee4 | ||
|
|
93821165be | ||
|
|
aaa0b858e4 | ||
|
|
5fa1938691 | ||
|
|
56ee3d4820 | ||
|
|
c2d9a1ed6f | ||
|
|
fcf9ab2798 | ||
|
|
35e445bd04 | ||
|
|
88ce3c31b7 | ||
|
|
16320a0f81 | ||
|
|
8c72fb3539 | ||
|
|
8ffe389daa | ||
|
|
189a4516a1 | ||
|
|
2576855ded | ||
|
|
7d4d48a35e | ||
|
|
cc6f759190 | ||
|
|
c23fc86a23 | ||
|
|
d2324bdda1 | ||
|
|
6f0ae9d49a | ||
|
|
0389af5724 | ||
|
|
1766e25f45 | ||
|
|
323001238a | ||
|
|
91f062f873 | ||
|
|
650a0cfbff | ||
|
|
e6b8b3d1d3 | ||
|
|
a170023f23 | ||
|
|
4be4c0cddc | ||
|
|
0de9d374df | ||
|
|
0df199198a | ||
|
|
7646e376e0 | ||
|
|
5996798a34 | ||
|
|
6fec532012 | ||
|
|
15713e0b7c | ||
|
|
a6a561af47 | ||
|
|
09c468a4b4 | ||
|
|
bcda1c2409 | ||
|
|
afcd8d9ab1 | ||
|
|
c9b1c91944 | ||
|
|
5d9434eb09 | ||
|
|
1a44b5d52a | ||
|
|
6635ca5e26 | ||
|
|
9c6c78833b | ||
|
|
9a9ab0813c | ||
|
|
0ccaaa48ce | ||
|
|
3f2fe98dd1 | ||
|
|
0d91e9c255 | ||
|
|
af926fbe1f | ||
|
|
83039ae2d4 | ||
|
|
4c53da6961 | ||
|
|
eb306f463e | ||
|
|
788835c5fd | ||
|
|
4d76606fa2 | ||
|
|
1baf7d34b3 | ||
|
|
c78159469a | ||
|
|
b72ca0289c | ||
|
|
46f670f8a2 | ||
|
|
4b44362b9f | ||
|
|
d068a29798 | ||
|
|
0836a51408 | ||
|
|
566cee8fe7 | ||
|
|
e85698e131 | ||
|
|
5f3c541c4c | ||
|
|
3c43e00d8a | ||
|
|
92d686d356 | ||
|
|
0f69e9c825 | ||
|
|
217d979458 | ||
|
|
cc289972fc | ||
|
|
c601e603c2 | ||
|
|
1002c6da1c | ||
|
|
0911337689 |
@@ -4,7 +4,7 @@ AccessModifierOffset: -2
|
|||||||
AlignAfterOpenBracket: Align
|
AlignAfterOpenBracket: Align
|
||||||
AlignConsecutiveAssignments: false
|
AlignConsecutiveAssignments: false
|
||||||
AlignConsecutiveDeclarations: false
|
AlignConsecutiveDeclarations: false
|
||||||
AlignEscapedNewlinesLeft: false
|
AlignEscapedNewlines: Right
|
||||||
AlignOperands: true
|
AlignOperands: true
|
||||||
AlignTrailingComments: true
|
AlignTrailingComments: true
|
||||||
AllowAllParametersOfDeclarationOnNextLine: true
|
AllowAllParametersOfDeclarationOnNextLine: true
|
||||||
@@ -16,10 +16,10 @@ AllowShortLoopsOnASingleLine: false
|
|||||||
AlwaysBreakAfterDefinitionReturnType: None
|
AlwaysBreakAfterDefinitionReturnType: None
|
||||||
AlwaysBreakAfterReturnType: None
|
AlwaysBreakAfterReturnType: None
|
||||||
AlwaysBreakBeforeMultilineStrings: false
|
AlwaysBreakBeforeMultilineStrings: false
|
||||||
AlwaysBreakTemplateDeclarations: false
|
AlwaysBreakTemplateDeclarations: MultiLine
|
||||||
BinPackArguments: true
|
BinPackArguments: true
|
||||||
BinPackParameters: true
|
BinPackParameters: true
|
||||||
BraceWrapping:
|
BraceWrapping:
|
||||||
AfterClass: false
|
AfterClass: false
|
||||||
AfterControlStatement: false
|
AfterControlStatement: false
|
||||||
AfterEnum: false
|
AfterEnum: false
|
||||||
@@ -28,17 +28,25 @@ BraceWrapping:
|
|||||||
AfterObjCDeclaration: false
|
AfterObjCDeclaration: false
|
||||||
AfterStruct: false
|
AfterStruct: false
|
||||||
AfterUnion: false
|
AfterUnion: false
|
||||||
|
AfterExternBlock: false
|
||||||
BeforeCatch: false
|
BeforeCatch: false
|
||||||
BeforeElse: false
|
BeforeElse: false
|
||||||
IndentBraces: false
|
IndentBraces: false
|
||||||
|
SplitEmptyFunction: true
|
||||||
|
SplitEmptyRecord: true
|
||||||
|
SplitEmptyNamespace: true
|
||||||
BreakBeforeBinaryOperators: None
|
BreakBeforeBinaryOperators: None
|
||||||
BreakBeforeBraces: Attach
|
BreakBeforeBraces: Attach
|
||||||
|
BreakBeforeInheritanceComma: false
|
||||||
|
BreakInheritanceList: BeforeColon
|
||||||
BreakBeforeTernaryOperators: true
|
BreakBeforeTernaryOperators: true
|
||||||
BreakConstructorInitializersBeforeComma: false
|
BreakConstructorInitializersBeforeComma: false
|
||||||
|
BreakConstructorInitializers: BeforeColon
|
||||||
BreakAfterJavaFieldAnnotations: false
|
BreakAfterJavaFieldAnnotations: false
|
||||||
BreakStringLiterals: true
|
BreakStringLiterals: true
|
||||||
ColumnLimit: 80
|
ColumnLimit: 80
|
||||||
CommentPragmas: '^ IWYU pragma:'
|
CommentPragmas: '^ IWYU pragma:'
|
||||||
|
CompactNamespaces: false
|
||||||
ConstructorInitializerAllOnOneLineOrOnePerLine: true
|
ConstructorInitializerAllOnOneLineOrOnePerLine: true
|
||||||
ConstructorInitializerIndentWidth: 4
|
ConstructorInitializerIndentWidth: 4
|
||||||
ContinuationIndentWidth: 4
|
ContinuationIndentWidth: 4
|
||||||
@@ -46,8 +54,13 @@ Cpp11BracedListStyle: true
|
|||||||
DerivePointerAlignment: false
|
DerivePointerAlignment: false
|
||||||
DisableFormat: false
|
DisableFormat: false
|
||||||
ExperimentalAutoDetectBinPacking: false
|
ExperimentalAutoDetectBinPacking: false
|
||||||
ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ]
|
FixNamespaceComments: true
|
||||||
IncludeCategories:
|
ForEachMacros:
|
||||||
|
- foreach
|
||||||
|
- Q_FOREACH
|
||||||
|
- BOOST_FOREACH
|
||||||
|
IncludeBlocks: Preserve
|
||||||
|
IncludeCategories:
|
||||||
- Regex: '^"(llvm|llvm-c|clang|clang-c)/'
|
- Regex: '^"(llvm|llvm-c|clang|clang-c)/'
|
||||||
Priority: 2
|
Priority: 2
|
||||||
- Regex: '^(<|"(gtest|isl|json)/)'
|
- Regex: '^(<|"(gtest|isl|json)/)'
|
||||||
@@ -56,6 +69,7 @@ IncludeCategories:
|
|||||||
Priority: 1
|
Priority: 1
|
||||||
IncludeIsMainRegex: '$'
|
IncludeIsMainRegex: '$'
|
||||||
IndentCaseLabels: false
|
IndentCaseLabels: false
|
||||||
|
IndentPPDirectives: AfterHash
|
||||||
IndentWidth: 2
|
IndentWidth: 2
|
||||||
IndentWrappedFunctionNames: false
|
IndentWrappedFunctionNames: false
|
||||||
JavaScriptQuotes: Leave
|
JavaScriptQuotes: Leave
|
||||||
@@ -65,22 +79,30 @@ MacroBlockBegin: ''
|
|||||||
MacroBlockEnd: ''
|
MacroBlockEnd: ''
|
||||||
MaxEmptyLinesToKeep: 1
|
MaxEmptyLinesToKeep: 1
|
||||||
NamespaceIndentation: None
|
NamespaceIndentation: None
|
||||||
|
ObjCBinPackProtocolList: Auto
|
||||||
ObjCBlockIndentWidth: 2
|
ObjCBlockIndentWidth: 2
|
||||||
ObjCSpaceAfterProperty: false
|
ObjCSpaceAfterProperty: false
|
||||||
ObjCSpaceBeforeProtocolList: true
|
ObjCSpaceBeforeProtocolList: true
|
||||||
|
PenaltyBreakAssignment: 2
|
||||||
PenaltyBreakBeforeFirstCallParameter: 19
|
PenaltyBreakBeforeFirstCallParameter: 19
|
||||||
PenaltyBreakComment: 300
|
PenaltyBreakComment: 300
|
||||||
PenaltyBreakFirstLessLess: 120
|
PenaltyBreakFirstLessLess: 120
|
||||||
PenaltyBreakString: 1000
|
PenaltyBreakString: 1000
|
||||||
|
PenaltyBreakTemplateDeclaration: 10
|
||||||
PenaltyExcessCharacter: 1000000
|
PenaltyExcessCharacter: 1000000
|
||||||
PenaltyReturnTypeOnItsOwnLine: 60
|
PenaltyReturnTypeOnItsOwnLine: 60
|
||||||
PointerAlignment: Right
|
PointerAlignment: Right
|
||||||
ReflowComments: true
|
ReflowComments: true
|
||||||
SortIncludes: false
|
SortIncludes: false
|
||||||
|
SortUsingDeclarations: true
|
||||||
SpaceAfterCStyleCast: false
|
SpaceAfterCStyleCast: false
|
||||||
SpaceAfterTemplateKeyword: true
|
SpaceAfterTemplateKeyword: true
|
||||||
SpaceBeforeAssignmentOperators: true
|
SpaceBeforeAssignmentOperators: true
|
||||||
|
SpaceBeforeCpp11BracedList: false
|
||||||
|
SpaceBeforeCtorInitializerColon: true
|
||||||
|
SpaceBeforeInheritanceColon: true
|
||||||
SpaceBeforeParens: ControlStatements
|
SpaceBeforeParens: ControlStatements
|
||||||
|
SpaceBeforeRangeBasedForLoopColon: true
|
||||||
SpaceInEmptyParentheses: false
|
SpaceInEmptyParentheses: false
|
||||||
SpacesBeforeTrailingComments: 1
|
SpacesBeforeTrailingComments: 1
|
||||||
SpacesInAngles: false
|
SpacesInAngles: false
|
||||||
|
|||||||
3
.gitmodules
vendored
3
.gitmodules
vendored
@@ -3,4 +3,5 @@
|
|||||||
url = https://github.com/mruby/mruby
|
url = https://github.com/mruby/mruby
|
||||||
[submodule "third-party/neverbleed"]
|
[submodule "third-party/neverbleed"]
|
||||||
path = third-party/neverbleed
|
path = third-party/neverbleed
|
||||||
url = https://github.com/h2o/neverbleed.git
|
url = https://github.com/tatsuhiro-t/neverbleed.git
|
||||||
|
branch = openssl111fix
|
||||||
|
|||||||
26
.travis.yml
26
.travis.yml
@@ -1,3 +1,4 @@
|
|||||||
|
dist: xenial
|
||||||
env:
|
env:
|
||||||
matrix:
|
matrix:
|
||||||
- CI_BUILD=cmake
|
- CI_BUILD=cmake
|
||||||
@@ -6,15 +7,13 @@ language: cpp
|
|||||||
compiler:
|
compiler:
|
||||||
- clang
|
- clang
|
||||||
- gcc
|
- gcc
|
||||||
sudo: false
|
sudo: required
|
||||||
addons:
|
addons:
|
||||||
apt:
|
apt:
|
||||||
sources:
|
sources:
|
||||||
- ubuntu-toolchain-r-test
|
- ubuntu-toolchain-r-test
|
||||||
- george-edison55-precise-backports
|
|
||||||
packages:
|
packages:
|
||||||
- g++-4.9
|
- g++-8
|
||||||
- libstdc++-4.9-dev
|
|
||||||
- autoconf
|
- autoconf
|
||||||
- automake
|
- automake
|
||||||
- autotools-dev
|
- autotools-dev
|
||||||
@@ -33,29 +32,18 @@ addons:
|
|||||||
- cmake-data
|
- cmake-data
|
||||||
before_install:
|
before_install:
|
||||||
- $CC --version
|
- $CC --version
|
||||||
- if [ "$CXX" = "g++" ]; then export CXX="g++-4.9" CC="gcc-4.9"; fi
|
- if [ "$CXX" = "g++" ]; then export CXX="g++-8" CC="gcc-8"; fi
|
||||||
- $CC --version
|
- $CC --version
|
||||||
- go version
|
- go version
|
||||||
- cmake --version
|
- cmake --version
|
||||||
before_script:
|
before_script:
|
||||||
# First build spdylay, since integration tests require it.
|
|
||||||
# spdylay is going to be built under third-party/spdylay
|
|
||||||
- cd third-party
|
|
||||||
- git clone https://github.com/tatsuhiro-t/spdylay.git
|
|
||||||
- cd spdylay
|
|
||||||
- autoreconf -i
|
|
||||||
# Don't use ASAN for spdylay since failmalloc does not work with it.
|
|
||||||
- ./configure --disable-src --disable-examples
|
|
||||||
- make check
|
|
||||||
- export SPDYLAY_HOME=$PWD
|
|
||||||
- cd ../..
|
|
||||||
# Now build nghttp2
|
# Now build nghttp2
|
||||||
- if [ "$CI_BUILD" = "autotools" ]; then autoreconf -i; fi
|
- if [ "$CI_BUILD" = "autotools" ]; then autoreconf -i; fi
|
||||||
- git submodule update --init
|
- git submodule update --init
|
||||||
- if [ "$CI_BUILD" = "autotools" ]; then ./configure --enable-werror --with-mruby --with-neverbleed LIBSPDYLAY_CFLAGS="-I$SPDYLAY_HOME/lib/includes" LIBSPDYLAY_LIBS="-L$SPDYLAY_HOME/lib/.libs -lspdylay" CPPFLAGS=-fsanitize=address LDFLAGS=-fsanitize=address; fi
|
- if [ "$CI_BUILD" = "autotools" ]; then ./configure --with-mruby; fi
|
||||||
- if [ "$CI_BUILD" = "cmake" ]; then cmake -DENABLE_WERROR=1 -DWITH_MRUBY=1 -DWITH_NEVERBLEED=1 -DSPDYLAY_INCLUDE_DIR="$SPDYLAY_HOME/lib/includes" -DSPDYLAY_LIBRARY="$SPDYLAY_HOME/lib/.libs/libspdylay.so"; fi
|
- if [ "$CI_BUILD" = "cmake" ]; then cmake -DENABLE_WERROR=1 -DWITH_MRUBY=1 -DWITH_NEVERBLEED=1; fi
|
||||||
script:
|
script:
|
||||||
- if [ "$CI_BUILD" = "autotools" ]; then make distcheck; fi
|
- if [ "$CI_BUILD" = "autotools" ]; then make distcheck DISTCHECK_CONFIGURE_FLAGS="--with-mruby --with-neverbleed --enable-werror CPPFLAGS=-fsanitize=address LDFLAGS=\"-fsanitize=address -fuse-ld=gold\""; fi
|
||||||
- if [ "$CI_BUILD" = "cmake" ]; then make check; fi
|
- if [ "$CI_BUILD" = "cmake" ]; then make check; fi
|
||||||
# As of April, 23, 2016, golang http2 build fails, probably because
|
# As of April, 23, 2016, golang http2 build fails, probably because
|
||||||
# the default go version is too old.
|
# the default go version is too old.
|
||||||
|
|||||||
24
AUTHORS
24
AUTHORS
@@ -16,35 +16,44 @@ github issues [2].
|
|||||||
187j3x1
|
187j3x1
|
||||||
Alek Storm
|
Alek Storm
|
||||||
Alex Nalivko
|
Alex Nalivko
|
||||||
|
Alexandros Konstantinakis-Karmis
|
||||||
Alexis La Goutte
|
Alexis La Goutte
|
||||||
Amir Pakdel
|
Amir Pakdel
|
||||||
Anders Bakken
|
Anders Bakken
|
||||||
Andreas Pohl
|
Andreas Pohl
|
||||||
Andy Davies
|
Andy Davies
|
||||||
Angus Gratton
|
Angus Gratton
|
||||||
|
Anna Henningsen
|
||||||
Ant Bryan
|
Ant Bryan
|
||||||
Benedikt Christoph Wolters
|
Benedikt Christoph Wolters
|
||||||
Benedikt Christoph Wolters
|
|
||||||
Benjamin Peterson
|
Benjamin Peterson
|
||||||
Bernard Spil
|
Bernard Spil
|
||||||
Bernard Spil
|
Brendan Heinonen
|
||||||
Brian Card
|
Brian Card
|
||||||
Brian Suh
|
Brian Suh
|
||||||
|
Daniel Evers
|
||||||
Daniel Stenberg
|
Daniel Stenberg
|
||||||
Dave Reisner
|
Dave Reisner
|
||||||
David Beitey
|
David Beitey
|
||||||
David Weekly
|
David Weekly
|
||||||
|
Dmitriy Vetutnev
|
||||||
|
Don
|
||||||
|
Dylan Plecki
|
||||||
Etienne Cimon
|
Etienne Cimon
|
||||||
Fabian Möller
|
Fabian Möller
|
||||||
Fabian Wiesel
|
Fabian Wiesel
|
||||||
Gabi Davar
|
Gabi Davar
|
||||||
|
Gitai
|
||||||
Google Inc.
|
Google Inc.
|
||||||
Jacob Champion
|
Jacob Champion
|
||||||
|
Jan Kundrát
|
||||||
Jan-E
|
Jan-E
|
||||||
Janusz Dziemidowicz
|
Janusz Dziemidowicz
|
||||||
Jay Satiro
|
Jay Satiro
|
||||||
|
Jeff 'Raid' Baitis
|
||||||
Jianqing Wang
|
Jianqing Wang
|
||||||
Jim Morrison
|
Jim Morrison
|
||||||
|
Josh Braegger
|
||||||
José F. Calcerrada
|
José F. Calcerrada
|
||||||
Kamil Dudka
|
Kamil Dudka
|
||||||
Kazuho Oku
|
Kazuho Oku
|
||||||
@@ -52,22 +61,29 @@ Kenny (kang-yen) Peng
|
|||||||
Kenny Peng
|
Kenny Peng
|
||||||
Kit Chan
|
Kit Chan
|
||||||
Kyle Schomp
|
Kyle Schomp
|
||||||
|
LazyHamster
|
||||||
Lucas Pardue
|
Lucas Pardue
|
||||||
MATSUMOTO Ryosuke
|
MATSUMOTO Ryosuke
|
||||||
|
Marc Bachmann
|
||||||
Matt Rudary
|
Matt Rudary
|
||||||
Matt Way
|
Matt Way
|
||||||
Mike Conlen
|
Mike Conlen
|
||||||
Mike Frysinger
|
Mike Frysinger
|
||||||
|
Mike Lothian
|
||||||
Nicholas Hurley
|
Nicholas Hurley
|
||||||
Nora Shoemaker
|
Nora Shoemaker
|
||||||
|
Pedro Santos
|
||||||
Peeyush Aggarwal
|
Peeyush Aggarwal
|
||||||
Peter Wu
|
Peter Wu
|
||||||
Piotr Sikora
|
Piotr Sikora
|
||||||
Raul Gutierrez Segales
|
Raul Gutierrez Segales
|
||||||
Remo E
|
Remo E
|
||||||
Reza Tavakoli
|
Reza Tavakoli
|
||||||
|
Rick Lei
|
||||||
Ross Smith II
|
Ross Smith II
|
||||||
Scott Mitchell
|
Scott Mitchell
|
||||||
|
Sebastiaan Deckers
|
||||||
|
Simon Frankenberger
|
||||||
Simone Basso
|
Simone Basso
|
||||||
Soham Sinha
|
Soham Sinha
|
||||||
Stefan Eissing
|
Stefan Eissing
|
||||||
@@ -78,11 +94,13 @@ Syohei YOSHIDA
|
|||||||
Tapanito
|
Tapanito
|
||||||
Tatsuhiko Kubo
|
Tatsuhiko Kubo
|
||||||
Tatsuhiro Tsujikawa
|
Tatsuhiro Tsujikawa
|
||||||
|
Tobias Geerinckx-Rice
|
||||||
Tom Harwood
|
Tom Harwood
|
||||||
Tomasz Buchert
|
Tomasz Buchert
|
||||||
Tomasz Torcz
|
Tomasz Torcz
|
||||||
Vernon Tang
|
Vernon Tang
|
||||||
Viacheslav Biriukov
|
Viacheslav Biriukov
|
||||||
|
Viktor Szakats
|
||||||
Viktor Szépe
|
Viktor Szépe
|
||||||
Wenfeng Liu
|
Wenfeng Liu
|
||||||
Xiaoguang Sun
|
Xiaoguang Sun
|
||||||
@@ -92,8 +110,10 @@ ayanamist
|
|||||||
bxshi
|
bxshi
|
||||||
clemahieu
|
clemahieu
|
||||||
dalf
|
dalf
|
||||||
|
dawg
|
||||||
es
|
es
|
||||||
fangdingjun
|
fangdingjun
|
||||||
|
jwchoi
|
||||||
kumagi
|
kumagi
|
||||||
lstefani
|
lstefani
|
||||||
makovich
|
makovich
|
||||||
|
|||||||
@@ -24,15 +24,15 @@
|
|||||||
|
|
||||||
cmake_minimum_required(VERSION 3.0)
|
cmake_minimum_required(VERSION 3.0)
|
||||||
# XXX using 1.8.90 instead of 1.9.0-DEV
|
# XXX using 1.8.90 instead of 1.9.0-DEV
|
||||||
project(nghttp2 VERSION 1.24.0)
|
project(nghttp2 VERSION 1.38.0)
|
||||||
|
|
||||||
# See versioning rule:
|
# See versioning rule:
|
||||||
# http://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html
|
# http://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html
|
||||||
set(LT_CURRENT 27)
|
set(LT_CURRENT 31)
|
||||||
set(LT_REVISION 3)
|
set(LT_REVISION 3)
|
||||||
set(LT_AGE 13)
|
set(LT_AGE 17)
|
||||||
|
|
||||||
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
|
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH})
|
||||||
include(Version)
|
include(Version)
|
||||||
|
|
||||||
math(EXPR LT_SOVERSION "${LT_CURRENT} - ${LT_AGE}")
|
math(EXPR LT_SOVERSION "${LT_CURRENT} - ${LT_AGE}")
|
||||||
@@ -79,7 +79,7 @@ else()
|
|||||||
set(ENABLE_PYTHON_BINDINGS_DEFAULT OFF)
|
set(ENABLE_PYTHON_BINDINGS_DEFAULT OFF)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
find_package(LibXml2 2.7.7)
|
find_package(LibXml2 2.6.26)
|
||||||
set(WITH_LIBXML2_DEFAULT ${LIBXML2_FOUND})
|
set(WITH_LIBXML2_DEFAULT ${LIBXML2_FOUND})
|
||||||
find_package(Jemalloc)
|
find_package(Jemalloc)
|
||||||
set(WITH_JEMALLOC_DEFAULT ${JEMALLOC_FOUND})
|
set(WITH_JEMALLOC_DEFAULT ${JEMALLOC_FOUND})
|
||||||
@@ -106,7 +106,7 @@ endif()
|
|||||||
foreach(_build_type "Release" "MinSizeRel" "RelWithDebInfo")
|
foreach(_build_type "Release" "MinSizeRel" "RelWithDebInfo")
|
||||||
foreach(_lang C CXX)
|
foreach(_lang C CXX)
|
||||||
string(TOUPPER "CMAKE_${_lang}_FLAGS_${_build_type}" _var)
|
string(TOUPPER "CMAKE_${_lang}_FLAGS_${_build_type}" _var)
|
||||||
string(REGEX REPLACE "(^| )[/-]D *NDEBUG($| )" "" ${_var} "${${_var}}")
|
string(REGEX REPLACE "(^| )[/-]D *NDEBUG($| )" " " ${_var} "${${_var}}")
|
||||||
endforeach()
|
endforeach()
|
||||||
endforeach()
|
endforeach()
|
||||||
|
|
||||||
@@ -117,7 +117,7 @@ else()
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
include(ExtractValidFlags)
|
include(ExtractValidFlags)
|
||||||
foreach(_cxx1x_flag -std=c++11 -std=c++0x)
|
foreach(_cxx1x_flag -std=c++14)
|
||||||
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})
|
||||||
@@ -302,6 +302,7 @@ check_type_size("time_t" SIZEOF_TIME_T)
|
|||||||
include(CheckFunctionExists)
|
include(CheckFunctionExists)
|
||||||
check_function_exists(_Exit HAVE__EXIT)
|
check_function_exists(_Exit HAVE__EXIT)
|
||||||
check_function_exists(accept4 HAVE_ACCEPT4)
|
check_function_exists(accept4 HAVE_ACCEPT4)
|
||||||
|
check_function_exists(mkostemp HAVE_MKOSTEMP)
|
||||||
|
|
||||||
include(CheckSymbolExists)
|
include(CheckSymbolExists)
|
||||||
# XXX does this correctly detect initgroups (un)availability on cygwin?
|
# XXX does this correctly detect initgroups (un)availability on cygwin?
|
||||||
|
|||||||
@@ -14,6 +14,8 @@ option(ENABLE_PYTHON_BINDINGS "Build Python bindings"
|
|||||||
${ENABLE_PYTHON_BINDINGS_DEFAULT})
|
${ENABLE_PYTHON_BINDINGS_DEFAULT})
|
||||||
option(ENABLE_FAILMALLOC "Build failmalloc test program" ON)
|
option(ENABLE_FAILMALLOC "Build failmalloc test program" ON)
|
||||||
option(ENABLE_LIB_ONLY "Build libnghttp2 only. This is a short hand for -DENABLE_APP=0 -DENABLE_EXAMPLES=0 -DENABLE_HPACK_TOOLS=0 -DENABLE_PYTHON_BINDINGS=0")
|
option(ENABLE_LIB_ONLY "Build libnghttp2 only. This is a short hand for -DENABLE_APP=0 -DENABLE_EXAMPLES=0 -DENABLE_HPACK_TOOLS=0 -DENABLE_PYTHON_BINDINGS=0")
|
||||||
|
option(ENABLE_STATIC_LIB "Build libnghttp2 in static mode also")
|
||||||
|
option(ENABLE_SHARED_LIB "Build libnghttp2 as a shared library" ON)
|
||||||
|
|
||||||
option(WITH_LIBXML2 "Use libxml2"
|
option(WITH_LIBXML2 "Use libxml2"
|
||||||
${WITH_LIBXML2_DEFAULT})
|
${WITH_LIBXML2_DEFAULT})
|
||||||
|
|||||||
@@ -10,39 +10,47 @@
|
|||||||
#
|
#
|
||||||
# $ sudo docker run -v /path/to/dest:/out nghttp2-android cp /root/build/nghttp2/src/nghttpx /out
|
# $ sudo docker run -v /path/to/dest:/out nghttp2-android cp /root/build/nghttp2/src/nghttpx /out
|
||||||
|
|
||||||
FROM ubuntu:vivid
|
|
||||||
|
|
||||||
|
# Only use standalone-toolchain for reduce size
|
||||||
|
FROM ubuntu:xenial
|
||||||
MAINTAINER Tatsuhiro Tsujikawa
|
MAINTAINER Tatsuhiro Tsujikawa
|
||||||
|
ENV ANDROID_HOME /root
|
||||||
ENV ANDROID_HOME /root/android
|
|
||||||
ENV PREFIX $ANDROID_HOME/usr/local
|
|
||||||
ENV TOOLCHAIN $ANDROID_HOME/toolchain
|
ENV TOOLCHAIN $ANDROID_HOME/toolchain
|
||||||
ENV PATH $TOOLCHAIN/bin:$PATH
|
ENV PATH $TOOLCHAIN/bin:$PATH
|
||||||
|
|
||||||
# It would be better to use nearest ubuntu archive mirror for faster
|
ENV NDK_VERSION r14b
|
||||||
# downloads.
|
|
||||||
# RUN sed -ie 's/archive\.ubuntu/jp.archive.ubuntu/g' /etc/apt/sources.list
|
|
||||||
|
|
||||||
RUN apt-get update
|
WORKDIR /root
|
||||||
# genisoimage, libc6-i386 and lib32stdc++6 are required to decompress ndk.
|
RUN apt-get update && \
|
||||||
RUN apt-get install -y make binutils autoconf automake autotools-dev libtool \
|
apt-get install -y unzip make binutils autoconf \
|
||||||
pkg-config git curl dpkg-dev libxml2-dev \
|
automake autotools-dev libtool pkg-config git \
|
||||||
genisoimage libc6-i386 lib32stdc++6
|
curl dpkg-dev libxml2-dev genisoimage libc6-i386 \
|
||||||
|
lib32stdc++6 python&& \
|
||||||
|
rm -rf /var/cache/apk/*
|
||||||
|
|
||||||
|
# Install toolchain
|
||||||
|
RUN curl -L -O https://dl.google.com/android/repository/android-ndk-$NDK_VERSION-linux-x86_64.zip && \
|
||||||
|
unzip -q android-ndk-$NDK_VERSION-linux-x86_64.zip && \
|
||||||
|
rm android-ndk-$NDK_VERSION-linux-x86_64.zip && \
|
||||||
|
mkdir -p $ANDROID_HOME/toolchain && \
|
||||||
|
$ANDROID_HOME/android-ndk-$NDK_VERSION/build/tools/make-standalone-toolchain.sh \
|
||||||
|
--install-dir=$ANDROID_HOME/toolchain \
|
||||||
|
--toolchain=arm-linux-androideabi-4.9 \
|
||||||
|
--force && \
|
||||||
|
rm -r android-ndk-$NDK_VERSION
|
||||||
|
|
||||||
|
ENV PREFIX /root/usr/local
|
||||||
|
|
||||||
|
# Setup version of libraries
|
||||||
|
ENV OPENSSL_VERSION 1.0.2d
|
||||||
|
ENV SPDYLAY_VERSION v1.4.0
|
||||||
|
ENV LIBEV_VERSION 4.19
|
||||||
|
ENV ZLIB_VERSION 1.2.8
|
||||||
|
ENV CARES_VERSION 1.13.0
|
||||||
|
ENV NGHTTP2_VERSION v1.24.0
|
||||||
|
|
||||||
WORKDIR /root/build
|
WORKDIR /root/build
|
||||||
RUN curl -L -O http://dl.google.com/android/ndk/android-ndk-r10d-linux-x86_64.bin && \
|
RUN git clone https://github.com/tatsuhiro-t/spdylay -b $SPDYLAY_VERSION --depth 1
|
||||||
chmod a+x android-ndk-r10d-linux-x86_64.bin && \
|
|
||||||
./android-ndk-r10d-linux-x86_64.bin && \
|
|
||||||
rm android-ndk-r10d-linux-x86_64.bin
|
|
||||||
|
|
||||||
WORKDIR /root/build/android-ndk-r10d
|
|
||||||
RUN /bin/bash build/tools/make-standalone-toolchain.sh \
|
|
||||||
--install-dir=$ANDROID_HOME/toolchain \
|
|
||||||
--toolchain=arm-linux-androideabi-4.9 --llvm-version=3.5 \
|
|
||||||
--system=linux-x86_64
|
|
||||||
|
|
||||||
WORKDIR /root/build
|
|
||||||
RUN git clone https://github.com/tatsuhiro-t/spdylay
|
|
||||||
WORKDIR /root/build/spdylay
|
WORKDIR /root/build/spdylay
|
||||||
RUN autoreconf -i && \
|
RUN autoreconf -i && \
|
||||||
./configure \
|
./configure \
|
||||||
@@ -59,22 +67,22 @@ RUN autoreconf -i && \
|
|||||||
make install
|
make install
|
||||||
|
|
||||||
WORKDIR /root/build
|
WORKDIR /root/build
|
||||||
RUN curl -L -O https://www.openssl.org/source/openssl-1.0.2d.tar.gz && \
|
RUN curl -L -O https://www.openssl.org/source/openssl-$OPENSSL_VERSION.tar.gz && \
|
||||||
tar xf openssl-1.0.2d.tar.gz && \
|
tar xf openssl-$OPENSSL_VERSION.tar.gz && \
|
||||||
rm openssl-1.0.2d.tar.gz
|
rm openssl-$OPENSSL_VERSION.tar.gz
|
||||||
|
|
||||||
WORKDIR /root/build/openssl-1.0.2d
|
WORKDIR /root/build/openssl-$OPENSSL_VERSION
|
||||||
RUN export CROSS_COMPILE=$TOOLCHAIN/bin/arm-linux-androideabi- && \
|
RUN export CROSS_COMPILE=$TOOLCHAIN/bin/arm-linux-androideabi- && \
|
||||||
./Configure --prefix=$PREFIX android && \
|
./Configure --prefix=$PREFIX android && \
|
||||||
make && make install_sw
|
make && make install_sw
|
||||||
|
|
||||||
WORKDIR /root/build
|
WORKDIR /root/build
|
||||||
RUN curl -L -O http://dist.schmorp.de/libev/libev-4.19.tar.gz && \
|
RUN curl -L -O http://dist.schmorp.de/libev/Attic/libev-$LIBEV_VERSION.tar.gz && \
|
||||||
curl -L -O https://gist.github.com/tatsuhiro-t/48c45f08950f587180ed/raw/80a8f003b5d1091eae497c5995bbaa68096e739b/libev-4.19-android.patch && \
|
curl -L -O https://gist.github.com/tatsuhiro-t/48c45f08950f587180ed/raw/80a8f003b5d1091eae497c5995bbaa68096e739b/libev-4.19-android.patch && \
|
||||||
tar xf libev-4.19.tar.gz && \
|
tar xf libev-$LIBEV_VERSION.tar.gz && \
|
||||||
rm libev-4.19.tar.gz
|
rm libev-$LIBEV_VERSION.tar.gz
|
||||||
|
|
||||||
WORKDIR /root/build/libev-4.19
|
WORKDIR /root/build/libev-$LIBEV_VERSION
|
||||||
RUN patch -p1 < ../libev-4.19-android.patch && \
|
RUN patch -p1 < ../libev-4.19-android.patch && \
|
||||||
./configure \
|
./configure \
|
||||||
--host=arm-linux-androideabi \
|
--host=arm-linux-androideabi \
|
||||||
@@ -87,11 +95,11 @@ RUN patch -p1 < ../libev-4.19-android.patch && \
|
|||||||
make install
|
make install
|
||||||
|
|
||||||
WORKDIR /root/build
|
WORKDIR /root/build
|
||||||
RUN curl -L -O http://zlib.net/zlib-1.2.8.tar.gz && \
|
RUN curl -L -O https://downloads.sourceforge.net/project/libpng/zlib/$ZLIB_VERSION/zlib-$ZLIB_VERSION.tar.gz && \
|
||||||
tar xf zlib-1.2.8.tar.gz && \
|
tar xf zlib-$ZLIB_VERSION.tar.gz && \
|
||||||
rm zlib-1.2.8.tar.gz
|
rm zlib-$ZLIB_VERSION.tar.gz
|
||||||
|
|
||||||
WORKDIR /root/build/zlib-1.2.8
|
WORKDIR /root/build/zlib-$ZLIB_VERSION
|
||||||
RUN HOST=arm-linux-androideabi \
|
RUN HOST=arm-linux-androideabi \
|
||||||
CC=$HOST-gcc \
|
CC=$HOST-gcc \
|
||||||
AR=$HOST-ar \
|
AR=$HOST-ar \
|
||||||
@@ -105,11 +113,26 @@ RUN HOST=arm-linux-androideabi \
|
|||||||
--static && \
|
--static && \
|
||||||
make install
|
make install
|
||||||
|
|
||||||
|
|
||||||
WORKDIR /root/build
|
WORKDIR /root/build
|
||||||
RUN git clone https://github.com/nghttp2/nghttp2
|
RUN curl -L -O https://c-ares.haxx.se/download/c-ares-$CARES_VERSION.tar.gz && \
|
||||||
|
tar xf c-ares-$CARES_VERSION.tar.gz && \
|
||||||
|
rm c-ares-$CARES_VERSION.tar.gz
|
||||||
|
|
||||||
|
WORKDIR /root/build/c-ares-$CARES_VERSION
|
||||||
|
RUN ./configure \
|
||||||
|
--host=arm-linux-androideabi \
|
||||||
|
--build=`dpkg-architecture -qDEB_BUILD_GNU_TYPE` \
|
||||||
|
--prefix=$PREFIX \
|
||||||
|
--disable-shared && \
|
||||||
|
make install
|
||||||
|
|
||||||
|
WORKDIR /root/build
|
||||||
|
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 \
|
||||||
|
--enable-app \
|
||||||
--disable-shared \
|
--disable-shared \
|
||||||
--host=arm-linux-androideabi \
|
--host=arm-linux-androideabi \
|
||||||
--build=`dpkg-architecture -qDEB_BUILD_GNU_TYPE` \
|
--build=`dpkg-architecture -qDEB_BUILD_GNU_TYPE` \
|
||||||
@@ -118,11 +141,10 @@ RUN autoreconf -i && \
|
|||||||
--disable-python-bindings \
|
--disable-python-bindings \
|
||||||
--disable-examples \
|
--disable-examples \
|
||||||
--disable-threads \
|
--disable-threads \
|
||||||
LIBSPDYLAY_CFLAGS=-I$PREFIX/usr/local/include \
|
CC="$TOOLCHAIN"/bin/arm-linux-androideabi-clang \
|
||||||
LIBSPDYLAY_LIBS="-L$PREFIX/usr/local/lib -lspdylay" \
|
CXX="$TOOLCHAIN"/bin/arm-linux-androideabi-clang++ \
|
||||||
CPPFLAGS="-fPIE -I$PREFIX/include" \
|
CPPFLAGS="-fPIE -I$PREFIX/include" \
|
||||||
CXXFLAGS="-fno-strict-aliasing" \
|
PKG_CONFIG_LIBDIR="$PREFIX/lib/pkgconfig" \
|
||||||
PKG_CONFIG_LIBDIR="$PREFIX/lib/pkgconfig" \
|
LDFLAGS="-fPIE -pie -L$PREFIX/lib" && \
|
||||||
LDFLAGS="-fPIE -pie -L$PREFIX/lib" && \
|
|
||||||
make && \
|
make && \
|
||||||
arm-linux-androideabi-strip src/nghttpx src/nghttpd src/nghttp
|
arm-linux-androideabi-strip src/nghttpx src/nghttpd src/nghttp
|
||||||
|
|||||||
94
README.rst
94
README.rst
@@ -4,10 +4,10 @@ nghttp2 - HTTP/2 C Library
|
|||||||
This is an implementation of the Hypertext Transfer Protocol version 2
|
This is an implementation of the Hypertext Transfer Protocol version 2
|
||||||
in C.
|
in C.
|
||||||
|
|
||||||
The framing layer of HTTP/2 is implemented as a reusable C
|
The framing layer of HTTP/2 is implemented as a reusable C library.
|
||||||
library. On top of that, we have implemented an HTTP/2 client, server
|
On top of that, we have implemented an HTTP/2 client, server and
|
||||||
and proxy. We have also developed load test and benchmarking tools for
|
proxy. We have also developed load test and benchmarking tools for
|
||||||
HTTP/2 and SPDY.
|
HTTP/2.
|
||||||
|
|
||||||
An HPACK encoder and decoder are available as a public API.
|
An HPACK encoder and decoder are available as a public API.
|
||||||
|
|
||||||
@@ -34,8 +34,8 @@ implementation.
|
|||||||
|
|
||||||
* https://nghttp2.org/ (TLS + ALPN/NPN)
|
* https://nghttp2.org/ (TLS + ALPN/NPN)
|
||||||
|
|
||||||
This endpoint supports ``h2``, ``h2-16``, ``h2-14``, ``spdy/3.1``
|
This endpoint supports ``h2``, ``h2-16``, ``h2-14``, and
|
||||||
and ``http/1.1`` via ALPN/NPN and requires TLSv1.2 for HTTP/2
|
``http/1.1`` via ALPN/NPN and requires TLSv1.2 for HTTP/2
|
||||||
connection.
|
connection.
|
||||||
|
|
||||||
* http://nghttp2.org/ (HTTP Upgrade and HTTP/2 Direct)
|
* http://nghttp2.org/ (HTTP Upgrade and HTTP/2 Direct)
|
||||||
@@ -76,18 +76,10 @@ ALPN support requires OpenSSL >= 1.0.2 (released 22 January 2015).
|
|||||||
LibreSSL >= 2.2.0 can be used instead of OpenSSL, but OpenSSL has more
|
LibreSSL >= 2.2.0 can be used instead of OpenSSL, but OpenSSL has more
|
||||||
features than LibreSSL at the time of this writing.
|
features than LibreSSL at the time of this writing.
|
||||||
|
|
||||||
To enable the SPDY protocol in the application program ``nghttpx`` and
|
|
||||||
``h2load``, the following package is required:
|
|
||||||
|
|
||||||
* spdylay >= 1.3.2
|
|
||||||
|
|
||||||
We no longer recommend to build nghttp2 with SPDY protocol support
|
|
||||||
enabled. SPDY support will be removed soon.
|
|
||||||
|
|
||||||
To enable ``-a`` option (getting linked assets from the downloaded
|
To enable ``-a`` option (getting linked assets from the downloaded
|
||||||
resource) in ``nghttp``, the following package is required:
|
resource) in ``nghttp``, the following package is required:
|
||||||
|
|
||||||
* libxml2 >= 2.7.7
|
* libxml2 >= 2.6.26
|
||||||
|
|
||||||
To enable systemd support in nghttpx, the following package is
|
To enable systemd support in nghttpx, the following package is
|
||||||
required:
|
required:
|
||||||
@@ -130,13 +122,9 @@ and above, run the following to install the required packages:
|
|||||||
|
|
||||||
sudo apt-get install g++ make binutils autoconf automake autotools-dev libtool pkg-config \
|
sudo apt-get install g++ make binutils autoconf automake autotools-dev libtool pkg-config \
|
||||||
zlib1g-dev libcunit1-dev libssl-dev libxml2-dev libev-dev libevent-dev libjansson-dev \
|
zlib1g-dev libcunit1-dev libssl-dev libxml2-dev libev-dev libevent-dev libjansson-dev \
|
||||||
libc-ares-dev libjemalloc-dev libsystemd-dev libspdylay-dev \
|
libc-ares-dev libjemalloc-dev libsystemd-dev \
|
||||||
cython python3-dev python-setuptools
|
cython python3-dev python-setuptools
|
||||||
|
|
||||||
Since Ubuntu 15.10, spdylay has been available as a package named
|
|
||||||
`libspdylay-dev`. For the earlier Ubuntu release, you need to build
|
|
||||||
it yourself: http://tatsuhiro-t.github.io/spdylay/
|
|
||||||
|
|
||||||
To enable mruby support for nghttpx, `mruby
|
To enable mruby support for nghttpx, `mruby
|
||||||
<https://github.com/mruby/mruby>`_ is required. We need to build
|
<https://github.com/mruby/mruby>`_ is required. We need to build
|
||||||
mruby with C++ ABI explicitly turned on, and probably need other
|
mruby with C++ ABI explicitly turned on, and probably need other
|
||||||
@@ -157,8 +145,10 @@ minimizes the risk of private key leakage when serious bug like
|
|||||||
Heartbleed is exploited. The neverbleed is disabled by default. To
|
Heartbleed is exploited. The neverbleed is disabled by default. To
|
||||||
enable it, use ``--with-neverbleed`` configure option.
|
enable it, use ``--with-neverbleed`` configure option.
|
||||||
|
|
||||||
In order to compile the source code, gcc >= 4.8.3 or clang >= 3.4 is
|
Compiling libnghttp2 C source code requires a C99 compiler. gcc 4.8
|
||||||
required.
|
is known to be adequate. In order to compile the C++ source code, gcc
|
||||||
|
>= 6.0 or clang >= 6.0 is required. C++ source code requires C++14
|
||||||
|
language features.
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|
|
||||||
@@ -332,7 +322,6 @@ its testing framework. We depend on the following libraries:
|
|||||||
* golang.org/x/net/http2
|
* golang.org/x/net/http2
|
||||||
* golang.org/x/net/websocket
|
* golang.org/x/net/websocket
|
||||||
* https://github.com/tatsuhiro-t/go-nghttp2
|
* https://github.com/tatsuhiro-t/go-nghttp2
|
||||||
* https://github.com/tatsuhiro-t/spdy
|
|
||||||
|
|
||||||
To download the above packages, after settings ``GOPATH``, run the
|
To download the above packages, after settings ``GOPATH``, run the
|
||||||
following command under ``integration-tests`` directory:
|
following command under ``integration-tests`` directory:
|
||||||
@@ -350,11 +339,6 @@ To run the tests, run the following command under
|
|||||||
|
|
||||||
Inside the tests, we use port 3009 to run the test subject server.
|
Inside the tests, we use port 3009 to run the test subject server.
|
||||||
|
|
||||||
.. note::
|
|
||||||
|
|
||||||
github.com/tatsuhiro-t/spdy is a copy used to be available at
|
|
||||||
golang.org/x/net/spdy, but it is now gone.
|
|
||||||
|
|
||||||
Migration from v0.7.15 or earlier
|
Migration from v0.7.15 or earlier
|
||||||
---------------------------------
|
---------------------------------
|
||||||
|
|
||||||
@@ -755,7 +739,7 @@ information. Here is sample output from ``nghttpd``:
|
|||||||
nghttpx - proxy
|
nghttpx - proxy
|
||||||
+++++++++++++++
|
+++++++++++++++
|
||||||
|
|
||||||
``nghttpx`` is a multi-threaded reverse proxy for HTTP/2, SPDY and
|
``nghttpx`` is a multi-threaded reverse proxy for HTTP/2, and
|
||||||
HTTP/1.1, and powers http://nghttp2.org and supports HTTP/2 server
|
HTTP/1.1, and powers http://nghttp2.org and supports HTTP/2 server
|
||||||
push.
|
push.
|
||||||
|
|
||||||
@@ -770,31 +754,30 @@ 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), OCSP
|
session IDs, session tickets (with automatic key rotation), OCSP
|
||||||
stapling, dynamic record sizing, ALPN/NPN, forward secrecy and SPDY &
|
stapling, dynamic record sizing, ALPN/NPN, forward secrecy and HTTP/2.
|
||||||
HTTP/2. ``nghttpx`` also offers the functionality to share session
|
``nghttpx`` also offers the functionality to share session cache and
|
||||||
cache and ticket keys among multiple ``nghttpx`` instances via
|
ticket keys among multiple ``nghttpx`` instances via memcached.
|
||||||
memcached.
|
|
||||||
|
|
||||||
``nghttpx`` has 2 operation modes:
|
``nghttpx`` has 2 operation modes:
|
||||||
|
|
||||||
================== ====================== ================ =============
|
================== ================ ================ =============
|
||||||
Mode option Frontend Backend Note
|
Mode option Frontend Backend Note
|
||||||
================== ====================== ================ =============
|
================== ================ ================ =============
|
||||||
default mode HTTP/2, SPDY, HTTP/1.1 HTTP/1.1, HTTP/2 Reverse proxy
|
default mode HTTP/2, HTTP/1.1 HTTP/1.1, HTTP/2 Reverse proxy
|
||||||
``--http2-proxy`` HTTP/2, SPDY, HTTP/1.1 HTTP/1.1, HTTP/2 Forward proxy
|
``--http2-proxy`` HTTP/2, HTTP/1.1 HTTP/1.1, HTTP/2 Forward proxy
|
||||||
================== ====================== ================ =============
|
================== ================ ================ =============
|
||||||
|
|
||||||
The interesting mode at the moment is the default mode. It works like
|
The interesting mode at the moment is the default mode. It works like
|
||||||
a reverse proxy and listens for HTTP/2, SPDY and HTTP/1.1 and can be
|
a reverse proxy and listens for HTTP/2, and HTTP/1.1 and can be
|
||||||
deployed as a SSL/TLS terminator for existing web server.
|
deployed as a SSL/TLS terminator for existing web server.
|
||||||
|
|
||||||
In all modes, the frontend connections are encrypted by SSL/TLS by
|
In all modes, the frontend connections are encrypted by SSL/TLS by
|
||||||
default. To disable encryption, use the ``no-tls`` keyword in
|
default. To disable encryption, use the ``no-tls`` keyword in
|
||||||
``--frontend`` option. If encryption is disabled, SPDY is disabled in
|
``--frontend`` option. If encryption is disabled, incoming HTTP/1.1
|
||||||
the frontend and incoming HTTP/1.1 connections can be upgraded to
|
connections can be upgraded to HTTP/2 through HTTP Upgrade. On the
|
||||||
HTTP/2 through HTTP Upgrade. On the other hard, backend connections
|
other hard, backend connections are not encrypted by default. To
|
||||||
are not encrypted by default. To encrypt backend connections, use
|
encrypt backend connections, use ``tls`` keyword in ``--backend``
|
||||||
``tls`` keyword in ``--backend`` option.
|
option.
|
||||||
|
|
||||||
``nghttpx`` supports a configuration file. See the ``--conf`` option and
|
``nghttpx`` supports a configuration file. See the ``--conf`` option and
|
||||||
sample configuration file ``nghttpx.conf.sample``.
|
sample configuration file ``nghttpx.conf.sample``.
|
||||||
@@ -804,16 +787,16 @@ server:
|
|||||||
|
|
||||||
.. code-block:: text
|
.. code-block:: text
|
||||||
|
|
||||||
Client <-- (HTTP/2, SPDY, HTTP/1.1) --> nghttpx <-- (HTTP/1.1, HTTP/2) --> Web Server
|
Client <-- (HTTP/2, HTTP/1.1) --> nghttpx <-- (HTTP/1.1, HTTP/2) --> Web Server
|
||||||
[reverse proxy]
|
[reverse proxy]
|
||||||
|
|
||||||
With the ``--http2-proxy`` option, it works as forward proxy, and it
|
With the ``--http2-proxy`` option, it works as forward proxy, and it
|
||||||
is so called secure HTTP/2 proxy (aka SPDY proxy):
|
is so called secure HTTP/2 proxy:
|
||||||
|
|
||||||
.. code-block:: text
|
.. code-block:: text
|
||||||
|
|
||||||
Client <-- (HTTP/2, SPDY, HTTP/1.1) --> nghttpx <-- (HTTP/1.1) --> Proxy
|
Client <-- (HTTP/2, HTTP/1.1) --> nghttpx <-- (HTTP/1.1) --> Proxy
|
||||||
[secure proxy] (e.g., Squid, ATS)
|
[secure proxy] (e.g., Squid, ATS)
|
||||||
|
|
||||||
The ``Client`` in the above example needs to be configured to use
|
The ``Client`` in the above example needs to be configured to use
|
||||||
``nghttpx`` as secure proxy.
|
``nghttpx`` as secure proxy.
|
||||||
@@ -845,7 +828,7 @@ proxy through an HTTP proxy:
|
|||||||
|
|
||||||
.. code-block:: text
|
.. code-block:: text
|
||||||
|
|
||||||
Client <-- (HTTP/2, SPDY, HTTP/1.1) --> nghttpx <-- (HTTP/2) --
|
Client <-- (HTTP/2, HTTP/1.1) --> nghttpx <-- (HTTP/2) --
|
||||||
|
|
||||||
--===================---> HTTP/2 Proxy
|
--===================---> HTTP/2 Proxy
|
||||||
(HTTP proxy tunnel) (e.g., nghttpx -s)
|
(HTTP proxy tunnel) (e.g., nghttpx -s)
|
||||||
@@ -853,9 +836,8 @@ proxy through an HTTP proxy:
|
|||||||
Benchmarking tool
|
Benchmarking tool
|
||||||
-----------------
|
-----------------
|
||||||
|
|
||||||
The ``h2load`` program is a benchmarking tool for HTTP/2 and SPDY.
|
The ``h2load`` program is a benchmarking tool for HTTP/2. The UI of
|
||||||
The SPDY support is enabled if the program was built with the spdylay
|
``h2load`` is heavily inspired by ``weighttp``
|
||||||
library. The UI of ``h2load`` is heavily inspired by ``weighttp``
|
|
||||||
(https://github.com/lighttpd/weighttp). The typical usage is as
|
(https://github.com/lighttpd/weighttp). The typical usage is as
|
||||||
follows:
|
follows:
|
||||||
|
|
||||||
@@ -971,7 +953,7 @@ output_length
|
|||||||
The length of the compressed header block.
|
The length of the compressed header block.
|
||||||
|
|
||||||
percentage_of_original_size
|
percentage_of_original_size
|
||||||
``input_length`` / ``output_length`` * 100
|
``output_length`` / ``input_length`` * 100
|
||||||
|
|
||||||
wire
|
wire
|
||||||
The compressed header block as a hex string.
|
The compressed header block as a hex string.
|
||||||
@@ -1352,7 +1334,7 @@ are:
|
|||||||
* Boost::Thread
|
* Boost::Thread
|
||||||
|
|
||||||
The server API is designed to build an HTTP/2 server very easily to utilize
|
The server API is designed to build an HTTP/2 server very easily to utilize
|
||||||
C++11 anonymous functions and closures. The bare minimum example of
|
C++14 anonymous functions and closures. The bare minimum example of
|
||||||
an HTTP/2 server looks like this:
|
an HTTP/2 server looks like this:
|
||||||
|
|
||||||
.. code-block:: cpp
|
.. code-block:: cpp
|
||||||
|
|||||||
@@ -40,6 +40,9 @@ if(LIBEVENT_INCLUDE_DIR)
|
|||||||
# Libevent 2.0
|
# Libevent 2.0
|
||||||
file(STRINGS "${LIBEVENT_INCLUDE_DIR}/event2/event-config.h"
|
file(STRINGS "${LIBEVENT_INCLUDE_DIR}/event2/event-config.h"
|
||||||
LIBEVENT_VERSION REGEX "${_version_regex}")
|
LIBEVENT_VERSION REGEX "${_version_regex}")
|
||||||
|
if("${LIBEVENT_VERSION}" STREQUAL "")
|
||||||
|
set(LIBEVENT_VERSION ${PC_LIBEVENT_VERSION})
|
||||||
|
endif()
|
||||||
else()
|
else()
|
||||||
# Libevent 1.4
|
# Libevent 1.4
|
||||||
file(STRINGS "${LIBEVENT_INCLUDE_DIR}/event-config.h"
|
file(STRINGS "${LIBEVENT_INCLUDE_DIR}/event-config.h"
|
||||||
|
|||||||
@@ -34,6 +34,9 @@
|
|||||||
/* Define to 1 if you have the `accept4` function. */
|
/* Define to 1 if you have the `accept4` function. */
|
||||||
#cmakedefine HAVE_ACCEPT4 1
|
#cmakedefine HAVE_ACCEPT4 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `mkostemp` function. */
|
||||||
|
#cmakedefine HAVE_MKOSTEMP 1
|
||||||
|
|
||||||
/* Define to 1 if you have the `initgroups` function. */
|
/* Define to 1 if you have the `initgroups` function. */
|
||||||
#cmakedefine01 HAVE_DECL_INITGROUPS
|
#cmakedefine01 HAVE_DECL_INITGROUPS
|
||||||
|
|
||||||
|
|||||||
40
configure.ac
40
configure.ac
@@ -25,7 +25,7 @@ dnl Do not change user variables!
|
|||||||
dnl http://www.gnu.org/software/automake/manual/html_node/Flag-Variables-Ordering.html
|
dnl http://www.gnu.org/software/automake/manual/html_node/Flag-Variables-Ordering.html
|
||||||
|
|
||||||
AC_PREREQ(2.61)
|
AC_PREREQ(2.61)
|
||||||
AC_INIT([nghttp2], [1.24.0], [t-tujikawa@users.sourceforge.net])
|
AC_INIT([nghttp2], [1.38.0], [t-tujikawa@users.sourceforge.net])
|
||||||
AC_CONFIG_AUX_DIR([.])
|
AC_CONFIG_AUX_DIR([.])
|
||||||
AC_CONFIG_MACRO_DIR([m4])
|
AC_CONFIG_MACRO_DIR([m4])
|
||||||
AC_CONFIG_HEADERS([config.h])
|
AC_CONFIG_HEADERS([config.h])
|
||||||
@@ -44,9 +44,9 @@ m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
|
|||||||
|
|
||||||
dnl See versioning rule:
|
dnl See versioning rule:
|
||||||
dnl http://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html
|
dnl http://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html
|
||||||
AC_SUBST(LT_CURRENT, 27)
|
AC_SUBST(LT_CURRENT, 31)
|
||||||
AC_SUBST(LT_REVISION, 3)
|
AC_SUBST(LT_REVISION, 3)
|
||||||
AC_SUBST(LT_AGE, 13)
|
AC_SUBST(LT_AGE, 17)
|
||||||
|
|
||||||
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"`
|
||||||
@@ -117,11 +117,6 @@ AC_ARG_WITH([jemalloc],
|
|||||||
[Use jemalloc [default=check]])],
|
[Use jemalloc [default=check]])],
|
||||||
[request_jemalloc=$withval], [request_jemalloc=check])
|
[request_jemalloc=$withval], [request_jemalloc=check])
|
||||||
|
|
||||||
AC_ARG_WITH([spdylay],
|
|
||||||
[AS_HELP_STRING([--with-spdylay],
|
|
||||||
[Use spdylay [default=no]])],
|
|
||||||
[request_spdylay=$withval], [request_spdylay=no])
|
|
||||||
|
|
||||||
AC_ARG_WITH([systemd],
|
AC_ARG_WITH([systemd],
|
||||||
[AS_HELP_STRING([--with-systemd],
|
[AS_HELP_STRING([--with-systemd],
|
||||||
[Enable systemd support in nghttpx [default=check]])],
|
[Enable systemd support in nghttpx [default=check]])],
|
||||||
@@ -185,7 +180,7 @@ fi
|
|||||||
save_CXXFLAGS="$CXXFLAGS"
|
save_CXXFLAGS="$CXXFLAGS"
|
||||||
CXXFLAGS=
|
CXXFLAGS=
|
||||||
|
|
||||||
AX_CXX_COMPILE_STDCXX_11([noext], [optional])
|
AX_CXX_COMPILE_STDCXX([14], [noext], [optional])
|
||||||
|
|
||||||
CXX1XCXXFLAGS="$CXXFLAGS"
|
CXX1XCXXFLAGS="$CXXFLAGS"
|
||||||
CXXFLAGS="$save_CXXFLAGS"
|
CXXFLAGS="$save_CXXFLAGS"
|
||||||
@@ -410,7 +405,7 @@ if test "x${request_systemd}" = "xyes" &&
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# libxml2 (for src/nghttp)
|
# libxml2 (for src/nghttp)
|
||||||
PKG_CHECK_MODULES([LIBXML2], [libxml-2.0 >= 2.7.7],
|
PKG_CHECK_MODULES([LIBXML2], [libxml-2.0 >= 2.6.26],
|
||||||
[have_libxml2=yes], [have_libxml2=no])
|
[have_libxml2=yes], [have_libxml2=no])
|
||||||
if test "x${have_libxml2}" = "xyes"; then
|
if test "x${have_libxml2}" = "xyes"; then
|
||||||
AC_DEFINE([HAVE_LIBXML2], [1], [Define to 1 if you have `libxml2` library.])
|
AC_DEFINE([HAVE_LIBXML2], [1], [Define to 1 if you have `libxml2` library.])
|
||||||
@@ -458,26 +453,6 @@ if test "x${request_jemalloc}" = "xyes" &&
|
|||||||
AC_MSG_ERROR([jemalloc was requested (--with-jemalloc) but not found])
|
AC_MSG_ERROR([jemalloc was requested (--with-jemalloc) but not found])
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# spdylay (for src/nghttpx and src/h2load)
|
|
||||||
have_spdylay=no
|
|
||||||
if test "x${request_spdylay}" != "xno"; then
|
|
||||||
PKG_CHECK_MODULES([LIBSPDYLAY], [libspdylay >= 1.3.2],
|
|
||||||
[have_spdylay=yes], [have_spdylay=no])
|
|
||||||
if test "x${have_spdylay}" = "xyes"; then
|
|
||||||
AC_DEFINE([HAVE_SPDYLAY], [1], [Define to 1 if you have `spdylay` library.])
|
|
||||||
else
|
|
||||||
AC_MSG_NOTICE($LIBSPDYLAY_PKG_ERRORS)
|
|
||||||
AC_MSG_NOTICE([The SPDY support in nghttpx and h2load will be disabled.])
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
if test "x${request_spdylay}" = "xyes" &&
|
|
||||||
test "x${have_spdylay}" != "xyes"; then
|
|
||||||
AC_MSG_ERROR([spdylay was requested (--with-spdylay) but not found])
|
|
||||||
fi
|
|
||||||
|
|
||||||
AM_CONDITIONAL([HAVE_SPDYLAY], [ test "x${have_spdylay}" = "xyes" ])
|
|
||||||
|
|
||||||
# Check Boost Asio library
|
# Check Boost Asio library
|
||||||
have_asio_lib=no
|
have_asio_lib=no
|
||||||
|
|
||||||
@@ -713,6 +688,7 @@ AC_CHECK_FUNCS([ \
|
|||||||
memchr \
|
memchr \
|
||||||
memmove \
|
memmove \
|
||||||
memset \
|
memset \
|
||||||
|
mkostemp \
|
||||||
socket \
|
socket \
|
||||||
sqrt \
|
sqrt \
|
||||||
strchr \
|
strchr \
|
||||||
@@ -804,6 +780,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"])
|
||||||
|
# Disable noexcept-type warning of g++-7. This is not harmful as
|
||||||
|
# long as all source files are compiled with the same compiler.
|
||||||
|
AX_CHECK_COMPILE_FLAG([-Wno-noexcept-type], [CXXFLAGS="$CXXFLAGS -Wno-noexcept-type"])
|
||||||
AC_LANG_POP()
|
AC_LANG_POP()
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -924,7 +903,6 @@ AC_MSG_NOTICE([summary of build options:
|
|||||||
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}')
|
||||||
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}')
|
||||||
Spdylay: ${have_spdylay} (CFLAGS='${LIBSPDYLAY_CFLAGS}' LIBS='${LIBSPDYLAY_LIBS}')
|
|
||||||
Jansson: ${have_jansson} (CFLAGS='${JANSSON_CFLAGS}' LIBS='${JANSSON_LIBS}')
|
Jansson: ${have_jansson} (CFLAGS='${JANSSON_CFLAGS}' LIBS='${JANSSON_LIBS}')
|
||||||
Jemalloc: ${have_jemalloc} (LIBS='${JEMALLOC_LIBS}')
|
Jemalloc: ${have_jemalloc} (LIBS='${JEMALLOC_LIBS}')
|
||||||
Zlib: ${have_zlib} (CFLAGS='${ZLIB_CFLAGS}' LIBS='${ZLIB_LIBS}')
|
Zlib: ${have_zlib} (CFLAGS='${ZLIB_CFLAGS}' LIBS='${ZLIB_LIBS}')
|
||||||
|
|||||||
@@ -49,6 +49,7 @@ set(APIDOCS
|
|||||||
nghttp2_rcbuf_decref.rst
|
nghttp2_rcbuf_decref.rst
|
||||||
nghttp2_rcbuf_get_buf.rst
|
nghttp2_rcbuf_get_buf.rst
|
||||||
nghttp2_rcbuf_incref.rst
|
nghttp2_rcbuf_incref.rst
|
||||||
|
nghttp2_rcbuf_is_static.rst
|
||||||
nghttp2_select_next_protocol.rst
|
nghttp2_select_next_protocol.rst
|
||||||
nghttp2_session_callbacks_del.rst
|
nghttp2_session_callbacks_del.rst
|
||||||
nghttp2_session_callbacks_new.rst
|
nghttp2_session_callbacks_new.rst
|
||||||
|
|||||||
@@ -74,12 +74,14 @@ APIDOCS= \
|
|||||||
nghttp2_rcbuf_decref.rst \
|
nghttp2_rcbuf_decref.rst \
|
||||||
nghttp2_rcbuf_get_buf.rst \
|
nghttp2_rcbuf_get_buf.rst \
|
||||||
nghttp2_rcbuf_incref.rst \
|
nghttp2_rcbuf_incref.rst \
|
||||||
|
nghttp2_rcbuf_is_static.rst \
|
||||||
nghttp2_select_next_protocol.rst \
|
nghttp2_select_next_protocol.rst \
|
||||||
nghttp2_session_callbacks_del.rst \
|
nghttp2_session_callbacks_del.rst \
|
||||||
nghttp2_session_callbacks_new.rst \
|
nghttp2_session_callbacks_new.rst \
|
||||||
nghttp2_session_callbacks_set_before_frame_send_callback.rst \
|
nghttp2_session_callbacks_set_before_frame_send_callback.rst \
|
||||||
nghttp2_session_callbacks_set_data_source_read_length_callback.rst \
|
nghttp2_session_callbacks_set_data_source_read_length_callback.rst \
|
||||||
nghttp2_session_callbacks_set_error_callback.rst \
|
nghttp2_session_callbacks_set_error_callback.rst \
|
||||||
|
nghttp2_session_callbacks_set_error_callback2.rst \
|
||||||
nghttp2_session_callbacks_set_on_begin_frame_callback.rst \
|
nghttp2_session_callbacks_set_on_begin_frame_callback.rst \
|
||||||
nghttp2_session_callbacks_set_on_begin_headers_callback.rst \
|
nghttp2_session_callbacks_set_on_begin_headers_callback.rst \
|
||||||
nghttp2_session_callbacks_set_on_data_chunk_recv_callback.rst \
|
nghttp2_session_callbacks_set_on_data_chunk_recv_callback.rst \
|
||||||
@@ -141,6 +143,7 @@ APIDOCS= \
|
|||||||
nghttp2_session_set_local_window_size.rst \
|
nghttp2_session_set_local_window_size.rst \
|
||||||
nghttp2_session_set_next_stream_id.rst \
|
nghttp2_session_set_next_stream_id.rst \
|
||||||
nghttp2_session_set_stream_user_data.rst \
|
nghttp2_session_set_stream_user_data.rst \
|
||||||
|
nghttp2_session_set_user_data.rst \
|
||||||
nghttp2_session_terminate_session.rst \
|
nghttp2_session_terminate_session.rst \
|
||||||
nghttp2_session_terminate_session2.rst \
|
nghttp2_session_terminate_session2.rst \
|
||||||
nghttp2_session_upgrade.rst \
|
nghttp2_session_upgrade.rst \
|
||||||
@@ -161,6 +164,7 @@ APIDOCS= \
|
|||||||
nghttp2_submit_extension.rst \
|
nghttp2_submit_extension.rst \
|
||||||
nghttp2_submit_goaway.rst \
|
nghttp2_submit_goaway.rst \
|
||||||
nghttp2_submit_headers.rst \
|
nghttp2_submit_headers.rst \
|
||||||
|
nghttp2_submit_origin.rst \
|
||||||
nghttp2_submit_ping.rst \
|
nghttp2_submit_ping.rst \
|
||||||
nghttp2_submit_priority.rst \
|
nghttp2_submit_priority.rst \
|
||||||
nghttp2_submit_push_promise.rst \
|
nghttp2_submit_push_promise.rst \
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import re
|
|||||||
|
|
||||||
from docutils import nodes
|
from docutils import nodes
|
||||||
from docutils.parsers.rst import directives
|
from docutils.parsers.rst import directives
|
||||||
|
from docutils.parsers.rst import Directive
|
||||||
|
|
||||||
from sphinx import addnodes
|
from sphinx import addnodes
|
||||||
from sphinx import version_info
|
from sphinx import version_info
|
||||||
@@ -21,10 +22,8 @@ from sphinx.locale import l_, _
|
|||||||
from sphinx.domains import Domain, ObjType, Index
|
from sphinx.domains import Domain, ObjType, Index
|
||||||
from sphinx.directives import ObjectDescription
|
from sphinx.directives import ObjectDescription
|
||||||
from sphinx.util.nodes import make_refnode
|
from sphinx.util.nodes import make_refnode
|
||||||
from sphinx.util.compat import Directive
|
|
||||||
from sphinx.util.docfields import Field, GroupedField, TypedField
|
from sphinx.util.docfields import Field, GroupedField, TypedField
|
||||||
|
|
||||||
|
|
||||||
# REs for Ruby signatures
|
# REs for Ruby signatures
|
||||||
rb_sig_re = re.compile(
|
rb_sig_re = re.compile(
|
||||||
r'''^ ([\w.]*\.)? # class name(s)
|
r'''^ ([\w.]*\.)? # class name(s)
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ _h2load()
|
|||||||
_get_comp_words_by_ref cur prev
|
_get_comp_words_by_ref cur prev
|
||||||
case $cur in
|
case $cur in
|
||||||
-*)
|
-*)
|
||||||
COMPREPLY=( $( compgen -W '--connection-window-bits --clients --verbose --ciphers --rate --no-tls-proto --header-table-size --requests --base-uri --h1 --threads --npn-list --rate-period --data --version --connection-inactivity-timeout --timing-script-file --encoder-header-table-size --max-concurrent-streams --connection-active-timeout --input-file --help --window-bits --header ' -- "$cur" ) )
|
COMPREPLY=( $( compgen -W '--connection-window-bits --clients --verbose --ciphers --rate --no-tls-proto --header-table-size --requests --log-file --base-uri --h1 --threads --npn-list --rate-period --data --version --connection-inactivity-timeout --timing-script-file --encoder-header-table-size --max-concurrent-streams --connection-active-timeout --input-file --help --window-bits --warm-up-time --duration --header ' -- "$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 '--worker-read-rate --include --frontend-http2-dump-response-header --tls-ticket-key-file --verify-client-cacert --max-response-header-fields --backend-http2-window-size --frontend-keep-alive-timeout --backend-request-buffer --max-request-header-fields --fastopen --backend-connect-timeout --tls-max-proto-version --conf --dns-lookup-timeout --backend-http2-max-concurrent-streams --worker-write-burst --npn-list --dns-max-try --fetch-ocsp-response-file --no-via --tls-session-cache-memcached-cert-file --no-http2-cipher-black-list --mruby-file --client-no-http2-cipher-black-list --stream-read-timeout --client-ciphers --ocsp-update-interval --forwarded-for --accesslog-syslog --dns-cache-timeout --frontend-http2-read-timeout --listener-disable-timeout --ciphers --client-psk-secrets --strip-incoming-x-forwarded-for --no-server-rewrite --private-key-passwd-file --backend-keep-alive-timeout --backend-http-proxy-uri --frontend-max-requests --rlimit-nofile --no-strip-incoming-x-forwarded-proto --tls-ticket-key-memcached-cert-file --no-verify-ocsp --forwarded-by --tls-session-cache-memcached-private-key-file --error-page --ocsp-startup --backend-write-timeout --tls-dyn-rec-warmup-threshold --tls-ticket-key-memcached-max-retry --frontend-http2-window-size --http2-no-cookie-crumbling --worker-read-burst --dh-param-file --accesslog-format --errorlog-syslog --redirect-https-port --request-header-field-buffer --api-max-request-body --frontend-http2-decoder-dynamic-table-size --errorlog-file --frontend-http2-max-concurrent-streams --psk-secrets --frontend-write-timeout --tls-ticket-key-cipher --read-burst --no-add-x-forwarded-proto --backend --server-name --insecure --backend-max-backoff --log-level --host-rewrite --tls-ticket-key-memcached-interval --frontend-http2-setting-timeout --frontend-http2-connection-window-size --worker-frontend-connections --syslog-facility --no-server-push --no-location-rewrite --single-thread --tls-session-cache-memcached --no-ocsp --backend-response-buffer --tls-min-proto-version --workers --add-forwarded --worker-write-rate --add-request-header --backend-http2-settings-timeout --subcert --ecdh-curves --no-kqueue --help --frontend-frame-debug --tls-sct-dir --pid-file --frontend-http2-dump-request-header --daemon --write-rate --altsvc --backend-http2-decoder-dynamic-table-size --user --add-x-forwarded-for --frontend-read-timeout --tls-ticket-key-memcached-max-fail --backlog --write-burst --backend-connections-per-host --response-header-field-buffer --tls-ticket-key-memcached-address-family --padding --tls-session-cache-memcached-address-family --stream-write-timeout --cacert --tls-ticket-key-memcached-private-key-file --accesslog-write-early --backend-address-family --backend-http2-connection-window-size --version --add-response-header --backend-read-timeout --frontend-http2-optimize-window-size --frontend --accesslog-file --http2-proxy --backend-http2-encoder-dynamic-table-size --client-private-key-file --single-process --client-cert-file --tls-ticket-key-memcached --tls-dyn-rec-idle-timeout --frontend-http2-optimize-write-buffer-size --verify-client --frontend-http2-encoder-dynamic-table-size --read-rate --backend-connections-per-frontend --strip-incoming-forwarded ' -- "$cur" ) )
|
COMPREPLY=( $( compgen -W '--worker-read-rate --include --frontend-http2-dump-response-header --tls-ticket-key-file --verify-client-cacert --max-response-header-fields --backend-http2-window-size --tls13-client-ciphers --frontend-keep-alive-timeout --backend-request-buffer --max-request-header-fields --backend-connect-timeout --tls-max-proto-version --conf --dns-lookup-timeout --backend-http2-max-concurrent-streams --worker-write-burst --npn-list --dns-max-try --fetch-ocsp-response-file --no-via --tls-session-cache-memcached-cert-file --no-http2-cipher-black-list --mruby-file --add-forwarded --client-no-http2-cipher-black-list --stream-read-timeout --client-ciphers --ocsp-update-interval --forwarded-for --accesslog-syslog --dns-cache-timeout --frontend-http2-read-timeout --listener-disable-timeout --ciphers --client-psk-secrets --strip-incoming-x-forwarded-for --no-server-rewrite --private-key-passwd-file --backend-keep-alive-timeout --backend-http-proxy-uri --frontend-max-requests --tls-no-postpone-early-data --rlimit-nofile --no-strip-incoming-x-forwarded-proto --tls-ticket-key-memcached-cert-file --no-verify-ocsp --forwarded-by --tls-session-cache-memcached-private-key-file --error-page --ocsp-startup --backend-write-timeout --tls-dyn-rec-warmup-threshold --tls-ticket-key-memcached-max-retry --frontend-http2-window-size --http2-no-cookie-crumbling --worker-read-burst --dh-param-file --accesslog-format --errorlog-syslog --redirect-https-port --request-header-field-buffer --api-max-request-body --frontend-http2-decoder-dynamic-table-size --errorlog-file --frontend-http2-max-concurrent-streams --psk-secrets --frontend-write-timeout --tls-ticket-key-cipher --read-burst --no-add-x-forwarded-proto --backend --server-name --insecure --backend-max-backoff --log-level --host-rewrite --tls-ticket-key-memcached-interval --frontend-http2-setting-timeout --frontend-http2-connection-window-size --worker-frontend-connections --syslog-facility --fastopen --no-location-rewrite --single-thread --tls-session-cache-memcached --no-ocsp --backend-response-buffer --tls-min-proto-version --workers --add-x-forwarded-for --no-server-push --worker-write-rate --add-request-header --backend-http2-settings-timeout --subcert --ignore-per-pattern-mruby-error --ecdh-curves --no-kqueue --help --frontend-frame-debug --tls-sct-dir --pid-file --frontend-http2-dump-request-header --daemon --write-rate --altsvc --backend-http2-decoder-dynamic-table-size --no-strip-incoming-early-data --user --verify-client-tolerate-expired --frontend-read-timeout --tls-ticket-key-memcached-max-fail --backlog --write-burst --backend-connections-per-host --tls-max-early-data --response-header-field-buffer --tls-ticket-key-memcached-address-family --padding --tls-session-cache-memcached-address-family --stream-write-timeout --cacert --tls-ticket-key-memcached-private-key-file --accesslog-write-early --backend-address-family --backend-http2-connection-window-size --tls13-ciphers --version --add-response-header --backend-read-timeout --frontend-http2-optimize-window-size --frontend --accesslog-file --http2-proxy --backend-http2-encoder-dynamic-table-size --client-private-key-file --single-process --client-cert-file --tls-ticket-key-memcached --tls-dyn-rec-idle-timeout --frontend-http2-optimize-write-buffer-size --verify-client --frontend-http2-encoder-dynamic-table-size --read-rate --backend-connections-per-frontend --strip-incoming-forwarded ' -- "$cur" ) )
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
_filedir
|
_filedir
|
||||||
|
|||||||
@@ -157,7 +157,7 @@ html_theme_path = ['@top_srcdir@/doc/_themes']
|
|||||||
|
|
||||||
# If true, SmartyPants will be used to convert quotes and dashes to
|
# If true, SmartyPants will be used to convert quotes and dashes to
|
||||||
# typographically correct entities.
|
# typographically correct entities.
|
||||||
html_use_smartypants = False
|
#html_use_smartypants = False
|
||||||
|
|
||||||
# Custom sidebar templates, maps document names to template names.
|
# Custom sidebar templates, maps document names to template names.
|
||||||
html_sidebars = {
|
html_sidebars = {
|
||||||
|
|||||||
2
doc/docutils.conf
Normal file
2
doc/docutils.conf
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
[parsers]
|
||||||
|
smart_quotes=no
|
||||||
57
doc/h2load.1
57
doc/h2load.1
@@ -1,6 +1,6 @@
|
|||||||
.\" Man page generated from reStructuredText.
|
.\" Man page generated from reStructuredText.
|
||||||
.
|
.
|
||||||
.TH "H2LOAD" "1" "Jul 02, 2017" "1.24.0" "nghttp2"
|
.TH "H2LOAD" "1" "Apr 18, 2019" "1.38.0" "nghttp2"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
h2load \- HTTP/2 benchmarking tool
|
h2load \- HTTP/2 benchmarking tool
|
||||||
.
|
.
|
||||||
@@ -35,7 +35,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
|||||||
\fBh2load\fP [OPTIONS]... [URI]...
|
\fBh2load\fP [OPTIONS]... [URI]...
|
||||||
.SH DESCRIPTION
|
.SH DESCRIPTION
|
||||||
.sp
|
.sp
|
||||||
benchmarking tool for HTTP/2 and SPDY server
|
benchmarking tool for HTTP/2 server
|
||||||
.INDENT 0.0
|
.INDENT 0.0
|
||||||
.TP
|
.TP
|
||||||
.B <URI>
|
.B <URI>
|
||||||
@@ -54,7 +54,9 @@ scheme, host or port values.
|
|||||||
Number of requests across all clients. If it is used
|
Number of requests across all clients. If it is used
|
||||||
with \fI\%\-\-timing\-script\-file\fP option, this option specifies
|
with \fI\%\-\-timing\-script\-file\fP option, this option specifies
|
||||||
the number of requests each client performs rather than
|
the number of requests each client performs rather than
|
||||||
the number of requests across all clients.
|
the number of requests across all clients. This option
|
||||||
|
is ignored if timing\-based benchmarking is enabled (see
|
||||||
|
\fI\%\-\-duration\fP option).
|
||||||
.sp
|
.sp
|
||||||
Default: \fB1\fP
|
Default: \fB1\fP
|
||||||
.UNINDENT
|
.UNINDENT
|
||||||
@@ -99,7 +101,6 @@ Default: \fB1\fP
|
|||||||
.TP
|
.TP
|
||||||
.B \-w, \-\-window\-bits=<N>
|
.B \-w, \-\-window\-bits=<N>
|
||||||
Sets the stream level initial window size to (2**<N>)\-1.
|
Sets the stream level initial window size to (2**<N>)\-1.
|
||||||
For SPDY, 2**<N> is used instead.
|
|
||||||
.sp
|
.sp
|
||||||
Default: \fB30\fP
|
Default: \fB30\fP
|
||||||
.UNINDENT
|
.UNINDENT
|
||||||
@@ -107,9 +108,7 @@ Default: \fB30\fP
|
|||||||
.TP
|
.TP
|
||||||
.B \-W, \-\-connection\-window\-bits=<N>
|
.B \-W, \-\-connection\-window\-bits=<N>
|
||||||
Sets the connection level initial window size to
|
Sets the connection level initial window size to
|
||||||
(2**<N>)\-1. For SPDY, if <N> is strictly less than 16,
|
(2**<N>)\-1.
|
||||||
this option is ignored. Otherwise 2**<N> is used for
|
|
||||||
SPDY.
|
|
||||||
.sp
|
.sp
|
||||||
Default: \fB30\fP
|
Default: \fB30\fP
|
||||||
.UNINDENT
|
.UNINDENT
|
||||||
@@ -131,8 +130,7 @@ Default: \fBECDHE\-ECDSA\-AES256\-GCM\-SHA384:ECDHE\-RSA\-AES256\-GCM\-SHA384:EC
|
|||||||
.B \-p, \-\-no\-tls\-proto=<PROTOID>
|
.B \-p, \-\-no\-tls\-proto=<PROTOID>
|
||||||
Specify ALPN identifier of the protocol to be used when
|
Specify ALPN identifier of the protocol to be used when
|
||||||
accessing http URI without SSL/TLS.
|
accessing http URI without SSL/TLS.
|
||||||
Available protocols: h2c and
|
Available protocols: h2c and http/1.1
|
||||||
http/1.1
|
|
||||||
.sp
|
.sp
|
||||||
Default: \fBh2c\fP
|
Default: \fBh2c\fP
|
||||||
.UNINDENT
|
.UNINDENT
|
||||||
@@ -157,7 +155,7 @@ example, with \fI\%\-t\fP2 and \fI\%\-r\fP4, each thread gets 2
|
|||||||
connections per period. When the rate is 0, the program
|
connections per period. When the rate is 0, the program
|
||||||
will run as it normally does, creating connections at
|
will run as it normally does, creating connections at
|
||||||
whatever variable rate it wants. The default value for
|
whatever variable rate it wants. The default value for
|
||||||
this option is 0.
|
this option is 0. \fI\%\-r\fP and \fI\%\-D\fP are mutually exclusive.
|
||||||
.UNINDENT
|
.UNINDENT
|
||||||
.INDENT 0.0
|
.INDENT 0.0
|
||||||
.TP
|
.TP
|
||||||
@@ -170,6 +168,20 @@ option is 1s.
|
|||||||
.UNINDENT
|
.UNINDENT
|
||||||
.INDENT 0.0
|
.INDENT 0.0
|
||||||
.TP
|
.TP
|
||||||
|
.B \-D, \-\-duration=<N>
|
||||||
|
Specifies the main duration for the measurements in case
|
||||||
|
of timing\-based benchmarking. \fI\%\-D\fP and \fI\%\-r\fP are mutually
|
||||||
|
exclusive.
|
||||||
|
.UNINDENT
|
||||||
|
.INDENT 0.0
|
||||||
|
.TP
|
||||||
|
.B \-\-warm\-up\-time=<DURATION>
|
||||||
|
Specifies the time period before starting the actual
|
||||||
|
measurements, in case of timing\-based benchmarking.
|
||||||
|
Needs to provided along with \fI\%\-D\fP option.
|
||||||
|
.UNINDENT
|
||||||
|
.INDENT 0.0
|
||||||
|
.TP
|
||||||
.B \-T, \-\-connection\-active\-timeout=<DURATION>
|
.B \-T, \-\-connection\-active\-timeout=<DURATION>
|
||||||
Specifies the maximum time that h2load is willing to
|
Specifies the maximum time that h2load is willing to
|
||||||
keep a connection open, regardless of the activity on
|
keep a connection open, regardless of the activity on
|
||||||
@@ -261,6 +273,17 @@ Default: \fB4K\fP
|
|||||||
.UNINDENT
|
.UNINDENT
|
||||||
.INDENT 0.0
|
.INDENT 0.0
|
||||||
.TP
|
.TP
|
||||||
|
.B \-\-log\-file=<PATH>
|
||||||
|
Write per\-request information to a file as tab\-separated
|
||||||
|
columns: start time as microseconds since epoch; HTTP
|
||||||
|
status code; microseconds until end of response. More
|
||||||
|
columns may be added later. Rows are ordered by end\-of\-
|
||||||
|
response time when using one worker thread, but may
|
||||||
|
appear slightly out of order with multiple threads due
|
||||||
|
to buffering. Status code is \-1 for failed streams.
|
||||||
|
.UNINDENT
|
||||||
|
.INDENT 0.0
|
||||||
|
.TP
|
||||||
.B \-v, \-\-verbose
|
.B \-v, \-\-verbose
|
||||||
Output debug information.
|
Output debug information.
|
||||||
.UNINDENT
|
.UNINDENT
|
||||||
@@ -335,8 +358,7 @@ compression. Let \fBdecompressed(headers)\fP to the number of bytes
|
|||||||
used for header fields after decompression. The \fBspace savings\fP
|
used for header fields after decompression. The \fBspace savings\fP
|
||||||
is calculated by (1 \- \fBheaders\fP / \fBdecompressed(headers)\fP) *
|
is calculated by (1 \- \fBheaders\fP / \fBdecompressed(headers)\fP) *
|
||||||
100. For HTTP/1.1, this is usually 0.00%, since it does not have
|
100. For HTTP/1.1, this is usually 0.00%, since it does not have
|
||||||
header compression. For HTTP/2 and SPDY, it shows some insightful
|
header compression. For HTTP/2, it shows some insightful numbers.
|
||||||
numbers.
|
|
||||||
.TP
|
.TP
|
||||||
.B data
|
.B data
|
||||||
The number of response body bytes received from the server.
|
The number of response body bytes received from the server.
|
||||||
@@ -366,13 +388,16 @@ range (mean +/\- sd) against total number of successful requests.
|
|||||||
.INDENT 7.0
|
.INDENT 7.0
|
||||||
.TP
|
.TP
|
||||||
.B min
|
.B min
|
||||||
The minimum time taken to connect to a server.
|
The minimum time taken to connect to a server including TLS
|
||||||
|
handshake.
|
||||||
.TP
|
.TP
|
||||||
.B max
|
.B max
|
||||||
The maximum time taken to connect to a server.
|
The maximum time taken to connect to a server including TLS
|
||||||
|
handshake.
|
||||||
.TP
|
.TP
|
||||||
.B mean
|
.B mean
|
||||||
The mean time taken to connect to a server.
|
The mean time taken to connect to a server including TLS
|
||||||
|
handshake.
|
||||||
.TP
|
.TP
|
||||||
.B sd
|
.B sd
|
||||||
The standard deviation of the time taken to connect to a server.
|
The standard deviation of the time taken to connect to a server.
|
||||||
@@ -433,7 +458,7 @@ h2load sets large flow control window by default, and effectively
|
|||||||
disables flow control to avoid under utilization of server
|
disables flow control to avoid under utilization of server
|
||||||
performance. To set smaller flow control window, use \fI\%\-w\fP and
|
performance. To set smaller flow control window, use \fI\%\-w\fP and
|
||||||
\fI\%\-W\fP options. For example, use \fB\-w16 \-W16\fP to set default
|
\fI\%\-W\fP options. For example, use \fB\-w16 \-W16\fP to set default
|
||||||
window size described in HTTP/2 and SPDY protocol specification.
|
window size described in HTTP/2 protocol specification.
|
||||||
.SH SEE ALSO
|
.SH SEE ALSO
|
||||||
.sp
|
.sp
|
||||||
\fBnghttp(1)\fP, \fBnghttpd(1)\fP, \fBnghttpx(1)\fP
|
\fBnghttp(1)\fP, \fBnghttpd(1)\fP, \fBnghttpx(1)\fP
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ SYNOPSIS
|
|||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
-----------
|
-----------
|
||||||
|
|
||||||
benchmarking tool for HTTP/2 and SPDY server
|
benchmarking tool for HTTP/2 server
|
||||||
|
|
||||||
.. describe:: <URI>
|
.. describe:: <URI>
|
||||||
|
|
||||||
@@ -34,7 +34,9 @@ OPTIONS
|
|||||||
Number of requests across all clients. If it is used
|
Number of requests across all clients. If it is used
|
||||||
with :option:`--timing-script-file` option, this option specifies
|
with :option:`--timing-script-file` option, this option specifies
|
||||||
the number of requests each client performs rather than
|
the number of requests each client performs rather than
|
||||||
the number of requests across all clients.
|
the number of requests across all clients. This option
|
||||||
|
is ignored if timing-based benchmarking is enabled (see
|
||||||
|
:option:`--duration` option).
|
||||||
|
|
||||||
Default: ``1``
|
Default: ``1``
|
||||||
|
|
||||||
@@ -74,16 +76,13 @@ OPTIONS
|
|||||||
.. option:: -w, --window-bits=<N>
|
.. option:: -w, --window-bits=<N>
|
||||||
|
|
||||||
Sets the stream level initial window size to (2\*\*<N>)-1.
|
Sets the stream level initial window size to (2\*\*<N>)-1.
|
||||||
For SPDY, 2\*\*<N> is used instead.
|
|
||||||
|
|
||||||
Default: ``30``
|
Default: ``30``
|
||||||
|
|
||||||
.. option:: -W, --connection-window-bits=<N>
|
.. option:: -W, --connection-window-bits=<N>
|
||||||
|
|
||||||
Sets the connection level initial window size to
|
Sets the connection level initial window size to
|
||||||
(2\*\*<N>)-1. For SPDY, if <N> is strictly less than 16,
|
(2\*\*<N>)-1.
|
||||||
this option is ignored. Otherwise 2\*\*<N> is used for
|
|
||||||
SPDY.
|
|
||||||
|
|
||||||
Default: ``30``
|
Default: ``30``
|
||||||
|
|
||||||
@@ -102,8 +101,7 @@ OPTIONS
|
|||||||
|
|
||||||
Specify ALPN identifier of the protocol to be used when
|
Specify ALPN identifier of the protocol to be used when
|
||||||
accessing http URI without SSL/TLS.
|
accessing http URI without SSL/TLS.
|
||||||
Available protocols: h2c and
|
Available protocols: h2c and http/1.1
|
||||||
http/1.1
|
|
||||||
|
|
||||||
Default: ``h2c``
|
Default: ``h2c``
|
||||||
|
|
||||||
@@ -126,7 +124,7 @@ OPTIONS
|
|||||||
connections per period. When the rate is 0, the program
|
connections per period. When the rate is 0, the program
|
||||||
will run as it normally does, creating connections at
|
will run as it normally does, creating connections at
|
||||||
whatever variable rate it wants. The default value for
|
whatever variable rate it wants. The default value for
|
||||||
this option is 0.
|
this option is 0. :option:`-r` and :option:`\-D` are mutually exclusive.
|
||||||
|
|
||||||
.. option:: --rate-period=<DURATION>
|
.. option:: --rate-period=<DURATION>
|
||||||
|
|
||||||
@@ -136,6 +134,18 @@ OPTIONS
|
|||||||
the rate option is not used. The default value for this
|
the rate option is not used. The default value for this
|
||||||
option is 1s.
|
option is 1s.
|
||||||
|
|
||||||
|
.. option:: -D, --duration=<N>
|
||||||
|
|
||||||
|
Specifies the main duration for the measurements in case
|
||||||
|
of timing-based benchmarking. :option:`-D` and :option:`\-r` are mutually
|
||||||
|
exclusive.
|
||||||
|
|
||||||
|
.. option:: --warm-up-time=<DURATION>
|
||||||
|
|
||||||
|
Specifies the time period before starting the actual
|
||||||
|
measurements, in case of timing-based benchmarking.
|
||||||
|
Needs to provided along with :option:`-D` option.
|
||||||
|
|
||||||
.. option:: -T, --connection-active-timeout=<DURATION>
|
.. option:: -T, --connection-active-timeout=<DURATION>
|
||||||
|
|
||||||
Specifies the maximum time that h2load is willing to
|
Specifies the maximum time that h2load is willing to
|
||||||
@@ -219,6 +229,16 @@ OPTIONS
|
|||||||
|
|
||||||
Default: ``4K``
|
Default: ``4K``
|
||||||
|
|
||||||
|
.. option:: --log-file=<PATH>
|
||||||
|
|
||||||
|
Write per-request information to a file as tab-separated
|
||||||
|
columns: start time as microseconds since epoch; HTTP
|
||||||
|
status code; microseconds until end of response. More
|
||||||
|
columns may be added later. Rows are ordered by end-of-
|
||||||
|
response time when using one worker thread, but may
|
||||||
|
appear slightly out of order with multiple threads due
|
||||||
|
to buffering. Status code is -1 for failed streams.
|
||||||
|
|
||||||
.. option:: -v, --verbose
|
.. option:: -v, --verbose
|
||||||
|
|
||||||
Output debug information.
|
Output debug information.
|
||||||
@@ -284,8 +304,7 @@ traffic
|
|||||||
used for header fields after decompression. The ``space savings``
|
used for header fields after decompression. The ``space savings``
|
||||||
is calculated by (1 - ``headers`` / ``decompressed(headers)``) *
|
is calculated by (1 - ``headers`` / ``decompressed(headers)``) *
|
||||||
100. For HTTP/1.1, this is usually 0.00%, since it does not have
|
100. For HTTP/1.1, this is usually 0.00%, since it does not have
|
||||||
header compression. For HTTP/2 and SPDY, it shows some insightful
|
header compression. For HTTP/2, it shows some insightful numbers.
|
||||||
numbers.
|
|
||||||
data
|
data
|
||||||
The number of response body bytes received from the server.
|
The number of response body bytes received from the server.
|
||||||
|
|
||||||
@@ -304,11 +323,14 @@ time for request
|
|||||||
|
|
||||||
time for connect
|
time for connect
|
||||||
min
|
min
|
||||||
The minimum time taken to connect to a server.
|
The minimum time taken to connect to a server including TLS
|
||||||
|
handshake.
|
||||||
max
|
max
|
||||||
The maximum time taken to connect to a server.
|
The maximum time taken to connect to a server including TLS
|
||||||
|
handshake.
|
||||||
mean
|
mean
|
||||||
The mean time taken to connect to a server.
|
The mean time taken to connect to a server including TLS
|
||||||
|
handshake.
|
||||||
sd
|
sd
|
||||||
The standard deviation of the time taken to connect to a server.
|
The standard deviation of the time taken to connect to a server.
|
||||||
+/- sd
|
+/- sd
|
||||||
@@ -353,7 +375,7 @@ h2load sets large flow control window by default, and effectively
|
|||||||
disables flow control to avoid under utilization of server
|
disables flow control to avoid under utilization of server
|
||||||
performance. To set smaller flow control window, use :option:`-w` and
|
performance. To set smaller flow control window, use :option:`-w` and
|
||||||
:option:`-W` options. For example, use ``-w16 -W16`` to set default
|
:option:`-W` options. For example, use ``-w16 -W16`` to set default
|
||||||
window size described in HTTP/2 and SPDY protocol specification.
|
window size described in HTTP/2 protocol specification.
|
||||||
|
|
||||||
SEE ALSO
|
SEE ALSO
|
||||||
--------
|
--------
|
||||||
|
|||||||
@@ -41,8 +41,7 @@ traffic
|
|||||||
used for header fields after decompression. The ``space savings``
|
used for header fields after decompression. The ``space savings``
|
||||||
is calculated by (1 - ``headers`` / ``decompressed(headers)``) *
|
is calculated by (1 - ``headers`` / ``decompressed(headers)``) *
|
||||||
100. For HTTP/1.1, this is usually 0.00%, since it does not have
|
100. For HTTP/1.1, this is usually 0.00%, since it does not have
|
||||||
header compression. For HTTP/2 and SPDY, it shows some insightful
|
header compression. For HTTP/2, it shows some insightful numbers.
|
||||||
numbers.
|
|
||||||
data
|
data
|
||||||
The number of response body bytes received from the server.
|
The number of response body bytes received from the server.
|
||||||
|
|
||||||
@@ -61,11 +60,14 @@ time for request
|
|||||||
|
|
||||||
time for connect
|
time for connect
|
||||||
min
|
min
|
||||||
The minimum time taken to connect to a server.
|
The minimum time taken to connect to a server including TLS
|
||||||
|
handshake.
|
||||||
max
|
max
|
||||||
The maximum time taken to connect to a server.
|
The maximum time taken to connect to a server including TLS
|
||||||
|
handshake.
|
||||||
mean
|
mean
|
||||||
The mean time taken to connect to a server.
|
The mean time taken to connect to a server including TLS
|
||||||
|
handshake.
|
||||||
sd
|
sd
|
||||||
The standard deviation of the time taken to connect to a server.
|
The standard deviation of the time taken to connect to a server.
|
||||||
+/- sd
|
+/- sd
|
||||||
@@ -110,7 +112,7 @@ h2load sets large flow control window by default, and effectively
|
|||||||
disables flow control to avoid under utilization of server
|
disables flow control to avoid under utilization of server
|
||||||
performance. To set smaller flow control window, use :option:`-w` and
|
performance. To set smaller flow control window, use :option:`-w` and
|
||||||
:option:`-W` options. For example, use ``-w16 -W16`` to set default
|
:option:`-W` options. For example, use ``-w16 -W16`` to set default
|
||||||
window size described in HTTP/2 and SPDY protocol specification.
|
window size described in HTTP/2 protocol specification.
|
||||||
|
|
||||||
SEE ALSO
|
SEE ALSO
|
||||||
--------
|
--------
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
.\" Man page generated from reStructuredText.
|
.\" Man page generated from reStructuredText.
|
||||||
.
|
.
|
||||||
.TH "NGHTTP" "1" "Jul 02, 2017" "1.24.0" "nghttp2"
|
.TH "NGHTTP" "1" "Apr 18, 2019" "1.38.0" "nghttp2"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
nghttp \- HTTP/2 client
|
nghttp \- HTTP/2 client
|
||||||
.
|
.
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
.\" Man page generated from reStructuredText.
|
.\" Man page generated from reStructuredText.
|
||||||
.
|
.
|
||||||
.TH "NGHTTPD" "1" "Jul 02, 2017" "1.24.0" "nghttp2"
|
.TH "NGHTTPD" "1" "Apr 18, 2019" "1.38.0" "nghttp2"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
nghttpd \- HTTP/2 server
|
nghttpd \- HTTP/2 server
|
||||||
.
|
.
|
||||||
|
|||||||
330
doc/nghttpx.1
330
doc/nghttpx.1
@@ -1,6 +1,6 @@
|
|||||||
.\" Man page generated from reStructuredText.
|
.\" Man page generated from reStructuredText.
|
||||||
.
|
.
|
||||||
.TH "NGHTTPX" "1" "Jul 02, 2017" "1.24.0" "nghttp2"
|
.TH "NGHTTPX" "1" "Apr 18, 2019" "1.38.0" "nghttp2"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
nghttpx \- HTTP/2 proxy
|
nghttpx \- HTTP/2 proxy
|
||||||
.
|
.
|
||||||
@@ -35,7 +35,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
|||||||
\fBnghttpx\fP [OPTIONS]... [<PRIVATE_KEY> <CERT>]
|
\fBnghttpx\fP [OPTIONS]... [<PRIVATE_KEY> <CERT>]
|
||||||
.SH DESCRIPTION
|
.SH DESCRIPTION
|
||||||
.sp
|
.sp
|
||||||
A reverse proxy for HTTP/2, HTTP/1 and SPDY.
|
A reverse proxy for HTTP/2, and HTTP/1.
|
||||||
.INDENT 0.0
|
.INDENT 0.0
|
||||||
.TP
|
.TP
|
||||||
.B <PRIVATE_KEY>
|
.B <PRIVATE_KEY>
|
||||||
@@ -75,7 +75,7 @@ matches request path "\fI/foo\fP"). If it does not end with
|
|||||||
"\fI/\fP", it performs exact match against the request path.
|
"\fI/\fP", it performs exact match against the request path.
|
||||||
If host is given, it performs a match against the
|
If host is given, it performs a match against the
|
||||||
request host. For a request received on the frontend
|
request host. For a request received on the frontend
|
||||||
lister with "sni\-fwd" parameter enabled, SNI host is
|
listener with "sni\-fwd" parameter enabled, SNI host is
|
||||||
used instead of a request host. If host alone is given,
|
used instead of a request host. If host alone is given,
|
||||||
"\fI/\fP" is appended to it, so that it matches all request
|
"\fI/\fP" is appended to it, so that it matches all request
|
||||||
paths under the host (e.g., specifying "nghttp2.org"
|
paths under the host (e.g., specifying "nghttp2.org"
|
||||||
@@ -137,7 +137,10 @@ Several parameters <PARAM> are accepted after <PATTERN>.
|
|||||||
The parameters are delimited by ";". The available
|
The parameters are delimited by ";". The available
|
||||||
parameters are: "proto=<PROTO>", "tls",
|
parameters are: "proto=<PROTO>", "tls",
|
||||||
"sni=<SNI_HOST>", "fall=<N>", "rise=<N>",
|
"sni=<SNI_HOST>", "fall=<N>", "rise=<N>",
|
||||||
"affinity=<METHOD>", "dns", and "redirect\-if\-not\-tls".
|
"affinity=<METHOD>", "dns", "redirect\-if\-not\-tls",
|
||||||
|
"upgrade\-scheme", "mruby=<PATH>",
|
||||||
|
"read\-timeout=<DURATION>", "write\-timeout=<DURATION>",
|
||||||
|
"group=<GROUP>", "group\-weight=<N>", and "weight=<N>".
|
||||||
The parameter consists of keyword, and optionally
|
The parameter consists of keyword, and optionally
|
||||||
followed by "=" and value. For example, the parameter
|
followed by "=" and value. For example, the parameter
|
||||||
"proto=h2" consists of the keyword "proto" and value
|
"proto=h2" consists of the keyword "proto" and value
|
||||||
@@ -180,16 +183,32 @@ state, and this is the default behaviour.
|
|||||||
The session affinity is enabled using
|
The session affinity is enabled using
|
||||||
"affinity=<METHOD>" parameter. If "ip" is given in
|
"affinity=<METHOD>" parameter. If "ip" is given in
|
||||||
<METHOD>, client IP based session affinity is enabled.
|
<METHOD>, client IP based session affinity is enabled.
|
||||||
If "none" is given in <METHOD>, session affinity is
|
If "cookie" is given in <METHOD>, cookie based session
|
||||||
disabled, and this is the default. The session affinity
|
affinity is enabled. If "none" is given in <METHOD>,
|
||||||
is enabled per <PATTERN>. If at least one backend has
|
session affinity is disabled, and this is the default.
|
||||||
"affinity" parameter, and its <METHOD> is not "none",
|
The session affinity is enabled per <PATTERN>. If at
|
||||||
session affinity is enabled for all backend servers
|
least one backend has "affinity" parameter, and its
|
||||||
sharing the same <PATTERN>. It is advised to set
|
<METHOD> is not "none", session affinity is enabled for
|
||||||
"affinity" parameter to all backend explicitly if
|
all backend servers sharing the same <PATTERN>. It is
|
||||||
session affinity is desired. The session affinity may
|
advised to set "affinity" parameter to all backend
|
||||||
break if one of the backend gets unreachable, or backend
|
explicitly if session affinity is desired. The session
|
||||||
settings are reloaded or replaced by API.
|
affinity may break if one of the backend gets
|
||||||
|
unreachable, or backend settings are reloaded or
|
||||||
|
replaced by API.
|
||||||
|
.sp
|
||||||
|
If "affinity=cookie" is used, the additional
|
||||||
|
configuration is required.
|
||||||
|
"affinity\-cookie\-name=<NAME>" must be used to specify a
|
||||||
|
name of cookie to use. Optionally,
|
||||||
|
"affinity\-cookie\-path=<PATH>" can be used to specify a
|
||||||
|
path which cookie is applied. The optional
|
||||||
|
"affinity\-cookie\-secure=<SECURE>" controls the Secure
|
||||||
|
attribute of a cookie. The default value is "auto", and
|
||||||
|
the Secure attribute is determined by a request scheme.
|
||||||
|
If a request scheme is "https", then Secure attribute is
|
||||||
|
set. Otherwise, it is not set. If <SECURE> is "yes",
|
||||||
|
the Secure attribute is always set. If <SECURE> is
|
||||||
|
"no", the Secure attribute is always omitted.
|
||||||
.sp
|
.sp
|
||||||
By default, name resolution of backend host name is done
|
By default, name resolution of backend host name is done
|
||||||
at start up, or reloading configuration. If "dns"
|
at start up, or reloading configuration. If "dns"
|
||||||
@@ -212,6 +231,51 @@ the same <PATTERN>. It is advised to set
|
|||||||
"redirect\-if\-no\-tls" parameter to all backends
|
"redirect\-if\-no\-tls" parameter to all backends
|
||||||
explicitly if this feature is desired.
|
explicitly if this feature is desired.
|
||||||
.sp
|
.sp
|
||||||
|
If "upgrade\-scheme" parameter is used along with "tls"
|
||||||
|
parameter, HTTP/2 :scheme pseudo header field is changed
|
||||||
|
to "https" from "http" when forwarding a request to this
|
||||||
|
particular backend. This is a workaround for a backend
|
||||||
|
server which requires "https" :scheme pseudo header
|
||||||
|
field on TLS encrypted connection.
|
||||||
|
.sp
|
||||||
|
"mruby=<PATH>" parameter specifies a path to mruby
|
||||||
|
script file which is invoked when this pattern is
|
||||||
|
matched. All backends which share the same pattern must
|
||||||
|
have the same mruby path.
|
||||||
|
.sp
|
||||||
|
"read\-timeout=<DURATION>" and "write\-timeout=<DURATION>"
|
||||||
|
parameters specify the read and write timeout of the
|
||||||
|
backend connection when this pattern is matched. All
|
||||||
|
backends which share the same pattern must have the same
|
||||||
|
timeouts. If these timeouts are entirely omitted for a
|
||||||
|
pattern, \fI\%\-\-backend\-read\-timeout\fP and
|
||||||
|
\fI\%\-\-backend\-write\-timeout\fP are used.
|
||||||
|
.sp
|
||||||
|
"group=<GROUP>" parameter specifies the name of group
|
||||||
|
this backend address belongs to. By default, it belongs
|
||||||
|
to the unnamed default group. The name of group is
|
||||||
|
unique per pattern. "group\-weight=<N>" parameter
|
||||||
|
specifies the weight of the group. The higher weight
|
||||||
|
gets more frequently selected by the load balancing
|
||||||
|
algorithm. <N> must be [1, 256] inclusive. The weight
|
||||||
|
8 has 4 times more weight than 2. <N> must be the same
|
||||||
|
for all addresses which share the same <GROUP>. If
|
||||||
|
"group\-weight" is omitted in an address, but the other
|
||||||
|
address which belongs to the same group specifies
|
||||||
|
"group\-weight", its weight is used. If no
|
||||||
|
"group\-weight" is specified for all addresses, the
|
||||||
|
weight of a group becomes 1. "group" and "group\-weight"
|
||||||
|
are ignored if session affinity is enabled.
|
||||||
|
.sp
|
||||||
|
"weight=<N>" parameter specifies the weight of the
|
||||||
|
backend address inside a group which this address
|
||||||
|
belongs to. The higher weight gets more frequently
|
||||||
|
selected by the load balancing algorithm. <N> must be
|
||||||
|
[1, 256] inclusive. The weight 8 has 4 times more
|
||||||
|
weight than weight 2. If this parameter is omitted,
|
||||||
|
weight becomes 1. "weight" is ignored if session
|
||||||
|
affinity is enabled.
|
||||||
|
.sp
|
||||||
Since ";" and ":" are used as delimiter, <PATTERN> must
|
Since ";" and ":" are used as delimiter, <PATTERN> must
|
||||||
not contain these characters. Since ";" has special
|
not contain these characters. Since ";" has special
|
||||||
meaning in shell, the option value must be quoted.
|
meaning in shell, the option value must be quoted.
|
||||||
@@ -455,8 +519,7 @@ this option will be simply ignored.
|
|||||||
.INDENT 0.0
|
.INDENT 0.0
|
||||||
.TP
|
.TP
|
||||||
.B \-\-frontend\-http2\-read\-timeout=<DURATION>
|
.B \-\-frontend\-http2\-read\-timeout=<DURATION>
|
||||||
Specify read timeout for HTTP/2 and SPDY frontend
|
Specify read timeout for HTTP/2 frontend connection.
|
||||||
connection.
|
|
||||||
.sp
|
.sp
|
||||||
Default: \fB3m\fP
|
Default: \fB3m\fP
|
||||||
.UNINDENT
|
.UNINDENT
|
||||||
@@ -485,16 +548,16 @@ Default: \fB1m\fP
|
|||||||
.INDENT 0.0
|
.INDENT 0.0
|
||||||
.TP
|
.TP
|
||||||
.B \-\-stream\-read\-timeout=<DURATION>
|
.B \-\-stream\-read\-timeout=<DURATION>
|
||||||
Specify read timeout for HTTP/2 and SPDY streams. 0
|
Specify read timeout for HTTP/2 streams. 0 means no
|
||||||
means no timeout.
|
timeout.
|
||||||
.sp
|
.sp
|
||||||
Default: \fB0\fP
|
Default: \fB0\fP
|
||||||
.UNINDENT
|
.UNINDENT
|
||||||
.INDENT 0.0
|
.INDENT 0.0
|
||||||
.TP
|
.TP
|
||||||
.B \-\-stream\-write\-timeout=<DURATION>
|
.B \-\-stream\-write\-timeout=<DURATION>
|
||||||
Specify write timeout for HTTP/2 and SPDY streams. 0
|
Specify write timeout for HTTP/2 streams. 0 means no
|
||||||
means no timeout.
|
timeout.
|
||||||
.sp
|
.sp
|
||||||
Default: \fB1m\fP
|
Default: \fB1m\fP
|
||||||
.UNINDENT
|
.UNINDENT
|
||||||
@@ -573,19 +636,43 @@ Default: \fB2m\fP
|
|||||||
.B \-\-ciphers=<SUITE>
|
.B \-\-ciphers=<SUITE>
|
||||||
Set allowed cipher list for frontend connection. The
|
Set allowed cipher list for frontend connection. The
|
||||||
format of the string is described in OpenSSL ciphers(1).
|
format of the string is described in OpenSSL ciphers(1).
|
||||||
|
This option sets cipher suites for TLSv1.2 or earlier.
|
||||||
|
Use \fI\%\-\-tls13\-ciphers\fP for TLSv1.3.
|
||||||
.sp
|
.sp
|
||||||
Default: \fBECDHE\-ECDSA\-AES256\-GCM\-SHA384:ECDHE\-RSA\-AES256\-GCM\-SHA384:ECDHE\-ECDSA\-CHACHA20\-POLY1305:ECDHE\-RSA\-CHACHA20\-POLY1305:ECDHE\-ECDSA\-AES128\-GCM\-SHA256:ECDHE\-RSA\-AES128\-GCM\-SHA256:ECDHE\-ECDSA\-AES256\-SHA384:ECDHE\-RSA\-AES256\-SHA384:ECDHE\-ECDSA\-AES128\-SHA256:ECDHE\-RSA\-AES128\-SHA256\fP
|
Default: \fBECDHE\-ECDSA\-AES256\-GCM\-SHA384:ECDHE\-RSA\-AES256\-GCM\-SHA384:ECDHE\-ECDSA\-CHACHA20\-POLY1305:ECDHE\-RSA\-CHACHA20\-POLY1305:ECDHE\-ECDSA\-AES128\-GCM\-SHA256:ECDHE\-RSA\-AES128\-GCM\-SHA256:ECDHE\-ECDSA\-AES256\-SHA384:ECDHE\-RSA\-AES256\-SHA384:ECDHE\-ECDSA\-AES128\-SHA256:ECDHE\-RSA\-AES128\-SHA256\fP
|
||||||
.UNINDENT
|
.UNINDENT
|
||||||
.INDENT 0.0
|
.INDENT 0.0
|
||||||
.TP
|
.TP
|
||||||
|
.B \-\-tls13\-ciphers=<SUITE>
|
||||||
|
Set allowed cipher list for frontend connection. The
|
||||||
|
format of the string is described in OpenSSL ciphers(1).
|
||||||
|
This option sets cipher suites for TLSv1.3. Use
|
||||||
|
\fI\%\-\-ciphers\fP for TLSv1.2 or earlier.
|
||||||
|
.sp
|
||||||
|
Default: \fBTLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256\fP
|
||||||
|
.UNINDENT
|
||||||
|
.INDENT 0.0
|
||||||
|
.TP
|
||||||
.B \-\-client\-ciphers=<SUITE>
|
.B \-\-client\-ciphers=<SUITE>
|
||||||
Set allowed cipher list for backend connection. The
|
Set allowed cipher list for backend connection. The
|
||||||
format of the string is described in OpenSSL ciphers(1).
|
format of the string is described in OpenSSL ciphers(1).
|
||||||
|
This option sets cipher suites for TLSv1.2 or earlier.
|
||||||
|
Use \fI\%\-\-tls13\-client\-ciphers\fP for TLSv1.3.
|
||||||
.sp
|
.sp
|
||||||
Default: \fBECDHE\-ECDSA\-AES256\-GCM\-SHA384:ECDHE\-RSA\-AES256\-GCM\-SHA384:ECDHE\-ECDSA\-CHACHA20\-POLY1305:ECDHE\-RSA\-CHACHA20\-POLY1305:ECDHE\-ECDSA\-AES128\-GCM\-SHA256:ECDHE\-RSA\-AES128\-GCM\-SHA256:ECDHE\-ECDSA\-AES256\-SHA384:ECDHE\-RSA\-AES256\-SHA384:ECDHE\-ECDSA\-AES128\-SHA256:ECDHE\-RSA\-AES128\-SHA256\fP
|
Default: \fBECDHE\-ECDSA\-AES256\-GCM\-SHA384:ECDHE\-RSA\-AES256\-GCM\-SHA384:ECDHE\-ECDSA\-CHACHA20\-POLY1305:ECDHE\-RSA\-CHACHA20\-POLY1305:ECDHE\-ECDSA\-AES128\-GCM\-SHA256:ECDHE\-RSA\-AES128\-GCM\-SHA256:ECDHE\-ECDSA\-AES256\-SHA384:ECDHE\-RSA\-AES256\-SHA384:ECDHE\-ECDSA\-AES128\-SHA256:ECDHE\-RSA\-AES128\-SHA256\fP
|
||||||
.UNINDENT
|
.UNINDENT
|
||||||
.INDENT 0.0
|
.INDENT 0.0
|
||||||
.TP
|
.TP
|
||||||
|
.B \-\-tls13\-client\-ciphers=<SUITE>
|
||||||
|
Set allowed cipher list for backend connection. The
|
||||||
|
format of the string is described in OpenSSL ciphers(1).
|
||||||
|
This option sets cipher suites for TLSv1.3. Use
|
||||||
|
\fI\%\-\-tls13\-client\-ciphers\fP for TLSv1.2 or earlier.
|
||||||
|
.sp
|
||||||
|
Default: \fBTLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256\fP
|
||||||
|
.UNINDENT
|
||||||
|
.INDENT 0.0
|
||||||
|
.TP
|
||||||
.B \-\-ecdh\-curves=<LIST>
|
.B \-\-ecdh\-curves=<LIST>
|
||||||
Set supported curve list for frontend connections.
|
Set supported curve list for frontend connections.
|
||||||
<LIST> is a colon separated list of curve NID or names
|
<LIST> is a colon separated list of curve NID or names
|
||||||
@@ -676,6 +763,14 @@ can contain multiple certificates.
|
|||||||
.UNINDENT
|
.UNINDENT
|
||||||
.INDENT 0.0
|
.INDENT 0.0
|
||||||
.TP
|
.TP
|
||||||
|
.B \-\-verify\-client\-tolerate\-expired
|
||||||
|
Accept expired client certificate. Operator should
|
||||||
|
handle the expired client certificate by some means
|
||||||
|
(e.g., mruby script). Otherwise, this option might
|
||||||
|
cause a security risk.
|
||||||
|
.UNINDENT
|
||||||
|
.INDENT 0.0
|
||||||
|
.TP
|
||||||
.B \-\-client\-private\-key\-file=<PATH>
|
.B \-\-client\-private\-key\-file=<PATH>
|
||||||
Path to file that contains client private key used in
|
Path to file that contains client private key used in
|
||||||
backend client authentication.
|
backend client authentication.
|
||||||
@@ -699,7 +794,7 @@ than TLSv1.2 is specified, make sure that the compatible
|
|||||||
ciphers are included in \fI\%\-\-ciphers\fP option. The default
|
ciphers are included in \fI\%\-\-ciphers\fP option. The default
|
||||||
cipher list only includes ciphers compatible with
|
cipher list only includes ciphers compatible with
|
||||||
TLSv1.2 or above. The available versions are:
|
TLSv1.2 or above. The available versions are:
|
||||||
TLSv1.2, TLSv1.1, and TLSv1.0
|
TLSv1.3, TLSv1.2, TLSv1.1, and TLSv1.0
|
||||||
.sp
|
.sp
|
||||||
Default: \fBTLSv1.2\fP
|
Default: \fBTLSv1.2\fP
|
||||||
.UNINDENT
|
.UNINDENT
|
||||||
@@ -712,9 +807,9 @@ done in case\-insensitive manner. The versions between
|
|||||||
enabled. If the protocol list advertised by client does
|
enabled. If the protocol list advertised by client does
|
||||||
not overlap this range, you will receive the error
|
not overlap this range, you will receive the error
|
||||||
message "unknown protocol". The available versions are:
|
message "unknown protocol". The available versions are:
|
||||||
TLSv1.2, TLSv1.1, and TLSv1.0
|
TLSv1.3, TLSv1.2, TLSv1.1, and TLSv1.0
|
||||||
.sp
|
.sp
|
||||||
Default: \fBTLSv1.2\fP
|
Default: \fBTLSv1.3\fP
|
||||||
.UNINDENT
|
.UNINDENT
|
||||||
.INDENT 0.0
|
.INDENT 0.0
|
||||||
.TP
|
.TP
|
||||||
@@ -967,14 +1062,32 @@ HTTP/2. To use those cipher suites with HTTP/2,
|
|||||||
consider to use \fI\%\-\-client\-no\-http2\-cipher\-black\-list\fP
|
consider to use \fI\%\-\-client\-no\-http2\-cipher\-black\-list\fP
|
||||||
option. But be aware its implications.
|
option. But be aware its implications.
|
||||||
.UNINDENT
|
.UNINDENT
|
||||||
.SS HTTP/2 and SPDY
|
.INDENT 0.0
|
||||||
|
.TP
|
||||||
|
.B \-\-tls\-no\-postpone\-early\-data
|
||||||
|
By default, nghttpx postpones forwarding HTTP requests
|
||||||
|
sent in early data, including those sent in partially in
|
||||||
|
it, until TLS handshake finishes. If all backend server
|
||||||
|
recognizes "Early\-Data" header field, using this option
|
||||||
|
makes nghttpx not postpone forwarding request and get
|
||||||
|
full potential of 0\-RTT data.
|
||||||
|
.UNINDENT
|
||||||
|
.INDENT 0.0
|
||||||
|
.TP
|
||||||
|
.B \-\-tls\-max\-early\-data=<SIZE>
|
||||||
|
Sets the maximum amount of 0\-RTT data that server
|
||||||
|
accepts.
|
||||||
|
.sp
|
||||||
|
Default: \fB16K\fP
|
||||||
|
.UNINDENT
|
||||||
|
.SS HTTP/2
|
||||||
.INDENT 0.0
|
.INDENT 0.0
|
||||||
.TP
|
.TP
|
||||||
.B \-c, \-\-frontend\-http2\-max\-concurrent\-streams=<N>
|
.B \-c, \-\-frontend\-http2\-max\-concurrent\-streams=<N>
|
||||||
Set the maximum number of the concurrent streams in one
|
Set the maximum number of the concurrent streams in one
|
||||||
frontend HTTP/2 and SPDY session.
|
frontend HTTP/2 session.
|
||||||
.sp
|
.sp
|
||||||
Default: \(ga\(ga 100\(ga\(ga
|
Default: \fB100\fP
|
||||||
.UNINDENT
|
.UNINDENT
|
||||||
.INDENT 0.0
|
.INDENT 0.0
|
||||||
.TP
|
.TP
|
||||||
@@ -989,17 +1102,16 @@ Default: \fB100\fP
|
|||||||
.INDENT 0.0
|
.INDENT 0.0
|
||||||
.TP
|
.TP
|
||||||
.B \-\-frontend\-http2\-window\-size=<SIZE>
|
.B \-\-frontend\-http2\-window\-size=<SIZE>
|
||||||
Sets the per\-stream initial window size of HTTP/2 and
|
Sets the per\-stream initial window size of HTTP/2
|
||||||
SPDY frontend connection.
|
frontend connection.
|
||||||
.sp
|
.sp
|
||||||
Default: \fB65535\fP
|
Default: \fB65535\fP
|
||||||
.UNINDENT
|
.UNINDENT
|
||||||
.INDENT 0.0
|
.INDENT 0.0
|
||||||
.TP
|
.TP
|
||||||
.B \-\-frontend\-http2\-connection\-window\-size=<SIZE>
|
.B \-\-frontend\-http2\-connection\-window\-size=<SIZE>
|
||||||
Sets the per\-connection window size of HTTP/2 and SPDY
|
Sets the per\-connection window size of HTTP/2 frontend
|
||||||
frontend connection. For SPDY connection, the value
|
connection.
|
||||||
less than 64KiB is rounded up to 64KiB.
|
|
||||||
.sp
|
.sp
|
||||||
Default: \fB65535\fP
|
Default: \fB65535\fP
|
||||||
.UNINDENT
|
.UNINDENT
|
||||||
@@ -1040,8 +1152,7 @@ default mode and HTTP/2 frontend via Link header field.
|
|||||||
It is also supported if both frontend and backend are
|
It is also supported if both frontend and backend are
|
||||||
HTTP/2 in default mode. In this case, server push from
|
HTTP/2 in default mode. In this case, server push from
|
||||||
backend session is relayed to frontend, and server push
|
backend session is relayed to frontend, and server push
|
||||||
via Link header field is also supported. SPDY frontend
|
via Link header field is also supported.
|
||||||
does not support server push.
|
|
||||||
.UNINDENT
|
.UNINDENT
|
||||||
.INDENT 0.0
|
.INDENT 0.0
|
||||||
.TP
|
.TP
|
||||||
@@ -1112,7 +1223,7 @@ Default: \fB4K\fP
|
|||||||
.INDENT 0.0
|
.INDENT 0.0
|
||||||
.TP
|
.TP
|
||||||
.B (default mode)
|
.B (default mode)
|
||||||
Accept HTTP/2, SPDY and HTTP/1.1 over SSL/TLS. "no\-tls"
|
Accept HTTP/2, and HTTP/1.1 over SSL/TLS. "no\-tls"
|
||||||
parameter is used in \fI\%\-\-frontend\fP option, accept HTTP/2
|
parameter is used in \fI\%\-\-frontend\fP option, accept HTTP/2
|
||||||
and HTTP/1.1 over cleartext TCP. The incoming HTTP/1.1
|
and HTTP/1.1 over cleartext TCP. The incoming HTTP/1.1
|
||||||
connection can be upgraded to HTTP/2 through HTTP
|
connection can be upgraded to HTTP/2 through HTTP
|
||||||
@@ -1184,6 +1295,21 @@ regardless of minor version.
|
|||||||
.IP \(bu 2
|
.IP \(bu 2
|
||||||
$tls_cipher: cipher used for SSL/TLS connection.
|
$tls_cipher: cipher used for SSL/TLS connection.
|
||||||
.IP \(bu 2
|
.IP \(bu 2
|
||||||
|
$tls_client_fingerprint_sha256: SHA\-256 fingerprint of
|
||||||
|
client certificate.
|
||||||
|
.IP \(bu 2
|
||||||
|
$tls_client_fingerprint_sha1: SHA\-1 fingerprint of
|
||||||
|
client certificate.
|
||||||
|
.IP \(bu 2
|
||||||
|
$tls_client_subject_name: subject name in client
|
||||||
|
certificate.
|
||||||
|
.IP \(bu 2
|
||||||
|
$tls_client_issuer_name: issuer name in client
|
||||||
|
certificate.
|
||||||
|
.IP \(bu 2
|
||||||
|
$tls_client_serial: serial number in client
|
||||||
|
certificate.
|
||||||
|
.IP \(bu 2
|
||||||
$tls_protocol: protocol for SSL/TLS connection.
|
$tls_protocol: protocol for SSL/TLS connection.
|
||||||
.IP \(bu 2
|
.IP \(bu 2
|
||||||
$tls_session_id: session ID for SSL/TLS connection.
|
$tls_session_id: session ID for SSL/TLS connection.
|
||||||
@@ -1317,6 +1443,12 @@ is received, it is left unaltered.
|
|||||||
.UNINDENT
|
.UNINDENT
|
||||||
.INDENT 0.0
|
.INDENT 0.0
|
||||||
.TP
|
.TP
|
||||||
|
.B \-\-no\-strip\-incoming\-early\-data
|
||||||
|
Don\(aqt strip Early\-Data header field from inbound client
|
||||||
|
requests.
|
||||||
|
.UNINDENT
|
||||||
|
.INDENT 0.0
|
||||||
|
.TP
|
||||||
.B \-\-no\-location\-rewrite
|
.B \-\-no\-location\-rewrite
|
||||||
Don\(aqt rewrite location header field in default mode.
|
Don\(aqt rewrite location header field in default mode.
|
||||||
When \fI\%\-\-http2\-proxy\fP is used, location header field will
|
When \fI\%\-\-http2\-proxy\fP is used, location header field will
|
||||||
@@ -1434,7 +1566,7 @@ Default: \fB443\fP
|
|||||||
.B \-\-api\-max\-request\-body=<SIZE>
|
.B \-\-api\-max\-request\-body=<SIZE>
|
||||||
Set the maximum size of request body for API request.
|
Set the maximum size of request body for API request.
|
||||||
.sp
|
.sp
|
||||||
Default: \fB16K\fP
|
Default: \fB32M\fP
|
||||||
.UNINDENT
|
.UNINDENT
|
||||||
.SS DNS
|
.SS DNS
|
||||||
.INDENT 0.0
|
.INDENT 0.0
|
||||||
@@ -1534,6 +1666,13 @@ signal handling feature is disabled.
|
|||||||
.B \-\-mruby\-file=<PATH>
|
.B \-\-mruby\-file=<PATH>
|
||||||
Set mruby script file
|
Set mruby script file
|
||||||
.UNINDENT
|
.UNINDENT
|
||||||
|
.INDENT 0.0
|
||||||
|
.TP
|
||||||
|
.B \-\-ignore\-per\-pattern\-mruby\-error
|
||||||
|
Ignore mruby compile error for per\-pattern mruby script
|
||||||
|
file. If error occurred, it is treated as if no mruby
|
||||||
|
file were specified for the pattern.
|
||||||
|
.UNINDENT
|
||||||
.SS Misc
|
.SS Misc
|
||||||
.INDENT 0.0
|
.INDENT 0.0
|
||||||
.TP
|
.TP
|
||||||
@@ -1634,7 +1773,7 @@ follows:
|
|||||||
.INDENT 7.0
|
.INDENT 7.0
|
||||||
.TP
|
.TP
|
||||||
.B <datetime>
|
.B <datetime>
|
||||||
It is a conbination of date and time when the log is written. It
|
It is a combination of date and time when the log is written. It
|
||||||
is in ISO 8601 format.
|
is in ISO 8601 format.
|
||||||
.TP
|
.TP
|
||||||
.B <master\-pid>
|
.B <master\-pid>
|
||||||
@@ -1789,7 +1928,7 @@ By default, session ID is shared by all worker threads.
|
|||||||
.sp
|
.sp
|
||||||
If \fI\%\-\-tls\-session\-cache\-memcached\fP is given, nghttpx will
|
If \fI\%\-\-tls\-session\-cache\-memcached\fP is given, nghttpx will
|
||||||
insert serialized session data to memcached with
|
insert serialized session data to memcached with
|
||||||
\fBnghttpx:tls\-session\-cache:\fP + lowercased hex string of session ID
|
\fBnghttpx:tls\-session\-cache:\fP + lowercase hex string of session ID
|
||||||
as a memcached entry key, with expiry time 12 hours. Session timeout
|
as a memcached entry key, with expiry time 12 hours. Session timeout
|
||||||
is set to 12 hours.
|
is set to 12 hours.
|
||||||
.sp
|
.sp
|
||||||
@@ -1871,6 +2010,17 @@ API is subject to change in the future release.
|
|||||||
.UNINDENT
|
.UNINDENT
|
||||||
.UNINDENT
|
.UNINDENT
|
||||||
.sp
|
.sp
|
||||||
|
\fBWARNING:\fP
|
||||||
|
.INDENT 0.0
|
||||||
|
.INDENT 3.5
|
||||||
|
Almost all string value returned from method, or attribute is a
|
||||||
|
fresh new mruby string, which involves memory allocation, and
|
||||||
|
copies. Therefore, it is strongly recommended to store a return
|
||||||
|
value in a local variable, and use it, instead of calling method or
|
||||||
|
accessing attribute repeatedly.
|
||||||
|
.UNINDENT
|
||||||
|
.UNINDENT
|
||||||
|
.sp
|
||||||
nghttpx allows users to extend its capability using mruby scripts.
|
nghttpx allows users to extend its capability using mruby scripts.
|
||||||
nghttpx has 2 hook points to execute mruby script: request phase and
|
nghttpx has 2 hook points to execute mruby script: request phase and
|
||||||
response phase. The request phase hook is invoked after all request
|
response phase. The request phase hook is invoked after all request
|
||||||
@@ -1880,9 +2030,28 @@ server. These hooks allows users to modify header fields, or common
|
|||||||
HTTP variables, like authority or request path, and even return custom
|
HTTP variables, like authority or request path, and even return custom
|
||||||
response without forwarding request to backend servers.
|
response without forwarding request to backend servers.
|
||||||
.sp
|
.sp
|
||||||
To specify mruby script file, use \fI\%\-\-mruby\-file\fP option. The
|
There are 2 levels of mruby script invocations: global and
|
||||||
script will be evaluated once per thread on startup, and it must
|
per\-pattern. The global mruby script is set by \fI\%\-\-mruby\-file\fP
|
||||||
instantiate object and evaluate it as the return value (e.g.,
|
option and is called for all requests. The per\-pattern mruby script
|
||||||
|
is set by "mruby" parameter in \fI\%\-b\fP option. It is invoked for
|
||||||
|
a request which matches the particular pattern. The order of hook
|
||||||
|
invocation is: global request phase hook, per\-pattern request phase
|
||||||
|
hook, per\-pattern response phase hook, and finally global response
|
||||||
|
phase hook. If a hook returns a response, any later hooks are not
|
||||||
|
invoked. The global request hook is invoked before the pattern
|
||||||
|
matching is made and changing request path may affect the pattern
|
||||||
|
matching.
|
||||||
|
.sp
|
||||||
|
Please note that request and response hooks of per\-pattern mruby
|
||||||
|
script for a single request might not come from the same script. This
|
||||||
|
might happen after a request hook is executed, backend failed for some
|
||||||
|
reason, and at the same time, backend configuration is replaced by API
|
||||||
|
request, and then the request uses new configuration on retry. The
|
||||||
|
response hook from new configuration, if it is specified, will be
|
||||||
|
invoked.
|
||||||
|
.sp
|
||||||
|
The all mruby script will be evaluated once per thread on startup, and
|
||||||
|
it must instantiate object and evaluate it as the return value (e.g.,
|
||||||
\fBApp.new\fP). This object is called app object. If app object
|
\fBApp.new\fP). This object is called app object. If app object
|
||||||
defines \fBon_req\fP method, it is called with \fI\%Nghttpx::Env\fP
|
defines \fBon_req\fP method, it is called with \fI\%Nghttpx::Env\fP
|
||||||
object on request hook. Similarly, if app object defines \fBon_resp\fP
|
object on request hook. Similarly, if app object defines \fBon_resp\fP
|
||||||
@@ -1919,7 +2088,7 @@ Return \fI\%Response\fP object.
|
|||||||
.TP
|
.TP
|
||||||
.B attribute [R] ctx
|
.B attribute [R] ctx
|
||||||
Return Ruby hash object. It persists until request finishes.
|
Return Ruby hash object. It persists until request finishes.
|
||||||
So values set in request phase hoo can be retrieved in
|
So values set in request phase hook can be retrieved in
|
||||||
response phase hook.
|
response phase hook.
|
||||||
.UNINDENT
|
.UNINDENT
|
||||||
.INDENT 7.0
|
.INDENT 7.0
|
||||||
@@ -1957,6 +2126,77 @@ Return true if TLS is used on the connection.
|
|||||||
.B attribute [R] tls_sni
|
.B attribute [R] tls_sni
|
||||||
Return the TLS SNI value which client sent in this connection.
|
Return the TLS SNI value which client sent in this connection.
|
||||||
.UNINDENT
|
.UNINDENT
|
||||||
|
.INDENT 7.0
|
||||||
|
.TP
|
||||||
|
.B attribute [R] tls_client_fingerprint_sha256
|
||||||
|
Return the SHA\-256 fingerprint of a client certificate.
|
||||||
|
.UNINDENT
|
||||||
|
.INDENT 7.0
|
||||||
|
.TP
|
||||||
|
.B attribute [R] tls_client_fingerprint_sha1
|
||||||
|
Return the SHA\-1 fingerprint of a client certificate.
|
||||||
|
.UNINDENT
|
||||||
|
.INDENT 7.0
|
||||||
|
.TP
|
||||||
|
.B attribute [R] tls_client_issuer_name
|
||||||
|
Return the issuer name of a client certificate.
|
||||||
|
.UNINDENT
|
||||||
|
.INDENT 7.0
|
||||||
|
.TP
|
||||||
|
.B attribute [R] tls_client_subject_name
|
||||||
|
Return the subject name of a client certificate.
|
||||||
|
.UNINDENT
|
||||||
|
.INDENT 7.0
|
||||||
|
.TP
|
||||||
|
.B attribute [R] tls_client_serial
|
||||||
|
Return the serial number of a client certificate.
|
||||||
|
.UNINDENT
|
||||||
|
.INDENT 7.0
|
||||||
|
.TP
|
||||||
|
.B attribute [R] tls_client_not_before
|
||||||
|
Return the start date of a client certificate in seconds since
|
||||||
|
the epoch.
|
||||||
|
.UNINDENT
|
||||||
|
.INDENT 7.0
|
||||||
|
.TP
|
||||||
|
.B attribute [R] tls_client_not_after
|
||||||
|
Return the end date of a client certificate in seconds since
|
||||||
|
the epoch.
|
||||||
|
.UNINDENT
|
||||||
|
.INDENT 7.0
|
||||||
|
.TP
|
||||||
|
.B attribute [R] tls_cipher
|
||||||
|
Return a TLS cipher negotiated in this connection.
|
||||||
|
.UNINDENT
|
||||||
|
.INDENT 7.0
|
||||||
|
.TP
|
||||||
|
.B attribute [R] tls_protocol
|
||||||
|
Return a TLS protocol version negotiated in this connection.
|
||||||
|
.UNINDENT
|
||||||
|
.INDENT 7.0
|
||||||
|
.TP
|
||||||
|
.B attribute [R] tls_session_id
|
||||||
|
Return a session ID for this connection in hex string.
|
||||||
|
.UNINDENT
|
||||||
|
.INDENT 7.0
|
||||||
|
.TP
|
||||||
|
.B attribute [R] tls_session_reused
|
||||||
|
Return true if, and only if a SSL/TLS session is reused.
|
||||||
|
.UNINDENT
|
||||||
|
.INDENT 7.0
|
||||||
|
.TP
|
||||||
|
.B attribute [R] alpn
|
||||||
|
Return ALPN identifier negotiated in this connection.
|
||||||
|
.UNINDENT
|
||||||
|
.INDENT 7.0
|
||||||
|
.TP
|
||||||
|
.B attribute [R] tls_handshake_finished
|
||||||
|
Return true if SSL/TLS handshake has finished. If it returns
|
||||||
|
false in the request phase hook, the request is received in
|
||||||
|
TLSv1.3 early data (0\-RTT) and might be vulnerable to the
|
||||||
|
replay attack. nghttpx will send Early\-Data header field to
|
||||||
|
backend servers to indicate this.
|
||||||
|
.UNINDENT
|
||||||
.UNINDENT
|
.UNINDENT
|
||||||
.INDENT 0.0
|
.INDENT 0.0
|
||||||
.TP
|
.TP
|
||||||
@@ -2108,10 +2348,10 @@ to the backend, and response phase hook for this request will
|
|||||||
not be invoked. When this method is called in response phase
|
not be invoked. When this method is called in response phase
|
||||||
hook, response from backend server is canceled and discarded.
|
hook, response from backend server is canceled and discarded.
|
||||||
The status code and response header fields should be set
|
The status code and response header fields should be set
|
||||||
before using this method. To set status code, use :rb:meth To
|
before using this method. To set status code, use
|
||||||
set response header fields, use
|
|
||||||
\fI\%Nghttpx::Response#status\fP\&. If status code is not
|
\fI\%Nghttpx::Response#status\fP\&. If status code is not
|
||||||
set, 200 is used. \fI\%Nghttpx::Response#add_header\fP and
|
set, 200 is used. To set response header fields,
|
||||||
|
\fI\%Nghttpx::Response#add_header\fP and
|
||||||
\fI\%Nghttpx::Response#set_header\fP\&. When this method is
|
\fI\%Nghttpx::Response#set_header\fP\&. When this method is
|
||||||
invoked in response phase hook, the response headers are
|
invoked in response phase hook, the response headers are
|
||||||
filled with the ones received from backend server. To send
|
filled with the ones received from backend server. To send
|
||||||
@@ -2234,7 +2474,7 @@ The replacement is done instantly without breaking existing
|
|||||||
connections or requests. It also avoids any process creation as is
|
connections or requests. It also avoids any process creation as is
|
||||||
the case with hot swapping with signals.
|
the case with hot swapping with signals.
|
||||||
.sp
|
.sp
|
||||||
The one limitation is that only numeric IP address is allowd in
|
The one limitation is that only numeric IP address is allowed in
|
||||||
\fI\%backend\fP in request body unless "dns" parameter
|
\fI\%backend\fP in request body unless "dns" parameter
|
||||||
is used while non numeric hostname is allowed in command\-line or
|
is used while non numeric hostname is allowed in command\-line or
|
||||||
configuration file is read using \fI\%\-\-conf\fP\&.
|
configuration file is read using \fI\%\-\-conf\fP\&.
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ SYNOPSIS
|
|||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
-----------
|
-----------
|
||||||
|
|
||||||
A reverse proxy for HTTP/2, HTTP/1 and SPDY.
|
A reverse proxy for HTTP/2, and HTTP/1.
|
||||||
|
|
||||||
.. describe:: <PRIVATE_KEY>
|
.. describe:: <PRIVATE_KEY>
|
||||||
|
|
||||||
@@ -59,7 +59,7 @@ Connections
|
|||||||
"*/*", it performs exact match against the request path.
|
"*/*", it performs exact match against the request path.
|
||||||
If host is given, it performs a match against the
|
If host is given, it performs a match against the
|
||||||
request host. For a request received on the frontend
|
request host. For a request received on the frontend
|
||||||
lister with "sni-fwd" parameter enabled, SNI host is
|
listener with "sni-fwd" parameter enabled, SNI host is
|
||||||
used instead of a request host. If host alone is given,
|
used instead of a request host. If host alone is given,
|
||||||
"*/*" is appended to it, so that it matches all request
|
"*/*" is appended to it, so that it matches all request
|
||||||
paths under the host (e.g., specifying "nghttp2.org"
|
paths under the host (e.g., specifying "nghttp2.org"
|
||||||
@@ -121,7 +121,10 @@ Connections
|
|||||||
The parameters are delimited by ";". The available
|
The parameters are delimited by ";". The available
|
||||||
parameters are: "proto=<PROTO>", "tls",
|
parameters are: "proto=<PROTO>", "tls",
|
||||||
"sni=<SNI_HOST>", "fall=<N>", "rise=<N>",
|
"sni=<SNI_HOST>", "fall=<N>", "rise=<N>",
|
||||||
"affinity=<METHOD>", "dns", and "redirect-if-not-tls".
|
"affinity=<METHOD>", "dns", "redirect-if-not-tls",
|
||||||
|
"upgrade-scheme", "mruby=<PATH>",
|
||||||
|
"read-timeout=<DURATION>", "write-timeout=<DURATION>",
|
||||||
|
"group=<GROUP>", "group-weight=<N>", and "weight=<N>".
|
||||||
The parameter consists of keyword, and optionally
|
The parameter consists of keyword, and optionally
|
||||||
followed by "=" and value. For example, the parameter
|
followed by "=" and value. For example, the parameter
|
||||||
"proto=h2" consists of the keyword "proto" and value
|
"proto=h2" consists of the keyword "proto" and value
|
||||||
@@ -164,16 +167,32 @@ Connections
|
|||||||
The session affinity is enabled using
|
The session affinity is enabled using
|
||||||
"affinity=<METHOD>" parameter. If "ip" is given in
|
"affinity=<METHOD>" parameter. If "ip" is given in
|
||||||
<METHOD>, client IP based session affinity is enabled.
|
<METHOD>, client IP based session affinity is enabled.
|
||||||
If "none" is given in <METHOD>, session affinity is
|
If "cookie" is given in <METHOD>, cookie based session
|
||||||
disabled, and this is the default. The session affinity
|
affinity is enabled. If "none" is given in <METHOD>,
|
||||||
is enabled per <PATTERN>. If at least one backend has
|
session affinity is disabled, and this is the default.
|
||||||
"affinity" parameter, and its <METHOD> is not "none",
|
The session affinity is enabled per <PATTERN>. If at
|
||||||
session affinity is enabled for all backend servers
|
least one backend has "affinity" parameter, and its
|
||||||
sharing the same <PATTERN>. It is advised to set
|
<METHOD> is not "none", session affinity is enabled for
|
||||||
"affinity" parameter to all backend explicitly if
|
all backend servers sharing the same <PATTERN>. It is
|
||||||
session affinity is desired. The session affinity may
|
advised to set "affinity" parameter to all backend
|
||||||
break if one of the backend gets unreachable, or backend
|
explicitly if session affinity is desired. The session
|
||||||
settings are reloaded or replaced by API.
|
affinity may break if one of the backend gets
|
||||||
|
unreachable, or backend settings are reloaded or
|
||||||
|
replaced by API.
|
||||||
|
|
||||||
|
If "affinity=cookie" is used, the additional
|
||||||
|
configuration is required.
|
||||||
|
"affinity-cookie-name=<NAME>" must be used to specify a
|
||||||
|
name of cookie to use. Optionally,
|
||||||
|
"affinity-cookie-path=<PATH>" can be used to specify a
|
||||||
|
path which cookie is applied. The optional
|
||||||
|
"affinity-cookie-secure=<SECURE>" controls the Secure
|
||||||
|
attribute of a cookie. The default value is "auto", and
|
||||||
|
the Secure attribute is determined by a request scheme.
|
||||||
|
If a request scheme is "https", then Secure attribute is
|
||||||
|
set. Otherwise, it is not set. If <SECURE> is "yes",
|
||||||
|
the Secure attribute is always set. If <SECURE> is
|
||||||
|
"no", the Secure attribute is always omitted.
|
||||||
|
|
||||||
By default, name resolution of backend host name is done
|
By default, name resolution of backend host name is done
|
||||||
at start up, or reloading configuration. If "dns"
|
at start up, or reloading configuration. If "dns"
|
||||||
@@ -196,6 +215,51 @@ Connections
|
|||||||
"redirect-if-no-tls" parameter to all backends
|
"redirect-if-no-tls" parameter to all backends
|
||||||
explicitly if this feature is desired.
|
explicitly if this feature is desired.
|
||||||
|
|
||||||
|
If "upgrade-scheme" parameter is used along with "tls"
|
||||||
|
parameter, HTTP/2 :scheme pseudo header field is changed
|
||||||
|
to "https" from "http" when forwarding a request to this
|
||||||
|
particular backend. This is a workaround for a backend
|
||||||
|
server which requires "https" :scheme pseudo header
|
||||||
|
field on TLS encrypted connection.
|
||||||
|
|
||||||
|
"mruby=<PATH>" parameter specifies a path to mruby
|
||||||
|
script file which is invoked when this pattern is
|
||||||
|
matched. All backends which share the same pattern must
|
||||||
|
have the same mruby path.
|
||||||
|
|
||||||
|
"read-timeout=<DURATION>" and "write-timeout=<DURATION>"
|
||||||
|
parameters specify the read and write timeout of the
|
||||||
|
backend connection when this pattern is matched. All
|
||||||
|
backends which share the same pattern must have the same
|
||||||
|
timeouts. If these timeouts are entirely omitted for a
|
||||||
|
pattern, :option:`--backend-read-timeout` and
|
||||||
|
:option:`--backend-write-timeout` are used.
|
||||||
|
|
||||||
|
"group=<GROUP>" parameter specifies the name of group
|
||||||
|
this backend address belongs to. By default, it belongs
|
||||||
|
to the unnamed default group. The name of group is
|
||||||
|
unique per pattern. "group-weight=<N>" parameter
|
||||||
|
specifies the weight of the group. The higher weight
|
||||||
|
gets more frequently selected by the load balancing
|
||||||
|
algorithm. <N> must be [1, 256] inclusive. The weight
|
||||||
|
8 has 4 times more weight than 2. <N> must be the same
|
||||||
|
for all addresses which share the same <GROUP>. If
|
||||||
|
"group-weight" is omitted in an address, but the other
|
||||||
|
address which belongs to the same group specifies
|
||||||
|
"group-weight", its weight is used. If no
|
||||||
|
"group-weight" is specified for all addresses, the
|
||||||
|
weight of a group becomes 1. "group" and "group-weight"
|
||||||
|
are ignored if session affinity is enabled.
|
||||||
|
|
||||||
|
"weight=<N>" parameter specifies the weight of the
|
||||||
|
backend address inside a group which this address
|
||||||
|
belongs to. The higher weight gets more frequently
|
||||||
|
selected by the load balancing algorithm. <N> must be
|
||||||
|
[1, 256] inclusive. The weight 8 has 4 times more
|
||||||
|
weight than weight 2. If this parameter is omitted,
|
||||||
|
weight becomes 1. "weight" is ignored if session
|
||||||
|
affinity is enabled.
|
||||||
|
|
||||||
Since ";" and ":" are used as delimiter, <PATTERN> must
|
Since ";" and ":" are used as delimiter, <PATTERN> must
|
||||||
not contain these characters. Since ";" has special
|
not contain these characters. Since ";" has special
|
||||||
meaning in shell, the option value must be quoted.
|
meaning in shell, the option value must be quoted.
|
||||||
@@ -424,8 +488,7 @@ Timeout
|
|||||||
|
|
||||||
.. option:: --frontend-http2-read-timeout=<DURATION>
|
.. option:: --frontend-http2-read-timeout=<DURATION>
|
||||||
|
|
||||||
Specify read timeout for HTTP/2 and SPDY frontend
|
Specify read timeout for HTTP/2 frontend connection.
|
||||||
connection.
|
|
||||||
|
|
||||||
Default: ``3m``
|
Default: ``3m``
|
||||||
|
|
||||||
@@ -450,15 +513,15 @@ Timeout
|
|||||||
|
|
||||||
.. option:: --stream-read-timeout=<DURATION>
|
.. option:: --stream-read-timeout=<DURATION>
|
||||||
|
|
||||||
Specify read timeout for HTTP/2 and SPDY streams. 0
|
Specify read timeout for HTTP/2 streams. 0 means no
|
||||||
means no timeout.
|
timeout.
|
||||||
|
|
||||||
Default: ``0``
|
Default: ``0``
|
||||||
|
|
||||||
.. option:: --stream-write-timeout=<DURATION>
|
.. option:: --stream-write-timeout=<DURATION>
|
||||||
|
|
||||||
Specify write timeout for HTTP/2 and SPDY streams. 0
|
Specify write timeout for HTTP/2 streams. 0 means no
|
||||||
means no timeout.
|
timeout.
|
||||||
|
|
||||||
Default: ``1m``
|
Default: ``1m``
|
||||||
|
|
||||||
@@ -531,16 +594,38 @@ SSL/TLS
|
|||||||
|
|
||||||
Set allowed cipher list for frontend connection. The
|
Set allowed cipher list for frontend connection. The
|
||||||
format of the string is described in OpenSSL ciphers(1).
|
format of the string is described in OpenSSL ciphers(1).
|
||||||
|
This option sets cipher suites for TLSv1.2 or earlier.
|
||||||
|
Use :option:`--tls13-ciphers` for TLSv1.3.
|
||||||
|
|
||||||
Default: ``ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256``
|
Default: ``ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256``
|
||||||
|
|
||||||
|
.. option:: --tls13-ciphers=<SUITE>
|
||||||
|
|
||||||
|
Set allowed cipher list for frontend connection. The
|
||||||
|
format of the string is described in OpenSSL ciphers(1).
|
||||||
|
This option sets cipher suites for TLSv1.3. Use
|
||||||
|
:option:`--ciphers` for TLSv1.2 or earlier.
|
||||||
|
|
||||||
|
Default: ``TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256``
|
||||||
|
|
||||||
.. option:: --client-ciphers=<SUITE>
|
.. option:: --client-ciphers=<SUITE>
|
||||||
|
|
||||||
Set allowed cipher list for backend connection. The
|
Set allowed cipher list for backend connection. The
|
||||||
format of the string is described in OpenSSL ciphers(1).
|
format of the string is described in OpenSSL ciphers(1).
|
||||||
|
This option sets cipher suites for TLSv1.2 or earlier.
|
||||||
|
Use :option:`--tls13-client-ciphers` for TLSv1.3.
|
||||||
|
|
||||||
Default: ``ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256``
|
Default: ``ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256``
|
||||||
|
|
||||||
|
.. option:: --tls13-client-ciphers=<SUITE>
|
||||||
|
|
||||||
|
Set allowed cipher list for backend connection. The
|
||||||
|
format of the string is described in OpenSSL ciphers(1).
|
||||||
|
This option sets cipher suites for TLSv1.3. Use
|
||||||
|
:option:`--tls13-client-ciphers` for TLSv1.2 or earlier.
|
||||||
|
|
||||||
|
Default: ``TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256``
|
||||||
|
|
||||||
.. option:: --ecdh-curves=<LIST>
|
.. option:: --ecdh-curves=<LIST>
|
||||||
|
|
||||||
Set supported curve list for frontend connections.
|
Set supported curve list for frontend connections.
|
||||||
@@ -622,6 +707,13 @@ SSL/TLS
|
|||||||
client certificate. The file must be in PEM format. It
|
client certificate. The file must be in PEM format. It
|
||||||
can contain multiple certificates.
|
can contain multiple certificates.
|
||||||
|
|
||||||
|
.. option:: --verify-client-tolerate-expired
|
||||||
|
|
||||||
|
Accept expired client certificate. Operator should
|
||||||
|
handle the expired client certificate by some means
|
||||||
|
(e.g., mruby script). Otherwise, this option might
|
||||||
|
cause a security risk.
|
||||||
|
|
||||||
.. option:: --client-private-key-file=<PATH>
|
.. option:: --client-private-key-file=<PATH>
|
||||||
|
|
||||||
Path to file that contains client private key used in
|
Path to file that contains client private key used in
|
||||||
@@ -644,7 +736,7 @@ SSL/TLS
|
|||||||
ciphers are included in :option:`--ciphers` option. The default
|
ciphers are included in :option:`--ciphers` option. The default
|
||||||
cipher list only includes ciphers compatible with
|
cipher list only includes ciphers compatible with
|
||||||
TLSv1.2 or above. The available versions are:
|
TLSv1.2 or above. The available versions are:
|
||||||
TLSv1.2, TLSv1.1, and TLSv1.0
|
TLSv1.3, TLSv1.2, TLSv1.1, and TLSv1.0
|
||||||
|
|
||||||
Default: ``TLSv1.2``
|
Default: ``TLSv1.2``
|
||||||
|
|
||||||
@@ -656,9 +748,9 @@ SSL/TLS
|
|||||||
enabled. If the protocol list advertised by client does
|
enabled. If the protocol list advertised by client does
|
||||||
not overlap this range, you will receive the error
|
not overlap this range, you will receive the error
|
||||||
message "unknown protocol". The available versions are:
|
message "unknown protocol". The available versions are:
|
||||||
TLSv1.2, TLSv1.1, and TLSv1.0
|
TLSv1.3, TLSv1.2, TLSv1.1, and TLSv1.0
|
||||||
|
|
||||||
Default: ``TLSv1.2``
|
Default: ``TLSv1.3``
|
||||||
|
|
||||||
.. option:: --tls-ticket-key-file=<PATH>
|
.. option:: --tls-ticket-key-file=<PATH>
|
||||||
|
|
||||||
@@ -886,16 +978,32 @@ SSL/TLS
|
|||||||
consider to use :option:`--client-no-http2-cipher-black-list`
|
consider to use :option:`--client-no-http2-cipher-black-list`
|
||||||
option. But be aware its implications.
|
option. But be aware its implications.
|
||||||
|
|
||||||
|
.. option:: --tls-no-postpone-early-data
|
||||||
|
|
||||||
HTTP/2 and SPDY
|
By default, nghttpx postpones forwarding HTTP requests
|
||||||
~~~~~~~~~~~~~~~
|
sent in early data, including those sent in partially in
|
||||||
|
it, until TLS handshake finishes. If all backend server
|
||||||
|
recognizes "Early-Data" header field, using this option
|
||||||
|
makes nghttpx not postpone forwarding request and get
|
||||||
|
full potential of 0-RTT data.
|
||||||
|
|
||||||
|
.. option:: --tls-max-early-data=<SIZE>
|
||||||
|
|
||||||
|
Sets the maximum amount of 0-RTT data that server
|
||||||
|
accepts.
|
||||||
|
|
||||||
|
Default: ``16K``
|
||||||
|
|
||||||
|
|
||||||
|
HTTP/2
|
||||||
|
~~~~~~
|
||||||
|
|
||||||
.. option:: -c, --frontend-http2-max-concurrent-streams=<N>
|
.. option:: -c, --frontend-http2-max-concurrent-streams=<N>
|
||||||
|
|
||||||
Set the maximum number of the concurrent streams in one
|
Set the maximum number of the concurrent streams in one
|
||||||
frontend HTTP/2 and SPDY session.
|
frontend HTTP/2 session.
|
||||||
|
|
||||||
Default: `` 100``
|
Default: ``100``
|
||||||
|
|
||||||
.. option:: --backend-http2-max-concurrent-streams=<N>
|
.. option:: --backend-http2-max-concurrent-streams=<N>
|
||||||
|
|
||||||
@@ -908,16 +1016,15 @@ HTTP/2 and SPDY
|
|||||||
|
|
||||||
.. option:: --frontend-http2-window-size=<SIZE>
|
.. option:: --frontend-http2-window-size=<SIZE>
|
||||||
|
|
||||||
Sets the per-stream initial window size of HTTP/2 and
|
Sets the per-stream initial window size of HTTP/2
|
||||||
SPDY frontend connection.
|
frontend connection.
|
||||||
|
|
||||||
Default: ``65535``
|
Default: ``65535``
|
||||||
|
|
||||||
.. option:: --frontend-http2-connection-window-size=<SIZE>
|
.. option:: --frontend-http2-connection-window-size=<SIZE>
|
||||||
|
|
||||||
Sets the per-connection window size of HTTP/2 and SPDY
|
Sets the per-connection window size of HTTP/2 frontend
|
||||||
frontend connection. For SPDY connection, the value
|
connection.
|
||||||
less than 64KiB is rounded up to 64KiB.
|
|
||||||
|
|
||||||
Default: ``65535``
|
Default: ``65535``
|
||||||
|
|
||||||
@@ -953,8 +1060,7 @@ HTTP/2 and SPDY
|
|||||||
It is also supported if both frontend and backend are
|
It is also supported if both frontend and backend are
|
||||||
HTTP/2 in default mode. In this case, server push from
|
HTTP/2 in default mode. In this case, server push from
|
||||||
backend session is relayed to frontend, and server push
|
backend session is relayed to frontend, and server push
|
||||||
via Link header field is also supported. SPDY frontend
|
via Link header field is also supported.
|
||||||
does not support server push.
|
|
||||||
|
|
||||||
.. option:: --frontend-http2-optimize-write-buffer-size
|
.. option:: --frontend-http2-optimize-write-buffer-size
|
||||||
|
|
||||||
@@ -1022,7 +1128,7 @@ Mode
|
|||||||
.. describe:: (default mode)
|
.. describe:: (default mode)
|
||||||
|
|
||||||
|
|
||||||
Accept HTTP/2, SPDY and HTTP/1.1 over SSL/TLS. "no-tls"
|
Accept HTTP/2, and HTTP/1.1 over SSL/TLS. "no-tls"
|
||||||
parameter is used in :option:`--frontend` option, accept HTTP/2
|
parameter is used in :option:`--frontend` option, accept HTTP/2
|
||||||
and HTTP/1.1 over cleartext TCP. The incoming HTTP/1.1
|
and HTTP/1.1 over cleartext TCP. The incoming HTTP/1.1
|
||||||
connection can be upgraded to HTTP/2 through HTTP
|
connection can be upgraded to HTTP/2 through HTTP
|
||||||
@@ -1078,6 +1184,16 @@ Logging
|
|||||||
the response. For HTTP/1, ALPN is always http/1.1,
|
the response. For HTTP/1, ALPN is always http/1.1,
|
||||||
regardless of minor version.
|
regardless of minor version.
|
||||||
* $tls_cipher: cipher used for SSL/TLS connection.
|
* $tls_cipher: cipher used for SSL/TLS connection.
|
||||||
|
* $tls_client_fingerprint_sha256: SHA-256 fingerprint of
|
||||||
|
client certificate.
|
||||||
|
* $tls_client_fingerprint_sha1: SHA-1 fingerprint of
|
||||||
|
client certificate.
|
||||||
|
* $tls_client_subject_name: subject name in client
|
||||||
|
certificate.
|
||||||
|
* $tls_client_issuer_name: issuer name in client
|
||||||
|
certificate.
|
||||||
|
* $tls_client_serial: serial number in client
|
||||||
|
certificate.
|
||||||
* $tls_protocol: protocol for SSL/TLS connection.
|
* $tls_protocol: protocol for SSL/TLS connection.
|
||||||
* $tls_session_id: session ID for SSL/TLS connection.
|
* $tls_session_id: session ID for SSL/TLS connection.
|
||||||
* $tls_session_reused: "r" if SSL/TLS session was
|
* $tls_session_reused: "r" if SSL/TLS session was
|
||||||
@@ -1194,6 +1310,11 @@ HTTP
|
|||||||
Don't append to Via header field. If Via header field
|
Don't append to Via header field. If Via header field
|
||||||
is received, it is left unaltered.
|
is received, it is left unaltered.
|
||||||
|
|
||||||
|
.. option:: --no-strip-incoming-early-data
|
||||||
|
|
||||||
|
Don't strip Early-Data header field from inbound client
|
||||||
|
requests.
|
||||||
|
|
||||||
.. option:: --no-location-rewrite
|
.. option:: --no-location-rewrite
|
||||||
|
|
||||||
Don't rewrite location header field in default mode.
|
Don't rewrite location header field in default mode.
|
||||||
@@ -1302,7 +1423,7 @@ API
|
|||||||
|
|
||||||
Set the maximum size of request body for API request.
|
Set the maximum size of request body for API request.
|
||||||
|
|
||||||
Default: ``16K``
|
Default: ``32M``
|
||||||
|
|
||||||
|
|
||||||
DNS
|
DNS
|
||||||
@@ -1402,6 +1523,12 @@ Scripting
|
|||||||
|
|
||||||
Set mruby script file
|
Set mruby script file
|
||||||
|
|
||||||
|
.. option:: --ignore-per-pattern-mruby-error
|
||||||
|
|
||||||
|
Ignore mruby compile error for per-pattern mruby script
|
||||||
|
file. If error occurred, it is treated as if no mruby
|
||||||
|
file were specified for the pattern.
|
||||||
|
|
||||||
|
|
||||||
Misc
|
Misc
|
||||||
~~~~
|
~~~~
|
||||||
@@ -1490,7 +1617,7 @@ Error log
|
|||||||
<datetime> <master-pid> <current-pid> <thread-id> <level> (<filename>:<line>) <msg>
|
<datetime> <master-pid> <current-pid> <thread-id> <level> (<filename>:<line>) <msg>
|
||||||
|
|
||||||
<datetime>
|
<datetime>
|
||||||
It is a conbination of date and time when the log is written. It
|
It is a combination of date and time when the log is written. It
|
||||||
is in ISO 8601 format.
|
is in ISO 8601 format.
|
||||||
|
|
||||||
<master-pid>
|
<master-pid>
|
||||||
@@ -1641,7 +1768,7 @@ By default, session ID is shared by all worker threads.
|
|||||||
|
|
||||||
If :option:`--tls-session-cache-memcached` is given, nghttpx will
|
If :option:`--tls-session-cache-memcached` is given, nghttpx will
|
||||||
insert serialized session data to memcached with
|
insert serialized session data to memcached with
|
||||||
``nghttpx:tls-session-cache:`` + lowercased hex string of session ID
|
``nghttpx:tls-session-cache:`` + lowercase hex string of session ID
|
||||||
as a memcached entry key, with expiry time 12 hours. Session timeout
|
as a memcached entry key, with expiry time 12 hours. Session timeout
|
||||||
is set to 12 hours.
|
is set to 12 hours.
|
||||||
|
|
||||||
@@ -1723,6 +1850,14 @@ MRUBY SCRIPTING
|
|||||||
The current mruby extension API is experimental and not frozen. The
|
The current mruby extension API is experimental and not frozen. The
|
||||||
API is subject to change in the future release.
|
API is subject to change in the future release.
|
||||||
|
|
||||||
|
.. warning::
|
||||||
|
|
||||||
|
Almost all string value returned from method, or attribute is a
|
||||||
|
fresh new mruby string, which involves memory allocation, and
|
||||||
|
copies. Therefore, it is strongly recommended to store a return
|
||||||
|
value in a local variable, and use it, instead of calling method or
|
||||||
|
accessing attribute repeatedly.
|
||||||
|
|
||||||
nghttpx allows users to extend its capability using mruby scripts.
|
nghttpx allows users to extend its capability using mruby scripts.
|
||||||
nghttpx has 2 hook points to execute mruby script: request phase and
|
nghttpx has 2 hook points to execute mruby script: request phase and
|
||||||
response phase. The request phase hook is invoked after all request
|
response phase. The request phase hook is invoked after all request
|
||||||
@@ -1732,9 +1867,28 @@ server. These hooks allows users to modify header fields, or common
|
|||||||
HTTP variables, like authority or request path, and even return custom
|
HTTP variables, like authority or request path, and even return custom
|
||||||
response without forwarding request to backend servers.
|
response without forwarding request to backend servers.
|
||||||
|
|
||||||
To specify mruby script file, use :option:`--mruby-file` option. The
|
There are 2 levels of mruby script invocations: global and
|
||||||
script will be evaluated once per thread on startup, and it must
|
per-pattern. The global mruby script is set by :option:`--mruby-file`
|
||||||
instantiate object and evaluate it as the return value (e.g.,
|
option and is called for all requests. The per-pattern mruby script
|
||||||
|
is set by "mruby" parameter in :option:`-b` option. It is invoked for
|
||||||
|
a request which matches the particular pattern. The order of hook
|
||||||
|
invocation is: global request phase hook, per-pattern request phase
|
||||||
|
hook, per-pattern response phase hook, and finally global response
|
||||||
|
phase hook. If a hook returns a response, any later hooks are not
|
||||||
|
invoked. The global request hook is invoked before the pattern
|
||||||
|
matching is made and changing request path may affect the pattern
|
||||||
|
matching.
|
||||||
|
|
||||||
|
Please note that request and response hooks of per-pattern mruby
|
||||||
|
script for a single request might not come from the same script. This
|
||||||
|
might happen after a request hook is executed, backend failed for some
|
||||||
|
reason, and at the same time, backend configuration is replaced by API
|
||||||
|
request, and then the request uses new configuration on retry. The
|
||||||
|
response hook from new configuration, if it is specified, will be
|
||||||
|
invoked.
|
||||||
|
|
||||||
|
The all mruby script will be evaluated once per thread on startup, and
|
||||||
|
it must instantiate object and evaluate it as the return value (e.g.,
|
||||||
``App.new``). This object is called app object. If app object
|
``App.new``). This object is called app object. If app object
|
||||||
defines ``on_req`` method, it is called with :rb:class:`Nghttpx::Env`
|
defines ``on_req`` method, it is called with :rb:class:`Nghttpx::Env`
|
||||||
object on request hook. Similarly, if app object defines ``on_resp``
|
object on request hook. Similarly, if app object defines ``on_resp``
|
||||||
@@ -1769,7 +1923,7 @@ respectively.
|
|||||||
.. rb:attr_reader:: ctx
|
.. rb:attr_reader:: ctx
|
||||||
|
|
||||||
Return Ruby hash object. It persists until request finishes.
|
Return Ruby hash object. It persists until request finishes.
|
||||||
So values set in request phase hoo can be retrieved in
|
So values set in request phase hook can be retrieved in
|
||||||
response phase hook.
|
response phase hook.
|
||||||
|
|
||||||
.. rb:attr_reader:: phase
|
.. rb:attr_reader:: phase
|
||||||
@@ -1801,6 +1955,64 @@ respectively.
|
|||||||
|
|
||||||
Return the TLS SNI value which client sent in this connection.
|
Return the TLS SNI value which client sent in this connection.
|
||||||
|
|
||||||
|
.. rb:attr_reader:: tls_client_fingerprint_sha256
|
||||||
|
|
||||||
|
Return the SHA-256 fingerprint of a client certificate.
|
||||||
|
|
||||||
|
.. rb:attr_reader:: tls_client_fingerprint_sha1
|
||||||
|
|
||||||
|
Return the SHA-1 fingerprint of a client certificate.
|
||||||
|
|
||||||
|
.. rb:attr_reader:: tls_client_issuer_name
|
||||||
|
|
||||||
|
Return the issuer name of a client certificate.
|
||||||
|
|
||||||
|
.. rb:attr_reader:: tls_client_subject_name
|
||||||
|
|
||||||
|
Return the subject name of a client certificate.
|
||||||
|
|
||||||
|
.. rb:attr_reader:: tls_client_serial
|
||||||
|
|
||||||
|
Return the serial number of a client certificate.
|
||||||
|
|
||||||
|
.. rb:attr_reader:: tls_client_not_before
|
||||||
|
|
||||||
|
Return the start date of a client certificate in seconds since
|
||||||
|
the epoch.
|
||||||
|
|
||||||
|
.. rb:attr_reader:: tls_client_not_after
|
||||||
|
|
||||||
|
Return the end date of a client certificate in seconds since
|
||||||
|
the epoch.
|
||||||
|
|
||||||
|
.. rb:attr_reader:: tls_cipher
|
||||||
|
|
||||||
|
Return a TLS cipher negotiated in this connection.
|
||||||
|
|
||||||
|
.. rb:attr_reader:: tls_protocol
|
||||||
|
|
||||||
|
Return a TLS protocol version negotiated in this connection.
|
||||||
|
|
||||||
|
.. rb:attr_reader:: tls_session_id
|
||||||
|
|
||||||
|
Return a session ID for this connection in hex string.
|
||||||
|
|
||||||
|
.. rb:attr_reader:: tls_session_reused
|
||||||
|
|
||||||
|
Return true if, and only if a SSL/TLS session is reused.
|
||||||
|
|
||||||
|
.. rb:attr_reader:: alpn
|
||||||
|
|
||||||
|
Return ALPN identifier negotiated in this connection.
|
||||||
|
|
||||||
|
.. rb:attr_reader:: tls_handshake_finished
|
||||||
|
|
||||||
|
Return true if SSL/TLS handshake has finished. If it returns
|
||||||
|
false in the request phase hook, the request is received in
|
||||||
|
TLSv1.3 early data (0-RTT) and might be vulnerable to the
|
||||||
|
replay attack. nghttpx will send Early-Data header field to
|
||||||
|
backend servers to indicate this.
|
||||||
|
|
||||||
.. rb:class:: Request
|
.. rb:class:: Request
|
||||||
|
|
||||||
Object to represent request from client. The modification to
|
Object to represent request from client. The modification to
|
||||||
@@ -1931,10 +2143,10 @@ respectively.
|
|||||||
not be invoked. When this method is called in response phase
|
not be invoked. When this method is called in response phase
|
||||||
hook, response from backend server is canceled and discarded.
|
hook, response from backend server is canceled and discarded.
|
||||||
The status code and response header fields should be set
|
The status code and response header fields should be set
|
||||||
before using this method. To set status code, use :rb:meth To
|
before using this method. To set status code, use
|
||||||
set response header fields, use
|
|
||||||
:rb:attr:`Nghttpx::Response#status`. If status code is not
|
:rb:attr:`Nghttpx::Response#status`. If status code is not
|
||||||
set, 200 is used. :rb:meth:`Nghttpx::Response#add_header` and
|
set, 200 is used. To set response header fields,
|
||||||
|
:rb:meth:`Nghttpx::Response#add_header` and
|
||||||
:rb:meth:`Nghttpx::Response#set_header`. When this method is
|
:rb:meth:`Nghttpx::Response#set_header`. When this method is
|
||||||
invoked in response phase hook, the response headers are
|
invoked in response phase hook, the response headers are
|
||||||
filled with the ones received from backend server. To send
|
filled with the ones received from backend server. To send
|
||||||
@@ -2045,7 +2257,7 @@ The replacement is done instantly without breaking existing
|
|||||||
connections or requests. It also avoids any process creation as is
|
connections or requests. It also avoids any process creation as is
|
||||||
the case with hot swapping with signals.
|
the case with hot swapping with signals.
|
||||||
|
|
||||||
The one limitation is that only numeric IP address is allowd in
|
The one limitation is that only numeric IP address is allowed in
|
||||||
:option:`backend <--backend>` in request body unless "dns" parameter
|
:option:`backend <--backend>` in request body unless "dns" parameter
|
||||||
is used while non numeric hostname is allowed in command-line or
|
is used while non numeric hostname is allowed in command-line or
|
||||||
configuration file is read using :option:`--conf`.
|
configuration file is read using :option:`--conf`.
|
||||||
|
|||||||
105
doc/nghttpx.h2r
105
doc/nghttpx.h2r
@@ -49,7 +49,7 @@ Error log
|
|||||||
<datetime> <master-pid> <current-pid> <thread-id> <level> (<filename>:<line>) <msg>
|
<datetime> <master-pid> <current-pid> <thread-id> <level> (<filename>:<line>) <msg>
|
||||||
|
|
||||||
<datetime>
|
<datetime>
|
||||||
It is a conbination of date and time when the log is written. It
|
It is a combination of date and time when the log is written. It
|
||||||
is in ISO 8601 format.
|
is in ISO 8601 format.
|
||||||
|
|
||||||
<master-pid>
|
<master-pid>
|
||||||
@@ -200,7 +200,7 @@ By default, session ID is shared by all worker threads.
|
|||||||
|
|
||||||
If :option:`--tls-session-cache-memcached` is given, nghttpx will
|
If :option:`--tls-session-cache-memcached` is given, nghttpx will
|
||||||
insert serialized session data to memcached with
|
insert serialized session data to memcached with
|
||||||
``nghttpx:tls-session-cache:`` + lowercased hex string of session ID
|
``nghttpx:tls-session-cache:`` + lowercase hex string of session ID
|
||||||
as a memcached entry key, with expiry time 12 hours. Session timeout
|
as a memcached entry key, with expiry time 12 hours. Session timeout
|
||||||
is set to 12 hours.
|
is set to 12 hours.
|
||||||
|
|
||||||
@@ -282,6 +282,14 @@ MRUBY SCRIPTING
|
|||||||
The current mruby extension API is experimental and not frozen. The
|
The current mruby extension API is experimental and not frozen. The
|
||||||
API is subject to change in the future release.
|
API is subject to change in the future release.
|
||||||
|
|
||||||
|
.. warning::
|
||||||
|
|
||||||
|
Almost all string value returned from method, or attribute is a
|
||||||
|
fresh new mruby string, which involves memory allocation, and
|
||||||
|
copies. Therefore, it is strongly recommended to store a return
|
||||||
|
value in a local variable, and use it, instead of calling method or
|
||||||
|
accessing attribute repeatedly.
|
||||||
|
|
||||||
nghttpx allows users to extend its capability using mruby scripts.
|
nghttpx allows users to extend its capability using mruby scripts.
|
||||||
nghttpx has 2 hook points to execute mruby script: request phase and
|
nghttpx has 2 hook points to execute mruby script: request phase and
|
||||||
response phase. The request phase hook is invoked after all request
|
response phase. The request phase hook is invoked after all request
|
||||||
@@ -291,9 +299,28 @@ server. These hooks allows users to modify header fields, or common
|
|||||||
HTTP variables, like authority or request path, and even return custom
|
HTTP variables, like authority or request path, and even return custom
|
||||||
response without forwarding request to backend servers.
|
response without forwarding request to backend servers.
|
||||||
|
|
||||||
To specify mruby script file, use :option:`--mruby-file` option. The
|
There are 2 levels of mruby script invocations: global and
|
||||||
script will be evaluated once per thread on startup, and it must
|
per-pattern. The global mruby script is set by :option:`--mruby-file`
|
||||||
instantiate object and evaluate it as the return value (e.g.,
|
option and is called for all requests. The per-pattern mruby script
|
||||||
|
is set by "mruby" parameter in :option:`-b` option. It is invoked for
|
||||||
|
a request which matches the particular pattern. The order of hook
|
||||||
|
invocation is: global request phase hook, per-pattern request phase
|
||||||
|
hook, per-pattern response phase hook, and finally global response
|
||||||
|
phase hook. If a hook returns a response, any later hooks are not
|
||||||
|
invoked. The global request hook is invoked before the pattern
|
||||||
|
matching is made and changing request path may affect the pattern
|
||||||
|
matching.
|
||||||
|
|
||||||
|
Please note that request and response hooks of per-pattern mruby
|
||||||
|
script for a single request might not come from the same script. This
|
||||||
|
might happen after a request hook is executed, backend failed for some
|
||||||
|
reason, and at the same time, backend configuration is replaced by API
|
||||||
|
request, and then the request uses new configuration on retry. The
|
||||||
|
response hook from new configuration, if it is specified, will be
|
||||||
|
invoked.
|
||||||
|
|
||||||
|
The all mruby script will be evaluated once per thread on startup, and
|
||||||
|
it must instantiate object and evaluate it as the return value (e.g.,
|
||||||
``App.new``). This object is called app object. If app object
|
``App.new``). This object is called app object. If app object
|
||||||
defines ``on_req`` method, it is called with :rb:class:`Nghttpx::Env`
|
defines ``on_req`` method, it is called with :rb:class:`Nghttpx::Env`
|
||||||
object on request hook. Similarly, if app object defines ``on_resp``
|
object on request hook. Similarly, if app object defines ``on_resp``
|
||||||
@@ -328,7 +355,7 @@ respectively.
|
|||||||
.. rb:attr_reader:: ctx
|
.. rb:attr_reader:: ctx
|
||||||
|
|
||||||
Return Ruby hash object. It persists until request finishes.
|
Return Ruby hash object. It persists until request finishes.
|
||||||
So values set in request phase hoo can be retrieved in
|
So values set in request phase hook can be retrieved in
|
||||||
response phase hook.
|
response phase hook.
|
||||||
|
|
||||||
.. rb:attr_reader:: phase
|
.. rb:attr_reader:: phase
|
||||||
@@ -360,6 +387,64 @@ respectively.
|
|||||||
|
|
||||||
Return the TLS SNI value which client sent in this connection.
|
Return the TLS SNI value which client sent in this connection.
|
||||||
|
|
||||||
|
.. rb:attr_reader:: tls_client_fingerprint_sha256
|
||||||
|
|
||||||
|
Return the SHA-256 fingerprint of a client certificate.
|
||||||
|
|
||||||
|
.. rb:attr_reader:: tls_client_fingerprint_sha1
|
||||||
|
|
||||||
|
Return the SHA-1 fingerprint of a client certificate.
|
||||||
|
|
||||||
|
.. rb:attr_reader:: tls_client_issuer_name
|
||||||
|
|
||||||
|
Return the issuer name of a client certificate.
|
||||||
|
|
||||||
|
.. rb:attr_reader:: tls_client_subject_name
|
||||||
|
|
||||||
|
Return the subject name of a client certificate.
|
||||||
|
|
||||||
|
.. rb:attr_reader:: tls_client_serial
|
||||||
|
|
||||||
|
Return the serial number of a client certificate.
|
||||||
|
|
||||||
|
.. rb:attr_reader:: tls_client_not_before
|
||||||
|
|
||||||
|
Return the start date of a client certificate in seconds since
|
||||||
|
the epoch.
|
||||||
|
|
||||||
|
.. rb:attr_reader:: tls_client_not_after
|
||||||
|
|
||||||
|
Return the end date of a client certificate in seconds since
|
||||||
|
the epoch.
|
||||||
|
|
||||||
|
.. rb:attr_reader:: tls_cipher
|
||||||
|
|
||||||
|
Return a TLS cipher negotiated in this connection.
|
||||||
|
|
||||||
|
.. rb:attr_reader:: tls_protocol
|
||||||
|
|
||||||
|
Return a TLS protocol version negotiated in this connection.
|
||||||
|
|
||||||
|
.. rb:attr_reader:: tls_session_id
|
||||||
|
|
||||||
|
Return a session ID for this connection in hex string.
|
||||||
|
|
||||||
|
.. rb:attr_reader:: tls_session_reused
|
||||||
|
|
||||||
|
Return true if, and only if a SSL/TLS session is reused.
|
||||||
|
|
||||||
|
.. rb:attr_reader:: alpn
|
||||||
|
|
||||||
|
Return ALPN identifier negotiated in this connection.
|
||||||
|
|
||||||
|
.. rb:attr_reader:: tls_handshake_finished
|
||||||
|
|
||||||
|
Return true if SSL/TLS handshake has finished. If it returns
|
||||||
|
false in the request phase hook, the request is received in
|
||||||
|
TLSv1.3 early data (0-RTT) and might be vulnerable to the
|
||||||
|
replay attack. nghttpx will send Early-Data header field to
|
||||||
|
backend servers to indicate this.
|
||||||
|
|
||||||
.. rb:class:: Request
|
.. rb:class:: Request
|
||||||
|
|
||||||
Object to represent request from client. The modification to
|
Object to represent request from client. The modification to
|
||||||
@@ -490,10 +575,10 @@ respectively.
|
|||||||
not be invoked. When this method is called in response phase
|
not be invoked. When this method is called in response phase
|
||||||
hook, response from backend server is canceled and discarded.
|
hook, response from backend server is canceled and discarded.
|
||||||
The status code and response header fields should be set
|
The status code and response header fields should be set
|
||||||
before using this method. To set status code, use :rb:meth To
|
before using this method. To set status code, use
|
||||||
set response header fields, use
|
|
||||||
:rb:attr:`Nghttpx::Response#status`. If status code is not
|
:rb:attr:`Nghttpx::Response#status`. If status code is not
|
||||||
set, 200 is used. :rb:meth:`Nghttpx::Response#add_header` and
|
set, 200 is used. To set response header fields,
|
||||||
|
:rb:meth:`Nghttpx::Response#add_header` and
|
||||||
:rb:meth:`Nghttpx::Response#set_header`. When this method is
|
:rb:meth:`Nghttpx::Response#set_header`. When this method is
|
||||||
invoked in response phase hook, the response headers are
|
invoked in response phase hook, the response headers are
|
||||||
filled with the ones received from backend server. To send
|
filled with the ones received from backend server. To send
|
||||||
@@ -604,7 +689,7 @@ The replacement is done instantly without breaking existing
|
|||||||
connections or requests. It also avoids any process creation as is
|
connections or requests. It also avoids any process creation as is
|
||||||
the case with hot swapping with signals.
|
the case with hot swapping with signals.
|
||||||
|
|
||||||
The one limitation is that only numeric IP address is allowd in
|
The one limitation is that only numeric IP address is allowed in
|
||||||
:option:`backend <--backend>` in request body unless "dns" parameter
|
:option:`backend <--backend>` in request body unless "dns" parameter
|
||||||
is used while non numeric hostname is allowed in command-line or
|
is used while non numeric hostname is allowed in command-line or
|
||||||
configuration file is read using :option:`--conf`.
|
configuration file is read using :option:`--conf`.
|
||||||
|
|||||||
@@ -110,9 +110,9 @@ HTTP Messaging
|
|||||||
|
|
||||||
By default, nghttp2 library checks HTTP messaging rules described in
|
By default, nghttp2 library checks HTTP messaging rules described in
|
||||||
`HTTP/2 specification, section 8
|
`HTTP/2 specification, section 8
|
||||||
<https://tools.ietf.org/html/draft-ietf-httpbis-http2-17#section-8>`_.
|
<https://tools.ietf.org/html/rfc7540#section-8>`_. Everything
|
||||||
Everything described in that section is not validated however. We
|
described in that section is not validated however. We briefly
|
||||||
briefly describe what the library does in this area. In the following
|
describe what the library does in this area. In the following
|
||||||
description, without loss of generality we omit CONTINUATION frame
|
description, without loss of generality we omit CONTINUATION frame
|
||||||
since they must follow HEADERS frame and are processed atomically. In
|
since they must follow HEADERS frame and are processed atomically. In
|
||||||
other words, they are just one big HEADERS frame. To disable these
|
other words, they are just one big HEADERS frame. To disable these
|
||||||
@@ -249,7 +249,7 @@ set to :type:`nghttp2_session_callbacks` using
|
|||||||
`nghttp2_session_callbacks_set_pack_extension_callback()`.
|
`nghttp2_session_callbacks_set_pack_extension_callback()`.
|
||||||
|
|
||||||
For example, we will illustrate how to send `ALTSVC
|
For example, we will illustrate how to send `ALTSVC
|
||||||
<https://tools.ietf.org/html/draft-ietf-httpbis-alt-svc-14>`_ frame.
|
<https://tools.ietf.org/html/rfc7838>`_ frame.
|
||||||
|
|
||||||
.. code-block:: c
|
.. code-block:: c
|
||||||
|
|
||||||
|
|||||||
@@ -26,16 +26,16 @@ 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 4.0.
|
between versions, we currently use clang-format-7.
|
||||||
|
|
||||||
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.
|
||||||
The pre-commit file is located at the root directory. Copy it under
|
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-7
|
||||||
clang-format-diff-4.0 in debian), either add it to PATH variable or
|
in debian), either add it to PATH variable or add git option
|
||||||
add git option ``clangformatdiff.binary`` to point to the script.
|
``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.
|
||||||
clang-format.el should come with clang distribution. If it is not
|
clang-format.el should come with clang distribution. If it is not
|
||||||
|
|||||||
@@ -3,10 +3,8 @@
|
|||||||
h2load - HTTP/2 benchmarking tool - HOW-TO
|
h2load - HTTP/2 benchmarking tool - HOW-TO
|
||||||
==========================================
|
==========================================
|
||||||
|
|
||||||
:doc:`h2load.1` is benchmarking tool for HTTP/2 and HTTP/1.1. If
|
:doc:`h2load.1` is benchmarking tool for HTTP/2 and HTTP/1.1. It
|
||||||
built with spdylay (http://tatsuhiro-t.github.io/spdylay/) library, it
|
supports SSL/TLS and clear text for all supported protocols.
|
||||||
also supports SPDY protocol. It supports SSL/TLS and clear text for
|
|
||||||
all supported protocols.
|
|
||||||
|
|
||||||
Compiling from source
|
Compiling from source
|
||||||
---------------------
|
---------------------
|
||||||
@@ -64,23 +62,40 @@ The benchmarking result looks like this:
|
|||||||
See the h2load manual page :ref:`h2load-1-output` section for the
|
See the h2load manual page :ref:`h2load-1-output` section for the
|
||||||
explanation of the above numbers.
|
explanation of the above numbers.
|
||||||
|
|
||||||
|
Timing-based load-testing
|
||||||
|
-------------------------
|
||||||
|
|
||||||
|
As of v1.26.0, h2load supports timing-based load-testing. This method
|
||||||
|
performs load-testing in terms of a given duration instead of a
|
||||||
|
pre-defined number of requests. The new option :option:`--duration`
|
||||||
|
specifies how long the load-testing takes. For example,
|
||||||
|
``--duration=10`` makes h2load perform load-testing against a server
|
||||||
|
for 10 seconds. You can also specify a “warming-up” period with
|
||||||
|
:option:`--warm-up-time`. If :option:`--duration` is used,
|
||||||
|
:option:`-n` option is ignored.
|
||||||
|
|
||||||
|
The following command performs load-testing for 10 seconds after 5
|
||||||
|
seconds warming up period:
|
||||||
|
|
||||||
|
.. code-block:: text
|
||||||
|
|
||||||
|
$ h2load -c100 -m100 --duration=10 --warm-up-time=5 https://localhost
|
||||||
|
|
||||||
Flow Control
|
Flow Control
|
||||||
------------
|
------------
|
||||||
|
|
||||||
HTTP/2 and SPDY/3 or later employ flow control and it may affect
|
HTTP/2 has flow control and it may affect benchmarking results. By
|
||||||
benchmarking results. By default, h2load uses large enough flow
|
default, h2load uses large enough flow control window, which
|
||||||
control window, which effectively disables flow control. To adjust
|
effectively disables flow control. To adjust receiver flow control
|
||||||
receiver flow control window size, there are following options:
|
window size, there are following options:
|
||||||
|
|
||||||
:option:`-w`
|
:option:`-w`
|
||||||
Sets the stream level initial window size to
|
Sets the stream level initial window size to
|
||||||
(2**<N>)-1. For SPDY, 2**<N> is used instead.
|
(2**<N>)-1.
|
||||||
|
|
||||||
:option:`-W`
|
:option:`-W`
|
||||||
Sets the connection level initial window size to
|
Sets the connection level initial window size to
|
||||||
(2**<N>)-1. For SPDY, if <N> is strictly less
|
(2**<N>)-1.
|
||||||
than 16, this option is ignored. Otherwise
|
|
||||||
2**<N> is used for SPDY.
|
|
||||||
|
|
||||||
Multi-Threading
|
Multi-Threading
|
||||||
---------------
|
---------------
|
||||||
|
|||||||
@@ -290,7 +290,7 @@ Normally, client does not stop even after all requests are done unless
|
|||||||
connection is lost. To stop client, call
|
connection is lost. To stop client, call
|
||||||
``nghttp2::asio_http2::server::session::shutdown()``.
|
``nghttp2::asio_http2::server::session::shutdown()``.
|
||||||
|
|
||||||
Recieve server push and enable SSL/TLS
|
Receive server push and enable SSL/TLS
|
||||||
++++++++++++++++++++++++++++++++++++++
|
++++++++++++++++++++++++++++++++++++++
|
||||||
|
|
||||||
.. code-block:: cpp
|
.. code-block:: cpp
|
||||||
|
|||||||
@@ -4,10 +4,10 @@ nghttpx - HTTP/2 proxy - HOW-TO
|
|||||||
===============================
|
===============================
|
||||||
|
|
||||||
:doc:`nghttpx.1` is a proxy translating protocols between HTTP/2 and
|
:doc:`nghttpx.1` is a proxy translating protocols between HTTP/2 and
|
||||||
other protocols (e.g., HTTP/1, SPDY). It operates in several modes
|
other protocols (e.g., HTTP/1). It operates in several modes and each
|
||||||
and each mode may require additional programs to work with. This
|
mode may require additional programs to work with. This article
|
||||||
article describes each operation mode and explains the intended
|
describes each operation mode and explains the intended use-cases. It
|
||||||
use-cases. It also covers some useful options later.
|
also covers some useful options later.
|
||||||
|
|
||||||
Default mode
|
Default mode
|
||||||
------------
|
------------
|
||||||
@@ -15,9 +15,7 @@ Default mode
|
|||||||
If nghttpx is invoked without :option:`--http2-proxy`, it operates in
|
If nghttpx is invoked without :option:`--http2-proxy`, it operates in
|
||||||
default mode. In this mode, it works as reverse proxy (gateway) for
|
default mode. In this mode, it works as reverse proxy (gateway) for
|
||||||
both HTTP/2 and HTTP/1 clients to backend servers. This is also known
|
both HTTP/2 and HTTP/1 clients to backend servers. This is also known
|
||||||
as "HTTP/2 router". If nghttpx is linked with spdylay library and
|
as "HTTP/2 router".
|
||||||
frontend connection is SSL/TLS, the frontend also supports SPDY
|
|
||||||
protocol.
|
|
||||||
|
|
||||||
By default, frontend connection is encrypted using SSL/TLS. So
|
By default, frontend connection is encrypted using SSL/TLS. So
|
||||||
server's private key and certificate must be supplied to the command
|
server's private key and certificate must be supplied to the command
|
||||||
@@ -25,11 +23,10 @@ line (or through configuration file). In this case, the frontend
|
|||||||
protocol selection will be done via ALPN or NPN.
|
protocol selection will be done via ALPN or NPN.
|
||||||
|
|
||||||
To turn off encryption on frontend connection, use ``no-tls`` keyword
|
To turn off encryption on frontend connection, use ``no-tls`` keyword
|
||||||
in :option:`--frontend` option. In this case, SPDY protocol is not
|
in :option:`--frontend` option. HTTP/2 and HTTP/1 are available on
|
||||||
available even if spdylay library is liked to nghttpx. HTTP/2 and
|
the frontend, and an HTTP/1 connection can be upgraded to HTTP/2 using
|
||||||
HTTP/1 are available on the frontend, and an HTTP/1 connection can be
|
HTTP Upgrade. Starting HTTP/2 connection by sending HTTP/2 connection
|
||||||
upgraded to HTTP/2 using HTTP Upgrade. Starting HTTP/2 connection by
|
preface is also supported.
|
||||||
sending HTTP/2 connection preface is also supported.
|
|
||||||
|
|
||||||
nghttpx can listen on multiple frontend addresses. This is achieved
|
nghttpx can listen on multiple frontend addresses. This is achieved
|
||||||
by using multiple :option:`--frontend` options. For each frontend
|
by using multiple :option:`--frontend` options. For each frontend
|
||||||
@@ -45,17 +42,17 @@ that default backend protocol is HTTP/1.1. To use HTTP/2 in backend,
|
|||||||
you have to specify ``h2`` in ``proto`` keyword in :option:`--backend`
|
you have to specify ``h2`` in ``proto`` keyword in :option:`--backend`
|
||||||
explicitly.
|
explicitly.
|
||||||
|
|
||||||
The backend is supposed to be Web server. For example, to make
|
The backend is supposed to be a Web server. For example, to make
|
||||||
nghttpx listen to encrypted HTTP/2 requests at port 8443, and a
|
nghttpx listen to encrypted HTTP/2 requests at port 8443, and a
|
||||||
backend Web server is configured to listen to HTTP request at port
|
backend Web server is configured to listen to HTTP requests at port
|
||||||
8080 in the same host, run nghttpx command-line like this:
|
8080 on the same host, run nghttpx command-line like this:
|
||||||
|
|
||||||
.. code-block:: text
|
.. code-block:: text
|
||||||
|
|
||||||
$ nghttpx -f0.0.0.0,8443 -b127.0.0.1,8080 /path/to/server.key /path/to/server.crt
|
$ nghttpx -f0.0.0.0,8443 -b127.0.0.1,8080 /path/to/server.key /path/to/server.crt
|
||||||
|
|
||||||
Then HTTP/2 enabled client can access to the nghttpx in HTTP/2. For
|
Then an HTTP/2 enabled client can access the nghttpx server using HTTP/2. For
|
||||||
example, you can send GET request to the server using nghttp:
|
example, you can send a GET request using nghttp:
|
||||||
|
|
||||||
.. code-block:: text
|
.. code-block:: text
|
||||||
|
|
||||||
@@ -66,19 +63,18 @@ HTTP/2 proxy mode
|
|||||||
|
|
||||||
If nghttpx is invoked with :option:`--http2-proxy` (or its shorthand
|
If nghttpx is invoked with :option:`--http2-proxy` (or its shorthand
|
||||||
:option:`-s`) option, it operates in HTTP/2 proxy mode. The supported
|
:option:`-s`) option, it operates in HTTP/2 proxy mode. The supported
|
||||||
protocols in frontend and backend connections are the same in `default
|
protocols in frontend and backend connections are the same as in `default
|
||||||
mode`_. The difference is that this mode acts like forward proxy and
|
mode`_. The difference is that this mode acts like a forward proxy and
|
||||||
assumes the backend is HTTP proxy server (e.g., Squid, Apache Traffic
|
assumes the backend is an HTTP proxy server (e.g., Squid, Apache Traffic
|
||||||
Server). HTTP/1 request must include absolute URI in request line.
|
Server). HTTP/1 requests must include an absolute URI in request line.
|
||||||
|
|
||||||
By default, frontend connection is encrypted. So this mode is also
|
By default, the frontend connection is encrypted. So this mode is
|
||||||
called secure proxy. If nghttpx is linked with spdylay, it supports
|
also called secure proxy.
|
||||||
SPDY protocols and it works as so called SPDY proxy.
|
|
||||||
|
|
||||||
To turn off encryption on frontend connection, use ``no-tls`` keyword
|
To turn off encryption on the frontend connection, use ``no-tls`` keyword
|
||||||
in :option:`--frontend` option.
|
in :option:`--frontend` option.
|
||||||
|
|
||||||
The backend must be HTTP proxy server. nghttpx supports multiple
|
The backend must be an HTTP proxy server. nghttpx supports multiple
|
||||||
backend server addresses. It translates incoming requests to HTTP
|
backend server addresses. It translates incoming requests to HTTP
|
||||||
request to backend server. The backend server performs real proxy
|
request to backend server. The backend server performs real proxy
|
||||||
work for each request, for example, dispatching requests to the origin
|
work for each request, for example, dispatching requests to the origin
|
||||||
@@ -92,7 +88,7 @@ connection, use :option:`--backend` option, and specify ``h2`` in
|
|||||||
|
|
||||||
For example, to make nghttpx listen to encrypted HTTP/2 requests at
|
For example, to make nghttpx listen to encrypted HTTP/2 requests at
|
||||||
port 8443, and a backend HTTP proxy server is configured to listen to
|
port 8443, and a backend HTTP proxy server is configured to listen to
|
||||||
HTTP/1 request at port 8080 in the same host, run nghttpx command-line
|
HTTP/1 requests at port 8080 on the same host, run nghttpx command-line
|
||||||
like this:
|
like this:
|
||||||
|
|
||||||
.. code-block:: text
|
.. code-block:: text
|
||||||
@@ -102,8 +98,8 @@ like this:
|
|||||||
At the time of this writing, Firefox 41 and Chromium v46 can use
|
At the time of this writing, Firefox 41 and Chromium v46 can use
|
||||||
nghttpx as HTTP/2 proxy.
|
nghttpx as HTTP/2 proxy.
|
||||||
|
|
||||||
To make Firefox or Chromium use nghttpx as HTTP/2 or SPDY proxy, user
|
To make Firefox or Chromium use nghttpx as HTTP/2 proxy, user has to
|
||||||
has to create proxy.pac script file like this:
|
create proxy.pac script file like this:
|
||||||
|
|
||||||
.. code-block:: javascript
|
.. code-block:: javascript
|
||||||
|
|
||||||
@@ -389,7 +385,7 @@ parameter in :option:`--backend` option, like so:
|
|||||||
|
|
||||||
.. code-block:: text
|
.. code-block:: text
|
||||||
|
|
||||||
backend=foo.example.com;;dns
|
backend=foo.example.com,80;;dns
|
||||||
|
|
||||||
nghttpx will cache resolved addresses for certain period of time. To
|
nghttpx will cache resolved addresses for certain period of time. To
|
||||||
change this cache period, use :option:`--dns-cache-timeout`.
|
change this cache period, use :option:`--dns-cache-timeout`.
|
||||||
@@ -405,6 +401,28 @@ like so:
|
|||||||
|
|
||||||
frontend=*,443;proxyproto
|
frontend=*,443;proxyproto
|
||||||
|
|
||||||
|
Session affinity
|
||||||
|
----------------
|
||||||
|
|
||||||
|
Two kinds of session affinity are available: client IP, and HTTP
|
||||||
|
Cookie.
|
||||||
|
|
||||||
|
To enable client IP based affinity, specify ``affinity=ip`` parameter
|
||||||
|
in :option:`--backend` option. If PROXY protocol is enabled, then an
|
||||||
|
address obtained from PROXY protocol is taken into consideration.
|
||||||
|
|
||||||
|
To enable HTTP Cookie based affinity, specify ``affinity=cookie``
|
||||||
|
parameter, and specify a name of cookie in ``affinity-cookie-name``
|
||||||
|
parameter. Optionally, a Path attribute can be specified in
|
||||||
|
``affinity-cookie-path`` parameter:
|
||||||
|
|
||||||
|
.. code-block:: text
|
||||||
|
|
||||||
|
backend=127.0.0.1,3000;;affinity=cookie;affinity-cookie-name=nghttpxlb;affinity-cookie-path=/
|
||||||
|
|
||||||
|
Secure attribute of cookie is set if client connection is protected by
|
||||||
|
TLS.
|
||||||
|
|
||||||
PSK cipher suites
|
PSK cipher suites
|
||||||
-----------------
|
-----------------
|
||||||
|
|
||||||
@@ -453,6 +471,33 @@ such PSK cipher suite with HTTP/2, disable HTTP/2 cipher black list by
|
|||||||
using :option:`--client-no-http2-cipher-black-list` option. But you
|
using :option:`--client-no-http2-cipher-black-list` option. But you
|
||||||
should understand its implications.
|
should understand its implications.
|
||||||
|
|
||||||
|
TLSv1.3
|
||||||
|
-------
|
||||||
|
|
||||||
|
As of nghttpx v1.34.0, if it is built with OpenSSL 1.1.1 or later, it
|
||||||
|
supports TLSv1.3. 0-RTT data is supported, but by default its
|
||||||
|
processing is postponed until TLS handshake completes to mitigate
|
||||||
|
replay attack. This costs extra round trip and reduces effectiveness
|
||||||
|
of 0-RTT data. :option:`--tls-no-postpone-early-data` makes nghttpx
|
||||||
|
not wait for handshake to complete before forwarding request included
|
||||||
|
in 0-RTT to get full potential of 0-RTT data. In this case, nghttpx
|
||||||
|
adds ``Early-Data: 1`` header field when forwarding a request to a
|
||||||
|
backend server. All backend servers should recognize this header
|
||||||
|
field and understand that there is a risk for replay attack. See `RFC
|
||||||
|
8470 <https://tools.ietf.org/html/rfc8470>`_ for ``Early-Data`` header
|
||||||
|
field.
|
||||||
|
|
||||||
|
nghttpx disables anti replay protection provided by OpenSSL. The anti
|
||||||
|
replay protection of OpenSSL requires that a resumed request must hit
|
||||||
|
the same server which generates the session ticket. Therefore it
|
||||||
|
might not work nicely in a deployment where there are multiple nghttpx
|
||||||
|
instances sharing ticket encryption keys via memcached.
|
||||||
|
|
||||||
|
Because TLSv1.3 completely changes the semantics of cipher suite
|
||||||
|
naming scheme and structure, nghttpx provides the new option
|
||||||
|
:option:`--tls13-ciphers` and :option:`--tls13-client-ciphers` to
|
||||||
|
change preferred cipher list for TLSv1.3.
|
||||||
|
|
||||||
Migration from nghttpx v1.18.x or earlier
|
Migration from nghttpx v1.18.x or earlier
|
||||||
-----------------------------------------
|
-----------------------------------------
|
||||||
|
|
||||||
|
|||||||
@@ -124,6 +124,7 @@ remote server. It's defined as::
|
|||||||
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_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,
|
||||||
AF_UNSPEC, host, port);
|
AF_UNSPEC, host, port);
|
||||||
|
|||||||
@@ -7,11 +7,8 @@ if(ENABLE_EXAMPLES)
|
|||||||
COMPILE_FLAGS "${WARNCXXFLAGS} ${CXX1XCXXFLAGS}")
|
COMPILE_FLAGS "${WARNCXXFLAGS} ${CXX1XCXXFLAGS}")
|
||||||
|
|
||||||
include_directories(
|
include_directories(
|
||||||
${CMAKE_SOURCE_DIR}
|
${CMAKE_CURRENT_SOURCE_DIR}
|
||||||
${CMAKE_SOURCE_DIR}/lib/includes
|
"${CMAKE_CURRENT_SOURCE_DIR}/../third-party"
|
||||||
${CMAKE_BINARY_DIR}/lib/includes
|
|
||||||
${CMAKE_SOURCE_DIR}/src/includes
|
|
||||||
${CMAKE_SOURCE_DIR}/third-party
|
|
||||||
|
|
||||||
${LIBEVENT_INCLUDE_DIRS}
|
${LIBEVENT_INCLUDE_DIRS}
|
||||||
${OPENSSL_INCLUDE_DIRS}
|
${OPENSSL_INCLUDE_DIRS}
|
||||||
|
|||||||
@@ -67,14 +67,14 @@ int main(int argc, char *argv[]) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
req->on_response([&sess](const response &res) {
|
req->on_response([](const response &res) {
|
||||||
std::cerr << "HTTP/2 " << res.status_code() << std::endl;
|
std::cerr << "HTTP/2 " << res.status_code() << std::endl;
|
||||||
for (auto &kv : res.header()) {
|
for (auto &kv : res.header()) {
|
||||||
std::cerr << kv.first << ": " << kv.second.value << "\n";
|
std::cerr << kv.first << ": " << kv.second.value << "\n";
|
||||||
}
|
}
|
||||||
std::cerr << std::endl;
|
std::cerr << std::endl;
|
||||||
|
|
||||||
res.on_data([&sess](const uint8_t *data, std::size_t len) {
|
res.on_data([](const uint8_t *data, std::size_t len) {
|
||||||
std::cerr.write(reinterpret_cast<const char *>(data), len);
|
std::cerr.write(reinterpret_cast<const char *>(data), len);
|
||||||
std::cerr << std::endl;
|
std::cerr << std::endl;
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -91,17 +91,17 @@ int main(int argc, char *argv[]) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
req->on_response([&sess, req](const response &res) {
|
req->on_response([](const response &res) {
|
||||||
std::cerr << "response header was received" << std::endl;
|
std::cerr << "response header was received" << std::endl;
|
||||||
print_header(res);
|
print_header(res);
|
||||||
|
|
||||||
res.on_data([&sess](const uint8_t *data, std::size_t len) {
|
res.on_data([](const uint8_t *data, std::size_t len) {
|
||||||
std::cerr.write(reinterpret_cast<const char *>(data), len);
|
std::cerr.write(reinterpret_cast<const char *>(data), len);
|
||||||
std::cerr << std::endl;
|
std::cerr << std::endl;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
req->on_close([&sess](uint32_t error_code) {
|
req->on_close([](uint32_t error_code) {
|
||||||
std::cerr << "request done with error_code=" << error_code << std::endl;
|
std::cerr << "request done with error_code=" << error_code << std::endl;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -36,10 +36,10 @@
|
|||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#ifdef HAVE_UNISTD_H
|
#ifdef HAVE_UNISTD_H
|
||||||
#include <unistd.h>
|
# include <unistd.h>
|
||||||
#endif // HAVE_UNISTD_H
|
#endif // HAVE_UNISTD_H
|
||||||
#ifdef HAVE_FCNTL_H
|
#ifdef HAVE_FCNTL_H
|
||||||
#include <fcntl.h>
|
# include <fcntl.h>
|
||||||
#endif // HAVE_FCNTL_H
|
#endif // HAVE_FCNTL_H
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|||||||
@@ -27,26 +27,26 @@
|
|||||||
* intentionally made simple.
|
* intentionally made simple.
|
||||||
*/
|
*/
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
#include <config.h>
|
# include <config.h>
|
||||||
#endif /* HAVE_CONFIG_H */
|
#endif /* HAVE_CONFIG_H */
|
||||||
|
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#ifdef HAVE_UNISTD_H
|
#ifdef HAVE_UNISTD_H
|
||||||
#include <unistd.h>
|
# include <unistd.h>
|
||||||
#endif /* HAVE_UNISTD_H */
|
#endif /* HAVE_UNISTD_H */
|
||||||
#ifdef HAVE_FCNTL_H
|
#ifdef HAVE_FCNTL_H
|
||||||
#include <fcntl.h>
|
# include <fcntl.h>
|
||||||
#endif /* HAVE_FCNTL_H */
|
#endif /* HAVE_FCNTL_H */
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#ifdef HAVE_SYS_SOCKET_H
|
#ifdef HAVE_SYS_SOCKET_H
|
||||||
#include <sys/socket.h>
|
# include <sys/socket.h>
|
||||||
#endif /* HAVE_SYS_SOCKET_H */
|
#endif /* HAVE_SYS_SOCKET_H */
|
||||||
#ifdef HAVE_NETDB_H
|
#ifdef HAVE_NETDB_H
|
||||||
#include <netdb.h>
|
# include <netdb.h>
|
||||||
#endif /* HAVE_NETDB_H */
|
#endif /* HAVE_NETDB_H */
|
||||||
#ifdef HAVE_NETINET_IN_H
|
#ifdef HAVE_NETINET_IN_H
|
||||||
#include <netinet/in.h>
|
# include <netinet/in.h>
|
||||||
#endif /* HAVE_NETINET_IN_H */
|
#endif /* HAVE_NETINET_IN_H */
|
||||||
#include <netinet/tcp.h>
|
#include <netinet/tcp.h>
|
||||||
#include <poll.h>
|
#include <poll.h>
|
||||||
@@ -345,6 +345,7 @@ static void setup_nghttp2_callbacks(nghttp2_session_callbacks *callbacks) {
|
|||||||
callbacks, on_data_chunk_recv_callback);
|
callbacks, on_data_chunk_recv_callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef OPENSSL_NO_NEXTPROTONEG
|
||||||
/*
|
/*
|
||||||
* Callback function for TLS NPN. Since this program only supports
|
* Callback function for TLS NPN. Since this program only supports
|
||||||
* HTTP/2 protocol, if server does not offer HTTP/2 the nghttp2
|
* HTTP/2 protocol, if server does not offer HTTP/2 the nghttp2
|
||||||
@@ -365,6 +366,7 @@ static int select_next_proto_cb(SSL *ssl, unsigned char **out,
|
|||||||
}
|
}
|
||||||
return SSL_TLSEXT_ERR_OK;
|
return SSL_TLSEXT_ERR_OK;
|
||||||
}
|
}
|
||||||
|
#endif /* !OPENSSL_NO_NEXTPROTONEG */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Setup SSL/TLS context.
|
* Setup SSL/TLS context.
|
||||||
@@ -375,7 +377,9 @@ static void init_ssl_ctx(SSL_CTX *ssl_ctx) {
|
|||||||
SSL_CTX_set_mode(ssl_ctx, SSL_MODE_AUTO_RETRY);
|
SSL_CTX_set_mode(ssl_ctx, SSL_MODE_AUTO_RETRY);
|
||||||
SSL_CTX_set_mode(ssl_ctx, SSL_MODE_RELEASE_BUFFERS);
|
SSL_CTX_set_mode(ssl_ctx, SSL_MODE_RELEASE_BUFFERS);
|
||||||
/* Set NPN callback */
|
/* Set NPN callback */
|
||||||
|
#ifndef OPENSSL_NO_NEXTPROTONEG
|
||||||
SSL_CTX_set_next_proto_select_cb(ssl_ctx, select_next_proto_cb, NULL);
|
SSL_CTX_set_next_proto_select_cb(ssl_ctx, select_next_proto_cb, NULL);
|
||||||
|
#endif /* !OPENSSL_NO_NEXTPROTONEG */
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ssl_handshake(SSL *ssl, int fd) {
|
static void ssl_handshake(SSL *ssl, int fd) {
|
||||||
|
|||||||
@@ -23,7 +23,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.
|
||||||
*/
|
*/
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
#include <config.h>
|
# include <config.h>
|
||||||
#endif /* !HAVE_CONFIG_H */
|
#endif /* !HAVE_CONFIG_H */
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|||||||
@@ -23,33 +23,33 @@
|
|||||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
#ifdef __sgi
|
#ifdef __sgi
|
||||||
#include <string.h>
|
# include <string.h>
|
||||||
#define errx(exitcode, format, args...) \
|
# define errx(exitcode, format, args...) \
|
||||||
{ \
|
{ \
|
||||||
warnx(format, ##args); \
|
warnx(format, ##args); \
|
||||||
exit(exitcode); \
|
exit(exitcode); \
|
||||||
}
|
}
|
||||||
#define warnx(format, args...) fprintf(stderr, format "\n", ##args)
|
# define warnx(format, args...) fprintf(stderr, format "\n", ##args)
|
||||||
char *strndup(const char *s, size_t size);
|
char *strndup(const char *s, size_t size);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
#include <config.h>
|
# include <config.h>
|
||||||
#endif /* HAVE_CONFIG_H */
|
#endif /* HAVE_CONFIG_H */
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#ifdef HAVE_UNISTD_H
|
#ifdef HAVE_UNISTD_H
|
||||||
#include <unistd.h>
|
# include <unistd.h>
|
||||||
#endif /* HAVE_UNISTD_H */
|
#endif /* HAVE_UNISTD_H */
|
||||||
#ifdef HAVE_SYS_SOCKET_H
|
#ifdef HAVE_SYS_SOCKET_H
|
||||||
#include <sys/socket.h>
|
# include <sys/socket.h>
|
||||||
#endif /* HAVE_SYS_SOCKET_H */
|
#endif /* HAVE_SYS_SOCKET_H */
|
||||||
#ifdef HAVE_NETINET_IN_H
|
#ifdef HAVE_NETINET_IN_H
|
||||||
#include <netinet/in.h>
|
# include <netinet/in.h>
|
||||||
#endif /* HAVE_NETINET_IN_H */
|
#endif /* HAVE_NETINET_IN_H */
|
||||||
#include <netinet/tcp.h>
|
#include <netinet/tcp.h>
|
||||||
#ifndef __sgi
|
#ifndef __sgi
|
||||||
#include <err.h>
|
# include <err.h>
|
||||||
#endif
|
#endif
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@@ -308,6 +308,7 @@ static int on_stream_close_callback(nghttp2_session *session, int32_t stream_id,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef OPENSSL_NO_NEXTPROTONEG
|
||||||
/* NPN TLS extension client callback. We check that server advertised
|
/* NPN TLS extension client callback. We check that server advertised
|
||||||
the HTTP/2 protocol the nghttp2 library supports. If not, exit
|
the HTTP/2 protocol the nghttp2 library supports. If not, exit
|
||||||
the program. */
|
the program. */
|
||||||
@@ -322,6 +323,7 @@ static int select_next_proto_cb(SSL *ssl, unsigned char **out,
|
|||||||
}
|
}
|
||||||
return SSL_TLSEXT_ERR_OK;
|
return SSL_TLSEXT_ERR_OK;
|
||||||
}
|
}
|
||||||
|
#endif /* !OPENSSL_NO_NEXTPROTONEG */
|
||||||
|
|
||||||
/* Create SSL_CTX. */
|
/* Create SSL_CTX. */
|
||||||
static SSL_CTX *create_ssl_ctx(void) {
|
static SSL_CTX *create_ssl_ctx(void) {
|
||||||
@@ -335,11 +337,13 @@ static SSL_CTX *create_ssl_ctx(void) {
|
|||||||
SSL_OP_ALL | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 |
|
SSL_OP_ALL | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 |
|
||||||
SSL_OP_NO_COMPRESSION |
|
SSL_OP_NO_COMPRESSION |
|
||||||
SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION);
|
SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION);
|
||||||
|
#ifndef OPENSSL_NO_NEXTPROTONEG
|
||||||
SSL_CTX_set_next_proto_select_cb(ssl_ctx, select_next_proto_cb, NULL);
|
SSL_CTX_set_next_proto_select_cb(ssl_ctx, select_next_proto_cb, NULL);
|
||||||
|
#endif /* !OPENSSL_NO_NEXTPROTONEG */
|
||||||
|
|
||||||
#if OPENSSL_VERSION_NUMBER >= 0x10002000L
|
#if OPENSSL_VERSION_NUMBER >= 0x10002000L
|
||||||
SSL_CTX_set_alpn_protos(ssl_ctx, (const unsigned char *)"\x02h2", 3);
|
SSL_CTX_set_alpn_protos(ssl_ctx, (const unsigned char *)"\x02h2", 3);
|
||||||
#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L
|
#endif /* OPENSSL_VERSION_NUMBER >= 0x10002000L */
|
||||||
|
|
||||||
return ssl_ctx;
|
return ssl_ctx;
|
||||||
}
|
}
|
||||||
@@ -504,12 +508,14 @@ static void eventcb(struct bufferevent *bev, short events, void *ptr) {
|
|||||||
|
|
||||||
ssl = bufferevent_openssl_get_ssl(session_data->bev);
|
ssl = bufferevent_openssl_get_ssl(session_data->bev);
|
||||||
|
|
||||||
|
#ifndef OPENSSL_NO_NEXTPROTONEG
|
||||||
SSL_get0_next_proto_negotiated(ssl, &alpn, &alpnlen);
|
SSL_get0_next_proto_negotiated(ssl, &alpn, &alpnlen);
|
||||||
|
#endif /* !OPENSSL_NO_NEXTPROTONEG */
|
||||||
#if OPENSSL_VERSION_NUMBER >= 0x10002000L
|
#if OPENSSL_VERSION_NUMBER >= 0x10002000L
|
||||||
if (alpn == NULL) {
|
if (alpn == NULL) {
|
||||||
SSL_get0_alpn_selected(ssl, &alpn, &alpnlen);
|
SSL_get0_alpn_selected(ssl, &alpn, &alpnlen);
|
||||||
}
|
}
|
||||||
#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L
|
#endif /* OPENSSL_VERSION_NUMBER >= 0x10002000L */
|
||||||
|
|
||||||
if (alpn == NULL || alpnlen != 2 || memcmp("h2", alpn, 2) != 0) {
|
if (alpn == NULL || alpnlen != 2 || memcmp("h2", alpn, 2) != 0) {
|
||||||
fprintf(stderr, "h2 is not negotiated\n");
|
fprintf(stderr, "h2 is not negotiated\n");
|
||||||
@@ -548,6 +554,7 @@ static void initiate_connection(struct event_base *evbase, SSL_CTX *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_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,
|
||||||
AF_UNSPEC, host, port);
|
AF_UNSPEC, host, port);
|
||||||
|
|||||||
@@ -23,41 +23,41 @@
|
|||||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
#ifdef __sgi
|
#ifdef __sgi
|
||||||
#define errx(exitcode, format, args...) \
|
# define errx(exitcode, format, args...) \
|
||||||
{ \
|
{ \
|
||||||
warnx(format, ##args); \
|
warnx(format, ##args); \
|
||||||
exit(exitcode); \
|
exit(exitcode); \
|
||||||
}
|
}
|
||||||
#define warn(format, args...) warnx(format ": %s", ##args, strerror(errno))
|
# define warn(format, args...) warnx(format ": %s", ##args, strerror(errno))
|
||||||
#define warnx(format, args...) fprintf(stderr, format "\n", ##args)
|
# define warnx(format, args...) fprintf(stderr, format "\n", ##args)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
#include <config.h>
|
# include <config.h>
|
||||||
#endif /* HAVE_CONFIG_H */
|
#endif /* HAVE_CONFIG_H */
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#ifdef HAVE_SYS_SOCKET_H
|
#ifdef HAVE_SYS_SOCKET_H
|
||||||
#include <sys/socket.h>
|
# include <sys/socket.h>
|
||||||
#endif /* HAVE_SYS_SOCKET_H */
|
#endif /* HAVE_SYS_SOCKET_H */
|
||||||
#ifdef HAVE_NETDB_H
|
#ifdef HAVE_NETDB_H
|
||||||
#include <netdb.h>
|
# include <netdb.h>
|
||||||
#endif /* HAVE_NETDB_H */
|
#endif /* HAVE_NETDB_H */
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#ifdef HAVE_UNISTD_H
|
#ifdef HAVE_UNISTD_H
|
||||||
#include <unistd.h>
|
# include <unistd.h>
|
||||||
#endif /* HAVE_UNISTD_H */
|
#endif /* HAVE_UNISTD_H */
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#ifdef HAVE_FCNTL_H
|
#ifdef HAVE_FCNTL_H
|
||||||
#include <fcntl.h>
|
# include <fcntl.h>
|
||||||
#endif /* HAVE_FCNTL_H */
|
#endif /* HAVE_FCNTL_H */
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#ifdef HAVE_NETINET_IN_H
|
#ifdef HAVE_NETINET_IN_H
|
||||||
#include <netinet/in.h>
|
# include <netinet/in.h>
|
||||||
#endif /* HAVE_NETINET_IN_H */
|
#endif /* HAVE_NETINET_IN_H */
|
||||||
#include <netinet/tcp.h>
|
#include <netinet/tcp.h>
|
||||||
#ifndef __sgi
|
#ifndef __sgi
|
||||||
#include <err.h>
|
# include <err.h>
|
||||||
#endif
|
#endif
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
@@ -109,6 +109,7 @@ struct app_context {
|
|||||||
static unsigned char next_proto_list[256];
|
static unsigned char next_proto_list[256];
|
||||||
static size_t next_proto_list_len;
|
static size_t next_proto_list_len;
|
||||||
|
|
||||||
|
#ifndef OPENSSL_NO_NEXTPROTONEG
|
||||||
static int next_proto_cb(SSL *ssl, const unsigned char **data,
|
static int next_proto_cb(SSL *ssl, const unsigned char **data,
|
||||||
unsigned int *len, void *arg) {
|
unsigned int *len, void *arg) {
|
||||||
(void)ssl;
|
(void)ssl;
|
||||||
@@ -118,6 +119,7 @@ static int next_proto_cb(SSL *ssl, const unsigned char **data,
|
|||||||
*len = (unsigned int)next_proto_list_len;
|
*len = (unsigned int)next_proto_list_len;
|
||||||
return SSL_TLSEXT_ERR_OK;
|
return SSL_TLSEXT_ERR_OK;
|
||||||
}
|
}
|
||||||
|
#endif /* !OPENSSL_NO_NEXTPROTONEG */
|
||||||
|
|
||||||
#if OPENSSL_VERSION_NUMBER >= 0x10002000L
|
#if OPENSSL_VERSION_NUMBER >= 0x10002000L
|
||||||
static int alpn_select_proto_cb(SSL *ssl, const unsigned char **out,
|
static int alpn_select_proto_cb(SSL *ssl, const unsigned char **out,
|
||||||
@@ -135,7 +137,7 @@ static int alpn_select_proto_cb(SSL *ssl, const unsigned char **out,
|
|||||||
|
|
||||||
return SSL_TLSEXT_ERR_OK;
|
return SSL_TLSEXT_ERR_OK;
|
||||||
}
|
}
|
||||||
#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L
|
#endif /* OPENSSL_VERSION_NUMBER >= 0x10002000L */
|
||||||
|
|
||||||
/* Create SSL_CTX. */
|
/* Create SSL_CTX. */
|
||||||
static SSL_CTX *create_ssl_ctx(const char *key_file, const char *cert_file) {
|
static SSL_CTX *create_ssl_ctx(const char *key_file, const char *cert_file) {
|
||||||
@@ -172,11 +174,13 @@ static SSL_CTX *create_ssl_ctx(const char *key_file, const char *cert_file) {
|
|||||||
NGHTTP2_PROTO_VERSION_ID_LEN);
|
NGHTTP2_PROTO_VERSION_ID_LEN);
|
||||||
next_proto_list_len = 1 + NGHTTP2_PROTO_VERSION_ID_LEN;
|
next_proto_list_len = 1 + NGHTTP2_PROTO_VERSION_ID_LEN;
|
||||||
|
|
||||||
|
#ifndef OPENSSL_NO_NEXTPROTONEG
|
||||||
SSL_CTX_set_next_protos_advertised_cb(ssl_ctx, next_proto_cb, NULL);
|
SSL_CTX_set_next_protos_advertised_cb(ssl_ctx, next_proto_cb, NULL);
|
||||||
|
#endif /* !OPENSSL_NO_NEXTPROTONEG */
|
||||||
|
|
||||||
#if OPENSSL_VERSION_NUMBER >= 0x10002000L
|
#if OPENSSL_VERSION_NUMBER >= 0x10002000L
|
||||||
SSL_CTX_set_alpn_select_cb(ssl_ctx, alpn_select_proto_cb, NULL);
|
SSL_CTX_set_alpn_select_cb(ssl_ctx, alpn_select_proto_cb, NULL);
|
||||||
#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L
|
#endif /* OPENSSL_VERSION_NUMBER >= 0x10002000L */
|
||||||
|
|
||||||
return ssl_ctx;
|
return ssl_ctx;
|
||||||
}
|
}
|
||||||
@@ -250,6 +254,7 @@ static http2_session_data *create_http2_session_data(app_context *app_ctx,
|
|||||||
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);
|
||||||
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);
|
||||||
if (rv != 0) {
|
if (rv != 0) {
|
||||||
@@ -689,12 +694,14 @@ static void eventcb(struct bufferevent *bev, short events, void *ptr) {
|
|||||||
|
|
||||||
ssl = bufferevent_openssl_get_ssl(session_data->bev);
|
ssl = bufferevent_openssl_get_ssl(session_data->bev);
|
||||||
|
|
||||||
|
#ifndef OPENSSL_NO_NEXTPROTONEG
|
||||||
SSL_get0_next_proto_negotiated(ssl, &alpn, &alpnlen);
|
SSL_get0_next_proto_negotiated(ssl, &alpn, &alpnlen);
|
||||||
|
#endif /* !OPENSSL_NO_NEXTPROTONEG */
|
||||||
#if OPENSSL_VERSION_NUMBER >= 0x10002000L
|
#if OPENSSL_VERSION_NUMBER >= 0x10002000L
|
||||||
if (alpn == NULL) {
|
if (alpn == NULL) {
|
||||||
SSL_get0_alpn_selected(ssl, &alpn, &alpnlen);
|
SSL_get0_alpn_selected(ssl, &alpn, &alpnlen);
|
||||||
}
|
}
|
||||||
#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L
|
#endif /* OPENSSL_VERSION_NUMBER >= 0x10002000L */
|
||||||
|
|
||||||
if (alpn == NULL || alpnlen != 2 || memcmp("h2", alpn, 2) != 0) {
|
if (alpn == NULL || alpnlen != 2 || memcmp("h2", alpn, 2) != 0) {
|
||||||
fprintf(stderr, "%s h2 is not negotiated\n", session_data->client_addr);
|
fprintf(stderr, "%s h2 is not negotiated\n", session_data->client_addr);
|
||||||
|
|||||||
@@ -23,8 +23,8 @@ following compiler/linker flags:
|
|||||||
|
|
||||||
.. code-block:: text
|
.. code-block:: text
|
||||||
|
|
||||||
CPPFLAGS="-fsanitize-coverage=edge -fsanitize=addres"
|
CPPFLAGS="-fsanitize-coverage=edge -fsanitize=address"
|
||||||
LDFLAGS="-fsanitize-coverage=edge -fsanitize=addres"
|
LDFLAGS="-fsanitize-coverage=edge -fsanitize=address"
|
||||||
|
|
||||||
Then, fuzz_target.cc can be built using the following command:
|
Then, fuzz_target.cc can be built using the following command:
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ HEADERS = [
|
|||||||
':scheme',
|
':scheme',
|
||||||
':status',
|
':status',
|
||||||
':host', # for spdy
|
':host', # for spdy
|
||||||
|
':protocol',
|
||||||
'expect',
|
'expect',
|
||||||
'host',
|
'host',
|
||||||
'if-modified-since',
|
'if-modified-since',
|
||||||
@@ -31,6 +32,9 @@ HEADERS = [
|
|||||||
"user-agent",
|
"user-agent",
|
||||||
"date",
|
"date",
|
||||||
"content-type",
|
"content-type",
|
||||||
|
"early-data",
|
||||||
|
"sec-websocket-accept",
|
||||||
|
"sec-websocket-key",
|
||||||
# disallowed h1 headers
|
# disallowed h1 headers
|
||||||
'connection',
|
'connection',
|
||||||
'keep-alive',
|
'keep-alive',
|
||||||
@@ -40,4 +44,4 @@ HEADERS = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
gentokenlookup(HEADERS, 'HD')
|
gentokenlookup(HEADERS, 'HD_')
|
||||||
|
|||||||
@@ -67,6 +67,7 @@ HEADERS = [
|
|||||||
('keep-alive',None),
|
('keep-alive',None),
|
||||||
('proxy-connection', None),
|
('proxy-connection', None),
|
||||||
('upgrade', None),
|
('upgrade', None),
|
||||||
|
(':protocol', None),
|
||||||
]
|
]
|
||||||
|
|
||||||
def to_enum_hd(k):
|
def to_enum_hd(k):
|
||||||
|
|||||||
@@ -50,4 +50,4 @@ if __name__ == '__main__':
|
|||||||
continue
|
continue
|
||||||
_, m, _ = line.split(',', 2)
|
_, m, _ = line.split(',', 2)
|
||||||
methods.append(m.strip())
|
methods.append(m.strip())
|
||||||
gentokenlookup(methods, 'HTTP')
|
gentokenlookup(methods, 'HTTP_')
|
||||||
|
|||||||
@@ -168,6 +168,13 @@ OPTIONS = [
|
|||||||
"no-strip-incoming-x-forwarded-proto",
|
"no-strip-incoming-x-forwarded-proto",
|
||||||
"ocsp-startup",
|
"ocsp-startup",
|
||||||
"no-verify-ocsp",
|
"no-verify-ocsp",
|
||||||
|
"verify-client-tolerate-expired",
|
||||||
|
"ignore-per-pattern-mruby-error",
|
||||||
|
"tls-no-postpone-early-data",
|
||||||
|
"tls-max-early-data",
|
||||||
|
"tls13-ciphers",
|
||||||
|
"tls13-client-ciphers",
|
||||||
|
"no-strip-incoming-early-data",
|
||||||
]
|
]
|
||||||
|
|
||||||
LOGVARS = [
|
LOGVARS = [
|
||||||
@@ -191,10 +198,15 @@ LOGVARS = [
|
|||||||
"tls_session_id",
|
"tls_session_id",
|
||||||
"tls_session_reused",
|
"tls_session_reused",
|
||||||
"tls_sni",
|
"tls_sni",
|
||||||
|
"tls_client_fingerprint_sha256",
|
||||||
|
"tls_client_fingerprint_sha1",
|
||||||
|
"tls_client_subject_name",
|
||||||
|
"tls_client_issuer_name",
|
||||||
|
"tls_client_serial",
|
||||||
"backend_host",
|
"backend_host",
|
||||||
"backend_port",
|
"backend_port",
|
||||||
]
|
]
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
gentokenlookup(OPTIONS, 'SHRPX_OPTID', value_type='char', comp_fun='util::strieq_l')
|
gentokenlookup(OPTIONS, 'SHRPX_OPTID_', value_type='char', comp_fun='util::strieq_l')
|
||||||
gentokenlookup(LOGVARS, 'SHRPX_LOGF', value_type='char', comp_fun='util::strieq_l', return_type='LogFragmentType', fail_value='SHRPX_LOGF_NONE')
|
gentokenlookup(LOGVARS, 'LogFragmentType::', value_type='char', comp_fun='util::strieq_l', return_type='LogFragmentType', fail_value='LogFragmentType::NONE')
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
|
|
||||||
def to_enum_hd(k, prefix):
|
def to_enum_hd(k, prefix):
|
||||||
res = prefix + '_'
|
res = prefix
|
||||||
for c in k.upper():
|
for c in k.upper():
|
||||||
if c == ':' or c == '-':
|
if c == ':' or c == '-':
|
||||||
res += '_'
|
res += '_'
|
||||||
@@ -30,7 +30,7 @@ enum {'''
|
|||||||
print '''\
|
print '''\
|
||||||
{},'''.format(to_enum_hd(k, prefix))
|
{},'''.format(to_enum_hd(k, prefix))
|
||||||
print '''\
|
print '''\
|
||||||
{}_MAXIDX,
|
{}MAXIDX,
|
||||||
}};'''.format(prefix)
|
}};'''.format(prefix)
|
||||||
|
|
||||||
def gen_index_header(tokens, prefix, value_type, comp_fun, return_type, fail_value):
|
def gen_index_header(tokens, prefix, value_type, comp_fun, return_type, fail_value):
|
||||||
|
|||||||
@@ -167,7 +167,7 @@ def format_text(text):
|
|||||||
else:
|
else:
|
||||||
text = re.sub(r'\*', r'\*', text)
|
text = re.sub(r'\*', r'\*', text)
|
||||||
# markup option reference
|
# markup option reference
|
||||||
text = re.sub(r'(^|\s)(-[a-zA-Z0-9]|--[a-zA-Z0-9-]+)',
|
text = re.sub(r'(^|\s)(-[a-zA-Z]|--[a-zA-Z0-9-]+)',
|
||||||
r'\1:option:`\2`', text)
|
r'\1:option:`\2`', text)
|
||||||
# sphinx does not like markup like ':option:`-f`='. We need
|
# sphinx does not like markup like ':option:`-f`='. We need
|
||||||
# backslash between ` and =.
|
# backslash between ` and =.
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
set(GO_FILES
|
set(GO_FILES
|
||||||
nghttpx_http1_test.go
|
nghttpx_http1_test.go
|
||||||
nghttpx_http2_test.go
|
nghttpx_http2_test.go
|
||||||
nghttpx_spdy_test.go
|
|
||||||
server_tester.go
|
server_tester.go
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -22,7 +21,6 @@ set(EXTRA_DIST
|
|||||||
add_custom_target(itprep
|
add_custom_target(itprep
|
||||||
COMMAND go get -d -v golang.org/x/net/http2
|
COMMAND go get -d -v golang.org/x/net/http2
|
||||||
COMMAND go get -d -v github.com/tatsuhiro-t/go-nghttp2
|
COMMAND go get -d -v github.com/tatsuhiro-t/go-nghttp2
|
||||||
COMMAND go get -d -v github.com/tatsuhiro-t/spdy
|
|
||||||
COMMAND go get -d -v golang.org/x/net/websocket
|
COMMAND go get -d -v golang.org/x/net/websocket
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -24,7 +24,6 @@
|
|||||||
GO_FILES = \
|
GO_FILES = \
|
||||||
nghttpx_http1_test.go \
|
nghttpx_http1_test.go \
|
||||||
nghttpx_http2_test.go \
|
nghttpx_http2_test.go \
|
||||||
nghttpx_spdy_test.go \
|
|
||||||
server_tester.go
|
server_tester.go
|
||||||
|
|
||||||
EXTRA_DIST = \
|
EXTRA_DIST = \
|
||||||
@@ -43,7 +42,6 @@ EXTRA_DIST = \
|
|||||||
itprep:
|
itprep:
|
||||||
go get -d -v golang.org/x/net/http2
|
go get -d -v golang.org/x/net/http2
|
||||||
go get -d -v github.com/tatsuhiro-t/go-nghttp2
|
go get -d -v github.com/tatsuhiro-t/go-nghttp2
|
||||||
go get -d -v github.com/tatsuhiro-t/spdy
|
|
||||||
go get -d -v golang.org/x/net/websocket
|
go get -d -v golang.org/x/net/websocket
|
||||||
|
|
||||||
it:
|
it:
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import (
|
|||||||
"golang.org/x/net/websocket"
|
"golang.org/x/net/websocket"
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"regexp"
|
||||||
"syscall"
|
"syscall"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
@@ -125,6 +126,54 @@ Content-Length: 0
|
|||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
// TestH1H1AffinityCookie tests that affinity cookie is sent back in
|
||||||
|
// cleartext http.
|
||||||
|
func TestH1H1AffinityCookie(t *testing.T) {
|
||||||
|
st := newServerTester([]string{"--affinity-cookie"}, t, noopHandler)
|
||||||
|
defer st.Close()
|
||||||
|
|
||||||
|
res, err := st.http1(requestParam{
|
||||||
|
name: "TestH1H1AffinityCookie",
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Error st.http1() = %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if got, want := res.status, 200; got != want {
|
||||||
|
t.Errorf("status = %v; want %v", got, want)
|
||||||
|
}
|
||||||
|
|
||||||
|
const pattern = `affinity=[0-9a-f]{8}; Path=/foo/bar`
|
||||||
|
validCookie := regexp.MustCompile(pattern)
|
||||||
|
if got := res.header.Get("Set-Cookie"); !validCookie.MatchString(got) {
|
||||||
|
t.Errorf("Set-Cookie: %v; want pattern %v", got, pattern)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestH1H1AffinityCookieTLS tests that affinity cookie is sent back
|
||||||
|
// in https.
|
||||||
|
func TestH1H1AffinityCookieTLS(t *testing.T) {
|
||||||
|
st := newServerTesterTLS([]string{"--alpn-h1", "--affinity-cookie"}, t, noopHandler)
|
||||||
|
defer st.Close()
|
||||||
|
|
||||||
|
res, err := st.http1(requestParam{
|
||||||
|
name: "TestH1H1AffinityCookieTLS",
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Error st.http1() = %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if got, want := res.status, 200; got != want {
|
||||||
|
t.Errorf("status = %v; want %v", got, want)
|
||||||
|
}
|
||||||
|
|
||||||
|
const pattern = `affinity=[0-9a-f]{8}; Path=/foo/bar; Secure`
|
||||||
|
validCookie := regexp.MustCompile(pattern)
|
||||||
|
if got := res.header.Get("Set-Cookie"); !validCookie.MatchString(got) {
|
||||||
|
t.Errorf("Set-Cookie: %v; want pattern %v", got, pattern)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// TestH1H1GracefulShutdown tests graceful shutdown.
|
// TestH1H1GracefulShutdown tests graceful shutdown.
|
||||||
func TestH1H1GracefulShutdown(t *testing.T) {
|
func TestH1H1GracefulShutdown(t *testing.T) {
|
||||||
st := newServerTester(nil, t, noopHandler)
|
st := newServerTester(nil, t, noopHandler)
|
||||||
@@ -162,7 +211,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); err == nil || err != want {
|
||||||
t.Errorf("st.conn.Read(): %v; want %v, %v", err, want)
|
t.Errorf("st.conn.Read(): %v; want %v", err, want)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1113,14 +1113,45 @@ func TestH2H1Upgrade(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TestH2H1ProxyProtocolV1ForwardedForObfuscated tests that Forwarded
|
||||||
|
// header field includes obfuscated address even if PROXY protocol
|
||||||
|
// version 1 containing TCP4 entry is accepted.
|
||||||
|
func TestH2H1ProxyProtocolV1ForwardedForObfuscated(t *testing.T) {
|
||||||
|
pattern := fmt.Sprintf(`^for=_[^;]+$`)
|
||||||
|
validFwd := regexp.MustCompile(pattern)
|
||||||
|
st := newServerTester([]string{"--accept-proxy-protocol", "--add-x-forwarded-for", "--add-forwarded=for", "--forwarded-for=obfuscated"}, t, func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
if got := r.Header.Get("Forwarded"); !validFwd.MatchString(got) {
|
||||||
|
t.Errorf("Forwarded: %v; want pattern %v", got, pattern)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
defer st.Close()
|
||||||
|
|
||||||
|
st.conn.Write([]byte("PROXY TCP4 192.168.0.2 192.168.0.100 12345 8080\r\n"))
|
||||||
|
|
||||||
|
res, err := st.http2(requestParam{
|
||||||
|
name: "TestH2H1ProxyProtocolV1ForwardedForObfuscated",
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Error st.http2() = %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if got, want := res.status, 200; got != want {
|
||||||
|
t.Errorf("res.status: %v; want %v", got, want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// TestH2H1ProxyProtocolV1TCP4 tests PROXY protocol version 1
|
// TestH2H1ProxyProtocolV1TCP4 tests PROXY protocol version 1
|
||||||
// containing TCP4 entry is accepted and X-Forwarded-For contains
|
// containing TCP4 entry is accepted and X-Forwarded-For contains
|
||||||
// advertised src address.
|
// advertised src address.
|
||||||
func TestH2H1ProxyProtocolV1TCP4(t *testing.T) {
|
func TestH2H1ProxyProtocolV1TCP4(t *testing.T) {
|
||||||
st := newServerTester([]string{"--accept-proxy-protocol", "--add-x-forwarded-for"}, t, func(w http.ResponseWriter, r *http.Request) {
|
st := newServerTester([]string{"--accept-proxy-protocol", "--add-x-forwarded-for", "--add-forwarded=for", "--forwarded-for=ip"}, t, func(w http.ResponseWriter, r *http.Request) {
|
||||||
if got, want := r.Header.Get("X-Forwarded-For"), "192.168.0.2"; got != want {
|
if got, want := r.Header.Get("X-Forwarded-For"), "192.168.0.2"; got != want {
|
||||||
t.Errorf("X-Forwarded-For: %v; want %v", got, want)
|
t.Errorf("X-Forwarded-For: %v; want %v", got, want)
|
||||||
}
|
}
|
||||||
|
if got, want := r.Header.Get("Forwarded"), "for=192.168.0.2"; got != want {
|
||||||
|
t.Errorf("Forwarded: %v; want %v", got, want)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
defer st.Close()
|
defer st.Close()
|
||||||
|
|
||||||
@@ -1143,10 +1174,13 @@ func TestH2H1ProxyProtocolV1TCP4(t *testing.T) {
|
|||||||
// containing TCP6 entry is accepted and X-Forwarded-For contains
|
// containing TCP6 entry is accepted and X-Forwarded-For contains
|
||||||
// advertised src address.
|
// advertised src address.
|
||||||
func TestH2H1ProxyProtocolV1TCP6(t *testing.T) {
|
func TestH2H1ProxyProtocolV1TCP6(t *testing.T) {
|
||||||
st := newServerTester([]string{"--accept-proxy-protocol", "--add-x-forwarded-for"}, t, func(w http.ResponseWriter, r *http.Request) {
|
st := newServerTester([]string{"--accept-proxy-protocol", "--add-x-forwarded-for", "--add-forwarded=for", "--forwarded-for=ip"}, t, func(w http.ResponseWriter, r *http.Request) {
|
||||||
if got, want := r.Header.Get("X-Forwarded-For"), "2001:0db8:85a3:0000:0000:8a2e:0370:7334"; got != want {
|
if got, want := r.Header.Get("X-Forwarded-For"), "2001:0db8:85a3:0000:0000:8a2e:0370:7334"; got != want {
|
||||||
t.Errorf("X-Forwarded-For: %v; want %v", got, want)
|
t.Errorf("X-Forwarded-For: %v; want %v", got, want)
|
||||||
}
|
}
|
||||||
|
if got, want := r.Header.Get("Forwarded"), `for="[2001:0db8:85a3:0000:0000:8a2e:0370:7334]"`; got != want {
|
||||||
|
t.Errorf("Forwarded: %v; want %v", got, want)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
defer st.Close()
|
defer st.Close()
|
||||||
|
|
||||||
@@ -1168,9 +1202,12 @@ func TestH2H1ProxyProtocolV1TCP6(t *testing.T) {
|
|||||||
// TestH2H1ProxyProtocolV1Unknown tests PROXY protocol version 1
|
// TestH2H1ProxyProtocolV1Unknown tests PROXY protocol version 1
|
||||||
// containing UNKNOWN entry is accepted.
|
// containing UNKNOWN entry is accepted.
|
||||||
func TestH2H1ProxyProtocolV1Unknown(t *testing.T) {
|
func TestH2H1ProxyProtocolV1Unknown(t *testing.T) {
|
||||||
st := newServerTester([]string{"--accept-proxy-protocol", "--add-x-forwarded-for"}, t, func(w http.ResponseWriter, r *http.Request) {
|
st := newServerTester([]string{"--accept-proxy-protocol", "--add-x-forwarded-for", "--add-forwarded=for", "--forwarded-for=ip"}, t, func(w http.ResponseWriter, r *http.Request) {
|
||||||
if got, notWant := r.Header.Get("X-Forwarded-For"), "192.168.0.2"; got == notWant {
|
if got, notWant := r.Header.Get("X-Forwarded-For"), "192.168.0.2"; got == notWant {
|
||||||
t.Errorf("X-Forwarded-For: %v")
|
t.Errorf("X-Forwarded-For: %v; want something else", got)
|
||||||
|
}
|
||||||
|
if got, notWant := r.Header.Get("Forwarded"), "for=192.168.0.2"; got == notWant {
|
||||||
|
t.Errorf("Forwarded: %v; want something else", got)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
defer st.Close()
|
defer st.Close()
|
||||||
@@ -1668,6 +1705,55 @@ func TestH2H1Code204TE(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TestH2H1AffinityCookie tests that affinity cookie is sent back in
|
||||||
|
// cleartext http.
|
||||||
|
func TestH2H1AffinityCookie(t *testing.T) {
|
||||||
|
st := newServerTester([]string{"--affinity-cookie"}, t, noopHandler)
|
||||||
|
defer st.Close()
|
||||||
|
|
||||||
|
res, err := st.http2(requestParam{
|
||||||
|
name: "TestH2H1AffinityCookie",
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Error st.http2() = %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if got, want := res.status, 200; got != want {
|
||||||
|
t.Errorf("status = %v; want %v", got, want)
|
||||||
|
}
|
||||||
|
|
||||||
|
const pattern = `affinity=[0-9a-f]{8}; Path=/foo/bar`
|
||||||
|
validCookie := regexp.MustCompile(pattern)
|
||||||
|
if got := res.header.Get("Set-Cookie"); !validCookie.MatchString(got) {
|
||||||
|
t.Errorf("Set-Cookie: %v; want pattern %v", got, pattern)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestH2H1AffinityCookieTLS tests that affinity cookie is sent back
|
||||||
|
// in https.
|
||||||
|
func TestH2H1AffinityCookieTLS(t *testing.T) {
|
||||||
|
st := newServerTesterTLS([]string{"--affinity-cookie"}, t, noopHandler)
|
||||||
|
defer st.Close()
|
||||||
|
|
||||||
|
res, err := st.http2(requestParam{
|
||||||
|
name: "TestH2H1AffinityCookieTLS",
|
||||||
|
scheme: "https",
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Error st.http2() = %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if got, want := res.status, 200; got != want {
|
||||||
|
t.Errorf("status = %v; want %v", got, want)
|
||||||
|
}
|
||||||
|
|
||||||
|
const pattern = `affinity=[0-9a-f]{8}; Path=/foo/bar; Secure`
|
||||||
|
validCookie := regexp.MustCompile(pattern)
|
||||||
|
if got := res.header.Get("Set-Cookie"); !validCookie.MatchString(got) {
|
||||||
|
t.Errorf("Set-Cookie: %v; want pattern %v", got, pattern)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// TestH2H1GracefulShutdown tests graceful shutdown.
|
// TestH2H1GracefulShutdown tests graceful shutdown.
|
||||||
func TestH2H1GracefulShutdown(t *testing.T) {
|
func TestH2H1GracefulShutdown(t *testing.T) {
|
||||||
st := newServerTester(nil, t, noopHandler)
|
st := newServerTester(nil, t, noopHandler)
|
||||||
|
|||||||
@@ -1,664 +0,0 @@
|
|||||||
package nghttp2
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"github.com/tatsuhiro-t/spdy"
|
|
||||||
"golang.org/x/net/http2/hpack"
|
|
||||||
"net/http"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
// TestS3H1PlainGET tests whether simple SPDY GET request works.
|
|
||||||
func TestS3H1PlainGET(t *testing.T) {
|
|
||||||
st := newServerTesterTLS([]string{"--npn-list=spdy/3.1"}, t, noopHandler)
|
|
||||||
defer st.Close()
|
|
||||||
|
|
||||||
res, err := st.spdy(requestParam{
|
|
||||||
name: "TestS3H1PlainGET",
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Error st.spdy() = %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
want := 200
|
|
||||||
if got := res.status; got != want {
|
|
||||||
t.Errorf("status = %v; want %v", got, want)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TestS3H1BadRequestCL tests that server rejects request whose
|
|
||||||
// content-length header field value does not match its request body
|
|
||||||
// size.
|
|
||||||
func TestS3H1BadRequestCL(t *testing.T) {
|
|
||||||
st := newServerTesterTLS([]string{"--npn-list=spdy/3.1"}, t, noopHandler)
|
|
||||||
defer st.Close()
|
|
||||||
|
|
||||||
// we set content-length: 1024, but the actual request body is
|
|
||||||
// 3 bytes.
|
|
||||||
res, err := st.spdy(requestParam{
|
|
||||||
name: "TestS3H1BadRequestCL",
|
|
||||||
method: "POST",
|
|
||||||
header: []hpack.HeaderField{
|
|
||||||
pair("content-length", "1024"),
|
|
||||||
},
|
|
||||||
body: []byte("foo"),
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Error st.spdy() = %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
want := spdy.ProtocolError
|
|
||||||
if got := res.spdyRstErrCode; got != want {
|
|
||||||
t.Errorf("res.spdyRstErrCode = %v; want %v", got, want)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TestS3H1MultipleRequestCL tests that server rejects request with
|
|
||||||
// multiple Content-Length request header fields.
|
|
||||||
func TestS3H1MultipleRequestCL(t *testing.T) {
|
|
||||||
st := newServerTesterTLS([]string{"--npn-list=spdy/3.1"}, t, func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
t.Errorf("server should not forward bad request")
|
|
||||||
})
|
|
||||||
defer st.Close()
|
|
||||||
|
|
||||||
res, err := st.spdy(requestParam{
|
|
||||||
name: "TestS3H1MultipleRequestCL",
|
|
||||||
header: []hpack.HeaderField{
|
|
||||||
pair("content-length", "1"),
|
|
||||||
pair("content-length", "1"),
|
|
||||||
},
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Error st.spdy() = %v", err)
|
|
||||||
}
|
|
||||||
want := 400
|
|
||||||
if got := res.status; got != want {
|
|
||||||
t.Errorf("status: %v; want %v", got, want)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TestS3H1InvalidRequestCL tests that server rejects request with
|
|
||||||
// Content-Length which cannot be parsed as a number.
|
|
||||||
func TestS3H1InvalidRequestCL(t *testing.T) {
|
|
||||||
st := newServerTesterTLS([]string{"--npn-list=spdy/3.1"}, t, func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
t.Errorf("server should not forward bad request")
|
|
||||||
})
|
|
||||||
defer st.Close()
|
|
||||||
|
|
||||||
res, err := st.spdy(requestParam{
|
|
||||||
name: "TestS3H1InvalidRequestCL",
|
|
||||||
header: []hpack.HeaderField{
|
|
||||||
pair("content-length", ""),
|
|
||||||
},
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Error st.spdy() = %v", err)
|
|
||||||
}
|
|
||||||
want := 400
|
|
||||||
if got := res.status; got != want {
|
|
||||||
t.Errorf("status: %v; want %v", got, want)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TestS3H1GenerateVia tests that server generates Via header field to and
|
|
||||||
// from backend server.
|
|
||||||
func TestS3H1GenerateVia(t *testing.T) {
|
|
||||||
st := newServerTesterTLS([]string{"--npn-list=spdy/3.1"}, t, func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
if got, want := r.Header.Get("Via"), "1.1 nghttpx"; got != want {
|
|
||||||
t.Errorf("Via: %v; want %v", got, want)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
defer st.Close()
|
|
||||||
|
|
||||||
res, err := st.spdy(requestParam{
|
|
||||||
name: "TestS3H1GenerateVia",
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Error st.spdy() = %v", err)
|
|
||||||
}
|
|
||||||
if got, want := res.header.Get("Via"), "1.1 nghttpx"; got != want {
|
|
||||||
t.Errorf("Via: %v; want %v", got, want)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TestS3H1AppendVia tests that server adds value to existing Via
|
|
||||||
// header field to and from backend server.
|
|
||||||
func TestS3H1AppendVia(t *testing.T) {
|
|
||||||
st := newServerTesterTLS([]string{"--npn-list=spdy/3.1"}, t, func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
if got, want := r.Header.Get("Via"), "foo, 1.1 nghttpx"; got != want {
|
|
||||||
t.Errorf("Via: %v; want %v", got, want)
|
|
||||||
}
|
|
||||||
w.Header().Add("Via", "bar")
|
|
||||||
})
|
|
||||||
defer st.Close()
|
|
||||||
|
|
||||||
res, err := st.spdy(requestParam{
|
|
||||||
name: "TestS3H1AppendVia",
|
|
||||||
header: []hpack.HeaderField{
|
|
||||||
pair("via", "foo"),
|
|
||||||
},
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Error st.spdy() = %v", err)
|
|
||||||
}
|
|
||||||
if got, want := res.header.Get("Via"), "bar, 1.1 nghttpx"; got != want {
|
|
||||||
t.Errorf("Via: %v; want %v", got, want)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TestS3H1NoVia tests that server does not add value to existing Via
|
|
||||||
// header field to and from backend server.
|
|
||||||
func TestS3H1NoVia(t *testing.T) {
|
|
||||||
st := newServerTesterTLS([]string{"--npn-list=spdy/3.1", "--no-via"}, t, func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
if got, want := r.Header.Get("Via"), "foo"; got != want {
|
|
||||||
t.Errorf("Via: %v; want %v", got, want)
|
|
||||||
}
|
|
||||||
w.Header().Add("Via", "bar")
|
|
||||||
})
|
|
||||||
defer st.Close()
|
|
||||||
|
|
||||||
res, err := st.spdy(requestParam{
|
|
||||||
name: "TestS3H1NoVia",
|
|
||||||
header: []hpack.HeaderField{
|
|
||||||
pair("via", "foo"),
|
|
||||||
},
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Error st.spdy() = %v", err)
|
|
||||||
}
|
|
||||||
if got, want := res.header.Get("Via"), "bar"; got != want {
|
|
||||||
t.Errorf("Via: %v; want %v", got, want)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TestS3H1HeaderFieldBuffer tests that request with header fields
|
|
||||||
// larger than configured buffer size is rejected.
|
|
||||||
func TestS3H1HeaderFieldBuffer(t *testing.T) {
|
|
||||||
st := newServerTesterTLS([]string{"--npn-list=spdy/3.1", "--request-header-field-buffer=10"}, t, func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
t.Fatal("execution path should not be here")
|
|
||||||
})
|
|
||||||
defer st.Close()
|
|
||||||
|
|
||||||
res, err := st.spdy(requestParam{
|
|
||||||
name: "TestS3H1HeaderFieldBuffer",
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Error st.spdy() = %v", err)
|
|
||||||
}
|
|
||||||
if got, want := res.spdyRstErrCode, spdy.InternalError; got != want {
|
|
||||||
t.Errorf("res.spdyRstErrCode: %v; want %v", got, want)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TestS3H1HeaderFields tests that request with header fields more
|
|
||||||
// than configured number is rejected.
|
|
||||||
func TestS3H1HeaderFields(t *testing.T) {
|
|
||||||
st := newServerTesterTLS([]string{"--npn-list=spdy/3.1", "--max-request-header-fields=1"}, t, func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
t.Fatal("execution path should not be here")
|
|
||||||
})
|
|
||||||
defer st.Close()
|
|
||||||
|
|
||||||
res, err := st.spdy(requestParam{
|
|
||||||
name: "TestS3H1HeaderFields",
|
|
||||||
// we have at least 5 pseudo-header fields sent, and
|
|
||||||
// that ensures that buffer limit exceeds.
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Error st.spdy() = %v", err)
|
|
||||||
}
|
|
||||||
if got, want := res.spdyRstErrCode, spdy.InternalError; got != want {
|
|
||||||
t.Errorf("res.spdyRstErrCode: %v; want %v", got, want)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TestS3H1InvalidMethod tests that server rejects invalid method with
|
|
||||||
// 501.
|
|
||||||
func TestS3H1InvalidMethod(t *testing.T) {
|
|
||||||
st := newServerTesterTLS([]string{"--npn-list=spdy/3.1"}, t, func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
t.Errorf("server should not forward this request")
|
|
||||||
})
|
|
||||||
defer st.Close()
|
|
||||||
|
|
||||||
res, err := st.spdy(requestParam{
|
|
||||||
name: "TestS3H1InvalidMethod",
|
|
||||||
method: "get",
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Error st.spdy() = %v", err)
|
|
||||||
}
|
|
||||||
if got, want := res.status, 501; got != want {
|
|
||||||
t.Errorf("status: %v; want %v", got, want)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TestS3H1BadHost tests that server rejects request including bad
|
|
||||||
// character in :host header field.
|
|
||||||
func TestS3H1BadHost(t *testing.T) {
|
|
||||||
st := newServerTesterTLS([]string{"--npn-list=spdy/3.1"}, t, func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
t.Errorf("server should not forward this request")
|
|
||||||
})
|
|
||||||
defer st.Close()
|
|
||||||
|
|
||||||
res, err := st.spdy(requestParam{
|
|
||||||
name: "TestS3H1BadHost",
|
|
||||||
authority: `foo\bar`,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Error st.spdy() = %v", err)
|
|
||||||
}
|
|
||||||
if got, want := res.status, 400; got != want {
|
|
||||||
t.Errorf("status: %v; want %v", got, want)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TestS3H1BadScheme tests that server rejects request including bad
|
|
||||||
// character in :scheme header field.
|
|
||||||
func TestS3H1BadScheme(t *testing.T) {
|
|
||||||
st := newServerTesterTLS([]string{"--npn-list=spdy/3.1"}, t, func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
t.Errorf("server should not forward this request")
|
|
||||||
})
|
|
||||||
defer st.Close()
|
|
||||||
|
|
||||||
res, err := st.spdy(requestParam{
|
|
||||||
name: "TestS3H1BadScheme",
|
|
||||||
scheme: `http*`,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Error st.spdy() = %v", err)
|
|
||||||
}
|
|
||||||
if got, want := res.status, 400; got != want {
|
|
||||||
t.Errorf("status: %v; want %v", got, want)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TestS3H1ReqPhaseSetHeader tests mruby request phase hook
|
|
||||||
// modifies request header fields.
|
|
||||||
func TestS3H1ReqPhaseSetHeader(t *testing.T) {
|
|
||||||
st := newServerTesterTLS([]string{"--npn-list=spdy/3.1", "--mruby-file=" + testDir + "/req-set-header.rb"}, t, func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
if got, want := r.Header.Get("User-Agent"), "mruby"; got != want {
|
|
||||||
t.Errorf("User-Agent = %v; want %v", got, want)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
defer st.Close()
|
|
||||||
|
|
||||||
res, err := st.spdy(requestParam{
|
|
||||||
name: "TestS3H1ReqPhaseSetHeader",
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Error st.spdy() = %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if got, want := res.status, 200; got != want {
|
|
||||||
t.Errorf("status = %v; want %v", got, want)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TestS3H1ReqPhaseReturn tests mruby request phase hook returns
|
|
||||||
// custom response.
|
|
||||||
func TestS3H1ReqPhaseReturn(t *testing.T) {
|
|
||||||
st := newServerTesterTLS([]string{"--npn-list=spdy/3.1", "--mruby-file=" + testDir + "/req-return.rb"}, t, func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
t.Fatalf("request should not be forwarded")
|
|
||||||
})
|
|
||||||
defer st.Close()
|
|
||||||
|
|
||||||
res, err := st.spdy(requestParam{
|
|
||||||
name: "TestS3H1ReqPhaseReturn",
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Error st.spdy() = %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if got, want := res.status, 404; got != want {
|
|
||||||
t.Errorf("status = %v; want %v", got, want)
|
|
||||||
}
|
|
||||||
|
|
||||||
hdtests := []struct {
|
|
||||||
k, v string
|
|
||||||
}{
|
|
||||||
{"content-length", "20"},
|
|
||||||
{"from", "mruby"},
|
|
||||||
}
|
|
||||||
for _, tt := range hdtests {
|
|
||||||
if got, want := res.header.Get(tt.k), tt.v; got != want {
|
|
||||||
t.Errorf("%v = %v; want %v", tt.k, got, want)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if got, want := string(res.body), "Hello World from req"; got != want {
|
|
||||||
t.Errorf("body = %v; want %v", got, want)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TestS3H1RespPhaseSetHeader tests mruby response phase hook modifies
|
|
||||||
// response header fields.
|
|
||||||
func TestS3H1RespPhaseSetHeader(t *testing.T) {
|
|
||||||
st := newServerTesterTLS([]string{"--npn-list=spdy/3.1", "--mruby-file=" + testDir + "/resp-set-header.rb"}, t, noopHandler)
|
|
||||||
defer st.Close()
|
|
||||||
|
|
||||||
res, err := st.spdy(requestParam{
|
|
||||||
name: "TestS3H1RespPhaseSetHeader",
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Error st.spdy() = %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if got, want := res.status, 200; got != want {
|
|
||||||
t.Errorf("status = %v; want %v", got, want)
|
|
||||||
}
|
|
||||||
|
|
||||||
if got, want := res.header.Get("alpha"), "bravo"; got != want {
|
|
||||||
t.Errorf("alpha = %v; want %v", got, want)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TestS3H1RespPhaseReturn tests mruby response phase hook returns
|
|
||||||
// custom response.
|
|
||||||
func TestS3H1RespPhaseReturn(t *testing.T) {
|
|
||||||
st := newServerTesterTLS([]string{"--npn-list=spdy/3.1", "--mruby-file=" + testDir + "/resp-return.rb"}, t, noopHandler)
|
|
||||||
defer st.Close()
|
|
||||||
|
|
||||||
res, err := st.spdy(requestParam{
|
|
||||||
name: "TestS3H1RespPhaseReturn",
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Error st.spdy() = %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if got, want := res.status, 404; got != want {
|
|
||||||
t.Errorf("status = %v; want %v", got, want)
|
|
||||||
}
|
|
||||||
|
|
||||||
hdtests := []struct {
|
|
||||||
k, v string
|
|
||||||
}{
|
|
||||||
{"content-length", "21"},
|
|
||||||
{"from", "mruby"},
|
|
||||||
}
|
|
||||||
for _, tt := range hdtests {
|
|
||||||
if got, want := res.header.Get(tt.k), tt.v; got != want {
|
|
||||||
t.Errorf("%v = %v; want %v", tt.k, got, want)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if got, want := string(res.body), "Hello World from resp"; got != want {
|
|
||||||
t.Errorf("body = %v; want %v", got, want)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// // TestS3H2ConnectFailure tests that server handles the situation that
|
|
||||||
// // connection attempt to HTTP/2 backend failed.
|
|
||||||
// func TestS3H2ConnectFailure(t *testing.T) {
|
|
||||||
// st := newServerTesterTLS([]string{"--npn-list=spdy/3.1", "--http2-bridge"}, t, noopHandler)
|
|
||||||
// defer st.Close()
|
|
||||||
|
|
||||||
// // simulate backend connect attempt failure
|
|
||||||
// st.ts.Close()
|
|
||||||
|
|
||||||
// res, err := st.spdy(requestParam{
|
|
||||||
// name: "TestS3H2ConnectFailure",
|
|
||||||
// })
|
|
||||||
// if err != nil {
|
|
||||||
// t.Fatalf("Error st.spdy() = %v", err)
|
|
||||||
// }
|
|
||||||
// want := 503
|
|
||||||
// if got := res.status; got != want {
|
|
||||||
// t.Errorf("status: %v; want %v", got, want)
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// TestS3H2ReqPhaseReturn tests mruby request phase hook returns
|
|
||||||
// custom response.
|
|
||||||
func TestS3H2ReqPhaseReturn(t *testing.T) {
|
|
||||||
st := newServerTesterTLS([]string{"--npn-list=spdy/3.1", "--http2-bridge", "--mruby-file=" + testDir + "/req-return.rb"}, t, func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
t.Fatalf("request should not be forwarded")
|
|
||||||
})
|
|
||||||
defer st.Close()
|
|
||||||
|
|
||||||
res, err := st.spdy(requestParam{
|
|
||||||
name: "TestS3H2ReqPhaseReturn",
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Error st.spdy() = %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if got, want := res.status, 404; got != want {
|
|
||||||
t.Errorf("status = %v; want %v", got, want)
|
|
||||||
}
|
|
||||||
|
|
||||||
hdtests := []struct {
|
|
||||||
k, v string
|
|
||||||
}{
|
|
||||||
{"content-length", "20"},
|
|
||||||
{"from", "mruby"},
|
|
||||||
}
|
|
||||||
for _, tt := range hdtests {
|
|
||||||
if got, want := res.header.Get(tt.k), tt.v; got != want {
|
|
||||||
t.Errorf("%v = %v; want %v", tt.k, got, want)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if got, want := string(res.body), "Hello World from req"; got != want {
|
|
||||||
t.Errorf("body = %v; want %v", got, want)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TestS3H2RespPhaseReturn tests mruby response phase hook returns
|
|
||||||
// custom response.
|
|
||||||
func TestS3H2RespPhaseReturn(t *testing.T) {
|
|
||||||
st := newServerTesterTLS([]string{"--npn-list=spdy/3.1", "--http2-bridge", "--mruby-file=" + testDir + "/resp-return.rb"}, t, noopHandler)
|
|
||||||
defer st.Close()
|
|
||||||
|
|
||||||
res, err := st.spdy(requestParam{
|
|
||||||
name: "TestS3H2RespPhaseReturn",
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Error st.spdy() = %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if got, want := res.status, 404; got != want {
|
|
||||||
t.Errorf("status = %v; want %v", got, want)
|
|
||||||
}
|
|
||||||
|
|
||||||
hdtests := []struct {
|
|
||||||
k, v string
|
|
||||||
}{
|
|
||||||
{"content-length", "21"},
|
|
||||||
{"from", "mruby"},
|
|
||||||
}
|
|
||||||
for _, tt := range hdtests {
|
|
||||||
if got, want := res.header.Get(tt.k), tt.v; got != want {
|
|
||||||
t.Errorf("%v = %v; want %v", tt.k, got, want)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if got, want := string(res.body), "Hello World from resp"; got != want {
|
|
||||||
t.Errorf("body = %v; want %v", got, want)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TestS3APIBackendconfig exercise backendconfig API endpoint routine
|
|
||||||
// for successful case.
|
|
||||||
func TestS3APIBackendconfig(t *testing.T) {
|
|
||||||
st := newServerTesterTLSConnectPort([]string{"--npn-list=spdy/3.1", "-f127.0.0.1,3010;api"}, t, func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
t.Fatalf("request should not be forwarded")
|
|
||||||
}, 3010)
|
|
||||||
defer st.Close()
|
|
||||||
|
|
||||||
res, err := st.spdy(requestParam{
|
|
||||||
name: "TestS3APIBackendconfig",
|
|
||||||
path: "/api/v1beta1/backendconfig",
|
|
||||||
method: "PUT",
|
|
||||||
body: []byte(`# comment
|
|
||||||
backend=127.0.0.1,3011
|
|
||||||
|
|
||||||
`),
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Error st.spdy() = %v", err)
|
|
||||||
}
|
|
||||||
if got, want := res.status, 200; got != want {
|
|
||||||
t.Errorf("res.status: %v; want %v", got, want)
|
|
||||||
}
|
|
||||||
|
|
||||||
var apiResp APIResponse
|
|
||||||
err = json.Unmarshal(res.body, &apiResp)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Error unmarshaling API response: %v", err)
|
|
||||||
}
|
|
||||||
if got, want := apiResp.Status, "Success"; got != want {
|
|
||||||
t.Errorf("apiResp.Status: %v; want %v", got, want)
|
|
||||||
}
|
|
||||||
if got, want := apiResp.Code, 200; got != want {
|
|
||||||
t.Errorf("apiResp.Status: %v; want %v", got, want)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TestS3APIBackendconfigQuery exercise backendconfig API endpoint
|
|
||||||
// routine with query.
|
|
||||||
func TestS3APIBackendconfigQuery(t *testing.T) {
|
|
||||||
st := newServerTesterTLSConnectPort([]string{"--npn-list=spdy/3.1", "-f127.0.0.1,3010;api"}, t, func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
t.Fatalf("request should not be forwarded")
|
|
||||||
}, 3010)
|
|
||||||
defer st.Close()
|
|
||||||
|
|
||||||
res, err := st.spdy(requestParam{
|
|
||||||
name: "TestS3APIBackendconfigQuery",
|
|
||||||
path: "/api/v1beta1/backendconfig?foo=bar",
|
|
||||||
method: "PUT",
|
|
||||||
body: []byte(`# comment
|
|
||||||
backend=127.0.0.1,3011
|
|
||||||
|
|
||||||
`),
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Error st.spdy() = %v", err)
|
|
||||||
}
|
|
||||||
if got, want := res.status, 200; got != want {
|
|
||||||
t.Errorf("res.status: %v; want %v", got, want)
|
|
||||||
}
|
|
||||||
|
|
||||||
var apiResp APIResponse
|
|
||||||
err = json.Unmarshal(res.body, &apiResp)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Error unmarshaling API response: %v", err)
|
|
||||||
}
|
|
||||||
if got, want := apiResp.Status, "Success"; got != want {
|
|
||||||
t.Errorf("apiResp.Status: %v; want %v", got, want)
|
|
||||||
}
|
|
||||||
if got, want := apiResp.Code, 200; got != want {
|
|
||||||
t.Errorf("apiResp.Status: %v; want %v", got, want)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TestS3APIBackendconfigBadMethod exercise backendconfig API endpoint
|
|
||||||
// routine with bad method.
|
|
||||||
func TestS3APIBackendconfigBadMethod(t *testing.T) {
|
|
||||||
st := newServerTesterTLSConnectPort([]string{"--npn-list=spdy/3.1", "-f127.0.0.1,3010;api"}, t, func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
t.Fatalf("request should not be forwarded")
|
|
||||||
}, 3010)
|
|
||||||
defer st.Close()
|
|
||||||
|
|
||||||
res, err := st.spdy(requestParam{
|
|
||||||
name: "TestS3APIBackendconfigBadMethod",
|
|
||||||
path: "/api/v1beta1/backendconfig",
|
|
||||||
method: "GET",
|
|
||||||
body: []byte(`# comment
|
|
||||||
backend=127.0.0.1,3011
|
|
||||||
|
|
||||||
`),
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Error st.spdy() = %v", err)
|
|
||||||
}
|
|
||||||
if got, want := res.status, 405; got != want {
|
|
||||||
t.Errorf("res.status: %v; want %v", got, want)
|
|
||||||
}
|
|
||||||
|
|
||||||
var apiResp APIResponse
|
|
||||||
err = json.Unmarshal(res.body, &apiResp)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Error unmarshaling API response: %v", err)
|
|
||||||
}
|
|
||||||
if got, want := apiResp.Status, "Failure"; got != want {
|
|
||||||
t.Errorf("apiResp.Status: %v; want %v", got, want)
|
|
||||||
}
|
|
||||||
if got, want := apiResp.Code, 405; got != want {
|
|
||||||
t.Errorf("apiResp.Status: %v; want %v", got, want)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TestS3APINotFound exercise backendconfig API endpoint routine when
|
|
||||||
// API endpoint is not found.
|
|
||||||
func TestS3APINotFound(t *testing.T) {
|
|
||||||
st := newServerTesterTLSConnectPort([]string{"--npn-list=spdy/3.1", "-f127.0.0.1,3010;api"}, t, func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
t.Fatalf("request should not be forwarded")
|
|
||||||
}, 3010)
|
|
||||||
defer st.Close()
|
|
||||||
|
|
||||||
res, err := st.spdy(requestParam{
|
|
||||||
name: "TestS3APINotFound",
|
|
||||||
path: "/api/notfound",
|
|
||||||
method: "GET",
|
|
||||||
body: []byte(`# comment
|
|
||||||
backend=127.0.0.1,3011
|
|
||||||
|
|
||||||
`),
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Error st.spdy() = %v", err)
|
|
||||||
}
|
|
||||||
if got, want := res.status, 404; got != want {
|
|
||||||
t.Errorf("res.status: %v; want %v", got, want)
|
|
||||||
}
|
|
||||||
|
|
||||||
var apiResp APIResponse
|
|
||||||
err = json.Unmarshal(res.body, &apiResp)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Error unmarshaling API response: %v", err)
|
|
||||||
}
|
|
||||||
if got, want := apiResp.Status, "Failure"; got != want {
|
|
||||||
t.Errorf("apiResp.Status: %v; want %v", got, want)
|
|
||||||
}
|
|
||||||
if got, want := apiResp.Code, 404; got != want {
|
|
||||||
t.Errorf("apiResp.Status: %v; want %v", got, want)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TestS3Healthmon tests health monitor endpoint.
|
|
||||||
func TestS3Healthmon(t *testing.T) {
|
|
||||||
st := newServerTesterTLSConnectPort([]string{"--npn-list=spdy/3.1", "-f127.0.0.1,3011;healthmon"}, t, func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
t.Fatalf("request should not be forwarded")
|
|
||||||
}, 3011)
|
|
||||||
defer st.Close()
|
|
||||||
|
|
||||||
res, err := st.spdy(requestParam{
|
|
||||||
name: "TestS3Healthmon",
|
|
||||||
path: "/alpha/bravo",
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Error st.spdy() = %v", err)
|
|
||||||
}
|
|
||||||
if got, want := res.status, 200; got != want {
|
|
||||||
t.Errorf("res.status: %v; want %v", got, want)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TestS3ResponseBeforeRequestEnd tests the situation where response
|
|
||||||
// ends before request body finishes.
|
|
||||||
func TestS3ResponseBeforeRequestEnd(t *testing.T) {
|
|
||||||
st := newServerTesterTLS([]string{"--npn-list=spdy/3.1", "--mruby-file=" + testDir + "/req-return.rb"}, t, func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
t.Fatal("request should not be forwarded")
|
|
||||||
})
|
|
||||||
defer st.Close()
|
|
||||||
|
|
||||||
res, err := st.spdy(requestParam{
|
|
||||||
name: "TestS3ResponseBeforeRequestEnd",
|
|
||||||
noEndStream: true,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Error st.spdy() = %v", err)
|
|
||||||
}
|
|
||||||
if got, want := res.status, 404; got != want {
|
|
||||||
t.Errorf("res.status: %v; want %v", got, want)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -7,7 +7,6 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/tatsuhiro-t/go-nghttp2"
|
"github.com/tatsuhiro-t/go-nghttp2"
|
||||||
"github.com/tatsuhiro-t/spdy"
|
|
||||||
"golang.org/x/net/http2"
|
"golang.org/x/net/http2"
|
||||||
"golang.org/x/net/http2/hpack"
|
"golang.org/x/net/http2/hpack"
|
||||||
"golang.org/x/net/websocket"
|
"golang.org/x/net/websocket"
|
||||||
@@ -53,14 +52,12 @@ type serverTester struct {
|
|||||||
h2PrefaceSent bool // HTTP/2 preface was sent in conn
|
h2PrefaceSent bool // HTTP/2 preface was sent in conn
|
||||||
nextStreamID uint32 // next stream ID
|
nextStreamID uint32 // next stream ID
|
||||||
fr *http2.Framer // HTTP/2 framer
|
fr *http2.Framer // HTTP/2 framer
|
||||||
spdyFr *spdy.Framer // SPDY/3.1 framer
|
|
||||||
headerBlkBuf bytes.Buffer // buffer to store encoded header block
|
headerBlkBuf bytes.Buffer // buffer to store encoded header block
|
||||||
enc *hpack.Encoder // HTTP/2 HPACK encoder
|
enc *hpack.Encoder // HTTP/2 HPACK encoder
|
||||||
header http.Header // received header fields
|
header http.Header // received header fields
|
||||||
dec *hpack.Decoder // HTTP/2 HPACK decoder
|
dec *hpack.Decoder // HTTP/2 HPACK decoder
|
||||||
authority string // server's host:port
|
authority string // server's host:port
|
||||||
frCh chan http2.Frame // used for incoming HTTP/2 frame
|
frCh chan http2.Frame // used for incoming HTTP/2 frame
|
||||||
spdyFrCh chan spdy.Frame // used for incoming SPDY frame
|
|
||||||
errCh chan error
|
errCh chan error
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -101,7 +98,7 @@ func newServerTesterInternal(src_args []string, t *testing.T, handler http.Handl
|
|||||||
|
|
||||||
args := []string{}
|
args := []string{}
|
||||||
|
|
||||||
var backendTLS, dns, externalDNS, acceptProxyProtocol, redirectIfNotTLS bool
|
var backendTLS, dns, externalDNS, acceptProxyProtocol, redirectIfNotTLS, affinityCookie, alpnH1 bool
|
||||||
|
|
||||||
for _, k := range src_args {
|
for _, k := range src_args {
|
||||||
switch k {
|
switch k {
|
||||||
@@ -116,6 +113,10 @@ func newServerTesterInternal(src_args []string, t *testing.T, handler http.Handl
|
|||||||
acceptProxyProtocol = true
|
acceptProxyProtocol = true
|
||||||
case "--redirect-if-not-tls":
|
case "--redirect-if-not-tls":
|
||||||
redirectIfNotTLS = true
|
redirectIfNotTLS = true
|
||||||
|
case "--affinity-cookie":
|
||||||
|
affinityCookie = true
|
||||||
|
case "--alpn-h1":
|
||||||
|
alpnH1 = true
|
||||||
default:
|
default:
|
||||||
args = append(args, k)
|
args = append(args, k)
|
||||||
}
|
}
|
||||||
@@ -168,6 +169,10 @@ func newServerTesterInternal(src_args []string, t *testing.T, handler http.Handl
|
|||||||
b += ";redirect-if-not-tls"
|
b += ";redirect-if-not-tls"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if affinityCookie {
|
||||||
|
b += ";affinity=cookie;affinity-cookie-name=affinity;affinity-cookie-path=/foo/bar"
|
||||||
|
}
|
||||||
|
|
||||||
noTLS := ";no-tls"
|
noTLS := ";no-tls"
|
||||||
if frontendTLS {
|
if frontendTLS {
|
||||||
noTLS = ""
|
noTLS = ""
|
||||||
@@ -193,7 +198,6 @@ func newServerTesterInternal(src_args []string, t *testing.T, handler http.Handl
|
|||||||
nextStreamID: 1,
|
nextStreamID: 1,
|
||||||
authority: authority,
|
authority: authority,
|
||||||
frCh: make(chan http2.Frame),
|
frCh: make(chan http2.Frame),
|
||||||
spdyFrCh: make(chan spdy.Frame),
|
|
||||||
errCh: make(chan error),
|
errCh: make(chan error),
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -218,7 +222,11 @@ func newServerTesterInternal(src_args []string, t *testing.T, handler http.Handl
|
|||||||
tlsConfig = clientConfig
|
tlsConfig = clientConfig
|
||||||
}
|
}
|
||||||
tlsConfig.InsecureSkipVerify = true
|
tlsConfig.InsecureSkipVerify = true
|
||||||
tlsConfig.NextProtos = []string{"h2", "spdy/3.1"}
|
if alpnH1 {
|
||||||
|
tlsConfig.NextProtos = []string{"http/1.1"}
|
||||||
|
} else {
|
||||||
|
tlsConfig.NextProtos = []string{"h2"}
|
||||||
|
}
|
||||||
conn, err = tls.Dial("tcp", authority, tlsConfig)
|
conn, err = tls.Dial("tcp", authority, tlsConfig)
|
||||||
} else {
|
} else {
|
||||||
conn, err = net.Dial("tcp", authority)
|
conn, err = net.Dial("tcp", authority)
|
||||||
@@ -244,12 +252,6 @@ func newServerTesterInternal(src_args []string, t *testing.T, handler http.Handl
|
|||||||
}
|
}
|
||||||
|
|
||||||
st.fr = http2.NewFramer(st.conn, st.conn)
|
st.fr = http2.NewFramer(st.conn, st.conn)
|
||||||
spdyFr, err := spdy.NewFramer(st.conn, st.conn)
|
|
||||||
if err != nil {
|
|
||||||
st.Close()
|
|
||||||
st.t.Fatalf("Error spdy.NewFramer: %v", err)
|
|
||||||
}
|
|
||||||
st.spdyFr = spdyFr
|
|
||||||
st.enc = hpack.NewEncoder(&st.headerBlkBuf)
|
st.enc = hpack.NewEncoder(&st.headerBlkBuf)
|
||||||
st.dec = hpack.NewDecoder(4096, func(f hpack.HeaderField) {
|
st.dec = hpack.NewDecoder(4096, func(f hpack.HeaderField) {
|
||||||
st.header.Add(f.Name, f.Value)
|
st.header.Add(f.Name, f.Value)
|
||||||
@@ -303,26 +305,6 @@ func (st *serverTester) readFrame() (http2.Frame, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (st *serverTester) readSpdyFrame() (spdy.Frame, error) {
|
|
||||||
go func() {
|
|
||||||
f, err := st.spdyFr.ReadFrame()
|
|
||||||
if err != nil {
|
|
||||||
st.errCh <- err
|
|
||||||
return
|
|
||||||
}
|
|
||||||
st.spdyFrCh <- f
|
|
||||||
}()
|
|
||||||
|
|
||||||
select {
|
|
||||||
case f := <-st.spdyFrCh:
|
|
||||||
return f, nil
|
|
||||||
case err := <-st.errCh:
|
|
||||||
return nil, err
|
|
||||||
case <-time.After(2 * time.Second):
|
|
||||||
return nil, errors.New("timeout waiting for frame")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type requestParam struct {
|
type requestParam struct {
|
||||||
name string // name for this request to identify the request in log easily
|
name string // name for this request to identify the request in log easily
|
||||||
streamID uint32 // stream ID, automatically assigned if 0
|
streamID uint32 // stream ID, automatically assigned if 0
|
||||||
@@ -463,122 +445,6 @@ func (st *serverTester) http1(rp requestParam) (*serverResponse, error) {
|
|||||||
return res, nil
|
return res, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (st *serverTester) spdy(rp requestParam) (*serverResponse, error) {
|
|
||||||
res := &serverResponse{}
|
|
||||||
|
|
||||||
var id spdy.StreamId
|
|
||||||
if rp.streamID != 0 {
|
|
||||||
id = spdy.StreamId(rp.streamID)
|
|
||||||
if id >= spdy.StreamId(st.nextStreamID) && id%2 == 1 {
|
|
||||||
st.nextStreamID = uint32(id) + 2
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
id = spdy.StreamId(st.nextStreamID)
|
|
||||||
st.nextStreamID += 2
|
|
||||||
}
|
|
||||||
|
|
||||||
method := "GET"
|
|
||||||
if rp.method != "" {
|
|
||||||
method = rp.method
|
|
||||||
}
|
|
||||||
|
|
||||||
scheme := "http"
|
|
||||||
if rp.scheme != "" {
|
|
||||||
scheme = rp.scheme
|
|
||||||
}
|
|
||||||
|
|
||||||
host := st.authority
|
|
||||||
if rp.authority != "" {
|
|
||||||
host = rp.authority
|
|
||||||
}
|
|
||||||
|
|
||||||
path := "/"
|
|
||||||
if rp.path != "" {
|
|
||||||
path = rp.path
|
|
||||||
}
|
|
||||||
|
|
||||||
header := make(http.Header)
|
|
||||||
header.Add(":method", method)
|
|
||||||
header.Add(":scheme", scheme)
|
|
||||||
header.Add(":host", host)
|
|
||||||
header.Add(":path", path)
|
|
||||||
header.Add(":version", "HTTP/1.1")
|
|
||||||
header.Add("test-case", rp.name)
|
|
||||||
for _, h := range rp.header {
|
|
||||||
header.Add(h.Name, h.Value)
|
|
||||||
}
|
|
||||||
|
|
||||||
var synStreamFlags spdy.ControlFlags
|
|
||||||
if len(rp.body) == 0 && !rp.noEndStream {
|
|
||||||
synStreamFlags = spdy.ControlFlagFin
|
|
||||||
}
|
|
||||||
if err := st.spdyFr.WriteFrame(&spdy.SynStreamFrame{
|
|
||||||
CFHeader: spdy.ControlFrameHeader{
|
|
||||||
Flags: synStreamFlags,
|
|
||||||
},
|
|
||||||
StreamId: id,
|
|
||||||
Headers: header,
|
|
||||||
}); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(rp.body) != 0 {
|
|
||||||
var dataFlags spdy.DataFlags
|
|
||||||
if !rp.noEndStream {
|
|
||||||
dataFlags = spdy.DataFlagFin
|
|
||||||
}
|
|
||||||
if err := st.spdyFr.WriteFrame(&spdy.DataFrame{
|
|
||||||
StreamId: id,
|
|
||||||
Flags: dataFlags,
|
|
||||||
Data: rp.body,
|
|
||||||
}); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
loop:
|
|
||||||
for {
|
|
||||||
fr, err := st.readSpdyFrame()
|
|
||||||
if err != nil {
|
|
||||||
return res, err
|
|
||||||
}
|
|
||||||
switch f := fr.(type) {
|
|
||||||
case *spdy.SynReplyFrame:
|
|
||||||
if f.StreamId != id {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
res.header = cloneHeader(f.Headers)
|
|
||||||
if _, err := fmt.Sscan(res.header.Get(":status"), &res.status); err != nil {
|
|
||||||
return res, fmt.Errorf("Error parsing status code: %v", err)
|
|
||||||
}
|
|
||||||
if f.CFHeader.Flags&spdy.ControlFlagFin != 0 {
|
|
||||||
break loop
|
|
||||||
}
|
|
||||||
case *spdy.DataFrame:
|
|
||||||
if f.StreamId != id {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
res.body = append(res.body, f.Data...)
|
|
||||||
if f.Flags&spdy.DataFlagFin != 0 {
|
|
||||||
break loop
|
|
||||||
}
|
|
||||||
case *spdy.RstStreamFrame:
|
|
||||||
if f.StreamId != id {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
res.spdyRstErrCode = f.Status
|
|
||||||
break loop
|
|
||||||
case *spdy.GoAwayFrame:
|
|
||||||
if f.Status == spdy.GoAwayOK {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
res.spdyGoAwayErrCode = f.Status
|
|
||||||
break loop
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return res, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (st *serverTester) http2(rp requestParam) (*serverResponse, error) {
|
func (st *serverTester) http2(rp requestParam) (*serverResponse, error) {
|
||||||
st.headerBlkBuf.Reset()
|
st.headerBlkBuf.Reset()
|
||||||
st.header = make(http.Header)
|
st.header = make(http.Header)
|
||||||
@@ -767,9 +633,7 @@ type serverResponse struct {
|
|||||||
streamID uint32 // stream ID in HTTP/2
|
streamID uint32 // stream ID in HTTP/2
|
||||||
errCode http2.ErrCode // error code received in HTTP/2 RST_STREAM or GOAWAY
|
errCode http2.ErrCode // error code received in HTTP/2 RST_STREAM or GOAWAY
|
||||||
connErr bool // true if HTTP/2 connection error
|
connErr bool // true if HTTP/2 connection error
|
||||||
spdyGoAwayErrCode spdy.GoAwayStatus // status code received in SPDY RST_STREAM
|
connClose bool // Connection: close is included in response header in HTTP/1 test
|
||||||
spdyRstErrCode spdy.RstStreamStatus // status code received in SPDY GOAWAY
|
|
||||||
connClose bool // Conection: close is included in response header in HTTP/1 test
|
|
||||||
reqHeader http.Header // http request header, currently only sotres pushed request header
|
reqHeader http.Header // http request header, currently only sotres pushed request header
|
||||||
pushResponse []*serverResponse // pushed response
|
pushResponse []*serverResponse // pushed response
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,14 +38,25 @@ if(WIN32)
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Public shared library
|
# Public shared library
|
||||||
add_library(nghttp2 SHARED ${NGHTTP2_SOURCES} ${NGHTTP2_RES})
|
if(ENABLE_SHARED_LIB)
|
||||||
set_target_properties(nghttp2 PROPERTIES
|
add_library(nghttp2 SHARED ${NGHTTP2_SOURCES} ${NGHTTP2_RES})
|
||||||
COMPILE_FLAGS "${WARNCFLAGS}"
|
set_target_properties(nghttp2 PROPERTIES
|
||||||
VERSION ${LT_VERSION} SOVERSION ${LT_SOVERSION}
|
COMPILE_FLAGS "${WARNCFLAGS}"
|
||||||
C_VISIBILITY_PRESET hidden
|
VERSION ${LT_VERSION} SOVERSION ${LT_SOVERSION}
|
||||||
)
|
C_VISIBILITY_PRESET hidden
|
||||||
|
)
|
||||||
|
target_include_directories(nghttp2 INTERFACE
|
||||||
|
"${CMAKE_CURRENT_BINARY_DIR}/includes"
|
||||||
|
"${CMAKE_CURRENT_SOURCE_DIR}/includes"
|
||||||
|
)
|
||||||
|
|
||||||
if(HAVE_CUNIT)
|
install(TARGETS nghttp2
|
||||||
|
ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}"
|
||||||
|
LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}"
|
||||||
|
RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(HAVE_CUNIT OR ENABLE_STATIC_LIB)
|
||||||
# Static library (for unittests because of symbol visibility)
|
# Static library (for unittests because of symbol visibility)
|
||||||
add_library(nghttp2_static STATIC ${NGHTTP2_SOURCES})
|
add_library(nghttp2_static STATIC ${NGHTTP2_SOURCES})
|
||||||
set_target_properties(nghttp2_static PROPERTIES
|
set_target_properties(nghttp2_static PROPERTIES
|
||||||
@@ -54,10 +65,12 @@ if(HAVE_CUNIT)
|
|||||||
ARCHIVE_OUTPUT_NAME nghttp2
|
ARCHIVE_OUTPUT_NAME nghttp2
|
||||||
)
|
)
|
||||||
target_compile_definitions(nghttp2_static PUBLIC "-DNGHTTP2_STATICLIB")
|
target_compile_definitions(nghttp2_static PUBLIC "-DNGHTTP2_STATICLIB")
|
||||||
|
if(ENABLE_STATIC_LIB)
|
||||||
|
install(TARGETS nghttp2_static
|
||||||
|
DESTINATION "${CMAKE_INSTALL_LIBDIR}")
|
||||||
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
install(TARGETS nghttp2
|
|
||||||
DESTINATION "${CMAKE_INSTALL_LIBDIR}")
|
|
||||||
|
|
||||||
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")
|
||||||
|
|||||||
@@ -28,7 +28,12 @@
|
|||||||
/* Define WIN32 when build target is Win32 API (borrowed from
|
/* Define WIN32 when build target is Win32 API (borrowed from
|
||||||
libcurl) */
|
libcurl) */
|
||||||
#if (defined(_WIN32) || defined(__WIN32__)) && !defined(WIN32)
|
#if (defined(_WIN32) || defined(__WIN32__)) && !defined(WIN32)
|
||||||
#define WIN32
|
# define WIN32
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Compatibility for non-Clang compilers */
|
||||||
|
#ifndef __has_declspec_attribute
|
||||||
|
# define __has_declspec_attribute(x) 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
@@ -40,9 +45,9 @@ extern "C" {
|
|||||||
/* 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 <stdarg.h>
|
#include <stdarg.h>
|
||||||
@@ -50,20 +55,21 @@ extern "C" {
|
|||||||
#include <nghttp2/nghttp2ver.h>
|
#include <nghttp2/nghttp2ver.h>
|
||||||
|
|
||||||
#ifdef NGHTTP2_STATICLIB
|
#ifdef NGHTTP2_STATICLIB
|
||||||
#define NGHTTP2_EXTERN
|
# define NGHTTP2_EXTERN
|
||||||
#elif defined(WIN32)
|
#elif defined(WIN32) || (__has_declspec_attribute(dllexport) && \
|
||||||
#ifdef BUILDING_NGHTTP2
|
__has_declspec_attribute(dllimport))
|
||||||
#define NGHTTP2_EXTERN __declspec(dllexport)
|
# ifdef BUILDING_NGHTTP2
|
||||||
#else /* !BUILDING_NGHTTP2 */
|
# define NGHTTP2_EXTERN __declspec(dllexport)
|
||||||
#define NGHTTP2_EXTERN __declspec(dllimport)
|
# else /* !BUILDING_NGHTTP2 */
|
||||||
#endif /* !BUILDING_NGHTTP2 */
|
# define NGHTTP2_EXTERN __declspec(dllimport)
|
||||||
#else /* !defined(WIN32) */
|
# endif /* !BUILDING_NGHTTP2 */
|
||||||
#ifdef BUILDING_NGHTTP2
|
#else /* !defined(WIN32) */
|
||||||
#define NGHTTP2_EXTERN __attribute__((visibility("default")))
|
# ifdef BUILDING_NGHTTP2
|
||||||
#else /* !BUILDING_NGHTTP2 */
|
# define NGHTTP2_EXTERN __attribute__((visibility("default")))
|
||||||
#define NGHTTP2_EXTERN
|
# else /* !BUILDING_NGHTTP2 */
|
||||||
#endif /* !BUILDING_NGHTTP2 */
|
# define NGHTTP2_EXTERN
|
||||||
#endif /* !defined(WIN32) */
|
# endif /* !BUILDING_NGHTTP2 */
|
||||||
|
#endif /* !defined(WIN32) */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @macro
|
* @macro
|
||||||
@@ -387,6 +393,11 @@ typedef enum {
|
|||||||
* Indicates that a processing was canceled.
|
* Indicates that a processing was canceled.
|
||||||
*/
|
*/
|
||||||
NGHTTP2_ERR_CANCEL = -535,
|
NGHTTP2_ERR_CANCEL = -535,
|
||||||
|
/**
|
||||||
|
* When a local endpoint expects to receive SETTINGS frame, it
|
||||||
|
* receives an other type of frame.
|
||||||
|
*/
|
||||||
|
NGHTTP2_ERR_SETTINGS_EXPECTED = -536,
|
||||||
/**
|
/**
|
||||||
* The errors < :enum:`NGHTTP2_ERR_FATAL` mean that the library is
|
* The errors < :enum:`NGHTTP2_ERR_FATAL` mean that the library is
|
||||||
* under unexpected condition and processing was terminated (e.g.,
|
* under unexpected condition and processing was terminated (e.g.,
|
||||||
@@ -469,6 +480,15 @@ NGHTTP2_EXTERN void nghttp2_rcbuf_decref(nghttp2_rcbuf *rcbuf);
|
|||||||
*/
|
*/
|
||||||
NGHTTP2_EXTERN nghttp2_vec nghttp2_rcbuf_get_buf(nghttp2_rcbuf *rcbuf);
|
NGHTTP2_EXTERN nghttp2_vec nghttp2_rcbuf_get_buf(nghttp2_rcbuf *rcbuf);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @function
|
||||||
|
*
|
||||||
|
* Returns nonzero if the underlying buffer is statically allocated,
|
||||||
|
* and 0 otherwise. This can be useful for language bindings that wish
|
||||||
|
* to avoid creating duplicate strings for these buffers.
|
||||||
|
*/
|
||||||
|
NGHTTP2_EXTERN int nghttp2_rcbuf_is_static(const nghttp2_rcbuf *rcbuf);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @enum
|
* @enum
|
||||||
*
|
*
|
||||||
@@ -597,7 +617,12 @@ typedef enum {
|
|||||||
* The ALTSVC frame, which is defined in `RFC 7383
|
* The ALTSVC frame, which is defined in `RFC 7383
|
||||||
* <https://tools.ietf.org/html/rfc7838#section-4>`_.
|
* <https://tools.ietf.org/html/rfc7838#section-4>`_.
|
||||||
*/
|
*/
|
||||||
NGHTTP2_ALTSVC = 0x0a
|
NGHTTP2_ALTSVC = 0x0a,
|
||||||
|
/**
|
||||||
|
* The ORIGIN frame, which is defined by `RFC 8336
|
||||||
|
* <https://tools.ietf.org/html/rfc8336>`_.
|
||||||
|
*/
|
||||||
|
NGHTTP2_ORIGIN = 0x0c
|
||||||
} nghttp2_frame_type;
|
} nghttp2_frame_type;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -661,7 +686,12 @@ typedef enum {
|
|||||||
/**
|
/**
|
||||||
* SETTINGS_MAX_HEADER_LIST_SIZE
|
* SETTINGS_MAX_HEADER_LIST_SIZE
|
||||||
*/
|
*/
|
||||||
NGHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE = 0x06
|
NGHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE = 0x06,
|
||||||
|
/**
|
||||||
|
* SETTINGS_ENABLE_CONNECT_PROTOCOL
|
||||||
|
* (`RFC 8441 <https://tools.ietf.org/html/rfc8441>`_)
|
||||||
|
*/
|
||||||
|
NGHTTP2_SETTINGS_ENABLE_CONNECT_PROTOCOL = 0x08
|
||||||
} nghttp2_settings_id;
|
} nghttp2_settings_id;
|
||||||
/* Note: If we add SETTINGS, update the capacity of
|
/* Note: If we add SETTINGS, update the capacity of
|
||||||
NGHTTP2_INBOUND_NUM_IV as well */
|
NGHTTP2_INBOUND_NUM_IV as well */
|
||||||
@@ -1978,6 +2008,9 @@ typedef ssize_t (*nghttp2_pack_extension_callback)(nghttp2_session *session,
|
|||||||
* of length |len|. |len| does not include the sentinel NULL
|
* of length |len|. |len| does not include the sentinel NULL
|
||||||
* character.
|
* character.
|
||||||
*
|
*
|
||||||
|
* This function is deprecated. The new application should use
|
||||||
|
* :type:`nghttp2_error_callback2`.
|
||||||
|
*
|
||||||
* The format of error message may change between nghttp2 library
|
* The format of error message may change between nghttp2 library
|
||||||
* versions. The application should not depend on the particular
|
* versions. The application should not depend on the particular
|
||||||
* format.
|
* format.
|
||||||
@@ -1994,6 +2027,33 @@ typedef ssize_t (*nghttp2_pack_extension_callback)(nghttp2_session *session,
|
|||||||
typedef int (*nghttp2_error_callback)(nghttp2_session *session, const char *msg,
|
typedef int (*nghttp2_error_callback)(nghttp2_session *session, const char *msg,
|
||||||
size_t len, void *user_data);
|
size_t len, void *user_data);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @functypedef
|
||||||
|
*
|
||||||
|
* Callback function invoked when library provides the error code, and
|
||||||
|
* message. This callback is solely for debugging purpose.
|
||||||
|
* |lib_error_code| is one of error code defined in
|
||||||
|
* :enum:`nghttp2_error`. The |msg| is typically NULL-terminated
|
||||||
|
* string of length |len|, and intended for human consumption. |len|
|
||||||
|
* does not include the sentinel NULL character.
|
||||||
|
*
|
||||||
|
* The format of error message may change between nghttp2 library
|
||||||
|
* versions. The application should not depend on the particular
|
||||||
|
* format.
|
||||||
|
*
|
||||||
|
* Normally, application should return 0 from this callback. If fatal
|
||||||
|
* error occurred while doing something in this callback, application
|
||||||
|
* should return :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`. In this case,
|
||||||
|
* library will return immediately with return value
|
||||||
|
* :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`. Currently, if nonzero value
|
||||||
|
* is returned from this callback, they are treated as
|
||||||
|
* :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`, but application should not
|
||||||
|
* rely on this details.
|
||||||
|
*/
|
||||||
|
typedef int (*nghttp2_error_callback2)(nghttp2_session *session,
|
||||||
|
int lib_error_code, const char *msg,
|
||||||
|
size_t len, void *user_data);
|
||||||
|
|
||||||
struct nghttp2_session_callbacks;
|
struct nghttp2_session_callbacks;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -2258,10 +2318,30 @@ nghttp2_session_callbacks_set_on_extension_chunk_recv_callback(
|
|||||||
*
|
*
|
||||||
* Sets callback function invoked when library tells error message to
|
* Sets callback function invoked when library tells error message to
|
||||||
* the application.
|
* the application.
|
||||||
|
*
|
||||||
|
* This function is deprecated. The new application should use
|
||||||
|
* `nghttp2_session_callbacks_set_error_callback2()`.
|
||||||
|
*
|
||||||
|
* If both :type:`nghttp2_error_callback` and
|
||||||
|
* :type:`nghttp2_error_callback2` are set, the latter takes
|
||||||
|
* precedence.
|
||||||
*/
|
*/
|
||||||
NGHTTP2_EXTERN void nghttp2_session_callbacks_set_error_callback(
|
NGHTTP2_EXTERN 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);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @function
|
||||||
|
*
|
||||||
|
* Sets callback function invoked when library tells error code, and
|
||||||
|
* message to the application.
|
||||||
|
*
|
||||||
|
* If both :type:`nghttp2_error_callback` and
|
||||||
|
* :type:`nghttp2_error_callback2` are set, the latter takes
|
||||||
|
* precedence.
|
||||||
|
*/
|
||||||
|
NGHTTP2_EXTERN void nghttp2_session_callbacks_set_error_callback2(
|
||||||
|
nghttp2_session_callbacks *cbs, nghttp2_error_callback2 error_callback2);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @functypedef
|
* @functypedef
|
||||||
*
|
*
|
||||||
@@ -2409,15 +2489,15 @@ nghttp2_option_set_no_auto_window_update(nghttp2_option *option, int val);
|
|||||||
*
|
*
|
||||||
* This option sets the SETTINGS_MAX_CONCURRENT_STREAMS value of
|
* This option sets the SETTINGS_MAX_CONCURRENT_STREAMS value of
|
||||||
* remote endpoint as if it is received in SETTINGS frame. Without
|
* remote endpoint as if it is received in SETTINGS frame. Without
|
||||||
* specifying this option, before the local endpoint receives
|
* specifying this option, the maximum number of outgoing concurrent
|
||||||
* SETTINGS_MAX_CONCURRENT_STREAMS in SETTINGS frame from remote
|
* streams is initially limited to 100 to avoid issues when the local
|
||||||
* endpoint, SETTINGS_MAX_CONCURRENT_STREAMS is unlimited. This may
|
* endpoint submits lots of requests before receiving initial SETTINGS
|
||||||
* cause problem if local endpoint submits lots of requests initially
|
* frame from the remote endpoint, since sending them at once to the
|
||||||
* and sending them at once to the remote peer may lead to the
|
* remote endpoint could lead to rejection of some of the requests.
|
||||||
* rejection of some requests. Specifying this option to the sensible
|
* This value will be overwritten when the local endpoint receives
|
||||||
* value, say 100, may avoid this kind of issue. This value will be
|
* initial SETTINGS frame from the remote endpoint, either to the
|
||||||
* overwritten if the local endpoint receives
|
* value advertised in SETTINGS_MAX_CONCURRENT_STREAMS or to the
|
||||||
* SETTINGS_MAX_CONCURRENT_STREAMS from the remote endpoint.
|
* default value (unlimited) if none was advertised.
|
||||||
*/
|
*/
|
||||||
NGHTTP2_EXTERN void
|
NGHTTP2_EXTERN void
|
||||||
nghttp2_option_set_peer_max_concurrent_streams(nghttp2_option *option,
|
nghttp2_option_set_peer_max_concurrent_streams(nghttp2_option *option,
|
||||||
@@ -3017,6 +3097,16 @@ NGHTTP2_EXTERN int
|
|||||||
nghttp2_session_set_stream_user_data(nghttp2_session *session,
|
nghttp2_session_set_stream_user_data(nghttp2_session *session,
|
||||||
int32_t stream_id, void *stream_user_data);
|
int32_t stream_id, void *stream_user_data);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @function
|
||||||
|
*
|
||||||
|
* Sets |user_data| to |session|, overwriting the existing user data
|
||||||
|
* specified in `nghttp2_session_client_new()`, or
|
||||||
|
* `nghttp2_session_server_new()`.
|
||||||
|
*/
|
||||||
|
NGHTTP2_EXTERN void nghttp2_session_set_user_data(nghttp2_session *session,
|
||||||
|
void *user_data);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @function
|
* @function
|
||||||
*
|
*
|
||||||
@@ -3723,10 +3813,13 @@ nghttp2_priority_spec_check_default(const nghttp2_priority_spec *pri_spec);
|
|||||||
* .. warning::
|
* .. warning::
|
||||||
*
|
*
|
||||||
* This function returns assigned stream ID if it succeeds. But
|
* This function returns assigned stream ID if it succeeds. But
|
||||||
* that stream is not opened yet. The application must not submit
|
* that stream is not created yet. The application must not submit
|
||||||
* frame to that stream ID before
|
* frame to that stream ID before
|
||||||
* :type:`nghttp2_before_frame_send_callback` is called for this
|
* :type:`nghttp2_before_frame_send_callback` is called for this
|
||||||
* frame.
|
* frame. This means `nghttp2_session_get_stream_user_data()` does
|
||||||
|
* not work before the callback. But
|
||||||
|
* `nghttp2_session_set_stream_user_data()` handles this situation
|
||||||
|
* specially, and it can set data to a stream during this period.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
NGHTTP2_EXTERN int32_t nghttp2_submit_request(
|
NGHTTP2_EXTERN int32_t nghttp2_submit_request(
|
||||||
@@ -4442,8 +4535,7 @@ typedef struct {
|
|||||||
* Submits ALTSVC frame.
|
* Submits ALTSVC frame.
|
||||||
*
|
*
|
||||||
* ALTSVC frame is a non-critical extension to HTTP/2, and defined in
|
* ALTSVC frame is a non-critical extension to HTTP/2, and defined in
|
||||||
* is defined in `RFC 7383
|
* `RFC 7383 <https://tools.ietf.org/html/rfc7838#section-4>`_.
|
||||||
* <https://tools.ietf.org/html/rfc7838#section-4>`_.
|
|
||||||
*
|
*
|
||||||
* The |flags| is currently ignored and should be
|
* The |flags| is currently ignored and should be
|
||||||
* :enum:`NGHTTP2_FLAG_NONE`.
|
* :enum:`NGHTTP2_FLAG_NONE`.
|
||||||
@@ -4477,6 +4569,81 @@ NGHTTP2_EXTERN int nghttp2_submit_altsvc(nghttp2_session *session,
|
|||||||
const uint8_t *field_value,
|
const uint8_t *field_value,
|
||||||
size_t field_value_len);
|
size_t field_value_len);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @struct
|
||||||
|
*
|
||||||
|
* The single entry of an origin.
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
/**
|
||||||
|
* The pointer to origin. No validation is made against this field
|
||||||
|
* by the library. This is not necessarily NULL-terminated.
|
||||||
|
*/
|
||||||
|
uint8_t *origin;
|
||||||
|
/**
|
||||||
|
* The length of the |origin|.
|
||||||
|
*/
|
||||||
|
size_t origin_len;
|
||||||
|
} nghttp2_origin_entry;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @struct
|
||||||
|
*
|
||||||
|
* The payload of ORIGIN frame. ORIGIN frame is a non-critical
|
||||||
|
* extension to HTTP/2 and defined by `RFC 8336
|
||||||
|
* <https://tools.ietf.org/html/rfc8336>`_.
|
||||||
|
*
|
||||||
|
* If this frame is received, and
|
||||||
|
* `nghttp2_option_set_user_recv_extension_type()` is not set, and
|
||||||
|
* `nghttp2_option_set_builtin_recv_extension_type()` is set for
|
||||||
|
* :enum:`NGHTTP2_ORIGIN`, ``nghttp2_extension.payload`` will point to
|
||||||
|
* this struct.
|
||||||
|
*
|
||||||
|
* It has the following members:
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
/**
|
||||||
|
* The number of origins contained in |ov|.
|
||||||
|
*/
|
||||||
|
size_t nov;
|
||||||
|
/**
|
||||||
|
* The pointer to the array of origins contained in ORIGIN frame.
|
||||||
|
*/
|
||||||
|
nghttp2_origin_entry *ov;
|
||||||
|
} nghttp2_ext_origin;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @function
|
||||||
|
*
|
||||||
|
* Submits ORIGIN frame.
|
||||||
|
*
|
||||||
|
* ORIGIN frame is a non-critical extension to HTTP/2 and defined by
|
||||||
|
* `RFC 8336 <https://tools.ietf.org/html/rfc8336>`_.
|
||||||
|
*
|
||||||
|
* The |flags| is currently ignored and should be
|
||||||
|
* :enum:`NGHTTP2_FLAG_NONE`.
|
||||||
|
*
|
||||||
|
* The |ov| points to the array of origins. The |nov| specifies the
|
||||||
|
* number of origins included in |ov|. This function creates copies
|
||||||
|
* of all elements in |ov|.
|
||||||
|
*
|
||||||
|
* The ORIGIN frame is only usable by a server. If this function is
|
||||||
|
* invoked with client side session, this function returns
|
||||||
|
* :enum:`NGHTTP2_ERR_INVALID_STATE`.
|
||||||
|
*
|
||||||
|
* :enum:`NGHTTP2_ERR_NOMEM`
|
||||||
|
* Out of memory
|
||||||
|
* :enum:`NGHTTP2_ERR_INVALID_STATE`
|
||||||
|
* The function is called from client side session.
|
||||||
|
* :enum:`NGHTTP2_ERR_INVALID_ARGUMENT`
|
||||||
|
* There are too many origins, or an origin is too large to fit
|
||||||
|
* into a default frame payload.
|
||||||
|
*/
|
||||||
|
NGHTTP2_EXTERN int nghttp2_submit_origin(nghttp2_session *session,
|
||||||
|
uint8_t flags,
|
||||||
|
const nghttp2_origin_entry *ov,
|
||||||
|
size_t nov);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @function
|
* @function
|
||||||
*
|
*
|
||||||
@@ -4693,8 +4860,8 @@ nghttp2_hd_deflate_change_table_size(nghttp2_hd_deflater *deflater,
|
|||||||
*
|
*
|
||||||
* After this function returns, it is safe to delete the |nva|.
|
* After this function returns, it is safe to delete the |nva|.
|
||||||
*
|
*
|
||||||
* This function returns 0 if it succeeds, or one of the following
|
* This function returns the number of bytes written to |buf| if it
|
||||||
* negative error codes:
|
* succeeds, or one of the following negative error codes:
|
||||||
*
|
*
|
||||||
* :enum:`NGHTTP2_ERR_NOMEM`
|
* :enum:`NGHTTP2_ERR_NOMEM`
|
||||||
* Out of memory.
|
* Out of memory.
|
||||||
@@ -4725,8 +4892,8 @@ NGHTTP2_EXTERN ssize_t nghttp2_hd_deflate_hd(nghttp2_hd_deflater *deflater,
|
|||||||
*
|
*
|
||||||
* After this function returns, it is safe to delete the |nva|.
|
* After this function returns, it is safe to delete the |nva|.
|
||||||
*
|
*
|
||||||
* This function returns 0 if it succeeds, or one of the following
|
* This function returns the number of bytes written to |vec| if it
|
||||||
* negative error codes:
|
* succeeds, or one of the following negative error codes:
|
||||||
*
|
*
|
||||||
* :enum:`NGHTTP2_ERR_NOMEM`
|
* :enum:`NGHTTP2_ERR_NOMEM`
|
||||||
* Out of memory.
|
* Out of memory.
|
||||||
|
|||||||
@@ -26,7 +26,7 @@
|
|||||||
#define NGHTTP2_BUF_H
|
#define NGHTTP2_BUF_H
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
#include <config.h>
|
# include <config.h>
|
||||||
#endif /* HAVE_CONFIG_H */
|
#endif /* HAVE_CONFIG_H */
|
||||||
|
|
||||||
#include <nghttp2/nghttp2.h>
|
#include <nghttp2/nghttp2.h>
|
||||||
@@ -398,7 +398,7 @@ int nghttp2_bufs_advance(nghttp2_bufs *bufs);
|
|||||||
void nghttp2_bufs_seek_last_present(nghttp2_bufs *bufs);
|
void nghttp2_bufs_seek_last_present(nghttp2_bufs *bufs);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Returns nonzero if bufs->cur->next is not emtpy.
|
* Returns nonzero if bufs->cur->next is not empty.
|
||||||
*/
|
*/
|
||||||
int nghttp2_bufs_next_present(nghttp2_bufs *bufs);
|
int nghttp2_bufs_next_present(nghttp2_bufs *bufs);
|
||||||
|
|
||||||
|
|||||||
@@ -168,3 +168,8 @@ 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(
|
||||||
|
nghttp2_session_callbacks *cbs, nghttp2_error_callback2 error_callback2) {
|
||||||
|
cbs->error_callback2 = error_callback2;
|
||||||
|
}
|
||||||
|
|||||||
@@ -26,7 +26,7 @@
|
|||||||
#define NGHTTP2_CALLBACKS_H
|
#define NGHTTP2_CALLBACKS_H
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
#include <config.h>
|
# include <config.h>
|
||||||
#endif /* HAVE_CONFIG_H */
|
#endif /* HAVE_CONFIG_H */
|
||||||
|
|
||||||
#include <nghttp2/nghttp2.h>
|
#include <nghttp2/nghttp2.h>
|
||||||
@@ -119,6 +119,7 @@ struct nghttp2_session_callbacks {
|
|||||||
nghttp2_unpack_extension_callback unpack_extension_callback;
|
nghttp2_unpack_extension_callback unpack_extension_callback;
|
||||||
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;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* NGHTTP2_CALLBACKS_H */
|
#endif /* NGHTTP2_CALLBACKS_H */
|
||||||
|
|||||||
@@ -26,18 +26,18 @@
|
|||||||
#define NGHTTP2_DEBUG_H
|
#define NGHTTP2_DEBUG_H
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
#include <config.h>
|
# include <config.h>
|
||||||
#endif /* HAVE_CONFIG_H */
|
#endif /* HAVE_CONFIG_H */
|
||||||
|
|
||||||
#include <nghttp2/nghttp2.h>
|
#include <nghttp2/nghttp2.h>
|
||||||
|
|
||||||
#ifdef DEBUGBUILD
|
#ifdef DEBUGBUILD
|
||||||
#define DEBUGF(...) nghttp2_debug_vprintf(__VA_ARGS__)
|
# define DEBUGF(...) nghttp2_debug_vprintf(__VA_ARGS__)
|
||||||
void nghttp2_debug_vprintf(const char *format, ...);
|
void nghttp2_debug_vprintf(const char *format, ...);
|
||||||
#else
|
#else
|
||||||
#define DEBUGF(...) \
|
# define DEBUGF(...) \
|
||||||
do { \
|
do { \
|
||||||
} while (0)
|
} while (0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /* NGHTTP2_DEBUG_H */
|
#endif /* NGHTTP2_DEBUG_H */
|
||||||
|
|||||||
@@ -215,11 +215,44 @@ void nghttp2_frame_altsvc_free(nghttp2_extension *frame, nghttp2_mem *mem) {
|
|||||||
nghttp2_ext_altsvc *altsvc;
|
nghttp2_ext_altsvc *altsvc;
|
||||||
|
|
||||||
altsvc = frame->payload;
|
altsvc = frame->payload;
|
||||||
|
if (altsvc == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
/* We use the same buffer for altsvc->origin and
|
/* We use the same buffer for altsvc->origin and
|
||||||
altsvc->field_value. */
|
altsvc->field_value. */
|
||||||
nghttp2_mem_free(mem, altsvc->origin);
|
nghttp2_mem_free(mem, altsvc->origin);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void nghttp2_frame_origin_init(nghttp2_extension *frame,
|
||||||
|
nghttp2_origin_entry *ov, size_t nov) {
|
||||||
|
nghttp2_ext_origin *origin;
|
||||||
|
size_t payloadlen = 0;
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
for (i = 0; i < nov; ++i) {
|
||||||
|
payloadlen += 2 + ov[i].origin_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
nghttp2_frame_hd_init(&frame->hd, payloadlen, NGHTTP2_ORIGIN,
|
||||||
|
NGHTTP2_FLAG_NONE, 0);
|
||||||
|
|
||||||
|
origin = frame->payload;
|
||||||
|
origin->ov = ov;
|
||||||
|
origin->nov = nov;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nghttp2_frame_origin_free(nghttp2_extension *frame, nghttp2_mem *mem) {
|
||||||
|
nghttp2_ext_origin *origin;
|
||||||
|
|
||||||
|
origin = frame->payload;
|
||||||
|
if (origin == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
/* We use the same buffer for all resources pointed by the field of
|
||||||
|
origin directly or indirectly. */
|
||||||
|
nghttp2_mem_free(mem, origin->ov);
|
||||||
|
}
|
||||||
|
|
||||||
size_t nghttp2_frame_priority_len(uint8_t flags) {
|
size_t nghttp2_frame_priority_len(uint8_t flags) {
|
||||||
if (flags & NGHTTP2_FLAG_PRIORITY) {
|
if (flags & NGHTTP2_FLAG_PRIORITY) {
|
||||||
return NGHTTP2_PRIORITY_SPECLEN;
|
return NGHTTP2_PRIORITY_SPECLEN;
|
||||||
@@ -743,6 +776,106 @@ int nghttp2_frame_unpack_altsvc_payload2(nghttp2_extension *frame,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int nghttp2_frame_pack_origin(nghttp2_bufs *bufs, nghttp2_extension *frame) {
|
||||||
|
nghttp2_buf *buf;
|
||||||
|
nghttp2_ext_origin *origin;
|
||||||
|
nghttp2_origin_entry *orig;
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
origin = frame->payload;
|
||||||
|
|
||||||
|
buf = &bufs->head->buf;
|
||||||
|
|
||||||
|
if (nghttp2_buf_avail(buf) < frame->hd.length) {
|
||||||
|
return NGHTTP2_ERR_FRAME_SIZE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
buf->pos -= NGHTTP2_FRAME_HDLEN;
|
||||||
|
|
||||||
|
nghttp2_frame_pack_frame_hd(buf->pos, &frame->hd);
|
||||||
|
|
||||||
|
for (i = 0; i < origin->nov; ++i) {
|
||||||
|
orig = &origin->ov[i];
|
||||||
|
nghttp2_put_uint16be(buf->last, (uint16_t)orig->origin_len);
|
||||||
|
buf->last += 2;
|
||||||
|
buf->last = nghttp2_cpymem(buf->last, orig->origin, orig->origin_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(nghttp2_buf_len(buf) == NGHTTP2_FRAME_HDLEN + frame->hd.length);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int nghttp2_frame_unpack_origin_payload(nghttp2_extension *frame,
|
||||||
|
const uint8_t *payload,
|
||||||
|
size_t payloadlen, nghttp2_mem *mem) {
|
||||||
|
nghttp2_ext_origin *origin;
|
||||||
|
const uint8_t *p, *end;
|
||||||
|
uint8_t *dst;
|
||||||
|
size_t originlen;
|
||||||
|
nghttp2_origin_entry *ov;
|
||||||
|
size_t nov = 0;
|
||||||
|
size_t len = 0;
|
||||||
|
|
||||||
|
origin = frame->payload;
|
||||||
|
p = payload;
|
||||||
|
end = p + payloadlen;
|
||||||
|
|
||||||
|
for (; p != end;) {
|
||||||
|
if (end - p < 2) {
|
||||||
|
return NGHTTP2_ERR_FRAME_SIZE_ERROR;
|
||||||
|
}
|
||||||
|
originlen = nghttp2_get_uint16(p);
|
||||||
|
p += 2;
|
||||||
|
if (originlen == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (originlen > (size_t)(end - p)) {
|
||||||
|
return NGHTTP2_ERR_FRAME_SIZE_ERROR;
|
||||||
|
}
|
||||||
|
p += originlen;
|
||||||
|
/* 1 for terminal NULL */
|
||||||
|
len += originlen + 1;
|
||||||
|
++nov;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nov == 0) {
|
||||||
|
origin->ov = NULL;
|
||||||
|
origin->nov = 0;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
len += nov * sizeof(nghttp2_origin_entry);
|
||||||
|
|
||||||
|
ov = nghttp2_mem_malloc(mem, len);
|
||||||
|
if (ov == NULL) {
|
||||||
|
return NGHTTP2_ERR_NOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
origin->ov = ov;
|
||||||
|
origin->nov = nov;
|
||||||
|
|
||||||
|
dst = (uint8_t *)ov + nov * sizeof(nghttp2_origin_entry);
|
||||||
|
p = payload;
|
||||||
|
|
||||||
|
for (; p != end;) {
|
||||||
|
originlen = nghttp2_get_uint16(p);
|
||||||
|
p += 2;
|
||||||
|
if (originlen == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
ov->origin = dst;
|
||||||
|
ov->origin_len = originlen;
|
||||||
|
dst = nghttp2_cpymem(dst, p, originlen);
|
||||||
|
*dst++ = '\0';
|
||||||
|
p += originlen;
|
||||||
|
++ov;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
nghttp2_settings_entry *nghttp2_frame_iv_copy(const nghttp2_settings_entry *iv,
|
nghttp2_settings_entry *nghttp2_frame_iv_copy(const nghttp2_settings_entry *iv,
|
||||||
size_t niv, nghttp2_mem *mem) {
|
size_t niv, nghttp2_mem *mem) {
|
||||||
nghttp2_settings_entry *iv_copy;
|
nghttp2_settings_entry *iv_copy;
|
||||||
@@ -917,6 +1050,11 @@ int nghttp2_iv_check(const nghttp2_settings_entry *iv, size_t niv) {
|
|||||||
break;
|
break;
|
||||||
case NGHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE:
|
case NGHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE:
|
||||||
break;
|
break;
|
||||||
|
case NGHTTP2_SETTINGS_ENABLE_CONNECT_PROTOCOL:
|
||||||
|
if (iv[i].value != 0 && iv[i].value != 1) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
|
|||||||
@@ -26,7 +26,7 @@
|
|||||||
#define NGHTTP2_FRAME_H
|
#define NGHTTP2_FRAME_H
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
#include <config.h>
|
# include <config.h>
|
||||||
#endif /* HAVE_CONFIG_H */
|
#endif /* HAVE_CONFIG_H */
|
||||||
|
|
||||||
#include <nghttp2/nghttp2.h>
|
#include <nghttp2/nghttp2.h>
|
||||||
@@ -70,7 +70,10 @@
|
|||||||
#define NGHTTP2_MAX_PADLEN 256
|
#define NGHTTP2_MAX_PADLEN 256
|
||||||
|
|
||||||
/* Union of extension frame payload */
|
/* Union of extension frame payload */
|
||||||
typedef union { nghttp2_ext_altsvc altsvc; } nghttp2_ext_frame_payload;
|
typedef union {
|
||||||
|
nghttp2_ext_altsvc altsvc;
|
||||||
|
nghttp2_ext_origin origin;
|
||||||
|
} nghttp2_ext_frame_payload;
|
||||||
|
|
||||||
void nghttp2_frame_pack_frame_hd(uint8_t *buf, const nghttp2_frame_hd *hd);
|
void nghttp2_frame_pack_frame_hd(uint8_t *buf, const nghttp2_frame_hd *hd);
|
||||||
|
|
||||||
@@ -390,6 +393,36 @@ int nghttp2_frame_unpack_altsvc_payload2(nghttp2_extension *frame,
|
|||||||
const uint8_t *payload,
|
const uint8_t *payload,
|
||||||
size_t payloadlen, nghttp2_mem *mem);
|
size_t payloadlen, nghttp2_mem *mem);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Packs ORIGIN frame |frame| in wire frame format and store it in
|
||||||
|
* |bufs|.
|
||||||
|
*
|
||||||
|
* The caller must make sure that nghttp2_bufs_reset(bufs) is called
|
||||||
|
* before calling this function.
|
||||||
|
*
|
||||||
|
* This function returns 0 if it succeeds, or one of the following
|
||||||
|
* negative error codes:
|
||||||
|
*
|
||||||
|
* NGHTTP2_ERR_FRAME_SIZE_ERROR
|
||||||
|
* The length of the frame is too large.
|
||||||
|
*/
|
||||||
|
int nghttp2_frame_pack_origin(nghttp2_bufs *bufs, nghttp2_extension *ext);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Unpacks ORIGIN wire format into |frame|. The |payload| of length
|
||||||
|
* |payloadlen| contains the frame payload.
|
||||||
|
*
|
||||||
|
* This function returns 0 if it succeeds, or one of the following
|
||||||
|
* negative error codes:
|
||||||
|
*
|
||||||
|
* NGHTTP2_ERR_NOMEM
|
||||||
|
* Out of memory.
|
||||||
|
* NGHTTP2_ERR_FRAME_SIZE_ERROR
|
||||||
|
* The payload is too small.
|
||||||
|
*/
|
||||||
|
int nghttp2_frame_unpack_origin_payload(nghttp2_extension *frame,
|
||||||
|
const uint8_t *payload,
|
||||||
|
size_t payloadlen, nghttp2_mem *mem);
|
||||||
/*
|
/*
|
||||||
* Initializes HEADERS frame |frame| with given values. |frame| takes
|
* Initializes HEADERS frame |frame| with given values. |frame| takes
|
||||||
* ownership of |nva|, so caller must not free it. If |stream_id| is
|
* ownership of |nva|, so caller must not free it. If |stream_id| is
|
||||||
@@ -487,6 +520,24 @@ void nghttp2_frame_altsvc_init(nghttp2_extension *frame, int32_t stream_id,
|
|||||||
*/
|
*/
|
||||||
void nghttp2_frame_altsvc_free(nghttp2_extension *frame, nghttp2_mem *mem);
|
void nghttp2_frame_altsvc_free(nghttp2_extension *frame, nghttp2_mem *mem);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initializes ORIGIN frame |frame| with given values. This function
|
||||||
|
* assumes that frame->payload points to nghttp2_ext_origin object.
|
||||||
|
* Also |ov| and the memory pointed by the field of its elements are
|
||||||
|
* allocated in single buffer, starting with |ov|. On success, this
|
||||||
|
* function takes ownership of |ov|, so caller must not free it.
|
||||||
|
*/
|
||||||
|
void nghttp2_frame_origin_init(nghttp2_extension *frame,
|
||||||
|
nghttp2_origin_entry *ov, size_t nov);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Frees up resources under |frame|. This function does not free
|
||||||
|
* nghttp2_ext_origin object pointed by frame->payload. This function
|
||||||
|
* only frees nghttp2_ext_origin.ov. Therefore, other fields must be
|
||||||
|
* allocated in the same buffer with ov.
|
||||||
|
*/
|
||||||
|
void nghttp2_frame_origin_free(nghttp2_extension *frame, nghttp2_mem *mem);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Returns the number of padding bytes after payload. The total
|
* Returns the number of padding bytes after payload. The total
|
||||||
* padding length is given in the |padlen|. The returned value does
|
* padding length is given in the |padlen|. The returned value does
|
||||||
|
|||||||
@@ -45,7 +45,7 @@
|
|||||||
/* 3rd parameter is nghttp2_token value for header field name. We use
|
/* 3rd parameter is nghttp2_token value for header field name. We use
|
||||||
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 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),
|
||||||
@@ -271,6 +271,15 @@ static int32_t lookup_token(const uint8_t *name, size_t namelen) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case 9:
|
||||||
|
switch (name[8]) {
|
||||||
|
case 'l':
|
||||||
|
if (memeq(":protoco", name, 8)) {
|
||||||
|
return NGHTTP2_TOKEN__PROTOCOL;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
case 10:
|
case 10:
|
||||||
switch (name[9]) {
|
switch (name[9]) {
|
||||||
case 'e':
|
case 'e':
|
||||||
@@ -1159,7 +1168,7 @@ static search_result search_static_table(const nghttp2_nv *nv, int32_t token,
|
|||||||
int name_only) {
|
int name_only) {
|
||||||
search_result res = {token, 0};
|
search_result res = {token, 0};
|
||||||
int i;
|
int i;
|
||||||
nghttp2_hd_static_entry *ent;
|
const nghttp2_hd_static_entry *ent;
|
||||||
|
|
||||||
if (name_only) {
|
if (name_only) {
|
||||||
return res;
|
return res;
|
||||||
@@ -1184,7 +1193,7 @@ static search_result search_hd_table(nghttp2_hd_context *context,
|
|||||||
int indexing_mode, nghttp2_hd_map *map,
|
int indexing_mode, nghttp2_hd_map *map,
|
||||||
uint32_t hash) {
|
uint32_t hash) {
|
||||||
search_result res = {-1, 0};
|
search_result res = {-1, 0};
|
||||||
nghttp2_hd_entry *ent;
|
const nghttp2_hd_entry *ent;
|
||||||
int exact_match;
|
int exact_match;
|
||||||
int name_only = indexing_mode == NGHTTP2_HD_NEVER_INDEXING;
|
int name_only = indexing_mode == NGHTTP2_HD_NEVER_INDEXING;
|
||||||
|
|
||||||
@@ -1289,8 +1298,9 @@ nghttp2_hd_nv nghttp2_hd_table_get(nghttp2_hd_context *context, size_t idx) {
|
|||||||
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 {
|
||||||
nghttp2_hd_static_entry *ent = &static_table[idx];
|
const nghttp2_hd_static_entry *ent = &static_table[idx];
|
||||||
nghttp2_hd_nv nv = {&ent->name, &ent->value, ent->token,
|
nghttp2_hd_nv nv = {(nghttp2_rcbuf *)&ent->name,
|
||||||
|
(nghttp2_rcbuf *)&ent->value, ent->token,
|
||||||
NGHTTP2_NV_FLAG_NONE};
|
NGHTTP2_NV_FLAG_NONE};
|
||||||
return nv;
|
return nv;
|
||||||
}
|
}
|
||||||
@@ -1380,7 +1390,7 @@ static int deflate_nv(nghttp2_hd_deflater *deflater, nghttp2_bufs *bufs,
|
|||||||
if (indexing_mode == NGHTTP2_HD_WITH_INDEXING) {
|
if (indexing_mode == NGHTTP2_HD_WITH_INDEXING) {
|
||||||
nghttp2_hd_nv hd_nv;
|
nghttp2_hd_nv hd_nv;
|
||||||
|
|
||||||
if (idx != -1 && idx < (ssize_t)NGHTTP2_STATIC_TABLE_LENGTH) {
|
if (idx != -1) {
|
||||||
hd_nv.name = nghttp2_hd_table_get(&deflater->ctx, (size_t)idx).name;
|
hd_nv.name = nghttp2_hd_table_get(&deflater->ctx, (size_t)idx).name;
|
||||||
nghttp2_rcbuf_incref(hd_nv.name);
|
nghttp2_rcbuf_incref(hd_nv.name);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -26,7 +26,7 @@
|
|||||||
#define NGHTTP2_HD_H
|
#define NGHTTP2_HD_H
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
#include <config.h>
|
# include <config.h>
|
||||||
#endif /* HAVE_CONFIG_H */
|
#endif /* HAVE_CONFIG_H */
|
||||||
|
|
||||||
#include <nghttp2/nghttp2.h>
|
#include <nghttp2/nghttp2.h>
|
||||||
@@ -111,6 +111,7 @@ typedef enum {
|
|||||||
NGHTTP2_TOKEN_KEEP_ALIVE,
|
NGHTTP2_TOKEN_KEEP_ALIVE,
|
||||||
NGHTTP2_TOKEN_PROXY_CONNECTION,
|
NGHTTP2_TOKEN_PROXY_CONNECTION,
|
||||||
NGHTTP2_TOKEN_UPGRADE,
|
NGHTTP2_TOKEN_UPGRADE,
|
||||||
|
NGHTTP2_TOKEN__PROTOCOL,
|
||||||
} nghttp2_token;
|
} nghttp2_token;
|
||||||
|
|
||||||
struct nghttp2_hd_entry;
|
struct nghttp2_hd_entry;
|
||||||
@@ -211,7 +212,9 @@ typedef struct {
|
|||||||
|
|
||||||
#define HD_MAP_SIZE 128
|
#define HD_MAP_SIZE 128
|
||||||
|
|
||||||
typedef struct { nghttp2_hd_entry *table[HD_MAP_SIZE]; } nghttp2_hd_map;
|
typedef struct {
|
||||||
|
nghttp2_hd_entry *table[HD_MAP_SIZE];
|
||||||
|
} nghttp2_hd_map;
|
||||||
|
|
||||||
struct nghttp2_hd_deflater {
|
struct nghttp2_hd_deflater {
|
||||||
nghttp2_hd_context ctx;
|
nghttp2_hd_context ctx;
|
||||||
@@ -313,7 +316,7 @@ void nghttp2_hd_deflate_free(nghttp2_hd_deflater *deflater);
|
|||||||
*
|
*
|
||||||
* This function expands |bufs| as necessary to store the result. If
|
* This function expands |bufs| as necessary to store the result. If
|
||||||
* buffers is full and the process still requires more space, this
|
* buffers is full and the process still requires more space, this
|
||||||
* funtion fails and returns NGHTTP2_ERR_HEADER_COMP.
|
* function fails and returns NGHTTP2_ERR_HEADER_COMP.
|
||||||
*
|
*
|
||||||
* After this function returns, it is safe to delete the |nva|.
|
* After this function returns, it is safe to delete the |nva|.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -26,7 +26,7 @@
|
|||||||
#define NGHTTP2_HD_HUFFMAN_H
|
#define NGHTTP2_HD_HUFFMAN_H
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
#include <config.h>
|
# include <config.h>
|
||||||
#endif /* HAVE_CONFIG_H */
|
#endif /* HAVE_CONFIG_H */
|
||||||
|
|
||||||
#include <nghttp2/nghttp2.h>
|
#include <nghttp2/nghttp2.h>
|
||||||
|
|||||||
@@ -322,6 +322,9 @@ const char *nghttp2_strerror(int error_code) {
|
|||||||
return "Internal error";
|
return "Internal error";
|
||||||
case NGHTTP2_ERR_CANCEL:
|
case NGHTTP2_ERR_CANCEL:
|
||||||
return "Cancel";
|
return "Cancel";
|
||||||
|
case NGHTTP2_ERR_SETTINGS_EXPECTED:
|
||||||
|
return "When a local endpoint expects to receive SETTINGS frame, it "
|
||||||
|
"receives an other type of frame";
|
||||||
case NGHTTP2_ERR_NOMEM:
|
case NGHTTP2_ERR_NOMEM:
|
||||||
return "Out of memory";
|
return "Out of memory";
|
||||||
case NGHTTP2_ERR_CALLBACK_FAILURE:
|
case NGHTTP2_ERR_CALLBACK_FAILURE:
|
||||||
@@ -337,7 +340,7 @@ const char *nghttp2_strerror(int error_code) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Generated by gennmchartbl.py */
|
/* Generated by gennmchartbl.py */
|
||||||
static 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 */,
|
||||||
@@ -425,7 +428,7 @@ int nghttp2_check_header_name(const uint8_t *name, size_t len) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Generated by genvchartbl.py */
|
/* Generated by genvchartbl.py */
|
||||||
static int VALID_HD_VALUE_CHARS[] = {
|
static 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 */,
|
||||||
|
|||||||
@@ -26,7 +26,7 @@
|
|||||||
#define NGHTTP2_HELPER_H
|
#define NGHTTP2_HELPER_H
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
#include <config.h>
|
# include <config.h>
|
||||||
#endif /* HAVE_CONFIG_H */
|
#endif /* HAVE_CONFIG_H */
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|||||||
@@ -113,7 +113,7 @@ static int check_path(nghttp2_stream *stream) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int http_request_on_header(nghttp2_stream *stream, nghttp2_hd_nv *nv,
|
static int http_request_on_header(nghttp2_stream *stream, nghttp2_hd_nv *nv,
|
||||||
int trailer) {
|
int trailer, int connect_protocol) {
|
||||||
if (nv->name->base[0] == ':') {
|
if (nv->name->base[0] == ':') {
|
||||||
if (trailer ||
|
if (trailer ||
|
||||||
(stream->http_flags & NGHTTP2_HTTP_FLAG_PSEUDO_HEADER_DISALLOWED)) {
|
(stream->http_flags & NGHTTP2_HTTP_FLAG_PSEUDO_HEADER_DISALLOWED)) {
|
||||||
@@ -146,10 +146,6 @@ static int http_request_on_header(nghttp2_stream *stream, nghttp2_hd_nv *nv,
|
|||||||
return NGHTTP2_ERR_HTTP_HEADER;
|
return NGHTTP2_ERR_HTTP_HEADER;
|
||||||
}
|
}
|
||||||
stream->http_flags |= NGHTTP2_HTTP_FLAG_METH_CONNECT;
|
stream->http_flags |= NGHTTP2_HTTP_FLAG_METH_CONNECT;
|
||||||
if (stream->http_flags &
|
|
||||||
(NGHTTP2_HTTP_FLAG__PATH | NGHTTP2_HTTP_FLAG__SCHEME)) {
|
|
||||||
return NGHTTP2_ERR_HTTP_HEADER;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'S':
|
case 'S':
|
||||||
@@ -162,9 +158,6 @@ static int http_request_on_header(nghttp2_stream *stream, nghttp2_hd_nv *nv,
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case NGHTTP2_TOKEN__PATH:
|
case NGHTTP2_TOKEN__PATH:
|
||||||
if (stream->http_flags & NGHTTP2_HTTP_FLAG_METH_CONNECT) {
|
|
||||||
return NGHTTP2_ERR_HTTP_HEADER;
|
|
||||||
}
|
|
||||||
if (!check_pseudo_header(stream, nv, NGHTTP2_HTTP_FLAG__PATH)) {
|
if (!check_pseudo_header(stream, nv, NGHTTP2_HTTP_FLAG__PATH)) {
|
||||||
return NGHTTP2_ERR_HTTP_HEADER;
|
return NGHTTP2_ERR_HTTP_HEADER;
|
||||||
}
|
}
|
||||||
@@ -175,9 +168,6 @@ static int http_request_on_header(nghttp2_stream *stream, nghttp2_hd_nv *nv,
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case NGHTTP2_TOKEN__SCHEME:
|
case NGHTTP2_TOKEN__SCHEME:
|
||||||
if (stream->http_flags & NGHTTP2_HTTP_FLAG_METH_CONNECT) {
|
|
||||||
return NGHTTP2_ERR_HTTP_HEADER;
|
|
||||||
}
|
|
||||||
if (!check_pseudo_header(stream, nv, NGHTTP2_HTTP_FLAG__SCHEME)) {
|
if (!check_pseudo_header(stream, nv, NGHTTP2_HTTP_FLAG__SCHEME)) {
|
||||||
return NGHTTP2_ERR_HTTP_HEADER;
|
return NGHTTP2_ERR_HTTP_HEADER;
|
||||||
}
|
}
|
||||||
@@ -186,6 +176,15 @@ static int http_request_on_header(nghttp2_stream *stream, nghttp2_hd_nv *nv,
|
|||||||
stream->http_flags |= NGHTTP2_HTTP_FLAG_SCHEME_HTTP;
|
stream->http_flags |= NGHTTP2_HTTP_FLAG_SCHEME_HTTP;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case NGHTTP2_TOKEN__PROTOCOL:
|
||||||
|
if (!connect_protocol) {
|
||||||
|
return NGHTTP2_ERR_HTTP_HEADER;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!check_pseudo_header(stream, nv, NGHTTP2_HTTP_FLAG__PROTOCOL)) {
|
||||||
|
return NGHTTP2_ERR_HTTP_HEADER;
|
||||||
|
}
|
||||||
|
break;
|
||||||
case NGHTTP2_TOKEN_HOST:
|
case NGHTTP2_TOKEN_HOST:
|
||||||
if (!check_pseudo_header(stream, nv, NGHTTP2_HTTP_FLAG_HOST)) {
|
if (!check_pseudo_header(stream, nv, NGHTTP2_HTTP_FLAG_HOST)) {
|
||||||
return NGHTTP2_ERR_HTTP_HEADER;
|
return NGHTTP2_ERR_HTTP_HEADER;
|
||||||
@@ -244,7 +243,7 @@ static int http_response_on_header(nghttp2_stream *stream, nghttp2_hd_nv *nv,
|
|||||||
return NGHTTP2_ERR_HTTP_HEADER;
|
return NGHTTP2_ERR_HTTP_HEADER;
|
||||||
}
|
}
|
||||||
stream->status_code = (int16_t)parse_uint(nv->value->base, nv->value->len);
|
stream->status_code = (int16_t)parse_uint(nv->value->base, nv->value->len);
|
||||||
if (stream->status_code == -1) {
|
if (stream->status_code == -1 || stream->status_code == 101) {
|
||||||
return NGHTTP2_ERR_HTTP_HEADER;
|
return NGHTTP2_ERR_HTTP_HEADER;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -265,7 +264,7 @@ static int http_response_on_header(nghttp2_stream *stream, nghttp2_hd_nv *nv,
|
|||||||
return NGHTTP2_ERR_REMOVE_HTTP_HEADER;
|
return NGHTTP2_ERR_REMOVE_HTTP_HEADER;
|
||||||
}
|
}
|
||||||
if (stream->status_code / 100 == 1 ||
|
if (stream->status_code / 100 == 1 ||
|
||||||
(stream->status_code == 200 &&
|
(stream->status_code / 100 == 2 &&
|
||||||
(stream->http_flags & NGHTTP2_HTTP_FLAG_METH_CONNECT))) {
|
(stream->http_flags & NGHTTP2_HTTP_FLAG_METH_CONNECT))) {
|
||||||
return NGHTTP2_ERR_HTTP_HEADER;
|
return NGHTTP2_ERR_HTTP_HEADER;
|
||||||
}
|
}
|
||||||
@@ -458,7 +457,9 @@ 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->pending_enable_connect_protocol);
|
||||||
}
|
}
|
||||||
|
|
||||||
return http_response_on_header(stream, nv, trailer);
|
return http_response_on_header(stream, nv, trailer);
|
||||||
@@ -466,8 +467,11 @@ int nghttp2_http_on_header(nghttp2_session *session, nghttp2_stream *stream,
|
|||||||
|
|
||||||
int nghttp2_http_on_request_headers(nghttp2_stream *stream,
|
int nghttp2_http_on_request_headers(nghttp2_stream *stream,
|
||||||
nghttp2_frame *frame) {
|
nghttp2_frame *frame) {
|
||||||
if (stream->http_flags & NGHTTP2_HTTP_FLAG_METH_CONNECT) {
|
if (!(stream->http_flags & NGHTTP2_HTTP_FLAG__PROTOCOL) &&
|
||||||
if ((stream->http_flags & NGHTTP2_HTTP_FLAG__AUTHORITY) == 0) {
|
(stream->http_flags & NGHTTP2_HTTP_FLAG_METH_CONNECT)) {
|
||||||
|
if ((stream->http_flags &
|
||||||
|
(NGHTTP2_HTTP_FLAG__SCHEME | NGHTTP2_HTTP_FLAG__PATH)) ||
|
||||||
|
(stream->http_flags & NGHTTP2_HTTP_FLAG__AUTHORITY) == 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
stream->content_length = -1;
|
stream->content_length = -1;
|
||||||
@@ -478,6 +482,11 @@ int nghttp2_http_on_request_headers(nghttp2_stream *stream,
|
|||||||
(NGHTTP2_HTTP_FLAG__AUTHORITY | NGHTTP2_HTTP_FLAG_HOST)) == 0) {
|
(NGHTTP2_HTTP_FLAG__AUTHORITY | NGHTTP2_HTTP_FLAG_HOST)) == 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
if ((stream->http_flags & NGHTTP2_HTTP_FLAG__PROTOCOL) &&
|
||||||
|
((stream->http_flags & NGHTTP2_HTTP_FLAG_METH_CONNECT) == 0 ||
|
||||||
|
(stream->http_flags & NGHTTP2_HTTP_FLAG__AUTHORITY) == 0)) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
if (!check_path(stream)) {
|
if (!check_path(stream)) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,7 +26,7 @@
|
|||||||
#define NGHTTP2_HTTP_H
|
#define NGHTTP2_HTTP_H
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
#include <config.h>
|
# include <config.h>
|
||||||
#endif /* HAVE_CONFIG_H */
|
#endif /* HAVE_CONFIG_H */
|
||||||
|
|
||||||
#include <nghttp2/nghttp2.h>
|
#include <nghttp2/nghttp2.h>
|
||||||
|
|||||||
@@ -26,7 +26,7 @@
|
|||||||
#define NGHTTP2_INT_H
|
#define NGHTTP2_INT_H
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
#include <config.h>
|
# include <config.h>
|
||||||
#endif /* HAVE_CONFIG_H */
|
#endif /* HAVE_CONFIG_H */
|
||||||
|
|
||||||
#include <nghttp2/nghttp2.h>
|
#include <nghttp2/nghttp2.h>
|
||||||
|
|||||||
@@ -26,7 +26,7 @@
|
|||||||
#define NGHTTP2_MAP_H
|
#define NGHTTP2_MAP_H
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
#include <config.h>
|
# include <config.h>
|
||||||
#endif /* HAVE_CONFIG_H */
|
#endif /* HAVE_CONFIG_H */
|
||||||
|
|
||||||
#include <nghttp2/nghttp2.h>
|
#include <nghttp2/nghttp2.h>
|
||||||
|
|||||||
@@ -26,7 +26,7 @@
|
|||||||
#define NGHTTP2_MEM_H
|
#define NGHTTP2_MEM_H
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
#include <config.h>
|
# include <config.h>
|
||||||
#endif /* HAVE_CONFIG_H */
|
#endif /* HAVE_CONFIG_H */
|
||||||
|
|
||||||
#include <nghttp2/nghttp2.h>
|
#include <nghttp2/nghttp2.h>
|
||||||
|
|||||||
@@ -26,15 +26,15 @@
|
|||||||
#define NGHTTP2_NET_H
|
#define NGHTTP2_NET_H
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
#include <config.h>
|
# include <config.h>
|
||||||
#endif /* HAVE_CONFIG_H */
|
#endif /* HAVE_CONFIG_H */
|
||||||
|
|
||||||
#ifdef HAVE_ARPA_INET_H
|
#ifdef HAVE_ARPA_INET_H
|
||||||
#include <arpa/inet.h>
|
# include <arpa/inet.h>
|
||||||
#endif /* HAVE_ARPA_INET_H */
|
#endif /* HAVE_ARPA_INET_H */
|
||||||
|
|
||||||
#ifdef HAVE_NETINET_IN_H
|
#ifdef HAVE_NETINET_IN_H
|
||||||
#include <netinet/in.h>
|
# include <netinet/in.h>
|
||||||
#endif /* HAVE_NETINET_IN_H */
|
#endif /* HAVE_NETINET_IN_H */
|
||||||
|
|
||||||
#include <nghttp2/nghttp2.h>
|
#include <nghttp2/nghttp2.h>
|
||||||
@@ -44,11 +44,11 @@
|
|||||||
define inline functions for those function so that we don't have
|
define inline functions for those function so that we don't have
|
||||||
dependeny on that lib. */
|
dependeny on that lib. */
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
# ifdef _MSC_VER
|
||||||
#define STIN static __inline
|
# define STIN static __inline
|
||||||
#else
|
# else
|
||||||
#define STIN static inline
|
# define STIN static inline
|
||||||
#endif
|
# endif
|
||||||
|
|
||||||
STIN uint32_t htonl(uint32_t hostlong) {
|
STIN uint32_t htonl(uint32_t hostlong) {
|
||||||
uint32_t res;
|
uint32_t res;
|
||||||
|
|||||||
@@ -26,7 +26,7 @@
|
|||||||
#define NGHTTP2_NPN_H
|
#define NGHTTP2_NPN_H
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
#include <config.h>
|
# include <config.h>
|
||||||
#endif /* HAVE_CONFIG_H */
|
#endif /* HAVE_CONFIG_H */
|
||||||
|
|
||||||
#include <nghttp2/nghttp2.h>
|
#include <nghttp2/nghttp2.h>
|
||||||
|
|||||||
@@ -86,6 +86,10 @@ void nghttp2_option_set_builtin_recv_extension_type(nghttp2_option *option,
|
|||||||
option->opt_set_mask |= NGHTTP2_OPT_BUILTIN_RECV_EXT_TYPES;
|
option->opt_set_mask |= NGHTTP2_OPT_BUILTIN_RECV_EXT_TYPES;
|
||||||
option->builtin_recv_ext_types |= NGHTTP2_TYPEMASK_ALTSVC;
|
option->builtin_recv_ext_types |= NGHTTP2_TYPEMASK_ALTSVC;
|
||||||
return;
|
return;
|
||||||
|
case NGHTTP2_ORIGIN:
|
||||||
|
option->opt_set_mask |= NGHTTP2_OPT_BUILTIN_RECV_EXT_TYPES;
|
||||||
|
option->builtin_recv_ext_types |= NGHTTP2_TYPEMASK_ORIGIN;
|
||||||
|
return;
|
||||||
default:
|
default:
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,7 +26,7 @@
|
|||||||
#define NGHTTP2_OPTION_H
|
#define NGHTTP2_OPTION_H
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
#include <config.h>
|
# include <config.h>
|
||||||
#endif /* HAVE_CONFIG_H */
|
#endif /* HAVE_CONFIG_H */
|
||||||
|
|
||||||
#include <nghttp2/nghttp2.h>
|
#include <nghttp2/nghttp2.h>
|
||||||
|
|||||||
@@ -86,6 +86,9 @@ void nghttp2_outbound_item_free(nghttp2_outbound_item *item, nghttp2_mem *mem) {
|
|||||||
case NGHTTP2_ALTSVC:
|
case NGHTTP2_ALTSVC:
|
||||||
nghttp2_frame_altsvc_free(&frame->ext, mem);
|
nghttp2_frame_altsvc_free(&frame->ext, mem);
|
||||||
break;
|
break;
|
||||||
|
case NGHTTP2_ORIGIN:
|
||||||
|
nghttp2_frame_origin_free(&frame->ext, mem);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
assert(0);
|
assert(0);
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -26,7 +26,7 @@
|
|||||||
#define NGHTTP2_OUTBOUND_ITEM_H
|
#define NGHTTP2_OUTBOUND_ITEM_H
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
#include <config.h>
|
# include <config.h>
|
||||||
#endif /* HAVE_CONFIG_H */
|
#endif /* HAVE_CONFIG_H */
|
||||||
|
|
||||||
#include <nghttp2/nghttp2.h>
|
#include <nghttp2/nghttp2.h>
|
||||||
@@ -112,7 +112,7 @@ struct nghttp2_outbound_item {
|
|||||||
nghttp2_ext_frame_payload ext_frame_payload;
|
nghttp2_ext_frame_payload ext_frame_payload;
|
||||||
nghttp2_aux_data aux_data;
|
nghttp2_aux_data aux_data;
|
||||||
/* The priority used in priority comparion. Smaller is served
|
/* The priority used in priority comparion. Smaller is served
|
||||||
ealier. For PING, SETTINGS and non-DATA frames (excluding
|
earlier. For PING, SETTINGS and non-DATA frames (excluding
|
||||||
response HEADERS frame) have dedicated cycle value defined above.
|
response HEADERS frame) have dedicated cycle value defined above.
|
||||||
For DATA frame, cycle is computed by taking into account of
|
For DATA frame, cycle is computed by taking into account of
|
||||||
effective weight and frame payload length previously sent, so
|
effective weight and frame payload length previously sent, so
|
||||||
|
|||||||
@@ -26,7 +26,7 @@
|
|||||||
#define NGHTTP2_PQ_H
|
#define NGHTTP2_PQ_H
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
#include <config.h>
|
# include <config.h>
|
||||||
#endif /* HAVE_CONFIG_H */
|
#endif /* HAVE_CONFIG_H */
|
||||||
|
|
||||||
#include <nghttp2/nghttp2.h>
|
#include <nghttp2/nghttp2.h>
|
||||||
@@ -35,14 +35,16 @@
|
|||||||
|
|
||||||
/* Implementation of priority queue */
|
/* Implementation of priority queue */
|
||||||
|
|
||||||
typedef struct { size_t index; } nghttp2_pq_entry;
|
typedef struct {
|
||||||
|
size_t index;
|
||||||
|
} nghttp2_pq_entry;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
/* The pointer to the pointer to the item stored */
|
/* The pointer to the pointer to the item stored */
|
||||||
nghttp2_pq_entry **q;
|
nghttp2_pq_entry **q;
|
||||||
/* Memory allocator */
|
/* Memory allocator */
|
||||||
nghttp2_mem *mem;
|
nghttp2_mem *mem;
|
||||||
/* The number of items sotred */
|
/* The number of items stored */
|
||||||
size_t length;
|
size_t length;
|
||||||
/* The maximum number of items this pq can store. This is
|
/* The maximum number of items this pq can store. This is
|
||||||
automatically extended when length is reached to this value. */
|
automatically extended when length is reached to this value. */
|
||||||
@@ -71,7 +73,7 @@ void nghttp2_pq_free(nghttp2_pq *pq);
|
|||||||
/*
|
/*
|
||||||
* Adds |item| to the priority queue |pq|.
|
* Adds |item| to the priority queue |pq|.
|
||||||
*
|
*
|
||||||
* This function returns 0 if it succeds, 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_NOMEM
|
* NGHTTP2_ERR_NOMEM
|
||||||
|
|||||||
@@ -26,7 +26,7 @@
|
|||||||
#define NGHTTP2_PRIORITY_SPEC_H
|
#define NGHTTP2_PRIORITY_SPEC_H
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
#include <config.h>
|
# include <config.h>
|
||||||
#endif /* HAVE_CONFIG_H */
|
#endif /* HAVE_CONFIG_H */
|
||||||
|
|
||||||
#include <nghttp2/nghttp2.h>
|
#include <nghttp2/nghttp2.h>
|
||||||
|
|||||||
@@ -26,7 +26,7 @@
|
|||||||
#define NGHTTP2_QUEUE_H
|
#define NGHTTP2_QUEUE_H
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
#include "config.h"
|
# include "config.h"
|
||||||
#endif /* HAVE_CONFIG_H */
|
#endif /* HAVE_CONFIG_H */
|
||||||
|
|
||||||
#include <nghttp2/nghttp2.h>
|
#include <nghttp2/nghttp2.h>
|
||||||
@@ -36,7 +36,9 @@ typedef struct nghttp2_queue_cell {
|
|||||||
struct nghttp2_queue_cell *next;
|
struct nghttp2_queue_cell *next;
|
||||||
} nghttp2_queue_cell;
|
} nghttp2_queue_cell;
|
||||||
|
|
||||||
typedef struct { nghttp2_queue_cell *front, *back; } nghttp2_queue;
|
typedef struct {
|
||||||
|
nghttp2_queue_cell *front, *back;
|
||||||
|
} nghttp2_queue;
|
||||||
|
|
||||||
void nghttp2_queue_init(nghttp2_queue *queue);
|
void nghttp2_queue_init(nghttp2_queue *queue);
|
||||||
void nghttp2_queue_free(nghttp2_queue *queue);
|
void nghttp2_queue_free(nghttp2_queue *queue);
|
||||||
|
|||||||
@@ -96,3 +96,7 @@ nghttp2_vec nghttp2_rcbuf_get_buf(nghttp2_rcbuf *rcbuf) {
|
|||||||
nghttp2_vec res = {rcbuf->base, rcbuf->len};
|
nghttp2_vec res = {rcbuf->base, rcbuf->len};
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int nghttp2_rcbuf_is_static(const nghttp2_rcbuf *rcbuf) {
|
||||||
|
return rcbuf->ref == -1;
|
||||||
|
}
|
||||||
|
|||||||
@@ -26,7 +26,7 @@
|
|||||||
#define NGHTTP2_RCBUF_H
|
#define NGHTTP2_RCBUF_H
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
#include <config.h>
|
# include <config.h>
|
||||||
#endif /* HAVE_CONFIG_H */
|
#endif /* HAVE_CONFIG_H */
|
||||||
|
|
||||||
#include <nghttp2/nghttp2.h>
|
#include <nghttp2/nghttp2.h>
|
||||||
|
|||||||
@@ -148,14 +148,16 @@ static int check_ext_type_set(const uint8_t *ext_types, uint8_t type) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int session_call_error_callback(nghttp2_session *session,
|
static int session_call_error_callback(nghttp2_session *session,
|
||||||
const char *fmt, ...) {
|
int lib_error_code, const char *fmt,
|
||||||
|
...) {
|
||||||
size_t bufsize;
|
size_t bufsize;
|
||||||
va_list ap;
|
va_list ap;
|
||||||
char *buf;
|
char *buf;
|
||||||
int rv;
|
int rv;
|
||||||
nghttp2_mem *mem;
|
nghttp2_mem *mem;
|
||||||
|
|
||||||
if (!session->callbacks.error_callback) {
|
if (!session->callbacks.error_callback &&
|
||||||
|
!session->callbacks.error_callback2) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -189,8 +191,13 @@ static int session_call_error_callback(nghttp2_session *session,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
rv = session->callbacks.error_callback(session, buf, (size_t)rv,
|
if (session->callbacks.error_callback2) {
|
||||||
session->user_data);
|
rv = session->callbacks.error_callback2(session, lib_error_code, buf,
|
||||||
|
(size_t)rv, session->user_data);
|
||||||
|
} else {
|
||||||
|
rv = session->callbacks.error_callback(session, buf, (size_t)rv,
|
||||||
|
session->user_data);
|
||||||
|
}
|
||||||
|
|
||||||
nghttp2_mem_free(mem, buf);
|
nghttp2_mem_free(mem, buf);
|
||||||
|
|
||||||
@@ -212,6 +219,10 @@ static int session_terminate_session(nghttp2_session *session,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Ignore all incoming frames because we are going to tear down the
|
||||||
|
session. */
|
||||||
|
session->iframe.state = NGHTTP2_IB_IGN_ALL;
|
||||||
|
|
||||||
if (reason == NULL) {
|
if (reason == NULL) {
|
||||||
debug_data = NULL;
|
debug_data = NULL;
|
||||||
debug_datalen = 0;
|
debug_datalen = 0;
|
||||||
@@ -337,6 +348,12 @@ static void session_inbound_frame_reset(nghttp2_session *session) {
|
|||||||
}
|
}
|
||||||
nghttp2_frame_altsvc_free(&iframe->frame.ext, mem);
|
nghttp2_frame_altsvc_free(&iframe->frame.ext, mem);
|
||||||
break;
|
break;
|
||||||
|
case NGHTTP2_ORIGIN:
|
||||||
|
if ((session->builtin_recv_ext_types & NGHTTP2_TYPEMASK_ORIGIN) == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
nghttp2_frame_origin_free(&iframe->frame.ext, mem);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -541,9 +558,8 @@ static int session_new(nghttp2_session **session_ptr,
|
|||||||
if (nghttp2_enable_strict_preface) {
|
if (nghttp2_enable_strict_preface) {
|
||||||
nghttp2_inbound_frame *iframe = &(*session_ptr)->iframe;
|
nghttp2_inbound_frame *iframe = &(*session_ptr)->iframe;
|
||||||
|
|
||||||
if (server &&
|
if (server && ((*session_ptr)->opt_flags &
|
||||||
((*session_ptr)->opt_flags & NGHTTP2_OPTMASK_NO_RECV_CLIENT_MAGIC) ==
|
NGHTTP2_OPTMASK_NO_RECV_CLIENT_MAGIC) == 0) {
|
||||||
0) {
|
|
||||||
iframe->state = NGHTTP2_IB_READ_CLIENT_MAGIC;
|
iframe->state = NGHTTP2_IB_READ_CLIENT_MAGIC;
|
||||||
iframe->payloadleft = NGHTTP2_CLIENT_MAGIC_LEN;
|
iframe->payloadleft = NGHTTP2_CLIENT_MAGIC_LEN;
|
||||||
} else {
|
} else {
|
||||||
@@ -1739,6 +1755,13 @@ static int session_predicate_altsvc_send(nghttp2_session *session,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int session_predicate_origin_send(nghttp2_session *session) {
|
||||||
|
if (session_is_closing(session)) {
|
||||||
|
return NGHTTP2_ERR_SESSION_CLOSING;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* Take into account settings max frame size and both connection-level
|
/* Take into account settings max frame size and both connection-level
|
||||||
flow control here */
|
flow control here */
|
||||||
static ssize_t
|
static ssize_t
|
||||||
@@ -2183,7 +2206,7 @@ static int session_prep_frame(nghttp2_session *session,
|
|||||||
closed. */
|
closed. */
|
||||||
stream = nghttp2_session_get_stream(session, frame->hd.stream_id);
|
stream = nghttp2_session_get_stream(session, frame->hd.stream_id);
|
||||||
|
|
||||||
/* predicte should fail if stream is NULL. */
|
/* predicate should fail if stream is NULL. */
|
||||||
rv = session_predicate_push_promise_send(session, stream);
|
rv = session_predicate_push_promise_send(session, stream);
|
||||||
if (rv != 0) {
|
if (rv != 0) {
|
||||||
return rv;
|
return rv;
|
||||||
@@ -2219,8 +2242,9 @@ static int session_prep_frame(nghttp2_session *session,
|
|||||||
assert(session->obq_flood_counter_ > 0);
|
assert(session->obq_flood_counter_ > 0);
|
||||||
--session->obq_flood_counter_;
|
--session->obq_flood_counter_;
|
||||||
}
|
}
|
||||||
|
/* PING frame is allowed to be sent unless termination GOAWAY is
|
||||||
if (session_is_closing(session)) {
|
sent */
|
||||||
|
if (session->goaway_flags & NGHTTP2_GOAWAY_TERM_ON_SEND) {
|
||||||
return NGHTTP2_ERR_SESSION_CLOSING;
|
return NGHTTP2_ERR_SESSION_CLOSING;
|
||||||
}
|
}
|
||||||
nghttp2_frame_pack_ping(&session->aob.framebufs, &frame->ping);
|
nghttp2_frame_pack_ping(&session->aob.framebufs, &frame->ping);
|
||||||
@@ -2269,6 +2293,18 @@ static int session_prep_frame(nghttp2_session *session,
|
|||||||
|
|
||||||
nghttp2_frame_pack_altsvc(&session->aob.framebufs, &frame->ext);
|
nghttp2_frame_pack_altsvc(&session->aob.framebufs, &frame->ext);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
case NGHTTP2_ORIGIN:
|
||||||
|
rv = session_predicate_origin_send(session);
|
||||||
|
if (rv != 0) {
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
rv = nghttp2_frame_pack_origin(&session->aob.framebufs, &frame->ext);
|
||||||
|
if (rv != 0) {
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
default:
|
default:
|
||||||
/* Unreachable here */
|
/* Unreachable here */
|
||||||
@@ -2411,19 +2447,16 @@ static int session_close_stream_on_goaway(nghttp2_session *session,
|
|||||||
nghttp2_stream *stream, *next_stream;
|
nghttp2_stream *stream, *next_stream;
|
||||||
nghttp2_close_stream_on_goaway_arg arg = {session, NULL, last_stream_id,
|
nghttp2_close_stream_on_goaway_arg arg = {session, NULL, last_stream_id,
|
||||||
incoming};
|
incoming};
|
||||||
uint32_t error_code;
|
|
||||||
|
|
||||||
rv = nghttp2_map_each(&session->streams, find_stream_on_goaway_func, &arg);
|
rv = nghttp2_map_each(&session->streams, find_stream_on_goaway_func, &arg);
|
||||||
assert(rv == 0);
|
assert(rv == 0);
|
||||||
|
|
||||||
error_code =
|
|
||||||
session->server && incoming ? NGHTTP2_REFUSED_STREAM : NGHTTP2_CANCEL;
|
|
||||||
|
|
||||||
stream = arg.head;
|
stream = arg.head;
|
||||||
while (stream) {
|
while (stream) {
|
||||||
next_stream = stream->closed_next;
|
next_stream = stream->closed_next;
|
||||||
stream->closed_next = NULL;
|
stream->closed_next = NULL;
|
||||||
rv = nghttp2_session_close_stream(session, stream->stream_id, error_code);
|
rv = nghttp2_session_close_stream(session, stream->stream_id,
|
||||||
|
NGHTTP2_REFUSED_STREAM);
|
||||||
|
|
||||||
/* stream may be deleted here */
|
/* stream may be deleted here */
|
||||||
|
|
||||||
@@ -3586,70 +3619,73 @@ static int inflate_header_block(nghttp2_session *session, nghttp2_frame *frame,
|
|||||||
|
|
||||||
if (call_header_cb && (inflate_flags & NGHTTP2_HD_INFLATE_EMIT)) {
|
if (call_header_cb && (inflate_flags & NGHTTP2_HD_INFLATE_EMIT)) {
|
||||||
rv = 0;
|
rv = 0;
|
||||||
if (subject_stream && session_enforce_http_messaging(session)) {
|
if (subject_stream) {
|
||||||
rv = nghttp2_http_on_header(session, subject_stream, frame, &nv,
|
if (session_enforce_http_messaging(session)) {
|
||||||
trailer);
|
rv = nghttp2_http_on_header(session, subject_stream, frame, &nv,
|
||||||
|
trailer);
|
||||||
|
|
||||||
if (rv == NGHTTP2_ERR_IGN_HTTP_HEADER) {
|
if (rv == NGHTTP2_ERR_IGN_HTTP_HEADER) {
|
||||||
/* Don't overwrite rv here */
|
/* Don't overwrite rv here */
|
||||||
int rv2;
|
int rv2;
|
||||||
|
|
||||||
rv2 = session_call_on_invalid_header(session, frame, &nv);
|
rv2 = session_call_on_invalid_header(session, frame, &nv);
|
||||||
if (rv2 == NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE) {
|
if (rv2 == NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE) {
|
||||||
rv = NGHTTP2_ERR_HTTP_HEADER;
|
rv = NGHTTP2_ERR_HTTP_HEADER;
|
||||||
} else {
|
} else {
|
||||||
if (rv2 != 0) {
|
if (rv2 != 0) {
|
||||||
return rv2;
|
return rv2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* header is ignored */
|
||||||
|
DEBUGF("recv: HTTP ignored: type=%u, id=%d, header %.*s: %.*s\n",
|
||||||
|
frame->hd.type, frame->hd.stream_id, (int)nv.name->len,
|
||||||
|
nv.name->base, (int)nv.value->len, nv.value->base);
|
||||||
|
|
||||||
|
rv2 = session_call_error_callback(
|
||||||
|
session, NGHTTP2_ERR_HTTP_HEADER,
|
||||||
|
"Ignoring received invalid HTTP header field: frame type: "
|
||||||
|
"%u, stream: %d, name: [%.*s], value: [%.*s]",
|
||||||
|
frame->hd.type, frame->hd.stream_id, (int)nv.name->len,
|
||||||
|
nv.name->base, (int)nv.value->len, nv.value->base);
|
||||||
|
|
||||||
|
if (nghttp2_is_fatal(rv2)) {
|
||||||
|
return rv2;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* header is ignored */
|
if (rv == NGHTTP2_ERR_HTTP_HEADER) {
|
||||||
DEBUGF("recv: HTTP ignored: type=%u, id=%d, header %.*s: %.*s\n",
|
DEBUGF("recv: HTTP error: type=%u, id=%d, header %.*s: %.*s\n",
|
||||||
frame->hd.type, frame->hd.stream_id, (int)nv.name->len,
|
frame->hd.type, frame->hd.stream_id, (int)nv.name->len,
|
||||||
nv.name->base, (int)nv.value->len, nv.value->base);
|
nv.name->base, (int)nv.value->len, nv.value->base);
|
||||||
|
|
||||||
rv2 = session_call_error_callback(
|
rv = session_call_error_callback(
|
||||||
session,
|
session, NGHTTP2_ERR_HTTP_HEADER,
|
||||||
"Ignoring received invalid HTTP header field: frame type: "
|
"Invalid HTTP header field was received: frame type: "
|
||||||
"%u, stream: %d, name: [%.*s], value: [%.*s]",
|
"%u, stream: %d, name: [%.*s], value: [%.*s]",
|
||||||
frame->hd.type, frame->hd.stream_id, (int)nv.name->len,
|
frame->hd.type, frame->hd.stream_id, (int)nv.name->len,
|
||||||
nv.name->base, (int)nv.value->len, nv.value->base);
|
nv.name->base, (int)nv.value->len, nv.value->base);
|
||||||
|
|
||||||
if (nghttp2_is_fatal(rv2)) {
|
if (nghttp2_is_fatal(rv)) {
|
||||||
return rv2;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rv = session_handle_invalid_stream2(session,
|
||||||
|
subject_stream->stream_id,
|
||||||
|
frame, NGHTTP2_ERR_HTTP_HEADER);
|
||||||
|
if (nghttp2_is_fatal(rv)) {
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (rv == 0) {
|
||||||
if (rv == NGHTTP2_ERR_HTTP_HEADER) {
|
rv = session_call_on_header(session, frame, &nv);
|
||||||
DEBUGF("recv: HTTP error: type=%u, id=%d, header %.*s: %.*s\n",
|
/* This handles NGHTTP2_ERR_PAUSE and
|
||||||
frame->hd.type, frame->hd.stream_id, (int)nv.name->len,
|
NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE as well */
|
||||||
nv.name->base, (int)nv.value->len, nv.value->base);
|
if (rv != 0) {
|
||||||
|
|
||||||
rv = session_call_error_callback(
|
|
||||||
session, "Invalid HTTP header field was received: frame type: "
|
|
||||||
"%u, stream: %d, name: [%.*s], value: [%.*s]",
|
|
||||||
frame->hd.type, frame->hd.stream_id, (int)nv.name->len,
|
|
||||||
nv.name->base, (int)nv.value->len, nv.value->base);
|
|
||||||
|
|
||||||
if (nghttp2_is_fatal(rv)) {
|
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
rv =
|
|
||||||
session_handle_invalid_stream2(session, subject_stream->stream_id,
|
|
||||||
frame, NGHTTP2_ERR_HTTP_HEADER);
|
|
||||||
if (nghttp2_is_fatal(rv)) {
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (rv == 0) {
|
|
||||||
rv = session_call_on_header(session, frame, &nv);
|
|
||||||
/* This handles NGHTTP2_ERR_PAUSE and
|
|
||||||
NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE as well */
|
|
||||||
if (rv != 0) {
|
|
||||||
return rv;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3781,7 +3817,7 @@ int nghttp2_session_on_request_headers_received(nghttp2_session *session,
|
|||||||
session, frame, NGHTTP2_ERR_PROTO, "request HEADERS: stream_id == 0");
|
session, frame, NGHTTP2_ERR_PROTO, "request HEADERS: stream_id == 0");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If client recieves idle stream from server, it is invalid
|
/* If client receives idle stream from server, it is invalid
|
||||||
regardless stream ID is even or odd. This is because client is
|
regardless stream ID is even or odd. This is because client is
|
||||||
not expected to receive request from server. */
|
not expected to receive request from server. */
|
||||||
if (!session->server) {
|
if (!session->server) {
|
||||||
@@ -4327,6 +4363,9 @@ int nghttp2_session_update_local_settings(nghttp2_session *session,
|
|||||||
case NGHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE:
|
case NGHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE:
|
||||||
session->local_settings.max_header_list_size = iv[i].value;
|
session->local_settings.max_header_list_size = iv[i].value;
|
||||||
break;
|
break;
|
||||||
|
case NGHTTP2_SETTINGS_ENABLE_CONNECT_PROTOCOL:
|
||||||
|
session->local_settings.enable_connect_protocol = iv[i].value;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4376,6 +4415,12 @@ int nghttp2_session_on_settings_received(nghttp2_session *session,
|
|||||||
return session_call_on_frame_received(session, frame);
|
return session_call_on_frame_received(session, frame);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!session->remote_settings_received) {
|
||||||
|
session->remote_settings.max_concurrent_streams =
|
||||||
|
NGHTTP2_DEFAULT_MAX_CONCURRENT_STREAMS;
|
||||||
|
session->remote_settings_received = 1;
|
||||||
|
}
|
||||||
|
|
||||||
for (i = 0; i < frame->settings.niv; ++i) {
|
for (i = 0; i < frame->settings.niv; ++i) {
|
||||||
nghttp2_settings_entry *entry = &frame->settings.iv[i];
|
nghttp2_settings_entry *entry = &frame->settings.iv[i];
|
||||||
|
|
||||||
@@ -4459,6 +4504,26 @@ int nghttp2_session_on_settings_received(nghttp2_session *session,
|
|||||||
|
|
||||||
session->remote_settings.max_header_list_size = entry->value;
|
session->remote_settings.max_header_list_size = entry->value;
|
||||||
|
|
||||||
|
break;
|
||||||
|
case NGHTTP2_SETTINGS_ENABLE_CONNECT_PROTOCOL:
|
||||||
|
|
||||||
|
if (entry->value != 0 && entry->value != 1) {
|
||||||
|
return session_handle_invalid_connection(
|
||||||
|
session, frame, NGHTTP2_ERR_PROTO,
|
||||||
|
"SETTINGS: invalid SETTINGS_ENABLE_CONNECT_PROTOCOL");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!session->server &&
|
||||||
|
session->remote_settings.enable_connect_protocol &&
|
||||||
|
entry->value == 0) {
|
||||||
|
return session_handle_invalid_connection(
|
||||||
|
session, frame, NGHTTP2_ERR_PROTO,
|
||||||
|
"SETTINGS: server attempted to disable "
|
||||||
|
"SETTINGS_ENABLE_CONNECT_PROTOCOL");
|
||||||
|
}
|
||||||
|
|
||||||
|
session->remote_settings.enable_connect_protocol = entry->value;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -4812,6 +4877,11 @@ int nghttp2_session_on_altsvc_received(nghttp2_session *session,
|
|||||||
return session_call_on_frame_received(session, frame);
|
return session_call_on_frame_received(session, frame);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int nghttp2_session_on_origin_received(nghttp2_session *session,
|
||||||
|
nghttp2_frame *frame) {
|
||||||
|
return session_call_on_frame_received(session, frame);
|
||||||
|
}
|
||||||
|
|
||||||
static int session_process_altsvc_frame(nghttp2_session *session) {
|
static int session_process_altsvc_frame(nghttp2_session *session) {
|
||||||
nghttp2_inbound_frame *iframe = &session->iframe;
|
nghttp2_inbound_frame *iframe = &session->iframe;
|
||||||
nghttp2_frame *frame = &iframe->frame;
|
nghttp2_frame *frame = &iframe->frame;
|
||||||
@@ -4827,6 +4897,25 @@ static int session_process_altsvc_frame(nghttp2_session *session) {
|
|||||||
return nghttp2_session_on_altsvc_received(session, frame);
|
return nghttp2_session_on_altsvc_received(session, frame);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int session_process_origin_frame(nghttp2_session *session) {
|
||||||
|
nghttp2_inbound_frame *iframe = &session->iframe;
|
||||||
|
nghttp2_frame *frame = &iframe->frame;
|
||||||
|
nghttp2_mem *mem = &session->mem;
|
||||||
|
int rv;
|
||||||
|
|
||||||
|
rv = nghttp2_frame_unpack_origin_payload(&frame->ext, iframe->lbuf.pos,
|
||||||
|
nghttp2_buf_len(&iframe->lbuf), mem);
|
||||||
|
if (rv != 0) {
|
||||||
|
if (nghttp2_is_fatal(rv)) {
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
/* Ignore ORIGIN frame which cannot be parsed. */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return nghttp2_session_on_origin_received(session, frame);
|
||||||
|
}
|
||||||
|
|
||||||
static int session_process_extension_frame(nghttp2_session *session) {
|
static int session_process_extension_frame(nghttp2_session *session) {
|
||||||
int rv;
|
int rv;
|
||||||
nghttp2_inbound_frame *iframe = &session->iframe;
|
nghttp2_inbound_frame *iframe = &session->iframe;
|
||||||
@@ -5186,6 +5275,7 @@ static void inbound_frame_set_settings_entry(nghttp2_inbound_frame *iframe) {
|
|||||||
case NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE:
|
case NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE:
|
||||||
case NGHTTP2_SETTINGS_MAX_FRAME_SIZE:
|
case NGHTTP2_SETTINGS_MAX_FRAME_SIZE:
|
||||||
case NGHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE:
|
case NGHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE:
|
||||||
|
case NGHTTP2_SETTINGS_ENABLE_CONNECT_PROTOCOL:
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
DEBUGF("recv: unknown settings id=0x%02x\n", iv.settings_id);
|
DEBUGF("recv: unknown settings id=0x%02x\n", iv.settings_id);
|
||||||
@@ -5341,13 +5431,11 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
|
|||||||
|
|
||||||
if (iframe->sbuf.pos[3] != NGHTTP2_SETTINGS ||
|
if (iframe->sbuf.pos[3] != NGHTTP2_SETTINGS ||
|
||||||
(iframe->sbuf.pos[4] & NGHTTP2_FLAG_ACK)) {
|
(iframe->sbuf.pos[4] & NGHTTP2_FLAG_ACK)) {
|
||||||
|
|
||||||
iframe->state = NGHTTP2_IB_IGN_ALL;
|
|
||||||
|
|
||||||
rv = session_call_error_callback(
|
rv = session_call_error_callback(
|
||||||
session, "Remote peer returned unexpected data while we expected "
|
session, NGHTTP2_ERR_SETTINGS_EXPECTED,
|
||||||
"SETTINGS frame. Perhaps, peer does not support HTTP/2 "
|
"Remote peer returned unexpected data while we expected "
|
||||||
"properly.");
|
"SETTINGS frame. Perhaps, peer does not support HTTP/2 "
|
||||||
|
"properly.");
|
||||||
|
|
||||||
if (nghttp2_is_fatal(rv)) {
|
if (nghttp2_is_fatal(rv)) {
|
||||||
return rv;
|
return rv;
|
||||||
@@ -5389,10 +5477,6 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
|
|||||||
DEBUGF("recv: length is too large %zu > %u\n", iframe->frame.hd.length,
|
DEBUGF("recv: length is too large %zu > %u\n", iframe->frame.hd.length,
|
||||||
session->local_settings.max_frame_size);
|
session->local_settings.max_frame_size);
|
||||||
|
|
||||||
busy = 1;
|
|
||||||
|
|
||||||
iframe->state = NGHTTP2_IB_IGN_PAYLOAD;
|
|
||||||
|
|
||||||
rv = nghttp2_session_terminate_session_with_reason(
|
rv = nghttp2_session_terminate_session_with_reason(
|
||||||
session, NGHTTP2_FRAME_SIZE_ERROR, "too large frame size");
|
session, NGHTTP2_FRAME_SIZE_ERROR, "too large frame size");
|
||||||
|
|
||||||
@@ -5400,7 +5484,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
|
|||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
return (ssize_t)inlen;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (iframe->frame.hd.type) {
|
switch (iframe->frame.hd.type) {
|
||||||
@@ -5414,6 +5498,9 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
|
|||||||
busy = 1;
|
busy = 1;
|
||||||
|
|
||||||
rv = session_on_data_received_fail_fast(session);
|
rv = session_on_data_received_fail_fast(session);
|
||||||
|
if (iframe->state == NGHTTP2_IB_IGN_ALL) {
|
||||||
|
return (ssize_t)inlen;
|
||||||
|
}
|
||||||
if (rv == NGHTTP2_ERR_IGN_PAYLOAD) {
|
if (rv == NGHTTP2_ERR_IGN_PAYLOAD) {
|
||||||
DEBUGF("recv: DATA not allowed stream_id=%d\n",
|
DEBUGF("recv: DATA not allowed stream_id=%d\n",
|
||||||
iframe->frame.hd.stream_id);
|
iframe->frame.hd.stream_id);
|
||||||
@@ -5427,7 +5514,6 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
|
|||||||
|
|
||||||
rv = inbound_frame_handle_pad(iframe, &iframe->frame.hd);
|
rv = inbound_frame_handle_pad(iframe, &iframe->frame.hd);
|
||||||
if (rv < 0) {
|
if (rv < 0) {
|
||||||
iframe->state = NGHTTP2_IB_IGN_DATA;
|
|
||||||
rv = nghttp2_session_terminate_session_with_reason(
|
rv = nghttp2_session_terminate_session_with_reason(
|
||||||
session, NGHTTP2_PROTOCOL_ERROR,
|
session, NGHTTP2_PROTOCOL_ERROR,
|
||||||
"DATA: insufficient padding space");
|
"DATA: insufficient padding space");
|
||||||
@@ -5435,7 +5521,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
|
|||||||
if (nghttp2_is_fatal(rv)) {
|
if (nghttp2_is_fatal(rv)) {
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
break;
|
return (ssize_t)inlen;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rv == 1) {
|
if (rv == 1) {
|
||||||
@@ -5456,17 +5542,13 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
|
|||||||
|
|
||||||
rv = inbound_frame_handle_pad(iframe, &iframe->frame.hd);
|
rv = inbound_frame_handle_pad(iframe, &iframe->frame.hd);
|
||||||
if (rv < 0) {
|
if (rv < 0) {
|
||||||
busy = 1;
|
|
||||||
|
|
||||||
iframe->state = NGHTTP2_IB_IGN_PAYLOAD;
|
|
||||||
|
|
||||||
rv = nghttp2_session_terminate_session_with_reason(
|
rv = nghttp2_session_terminate_session_with_reason(
|
||||||
session, NGHTTP2_PROTOCOL_ERROR,
|
session, NGHTTP2_PROTOCOL_ERROR,
|
||||||
"HEADERS: insufficient padding space");
|
"HEADERS: insufficient padding space");
|
||||||
if (nghttp2_is_fatal(rv)) {
|
if (nghttp2_is_fatal(rv)) {
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
break;
|
return (ssize_t)inlen;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rv == 1) {
|
if (rv == 1) {
|
||||||
@@ -5508,6 +5590,10 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
|
|||||||
|
|
||||||
busy = 1;
|
busy = 1;
|
||||||
|
|
||||||
|
if (iframe->state == NGHTTP2_IB_IGN_ALL) {
|
||||||
|
return (ssize_t)inlen;
|
||||||
|
}
|
||||||
|
|
||||||
if (rv == NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE) {
|
if (rv == NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE) {
|
||||||
rv = nghttp2_session_add_rst_stream(
|
rv = nghttp2_session_add_rst_stream(
|
||||||
session, iframe->frame.hd.stream_id, NGHTTP2_INTERNAL_ERROR);
|
session, iframe->frame.hd.stream_id, NGHTTP2_INTERNAL_ERROR);
|
||||||
@@ -5588,13 +5674,13 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
|
|||||||
if (iframe->payloadleft) {
|
if (iframe->payloadleft) {
|
||||||
nghttp2_settings_entry *min_header_table_size_entry;
|
nghttp2_settings_entry *min_header_table_size_entry;
|
||||||
|
|
||||||
/* We allocate iv with addtional one entry, to store the
|
/* We allocate iv with additional one entry, to store the
|
||||||
minimum header table size. */
|
minimum header table size. */
|
||||||
iframe->max_niv =
|
iframe->max_niv =
|
||||||
iframe->frame.hd.length / NGHTTP2_FRAME_SETTINGS_ENTRY_LENGTH + 1;
|
iframe->frame.hd.length / NGHTTP2_FRAME_SETTINGS_ENTRY_LENGTH + 1;
|
||||||
|
|
||||||
iframe->iv = nghttp2_mem_malloc(
|
iframe->iv = nghttp2_mem_malloc(mem, sizeof(nghttp2_settings_entry) *
|
||||||
mem, sizeof(nghttp2_settings_entry) * iframe->max_niv);
|
iframe->max_niv);
|
||||||
|
|
||||||
if (!iframe->iv) {
|
if (!iframe->iv) {
|
||||||
return NGHTTP2_ERR_NOMEM;
|
return NGHTTP2_ERR_NOMEM;
|
||||||
@@ -5622,15 +5708,13 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
|
|||||||
|
|
||||||
rv = inbound_frame_handle_pad(iframe, &iframe->frame.hd);
|
rv = inbound_frame_handle_pad(iframe, &iframe->frame.hd);
|
||||||
if (rv < 0) {
|
if (rv < 0) {
|
||||||
busy = 1;
|
|
||||||
iframe->state = NGHTTP2_IB_IGN_PAYLOAD;
|
|
||||||
rv = nghttp2_session_terminate_session_with_reason(
|
rv = nghttp2_session_terminate_session_with_reason(
|
||||||
session, NGHTTP2_PROTOCOL_ERROR,
|
session, NGHTTP2_PROTOCOL_ERROR,
|
||||||
"PUSH_PROMISE: insufficient padding space");
|
"PUSH_PROMISE: insufficient padding space");
|
||||||
if (nghttp2_is_fatal(rv)) {
|
if (nghttp2_is_fatal(rv)) {
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
break;
|
return (ssize_t)inlen;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rv == 1) {
|
if (rv == 1) {
|
||||||
@@ -5690,11 +5774,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
|
|||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
busy = 1;
|
return (ssize_t)inlen;
|
||||||
|
|
||||||
iframe->state = NGHTTP2_IB_IGN_PAYLOAD;
|
|
||||||
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
DEBUGF("recv: extension frame\n");
|
DEBUGF("recv: extension frame\n");
|
||||||
|
|
||||||
@@ -5747,6 +5827,42 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
|
|||||||
iframe->state = NGHTTP2_IB_READ_NBYTE;
|
iframe->state = NGHTTP2_IB_READ_NBYTE;
|
||||||
inbound_frame_set_mark(iframe, 2);
|
inbound_frame_set_mark(iframe, 2);
|
||||||
|
|
||||||
|
break;
|
||||||
|
case NGHTTP2_ORIGIN:
|
||||||
|
if (!(session->builtin_recv_ext_types & NGHTTP2_TYPEMASK_ORIGIN)) {
|
||||||
|
busy = 1;
|
||||||
|
iframe->state = NGHTTP2_IB_IGN_PAYLOAD;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
DEBUGF("recv: ORIGIN\n");
|
||||||
|
|
||||||
|
iframe->frame.ext.payload = &iframe->ext_frame_payload.origin;
|
||||||
|
|
||||||
|
if (session->server || iframe->frame.hd.stream_id ||
|
||||||
|
(iframe->frame.hd.flags & 0xf0)) {
|
||||||
|
busy = 1;
|
||||||
|
iframe->state = NGHTTP2_IB_IGN_PAYLOAD;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
iframe->frame.hd.flags = NGHTTP2_FLAG_NONE;
|
||||||
|
|
||||||
|
if (iframe->payloadleft) {
|
||||||
|
iframe->raw_lbuf = nghttp2_mem_malloc(mem, iframe->payloadleft);
|
||||||
|
|
||||||
|
if (iframe->raw_lbuf == NULL) {
|
||||||
|
return NGHTTP2_ERR_NOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
nghttp2_buf_wrap_init(&iframe->lbuf, iframe->raw_lbuf,
|
||||||
|
iframe->payloadleft);
|
||||||
|
} else {
|
||||||
|
busy = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
iframe->state = NGHTTP2_IB_READ_ORIGIN_PAYLOAD;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
busy = 1;
|
busy = 1;
|
||||||
@@ -5764,6 +5880,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
|
|||||||
case NGHTTP2_IB_IGN_PAYLOAD:
|
case NGHTTP2_IB_IGN_PAYLOAD:
|
||||||
case NGHTTP2_IB_FRAME_SIZE_ERROR:
|
case NGHTTP2_IB_FRAME_SIZE_ERROR:
|
||||||
case NGHTTP2_IB_IGN_DATA:
|
case NGHTTP2_IB_IGN_DATA:
|
||||||
|
case NGHTTP2_IB_IGN_ALL:
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
rv = session_call_on_begin_frame(session, &iframe->frame.hd);
|
rv = session_call_on_begin_frame(session, &iframe->frame.hd);
|
||||||
@@ -5794,21 +5911,19 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
|
|||||||
case NGHTTP2_HEADERS:
|
case NGHTTP2_HEADERS:
|
||||||
if (iframe->padlen == 0 &&
|
if (iframe->padlen == 0 &&
|
||||||
(iframe->frame.hd.flags & NGHTTP2_FLAG_PADDED)) {
|
(iframe->frame.hd.flags & NGHTTP2_FLAG_PADDED)) {
|
||||||
|
pri_fieldlen = nghttp2_frame_priority_len(iframe->frame.hd.flags);
|
||||||
padlen = inbound_frame_compute_pad(iframe);
|
padlen = inbound_frame_compute_pad(iframe);
|
||||||
if (padlen < 0) {
|
if (padlen < 0 ||
|
||||||
busy = 1;
|
(size_t)padlen + pri_fieldlen > 1 + iframe->payloadleft) {
|
||||||
rv = nghttp2_session_terminate_session_with_reason(
|
rv = nghttp2_session_terminate_session_with_reason(
|
||||||
session, NGHTTP2_PROTOCOL_ERROR, "HEADERS: invalid padding");
|
session, NGHTTP2_PROTOCOL_ERROR, "HEADERS: invalid padding");
|
||||||
if (nghttp2_is_fatal(rv)) {
|
if (nghttp2_is_fatal(rv)) {
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
iframe->state = NGHTTP2_IB_IGN_PAYLOAD;
|
return (ssize_t)inlen;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
iframe->frame.headers.padlen = (size_t)padlen;
|
iframe->frame.headers.padlen = (size_t)padlen;
|
||||||
|
|
||||||
pri_fieldlen = nghttp2_frame_priority_len(iframe->frame.hd.flags);
|
|
||||||
|
|
||||||
if (pri_fieldlen > 0) {
|
if (pri_fieldlen > 0) {
|
||||||
if (iframe->payloadleft < pri_fieldlen) {
|
if (iframe->payloadleft < pri_fieldlen) {
|
||||||
busy = 1;
|
busy = 1;
|
||||||
@@ -5831,6 +5946,10 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
|
|||||||
|
|
||||||
busy = 1;
|
busy = 1;
|
||||||
|
|
||||||
|
if (iframe->state == NGHTTP2_IB_IGN_ALL) {
|
||||||
|
return (ssize_t)inlen;
|
||||||
|
}
|
||||||
|
|
||||||
if (rv == NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE) {
|
if (rv == NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE) {
|
||||||
rv = nghttp2_session_add_rst_stream(
|
rv = nghttp2_session_add_rst_stream(
|
||||||
session, iframe->frame.hd.stream_id, NGHTTP2_INTERNAL_ERROR);
|
session, iframe->frame.hd.stream_id, NGHTTP2_INTERNAL_ERROR);
|
||||||
@@ -5855,6 +5974,10 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
|
|||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (iframe->state == NGHTTP2_IB_IGN_ALL) {
|
||||||
|
return (ssize_t)inlen;
|
||||||
|
}
|
||||||
|
|
||||||
session_inbound_frame_reset(session);
|
session_inbound_frame_reset(session);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@@ -5864,6 +5987,10 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
|
|||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (iframe->state == NGHTTP2_IB_IGN_ALL) {
|
||||||
|
return (ssize_t)inlen;
|
||||||
|
}
|
||||||
|
|
||||||
session_inbound_frame_reset(session);
|
session_inbound_frame_reset(session);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@@ -5871,16 +5998,15 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
|
|||||||
if (iframe->padlen == 0 &&
|
if (iframe->padlen == 0 &&
|
||||||
(iframe->frame.hd.flags & NGHTTP2_FLAG_PADDED)) {
|
(iframe->frame.hd.flags & NGHTTP2_FLAG_PADDED)) {
|
||||||
padlen = inbound_frame_compute_pad(iframe);
|
padlen = inbound_frame_compute_pad(iframe);
|
||||||
if (padlen < 0) {
|
if (padlen < 0 || (size_t)padlen + 4 /* promised stream id */
|
||||||
busy = 1;
|
> 1 + iframe->payloadleft) {
|
||||||
rv = nghttp2_session_terminate_session_with_reason(
|
rv = nghttp2_session_terminate_session_with_reason(
|
||||||
session, NGHTTP2_PROTOCOL_ERROR,
|
session, NGHTTP2_PROTOCOL_ERROR,
|
||||||
"PUSH_PROMISE: invalid padding");
|
"PUSH_PROMISE: invalid padding");
|
||||||
if (nghttp2_is_fatal(rv)) {
|
if (nghttp2_is_fatal(rv)) {
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
iframe->state = NGHTTP2_IB_IGN_PAYLOAD;
|
return (ssize_t)inlen;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
iframe->frame.push_promise.padlen = (size_t)padlen;
|
iframe->frame.push_promise.padlen = (size_t)padlen;
|
||||||
@@ -5905,6 +6031,10 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
|
|||||||
|
|
||||||
busy = 1;
|
busy = 1;
|
||||||
|
|
||||||
|
if (iframe->state == NGHTTP2_IB_IGN_ALL) {
|
||||||
|
return (ssize_t)inlen;
|
||||||
|
}
|
||||||
|
|
||||||
if (rv == NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE) {
|
if (rv == NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE) {
|
||||||
rv = nghttp2_session_add_rst_stream(
|
rv = nghttp2_session_add_rst_stream(
|
||||||
session, iframe->frame.push_promise.promised_stream_id,
|
session, iframe->frame.push_promise.promised_stream_id,
|
||||||
@@ -5930,6 +6060,10 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
|
|||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (iframe->state == NGHTTP2_IB_IGN_ALL) {
|
||||||
|
return (ssize_t)inlen;
|
||||||
|
}
|
||||||
|
|
||||||
session_inbound_frame_reset(session);
|
session_inbound_frame_reset(session);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@@ -5961,6 +6095,10 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
|
|||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (iframe->state == NGHTTP2_IB_IGN_ALL) {
|
||||||
|
return (ssize_t)inlen;
|
||||||
|
}
|
||||||
|
|
||||||
session_inbound_frame_reset(session);
|
session_inbound_frame_reset(session);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@@ -6022,6 +6160,12 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
|
|||||||
|
|
||||||
data_readlen = inbound_frame_effective_readlen(
|
data_readlen = inbound_frame_effective_readlen(
|
||||||
iframe, iframe->payloadleft - readlen, readlen);
|
iframe, iframe->payloadleft - readlen, readlen);
|
||||||
|
|
||||||
|
if (data_readlen == -1) {
|
||||||
|
/* everything is padding */
|
||||||
|
data_readlen = 0;
|
||||||
|
}
|
||||||
|
|
||||||
trail_padlen = nghttp2_frame_trail_padlen(&iframe->frame, iframe->padlen);
|
trail_padlen = nghttp2_frame_trail_padlen(&iframe->frame, iframe->padlen);
|
||||||
|
|
||||||
final = (iframe->frame.hd.flags & NGHTTP2_FLAG_END_HEADERS) &&
|
final = (iframe->frame.hd.flags & NGHTTP2_FLAG_END_HEADERS) &&
|
||||||
@@ -6041,6 +6185,10 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
|
|||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (iframe->state == NGHTTP2_IB_IGN_ALL) {
|
||||||
|
return (ssize_t)inlen;
|
||||||
|
}
|
||||||
|
|
||||||
if (rv == NGHTTP2_ERR_PAUSE) {
|
if (rv == NGHTTP2_ERR_PAUSE) {
|
||||||
in += hd_proclen;
|
in += hd_proclen;
|
||||||
iframe->payloadleft -= hd_proclen;
|
iframe->payloadleft -= hd_proclen;
|
||||||
@@ -6150,11 +6298,9 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
|
|||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
busy = 1;
|
assert(iframe->state == NGHTTP2_IB_IGN_ALL);
|
||||||
|
|
||||||
iframe->state = NGHTTP2_IB_IGN_PAYLOAD;
|
return (ssize_t)inlen;
|
||||||
|
|
||||||
break;
|
|
||||||
case NGHTTP2_IB_READ_SETTINGS:
|
case NGHTTP2_IB_READ_SETTINGS:
|
||||||
DEBUGF("recv: [IB_READ_SETTINGS]\n");
|
DEBUGF("recv: [IB_READ_SETTINGS]\n");
|
||||||
|
|
||||||
@@ -6183,6 +6329,10 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
|
|||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (iframe->state == NGHTTP2_IB_IGN_ALL) {
|
||||||
|
return (ssize_t)inlen;
|
||||||
|
}
|
||||||
|
|
||||||
session_inbound_frame_reset(session);
|
session_inbound_frame_reset(session);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@@ -6213,6 +6363,10 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
|
|||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (iframe->state == NGHTTP2_IB_IGN_ALL) {
|
||||||
|
return (ssize_t)inlen;
|
||||||
|
}
|
||||||
|
|
||||||
session_inbound_frame_reset(session);
|
session_inbound_frame_reset(session);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@@ -6252,11 +6406,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
|
|||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
busy = 1;
|
return (ssize_t)inlen;
|
||||||
|
|
||||||
iframe->state = NGHTTP2_IB_IGN_PAYLOAD;
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* CONTINUATION won't bear NGHTTP2_PADDED flag */
|
/* CONTINUATION won't bear NGHTTP2_PADDED flag */
|
||||||
@@ -6300,6 +6450,10 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
|
|||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (iframe->state == NGHTTP2_IB_IGN_ALL) {
|
||||||
|
return (ssize_t)inlen;
|
||||||
|
}
|
||||||
|
|
||||||
/* Pad Length field is consumed immediately */
|
/* Pad Length field is consumed immediately */
|
||||||
rv =
|
rv =
|
||||||
nghttp2_session_consume(session, iframe->frame.hd.stream_id, readlen);
|
nghttp2_session_consume(session, iframe->frame.hd.stream_id, readlen);
|
||||||
@@ -6308,6 +6462,10 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
|
|||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (iframe->state == NGHTTP2_IB_IGN_ALL) {
|
||||||
|
return (ssize_t)inlen;
|
||||||
|
}
|
||||||
|
|
||||||
stream = nghttp2_session_get_stream(session, iframe->frame.hd.stream_id);
|
stream = nghttp2_session_get_stream(session, iframe->frame.hd.stream_id);
|
||||||
if (stream) {
|
if (stream) {
|
||||||
rv = session_update_recv_stream_window_size(
|
rv = session_update_recv_stream_window_size(
|
||||||
@@ -6328,8 +6486,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
|
|||||||
if (nghttp2_is_fatal(rv)) {
|
if (nghttp2_is_fatal(rv)) {
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
iframe->state = NGHTTP2_IB_IGN_DATA;
|
return (ssize_t)inlen;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
iframe->frame.data.padlen = (size_t)padlen;
|
iframe->frame.data.padlen = (size_t)padlen;
|
||||||
@@ -6363,6 +6520,10 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
|
|||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (iframe->state == NGHTTP2_IB_IGN_ALL) {
|
||||||
|
return (ssize_t)inlen;
|
||||||
|
}
|
||||||
|
|
||||||
rv = session_update_recv_stream_window_size(
|
rv = session_update_recv_stream_window_size(
|
||||||
session, stream, readlen,
|
session, stream, readlen,
|
||||||
iframe->payloadleft ||
|
iframe->payloadleft ||
|
||||||
@@ -6389,6 +6550,10 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
|
|||||||
if (nghttp2_is_fatal(rv)) {
|
if (nghttp2_is_fatal(rv)) {
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (iframe->state == NGHTTP2_IB_IGN_ALL) {
|
||||||
|
return (ssize_t)inlen;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DEBUGF("recv: data_readlen=%zd\n", data_readlen);
|
DEBUGF("recv: data_readlen=%zd\n", data_readlen);
|
||||||
@@ -6404,6 +6569,10 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
|
|||||||
if (nghttp2_is_fatal(rv)) {
|
if (nghttp2_is_fatal(rv)) {
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (iframe->state == NGHTTP2_IB_IGN_DATA) {
|
||||||
|
return (ssize_t)inlen;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rv = nghttp2_session_add_rst_stream(
|
rv = nghttp2_session_add_rst_stream(
|
||||||
@@ -6461,6 +6630,10 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
|
|||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (iframe->state == NGHTTP2_IB_IGN_ALL) {
|
||||||
|
return (ssize_t)inlen;
|
||||||
|
}
|
||||||
|
|
||||||
if (session->opt_flags & NGHTTP2_OPTMASK_NO_AUTO_WINDOW_UPDATE) {
|
if (session->opt_flags & NGHTTP2_OPTMASK_NO_AUTO_WINDOW_UPDATE) {
|
||||||
|
|
||||||
/* Ignored DATA is considered as "consumed" immediately. */
|
/* Ignored DATA is considered as "consumed" immediately. */
|
||||||
@@ -6469,6 +6642,10 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
|
|||||||
if (nghttp2_is_fatal(rv)) {
|
if (nghttp2_is_fatal(rv)) {
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (iframe->state == NGHTTP2_IB_IGN_ALL) {
|
||||||
|
return (ssize_t)inlen;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -6523,7 +6700,6 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
|
|||||||
DEBUGF("recv: [IB_READ_ALTSVC_PAYLOAD]\n");
|
DEBUGF("recv: [IB_READ_ALTSVC_PAYLOAD]\n");
|
||||||
|
|
||||||
readlen = inbound_frame_payload_readlen(iframe, in, last);
|
readlen = inbound_frame_payload_readlen(iframe, in, last);
|
||||||
|
|
||||||
if (readlen > 0) {
|
if (readlen > 0) {
|
||||||
iframe->lbuf.last = nghttp2_cpymem(iframe->lbuf.last, in, readlen);
|
iframe->lbuf.last = nghttp2_cpymem(iframe->lbuf.last, in, readlen);
|
||||||
|
|
||||||
@@ -6541,11 +6717,44 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
|
|||||||
}
|
}
|
||||||
|
|
||||||
rv = session_process_altsvc_frame(session);
|
rv = session_process_altsvc_frame(session);
|
||||||
|
if (nghttp2_is_fatal(rv)) {
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
session_inbound_frame_reset(session);
|
||||||
|
|
||||||
|
break;
|
||||||
|
case NGHTTP2_IB_READ_ORIGIN_PAYLOAD:
|
||||||
|
DEBUGF("recv: [IB_READ_ORIGIN_PAYLOAD]\n");
|
||||||
|
|
||||||
|
readlen = inbound_frame_payload_readlen(iframe, in, last);
|
||||||
|
|
||||||
|
if (readlen > 0) {
|
||||||
|
iframe->lbuf.last = nghttp2_cpymem(iframe->lbuf.last, in, readlen);
|
||||||
|
|
||||||
|
iframe->payloadleft -= readlen;
|
||||||
|
in += readlen;
|
||||||
|
}
|
||||||
|
|
||||||
|
DEBUGF("recv: readlen=%zu, payloadleft=%zu\n", readlen,
|
||||||
|
iframe->payloadleft);
|
||||||
|
|
||||||
|
if (iframe->payloadleft) {
|
||||||
|
assert(nghttp2_buf_avail(&iframe->lbuf) > 0);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
rv = session_process_origin_frame(session);
|
||||||
|
|
||||||
if (nghttp2_is_fatal(rv)) {
|
if (nghttp2_is_fatal(rv)) {
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (iframe->state == NGHTTP2_IB_IGN_ALL) {
|
||||||
|
return (ssize_t)inlen;
|
||||||
|
}
|
||||||
|
|
||||||
session_inbound_frame_reset(session);
|
session_inbound_frame_reset(session);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@@ -6869,6 +7078,13 @@ int nghttp2_session_add_settings(nghttp2_session *session, uint8_t flags,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (i = niv; i > 0; --i) {
|
||||||
|
if (iv[i - 1].settings_id == NGHTTP2_SETTINGS_ENABLE_CONNECT_PROTOCOL) {
|
||||||
|
session->pending_enable_connect_protocol = (uint8_t)iv[i - 1].value;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -7025,12 +7241,42 @@ int nghttp2_session_set_stream_user_data(nghttp2_session *session,
|
|||||||
int32_t stream_id,
|
int32_t stream_id,
|
||||||
void *stream_user_data) {
|
void *stream_user_data) {
|
||||||
nghttp2_stream *stream;
|
nghttp2_stream *stream;
|
||||||
|
nghttp2_frame *frame;
|
||||||
|
nghttp2_outbound_item *item;
|
||||||
|
|
||||||
stream = nghttp2_session_get_stream(session, stream_id);
|
stream = nghttp2_session_get_stream(session, stream_id);
|
||||||
if (!stream) {
|
if (stream) {
|
||||||
|
stream->stream_user_data = stream_user_data;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (session->server || !nghttp2_session_is_my_stream_id(session, stream_id) ||
|
||||||
|
!nghttp2_outbound_queue_top(&session->ob_syn)) {
|
||||||
return NGHTTP2_ERR_INVALID_ARGUMENT;
|
return NGHTTP2_ERR_INVALID_ARGUMENT;
|
||||||
}
|
}
|
||||||
stream->stream_user_data = stream_user_data;
|
|
||||||
return 0;
|
frame = &nghttp2_outbound_queue_top(&session->ob_syn)->frame;
|
||||||
|
assert(frame->hd.type == NGHTTP2_HEADERS);
|
||||||
|
|
||||||
|
if (frame->hd.stream_id > stream_id ||
|
||||||
|
(uint32_t)stream_id >= session->next_stream_id) {
|
||||||
|
return NGHTTP2_ERR_INVALID_ARGUMENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (item = session->ob_syn.head; item; item = item->qnext) {
|
||||||
|
if (item->frame.hd.stream_id < stream_id) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (item->frame.hd.stream_id > stream_id) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
item->aux_data.headers.stream_user_data = stream_user_data;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NGHTTP2_ERR_INVALID_ARGUMENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
int nghttp2_session_resume_data(nghttp2_session *session, int32_t stream_id) {
|
int nghttp2_session_resume_data(nghttp2_session *session, int32_t stream_id) {
|
||||||
@@ -7147,6 +7393,8 @@ uint32_t nghttp2_session_get_remote_settings(nghttp2_session *session,
|
|||||||
return session->remote_settings.max_frame_size;
|
return session->remote_settings.max_frame_size;
|
||||||
case NGHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE:
|
case NGHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE:
|
||||||
return session->remote_settings.max_header_list_size;
|
return session->remote_settings.max_header_list_size;
|
||||||
|
case NGHTTP2_SETTINGS_ENABLE_CONNECT_PROTOCOL:
|
||||||
|
return session->remote_settings.enable_connect_protocol;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(0);
|
assert(0);
|
||||||
@@ -7168,6 +7416,8 @@ uint32_t nghttp2_session_get_local_settings(nghttp2_session *session,
|
|||||||
return session->local_settings.max_frame_size;
|
return session->local_settings.max_frame_size;
|
||||||
case NGHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE:
|
case NGHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE:
|
||||||
return session->local_settings.max_header_list_size;
|
return session->local_settings.max_header_list_size;
|
||||||
|
case NGHTTP2_SETTINGS_ENABLE_CONNECT_PROTOCOL:
|
||||||
|
return session->local_settings.enable_connect_protocol;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(0);
|
assert(0);
|
||||||
@@ -7515,3 +7765,7 @@ size_t
|
|||||||
nghttp2_session_get_hd_deflate_dynamic_table_size(nghttp2_session *session) {
|
nghttp2_session_get_hd_deflate_dynamic_table_size(nghttp2_session *session) {
|
||||||
return nghttp2_hd_deflate_get_dynamic_table_size(&session->hd_deflater);
|
return nghttp2_hd_deflate_get_dynamic_table_size(&session->hd_deflater);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void nghttp2_session_set_user_data(nghttp2_session *session, void *user_data) {
|
||||||
|
session->user_data = user_data;
|
||||||
|
}
|
||||||
|
|||||||
@@ -26,7 +26,7 @@
|
|||||||
#define NGHTTP2_SESSION_H
|
#define NGHTTP2_SESSION_H
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
#include <config.h>
|
# include <config.h>
|
||||||
#endif /* HAVE_CONFIG_H */
|
#endif /* HAVE_CONFIG_H */
|
||||||
|
|
||||||
#include <nghttp2/nghttp2.h>
|
#include <nghttp2/nghttp2.h>
|
||||||
@@ -61,7 +61,8 @@ typedef enum {
|
|||||||
*/
|
*/
|
||||||
typedef enum {
|
typedef enum {
|
||||||
NGHTTP2_TYPEMASK_NONE = 0,
|
NGHTTP2_TYPEMASK_NONE = 0,
|
||||||
NGHTTP2_TYPEMASK_ALTSVC = 1 << 0
|
NGHTTP2_TYPEMASK_ALTSVC = 1 << 0,
|
||||||
|
NGHTTP2_TYPEMASK_ORIGIN = 1 << 1
|
||||||
} nghttp2_typemask;
|
} nghttp2_typemask;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
@@ -121,6 +122,7 @@ typedef enum {
|
|||||||
NGHTTP2_IB_IGN_DATA,
|
NGHTTP2_IB_IGN_DATA,
|
||||||
NGHTTP2_IB_IGN_ALL,
|
NGHTTP2_IB_IGN_ALL,
|
||||||
NGHTTP2_IB_READ_ALTSVC_PAYLOAD,
|
NGHTTP2_IB_READ_ALTSVC_PAYLOAD,
|
||||||
|
NGHTTP2_IB_READ_ORIGIN_PAYLOAD,
|
||||||
NGHTTP2_IB_READ_EXTENSION_PAYLOAD
|
NGHTTP2_IB_READ_EXTENSION_PAYLOAD
|
||||||
} nghttp2_inbound_state;
|
} nghttp2_inbound_state;
|
||||||
|
|
||||||
@@ -162,6 +164,7 @@ typedef struct {
|
|||||||
uint32_t initial_window_size;
|
uint32_t initial_window_size;
|
||||||
uint32_t max_frame_size;
|
uint32_t max_frame_size;
|
||||||
uint32_t max_header_list_size;
|
uint32_t max_header_list_size;
|
||||||
|
uint32_t enable_connect_protocol;
|
||||||
} nghttp2_settings_storage;
|
} nghttp2_settings_storage;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
@@ -206,9 +209,6 @@ struct nghttp2_session {
|
|||||||
nghttp2_session_callbacks callbacks;
|
nghttp2_session_callbacks callbacks;
|
||||||
/* Memory allocator */
|
/* Memory allocator */
|
||||||
nghttp2_mem mem;
|
nghttp2_mem mem;
|
||||||
/* Base value when we schedule next DATA frame write. This is
|
|
||||||
updated when one frame was written. */
|
|
||||||
uint64_t last_cycle;
|
|
||||||
void *user_data;
|
void *user_data;
|
||||||
/* Points to the latest incoming closed stream. NULL if there is no
|
/* Points to the latest incoming closed stream. NULL if there is no
|
||||||
closed stream. Only used when session is initialized as
|
closed stream. Only used when session is initialized as
|
||||||
@@ -301,8 +301,10 @@ struct nghttp2_session {
|
|||||||
increased/decreased by submitting WINDOW_UPDATE. See
|
increased/decreased by submitting WINDOW_UPDATE. See
|
||||||
nghttp2_submit_window_update(). */
|
nghttp2_submit_window_update(). */
|
||||||
int32_t local_window_size;
|
int32_t local_window_size;
|
||||||
/* Settings value received from the remote endpoint. We just use ID
|
/* This flag is used to indicate that the local endpoint received initial
|
||||||
as index. The index = 0 is unused. */
|
SETTINGS frame from the remote endpoint. */
|
||||||
|
uint8_t remote_settings_received;
|
||||||
|
/* Settings value received from the remote endpoint. */
|
||||||
nghttp2_settings_storage remote_settings;
|
nghttp2_settings_storage remote_settings;
|
||||||
/* Settings value of the local endpoint. */
|
/* Settings value of the local endpoint. */
|
||||||
nghttp2_settings_storage local_settings;
|
nghttp2_settings_storage local_settings;
|
||||||
@@ -311,15 +313,18 @@ struct nghttp2_session {
|
|||||||
/* Unacked local SETTINGS_MAX_CONCURRENT_STREAMS value. We use this
|
/* Unacked local SETTINGS_MAX_CONCURRENT_STREAMS value. We use this
|
||||||
to refuse the incoming stream if it exceeds this value. */
|
to refuse the incoming stream if it exceeds this value. */
|
||||||
uint32_t pending_local_max_concurrent_stream;
|
uint32_t pending_local_max_concurrent_stream;
|
||||||
/* The bitwose OR of zero or more of nghttp2_typemask to indicate
|
/* The bitwise OR of zero or more of nghttp2_typemask to indicate
|
||||||
that the default handling of extension frame is enabled. */
|
that the default handling of extension frame is enabled. */
|
||||||
uint32_t builtin_recv_ext_types;
|
uint32_t builtin_recv_ext_types;
|
||||||
/* Unacked local ENABLE_PUSH value. We use this to refuse
|
/* Unacked local ENABLE_PUSH value. We use this to refuse
|
||||||
PUSH_PROMISE before SETTINGS ACK is received. */
|
PUSH_PROMISE before SETTINGS ACK is received. */
|
||||||
uint8_t pending_enable_push;
|
uint8_t pending_enable_push;
|
||||||
|
/* Unacked local ENABLE_CONNECT_PROTOCOL value. We use this to
|
||||||
|
accept :protocol header field before SETTINGS_ACK is received. */
|
||||||
|
uint8_t pending_enable_connect_protocol;
|
||||||
/* 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 recieved. The flags are
|
/* Flags indicating GOAWAY is sent and/or received. The flags are
|
||||||
composed by bitwise OR-ing nghttp2_goaway_flag. */
|
composed by bitwise OR-ing nghttp2_goaway_flag. */
|
||||||
uint8_t goaway_flags;
|
uint8_t goaway_flags;
|
||||||
/* This flag is used to reduce excessive queuing of WINDOW_UPDATE to
|
/* This flag is used to reduce excessive queuing of WINDOW_UPDATE to
|
||||||
@@ -698,7 +703,7 @@ int nghttp2_session_on_push_promise_received(nghttp2_session *session,
|
|||||||
* NGHTTP2_ERR_NOMEM
|
* NGHTTP2_ERR_NOMEM
|
||||||
* Out of memory.
|
* Out of memory.
|
||||||
* NGHTTP2_ERR_CALLBACK_FAILURE
|
* NGHTTP2_ERR_CALLBACK_FAILURE
|
||||||
* The callback function failed.
|
* The callback function failed.
|
||||||
* NGHTTP2_ERR_FLOODED
|
* NGHTTP2_ERR_FLOODED
|
||||||
* There are too many items in outbound queue, and this is most
|
* There are too many items in outbound queue, and this is most
|
||||||
* likely caused by misbehaviour of peer.
|
* likely caused by misbehaviour of peer.
|
||||||
@@ -716,13 +721,13 @@ int nghttp2_session_on_ping_received(nghttp2_session *session,
|
|||||||
* NGHTTP2_ERR_NOMEM
|
* NGHTTP2_ERR_NOMEM
|
||||||
* Out of memory.
|
* Out of memory.
|
||||||
* NGHTTP2_ERR_CALLBACK_FAILURE
|
* NGHTTP2_ERR_CALLBACK_FAILURE
|
||||||
* The callback function failed.
|
* The callback function failed.
|
||||||
*/
|
*/
|
||||||
int nghttp2_session_on_goaway_received(nghttp2_session *session,
|
int nghttp2_session_on_goaway_received(nghttp2_session *session,
|
||||||
nghttp2_frame *frame);
|
nghttp2_frame *frame);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Called when WINDOW_UPDATE is recieved, assuming |frame| is properly
|
* Called when WINDOW_UPDATE is received, assuming |frame| is properly
|
||||||
* initialized.
|
* initialized.
|
||||||
*
|
*
|
||||||
* This function returns 0 if it succeeds, or one of the following
|
* This function returns 0 if it succeeds, or one of the following
|
||||||
@@ -731,24 +736,37 @@ int nghttp2_session_on_goaway_received(nghttp2_session *session,
|
|||||||
* NGHTTP2_ERR_NOMEM
|
* NGHTTP2_ERR_NOMEM
|
||||||
* Out of memory.
|
* Out of memory.
|
||||||
* NGHTTP2_ERR_CALLBACK_FAILURE
|
* NGHTTP2_ERR_CALLBACK_FAILURE
|
||||||
* The callback function failed.
|
* The callback function failed.
|
||||||
*/
|
*/
|
||||||
int nghttp2_session_on_window_update_received(nghttp2_session *session,
|
int nghttp2_session_on_window_update_received(nghttp2_session *session,
|
||||||
nghttp2_frame *frame);
|
nghttp2_frame *frame);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Called when ALTSVC is recieved, assuming |frame| is properly
|
* Called when ALTSVC is received, assuming |frame| is properly
|
||||||
* initialized.
|
* initialized.
|
||||||
*
|
*
|
||||||
* 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_CALLBACK_FAILURE
|
* NGHTTP2_ERR_CALLBACK_FAILURE
|
||||||
* The callback function failed.
|
* The callback function failed.
|
||||||
*/
|
*/
|
||||||
int nghttp2_session_on_altsvc_received(nghttp2_session *session,
|
int nghttp2_session_on_altsvc_received(nghttp2_session *session,
|
||||||
nghttp2_frame *frame);
|
nghttp2_frame *frame);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Called when ORIGIN is received, assuming |frame| is properly
|
||||||
|
* initialized.
|
||||||
|
*
|
||||||
|
* This function returns 0 if it succeeds, or one of the following
|
||||||
|
* negative error codes:
|
||||||
|
*
|
||||||
|
* NGHTTP2_ERR_CALLBACK_FAILURE
|
||||||
|
* The callback function failed.
|
||||||
|
*/
|
||||||
|
int nghttp2_session_on_origin_received(nghttp2_session *session,
|
||||||
|
nghttp2_frame *frame);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Called when DATA is received, assuming |frame| is properly
|
* Called when DATA is received, assuming |frame| is properly
|
||||||
* initialized.
|
* initialized.
|
||||||
@@ -759,7 +777,7 @@ int nghttp2_session_on_altsvc_received(nghttp2_session *session,
|
|||||||
* NGHTTP2_ERR_NOMEM
|
* NGHTTP2_ERR_NOMEM
|
||||||
* Out of memory.
|
* Out of memory.
|
||||||
* NGHTTP2_ERR_CALLBACK_FAILURE
|
* NGHTTP2_ERR_CALLBACK_FAILURE
|
||||||
* The callback function failed.
|
* The callback function failed.
|
||||||
*/
|
*/
|
||||||
int nghttp2_session_on_data_received(nghttp2_session *session,
|
int nghttp2_session_on_data_received(nghttp2_session *session,
|
||||||
nghttp2_frame *frame);
|
nghttp2_frame *frame);
|
||||||
|
|||||||
@@ -30,6 +30,7 @@
|
|||||||
#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"
|
||||||
|
|
||||||
/* Maximum distance between any two stream's cycle in the same
|
/* Maximum distance between any two stream's cycle in the same
|
||||||
prirority queue. Imagine stream A's cycle is A, and stream B's
|
prirority queue. Imagine stream A's cycle is A, and stream B's
|
||||||
@@ -40,7 +41,8 @@
|
|||||||
words, B is really greater than or equal to A. Otherwise, A is a
|
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
|
result of overflow, and it is actually A > B if we consider that
|
||||||
fact. */
|
fact. */
|
||||||
#define NGHTTP2_MAX_CYCLE_DISTANCE (16384 * 256 + 255)
|
#define NGHTTP2_MAX_CYCLE_DISTANCE \
|
||||||
|
((uint64_t)NGHTTP2_MAX_FRAME_SIZE_MAX * 256 + 255)
|
||||||
|
|
||||||
static int stream_less(const void *lhsx, const void *rhsx) {
|
static int stream_less(const void *lhsx, const void *rhsx) {
|
||||||
const nghttp2_stream *lhs, *rhs;
|
const nghttp2_stream *lhs, *rhs;
|
||||||
@@ -52,11 +54,7 @@ static int stream_less(const void *lhsx, const void *rhsx) {
|
|||||||
return lhs->seq < rhs->seq;
|
return lhs->seq < rhs->seq;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lhs->cycle < rhs->cycle) {
|
return rhs->cycle - lhs->cycle <= NGHTTP2_MAX_CYCLE_DISTANCE;
|
||||||
return rhs->cycle - lhs->cycle <= NGHTTP2_MAX_CYCLE_DISTANCE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return lhs->cycle - rhs->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,
|
||||||
@@ -135,14 +133,14 @@ static int stream_subtree_active(nghttp2_stream *stream) {
|
|||||||
/*
|
/*
|
||||||
* Returns next cycle for |stream|.
|
* Returns next cycle for |stream|.
|
||||||
*/
|
*/
|
||||||
static void stream_next_cycle(nghttp2_stream *stream, uint32_t last_cycle) {
|
static void stream_next_cycle(nghttp2_stream *stream, uint64_t last_cycle) {
|
||||||
uint32_t penalty;
|
uint64_t penalty;
|
||||||
|
|
||||||
penalty = (uint32_t)stream->last_writelen * NGHTTP2_MAX_WEIGHT +
|
penalty = (uint64_t)stream->last_writelen * NGHTTP2_MAX_WEIGHT +
|
||||||
stream->pending_penalty;
|
stream->pending_penalty;
|
||||||
|
|
||||||
stream->cycle = last_cycle + penalty / (uint32_t)stream->weight;
|
stream->cycle = last_cycle + penalty / (uint32_t)stream->weight;
|
||||||
stream->pending_penalty = 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) {
|
static int stream_obq_push(nghttp2_stream *dep_stream, nghttp2_stream *stream) {
|
||||||
@@ -153,7 +151,7 @@ static int stream_obq_push(nghttp2_stream *dep_stream, nghttp2_stream *stream) {
|
|||||||
stream_next_cycle(stream, dep_stream->descendant_last_cycle);
|
stream_next_cycle(stream, dep_stream->descendant_last_cycle);
|
||||||
stream->seq = dep_stream->descendant_next_seq++;
|
stream->seq = dep_stream->descendant_next_seq++;
|
||||||
|
|
||||||
DEBUGF("stream: stream=%d obq push cycle=%d\n", stream->stream_id,
|
DEBUGF("stream: stream=%d obq push cycle=%lu\n", stream->stream_id,
|
||||||
stream->cycle);
|
stream->cycle);
|
||||||
|
|
||||||
DEBUGF("stream: push stream %d to stream %d\n", stream->stream_id,
|
DEBUGF("stream: push stream %d to stream %d\n", stream->stream_id,
|
||||||
@@ -239,7 +237,7 @@ void nghttp2_stream_reschedule(nghttp2_stream *stream) {
|
|||||||
|
|
||||||
nghttp2_pq_push(&dep_stream->obq, &stream->pq_entry);
|
nghttp2_pq_push(&dep_stream->obq, &stream->pq_entry);
|
||||||
|
|
||||||
DEBUGF("stream: stream=%d obq resched cycle=%d\n", stream->stream_id,
|
DEBUGF("stream: stream=%d obq resched cycle=%lu\n", stream->stream_id,
|
||||||
stream->cycle);
|
stream->cycle);
|
||||||
|
|
||||||
dep_stream->last_writelen = stream->last_writelen;
|
dep_stream->last_writelen = stream->last_writelen;
|
||||||
@@ -248,9 +246,9 @@ void nghttp2_stream_reschedule(nghttp2_stream *stream) {
|
|||||||
|
|
||||||
void nghttp2_stream_change_weight(nghttp2_stream *stream, int32_t weight) {
|
void nghttp2_stream_change_weight(nghttp2_stream *stream, int32_t weight) {
|
||||||
nghttp2_stream *dep_stream;
|
nghttp2_stream *dep_stream;
|
||||||
uint32_t last_cycle;
|
uint64_t last_cycle;
|
||||||
int32_t old_weight;
|
int32_t old_weight;
|
||||||
uint32_t wlen_penalty;
|
uint64_t wlen_penalty;
|
||||||
|
|
||||||
if (stream->weight == weight) {
|
if (stream->weight == weight) {
|
||||||
return;
|
return;
|
||||||
@@ -273,7 +271,7 @@ void nghttp2_stream_change_weight(nghttp2_stream *stream, int32_t weight) {
|
|||||||
|
|
||||||
nghttp2_pq_remove(&dep_stream->obq, &stream->pq_entry);
|
nghttp2_pq_remove(&dep_stream->obq, &stream->pq_entry);
|
||||||
|
|
||||||
wlen_penalty = (uint32_t)stream->last_writelen * NGHTTP2_MAX_WEIGHT;
|
wlen_penalty = (uint64_t)stream->last_writelen * NGHTTP2_MAX_WEIGHT;
|
||||||
|
|
||||||
/* Compute old stream->pending_penalty we used to calculate
|
/* Compute old stream->pending_penalty we used to calculate
|
||||||
stream->cycle */
|
stream->cycle */
|
||||||
@@ -289,9 +287,8 @@ void nghttp2_stream_change_weight(nghttp2_stream *stream, int32_t weight) {
|
|||||||
place */
|
place */
|
||||||
stream_next_cycle(stream, last_cycle);
|
stream_next_cycle(stream, last_cycle);
|
||||||
|
|
||||||
if (stream->cycle < dep_stream->descendant_last_cycle &&
|
if (dep_stream->descendant_last_cycle - stream->cycle <=
|
||||||
(dep_stream->descendant_last_cycle - stream->cycle) <=
|
NGHTTP2_MAX_CYCLE_DISTANCE) {
|
||||||
NGHTTP2_MAX_CYCLE_DISTANCE) {
|
|
||||||
stream->cycle = dep_stream->descendant_last_cycle;
|
stream->cycle = dep_stream->descendant_last_cycle;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -299,7 +296,7 @@ void nghttp2_stream_change_weight(nghttp2_stream *stream, int32_t weight) {
|
|||||||
|
|
||||||
nghttp2_pq_push(&dep_stream->obq, &stream->pq_entry);
|
nghttp2_pq_push(&dep_stream->obq, &stream->pq_entry);
|
||||||
|
|
||||||
DEBUGF("stream: stream=%d obq resched cycle=%d\n", stream->stream_id,
|
DEBUGF("stream: stream=%d obq resched cycle=%lu\n", stream->stream_id,
|
||||||
stream->cycle);
|
stream->cycle);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -366,8 +363,9 @@ static void check_queued(nghttp2_stream *stream) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (queued == 0) {
|
if (queued == 0) {
|
||||||
fprintf(stderr, "stream(%p)=%d, stream->queued == 1, and "
|
fprintf(stderr,
|
||||||
"!stream_active(), but no descendants is queued\n",
|
"stream(%p)=%d, stream->queued == 1, and "
|
||||||
|
"!stream_active(), but no descendants is queued\n",
|
||||||
stream, stream->stream_id);
|
stream, stream->stream_id);
|
||||||
assert(0);
|
assert(0);
|
||||||
}
|
}
|
||||||
@@ -378,9 +376,10 @@ static void check_queued(nghttp2_stream *stream) {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (stream_active(stream) || !nghttp2_pq_empty(&stream->obq)) {
|
if (stream_active(stream) || !nghttp2_pq_empty(&stream->obq)) {
|
||||||
fprintf(stderr, "stream(%p) = %d, stream->queued == 0, but "
|
fprintf(stderr,
|
||||||
"stream_active(stream) == %d and "
|
"stream(%p) = %d, stream->queued == 0, but "
|
||||||
"nghttp2_pq_size(&stream->obq) = %zu\n",
|
"stream_active(stream) == %d and "
|
||||||
|
"nghttp2_pq_size(&stream->obq) = %zu\n",
|
||||||
stream, stream->stream_id, stream_active(stream),
|
stream, stream->stream_id, stream_active(stream),
|
||||||
nghttp2_pq_size(&stream->obq));
|
nghttp2_pq_size(&stream->obq));
|
||||||
assert(0);
|
assert(0);
|
||||||
|
|||||||
@@ -26,7 +26,7 @@
|
|||||||
#define NGHTTP2_STREAM_H
|
#define NGHTTP2_STREAM_H
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
#include <config.h>
|
# include <config.h>
|
||||||
#endif /* HAVE_CONFIG_H */
|
#endif /* HAVE_CONFIG_H */
|
||||||
|
|
||||||
#include <nghttp2/nghttp2.h>
|
#include <nghttp2/nghttp2.h>
|
||||||
@@ -130,7 +130,8 @@ typedef enum {
|
|||||||
/* "http" or "https" scheme */
|
/* "http" or "https" scheme */
|
||||||
NGHTTP2_HTTP_FLAG_SCHEME_HTTP = 1 << 13,
|
NGHTTP2_HTTP_FLAG_SCHEME_HTTP = 1 << 13,
|
||||||
/* set if final response is expected */
|
/* set if final response is expected */
|
||||||
NGHTTP2_HTTP_FLAG_EXPECT_FINAL_RESPONSE = 1 << 14
|
NGHTTP2_HTTP_FLAG_EXPECT_FINAL_RESPONSE = 1 << 14,
|
||||||
|
NGHTTP2_HTTP_FLAG__PROTOCOL = 1 << 15,
|
||||||
} nghttp2_http_flag;
|
} nghttp2_http_flag;
|
||||||
|
|
||||||
struct nghttp2_stream {
|
struct nghttp2_stream {
|
||||||
@@ -147,9 +148,9 @@ struct nghttp2_stream {
|
|||||||
/* 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. */
|
/* Base last_cycle for direct descendent streams. */
|
||||||
uint32_t descendant_last_cycle;
|
uint64_t descendant_last_cycle;
|
||||||
/* Next scheduled time to sent item */
|
/* Next scheduled time to sent item */
|
||||||
uint32_t cycle;
|
uint64_t cycle;
|
||||||
/* Next seq used for direct descendant streams */
|
/* Next seq used for direct descendant streams */
|
||||||
uint64_t descendant_next_seq;
|
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
|
||||||
|
|||||||
@@ -571,6 +571,89 @@ fail_item_malloc:
|
|||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int nghttp2_submit_origin(nghttp2_session *session, uint8_t flags,
|
||||||
|
const nghttp2_origin_entry *ov, size_t nov) {
|
||||||
|
nghttp2_mem *mem;
|
||||||
|
uint8_t *p;
|
||||||
|
nghttp2_outbound_item *item;
|
||||||
|
nghttp2_frame *frame;
|
||||||
|
nghttp2_ext_origin *origin;
|
||||||
|
nghttp2_origin_entry *ov_copy;
|
||||||
|
size_t len = 0;
|
||||||
|
size_t i;
|
||||||
|
int rv;
|
||||||
|
(void)flags;
|
||||||
|
|
||||||
|
mem = &session->mem;
|
||||||
|
|
||||||
|
if (!session->server) {
|
||||||
|
return NGHTTP2_ERR_INVALID_STATE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nov) {
|
||||||
|
for (i = 0; i < nov; ++i) {
|
||||||
|
len += ov[i].origin_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (2 * nov + len > NGHTTP2_MAX_PAYLOADLEN) {
|
||||||
|
return NGHTTP2_ERR_INVALID_ARGUMENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The last nov is added for terminal NULL character. */
|
||||||
|
ov_copy =
|
||||||
|
nghttp2_mem_malloc(mem, nov * sizeof(nghttp2_origin_entry) + len + nov);
|
||||||
|
if (ov_copy == NULL) {
|
||||||
|
return NGHTTP2_ERR_NOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
p = (uint8_t *)ov_copy + nov * sizeof(nghttp2_origin_entry);
|
||||||
|
|
||||||
|
for (i = 0; i < nov; ++i) {
|
||||||
|
ov_copy[i].origin = p;
|
||||||
|
ov_copy[i].origin_len = ov[i].origin_len;
|
||||||
|
p = nghttp2_cpymem(p, ov[i].origin, ov[i].origin_len);
|
||||||
|
*p++ = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
assert((size_t)(p - (uint8_t *)ov_copy) ==
|
||||||
|
nov * sizeof(nghttp2_origin_entry) + len + nov);
|
||||||
|
} else {
|
||||||
|
ov_copy = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
item = nghttp2_mem_malloc(mem, sizeof(nghttp2_outbound_item));
|
||||||
|
if (item == NULL) {
|
||||||
|
rv = NGHTTP2_ERR_NOMEM;
|
||||||
|
goto fail_item_malloc;
|
||||||
|
}
|
||||||
|
|
||||||
|
nghttp2_outbound_item_init(item);
|
||||||
|
|
||||||
|
item->aux_data.ext.builtin = 1;
|
||||||
|
|
||||||
|
origin = &item->ext_frame_payload.origin;
|
||||||
|
|
||||||
|
frame = &item->frame;
|
||||||
|
frame->ext.payload = origin;
|
||||||
|
|
||||||
|
nghttp2_frame_origin_init(&frame->ext, ov_copy, nov);
|
||||||
|
|
||||||
|
rv = nghttp2_session_add_item(session, item);
|
||||||
|
if (rv != 0) {
|
||||||
|
nghttp2_frame_origin_free(&frame->ext, mem);
|
||||||
|
nghttp2_mem_free(mem, item);
|
||||||
|
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
fail_item_malloc:
|
||||||
|
free(ov_copy);
|
||||||
|
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
static uint8_t set_request_flags(const nghttp2_priority_spec *pri_spec,
|
static uint8_t set_request_flags(const nghttp2_priority_spec *pri_spec,
|
||||||
const nghttp2_data_provider *data_prd) {
|
const nghttp2_data_provider *data_prd) {
|
||||||
uint8_t flags = NGHTTP2_FLAG_NONE;
|
uint8_t flags = NGHTTP2_FLAG_NONE;
|
||||||
|
|||||||
@@ -26,7 +26,7 @@
|
|||||||
#define NGHTTP2_SUBMIT_H
|
#define NGHTTP2_SUBMIT_H
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
#include <config.h>
|
# include <config.h>
|
||||||
#endif /* HAVE_CONFIG_H */
|
#endif /* HAVE_CONFIG_H */
|
||||||
|
|
||||||
#include <nghttp2/nghttp2.h>
|
#include <nghttp2/nghttp2.h>
|
||||||
|
|||||||
@@ -23,7 +23,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.
|
||||||
*/
|
*/
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
#include <config.h>
|
# include <config.h>
|
||||||
#endif /* HAVE_CONFIG_H */
|
#endif /* HAVE_CONFIG_H */
|
||||||
|
|
||||||
#include <nghttp2/nghttp2.h>
|
#include <nghttp2/nghttp2.h>
|
||||||
|
|||||||
948
m4/ax_cxx_compile_stdcxx.m4
Normal file
948
m4/ax_cxx_compile_stdcxx.m4
Normal file
@@ -0,0 +1,948 @@
|
|||||||
|
# ===========================================================================
|
||||||
|
# https://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx.html
|
||||||
|
# ===========================================================================
|
||||||
|
#
|
||||||
|
# SYNOPSIS
|
||||||
|
#
|
||||||
|
# AX_CXX_COMPILE_STDCXX(VERSION, [ext|noext], [mandatory|optional])
|
||||||
|
#
|
||||||
|
# DESCRIPTION
|
||||||
|
#
|
||||||
|
# Check for baseline language coverage in the compiler for the specified
|
||||||
|
# version of the C++ standard. If necessary, add switches to CXX and
|
||||||
|
# CXXCPP to enable support. VERSION may be '11' (for the C++11 standard)
|
||||||
|
# or '14' (for the C++14 standard).
|
||||||
|
#
|
||||||
|
# The second argument, if specified, indicates whether you insist on an
|
||||||
|
# extended mode (e.g. -std=gnu++11) or a strict conformance mode (e.g.
|
||||||
|
# -std=c++11). If neither is specified, you get whatever works, with
|
||||||
|
# preference for an extended mode.
|
||||||
|
#
|
||||||
|
# The third argument, if specified 'mandatory' or if left unspecified,
|
||||||
|
# indicates that baseline support for the specified C++ standard is
|
||||||
|
# required and that the macro should error out if no mode with that
|
||||||
|
# support is found. If specified 'optional', then configuration proceeds
|
||||||
|
# regardless, after defining HAVE_CXX${VERSION} if and only if a
|
||||||
|
# supporting mode is found.
|
||||||
|
#
|
||||||
|
# LICENSE
|
||||||
|
#
|
||||||
|
# Copyright (c) 2008 Benjamin Kosnik <bkoz@redhat.com>
|
||||||
|
# Copyright (c) 2012 Zack Weinberg <zackw@panix.com>
|
||||||
|
# Copyright (c) 2013 Roy Stogner <roystgnr@ices.utexas.edu>
|
||||||
|
# Copyright (c) 2014, 2015 Google Inc.; contributed by Alexey Sokolov <sokolov@google.com>
|
||||||
|
# Copyright (c) 2015 Paul Norman <penorman@mac.com>
|
||||||
|
# Copyright (c) 2015 Moritz Klammler <moritz@klammler.eu>
|
||||||
|
# Copyright (c) 2016, 2018 Krzesimir Nowak <qdlacz@gmail.com>
|
||||||
|
#
|
||||||
|
# Copying and distribution of this file, with or without modification, are
|
||||||
|
# permitted in any medium without royalty provided the copyright notice
|
||||||
|
# and this notice are preserved. This file is offered as-is, without any
|
||||||
|
# warranty.
|
||||||
|
|
||||||
|
#serial 10
|
||||||
|
|
||||||
|
dnl This macro is based on the code from the AX_CXX_COMPILE_STDCXX_11 macro
|
||||||
|
dnl (serial version number 13).
|
||||||
|
|
||||||
|
AC_DEFUN([AX_CXX_COMPILE_STDCXX], [dnl
|
||||||
|
m4_if([$1], [11], [ax_cxx_compile_alternatives="11 0x"],
|
||||||
|
[$1], [14], [ax_cxx_compile_alternatives="14 1y"],
|
||||||
|
[$1], [17], [ax_cxx_compile_alternatives="17 1z"],
|
||||||
|
[m4_fatal([invalid first argument `$1' to AX_CXX_COMPILE_STDCXX])])dnl
|
||||||
|
m4_if([$2], [], [],
|
||||||
|
[$2], [ext], [],
|
||||||
|
[$2], [noext], [],
|
||||||
|
[m4_fatal([invalid second argument `$2' to AX_CXX_COMPILE_STDCXX])])dnl
|
||||||
|
m4_if([$3], [], [ax_cxx_compile_cxx$1_required=true],
|
||||||
|
[$3], [mandatory], [ax_cxx_compile_cxx$1_required=true],
|
||||||
|
[$3], [optional], [ax_cxx_compile_cxx$1_required=false],
|
||||||
|
[m4_fatal([invalid third argument `$3' to AX_CXX_COMPILE_STDCXX])])
|
||||||
|
AC_LANG_PUSH([C++])dnl
|
||||||
|
ac_success=no
|
||||||
|
|
||||||
|
m4_if([$2], [noext], [], [dnl
|
||||||
|
if test x$ac_success = xno; then
|
||||||
|
for alternative in ${ax_cxx_compile_alternatives}; do
|
||||||
|
switch="-std=gnu++${alternative}"
|
||||||
|
cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch])
|
||||||
|
AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch,
|
||||||
|
$cachevar,
|
||||||
|
[ac_save_CXX="$CXX"
|
||||||
|
CXX="$CXX $switch"
|
||||||
|
AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])],
|
||||||
|
[eval $cachevar=yes],
|
||||||
|
[eval $cachevar=no])
|
||||||
|
CXX="$ac_save_CXX"])
|
||||||
|
if eval test x\$$cachevar = xyes; then
|
||||||
|
CXX="$CXX $switch"
|
||||||
|
if test -n "$CXXCPP" ; then
|
||||||
|
CXXCPP="$CXXCPP $switch"
|
||||||
|
fi
|
||||||
|
ac_success=yes
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
fi])
|
||||||
|
|
||||||
|
m4_if([$2], [ext], [], [dnl
|
||||||
|
if test x$ac_success = xno; then
|
||||||
|
dnl HP's aCC needs +std=c++11 according to:
|
||||||
|
dnl http://h21007.www2.hp.com/portal/download/files/unprot/aCxx/PDF_Release_Notes/769149-001.pdf
|
||||||
|
dnl Cray's crayCC needs "-h std=c++11"
|
||||||
|
for alternative in ${ax_cxx_compile_alternatives}; do
|
||||||
|
for switch in -std=c++${alternative} +std=c++${alternative} "-h std=c++${alternative}"; do
|
||||||
|
cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch])
|
||||||
|
AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch,
|
||||||
|
$cachevar,
|
||||||
|
[ac_save_CXX="$CXX"
|
||||||
|
CXX="$CXX $switch"
|
||||||
|
AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])],
|
||||||
|
[eval $cachevar=yes],
|
||||||
|
[eval $cachevar=no])
|
||||||
|
CXX="$ac_save_CXX"])
|
||||||
|
if eval test x\$$cachevar = xyes; then
|
||||||
|
CXX="$CXX $switch"
|
||||||
|
if test -n "$CXXCPP" ; then
|
||||||
|
CXXCPP="$CXXCPP $switch"
|
||||||
|
fi
|
||||||
|
ac_success=yes
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
if test x$ac_success = xyes; then
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
fi])
|
||||||
|
AC_LANG_POP([C++])
|
||||||
|
if test x$ax_cxx_compile_cxx$1_required = xtrue; then
|
||||||
|
if test x$ac_success = xno; then
|
||||||
|
AC_MSG_ERROR([*** A compiler with support for C++$1 language features is required.])
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
if test x$ac_success = xno; then
|
||||||
|
HAVE_CXX$1=0
|
||||||
|
AC_MSG_NOTICE([No compiler with C++$1 support was found])
|
||||||
|
else
|
||||||
|
HAVE_CXX$1=1
|
||||||
|
AC_DEFINE(HAVE_CXX$1,1,
|
||||||
|
[define if the compiler supports basic C++$1 syntax])
|
||||||
|
fi
|
||||||
|
AC_SUBST(HAVE_CXX$1)
|
||||||
|
])
|
||||||
|
|
||||||
|
|
||||||
|
dnl Test body for checking C++11 support
|
||||||
|
|
||||||
|
m4_define([_AX_CXX_COMPILE_STDCXX_testbody_11],
|
||||||
|
_AX_CXX_COMPILE_STDCXX_testbody_new_in_11
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
dnl Test body for checking C++14 support
|
||||||
|
|
||||||
|
m4_define([_AX_CXX_COMPILE_STDCXX_testbody_14],
|
||||||
|
_AX_CXX_COMPILE_STDCXX_testbody_new_in_11
|
||||||
|
_AX_CXX_COMPILE_STDCXX_testbody_new_in_14
|
||||||
|
)
|
||||||
|
|
||||||
|
m4_define([_AX_CXX_COMPILE_STDCXX_testbody_17],
|
||||||
|
_AX_CXX_COMPILE_STDCXX_testbody_new_in_11
|
||||||
|
_AX_CXX_COMPILE_STDCXX_testbody_new_in_14
|
||||||
|
_AX_CXX_COMPILE_STDCXX_testbody_new_in_17
|
||||||
|
)
|
||||||
|
|
||||||
|
dnl Tests for new features in C++11
|
||||||
|
|
||||||
|
m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_11], [[
|
||||||
|
|
||||||
|
// If the compiler admits that it is not ready for C++11, why torture it?
|
||||||
|
// Hopefully, this will speed up the test.
|
||||||
|
|
||||||
|
#ifndef __cplusplus
|
||||||
|
|
||||||
|
#error "This is not a C++ compiler"
|
||||||
|
|
||||||
|
#elif __cplusplus < 201103L
|
||||||
|
|
||||||
|
#error "This is not a C++11 compiler"
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
namespace cxx11
|
||||||
|
{
|
||||||
|
|
||||||
|
namespace test_static_assert
|
||||||
|
{
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct check
|
||||||
|
{
|
||||||
|
static_assert(sizeof(int) <= sizeof(T), "not big enough");
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_final_override
|
||||||
|
{
|
||||||
|
|
||||||
|
struct Base
|
||||||
|
{
|
||||||
|
virtual void f() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Derived : public Base
|
||||||
|
{
|
||||||
|
virtual void f() override {}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_double_right_angle_brackets
|
||||||
|
{
|
||||||
|
|
||||||
|
template < typename T >
|
||||||
|
struct check {};
|
||||||
|
|
||||||
|
typedef check<void> single_type;
|
||||||
|
typedef check<check<void>> double_type;
|
||||||
|
typedef check<check<check<void>>> triple_type;
|
||||||
|
typedef check<check<check<check<void>>>> quadruple_type;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_decltype
|
||||||
|
{
|
||||||
|
|
||||||
|
int
|
||||||
|
f()
|
||||||
|
{
|
||||||
|
int a = 1;
|
||||||
|
decltype(a) b = 2;
|
||||||
|
return a + b;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_type_deduction
|
||||||
|
{
|
||||||
|
|
||||||
|
template < typename T1, typename T2 >
|
||||||
|
struct is_same
|
||||||
|
{
|
||||||
|
static const bool value = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
template < typename T >
|
||||||
|
struct is_same<T, T>
|
||||||
|
{
|
||||||
|
static const bool value = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
template < typename T1, typename T2 >
|
||||||
|
auto
|
||||||
|
add(T1 a1, T2 a2) -> decltype(a1 + a2)
|
||||||
|
{
|
||||||
|
return a1 + a2;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
test(const int c, volatile int v)
|
||||||
|
{
|
||||||
|
static_assert(is_same<int, decltype(0)>::value == true, "");
|
||||||
|
static_assert(is_same<int, decltype(c)>::value == false, "");
|
||||||
|
static_assert(is_same<int, decltype(v)>::value == false, "");
|
||||||
|
auto ac = c;
|
||||||
|
auto av = v;
|
||||||
|
auto sumi = ac + av + 'x';
|
||||||
|
auto sumf = ac + av + 1.0;
|
||||||
|
static_assert(is_same<int, decltype(ac)>::value == true, "");
|
||||||
|
static_assert(is_same<int, decltype(av)>::value == true, "");
|
||||||
|
static_assert(is_same<int, decltype(sumi)>::value == true, "");
|
||||||
|
static_assert(is_same<int, decltype(sumf)>::value == false, "");
|
||||||
|
static_assert(is_same<int, decltype(add(c, v))>::value == true, "");
|
||||||
|
return (sumf > 0.0) ? sumi : add(c, v);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_noexcept
|
||||||
|
{
|
||||||
|
|
||||||
|
int f() { return 0; }
|
||||||
|
int g() noexcept { return 0; }
|
||||||
|
|
||||||
|
static_assert(noexcept(f()) == false, "");
|
||||||
|
static_assert(noexcept(g()) == true, "");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_constexpr
|
||||||
|
{
|
||||||
|
|
||||||
|
template < typename CharT >
|
||||||
|
unsigned long constexpr
|
||||||
|
strlen_c_r(const CharT *const s, const unsigned long acc) noexcept
|
||||||
|
{
|
||||||
|
return *s ? strlen_c_r(s + 1, acc + 1) : acc;
|
||||||
|
}
|
||||||
|
|
||||||
|
template < typename CharT >
|
||||||
|
unsigned long constexpr
|
||||||
|
strlen_c(const CharT *const s) noexcept
|
||||||
|
{
|
||||||
|
return strlen_c_r(s, 0UL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static_assert(strlen_c("") == 0UL, "");
|
||||||
|
static_assert(strlen_c("1") == 1UL, "");
|
||||||
|
static_assert(strlen_c("example") == 7UL, "");
|
||||||
|
static_assert(strlen_c("another\0example") == 7UL, "");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_rvalue_references
|
||||||
|
{
|
||||||
|
|
||||||
|
template < int N >
|
||||||
|
struct answer
|
||||||
|
{
|
||||||
|
static constexpr int value = N;
|
||||||
|
};
|
||||||
|
|
||||||
|
answer<1> f(int&) { return answer<1>(); }
|
||||||
|
answer<2> f(const int&) { return answer<2>(); }
|
||||||
|
answer<3> f(int&&) { return answer<3>(); }
|
||||||
|
|
||||||
|
void
|
||||||
|
test()
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
const int c = 0;
|
||||||
|
static_assert(decltype(f(i))::value == 1, "");
|
||||||
|
static_assert(decltype(f(c))::value == 2, "");
|
||||||
|
static_assert(decltype(f(0))::value == 3, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_uniform_initialization
|
||||||
|
{
|
||||||
|
|
||||||
|
struct test
|
||||||
|
{
|
||||||
|
static const int zero {};
|
||||||
|
static const int one {1};
|
||||||
|
};
|
||||||
|
|
||||||
|
static_assert(test::zero == 0, "");
|
||||||
|
static_assert(test::one == 1, "");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_lambdas
|
||||||
|
{
|
||||||
|
|
||||||
|
void
|
||||||
|
test1()
|
||||||
|
{
|
||||||
|
auto lambda1 = [](){};
|
||||||
|
auto lambda2 = lambda1;
|
||||||
|
lambda1();
|
||||||
|
lambda2();
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
test2()
|
||||||
|
{
|
||||||
|
auto a = [](int i, int j){ return i + j; }(1, 2);
|
||||||
|
auto b = []() -> int { return '0'; }();
|
||||||
|
auto c = [=](){ return a + b; }();
|
||||||
|
auto d = [&](){ return c; }();
|
||||||
|
auto e = [a, &b](int x) mutable {
|
||||||
|
const auto identity = [](int y){ return y; };
|
||||||
|
for (auto i = 0; i < a; ++i)
|
||||||
|
a += b--;
|
||||||
|
return x + identity(a + b);
|
||||||
|
}(0);
|
||||||
|
return a + b + c + d + e;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
test3()
|
||||||
|
{
|
||||||
|
const auto nullary = [](){ return 0; };
|
||||||
|
const auto unary = [](int x){ return x; };
|
||||||
|
using nullary_t = decltype(nullary);
|
||||||
|
using unary_t = decltype(unary);
|
||||||
|
const auto higher1st = [](nullary_t f){ return f(); };
|
||||||
|
const auto higher2nd = [unary](nullary_t f1){
|
||||||
|
return [unary, f1](unary_t f2){ return f2(unary(f1())); };
|
||||||
|
};
|
||||||
|
return higher1st(nullary) + higher2nd(nullary)(unary);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_variadic_templates
|
||||||
|
{
|
||||||
|
|
||||||
|
template <int...>
|
||||||
|
struct sum;
|
||||||
|
|
||||||
|
template <int N0, int... N1toN>
|
||||||
|
struct sum<N0, N1toN...>
|
||||||
|
{
|
||||||
|
static constexpr auto value = N0 + sum<N1toN...>::value;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct sum<>
|
||||||
|
{
|
||||||
|
static constexpr auto value = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
static_assert(sum<>::value == 0, "");
|
||||||
|
static_assert(sum<1>::value == 1, "");
|
||||||
|
static_assert(sum<23>::value == 23, "");
|
||||||
|
static_assert(sum<1, 2>::value == 3, "");
|
||||||
|
static_assert(sum<5, 5, 11>::value == 21, "");
|
||||||
|
static_assert(sum<2, 3, 5, 7, 11, 13>::value == 41, "");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// http://stackoverflow.com/questions/13728184/template-aliases-and-sfinae
|
||||||
|
// Clang 3.1 fails with headers of libstd++ 4.8.3 when using std::function
|
||||||
|
// because of this.
|
||||||
|
namespace test_template_alias_sfinae
|
||||||
|
{
|
||||||
|
|
||||||
|
struct foo {};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
using member = typename T::member_type;
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void func(...) {}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void func(member<T>*) {}
|
||||||
|
|
||||||
|
void test();
|
||||||
|
|
||||||
|
void test() { func<foo>(0); }
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace cxx11
|
||||||
|
|
||||||
|
#endif // __cplusplus >= 201103L
|
||||||
|
|
||||||
|
]])
|
||||||
|
|
||||||
|
|
||||||
|
dnl Tests for new features in C++14
|
||||||
|
|
||||||
|
m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_14], [[
|
||||||
|
|
||||||
|
// If the compiler admits that it is not ready for C++14, why torture it?
|
||||||
|
// Hopefully, this will speed up the test.
|
||||||
|
|
||||||
|
#ifndef __cplusplus
|
||||||
|
|
||||||
|
#error "This is not a C++ compiler"
|
||||||
|
|
||||||
|
#elif __cplusplus < 201402L
|
||||||
|
|
||||||
|
#error "This is not a C++14 compiler"
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
namespace cxx14
|
||||||
|
{
|
||||||
|
|
||||||
|
namespace test_polymorphic_lambdas
|
||||||
|
{
|
||||||
|
|
||||||
|
int
|
||||||
|
test()
|
||||||
|
{
|
||||||
|
const auto lambda = [](auto&&... args){
|
||||||
|
const auto istiny = [](auto x){
|
||||||
|
return (sizeof(x) == 1UL) ? 1 : 0;
|
||||||
|
};
|
||||||
|
const int aretiny[] = { istiny(args)... };
|
||||||
|
return aretiny[0];
|
||||||
|
};
|
||||||
|
return lambda(1, 1L, 1.0f, '1');
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_binary_literals
|
||||||
|
{
|
||||||
|
|
||||||
|
constexpr auto ivii = 0b0000000000101010;
|
||||||
|
static_assert(ivii == 42, "wrong value");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_generalized_constexpr
|
||||||
|
{
|
||||||
|
|
||||||
|
template < typename CharT >
|
||||||
|
constexpr unsigned long
|
||||||
|
strlen_c(const CharT *const s) noexcept
|
||||||
|
{
|
||||||
|
auto length = 0UL;
|
||||||
|
for (auto p = s; *p; ++p)
|
||||||
|
++length;
|
||||||
|
return length;
|
||||||
|
}
|
||||||
|
|
||||||
|
static_assert(strlen_c("") == 0UL, "");
|
||||||
|
static_assert(strlen_c("x") == 1UL, "");
|
||||||
|
static_assert(strlen_c("test") == 4UL, "");
|
||||||
|
static_assert(strlen_c("another\0test") == 7UL, "");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_lambda_init_capture
|
||||||
|
{
|
||||||
|
|
||||||
|
int
|
||||||
|
test()
|
||||||
|
{
|
||||||
|
auto x = 0;
|
||||||
|
const auto lambda1 = [a = x](int b){ return a + b; };
|
||||||
|
const auto lambda2 = [a = lambda1(x)](){ return a; };
|
||||||
|
return lambda2();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_digit_separators
|
||||||
|
{
|
||||||
|
|
||||||
|
constexpr auto ten_million = 100'000'000;
|
||||||
|
static_assert(ten_million == 100000000, "");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_return_type_deduction
|
||||||
|
{
|
||||||
|
|
||||||
|
auto f(int& x) { return x; }
|
||||||
|
decltype(auto) g(int& x) { return x; }
|
||||||
|
|
||||||
|
template < typename T1, typename T2 >
|
||||||
|
struct is_same
|
||||||
|
{
|
||||||
|
static constexpr auto value = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
template < typename T >
|
||||||
|
struct is_same<T, T>
|
||||||
|
{
|
||||||
|
static constexpr auto value = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
int
|
||||||
|
test()
|
||||||
|
{
|
||||||
|
auto x = 0;
|
||||||
|
static_assert(is_same<int, decltype(f(x))>::value, "");
|
||||||
|
static_assert(is_same<int&, decltype(g(x))>::value, "");
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace cxx14
|
||||||
|
|
||||||
|
#endif // __cplusplus >= 201402L
|
||||||
|
|
||||||
|
]])
|
||||||
|
|
||||||
|
|
||||||
|
dnl Tests for new features in C++17
|
||||||
|
|
||||||
|
m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_17], [[
|
||||||
|
|
||||||
|
// If the compiler admits that it is not ready for C++17, why torture it?
|
||||||
|
// Hopefully, this will speed up the test.
|
||||||
|
|
||||||
|
#ifndef __cplusplus
|
||||||
|
|
||||||
|
#error "This is not a C++ compiler"
|
||||||
|
|
||||||
|
#elif __cplusplus < 201703L
|
||||||
|
|
||||||
|
#error "This is not a C++17 compiler"
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#include <initializer_list>
|
||||||
|
#include <utility>
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
|
namespace cxx17
|
||||||
|
{
|
||||||
|
|
||||||
|
namespace test_constexpr_lambdas
|
||||||
|
{
|
||||||
|
|
||||||
|
constexpr int foo = [](){return 42;}();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test::nested_namespace::definitions
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_fold_expression
|
||||||
|
{
|
||||||
|
|
||||||
|
template<typename... Args>
|
||||||
|
int multiply(Args... args)
|
||||||
|
{
|
||||||
|
return (args * ... * 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename... Args>
|
||||||
|
bool all(Args... args)
|
||||||
|
{
|
||||||
|
return (args && ...);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_extended_static_assert
|
||||||
|
{
|
||||||
|
|
||||||
|
static_assert (true);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_auto_brace_init_list
|
||||||
|
{
|
||||||
|
|
||||||
|
auto foo = {5};
|
||||||
|
auto bar {5};
|
||||||
|
|
||||||
|
static_assert(std::is_same<std::initializer_list<int>, decltype(foo)>::value);
|
||||||
|
static_assert(std::is_same<int, decltype(bar)>::value);
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_typename_in_template_template_parameter
|
||||||
|
{
|
||||||
|
|
||||||
|
template<template<typename> typename X> struct D;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_fallthrough_nodiscard_maybe_unused_attributes
|
||||||
|
{
|
||||||
|
|
||||||
|
int f1()
|
||||||
|
{
|
||||||
|
return 42;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] int f2()
|
||||||
|
{
|
||||||
|
[[maybe_unused]] auto unused = f1();
|
||||||
|
|
||||||
|
switch (f1())
|
||||||
|
{
|
||||||
|
case 17:
|
||||||
|
f1();
|
||||||
|
[[fallthrough]];
|
||||||
|
case 42:
|
||||||
|
f1();
|
||||||
|
}
|
||||||
|
return f1();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_extended_aggregate_initialization
|
||||||
|
{
|
||||||
|
|
||||||
|
struct base1
|
||||||
|
{
|
||||||
|
int b1, b2 = 42;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct base2
|
||||||
|
{
|
||||||
|
base2() {
|
||||||
|
b3 = 42;
|
||||||
|
}
|
||||||
|
int b3;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct derived : base1, base2
|
||||||
|
{
|
||||||
|
int d;
|
||||||
|
};
|
||||||
|
|
||||||
|
derived d1 {{1, 2}, {}, 4}; // full initialization
|
||||||
|
derived d2 {{}, {}, 4}; // value-initialized bases
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_general_range_based_for_loop
|
||||||
|
{
|
||||||
|
|
||||||
|
struct iter
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
int& operator* ()
|
||||||
|
{
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
const int& operator* () const
|
||||||
|
{
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
iter& operator++()
|
||||||
|
{
|
||||||
|
++i;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct sentinel
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
};
|
||||||
|
|
||||||
|
bool operator== (const iter& i, const sentinel& s)
|
||||||
|
{
|
||||||
|
return i.i == s.i;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator!= (const iter& i, const sentinel& s)
|
||||||
|
{
|
||||||
|
return !(i == s);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct range
|
||||||
|
{
|
||||||
|
iter begin() const
|
||||||
|
{
|
||||||
|
return {0};
|
||||||
|
}
|
||||||
|
|
||||||
|
sentinel end() const
|
||||||
|
{
|
||||||
|
return {5};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void f()
|
||||||
|
{
|
||||||
|
range r {};
|
||||||
|
|
||||||
|
for (auto i : r)
|
||||||
|
{
|
||||||
|
[[maybe_unused]] auto v = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_lambda_capture_asterisk_this_by_value
|
||||||
|
{
|
||||||
|
|
||||||
|
struct t
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
int foo()
|
||||||
|
{
|
||||||
|
return [*this]()
|
||||||
|
{
|
||||||
|
return i;
|
||||||
|
}();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_enum_class_construction
|
||||||
|
{
|
||||||
|
|
||||||
|
enum class byte : unsigned char
|
||||||
|
{};
|
||||||
|
|
||||||
|
byte foo {42};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_constexpr_if
|
||||||
|
{
|
||||||
|
|
||||||
|
template <bool cond>
|
||||||
|
int f ()
|
||||||
|
{
|
||||||
|
if constexpr(cond)
|
||||||
|
{
|
||||||
|
return 13;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return 42;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_selection_statement_with_initializer
|
||||||
|
{
|
||||||
|
|
||||||
|
int f()
|
||||||
|
{
|
||||||
|
return 13;
|
||||||
|
}
|
||||||
|
|
||||||
|
int f2()
|
||||||
|
{
|
||||||
|
if (auto i = f(); i > 0)
|
||||||
|
{
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (auto i = f(); i + 4)
|
||||||
|
{
|
||||||
|
case 17:
|
||||||
|
return 2;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_template_argument_deduction_for_class_templates
|
||||||
|
{
|
||||||
|
|
||||||
|
template <typename T1, typename T2>
|
||||||
|
struct pair
|
||||||
|
{
|
||||||
|
pair (T1 p1, T2 p2)
|
||||||
|
: m1 {p1},
|
||||||
|
m2 {p2}
|
||||||
|
{}
|
||||||
|
|
||||||
|
T1 m1;
|
||||||
|
T2 m2;
|
||||||
|
};
|
||||||
|
|
||||||
|
void f()
|
||||||
|
{
|
||||||
|
[[maybe_unused]] auto p = pair{13, 42u};
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_non_type_auto_template_parameters
|
||||||
|
{
|
||||||
|
|
||||||
|
template <auto n>
|
||||||
|
struct B
|
||||||
|
{};
|
||||||
|
|
||||||
|
B<5> b1;
|
||||||
|
B<'a'> b2;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_structured_bindings
|
||||||
|
{
|
||||||
|
|
||||||
|
int arr[2] = { 1, 2 };
|
||||||
|
std::pair<int, int> pr = { 1, 2 };
|
||||||
|
|
||||||
|
auto f1() -> int(&)[2]
|
||||||
|
{
|
||||||
|
return arr;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto f2() -> std::pair<int, int>&
|
||||||
|
{
|
||||||
|
return pr;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct S
|
||||||
|
{
|
||||||
|
int x1 : 2;
|
||||||
|
volatile double y1;
|
||||||
|
};
|
||||||
|
|
||||||
|
S f3()
|
||||||
|
{
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
auto [ x1, y1 ] = f1();
|
||||||
|
auto& [ xr1, yr1 ] = f1();
|
||||||
|
auto [ x2, y2 ] = f2();
|
||||||
|
auto& [ xr2, yr2 ] = f2();
|
||||||
|
const auto [ x3, y3 ] = f3();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_exception_spec_type_system
|
||||||
|
{
|
||||||
|
|
||||||
|
struct Good {};
|
||||||
|
struct Bad {};
|
||||||
|
|
||||||
|
void g1() noexcept;
|
||||||
|
void g2();
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
Bad
|
||||||
|
f(T*, T*);
|
||||||
|
|
||||||
|
template<typename T1, typename T2>
|
||||||
|
Good
|
||||||
|
f(T1*, T2*);
|
||||||
|
|
||||||
|
static_assert (std::is_same_v<Good, decltype(f(g1, g2))>);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_inline_variables
|
||||||
|
{
|
||||||
|
|
||||||
|
template<class T> void f(T)
|
||||||
|
{}
|
||||||
|
|
||||||
|
template<class T> inline T g(T)
|
||||||
|
{
|
||||||
|
return T{};
|
||||||
|
}
|
||||||
|
|
||||||
|
template<> inline void f<>(int)
|
||||||
|
{}
|
||||||
|
|
||||||
|
template<> int g<>(int)
|
||||||
|
{
|
||||||
|
return 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace cxx17
|
||||||
|
|
||||||
|
#endif // __cplusplus < 201703L
|
||||||
|
|
||||||
|
]])
|
||||||
@@ -1,133 +0,0 @@
|
|||||||
# ============================================================================
|
|
||||||
# http://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx_11.html
|
|
||||||
# ============================================================================
|
|
||||||
#
|
|
||||||
# SYNOPSIS
|
|
||||||
#
|
|
||||||
# AX_CXX_COMPILE_STDCXX_11([ext|noext],[mandatory|optional])
|
|
||||||
#
|
|
||||||
# DESCRIPTION
|
|
||||||
#
|
|
||||||
# Check for baseline language coverage in the compiler for the C++11
|
|
||||||
# standard; if necessary, add switches to CXXFLAGS to enable support.
|
|
||||||
#
|
|
||||||
# The first argument, if specified, indicates whether you insist on an
|
|
||||||
# extended mode (e.g. -std=gnu++11) or a strict conformance mode (e.g.
|
|
||||||
# -std=c++11). If neither is specified, you get whatever works, with
|
|
||||||
# preference for an extended mode.
|
|
||||||
#
|
|
||||||
# The second argument, if specified 'mandatory' or if left unspecified,
|
|
||||||
# indicates that baseline C++11 support is required and that the macro
|
|
||||||
# should error out if no mode with that support is found. If specified
|
|
||||||
# 'optional', then configuration proceeds regardless, after defining
|
|
||||||
# HAVE_CXX11 if and only if a supporting mode is found.
|
|
||||||
#
|
|
||||||
# LICENSE
|
|
||||||
#
|
|
||||||
# Copyright (c) 2008 Benjamin Kosnik <bkoz@redhat.com>
|
|
||||||
# Copyright (c) 2012 Zack Weinberg <zackw@panix.com>
|
|
||||||
# Copyright (c) 2013 Roy Stogner <roystgnr@ices.utexas.edu>
|
|
||||||
#
|
|
||||||
# Copying and distribution of this file, with or without modification, are
|
|
||||||
# permitted in any medium without royalty provided the copyright notice
|
|
||||||
# and this notice are preserved. This file is offered as-is, without any
|
|
||||||
# warranty.
|
|
||||||
|
|
||||||
#serial 3
|
|
||||||
|
|
||||||
m4_define([_AX_CXX_COMPILE_STDCXX_11_testbody], [
|
|
||||||
template <typename T>
|
|
||||||
struct check
|
|
||||||
{
|
|
||||||
static_assert(sizeof(int) <= sizeof(T), "not big enough");
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef check<check<bool>> right_angle_brackets;
|
|
||||||
|
|
||||||
int a;
|
|
||||||
decltype(a) b;
|
|
||||||
|
|
||||||
typedef check<int> check_type;
|
|
||||||
check_type c;
|
|
||||||
check_type&& cr = static_cast<check_type&&>(c);
|
|
||||||
|
|
||||||
auto d = a;
|
|
||||||
])
|
|
||||||
|
|
||||||
AC_DEFUN([AX_CXX_COMPILE_STDCXX_11], [dnl
|
|
||||||
m4_if([$1], [], [],
|
|
||||||
[$1], [ext], [],
|
|
||||||
[$1], [noext], [],
|
|
||||||
[m4_fatal([invalid argument `$1' to AX_CXX_COMPILE_STDCXX_11])])dnl
|
|
||||||
m4_if([$2], [], [ax_cxx_compile_cxx11_required=true],
|
|
||||||
[$2], [mandatory], [ax_cxx_compile_cxx11_required=true],
|
|
||||||
[$2], [optional], [ax_cxx_compile_cxx11_required=false],
|
|
||||||
[m4_fatal([invalid second argument `$2' to AX_CXX_COMPILE_STDCXX_11])])dnl
|
|
||||||
AC_LANG_PUSH([C++])dnl
|
|
||||||
ac_success=no
|
|
||||||
AC_CACHE_CHECK(whether $CXX supports C++11 features by default,
|
|
||||||
ax_cv_cxx_compile_cxx11,
|
|
||||||
[AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_11_testbody])],
|
|
||||||
[ax_cv_cxx_compile_cxx11=yes],
|
|
||||||
[ax_cv_cxx_compile_cxx11=no])])
|
|
||||||
if test x$ax_cv_cxx_compile_cxx11 = xyes; then
|
|
||||||
ac_success=yes
|
|
||||||
fi
|
|
||||||
|
|
||||||
m4_if([$1], [noext], [], [dnl
|
|
||||||
if test x$ac_success = xno; then
|
|
||||||
for switch in -std=gnu++11 -std=gnu++0x; do
|
|
||||||
cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx11_$switch])
|
|
||||||
AC_CACHE_CHECK(whether $CXX supports C++11 features with $switch,
|
|
||||||
$cachevar,
|
|
||||||
[ac_save_CXXFLAGS="$CXXFLAGS"
|
|
||||||
CXXFLAGS="$CXXFLAGS $switch"
|
|
||||||
AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_11_testbody])],
|
|
||||||
[eval $cachevar=yes],
|
|
||||||
[eval $cachevar=no])
|
|
||||||
CXXFLAGS="$ac_save_CXXFLAGS"])
|
|
||||||
if eval test x\$$cachevar = xyes; then
|
|
||||||
CXXFLAGS="$CXXFLAGS $switch"
|
|
||||||
ac_success=yes
|
|
||||||
break
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
fi])
|
|
||||||
|
|
||||||
m4_if([$1], [ext], [], [dnl
|
|
||||||
if test x$ac_success = xno; then
|
|
||||||
for switch in -std=c++11 -std=c++0x; do
|
|
||||||
cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx11_$switch])
|
|
||||||
AC_CACHE_CHECK(whether $CXX supports C++11 features with $switch,
|
|
||||||
$cachevar,
|
|
||||||
[ac_save_CXXFLAGS="$CXXFLAGS"
|
|
||||||
CXXFLAGS="$CXXFLAGS $switch"
|
|
||||||
AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_11_testbody])],
|
|
||||||
[eval $cachevar=yes],
|
|
||||||
[eval $cachevar=no])
|
|
||||||
CXXFLAGS="$ac_save_CXXFLAGS"])
|
|
||||||
if eval test x\$$cachevar = xyes; then
|
|
||||||
CXXFLAGS="$CXXFLAGS $switch"
|
|
||||||
ac_success=yes
|
|
||||||
break
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
fi])
|
|
||||||
AC_LANG_POP([C++])
|
|
||||||
if test x$ax_cxx_compile_cxx11_required = xtrue; then
|
|
||||||
if test x$ac_success = xno; then
|
|
||||||
AC_MSG_ERROR([*** A compiler with support for C++11 language features is required.])
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
if test x$ac_success = xno; then
|
|
||||||
HAVE_CXX11=0
|
|
||||||
AC_MSG_NOTICE([No compiler with C++11 support was found])
|
|
||||||
else
|
|
||||||
HAVE_CXX11=1
|
|
||||||
AC_DEFINE(HAVE_CXX11,1,
|
|
||||||
[define if the compiler supports basic C++11 syntax])
|
|
||||||
fi
|
|
||||||
|
|
||||||
AC_SUBST(HAVE_CXX11)
|
|
||||||
fi
|
|
||||||
])
|
|
||||||
@@ -8,11 +8,8 @@ set_source_files_properties(${cxx_sources} PROPERTIES
|
|||||||
COMPILE_FLAGS "${WARNCXXFLAGS} ${CXX1XCXXFLAGS}")
|
COMPILE_FLAGS "${WARNCXXFLAGS} ${CXX1XCXXFLAGS}")
|
||||||
|
|
||||||
include_directories(
|
include_directories(
|
||||||
"${CMAKE_SOURCE_DIR}/lib/includes"
|
"${CMAKE_CURRENT_SOURCE_DIR}/includes"
|
||||||
"${CMAKE_BINARY_DIR}/lib/includes"
|
"${CMAKE_CURRENT_SOURCE_DIR}/../third-party"
|
||||||
"${CMAKE_SOURCE_DIR}/lib"
|
|
||||||
"${CMAKE_SOURCE_DIR}/src/includes"
|
|
||||||
"${CMAKE_SOURCE_DIR}/third-party"
|
|
||||||
|
|
||||||
${JEMALLOC_INCLUDE_DIRS}
|
${JEMALLOC_INCLUDE_DIRS}
|
||||||
${SPDYLAY_INCLUDE_DIRS}
|
${SPDYLAY_INCLUDE_DIRS}
|
||||||
@@ -252,6 +249,11 @@ if(ENABLE_ASIO_LIB)
|
|||||||
${OPENSSL_INCLUDE_DIRS}
|
${OPENSSL_INCLUDE_DIRS}
|
||||||
${Boost_INCLUDE_DIRS}
|
${Boost_INCLUDE_DIRS}
|
||||||
)
|
)
|
||||||
|
target_include_directories(nghttp2_asio INTERFACE
|
||||||
|
"${CMAKE_CURRENT_BINARY_DIR}/../lib/includes"
|
||||||
|
"${CMAKE_CURRENT_SOURCE_DIR}/../lib/includes"
|
||||||
|
"${CMAKE_CURRENT_SOURCE_DIR}/includes"
|
||||||
|
)
|
||||||
target_link_libraries(nghttp2_asio
|
target_link_libraries(nghttp2_asio
|
||||||
nghttp2
|
nghttp2
|
||||||
${OPENSSL_LIBRARIES}
|
${OPENSSL_LIBRARIES}
|
||||||
@@ -261,7 +263,9 @@ if(ENABLE_ASIO_LIB)
|
|||||||
VERSION 1.0.0 SOVERSION 1)
|
VERSION 1.0.0 SOVERSION 1)
|
||||||
|
|
||||||
install(TARGETS nghttp2_asio
|
install(TARGETS nghttp2_asio
|
||||||
DESTINATION "${CMAKE_INSTALL_LIBDIR}")
|
ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}"
|
||||||
|
LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}"
|
||||||
|
RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}")
|
||||||
|
|
||||||
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/libnghttp2_asio.pc"
|
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/libnghttp2_asio.pc"
|
||||||
DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig")
|
DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig")
|
||||||
|
|||||||
@@ -32,7 +32,7 @@
|
|||||||
|
|
||||||
#ifdef HAVE_LIBXML2
|
#ifdef HAVE_LIBXML2
|
||||||
|
|
||||||
#include <libxml/HTMLparser.h>
|
# include <libxml/HTMLparser.h>
|
||||||
|
|
||||||
#endif // HAVE_LIBXML2
|
#endif // HAVE_LIBXML2
|
||||||
|
|
||||||
|
|||||||
@@ -26,23 +26,23 @@
|
|||||||
|
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#ifdef HAVE_SYS_SOCKET_H
|
#ifdef HAVE_SYS_SOCKET_H
|
||||||
#include <sys/socket.h>
|
# include <sys/socket.h>
|
||||||
#endif // HAVE_SYS_SOCKET_H
|
#endif // HAVE_SYS_SOCKET_H
|
||||||
#ifdef HAVE_NETDB_H
|
#ifdef HAVE_NETDB_H
|
||||||
#include <netdb.h>
|
# include <netdb.h>
|
||||||
#endif // HAVE_NETDB_H
|
#endif // HAVE_NETDB_H
|
||||||
#ifdef HAVE_UNISTD_H
|
#ifdef HAVE_UNISTD_H
|
||||||
#include <unistd.h>
|
# include <unistd.h>
|
||||||
#endif // HAVE_UNISTD_H
|
#endif // HAVE_UNISTD_H
|
||||||
#ifdef HAVE_FCNTL_H
|
#ifdef HAVE_FCNTL_H
|
||||||
#include <fcntl.h>
|
# include <fcntl.h>
|
||||||
#endif // HAVE_FCNTL_H
|
#endif // HAVE_FCNTL_H
|
||||||
#ifdef HAVE_NETINET_IN_H
|
#ifdef HAVE_NETINET_IN_H
|
||||||
#include <netinet/in.h>
|
# include <netinet/in.h>
|
||||||
#endif // HAVE_NETINET_IN_H
|
#endif // HAVE_NETINET_IN_H
|
||||||
#include <netinet/tcp.h>
|
#include <netinet/tcp.h>
|
||||||
#ifdef HAVE_ARPA_INET_H
|
#ifdef HAVE_ARPA_INET_H
|
||||||
#include <arpa/inet.h>
|
# include <arpa/inet.h>
|
||||||
#endif // HAVE_ARPA_INET_H
|
#endif // HAVE_ARPA_INET_H
|
||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
@@ -64,7 +64,7 @@
|
|||||||
#include "template.h"
|
#include "template.h"
|
||||||
|
|
||||||
#ifndef O_BINARY
|
#ifndef O_BINARY
|
||||||
#define O_BINARY (0)
|
# define O_BINARY (0)
|
||||||
#endif // O_BINARY
|
#endif // O_BINARY
|
||||||
|
|
||||||
namespace nghttp2 {
|
namespace nghttp2 {
|
||||||
@@ -305,7 +305,7 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
auto handler =
|
auto handler =
|
||||||
make_unique<Http2Handler>(this, fd, ssl, get_next_session_id());
|
std::make_unique<Http2Handler>(this, fd, ssl, get_next_session_id());
|
||||||
if (!ssl) {
|
if (!ssl) {
|
||||||
if (handler->connection_made() != 0) {
|
if (handler->connection_made() != 0) {
|
||||||
return;
|
return;
|
||||||
@@ -358,11 +358,11 @@ public:
|
|||||||
}
|
}
|
||||||
FileEntry *cache_fd(const std::string &path, const FileEntry &ent) {
|
FileEntry *cache_fd(const std::string &path, const FileEntry &ent) {
|
||||||
#ifdef HAVE_STD_MAP_EMPLACE
|
#ifdef HAVE_STD_MAP_EMPLACE
|
||||||
auto rv = fd_cache_.emplace(path, make_unique<FileEntry>(ent));
|
auto rv = fd_cache_.emplace(path, std::make_unique<FileEntry>(ent));
|
||||||
#else // !HAVE_STD_MAP_EMPLACE
|
#else // !HAVE_STD_MAP_EMPLACE
|
||||||
// for gcc-4.7
|
// for gcc-4.7
|
||||||
auto rv =
|
auto rv = fd_cache_.insert(
|
||||||
fd_cache_.insert(std::make_pair(path, make_unique<FileEntry>(ent)));
|
std::make_pair(path, std::make_unique<FileEntry>(ent)));
|
||||||
#endif // !HAVE_STD_MAP_EMPLACE
|
#endif // !HAVE_STD_MAP_EMPLACE
|
||||||
auto &res = (*rv).second;
|
auto &res = (*rv).second;
|
||||||
res->it = rv;
|
res->it = rv;
|
||||||
@@ -888,7 +888,9 @@ int Http2Handler::verify_npn_result() {
|
|||||||
const unsigned char *next_proto = nullptr;
|
const unsigned char *next_proto = nullptr;
|
||||||
unsigned int next_proto_len;
|
unsigned int next_proto_len;
|
||||||
// Check the negotiated protocol in NPN or ALPN
|
// Check the negotiated protocol in NPN or ALPN
|
||||||
|
#ifndef OPENSSL_NO_NEXTPROTONEG
|
||||||
SSL_get0_next_proto_negotiated(ssl_, &next_proto, &next_proto_len);
|
SSL_get0_next_proto_negotiated(ssl_, &next_proto, &next_proto_len);
|
||||||
|
#endif // !OPENSSL_NO_NEXTPROTONEG
|
||||||
for (int i = 0; i < 2; ++i) {
|
for (int i = 0; i < 2; ++i) {
|
||||||
if (next_proto) {
|
if (next_proto) {
|
||||||
auto proto = StringRef{next_proto, next_proto_len};
|
auto proto = StringRef{next_proto, next_proto_len};
|
||||||
@@ -1021,7 +1023,7 @@ int Http2Handler::submit_push_promise(Stream *stream,
|
|||||||
return promised_stream_id;
|
return promised_stream_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto promised_stream = make_unique<Stream>(this, promised_stream_id);
|
auto promised_stream = std::make_unique<Stream>(this, promised_stream_id);
|
||||||
|
|
||||||
auto &promised_header = promised_stream->header;
|
auto &promised_header = promised_stream->header;
|
||||||
promised_header.method = StringRef::from_lit("GET");
|
promised_header.method = StringRef::from_lit("GET");
|
||||||
@@ -1475,7 +1477,7 @@ int on_begin_headers_callback(nghttp2_session *session,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto stream = make_unique<Stream>(hd, frame->hd.stream_id);
|
auto stream = std::make_unique<Stream>(hd, frame->hd.stream_id);
|
||||||
|
|
||||||
add_stream_read_timeout(stream.get());
|
add_stream_read_timeout(stream.get());
|
||||||
|
|
||||||
@@ -1749,8 +1751,8 @@ void fill_callback(nghttp2_session_callbacks *callbacks, const Config *config) {
|
|||||||
nghttp2_session_callbacks_set_on_invalid_frame_recv_callback(
|
nghttp2_session_callbacks_set_on_invalid_frame_recv_callback(
|
||||||
callbacks, verbose_on_invalid_frame_recv_callback);
|
callbacks, verbose_on_invalid_frame_recv_callback);
|
||||||
|
|
||||||
nghttp2_session_callbacks_set_error_callback(callbacks,
|
nghttp2_session_callbacks_set_error_callback2(callbacks,
|
||||||
verbose_error_callback);
|
verbose_error_callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
nghttp2_session_callbacks_set_on_data_chunk_recv_callback(
|
nghttp2_session_callbacks_set_on_data_chunk_recv_callback(
|
||||||
@@ -1779,7 +1781,7 @@ struct ClientInfo {
|
|||||||
struct Worker {
|
struct Worker {
|
||||||
std::unique_ptr<Sessions> sessions;
|
std::unique_ptr<Sessions> sessions;
|
||||||
ev_async w;
|
ev_async w;
|
||||||
// protectes q
|
// protects q
|
||||||
std::mutex m;
|
std::mutex m;
|
||||||
std::deque<ClientInfo> q;
|
std::deque<ClientInfo> q;
|
||||||
};
|
};
|
||||||
@@ -1830,10 +1832,10 @@ public:
|
|||||||
if (config_->verbose) {
|
if (config_->verbose) {
|
||||||
std::cerr << "spawning thread #" << i << std::endl;
|
std::cerr << "spawning thread #" << i << std::endl;
|
||||||
}
|
}
|
||||||
auto worker = make_unique<Worker>();
|
auto worker = std::make_unique<Worker>();
|
||||||
auto loop = ev_loop_new(get_ev_loop_flags());
|
auto loop = ev_loop_new(get_ev_loop_flags());
|
||||||
worker->sessions =
|
worker->sessions = std::make_unique<Sessions>(sv, loop, config_,
|
||||||
make_unique<Sessions>(sv, loop, config_, sessions_->get_ssl_ctx());
|
sessions_->get_ssl_ctx());
|
||||||
ev_async_init(&worker->w, worker_acceptcb);
|
ev_async_init(&worker->w, worker_acceptcb);
|
||||||
worker->w.data = worker.get();
|
worker->w.data = worker.get();
|
||||||
ev_async_start(loop, &worker->w);
|
ev_async_start(loop, &worker->w);
|
||||||
@@ -1982,6 +1984,7 @@ HttpServer::HttpServer(const Config *config) : config_(config) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef OPENSSL_NO_NEXTPROTONEG
|
||||||
namespace {
|
namespace {
|
||||||
int next_proto_cb(SSL *s, const unsigned char **data, unsigned int *len,
|
int next_proto_cb(SSL *s, const unsigned char **data, unsigned int *len,
|
||||||
void *arg) {
|
void *arg) {
|
||||||
@@ -1991,6 +1994,7 @@ int next_proto_cb(SSL *s, const unsigned char **data, unsigned int *len,
|
|||||||
return SSL_TLSEXT_ERR_OK;
|
return SSL_TLSEXT_ERR_OK;
|
||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
#endif // !OPENSSL_NO_NEXTPROTONEG
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
int verify_callback(int preverify_ok, X509_STORE_CTX *ctx) {
|
int verify_callback(int preverify_ok, X509_STORE_CTX *ctx) {
|
||||||
@@ -2156,7 +2160,7 @@ int HttpServer::run() {
|
|||||||
}
|
}
|
||||||
SSL_CTX_set_tmp_ecdh(ssl_ctx, ecdh);
|
SSL_CTX_set_tmp_ecdh(ssl_ctx, ecdh);
|
||||||
EC_KEY_free(ecdh);
|
EC_KEY_free(ecdh);
|
||||||
// #endif // OPENSSL_VERSION_NUBMER < 0x10002000L
|
// #endif // OPENSSL_VERSION_NUBMER < 0x10002000L
|
||||||
|
|
||||||
#endif // OPENSSL_NO_EC
|
#endif // OPENSSL_NO_EC
|
||||||
|
|
||||||
@@ -2205,7 +2209,9 @@ int HttpServer::run() {
|
|||||||
|
|
||||||
next_proto = util::get_default_alpn();
|
next_proto = util::get_default_alpn();
|
||||||
|
|
||||||
|
#ifndef OPENSSL_NO_NEXTPROTONEG
|
||||||
SSL_CTX_set_next_protos_advertised_cb(ssl_ctx, next_proto_cb, &next_proto);
|
SSL_CTX_set_next_protos_advertised_cb(ssl_ctx, next_proto_cb, &next_proto);
|
||||||
|
#endif // !OPENSSL_NO_NEXTPROTONEG
|
||||||
#if OPENSSL_VERSION_NUMBER >= 0x10002000L
|
#if OPENSSL_VERSION_NUMBER >= 0x10002000L
|
||||||
// ALPN selection callback
|
// ALPN selection callback
|
||||||
SSL_CTX_set_alpn_select_cb(ssl_ctx, alpn_select_proto_cb, this);
|
SSL_CTX_set_alpn_select_cb(ssl_ctx, alpn_select_proto_cb, this);
|
||||||
|
|||||||
@@ -40,7 +40,6 @@ AM_CPPFLAGS = \
|
|||||||
-I$(top_srcdir)/lib \
|
-I$(top_srcdir)/lib \
|
||||||
-I$(top_srcdir)/src/includes \
|
-I$(top_srcdir)/src/includes \
|
||||||
-I$(top_srcdir)/third-party \
|
-I$(top_srcdir)/third-party \
|
||||||
@LIBSPDYLAY_CFLAGS@ \
|
|
||||||
@LIBXML2_CFLAGS@ \
|
@LIBXML2_CFLAGS@ \
|
||||||
@LIBEV_CFLAGS@ \
|
@LIBEV_CFLAGS@ \
|
||||||
@OPENSSL_CFLAGS@ \
|
@OPENSSL_CFLAGS@ \
|
||||||
@@ -52,7 +51,6 @@ AM_CPPFLAGS = \
|
|||||||
LDADD = $(top_builddir)/lib/libnghttp2.la \
|
LDADD = $(top_builddir)/lib/libnghttp2.la \
|
||||||
$(top_builddir)/third-party/libhttp-parser.la \
|
$(top_builddir)/third-party/libhttp-parser.la \
|
||||||
@JEMALLOC_LIBS@ \
|
@JEMALLOC_LIBS@ \
|
||||||
@LIBSPDYLAY_LIBS@ \
|
|
||||||
@LIBXML2_LIBS@ \
|
@LIBXML2_LIBS@ \
|
||||||
@LIBEV_LIBS@ \
|
@LIBEV_LIBS@ \
|
||||||
@OPENSSL_LIBS@ \
|
@OPENSSL_LIBS@ \
|
||||||
@@ -97,10 +95,6 @@ h2load_SOURCES = util.cc util.h \
|
|||||||
h2load_http2_session.cc h2load_http2_session.h \
|
h2load_http2_session.cc h2load_http2_session.h \
|
||||||
h2load_http1_session.cc h2load_http1_session.h
|
h2load_http1_session.cc h2load_http1_session.h
|
||||||
|
|
||||||
if HAVE_SPDYLAY
|
|
||||||
h2load_SOURCES += h2load_spdy_session.cc h2load_spdy_session.h
|
|
||||||
endif # HAVE_SPDYLAY
|
|
||||||
|
|
||||||
NGHTTPX_SRCS = \
|
NGHTTPX_SRCS = \
|
||||||
util.cc util.h http2.cc http2.h timegm.c timegm.h base64.h \
|
util.cc util.h http2.cc http2.h timegm.c timegm.h base64.h \
|
||||||
app_helper.cc app_helper.h \
|
app_helper.cc app_helper.h \
|
||||||
@@ -148,10 +142,6 @@ NGHTTPX_SRCS = \
|
|||||||
buffer.h memchunk.h template.h allocator.h \
|
buffer.h memchunk.h template.h allocator.h \
|
||||||
xsi_strerror.c xsi_strerror.h
|
xsi_strerror.c xsi_strerror.h
|
||||||
|
|
||||||
if HAVE_SPDYLAY
|
|
||||||
NGHTTPX_SRCS += shrpx_spdy_upstream.cc shrpx_spdy_upstream.h
|
|
||||||
endif # HAVE_SPDYLAY
|
|
||||||
|
|
||||||
if HAVE_MRUBY
|
if HAVE_MRUBY
|
||||||
NGHTTPX_SRCS += \
|
NGHTTPX_SRCS += \
|
||||||
shrpx_mruby.cc shrpx_mruby.h \
|
shrpx_mruby.cc shrpx_mruby.h \
|
||||||
|
|||||||
@@ -27,9 +27,12 @@
|
|||||||
|
|
||||||
#include "nghttp2_config.h"
|
#include "nghttp2_config.h"
|
||||||
|
|
||||||
#include <sys/uio.h>
|
#ifndef _WIN32
|
||||||
|
# include <sys/uio.h>
|
||||||
|
#endif // !_WIN32
|
||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
#include "template.h"
|
#include "template.h"
|
||||||
|
|
||||||
@@ -63,25 +66,19 @@ struct BlockAllocator {
|
|||||||
~BlockAllocator() { reset(); }
|
~BlockAllocator() { reset(); }
|
||||||
|
|
||||||
BlockAllocator(BlockAllocator &&other) noexcept
|
BlockAllocator(BlockAllocator &&other) noexcept
|
||||||
: retain(other.retain),
|
: retain{std::exchange(other.retain, nullptr)},
|
||||||
head(other.head),
|
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) {}
|
||||||
other.retain = nullptr;
|
|
||||||
other.head = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
BlockAllocator &operator=(BlockAllocator &&other) noexcept {
|
BlockAllocator &operator=(BlockAllocator &&other) noexcept {
|
||||||
reset();
|
reset();
|
||||||
|
|
||||||
retain = other.retain;
|
retain = std::exchange(other.retain, nullptr);
|
||||||
head = other.head;
|
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;
|
||||||
|
|
||||||
other.retain = nullptr;
|
|
||||||
other.head = nullptr;
|
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -271,6 +268,6 @@ ByteRef make_byte_ref(BlockAllocator &alloc, size_t size) {
|
|||||||
return {dst, size};
|
return {dst, size};
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace aria2
|
} // namespace nghttp2
|
||||||
|
|
||||||
#endif // ALLOCATOR_H
|
#endif // ALLOCATOR_H
|
||||||
|
|||||||
@@ -24,19 +24,19 @@
|
|||||||
*/
|
*/
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#ifdef HAVE_SYS_SOCKET_H
|
#ifdef HAVE_SYS_SOCKET_H
|
||||||
#include <sys/socket.h>
|
# include <sys/socket.h>
|
||||||
#endif // HAVE_SYS_SOCKET_H
|
#endif // HAVE_SYS_SOCKET_H
|
||||||
#ifdef HAVE_NETDB_H
|
#ifdef HAVE_NETDB_H
|
||||||
#include <netdb.h>
|
# include <netdb.h>
|
||||||
#endif // HAVE_NETDB_H
|
#endif // HAVE_NETDB_H
|
||||||
#ifdef HAVE_UNISTD_H
|
#ifdef HAVE_UNISTD_H
|
||||||
#include <unistd.h>
|
# include <unistd.h>
|
||||||
#endif // HAVE_UNISTD_H
|
#endif // HAVE_UNISTD_H
|
||||||
#ifdef HAVE_FCNTL_H
|
#ifdef HAVE_FCNTL_H
|
||||||
#include <fcntl.h>
|
# include <fcntl.h>
|
||||||
#endif // HAVE_FCNTL_H
|
#endif // HAVE_FCNTL_H
|
||||||
#ifdef HAVE_NETINET_IN_H
|
#ifdef HAVE_NETINET_IN_H
|
||||||
#include <netinet/in.h>
|
# include <netinet/in.h>
|
||||||
#endif // HAVE_NETINET_IN_H
|
#endif // HAVE_NETINET_IN_H
|
||||||
#include <netinet/tcp.h>
|
#include <netinet/tcp.h>
|
||||||
#include <poll.h>
|
#include <poll.h>
|
||||||
@@ -77,6 +77,8 @@ const char *strsettingsid(int32_t id) {
|
|||||||
return "SETTINGS_MAX_FRAME_SIZE";
|
return "SETTINGS_MAX_FRAME_SIZE";
|
||||||
case NGHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE:
|
case NGHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE:
|
||||||
return "SETTINGS_MAX_HEADER_LIST_SIZE";
|
return "SETTINGS_MAX_HEADER_LIST_SIZE";
|
||||||
|
case NGHTTP2_SETTINGS_ENABLE_CONNECT_PROTOCOL:
|
||||||
|
return "SETTINGS_ENABLE_CONNECT_PROTOCOL";
|
||||||
default:
|
default:
|
||||||
return "UNKNOWN";
|
return "UNKNOWN";
|
||||||
}
|
}
|
||||||
@@ -106,6 +108,8 @@ std::string strframetype(uint8_t type) {
|
|||||||
return "WINDOW_UPDATE";
|
return "WINDOW_UPDATE";
|
||||||
case NGHTTP2_ALTSVC:
|
case NGHTTP2_ALTSVC:
|
||||||
return "ALTSVC";
|
return "ALTSVC";
|
||||||
|
case NGHTTP2_ORIGIN:
|
||||||
|
return "ORIGIN";
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string s = "extension(0x";
|
std::string s = "extension(0x";
|
||||||
@@ -155,7 +159,7 @@ void print_nv(nghttp2_nv *nva, size_t nvlen) {
|
|||||||
print_nv(nva);
|
print_nv(nva);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} // namelen
|
} // namespace
|
||||||
|
|
||||||
void print_timer() {
|
void print_timer() {
|
||||||
auto millis = get_timer();
|
auto millis = get_timer();
|
||||||
@@ -327,8 +331,9 @@ void print_frame(print_type ptype, const nghttp2_frame *frame) {
|
|||||||
break;
|
break;
|
||||||
case NGHTTP2_GOAWAY:
|
case NGHTTP2_GOAWAY:
|
||||||
print_frame_attr_indent();
|
print_frame_attr_indent();
|
||||||
fprintf(outfile, "(last_stream_id=%d, error_code=%s(0x%02x), "
|
fprintf(outfile,
|
||||||
"opaque_data(%u)=[%s])\n",
|
"(last_stream_id=%d, error_code=%s(0x%02x), "
|
||||||
|
"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,
|
||||||
@@ -350,6 +355,15 @@ void print_frame(print_type ptype, const nghttp2_frame *frame) {
|
|||||||
static_cast<int>(altsvc->field_value_len), altsvc->field_value);
|
static_cast<int>(altsvc->field_value_len), altsvc->field_value);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case NGHTTP2_ORIGIN: {
|
||||||
|
auto origin = static_cast<nghttp2_ext_origin *>(frame->ext.payload);
|
||||||
|
for (size_t i = 0; i < origin->nov; ++i) {
|
||||||
|
auto ent = &origin->ov[i];
|
||||||
|
print_frame_attr_indent();
|
||||||
|
fprintf(outfile, "[%.*s]\n", (int)ent->origin_len, ent->origin);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -425,8 +439,8 @@ int verbose_on_data_chunk_recv_callback(nghttp2_session *session, uint8_t flags,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int verbose_error_callback(nghttp2_session *session, const char *msg,
|
int verbose_error_callback(nghttp2_session *session, int lib_error_code,
|
||||||
size_t len, void *user_data) {
|
const char *msg, size_t len, void *user_data) {
|
||||||
print_timer();
|
print_timer();
|
||||||
fprintf(outfile, " [ERROR] %.*s\n", (int)len, msg);
|
fprintf(outfile, " [ERROR] %.*s\n", (int)len, msg);
|
||||||
fflush(outfile);
|
fflush(outfile);
|
||||||
|
|||||||
@@ -30,7 +30,7 @@
|
|||||||
#include <cinttypes>
|
#include <cinttypes>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#ifdef HAVE_SYS_TIME_H
|
#ifdef HAVE_SYS_TIME_H
|
||||||
#include <sys/time.h>
|
# include <sys/time.h>
|
||||||
#endif // HAVE_SYS_TIME_H
|
#endif // HAVE_SYS_TIME_H
|
||||||
#include <poll.h>
|
#include <poll.h>
|
||||||
|
|
||||||
@@ -60,8 +60,8 @@ int verbose_on_data_chunk_recv_callback(nghttp2_session *session, uint8_t flags,
|
|||||||
int32_t stream_id, const uint8_t *data,
|
int32_t stream_id, const uint8_t *data,
|
||||||
size_t len, void *user_data);
|
size_t len, void *user_data);
|
||||||
|
|
||||||
int verbose_error_callback(nghttp2_session *session, const char *msg,
|
int verbose_error_callback(nghttp2_session *session, int lib_error_code,
|
||||||
size_t len, void *user_data);
|
const char *msg, size_t len, void *user_data);
|
||||||
|
|
||||||
// Returns difference between |a| and |b| in milliseconds, assuming
|
// Returns difference between |a| and |b| in milliseconds, assuming
|
||||||
// |a| is more recent than |b|.
|
// |a| is more recent than |b|.
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ namespace nghttp2 {
|
|||||||
namespace asio_http2 {
|
namespace asio_http2 {
|
||||||
namespace client {
|
namespace client {
|
||||||
|
|
||||||
request::request() : impl_(make_unique<request_impl>()) {}
|
request::request() : impl_(std::make_unique<request_impl>()) {}
|
||||||
|
|
||||||
request::~request() {}
|
request::~request() {}
|
||||||
|
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ namespace nghttp2 {
|
|||||||
namespace asio_http2 {
|
namespace asio_http2 {
|
||||||
namespace client {
|
namespace client {
|
||||||
|
|
||||||
response::response() : impl_(make_unique<response_impl>()) {}
|
response::response() : impl_(std::make_unique<response_impl>()) {}
|
||||||
|
|
||||||
response::~response() {}
|
response::~response() {}
|
||||||
|
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user