mirror of
https://github.com/nghttp2/nghttp2.git
synced 2025-12-06 18:18:52 +08:00
Compare commits
380 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8f7b008b15 | ||
|
|
83086ba91a | ||
|
|
c3b4662563 | ||
|
|
3eecc2ca45 | ||
|
|
881c060d8c | ||
|
|
f8da73bd04 | ||
|
|
336a98feb0 | ||
|
|
ef41583614 | ||
|
|
979e6c5325 | ||
|
|
b7d1610141 | ||
|
|
cd53bd81bf | ||
|
|
e5625b8cf0 | ||
|
|
c663349f24 | ||
|
|
854e9fe395 | ||
|
|
c60ea227cc | ||
|
|
49cd8e6e73 | ||
|
|
3b17a659f6 | ||
|
|
600fcdf52d | ||
|
|
4922bb41d6 | ||
|
|
aad8697575 | ||
|
|
dc7a7df61c | ||
|
|
b3f85e2daa | ||
|
|
ffb49c6c58 | ||
|
|
2ec585518e | ||
|
|
459df42b8b | ||
|
|
a4c1fed513 | ||
|
|
866eadb5de | ||
|
|
5e13274b7c | ||
|
|
e0d7f7de5e | ||
|
|
df575f968f | ||
|
|
1fff737955 | ||
|
|
b40c6c862f | ||
|
|
9bc2c75e38 | ||
|
|
2d5f76594a | ||
|
|
cc05c5fe8c | ||
|
|
66d7b194d4 | ||
|
|
41060943bd | ||
|
|
5ae9bb8925 | ||
|
|
bb519154fe | ||
|
|
77f5487a58 | ||
|
|
db9a8f6efe | ||
|
|
6f28a69b7d | ||
|
|
6ce4835eea | ||
|
|
29042f1c95 | ||
|
|
d08c43951f | ||
|
|
5d6964cf81 | ||
|
|
0d855bfc1b | ||
|
|
6f967c6ef3 | ||
|
|
b8a43db84c | ||
|
|
70b62c1a32 | ||
|
|
28b1f0b90f | ||
|
|
1dd966f189 | ||
|
|
fe8946ddc7 | ||
|
|
72b71a6ba3 | ||
|
|
f8933fe504 | ||
|
|
89c33d690f | ||
|
|
7079dc5e75 | ||
|
|
5080db84e2 | ||
|
|
053c7ac588 | ||
|
|
8a59ce6d37 | ||
|
|
f2fde180cd | ||
|
|
95efb3e19d | ||
|
|
0a6ce87c22 | ||
|
|
2aa79fa91d | ||
|
|
3980678d24 | ||
|
|
319d5ab1c6 | ||
|
|
448bbbc38c | ||
|
|
e575a2aad9 | ||
|
|
4f7aedc9d2 | ||
|
|
7a5908933e | ||
|
|
ee44313445 | ||
|
|
abef9b90ef | ||
|
|
12a999f0b8 | ||
|
|
acfb360770 | ||
|
|
bdfd14c2b7 | ||
|
|
cddc09feaa | ||
|
|
3c3b6ae8ca | ||
|
|
2f83aa9e1b | ||
|
|
fc591d0cd6 | ||
|
|
9a17c3efc6 | ||
|
|
b7220f075c | ||
|
|
a1556fd11f | ||
|
|
77f1c872b1 | ||
|
|
49ce44e1f5 | ||
|
|
f54b3ffc0e | ||
|
|
b0f5e5cc79 | ||
|
|
8d6ecd66cc | ||
|
|
f82fb52187 | ||
|
|
2e1975ddf6 | ||
|
|
97ce392bcc | ||
|
|
afefbda518 | ||
|
|
4fca2502d8 | ||
|
|
6975c336fc | ||
|
|
0288093caf | ||
|
|
a3a034813b | ||
|
|
c64d2573dc | ||
|
|
f028cc4392 | ||
|
|
302e37460f | ||
|
|
3cdbc5f525 | ||
|
|
a69251864b | ||
|
|
45d63d2006 | ||
|
|
cbba1ebf8f | ||
|
|
e86d1378da | ||
|
|
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 |
@@ -2,24 +2,29 @@
|
||||
Language: Cpp
|
||||
AccessModifierOffset: -2
|
||||
AlignAfterOpenBracket: Align
|
||||
AlignConsecutiveMacros: false
|
||||
AlignConsecutiveAssignments: false
|
||||
AlignConsecutiveDeclarations: false
|
||||
AlignEscapedNewlines: Right
|
||||
AlignOperands: true
|
||||
AlignTrailingComments: true
|
||||
AllowAllArgumentsOnNextLine: true
|
||||
AllowAllConstructorInitializersOnNextLine: true
|
||||
AllowAllParametersOfDeclarationOnNextLine: true
|
||||
AllowShortBlocksOnASingleLine: false
|
||||
AllowShortCaseLabelsOnASingleLine: false
|
||||
AllowShortFunctionsOnASingleLine: All
|
||||
AllowShortIfStatementsOnASingleLine: false
|
||||
AllowShortLambdasOnASingleLine: All
|
||||
AllowShortIfStatementsOnASingleLine: Never
|
||||
AllowShortLoopsOnASingleLine: false
|
||||
AlwaysBreakAfterDefinitionReturnType: None
|
||||
AlwaysBreakAfterReturnType: None
|
||||
AlwaysBreakBeforeMultilineStrings: false
|
||||
AlwaysBreakTemplateDeclarations: false
|
||||
AlwaysBreakTemplateDeclarations: MultiLine
|
||||
BinPackArguments: true
|
||||
BinPackParameters: true
|
||||
BraceWrapping:
|
||||
AfterCaseLabel: false
|
||||
AfterClass: false
|
||||
AfterControlStatement: false
|
||||
AfterEnum: false
|
||||
@@ -28,6 +33,7 @@ BraceWrapping:
|
||||
AfterObjCDeclaration: false
|
||||
AfterStruct: false
|
||||
AfterUnion: false
|
||||
AfterExternBlock: false
|
||||
BeforeCatch: false
|
||||
BeforeElse: false
|
||||
IndentBraces: false
|
||||
@@ -37,6 +43,7 @@ BraceWrapping:
|
||||
BreakBeforeBinaryOperators: None
|
||||
BreakBeforeBraces: Attach
|
||||
BreakBeforeInheritanceComma: false
|
||||
BreakInheritanceList: BeforeColon
|
||||
BreakBeforeTernaryOperators: true
|
||||
BreakConstructorInitializersBeforeComma: false
|
||||
BreakConstructorInitializers: BeforeColon
|
||||
@@ -57,6 +64,7 @@ ForEachMacros:
|
||||
- foreach
|
||||
- Q_FOREACH
|
||||
- BOOST_FOREACH
|
||||
IncludeBlocks: Preserve
|
||||
IncludeCategories:
|
||||
- Regex: '^"(llvm|llvm-c|clang|clang-c)/'
|
||||
Priority: 2
|
||||
@@ -66,6 +74,7 @@ IncludeCategories:
|
||||
Priority: 1
|
||||
IncludeIsMainRegex: '$'
|
||||
IndentCaseLabels: false
|
||||
IndentPPDirectives: AfterHash
|
||||
IndentWidth: 2
|
||||
IndentWrappedFunctionNames: false
|
||||
JavaScriptQuotes: Leave
|
||||
@@ -75,6 +84,7 @@ MacroBlockBegin: ''
|
||||
MacroBlockEnd: ''
|
||||
MaxEmptyLinesToKeep: 1
|
||||
NamespaceIndentation: None
|
||||
ObjCBinPackProtocolList: Auto
|
||||
ObjCBlockIndentWidth: 2
|
||||
ObjCSpaceAfterProperty: false
|
||||
ObjCSpaceBeforeProtocolList: true
|
||||
@@ -83,6 +93,7 @@ PenaltyBreakBeforeFirstCallParameter: 19
|
||||
PenaltyBreakComment: 300
|
||||
PenaltyBreakFirstLessLess: 120
|
||||
PenaltyBreakString: 1000
|
||||
PenaltyBreakTemplateDeclaration: 10
|
||||
PenaltyExcessCharacter: 1000000
|
||||
PenaltyReturnTypeOnItsOwnLine: 60
|
||||
PointerAlignment: Right
|
||||
@@ -90,9 +101,14 @@ ReflowComments: true
|
||||
SortIncludes: false
|
||||
SortUsingDeclarations: true
|
||||
SpaceAfterCStyleCast: false
|
||||
SpaceAfterLogicalNot: false
|
||||
SpaceAfterTemplateKeyword: true
|
||||
SpaceBeforeAssignmentOperators: true
|
||||
SpaceBeforeCpp11BracedList: false
|
||||
SpaceBeforeCtorInitializerColon: true
|
||||
SpaceBeforeInheritanceColon: true
|
||||
SpaceBeforeParens: ControlStatements
|
||||
SpaceBeforeRangeBasedForLoopColon: true
|
||||
SpaceInEmptyParentheses: false
|
||||
SpacesBeforeTrailingComments: 1
|
||||
SpacesInAngles: false
|
||||
@@ -101,6 +117,9 @@ SpacesInCStyleCastParentheses: false
|
||||
SpacesInParentheses: false
|
||||
SpacesInSquareBrackets: false
|
||||
Standard: Cpp11
|
||||
StatementMacros:
|
||||
- Q_UNUSED
|
||||
- QT_REQUIRE_VERSION
|
||||
TabWidth: 8
|
||||
UseTab: Never
|
||||
...
|
||||
|
||||
23
.github/workflows/fuzz.yml
vendored
Normal file
23
.github/workflows/fuzz.yml
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
name: CIFuzz
|
||||
on: [pull_request]
|
||||
jobs:
|
||||
Fuzzing:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Build Fuzzers
|
||||
uses: google/oss-fuzz/infra/cifuzz/actions/build_fuzzers@master
|
||||
with:
|
||||
oss-fuzz-project-name: 'nghttp2'
|
||||
dry-run: false
|
||||
- name: Run Fuzzers
|
||||
uses: google/oss-fuzz/infra/cifuzz/actions/run_fuzzers@master
|
||||
with:
|
||||
oss-fuzz-project-name: 'nghttp2'
|
||||
fuzz-seconds: 600
|
||||
dry-run: false
|
||||
- name: Upload Crash
|
||||
uses: actions/upload-artifact@v1
|
||||
if: failure()
|
||||
with:
|
||||
name: artifacts
|
||||
path: ./out/artifacts
|
||||
3
.gitmodules
vendored
3
.gitmodules
vendored
@@ -3,4 +3,5 @@
|
||||
url = https://github.com/mruby/mruby
|
||||
[submodule "third-party/neverbleed"]
|
||||
path = third-party/neverbleed
|
||||
url = https://github.com/h2o/neverbleed.git
|
||||
url = https://github.com/tatsuhiro-t/neverbleed.git
|
||||
branch = openssl111fix
|
||||
|
||||
70
.travis.yml
70
.travis.yml
@@ -1,19 +1,27 @@
|
||||
dist: trusty
|
||||
dist: xenial
|
||||
os:
|
||||
- linux
|
||||
compiler:
|
||||
- clang
|
||||
- gcc
|
||||
env:
|
||||
matrix:
|
||||
- CI_BUILD=cmake
|
||||
- CI_BUILD=autotools
|
||||
matrix:
|
||||
include:
|
||||
- os: osx
|
||||
compiler: clang
|
||||
osx_image: xcode10.2
|
||||
env: CI_BUILD=autotools
|
||||
language: cpp
|
||||
compiler:
|
||||
- clang
|
||||
- gcc
|
||||
sudo: required
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
packages:
|
||||
- g++-7
|
||||
- g++-8
|
||||
- autoconf
|
||||
- automake
|
||||
- autotools-dev
|
||||
@@ -30,24 +38,52 @@ addons:
|
||||
- libc-ares-dev
|
||||
- cmake
|
||||
- cmake-data
|
||||
homebrew:
|
||||
packages:
|
||||
- libev
|
||||
- libevent
|
||||
- c-ares
|
||||
- cunit
|
||||
- libressl
|
||||
before_install:
|
||||
- $CC --version
|
||||
- if [ "$CXX" = "g++" ]; then export CXX="g++-7" CC="gcc-7"; fi
|
||||
- if [ "$CXX" = "g++" ]; then export CXX="g++-8" CC="gcc-8"; fi
|
||||
- $CC --version
|
||||
- go version
|
||||
- cmake --version
|
||||
before_script:
|
||||
- |
|
||||
if [ "$TRAVIS_OS_NAME" = "linux" ]; then
|
||||
CPPFLAGS="-fsanitize=address" LDFLAGS="-fsanitize=address -fuse-ld=gold"
|
||||
fi
|
||||
- |
|
||||
if [ "$TRAVIS_OS_NAME" = "osx" ]; then
|
||||
PKG_CONFIG_PATH="/usr/local/opt/libressl/lib/pkgconfig:/usr/local/opt/libxml2/lib/pkgconfig"
|
||||
fi
|
||||
# Now build nghttp2
|
||||
- if [ "$CI_BUILD" = "autotools" ]; then autoreconf -i; fi
|
||||
- git submodule update --init
|
||||
- if [ "$CI_BUILD" = "autotools" ]; then ./configure --with-mruby; fi
|
||||
- if [ "$CI_BUILD" = "cmake" ]; then cmake -DENABLE_WERROR=1 -DWITH_MRUBY=1 -DWITH_NEVERBLEED=1; fi
|
||||
- |
|
||||
if [ "$CI_BUILD" = "autotools" ]; then
|
||||
autoreconf -i && ./configure --with-mruby PKG_CONFIG_PATH=$PKG_CONFIG_PATH
|
||||
fi
|
||||
- |
|
||||
if [ "$CI_BUILD" = "cmake" ]; then
|
||||
cmake -DENABLE_WERROR=1 -DWITH_MRUBY=1 -DWITH_NEVERBLEED=1
|
||||
fi
|
||||
script:
|
||||
- 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
|
||||
# As of April, 23, 2016, golang http2 build fails, probably because
|
||||
# the default go version is too old.
|
||||
# - cd integration-tests
|
||||
# - export GOPATH="$PWD/integration-tests/golang"
|
||||
# - make itprep
|
||||
# - make it
|
||||
- |
|
||||
if [ "$CI_BUILD" = "autotools" ]; then
|
||||
make distcheck DISTCHECK_CONFIGURE_FLAGS="--with-mruby --with-neverbleed --enable-werror CPPFLAGS=$CPPFLAGS LDFLAGS=\"$LDFLAGS\" PKG_CONFIG_PATH=$PKG_CONFIG_PATH"
|
||||
fi
|
||||
- |
|
||||
if [ "$CI_BUILD" = "cmake" ]; then
|
||||
make && make check
|
||||
fi
|
||||
- |
|
||||
if [ "$CI_BUILD" = "cmake" ]; then
|
||||
# Integration tests for nghttpx; autotools build erases build
|
||||
# for packaging test.
|
||||
cd integration-tests
|
||||
export GO111MODULE=on
|
||||
make it
|
||||
fi
|
||||
|
||||
21
AUTHORS
21
AUTHORS
@@ -14,12 +14,15 @@ github issues [2].
|
||||
--------
|
||||
|
||||
187j3x1
|
||||
Adam Gołębiowski
|
||||
Alek Storm
|
||||
Alex Nalivko
|
||||
Alexandros Konstantinakis-Karmis
|
||||
Alexis La Goutte
|
||||
Amir Pakdel
|
||||
Anders Bakken
|
||||
Andreas Pohl
|
||||
Andrew Penkrat
|
||||
Andy Davies
|
||||
Angus Gratton
|
||||
Anna Henningsen
|
||||
@@ -27,6 +30,7 @@ Ant Bryan
|
||||
Benedikt Christoph Wolters
|
||||
Benjamin Peterson
|
||||
Bernard Spil
|
||||
Brendan Heinonen
|
||||
Brian Card
|
||||
Brian Suh
|
||||
Daniel Evers
|
||||
@@ -35,18 +39,27 @@ Dave Reisner
|
||||
David Beitey
|
||||
David Weekly
|
||||
Dmitriy Vetutnev
|
||||
Don
|
||||
Dylan Plecki
|
||||
Etienne Cimon
|
||||
Fabian Möller
|
||||
Fabian Wiesel
|
||||
Gabi Davar
|
||||
Gaël PORTAY
|
||||
Geoff Hill
|
||||
Gitai
|
||||
Google Inc.
|
||||
Jacky Tian
|
||||
Jacob Champion
|
||||
James M Snell
|
||||
Jan Kundrát
|
||||
Jan-E
|
||||
Janusz Dziemidowicz
|
||||
Jay Satiro
|
||||
Jeff 'Raid' Baitis
|
||||
Jianqing Wang
|
||||
Jim Morrison
|
||||
Josh Braegger
|
||||
José F. Calcerrada
|
||||
Kamil Dudka
|
||||
Kazuho Oku
|
||||
@@ -55,6 +68,7 @@ Kenny Peng
|
||||
Kit Chan
|
||||
Kyle Schomp
|
||||
LazyHamster
|
||||
Leo Neat
|
||||
Lucas Pardue
|
||||
MATSUMOTO Ryosuke
|
||||
Marc Bachmann
|
||||
@@ -65,16 +79,19 @@ Mike Frysinger
|
||||
Mike Lothian
|
||||
Nicholas Hurley
|
||||
Nora Shoemaker
|
||||
Pedro Santos
|
||||
Peeyush Aggarwal
|
||||
Peter Wu
|
||||
Piotr Sikora
|
||||
Raul Gutierrez Segales
|
||||
Remo E
|
||||
Reza Tavakoli
|
||||
Richard Wolfert
|
||||
Rick Lei
|
||||
Ross Smith II
|
||||
Scott Mitchell
|
||||
Sebastiaan Deckers
|
||||
Simon Frankenberger
|
||||
Simone Basso
|
||||
Soham Sinha
|
||||
Stefan Eissing
|
||||
@@ -91,8 +108,10 @@ Tomasz Buchert
|
||||
Tomasz Torcz
|
||||
Vernon Tang
|
||||
Viacheslav Biriukov
|
||||
Viktor Szakats
|
||||
Viktor Szépe
|
||||
Wenfeng Liu
|
||||
William A Rowe Jr
|
||||
Xiaoguang Sun
|
||||
Zhuoyun Wei
|
||||
acesso
|
||||
@@ -100,8 +119,10 @@ ayanamist
|
||||
bxshi
|
||||
clemahieu
|
||||
dalf
|
||||
dawg
|
||||
es
|
||||
fangdingjun
|
||||
jwchoi
|
||||
kumagi
|
||||
lstefani
|
||||
makovich
|
||||
|
||||
@@ -24,13 +24,13 @@
|
||||
|
||||
cmake_minimum_required(VERSION 3.0)
|
||||
# XXX using 1.8.90 instead of 1.9.0-DEV
|
||||
project(nghttp2 VERSION 1.29.0)
|
||||
project(nghttp2 VERSION 1.41.0)
|
||||
|
||||
# See versioning rule:
|
||||
# http://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html
|
||||
set(LT_CURRENT 29)
|
||||
set(LT_REVISION 1)
|
||||
set(LT_AGE 15)
|
||||
set(LT_CURRENT 34)
|
||||
set(LT_REVISION 0)
|
||||
set(LT_AGE 20)
|
||||
|
||||
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH})
|
||||
include(Version)
|
||||
@@ -66,6 +66,7 @@ if(OPENSSL_FOUND AND LIBEV_FOUND AND ZLIB_FOUND)
|
||||
else()
|
||||
set(ENABLE_APP_DEFAULT OFF)
|
||||
endif()
|
||||
find_package(Systemd 209)
|
||||
find_package(Jansson 2.5)
|
||||
set(ENABLE_HPACK_TOOLS_DEFAULT ${JANSSON_FOUND})
|
||||
# 2.0.8 is required because we use evconnlistener_set_error_cb()
|
||||
@@ -117,7 +118,7 @@ else()
|
||||
endif()
|
||||
|
||||
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})
|
||||
if(_cxx1x_flag_supported)
|
||||
set(CXX1XCXXFLAGS ${_cxx1x_flag})
|
||||
@@ -193,6 +194,7 @@ endif()
|
||||
# libev (for src)
|
||||
set(HAVE_LIBEV ${LIBEV_FOUND})
|
||||
set(HAVE_ZLIB ${ZLIB_FOUND})
|
||||
set(HAVE_SYSTEMD ${SYSTEMD_FOUND})
|
||||
set(HAVE_LIBEVENT_OPENSSL ${LIBEVENT_FOUND})
|
||||
if(LIBEVENT_FOUND)
|
||||
# Must both link the core and openssl libraries.
|
||||
@@ -385,6 +387,15 @@ else()
|
||||
)
|
||||
endif()
|
||||
|
||||
if(ENABLE_STATIC_CRT)
|
||||
foreach(lang C CXX)
|
||||
foreach(suffix "" _DEBUG _MINSIZEREL _RELEASE _RELWITHDEBINFO)
|
||||
set(var "CMAKE_${lang}_FLAGS${suffix}")
|
||||
string(REPLACE "/MD" "/MT" ${var} "${${var}}")
|
||||
endforeach()
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
if(ENABLE_DEBUG)
|
||||
set(DEBUGBUILD 1)
|
||||
endif()
|
||||
@@ -497,6 +508,7 @@ message(STATUS "summary of build options:
|
||||
Jansson: ${HAVE_JANSSON} (LIBS='${JANSSON_LIBRARIES}')
|
||||
Jemalloc: ${HAVE_JEMALLOC} (LIBS='${JEMALLOC_LIBRARIES}')
|
||||
Zlib: ${HAVE_ZLIB} (LIBS='${ZLIB_LIBRARIES}')
|
||||
Systemd: ${HAVE_SYSTEMD} (LIBS='${SYSTEMD_LIBRARIES}')
|
||||
Boost::System: ${Boost_SYSTEM_LIBRARY}
|
||||
Boost::Thread: ${Boost_THREAD_LIBRARY}
|
||||
Third-party:
|
||||
|
||||
@@ -14,6 +14,9 @@ option(ENABLE_PYTHON_BINDINGS "Build Python bindings"
|
||||
${ENABLE_PYTHON_BINDINGS_DEFAULT})
|
||||
option(ENABLE_FAILMALLOC "Build failmalloc test program" ON)
|
||||
option(ENABLE_LIB_ONLY "Build libnghttp2 only. This is a short hand for -DENABLE_APP=0 -DENABLE_EXAMPLES=0 -DENABLE_HPACK_TOOLS=0 -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(ENABLE_STATIC_CRT "Build libnghttp2 against the MS LIBCMT[d]")
|
||||
|
||||
option(WITH_LIBXML2 "Use libxml2"
|
||||
${WITH_LIBXML2_DEFAULT})
|
||||
|
||||
17
README.rst
17
README.rst
@@ -145,8 +145,10 @@ minimizes the risk of private key leakage when serious bug like
|
||||
Heartbleed is exploited. The neverbleed is disabled by default. To
|
||||
enable it, use ``--with-neverbleed`` configure option.
|
||||
|
||||
In order to compile the source code, gcc >= 4.8.3 or clang >= 3.4 is
|
||||
required.
|
||||
Compiling libnghttp2 C source code requires a C99 compiler. gcc 4.8
|
||||
is known to be adequate. In order to compile the C++ source code, gcc
|
||||
>= 6.0 or clang >= 6.0 is required. C++ source code requires C++14
|
||||
language features.
|
||||
|
||||
.. note::
|
||||
|
||||
@@ -321,12 +323,7 @@ its testing framework. We depend on the following libraries:
|
||||
* golang.org/x/net/websocket
|
||||
* https://github.com/tatsuhiro-t/go-nghttp2
|
||||
|
||||
To download the above packages, after settings ``GOPATH``, run the
|
||||
following command under ``integration-tests`` directory:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
$ make itprep
|
||||
Go modules will download these dependencies automatically.
|
||||
|
||||
To run the tests, run the following command under
|
||||
``integration-tests`` directory:
|
||||
@@ -951,7 +948,7 @@ output_length
|
||||
The length of the compressed header block.
|
||||
|
||||
percentage_of_original_size
|
||||
``input_length`` / ``output_length`` * 100
|
||||
``output_length`` / ``input_length`` * 100
|
||||
|
||||
wire
|
||||
The compressed header block as a hex string.
|
||||
@@ -1332,7 +1329,7 @@ are:
|
||||
* Boost::Thread
|
||||
|
||||
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:
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
@@ -40,6 +40,9 @@ if(LIBEVENT_INCLUDE_DIR)
|
||||
# Libevent 2.0
|
||||
file(STRINGS "${LIBEVENT_INCLUDE_DIR}/event2/event-config.h"
|
||||
LIBEVENT_VERSION REGEX "${_version_regex}")
|
||||
if("${LIBEVENT_VERSION}" STREQUAL "")
|
||||
set(LIBEVENT_VERSION ${PC_LIBEVENT_VERSION})
|
||||
endif()
|
||||
else()
|
||||
# Libevent 1.4
|
||||
file(STRINGS "${LIBEVENT_INCLUDE_DIR}/event-config.h"
|
||||
|
||||
19
cmake/FindSystemd.cmake
Normal file
19
cmake/FindSystemd.cmake
Normal file
@@ -0,0 +1,19 @@
|
||||
# - Try to find systemd
|
||||
# Once done this will define
|
||||
# SYSTEMD_FOUND - System has systemd
|
||||
# SYSTEMD_INCLUDE_DIRS - The systemd include directories
|
||||
# SYSTEMD_LIBRARIES - The libraries needed to use systemd
|
||||
|
||||
include(FeatureSummary)
|
||||
set_package_properties(Systemd PROPERTIES
|
||||
URL "http://freedesktop.org/wiki/Software/systemd/"
|
||||
DESCRIPTION "System and Service Manager")
|
||||
|
||||
find_package(PkgConfig QUIET)
|
||||
pkg_check_modules(PC_SYSTEMD QUIET libsystemd)
|
||||
find_library(SYSTEMD_LIBRARIES NAMES systemd ${PC_SYSTEMD_LIBRARY_DIRS})
|
||||
find_path(SYSTEMD_INCLUDE_DIRS systemd/sd-login.h HINTS ${PC_SYSTEMD_INCLUDE_DIRS})
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(SYSTEMD DEFAULT_MSG SYSTEMD_INCLUDE_DIRS SYSTEMD_LIBRARIES)
|
||||
mark_as_advanced(SYSTEMD_INCLUDE_DIRS SYSTEMD_LIBRARIES)
|
||||
14
configure.ac
14
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
|
||||
|
||||
AC_PREREQ(2.61)
|
||||
AC_INIT([nghttp2], [1.29.0], [t-tujikawa@users.sourceforge.net])
|
||||
AC_INIT([nghttp2], [1.41.0], [t-tujikawa@users.sourceforge.net])
|
||||
AC_CONFIG_AUX_DIR([.])
|
||||
AC_CONFIG_MACRO_DIR([m4])
|
||||
AC_CONFIG_HEADERS([config.h])
|
||||
@@ -44,9 +44,9 @@ m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
|
||||
|
||||
dnl See versioning rule:
|
||||
dnl http://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html
|
||||
AC_SUBST(LT_CURRENT, 29)
|
||||
AC_SUBST(LT_REVISION, 1)
|
||||
AC_SUBST(LT_AGE, 15)
|
||||
AC_SUBST(LT_CURRENT, 34)
|
||||
AC_SUBST(LT_REVISION, 0)
|
||||
AC_SUBST(LT_AGE, 20)
|
||||
|
||||
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"`
|
||||
@@ -180,7 +180,7 @@ fi
|
||||
save_CXXFLAGS="$CXXFLAGS"
|
||||
CXXFLAGS=
|
||||
|
||||
AX_CXX_COMPILE_STDCXX_11([noext], [optional])
|
||||
AX_CXX_COMPILE_STDCXX([14], [noext], [optional])
|
||||
|
||||
CXX1XCXXFLAGS="$CXXFLAGS"
|
||||
CXXFLAGS="$save_CXXFLAGS"
|
||||
@@ -899,9 +899,9 @@ AC_MSG_NOTICE([summary of build options:
|
||||
Failmalloc: ${enable_failmalloc}
|
||||
Libs:
|
||||
OpenSSL: ${have_openssl} (CFLAGS='${OPENSSL_CFLAGS}' LIBS='${OPENSSL_LIBS}')
|
||||
Libxml2: ${have_libxml2} (CFLAGS='${LIBXML2_CPPFLAGS}' LIBS='${LIBXML2_LIBS}')
|
||||
Libxml2: ${have_libxml2} (CFLAGS='${LIBXML2_CFLAGS}' LIBS='${LIBXML2_LIBS}')
|
||||
Libev: ${have_libev} (CFLAGS='${LIBEV_CFLAGS}' LIBS='${LIBEV_LIBS}')
|
||||
Libc-ares ${have_libcares} (CFLAGS='${LIBCARES_CFLAGS}' LIBS='${LIBCARES_LIBS}')
|
||||
Libc-ares: ${have_libcares} (CFLAGS='${LIBCARES_CFLAGS}' LIBS='${LIBCARES_LIBS}')
|
||||
Libevent(SSL): ${have_libevent_openssl} (CFLAGS='${LIBEVENT_OPENSSL_CFLAGS}' LIBS='${LIBEVENT_OPENSSL_LIBS}')
|
||||
Jansson: ${have_jansson} (CFLAGS='${JANSSON_CFLAGS}' LIBS='${JANSSON_LIBS}')
|
||||
Jemalloc: ${have_jemalloc} (LIBS='${JEMALLOC_LIBS}')
|
||||
|
||||
@@ -42,6 +42,7 @@ set(APIDOCS
|
||||
nghttp2_option_set_no_recv_client_magic.rst
|
||||
nghttp2_option_set_peer_max_concurrent_streams.rst
|
||||
nghttp2_option_set_user_recv_extension_type.rst
|
||||
nghttp2_option_set_max_settings.rst
|
||||
nghttp2_pack_settings_payload.rst
|
||||
nghttp2_priority_spec_check_default.rst
|
||||
nghttp2_priority_spec_default_init.rst
|
||||
|
||||
@@ -27,6 +27,7 @@ APIDOCS= \
|
||||
macros.rst \
|
||||
enums.rst \
|
||||
types.rst \
|
||||
nghttp2_check_authority.rst \
|
||||
nghttp2_check_header_name.rst \
|
||||
nghttp2_check_header_value.rst \
|
||||
nghttp2_hd_deflate_bound.rst \
|
||||
@@ -67,6 +68,8 @@ APIDOCS= \
|
||||
nghttp2_option_set_no_recv_client_magic.rst \
|
||||
nghttp2_option_set_peer_max_concurrent_streams.rst \
|
||||
nghttp2_option_set_user_recv_extension_type.rst \
|
||||
nghttp2_option_set_max_outbound_ack.rst \
|
||||
nghttp2_option_set_max_settings.rst \
|
||||
nghttp2_pack_settings_payload.rst \
|
||||
nghttp2_priority_spec_check_default.rst \
|
||||
nghttp2_priority_spec_default_init.rst \
|
||||
@@ -143,6 +146,7 @@ APIDOCS= \
|
||||
nghttp2_session_set_local_window_size.rst \
|
||||
nghttp2_session_set_next_stream_id.rst \
|
||||
nghttp2_session_set_stream_user_data.rst \
|
||||
nghttp2_session_set_user_data.rst \
|
||||
nghttp2_session_terminate_session.rst \
|
||||
nghttp2_session_terminate_session2.rst \
|
||||
nghttp2_session_upgrade.rst \
|
||||
@@ -163,6 +167,7 @@ APIDOCS= \
|
||||
nghttp2_submit_extension.rst \
|
||||
nghttp2_submit_goaway.rst \
|
||||
nghttp2_submit_headers.rst \
|
||||
nghttp2_submit_origin.rst \
|
||||
nghttp2_submit_ping.rst \
|
||||
nghttp2_submit_priority.rst \
|
||||
nghttp2_submit_push_promise.rst \
|
||||
|
||||
@@ -8,7 +8,7 @@ _h2load()
|
||||
_get_comp_words_by_ref cur prev
|
||||
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 --warm-up-time --duration --header ' -- "$cur" ) )
|
||||
COMPREPLY=( $( compgen -W '--connection-window-bits --clients --verbose --ciphers --rate --no-tls-proto --connect-to --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
|
||||
|
||||
@@ -8,7 +8,7 @@ _nghttpx()
|
||||
_get_comp_words_by_ref cur prev
|
||||
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
|
||||
|
||||
33
doc/h2load.1
33
doc/h2load.1
@@ -1,6 +1,6 @@
|
||||
.\" Man page generated from reStructuredText.
|
||||
.
|
||||
.TH "H2LOAD" "1" "Dec 19, 2017" "1.29.0" "nghttp2"
|
||||
.TH "H2LOAD" "1" "Jun 02, 2020" "1.41.0" "nghttp2"
|
||||
.SH NAME
|
||||
h2load \- HTTP/2 benchmarking tool
|
||||
.
|
||||
@@ -155,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
|
||||
will run as it normally does, creating connections at
|
||||
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
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
@@ -170,7 +170,8 @@ option is 1s.
|
||||
.TP
|
||||
.B \-D, \-\-duration=<N>
|
||||
Specifies the main duration for the measurements in case
|
||||
of timing\-based benchmarking.
|
||||
of timing\-based benchmarking. \fI\%\-D\fP and \fI\%\-r\fP are mutually
|
||||
exclusive.
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
@@ -272,6 +273,23 @@ Default: \fB4K\fP
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.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 \-\-connect\-to=<HOST>[:<PORT>]
|
||||
Host and port to connect instead of using the authority
|
||||
in <URI>.
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \-v, \-\-verbose
|
||||
Output debug information.
|
||||
.UNINDENT
|
||||
@@ -376,13 +394,16 @@ range (mean +/\- sd) against total number of successful requests.
|
||||
.INDENT 7.0
|
||||
.TP
|
||||
.B min
|
||||
The minimum time taken to connect to a server.
|
||||
The minimum time taken to connect to a server including TLS
|
||||
handshake.
|
||||
.TP
|
||||
.B max
|
||||
The maximum time taken to connect to a server.
|
||||
The maximum time taken to connect to a server including TLS
|
||||
handshake.
|
||||
.TP
|
||||
.B mean
|
||||
The mean time taken to connect to a server.
|
||||
The mean time taken to connect to a server including TLS
|
||||
handshake.
|
||||
.TP
|
||||
.B sd
|
||||
The standard deviation of the time taken to connect to a server.
|
||||
|
||||
@@ -124,7 +124,7 @@ OPTIONS
|
||||
connections per period. When the rate is 0, the program
|
||||
will run as it normally does, creating connections at
|
||||
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>
|
||||
|
||||
@@ -137,7 +137,8 @@ OPTIONS
|
||||
.. option:: -D, --duration=<N>
|
||||
|
||||
Specifies the main duration for the measurements in case
|
||||
of timing-based benchmarking.
|
||||
of timing-based benchmarking. :option:`-D` and :option:`\-r` are mutually
|
||||
exclusive.
|
||||
|
||||
.. option:: --warm-up-time=<DURATION>
|
||||
|
||||
@@ -228,6 +229,21 @@ OPTIONS
|
||||
|
||||
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:: --connect-to=<HOST>[:<PORT>]
|
||||
|
||||
Host and port to connect instead of using the authority
|
||||
in <URI>.
|
||||
|
||||
.. option:: -v, --verbose
|
||||
|
||||
Output debug information.
|
||||
@@ -312,11 +328,14 @@ time for request
|
||||
|
||||
time for connect
|
||||
min
|
||||
The minimum time taken to connect to a server.
|
||||
The minimum time taken to connect to a server including TLS
|
||||
handshake.
|
||||
max
|
||||
The maximum time taken to connect to a server.
|
||||
The maximum time taken to connect to a server including TLS
|
||||
handshake.
|
||||
mean
|
||||
The mean time taken to connect to a server.
|
||||
The mean time taken to connect to a server including TLS
|
||||
handshake.
|
||||
sd
|
||||
The standard deviation of the time taken to connect to a server.
|
||||
+/- sd
|
||||
|
||||
@@ -60,11 +60,14 @@ time for request
|
||||
|
||||
time for connect
|
||||
min
|
||||
The minimum time taken to connect to a server.
|
||||
The minimum time taken to connect to a server including TLS
|
||||
handshake.
|
||||
max
|
||||
The maximum time taken to connect to a server.
|
||||
The maximum time taken to connect to a server including TLS
|
||||
handshake.
|
||||
mean
|
||||
The mean time taken to connect to a server.
|
||||
The mean time taken to connect to a server including TLS
|
||||
handshake.
|
||||
sd
|
||||
The standard deviation of the time taken to connect to a server.
|
||||
+/- sd
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
.\" Man page generated from reStructuredText.
|
||||
.
|
||||
.TH "NGHTTP" "1" "Dec 19, 2017" "1.29.0" "nghttp2"
|
||||
.TH "NGHTTP" "1" "Jun 02, 2020" "1.41.0" "nghttp2"
|
||||
.SH NAME
|
||||
nghttp \- HTTP/2 client
|
||||
.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
.\" Man page generated from reStructuredText.
|
||||
.
|
||||
.TH "NGHTTPD" "1" "Dec 19, 2017" "1.29.0" "nghttp2"
|
||||
.TH "NGHTTPD" "1" "Jun 02, 2020" "1.41.0" "nghttp2"
|
||||
.SH NAME
|
||||
nghttpd \- HTTP/2 server
|
||||
.
|
||||
|
||||
177
doc/nghttpx.1
177
doc/nghttpx.1
@@ -1,6 +1,6 @@
|
||||
.\" Man page generated from reStructuredText.
|
||||
.
|
||||
.TH "NGHTTPX" "1" "Dec 19, 2017" "1.29.0" "nghttp2"
|
||||
.TH "NGHTTPX" "1" "Jun 02, 2020" "1.41.0" "nghttp2"
|
||||
.SH NAME
|
||||
nghttpx \- HTTP/2 proxy
|
||||
.
|
||||
@@ -137,7 +137,10 @@ Several parameters <PARAM> are accepted after <PATTERN>.
|
||||
The parameters are delimited by ";". The available
|
||||
parameters are: "proto=<PROTO>", "tls",
|
||||
"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
|
||||
followed by "=" and value. For example, the parameter
|
||||
"proto=h2" consists of the keyword "proto" and value
|
||||
@@ -228,6 +231,51 @@ the same <PATTERN>. It is advised to set
|
||||
"redirect\-if\-no\-tls" parameter to all backends
|
||||
explicitly if this feature is desired.
|
||||
.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
|
||||
not contain these characters. Since ";" has special
|
||||
meaning in shell, the option value must be quoted.
|
||||
@@ -268,7 +316,7 @@ specify "healthmon" parameter. This is disabled by
|
||||
default. Any requests which come through this address
|
||||
are replied with 200 HTTP status, without no body.
|
||||
.sp
|
||||
To accept PROXY protocol version 1 on frontend
|
||||
To accept PROXY protocol version 1 and 2 on frontend
|
||||
connection, specify "proxyproto" parameter. This is
|
||||
disabled by default.
|
||||
.sp
|
||||
@@ -588,19 +636,43 @@ Default: \fB2m\fP
|
||||
.B \-\-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.2 or earlier.
|
||||
Use \fI\%\-\-tls13\-ciphers\fP for TLSv1.3.
|
||||
.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
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.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>
|
||||
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.2 or earlier.
|
||||
Use \fI\%\-\-tls13\-client\-ciphers\fP for TLSv1.3.
|
||||
.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
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.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>
|
||||
Set supported curve list for frontend connections.
|
||||
<LIST> is a colon separated list of curve NID or names
|
||||
@@ -691,6 +763,14 @@ can contain multiple certificates.
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.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>
|
||||
Path to file that contains client private key used in
|
||||
backend client authentication.
|
||||
@@ -714,7 +794,7 @@ than TLSv1.2 is specified, make sure that the compatible
|
||||
ciphers are included in \fI\%\-\-ciphers\fP option. The default
|
||||
cipher list only includes ciphers compatible with
|
||||
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
|
||||
Default: \fBTLSv1.2\fP
|
||||
.UNINDENT
|
||||
@@ -727,9 +807,9 @@ done in case\-insensitive manner. The versions between
|
||||
enabled. If the protocol list advertised by client does
|
||||
not overlap this range, you will receive the error
|
||||
message "unknown protocol". The available versions are:
|
||||
TLSv1.2, TLSv1.1, and TLSv1.0
|
||||
TLSv1.3, TLSv1.2, TLSv1.1, and TLSv1.0
|
||||
.sp
|
||||
Default: \fBTLSv1.2\fP
|
||||
Default: \fBTLSv1.3\fP
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
@@ -982,6 +1062,24 @@ HTTP/2. To use those cipher suites with HTTP/2,
|
||||
consider to use \fI\%\-\-client\-no\-http2\-cipher\-black\-list\fP
|
||||
option. But be aware its implications.
|
||||
.UNINDENT
|
||||
.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
|
||||
.TP
|
||||
@@ -989,7 +1087,7 @@ option. But be aware its implications.
|
||||
Set the maximum number of the concurrent streams in one
|
||||
frontend HTTP/2 session.
|
||||
.sp
|
||||
Default: \(ga\(ga 100\(ga\(ga
|
||||
Default: \fB100\fP
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
@@ -1345,6 +1443,12 @@ is received, it is left unaltered.
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.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
|
||||
Don\(aqt rewrite location header field in default mode.
|
||||
When \fI\%\-\-http2\-proxy\fP is used, location header field will
|
||||
@@ -1562,6 +1666,13 @@ signal handling feature is disabled.
|
||||
.B \-\-mruby\-file=<PATH>
|
||||
Set mruby script file
|
||||
.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
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
@@ -1919,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
|
||||
response without forwarding request to backend servers.
|
||||
.sp
|
||||
To specify mruby script file, use \fI\%\-\-mruby\-file\fP option. The
|
||||
script will be evaluated once per thread on startup, and it must
|
||||
instantiate object and evaluate it as the return value (e.g.,
|
||||
There are 2 levels of mruby script invocations: global and
|
||||
per\-pattern. The global mruby script is set by \fI\%\-\-mruby\-file\fP
|
||||
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
|
||||
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
|
||||
@@ -2023,6 +2153,18 @@ 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
|
||||
@@ -2046,6 +2188,15 @@ Return true if, and only if a SSL/TLS session is reused.
|
||||
.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
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
@@ -2197,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
|
||||
hook, response from backend server is canceled and discarded.
|
||||
The status code and response header fields should be set
|
||||
before using this method. To set status code, use :rb:meth To
|
||||
set response header fields, use
|
||||
before using this method. To set status code, use
|
||||
\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
|
||||
invoked in response phase hook, the response headers are
|
||||
filled with the ones received from backend server. To send
|
||||
|
||||
@@ -121,7 +121,10 @@ Connections
|
||||
The parameters are delimited by ";". The available
|
||||
parameters are: "proto=<PROTO>", "tls",
|
||||
"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
|
||||
followed by "=" and value. For example, the parameter
|
||||
"proto=h2" consists of the keyword "proto" and value
|
||||
@@ -212,6 +215,51 @@ Connections
|
||||
"redirect-if-no-tls" parameter to all backends
|
||||
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
|
||||
not contain these characters. Since ";" has special
|
||||
meaning in shell, the option value must be quoted.
|
||||
@@ -252,7 +300,7 @@ Connections
|
||||
default. Any requests which come through this address
|
||||
are replied with 200 HTTP status, without no body.
|
||||
|
||||
To accept PROXY protocol version 1 on frontend
|
||||
To accept PROXY protocol version 1 and 2 on frontend
|
||||
connection, specify "proxyproto" parameter. This is
|
||||
disabled by default.
|
||||
|
||||
@@ -546,16 +594,38 @@ SSL/TLS
|
||||
|
||||
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.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``
|
||||
|
||||
.. 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>
|
||||
|
||||
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.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``
|
||||
|
||||
.. 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>
|
||||
|
||||
Set supported curve list for frontend connections.
|
||||
@@ -637,6 +707,13 @@ SSL/TLS
|
||||
client certificate. The file must be in PEM format. It
|
||||
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>
|
||||
|
||||
Path to file that contains client private key used in
|
||||
@@ -659,7 +736,7 @@ SSL/TLS
|
||||
ciphers are included in :option:`--ciphers` option. The default
|
||||
cipher list only includes ciphers compatible with
|
||||
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``
|
||||
|
||||
@@ -671,9 +748,9 @@ SSL/TLS
|
||||
enabled. If the protocol list advertised by client does
|
||||
not overlap this range, you will receive the error
|
||||
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>
|
||||
|
||||
@@ -901,6 +978,22 @@ SSL/TLS
|
||||
consider to use :option:`--client-no-http2-cipher-black-list`
|
||||
option. But be aware its implications.
|
||||
|
||||
.. option:: --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.
|
||||
|
||||
.. option:: --tls-max-early-data=<SIZE>
|
||||
|
||||
Sets the maximum amount of 0-RTT data that server
|
||||
accepts.
|
||||
|
||||
Default: ``16K``
|
||||
|
||||
|
||||
HTTP/2
|
||||
~~~~~~
|
||||
@@ -910,7 +1003,7 @@ HTTP/2
|
||||
Set the maximum number of the concurrent streams in one
|
||||
frontend HTTP/2 session.
|
||||
|
||||
Default: `` 100``
|
||||
Default: ``100``
|
||||
|
||||
.. option:: --backend-http2-max-concurrent-streams=<N>
|
||||
|
||||
@@ -1217,6 +1310,11 @@ HTTP
|
||||
Don't append to Via header field. If Via header field
|
||||
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
|
||||
|
||||
Don't rewrite location header field in default mode.
|
||||
@@ -1425,6 +1523,12 @@ Scripting
|
||||
|
||||
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
|
||||
~~~~
|
||||
@@ -1763,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
|
||||
response without forwarding request to backend servers.
|
||||
|
||||
To specify mruby script file, use :option:`--mruby-file` option. The
|
||||
script will be evaluated once per thread on startup, and it must
|
||||
instantiate object and evaluate it as the return value (e.g.,
|
||||
There are 2 levels of mruby script invocations: global and
|
||||
per-pattern. The global mruby script is set by :option:`--mruby-file`
|
||||
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
|
||||
defines ``on_req`` method, it is called with :rb:class:`Nghttpx::Env`
|
||||
object on request hook. Similarly, if app object defines ``on_resp``
|
||||
@@ -1852,6 +1975,16 @@ respectively.
|
||||
|
||||
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.
|
||||
@@ -1872,6 +2005,14 @@ respectively.
|
||||
|
||||
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
|
||||
|
||||
Object to represent request from client. The modification to
|
||||
@@ -2002,10 +2143,10 @@ respectively.
|
||||
not be invoked. When this method is called in response phase
|
||||
hook, response from backend server is canceled and discarded.
|
||||
The status code and response header fields should be set
|
||||
before using this method. To set status code, use :rb:meth To
|
||||
set response header fields, use
|
||||
before using this method. To set status code, use
|
||||
: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
|
||||
invoked in response phase hook, the response headers are
|
||||
filled with the ones received from backend server. To send
|
||||
|
||||
@@ -299,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
|
||||
response without forwarding request to backend servers.
|
||||
|
||||
To specify mruby script file, use :option:`--mruby-file` option. The
|
||||
script will be evaluated once per thread on startup, and it must
|
||||
instantiate object and evaluate it as the return value (e.g.,
|
||||
There are 2 levels of mruby script invocations: global and
|
||||
per-pattern. The global mruby script is set by :option:`--mruby-file`
|
||||
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
|
||||
defines ``on_req`` method, it is called with :rb:class:`Nghttpx::Env`
|
||||
object on request hook. Similarly, if app object defines ``on_resp``
|
||||
@@ -388,6 +407,16 @@ respectively.
|
||||
|
||||
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.
|
||||
@@ -408,6 +437,14 @@ respectively.
|
||||
|
||||
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
|
||||
|
||||
Object to represent request from client. The modification to
|
||||
@@ -538,10 +575,10 @@ respectively.
|
||||
not be invoked. When this method is called in response phase
|
||||
hook, response from backend server is canceled and discarded.
|
||||
The status code and response header fields should be set
|
||||
before using this method. To set status code, use :rb:meth To
|
||||
set response header fields, use
|
||||
before using this method. To set status code, use
|
||||
: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
|
||||
invoked in response phase hook, the response headers are
|
||||
filled with the ones received from backend server. To send
|
||||
|
||||
@@ -110,9 +110,9 @@ HTTP Messaging
|
||||
|
||||
By default, nghttp2 library checks HTTP messaging rules described in
|
||||
`HTTP/2 specification, section 8
|
||||
<https://tools.ietf.org/html/draft-ietf-httpbis-http2-17#section-8>`_.
|
||||
Everything described in that section is not validated however. We
|
||||
briefly describe what the library does in this area. In the following
|
||||
<https://tools.ietf.org/html/rfc7540#section-8>`_. Everything
|
||||
described in that section is not validated however. We briefly
|
||||
describe what the library does in this area. In the following
|
||||
description, without loss of generality we omit CONTINUATION frame
|
||||
since they must follow HEADERS frame and are processed atomically. In
|
||||
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()`.
|
||||
|
||||
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
|
||||
|
||||
|
||||
@@ -26,16 +26,16 @@ Coding style
|
||||
We use clang-format to format source code consistently. The
|
||||
clang-format configuration file .clang-format is located at the root
|
||||
directory. Since clang-format produces slightly different results
|
||||
between versions, we currently use clang-format-5.0.
|
||||
between versions, we currently use clang-format-9.
|
||||
|
||||
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.
|
||||
The pre-commit file is located at the root directory. Copy it under
|
||||
.git/hooks and make sure that it is executable. The pre-commit script
|
||||
uses clang-format-diff.py to detect any style errors. If it is not in
|
||||
your PATH or it exists under different name (e.g.,
|
||||
clang-format-diff-5.0 in debian), either add it to PATH variable or
|
||||
add git option ``clangformatdiff.binary`` to point to the script.
|
||||
your PATH or it exists under different name (e.g., clang-format-diff-9
|
||||
in debian), either add it to PATH variable or add git option
|
||||
``clangformatdiff.binary`` to point to the script.
|
||||
|
||||
For emacs users, integrating clang-format to emacs is very easy.
|
||||
clang-format.el should come with clang distribution. If it is not
|
||||
|
||||
@@ -401,6 +401,9 @@ like so:
|
||||
|
||||
frontend=*,443;proxyproto
|
||||
|
||||
nghttpx supports both PROXY protocol v1 and v2. AF_UNIX in PROXY
|
||||
protocol version 2 is ignored.
|
||||
|
||||
Session affinity
|
||||
----------------
|
||||
|
||||
@@ -471,6 +474,41 @@ 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
|
||||
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.
|
||||
|
||||
WebSockets over HTTP/2
|
||||
----------------------
|
||||
|
||||
nghttpx supports `RFC 8441 <https://tools.ietf.org/html/rfc8441>`_
|
||||
Bootstrapping WebSockets with HTTP/2 for both frontend and backend
|
||||
connections. This feature is enabled by default and no configuration
|
||||
is required.
|
||||
|
||||
Migration from nghttpx v1.18.x or earlier
|
||||
-----------------------------------------
|
||||
|
||||
|
||||
@@ -422,7 +422,7 @@ the ``on_header_callback()`` is called for each name/value pair::
|
||||
return 0;
|
||||
}
|
||||
|
||||
In this tutorial, we just print the name/value pairs on stdout.
|
||||
In this tutorial, we just print the name/value pairs on stderr.
|
||||
|
||||
After the HEADERS frame has been fully received (and thus all response
|
||||
header name/value pairs have been received), the
|
||||
|
||||
@@ -9,6 +9,7 @@ if(ENABLE_EXAMPLES)
|
||||
include_directories(
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/../third-party"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/../third-party/llhttp/include"
|
||||
|
||||
${LIBEVENT_INCLUDE_DIRS}
|
||||
${OPENSSL_INCLUDE_DIRS}
|
||||
@@ -21,14 +22,24 @@ if(ENABLE_EXAMPLES)
|
||||
${APP_LIBRARIES}
|
||||
)
|
||||
|
||||
add_executable(client client.c $<TARGET_OBJECTS:http-parser>)
|
||||
add_executable(libevent-client libevent-client.c $<TARGET_OBJECTS:http-parser>)
|
||||
add_executable(libevent-server libevent-server.c $<TARGET_OBJECTS:http-parser>)
|
||||
add_executable(deflate deflate.c $<TARGET_OBJECTS:http-parser>)
|
||||
add_executable(client client.c $<TARGET_OBJECTS:llhttp>
|
||||
$<TARGET_OBJECTS:url-parser>
|
||||
)
|
||||
add_executable(libevent-client libevent-client.c $<TARGET_OBJECTS:llhttp>
|
||||
$<TARGET_OBJECTS:url-parser>
|
||||
)
|
||||
add_executable(libevent-server libevent-server.c $<TARGET_OBJECTS:llhttp>
|
||||
$<TARGET_OBJECTS:url-parser>
|
||||
)
|
||||
add_executable(deflate deflate.c $<TARGET_OBJECTS:llhttp>
|
||||
$<TARGET_OBJECTS:url-parser>
|
||||
)
|
||||
|
||||
if(ENABLE_ASIO_LIB)
|
||||
foreach(name asio-sv asio-sv2 asio-cl asio-cl2)
|
||||
add_executable(${name} ${name}.cc $<TARGET_OBJECTS:http-parser>)
|
||||
add_executable(${name} ${name}.cc $<TARGET_OBJECTS:llhttp>
|
||||
$<TARGET_OBJECTS:url-parser>
|
||||
)
|
||||
target_include_directories(${name} PRIVATE
|
||||
${OPENSSL_INCLUDE_DIRS}
|
||||
${Boost_INCLUDE_DIRS}
|
||||
|
||||
@@ -36,7 +36,7 @@ AM_CPPFLAGS = \
|
||||
@OPENSSL_CFLAGS@ \
|
||||
@DEFS@
|
||||
LDADD = $(top_builddir)/lib/libnghttp2.la \
|
||||
$(top_builddir)/third-party/libhttp-parser.la \
|
||||
$(top_builddir)/third-party/liburl-parser.la \
|
||||
@LIBEVENT_OPENSSL_LIBS@ \
|
||||
@OPENSSL_LIBS@ \
|
||||
@APPLDFLAGS@
|
||||
@@ -61,7 +61,7 @@ noinst_PROGRAMS += asio-sv asio-sv2 asio-cl asio-cl2
|
||||
ASIOCPPFLAGS = ${AM_CPPFLAGS} ${BOOST_CPPFLAGS}
|
||||
ASIOLDADD = $(top_builddir)/lib/libnghttp2.la \
|
||||
$(top_builddir)/src/libnghttp2_asio.la @JEMALLOC_LIBS@ \
|
||||
$(top_builddir)/third-party/libhttp-parser.la \
|
||||
$(top_builddir)/third-party/liburl-parser.la \
|
||||
@OPENSSL_LIBS@ \
|
||||
${BOOST_LDFLAGS} \
|
||||
${BOOST_ASIO_LIB} \
|
||||
|
||||
@@ -67,14 +67,14 @@ int main(int argc, char *argv[]) {
|
||||
return;
|
||||
}
|
||||
|
||||
req->on_response([&sess](const response &res) {
|
||||
req->on_response([](const response &res) {
|
||||
std::cerr << "HTTP/2 " << res.status_code() << std::endl;
|
||||
for (auto &kv : res.header()) {
|
||||
std::cerr << kv.first << ": " << kv.second.value << "\n";
|
||||
}
|
||||
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 << std::endl;
|
||||
});
|
||||
|
||||
@@ -91,17 +91,17 @@ int main(int argc, char *argv[]) {
|
||||
return;
|
||||
}
|
||||
|
||||
req->on_response([&sess, req](const response &res) {
|
||||
req->on_response([](const response &res) {
|
||||
std::cerr << "response header was received" << std::endl;
|
||||
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 << 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;
|
||||
});
|
||||
|
||||
|
||||
@@ -36,10 +36,10 @@
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
# include <unistd.h>
|
||||
#endif // HAVE_UNISTD_H
|
||||
#ifdef HAVE_FCNTL_H
|
||||
#include <fcntl.h>
|
||||
# include <fcntl.h>
|
||||
#endif // HAVE_FCNTL_H
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
@@ -27,26 +27,26 @@
|
||||
* intentionally made simple.
|
||||
*/
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
# include <config.h>
|
||||
#endif /* HAVE_CONFIG_H */
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <stdlib.h>
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
# include <unistd.h>
|
||||
#endif /* HAVE_UNISTD_H */
|
||||
#ifdef HAVE_FCNTL_H
|
||||
#include <fcntl.h>
|
||||
# include <fcntl.h>
|
||||
#endif /* HAVE_FCNTL_H */
|
||||
#include <sys/types.h>
|
||||
#ifdef HAVE_SYS_SOCKET_H
|
||||
#include <sys/socket.h>
|
||||
# include <sys/socket.h>
|
||||
#endif /* HAVE_SYS_SOCKET_H */
|
||||
#ifdef HAVE_NETDB_H
|
||||
#include <netdb.h>
|
||||
# include <netdb.h>
|
||||
#endif /* HAVE_NETDB_H */
|
||||
#ifdef HAVE_NETINET_IN_H
|
||||
#include <netinet/in.h>
|
||||
# include <netinet/in.h>
|
||||
#endif /* HAVE_NETINET_IN_H */
|
||||
#include <netinet/tcp.h>
|
||||
#include <poll.h>
|
||||
@@ -345,6 +345,7 @@ static void setup_nghttp2_callbacks(nghttp2_session_callbacks *callbacks) {
|
||||
callbacks, on_data_chunk_recv_callback);
|
||||
}
|
||||
|
||||
#ifndef OPENSSL_NO_NEXTPROTONEG
|
||||
/*
|
||||
* Callback function for TLS NPN. Since this program only supports
|
||||
* 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;
|
||||
}
|
||||
#endif /* !OPENSSL_NO_NEXTPROTONEG */
|
||||
|
||||
/*
|
||||
* 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_RELEASE_BUFFERS);
|
||||
/* Set NPN callback */
|
||||
#ifndef OPENSSL_NO_NEXTPROTONEG
|
||||
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) {
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
# include <config.h>
|
||||
#endif /* !HAVE_CONFIG_H */
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
@@ -23,33 +23,33 @@
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#ifdef __sgi
|
||||
#include <string.h>
|
||||
#define errx(exitcode, format, args...) \
|
||||
{ \
|
||||
warnx(format, ##args); \
|
||||
exit(exitcode); \
|
||||
}
|
||||
#define warnx(format, args...) fprintf(stderr, format "\n", ##args)
|
||||
# include <string.h>
|
||||
# define errx(exitcode, format, args...) \
|
||||
{ \
|
||||
warnx(format, ##args); \
|
||||
exit(exitcode); \
|
||||
}
|
||||
# define warnx(format, args...) fprintf(stderr, format "\n", ##args)
|
||||
char *strndup(const char *s, size_t size);
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
# include <config.h>
|
||||
#endif /* HAVE_CONFIG_H */
|
||||
|
||||
#include <sys/types.h>
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
# include <unistd.h>
|
||||
#endif /* HAVE_UNISTD_H */
|
||||
#ifdef HAVE_SYS_SOCKET_H
|
||||
#include <sys/socket.h>
|
||||
# include <sys/socket.h>
|
||||
#endif /* HAVE_SYS_SOCKET_H */
|
||||
#ifdef HAVE_NETINET_IN_H
|
||||
#include <netinet/in.h>
|
||||
# include <netinet/in.h>
|
||||
#endif /* HAVE_NETINET_IN_H */
|
||||
#include <netinet/tcp.h>
|
||||
#ifndef __sgi
|
||||
#include <err.h>
|
||||
# include <err.h>
|
||||
#endif
|
||||
#include <signal.h>
|
||||
#include <string.h>
|
||||
@@ -65,7 +65,7 @@ char *strndup(const char *s, size_t size);
|
||||
|
||||
#include <nghttp2/nghttp2.h>
|
||||
|
||||
#include "http-parser/http_parser.h"
|
||||
#include "url-parser/url_parser.h"
|
||||
|
||||
#define ARRLEN(x) (sizeof(x) / sizeof(x[0]))
|
||||
|
||||
@@ -308,6 +308,7 @@ static int on_stream_close_callback(nghttp2_session *session, int32_t stream_id,
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifndef OPENSSL_NO_NEXTPROTONEG
|
||||
/* NPN TLS extension client callback. We check that server advertised
|
||||
the HTTP/2 protocol the nghttp2 library supports. If not, exit
|
||||
the program. */
|
||||
@@ -322,6 +323,7 @@ static int select_next_proto_cb(SSL *ssl, unsigned char **out,
|
||||
}
|
||||
return SSL_TLSEXT_ERR_OK;
|
||||
}
|
||||
#endif /* !OPENSSL_NO_NEXTPROTONEG */
|
||||
|
||||
/* Create SSL_CTX. */
|
||||
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_NO_COMPRESSION |
|
||||
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);
|
||||
#endif /* !OPENSSL_NO_NEXTPROTONEG */
|
||||
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x10002000L
|
||||
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;
|
||||
}
|
||||
@@ -504,12 +508,14 @@ static void eventcb(struct bufferevent *bev, short events, void *ptr) {
|
||||
|
||||
ssl = bufferevent_openssl_get_ssl(session_data->bev);
|
||||
|
||||
#ifndef OPENSSL_NO_NEXTPROTONEG
|
||||
SSL_get0_next_proto_negotiated(ssl, &alpn, &alpnlen);
|
||||
#endif /* !OPENSSL_NO_NEXTPROTONEG */
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x10002000L
|
||||
if (alpn == NULL) {
|
||||
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) {
|
||||
fprintf(stderr, "h2 is not negotiated\n");
|
||||
|
||||
@@ -23,41 +23,41 @@
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#ifdef __sgi
|
||||
#define errx(exitcode, format, args...) \
|
||||
{ \
|
||||
warnx(format, ##args); \
|
||||
exit(exitcode); \
|
||||
}
|
||||
#define warn(format, args...) warnx(format ": %s", ##args, strerror(errno))
|
||||
#define warnx(format, args...) fprintf(stderr, format "\n", ##args)
|
||||
# define errx(exitcode, format, args...) \
|
||||
{ \
|
||||
warnx(format, ##args); \
|
||||
exit(exitcode); \
|
||||
}
|
||||
# define warn(format, args...) warnx(format ": %s", ##args, strerror(errno))
|
||||
# define warnx(format, args...) fprintf(stderr, format "\n", ##args)
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
# include <config.h>
|
||||
#endif /* HAVE_CONFIG_H */
|
||||
|
||||
#include <sys/types.h>
|
||||
#ifdef HAVE_SYS_SOCKET_H
|
||||
#include <sys/socket.h>
|
||||
# include <sys/socket.h>
|
||||
#endif /* HAVE_SYS_SOCKET_H */
|
||||
#ifdef HAVE_NETDB_H
|
||||
#include <netdb.h>
|
||||
# include <netdb.h>
|
||||
#endif /* HAVE_NETDB_H */
|
||||
#include <signal.h>
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
# include <unistd.h>
|
||||
#endif /* HAVE_UNISTD_H */
|
||||
#include <sys/stat.h>
|
||||
#ifdef HAVE_FCNTL_H
|
||||
#include <fcntl.h>
|
||||
# include <fcntl.h>
|
||||
#endif /* HAVE_FCNTL_H */
|
||||
#include <ctype.h>
|
||||
#ifdef HAVE_NETINET_IN_H
|
||||
#include <netinet/in.h>
|
||||
# include <netinet/in.h>
|
||||
#endif /* HAVE_NETINET_IN_H */
|
||||
#include <netinet/tcp.h>
|
||||
#ifndef __sgi
|
||||
#include <err.h>
|
||||
# include <err.h>
|
||||
#endif
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
@@ -109,6 +109,7 @@ struct app_context {
|
||||
static unsigned char next_proto_list[256];
|
||||
static size_t next_proto_list_len;
|
||||
|
||||
#ifndef OPENSSL_NO_NEXTPROTONEG
|
||||
static int next_proto_cb(SSL *ssl, const unsigned char **data,
|
||||
unsigned int *len, void *arg) {
|
||||
(void)ssl;
|
||||
@@ -118,6 +119,7 @@ static int next_proto_cb(SSL *ssl, const unsigned char **data,
|
||||
*len = (unsigned int)next_proto_list_len;
|
||||
return SSL_TLSEXT_ERR_OK;
|
||||
}
|
||||
#endif /* !OPENSSL_NO_NEXTPROTONEG */
|
||||
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x10002000L
|
||||
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;
|
||||
}
|
||||
#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L
|
||||
#endif /* OPENSSL_VERSION_NUMBER >= 0x10002000L */
|
||||
|
||||
/* Create SSL_CTX. */
|
||||
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);
|
||||
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);
|
||||
#endif /* !OPENSSL_NO_NEXTPROTONEG */
|
||||
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x10002000L
|
||||
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;
|
||||
}
|
||||
@@ -690,12 +694,14 @@ static void eventcb(struct bufferevent *bev, short events, void *ptr) {
|
||||
|
||||
ssl = bufferevent_openssl_get_ssl(session_data->bev);
|
||||
|
||||
#ifndef OPENSSL_NO_NEXTPROTONEG
|
||||
SSL_get0_next_proto_negotiated(ssl, &alpn, &alpnlen);
|
||||
#endif /* !OPENSSL_NO_NEXTPROTONEG */
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x10002000L
|
||||
if (alpn == NULL) {
|
||||
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) {
|
||||
fprintf(stderr, "%s h2 is not negotiated\n", session_data->client_addr);
|
||||
|
||||
@@ -9,6 +9,7 @@ HEADERS = [
|
||||
':scheme',
|
||||
':status',
|
||||
':host', # for spdy
|
||||
':protocol',
|
||||
'expect',
|
||||
'host',
|
||||
'if-modified-since',
|
||||
@@ -31,6 +32,9 @@ HEADERS = [
|
||||
"user-agent",
|
||||
"date",
|
||||
"content-type",
|
||||
"early-data",
|
||||
"sec-websocket-accept",
|
||||
"sec-websocket-key",
|
||||
# disallowed h1 headers
|
||||
'connection',
|
||||
'keep-alive',
|
||||
@@ -40,4 +44,4 @@ HEADERS = [
|
||||
]
|
||||
|
||||
if __name__ == '__main__':
|
||||
gentokenlookup(HEADERS, 'HD')
|
||||
gentokenlookup(HEADERS, 'HD_')
|
||||
|
||||
@@ -67,6 +67,7 @@ HEADERS = [
|
||||
('keep-alive',None),
|
||||
('proxy-connection', None),
|
||||
('upgrade', None),
|
||||
(':protocol', None),
|
||||
]
|
||||
|
||||
def to_enum_hd(k):
|
||||
|
||||
@@ -4,42 +4,42 @@ from io import StringIO
|
||||
|
||||
from gentokenlookup import gentokenlookup
|
||||
|
||||
# copied from http-parser/http_parser.h, and stripped trailing spaces
|
||||
# and backslashes.
|
||||
# copied from llhttp.h, and stripped trailing spaces and backslashes.
|
||||
SRC = '''
|
||||
XX(0, DELETE, DELETE)
|
||||
XX(1, GET, GET)
|
||||
XX(2, HEAD, HEAD)
|
||||
XX(3, POST, POST)
|
||||
XX(4, PUT, PUT)
|
||||
/* pathological */
|
||||
XX(5, CONNECT, CONNECT)
|
||||
XX(6, OPTIONS, OPTIONS)
|
||||
XX(7, TRACE, TRACE)
|
||||
/* webdav */
|
||||
XX(8, COPY, COPY)
|
||||
XX(9, LOCK, LOCK)
|
||||
XX(10, MKCOL, MKCOL)
|
||||
XX(11, MOVE, MOVE)
|
||||
XX(12, PROPFIND, PROPFIND)
|
||||
XX(13, PROPPATCH, PROPPATCH)
|
||||
XX(14, SEARCH, SEARCH)
|
||||
XX(15, UNLOCK, UNLOCK)
|
||||
/* subversion */
|
||||
XX(16, REPORT, REPORT)
|
||||
XX(17, MKACTIVITY, MKACTIVITY)
|
||||
XX(18, CHECKOUT, CHECKOUT)
|
||||
XX(19, MERGE, MERGE)
|
||||
/* upnp */
|
||||
XX(20, MSEARCH, M-SEARCH)
|
||||
XX(21, NOTIFY, NOTIFY)
|
||||
XX(22, SUBSCRIBE, SUBSCRIBE)
|
||||
XX(23, UNSUBSCRIBE, UNSUBSCRIBE)
|
||||
/* RFC-5789 */
|
||||
XX(24, PATCH, PATCH)
|
||||
XX(25, PURGE, PURGE)
|
||||
/* CalDAV */
|
||||
XX(26, MKCALENDAR, MKCALENDAR)
|
||||
XX(0, DELETE, DELETE)
|
||||
XX(1, GET, GET)
|
||||
XX(2, HEAD, HEAD)
|
||||
XX(3, POST, POST)
|
||||
XX(4, PUT, PUT)
|
||||
XX(5, CONNECT, CONNECT)
|
||||
XX(6, OPTIONS, OPTIONS)
|
||||
XX(7, TRACE, TRACE)
|
||||
XX(8, COPY, COPY)
|
||||
XX(9, LOCK, LOCK)
|
||||
XX(10, MKCOL, MKCOL)
|
||||
XX(11, MOVE, MOVE)
|
||||
XX(12, PROPFIND, PROPFIND)
|
||||
XX(13, PROPPATCH, PROPPATCH)
|
||||
XX(14, SEARCH, SEARCH)
|
||||
XX(15, UNLOCK, UNLOCK)
|
||||
XX(16, BIND, BIND)
|
||||
XX(17, REBIND, REBIND)
|
||||
XX(18, UNBIND, UNBIND)
|
||||
XX(19, ACL, ACL)
|
||||
XX(20, REPORT, REPORT)
|
||||
XX(21, MKACTIVITY, MKACTIVITY)
|
||||
XX(22, CHECKOUT, CHECKOUT)
|
||||
XX(23, MERGE, MERGE)
|
||||
XX(24, MSEARCH, M-SEARCH)
|
||||
XX(25, NOTIFY, NOTIFY)
|
||||
XX(26, SUBSCRIBE, SUBSCRIBE)
|
||||
XX(27, UNSUBSCRIBE, UNSUBSCRIBE)
|
||||
XX(28, PATCH, PATCH)
|
||||
XX(29, PURGE, PURGE)
|
||||
XX(30, MKCALENDAR, MKCALENDAR)
|
||||
XX(31, LINK, LINK)
|
||||
XX(32, UNLINK, UNLINK)
|
||||
XX(33, SOURCE, SOURCE)
|
||||
'''
|
||||
|
||||
if __name__ == '__main__':
|
||||
@@ -50,4 +50,4 @@ if __name__ == '__main__':
|
||||
continue
|
||||
_, m, _ = line.split(',', 2)
|
||||
methods.append(m.strip())
|
||||
gentokenlookup(methods, 'HTTP')
|
||||
gentokenlookup(methods, 'HTTP_')
|
||||
|
||||
@@ -168,6 +168,13 @@ OPTIONS = [
|
||||
"no-strip-incoming-x-forwarded-proto",
|
||||
"ocsp-startup",
|
||||
"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 = [
|
||||
@@ -201,5 +208,5 @@ LOGVARS = [
|
||||
]
|
||||
|
||||
if __name__ == '__main__':
|
||||
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(OPTIONS, 'SHRPX_OPTID_', value_type='char', comp_fun='util::strieq_l')
|
||||
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
|
||||
|
||||
def to_enum_hd(k, prefix):
|
||||
res = prefix + '_'
|
||||
res = prefix
|
||||
for c in k.upper():
|
||||
if c == ':' or c == '-':
|
||||
res += '_'
|
||||
@@ -30,7 +30,7 @@ enum {'''
|
||||
print '''\
|
||||
{},'''.format(to_enum_hd(k, prefix))
|
||||
print '''\
|
||||
{}_MAXIDX,
|
||||
{}MAXIDX,
|
||||
}};'''.format(prefix)
|
||||
|
||||
def gen_index_header(tokens, prefix, value_type, comp_fun, return_type, fail_value):
|
||||
|
||||
@@ -167,7 +167,7 @@ def format_text(text):
|
||||
else:
|
||||
text = re.sub(r'\*', r'\*', text)
|
||||
# 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)
|
||||
# sphinx does not like markup like ':option:`-f`='. We need
|
||||
# backslash between ` and =.
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
set(GO_FILES
|
||||
nghttpx_http1_test.go
|
||||
nghttpx_http2_test.go
|
||||
nghttpx_spdy_test.go
|
||||
server_tester.go
|
||||
)
|
||||
|
||||
@@ -22,7 +21,6 @@ set(EXTRA_DIST
|
||||
add_custom_target(itprep
|
||||
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/spdy
|
||||
COMMAND go get -d -v golang.org/x/net/websocket
|
||||
)
|
||||
|
||||
|
||||
@@ -39,11 +39,6 @@ EXTRA_DIST = \
|
||||
req-return.rb \
|
||||
resp-return.rb
|
||||
|
||||
itprep:
|
||||
go get -d -v golang.org/x/net/http2
|
||||
go get -d -v github.com/tatsuhiro-t/go-nghttp2
|
||||
go get -d -v golang.org/x/net/websocket
|
||||
|
||||
it:
|
||||
for i in $(GO_FILES); do [ -e $(builddir)/$$i ] || cp $(srcdir)/$$i $(builddir); done
|
||||
sh setenv go test -v
|
||||
|
||||
@@ -625,6 +625,35 @@ func TestH1H1HTTPSRedirectPort(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TestH1H1POSTRequests tests that server can handle 2 requests with
|
||||
// request body.
|
||||
func TestH1H1POSTRequests(t *testing.T) {
|
||||
st := newServerTester(nil, t, noopHandler)
|
||||
defer st.Close()
|
||||
|
||||
res, err := st.http1(requestParam{
|
||||
name: "TestH1H1POSTRequestsNo1",
|
||||
body: make([]byte, 1),
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("Error st.http1() = %v", err)
|
||||
}
|
||||
if got, want := res.status, 200; got != want {
|
||||
t.Errorf("res.status: %v; want %v", got, want)
|
||||
}
|
||||
|
||||
res, err = st.http1(requestParam{
|
||||
name: "TestH1H1POSTRequestsNo2",
|
||||
body: make([]byte, 65536),
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("Error st.http1() = %v", err)
|
||||
}
|
||||
if got, want := res.status, 200; got != want {
|
||||
t.Errorf("res.status: %v; want %v", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
// // TestH1H2ConnectFailure tests that server handles the situation that
|
||||
// // connection attempt to HTTP/2 backend failed.
|
||||
// func TestH1H2ConnectFailure(t *testing.T) {
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
"golang.org/x/net/http2/hpack"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"net/http"
|
||||
"regexp"
|
||||
"strings"
|
||||
@@ -1506,6 +1507,235 @@ func TestH2H1ProxyProtocolV1InvalidID(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TestH2H1ProxyProtocolV2TCP4 tests PROXY protocol version 2
|
||||
// containing AF_INET family is accepted and X-Forwarded-For contains
|
||||
// advertised src address.
|
||||
func TestH2H1ProxyProtocolV2TCP4(t *testing.T) {
|
||||
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 {
|
||||
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()
|
||||
|
||||
var b bytes.Buffer
|
||||
writeProxyProtocolV2(&b, proxyProtocolV2{
|
||||
command: proxyProtocolV2CommandProxy,
|
||||
sourceAddress: &net.TCPAddr{
|
||||
IP: net.ParseIP("192.168.0.2").To4(),
|
||||
Port: 12345,
|
||||
},
|
||||
destinationAddress: &net.TCPAddr{
|
||||
IP: net.ParseIP("192.168.0.100").To4(),
|
||||
Port: 8080,
|
||||
},
|
||||
additionalData: []byte("foobar"),
|
||||
})
|
||||
st.conn.Write(b.Bytes())
|
||||
|
||||
res, err := st.http2(requestParam{
|
||||
name: "TestH2H1ProxyProtocolV2TCP4",
|
||||
})
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
// TestH2H1ProxyProtocolV2TCP6 tests PROXY protocol version 2
|
||||
// containing AF_INET6 family is accepted and X-Forwarded-For contains
|
||||
// advertised src address.
|
||||
func TestH2H1ProxyProtocolV2TCP6(t *testing.T) {
|
||||
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:db8:85a3::8a2e:370:7334"; got != want {
|
||||
t.Errorf("X-Forwarded-For: %v; want %v", got, want)
|
||||
}
|
||||
if got, want := r.Header.Get("Forwarded"), `for="[2001:db8:85a3::8a2e:370:7334]"`; got != want {
|
||||
t.Errorf("Forwarded: %v; want %v", got, want)
|
||||
}
|
||||
})
|
||||
defer st.Close()
|
||||
|
||||
var b bytes.Buffer
|
||||
writeProxyProtocolV2(&b, proxyProtocolV2{
|
||||
command: proxyProtocolV2CommandProxy,
|
||||
sourceAddress: &net.TCPAddr{
|
||||
IP: net.ParseIP("2001:0db8:85a3:0000:0000:8a2e:0370:7334"),
|
||||
Port: 12345,
|
||||
},
|
||||
destinationAddress: &net.TCPAddr{
|
||||
IP: net.ParseIP("::1"),
|
||||
Port: 8080,
|
||||
},
|
||||
additionalData: []byte("foobar"),
|
||||
})
|
||||
st.conn.Write(b.Bytes())
|
||||
|
||||
res, err := st.http2(requestParam{
|
||||
name: "TestH2H1ProxyProtocolV2TCP6",
|
||||
})
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
// TestH2H1ProxyProtocolV2Local tests PROXY protocol version 2
|
||||
// containing cmd == Local is ignored.
|
||||
func TestH2H1ProxyProtocolV2Local(t *testing.T) {
|
||||
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"), "127.0.0.1"; got != want {
|
||||
t.Errorf("X-Forwarded-For: %v; want %v", got, want)
|
||||
}
|
||||
if got, want := r.Header.Get("Forwarded"), "for=127.0.0.1"; got != want {
|
||||
t.Errorf("Forwarded: %v; want %v", got, want)
|
||||
}
|
||||
})
|
||||
defer st.Close()
|
||||
|
||||
var b bytes.Buffer
|
||||
writeProxyProtocolV2(&b, proxyProtocolV2{
|
||||
command: proxyProtocolV2CommandLocal,
|
||||
sourceAddress: &net.TCPAddr{
|
||||
IP: net.ParseIP("192.168.0.2").To4(),
|
||||
Port: 12345,
|
||||
},
|
||||
destinationAddress: &net.TCPAddr{
|
||||
IP: net.ParseIP("192.168.0.100").To4(),
|
||||
Port: 8080,
|
||||
},
|
||||
additionalData: []byte("foobar"),
|
||||
})
|
||||
st.conn.Write(b.Bytes())
|
||||
|
||||
res, err := st.http2(requestParam{
|
||||
name: "TestH2H1ProxyProtocolV2Local",
|
||||
})
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
// TestH2H1ProxyProtocolV2UnknownCmd tests PROXY protocol version 2
|
||||
// containing unknown cmd should be rejected.
|
||||
func TestH2H1ProxyProtocolV2UnknownCmd(t *testing.T) {
|
||||
st := newServerTester([]string{"--accept-proxy-protocol"}, t, noopHandler)
|
||||
defer st.Close()
|
||||
|
||||
var b bytes.Buffer
|
||||
writeProxyProtocolV2(&b, proxyProtocolV2{
|
||||
command: 0xf,
|
||||
sourceAddress: &net.TCPAddr{
|
||||
IP: net.ParseIP("192.168.0.2").To4(),
|
||||
Port: 12345,
|
||||
},
|
||||
destinationAddress: &net.TCPAddr{
|
||||
IP: net.ParseIP("192.168.0.100").To4(),
|
||||
Port: 8080,
|
||||
},
|
||||
additionalData: []byte("foobar"),
|
||||
})
|
||||
st.conn.Write(b.Bytes())
|
||||
|
||||
_, err := st.http2(requestParam{
|
||||
name: "TestH2H1ProxyProtocolV2UnknownCmd",
|
||||
})
|
||||
|
||||
if err == nil {
|
||||
t.Fatalf("connection was not terminated")
|
||||
}
|
||||
}
|
||||
|
||||
// TestH2H1ProxyProtocolV2Unix tests PROXY protocol version 2
|
||||
// containing AF_UNIX family is ignored.
|
||||
func TestH2H1ProxyProtocolV2Unix(t *testing.T) {
|
||||
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"), "127.0.0.1"; got != want {
|
||||
t.Errorf("X-Forwarded-For: %v; want %v", got, want)
|
||||
}
|
||||
if got, want := r.Header.Get("Forwarded"), "for=127.0.0.1"; got != want {
|
||||
t.Errorf("Forwarded: %v; want %v", got, want)
|
||||
}
|
||||
})
|
||||
defer st.Close()
|
||||
|
||||
var b bytes.Buffer
|
||||
writeProxyProtocolV2(&b, proxyProtocolV2{
|
||||
command: proxyProtocolV2CommandProxy,
|
||||
sourceAddress: &net.UnixAddr{
|
||||
Name: "/foo",
|
||||
Net: "unix",
|
||||
},
|
||||
destinationAddress: &net.UnixAddr{
|
||||
Name: "/bar",
|
||||
Net: "unix",
|
||||
},
|
||||
additionalData: []byte("foobar"),
|
||||
})
|
||||
st.conn.Write(b.Bytes())
|
||||
|
||||
res, err := st.http2(requestParam{
|
||||
name: "TestH2H1ProxyProtocolV2Unix",
|
||||
})
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
// TestH2H1ProxyProtocolV2Unspec tests PROXY protocol version 2
|
||||
// containing AF_UNSPEC family is ignored.
|
||||
func TestH2H1ProxyProtocolV2Unspec(t *testing.T) {
|
||||
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"), "127.0.0.1"; got != want {
|
||||
t.Errorf("X-Forwarded-For: %v; want %v", got, want)
|
||||
}
|
||||
if got, want := r.Header.Get("Forwarded"), "for=127.0.0.1"; got != want {
|
||||
t.Errorf("Forwarded: %v; want %v", got, want)
|
||||
}
|
||||
})
|
||||
defer st.Close()
|
||||
|
||||
var b bytes.Buffer
|
||||
writeProxyProtocolV2(&b, proxyProtocolV2{
|
||||
command: proxyProtocolV2CommandProxy,
|
||||
additionalData: []byte("foobar"),
|
||||
})
|
||||
st.conn.Write(b.Bytes())
|
||||
|
||||
res, err := st.http2(requestParam{
|
||||
name: "TestH2H1ProxyProtocolV2Unspec",
|
||||
})
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
// TestH2H1ExternalDNS tests that DNS resolution using external DNS
|
||||
// with HTTP/1 backend works.
|
||||
func TestH2H1ExternalDNS(t *testing.T) {
|
||||
|
||||
@@ -4,10 +4,10 @@ import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"crypto/tls"
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/tatsuhiro-t/go-nghttp2"
|
||||
"github.com/tatsuhiro-t/spdy"
|
||||
"golang.org/x/net/http2"
|
||||
"golang.org/x/net/http2/hpack"
|
||||
"golang.org/x/net/websocket"
|
||||
@@ -53,14 +53,12 @@ type serverTester struct {
|
||||
h2PrefaceSent bool // HTTP/2 preface was sent in conn
|
||||
nextStreamID uint32 // next stream ID
|
||||
fr *http2.Framer // HTTP/2 framer
|
||||
spdyFr *spdy.Framer // SPDY/3.1 framer
|
||||
headerBlkBuf bytes.Buffer // buffer to store encoded header block
|
||||
enc *hpack.Encoder // HTTP/2 HPACK encoder
|
||||
header http.Header // received header fields
|
||||
dec *hpack.Decoder // HTTP/2 HPACK decoder
|
||||
authority string // server's host:port
|
||||
frCh chan http2.Frame // used for incoming HTTP/2 frame
|
||||
spdyFrCh chan spdy.Frame // used for incoming SPDY frame
|
||||
errCh chan error
|
||||
}
|
||||
|
||||
@@ -201,7 +199,6 @@ func newServerTesterInternal(src_args []string, t *testing.T, handler http.Handl
|
||||
nextStreamID: 1,
|
||||
authority: authority,
|
||||
frCh: make(chan http2.Frame),
|
||||
spdyFrCh: make(chan spdy.Frame),
|
||||
errCh: make(chan error),
|
||||
}
|
||||
|
||||
@@ -229,7 +226,7 @@ func newServerTesterInternal(src_args []string, t *testing.T, handler http.Handl
|
||||
if alpnH1 {
|
||||
tlsConfig.NextProtos = []string{"http/1.1"}
|
||||
} else {
|
||||
tlsConfig.NextProtos = []string{"h2", "spdy/3.1"}
|
||||
tlsConfig.NextProtos = []string{"h2"}
|
||||
}
|
||||
conn, err = tls.Dial("tcp", authority, tlsConfig)
|
||||
} else {
|
||||
@@ -256,12 +253,6 @@ func newServerTesterInternal(src_args []string, t *testing.T, handler http.Handl
|
||||
}
|
||||
|
||||
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.dec = hpack.NewDecoder(4096, func(f hpack.HeaderField) {
|
||||
st.header.Add(f.Name, f.Value)
|
||||
@@ -315,26 +306,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 {
|
||||
name string // name for this request to identify the request in log easily
|
||||
streamID uint32 // stream ID, automatically assigned if 0
|
||||
@@ -475,122 +446,6 @@ func (st *serverTester) http1(rp requestParam) (*serverResponse, error) {
|
||||
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) {
|
||||
st.headerBlkBuf.Reset()
|
||||
st.header = make(http.Header)
|
||||
@@ -773,17 +628,15 @@ func streamEnded(mainSr *serverResponse, streams map[uint32]*serverResponse, sr
|
||||
}
|
||||
|
||||
type serverResponse struct {
|
||||
status int // HTTP status code
|
||||
header http.Header // response header fields
|
||||
body []byte // response body
|
||||
streamID uint32 // stream ID in HTTP/2
|
||||
errCode http2.ErrCode // error code received in HTTP/2 RST_STREAM or GOAWAY
|
||||
connErr bool // true if HTTP/2 connection error
|
||||
spdyGoAwayErrCode spdy.GoAwayStatus // status code received in SPDY RST_STREAM
|
||||
spdyRstErrCode spdy.RstStreamStatus // status code received in SPDY GOAWAY
|
||||
connClose bool // Connection: close is included in response header in HTTP/1 test
|
||||
reqHeader http.Header // http request header, currently only sotres pushed request header
|
||||
pushResponse []*serverResponse // pushed response
|
||||
status int // HTTP status code
|
||||
header http.Header // response header fields
|
||||
body []byte // response body
|
||||
streamID uint32 // stream ID in HTTP/2
|
||||
errCode http2.ErrCode // error code received in HTTP/2 RST_STREAM or GOAWAY
|
||||
connErr bool // true if HTTP/2 connection error
|
||||
connClose bool // Connection: close is included in response header in HTTP/1 test
|
||||
reqHeader http.Header // http request header, currently only sotres pushed request header
|
||||
pushResponse []*serverResponse // pushed response
|
||||
}
|
||||
|
||||
type ByStreamID []*serverResponse
|
||||
@@ -810,10 +663,102 @@ func cloneHeader(h http.Header) http.Header {
|
||||
return h2
|
||||
}
|
||||
|
||||
func noopHandler(w http.ResponseWriter, r *http.Request) {}
|
||||
func noopHandler(w http.ResponseWriter, r *http.Request) {
|
||||
ioutil.ReadAll(r.Body)
|
||||
}
|
||||
|
||||
type APIResponse struct {
|
||||
Status string `json:"status,omitempty"`
|
||||
Code int `json:"code,omitempty"`
|
||||
Data map[string]interface{} `json:"data,omitempty"`
|
||||
}
|
||||
|
||||
type proxyProtocolV2 struct {
|
||||
command proxyProtocolV2Command
|
||||
sourceAddress net.Addr
|
||||
destinationAddress net.Addr
|
||||
additionalData []byte
|
||||
}
|
||||
|
||||
type proxyProtocolV2Command int
|
||||
|
||||
const (
|
||||
proxyProtocolV2CommandLocal proxyProtocolV2Command = 0x0
|
||||
proxyProtocolV2CommandProxy proxyProtocolV2Command = 0x1
|
||||
)
|
||||
|
||||
type proxyProtocolV2Family int
|
||||
|
||||
const (
|
||||
proxyProtocolV2FamilyUnspec proxyProtocolV2Family = 0x0
|
||||
proxyProtocolV2FamilyInet proxyProtocolV2Family = 0x1
|
||||
proxyProtocolV2FamilyInet6 proxyProtocolV2Family = 0x2
|
||||
proxyProtocolV2FamilyUnix proxyProtocolV2Family = 0x3
|
||||
)
|
||||
|
||||
type proxyProtocolV2Protocol int
|
||||
|
||||
const (
|
||||
proxyProtocolV2ProtocolUnspec proxyProtocolV2Protocol = 0x0
|
||||
proxyProtocolV2ProtocolStream proxyProtocolV2Protocol = 0x1
|
||||
proxyProtocolV2ProtocolDgram proxyProtocolV2Protocol = 0x2
|
||||
)
|
||||
|
||||
func writeProxyProtocolV2(w io.Writer, hdr proxyProtocolV2) {
|
||||
w.Write([]byte{0x0D, 0x0A, 0x0D, 0x0A, 0x00, 0x0D, 0x0A, 0x51, 0x55, 0x49, 0x54, 0x0A})
|
||||
w.Write([]byte{byte(0x20 | hdr.command)})
|
||||
|
||||
switch srcAddr := hdr.sourceAddress.(type) {
|
||||
case *net.TCPAddr:
|
||||
dstAddr := hdr.destinationAddress.(*net.TCPAddr)
|
||||
if len(srcAddr.IP) != len(dstAddr.IP) {
|
||||
panic("len(srcAddr.IP) != len(dstAddr.IP)")
|
||||
}
|
||||
var fam byte
|
||||
if len(srcAddr.IP) == 4 {
|
||||
fam = byte(proxyProtocolV2FamilyInet << 4)
|
||||
} else {
|
||||
fam = byte(proxyProtocolV2FamilyInet6 << 4)
|
||||
}
|
||||
fam |= byte(proxyProtocolV2ProtocolStream)
|
||||
w.Write([]byte{fam})
|
||||
length := uint16(len(srcAddr.IP)*2 + 4 + len(hdr.additionalData))
|
||||
binary.Write(w, binary.BigEndian, length)
|
||||
w.Write(srcAddr.IP)
|
||||
w.Write(dstAddr.IP)
|
||||
binary.Write(w, binary.BigEndian, uint16(srcAddr.Port))
|
||||
binary.Write(w, binary.BigEndian, uint16(dstAddr.Port))
|
||||
case *net.UnixAddr:
|
||||
dstAddr := hdr.destinationAddress.(*net.UnixAddr)
|
||||
if len(srcAddr.Name) > 108 {
|
||||
panic("too long Unix source address")
|
||||
}
|
||||
if len(dstAddr.Name) > 108 {
|
||||
panic("too long Unix destination address")
|
||||
}
|
||||
fam := byte(proxyProtocolV2FamilyUnix << 4)
|
||||
switch srcAddr.Net {
|
||||
case "unix":
|
||||
fam |= byte(proxyProtocolV2ProtocolStream)
|
||||
case "unixdgram":
|
||||
fam |= byte(proxyProtocolV2ProtocolDgram)
|
||||
default:
|
||||
fam |= byte(proxyProtocolV2ProtocolUnspec)
|
||||
}
|
||||
w.Write([]byte{fam})
|
||||
length := uint16(216 + len(hdr.additionalData))
|
||||
binary.Write(w, binary.BigEndian, length)
|
||||
zeros := make([]byte, 108)
|
||||
w.Write([]byte(srcAddr.Name))
|
||||
w.Write(zeros[:108-len(srcAddr.Name)])
|
||||
w.Write([]byte(dstAddr.Name))
|
||||
w.Write(zeros[:108-len(dstAddr.Name)])
|
||||
default:
|
||||
fam := byte(proxyProtocolV2FamilyUnspec<<4) | byte(proxyProtocolV2ProtocolUnspec)
|
||||
w.Write([]byte{fam})
|
||||
length := uint16(len(hdr.additionalData))
|
||||
binary.Write(w, binary.BigEndian, length)
|
||||
}
|
||||
|
||||
w.Write(hdr.additionalData)
|
||||
}
|
||||
|
||||
@@ -38,30 +38,39 @@ if(WIN32)
|
||||
endif()
|
||||
|
||||
# Public shared library
|
||||
add_library(nghttp2 SHARED ${NGHTTP2_SOURCES} ${NGHTTP2_RES})
|
||||
set_target_properties(nghttp2 PROPERTIES
|
||||
COMPILE_FLAGS "${WARNCFLAGS}"
|
||||
VERSION ${LT_VERSION} SOVERSION ${LT_SOVERSION}
|
||||
C_VISIBILITY_PRESET hidden
|
||||
)
|
||||
target_include_directories(nghttp2 INTERFACE
|
||||
if(ENABLE_SHARED_LIB)
|
||||
add_library(nghttp2 SHARED ${NGHTTP2_SOURCES} ${NGHTTP2_RES})
|
||||
set_target_properties(nghttp2 PROPERTIES
|
||||
COMPILE_FLAGS "${WARNCFLAGS}"
|
||||
VERSION ${LT_VERSION} SOVERSION ${LT_SOVERSION}
|
||||
C_VISIBILITY_PRESET hidden
|
||||
)
|
||||
target_include_directories(nghttp2 INTERFACE
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/includes"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/includes"
|
||||
)
|
||||
)
|
||||
|
||||
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)
|
||||
add_library(nghttp2_static STATIC ${NGHTTP2_SOURCES})
|
||||
set_target_properties(nghttp2_static PROPERTIES
|
||||
COMPILE_FLAGS "${WARNCFLAGS}"
|
||||
VERSION ${LT_VERSION} SOVERSION ${LT_SOVERSION}
|
||||
ARCHIVE_OUTPUT_NAME nghttp2
|
||||
ARCHIVE_OUTPUT_NAME nghttp2${STATIC_LIB_SUFFIX}
|
||||
)
|
||||
target_compile_definitions(nghttp2_static PUBLIC "-DNGHTTP2_STATICLIB")
|
||||
if(ENABLE_STATIC_LIB)
|
||||
install(TARGETS nghttp2_static
|
||||
DESTINATION "${CMAKE_INSTALL_LIBDIR}")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
install(TARGETS nghttp2
|
||||
DESTINATION "${CMAKE_INSTALL_LIBDIR}")
|
||||
|
||||
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/libnghttp2.pc"
|
||||
DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig")
|
||||
|
||||
@@ -28,7 +28,12 @@
|
||||
/* Define WIN32 when build target is Win32 API (borrowed from
|
||||
libcurl) */
|
||||
#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
|
||||
|
||||
#ifdef __cplusplus
|
||||
@@ -40,9 +45,9 @@ extern "C" {
|
||||
/* MSVC < 2013 does not have inttypes.h because it is not C99
|
||||
compliant. See compiler macros and version number in
|
||||
https://sourceforge.net/p/predef/wiki/Compilers/ */
|
||||
#include <stdint.h>
|
||||
# include <stdint.h>
|
||||
#else /* !defined(_MSC_VER) || (_MSC_VER >= 1800) */
|
||||
#include <inttypes.h>
|
||||
# include <inttypes.h>
|
||||
#endif /* !defined(_MSC_VER) || (_MSC_VER >= 1800) */
|
||||
#include <sys/types.h>
|
||||
#include <stdarg.h>
|
||||
@@ -50,20 +55,21 @@ extern "C" {
|
||||
#include <nghttp2/nghttp2ver.h>
|
||||
|
||||
#ifdef NGHTTP2_STATICLIB
|
||||
#define NGHTTP2_EXTERN
|
||||
#elif defined(WIN32)
|
||||
#ifdef BUILDING_NGHTTP2
|
||||
#define NGHTTP2_EXTERN __declspec(dllexport)
|
||||
#else /* !BUILDING_NGHTTP2 */
|
||||
#define NGHTTP2_EXTERN __declspec(dllimport)
|
||||
#endif /* !BUILDING_NGHTTP2 */
|
||||
#else /* !defined(WIN32) */
|
||||
#ifdef BUILDING_NGHTTP2
|
||||
#define NGHTTP2_EXTERN __attribute__((visibility("default")))
|
||||
#else /* !BUILDING_NGHTTP2 */
|
||||
#define NGHTTP2_EXTERN
|
||||
#endif /* !BUILDING_NGHTTP2 */
|
||||
#endif /* !defined(WIN32) */
|
||||
# define NGHTTP2_EXTERN
|
||||
#elif defined(WIN32) || (__has_declspec_attribute(dllexport) && \
|
||||
__has_declspec_attribute(dllimport))
|
||||
# ifdef BUILDING_NGHTTP2
|
||||
# define NGHTTP2_EXTERN __declspec(dllexport)
|
||||
# else /* !BUILDING_NGHTTP2 */
|
||||
# define NGHTTP2_EXTERN __declspec(dllimport)
|
||||
# endif /* !BUILDING_NGHTTP2 */
|
||||
#else /* !defined(WIN32) */
|
||||
# ifdef BUILDING_NGHTTP2
|
||||
# define NGHTTP2_EXTERN __attribute__((visibility("default")))
|
||||
# else /* !BUILDING_NGHTTP2 */
|
||||
# define NGHTTP2_EXTERN
|
||||
# endif /* !BUILDING_NGHTTP2 */
|
||||
#endif /* !defined(WIN32) */
|
||||
|
||||
/**
|
||||
* @macro
|
||||
@@ -222,6 +228,13 @@ typedef struct {
|
||||
*/
|
||||
#define NGHTTP2_CLIENT_MAGIC_LEN 24
|
||||
|
||||
/**
|
||||
* @macro
|
||||
*
|
||||
* The default max number of settings per SETTINGS frame
|
||||
*/
|
||||
#define NGHTTP2_DEFAULT_MAX_SETTINGS 32
|
||||
|
||||
/**
|
||||
* @enum
|
||||
*
|
||||
@@ -392,6 +405,11 @@ typedef enum {
|
||||
* receives an other type of frame.
|
||||
*/
|
||||
NGHTTP2_ERR_SETTINGS_EXPECTED = -536,
|
||||
/**
|
||||
* When a local endpoint receives too many settings entries
|
||||
* in a single SETTINGS frame.
|
||||
*/
|
||||
NGHTTP2_ERR_TOO_MANY_SETTINGS = -537,
|
||||
/**
|
||||
* The errors < :enum:`NGHTTP2_ERR_FATAL` mean that the library is
|
||||
* under unexpected condition and processing was terminated (e.g.,
|
||||
@@ -611,7 +629,12 @@ typedef enum {
|
||||
* The ALTSVC frame, which is defined in `RFC 7383
|
||||
* <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;
|
||||
|
||||
/**
|
||||
@@ -675,7 +698,12 @@ typedef enum {
|
||||
/**
|
||||
* 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;
|
||||
/* Note: If we add SETTINGS, update the capacity of
|
||||
NGHTTP2_INBOUND_NUM_IV as well */
|
||||
@@ -2473,15 +2501,15 @@ nghttp2_option_set_no_auto_window_update(nghttp2_option *option, int val);
|
||||
*
|
||||
* This option sets the SETTINGS_MAX_CONCURRENT_STREAMS value of
|
||||
* remote endpoint as if it is received in SETTINGS frame. Without
|
||||
* specifying this option, before the local endpoint receives
|
||||
* SETTINGS_MAX_CONCURRENT_STREAMS in SETTINGS frame from remote
|
||||
* endpoint, SETTINGS_MAX_CONCURRENT_STREAMS is unlimited. This may
|
||||
* cause problem if local endpoint submits lots of requests initially
|
||||
* and sending them at once to the remote peer may lead to the
|
||||
* rejection of some requests. Specifying this option to the sensible
|
||||
* value, say 100, may avoid this kind of issue. This value will be
|
||||
* overwritten if the local endpoint receives
|
||||
* SETTINGS_MAX_CONCURRENT_STREAMS from the remote endpoint.
|
||||
* specifying this option, the maximum number of outgoing concurrent
|
||||
* streams is initially limited to 100 to avoid issues when the local
|
||||
* endpoint submits lots of requests before receiving initial SETTINGS
|
||||
* frame from the remote endpoint, since sending them at once to the
|
||||
* remote endpoint could lead to rejection of some of the requests.
|
||||
* This value will be overwritten when the local endpoint receives
|
||||
* initial SETTINGS frame from the remote endpoint, either to the
|
||||
* value advertised in SETTINGS_MAX_CONCURRENT_STREAMS or to the
|
||||
* default value (unlimited) if none was advertised.
|
||||
*/
|
||||
NGHTTP2_EXTERN void
|
||||
nghttp2_option_set_peer_max_concurrent_streams(nghttp2_option *option,
|
||||
@@ -2632,6 +2660,28 @@ nghttp2_option_set_max_deflate_dynamic_table_size(nghttp2_option *option,
|
||||
NGHTTP2_EXTERN void nghttp2_option_set_no_closed_streams(nghttp2_option *option,
|
||||
int val);
|
||||
|
||||
/**
|
||||
* @function
|
||||
*
|
||||
* This function sets the maximum number of outgoing SETTINGS ACK and
|
||||
* PING ACK frames retained in :type:`nghttp2_session` object. If
|
||||
* more than those frames are retained, the peer is considered to be
|
||||
* misbehaving and session will be closed. The default value is 1000.
|
||||
*/
|
||||
NGHTTP2_EXTERN void nghttp2_option_set_max_outbound_ack(nghttp2_option *option,
|
||||
size_t val);
|
||||
|
||||
/**
|
||||
* @function
|
||||
*
|
||||
* This function sets the maximum number of SETTINGS entries per
|
||||
* SETTINGS frame that will be accepted. If more than those entries
|
||||
* are received, the peer is considered to be misbehaving and session
|
||||
* will be closed. The default value is 32.
|
||||
*/
|
||||
NGHTTP2_EXTERN void nghttp2_option_set_max_settings(nghttp2_option *option,
|
||||
size_t val);
|
||||
|
||||
/**
|
||||
* @function
|
||||
*
|
||||
@@ -3081,6 +3131,16 @@ NGHTTP2_EXTERN int
|
||||
nghttp2_session_set_stream_user_data(nghttp2_session *session,
|
||||
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
|
||||
*
|
||||
@@ -3787,10 +3847,13 @@ nghttp2_priority_spec_check_default(const nghttp2_priority_spec *pri_spec);
|
||||
* .. warning::
|
||||
*
|
||||
* 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
|
||||
* :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(
|
||||
@@ -4506,8 +4569,7 @@ typedef struct {
|
||||
* Submits ALTSVC frame.
|
||||
*
|
||||
* ALTSVC frame is a non-critical extension to HTTP/2, and defined in
|
||||
* is defined in `RFC 7383
|
||||
* <https://tools.ietf.org/html/rfc7838#section-4>`_.
|
||||
* `RFC 7383 <https://tools.ietf.org/html/rfc7838#section-4>`_.
|
||||
*
|
||||
* The |flags| is currently ignored and should be
|
||||
* :enum:`NGHTTP2_FLAG_NONE`.
|
||||
@@ -4541,6 +4603,81 @@ NGHTTP2_EXTERN int nghttp2_submit_altsvc(nghttp2_session *session,
|
||||
const uint8_t *field_value,
|
||||
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
|
||||
*
|
||||
@@ -4655,6 +4792,19 @@ NGHTTP2_EXTERN int nghttp2_check_header_name(const uint8_t *name, size_t len);
|
||||
*/
|
||||
NGHTTP2_EXTERN int nghttp2_check_header_value(const uint8_t *value, size_t len);
|
||||
|
||||
/**
|
||||
* @function
|
||||
*
|
||||
* Returns nonzero if the |value| which is supposed to the value of
|
||||
* :authority or host header field is valid according to
|
||||
* https://tools.ietf.org/html/rfc3986#section-3.2
|
||||
*
|
||||
* |value| is valid if it merely consists of the allowed characters.
|
||||
* In particular, it does not check whether |value| follows the syntax
|
||||
* of authority.
|
||||
*/
|
||||
NGHTTP2_EXTERN int nghttp2_check_authority(const uint8_t *value, size_t len);
|
||||
|
||||
/* HPACK API */
|
||||
|
||||
struct nghttp2_hd_deflater;
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
#define NGHTTP2_BUF_H
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
# include <config.h>
|
||||
#endif /* HAVE_CONFIG_H */
|
||||
|
||||
#include <nghttp2/nghttp2.h>
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
#define NGHTTP2_CALLBACKS_H
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
# include <config.h>
|
||||
#endif /* HAVE_CONFIG_H */
|
||||
|
||||
#include <nghttp2/nghttp2.h>
|
||||
|
||||
@@ -26,18 +26,18 @@
|
||||
#define NGHTTP2_DEBUG_H
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
# include <config.h>
|
||||
#endif /* HAVE_CONFIG_H */
|
||||
|
||||
#include <nghttp2/nghttp2.h>
|
||||
|
||||
#ifdef DEBUGBUILD
|
||||
#define DEBUGF(...) nghttp2_debug_vprintf(__VA_ARGS__)
|
||||
# define DEBUGF(...) nghttp2_debug_vprintf(__VA_ARGS__)
|
||||
void nghttp2_debug_vprintf(const char *format, ...);
|
||||
#else
|
||||
#define DEBUGF(...) \
|
||||
do { \
|
||||
} while (0)
|
||||
# define DEBUGF(...) \
|
||||
do { \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
#endif /* NGHTTP2_DEBUG_H */
|
||||
|
||||
@@ -215,11 +215,44 @@ void nghttp2_frame_altsvc_free(nghttp2_extension *frame, nghttp2_mem *mem) {
|
||||
nghttp2_ext_altsvc *altsvc;
|
||||
|
||||
altsvc = frame->payload;
|
||||
if (altsvc == NULL) {
|
||||
return;
|
||||
}
|
||||
/* We use the same buffer for altsvc->origin and
|
||||
altsvc->field_value. */
|
||||
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) {
|
||||
if (flags & NGHTTP2_FLAG_PRIORITY) {
|
||||
return NGHTTP2_PRIORITY_SPECLEN;
|
||||
@@ -743,6 +776,106 @@ int nghttp2_frame_unpack_altsvc_payload2(nghttp2_extension *frame,
|
||||
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,
|
||||
size_t niv, nghttp2_mem *mem) {
|
||||
nghttp2_settings_entry *iv_copy;
|
||||
@@ -917,6 +1050,11 @@ int nghttp2_iv_check(const nghttp2_settings_entry *iv, size_t niv) {
|
||||
break;
|
||||
case NGHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE:
|
||||
break;
|
||||
case NGHTTP2_SETTINGS_ENABLE_CONNECT_PROTOCOL:
|
||||
if (iv[i].value != 0 && iv[i].value != 1) {
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
#define NGHTTP2_FRAME_H
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
# include <config.h>
|
||||
#endif /* HAVE_CONFIG_H */
|
||||
|
||||
#include <nghttp2/nghttp2.h>
|
||||
@@ -72,6 +72,7 @@
|
||||
/* Union of extension 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);
|
||||
@@ -392,6 +393,36 @@ int nghttp2_frame_unpack_altsvc_payload2(nghttp2_extension *frame,
|
||||
const uint8_t *payload,
|
||||
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
|
||||
* ownership of |nva|, so caller must not free it. If |stream_id| is
|
||||
@@ -489,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);
|
||||
|
||||
/*
|
||||
* 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
|
||||
* 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
|
||||
first enum value if same header names are repeated (e.g.,
|
||||
: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(":method", "GET", 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;
|
||||
case 9:
|
||||
switch (name[8]) {
|
||||
case 'l':
|
||||
if (memeq(":protoco", name, 8)) {
|
||||
return NGHTTP2_TOKEN__PROTOCOL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 10:
|
||||
switch (name[9]) {
|
||||
case 'e':
|
||||
@@ -1159,7 +1168,7 @@ static search_result search_static_table(const nghttp2_nv *nv, int32_t token,
|
||||
int name_only) {
|
||||
search_result res = {token, 0};
|
||||
int i;
|
||||
nghttp2_hd_static_entry *ent;
|
||||
const nghttp2_hd_static_entry *ent;
|
||||
|
||||
if (name_only) {
|
||||
return res;
|
||||
@@ -1184,7 +1193,7 @@ static search_result search_hd_table(nghttp2_hd_context *context,
|
||||
int indexing_mode, nghttp2_hd_map *map,
|
||||
uint32_t hash) {
|
||||
search_result res = {-1, 0};
|
||||
nghttp2_hd_entry *ent;
|
||||
const nghttp2_hd_entry *ent;
|
||||
int exact_match;
|
||||
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)
|
||||
->nv;
|
||||
} else {
|
||||
nghttp2_hd_static_entry *ent = &static_table[idx];
|
||||
nghttp2_hd_nv nv = {&ent->name, &ent->value, ent->token,
|
||||
const nghttp2_hd_static_entry *ent = &static_table[idx];
|
||||
nghttp2_hd_nv nv = {(nghttp2_rcbuf *)&ent->name,
|
||||
(nghttp2_rcbuf *)&ent->value, ent->token,
|
||||
NGHTTP2_NV_FLAG_NONE};
|
||||
return nv;
|
||||
}
|
||||
@@ -1380,7 +1390,7 @@ static int deflate_nv(nghttp2_hd_deflater *deflater, nghttp2_bufs *bufs,
|
||||
if (indexing_mode == NGHTTP2_HD_WITH_INDEXING) {
|
||||
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;
|
||||
nghttp2_rcbuf_incref(hd_nv.name);
|
||||
} else {
|
||||
@@ -1684,6 +1694,11 @@ static ssize_t hd_inflate_read_huff(nghttp2_hd_inflater *inflater,
|
||||
DEBUGF("inflatehd: huffman decoding failed\n");
|
||||
return readlen;
|
||||
}
|
||||
if (nghttp2_hd_huff_decode_failure_state(&inflater->huff_decode_ctx)) {
|
||||
DEBUGF("inflatehd: huffman decoding failed\n");
|
||||
return NGHTTP2_ERR_HEADER_COMP;
|
||||
}
|
||||
|
||||
inflater->left -= (size_t)readlen;
|
||||
return readlen;
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
#define NGHTTP2_HD_H
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
# include <config.h>
|
||||
#endif /* HAVE_CONFIG_H */
|
||||
|
||||
#include <nghttp2/nghttp2.h>
|
||||
@@ -111,6 +111,7 @@ typedef enum {
|
||||
NGHTTP2_TOKEN_KEEP_ALIVE,
|
||||
NGHTTP2_TOKEN_PROXY_CONNECTION,
|
||||
NGHTTP2_TOKEN_UPGRADE,
|
||||
NGHTTP2_TOKEN__PROTOCOL,
|
||||
} nghttp2_token;
|
||||
|
||||
struct nghttp2_hd_entry;
|
||||
@@ -429,4 +430,10 @@ ssize_t nghttp2_hd_huff_decode(nghttp2_hd_huff_decode_context *ctx,
|
||||
nghttp2_buf *buf, const uint8_t *src,
|
||||
size_t srclen, int fin);
|
||||
|
||||
/*
|
||||
* nghttp2_hd_huff_decode_failure_state returns nonzero if |ctx|
|
||||
* indicates that huffman decoding context is in failure state.
|
||||
*/
|
||||
int nghttp2_hd_huff_decode_failure_state(nghttp2_hd_huff_decode_context *ctx);
|
||||
|
||||
#endif /* NGHTTP2_HD_H */
|
||||
|
||||
@@ -29,114 +29,7 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#include "nghttp2_hd.h"
|
||||
|
||||
/*
|
||||
* Encodes huffman code |sym| into |*dest_ptr|, whose least |rembits|
|
||||
* bits are not filled yet. The |rembits| must be in range [1, 8],
|
||||
* inclusive. At the end of the process, the |*dest_ptr| is updated
|
||||
* and points where next output should be placed. The number of
|
||||
* unfilled bits in the pointed location is returned.
|
||||
*/
|
||||
static ssize_t huff_encode_sym(nghttp2_bufs *bufs, size_t *avail_ptr,
|
||||
size_t rembits, const nghttp2_huff_sym *sym) {
|
||||
int rv;
|
||||
size_t nbits = sym->nbits;
|
||||
uint32_t code = sym->code;
|
||||
|
||||
/* We assume that sym->nbits <= 32 */
|
||||
if (rembits > nbits) {
|
||||
nghttp2_bufs_fast_orb_hold(bufs, (uint8_t)(code << (rembits - nbits)));
|
||||
return (ssize_t)(rembits - nbits);
|
||||
}
|
||||
|
||||
if (rembits == nbits) {
|
||||
nghttp2_bufs_fast_orb(bufs, (uint8_t)code);
|
||||
--*avail_ptr;
|
||||
return 8;
|
||||
}
|
||||
|
||||
nghttp2_bufs_fast_orb(bufs, (uint8_t)(code >> (nbits - rembits)));
|
||||
--*avail_ptr;
|
||||
|
||||
nbits -= rembits;
|
||||
if (nbits & 0x7) {
|
||||
/* align code to MSB byte boundary */
|
||||
code <<= 8 - (nbits & 0x7);
|
||||
}
|
||||
|
||||
if (*avail_ptr < (nbits + 7) / 8) {
|
||||
/* slow path */
|
||||
if (nbits > 24) {
|
||||
rv = nghttp2_bufs_addb(bufs, (uint8_t)(code >> 24));
|
||||
if (rv != 0) {
|
||||
return rv;
|
||||
}
|
||||
nbits -= 8;
|
||||
}
|
||||
if (nbits > 16) {
|
||||
rv = nghttp2_bufs_addb(bufs, (uint8_t)(code >> 16));
|
||||
if (rv != 0) {
|
||||
return rv;
|
||||
}
|
||||
nbits -= 8;
|
||||
}
|
||||
if (nbits > 8) {
|
||||
rv = nghttp2_bufs_addb(bufs, (uint8_t)(code >> 8));
|
||||
if (rv != 0) {
|
||||
return rv;
|
||||
}
|
||||
nbits -= 8;
|
||||
}
|
||||
if (nbits == 8) {
|
||||
rv = nghttp2_bufs_addb(bufs, (uint8_t)code);
|
||||
if (rv != 0) {
|
||||
return rv;
|
||||
}
|
||||
*avail_ptr = nghttp2_bufs_cur_avail(bufs);
|
||||
return 8;
|
||||
}
|
||||
|
||||
rv = nghttp2_bufs_addb_hold(bufs, (uint8_t)code);
|
||||
if (rv != 0) {
|
||||
return rv;
|
||||
}
|
||||
*avail_ptr = nghttp2_bufs_cur_avail(bufs);
|
||||
return (ssize_t)(8 - nbits);
|
||||
}
|
||||
|
||||
/* fast path, since most code is less than 8 */
|
||||
if (nbits < 8) {
|
||||
nghttp2_bufs_fast_addb_hold(bufs, (uint8_t)code);
|
||||
*avail_ptr = nghttp2_bufs_cur_avail(bufs);
|
||||
return (ssize_t)(8 - nbits);
|
||||
}
|
||||
|
||||
/* handle longer code path */
|
||||
if (nbits > 24) {
|
||||
nghttp2_bufs_fast_addb(bufs, (uint8_t)(code >> 24));
|
||||
nbits -= 8;
|
||||
}
|
||||
|
||||
if (nbits > 16) {
|
||||
nghttp2_bufs_fast_addb(bufs, (uint8_t)(code >> 16));
|
||||
nbits -= 8;
|
||||
}
|
||||
|
||||
if (nbits > 8) {
|
||||
nghttp2_bufs_fast_addb(bufs, (uint8_t)(code >> 8));
|
||||
nbits -= 8;
|
||||
}
|
||||
|
||||
if (nbits == 8) {
|
||||
nghttp2_bufs_fast_addb(bufs, (uint8_t)code);
|
||||
*avail_ptr = nghttp2_bufs_cur_avail(bufs);
|
||||
return 8;
|
||||
}
|
||||
|
||||
nghttp2_bufs_fast_addb_hold(bufs, (uint8_t)code);
|
||||
*avail_ptr = nghttp2_bufs_cur_avail(bufs);
|
||||
return (ssize_t)(8 - nbits);
|
||||
}
|
||||
#include "nghttp2_net.h"
|
||||
|
||||
size_t nghttp2_hd_huff_encode_count(const uint8_t *src, size_t len) {
|
||||
size_t i;
|
||||
@@ -151,81 +44,101 @@ size_t nghttp2_hd_huff_encode_count(const uint8_t *src, size_t len) {
|
||||
|
||||
int nghttp2_hd_huff_encode(nghttp2_bufs *bufs, const uint8_t *src,
|
||||
size_t srclen) {
|
||||
int rv;
|
||||
ssize_t rembits = 8;
|
||||
size_t i;
|
||||
const nghttp2_huff_sym *sym;
|
||||
const uint8_t *end = src + srclen;
|
||||
uint64_t code = 0;
|
||||
uint32_t x;
|
||||
size_t nbits = 0;
|
||||
size_t avail;
|
||||
int rv;
|
||||
|
||||
avail = nghttp2_bufs_cur_avail(bufs);
|
||||
|
||||
for (i = 0; i < srclen; ++i) {
|
||||
const nghttp2_huff_sym *sym = &huff_sym_table[src[i]];
|
||||
if (rembits == 8) {
|
||||
if (avail) {
|
||||
nghttp2_bufs_fast_addb_hold(bufs, 0);
|
||||
} else {
|
||||
rv = nghttp2_bufs_addb_hold(bufs, 0);
|
||||
if (rv != 0) {
|
||||
return rv;
|
||||
}
|
||||
avail = nghttp2_bufs_cur_avail(bufs);
|
||||
for (; src != end;) {
|
||||
sym = &huff_sym_table[*src++];
|
||||
code |= (uint64_t)sym->code << (32 - nbits);
|
||||
nbits += sym->nbits;
|
||||
if (nbits < 32) {
|
||||
continue;
|
||||
}
|
||||
if (avail >= 4) {
|
||||
x = htonl((uint32_t)(code >> 32));
|
||||
memcpy(bufs->cur->buf.last, &x, 4);
|
||||
bufs->cur->buf.last += 4;
|
||||
avail -= 4;
|
||||
code <<= 32;
|
||||
nbits -= 32;
|
||||
continue;
|
||||
}
|
||||
|
||||
for (; nbits >= 8;) {
|
||||
rv = nghttp2_bufs_addb(bufs, (uint8_t)(code >> 56));
|
||||
if (rv != 0) {
|
||||
return rv;
|
||||
}
|
||||
code <<= 8;
|
||||
nbits -= 8;
|
||||
}
|
||||
rembits = huff_encode_sym(bufs, &avail, (size_t)rembits, sym);
|
||||
if (rembits < 0) {
|
||||
return (int)rembits;
|
||||
}
|
||||
|
||||
avail = nghttp2_bufs_cur_avail(bufs);
|
||||
}
|
||||
/* 256 is special terminal symbol, pad with its prefix */
|
||||
if (rembits < 8) {
|
||||
/* if rembits < 8, we should have at least 1 buffer space
|
||||
available */
|
||||
const nghttp2_huff_sym *sym = &huff_sym_table[256];
|
||||
assert(avail);
|
||||
/* Caution we no longer adjust avail here */
|
||||
nghttp2_bufs_fast_orb(
|
||||
bufs, (uint8_t)(sym->code >> (sym->nbits - (size_t)rembits)));
|
||||
|
||||
for (; nbits >= 8;) {
|
||||
rv = nghttp2_bufs_addb(bufs, (uint8_t)(code >> 56));
|
||||
if (rv != 0) {
|
||||
return rv;
|
||||
}
|
||||
code <<= 8;
|
||||
nbits -= 8;
|
||||
}
|
||||
|
||||
if (nbits) {
|
||||
rv = nghttp2_bufs_addb(
|
||||
bufs, (uint8_t)((uint8_t)(code >> 56) | ((1 << (8 - nbits)) - 1)));
|
||||
if (rv != 0) {
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void nghttp2_hd_huff_decode_context_init(nghttp2_hd_huff_decode_context *ctx) {
|
||||
ctx->state = 0;
|
||||
ctx->accept = 1;
|
||||
ctx->fstate = NGHTTP2_HUFF_ACCEPTED;
|
||||
}
|
||||
|
||||
ssize_t nghttp2_hd_huff_decode(nghttp2_hd_huff_decode_context *ctx,
|
||||
nghttp2_buf *buf, const uint8_t *src,
|
||||
size_t srclen, int final) {
|
||||
size_t i;
|
||||
const uint8_t *end = src + srclen;
|
||||
nghttp2_huff_decode node = {ctx->fstate, 0};
|
||||
const nghttp2_huff_decode *t = &node;
|
||||
uint8_t c;
|
||||
|
||||
/* We use the decoding algorithm described in
|
||||
http://graphics.ics.uci.edu/pub/Prefix.pdf */
|
||||
for (i = 0; i < srclen; ++i) {
|
||||
const nghttp2_huff_decode *t;
|
||||
|
||||
t = &huff_decode_table[ctx->state][src[i] >> 4];
|
||||
if (t->flags & NGHTTP2_HUFF_FAIL) {
|
||||
return NGHTTP2_ERR_HEADER_COMP;
|
||||
}
|
||||
if (t->flags & NGHTTP2_HUFF_SYM) {
|
||||
for (; src != end;) {
|
||||
c = *src++;
|
||||
t = &huff_decode_table[t->fstate & 0x1ff][c >> 4];
|
||||
if (t->fstate & NGHTTP2_HUFF_SYM) {
|
||||
*buf->last++ = t->sym;
|
||||
}
|
||||
|
||||
t = &huff_decode_table[t->state][src[i] & 0xf];
|
||||
if (t->flags & NGHTTP2_HUFF_FAIL) {
|
||||
return NGHTTP2_ERR_HEADER_COMP;
|
||||
}
|
||||
if (t->flags & NGHTTP2_HUFF_SYM) {
|
||||
t = &huff_decode_table[t->fstate & 0x1ff][c & 0xf];
|
||||
if (t->fstate & NGHTTP2_HUFF_SYM) {
|
||||
*buf->last++ = t->sym;
|
||||
}
|
||||
|
||||
ctx->state = t->state;
|
||||
ctx->accept = (t->flags & NGHTTP2_HUFF_ACCEPTED) != 0;
|
||||
}
|
||||
if (final && !ctx->accept) {
|
||||
|
||||
ctx->fstate = t->fstate;
|
||||
|
||||
if (final && !(ctx->fstate & NGHTTP2_HUFF_ACCEPTED)) {
|
||||
return NGHTTP2_ERR_HEADER_COMP;
|
||||
}
|
||||
return (ssize_t)i;
|
||||
|
||||
return (ssize_t)srclen;
|
||||
}
|
||||
|
||||
int nghttp2_hd_huff_decode_failure_state(nghttp2_hd_huff_decode_context *ctx) {
|
||||
return ctx->fstate == 0x100;
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
#define NGHTTP2_HD_HUFFMAN_H
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
# include <config.h>
|
||||
#endif /* HAVE_CONFIG_H */
|
||||
|
||||
#include <nghttp2/nghttp2.h>
|
||||
@@ -34,21 +34,20 @@
|
||||
typedef enum {
|
||||
/* FSA accepts this state as the end of huffman encoding
|
||||
sequence. */
|
||||
NGHTTP2_HUFF_ACCEPTED = 1,
|
||||
NGHTTP2_HUFF_ACCEPTED = 1 << 14,
|
||||
/* This state emits symbol */
|
||||
NGHTTP2_HUFF_SYM = (1 << 1),
|
||||
/* If state machine reaches this state, decoding fails. */
|
||||
NGHTTP2_HUFF_FAIL = (1 << 2)
|
||||
NGHTTP2_HUFF_SYM = 1 << 15,
|
||||
} nghttp2_huff_decode_flag;
|
||||
|
||||
typedef struct {
|
||||
/* huffman decoding state, which is actually the node ID of internal
|
||||
huffman tree. We have 257 leaf nodes, but they are identical to
|
||||
root node other than emitting a symbol, so we have 256 internal
|
||||
nodes [1..255], inclusive. */
|
||||
uint8_t state;
|
||||
/* bitwise OR of zero or more of the nghttp2_huff_decode_flag */
|
||||
uint8_t flags;
|
||||
/* fstate is the current huffman decoding state, which is actually
|
||||
the node ID of internal huffman tree with
|
||||
nghttp2_huff_decode_flag OR-ed. We have 257 leaf nodes, but they
|
||||
are identical to root node other than emitting a symbol, so we
|
||||
have 256 internal nodes [1..255], inclusive. The node ID 256 is
|
||||
a special node and it is a terminal state that means decoding
|
||||
failed. */
|
||||
uint16_t fstate;
|
||||
/* symbol if NGHTTP2_HUFF_SYM flag set */
|
||||
uint8_t sym;
|
||||
} nghttp2_huff_decode;
|
||||
@@ -56,12 +55,8 @@ typedef struct {
|
||||
typedef nghttp2_huff_decode huff_decode_table_type[16];
|
||||
|
||||
typedef struct {
|
||||
/* Current huffman decoding state. We stripped leaf nodes, so the
|
||||
value range is [0..255], inclusive. */
|
||||
uint8_t state;
|
||||
/* nonzero if we can say that the decoding process succeeds at this
|
||||
state */
|
||||
uint8_t accept;
|
||||
/* fstate is the current huffman decoding state. */
|
||||
uint16_t fstate;
|
||||
} nghttp2_hd_huff_decode_context;
|
||||
|
||||
typedef struct {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -334,13 +334,15 @@ const char *nghttp2_strerror(int error_code) {
|
||||
case NGHTTP2_ERR_FLOODED:
|
||||
return "Flooding was detected in this HTTP/2 session, and it must be "
|
||||
"closed";
|
||||
case NGHTTP2_ERR_TOO_MANY_SETTINGS:
|
||||
return "SETTINGS frame contained more than the maximum allowed entries";
|
||||
default:
|
||||
return "Unknown error code";
|
||||
}
|
||||
}
|
||||
|
||||
/* 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 /* EOT */, 0 /* ENQ */, 0 /* ACK */, 0 /* BEL */,
|
||||
0 /* BS */, 0 /* HT */, 0 /* LF */, 0 /* VT */,
|
||||
@@ -428,7 +430,7 @@ int nghttp2_check_header_name(const uint8_t *name, size_t len) {
|
||||
}
|
||||
|
||||
/* 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 /* EOT */, 0 /* ENQ */, 0 /* ACK */, 0 /* BEL */,
|
||||
0 /* BS */, 1 /* HT */, 0 /* LF */, 0 /* VT */,
|
||||
@@ -505,6 +507,84 @@ int nghttp2_check_header_value(const uint8_t *value, size_t len) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Generated by genauthroitychartbl.py */
|
||||
static char VALID_AUTHORITY_CHARS[] = {
|
||||
0 /* NUL */, 0 /* SOH */, 0 /* STX */, 0 /* ETX */,
|
||||
0 /* EOT */, 0 /* ENQ */, 0 /* ACK */, 0 /* BEL */,
|
||||
0 /* BS */, 0 /* HT */, 0 /* LF */, 0 /* VT */,
|
||||
0 /* FF */, 0 /* CR */, 0 /* SO */, 0 /* SI */,
|
||||
0 /* DLE */, 0 /* DC1 */, 0 /* DC2 */, 0 /* DC3 */,
|
||||
0 /* DC4 */, 0 /* NAK */, 0 /* SYN */, 0 /* ETB */,
|
||||
0 /* CAN */, 0 /* EM */, 0 /* SUB */, 0 /* ESC */,
|
||||
0 /* FS */, 0 /* GS */, 0 /* RS */, 0 /* US */,
|
||||
0 /* SPC */, 1 /* ! */, 0 /* " */, 0 /* # */,
|
||||
1 /* $ */, 1 /* % */, 1 /* & */, 1 /* ' */,
|
||||
1 /* ( */, 1 /* ) */, 1 /* * */, 1 /* + */,
|
||||
1 /* , */, 1 /* - */, 1 /* . */, 0 /* / */,
|
||||
1 /* 0 */, 1 /* 1 */, 1 /* 2 */, 1 /* 3 */,
|
||||
1 /* 4 */, 1 /* 5 */, 1 /* 6 */, 1 /* 7 */,
|
||||
1 /* 8 */, 1 /* 9 */, 1 /* : */, 1 /* ; */,
|
||||
0 /* < */, 1 /* = */, 0 /* > */, 0 /* ? */,
|
||||
1 /* @ */, 1 /* A */, 1 /* B */, 1 /* C */,
|
||||
1 /* D */, 1 /* E */, 1 /* F */, 1 /* G */,
|
||||
1 /* H */, 1 /* I */, 1 /* J */, 1 /* K */,
|
||||
1 /* L */, 1 /* M */, 1 /* N */, 1 /* O */,
|
||||
1 /* P */, 1 /* Q */, 1 /* R */, 1 /* S */,
|
||||
1 /* T */, 1 /* U */, 1 /* V */, 1 /* W */,
|
||||
1 /* X */, 1 /* Y */, 1 /* Z */, 1 /* [ */,
|
||||
0 /* \ */, 1 /* ] */, 0 /* ^ */, 1 /* _ */,
|
||||
0 /* ` */, 1 /* a */, 1 /* b */, 1 /* c */,
|
||||
1 /* d */, 1 /* e */, 1 /* f */, 1 /* g */,
|
||||
1 /* h */, 1 /* i */, 1 /* j */, 1 /* k */,
|
||||
1 /* l */, 1 /* m */, 1 /* n */, 1 /* o */,
|
||||
1 /* p */, 1 /* q */, 1 /* r */, 1 /* s */,
|
||||
1 /* t */, 1 /* u */, 1 /* v */, 1 /* w */,
|
||||
1 /* x */, 1 /* y */, 1 /* z */, 0 /* { */,
|
||||
0 /* | */, 0 /* } */, 1 /* ~ */, 0 /* DEL */,
|
||||
0 /* 0x80 */, 0 /* 0x81 */, 0 /* 0x82 */, 0 /* 0x83 */,
|
||||
0 /* 0x84 */, 0 /* 0x85 */, 0 /* 0x86 */, 0 /* 0x87 */,
|
||||
0 /* 0x88 */, 0 /* 0x89 */, 0 /* 0x8a */, 0 /* 0x8b */,
|
||||
0 /* 0x8c */, 0 /* 0x8d */, 0 /* 0x8e */, 0 /* 0x8f */,
|
||||
0 /* 0x90 */, 0 /* 0x91 */, 0 /* 0x92 */, 0 /* 0x93 */,
|
||||
0 /* 0x94 */, 0 /* 0x95 */, 0 /* 0x96 */, 0 /* 0x97 */,
|
||||
0 /* 0x98 */, 0 /* 0x99 */, 0 /* 0x9a */, 0 /* 0x9b */,
|
||||
0 /* 0x9c */, 0 /* 0x9d */, 0 /* 0x9e */, 0 /* 0x9f */,
|
||||
0 /* 0xa0 */, 0 /* 0xa1 */, 0 /* 0xa2 */, 0 /* 0xa3 */,
|
||||
0 /* 0xa4 */, 0 /* 0xa5 */, 0 /* 0xa6 */, 0 /* 0xa7 */,
|
||||
0 /* 0xa8 */, 0 /* 0xa9 */, 0 /* 0xaa */, 0 /* 0xab */,
|
||||
0 /* 0xac */, 0 /* 0xad */, 0 /* 0xae */, 0 /* 0xaf */,
|
||||
0 /* 0xb0 */, 0 /* 0xb1 */, 0 /* 0xb2 */, 0 /* 0xb3 */,
|
||||
0 /* 0xb4 */, 0 /* 0xb5 */, 0 /* 0xb6 */, 0 /* 0xb7 */,
|
||||
0 /* 0xb8 */, 0 /* 0xb9 */, 0 /* 0xba */, 0 /* 0xbb */,
|
||||
0 /* 0xbc */, 0 /* 0xbd */, 0 /* 0xbe */, 0 /* 0xbf */,
|
||||
0 /* 0xc0 */, 0 /* 0xc1 */, 0 /* 0xc2 */, 0 /* 0xc3 */,
|
||||
0 /* 0xc4 */, 0 /* 0xc5 */, 0 /* 0xc6 */, 0 /* 0xc7 */,
|
||||
0 /* 0xc8 */, 0 /* 0xc9 */, 0 /* 0xca */, 0 /* 0xcb */,
|
||||
0 /* 0xcc */, 0 /* 0xcd */, 0 /* 0xce */, 0 /* 0xcf */,
|
||||
0 /* 0xd0 */, 0 /* 0xd1 */, 0 /* 0xd2 */, 0 /* 0xd3 */,
|
||||
0 /* 0xd4 */, 0 /* 0xd5 */, 0 /* 0xd6 */, 0 /* 0xd7 */,
|
||||
0 /* 0xd8 */, 0 /* 0xd9 */, 0 /* 0xda */, 0 /* 0xdb */,
|
||||
0 /* 0xdc */, 0 /* 0xdd */, 0 /* 0xde */, 0 /* 0xdf */,
|
||||
0 /* 0xe0 */, 0 /* 0xe1 */, 0 /* 0xe2 */, 0 /* 0xe3 */,
|
||||
0 /* 0xe4 */, 0 /* 0xe5 */, 0 /* 0xe6 */, 0 /* 0xe7 */,
|
||||
0 /* 0xe8 */, 0 /* 0xe9 */, 0 /* 0xea */, 0 /* 0xeb */,
|
||||
0 /* 0xec */, 0 /* 0xed */, 0 /* 0xee */, 0 /* 0xef */,
|
||||
0 /* 0xf0 */, 0 /* 0xf1 */, 0 /* 0xf2 */, 0 /* 0xf3 */,
|
||||
0 /* 0xf4 */, 0 /* 0xf5 */, 0 /* 0xf6 */, 0 /* 0xf7 */,
|
||||
0 /* 0xf8 */, 0 /* 0xf9 */, 0 /* 0xfa */, 0 /* 0xfb */,
|
||||
0 /* 0xfc */, 0 /* 0xfd */, 0 /* 0xfe */, 0 /* 0xff */
|
||||
};
|
||||
|
||||
int nghttp2_check_authority(const uint8_t *value, size_t len) {
|
||||
const uint8_t *last;
|
||||
for (last = value + len; value != last; ++value) {
|
||||
if (!VALID_AUTHORITY_CHARS[*value]) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint8_t *nghttp2_cpymem(uint8_t *dest, const void *src, size_t len) {
|
||||
if (len == 0) {
|
||||
return dest;
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
#define NGHTTP2_HELPER_H
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
# include <config.h>
|
||||
#endif /* HAVE_CONFIG_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,
|
||||
int trailer) {
|
||||
int trailer, int connect_protocol) {
|
||||
if (nv->name->base[0] == ':') {
|
||||
if (trailer ||
|
||||
(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;
|
||||
}
|
||||
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;
|
||||
case 'S':
|
||||
@@ -162,9 +158,6 @@ static int http_request_on_header(nghttp2_stream *stream, nghttp2_hd_nv *nv,
|
||||
}
|
||||
break;
|
||||
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)) {
|
||||
return NGHTTP2_ERR_HTTP_HEADER;
|
||||
}
|
||||
@@ -175,9 +168,6 @@ static int http_request_on_header(nghttp2_stream *stream, nghttp2_hd_nv *nv,
|
||||
}
|
||||
break;
|
||||
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)) {
|
||||
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;
|
||||
}
|
||||
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:
|
||||
if (!check_pseudo_header(stream, nv, NGHTTP2_HTTP_FLAG_HOST)) {
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
break;
|
||||
@@ -264,11 +263,14 @@ static int http_response_on_header(nghttp2_stream *stream, nghttp2_hd_nv *nv,
|
||||
stream->content_length = 0;
|
||||
return NGHTTP2_ERR_REMOVE_HTTP_HEADER;
|
||||
}
|
||||
if (stream->status_code / 100 == 1 ||
|
||||
(stream->status_code == 200 &&
|
||||
(stream->http_flags & NGHTTP2_HTTP_FLAG_METH_CONNECT))) {
|
||||
if (stream->status_code / 100 == 1) {
|
||||
return NGHTTP2_ERR_HTTP_HEADER;
|
||||
}
|
||||
/* https://tools.ietf.org/html/rfc7230#section-3.3.3 */
|
||||
if (stream->status_code / 100 == 2 &&
|
||||
(stream->http_flags & NGHTTP2_HTTP_FLAG_METH_CONNECT)) {
|
||||
return NGHTTP2_ERR_REMOVE_HTTP_HEADER;
|
||||
}
|
||||
if (stream->content_length != -1) {
|
||||
return NGHTTP2_ERR_HTTP_HEADER;
|
||||
}
|
||||
@@ -303,84 +305,6 @@ static int http_response_on_header(nghttp2_stream *stream, nghttp2_hd_nv *nv,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Generated by genauthroitychartbl.py */
|
||||
static char VALID_AUTHORITY_CHARS[] = {
|
||||
0 /* NUL */, 0 /* SOH */, 0 /* STX */, 0 /* ETX */,
|
||||
0 /* EOT */, 0 /* ENQ */, 0 /* ACK */, 0 /* BEL */,
|
||||
0 /* BS */, 0 /* HT */, 0 /* LF */, 0 /* VT */,
|
||||
0 /* FF */, 0 /* CR */, 0 /* SO */, 0 /* SI */,
|
||||
0 /* DLE */, 0 /* DC1 */, 0 /* DC2 */, 0 /* DC3 */,
|
||||
0 /* DC4 */, 0 /* NAK */, 0 /* SYN */, 0 /* ETB */,
|
||||
0 /* CAN */, 0 /* EM */, 0 /* SUB */, 0 /* ESC */,
|
||||
0 /* FS */, 0 /* GS */, 0 /* RS */, 0 /* US */,
|
||||
0 /* SPC */, 1 /* ! */, 0 /* " */, 0 /* # */,
|
||||
1 /* $ */, 1 /* % */, 1 /* & */, 1 /* ' */,
|
||||
1 /* ( */, 1 /* ) */, 1 /* * */, 1 /* + */,
|
||||
1 /* , */, 1 /* - */, 1 /* . */, 0 /* / */,
|
||||
1 /* 0 */, 1 /* 1 */, 1 /* 2 */, 1 /* 3 */,
|
||||
1 /* 4 */, 1 /* 5 */, 1 /* 6 */, 1 /* 7 */,
|
||||
1 /* 8 */, 1 /* 9 */, 1 /* : */, 1 /* ; */,
|
||||
0 /* < */, 1 /* = */, 0 /* > */, 0 /* ? */,
|
||||
1 /* @ */, 1 /* A */, 1 /* B */, 1 /* C */,
|
||||
1 /* D */, 1 /* E */, 1 /* F */, 1 /* G */,
|
||||
1 /* H */, 1 /* I */, 1 /* J */, 1 /* K */,
|
||||
1 /* L */, 1 /* M */, 1 /* N */, 1 /* O */,
|
||||
1 /* P */, 1 /* Q */, 1 /* R */, 1 /* S */,
|
||||
1 /* T */, 1 /* U */, 1 /* V */, 1 /* W */,
|
||||
1 /* X */, 1 /* Y */, 1 /* Z */, 1 /* [ */,
|
||||
0 /* \ */, 1 /* ] */, 0 /* ^ */, 1 /* _ */,
|
||||
0 /* ` */, 1 /* a */, 1 /* b */, 1 /* c */,
|
||||
1 /* d */, 1 /* e */, 1 /* f */, 1 /* g */,
|
||||
1 /* h */, 1 /* i */, 1 /* j */, 1 /* k */,
|
||||
1 /* l */, 1 /* m */, 1 /* n */, 1 /* o */,
|
||||
1 /* p */, 1 /* q */, 1 /* r */, 1 /* s */,
|
||||
1 /* t */, 1 /* u */, 1 /* v */, 1 /* w */,
|
||||
1 /* x */, 1 /* y */, 1 /* z */, 0 /* { */,
|
||||
0 /* | */, 0 /* } */, 1 /* ~ */, 0 /* DEL */,
|
||||
0 /* 0x80 */, 0 /* 0x81 */, 0 /* 0x82 */, 0 /* 0x83 */,
|
||||
0 /* 0x84 */, 0 /* 0x85 */, 0 /* 0x86 */, 0 /* 0x87 */,
|
||||
0 /* 0x88 */, 0 /* 0x89 */, 0 /* 0x8a */, 0 /* 0x8b */,
|
||||
0 /* 0x8c */, 0 /* 0x8d */, 0 /* 0x8e */, 0 /* 0x8f */,
|
||||
0 /* 0x90 */, 0 /* 0x91 */, 0 /* 0x92 */, 0 /* 0x93 */,
|
||||
0 /* 0x94 */, 0 /* 0x95 */, 0 /* 0x96 */, 0 /* 0x97 */,
|
||||
0 /* 0x98 */, 0 /* 0x99 */, 0 /* 0x9a */, 0 /* 0x9b */,
|
||||
0 /* 0x9c */, 0 /* 0x9d */, 0 /* 0x9e */, 0 /* 0x9f */,
|
||||
0 /* 0xa0 */, 0 /* 0xa1 */, 0 /* 0xa2 */, 0 /* 0xa3 */,
|
||||
0 /* 0xa4 */, 0 /* 0xa5 */, 0 /* 0xa6 */, 0 /* 0xa7 */,
|
||||
0 /* 0xa8 */, 0 /* 0xa9 */, 0 /* 0xaa */, 0 /* 0xab */,
|
||||
0 /* 0xac */, 0 /* 0xad */, 0 /* 0xae */, 0 /* 0xaf */,
|
||||
0 /* 0xb0 */, 0 /* 0xb1 */, 0 /* 0xb2 */, 0 /* 0xb3 */,
|
||||
0 /* 0xb4 */, 0 /* 0xb5 */, 0 /* 0xb6 */, 0 /* 0xb7 */,
|
||||
0 /* 0xb8 */, 0 /* 0xb9 */, 0 /* 0xba */, 0 /* 0xbb */,
|
||||
0 /* 0xbc */, 0 /* 0xbd */, 0 /* 0xbe */, 0 /* 0xbf */,
|
||||
0 /* 0xc0 */, 0 /* 0xc1 */, 0 /* 0xc2 */, 0 /* 0xc3 */,
|
||||
0 /* 0xc4 */, 0 /* 0xc5 */, 0 /* 0xc6 */, 0 /* 0xc7 */,
|
||||
0 /* 0xc8 */, 0 /* 0xc9 */, 0 /* 0xca */, 0 /* 0xcb */,
|
||||
0 /* 0xcc */, 0 /* 0xcd */, 0 /* 0xce */, 0 /* 0xcf */,
|
||||
0 /* 0xd0 */, 0 /* 0xd1 */, 0 /* 0xd2 */, 0 /* 0xd3 */,
|
||||
0 /* 0xd4 */, 0 /* 0xd5 */, 0 /* 0xd6 */, 0 /* 0xd7 */,
|
||||
0 /* 0xd8 */, 0 /* 0xd9 */, 0 /* 0xda */, 0 /* 0xdb */,
|
||||
0 /* 0xdc */, 0 /* 0xdd */, 0 /* 0xde */, 0 /* 0xdf */,
|
||||
0 /* 0xe0 */, 0 /* 0xe1 */, 0 /* 0xe2 */, 0 /* 0xe3 */,
|
||||
0 /* 0xe4 */, 0 /* 0xe5 */, 0 /* 0xe6 */, 0 /* 0xe7 */,
|
||||
0 /* 0xe8 */, 0 /* 0xe9 */, 0 /* 0xea */, 0 /* 0xeb */,
|
||||
0 /* 0xec */, 0 /* 0xed */, 0 /* 0xee */, 0 /* 0xef */,
|
||||
0 /* 0xf0 */, 0 /* 0xf1 */, 0 /* 0xf2 */, 0 /* 0xf3 */,
|
||||
0 /* 0xf4 */, 0 /* 0xf5 */, 0 /* 0xf6 */, 0 /* 0xf7 */,
|
||||
0 /* 0xf8 */, 0 /* 0xf9 */, 0 /* 0xfa */, 0 /* 0xfb */,
|
||||
0 /* 0xfc */, 0 /* 0xfd */, 0 /* 0xfe */, 0 /* 0xff */
|
||||
};
|
||||
|
||||
static int check_authority(const uint8_t *value, size_t len) {
|
||||
const uint8_t *last;
|
||||
for (last = value + len; value != last; ++value) {
|
||||
if (!VALID_AUTHORITY_CHARS[*value]) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int check_scheme(const uint8_t *value, size_t len) {
|
||||
const uint8_t *last;
|
||||
if (len == 0) {
|
||||
@@ -438,7 +362,7 @@ int nghttp2_http_on_header(nghttp2_session *session, nghttp2_stream *stream,
|
||||
|
||||
if (nv->token == NGHTTP2_TOKEN__AUTHORITY ||
|
||||
nv->token == NGHTTP2_TOKEN_HOST) {
|
||||
rv = check_authority(nv->value->base, nv->value->len);
|
||||
rv = nghttp2_check_authority(nv->value->base, nv->value->len);
|
||||
} else if (nv->token == NGHTTP2_TOKEN__SCHEME) {
|
||||
rv = check_scheme(nv->value->base, nv->value->len);
|
||||
} else {
|
||||
@@ -458,7 +382,9 @@ int nghttp2_http_on_header(nghttp2_session *session, nghttp2_stream *stream,
|
||||
}
|
||||
|
||||
if (session->server || frame->hd.type == NGHTTP2_PUSH_PROMISE) {
|
||||
return http_request_on_header(stream, nv, trailer);
|
||||
return http_request_on_header(stream, nv, trailer,
|
||||
session->server &&
|
||||
session->pending_enable_connect_protocol);
|
||||
}
|
||||
|
||||
return http_response_on_header(stream, nv, trailer);
|
||||
@@ -466,8 +392,11 @@ int nghttp2_http_on_header(nghttp2_session *session, nghttp2_stream *stream,
|
||||
|
||||
int nghttp2_http_on_request_headers(nghttp2_stream *stream,
|
||||
nghttp2_frame *frame) {
|
||||
if (stream->http_flags & NGHTTP2_HTTP_FLAG_METH_CONNECT) {
|
||||
if ((stream->http_flags & NGHTTP2_HTTP_FLAG__AUTHORITY) == 0) {
|
||||
if (!(stream->http_flags & NGHTTP2_HTTP_FLAG__PROTOCOL) &&
|
||||
(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;
|
||||
}
|
||||
stream->content_length = -1;
|
||||
@@ -478,6 +407,11 @@ int nghttp2_http_on_request_headers(nghttp2_stream *stream,
|
||||
(NGHTTP2_HTTP_FLAG__AUTHORITY | NGHTTP2_HTTP_FLAG_HOST)) == 0) {
|
||||
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)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
#define NGHTTP2_HTTP_H
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
# include <config.h>
|
||||
#endif /* HAVE_CONFIG_H */
|
||||
|
||||
#include <nghttp2/nghttp2.h>
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
#define NGHTTP2_INT_H
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
# include <config.h>
|
||||
#endif /* HAVE_CONFIG_H */
|
||||
|
||||
#include <nghttp2/nghttp2.h>
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
#define NGHTTP2_MAP_H
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
# include <config.h>
|
||||
#endif /* HAVE_CONFIG_H */
|
||||
|
||||
#include <nghttp2/nghttp2.h>
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
#define NGHTTP2_MEM_H
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
# include <config.h>
|
||||
#endif /* HAVE_CONFIG_H */
|
||||
|
||||
#include <nghttp2/nghttp2.h>
|
||||
|
||||
@@ -26,15 +26,15 @@
|
||||
#define NGHTTP2_NET_H
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
# include <config.h>
|
||||
#endif /* HAVE_CONFIG_H */
|
||||
|
||||
#ifdef HAVE_ARPA_INET_H
|
||||
#include <arpa/inet.h>
|
||||
# include <arpa/inet.h>
|
||||
#endif /* HAVE_ARPA_INET_H */
|
||||
|
||||
#ifdef HAVE_NETINET_IN_H
|
||||
#include <netinet/in.h>
|
||||
# include <netinet/in.h>
|
||||
#endif /* HAVE_NETINET_IN_H */
|
||||
|
||||
#include <nghttp2/nghttp2.h>
|
||||
@@ -44,11 +44,11 @@
|
||||
define inline functions for those function so that we don't have
|
||||
dependeny on that lib. */
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define STIN static __inline
|
||||
#else
|
||||
#define STIN static inline
|
||||
#endif
|
||||
# ifdef _MSC_VER
|
||||
# define STIN static __inline
|
||||
# else
|
||||
# define STIN static inline
|
||||
# endif
|
||||
|
||||
STIN uint32_t htonl(uint32_t hostlong) {
|
||||
uint32_t res;
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
#define NGHTTP2_NPN_H
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
# include <config.h>
|
||||
#endif /* HAVE_CONFIG_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->builtin_recv_ext_types |= NGHTTP2_TYPEMASK_ALTSVC;
|
||||
return;
|
||||
case NGHTTP2_ORIGIN:
|
||||
option->opt_set_mask |= NGHTTP2_OPT_BUILTIN_RECV_EXT_TYPES;
|
||||
option->builtin_recv_ext_types |= NGHTTP2_TYPEMASK_ORIGIN;
|
||||
return;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
@@ -112,3 +116,13 @@ void nghttp2_option_set_no_closed_streams(nghttp2_option *option, int val) {
|
||||
option->opt_set_mask |= NGHTTP2_OPT_NO_CLOSED_STREAMS;
|
||||
option->no_closed_streams = val;
|
||||
}
|
||||
|
||||
void nghttp2_option_set_max_outbound_ack(nghttp2_option *option, size_t val) {
|
||||
option->opt_set_mask |= NGHTTP2_OPT_MAX_OUTBOUND_ACK;
|
||||
option->max_outbound_ack = val;
|
||||
}
|
||||
|
||||
void nghttp2_option_set_max_settings(nghttp2_option *option, size_t val) {
|
||||
option->opt_set_mask |= NGHTTP2_OPT_MAX_SETTINGS;
|
||||
option->max_settings = val;
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
#define NGHTTP2_OPTION_H
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
# include <config.h>
|
||||
#endif /* HAVE_CONFIG_H */
|
||||
|
||||
#include <nghttp2/nghttp2.h>
|
||||
@@ -66,6 +66,8 @@ typedef enum {
|
||||
NGHTTP2_OPT_MAX_SEND_HEADER_BLOCK_LENGTH = 1 << 8,
|
||||
NGHTTP2_OPT_MAX_DEFLATE_DYNAMIC_TABLE_SIZE = 1 << 9,
|
||||
NGHTTP2_OPT_NO_CLOSED_STREAMS = 1 << 10,
|
||||
NGHTTP2_OPT_MAX_OUTBOUND_ACK = 1 << 11,
|
||||
NGHTTP2_OPT_MAX_SETTINGS = 1 << 12,
|
||||
} nghttp2_option_flag;
|
||||
|
||||
/**
|
||||
@@ -80,6 +82,14 @@ struct nghttp2_option {
|
||||
* NGHTTP2_OPT_MAX_DEFLATE_DYNAMIC_TABLE_SIZE
|
||||
*/
|
||||
size_t max_deflate_dynamic_table_size;
|
||||
/**
|
||||
* NGHTTP2_OPT_MAX_OUTBOUND_ACK
|
||||
*/
|
||||
size_t max_outbound_ack;
|
||||
/**
|
||||
* NGHTTP2_OPT_MAX_SETTINGS
|
||||
*/
|
||||
size_t max_settings;
|
||||
/**
|
||||
* Bitwise OR of nghttp2_option_flag to determine that which fields
|
||||
* are specified.
|
||||
|
||||
@@ -86,6 +86,9 @@ void nghttp2_outbound_item_free(nghttp2_outbound_item *item, nghttp2_mem *mem) {
|
||||
case NGHTTP2_ALTSVC:
|
||||
nghttp2_frame_altsvc_free(&frame->ext, mem);
|
||||
break;
|
||||
case NGHTTP2_ORIGIN:
|
||||
nghttp2_frame_origin_free(&frame->ext, mem);
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
break;
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
#define NGHTTP2_OUTBOUND_ITEM_H
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
# include <config.h>
|
||||
#endif /* HAVE_CONFIG_H */
|
||||
|
||||
#include <nghttp2/nghttp2.h>
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
#define NGHTTP2_PQ_H
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
# include <config.h>
|
||||
#endif /* HAVE_CONFIG_H */
|
||||
|
||||
#include <nghttp2/nghttp2.h>
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
#define NGHTTP2_PRIORITY_SPEC_H
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
# include <config.h>
|
||||
#endif /* HAVE_CONFIG_H */
|
||||
|
||||
#include <nghttp2/nghttp2.h>
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
#define NGHTTP2_QUEUE_H
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
# include "config.h"
|
||||
#endif /* HAVE_CONFIG_H */
|
||||
|
||||
#include <nghttp2/nghttp2.h>
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
#define NGHTTP2_RCBUF_H
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
# include <config.h>
|
||||
#endif /* HAVE_CONFIG_H */
|
||||
|
||||
#include <nghttp2/nghttp2.h>
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -26,7 +26,7 @@
|
||||
#define NGHTTP2_SESSION_H
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
# include <config.h>
|
||||
#endif /* HAVE_CONFIG_H */
|
||||
|
||||
#include <nghttp2/nghttp2.h>
|
||||
@@ -61,7 +61,8 @@ typedef enum {
|
||||
*/
|
||||
typedef enum {
|
||||
NGHTTP2_TYPEMASK_NONE = 0,
|
||||
NGHTTP2_TYPEMASK_ALTSVC = 1 << 0
|
||||
NGHTTP2_TYPEMASK_ALTSVC = 1 << 0,
|
||||
NGHTTP2_TYPEMASK_ORIGIN = 1 << 1
|
||||
} nghttp2_typemask;
|
||||
|
||||
typedef enum {
|
||||
@@ -96,7 +97,7 @@ typedef struct {
|
||||
response frames are stacked up, which leads to memory exhaustion.
|
||||
The value selected here is arbitrary, but safe value and if we have
|
||||
these frames in this number, it is considered suspicious. */
|
||||
#define NGHTTP2_MAX_OBQ_FLOOD_ITEM 10000
|
||||
#define NGHTTP2_DEFAULT_MAX_OBQ_FLOOD_ITEM 1000
|
||||
|
||||
/* The default value of maximum number of concurrent streams. */
|
||||
#define NGHTTP2_DEFAULT_MAX_CONCURRENT_STREAMS 0xffffffffu
|
||||
@@ -121,6 +122,7 @@ typedef enum {
|
||||
NGHTTP2_IB_IGN_DATA,
|
||||
NGHTTP2_IB_IGN_ALL,
|
||||
NGHTTP2_IB_READ_ALTSVC_PAYLOAD,
|
||||
NGHTTP2_IB_READ_ORIGIN_PAYLOAD,
|
||||
NGHTTP2_IB_READ_EXTENSION_PAYLOAD
|
||||
} nghttp2_inbound_state;
|
||||
|
||||
@@ -162,6 +164,7 @@ typedef struct {
|
||||
uint32_t initial_window_size;
|
||||
uint32_t max_frame_size;
|
||||
uint32_t max_header_list_size;
|
||||
uint32_t enable_connect_protocol;
|
||||
} nghttp2_settings_storage;
|
||||
|
||||
typedef enum {
|
||||
@@ -206,9 +209,6 @@ struct nghttp2_session {
|
||||
nghttp2_session_callbacks callbacks;
|
||||
/* Memory allocator */
|
||||
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;
|
||||
/* Points to the latest incoming closed stream. NULL if there is no
|
||||
closed stream. Only used when session is initialized as
|
||||
@@ -258,11 +258,17 @@ struct nghttp2_session {
|
||||
size_t num_idle_streams;
|
||||
/* The number of bytes allocated for nvbuf */
|
||||
size_t nvbuflen;
|
||||
/* Counter for detecting flooding in outbound queue */
|
||||
/* Counter for detecting flooding in outbound queue. If it exceeds
|
||||
max_outbound_ack, session will be closed. */
|
||||
size_t obq_flood_counter_;
|
||||
/* The maximum number of outgoing SETTINGS ACK and PING ACK in
|
||||
outbound queue. */
|
||||
size_t max_outbound_ack;
|
||||
/* The maximum length of header block to send. Calculated by the
|
||||
same way as nghttp2_hd_deflate_bound() does. */
|
||||
size_t max_send_header_block_length;
|
||||
/* The maximum number of settings accepted per SETTINGS frame. */
|
||||
size_t max_settings;
|
||||
/* Next Stream ID. Made unsigned int to detect >= (1 << 31). */
|
||||
uint32_t next_stream_id;
|
||||
/* The last stream ID this session initiated. For client session,
|
||||
@@ -301,8 +307,10 @@ struct nghttp2_session {
|
||||
increased/decreased by submitting WINDOW_UPDATE. See
|
||||
nghttp2_submit_window_update(). */
|
||||
int32_t local_window_size;
|
||||
/* Settings value received from the remote endpoint. We just use ID
|
||||
as index. The index = 0 is unused. */
|
||||
/* This flag is used to indicate that the local endpoint received initial
|
||||
SETTINGS frame from the remote endpoint. */
|
||||
uint8_t remote_settings_received;
|
||||
/* Settings value received from the remote endpoint. */
|
||||
nghttp2_settings_storage remote_settings;
|
||||
/* Settings value of the local endpoint. */
|
||||
nghttp2_settings_storage local_settings;
|
||||
@@ -317,6 +325,9 @@ struct nghttp2_session {
|
||||
/* Unacked local ENABLE_PUSH value. We use this to refuse
|
||||
PUSH_PROMISE before SETTINGS ACK is received. */
|
||||
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. */
|
||||
uint8_t server;
|
||||
/* Flags indicating GOAWAY is sent and/or received. The flags are
|
||||
@@ -698,7 +709,7 @@ int nghttp2_session_on_push_promise_received(nghttp2_session *session,
|
||||
* NGHTTP2_ERR_NOMEM
|
||||
* Out of memory.
|
||||
* NGHTTP2_ERR_CALLBACK_FAILURE
|
||||
* The callback function failed.
|
||||
* The callback function failed.
|
||||
* NGHTTP2_ERR_FLOODED
|
||||
* There are too many items in outbound queue, and this is most
|
||||
* likely caused by misbehaviour of peer.
|
||||
@@ -716,7 +727,7 @@ int nghttp2_session_on_ping_received(nghttp2_session *session,
|
||||
* NGHTTP2_ERR_NOMEM
|
||||
* Out of memory.
|
||||
* NGHTTP2_ERR_CALLBACK_FAILURE
|
||||
* The callback function failed.
|
||||
* The callback function failed.
|
||||
*/
|
||||
int nghttp2_session_on_goaway_received(nghttp2_session *session,
|
||||
nghttp2_frame *frame);
|
||||
@@ -731,7 +742,7 @@ int nghttp2_session_on_goaway_received(nghttp2_session *session,
|
||||
* NGHTTP2_ERR_NOMEM
|
||||
* Out of memory.
|
||||
* NGHTTP2_ERR_CALLBACK_FAILURE
|
||||
* The callback function failed.
|
||||
* The callback function failed.
|
||||
*/
|
||||
int nghttp2_session_on_window_update_received(nghttp2_session *session,
|
||||
nghttp2_frame *frame);
|
||||
@@ -744,11 +755,24 @@ int nghttp2_session_on_window_update_received(nghttp2_session *session,
|
||||
* negative error codes:
|
||||
*
|
||||
* NGHTTP2_ERR_CALLBACK_FAILURE
|
||||
* The callback function failed.
|
||||
* The callback function failed.
|
||||
*/
|
||||
int nghttp2_session_on_altsvc_received(nghttp2_session *session,
|
||||
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
|
||||
* initialized.
|
||||
@@ -759,7 +783,7 @@ int nghttp2_session_on_altsvc_received(nghttp2_session *session,
|
||||
* NGHTTP2_ERR_NOMEM
|
||||
* Out of memory.
|
||||
* NGHTTP2_ERR_CALLBACK_FAILURE
|
||||
* The callback function failed.
|
||||
* The callback function failed.
|
||||
*/
|
||||
int nghttp2_session_on_data_received(nghttp2_session *session,
|
||||
nghttp2_frame *frame);
|
||||
@@ -876,4 +900,36 @@ int nghttp2_session_terminate_session_with_reason(nghttp2_session *session,
|
||||
uint32_t error_code,
|
||||
const char *reason);
|
||||
|
||||
/*
|
||||
* Accumulates received bytes |delta_size| for connection-level flow
|
||||
* control and decides whether to send WINDOW_UPDATE to the
|
||||
* connection. If NGHTTP2_OPT_NO_AUTO_WINDOW_UPDATE is set,
|
||||
* WINDOW_UPDATE will not be sent.
|
||||
*
|
||||
* This function returns 0 if it succeeds, or one of the following
|
||||
* negative error codes:
|
||||
*
|
||||
* NGHTTP2_ERR_NOMEM
|
||||
* Out of memory.
|
||||
*/
|
||||
int nghttp2_session_update_recv_connection_window_size(nghttp2_session *session,
|
||||
size_t delta_size);
|
||||
|
||||
/*
|
||||
* Accumulates received bytes |delta_size| for stream-level flow
|
||||
* control and decides whether to send WINDOW_UPDATE to that stream.
|
||||
* If NGHTTP2_OPT_NO_AUTO_WINDOW_UPDATE is set, WINDOW_UPDATE will not
|
||||
* be sent.
|
||||
*
|
||||
* This function returns 0 if it succeeds, or one of the following
|
||||
* negative error codes:
|
||||
*
|
||||
* NGHTTP2_ERR_NOMEM
|
||||
* Out of memory.
|
||||
*/
|
||||
int nghttp2_session_update_recv_stream_window_size(nghttp2_session *session,
|
||||
nghttp2_stream *stream,
|
||||
size_t delta_size,
|
||||
int send_window_update);
|
||||
|
||||
#endif /* NGHTTP2_SESSION_H */
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#include "nghttp2_session.h"
|
||||
#include "nghttp2_helper.h"
|
||||
#include "nghttp2_debug.h"
|
||||
#include "nghttp2_frame.h"
|
||||
|
||||
/* Maximum distance between any two stream's cycle in the same
|
||||
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
|
||||
result of overflow, and it is actually A > B if we consider that
|
||||
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) {
|
||||
const nghttp2_stream *lhs, *rhs;
|
||||
@@ -52,11 +54,7 @@ static int stream_less(const void *lhsx, const void *rhsx) {
|
||||
return lhs->seq < rhs->seq;
|
||||
}
|
||||
|
||||
if (lhs->cycle < rhs->cycle) {
|
||||
return rhs->cycle - lhs->cycle <= NGHTTP2_MAX_CYCLE_DISTANCE;
|
||||
}
|
||||
|
||||
return lhs->cycle - rhs->cycle > NGHTTP2_MAX_CYCLE_DISTANCE;
|
||||
return rhs->cycle - lhs->cycle <= NGHTTP2_MAX_CYCLE_DISTANCE;
|
||||
}
|
||||
|
||||
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|.
|
||||
*/
|
||||
static void stream_next_cycle(nghttp2_stream *stream, uint32_t last_cycle) {
|
||||
uint32_t penalty;
|
||||
static void stream_next_cycle(nghttp2_stream *stream, uint64_t last_cycle) {
|
||||
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->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) {
|
||||
@@ -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->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);
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
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) {
|
||||
nghttp2_stream *dep_stream;
|
||||
uint32_t last_cycle;
|
||||
uint64_t last_cycle;
|
||||
int32_t old_weight;
|
||||
uint32_t wlen_penalty;
|
||||
uint64_t wlen_penalty;
|
||||
|
||||
if (stream->weight == weight) {
|
||||
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);
|
||||
|
||||
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
|
||||
stream->cycle */
|
||||
@@ -289,9 +287,8 @@ void nghttp2_stream_change_weight(nghttp2_stream *stream, int32_t weight) {
|
||||
place */
|
||||
stream_next_cycle(stream, last_cycle);
|
||||
|
||||
if (stream->cycle < dep_stream->descendant_last_cycle &&
|
||||
(dep_stream->descendant_last_cycle - stream->cycle) <=
|
||||
NGHTTP2_MAX_CYCLE_DISTANCE) {
|
||||
if (dep_stream->descendant_last_cycle - stream->cycle <=
|
||||
NGHTTP2_MAX_CYCLE_DISTANCE) {
|
||||
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);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
#define NGHTTP2_STREAM_H
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
# include <config.h>
|
||||
#endif /* HAVE_CONFIG_H */
|
||||
|
||||
#include <nghttp2/nghttp2.h>
|
||||
@@ -130,7 +130,8 @@ typedef enum {
|
||||
/* "http" or "https" scheme */
|
||||
NGHTTP2_HTTP_FLAG_SCHEME_HTTP = 1 << 13,
|
||||
/* 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;
|
||||
|
||||
struct nghttp2_stream {
|
||||
@@ -147,9 +148,9 @@ struct nghttp2_stream {
|
||||
/* Received body so far */
|
||||
int64_t recv_content_length;
|
||||
/* Base last_cycle for direct descendent streams. */
|
||||
uint32_t descendant_last_cycle;
|
||||
uint64_t descendant_last_cycle;
|
||||
/* Next scheduled time to sent item */
|
||||
uint32_t cycle;
|
||||
uint64_t cycle;
|
||||
/* Next seq used for direct descendant streams */
|
||||
uint64_t descendant_next_seq;
|
||||
/* Secondary key for prioritization to break a tie for cycle. This
|
||||
|
||||
@@ -450,6 +450,13 @@ int nghttp2_session_set_local_window_size(nghttp2_session *session,
|
||||
if (rv != 0) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (window_size_increment > 0) {
|
||||
return nghttp2_session_add_window_update(session, 0, stream_id,
|
||||
window_size_increment);
|
||||
}
|
||||
|
||||
return nghttp2_session_update_recv_connection_window_size(session, 0);
|
||||
} else {
|
||||
stream = nghttp2_session_get_stream(session, stream_id);
|
||||
|
||||
@@ -476,11 +483,14 @@ int nghttp2_session_set_local_window_size(nghttp2_session *session,
|
||||
if (rv != 0) {
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
|
||||
if (window_size_increment > 0) {
|
||||
return nghttp2_session_add_window_update(session, 0, stream_id,
|
||||
window_size_increment);
|
||||
if (window_size_increment > 0) {
|
||||
return nghttp2_session_add_window_update(session, 0, stream_id,
|
||||
window_size_increment);
|
||||
}
|
||||
|
||||
return nghttp2_session_update_recv_stream_window_size(session, stream, 0,
|
||||
1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -571,6 +581,89 @@ fail_item_malloc:
|
||||
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,
|
||||
const nghttp2_data_provider *data_prd) {
|
||||
uint8_t flags = NGHTTP2_FLAG_NONE;
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
#define NGHTTP2_SUBMIT_H
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
# include <config.h>
|
||||
#endif /* HAVE_CONFIG_H */
|
||||
|
||||
#include <nghttp2/nghttp2.h>
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
# include <config.h>
|
||||
#endif /* HAVE_CONFIG_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
|
||||
])
|
||||
40
mkhufftbl.py
40
mkhufftbl.py
@@ -357,9 +357,8 @@ def _build_transition_table(ctx, node):
|
||||
def huffman_tree_build_transition_table(ctx):
|
||||
_build_transition_table(ctx, ctx.root)
|
||||
|
||||
NGHTTP2_HUFF_ACCEPTED = 1
|
||||
NGHTTP2_HUFF_SYM = 1 << 1
|
||||
NGHTTP2_HUFF_FAIL = 1 << 2
|
||||
NGHTTP2_HUFF_ACCEPTED = 1 << 14
|
||||
NGHTTP2_HUFF_SYM = 1 << 15
|
||||
|
||||
def _print_transition_table(node):
|
||||
if node.term is not None:
|
||||
@@ -374,8 +373,7 @@ def _print_transition_table(node):
|
||||
out = sym
|
||||
flags |= NGHTTP2_HUFF_SYM
|
||||
if nd is None:
|
||||
id = 0
|
||||
flags |= NGHTTP2_HUFF_FAIL
|
||||
id = 256
|
||||
else:
|
||||
id = nd.id
|
||||
if id is None:
|
||||
@@ -384,13 +382,32 @@ def _print_transition_table(node):
|
||||
flags |= NGHTTP2_HUFF_ACCEPTED
|
||||
elif nd.accept:
|
||||
flags |= NGHTTP2_HUFF_ACCEPTED
|
||||
print ' {{{}, 0x{:02x}, {}}},'.format(id, flags, out)
|
||||
print ' {{0x{:02x}, {}}},'.format(id | flags, out)
|
||||
print '},'
|
||||
_print_transition_table(node.left)
|
||||
_print_transition_table(node.right)
|
||||
|
||||
def huffman_tree_print_transition_table(ctx):
|
||||
_print_transition_table(ctx.root)
|
||||
print '/* 256 */'
|
||||
print '{'
|
||||
print ' {0x100, 0},'
|
||||
print ' {0x100, 0},'
|
||||
print ' {0x100, 0},'
|
||||
print ' {0x100, 0},'
|
||||
print ' {0x100, 0},'
|
||||
print ' {0x100, 0},'
|
||||
print ' {0x100, 0},'
|
||||
print ' {0x100, 0},'
|
||||
print ' {0x100, 0},'
|
||||
print ' {0x100, 0},'
|
||||
print ' {0x100, 0},'
|
||||
print ' {0x100, 0},'
|
||||
print ' {0x100, 0},'
|
||||
print ' {0x100, 0},'
|
||||
print ' {0x100, 0},'
|
||||
print ' {0x100, 0},'
|
||||
print '},'
|
||||
|
||||
if __name__ == '__main__':
|
||||
ctx = Context()
|
||||
@@ -423,9 +440,12 @@ typedef struct {
|
||||
print '''\
|
||||
const nghttp2_huff_sym huff_sym_table[] = {'''
|
||||
for i in range(257):
|
||||
nbits = symbol_tbl[i][0]
|
||||
k = int(symbol_tbl[i][1], 16)
|
||||
k = k << (32 - nbits)
|
||||
print '''\
|
||||
{{ {}, 0x{}u }}{}\
|
||||
'''.format(symbol_tbl[i][0], symbol_tbl[i][1], ',' if i < 256 else '')
|
||||
'''.format(symbol_tbl[i][0], hex(k)[2:], ',' if i < 256 else '')
|
||||
print '};'
|
||||
print ''
|
||||
|
||||
@@ -433,14 +453,12 @@ const nghttp2_huff_sym huff_sym_table[] = {'''
|
||||
enum {{
|
||||
NGHTTP2_HUFF_ACCEPTED = {},
|
||||
NGHTTP2_HUFF_SYM = {},
|
||||
NGHTTP2_HUFF_FAIL = {},
|
||||
}} nghttp2_huff_decode_flag;
|
||||
'''.format(NGHTTP2_HUFF_ACCEPTED, NGHTTP2_HUFF_SYM, NGHTTP2_HUFF_FAIL)
|
||||
'''.format(NGHTTP2_HUFF_ACCEPTED, NGHTTP2_HUFF_SYM)
|
||||
|
||||
print '''\
|
||||
typedef struct {
|
||||
uint8_t state;
|
||||
uint8_t flags;
|
||||
uint16_t fstate;
|
||||
uint8_t sym;
|
||||
} nghttp2_huff_decode;
|
||||
'''
|
||||
|
||||
@@ -10,9 +10,9 @@ set_source_files_properties(${cxx_sources} PROPERTIES
|
||||
include_directories(
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/includes"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/../third-party"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/../third-party/llhttp/include"
|
||||
|
||||
${JEMALLOC_INCLUDE_DIRS}
|
||||
${SPDYLAY_INCLUDE_DIRS}
|
||||
${LIBXML2_INCLUDE_DIRS}
|
||||
${LIBEV_INCLUDE_DIRS}
|
||||
${OPENSSL_INCLUDE_DIRS}
|
||||
@@ -25,7 +25,6 @@ include_directories(
|
||||
link_libraries(
|
||||
nghttp2
|
||||
${JEMALLOC_LIBRARIES}
|
||||
${SPDYLAY_LIBRARIES}
|
||||
${LIBXML2_LIBRARIES}
|
||||
${LIBEV_LIBRARIES}
|
||||
${OPENSSL_LIBRARIES}
|
||||
@@ -68,11 +67,6 @@ if(ENABLE_APP)
|
||||
h2load_http2_session.cc
|
||||
h2load_http1_session.cc
|
||||
)
|
||||
if(HAVE_SPDYLAY)
|
||||
list(APPEND H2LOAD_SOURCES
|
||||
h2load_spdy_session.cc
|
||||
)
|
||||
endif()
|
||||
|
||||
|
||||
# Common libnhttpx sources (used for nghttpx and unit tests)
|
||||
@@ -116,11 +110,6 @@ if(ENABLE_APP)
|
||||
shrpx_dns_tracker.cc
|
||||
xsi_strerror.c
|
||||
)
|
||||
if(HAVE_SPDYLAY)
|
||||
list(APPEND NGHTTPX_SRCS
|
||||
shrpx_spdy_upstream.cc
|
||||
)
|
||||
endif()
|
||||
if(HAVE_MRUBY)
|
||||
list(APPEND NGHTTPX_SRCS
|
||||
shrpx_mruby.cc
|
||||
@@ -137,6 +126,12 @@ if(ENABLE_APP)
|
||||
shrpx.cc
|
||||
)
|
||||
|
||||
if(HAVE_SYSTEMD)
|
||||
target_link_libraries(nghttpx_static ${SYSTEMD_LIBRARIES})
|
||||
target_compile_definitions(nghttpx_static PUBLIC HAVE_LIBSYSTEMD)
|
||||
target_include_directories(nghttpx_static PUBLIC ${SYSTEMD_INCLUDE_DIRS})
|
||||
endif()
|
||||
|
||||
if(HAVE_MRUBY)
|
||||
target_link_libraries(nghttpx_static mruby-lib)
|
||||
endif()
|
||||
@@ -166,7 +161,8 @@ if(ENABLE_APP)
|
||||
)
|
||||
add_executable(nghttpx-unittest EXCLUDE_FROM_ALL
|
||||
${NGHTTPX_UNITTEST_SOURCES}
|
||||
$<TARGET_OBJECTS:http-parser>
|
||||
$<TARGET_OBJECTS:llhttp>
|
||||
$<TARGET_OBJECTS:url-parser>
|
||||
)
|
||||
target_include_directories(nghttpx-unittest PRIVATE ${CUNIT_INCLUDE_DIRS})
|
||||
target_compile_definitions(nghttpx-unittest
|
||||
@@ -184,12 +180,20 @@ if(ENABLE_APP)
|
||||
add_dependencies(check nghttpx-unittest)
|
||||
endif()
|
||||
|
||||
add_executable(nghttp ${NGHTTP_SOURCES} $<TARGET_OBJECTS:http-parser>)
|
||||
add_executable(nghttpd ${NGHTTPD_SOURCES} $<TARGET_OBJECTS:http-parser>)
|
||||
add_executable(nghttpx ${NGHTTPX-bin_SOURCES} $<TARGET_OBJECTS:http-parser>)
|
||||
add_executable(nghttp ${NGHTTP_SOURCES} $<TARGET_OBJECTS:llhttp>
|
||||
$<TARGET_OBJECTS:url-parser>
|
||||
)
|
||||
add_executable(nghttpd ${NGHTTPD_SOURCES} $<TARGET_OBJECTS:llhttp>
|
||||
$<TARGET_OBJECTS:url-parser>
|
||||
)
|
||||
add_executable(nghttpx ${NGHTTPX-bin_SOURCES} $<TARGET_OBJECTS:llhttp>
|
||||
$<TARGET_OBJECTS:url-parser>
|
||||
)
|
||||
target_compile_definitions(nghttpx PRIVATE "-DPKGDATADIR=\"${PKGDATADIR}\"")
|
||||
target_link_libraries(nghttpx nghttpx_static)
|
||||
add_executable(h2load ${H2LOAD_SOURCES} $<TARGET_OBJECTS:http-parser>)
|
||||
add_executable(h2load ${H2LOAD_SOURCES} $<TARGET_OBJECTS:llhttp>
|
||||
$<TARGET_OBJECTS:url-parser>
|
||||
)
|
||||
|
||||
install(TARGETS nghttp nghttpd nghttpx h2load
|
||||
RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}")
|
||||
@@ -243,7 +247,8 @@ if(ENABLE_ASIO_LIB)
|
||||
|
||||
add_library(nghttp2_asio SHARED
|
||||
${NGHTTP2_ASIO_SOURCES}
|
||||
$<TARGET_OBJECTS:http-parser>
|
||||
$<TARGET_OBJECTS:llhttp>
|
||||
$<TARGET_OBJECTS:url-parser>
|
||||
)
|
||||
target_include_directories(nghttp2_asio PRIVATE
|
||||
${OPENSSL_INCLUDE_DIRS}
|
||||
@@ -263,7 +268,9 @@ if(ENABLE_ASIO_LIB)
|
||||
VERSION 1.0.0 SOVERSION 1)
|
||||
|
||||
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"
|
||||
DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig")
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
|
||||
#ifdef HAVE_LIBXML2
|
||||
|
||||
#include <libxml/HTMLparser.h>
|
||||
# include <libxml/HTMLparser.h>
|
||||
|
||||
#endif // HAVE_LIBXML2
|
||||
|
||||
|
||||
@@ -26,23 +26,23 @@
|
||||
|
||||
#include <sys/stat.h>
|
||||
#ifdef HAVE_SYS_SOCKET_H
|
||||
#include <sys/socket.h>
|
||||
# include <sys/socket.h>
|
||||
#endif // HAVE_SYS_SOCKET_H
|
||||
#ifdef HAVE_NETDB_H
|
||||
#include <netdb.h>
|
||||
# include <netdb.h>
|
||||
#endif // HAVE_NETDB_H
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
# include <unistd.h>
|
||||
#endif // HAVE_UNISTD_H
|
||||
#ifdef HAVE_FCNTL_H
|
||||
#include <fcntl.h>
|
||||
# include <fcntl.h>
|
||||
#endif // HAVE_FCNTL_H
|
||||
#ifdef HAVE_NETINET_IN_H
|
||||
#include <netinet/in.h>
|
||||
# include <netinet/in.h>
|
||||
#endif // HAVE_NETINET_IN_H
|
||||
#include <netinet/tcp.h>
|
||||
#ifdef HAVE_ARPA_INET_H
|
||||
#include <arpa/inet.h>
|
||||
# include <arpa/inet.h>
|
||||
#endif // HAVE_ARPA_INET_H
|
||||
|
||||
#include <cassert>
|
||||
@@ -64,7 +64,7 @@
|
||||
#include "template.h"
|
||||
|
||||
#ifndef O_BINARY
|
||||
#define O_BINARY (0)
|
||||
# define O_BINARY (0)
|
||||
#endif // O_BINARY
|
||||
|
||||
namespace nghttp2 {
|
||||
@@ -305,7 +305,7 @@ public:
|
||||
}
|
||||
}
|
||||
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 (handler->connection_made() != 0) {
|
||||
return;
|
||||
@@ -358,11 +358,11 @@ public:
|
||||
}
|
||||
FileEntry *cache_fd(const std::string &path, const FileEntry &ent) {
|
||||
#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
|
||||
// for gcc-4.7
|
||||
auto rv =
|
||||
fd_cache_.insert(std::make_pair(path, make_unique<FileEntry>(ent)));
|
||||
auto rv = fd_cache_.insert(
|
||||
std::make_pair(path, std::make_unique<FileEntry>(ent)));
|
||||
#endif // !HAVE_STD_MAP_EMPLACE
|
||||
auto &res = (*rv).second;
|
||||
res->it = rv;
|
||||
@@ -624,32 +624,30 @@ int Http2Handler::read_clear() {
|
||||
int rv;
|
||||
std::array<uint8_t, 8_k> buf;
|
||||
|
||||
for (;;) {
|
||||
ssize_t nread;
|
||||
while ((nread = read(fd_, buf.data(), buf.size())) == -1 && errno == EINTR)
|
||||
;
|
||||
if (nread == -1) {
|
||||
if (errno == EAGAIN || errno == EWOULDBLOCK) {
|
||||
break;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
if (nread == 0) {
|
||||
return -1;
|
||||
ssize_t nread;
|
||||
while ((nread = read(fd_, buf.data(), buf.size())) == -1 && errno == EINTR)
|
||||
;
|
||||
if (nread == -1) {
|
||||
if (errno == EAGAIN || errno == EWOULDBLOCK) {
|
||||
return write_(*this);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
if (nread == 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (get_config()->hexdump) {
|
||||
util::hexdump(stdout, buf.data(), nread);
|
||||
}
|
||||
if (get_config()->hexdump) {
|
||||
util::hexdump(stdout, buf.data(), nread);
|
||||
}
|
||||
|
||||
rv = nghttp2_session_mem_recv(session_, buf.data(), nread);
|
||||
if (rv < 0) {
|
||||
if (rv != NGHTTP2_ERR_BAD_CLIENT_MAGIC) {
|
||||
std::cerr << "nghttp2_session_mem_recv() returned error: "
|
||||
<< nghttp2_strerror(rv) << std::endl;
|
||||
}
|
||||
return -1;
|
||||
rv = nghttp2_session_mem_recv(session_, buf.data(), nread);
|
||||
if (rv < 0) {
|
||||
if (rv != NGHTTP2_ERR_BAD_CLIENT_MAGIC) {
|
||||
std::cerr << "nghttp2_session_mem_recv() returned error: "
|
||||
<< nghttp2_strerror(rv) << std::endl;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
return write_(*this);
|
||||
@@ -745,39 +743,36 @@ int Http2Handler::read_tls() {
|
||||
|
||||
ERR_clear_error();
|
||||
|
||||
for (;;) {
|
||||
auto rv = SSL_read(ssl_, buf.data(), buf.size());
|
||||
auto rv = SSL_read(ssl_, buf.data(), buf.size());
|
||||
|
||||
if (rv <= 0) {
|
||||
auto err = SSL_get_error(ssl_, rv);
|
||||
switch (err) {
|
||||
case SSL_ERROR_WANT_READ:
|
||||
goto fin;
|
||||
case SSL_ERROR_WANT_WRITE:
|
||||
// renegotiation started
|
||||
return -1;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
auto nread = rv;
|
||||
|
||||
if (get_config()->hexdump) {
|
||||
util::hexdump(stdout, buf.data(), nread);
|
||||
}
|
||||
|
||||
rv = nghttp2_session_mem_recv(session_, buf.data(), nread);
|
||||
if (rv < 0) {
|
||||
if (rv != NGHTTP2_ERR_BAD_CLIENT_MAGIC) {
|
||||
std::cerr << "nghttp2_session_mem_recv() returned error: "
|
||||
<< nghttp2_strerror(rv) << std::endl;
|
||||
}
|
||||
if (rv <= 0) {
|
||||
auto err = SSL_get_error(ssl_, rv);
|
||||
switch (err) {
|
||||
case SSL_ERROR_WANT_READ:
|
||||
return write_(*this);
|
||||
case SSL_ERROR_WANT_WRITE:
|
||||
// renegotiation started
|
||||
return -1;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
fin:
|
||||
auto nread = rv;
|
||||
|
||||
if (get_config()->hexdump) {
|
||||
util::hexdump(stdout, buf.data(), nread);
|
||||
}
|
||||
|
||||
rv = nghttp2_session_mem_recv(session_, buf.data(), nread);
|
||||
if (rv < 0) {
|
||||
if (rv != NGHTTP2_ERR_BAD_CLIENT_MAGIC) {
|
||||
std::cerr << "nghttp2_session_mem_recv() returned error: "
|
||||
<< nghttp2_strerror(rv) << std::endl;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
return write_(*this);
|
||||
}
|
||||
|
||||
@@ -888,7 +883,9 @@ int Http2Handler::verify_npn_result() {
|
||||
const unsigned char *next_proto = nullptr;
|
||||
unsigned int next_proto_len;
|
||||
// Check the negotiated protocol in NPN or ALPN
|
||||
#ifndef OPENSSL_NO_NEXTPROTONEG
|
||||
SSL_get0_next_proto_negotiated(ssl_, &next_proto, &next_proto_len);
|
||||
#endif // !OPENSSL_NO_NEXTPROTONEG
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
if (next_proto) {
|
||||
auto proto = StringRef{next_proto, next_proto_len};
|
||||
@@ -1021,7 +1018,7 @@ int Http2Handler::submit_push_promise(Stream *stream,
|
||||
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;
|
||||
promised_header.method = StringRef::from_lit("GET");
|
||||
@@ -1475,7 +1472,7 @@ int on_begin_headers_callback(nghttp2_session *session,
|
||||
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());
|
||||
|
||||
@@ -1830,10 +1827,10 @@ public:
|
||||
if (config_->verbose) {
|
||||
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());
|
||||
worker->sessions =
|
||||
make_unique<Sessions>(sv, loop, config_, sessions_->get_ssl_ctx());
|
||||
worker->sessions = std::make_unique<Sessions>(sv, loop, config_,
|
||||
sessions_->get_ssl_ctx());
|
||||
ev_async_init(&worker->w, worker_acceptcb);
|
||||
worker->w.data = worker.get();
|
||||
ev_async_start(loop, &worker->w);
|
||||
@@ -1982,6 +1979,7 @@ HttpServer::HttpServer(const Config *config) : config_(config) {
|
||||
};
|
||||
}
|
||||
|
||||
#ifndef OPENSSL_NO_NEXTPROTONEG
|
||||
namespace {
|
||||
int next_proto_cb(SSL *s, const unsigned char **data, unsigned int *len,
|
||||
void *arg) {
|
||||
@@ -1991,6 +1989,7 @@ int next_proto_cb(SSL *s, const unsigned char **data, unsigned int *len,
|
||||
return SSL_TLSEXT_ERR_OK;
|
||||
}
|
||||
} // namespace
|
||||
#endif // !OPENSSL_NO_NEXTPROTONEG
|
||||
|
||||
namespace {
|
||||
int verify_callback(int preverify_ok, X509_STORE_CTX *ctx) {
|
||||
@@ -2205,7 +2204,9 @@ int HttpServer::run() {
|
||||
|
||||
next_proto = util::get_default_alpn();
|
||||
|
||||
#ifndef OPENSSL_NO_NEXTPROTONEG
|
||||
SSL_CTX_set_next_protos_advertised_cb(ssl_ctx, next_proto_cb, &next_proto);
|
||||
#endif // !OPENSSL_NO_NEXTPROTONEG
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x10002000L
|
||||
// ALPN selection callback
|
||||
SSL_CTX_set_alpn_select_cb(ssl_ctx, alpn_select_proto_cb, this);
|
||||
|
||||
@@ -40,6 +40,7 @@ AM_CPPFLAGS = \
|
||||
-I$(top_srcdir)/lib \
|
||||
-I$(top_srcdir)/src/includes \
|
||||
-I$(top_srcdir)/third-party \
|
||||
-I$(top_srcdir)/third-party/llhttp/include \
|
||||
@LIBXML2_CFLAGS@ \
|
||||
@LIBEV_CFLAGS@ \
|
||||
@OPENSSL_CFLAGS@ \
|
||||
@@ -49,7 +50,8 @@ AM_CPPFLAGS = \
|
||||
@DEFS@
|
||||
|
||||
LDADD = $(top_builddir)/lib/libnghttp2.la \
|
||||
$(top_builddir)/third-party/libhttp-parser.la \
|
||||
$(top_builddir)/third-party/liburl-parser.la \
|
||||
$(top_builddir)/third-party/libllhttp.la \
|
||||
@JEMALLOC_LIBS@ \
|
||||
@LIBXML2_LIBS@ \
|
||||
@LIBEV_LIBS@ \
|
||||
@@ -263,7 +265,8 @@ libnghttp2_asio_la_CPPFLAGS = ${AM_CPPFLAGS} ${BOOST_CPPFLAGS}
|
||||
libnghttp2_asio_la_LDFLAGS = -no-undefined -version-info 1:0:0
|
||||
libnghttp2_asio_la_LIBADD = \
|
||||
$(top_builddir)/lib/libnghttp2.la \
|
||||
$(top_builddir)/third-party/libhttp-parser.la \
|
||||
$(top_builddir)/third-party/liburl-parser.la \
|
||||
$(top_builddir)/third-party/libllhttp.la \
|
||||
@OPENSSL_LIBS@ \
|
||||
${BOOST_LDFLAGS} \
|
||||
${BOOST_ASIO_LIB} \
|
||||
|
||||
@@ -28,10 +28,11 @@
|
||||
#include "nghttp2_config.h"
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <sys/uio.h>
|
||||
# include <sys/uio.h>
|
||||
#endif // !_WIN32
|
||||
|
||||
#include <cassert>
|
||||
#include <utility>
|
||||
|
||||
#include "template.h"
|
||||
|
||||
@@ -65,25 +66,19 @@ struct BlockAllocator {
|
||||
~BlockAllocator() { reset(); }
|
||||
|
||||
BlockAllocator(BlockAllocator &&other) noexcept
|
||||
: retain(other.retain),
|
||||
head(other.head),
|
||||
: retain{std::exchange(other.retain, nullptr)},
|
||||
head{std::exchange(other.head, nullptr)},
|
||||
block_size(other.block_size),
|
||||
isolation_threshold(other.isolation_threshold) {
|
||||
other.retain = nullptr;
|
||||
other.head = nullptr;
|
||||
}
|
||||
isolation_threshold(other.isolation_threshold) {}
|
||||
|
||||
BlockAllocator &operator=(BlockAllocator &&other) noexcept {
|
||||
reset();
|
||||
|
||||
retain = other.retain;
|
||||
head = other.head;
|
||||
retain = std::exchange(other.retain, nullptr);
|
||||
head = std::exchange(other.head, nullptr);
|
||||
block_size = other.block_size;
|
||||
isolation_threshold = other.isolation_threshold;
|
||||
|
||||
other.retain = nullptr;
|
||||
other.head = nullptr;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
@@ -24,19 +24,19 @@
|
||||
*/
|
||||
#include <sys/types.h>
|
||||
#ifdef HAVE_SYS_SOCKET_H
|
||||
#include <sys/socket.h>
|
||||
# include <sys/socket.h>
|
||||
#endif // HAVE_SYS_SOCKET_H
|
||||
#ifdef HAVE_NETDB_H
|
||||
#include <netdb.h>
|
||||
# include <netdb.h>
|
||||
#endif // HAVE_NETDB_H
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
# include <unistd.h>
|
||||
#endif // HAVE_UNISTD_H
|
||||
#ifdef HAVE_FCNTL_H
|
||||
#include <fcntl.h>
|
||||
# include <fcntl.h>
|
||||
#endif // HAVE_FCNTL_H
|
||||
#ifdef HAVE_NETINET_IN_H
|
||||
#include <netinet/in.h>
|
||||
# include <netinet/in.h>
|
||||
#endif // HAVE_NETINET_IN_H
|
||||
#include <netinet/tcp.h>
|
||||
#include <poll.h>
|
||||
@@ -77,6 +77,8 @@ const char *strsettingsid(int32_t id) {
|
||||
return "SETTINGS_MAX_FRAME_SIZE";
|
||||
case NGHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE:
|
||||
return "SETTINGS_MAX_HEADER_LIST_SIZE";
|
||||
case NGHTTP2_SETTINGS_ENABLE_CONNECT_PROTOCOL:
|
||||
return "SETTINGS_ENABLE_CONNECT_PROTOCOL";
|
||||
default:
|
||||
return "UNKNOWN";
|
||||
}
|
||||
@@ -106,6 +108,8 @@ std::string strframetype(uint8_t type) {
|
||||
return "WINDOW_UPDATE";
|
||||
case NGHTTP2_ALTSVC:
|
||||
return "ALTSVC";
|
||||
case NGHTTP2_ORIGIN:
|
||||
return "ORIGIN";
|
||||
}
|
||||
|
||||
std::string s = "extension(0x";
|
||||
@@ -351,6 +355,15 @@ void print_frame(print_type ptype, const nghttp2_frame *frame) {
|
||||
static_cast<int>(altsvc->field_value_len), altsvc->field_value);
|
||||
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:
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
#include <cinttypes>
|
||||
#include <cstdlib>
|
||||
#ifdef HAVE_SYS_TIME_H
|
||||
#include <sys/time.h>
|
||||
# include <sys/time.h>
|
||||
#endif // HAVE_SYS_TIME_H
|
||||
#include <poll.h>
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ namespace nghttp2 {
|
||||
namespace asio_http2 {
|
||||
namespace client {
|
||||
|
||||
request::request() : impl_(make_unique<request_impl>()) {}
|
||||
request::request() : impl_(std::make_unique<request_impl>()) {}
|
||||
|
||||
request::~request() {}
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ namespace nghttp2 {
|
||||
namespace asio_http2 {
|
||||
namespace client {
|
||||
|
||||
response::response() : impl_(make_unique<response_impl>()) {}
|
||||
response::response() : impl_(std::make_unique<response_impl>()) {}
|
||||
|
||||
response::~response() {}
|
||||
|
||||
|
||||
@@ -44,6 +44,15 @@ session::session(boost::asio::io_service &io_service, const std::string &host,
|
||||
impl_->start_resolve(host, service);
|
||||
}
|
||||
|
||||
session::session(boost::asio::io_service &io_service,
|
||||
const boost::asio::ip::tcp::endpoint &local_endpoint,
|
||||
const std::string &host, const std::string &service)
|
||||
: impl_(std::make_shared<session_tcp_impl>(
|
||||
io_service, local_endpoint, host, service,
|
||||
boost::posix_time::seconds(60))) {
|
||||
impl_->start_resolve(host, service);
|
||||
}
|
||||
|
||||
session::session(boost::asio::io_service &io_service, const std::string &host,
|
||||
const std::string &service,
|
||||
const boost::posix_time::time_duration &connect_timeout)
|
||||
@@ -52,6 +61,15 @@ session::session(boost::asio::io_service &io_service, const std::string &host,
|
||||
impl_->start_resolve(host, service);
|
||||
}
|
||||
|
||||
session::session(boost::asio::io_service &io_service,
|
||||
const boost::asio::ip::tcp::endpoint &local_endpoint,
|
||||
const std::string &host, const std::string &service,
|
||||
const boost::posix_time::time_duration &connect_timeout)
|
||||
: impl_(std::make_shared<session_tcp_impl>(io_service, local_endpoint, host,
|
||||
service, connect_timeout)) {
|
||||
impl_->start_resolve(host, service);
|
||||
}
|
||||
|
||||
session::session(boost::asio::io_service &io_service,
|
||||
boost::asio::ssl::context &tls_ctx, const std::string &host,
|
||||
const std::string &service)
|
||||
@@ -136,7 +154,7 @@ const nghttp2_priority_spec *priority_spec::get() const {
|
||||
return &spec_;
|
||||
}
|
||||
|
||||
const bool priority_spec::valid() const { return valid_; }
|
||||
bool priority_spec::valid() const { return valid_; }
|
||||
|
||||
} // namespace client
|
||||
} // namespace asio_http2
|
||||
|
||||
@@ -473,7 +473,7 @@ stream *session_impl::create_push_stream(int32_t stream_id) {
|
||||
}
|
||||
|
||||
std::unique_ptr<stream> session_impl::create_stream() {
|
||||
return make_unique<stream>(this);
|
||||
return std::make_unique<stream>(this);
|
||||
}
|
||||
|
||||
const request *session_impl::submit(boost::system::error_code &ec,
|
||||
|
||||
@@ -34,24 +34,35 @@ session_tcp_impl::session_tcp_impl(
|
||||
const boost::posix_time::time_duration &connect_timeout)
|
||||
: session_impl(io_service, connect_timeout), socket_(io_service) {}
|
||||
|
||||
session_tcp_impl::session_tcp_impl(
|
||||
boost::asio::io_service &io_service,
|
||||
const boost::asio::ip::tcp::endpoint &local_endpoint,
|
||||
const std::string &host, const std::string &service,
|
||||
const boost::posix_time::time_duration &connect_timeout)
|
||||
: session_impl(io_service, connect_timeout), socket_(io_service) {
|
||||
socket_.open(local_endpoint.protocol());
|
||||
boost::asio::socket_base::reuse_address option(true);
|
||||
socket_.set_option(option);
|
||||
socket_.bind(local_endpoint);
|
||||
}
|
||||
|
||||
session_tcp_impl::~session_tcp_impl() {}
|
||||
|
||||
void session_tcp_impl::start_connect(tcp::resolver::iterator endpoint_it) {
|
||||
auto self = shared_from_this();
|
||||
boost::asio::async_connect(socket_, endpoint_it,
|
||||
[self](const boost::system::error_code &ec,
|
||||
tcp::resolver::iterator endpoint_it) {
|
||||
if (self->stopped()) {
|
||||
return;
|
||||
}
|
||||
socket_.async_connect(
|
||||
*endpoint_it, [self, endpoint_it](const boost::system::error_code &ec) {
|
||||
if (self->stopped()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (ec) {
|
||||
self->not_connected(ec);
|
||||
return;
|
||||
}
|
||||
if (ec) {
|
||||
self->not_connected(ec);
|
||||
return;
|
||||
}
|
||||
|
||||
self->connected(endpoint_it);
|
||||
});
|
||||
self->connected(endpoint_it);
|
||||
});
|
||||
}
|
||||
|
||||
tcp::socket &session_tcp_impl::socket() { return socket_; }
|
||||
|
||||
@@ -40,6 +40,10 @@ public:
|
||||
session_tcp_impl(boost::asio::io_service &io_service, const std::string &host,
|
||||
const std::string &service,
|
||||
const boost::posix_time::time_duration &connect_timeout);
|
||||
session_tcp_impl(boost::asio::io_service &io_service,
|
||||
const boost::asio::ip::tcp::endpoint &local_endpoint,
|
||||
const std::string &host, const std::string &service,
|
||||
const boost::posix_time::time_duration &connect_timeout);
|
||||
virtual ~session_tcp_impl();
|
||||
|
||||
virtual void start_connect(tcp::resolver::iterator endpoint_it);
|
||||
|
||||
@@ -38,6 +38,10 @@ session_tls_impl::session_tls_impl(
|
||||
// ssl::context::set_verify_mode(boost::asio::ssl::verify_peer) is
|
||||
// not used, which is what we want.
|
||||
socket_.set_verify_callback(boost::asio::ssl::rfc2818_verification(host));
|
||||
auto ssl = socket_.native_handle();
|
||||
if (!util::numeric_host(host.c_str())) {
|
||||
SSL_set_tlsext_host_name(ssl, host.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
session_tls_impl::~session_tls_impl() {}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user