mirror of
https://github.com/nghttp2/nghttp2.git
synced 2025-12-08 11:08:52 +08:00
Compare commits
516 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0880de4668 | ||
|
|
e4454672f0 | ||
|
|
e15a5517c7 | ||
|
|
9b0044d051 | ||
|
|
e9e5e15bbf | ||
|
|
2c7ef6442d | ||
|
|
d3ecf78031 | ||
|
|
d01db47215 | ||
|
|
8a760d0726 | ||
|
|
73bfe4bf21 | ||
|
|
6e5e9bceca | ||
|
|
0476f0efbc | ||
|
|
ca23a490c3 | ||
|
|
ee2a4b625b | ||
|
|
cec4bf08a2 | ||
|
|
ebf4b7eaee | ||
|
|
0bf5b764fa | ||
|
|
081eb29e9f | ||
|
|
ca81d89fe1 | ||
|
|
450ed6afce | ||
|
|
e72f4af5de | ||
|
|
3fa6a6349c | ||
|
|
6c0fd9400d | ||
|
|
de81da7621 | ||
|
|
8593b1f46c | ||
|
|
0e9d325dee | ||
|
|
534b74b725 | ||
|
|
090c7fe26c | ||
|
|
527cdebfee | ||
|
|
a2667a6692 | ||
|
|
aedc348754 | ||
|
|
19fbcf5238 | ||
|
|
6fe99003df | ||
|
|
0139746d53 | ||
|
|
8dd0c86bde | ||
|
|
5d4df477e8 | ||
|
|
2b355a338c | ||
|
|
cfeec12a52 | ||
|
|
26e2d53536 | ||
|
|
d921c54209 | ||
|
|
8f729331c1 | ||
|
|
a25dd12811 | ||
|
|
2f1565b0e2 | ||
|
|
389ae66d12 | ||
|
|
a60e00c628 | ||
|
|
53ce088694 | ||
|
|
e802ccc02a | ||
|
|
17428a5d09 | ||
|
|
83683742f1 | ||
|
|
fa585e9182 | ||
|
|
7434a37016 | ||
|
|
a2c47748f0 | ||
|
|
1784c1c0d1 | ||
|
|
59a9534a2d | ||
|
|
7fcbcd786e | ||
|
|
4e0738d24a | ||
|
|
1e0413f4a6 | ||
|
|
06e7219d10 | ||
|
|
c06c069126 | ||
|
|
d8ed2559f6 | ||
|
|
d829be3517 | ||
|
|
6aa9f6c72e | ||
|
|
4181fffc02 | ||
|
|
8f8eef40e8 | ||
|
|
3a95bf47f3 | ||
|
|
c218d441ea | ||
|
|
1952b166e9 | ||
|
|
bcfb5d8305 | ||
|
|
37fb82621c | ||
|
|
00bd05edcc | ||
|
|
45c67616b9 | ||
|
|
d94ce2a557 | ||
|
|
8a5c731533 | ||
|
|
6dfb3bdb8f | ||
|
|
43649c8004 | ||
|
|
b35fa94ba5 | ||
|
|
ee6565feb7 | ||
|
|
7caa11f09e | ||
|
|
cb73b18a53 | ||
|
|
4da70b34d1 | ||
|
|
cd868f00b9 | ||
|
|
9fc31cfd16 | ||
|
|
e9f04ae0ad | ||
|
|
5e75f0ac81 | ||
|
|
8c3f077c5e | ||
|
|
9cbe936a25 | ||
|
|
b815972b03 | ||
|
|
59b6d0d1d9 | ||
|
|
028eeeefeb | ||
|
|
1feb3679fe | ||
|
|
b00d8da2e2 | ||
|
|
9df3962d08 | ||
|
|
304bfcbb70 | ||
|
|
280845e52e | ||
|
|
bdc5d5a6d1 | ||
|
|
c9ff3599de | ||
|
|
15912bf810 | ||
|
|
9e65104b00 | ||
|
|
80ecefebb5 | ||
|
|
43b4369fba | ||
|
|
89b30903cc | ||
|
|
4904c736e1 | ||
|
|
3b45a19423 | ||
|
|
fbf4a7b750 | ||
|
|
2a190bf5ee | ||
|
|
877a78186c | ||
|
|
3d363ae478 | ||
|
|
73141a7698 | ||
|
|
eacf3484ca | ||
|
|
45ac57609b | ||
|
|
3190d030f7 | ||
|
|
6979a07da6 | ||
|
|
768e383662 | ||
|
|
6fd2f9e027 | ||
|
|
54359802fa | ||
|
|
bc57689f17 | ||
|
|
3ae75e840e | ||
|
|
7f79fbfa3e | ||
|
|
4c10abe99e | ||
|
|
2fed8b4945 | ||
|
|
f266ee500d | ||
|
|
708912fe20 | ||
|
|
f90a801609 | ||
|
|
107b7814fa | ||
|
|
bd70a1546c | ||
|
|
6e660ddc4b | ||
|
|
ea28e672ae | ||
|
|
fe8685e37f | ||
|
|
62c12b673b | ||
|
|
9ba0b7fde0 | ||
|
|
f9f5db5b6a | ||
|
|
7ef3a91d9b | ||
|
|
e435050378 | ||
|
|
8f5b450237 | ||
|
|
5f5fdc780f | ||
|
|
fd48570e7f | ||
|
|
daa4260f61 | ||
|
|
451853f39b | ||
|
|
dfab53ef65 | ||
|
|
5d4d517535 | ||
|
|
c36b8ee88a | ||
|
|
2e84de0be9 | ||
|
|
e18beaa3bd | ||
|
|
4890cb0fb8 | ||
|
|
06fb688be2 | ||
|
|
56d5406bce | ||
|
|
0196b2cc03 | ||
|
|
de7da99453 | ||
|
|
40124de400 | ||
|
|
6d7f80ed7f | ||
|
|
7bf98f2729 | ||
|
|
e434b74e50 | ||
|
|
7784fa979d | ||
|
|
8391ae7a57 | ||
|
|
d63d2568b7 | ||
|
|
d8d94e7a69 | ||
|
|
ef3b25e152 | ||
|
|
52ae8b7d9f | ||
|
|
d204cd0880 | ||
|
|
32a5793b02 | ||
|
|
b81979f35b | ||
|
|
808271a5a9 | ||
|
|
4bfd528d44 | ||
|
|
2fefe482bf | ||
|
|
1c2ba03f94 | ||
|
|
5edfa62c7b | ||
|
|
efad89d9d2 | ||
|
|
a8dfe825d0 | ||
|
|
a9b0230e57 | ||
|
|
01b16f64f4 | ||
|
|
b41ca012b4 | ||
|
|
d2b58bd0cd | ||
|
|
fc43fc1805 | ||
|
|
1616d9ef05 | ||
|
|
05b29df6eb | ||
|
|
9f0c59d6dd | ||
|
|
af02195b60 | ||
|
|
0f46173c2d | ||
|
|
ac22e0efe3 | ||
|
|
031ae82552 | ||
|
|
6b3e58127d | ||
|
|
5e576bda7d | ||
|
|
6039258f01 | ||
|
|
121e401166 | ||
|
|
67ab8145c7 | ||
|
|
68b663eaba | ||
|
|
c9f3166c4d | ||
|
|
eafb876a5b | ||
|
|
c8790efadf | ||
|
|
fbcf341878 | ||
|
|
1adb1d9bb7 | ||
|
|
c9bf55f125 | ||
|
|
2b07607cac | ||
|
|
556fa9f781 | ||
|
|
827da803f6 | ||
|
|
b1496253d0 | ||
|
|
811608bef8 | ||
|
|
db304adf70 | ||
|
|
ef94a3be9a | ||
|
|
2f283177f7 | ||
|
|
b13eb2c13f | ||
|
|
9707f9bfbe | ||
|
|
53785c2434 | ||
|
|
4f450d0f5a | ||
|
|
86a36fec8a | ||
|
|
5ccd54734a | ||
|
|
ecf42e76a8 | ||
|
|
c72e5f116d | ||
|
|
d79fd53b67 | ||
|
|
0bfdc8682d | ||
|
|
af5f768a52 | ||
|
|
9a51528aab | ||
|
|
e403873ac8 | ||
|
|
e004f75e77 | ||
|
|
55e02bdb70 | ||
|
|
d28170aaeb | ||
|
|
d2e9479da4 | ||
|
|
e0c815249d | ||
|
|
f5053fb2ad | ||
|
|
53ca70ae70 | ||
|
|
eea717d21b | ||
|
|
2e86b1bd77 | ||
|
|
8b638f219c | ||
|
|
91340d59bb | ||
|
|
3eafe7e630 | ||
|
|
923014d163 | ||
|
|
4fe2aab723 | ||
|
|
65c9142cd1 | ||
|
|
d159ff9baa | ||
|
|
4ef64cab52 | ||
|
|
a7ae4f80ab | ||
|
|
075788af7c | ||
|
|
24d4afb967 | ||
|
|
a4d961eb17 | ||
|
|
1d8abe7d1c | ||
|
|
6ad6c61af2 | ||
|
|
1440e88347 | ||
|
|
4e34e45be6 | ||
|
|
3ebd7f9966 | ||
|
|
ef7b349928 | ||
|
|
abdd0ea313 | ||
|
|
7eb7740e01 | ||
|
|
bbc091d762 | ||
|
|
4fa4e5fdad | ||
|
|
06b758de98 | ||
|
|
c98c67ae73 | ||
|
|
32e26bcf68 | ||
|
|
b420749135 | ||
|
|
47e886b5a0 | ||
|
|
cf5b34a12e | ||
|
|
91328046dd | ||
|
|
d34515372a | ||
|
|
2a79151248 | ||
|
|
b07227a169 | ||
|
|
1213986096 | ||
|
|
fe0f31a85c | ||
|
|
550000f160 | ||
|
|
36a9d3620e | ||
|
|
e6463c00f7 | ||
|
|
c827d07c10 | ||
|
|
f8e31cf478 | ||
|
|
963cbb4cce | ||
|
|
a1e557a725 | ||
|
|
a6c036e719 | ||
|
|
80627afe00 | ||
|
|
052a3fafa9 | ||
|
|
5535d099f6 | ||
|
|
23e555662e | ||
|
|
bbe10abe2e | ||
|
|
a86e70d278 | ||
|
|
ba484c41a9 | ||
|
|
413674f3ab | ||
|
|
e907529aaf | ||
|
|
05f517b118 | ||
|
|
d99de27967 | ||
|
|
ceeb73fbfb | ||
|
|
f336a3dfde | ||
|
|
196e533430 | ||
|
|
eefe3759f1 | ||
|
|
fd18019e84 | ||
|
|
8dfd1c3f95 | ||
|
|
d448ee9fa5 | ||
|
|
0f6f47ebc9 | ||
|
|
03c416a2ca | ||
|
|
2ac38479f5 | ||
|
|
a4e447bd84 | ||
|
|
bf292cc752 | ||
|
|
3ed14f2b38 | ||
|
|
c3574b711d | ||
|
|
8d9c80a285 | ||
|
|
34b18758cb | ||
|
|
89fb8dd503 | ||
|
|
7634e06611 | ||
|
|
9278383c1a | ||
|
|
86ba78b461 | ||
|
|
82320337ea | ||
|
|
3b7cabf15a | ||
|
|
63aa83ac42 | ||
|
|
9a09d9602b | ||
|
|
9ac5a1a773 | ||
|
|
1814fc1f2f | ||
|
|
23f2cb85fe | ||
|
|
1c07b88b2a | ||
|
|
44484e2ed5 | ||
|
|
78f542d59e | ||
|
|
99f658d600 | ||
|
|
aa2955c8fb | ||
|
|
d995c75173 | ||
|
|
bb7a0c78ce | ||
|
|
4993297326 | ||
|
|
e0089070f5 | ||
|
|
c3c418ce7a | ||
|
|
2643afa593 | ||
|
|
1a118fc0b2 | ||
|
|
1af84eca7b | ||
|
|
e3fbf4b0f1 | ||
|
|
ac080aeabb | ||
|
|
f59f7b6ded | ||
|
|
d73b5d42e9 | ||
|
|
8b0c12219a | ||
|
|
f0fce329b3 | ||
|
|
c39db11532 | ||
|
|
be06de738c | ||
|
|
3b82d4848a | ||
|
|
5504920feb | ||
|
|
faa3831d05 | ||
|
|
75d836c21e | ||
|
|
0b730de705 | ||
|
|
4f2b72dbeb | ||
|
|
5faf84cf2f | ||
|
|
784c1dbe36 | ||
|
|
74c6a20d96 | ||
|
|
901d8d777c | ||
|
|
880fa82e65 | ||
|
|
855e65b9c8 | ||
|
|
a2f37abdbe | ||
|
|
e9b9de1006 | ||
|
|
ab32a1bb40 | ||
|
|
e81aeb6fe4 | ||
|
|
a404ba5c12 | ||
|
|
7d15a7aa6b | ||
|
|
d41fd15d23 | ||
|
|
c1f08ca2f6 | ||
|
|
aeb5185a44 | ||
|
|
88171ab2bf | ||
|
|
02d1de1d9d | ||
|
|
339bc419bf | ||
|
|
81e817f695 | ||
|
|
6659de1cfd | ||
|
|
9e11a12c72 | ||
|
|
a1e9e5f640 | ||
|
|
2f02abfe7a | ||
|
|
3bca3282f1 | ||
|
|
646615022d | ||
|
|
dd293082fc | ||
|
|
9e235fe957 | ||
|
|
2b47d4b525 | ||
|
|
fa5ac09ade | ||
|
|
a993d99977 | ||
|
|
d400319bcc | ||
|
|
10d00c8a53 | ||
|
|
b559f69199 | ||
|
|
4513bfc3fc | ||
|
|
5e373a3514 | ||
|
|
0df91a4b0c | ||
|
|
c362f9d36c | ||
|
|
9b568cf542 | ||
|
|
6be52029db | ||
|
|
fef9e8fb20 | ||
|
|
09bb8350e8 | ||
|
|
10ebb3825a | ||
|
|
8bdf022465 | ||
|
|
14f1169a5a | ||
|
|
93dd369b0e | ||
|
|
bb3c2a3664 | ||
|
|
11903f36a9 | ||
|
|
afedd3aa06 | ||
|
|
242c0c3988 | ||
|
|
ed3b31fa4c | ||
|
|
b7be212c30 | ||
|
|
ac92a4daae | ||
|
|
ed1c6ed344 | ||
|
|
f804e92785 | ||
|
|
9275353a47 | ||
|
|
d1bc03bd57 | ||
|
|
853b9ccd3c | ||
|
|
dd02d164ba | ||
|
|
c36d0cb807 | ||
|
|
68ed952004 | ||
|
|
f7f8592d6d | ||
|
|
500eb25302 | ||
|
|
d074d20ad4 | ||
|
|
66e5d45994 | ||
|
|
e68fa65166 | ||
|
|
d5b11e6f94 | ||
|
|
51909d8bf8 | ||
|
|
299b6a4e31 | ||
|
|
a7407b28ce | ||
|
|
4397a37b31 | ||
|
|
996b02c2fe | ||
|
|
f27d667cec | ||
|
|
50c2a0fc99 | ||
|
|
9a7dad6a50 | ||
|
|
12e6caadce | ||
|
|
3cdfcd3819 | ||
|
|
87396313d6 | ||
|
|
48ee27dcd0 | ||
|
|
cb94c00a36 | ||
|
|
fa00277afe | ||
|
|
bf5565ea2c | ||
|
|
da6f0dd646 | ||
|
|
71dd4399fc | ||
|
|
08c0dad06f | ||
|
|
be9066bd7a | ||
|
|
13aa7e5e78 | ||
|
|
0dbcb08e64 | ||
|
|
a158d1dbb4 | ||
|
|
5742430337 | ||
|
|
75453db4ce | ||
|
|
458613c923 | ||
|
|
f29a47d577 | ||
|
|
4b6e156ddf | ||
|
|
5e26011caf | ||
|
|
4cd3369ed1 | ||
|
|
90b2fbea66 | ||
|
|
5b725c8a83 | ||
|
|
83e079322e | ||
|
|
cc0207c967 | ||
|
|
1f84d34371 | ||
|
|
f1808e1a0f | ||
|
|
07cc22bffa | ||
|
|
db0a936158 | ||
|
|
e1c1168db3 | ||
|
|
f5606f9855 | ||
|
|
d014becee2 | ||
|
|
b27c5481ef | ||
|
|
fe6288421f | ||
|
|
6e60f76825 | ||
|
|
5784ff5b46 | ||
|
|
d75fddda00 | ||
|
|
c17cf5f1f5 | ||
|
|
2fb05c54ad | ||
|
|
9555260a65 | ||
|
|
4ce6c8e1dc | ||
|
|
6677faed55 | ||
|
|
8a8838de29 | ||
|
|
fa453878c4 | ||
|
|
93072a2828 | ||
|
|
f52d191a69 | ||
|
|
84f36115e5 | ||
|
|
8dd0637645 | ||
|
|
4d6bca22cc | ||
|
|
7bb4146e58 | ||
|
|
ed5f3df612 | ||
|
|
f402668a4e | ||
|
|
f723380e32 | ||
|
|
1db823f451 | ||
|
|
fcd710e31d | ||
|
|
6922b336b0 | ||
|
|
6edf4343b2 | ||
|
|
81864f3c7f | ||
|
|
2a0c0a2598 | ||
|
|
3db4000c80 | ||
|
|
c7b33ceea9 | ||
|
|
e47a2cc34a | ||
|
|
aa77184ed5 | ||
|
|
58ff9e5188 | ||
|
|
a0bf1d13bb | ||
|
|
c47ab92f69 | ||
|
|
ad4b9529dc | ||
|
|
b5819be055 | ||
|
|
21dfefa0c3 | ||
|
|
4c013d1087 | ||
|
|
825b296d12 | ||
|
|
514b7743d6 | ||
|
|
5265110509 | ||
|
|
aa96bfcb27 | ||
|
|
c7f062aeca | ||
|
|
32eeffcd11 | ||
|
|
67a93b53a3 | ||
|
|
941024f193 | ||
|
|
127adf6acf | ||
|
|
ff3655c7cd | ||
|
|
b58c6402f9 | ||
|
|
0af7b9bb84 | ||
|
|
188cd1ef6b | ||
|
|
aa82e0132a | ||
|
|
dbd027c796 | ||
|
|
999baf9090 | ||
|
|
ce5b1e9235 | ||
|
|
ac29d9da5f | ||
|
|
44495acf4f | ||
|
|
29263b1b41 | ||
|
|
3d2e252e2c | ||
|
|
e1337244d3 | ||
|
|
885ea764a0 | ||
|
|
58a38d00e4 | ||
|
|
24a1554e3a | ||
|
|
d167c34753 | ||
|
|
4fd86afb89 | ||
|
|
a2aa9d1fc7 | ||
|
|
283cbc4df5 | ||
|
|
18d98dd215 | ||
|
|
3dee622df6 | ||
|
|
6b81eeb106 | ||
|
|
594bc072ae | ||
|
|
077259c08c | ||
|
|
168f210f34 | ||
|
|
a86dbfd723 | ||
|
|
daef61594c | ||
|
|
de7b174cec | ||
|
|
d6af4a90d5 | ||
|
|
ea6079c2ab | ||
|
|
3fbebd97cd | ||
|
|
b3f18d73f5 | ||
|
|
cfbe1ff69c |
@@ -35,7 +35,29 @@ AlignConsecutiveShortCaseStatements:
|
||||
Enabled: false
|
||||
AcrossEmptyLines: false
|
||||
AcrossComments: false
|
||||
AlignCaseArrows: false
|
||||
AlignCaseColons: false
|
||||
AlignConsecutiveTableGenBreakingDAGArgColons:
|
||||
Enabled: false
|
||||
AcrossEmptyLines: false
|
||||
AcrossComments: false
|
||||
AlignCompound: false
|
||||
AlignFunctionPointers: false
|
||||
PadOperators: false
|
||||
AlignConsecutiveTableGenCondOperatorColons:
|
||||
Enabled: false
|
||||
AcrossEmptyLines: false
|
||||
AcrossComments: false
|
||||
AlignCompound: false
|
||||
AlignFunctionPointers: false
|
||||
PadOperators: false
|
||||
AlignConsecutiveTableGenDefinitionColons:
|
||||
Enabled: false
|
||||
AcrossEmptyLines: false
|
||||
AcrossComments: false
|
||||
AlignCompound: false
|
||||
AlignFunctionPointers: false
|
||||
PadOperators: false
|
||||
AlignEscapedNewlines: Right
|
||||
AlignOperands: Align
|
||||
AlignTrailingComments:
|
||||
@@ -45,6 +67,7 @@ AllowAllArgumentsOnNextLine: true
|
||||
AllowAllParametersOfDeclarationOnNextLine: true
|
||||
AllowBreakBeforeNoexceptSpecifier: Never
|
||||
AllowShortBlocksOnASingleLine: Never
|
||||
AllowShortCaseExpressionOnASingleLine: true
|
||||
AllowShortCaseLabelsOnASingleLine: false
|
||||
AllowShortCompoundRequirementOnASingleLine: true
|
||||
AllowShortEnumsOnASingleLine: true
|
||||
@@ -53,9 +76,7 @@ AllowShortIfStatementsOnASingleLine: Never
|
||||
AllowShortLambdasOnASingleLine: All
|
||||
AllowShortLoopsOnASingleLine: false
|
||||
AlwaysBreakAfterDefinitionReturnType: None
|
||||
AlwaysBreakAfterReturnType: None
|
||||
AlwaysBreakBeforeMultilineStrings: false
|
||||
AlwaysBreakTemplateDeclarations: MultiLine
|
||||
AttributeMacros:
|
||||
- __capability
|
||||
BinPackArguments: true
|
||||
@@ -83,6 +104,7 @@ BraceWrapping:
|
||||
BreakAdjacentStringLiterals: true
|
||||
BreakAfterAttributes: Leave
|
||||
BreakAfterJavaFieldAnnotations: false
|
||||
BreakAfterReturnType: None
|
||||
BreakArrays: true
|
||||
BreakBeforeBinaryOperators: None
|
||||
BreakBeforeConceptDeclarations: Always
|
||||
@@ -90,8 +112,10 @@ BreakBeforeBraces: Attach
|
||||
BreakBeforeInlineASMColon: OnlyMultiline
|
||||
BreakBeforeTernaryOperators: true
|
||||
BreakConstructorInitializers: BeforeColon
|
||||
BreakFunctionDefinitionParameters: false
|
||||
BreakInheritanceList: BeforeColon
|
||||
BreakStringLiterals: true
|
||||
BreakTemplateDeclarations: MultiLine
|
||||
ColumnLimit: 80
|
||||
CommentPragmas: '^ IWYU pragma:'
|
||||
CompactNamespaces: false
|
||||
@@ -147,12 +171,15 @@ IntegerLiteralSeparator:
|
||||
HexMinDigits: 0
|
||||
JavaScriptQuotes: Leave
|
||||
JavaScriptWrapImports: true
|
||||
KeepEmptyLinesAtTheStartOfBlocks: false
|
||||
KeepEmptyLinesAtEOF: false
|
||||
KeepEmptyLines:
|
||||
AtEndOfFile: false
|
||||
AtStartOfBlock: false
|
||||
AtStartOfFile: true
|
||||
LambdaBodyIndentation: Signature
|
||||
LineEnding: DeriveLF
|
||||
MacroBlockBegin: ''
|
||||
MacroBlockEnd: ''
|
||||
MainIncludeChar: Quote
|
||||
MaxEmptyLinesToKeep: 1
|
||||
NamespaceIndentation: None
|
||||
ObjCBinPackProtocolList: Auto
|
||||
@@ -221,6 +248,7 @@ SpacesInLineCommentPrefix:
|
||||
Maximum: -1
|
||||
SpacesInParens: Never
|
||||
SpacesInParensOptions:
|
||||
ExceptDoubleParentheses: false
|
||||
InCStyleCasts: false
|
||||
InConditionalStatements: false
|
||||
InEmptyParentheses: false
|
||||
@@ -235,6 +263,7 @@ StatementMacros:
|
||||
- munit_void_test_decl
|
||||
- nghttp2_max_def
|
||||
- nghttp2_min_def
|
||||
TableGenBreakInsideDAGArg: DontBreak
|
||||
TabWidth: 8
|
||||
UseTab: Never
|
||||
VerilogBreakBetweenInstancePorts: true
|
||||
|
||||
24
.github/workflows/android.yml
vendored
Normal file
24
.github/workflows/android.yml
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
name: android
|
||||
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- Dockerfile.android
|
||||
- .github/workflows/android.yml
|
||||
branches:
|
||||
- '**'
|
||||
|
||||
permissions: read-all
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-24.04
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
- name: Build
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
file: Dockerfile.android
|
||||
95
.github/workflows/build.yml
vendored
95
.github/workflows/build.yml
vendored
@@ -5,26 +5,26 @@ on: [push, pull_request]
|
||||
permissions: read-all
|
||||
|
||||
env:
|
||||
LIBBPF_VERSION: v1.5.0
|
||||
LIBBPF_VERSION: v1.6.2
|
||||
OPENSSL1_VERSION: 1_1_1w+quic
|
||||
OPENSSL3_VERSION: 3.1.7+quic
|
||||
BORINGSSL_VERSION: 294ab9730c570213b496cfc2fc14b3c0bfcd4bcc
|
||||
AWSLC_VERSION: v1.46.1
|
||||
NGHTTP3_VERSION: v1.8.0
|
||||
NGTCP2_VERSION: v1.11.0
|
||||
WOLFSSL_VERSION: v5.7.6-stable
|
||||
OPENSSL3_VERSION: 3.6.0
|
||||
BORINGSSL_VERSION: db1a8456167249f95b854a1cd24c6b553d0f1567
|
||||
AWSLC_VERSION: v1.62.0
|
||||
NGHTTP3_VERSION: v1.12.0
|
||||
NGTCP2_VERSION: v1.17.0
|
||||
WOLFSSL_VERSION: v5.8.2-stable
|
||||
|
||||
jobs:
|
||||
build-cache:
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-24.04, macos-13, macos-14]
|
||||
os: [ubuntu-24.04, macos-14, macos-15]
|
||||
|
||||
runs-on: ${{ matrix.os }}
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
- name: Restore libbpf cache
|
||||
id: cache-libbpf
|
||||
uses: actions/cache@v4
|
||||
@@ -49,8 +49,8 @@ jobs:
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
boringssl/build/crypto/libcrypto.a
|
||||
boringssl/build/ssl/libssl.a
|
||||
boringssl/build/libcrypto.a
|
||||
boringssl/build/libssl.a
|
||||
boringssl/include
|
||||
key: ${{ matrix.os }}-boringssl-${{ env.BORINGSSL_VERSION }}
|
||||
- name: Restore aws-lc cache
|
||||
@@ -133,12 +133,12 @@ jobs:
|
||||
./config --prefix=$PWD/build
|
||||
make -j"$(nproc 2> /dev/null || sysctl -n hw.ncpu)"
|
||||
make install_sw
|
||||
- name: Build quictls/openssl v3.x
|
||||
- name: Build openssl/openssl v3.x
|
||||
if: steps.cache-openssl3.outputs.cache-hit != 'true'
|
||||
run: |
|
||||
git clone --recursive --shallow-submodules --depth 1 -b openssl-${{ env.OPENSSL3_VERSION }} https://github.com/quictls/openssl openssl3
|
||||
git clone --recursive --shallow-submodules --depth 1 -b openssl-${{ env.OPENSSL3_VERSION }} https://github.com/openssl/openssl openssl3
|
||||
cd openssl3
|
||||
./config enable-ktls --prefix=$PWD/build --libdir=$PWD/build/lib
|
||||
./config enable-ktls --prefix=$PWD/build
|
||||
make -j"$(nproc 2> /dev/null || sysctl -n hw.ncpu)"
|
||||
make install_sw
|
||||
- name: Build BoringSSL
|
||||
@@ -190,7 +190,7 @@ jobs:
|
||||
./configure --prefix=$PWD/build --enable-lib-only \
|
||||
PKG_CONFIG_PATH="../openssl1/build/lib/pkgconfig:../wolfssl/build/lib/pkgconfig" \
|
||||
BORINGSSL_CFLAGS="-I$PWD/../boringssl/include/" \
|
||||
BORINGSSL_LIBS="-L$PWD/../boringssl/build/ssl -lssl -L$PWD/../boringssl/build/crypto -lcrypto" \
|
||||
BORINGSSL_LIBS="-L$PWD/../boringssl/build -lssl -lcrypto" \
|
||||
--disable-dependency-tracking \
|
||||
--with-boringssl \
|
||||
--with-wolfssl
|
||||
@@ -203,7 +203,7 @@ jobs:
|
||||
cd ngtcp2-openssl3
|
||||
autoreconf -i
|
||||
./configure --prefix=$PWD/build --enable-lib-only \
|
||||
PKG_CONFIG_PATH="../openssl3/build/lib/pkgconfig" \
|
||||
PKG_CONFIG_PATH="../openssl3/build/lib64/pkgconfig:../openssl3/build/lib/pkgconfig" \
|
||||
BORINGSSL_CFLAGS="-I$PWD/../aws-lc/include/" \
|
||||
BORINGSSL_LIBS="-L$PWD/../aws-lc/build/ssl -lssl -L$PWD/../aws-lc/build/crypto -lcrypto" \
|
||||
--disable-dependency-tracking \
|
||||
@@ -217,40 +217,36 @@ jobs:
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-24.04, macos-13, macos-14]
|
||||
os: [ubuntu-24.04, macos-14, macos-15]
|
||||
compiler: [gcc, clang]
|
||||
buildtool: [autotools, cmake]
|
||||
http3: [http3, no-http3]
|
||||
openssl: [openssl1, openssl3, boringssl, awslc, wolfssl]
|
||||
exclude:
|
||||
- os: macos-13
|
||||
openssl: openssl3
|
||||
- os: macos-14
|
||||
openssl: openssl3
|
||||
- http3: no-http3
|
||||
openssl: openssl3
|
||||
- os: macos-13
|
||||
compiler: gcc
|
||||
- os: macos-14
|
||||
compiler: gcc
|
||||
- # disable macos cmake because of include path issue
|
||||
os: macos-13
|
||||
buildtool: cmake
|
||||
- os: macos-15
|
||||
compiler: gcc
|
||||
- # disable macos cmake because of include path issue
|
||||
os: macos-14
|
||||
buildtool: cmake
|
||||
- os: macos-13
|
||||
openssl: boringssl
|
||||
- # disable macos cmake because of include path issue
|
||||
os: macos-15
|
||||
buildtool: cmake
|
||||
- os: macos-14
|
||||
openssl: boringssl
|
||||
- os: macos-15
|
||||
openssl: boringssl
|
||||
- openssl: boringssl
|
||||
buildtool: cmake
|
||||
- openssl: boringssl
|
||||
compiler: gcc
|
||||
- os: macos-13
|
||||
openssl: awslc
|
||||
- os: macos-14
|
||||
openssl: awslc
|
||||
- os: macos-15
|
||||
openssl: awslc
|
||||
- openssl: awslc
|
||||
buildtool: cmake
|
||||
- openssl: awslc
|
||||
@@ -266,7 +262,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
submodules: recursive
|
||||
- name: Linux setup
|
||||
@@ -275,7 +271,7 @@ jobs:
|
||||
sudo apt-get update
|
||||
sudo apt-get install \
|
||||
g++-14 \
|
||||
clang-18 \
|
||||
clang-19 \
|
||||
autoconf \
|
||||
automake \
|
||||
autotools-dev \
|
||||
@@ -314,8 +310,8 @@ jobs:
|
||||
- name: Setup clang (Linux)
|
||||
if: runner.os == 'Linux' && matrix.compiler == 'clang'
|
||||
run: |
|
||||
echo 'CC=clang-18' >> $GITHUB_ENV
|
||||
echo 'CXX=clang++-18' >> $GITHUB_ENV
|
||||
echo 'CC=clang-19' >> $GITHUB_ENV
|
||||
echo 'CXX=clang++-19' >> $GITHUB_ENV
|
||||
- name: Setup clang (MacOS)
|
||||
if: runner.os == 'macOS' && matrix.compiler == 'clang'
|
||||
run: |
|
||||
@@ -351,7 +347,7 @@ jobs:
|
||||
echo 'EXTRA_AUTOTOOLS_OPTS='"$EXTRA_AUTOTOOLS_OPTS" >> $GITHUB_ENV
|
||||
echo 'EXTRA_CMAKE_OPTS='"$EXTRA_CMAKE_OPTS" >> $GITHUB_ENV
|
||||
- name: Setup libev variables
|
||||
if: matrix.os == 'macos-14'
|
||||
if: runner.os == 'macOS'
|
||||
run: |
|
||||
LIBEV_CFLAGS="-I/opt/homebrew/Cellar/libev/4.33/include"
|
||||
LIBEV_LIBS="-L/opt/homebrew/Cellar/libev/4.33/lib -lev"
|
||||
@@ -365,7 +361,7 @@ jobs:
|
||||
path: openssl1/build
|
||||
key: ${{ matrix.os }}-openssl-${{ env.OPENSSL1_VERSION }}
|
||||
fail-on-cache-miss: true
|
||||
- name: Restore quictls/openssl v3.x cache
|
||||
- name: Restore openssl/openssl v3.x cache
|
||||
uses: actions/cache/restore@v4
|
||||
if: matrix.openssl == 'openssl3'
|
||||
with:
|
||||
@@ -377,8 +373,8 @@ jobs:
|
||||
if: matrix.openssl == 'boringssl'
|
||||
with:
|
||||
path: |
|
||||
boringssl/build/crypto/libcrypto.a
|
||||
boringssl/build/ssl/libssl.a
|
||||
boringssl/build/libcrypto.a
|
||||
boringssl/build/libssl.a
|
||||
boringssl/include
|
||||
key: ${{ matrix.os }}-boringssl-${{ env.BORINGSSL_VERSION }}
|
||||
fail-on-cache-miss: true
|
||||
@@ -398,7 +394,7 @@ jobs:
|
||||
cd boringssl
|
||||
|
||||
OPENSSL_CFLAGS="-I$PWD/include/"
|
||||
OPENSSL_LIBS="-L$PWD/build/ssl -lssl -L$PWD/build/crypto -lcrypto -pthread"
|
||||
OPENSSL_LIBS="-L$PWD/build -lssl -lcrypto -pthread"
|
||||
EXTRA_AUTOTOOLS_OPTS="$EXTRA_AUTOTOOLS_OPTS --without-neverbleed --without-jemalloc --disable-examples"
|
||||
|
||||
echo 'OPENSSL_CFLAGS='"$OPENSSL_CFLAGS" >> $GITHUB_ENV
|
||||
@@ -459,16 +455,16 @@ jobs:
|
||||
- name: Setup extra environment variables
|
||||
if: matrix.http3 == 'no-http3'
|
||||
run: |
|
||||
PKG_CONFIG_PATH="$PWD/openssl1/build/lib/pkgconfig:$PWD/openssl3/build/lib/pkgconfig:$PWD/wolfssl/build/lib/pkgconfig:$PKG_CONFIG_PATH"
|
||||
LDFLAGS="$LDFLAGS -Wl,-rpath,$PWD/openssl1/build/lib -Wl,-rpath,$PWD/openssl3/build/lib"
|
||||
PKG_CONFIG_PATH="$PWD/openssl1/build/lib/pkgconfig:$PWD/openssl3/build/lib64/pkgconfig:$PWD/openssl3/build/lib/pkgconfig:$PWD/wolfssl/build/lib/pkgconfig:$PKG_CONFIG_PATH"
|
||||
LDFLAGS="$LDFLAGS -Wl,-rpath,$PWD/openssl1/build/lib -Wl,-rpath,$PWD/openssl3/build/lib64 -Wl,-rpath,$PWD/openssl3/build/lib"
|
||||
|
||||
echo 'PKG_CONFIG_PATH='"$PKG_CONFIG_PATH" >> $GITHUB_ENV
|
||||
echo 'LDFLAGS='"$LDFLAGS" >> $GITHUB_ENV
|
||||
- name: Setup extra environment variables for HTTP/3
|
||||
if: matrix.http3 == 'http3'
|
||||
run: |
|
||||
PKG_CONFIG_PATH="$PWD/openssl1/build/lib/pkgconfig:$PWD/openssl3/build/lib/pkgconfig:$PWD/wolfssl/build/lib/pkgconfig:$PWD/nghttp3/build/lib/pkgconfig:$PWD/ngtcp2-openssl1/build/lib/pkgconfig:$PWD/ngtcp2-openssl3/build/lib/pkgconfig:$PWD/libbpf/build/lib64/pkgconfig:$PKG_CONFIG_PATH"
|
||||
LDFLAGS="$LDFLAGS -Wl,-rpath,$PWD/openssl1/build/lib -Wl,-rpath,$PWD/openssl3/build/lib -Wl,-rpath,$PWD/libbpf/build/lib64"
|
||||
PKG_CONFIG_PATH="$PWD/openssl1/build/lib/pkgconfig:$PWD/openssl3/build/lib64/pkgconfig:$PWD/openssl3/build/lib/pkgconfig:$PWD/wolfssl/build/lib/pkgconfig:$PWD/nghttp3/build/lib/pkgconfig:$PWD/ngtcp2-openssl1/build/lib/pkgconfig:$PWD/ngtcp2-openssl3/build/lib/pkgconfig:$PWD/libbpf/build/lib64/pkgconfig:$PKG_CONFIG_PATH"
|
||||
LDFLAGS="$LDFLAGS -Wl,-rpath,$PWD/openssl1/build/lib -Wl,-rpath,$PWD/openssl3/build/lib64 -Wl,-rpath,$PWD/openssl3/build/lib -Wl,-rpath,$PWD/libbpf/build/lib64"
|
||||
EXTRA_AUTOTOOLS_OPTS="$EXTRA_AUTOTOOLS_OPTS --enable-http3"
|
||||
EXTRA_CMAKE_OPTS="$EXTRA_CMAKE_OPTS -DENABLE_HTTP3=1"
|
||||
|
||||
@@ -528,15 +524,16 @@ jobs:
|
||||
cd $NGHTTP2_BUILD_DIR
|
||||
make -j"$(nproc 2> /dev/null || sysctl -n hw.ncpu)"
|
||||
make -j"$(nproc 2> /dev/null || sysctl -n hw.ncpu)" check
|
||||
- uses: actions/setup-go@v5
|
||||
- uses: actions/setup-go@v6
|
||||
if: matrix.buildtool != 'distcheck'
|
||||
with:
|
||||
go-version: "1.22"
|
||||
go-version: "1.24"
|
||||
- name: Integration test
|
||||
# Integration tests for nghttpx; autotools erases build
|
||||
# artifacts.
|
||||
if: matrix.buildtool != 'distcheck'
|
||||
run: |
|
||||
sudo sh -c 'echo "127.0.0.1 127.0.0.1.nip.io" >> /etc/hosts'
|
||||
cd $NGHTTP2_BUILD_DIR/integration-tests
|
||||
make it
|
||||
|
||||
@@ -552,7 +549,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
submodules: recursive
|
||||
- name: Prepare for i386
|
||||
@@ -600,7 +597,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
submodules: recursive
|
||||
- uses: microsoft/setup-msbuild@v2
|
||||
@@ -625,7 +622,7 @@ jobs:
|
||||
runs-on: ubuntu-24.04
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v5
|
||||
with:
|
||||
fetch-depth: 0
|
||||
submodules: recursive
|
||||
@@ -642,7 +639,7 @@ jobs:
|
||||
GPG_KEY: ${{ secrets.GPG_KEY }}
|
||||
GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }}
|
||||
- name: Make release
|
||||
uses: actions/github-script@v7
|
||||
uses: actions/github-script@v8
|
||||
with:
|
||||
script: |
|
||||
const fs = require('fs')
|
||||
|
||||
2
.github/workflows/docker.yaml
vendored
2
.github/workflows/docker.yaml
vendored
@@ -14,7 +14,7 @@ jobs:
|
||||
runs-on: ubuntu-24.04
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v5
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
- name: Build
|
||||
|
||||
2
.github/workflows/fuzz.yml
vendored
2
.github/workflows/fuzz.yml
vendored
@@ -24,7 +24,7 @@ jobs:
|
||||
fuzz-seconds: 600
|
||||
dry-run: false
|
||||
- name: Upload Crash
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v5
|
||||
if: failure()
|
||||
with:
|
||||
name: artifacts
|
||||
|
||||
2
.github/workflows/stale.yaml
vendored
2
.github/workflows/stale.yaml
vendored
@@ -13,7 +13,7 @@ jobs:
|
||||
runs-on: ubuntu-24.04
|
||||
|
||||
steps:
|
||||
- uses: actions/stale@v9
|
||||
- uses: actions/stale@v10
|
||||
with:
|
||||
stale-issue-message: 'This issue is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 7 days.'
|
||||
days-before-stale: 30
|
||||
|
||||
7
AUTHORS
7
AUTHORS
@@ -80,6 +80,7 @@ Jonas Kvinge
|
||||
Josh Braegger
|
||||
José F. Calcerrada
|
||||
Kamil Dudka
|
||||
Karthik Dasari
|
||||
Kazuho Oku
|
||||
Kenny (kang-yen) Peng
|
||||
Kenny Peng
|
||||
@@ -89,6 +90,7 @@ LazyHamster
|
||||
Leo Neat
|
||||
Lorenz Nickel
|
||||
Lucas Pardue
|
||||
Lukas Märdian
|
||||
MATSUMOTO Ryosuke
|
||||
Marc Bachmann
|
||||
Marcelo Trylesinski
|
||||
@@ -104,6 +106,7 @@ Nora Shoemaker
|
||||
Paweł Wegner
|
||||
Pedro Santos
|
||||
Peeyush Aggarwal
|
||||
Peng-Yu Chen
|
||||
Peter Wu
|
||||
Piotr Sikora
|
||||
PufferOverflow
|
||||
@@ -119,6 +122,7 @@ Ryan Carsten Schmidt
|
||||
Ryo Ota
|
||||
Scott Mitchell
|
||||
Sebastiaan Deckers
|
||||
Sergei Trofimovich
|
||||
Sergey Fedorov
|
||||
Shelley Vohr
|
||||
Simon Frankenberger
|
||||
@@ -146,15 +150,18 @@ Ville Vesilehto
|
||||
Wenfeng Liu
|
||||
William A Rowe Jr
|
||||
Xiaoguang Sun
|
||||
Zachary Turner
|
||||
Zhuoyun Wei
|
||||
acesso
|
||||
ayanamist
|
||||
bmarques1995
|
||||
bxshi
|
||||
clemahieu
|
||||
dalf
|
||||
dawg
|
||||
es
|
||||
fangdingjun
|
||||
feicong
|
||||
hrxi
|
||||
jwchoi
|
||||
kumagi
|
||||
|
||||
@@ -24,13 +24,13 @@
|
||||
|
||||
cmake_minimum_required(VERSION 3.14)
|
||||
# XXX using 1.8.90 instead of 1.9.0-DEV
|
||||
project(nghttp2 VERSION 1.65.0 LANGUAGES C)
|
||||
project(nghttp2 VERSION 1.68.90 LANGUAGES C)
|
||||
|
||||
# See versioning rule:
|
||||
# https://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html
|
||||
set(LT_CURRENT 42)
|
||||
set(LT_REVISION 4)
|
||||
set(LT_AGE 28)
|
||||
set(LT_CURRENT 43)
|
||||
set(LT_REVISION 2)
|
||||
set(LT_AGE 29)
|
||||
|
||||
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH})
|
||||
include(Version)
|
||||
@@ -71,20 +71,8 @@ if(WITH_WOLFSSL)
|
||||
else()
|
||||
find_package(OpenSSL 1.1.1)
|
||||
endif()
|
||||
find_package(Libngtcp2 1.0.0)
|
||||
if(OPENSSL_FOUND)
|
||||
find_package(Libngtcp2_crypto_quictls 1.0.0)
|
||||
if(LIBNGTCP2_CRYPTO_QUICTLS_FOUND)
|
||||
set(HAVE_LIBNGTCP2_CRYPTO_QUICTLS 1)
|
||||
endif()
|
||||
endif()
|
||||
if(WOLFSSL_FOUND)
|
||||
find_package(Libngtcp2_crypto_wolfssl 1.0.0)
|
||||
if(LIBNGTCP2_CRYPTO_WOLFSSL_FOUND)
|
||||
set(HAVE_LIBNGTCP2_CRYPTO_WOLFSSL 1)
|
||||
endif()
|
||||
endif()
|
||||
find_package(Libnghttp3 1.1.0)
|
||||
find_package(Libngtcp2 1.15.0)
|
||||
find_package(Libnghttp3 1.11.0)
|
||||
if(WITH_LIBBPF)
|
||||
find_package(Libbpf 0.7.0)
|
||||
if(NOT LIBBPF_FOUND)
|
||||
@@ -155,10 +143,10 @@ if(NOT ENABLE_LIB_ONLY)
|
||||
#include <vector>
|
||||
#include <future>
|
||||
int main() { std::vector<std::future<int>> v; }" HAVE_STD_FUTURE)
|
||||
# Check that std::map::emplace is available for g++-4.7.
|
||||
# Check that std::chrono::time_zone is available.
|
||||
check_cxx_source_compiles("
|
||||
#include <map>
|
||||
int main() { std::map<int, int>().emplace(1, 2); }" HAVE_STD_MAP_EMPLACE)
|
||||
#include <chrono>
|
||||
int main() { auto tz = std::chrono::current_zone(); (void)tz; }" HAVE_STD_CHRONO_TIME_ZONE)
|
||||
cmake_pop_check_state()
|
||||
endif()
|
||||
|
||||
@@ -196,10 +184,14 @@ if(NOT ENABLE_LIB_ONLY AND OPENSSL_FOUND)
|
||||
if(WIN32)
|
||||
set(CMAKE_REQUIRED_LIBRARIES "${CMAKE_REQUIRED_LIBRARIES}" "ws2_32" "bcrypt")
|
||||
endif()
|
||||
check_symbol_exists("LIBRESSL_VERSION_NUMBER" "openssl/opensslv.h" LIBRESSL_FOUND)
|
||||
if(ENABLE_HTTP3)
|
||||
check_symbol_exists(SSL_provide_quic_data "openssl/ssl.h" HAVE_SSL_PROVIDE_QUIC_DATA)
|
||||
if(NOT HAVE_SSL_PROVIDE_QUIC_DATA)
|
||||
message(WARNING "OpenSSL in ${OPENSSL_LIBRARIES} does not have SSL_provide_quic_data. HTTP/3 support cannot be enabled")
|
||||
check_symbol_exists(SSL_set_quic_tls_cbs "openssl/ssl.h" HAVE_SSL_SET_QUIC_TLS_CBS)
|
||||
if(NOT HAVE_SSL_SET_QUIC_TLS_CBS)
|
||||
message(WARNING "OpenSSL in ${OPENSSL_LIBRARIES} has neither SSL_provide_quic_data nor SSL_set_quic_tls_cbs. HTTP/3 support cannot be enabled")
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
cmake_pop_check_state()
|
||||
@@ -279,12 +271,41 @@ if(ENABLE_APP AND NOT (ZLIB_FOUND AND (OPENSSL_FOUND OR WOLFSSL_FOUND) AND LIBEV
|
||||
message(FATAL_ERROR "Applications were requested (ENABLE_APP=1) but dependencies are not met.")
|
||||
endif()
|
||||
|
||||
# HTTP/3 requires libngtcp2 + (quictls/openssl +
|
||||
# libngtcp2_crypto_quictls or wolfSSL + libngtcp2_crypto_wolfssl) and
|
||||
# libnghttp3.
|
||||
if(ENABLE_HTTP3)
|
||||
if(HAVE_SSL_PROVIDE_QUIC_DATA AND NOT LIBRESSL_FOUND)
|
||||
find_package(Libngtcp2_crypto_quictls 1.15.0)
|
||||
if(LIBNGTCP2_CRYPTO_QUICTLS_FOUND)
|
||||
set(HAVE_LIBNGTCP2_CRYPTO_QUICTLS 1)
|
||||
endif()
|
||||
elseif(HAVE_SSL_PROVIDE_QUIC_DATA AND LIBRESSL_FOUND)
|
||||
find_package(Libngtcp2_crypto_libressl 1.15.0)
|
||||
if(LIBNGTCP2_CRYPTO_LIBRESSL_FOUND)
|
||||
set(HAVE_LIBNGTCP2_CRYPTO_LIBRESSL 1)
|
||||
endif()
|
||||
elseif(HAVE_WOLFSSL_SSL_PROVIDE_QUIC_DATA)
|
||||
find_package(Libngtcp2_crypto_wolfssl 1.15.0)
|
||||
if(LIBNGTCP2_CRYPTO_WOLFSSL_FOUND)
|
||||
set(HAVE_LIBNGTCP2_CRYPTO_WOLFSSL 1)
|
||||
endif()
|
||||
elseif(HAVE_SSL_SET_QUIC_TLS_CBS)
|
||||
find_package(Libngtcp2_crypto_ossl 1.15.0)
|
||||
if(LIBNGTCP2_CRYPTO_OSSL_FOUND)
|
||||
set(HAVE_LIBNGTCP2_CRYPTO_OSSL 1)
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# HTTP/3 requires libngtcp2 + nghttp3 + one of:
|
||||
#
|
||||
# - quictls/openssl + libngtcp2_crypto_quictls
|
||||
# - libressl + libngtcp2_crypto_libressl
|
||||
# - wolfSSL + libngtcp2_crypto_wolfssl
|
||||
# - openssl/openssl + libngtcp2_crypto_ossl
|
||||
if(ENABLE_HTTP3 AND NOT (LIBNGTCP2_FOUND AND LIBNGHTTP3_FOUND AND
|
||||
((HAVE_SSL_PROVIDE_QUIC_DATA AND LIBNGTCP2_CRYPTO_QUICTLS_FOUND) OR
|
||||
(HAVE_WOLFSSL_SSL_PROVIDE_QUIC_DATA AND LIBNGTCP2_CRYPTO_WOLFSSL_FOUND))))
|
||||
((HAVE_SSL_PROVIDE_QUIC_DATA AND NOT LIBRESSL_FOUND AND LIBNGTCP2_CRYPTO_QUICTLS_FOUND) OR
|
||||
(HAVE_SSL_PROVIDE_QUIC_DATA AND LIBRESSL_FOUND AND LIBNGTCP2_CRYPTO_LIBRESSL_FOUND) OR
|
||||
(HAVE_WOLFSSL_SSL_PROVIDE_QUIC_DATA AND LIBNGTCP2_CRYPTO_WOLFSSL_FOUND) OR
|
||||
(HAVE_SSL_SET_QUIC_TLS_CBS AND LIBNGTCP2_CRYPTO_OSSL_FOUND))))
|
||||
message(FATAL_ERROR "HTTP/3 was requested (ENABLE_HTTP3=1) but dependencies are not met.")
|
||||
endif()
|
||||
|
||||
@@ -361,7 +382,7 @@ check_function_exists(clock_gettime HAVE_CLOCK_GETTIME)
|
||||
check_function_exists(mkostemp HAVE_MKOSTEMP)
|
||||
check_function_exists(pipe2 HAVE_PIPE2)
|
||||
|
||||
check_symbol_exists(GetTickCount64 sysinfoapi.h HAVE_GETTICKCOUNT64)
|
||||
check_symbol_exists(GetTickCount64 "windows.h;sysinfoapi.h" HAVE_GETTICKCOUNT64)
|
||||
|
||||
include(CheckSymbolExists)
|
||||
# XXX does this correctly detect initgroups (un)availability on cygwin?
|
||||
@@ -478,7 +499,6 @@ if(ENABLE_DOC)
|
||||
add_subdirectory(doc)
|
||||
endif()
|
||||
add_subdirectory(contrib)
|
||||
add_subdirectory(script)
|
||||
add_subdirectory(bpf)
|
||||
|
||||
|
||||
@@ -512,6 +532,7 @@ message(STATUS "summary of build options:
|
||||
Libc-ares: ${HAVE_LIBCARES} (LIBS='${LIBCARES_LIBRARIES}')
|
||||
Libngtcp2: ${HAVE_LIBNGTCP2} (LIBS='${LIBNGTCP2_LIBRARIES}')
|
||||
Libngtcp2_crypto_quictls: ${HAVE_LIBNGTCP2_CRYPTO_QUICTLS} (LIBS='${LIBNGTCP2_CRYPTO_QUICTLS_LIBRARIES}')
|
||||
Libngtcp2_crypto_libressl: ${HAVE_LIBNGTCP2_CRYPTO_LIBRESSL} (LIBS='${LIBNGTCP2_CRYPTO_LIBRESSL_LIBRARIES}')
|
||||
Libngtcp2_crypto_wolfssl: ${HAVE_LIBNGTCP2_CRYPTO_WOLFSSL} (LIBS='${LIBNGTCP2_CRYPTO_WOLFSSL_LIBRARIES}')
|
||||
Libnghttp3: ${HAVE_LIBNGHTTP3} (LIBS='${LIBNGHTTP3_LIBRARIES}')
|
||||
Libbpf: ${HAVE_LIBBPF} (LIBS='${LIBBPF_LIBRARIES}')
|
||||
|
||||
@@ -12,21 +12,21 @@
|
||||
|
||||
|
||||
# Only use standalone-toolchain for reduce size
|
||||
FROM ubuntu:22.04
|
||||
MAINTAINER Tatsuhiro Tsujikawa
|
||||
FROM ubuntu:24.04
|
||||
LABEL org.opencontainers.image.authors="Tatsuhiro Tsujikawa"
|
||||
|
||||
ENV NDK_VERSION r26d
|
||||
ENV NDK /root/android-ndk-$NDK_VERSION
|
||||
ENV TOOLCHAIN $NDK/toolchains/llvm/prebuilt/linux-x86_64
|
||||
ENV TARGET aarch64-linux-android
|
||||
ENV API 33
|
||||
ENV AR $TOOLCHAIN/bin/llvm-ar
|
||||
ENV CC $TOOLCHAIN/bin/$TARGET$API-clang
|
||||
ENV CXX $TOOLCHAIN/bin/$TARGET$API-clang++
|
||||
ENV LD $TOOLCHAIN/bin/ld
|
||||
ENV RANDLIB $TOOLCHAIN/bin/llvm-ranlib
|
||||
ENV STRIP $TOOLCHAIN/bin/llvm-strip
|
||||
ENV PREFIX /root/usr/local
|
||||
ARG NDK_VERSION=r27c
|
||||
ARG NDK=/root/android-ndk-$NDK_VERSION
|
||||
ARG TOOLCHAIN=$NDK/toolchains/llvm/prebuilt/linux-x86_64
|
||||
ARG TARGET=aarch64-linux-android
|
||||
ARG API=33
|
||||
ARG AR=$TOOLCHAIN/bin/llvm-ar
|
||||
ARG CC=$TOOLCHAIN/bin/$TARGET$API-clang
|
||||
ARG CXX=$TOOLCHAIN/bin/$TARGET$API-clang++
|
||||
ARG LD=$TOOLCHAIN/bin/ld
|
||||
ARG RANDLIB=$TOOLCHAIN/bin/llvm-ranlib
|
||||
ARG STRIP=$TOOLCHAIN/bin/llvm-strip
|
||||
ARG PREFIX=/root/usr/local
|
||||
|
||||
WORKDIR /root
|
||||
RUN apt-get update && \
|
||||
@@ -42,11 +42,11 @@ RUN curl -L -O https://dl.google.com/android/repository/android-ndk-$NDK_VERSION
|
||||
rm android-ndk-$NDK_VERSION-linux.zip
|
||||
|
||||
# Setup version of libraries
|
||||
ENV OPENSSL_VERSION 1.1.1w
|
||||
ENV LIBEV_VERSION 4.33
|
||||
ENV ZLIB_VERSION 1.3.1
|
||||
ENV CARES_VERSION 1.18.1
|
||||
ENV NGHTTP2_VERSION master
|
||||
ARG OPENSSL_VERSION=1.1.1w
|
||||
ARG LIBEV_VERSION=4.33
|
||||
ARG ZLIB_VERSION=1.3.1
|
||||
ARG CARES_VERSION=1.18.1
|
||||
ARG NGHTTP2_VERSION=master
|
||||
|
||||
WORKDIR /root/build
|
||||
RUN curl -L -O https://www.openssl.org/source/openssl-$OPENSSL_VERSION.tar.gz && \
|
||||
@@ -105,7 +105,7 @@ RUN ./configure \
|
||||
make install
|
||||
|
||||
WORKDIR /root/build
|
||||
RUN git clone https://github.com/nghttp2/nghttp2 -b $NGHTTP2_VERSION --depth 1
|
||||
RUN git clone --recursive --shallow-submodules https://github.com/nghttp2/nghttp2 -b $NGHTTP2_VERSION --depth 1
|
||||
WORKDIR /root/build/nghttp2
|
||||
RUN autoreconf -i && \
|
||||
./configure \
|
||||
@@ -119,6 +119,6 @@ RUN autoreconf -i && \
|
||||
--disable-threads \
|
||||
CPPFLAGS="-fPIE -I$PREFIX/include" \
|
||||
PKG_CONFIG_LIBDIR="$PREFIX/lib/pkgconfig" \
|
||||
LDFLAGS="-fPIE -pie -L$PREFIX/lib" && \
|
||||
LDFLAGS="-static-libstdc++ -static-libgcc -fPIE -pie -L$PREFIX/lib" && \
|
||||
make && \
|
||||
$STRIP src/nghttpx src/nghttpd src/nghttp
|
||||
|
||||
@@ -20,8 +20,8 @@
|
||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
SUBDIRS = lib third-party src bpf examples tests integration-tests \
|
||||
doc contrib script
|
||||
SUBDIRS = lib tests third-party src bpf examples integration-tests \
|
||||
doc contrib
|
||||
|
||||
ACLOCAL_AMFLAGS = -I m4
|
||||
|
||||
@@ -47,6 +47,7 @@ EXTRA_DIST = nghttpx.conf.sample proxy.pac.sample android-config android-env \
|
||||
cmake/FindLibbrotlienc.cmake \
|
||||
cmake/FindLibbrotlidec.cmake \
|
||||
cmake/FindLibngtcp2_crypto_wolfssl.cmake \
|
||||
cmake/FindLibngtcp2_crypto_ossl.cmake \
|
||||
cmake/FindWolfSSL.cmake \
|
||||
cmake/PickyWarningsC.cmake \
|
||||
cmake/PickyWarningsCXX.cmake
|
||||
|
||||
33
README.rst
33
README.rst
@@ -31,9 +31,8 @@ implementation.
|
||||
|
||||
* https://nghttp2.org/ (TLS + ALPN and HTTP/3)
|
||||
|
||||
This endpoint supports ``h2``, ``h2-16``, ``h2-14``, and
|
||||
``http/1.1`` via ALPN and requires TLSv1.2 for HTTP/2
|
||||
connection.
|
||||
This endpoint supports ``h2`` and ``http/1.1`` via ALPN and requires
|
||||
TLSv1.2 for HTTP/2 connection.
|
||||
|
||||
It also supports HTTP/3.
|
||||
|
||||
@@ -123,13 +122,13 @@ exploited. The neverbleed is disabled by default. To enable it, use
|
||||
To enable the experimental HTTP/3 support for h2load and nghttpx, the
|
||||
following libraries are required:
|
||||
|
||||
* `OpenSSL with QUIC support
|
||||
* `quictls
|
||||
<https://github.com/quictls/openssl/tree/OpenSSL_1_1_1w+quic>`_; or
|
||||
wolfSSL; or LibreSSL (does not support 0RTT); or aws-lc; or
|
||||
`BoringSSL <https://boringssl.googlesource.com/boringssl/>`_ (commit
|
||||
294ab9730c570213b496cfc2fc14b3c0bfcd4bcc)
|
||||
* `ngtcp2 <https://github.com/ngtcp2/ngtcp2>`_ >= 1.4.0
|
||||
* `nghttp3 <https://github.com/ngtcp2/nghttp3>`_ >= 1.1.0
|
||||
db1a8456167249f95b854a1cd24c6b553d0f1567); or OpenSSL >= 3.5.0
|
||||
* `ngtcp2 <https://github.com/ngtcp2/ngtcp2>`_ >= 1.16.0
|
||||
* `nghttp3 <https://github.com/ngtcp2/nghttp3>`_ >= 1.12.0
|
||||
|
||||
Use ``--enable-http3`` configure option to enable HTTP/3 feature for
|
||||
h2load and nghttpx.
|
||||
@@ -151,7 +150,7 @@ executable.
|
||||
Compiling libnghttp2 C source code requires a C99 compiler. gcc 4.8
|
||||
is known to be adequate. In order to compile the C++ source code,
|
||||
C++20 compliant compiler is required. At least g++ >= 12 and
|
||||
clang++ >= 15 are known to work.
|
||||
clang++ >= 18 are known to work.
|
||||
|
||||
.. note::
|
||||
|
||||
@@ -341,7 +340,7 @@ Build aws-lc:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
$ git clone --depth 1 -b v1.46.1 https://github.com/aws/aws-lc
|
||||
$ git clone --depth 1 -b v1.62.0 https://github.com/aws/aws-lc
|
||||
$ cd aws-lc
|
||||
$ cmake -B build -DDISABLE_GO=ON --install-prefix=$PWD/opt
|
||||
$ make -j$(nproc) -C build
|
||||
@@ -352,7 +351,7 @@ Build nghttp3:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
$ git clone --depth 1 -b v1.8.0 https://github.com/ngtcp2/nghttp3
|
||||
$ git clone --depth 1 -b v1.12.0 https://github.com/ngtcp2/nghttp3
|
||||
$ cd nghttp3
|
||||
$ git submodule update --init --depth 1
|
||||
$ autoreconf -i
|
||||
@@ -365,7 +364,7 @@ Build ngtcp2:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
$ git clone --depth 1 -b v1.11.0 https://github.com/ngtcp2/ngtcp2
|
||||
$ git clone --depth 1 -b v1.17.0 https://github.com/ngtcp2/ngtcp2
|
||||
$ cd ngtcp2
|
||||
$ git submodule update --init --depth 1
|
||||
$ autoreconf -i
|
||||
@@ -381,7 +380,7 @@ from source:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
$ git clone --depth 1 -b v1.5.0 https://github.com/libbpf/libbpf
|
||||
$ git clone --depth 1 -b v1.6.2 https://github.com/libbpf/libbpf
|
||||
$ cd libbpf
|
||||
$ PREFIX=$PWD/build make -C src install
|
||||
$ cd ..
|
||||
@@ -395,7 +394,7 @@ Build nghttp2:
|
||||
$ git submodule update --init
|
||||
$ autoreconf -i
|
||||
$ ./configure --with-mruby --enable-http3 --with-libbpf \
|
||||
CC=clang-15 CXX=clang++-15 \
|
||||
CC=clang-19 CXX=clang++-19 \
|
||||
PKG_CONFIG_PATH="$PWD/../aws-lc/opt/lib/pkgconfig:$PWD/../nghttp3/build/lib/pkgconfig:$PWD/../ngtcp2/build/lib/pkgconfig:$PWD/../libbpf/build/lib64/pkgconfig" \
|
||||
LDFLAGS="$LDFLAGS -Wl,-rpath,$PWD/../aws-lc/opt/lib -Wl,-rpath,$PWD/../libbpf/build/lib64"
|
||||
$ make -j$(nproc)
|
||||
@@ -847,10 +846,10 @@ to know how to migrate from earlier releases.
|
||||
|
||||
``nghttpx`` implements `important performance-oriented features
|
||||
<https://istlsfastyet.com/#server-performance>`_ in TLS, such as
|
||||
session IDs, session tickets (with automatic key rotation), OCSP
|
||||
stapling, dynamic record sizing, ALPN, forward secrecy and HTTP/2.
|
||||
``nghttpx`` also offers the functionality to share session cache and
|
||||
ticket keys among multiple ``nghttpx`` instances via memcached.
|
||||
session IDs, session tickets (with automatic key rotation), dynamic
|
||||
record sizing, ALPN, forward secrecy and HTTP/2. ``nghttpx`` also
|
||||
offers the functionality to share ticket keys among multiple
|
||||
``nghttpx`` instances via memcached.
|
||||
|
||||
``nghttpx`` has 2 operation modes:
|
||||
|
||||
|
||||
43
cmake/FindLibngtcp2_crypto_libressl.cmake
Normal file
43
cmake/FindLibngtcp2_crypto_libressl.cmake
Normal file
@@ -0,0 +1,43 @@
|
||||
# - Try to find libngtcp2_crypto_libressl
|
||||
# Once done this will define
|
||||
# LIBNGTCP2_CRYPTO_LIBRESSL_FOUND - System has libngtcp2_crypto_libressl
|
||||
# LIBNGTCP2_CRYPTO_LIBRESSL_INCLUDE_DIRS - The libngtcp2_crypto_libressl include directories
|
||||
# LIBNGTCP2_CRYPTO_LIBRESSL_LIBRARIES - The libraries needed to use libngtcp2_crypto_libressl
|
||||
|
||||
find_package(PkgConfig QUIET)
|
||||
pkg_check_modules(PC_LIBNGTCP2_CRYPTO_LIBRESSL QUIET libngtcp2_crypto_libressl)
|
||||
|
||||
find_path(LIBNGTCP2_CRYPTO_LIBRESSL_INCLUDE_DIR
|
||||
NAMES ngtcp2/ngtcp2_crypto_quictls.h
|
||||
HINTS ${PC_LIBNGTCP2_CRYPTO_LIBRESSL_INCLUDE_DIRS}
|
||||
)
|
||||
find_library(LIBNGTCP2_CRYPTO_LIBRESSL_LIBRARY
|
||||
NAMES ngtcp2_crypto_libressl
|
||||
HINTS ${PC_LIBNGTCP2_CRYPTO_LIBRESSL_LIBRARY_DIRS}
|
||||
)
|
||||
|
||||
if(LIBNGTCP2_CRYPTO_LIBRESSL_INCLUDE_DIR)
|
||||
set(_version_regex "^#define[ \t]+NGTCP2_VERSION[ \t]+\"([^\"]+)\".*")
|
||||
file(STRINGS "${LIBNGTCP2_CRYPTO_LIBRESSL_INCLUDE_DIR}/ngtcp2/version.h"
|
||||
LIBNGTCP2_CRYPTO_LIBRESSL_VERSION REGEX "${_version_regex}")
|
||||
string(REGEX REPLACE "${_version_regex}" "\\1"
|
||||
LIBNGTCP2_CRYPTO_LIBRESSL_VERSION "${LIBNGTCP2_CRYPTO_LIBRESSL_VERSION}")
|
||||
unset(_version_regex)
|
||||
endif()
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
# handle the QUIETLY and REQUIRED arguments and set
|
||||
# LIBNGTCP2_CRYPTO_LIBRESSL_FOUND to TRUE if all listed variables are
|
||||
# TRUE and the requested version matches.
|
||||
find_package_handle_standard_args(Libngtcp2_crypto_libressl REQUIRED_VARS
|
||||
LIBNGTCP2_CRYPTO_LIBRESSL_LIBRARY
|
||||
LIBNGTCP2_CRYPTO_LIBRESSL_INCLUDE_DIR
|
||||
VERSION_VAR LIBNGTCP2_CRYPTO_LIBRESSL_VERSION)
|
||||
|
||||
if(LIBNGTCP2_CRYPTO_LIBRESSL_FOUND)
|
||||
set(LIBNGTCP2_CRYPTO_LIBRESSL_LIBRARIES ${LIBNGTCP2_CRYPTO_LIBRESSL_LIBRARY})
|
||||
set(LIBNGTCP2_CRYPTO_LIBRESSL_INCLUDE_DIRS ${LIBNGTCP2_CRYPTO_LIBRESSL_INCLUDE_DIR})
|
||||
endif()
|
||||
|
||||
mark_as_advanced(LIBNGTCP2_CRYPTO_LIBRESSL_INCLUDE_DIR
|
||||
LIBNGTCP2_CRYPTO_LIBRESSL_LIBRARY)
|
||||
43
cmake/FindLibngtcp2_crypto_ossl.cmake
Normal file
43
cmake/FindLibngtcp2_crypto_ossl.cmake
Normal file
@@ -0,0 +1,43 @@
|
||||
# - Try to find libngtcp2_crypto_ossl
|
||||
# Once done this will define
|
||||
# LIBNGTCP2_CRYPTO_OSSL_FOUND - System has libngtcp2_crypto_ossl
|
||||
# LIBNGTCP2_CRYPTO_OSSL_INCLUDE_DIRS - The libngtcp2_crypto_ossl include directories
|
||||
# LIBNGTCP2_CRYPTO_OSSL_LIBRARIES - The libraries needed to use libngtcp2_crypto_ossl
|
||||
|
||||
find_package(PkgConfig QUIET)
|
||||
pkg_check_modules(PC_LIBNGTCP2_CRYPTO_OSSL QUIET libngtcp2_crypto_ossl)
|
||||
|
||||
find_path(LIBNGTCP2_CRYPTO_OSSL_INCLUDE_DIR
|
||||
NAMES ngtcp2/ngtcp2_crypto_ossl.h
|
||||
HINTS ${PC_LIBNGTCP2_CRYPTO_OSSL_INCLUDE_DIRS}
|
||||
)
|
||||
find_library(LIBNGTCP2_CRYPTO_OSSL_LIBRARY
|
||||
NAMES ngtcp2_crypto_ossl
|
||||
HINTS ${PC_LIBNGTCP2_CRYPTO_OSSL_LIBRARY_DIRS}
|
||||
)
|
||||
|
||||
if(LIBNGTCP2_CRYPTO_OSSL_INCLUDE_DIR)
|
||||
set(_version_regex "^#define[ \t]+NGTCP2_VERSION[ \t]+\"([^\"]+)\".*")
|
||||
file(STRINGS "${LIBNGTCP2_CRYPTO_OSSL_INCLUDE_DIR}/ngtcp2/version.h"
|
||||
LIBNGTCP2_CRYPTO_OSSL_VERSION REGEX "${_version_regex}")
|
||||
string(REGEX REPLACE "${_version_regex}" "\\1"
|
||||
LIBNGTCP2_CRYPTO_OSSL_VERSION "${LIBNGTCP2_CRYPTO_OSSL_VERSION}")
|
||||
unset(_version_regex)
|
||||
endif()
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
# handle the QUIETLY and REQUIRED arguments and set
|
||||
# LIBNGTCP2_CRYPTO_OSSL_FOUND to TRUE if all listed variables are
|
||||
# TRUE and the requested version matches.
|
||||
find_package_handle_standard_args(Libngtcp2_crypto_ossl REQUIRED_VARS
|
||||
LIBNGTCP2_CRYPTO_OSSL_LIBRARY
|
||||
LIBNGTCP2_CRYPTO_OSSL_INCLUDE_DIR
|
||||
VERSION_VAR LIBNGTCP2_CRYPTO_OSSL_VERSION)
|
||||
|
||||
if(LIBNGTCP2_CRYPTO_OSSL_FOUND)
|
||||
set(LIBNGTCP2_CRYPTO_OSSL_LIBRARIES ${LIBNGTCP2_CRYPTO_OSSL_LIBRARY})
|
||||
set(LIBNGTCP2_CRYPTO_OSSL_INCLUDE_DIRS ${LIBNGTCP2_CRYPTO_OSSL_INCLUDE_DIR})
|
||||
endif()
|
||||
|
||||
mark_as_advanced(LIBNGTCP2_CRYPTO_OSSL_INCLUDE_DIR
|
||||
LIBNGTCP2_CRYPTO_OSSL_LIBRARY)
|
||||
@@ -4,8 +4,8 @@
|
||||
/* Define to `int' if <sys/types.h> does not define. */
|
||||
#cmakedefine ssize_t @ssize_t@
|
||||
|
||||
/* Define to 1 if you have the `std::map::emplace`. */
|
||||
#cmakedefine HAVE_STD_MAP_EMPLACE 1
|
||||
/* Define to 1 if you have the `std::chrono::time_zone`. */
|
||||
#cmakedefine HAVE_STD_CHRONO_TIME_ZONE 1
|
||||
|
||||
/* Define to 1 if you have `libjansson` library. */
|
||||
#cmakedefine HAVE_JANSSON 1
|
||||
@@ -100,6 +100,9 @@
|
||||
/* Define to 1 if you have `libngtcp2_crypto_quictls` library. */
|
||||
#cmakedefine HAVE_LIBNGTCP2_CRYPTO_QUICTLS
|
||||
|
||||
/* Define to 1 if you have `libngtcp2_crypto_libressl` library. */
|
||||
#cmakedefine HAVE_LIBNGTCP2_CRYPTO_LIBRESSL
|
||||
|
||||
/* Define to 1 if you have `libngtcp2_crypto_wolfssl` library. */
|
||||
#cmakedefine HAVE_LIBNGTCP2_CRYPTO_WOLFSSL 1
|
||||
|
||||
|
||||
124
configure.ac
124
configure.ac
@@ -25,7 +25,7 @@ dnl Do not change user variables!
|
||||
dnl https://www.gnu.org/software/automake/manual/html_node/Flag-Variables-Ordering.html
|
||||
|
||||
AC_PREREQ(2.61)
|
||||
AC_INIT([nghttp2], [1.65.0], [t-tujikawa@users.sourceforge.net])
|
||||
AC_INIT([nghttp2], [1.69.0-DEV], [t-tujikawa@users.sourceforge.net])
|
||||
AC_CONFIG_AUX_DIR([.])
|
||||
AC_CONFIG_MACRO_DIR([m4])
|
||||
AC_CONFIG_HEADERS([config.h])
|
||||
@@ -44,9 +44,9 @@ m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
|
||||
|
||||
dnl See versioning rule:
|
||||
dnl https://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html
|
||||
AC_SUBST(LT_CURRENT, 42)
|
||||
AC_SUBST(LT_REVISION, 4)
|
||||
AC_SUBST(LT_AGE, 28)
|
||||
AC_SUBST(LT_CURRENT, 43)
|
||||
AC_SUBST(LT_REVISION, 2)
|
||||
AC_SUBST(LT_AGE, 29)
|
||||
|
||||
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"`
|
||||
@@ -272,22 +272,6 @@ std::vector<std::future<int>> v;
|
||||
[have_std_future=no
|
||||
AC_MSG_RESULT([no])])
|
||||
|
||||
# Check that std::map::emplace is available for g++-4.7.
|
||||
AC_MSG_CHECKING([whether std::map::emplace is available])
|
||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM(
|
||||
[[
|
||||
#include <map>
|
||||
]],
|
||||
[[
|
||||
std::map<int, int>().emplace(1, 2);
|
||||
]])],
|
||||
[AC_DEFINE([HAVE_STD_MAP_EMPLACE], [1],
|
||||
[Define to 1 if you have the `std::map::emplace`.])
|
||||
have_std_map_emplace=yes
|
||||
AC_MSG_RESULT([yes])],
|
||||
[have_std_map_emplace=no
|
||||
AC_MSG_RESULT([no])])
|
||||
|
||||
# Check that std::atomic<std::shared_ptr<T>> is supported.
|
||||
AC_MSG_CHECKING([whether std::atomic<std::shared_ptr<T>> is supported])
|
||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM(
|
||||
@@ -307,19 +291,21 @@ a.store(p);
|
||||
[have_atomic_std_shared_ptr=no
|
||||
AC_MSG_RESULT([no])])
|
||||
|
||||
# Check that thread_local storage specifier is available
|
||||
AC_MSG_CHECKING([whether thread_local storage class specifier is available.])
|
||||
# Check that std::chrono::time_zone is available.
|
||||
AC_MSG_CHECKING([whether std::chrono::time_zone is available])
|
||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM(
|
||||
,
|
||||
[[
|
||||
thread_local int a = 0;
|
||||
(void)a;
|
||||
#include <chrono>
|
||||
]],
|
||||
[[
|
||||
auto tz = std::chrono::current_zone();
|
||||
(void)tz;
|
||||
]])],
|
||||
[AC_DEFINE([HAVE_THREAD_LOCAL], [1],
|
||||
[Define to 1 if you have thread_local storage specifier.])
|
||||
have_thread_local=yes
|
||||
[AC_DEFINE([HAVE_STD_CHRONO_TIME_ZONE], [1],
|
||||
[Define to 1 if you have the `std::chrono::time_zone`.])
|
||||
have_std_chrono_time_zone=yes
|
||||
AC_MSG_RESULT([yes])],
|
||||
[have_Thread_local=no
|
||||
[have_std_chrono_time_zone=no
|
||||
AC_MSG_RESULT([no])])
|
||||
|
||||
CXXFLAGS=$save_CXXFLAGS
|
||||
@@ -450,6 +436,22 @@ if test "x${request_openssl}" != "xno" &&
|
||||
[AC_MSG_RESULT([yes]); have_ssl_provide_quic_data=yes],
|
||||
[AC_MSG_RESULT([no]); have_ssl_provide_quic_data=no])
|
||||
|
||||
# Check whether this is libressl or not
|
||||
AC_CHECK_DECLS([LIBRESSL_VERSION_NUMBER],
|
||||
[have_libressl=yes], [have_libressl=no],
|
||||
[[
|
||||
#include <openssl/opensslv.h>
|
||||
]])
|
||||
|
||||
AC_MSG_CHECKING([for SSL_set_quic_tls_cbs])
|
||||
AC_LINK_IFELSE([AC_LANG_PROGRAM([[
|
||||
#include <openssl/ssl.h>
|
||||
]], [[
|
||||
SSL_set_quic_tls_cbs(NULL, NULL, NULL);
|
||||
]])],
|
||||
[AC_MSG_RESULT([yes]); have_ossl_quic=yes],
|
||||
[AC_MSG_RESULT([no]); have_ossl_quic=no])
|
||||
|
||||
# boringssl has SSL_set_quic_early_data_context.
|
||||
AC_MSG_CHECKING([for SSL_set_quic_early_data_context])
|
||||
AC_LINK_IFELSE([AC_LANG_PROGRAM([[
|
||||
@@ -530,7 +532,7 @@ fi
|
||||
# ngtcp2 (for src)
|
||||
have_libngtcp2=no
|
||||
if test "x${request_libngtcp2}" != "xno"; then
|
||||
PKG_CHECK_MODULES([LIBNGTCP2], [libngtcp2 >= 1.4.0], [have_libngtcp2=yes],
|
||||
PKG_CHECK_MODULES([LIBNGTCP2], [libngtcp2 >= 1.16.0], [have_libngtcp2=yes],
|
||||
[have_libngtcp2=no])
|
||||
if test "x${have_libngtcp2}" = "xno"; then
|
||||
AC_MSG_NOTICE($LIBNGTCP2_PKG_ERRORS)
|
||||
@@ -547,7 +549,7 @@ have_libngtcp2_crypto_wolfssl=no
|
||||
if test "x${have_wolfssl_quic}" = "xyes" &&
|
||||
test "x${request_libngtcp2}" != "xno"; then
|
||||
PKG_CHECK_MODULES([LIBNGTCP2_CRYPTO_WOLFSSL],
|
||||
[libngtcp2_crypto_wolfssl >= 1.0.0],
|
||||
[libngtcp2_crypto_wolfssl >= 1.16.0],
|
||||
[have_libngtcp2_crypto_wolfssl=yes],
|
||||
[have_libngtcp2_crypto_wolfssl=no])
|
||||
if test "x${have_libngtcp2_crypto_wolfssl}" = "xno"; then
|
||||
@@ -567,10 +569,11 @@ fi
|
||||
# ngtcp2_crypto_quictls (for src)
|
||||
have_libngtcp2_crypto_quictls=no
|
||||
if test "x${have_ssl_provide_quic_data}" = "xyes" &&
|
||||
test "x${have_libressl}" != "xyes" &&
|
||||
test "x${have_boringssl_quic}" != "xyes" &&
|
||||
test "x${request_libngtcp2}" != "xno"; then
|
||||
PKG_CHECK_MODULES([LIBNGTCP2_CRYPTO_QUICTLS],
|
||||
[libngtcp2_crypto_quictls >= 1.0.0],
|
||||
[libngtcp2_crypto_quictls >= 1.16.0],
|
||||
[have_libngtcp2_crypto_quictls=yes],
|
||||
[have_libngtcp2_crypto_quictls=no])
|
||||
if test "x${have_libngtcp2_crypto_quictls}" = "xno"; then
|
||||
@@ -582,12 +585,37 @@ if test "x${have_ssl_provide_quic_data}" = "xyes" &&
|
||||
fi
|
||||
|
||||
if test "x${have_ssl_provide_quic_data}" = "xyes" &&
|
||||
test "x${have_libressl}" != "xyes" &&
|
||||
test "x${have_boringssl_quic}" != "xyes" &&
|
||||
test "x${request_libngtcp2}" = "xyes" &&
|
||||
test "x${have_libngtcp2_crypto_quictls}" != "xyes"; then
|
||||
AC_MSG_ERROR([libngtcp2_crypto_quictls was requested (--with-libngtcp2) but not found])
|
||||
fi
|
||||
|
||||
# ngtcp2_crypto_libressl (for src)
|
||||
have_libngtcp2_crypto_libressl=no
|
||||
if test "x${have_ssl_provide_quic_data}" = "xyes" &&
|
||||
test "x${have_libressl}" = "xyes" &&
|
||||
test "x${request_libngtcp2}" != "xno"; then
|
||||
PKG_CHECK_MODULES([LIBNGTCP2_CRYPTO_LIBRESSL],
|
||||
[libngtcp2_crypto_libressl >= 1.16.0],
|
||||
[have_libngtcp2_crypto_libressl=yes],
|
||||
[have_libngtcp2_crypto_libressl=no])
|
||||
if test "x${have_libngtcp2_crypto_libressl}" = "xno"; then
|
||||
AC_MSG_NOTICE($LIBNGTCP2_CRYPTO_LIBRESSL_PKG_ERRORS)
|
||||
else
|
||||
AC_DEFINE([HAVE_LIBNGTCP2_CRYPTO_LIBRESSL], [1],
|
||||
[Define to 1 if you have `libngtcp2_crypto_libressl` library.])
|
||||
fi
|
||||
fi
|
||||
|
||||
if test "x${have_ssl_provide_quic_data}" = "xyes" &&
|
||||
test "x${have_libressl}" = "xyes" &&
|
||||
test "x${request_libngtcp2}" = "xyes" &&
|
||||
test "x${have_libngtcp2_crypto_libressl}" != "xyes"; then
|
||||
AC_MSG_ERROR([libngtcp2_crypto_libressl was requested (--with-libngtcp2) but not found])
|
||||
fi
|
||||
|
||||
# ngtcp2_crypto_boringssl (for src)
|
||||
have_libngtcp2_crypto_boringssl=no
|
||||
if test "x${have_boringssl_quic}" = "xyes" &&
|
||||
@@ -610,10 +638,32 @@ if test "x${have_boringssl_quic}" = "xyes" &&
|
||||
AC_MSG_ERROR([libngtcp2_crypto_boringssl was requested (--with-libngtcp2) but not found])
|
||||
fi
|
||||
|
||||
# ngtcp2_crypto_ossl (for src)
|
||||
have_libngtcp2_crypto_ossl=no
|
||||
if test "x${have_ossl_quic}" = "xyes" &&
|
||||
test "x${request_libngtcp2}" != "xno"; then
|
||||
PKG_CHECK_MODULES([LIBNGTCP2_CRYPTO_OSSL],
|
||||
[libngtcp2_crypto_ossl >= 1.16.0],
|
||||
[have_libngtcp2_crypto_ossl=yes],
|
||||
[have_libngtcp2_crypto_ossl=no])
|
||||
if test "x${have_libngtcp2_crypto_ossl}" = "xno"; then
|
||||
AC_MSG_NOTICE($LIBNGTCP2_CRYPTO_OSSL_PKG_ERRORS)
|
||||
else
|
||||
AC_DEFINE([HAVE_LIBNGTCP2_CRYPTO_OSSL], [1],
|
||||
[Define to 1 if you have `libngtcp2_crypto_ossl` library.])
|
||||
fi
|
||||
fi
|
||||
|
||||
if test "x${have_ossl_quic}" = "xyes" &&
|
||||
test "x${request_libngtcp2}" = "xyes" &&
|
||||
test "x${have_libngtcp2_crypto_ossl}" != "xyes"; then
|
||||
AC_MSG_ERROR([libngtcp2_crypto_ossl was requested (--with-libngtcp2) but not found])
|
||||
fi
|
||||
|
||||
# nghttp3 (for src)
|
||||
have_libnghttp3=no
|
||||
if test "x${request_libnghttp3}" != "xno"; then
|
||||
PKG_CHECK_MODULES([LIBNGHTTP3], [libnghttp3 >= 1.1.0], [have_libnghttp3=yes],
|
||||
PKG_CHECK_MODULES([LIBNGHTTP3], [libnghttp3 >= 1.12.0], [have_libnghttp3=yes],
|
||||
[have_libnghttp3=no])
|
||||
if test "x${have_libnghttp3}" = "xno"; then
|
||||
AC_MSG_NOTICE($LIBNGHTTP3_PKG_ERRORS)
|
||||
@@ -842,7 +892,9 @@ if test "x${request_http3}" != "xno" &&
|
||||
test "x${have_libngtcp2}" = "xyes" &&
|
||||
(test "x${have_libngtcp2_crypto_wolfssl}" = "xyes" ||
|
||||
test "x${have_libngtcp2_crypto_quictls}" = "xyes" ||
|
||||
test "x${have_libngtcp2_crypto_boringssl}" = "xyes") &&
|
||||
test "x${have_libngtcp2_crypto_libressl}" = "xyes" ||
|
||||
test "x${have_libngtcp2_crypto_boringssl}" = "xyes" ||
|
||||
test "x${have_libngtcp2_crypto_ossl}" = "xyes") &&
|
||||
test "x${have_libnghttp3}" = "xyes"; then
|
||||
enable_http3=yes
|
||||
AC_DEFINE([ENABLE_HTTP3], [1], [Define to 1 if HTTP/3 is enabled.])
|
||||
@@ -1135,6 +1187,7 @@ if test "x$werror" != "xno"; then
|
||||
AX_CHECK_COMPILE_FLAG([-Wformat-security], [CXXFLAGS="$CXXFLAGS -Wformat-security"])
|
||||
AX_CHECK_COMPILE_FLAG([-Wsometimes-uninitialized], [CXXFLAGS="$CXXFLAGS -Wsometimes-uninitialized"])
|
||||
AX_CHECK_COMPILE_FLAG([-Wextra-semi], [CXXFLAGS="$CXXFLAGS -Wextra-semi"])
|
||||
AX_CHECK_COMPILE_FLAG([-Wconversion], [CXXFLAGS="$CXXFLAGS -Wconversion"])
|
||||
# Disable noexcept-type warning of g++-7. This is not harmful as
|
||||
# long as all source files are compiled with the same compiler.
|
||||
AX_CHECK_COMPILE_FLAG([-Wno-noexcept-type], [CXXFLAGS="$CXXFLAGS -Wno-noexcept-type"])
|
||||
@@ -1206,7 +1259,6 @@ AC_CONFIG_FILES([
|
||||
doc/nghttp2ver.h.rst
|
||||
doc/contribute.rst
|
||||
contrib/Makefile
|
||||
script/Makefile
|
||||
])
|
||||
AC_OUTPUT
|
||||
|
||||
@@ -1255,7 +1307,9 @@ AC_MSG_NOTICE([summary of build options:
|
||||
Libc-ares: ${have_libcares} (CFLAGS='${LIBCARES_CFLAGS}' LIBS='${LIBCARES_LIBS}')
|
||||
libngtcp2: ${have_libngtcp2} (CFLAGS='${LIBNGTCP2_CFLAGS}' LIBS='${LIBNGTCP2_LIBS}')
|
||||
libngtcp2_crypto_quictls: ${have_libngtcp2_crypto_quictls} (CFLAGS='${LIBNGTCP2_CRYPTO_QUICTLS_CFLAGS}' LIBS='${LIBNGTCP2_CRYPTO_QUICTLS_LIBS}')
|
||||
libngtcp2_crypto_libressl: ${have_libngtcp2_crypto_libressl} (CFLAGS='${LIBNGTCP2_CRYPTO_LIBRESSL_CFLAGS}' LIBS='${LIBNGTCP2_CRYPTO_LIBRESSL_LIBS}')
|
||||
libngtcp2_crypto_boringssl: ${have_libngtcp2_crypto_boringssl} (CFLAGS='${LIBNGTCP2_CRYPTO_BORINGSSL_CFLAGS}' LIBS='${LIBNGTCP2_CRYPTO_BORINGSSL_LIBS}')
|
||||
libngtcp2_crypto_ossl: ${have_libngtcp2_crypto_ossl} (CFLAGS='${LIBNGTCP2_CRYPTO_OSSL_CFLAGS}' LIBS='${LIBNGTCP2_CRYPTO_OSSL_LIBS}')
|
||||
libnghttp3: ${have_libnghttp3} (CFLAGS='${LIBNGHTTP3_CFLAGS}' LIBS='${LIBNGHTTP3_LIBS}')
|
||||
libbpf: ${have_libbpf} (CFLAGS='${LIBBPF_CFLAGS}' LIBS='${LIBBPF_LIBS}')
|
||||
Libevent(SSL): ${have_libevent_openssl} (CFLAGS='${LIBEVENT_OPENSSL_CFLAGS}' LIBS='${LIBEVENT_OPENSSL_LIBS}')
|
||||
|
||||
@@ -81,6 +81,7 @@ APIDOCS= \
|
||||
nghttp2_option_set_max_outbound_ack.rst \
|
||||
nghttp2_option_set_max_settings.rst \
|
||||
nghttp2_option_set_stream_reset_rate_limit.rst \
|
||||
nghttp2_option_set_glitch_rate_limit.rst \
|
||||
nghttp2_pack_settings_payload.rst \
|
||||
nghttp2_pack_settings_payload2.rst \
|
||||
nghttp2_priority_spec_check_default.rst \
|
||||
@@ -114,6 +115,7 @@ APIDOCS= \
|
||||
nghttp2_session_callbacks_set_on_stream_close_callback.rst \
|
||||
nghttp2_session_callbacks_set_pack_extension_callback.rst \
|
||||
nghttp2_session_callbacks_set_pack_extension_callback2.rst \
|
||||
nghttp2_session_callbacks_set_rand_callback.rst \
|
||||
nghttp2_session_callbacks_set_recv_callback.rst \
|
||||
nghttp2_session_callbacks_set_recv_callback2.rst \
|
||||
nghttp2_session_callbacks_set_select_padding_callback.rst \
|
||||
|
||||
@@ -111,7 +111,7 @@ The example follows::
|
||||
|
||||
``@struct`` is used to refer to the struct. Currently, only struct
|
||||
typedefs are supported. The comment block is used for the document for
|
||||
the struct type itself.To document each member, put comment block
|
||||
the struct type itself. To document each member, put comment block
|
||||
starting with the line ``/**`` and ending with the ``*/`` just before
|
||||
the member. When the line starts with ``}`` is encountered, the
|
||||
``mkapiref.py`` extracts strings next to ``}`` as the name of struct.
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
sphinxcontrib
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
This package is a namespace package that contains all extensions
|
||||
distributed in the ``sphinx-contrib`` distribution.
|
||||
|
||||
:copyright: Copyright 2007-2009 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
|
||||
__import__('pkg_resources').declare_namespace(__name__)
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ _nghttpd()
|
||||
_get_comp_words_by_ref cur prev
|
||||
case $cur in
|
||||
-*)
|
||||
COMPREPLY=( $( compgen -W '--address --daemon --verify-client --htdocs --verbose --no-tls --header-table-size --encoder-header-table-size --color --push --padding --max-concurrent-streams --workers --error-gzip --window-bits --connection-window-bits --dh-param-file --early-response --trailer --hexdump --echo-upload --mime-types-file --no-content-length --ktls --version --help ' -- "$cur" ) )
|
||||
COMPREPLY=( $( compgen -W '--address --daemon --verify-client --htdocs --verbose --no-tls --header-table-size --encoder-header-table-size --color --push --padding --max-concurrent-streams --workers --error-gzip --window-bits --connection-window-bits --dh-param-file --early-response --trailer --hexdump --echo-upload --mime-types-file --no-content-length --groups --ktls --version --help ' -- "$cur" ) )
|
||||
;;
|
||||
*)
|
||||
_filedir
|
||||
|
||||
@@ -8,7 +8,7 @@ _nghttpx()
|
||||
_get_comp_words_by_ref cur prev
|
||||
case $cur in
|
||||
-*)
|
||||
COMPREPLY=( $( compgen -W '--backend --frontend --backlog --backend-address-family --backend-http-proxy-uri --workers --single-thread --read-rate --read-burst --write-rate --write-burst --worker-read-rate --worker-read-burst --worker-write-rate --worker-write-burst --worker-frontend-connections --backend-connections-per-host --backend-connections-per-frontend --rlimit-nofile --rlimit-memlock --backend-request-buffer --backend-response-buffer --fastopen --no-kqueue --frontend-http2-idle-timeout --frontend-http3-idle-timeout --frontend-write-timeout --frontend-keep-alive-timeout --frontend-header-timeout --stream-read-timeout --stream-write-timeout --backend-read-timeout --backend-write-timeout --backend-connect-timeout --backend-keep-alive-timeout --listener-disable-timeout --frontend-http2-setting-timeout --backend-http2-settings-timeout --backend-max-backoff --ciphers --tls13-ciphers --client-ciphers --tls13-client-ciphers --ecdh-curves --insecure --cacert --private-key-passwd-file --subcert --dh-param-file --alpn-list --verify-client --verify-client-cacert --verify-client-tolerate-expired --client-private-key-file --client-cert-file --tls-min-proto-version --tls-max-proto-version --tls-ticket-key-file --tls-ticket-key-memcached --tls-ticket-key-memcached-address-family --tls-ticket-key-memcached-interval --tls-ticket-key-memcached-max-retry --tls-ticket-key-memcached-max-fail --tls-ticket-key-cipher --tls-ticket-key-memcached-cert-file --tls-ticket-key-memcached-private-key-file --fetch-ocsp-response-file --ocsp-update-interval --ocsp-startup --no-verify-ocsp --no-ocsp --tls-session-cache-memcached --tls-session-cache-memcached-address-family --tls-session-cache-memcached-cert-file --tls-session-cache-memcached-private-key-file --tls-dyn-rec-warmup-threshold --tls-dyn-rec-idle-timeout --no-http2-cipher-block-list --client-no-http2-cipher-block-list --tls-sct-dir --psk-secrets --client-psk-secrets --tls-no-postpone-early-data --tls-max-early-data --tls-ktls --frontend-http2-max-concurrent-streams --backend-http2-max-concurrent-streams --frontend-http2-window-size --frontend-http2-connection-window-size --backend-http2-window-size --backend-http2-connection-window-size --http2-no-cookie-crumbling --padding --no-server-push --frontend-http2-optimize-write-buffer-size --frontend-http2-optimize-window-size --frontend-http2-encoder-dynamic-table-size --frontend-http2-decoder-dynamic-table-size --backend-http2-encoder-dynamic-table-size --backend-http2-decoder-dynamic-table-size --http2-proxy --log-level --accesslog-file --accesslog-syslog --accesslog-format --accesslog-write-early --errorlog-file --errorlog-syslog --syslog-facility --add-x-forwarded-for --strip-incoming-x-forwarded-for --no-add-x-forwarded-proto --no-strip-incoming-x-forwarded-proto --add-forwarded --strip-incoming-forwarded --forwarded-by --forwarded-for --no-via --no-strip-incoming-early-data --no-location-rewrite --host-rewrite --altsvc --http2-altsvc --add-request-header --add-response-header --request-header-field-buffer --max-request-header-fields --response-header-field-buffer --max-response-header-fields --error-page --server-name --no-server-rewrite --redirect-https-port --require-http-scheme --api-max-request-body --dns-cache-timeout --dns-lookup-timeout --dns-max-try --frontend-max-requests --frontend-http2-dump-request-header --frontend-http2-dump-response-header --frontend-frame-debug --daemon --pid-file --user --single-process --max-worker-processes --worker-process-grace-shutdown-period --mruby-file --ignore-per-pattern-mruby-error --frontend-quic-idle-timeout --frontend-quic-debug-log --quic-bpf-program-file --frontend-quic-early-data --frontend-quic-qlog-dir --frontend-quic-require-token --frontend-quic-congestion-controller --frontend-quic-secret-file --quic-server-id --frontend-quic-initial-rtt --no-quic-bpf --frontend-http3-window-size --frontend-http3-connection-window-size --frontend-http3-max-window-size --frontend-http3-max-connection-window-size --frontend-http3-max-concurrent-streams --conf --include --version --help ' -- "$cur" ) )
|
||||
COMPREPLY=( $( compgen -W '--backend --frontend --backlog --backend-address-family --backend-http-proxy-uri --workers --single-thread --read-rate --read-burst --write-rate --write-burst --worker-read-rate --worker-read-burst --worker-write-rate --worker-write-burst --worker-frontend-connections --backend-connections-per-host --backend-connections-per-frontend --rlimit-nofile --rlimit-memlock --backend-request-buffer --backend-response-buffer --fastopen --no-kqueue --frontend-http2-idle-timeout --frontend-http3-idle-timeout --frontend-write-timeout --frontend-keep-alive-timeout --frontend-header-timeout --stream-read-timeout --stream-write-timeout --backend-read-timeout --backend-write-timeout --backend-connect-timeout --backend-keep-alive-timeout --listener-disable-timeout --frontend-http2-setting-timeout --backend-http2-settings-timeout --backend-max-backoff --ciphers --tls13-ciphers --client-ciphers --tls13-client-ciphers --groups --insecure --cacert --private-key-passwd-file --subcert --dh-param-file --alpn-list --verify-client --verify-client-cacert --verify-client-tolerate-expired --client-private-key-file --client-cert-file --tls-min-proto-version --tls-max-proto-version --tls-ticket-key-file --tls-ticket-key-memcached --tls-ticket-key-memcached-address-family --tls-ticket-key-memcached-interval --tls-ticket-key-memcached-max-retry --tls-ticket-key-memcached-max-fail --tls-ticket-key-cipher --tls-ticket-key-memcached-cert-file --tls-ticket-key-memcached-private-key-file --tls-dyn-rec-warmup-threshold --tls-dyn-rec-idle-timeout --no-http2-cipher-block-list --client-no-http2-cipher-block-list --tls-sct-dir --psk-secrets --client-psk-secrets --tls-no-postpone-early-data --tls-max-early-data --tls-ktls --frontend-http2-max-concurrent-streams --backend-http2-max-concurrent-streams --frontend-http2-window-size --frontend-http2-connection-window-size --backend-http2-window-size --backend-http2-connection-window-size --http2-no-cookie-crumbling --padding --no-server-push --frontend-http2-optimize-write-buffer-size --frontend-http2-optimize-window-size --frontend-http2-encoder-dynamic-table-size --frontend-http2-decoder-dynamic-table-size --backend-http2-encoder-dynamic-table-size --backend-http2-decoder-dynamic-table-size --http2-proxy --log-level --accesslog-file --accesslog-syslog --accesslog-format --accesslog-write-early --errorlog-file --errorlog-syslog --syslog-facility --add-x-forwarded-for --strip-incoming-x-forwarded-for --no-add-x-forwarded-proto --no-strip-incoming-x-forwarded-proto --add-forwarded --strip-incoming-forwarded --forwarded-by --forwarded-for --no-via --no-strip-incoming-early-data --no-location-rewrite --host-rewrite --altsvc --http2-altsvc --add-request-header --add-response-header --request-header-field-buffer --max-request-header-fields --response-header-field-buffer --max-response-header-fields --error-page --server-name --no-server-rewrite --redirect-https-port --require-http-scheme --api-max-request-body --dns-cache-timeout --dns-lookup-timeout --dns-max-try --frontend-max-requests --frontend-http2-dump-request-header --frontend-http2-dump-response-header --frontend-frame-debug --daemon --pid-file --user --single-process --max-worker-processes --worker-process-grace-shutdown-period --mruby-file --ignore-per-pattern-mruby-error --frontend-quic-idle-timeout --frontend-quic-debug-log --quic-bpf-program-file --frontend-quic-early-data --frontend-quic-qlog-dir --frontend-quic-require-token --frontend-quic-congestion-controller --frontend-quic-secret-file --quic-server-id --frontend-quic-initial-rtt --no-quic-bpf --frontend-http3-window-size --frontend-http3-connection-window-size --frontend-http3-max-window-size --frontend-http3-max-connection-window-size --frontend-http3-max-concurrent-streams --conf --include --version --help ' -- "$cur" ) )
|
||||
;;
|
||||
*)
|
||||
_filedir
|
||||
|
||||
12
doc/h2load.1
12
doc/h2load.1
@@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
||||
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
||||
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
|
||||
..
|
||||
.TH "H2LOAD" "1" "Jan 12, 2025" "1.65.0-DEV" "nghttp2"
|
||||
.TH "H2LOAD" "1" "Oct 25, 2025" "1.68.0" "nghttp2"
|
||||
.SH NAME
|
||||
h2load \- HTTP/2 benchmarking tool
|
||||
.SH SYNOPSIS
|
||||
@@ -109,9 +109,9 @@ Default: \fB16K\fP
|
||||
.TP
|
||||
.B \-w, \-\-window\-bits=<N>
|
||||
Sets the stream level initial window size to (2**<N>)\-1.
|
||||
For QUIC, <N> is capped to 26 (roughly 64MiB).
|
||||
.sp
|
||||
Default: \fB30\fP
|
||||
For QUIC, <N> is capped to 26 (roughly 64MiB). It
|
||||
defaults to 24 (16MiB) for QUIC, and 30 for other
|
||||
protocols.
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
@@ -262,7 +262,7 @@ protocol comes first. The parameter must be delimited
|
||||
by a single comma only and any white spaces are treated
|
||||
as a part of protocol string.
|
||||
.sp
|
||||
Default: \fBh2,h2\-16,h2\-14,http/1.1\fP
|
||||
Default: \fBh2,http/1.1\fP
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
@@ -388,7 +388,7 @@ The number of requests completed.
|
||||
.TP
|
||||
.B succeeded
|
||||
The number of requests completed successfully. Only HTTP status
|
||||
code 2xx or3xx are considered as success.
|
||||
code 2xx or 3xx are considered as success.
|
||||
.TP
|
||||
.B failed
|
||||
The number of requests failed, including HTTP level failures
|
||||
|
||||
@@ -83,9 +83,9 @@ OPTIONS
|
||||
.. option:: -w, --window-bits=<N>
|
||||
|
||||
Sets the stream level initial window size to (2\*\*<N>)-1.
|
||||
For QUIC, <N> is capped to 26 (roughly 64MiB).
|
||||
|
||||
Default: ``30``
|
||||
For QUIC, <N> is capped to 26 (roughly 64MiB). It
|
||||
defaults to 24 (16MiB) for QUIC, and 30 for other
|
||||
protocols.
|
||||
|
||||
.. option:: -W, --connection-window-bits=<N>
|
||||
|
||||
@@ -221,7 +221,7 @@ OPTIONS
|
||||
by a single comma only and any white spaces are treated
|
||||
as a part of protocol string.
|
||||
|
||||
Default: ``h2,h2-16,h2-14,http/1.1``
|
||||
Default: ``h2,http/1.1``
|
||||
|
||||
.. option:: --h1
|
||||
|
||||
@@ -331,7 +331,7 @@ requests
|
||||
The number of requests completed.
|
||||
succeeded
|
||||
The number of requests completed successfully. Only HTTP status
|
||||
code 2xx or3xx are considered as success.
|
||||
code 2xx or 3xx are considered as success.
|
||||
failed
|
||||
The number of requests failed, including HTTP level failures
|
||||
(non-successful HTTP status code).
|
||||
|
||||
@@ -12,7 +12,7 @@ requests
|
||||
The number of requests completed.
|
||||
succeeded
|
||||
The number of requests completed successfully. Only HTTP status
|
||||
code 2xx or3xx are considered as success.
|
||||
code 2xx or 3xx are considered as success.
|
||||
failed
|
||||
The number of requests failed, including HTTP level failures
|
||||
(non-successful HTTP status code).
|
||||
|
||||
@@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
||||
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
||||
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
|
||||
..
|
||||
.TH "NGHTTP" "1" "Jan 12, 2025" "1.65.0-DEV" "nghttp2"
|
||||
.TH "NGHTTP" "1" "Oct 25, 2025" "1.68.0" "nghttp2"
|
||||
.SH NAME
|
||||
nghttp \- HTTP/2 client
|
||||
.SH SYNOPSIS
|
||||
@@ -243,11 +243,6 @@ Enable ktls.
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \-\-no\-rfc7540\-pri
|
||||
Disable RFC7540 priorities.
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \-\-version
|
||||
Display version information and exit.
|
||||
.UNINDENT
|
||||
|
||||
@@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
||||
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
||||
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
|
||||
..
|
||||
.TH "NGHTTPD" "1" "Jan 12, 2025" "1.65.0-DEV" "nghttp2"
|
||||
.TH "NGHTTPD" "1" "Oct 25, 2025" "1.68.0" "nghttp2"
|
||||
.SH NAME
|
||||
nghttpd \- HTTP/2 server
|
||||
.SH SYNOPSIS
|
||||
@@ -204,6 +204,13 @@ Don\(aqt send content\-length header field.
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \-\-groups=<GROUPS>
|
||||
Specify the supported groups.
|
||||
.sp
|
||||
Default: \fBX25519:P\-256:P\-384:P\-521\fP
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \-\-ktls
|
||||
Enable ktls.
|
||||
.UNINDENT
|
||||
|
||||
@@ -159,6 +159,12 @@ OPTIONS
|
||||
|
||||
Don't send content-length header field.
|
||||
|
||||
.. option:: --groups=<GROUPS>
|
||||
|
||||
Specify the supported groups.
|
||||
|
||||
Default: ``X25519:P-256:P-384:P-521``
|
||||
|
||||
.. option:: --ktls
|
||||
|
||||
Enable ktls.
|
||||
|
||||
170
doc/nghttpx.1
170
doc/nghttpx.1
@@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
||||
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
||||
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
|
||||
..
|
||||
.TH "NGHTTPX" "1" "Jan 12, 2025" "1.65.0-DEV" "nghttp2"
|
||||
.TH "NGHTTPX" "1" "Oct 25, 2025" "1.68.0" "nghttp2"
|
||||
.SH NAME
|
||||
nghttpx \- HTTP/2 proxy
|
||||
.SH SYNOPSIS
|
||||
@@ -46,8 +46,7 @@ Set path to server\(aqs private key. Required unless
|
||||
.TP
|
||||
.B <CERT>
|
||||
Set path to server\(aqs certificate. Required unless
|
||||
\(dqno\-tls\(dq parameter is used in \fI\%\-\-frontend\fP option. To
|
||||
make OCSP stapling work, this must be an absolute path.
|
||||
\(dqno\-tls\(dq parameter is used in \fI\%\-\-frontend\fP option.
|
||||
.UNINDENT
|
||||
.SH OPTIONS
|
||||
.sp
|
||||
@@ -688,8 +687,8 @@ 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.
|
||||
This option sets cipher suites for TLSv1.2. Use
|
||||
\fI\%\-\-tls13\-ciphers\fP for TLSv1.3.
|
||||
.sp
|
||||
Default: \fBECDHE\-ECDSA\-AES128\-GCM\-SHA256:ECDHE\-RSA\-AES128\-GCM\-SHA256:ECDHE\-ECDSA\-AES256\-GCM\-SHA384:ECDHE\-RSA\-AES256\-GCM\-SHA384:ECDHE\-ECDSA\-CHACHA20\-POLY1305:ECDHE\-RSA\-CHACHA20\-POLY1305:DHE\-RSA\-AES128\-GCM\-SHA256:DHE\-RSA\-AES256\-GCM\-SHA384\fP
|
||||
.UNINDENT
|
||||
@@ -699,7 +698,7 @@ Default: \fBECDHE\-ECDSA\-AES128\-GCM\-SHA256:ECDHE\-RSA\-AES128\-GCM\-SHA256:EC
|
||||
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.
|
||||
\fI\%\-\-ciphers\fP for TLSv1.2.
|
||||
.sp
|
||||
Default: \fBTLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256\fP
|
||||
.UNINDENT
|
||||
@@ -708,8 +707,8 @@ Default: \fBTLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_
|
||||
.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.
|
||||
This option sets cipher suites for TLSv1.2. Use
|
||||
\fI\%\-\-tls13\-client\-ciphers\fP for TLSv1.3.
|
||||
.sp
|
||||
Default: \fBECDHE\-ECDSA\-AES128\-GCM\-SHA256:ECDHE\-RSA\-AES128\-GCM\-SHA256:ECDHE\-ECDSA\-AES256\-GCM\-SHA384:ECDHE\-RSA\-AES256\-GCM\-SHA384:ECDHE\-ECDSA\-CHACHA20\-POLY1305:ECDHE\-RSA\-CHACHA20\-POLY1305:DHE\-RSA\-AES128\-GCM\-SHA256:DHE\-RSA\-AES256\-GCM\-SHA384\fP
|
||||
.UNINDENT
|
||||
@@ -719,15 +718,15 @@ Default: \fBECDHE\-ECDSA\-AES128\-GCM\-SHA256:ECDHE\-RSA\-AES128\-GCM\-SHA256:EC
|
||||
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.
|
||||
\fI\%\-\-client\-ciphers\fP for TLSv1.2.
|
||||
.sp
|
||||
Default: \fBTLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_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
|
||||
.B \-\-groups=<LIST>
|
||||
Set the supported group list for frontend connections.
|
||||
<LIST> is a colon separated list of group NID or names
|
||||
in the preference order. The supported curves depend on
|
||||
the linked OpenSSL library. This function requires
|
||||
OpenSSL >= 1.0.2.
|
||||
@@ -745,12 +744,10 @@ enabled for backend connections.
|
||||
.B \-\-cacert=<PATH>
|
||||
Set path to trusted CA certificate file. It is used in
|
||||
backend TLS connections to verify peer\(aqs certificate.
|
||||
It is also used to verify OCSP response from the script
|
||||
set by \fI\%\-\-fetch\-ocsp\-response\-file\fP\&. The file must be in
|
||||
PEM format. It can contain multiple certificates. If
|
||||
the linked OpenSSL is configured to load system wide
|
||||
certificates, they are loaded at startup regardless of
|
||||
this option.
|
||||
The file must be in PEM format. It can contain multiple
|
||||
certificates. If the linked OpenSSL is configured to
|
||||
load system wide certificates, they are loaded at
|
||||
startup regardless of this option.
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
@@ -765,13 +762,12 @@ password protected it\(aqll be requested interactively.
|
||||
Specify additional certificate and private key file.
|
||||
nghttpx will choose certificates based on the hostname
|
||||
indicated by client using TLS SNI extension. If nghttpx
|
||||
is built with OpenSSL >= 1.0.2, the shared elliptic
|
||||
curves (e.g., P\-256) between client and server are also
|
||||
taken into consideration. This allows nghttpx to send
|
||||
ECDSA certificate to modern clients, while sending RSA
|
||||
based certificate to older clients. This option can be
|
||||
used multiple times. To make OCSP stapling work,
|
||||
<CERTPATH> must be absolute path.
|
||||
is built with OpenSSL >= 1.0.2, the signature algorithms
|
||||
(e.g., ECDSA+SHA256) presented by client are also taken
|
||||
into consideration. This allows nghttpx to send ML\-DSA
|
||||
or ECDSA certificate to modern clients, while sending
|
||||
RSA based certificate to older clients. This option can
|
||||
be used multiple times.
|
||||
.sp
|
||||
Additional parameter can be specified in <PARAM>. The
|
||||
available <PARAM> is \(dqsct\-dir=<DIR>\(dq.
|
||||
@@ -798,7 +794,7 @@ protocol comes first. The parameter must be delimited
|
||||
by a single comma only and any white spaces are treated
|
||||
as a part of protocol string.
|
||||
.sp
|
||||
Default: \fBh2,h2\-16,h2\-14,http/1.1\fP
|
||||
Default: \fBh2,http/1.1\fP
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
@@ -840,12 +836,8 @@ done in case\-insensitive manner. The versions between
|
||||
\fI\%\-\-tls\-min\-proto\-version\fP and \fI\%\-\-tls\-max\-proto\-version\fP are
|
||||
enabled. If the protocol list advertised by client does
|
||||
not overlap this range, you will receive the error
|
||||
message \(dqunknown protocol\(dq. If a protocol version lower
|
||||
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.3, TLSv1.2, TLSv1.1, and TLSv1.0
|
||||
message \(dqunknown protocol\(dq. The available versions are:
|
||||
TLSv1.3 and TLSv1.2
|
||||
.sp
|
||||
Default: \fBTLSv1.2\fP
|
||||
.UNINDENT
|
||||
@@ -858,7 +850,7 @@ 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 \(dqunknown protocol\(dq. The available versions are:
|
||||
TLSv1.3, TLSv1.2, TLSv1.1, and TLSv1.0
|
||||
TLSv1.3 and TLSv1.2
|
||||
.sp
|
||||
Default: \fBTLSv1.3\fP
|
||||
.UNINDENT
|
||||
@@ -962,72 +954,6 @@ get TLS ticket keys.
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \-\-fetch\-ocsp\-response\-file=<PATH>
|
||||
Path to fetch\-ocsp\-response script file. It should be
|
||||
absolute path.
|
||||
.sp
|
||||
Default: \fB/usr/local/share/nghttp2/fetch\-ocsp\-response\fP
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \-\-ocsp\-update\-interval=<DURATION>
|
||||
Set interval to update OCSP response cache.
|
||||
.sp
|
||||
Default: \fB4h\fP
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \-\-ocsp\-startup
|
||||
Start accepting connections after initial attempts to
|
||||
get OCSP responses finish. It does not matter some of
|
||||
the attempts fail. This feature is useful if OCSP
|
||||
responses must be available before accepting
|
||||
connections.
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \-\-no\-verify\-ocsp
|
||||
nghttpx does not verify OCSP response.
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \-\-no\-ocsp
|
||||
Disable OCSP stapling.
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \-\-tls\-session\-cache\-memcached=<HOST>,<PORT>[;tls]
|
||||
Specify address of memcached server to store session
|
||||
cache. This enables shared session cache between
|
||||
multiple nghttpx instances. Optionally, memcached
|
||||
connection can be encrypted with TLS by specifying \(dqtls\(dq
|
||||
parameter.
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \-\-tls\-session\-cache\-memcached\-address\-family=(auto|IPv4|IPv6)
|
||||
Specify address family of memcached connections to store
|
||||
session cache. If \(dqauto\(dq is given, both IPv4 and IPv6
|
||||
are considered. If \(dqIPv4\(dq is given, only IPv4 address
|
||||
is considered. If \(dqIPv6\(dq is given, only IPv6 address is
|
||||
considered.
|
||||
.sp
|
||||
Default: \fBauto\fP
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \-\-tls\-session\-cache\-memcached\-cert\-file=<PATH>
|
||||
Path to client certificate for memcached connections to
|
||||
store session cache.
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \-\-tls\-session\-cache\-memcached\-private\-key\-file=<PATH>
|
||||
Path to client private key for memcached connections to
|
||||
store session cache.
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \-\-tls\-dyn\-rec\-warmup\-threshold=<SIZE>
|
||||
Specify the threshold size for TLS dynamic record size
|
||||
behaviour. During a TLS session, after the threshold
|
||||
@@ -1135,8 +1061,7 @@ Default: \fB16K\fP
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \-\-tls\-ktls
|
||||
Enable ktls. For server, ktls is enable if
|
||||
\fI\%\-\-tls\-session\-cache\-memcached\fP is not configured.
|
||||
Enable ktls.
|
||||
.UNINDENT
|
||||
.SS HTTP/2
|
||||
.INDENT 0.0
|
||||
@@ -1675,7 +1600,7 @@ initial DNS query. For the 2nd and later queries,
|
||||
server is given time based on this timeout, and it is
|
||||
scaled linearly.
|
||||
.sp
|
||||
Default: \fB5s\fP
|
||||
Default: \fB250ms\fP
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
@@ -1683,7 +1608,7 @@ Default: \fB5s\fP
|
||||
Set the number of DNS query before nghttpx gives up name
|
||||
lookup.
|
||||
.sp
|
||||
Default: \fB2\fP
|
||||
Default: \fB3\fP
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
@@ -2154,35 +2079,6 @@ specified socket already exists in the file system, nghttpx first
|
||||
deletes it. However, if SIGUSR2 is used to execute new binary and
|
||||
both old and new configurations use same filename, new binary does not
|
||||
delete the socket and continues to use it.
|
||||
.SH OCSP STAPLING
|
||||
.sp
|
||||
OCSP query is done using external Python script
|
||||
\fBfetch\-ocsp\-response\fP, which has been originally developed in Perl
|
||||
as part of h2o project (\X'tty: link https://github.com/h2o/h2o'\fI\%https://github.com/h2o/h2o\fP\X'tty: link'), and was
|
||||
translated into Python.
|
||||
.sp
|
||||
The script file is usually installed under
|
||||
\fB$(prefix)/share/nghttp2/\fP directory. The actual path to script can
|
||||
be customized using \fI\%\-\-fetch\-ocsp\-response\-file\fP option.
|
||||
.sp
|
||||
If OCSP query is failed, previous OCSP response, if any, is continued
|
||||
to be used.
|
||||
.sp
|
||||
\fI\%\-\-fetch\-ocsp\-response\-file\fP option provides wide range of
|
||||
possibility to manage OCSP response. It can take an arbitrary script
|
||||
or executable. The requirement is that it supports the command\-line
|
||||
interface of \fBfetch\-ocsp\-response\fP script, and it must return a
|
||||
valid DER encoded OCSP response on success. It must return exit code
|
||||
0 on success, and 75 for temporary error, and the other error code for
|
||||
generic failure. For large cluster of servers, it is not efficient
|
||||
for each server to perform OCSP query using \fBfetch\-ocsp\-response\fP\&.
|
||||
Instead, you can retrieve OCSP response in some way, and store it in a
|
||||
disk or a shared database. Then specify a program in
|
||||
\fI\%\-\-fetch\-ocsp\-response\-file\fP to fetch it from those stores.
|
||||
This could provide a way to share the OCSP response between fleet of
|
||||
servers, and also any OCSP query strategy can be applied which may be
|
||||
beyond the ability of nghttpx itself or \fBfetch\-ocsp\-response\fP
|
||||
script.
|
||||
.SH TLS SESSION RESUMPTION
|
||||
.sp
|
||||
nghttpx supports TLS session resumption through both session ID and
|
||||
@@ -2190,16 +2086,6 @@ session ticket.
|
||||
.SS SESSION ID RESUMPTION
|
||||
.sp
|
||||
By default, session ID is shared by all worker threads.
|
||||
.sp
|
||||
If \fI\%\-\-tls\-session\-cache\-memcached\fP is given, nghttpx will
|
||||
insert serialized session data to memcached with
|
||||
\fBnghttpx:tls\-session\-cache:\fP + lowercase hex string of session ID
|
||||
as a memcached entry key, with expiry time 12 hours. Session timeout
|
||||
is set to 12 hours.
|
||||
.sp
|
||||
By default, connections to memcached server are not encrypted. To
|
||||
enable encryption, use \fBtls\fP keyword in
|
||||
\fI\%\-\-tls\-session\-cache\-memcached\fP option.
|
||||
.SS TLS SESSION TICKET RESUMPTION
|
||||
.sp
|
||||
By default, session ticket is shared by all worker threads. The
|
||||
|
||||
@@ -25,8 +25,7 @@ A reverse proxy for HTTP/3, HTTP/2, and HTTP/1.
|
||||
.. describe:: <CERT>
|
||||
|
||||
Set path to server's certificate. Required unless
|
||||
"no-tls" parameter is used in :option:`--frontend` option. To
|
||||
make OCSP stapling work, this must be an absolute path.
|
||||
"no-tls" parameter is used in :option:`--frontend` option.
|
||||
|
||||
|
||||
OPTIONS
|
||||
@@ -644,8 +643,8 @@ 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.
|
||||
This option sets cipher suites for TLSv1.2. Use
|
||||
:option:`--tls13-ciphers` for TLSv1.3.
|
||||
|
||||
Default: ``ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384``
|
||||
|
||||
@@ -654,7 +653,7 @@ 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.3. Use
|
||||
:option:`--ciphers` for TLSv1.2 or earlier.
|
||||
:option:`--ciphers` for TLSv1.2.
|
||||
|
||||
Default: ``TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256``
|
||||
|
||||
@@ -662,8 +661,8 @@ SSL/TLS
|
||||
|
||||
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.
|
||||
This option sets cipher suites for TLSv1.2. Use
|
||||
:option:`--tls13-client-ciphers` for TLSv1.3.
|
||||
|
||||
Default: ``ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384``
|
||||
|
||||
@@ -672,14 +671,14 @@ SSL/TLS
|
||||
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.
|
||||
:option:`--client-ciphers` for TLSv1.2.
|
||||
|
||||
Default: ``TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256``
|
||||
|
||||
.. option:: --ecdh-curves=<LIST>
|
||||
.. option:: --groups=<LIST>
|
||||
|
||||
Set supported curve list for frontend connections.
|
||||
<LIST> is a colon separated list of curve NID or names
|
||||
Set the supported group list for frontend connections.
|
||||
<LIST> is a colon separated list of group NID or names
|
||||
in the preference order. The supported curves depend on
|
||||
the linked OpenSSL library. This function requires
|
||||
OpenSSL >= 1.0.2.
|
||||
@@ -695,12 +694,10 @@ SSL/TLS
|
||||
|
||||
Set path to trusted CA certificate file. It is used in
|
||||
backend TLS connections to verify peer's certificate.
|
||||
It is also used to verify OCSP response from the script
|
||||
set by :option:`--fetch-ocsp-response-file`\. The file must be in
|
||||
PEM format. It can contain multiple certificates. If
|
||||
the linked OpenSSL is configured to load system wide
|
||||
certificates, they are loaded at startup regardless of
|
||||
this option.
|
||||
The file must be in PEM format. It can contain multiple
|
||||
certificates. If the linked OpenSSL is configured to
|
||||
load system wide certificates, they are loaded at
|
||||
startup regardless of this option.
|
||||
|
||||
.. option:: --private-key-passwd-file=<PATH>
|
||||
|
||||
@@ -713,13 +710,12 @@ SSL/TLS
|
||||
Specify additional certificate and private key file.
|
||||
nghttpx will choose certificates based on the hostname
|
||||
indicated by client using TLS SNI extension. If nghttpx
|
||||
is built with OpenSSL >= 1.0.2, the shared elliptic
|
||||
curves (e.g., P-256) between client and server are also
|
||||
taken into consideration. This allows nghttpx to send
|
||||
ECDSA certificate to modern clients, while sending RSA
|
||||
based certificate to older clients. This option can be
|
||||
used multiple times. To make OCSP stapling work,
|
||||
<CERTPATH> must be absolute path.
|
||||
is built with OpenSSL >= 1.0.2, the signature algorithms
|
||||
(e.g., ECDSA+SHA256) presented by client are also taken
|
||||
into consideration. This allows nghttpx to send ML-DSA
|
||||
or ECDSA certificate to modern clients, while sending
|
||||
RSA based certificate to older clients. This option can
|
||||
be used multiple times.
|
||||
|
||||
Additional parameter can be specified in <PARAM>. The
|
||||
available <PARAM> is "sct-dir=<DIR>".
|
||||
@@ -744,7 +740,7 @@ SSL/TLS
|
||||
by a single comma only and any white spaces are treated
|
||||
as a part of protocol string.
|
||||
|
||||
Default: ``h2,h2-16,h2-14,http/1.1``
|
||||
Default: ``h2,http/1.1``
|
||||
|
||||
.. option:: --verify-client
|
||||
|
||||
@@ -780,12 +776,8 @@ SSL/TLS
|
||||
:option:`--tls-min-proto-version` and :option:`\--tls-max-proto-version` are
|
||||
enabled. If the protocol list advertised by client does
|
||||
not overlap this range, you will receive the error
|
||||
message "unknown protocol". If a protocol version lower
|
||||
than TLSv1.2 is specified, make sure that the compatible
|
||||
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.3, TLSv1.2, TLSv1.1, and TLSv1.0
|
||||
message "unknown protocol". The available versions are:
|
||||
TLSv1.3 and TLSv1.2
|
||||
|
||||
Default: ``TLSv1.2``
|
||||
|
||||
@@ -797,7 +789,7 @@ 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.3, TLSv1.2, TLSv1.1, and TLSv1.0
|
||||
TLSv1.3 and TLSv1.2
|
||||
|
||||
Default: ``TLSv1.3``
|
||||
|
||||
@@ -890,63 +882,6 @@ SSL/TLS
|
||||
Path to client private key for memcached connections to
|
||||
get TLS ticket keys.
|
||||
|
||||
.. option:: --fetch-ocsp-response-file=<PATH>
|
||||
|
||||
Path to fetch-ocsp-response script file. It should be
|
||||
absolute path.
|
||||
|
||||
Default: ``/usr/local/share/nghttp2/fetch-ocsp-response``
|
||||
|
||||
.. option:: --ocsp-update-interval=<DURATION>
|
||||
|
||||
Set interval to update OCSP response cache.
|
||||
|
||||
Default: ``4h``
|
||||
|
||||
.. option:: --ocsp-startup
|
||||
|
||||
Start accepting connections after initial attempts to
|
||||
get OCSP responses finish. It does not matter some of
|
||||
the attempts fail. This feature is useful if OCSP
|
||||
responses must be available before accepting
|
||||
connections.
|
||||
|
||||
.. option:: --no-verify-ocsp
|
||||
|
||||
nghttpx does not verify OCSP response.
|
||||
|
||||
.. option:: --no-ocsp
|
||||
|
||||
Disable OCSP stapling.
|
||||
|
||||
.. option:: --tls-session-cache-memcached=<HOST>,<PORT>[;tls]
|
||||
|
||||
Specify address of memcached server to store session
|
||||
cache. This enables shared session cache between
|
||||
multiple nghttpx instances. Optionally, memcached
|
||||
connection can be encrypted with TLS by specifying "tls"
|
||||
parameter.
|
||||
|
||||
.. option:: --tls-session-cache-memcached-address-family=(auto|IPv4|IPv6)
|
||||
|
||||
Specify address family of memcached connections to store
|
||||
session cache. If "auto" is given, both IPv4 and IPv6
|
||||
are considered. If "IPv4" is given, only IPv4 address
|
||||
is considered. If "IPv6" is given, only IPv6 address is
|
||||
considered.
|
||||
|
||||
Default: ``auto``
|
||||
|
||||
.. option:: --tls-session-cache-memcached-cert-file=<PATH>
|
||||
|
||||
Path to client certificate for memcached connections to
|
||||
store session cache.
|
||||
|
||||
.. option:: --tls-session-cache-memcached-private-key-file=<PATH>
|
||||
|
||||
Path to client private key for memcached connections to
|
||||
store session cache.
|
||||
|
||||
.. option:: --tls-dyn-rec-warmup-threshold=<SIZE>
|
||||
|
||||
Specify the threshold size for TLS dynamic record size
|
||||
@@ -1046,8 +981,7 @@ SSL/TLS
|
||||
|
||||
.. option:: --tls-ktls
|
||||
|
||||
Enable ktls. For server, ktls is enable if
|
||||
:option:`--tls-session-cache-memcached` is not configured.
|
||||
Enable ktls.
|
||||
|
||||
|
||||
HTTP/2
|
||||
@@ -1524,14 +1458,14 @@ DNS
|
||||
server is given time based on this timeout, and it is
|
||||
scaled linearly.
|
||||
|
||||
Default: ``5s``
|
||||
Default: ``250ms``
|
||||
|
||||
.. option:: --dns-max-try=<N>
|
||||
|
||||
Set the number of DNS query before nghttpx gives up name
|
||||
lookup.
|
||||
|
||||
Default: ``2``
|
||||
Default: ``3``
|
||||
|
||||
.. option:: --frontend-max-requests=<N>
|
||||
|
||||
@@ -1971,37 +1905,6 @@ deletes it. However, if SIGUSR2 is used to execute new binary and
|
||||
both old and new configurations use same filename, new binary does not
|
||||
delete the socket and continues to use it.
|
||||
|
||||
OCSP STAPLING
|
||||
-------------
|
||||
|
||||
OCSP query is done using external Python script
|
||||
``fetch-ocsp-response``, which has been originally developed in Perl
|
||||
as part of h2o project (https://github.com/h2o/h2o), and was
|
||||
translated into Python.
|
||||
|
||||
The script file is usually installed under
|
||||
``$(prefix)/share/nghttp2/`` directory. The actual path to script can
|
||||
be customized using :option:`--fetch-ocsp-response-file` option.
|
||||
|
||||
If OCSP query is failed, previous OCSP response, if any, is continued
|
||||
to be used.
|
||||
|
||||
:option:`--fetch-ocsp-response-file` option provides wide range of
|
||||
possibility to manage OCSP response. It can take an arbitrary script
|
||||
or executable. The requirement is that it supports the command-line
|
||||
interface of ``fetch-ocsp-response`` script, and it must return a
|
||||
valid DER encoded OCSP response on success. It must return exit code
|
||||
0 on success, and 75 for temporary error, and the other error code for
|
||||
generic failure. For large cluster of servers, it is not efficient
|
||||
for each server to perform OCSP query using ``fetch-ocsp-response``.
|
||||
Instead, you can retrieve OCSP response in some way, and store it in a
|
||||
disk or a shared database. Then specify a program in
|
||||
:option:`--fetch-ocsp-response-file` to fetch it from those stores.
|
||||
This could provide a way to share the OCSP response between fleet of
|
||||
servers, and also any OCSP query strategy can be applied which may be
|
||||
beyond the ability of nghttpx itself or ``fetch-ocsp-response``
|
||||
script.
|
||||
|
||||
TLS SESSION RESUMPTION
|
||||
----------------------
|
||||
|
||||
@@ -2013,16 +1916,6 @@ SESSION ID RESUMPTION
|
||||
|
||||
By default, session ID is shared by all worker threads.
|
||||
|
||||
If :option:`--tls-session-cache-memcached` is given, nghttpx will
|
||||
insert serialized session data to memcached with
|
||||
``nghttpx:tls-session-cache:`` + lowercase hex string of session ID
|
||||
as a memcached entry key, with expiry time 12 hours. Session timeout
|
||||
is set to 12 hours.
|
||||
|
||||
By default, connections to memcached server are not encrypted. To
|
||||
enable encryption, use ``tls`` keyword in
|
||||
:option:`--tls-session-cache-memcached` option.
|
||||
|
||||
TLS SESSION TICKET RESUMPTION
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
||||
@@ -156,37 +156,6 @@ deletes it. However, if SIGUSR2 is used to execute new binary and
|
||||
both old and new configurations use same filename, new binary does not
|
||||
delete the socket and continues to use it.
|
||||
|
||||
OCSP STAPLING
|
||||
-------------
|
||||
|
||||
OCSP query is done using external Python script
|
||||
``fetch-ocsp-response``, which has been originally developed in Perl
|
||||
as part of h2o project (https://github.com/h2o/h2o), and was
|
||||
translated into Python.
|
||||
|
||||
The script file is usually installed under
|
||||
``$(prefix)/share/nghttp2/`` directory. The actual path to script can
|
||||
be customized using :option:`--fetch-ocsp-response-file` option.
|
||||
|
||||
If OCSP query is failed, previous OCSP response, if any, is continued
|
||||
to be used.
|
||||
|
||||
:option:`--fetch-ocsp-response-file` option provides wide range of
|
||||
possibility to manage OCSP response. It can take an arbitrary script
|
||||
or executable. The requirement is that it supports the command-line
|
||||
interface of ``fetch-ocsp-response`` script, and it must return a
|
||||
valid DER encoded OCSP response on success. It must return exit code
|
||||
0 on success, and 75 for temporary error, and the other error code for
|
||||
generic failure. For large cluster of servers, it is not efficient
|
||||
for each server to perform OCSP query using ``fetch-ocsp-response``.
|
||||
Instead, you can retrieve OCSP response in some way, and store it in a
|
||||
disk or a shared database. Then specify a program in
|
||||
:option:`--fetch-ocsp-response-file` to fetch it from those stores.
|
||||
This could provide a way to share the OCSP response between fleet of
|
||||
servers, and also any OCSP query strategy can be applied which may be
|
||||
beyond the ability of nghttpx itself or ``fetch-ocsp-response``
|
||||
script.
|
||||
|
||||
TLS SESSION RESUMPTION
|
||||
----------------------
|
||||
|
||||
@@ -198,16 +167,6 @@ SESSION ID RESUMPTION
|
||||
|
||||
By default, session ID is shared by all worker threads.
|
||||
|
||||
If :option:`--tls-session-cache-memcached` is given, nghttpx will
|
||||
insert serialized session data to memcached with
|
||||
``nghttpx:tls-session-cache:`` + lowercase hex string of session ID
|
||||
as a memcached entry key, with expiry time 12 hours. Session timeout
|
||||
is set to 12 hours.
|
||||
|
||||
By default, connections to memcached server are not encrypted. To
|
||||
enable encryption, use ``tls`` keyword in
|
||||
:option:`--tls-session-cache-memcached` option.
|
||||
|
||||
TLS SESSION TICKET RESUMPTION
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ Coding style
|
||||
We use clang-format to format source code consistently. The
|
||||
clang-format configuration file .clang-format is located at the root
|
||||
directory. Since clang-format produces slightly different results
|
||||
between versions, we currently use clang-format-18.
|
||||
between versions, we currently use clang-format-19.
|
||||
|
||||
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.
|
||||
|
||||
@@ -167,8 +167,7 @@ Enable SSL/TLS on memcached connection
|
||||
|
||||
By default, memcached connection is not encrypted. To enable
|
||||
encryption, use ``tls`` keyword in
|
||||
:option:`--tls-ticket-key-memcached` for TLS ticket key, and
|
||||
:option:`--tls-session-cache-memcached` for TLS session cache.
|
||||
:option:`--tls-ticket-key-memcached`.
|
||||
|
||||
Specifying additional server certificates
|
||||
-----------------------------------------
|
||||
|
||||
@@ -4,33 +4,36 @@ ARG NGHTTP2_BRANCH=master
|
||||
|
||||
RUN apt-get update && \
|
||||
DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
|
||||
git clang make binutils autoconf automake autotools-dev libtool \
|
||||
git clang-19 make binutils autoconf automake autotools-dev libtool \
|
||||
pkg-config cmake cmake-data \
|
||||
zlib1g-dev libev-dev libjemalloc-dev ruby-dev libc-ares-dev bison \
|
||||
libelf-dev libbrotli-dev
|
||||
|
||||
RUN git clone --recursive --shallow-submodules --depth 1 -b v1.46.1 https://github.com/aws/aws-lc && \
|
||||
RUN git clone --recursive --shallow-submodules --depth 1 -b v1.62.0 https://github.com/aws/aws-lc && \
|
||||
cd aws-lc && \
|
||||
export CC=clang-19 CXX=clang++-19 && \
|
||||
cmake -B build -DDISABLE_GO=ON && \
|
||||
make -j$(nproc) -C build && \
|
||||
cmake --install build && \
|
||||
cd .. && \
|
||||
rm -rf aws-lc
|
||||
|
||||
RUN git clone --recursive --shallow-submodules --depth 1 -b v1.8.0 https://github.com/ngtcp2/nghttp3 && \
|
||||
RUN git clone --recursive --shallow-submodules --depth 1 -b v1.12.0 https://github.com/ngtcp2/nghttp3 && \
|
||||
cd nghttp3 && \
|
||||
autoreconf -i && \
|
||||
./configure --disable-dependency-tracking --enable-lib-only && \
|
||||
./configure --disable-dependency-tracking --enable-lib-only \
|
||||
CC=clang-19 CXX=clang++-19 && \
|
||||
make -j$(nproc) && \
|
||||
make install-strip && \
|
||||
cd .. && \
|
||||
rm -rf nghttp3
|
||||
|
||||
RUN git clone --recursive --shallow-submodules --depth 1 -b v1.11.0 https://github.com/ngtcp2/ngtcp2 && \
|
||||
RUN git clone --recursive --shallow-submodules --depth 1 -b v1.17.0 https://github.com/ngtcp2/ngtcp2 && \
|
||||
cd ngtcp2 && \
|
||||
autoreconf -i && \
|
||||
./configure --disable-dependency-tracking --enable-lib-only \
|
||||
--with-boringssl \
|
||||
CC=clang-19 CXX=clang++-19 \
|
||||
LIBTOOL_LDFLAGS="-static-libtool-libs" \
|
||||
BORINGSSL_LIBS="-l:libssl.a -l:libcrypto.a" \
|
||||
PKG_CONFIG_PATH="/usr/local/lib64/pkgconfig" && \
|
||||
@@ -39,9 +42,9 @@ RUN git clone --recursive --shallow-submodules --depth 1 -b v1.11.0 https://gith
|
||||
cd .. && \
|
||||
rm -rf ngtcp2
|
||||
|
||||
RUN git clone --depth 1 -b v1.5.0 https://github.com/libbpf/libbpf && \
|
||||
RUN git clone --depth 1 -b v1.6.2 https://github.com/libbpf/libbpf && \
|
||||
cd libbpf && \
|
||||
PREFIX=/usr/local make -C src install && \
|
||||
CC=clang-19 PREFIX=/usr/local make -C src install && \
|
||||
cd .. && \
|
||||
rm -rf libbpf
|
||||
|
||||
@@ -53,7 +56,7 @@ RUN git clone --recursive --shallow-submodules --depth 1 -b $NGHTTP2_BRANCH http
|
||||
--with-mruby \
|
||||
--enable-http3 --with-libbpf \
|
||||
--with-libbrotlienc --with-libbrotlidec \
|
||||
CC=clang CXX=clang++ \
|
||||
CC=clang-19 CXX=clang++-19 \
|
||||
LIBTOOL_LDFLAGS="-static-libtool-libs" \
|
||||
OPENSSL_LIBS="-l:libssl.a -l:libcrypto.a" \
|
||||
LIBEV_LIBS="-l:libev.a" \
|
||||
@@ -71,9 +74,6 @@ RUN git clone --recursive --shallow-submodules --depth 1 -b $NGHTTP2_BRANCH http
|
||||
|
||||
FROM gcr.io/distroless/base-nossl-debian12
|
||||
|
||||
COPY --from=build --link \
|
||||
/usr/local/share/nghttp2/ \
|
||||
/usr/local/share/nghttp2/
|
||||
COPY --from=build --link \
|
||||
/usr/local/bin/h2load \
|
||||
/usr/local/bin/nghttpx \
|
||||
|
||||
@@ -28,26 +28,26 @@
|
||||
*/
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif /* HAVE_CONFIG_H */
|
||||
#endif /* defined(HAVE_CONFIG_H) */
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <stdlib.h>
|
||||
#ifdef HAVE_UNISTD_H
|
||||
# include <unistd.h>
|
||||
#endif /* HAVE_UNISTD_H */
|
||||
#endif /* defined(HAVE_UNISTD_H) */
|
||||
#ifdef HAVE_FCNTL_H
|
||||
# include <fcntl.h>
|
||||
#endif /* HAVE_FCNTL_H */
|
||||
#endif /* defined(HAVE_FCNTL_H) */
|
||||
#include <sys/types.h>
|
||||
#ifdef HAVE_SYS_SOCKET_H
|
||||
# include <sys/socket.h>
|
||||
#endif /* HAVE_SYS_SOCKET_H */
|
||||
#endif /* defined(HAVE_SYS_SOCKET_H) */
|
||||
#ifdef HAVE_NETDB_H
|
||||
# include <netdb.h>
|
||||
#endif /* HAVE_NETDB_H */
|
||||
#endif /* defined(HAVE_NETDB_H) */
|
||||
#ifdef HAVE_NETINET_IN_H
|
||||
# include <netinet/in.h>
|
||||
#endif /* HAVE_NETINET_IN_H */
|
||||
#endif /* defined(HAVE_NETINET_IN_H) */
|
||||
#include <netinet/tcp.h>
|
||||
#include <poll.h>
|
||||
#include <signal.h>
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
*/
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif /* !HAVE_CONFIG_H */
|
||||
#endif /* defined(HAVE_CONFIG_H) */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
@@ -31,26 +31,26 @@
|
||||
}
|
||||
# define warnx(format, args...) fprintf(stderr, format "\n", ##args)
|
||||
char *strndup(const char *s, size_t size);
|
||||
#endif
|
||||
#endif /* defined(__sgi) */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif /* HAVE_CONFIG_H */
|
||||
#endif /* defined(HAVE_CONFIG_H) */
|
||||
|
||||
#include <sys/types.h>
|
||||
#ifdef HAVE_UNISTD_H
|
||||
# include <unistd.h>
|
||||
#endif /* HAVE_UNISTD_H */
|
||||
#endif /* defined(HAVE_UNISTD_H) */
|
||||
#ifdef HAVE_SYS_SOCKET_H
|
||||
# include <sys/socket.h>
|
||||
#endif /* HAVE_SYS_SOCKET_H */
|
||||
#endif /* defined(HAVE_SYS_SOCKET_H) */
|
||||
#ifdef HAVE_NETINET_IN_H
|
||||
# include <netinet/in.h>
|
||||
#endif /* HAVE_NETINET_IN_H */
|
||||
#endif /* defined(HAVE_NETINET_IN_H) */
|
||||
#include <netinet/tcp.h>
|
||||
#ifndef __sgi
|
||||
# include <err.h>
|
||||
#endif
|
||||
#endif /* !defined(__sgi) */
|
||||
#include <signal.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
@@ -30,35 +30,35 @@
|
||||
}
|
||||
# define warn(format, args...) warnx(format ": %s", ##args, strerror(errno))
|
||||
# define warnx(format, args...) fprintf(stderr, format "\n", ##args)
|
||||
#endif
|
||||
#endif /* defined(__sgi) */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif /* HAVE_CONFIG_H */
|
||||
#endif /* defined(HAVE_CONFIG_H) */
|
||||
|
||||
#include <sys/types.h>
|
||||
#ifdef HAVE_SYS_SOCKET_H
|
||||
# include <sys/socket.h>
|
||||
#endif /* HAVE_SYS_SOCKET_H */
|
||||
#endif /* defined(HAVE_SYS_SOCKET_H) */
|
||||
#ifdef HAVE_NETDB_H
|
||||
# include <netdb.h>
|
||||
#endif /* HAVE_NETDB_H */
|
||||
#endif /* defined(HAVE_NETDB_H) */
|
||||
#include <signal.h>
|
||||
#ifdef HAVE_UNISTD_H
|
||||
# include <unistd.h>
|
||||
#endif /* HAVE_UNISTD_H */
|
||||
#endif /* defined(HAVE_UNISTD_H) */
|
||||
#include <sys/stat.h>
|
||||
#ifdef HAVE_FCNTL_H
|
||||
# include <fcntl.h>
|
||||
#endif /* HAVE_FCNTL_H */
|
||||
#endif /* defined(HAVE_FCNTL_H) */
|
||||
#include <ctype.h>
|
||||
#ifdef HAVE_NETINET_IN_H
|
||||
# include <netinet/in.h>
|
||||
#endif /* HAVE_NETINET_IN_H */
|
||||
#endif /* defined(HAVE_NETINET_IN_H) */
|
||||
#include <netinet/tcp.h>
|
||||
#ifndef __sgi
|
||||
# include <err.h>
|
||||
#endif
|
||||
#endif /* !defined(__sgi) */
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
@@ -136,11 +136,11 @@ static SSL_CTX *create_ssl_ctx(const char *key_file, const char *cert_file) {
|
||||
SSL_OP_NO_COMPRESSION |
|
||||
SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION);
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
|
||||
if (SSL_CTX_set1_curves_list(ssl_ctx, "P-256") != 1) {
|
||||
errx(1, "SSL_CTX_set1_curves_list failed: %s",
|
||||
if (SSL_CTX_set1_groups_list(ssl_ctx, "P-256") != 1) {
|
||||
errx(1, "SSL_CTX_set1_groups_list failed: %s",
|
||||
ERR_error_string(ERR_get_error(), NULL));
|
||||
}
|
||||
#else /* !(OPENSSL_VERSION_NUMBER >= 0x30000000L) */
|
||||
#else /* OPENSSL_VERSION_NUMBER < 0x30000000L */
|
||||
{
|
||||
EC_KEY *ecdh;
|
||||
ecdh = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
|
||||
@@ -151,7 +151,7 @@ static SSL_CTX *create_ssl_ctx(const char *key_file, const char *cert_file) {
|
||||
SSL_CTX_set_tmp_ecdh(ssl_ctx, ecdh);
|
||||
EC_KEY_free(ecdh);
|
||||
}
|
||||
#endif /* !(OPENSSL_VERSION_NUMBER >= 0x30000000L) */
|
||||
#endif /* OPENSSL_VERSION_NUMBER < 0x30000000L */
|
||||
|
||||
if (SSL_CTX_use_PrivateKey_file(ssl_ctx, key_file, SSL_FILETYPE_PEM) != 1) {
|
||||
errx(1, "Could not read private key file %s", key_file);
|
||||
@@ -727,7 +727,7 @@ static void start_listen(struct event_base *evbase, const char *service,
|
||||
hints.ai_flags = AI_PASSIVE;
|
||||
#ifdef AI_ADDRCONFIG
|
||||
hints.ai_flags |= AI_ADDRCONFIG;
|
||||
#endif /* AI_ADDRCONFIG */
|
||||
#endif /* defined(AI_ADDRCONFIG) */
|
||||
|
||||
rv = getaddrinfo(NULL, service, &hints, &res);
|
||||
if (rv != 0) {
|
||||
|
||||
@@ -204,6 +204,7 @@ OPTIONS = [
|
||||
"frontend-header-timeout",
|
||||
"frontend-http2-idle-timeout",
|
||||
"frontend-http3-idle-timeout",
|
||||
"groups",
|
||||
]
|
||||
|
||||
LOGVARS = [
|
||||
|
||||
@@ -35,7 +35,7 @@ enum {''')
|
||||
|
||||
def gen_index_header(tokens, prefix, comp_fun, return_type, fail_value):
|
||||
print('''\
|
||||
{} lookup_token(const StringRef &name) {{
|
||||
{} lookup_token(const std::string_view &name) {{
|
||||
switch (name.size()) {{'''.format(return_type))
|
||||
b = build_header(tokens)
|
||||
for size in sorted(b.keys()):
|
||||
@@ -50,7 +50,7 @@ def gen_index_header(tokens, prefix, comp_fun, return_type, fail_value):
|
||||
case '{}':'''.format(c))
|
||||
for k in headers:
|
||||
print('''\
|
||||
if ({}("{}"_sr, name, {})) {{
|
||||
if ({}("{}"sv, name.substr(0, {}))) {{
|
||||
return {};
|
||||
}}'''.format(comp_fun, k[:-1], size - 1, to_enum_hd(k, prefix)))
|
||||
print('''\
|
||||
|
||||
23
go.mod
23
go.mod
@@ -1,25 +1,20 @@
|
||||
module github.com/nghttp2/nghttp2
|
||||
|
||||
go 1.22.0
|
||||
go 1.24.0
|
||||
|
||||
require (
|
||||
github.com/bradfitz/gomemcache v0.0.0-20230905024940-24af94b03874
|
||||
github.com/quic-go/quic-go v0.49.0
|
||||
github.com/quic-go/quic-go v0.55.0
|
||||
github.com/tatsuhiro-t/go-nghttp2 v0.0.0-20240121064059-46ccb0a462a8
|
||||
golang.org/x/net v0.35.0
|
||||
golang.org/x/net v0.46.0
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect
|
||||
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 // indirect
|
||||
github.com/onsi/ginkgo/v2 v2.9.5 // indirect
|
||||
github.com/quic-go/qpack v0.5.1 // indirect
|
||||
go.uber.org/mock v0.5.0 // indirect
|
||||
golang.org/x/crypto v0.33.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842 // indirect
|
||||
golang.org/x/mod v0.18.0 // indirect
|
||||
golang.org/x/sync v0.11.0 // indirect
|
||||
golang.org/x/sys v0.30.0 // indirect
|
||||
golang.org/x/text v0.22.0 // indirect
|
||||
golang.org/x/tools v0.22.0 // indirect
|
||||
golang.org/x/crypto v0.43.0 // indirect
|
||||
golang.org/x/mod v0.28.0 // indirect
|
||||
golang.org/x/sync v0.17.0 // indirect
|
||||
golang.org/x/sys v0.37.0 // indirect
|
||||
golang.org/x/text v0.30.0 // indirect
|
||||
golang.org/x/tools v0.37.0 // indirect
|
||||
)
|
||||
|
||||
64
go.sum
64
go.sum
@@ -1,62 +1,34 @@
|
||||
github.com/bradfitz/gomemcache v0.0.0-20230905024940-24af94b03874 h1:N7oVaKyGp8bttX0bfZGmcGkjz7DLQXhAn3DNd3T0ous=
|
||||
github.com/bradfitz/gomemcache v0.0.0-20230905024940-24af94b03874/go.mod h1:r5xuitiExdLAJ09PR7vBVENGvp4ZuTBeWTGtxuX3K+c=
|
||||
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
||||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
|
||||
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ=
|
||||
github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI=
|
||||
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls=
|
||||
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
|
||||
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 h1:yAJXTCF9TqKcTiHJAE8dj7HMvPfh66eeA2JYW7eFpSE=
|
||||
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||
github.com/onsi/ginkgo/v2 v2.9.5 h1:+6Hr4uxzP4XIUyAkg61dWBw8lb/gc4/X5luuxN/EC+Q=
|
||||
github.com/onsi/ginkgo/v2 v2.9.5/go.mod h1:tvAoo1QUJwNEU2ITftXTpR7R1RbCzoZUOs3RonqW57k=
|
||||
github.com/onsi/gomega v1.27.6 h1:ENqfyGeS5AX/rlXDd/ETokDz93u0YufY1Pgxuy/PvWE=
|
||||
github.com/onsi/gomega v1.27.6/go.mod h1:PIQNjfQwkP3aQAH7lf7j87O/5FiNr+ZR8+ipb+qQlhg=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/quic-go/qpack v0.5.1 h1:giqksBPnT/HDtZ6VhtFKgoLOWmlyo9Ei6u9PqzIMbhI=
|
||||
github.com/quic-go/qpack v0.5.1/go.mod h1:+PC4XFrEskIVkcLzpEkbLqq1uCoxPhQuvK5rH1ZgaEg=
|
||||
github.com/quic-go/quic-go v0.49.0 h1:w5iJHXwHxs1QxyBv1EHKuC50GX5to8mJAxvtnttJp94=
|
||||
github.com/quic-go/quic-go v0.49.0/go.mod h1:s2wDnmCdooUQBmQfpUSTCYBl1/D4FcqbULMMkASvR6s=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/quic-go/quic-go v0.55.0 h1:zccPQIqYCXDt5NmcEabyYvOnomjs8Tlwl7tISjJh9Mk=
|
||||
github.com/quic-go/quic-go v0.55.0/go.mod h1:DR51ilwU1uE164KuWXhinFcKWGlEjzys2l8zUl5Ss1U=
|
||||
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
||||
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/tatsuhiro-t/go-nghttp2 v0.0.0-20240121064059-46ccb0a462a8 h1:zKJxuRe+a0O34V81GAZWOrotuU6mveT30QLjJ7OPMMg=
|
||||
github.com/tatsuhiro-t/go-nghttp2 v0.0.0-20240121064059-46ccb0a462a8/go.mod h1:gTqc3Q4boc+cKRlSFywTYdX9t6VGRcsThlNIWwaL3Dc=
|
||||
go.uber.org/mock v0.5.0 h1:KAMbZvZPyBPWgD14IrIQ38QCyjwpvVVV6K/bHl1IwQU=
|
||||
go.uber.org/mock v0.5.0/go.mod h1:ge71pBPLYDk7QIi1LupWxdAykm7KIEFchiOqd6z7qMM=
|
||||
golang.org/x/crypto v0.33.0 h1:IOBPskki6Lysi0lo9qQvbxiQ+FvsCC/YWOecCHAixus=
|
||||
golang.org/x/crypto v0.33.0/go.mod h1:bVdXmD7IV/4GdElGPozy6U7lWdRXA4qyRVGJV57uQ5M=
|
||||
golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842 h1:vr/HnozRka3pE4EsMEg1lgkXJkTFJCVUX+S/ZT6wYzM=
|
||||
golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842/go.mod h1:XtvwrStGgqGPLc4cjQfWqZHG1YFdYs6swckp8vpsjnc=
|
||||
golang.org/x/mod v0.18.0 h1:5+9lSbEzPSdWkH32vYPBwEpX8KwDbM52Ud9xBUvNlb0=
|
||||
golang.org/x/mod v0.18.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||
golang.org/x/net v0.35.0 h1:T5GQRQb2y08kTAByq9L4/bz8cipCdA8FbRTXewonqY8=
|
||||
golang.org/x/net v0.35.0/go.mod h1:EglIi67kWsHKlRzzVMUD93VMSWGFOMSZgxFjparz1Qk=
|
||||
golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w=
|
||||
golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc=
|
||||
golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM=
|
||||
golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY=
|
||||
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
|
||||
golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
||||
golang.org/x/tools v0.22.0 h1:gqSGLZqv+AI9lIQzniJ0nZDRG5GBPsSi+DRNHWNz6yA=
|
||||
golang.org/x/tools v0.22.0/go.mod h1:aCwcsjqvq7Yqt6TNyX7QMU2enbQ/Gt0bo6krSeEri+c=
|
||||
google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI=
|
||||
google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
go.uber.org/mock v0.5.2 h1:LbtPTcP8A5k9WPXj54PPPbjcI4Y6lhyOZXn+VS7wNko=
|
||||
go.uber.org/mock v0.5.2/go.mod h1:wLlUxC2vVTPTaE3UD51E0BGOAElKrILxhVSDYQLld5o=
|
||||
golang.org/x/crypto v0.43.0 h1:dduJYIi3A3KOfdGOHX8AVZ/jGiyPa3IbBozJ5kNuE04=
|
||||
golang.org/x/crypto v0.43.0/go.mod h1:BFbav4mRNlXJL4wNeejLpWxB7wMbc79PdRGhWKncxR0=
|
||||
golang.org/x/mod v0.28.0 h1:gQBtGhjxykdjY9YhZpSlZIsbnaE2+PgjfLWUQTnoZ1U=
|
||||
golang.org/x/mod v0.28.0/go.mod h1:yfB/L0NOf/kmEbXjzCPOx1iK1fRutOydrCMsqRhEBxI=
|
||||
golang.org/x/net v0.46.0 h1:giFlY12I07fugqwPuWJi68oOnpfqFnJIJzaIIm2JVV4=
|
||||
golang.org/x/net v0.46.0/go.mod h1:Q9BGdFy1y4nkUwiLvT5qtyhAnEHgnQ/zd8PfU6nc210=
|
||||
golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug=
|
||||
golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
|
||||
golang.org/x/sys v0.37.0 h1:fdNQudmxPjkdUTPnLn5mdQv7Zwvbvpaxqs831goi9kQ=
|
||||
golang.org/x/sys v0.37.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
||||
golang.org/x/text v0.30.0 h1:yznKA/E9zq54KzlzBEAWn1NXSQ8DIp/NYMy88xJjl4k=
|
||||
golang.org/x/text v0.30.0/go.mod h1:yDdHFIX9t+tORqspjENWgzaCVXgk0yYnYuSZ8UzzBVM=
|
||||
golang.org/x/tools v0.37.0 h1:DVSRzp7FwePZW356yEAChSdNcQo6Nsp+fex1SUW09lE=
|
||||
golang.org/x/tools v0.37.0/go.mod h1:MBN5QPQtLMHVdvsbtarmTNukZDdgwdwlO5qGacAzF0w=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
|
||||
@@ -882,12 +882,39 @@ func TestH1H1CONNECTMethodFailure(t *testing.T) {
|
||||
if _, err := io.ReadAll(resp.Body); err != nil {
|
||||
t.Fatalf("Error io.ReadAll() = %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
if _, err := io.WriteString(st.conn, "CONNECT 127.0.0.1:443 HTTP/1.1\r\nTest-Case: TestH1H1CONNECTMethodFailure\r\nHost: 127.0.0.1:443\r\nrequired-header: foo\r\n\r\n"); err != nil {
|
||||
// TestH1H1CONNECTMethod tests that CONNECT request succeeds.
|
||||
func TestH1H1CONNECTMethod(t *testing.T) {
|
||||
opts := options{
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
hj, ok := w.(http.Hijacker)
|
||||
if !ok {
|
||||
http.Error(w, "Could not hijack the connection", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
_, bufrw, err := hj.Hijack()
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
if _, err := bufrw.WriteString("HTTP/1.1 200\r\n\r\n"); err != nil {
|
||||
t.Fatalf("Error bufrw.WriteString() = %v", err)
|
||||
}
|
||||
|
||||
bufrw.Flush()
|
||||
},
|
||||
}
|
||||
|
||||
st := newServerTester(t, opts)
|
||||
defer st.Close()
|
||||
|
||||
if _, err := io.WriteString(st.conn, "CONNECT 127.0.0.1:443 HTTP/1.1\r\nTest-Case: TestH1H1CONNECTMethod\r\nHost: 127.0.0.1:443\r\n\r\n"); err != nil {
|
||||
t.Fatalf("Error io.WriteString() = %v", err)
|
||||
}
|
||||
|
||||
resp, err = http.ReadResponse(bufio.NewReader(st.conn), nil)
|
||||
resp, err := http.ReadResponse(bufio.NewReader(st.conn), nil)
|
||||
if err != nil {
|
||||
t.Fatalf("Error http.ReadResponse() = %v", err)
|
||||
}
|
||||
|
||||
@@ -1334,7 +1334,6 @@ func TestH2H1Upgrade(t *testing.T) {
|
||||
pair("HTTP2-Settings", "AAMAAABkAAQAAP__"),
|
||||
},
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
t.Fatalf("Error st.http1() = %v", err)
|
||||
}
|
||||
|
||||
@@ -161,7 +161,7 @@ func newServerTester(t *testing.T, opts options) *serverTester {
|
||||
b := "-b"
|
||||
|
||||
if !externalDNS {
|
||||
b += fmt.Sprintf("%v;", strings.Replace(backendURL.Host, ":", ",", -1))
|
||||
b += fmt.Sprintf("%v;", strings.ReplaceAll(backendURL.Host, ":", ","))
|
||||
} else {
|
||||
sep := strings.LastIndex(backendURL.Host, ":")
|
||||
if sep == -1 {
|
||||
@@ -170,6 +170,8 @@ func newServerTester(t *testing.T, opts options) *serverTester {
|
||||
|
||||
// We use awesome service nip.io.
|
||||
b += fmt.Sprintf("%v.nip.io,%v;", backendURL.Host[:sep], backendURL.Host[sep+1:])
|
||||
// Make external DNS tests less flaky.
|
||||
args = append(args, "--backend-address-family=IPv4")
|
||||
}
|
||||
|
||||
if backendTLS {
|
||||
@@ -206,7 +208,19 @@ func newServerTester(t *testing.T, opts options) *serverTester {
|
||||
if opts.quic {
|
||||
args = append(args,
|
||||
fmt.Sprintf("-f127.0.0.1,%v;quic", serverPort),
|
||||
"--no-quic-bpf")
|
||||
"--no-quic-bpf",
|
||||
// quic-go client just closes connection after
|
||||
// receiving the first GOAWAY without any
|
||||
// indication like sending CONNECTION_CLOSE if
|
||||
// there is no active stream. If that
|
||||
// happens, server keeps resending 2nd GOAWAY
|
||||
// until idle timeout passes. If that happens
|
||||
// during Close(), the process will be killed
|
||||
// because the default idle timeout is longer
|
||||
// than the close timeout. Shorten the idle
|
||||
// timeout to prevent it from happening.
|
||||
"--frontend-quic-idle-timeout=5",
|
||||
)
|
||||
}
|
||||
|
||||
authority := fmt.Sprintf("127.0.0.1:%v", opts.connectPort)
|
||||
@@ -309,14 +323,14 @@ func (st *serverTester) Close() {
|
||||
close(done)
|
||||
}()
|
||||
|
||||
if err := st.cmd.Process.Signal(syscall.SIGQUIT); err != nil {
|
||||
if err := st.cmd.Process.Signal(syscall.SIGQUIT); err != nil && !errors.Is(err, os.ErrProcessDone) {
|
||||
st.t.Errorf("Error st.cmd.Process.Signal() = %v", err)
|
||||
}
|
||||
|
||||
select {
|
||||
case <-done:
|
||||
case <-time.After(10 * time.Second):
|
||||
if err := st.cmd.Process.Kill(); err != nil {
|
||||
if err := st.cmd.Process.Kill(); err != nil && !errors.Is(err, os.ErrProcessDone) {
|
||||
st.t.Errorf("Error st.cmd.Process.Kill() = %v", err)
|
||||
}
|
||||
|
||||
@@ -631,7 +645,7 @@ loop:
|
||||
return res, err
|
||||
}
|
||||
|
||||
sr, ok := streams[f.FrameHeader.StreamID]
|
||||
sr, ok := streams[f.StreamID]
|
||||
if !ok {
|
||||
st.header = make(http.Header)
|
||||
break
|
||||
@@ -643,7 +657,7 @@ loop:
|
||||
|
||||
status, err = strconv.Atoi(sr.header.Get(":status"))
|
||||
if err != nil {
|
||||
return res, fmt.Errorf("Error parsing status code: %w", err)
|
||||
return res, fmt.Errorf("could not parse :status: %w", err)
|
||||
}
|
||||
|
||||
sr.status = status
|
||||
@@ -664,7 +678,7 @@ loop:
|
||||
|
||||
streams[sr.streamID] = sr
|
||||
case *http2.DataFrame:
|
||||
sr, ok := streams[f.FrameHeader.StreamID]
|
||||
sr, ok := streams[f.StreamID]
|
||||
if !ok {
|
||||
break
|
||||
}
|
||||
@@ -675,7 +689,7 @@ loop:
|
||||
break loop
|
||||
}
|
||||
case *http2.RSTStreamFrame:
|
||||
sr, ok := streams[f.FrameHeader.StreamID]
|
||||
sr, ok := streams[f.StreamID]
|
||||
if !ok {
|
||||
break
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ import (
|
||||
)
|
||||
|
||||
func (st *serverTester) http3(rp requestParam) (*serverResponse, error) {
|
||||
rt := &http3.RoundTripper{
|
||||
rt := &http3.Transport{
|
||||
TLSClientConfig: &tls.Config{
|
||||
InsecureSkipVerify: true,
|
||||
},
|
||||
|
||||
@@ -47,7 +47,29 @@ if(WIN32)
|
||||
set(NGHTTP2_RES ${CMAKE_CURRENT_BINARY_DIR}/version.rc)
|
||||
endif()
|
||||
|
||||
set(EXPORT_SET "${PROJECT_NAME}-targets")
|
||||
set(NGHTTP2_GENERATED_DIR "${CMAKE_CURRENT_BINARY_DIR}/generated")
|
||||
set(NGHTTP2_VERSION_CONFIG "${NGHTTP2_GENERATED_DIR}/${PROJECT_NAME}ConfigVersion.cmake")
|
||||
set(NGHTTP2_PROJECT_CONFIG "${NGHTTP2_GENERATED_DIR}/${PROJECT_NAME}Config.cmake")
|
||||
set(NGHTTP2_TARGETS_EXPORT_NAME "${PROJECT_NAME}Targets")
|
||||
set(NGHTTP2_CONFIG_INSTALL_DIR "lib/cmake/${PROJECT_NAME}")
|
||||
set(NGHTTP2_NAMESPACE "${PROJECT_NAME}::")
|
||||
set(NGHTTP2_VERSION ${PROJECT_VERSION})
|
||||
|
||||
include(CMakePackageConfigHelpers)
|
||||
write_basic_package_version_file(
|
||||
"${NGHTTP2_VERSION_CONFIG}" VERSION ${NGHTTP2_VERSION} COMPATIBILITY SameMajorVersion
|
||||
)
|
||||
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/config.cmake.in" "${NGHTTP2_PROJECT_CONFIG}" @ONLY)
|
||||
|
||||
# Install cmake config files
|
||||
install(
|
||||
FILES "${NGHTTP2_PROJECT_CONFIG}" "${NGHTTP2_VERSION_CONFIG}"
|
||||
DESTINATION "${NGHTTP2_CONFIG_INSTALL_DIR}")
|
||||
|
||||
install(
|
||||
EXPORT "${NGHTTP2_TARGETS_EXPORT_NAME}"
|
||||
NAMESPACE "${NGHTTP2_NAMESPACE}"
|
||||
DESTINATION "${NGHTTP2_CONFIG_INSTALL_DIR}")
|
||||
|
||||
# Public shared library
|
||||
if(BUILD_SHARED_LIBS)
|
||||
@@ -65,7 +87,11 @@ if(BUILD_SHARED_LIBS)
|
||||
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
|
||||
)
|
||||
|
||||
install(TARGETS ${SHARED_LIB} EXPORT ${EXPORT_SET})
|
||||
install(TARGETS ${SHARED_LIB}
|
||||
EXPORT ${NGHTTP2_TARGETS_EXPORT_NAME}
|
||||
ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}"
|
||||
LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}"
|
||||
RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}")
|
||||
list(APPEND nghttp2_exports ${SHARED_LIB})
|
||||
endif()
|
||||
|
||||
@@ -87,7 +113,9 @@ if(BUILD_STATIC_LIBS)
|
||||
|
||||
target_compile_definitions(${STATIC_LIB} PUBLIC "-DNGHTTP2_STATICLIB")
|
||||
|
||||
install(TARGETS ${STATIC_LIB} EXPORT ${EXPORT_SET})
|
||||
install(TARGETS ${STATIC_LIB}
|
||||
EXPORT ${NGHTTP2_TARGETS_EXPORT_NAME}
|
||||
ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}")
|
||||
list(APPEND nghttp2_exports ${STATIC_LIB})
|
||||
endif()
|
||||
|
||||
@@ -97,11 +125,7 @@ else()
|
||||
set(LIB_SELECTED ${STATIC_LIB})
|
||||
endif()
|
||||
|
||||
add_library(${PROJECT_NAME}::nghttp2 ALIAS ${LIB_SELECTED})
|
||||
add_library(nghttp2 ALIAS ${LIB_SELECTED})
|
||||
|
||||
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/libnghttp2.pc"
|
||||
DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig")
|
||||
|
||||
install(EXPORT ${EXPORT_SET}
|
||||
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}
|
||||
NAMESPACE ${PROJECT_NAME}::)
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
SUBDIRS = includes
|
||||
|
||||
EXTRA_DIST = Makefile.msvc CMakeLists.txt version.rc.in
|
||||
EXTRA_DIST = Makefile.msvc CMakeLists.txt version.rc.in config.cmake.in
|
||||
|
||||
AM_CFLAGS = $(WARNCFLAGS) $(EXTRACFLAG)
|
||||
AM_CPPFLAGS = -I$(srcdir)/includes -I$(builddir)/includes -DBUILDING_NGHTTP2 \
|
||||
|
||||
3
lib/config.cmake.in
Normal file
3
lib/config.cmake.in
Normal file
@@ -0,0 +1,3 @@
|
||||
include(CMakeFindDependencyMacro)
|
||||
|
||||
include("${CMAKE_CURRENT_LIST_DIR}/@NGHTTP2_TARGETS_EXPORT_NAME@.cmake")
|
||||
@@ -2039,18 +2039,19 @@ typedef int (*nghttp2_on_header_callback2)(nghttp2_session *session,
|
||||
/**
|
||||
* @functypedef
|
||||
*
|
||||
* Callback function invoked when a invalid header name/value pair is
|
||||
* Callback function invoked when an invalid header name/value pair is
|
||||
* received for the |frame|.
|
||||
*
|
||||
* The parameter and behaviour are similar to
|
||||
* :type:`nghttp2_on_header_callback`. The difference is that this
|
||||
* callback is only invoked when a invalid header name/value pair is
|
||||
* received which is treated as stream error if this callback is not
|
||||
* set. Only invalid regular header field are passed to this
|
||||
* callback. In other words, invalid pseudo header field is not
|
||||
* passed to this callback. Also header fields which includes upper
|
||||
* cased latter are also treated as error without passing them to this
|
||||
* callback.
|
||||
* callback is only invoked when an invalid header name/value pair is
|
||||
* received which is treated as stream error if this callback returns
|
||||
* :enum:`nghttp2_error.NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE` and
|
||||
* :type:`nghttp2_on_invalid_header_callback2` is not set. Only
|
||||
* invalid regular header field are passed to this callback. In other
|
||||
* words, invalid pseudo header field is not passed to this callback.
|
||||
* Also header fields which includes upper cased latter are also
|
||||
* treated as error without passing them to this callback.
|
||||
*
|
||||
* This callback is only considered if HTTP messaging validation is
|
||||
* turned on (which is on by default, see
|
||||
@@ -2076,17 +2077,18 @@ typedef int (*nghttp2_on_invalid_header_callback)(
|
||||
/**
|
||||
* @functypedef
|
||||
*
|
||||
* Callback function invoked when a invalid header name/value pair is
|
||||
* Callback function invoked when an invalid header name/value pair is
|
||||
* received for the |frame|.
|
||||
*
|
||||
* The parameter and behaviour are similar to
|
||||
* :type:`nghttp2_on_header_callback2`. The difference is that this
|
||||
* callback is only invoked when a invalid header name/value pair is
|
||||
* received which is silently ignored if this callback is not set.
|
||||
* Only invalid regular header field are passed to this callback. In
|
||||
* other words, invalid pseudo header field is not passed to this
|
||||
* callback. Also header fields which includes upper cased latter are
|
||||
* also treated as error without passing them to this callback.
|
||||
* callback is only invoked when an invalid header name/value pair is
|
||||
* received which is silently ignored if neither this callback nor
|
||||
* :type:`nghttp2_on_invalid_header_callback` is set. Only invalid
|
||||
* regular header field are passed to this callback. In other words,
|
||||
* invalid pseudo header field is not passed to this callback. Also
|
||||
* header fields which includes upper cased latter are also treated as
|
||||
* error without passing them to this callback.
|
||||
*
|
||||
* This callback is only considered if HTTP messaging validation is
|
||||
* turned on (which is on by default, see
|
||||
@@ -2445,6 +2447,15 @@ typedef int (*nghttp2_error_callback2)(nghttp2_session *session,
|
||||
int lib_error_code, const char *msg,
|
||||
size_t len, void *user_data);
|
||||
|
||||
/**
|
||||
* @functypedef
|
||||
*
|
||||
* Callback function invoked when unpredictable data of |destlen|
|
||||
* bytes are needed. The implementation must write unpredictable data
|
||||
* of |destlen| bytes into the buffer pointed by |dest|.
|
||||
*/
|
||||
typedef void (*nghttp2_rand_callback)(uint8_t *dest, size_t destlen);
|
||||
|
||||
struct nghttp2_session_callbacks;
|
||||
|
||||
/**
|
||||
@@ -2649,7 +2660,7 @@ NGHTTP2_EXTERN void nghttp2_session_callbacks_set_on_header_callback2(
|
||||
/**
|
||||
* @function
|
||||
*
|
||||
* Sets callback function invoked when a invalid header name/value
|
||||
* Sets callback function invoked when an invalid header name/value
|
||||
* pair is received. If both
|
||||
* `nghttp2_session_callbacks_set_on_invalid_header_callback()` and
|
||||
* `nghttp2_session_callbacks_set_on_invalid_header_callback2()` are
|
||||
@@ -2662,7 +2673,7 @@ NGHTTP2_EXTERN void nghttp2_session_callbacks_set_on_invalid_header_callback(
|
||||
/**
|
||||
* @function
|
||||
*
|
||||
* Sets callback function invoked when a invalid header name/value
|
||||
* Sets callback function invoked when an invalid header name/value
|
||||
* pair is received.
|
||||
*/
|
||||
NGHTTP2_EXTERN void nghttp2_session_callbacks_set_on_invalid_header_callback2(
|
||||
@@ -2833,6 +2844,18 @@ NGHTTP2_EXTERN void nghttp2_session_callbacks_set_error_callback(
|
||||
NGHTTP2_EXTERN void nghttp2_session_callbacks_set_error_callback2(
|
||||
nghttp2_session_callbacks *cbs, nghttp2_error_callback2 error_callback2);
|
||||
|
||||
/**
|
||||
* @function
|
||||
*
|
||||
* Sets callback function invoked when unpredictable data is needed.
|
||||
* Although this callback is optional due to the backward
|
||||
* compatibility, it is recommended to specify it to harden the
|
||||
* runtime behavior against suspicious activities of a remote
|
||||
* endpoint.
|
||||
*/
|
||||
NGHTTP2_EXTERN void nghttp2_session_callbacks_set_rand_callback(
|
||||
nghttp2_session_callbacks *cbs, nghttp2_rand_callback rand_callback);
|
||||
|
||||
/**
|
||||
* @functypedef
|
||||
*
|
||||
@@ -3218,6 +3241,23 @@ nghttp2_option_set_stream_reset_rate_limit(nghttp2_option *option,
|
||||
NGHTTP2_EXTERN void nghttp2_option_set_max_continuations(nghttp2_option *option,
|
||||
size_t val);
|
||||
|
||||
/**
|
||||
* @function
|
||||
*
|
||||
* This function sets the rate limit for the "glitches", the
|
||||
* suspicious activities from a remote endpoint. It is a token-bucket
|
||||
* based rate limiter. |burst| specifies the number of tokens that is
|
||||
* initially available. The maximum number of tokens is capped to
|
||||
* this value. |rate| specifies the number of tokens that are
|
||||
* regenerated per second. When a suspicious activity is detected,
|
||||
* some amount of tokens are consumed. If there is no token
|
||||
* available, GOAWAY is sent to tear down the connection. |burst| and
|
||||
* |rate| default to 1000 and 33 respectively.
|
||||
*/
|
||||
NGHTTP2_EXTERN void nghttp2_option_set_glitch_rate_limit(nghttp2_option *option,
|
||||
uint64_t burst,
|
||||
uint64_t rate);
|
||||
|
||||
/**
|
||||
* @function
|
||||
*
|
||||
|
||||
@@ -27,8 +27,8 @@
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif /* HAVE_CONFIG_H */
|
||||
#endif /* defined(HAVE_CONFIG_H) */
|
||||
|
||||
#include <nghttp2/nghttp2.h>
|
||||
|
||||
#endif /* NGHTTP2_ALPN_H */
|
||||
#endif /* !defined(NGHTTP2_ALPN_H) */
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif /* HAVE_CONFIG_H */
|
||||
#endif /* defined(HAVE_CONFIG_H) */
|
||||
|
||||
#include <nghttp2/nghttp2.h>
|
||||
|
||||
@@ -409,4 +409,4 @@ int nghttp2_bufs_next_present(nghttp2_bufs *bufs);
|
||||
*/
|
||||
size_t nghttp2_bufs_len(nghttp2_bufs *bufs);
|
||||
|
||||
#endif /* NGHTTP2_BUF_H */
|
||||
#endif /* !defined(NGHTTP2_BUF_H) */
|
||||
|
||||
@@ -201,3 +201,8 @@ void nghttp2_session_callbacks_set_error_callback2(
|
||||
nghttp2_session_callbacks *cbs, nghttp2_error_callback2 error_callback2) {
|
||||
cbs->error_callback2 = error_callback2;
|
||||
}
|
||||
|
||||
void nghttp2_session_callbacks_set_rand_callback(
|
||||
nghttp2_session_callbacks *cbs, nghttp2_rand_callback rand_callback) {
|
||||
cbs->rand_callback = rand_callback;
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif /* HAVE_CONFIG_H */
|
||||
#endif /* defined(HAVE_CONFIG_H) */
|
||||
|
||||
#include <nghttp2/nghttp2.h>
|
||||
|
||||
@@ -151,6 +151,7 @@ struct nghttp2_session_callbacks {
|
||||
nghttp2_on_extension_chunk_recv_callback on_extension_chunk_recv_callback;
|
||||
nghttp2_error_callback error_callback;
|
||||
nghttp2_error_callback2 error_callback2;
|
||||
nghttp2_rand_callback rand_callback;
|
||||
};
|
||||
|
||||
#endif /* NGHTTP2_CALLBACKS_H */
|
||||
#endif /* !defined(NGHTTP2_CALLBACKS_H) */
|
||||
|
||||
@@ -50,11 +50,11 @@ void nghttp2_set_debug_vprintf_callback(
|
||||
static_debug_vprintf_callback = debug_vprintf_callback;
|
||||
}
|
||||
|
||||
#else /* !DEBUGBUILD */
|
||||
#else /* !defined(DEBUGBUILD) */
|
||||
|
||||
void nghttp2_set_debug_vprintf_callback(
|
||||
nghttp2_debug_vprintf_callback debug_vprintf_callback) {
|
||||
(void)debug_vprintf_callback;
|
||||
}
|
||||
|
||||
#endif /* !DEBUGBUILD */
|
||||
#endif /* !defined(DEBUGBUILD) */
|
||||
|
||||
@@ -27,17 +27,17 @@
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif /* HAVE_CONFIG_H */
|
||||
#endif /* defined(HAVE_CONFIG_H) */
|
||||
|
||||
#include <nghttp2/nghttp2.h>
|
||||
|
||||
#ifdef DEBUGBUILD
|
||||
# define DEBUGF(...) nghttp2_debug_vprintf(__VA_ARGS__)
|
||||
void nghttp2_debug_vprintf(const char *format, ...);
|
||||
#else
|
||||
#else /* !defined(DEBUGBUILD) */
|
||||
# define DEBUGF(...) \
|
||||
do { \
|
||||
} while (0)
|
||||
#endif
|
||||
#endif /* !defined(DEBUGBUILD) */
|
||||
|
||||
#endif /* NGHTTP2_DEBUG_H */
|
||||
#endif /* !defined(NGHTTP2_DEBUG_H) */
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif /* HAVE_CONFIG_H */
|
||||
#endif /* defined(HAVE_CONFIG_H) */
|
||||
|
||||
#include <nghttp2/nghttp2.h>
|
||||
|
||||
@@ -62,4 +62,4 @@ void nghttp2_extpri_from_uint8(nghttp2_extpri *extpri, uint8_t u8extpri);
|
||||
*/
|
||||
#define nghttp2_extpri_uint8_inc(PRI) (((PRI) & NGHTTP2_EXTPRI_INC_MASK) != 0)
|
||||
|
||||
#endif /* NGHTTP2_EXTPRI_H */
|
||||
#endif /* !defined(NGHTTP2_EXTPRI_H) */
|
||||
|
||||
@@ -27,17 +27,14 @@
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif /* HAVE_CONFIG_H */
|
||||
#endif /* defined(HAVE_CONFIG_H) */
|
||||
|
||||
#include <nghttp2/nghttp2.h>
|
||||
#include "nghttp2_hd.h"
|
||||
#include "nghttp2_buf.h"
|
||||
|
||||
#define NGHTTP2_STREAM_ID_MASK ((1u << 31) - 1)
|
||||
#define NGHTTP2_PRI_GROUP_ID_MASK ((1u << 31) - 1)
|
||||
#define NGHTTP2_PRIORITY_MASK ((1u << 31) - 1)
|
||||
#define NGHTTP2_WINDOW_SIZE_INCREMENT_MASK ((1u << 31) - 1)
|
||||
#define NGHTTP2_SETTINGS_ID_MASK ((1 << 24) - 1)
|
||||
|
||||
/* The number of bytes of frame header. */
|
||||
#define NGHTTP2_FRAME_HDLEN 9
|
||||
@@ -634,4 +631,4 @@ int nghttp2_iv_check(const nghttp2_settings_entry *iv, size_t niv);
|
||||
void nghttp2_frame_add_pad(nghttp2_bufs *bufs, nghttp2_frame_hd *hd,
|
||||
size_t padlen, int framehd_only);
|
||||
|
||||
#endif /* NGHTTP2_FRAME_H */
|
||||
#endif /* !defined(NGHTTP2_FRAME_H) */
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif /* HAVE_CONFIG_H */
|
||||
#endif /* defined(HAVE_CONFIG_H) */
|
||||
|
||||
#include <nghttp2/nghttp2.h>
|
||||
|
||||
@@ -439,4 +439,4 @@ nghttp2_ssize nghttp2_hd_huff_decode(nghttp2_hd_huff_decode_context *ctx,
|
||||
*/
|
||||
int nghttp2_hd_huff_decode_failure_state(nghttp2_hd_huff_decode_context *ctx);
|
||||
|
||||
#endif /* NGHTTP2_HD_H */
|
||||
#endif /* !defined(NGHTTP2_HD_H) */
|
||||
|
||||
@@ -104,15 +104,15 @@ int nghttp2_hd_huff_encode(nghttp2_bufs *bufs, const uint8_t *src,
|
||||
}
|
||||
|
||||
void nghttp2_hd_huff_decode_context_init(nghttp2_hd_huff_decode_context *ctx) {
|
||||
ctx->fstate = NGHTTP2_HUFF_ACCEPTED;
|
||||
ctx->fstate = 0;
|
||||
ctx->flags = NGHTTP2_HUFF_ACCEPTED;
|
||||
}
|
||||
|
||||
nghttp2_ssize nghttp2_hd_huff_decode(nghttp2_hd_huff_decode_context *ctx,
|
||||
nghttp2_buf *buf, const uint8_t *src,
|
||||
size_t srclen, int final) {
|
||||
const uint8_t *end = src + srclen;
|
||||
nghttp2_huff_decode node = {ctx->fstate, 0};
|
||||
const nghttp2_huff_decode *t = &node;
|
||||
nghttp2_huff_decode t = {ctx->fstate, ctx->flags, 0};
|
||||
uint8_t c;
|
||||
|
||||
/* We use the decoding algorithm described in
|
||||
@@ -121,20 +121,21 @@ nghttp2_ssize nghttp2_hd_huff_decode(nghttp2_hd_huff_decode_context *ctx,
|
||||
- https://github.com/nghttp2/nghttp2/files/15141264/Prefix.pdf */
|
||||
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.fstate][c >> 4];
|
||||
if (t.flags & NGHTTP2_HUFF_SYM) {
|
||||
*buf->last++ = t.sym;
|
||||
}
|
||||
|
||||
t = &huff_decode_table[t->fstate & 0x1ff][c & 0xf];
|
||||
if (t->fstate & NGHTTP2_HUFF_SYM) {
|
||||
*buf->last++ = t->sym;
|
||||
t = huff_decode_table[t.fstate][c & 0xf];
|
||||
if (t.flags & NGHTTP2_HUFF_SYM) {
|
||||
*buf->last++ = t.sym;
|
||||
}
|
||||
}
|
||||
|
||||
ctx->fstate = t->fstate;
|
||||
ctx->fstate = t.fstate;
|
||||
ctx->flags = t.flags;
|
||||
|
||||
if (final && !(ctx->fstate & NGHTTP2_HUFF_ACCEPTED)) {
|
||||
if (final && !(ctx->flags & NGHTTP2_HUFF_ACCEPTED)) {
|
||||
return NGHTTP2_ERR_HEADER_COMP;
|
||||
}
|
||||
|
||||
|
||||
@@ -27,16 +27,16 @@
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif /* HAVE_CONFIG_H */
|
||||
#endif /* defined(HAVE_CONFIG_H) */
|
||||
|
||||
#include <nghttp2/nghttp2.h>
|
||||
|
||||
typedef enum {
|
||||
/* FSA accepts this state as the end of huffman encoding
|
||||
sequence. */
|
||||
NGHTTP2_HUFF_ACCEPTED = 1 << 14,
|
||||
NGHTTP2_HUFF_ACCEPTED = 1,
|
||||
/* This state emits symbol */
|
||||
NGHTTP2_HUFF_SYM = 1 << 15,
|
||||
NGHTTP2_HUFF_SYM = 1 << 1,
|
||||
} nghttp2_huff_decode_flag;
|
||||
|
||||
typedef struct {
|
||||
@@ -48,6 +48,7 @@ typedef struct {
|
||||
a special node and it is a terminal state that means decoding
|
||||
failed. */
|
||||
uint16_t fstate;
|
||||
uint8_t flags;
|
||||
/* symbol if NGHTTP2_HUFF_SYM flag set */
|
||||
uint8_t sym;
|
||||
} nghttp2_huff_decode;
|
||||
@@ -57,6 +58,7 @@ typedef nghttp2_huff_decode huff_decode_table_type[16];
|
||||
typedef struct {
|
||||
/* fstate is the current huffman decoding state. */
|
||||
uint16_t fstate;
|
||||
uint8_t flags;
|
||||
} nghttp2_hd_huff_decode_context;
|
||||
|
||||
typedef struct {
|
||||
@@ -69,4 +71,4 @@ typedef struct {
|
||||
extern const nghttp2_huff_sym huff_sym_table[];
|
||||
extern const nghttp2_huff_decode huff_decode_table[][16];
|
||||
|
||||
#endif /* NGHTTP2_HD_HUFFMAN_H */
|
||||
#endif /* !defined(NGHTTP2_HD_HUFFMAN_H) */
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -27,7 +27,7 @@
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif /* HAVE_CONFIG_H */
|
||||
#endif /* defined(HAVE_CONFIG_H) */
|
||||
|
||||
#include <string.h>
|
||||
#include <stddef.h>
|
||||
@@ -142,4 +142,4 @@ int nghttp2_should_send_window_update(int32_t local_window_size,
|
||||
*/
|
||||
uint8_t *nghttp2_cpymem(uint8_t *dest, const void *src, size_t len);
|
||||
|
||||
#endif /* NGHTTP2_HELPER_H */
|
||||
#endif /* !defined(NGHTTP2_HELPER_H) */
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif /* HAVE_CONFIG_H */
|
||||
#endif /* defined(HAVE_CONFIG_H) */
|
||||
|
||||
#include <nghttp2/nghttp2.h>
|
||||
#include "nghttp2_session.h"
|
||||
@@ -97,4 +97,4 @@ void nghttp2_http_record_request_method(nghttp2_stream *stream,
|
||||
int nghttp2_http_parse_priority(nghttp2_extpri *dest, const uint8_t *value,
|
||||
size_t valuelen);
|
||||
|
||||
#endif /* NGHTTP2_HTTP_H */
|
||||
#endif /* !defined(NGHTTP2_HTTP_H) */
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif /* HAVE_CONFIG_H */
|
||||
#endif /* defined(HAVE_CONFIG_H) */
|
||||
|
||||
#include <nghttp2/nghttp2.h>
|
||||
|
||||
@@ -39,7 +39,6 @@ typedef int (*nghttp2_less)(const void *lhs, const void *rhs);
|
||||
/* Internal error code. They must be in the range [-499, -100],
|
||||
inclusive. */
|
||||
typedef enum {
|
||||
NGHTTP2_ERR_CREDENTIAL_PENDING = -101,
|
||||
NGHTTP2_ERR_IGN_HEADER_BLOCK = -103,
|
||||
NGHTTP2_ERR_IGN_PAYLOAD = -104,
|
||||
/*
|
||||
@@ -52,7 +51,11 @@ typedef enum {
|
||||
* Unlike NGHTTP2_ERR_IGN_HTTP_HEADER, this does not invoke
|
||||
* nghttp2_on_invalid_header_callback.
|
||||
*/
|
||||
NGHTTP2_ERR_REMOVE_HTTP_HEADER = -106
|
||||
NGHTTP2_ERR_REMOVE_HTTP_HEADER = -106,
|
||||
/*
|
||||
* Cancel pushed stream.
|
||||
*/
|
||||
NGHTTP2_ERR_PUSH_CANCEL = -107,
|
||||
} nghttp2_internal_error;
|
||||
|
||||
#endif /* NGHTTP2_INT_H */
|
||||
#endif /* !defined(NGHTTP2_INT_H) */
|
||||
|
||||
@@ -31,13 +31,13 @@
|
||||
|
||||
#include "nghttp2_helper.h"
|
||||
|
||||
#define NGHTTP2_INITIAL_TABLE_LENBITS 4
|
||||
#define NGHTTP2_INITIAL_HASHBITS 4
|
||||
|
||||
void nghttp2_map_init(nghttp2_map *map, nghttp2_mem *mem) {
|
||||
map->mem = mem;
|
||||
map->hashbits = 0;
|
||||
map->table = NULL;
|
||||
map->size = 0;
|
||||
void nghttp2_map_init(nghttp2_map *map, uint64_t seed, nghttp2_mem *mem) {
|
||||
*map = (nghttp2_map){
|
||||
.mem = mem,
|
||||
.seed = seed,
|
||||
};
|
||||
}
|
||||
|
||||
void nghttp2_map_free(nghttp2_map *map) {
|
||||
@@ -45,30 +45,27 @@ void nghttp2_map_free(nghttp2_map *map) {
|
||||
return;
|
||||
}
|
||||
|
||||
nghttp2_mem_free(map->mem, map->table);
|
||||
nghttp2_mem_free(map->mem, map->keys);
|
||||
}
|
||||
|
||||
int nghttp2_map_each(const nghttp2_map *map, int (*func)(void *data, void *ptr),
|
||||
void *ptr) {
|
||||
int rv;
|
||||
size_t i;
|
||||
nghttp2_map_bucket *bkt;
|
||||
size_t tablelen;
|
||||
|
||||
if (map->size == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
tablelen = 1u << map->hashbits;
|
||||
tablelen = (size_t)1 << map->hashbits;
|
||||
|
||||
for (i = 0; i < tablelen; ++i) {
|
||||
bkt = &map->table[i];
|
||||
|
||||
if (bkt->data == NULL) {
|
||||
if (map->psl[i] == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
rv = func(bkt->data, ptr);
|
||||
rv = func(map->data[i], ptr);
|
||||
if (rv != 0) {
|
||||
return rv;
|
||||
}
|
||||
@@ -77,164 +74,230 @@ int nghttp2_map_each(const nghttp2_map *map, int (*func)(void *data, void *ptr),
|
||||
return 0;
|
||||
}
|
||||
|
||||
static size_t hash(nghttp2_map_key_type key, size_t bits) {
|
||||
return (size_t)(((uint32_t)key * 2654435769u) >> (32 - bits));
|
||||
}
|
||||
/* Hasher from
|
||||
https://github.com/rust-lang/rustc-hash/blob/dc5c33f1283de2da64d8d7a06401d91aded03ad4/src/lib.rs
|
||||
to maximize the output's sensitivity to all input bits. */
|
||||
#define NGHTTP2_MAP_HASHER 0xf1357aea2e62a9c5ull
|
||||
/* 64-bit Fibonacci hashing constant, Golden Ratio constant, to get
|
||||
the high bits with the good distribution. */
|
||||
#define NGHTTP2_MAP_FIBO 0x9e3779b97f4a7c15ull
|
||||
|
||||
static void map_bucket_swap(nghttp2_map_bucket *a, nghttp2_map_bucket *b) {
|
||||
nghttp2_map_bucket c = *a;
|
||||
static size_t map_index(const nghttp2_map *map, nghttp2_map_key_type key32) {
|
||||
uint64_t key = (uint64_t)key32;
|
||||
|
||||
*a = *b;
|
||||
*b = c;
|
||||
key += map->seed;
|
||||
key *= NGHTTP2_MAP_HASHER;
|
||||
return (size_t)((key * NGHTTP2_MAP_FIBO) >> (64 - map->hashbits));
|
||||
}
|
||||
|
||||
#ifndef WIN32
|
||||
void nghttp2_map_print_distance(const nghttp2_map *map) {
|
||||
size_t i;
|
||||
size_t idx;
|
||||
nghttp2_map_bucket *bkt;
|
||||
size_t tablelen;
|
||||
|
||||
if (map->size == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
tablelen = 1u << map->hashbits;
|
||||
tablelen = (size_t)1 << map->hashbits;
|
||||
|
||||
for (i = 0; i < tablelen; ++i) {
|
||||
bkt = &map->table[i];
|
||||
|
||||
if (bkt->data == NULL) {
|
||||
if (map->psl[i] == 0) {
|
||||
fprintf(stderr, "@%zu <EMPTY>\n", i);
|
||||
continue;
|
||||
}
|
||||
|
||||
idx = hash(bkt->key, map->hashbits);
|
||||
fprintf(stderr, "@%zu hash=%zu key=%d base=%zu distance=%u\n", i,
|
||||
hash(bkt->key, map->hashbits), bkt->key, idx, bkt->psl);
|
||||
idx = map_index(map, map->keys[i]);
|
||||
fprintf(stderr, "@%zu key=%d base=%zu distance=%u\n", i, map->keys[i], idx,
|
||||
map->psl[i] - 1);
|
||||
}
|
||||
}
|
||||
#endif /* !WIN32 */
|
||||
#endif /* !defined(WIN32) */
|
||||
|
||||
static int insert(nghttp2_map_bucket *table, size_t hashbits,
|
||||
nghttp2_map_key_type key, void *data) {
|
||||
size_t idx = hash(key, hashbits);
|
||||
nghttp2_map_bucket b = {0, key, data}, *bkt;
|
||||
size_t mask = (1u << hashbits) - 1;
|
||||
static void map_set_entry(nghttp2_map *map, size_t idx,
|
||||
nghttp2_map_key_type key, void *data, size_t psl) {
|
||||
map->keys[idx] = key;
|
||||
map->data[idx] = data;
|
||||
map->psl[idx] = (uint8_t)psl;
|
||||
}
|
||||
|
||||
#define NGHTTP2_SWAP(TYPE, A, B) \
|
||||
do { \
|
||||
TYPE t = (TYPE) * (A); \
|
||||
\
|
||||
*(A) = *(B); \
|
||||
*(B) = t; \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* map_insert inserts |key| and |data| to |map|, and returns the index
|
||||
* where the pair is stored if it succeeds. Otherwise, it returns one
|
||||
* of the following negative error codes:
|
||||
*
|
||||
* NGHTTP2_ERR_INVALID_ARGUMENT
|
||||
* The another data associated to |key| is already present.
|
||||
*/
|
||||
static nghttp2_ssize map_insert(nghttp2_map *map, nghttp2_map_key_type key,
|
||||
void *data) {
|
||||
size_t idx = map_index(map, key);
|
||||
size_t mask = ((size_t)1 << map->hashbits) - 1;
|
||||
size_t psl = 1;
|
||||
size_t kpsl;
|
||||
|
||||
for (;;) {
|
||||
bkt = &table[idx];
|
||||
kpsl = map->psl[idx];
|
||||
|
||||
if (bkt->data == NULL) {
|
||||
*bkt = b;
|
||||
return 0;
|
||||
if (kpsl == 0) {
|
||||
map_set_entry(map, idx, key, data, psl);
|
||||
++map->size;
|
||||
|
||||
return (nghttp2_ssize)idx;
|
||||
}
|
||||
|
||||
if (b.psl > bkt->psl) {
|
||||
map_bucket_swap(bkt, &b);
|
||||
} else if (bkt->key == key) {
|
||||
/* TODO This check is just a waste after first swap or if this
|
||||
function is called from map_resize. That said, there is no
|
||||
difference with or without this conditional in performance
|
||||
wise. */
|
||||
if (psl > kpsl) {
|
||||
NGHTTP2_SWAP(nghttp2_map_key_type, &key, &map->keys[idx]);
|
||||
NGHTTP2_SWAP(void *, &data, &map->data[idx]);
|
||||
NGHTTP2_SWAP(uint8_t, &psl, &map->psl[idx]);
|
||||
} else if (map->keys[idx] == key) {
|
||||
/* This check ensures that no duplicate keys are inserted. But
|
||||
it is just a waste after first swap or if this function is
|
||||
called from map_resize. That said, there is no difference
|
||||
with or without this conditional in performance wise. */
|
||||
return NGHTTP2_ERR_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
++b.psl;
|
||||
++psl;
|
||||
idx = (idx + 1) & mask;
|
||||
}
|
||||
}
|
||||
|
||||
/* NGHTTP2_MAP_MAX_HASHBITS is the maximum number of bits used for
|
||||
hash table. The theoretical limit of the maximum number of keys
|
||||
that can be stored is 1 << NGHTTP2_MAP_MAX_HASHBITS. */
|
||||
#define NGHTTP2_MAP_MAX_HASHBITS (sizeof(size_t) * 8 - 1)
|
||||
|
||||
static int map_resize(nghttp2_map *map, size_t new_hashbits) {
|
||||
size_t i;
|
||||
nghttp2_map_bucket *new_table;
|
||||
nghttp2_map_bucket *bkt;
|
||||
size_t tablelen;
|
||||
int rv;
|
||||
(void)rv;
|
||||
nghttp2_ssize idx;
|
||||
nghttp2_map new_map = {
|
||||
.mem = map->mem,
|
||||
.seed = map->seed,
|
||||
.hashbits = new_hashbits,
|
||||
};
|
||||
void *buf;
|
||||
(void)idx;
|
||||
|
||||
new_table = nghttp2_mem_calloc(map->mem, 1u << new_hashbits,
|
||||
sizeof(nghttp2_map_bucket));
|
||||
if (new_table == NULL) {
|
||||
if (new_hashbits > NGHTTP2_MAP_MAX_HASHBITS) {
|
||||
return NGHTTP2_ERR_NOMEM;
|
||||
}
|
||||
|
||||
tablelen = (size_t)1 << new_hashbits;
|
||||
|
||||
buf = nghttp2_mem_calloc(map->mem, tablelen,
|
||||
sizeof(nghttp2_map_key_type) + sizeof(void *) +
|
||||
sizeof(uint8_t));
|
||||
if (buf == NULL) {
|
||||
return NGHTTP2_ERR_NOMEM;
|
||||
}
|
||||
|
||||
new_map.keys = buf;
|
||||
new_map.data =
|
||||
(void *)((uint8_t *)new_map.keys + tablelen * sizeof(nghttp2_map_key_type));
|
||||
new_map.psl = (uint8_t *)new_map.data + tablelen * sizeof(void *);
|
||||
|
||||
if (map->size) {
|
||||
tablelen = 1u << map->hashbits;
|
||||
tablelen = (size_t)1 << map->hashbits;
|
||||
|
||||
for (i = 0; i < tablelen; ++i) {
|
||||
bkt = &map->table[i];
|
||||
if (bkt->data == NULL) {
|
||||
if (map->psl[i] == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
rv = insert(new_table, new_hashbits, bkt->key, bkt->data);
|
||||
idx = map_insert(&new_map, map->keys[i], map->data[i]);
|
||||
|
||||
assert(0 == rv);
|
||||
/* map_insert must not fail because all keys are unique during
|
||||
resize. */
|
||||
assert(idx >= 0);
|
||||
}
|
||||
}
|
||||
|
||||
nghttp2_mem_free(map->mem, map->table);
|
||||
nghttp2_mem_free(map->mem, map->keys);
|
||||
map->keys = new_map.keys;
|
||||
map->data = new_map.data;
|
||||
map->psl = new_map.psl;
|
||||
map->hashbits = new_hashbits;
|
||||
map->table = new_table;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* NGHTTP2_MAX_PSL_RESIZE_THRESH is the maximum psl threshold. If
|
||||
reached, resize the table. */
|
||||
#define NGHTTP2_MAX_PSL_RESIZE_THRESH 128
|
||||
|
||||
int nghttp2_map_insert(nghttp2_map *map, nghttp2_map_key_type key, void *data) {
|
||||
int rv;
|
||||
size_t tablelen;
|
||||
nghttp2_ssize idx;
|
||||
|
||||
assert(data);
|
||||
|
||||
/* Load factor is 0.75 */
|
||||
/* Under the very initial condition, that is map->size == 0 and
|
||||
map->hashbits == 0, 4 > 3 still holds nicely. */
|
||||
if ((map->size + 1) * 4 > (1u << map->hashbits) * 3) {
|
||||
if (map->hashbits) {
|
||||
rv = map_resize(map, map->hashbits + 1);
|
||||
if (rv != 0) {
|
||||
return rv;
|
||||
}
|
||||
} else {
|
||||
rv = map_resize(map, NGHTTP2_INITIAL_TABLE_LENBITS);
|
||||
if (rv != 0) {
|
||||
return rv;
|
||||
}
|
||||
/* tablelen is incorrect if map->hashbits == 0 which leads to
|
||||
tablelen = 1, but it is only used to check the load factor, and
|
||||
it works in this special case. */
|
||||
tablelen = (size_t)1 << map->hashbits;
|
||||
|
||||
/* Load factor is 7 / 8. Because tablelen is power of 2, (tablelen
|
||||
- (tablelen >> 3)) computes tablelen * 7 / 8. */
|
||||
if (map->size + 1 >= (tablelen - (tablelen >> 3))) {
|
||||
rv = map_resize(map, map->hashbits ? map->hashbits + 1
|
||||
: NGHTTP2_INITIAL_HASHBITS);
|
||||
if (rv != 0) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
idx = map_insert(map, key, data);
|
||||
if (idx < 0) {
|
||||
return (int)idx;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
rv = insert(map->table, map->hashbits, key, data);
|
||||
if (rv != 0) {
|
||||
return rv;
|
||||
idx = map_insert(map, key, data);
|
||||
if (idx < 0) {
|
||||
return (int)idx;
|
||||
}
|
||||
|
||||
++map->size;
|
||||
/* Resize if psl reaches really large value which is almost
|
||||
improbable, but just in case. */
|
||||
if (map->psl[idx] - 1 < NGHTTP2_MAX_PSL_RESIZE_THRESH) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return map_resize(map, map->hashbits + 1);
|
||||
}
|
||||
|
||||
void *nghttp2_map_find(const nghttp2_map *map, nghttp2_map_key_type key) {
|
||||
size_t idx;
|
||||
nghttp2_map_bucket *bkt;
|
||||
size_t psl = 0;
|
||||
size_t psl = 1;
|
||||
size_t mask;
|
||||
|
||||
if (map->size == 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
idx = hash(key, map->hashbits);
|
||||
mask = (1u << map->hashbits) - 1;
|
||||
idx = map_index(map, key);
|
||||
mask = ((size_t)1 << map->hashbits) - 1;
|
||||
|
||||
for (;;) {
|
||||
bkt = &map->table[idx];
|
||||
|
||||
if (bkt->data == NULL || psl > bkt->psl) {
|
||||
if (psl > map->psl[idx]) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (bkt->key == key) {
|
||||
return bkt->data;
|
||||
if (map->keys[idx] == key) {
|
||||
return map->data[idx];
|
||||
}
|
||||
|
||||
++psl;
|
||||
@@ -244,38 +307,36 @@ void *nghttp2_map_find(const nghttp2_map *map, nghttp2_map_key_type key) {
|
||||
|
||||
int nghttp2_map_remove(nghttp2_map *map, nghttp2_map_key_type key) {
|
||||
size_t idx;
|
||||
nghttp2_map_bucket *b, *bkt;
|
||||
size_t psl = 0;
|
||||
size_t dest;
|
||||
size_t psl = 1, kpsl;
|
||||
size_t mask;
|
||||
|
||||
if (map->size == 0) {
|
||||
return NGHTTP2_ERR_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
idx = hash(key, map->hashbits);
|
||||
mask = (1u << map->hashbits) - 1;
|
||||
idx = map_index(map, key);
|
||||
mask = ((size_t)1 << map->hashbits) - 1;
|
||||
|
||||
for (;;) {
|
||||
bkt = &map->table[idx];
|
||||
|
||||
if (bkt->data == NULL || psl > bkt->psl) {
|
||||
if (psl > map->psl[idx]) {
|
||||
return NGHTTP2_ERR_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
if (bkt->key == key) {
|
||||
b = bkt;
|
||||
if (map->keys[idx] == key) {
|
||||
dest = idx;
|
||||
idx = (idx + 1) & mask;
|
||||
|
||||
for (;;) {
|
||||
bkt = &map->table[idx];
|
||||
if (bkt->data == NULL || bkt->psl == 0) {
|
||||
b->data = NULL;
|
||||
kpsl = map->psl[idx];
|
||||
if (kpsl <= 1) {
|
||||
map->psl[dest] = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
--bkt->psl;
|
||||
*b = *bkt;
|
||||
b = bkt;
|
||||
map_set_entry(map, dest, map->keys[idx], map->data[idx], kpsl - 1);
|
||||
|
||||
dest = idx;
|
||||
|
||||
idx = (idx + 1) & mask;
|
||||
}
|
||||
@@ -295,7 +356,7 @@ void nghttp2_map_clear(nghttp2_map *map) {
|
||||
return;
|
||||
}
|
||||
|
||||
memset(map->table, 0, sizeof(*map->table) * (1u << map->hashbits));
|
||||
memset(map->psl, 0, sizeof(*map->psl) * ((size_t)1 << map->hashbits));
|
||||
map->size = 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif /* HAVE_CONFIG_H */
|
||||
#endif /* defined(HAVE_CONFIG_H) */
|
||||
|
||||
#include <nghttp2/nghttp2.h>
|
||||
|
||||
@@ -38,15 +38,15 @@
|
||||
|
||||
typedef int32_t nghttp2_map_key_type;
|
||||
|
||||
typedef struct nghttp2_map_bucket {
|
||||
uint32_t psl;
|
||||
nghttp2_map_key_type key;
|
||||
void *data;
|
||||
} nghttp2_map_bucket;
|
||||
|
||||
typedef struct nghttp2_map {
|
||||
nghttp2_map_bucket *table;
|
||||
nghttp2_map_key_type *keys;
|
||||
void **data;
|
||||
/* psl is the Probe Sequence Length. 0 has special meaning that the
|
||||
element is not stored at i-th position if psl[i] == 0. Because
|
||||
of this, the actual psl value is psl[i] - 1 if psl[i] > 0. */
|
||||
uint8_t *psl;
|
||||
nghttp2_mem *mem;
|
||||
uint64_t seed;
|
||||
size_t size;
|
||||
size_t hashbits;
|
||||
} nghttp2_map;
|
||||
@@ -54,7 +54,7 @@ typedef struct nghttp2_map {
|
||||
/*
|
||||
* nghttp2_map_init initializes the map |map|.
|
||||
*/
|
||||
void nghttp2_map_init(nghttp2_map *map, nghttp2_mem *mem);
|
||||
void nghttp2_map_init(nghttp2_map *map, uint64_t seed, nghttp2_mem *mem);
|
||||
|
||||
/*
|
||||
* nghttp2_map_free deallocates any resources allocated for |map|.
|
||||
@@ -123,6 +123,6 @@ int nghttp2_map_each(const nghttp2_map *map, int (*func)(void *data, void *ptr),
|
||||
|
||||
#ifndef WIN32
|
||||
void nghttp2_map_print_distance(const nghttp2_map *map);
|
||||
#endif /* !WIN32 */
|
||||
#endif /* !defined(WIN32) */
|
||||
|
||||
#endif /* NGHTTP2_MAP_H */
|
||||
#endif /* !defined(NGHTTP2_MAP_H) */
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif /* HAVE_CONFIG_H */
|
||||
#endif /* defined(HAVE_CONFIG_H) */
|
||||
|
||||
#include <nghttp2/nghttp2.h>
|
||||
|
||||
@@ -42,4 +42,4 @@ void nghttp2_mem_free2(nghttp2_free free_func, void *ptr, void *mem_user_data);
|
||||
void *nghttp2_mem_calloc(nghttp2_mem *mem, size_t nmemb, size_t size);
|
||||
void *nghttp2_mem_realloc(nghttp2_mem *mem, void *ptr, size_t size);
|
||||
|
||||
#endif /* NGHTTP2_MEM_H */
|
||||
#endif /* !defined(NGHTTP2_MEM_H) */
|
||||
|
||||
@@ -27,28 +27,28 @@
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif /* HAVE_CONFIG_H */
|
||||
#endif /* defined(HAVE_CONFIG_H) */
|
||||
|
||||
#ifdef HAVE_ARPA_INET_H
|
||||
# include <arpa/inet.h>
|
||||
#endif /* HAVE_ARPA_INET_H */
|
||||
#endif /* defined(HAVE_ARPA_INET_H) */
|
||||
|
||||
#ifdef HAVE_NETINET_IN_H
|
||||
# include <netinet/in.h>
|
||||
#endif /* HAVE_NETINET_IN_H */
|
||||
#endif /* defined(HAVE_NETINET_IN_H) */
|
||||
|
||||
#include <nghttp2/nghttp2.h>
|
||||
|
||||
#if defined(WIN32)
|
||||
#ifdef WIN32
|
||||
/* Windows requires ws2_32 library for ntonl family functions. We
|
||||
define inline functions for those function so that we don't have
|
||||
dependency on that lib. */
|
||||
|
||||
# ifdef _MSC_VER
|
||||
# define STIN static __inline
|
||||
# else
|
||||
# else /* !defined(_MSC_VER) */
|
||||
# define STIN static inline
|
||||
# endif
|
||||
# endif /* !defined(_MSC_VER) */
|
||||
|
||||
STIN uint32_t htonl(uint32_t hostlong) {
|
||||
uint32_t res;
|
||||
@@ -86,6 +86,6 @@ STIN uint16_t ntohs(uint16_t netshort) {
|
||||
return res;
|
||||
}
|
||||
|
||||
#endif /* WIN32 */
|
||||
#endif /* defined(WIN32) */
|
||||
|
||||
#endif /* NGHTTP2_NET_H */
|
||||
#endif /* !defined(NGHTTP2_NET_H) */
|
||||
|
||||
@@ -155,3 +155,10 @@ void nghttp2_option_set_max_continuations(nghttp2_option *option, size_t val) {
|
||||
option->opt_set_mask |= NGHTTP2_OPT_MAX_CONTINUATIONS;
|
||||
option->max_continuations = val;
|
||||
}
|
||||
|
||||
void nghttp2_option_set_glitch_rate_limit(nghttp2_option *option,
|
||||
uint64_t burst, uint64_t rate) {
|
||||
option->opt_set_mask |= NGHTTP2_OPT_GLITCH_RATE_LIMIT;
|
||||
option->glitch_burst = burst;
|
||||
option->glitch_rate = rate;
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif /* HAVE_CONFIG_H */
|
||||
#endif /* defined(HAVE_CONFIG_H) */
|
||||
|
||||
#include <nghttp2/nghttp2.h>
|
||||
|
||||
@@ -72,6 +72,7 @@ typedef enum {
|
||||
NGHTTP2_OPT_NO_RFC9113_LEADING_AND_TRAILING_WS_VALIDATION = 1 << 14,
|
||||
NGHTTP2_OPT_STREAM_RESET_RATE_LIMIT = 1 << 15,
|
||||
NGHTTP2_OPT_MAX_CONTINUATIONS = 1 << 16,
|
||||
NGHTTP2_OPT_GLITCH_RATE_LIMIT = 1 << 17,
|
||||
} nghttp2_option_flag;
|
||||
|
||||
/**
|
||||
@@ -83,6 +84,11 @@ struct nghttp2_option {
|
||||
*/
|
||||
uint64_t stream_reset_burst;
|
||||
uint64_t stream_reset_rate;
|
||||
/**
|
||||
* NGHTTP2_OPT_GLITCH_RATE_LIMIT
|
||||
*/
|
||||
uint64_t glitch_burst;
|
||||
uint64_t glitch_rate;
|
||||
/**
|
||||
* NGHTTP2_OPT_MAX_SEND_HEADER_BLOCK_LENGTH
|
||||
*/
|
||||
@@ -154,4 +160,4 @@ struct nghttp2_option {
|
||||
uint8_t user_recv_ext_types[32];
|
||||
};
|
||||
|
||||
#endif /* NGHTTP2_OPTION_H */
|
||||
#endif /* !defined(NGHTTP2_OPTION_H) */
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif /* HAVE_CONFIG_H */
|
||||
#endif /* defined(HAVE_CONFIG_H) */
|
||||
|
||||
#include <nghttp2/nghttp2.h>
|
||||
#include "nghttp2_frame.h"
|
||||
@@ -186,4 +186,4 @@ void nghttp2_outbound_queue_pop(nghttp2_outbound_queue *q);
|
||||
/* Returns the size of the queue */
|
||||
#define nghttp2_outbound_queue_size(Q) ((Q)->n)
|
||||
|
||||
#endif /* NGHTTP2_OUTBOUND_ITEM_H */
|
||||
#endif /* !defined(NGHTTP2_OUTBOUND_ITEM_H) */
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif /* HAVE_CONFIG_H */
|
||||
#endif /* defined(HAVE_CONFIG_H) */
|
||||
|
||||
#include <nghttp2/nghttp2.h>
|
||||
#include "nghttp2_int.h"
|
||||
@@ -121,4 +121,4 @@ int nghttp2_pq_each(nghttp2_pq *pq, nghttp2_pq_item_cb fun, void *arg);
|
||||
*/
|
||||
void nghttp2_pq_remove(nghttp2_pq *pq, nghttp2_pq_entry *item);
|
||||
|
||||
#endif /* NGHTTP2_PQ_H */
|
||||
#endif /* !defined(NGHTTP2_PQ_H) */
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif /* HAVE_CONFIG_H */
|
||||
#endif /* defined(HAVE_CONFIG_H) */
|
||||
|
||||
#include <nghttp2/nghttp2.h>
|
||||
|
||||
@@ -39,4 +39,4 @@
|
||||
*/
|
||||
void nghttp2_priority_spec_normalize_weight(nghttp2_priority_spec *pri_spec);
|
||||
|
||||
#endif /* NGHTTP2_PRIORITY_SPEC_H */
|
||||
#endif /* !defined(NGHTTP2_PRIORITY_SPEC_H) */
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif /* HAVE_CONFIG_H */
|
||||
#endif /* defined(HAVE_CONFIG_H) */
|
||||
|
||||
#include <nghttp2/nghttp2.h>
|
||||
|
||||
@@ -48,4 +48,4 @@ void *nghttp2_queue_front(nghttp2_queue *queue);
|
||||
void *nghttp2_queue_back(nghttp2_queue *queue);
|
||||
int nghttp2_queue_empty(nghttp2_queue *queue);
|
||||
|
||||
#endif /* NGHTTP2_QUEUE_H */
|
||||
#endif /* !defined(NGHTTP2_QUEUE_H) */
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif /* HAVE_CONFIG_H */
|
||||
#endif /* defined(HAVE_CONFIG_H) */
|
||||
|
||||
#include <nghttp2/nghttp2.h>
|
||||
|
||||
@@ -54,4 +54,4 @@ void nghttp2_ratelim_update(nghttp2_ratelim *rl, uint64_t tstamp);
|
||||
succeeds, or -1. */
|
||||
int nghttp2_ratelim_drain(nghttp2_ratelim *rl, uint64_t n);
|
||||
|
||||
#endif /* NGHTTP2_RATELIM_H */
|
||||
#endif /* !defined(NGHTTP2_RATELIM_H) */
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif /* HAVE_CONFIG_H */
|
||||
#endif /* defined(HAVE_CONFIG_H) */
|
||||
|
||||
#include <nghttp2/nghttp2.h>
|
||||
|
||||
@@ -77,4 +77,4 @@ int nghttp2_rcbuf_new2(nghttp2_rcbuf **rcbuf_ptr, const uint8_t *src,
|
||||
*/
|
||||
void nghttp2_rcbuf_del(nghttp2_rcbuf *rcbuf);
|
||||
|
||||
#endif /* NGHTTP2_RCBUF_H */
|
||||
#endif /* !defined(NGHTTP2_RCBUF_H) */
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
#include "nghttp2_debug.h"
|
||||
#include "nghttp2_submit.h"
|
||||
|
||||
nghttp2_stream root;
|
||||
nghttp2_stream nghttp2_stream_root;
|
||||
|
||||
/*
|
||||
* Returns non-zero if the number of outgoing opened streams is larger
|
||||
@@ -438,6 +438,7 @@ static int session_new(nghttp2_session **session_ptr,
|
||||
size_t max_deflate_dynamic_table_size =
|
||||
NGHTTP2_HD_DEFAULT_MAX_DEFLATE_BUFFER_SIZE;
|
||||
size_t i;
|
||||
uint64_t map_seed;
|
||||
|
||||
if (mem == NULL) {
|
||||
mem = nghttp2_mem_default();
|
||||
@@ -474,6 +475,10 @@ static int session_new(nghttp2_session **session_ptr,
|
||||
NGHTTP2_DEFAULT_STREAM_RESET_BURST,
|
||||
NGHTTP2_DEFAULT_STREAM_RESET_RATE);
|
||||
|
||||
nghttp2_ratelim_init(&(*session_ptr)->glitch_ratelim,
|
||||
NGHTTP2_DEFAULT_GLITCH_BURST,
|
||||
NGHTTP2_DEFAULT_GLITCH_RATE);
|
||||
|
||||
if (server) {
|
||||
(*session_ptr)->server = 1;
|
||||
}
|
||||
@@ -566,6 +571,11 @@ static int session_new(nghttp2_session **session_ptr,
|
||||
if (option->opt_set_mask & NGHTTP2_OPT_MAX_CONTINUATIONS) {
|
||||
(*session_ptr)->max_continuations = option->max_continuations;
|
||||
}
|
||||
|
||||
if (option->opt_set_mask & NGHTTP2_OPT_GLITCH_RATE_LIMIT) {
|
||||
nghttp2_ratelim_init(&(*session_ptr)->glitch_ratelim,
|
||||
option->glitch_burst, option->glitch_rate);
|
||||
}
|
||||
}
|
||||
|
||||
rv = nghttp2_hd_deflate_init2(&(*session_ptr)->hd_deflater,
|
||||
@@ -594,7 +604,13 @@ static int session_new(nghttp2_session **session_ptr,
|
||||
goto fail_aob_framebuf;
|
||||
}
|
||||
|
||||
nghttp2_map_init(&(*session_ptr)->streams, mem);
|
||||
if (callbacks->rand_callback) {
|
||||
callbacks->rand_callback((uint8_t *)&map_seed, sizeof(map_seed));
|
||||
} else {
|
||||
map_seed = 0;
|
||||
}
|
||||
|
||||
nghttp2_map_init(&(*session_ptr)->streams, map_seed, mem);
|
||||
|
||||
active_outbound_item_reset(&(*session_ptr)->aob, mem);
|
||||
|
||||
@@ -1092,6 +1108,15 @@ int nghttp2_session_add_item(nghttp2_session *session,
|
||||
|
||||
int nghttp2_session_add_rst_stream(nghttp2_session *session, int32_t stream_id,
|
||||
uint32_t error_code) {
|
||||
return nghttp2_session_add_rst_stream_continue(
|
||||
session, stream_id, error_code,
|
||||
/* continue_without_stream = */ 1);
|
||||
}
|
||||
|
||||
int nghttp2_session_add_rst_stream_continue(nghttp2_session *session,
|
||||
int32_t stream_id,
|
||||
uint32_t error_code,
|
||||
int continue_without_stream) {
|
||||
int rv;
|
||||
nghttp2_outbound_item *item;
|
||||
nghttp2_frame *frame;
|
||||
@@ -1148,6 +1173,12 @@ int nghttp2_session_add_rst_stream(nghttp2_session *session, int32_t stream_id,
|
||||
}
|
||||
}
|
||||
|
||||
/* To keep the old behaviour, do not fail if stream was not
|
||||
found. */
|
||||
if (!continue_without_stream && !stream) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
item = nghttp2_mem_malloc(mem, sizeof(nghttp2_outbound_item));
|
||||
if (item == NULL) {
|
||||
return NGHTTP2_ERR_NOMEM;
|
||||
@@ -3241,7 +3272,9 @@ static int session_call_on_invalid_header(nghttp2_session *session,
|
||||
session, frame, nv->name->base, nv->name->len, nv->value->base,
|
||||
nv->value->len, nv->flags, session->user_data);
|
||||
} else {
|
||||
return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
|
||||
/* If both callbacks are not set, the invalid field nv is
|
||||
ignored. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (rv == NGHTTP2_ERR_PAUSE || rv == NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE) {
|
||||
@@ -3326,6 +3359,10 @@ static uint32_t get_error_code_from_lib_error_code(int lib_error_code) {
|
||||
case NGHTTP2_ERR_HTTP_HEADER:
|
||||
case NGHTTP2_ERR_HTTP_MESSAGING:
|
||||
return NGHTTP2_PROTOCOL_ERROR;
|
||||
case NGHTTP2_ERR_INTERNAL:
|
||||
return NGHTTP2_INTERNAL_ERROR;
|
||||
case NGHTTP2_ERR_PUSH_CANCEL:
|
||||
return NGHTTP2_CANCEL;
|
||||
default:
|
||||
return NGHTTP2_INTERNAL_ERROR;
|
||||
}
|
||||
@@ -3352,17 +3389,32 @@ static int session_call_on_invalid_frame_recv_callback(nghttp2_session *session,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int session_update_glitch_ratelim(nghttp2_session *session) {
|
||||
if (session->goaway_flags & NGHTTP2_GOAWAY_TERM_ON_SEND) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
nghttp2_ratelim_update(&session->glitch_ratelim, nghttp2_time_now_sec());
|
||||
|
||||
if (nghttp2_ratelim_drain(&session->glitch_ratelim, 1) == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return nghttp2_session_terminate_session(session, NGHTTP2_ENHANCE_YOUR_CALM);
|
||||
}
|
||||
|
||||
static int session_handle_invalid_stream2(nghttp2_session *session,
|
||||
int32_t stream_id,
|
||||
nghttp2_frame *frame,
|
||||
int lib_error_code) {
|
||||
int rv;
|
||||
|
||||
rv = nghttp2_session_add_rst_stream(
|
||||
session, stream_id, get_error_code_from_lib_error_code(lib_error_code));
|
||||
if (rv != 0) {
|
||||
return rv;
|
||||
}
|
||||
if (session->callbacks.on_invalid_frame_recv_callback) {
|
||||
if (frame && session->callbacks.on_invalid_frame_recv_callback) {
|
||||
if (session->callbacks.on_invalid_frame_recv_callback(
|
||||
session, frame, lib_error_code, session->user_data) != 0) {
|
||||
return NGHTTP2_ERR_CALLBACK_FAILURE;
|
||||
@@ -3517,7 +3569,29 @@ static int inflate_header_block(nghttp2_session *session, nghttp2_frame *frame,
|
||||
|
||||
rv2 = session_call_on_invalid_header(session, frame, &nv);
|
||||
if (rv2 == NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE) {
|
||||
rv = NGHTTP2_ERR_HTTP_HEADER;
|
||||
DEBUGF("recv: HTTP error: type=%u, id=%d, header %.*s: %.*s\n",
|
||||
frame->hd.type, frame->hd.stream_id, (int)nv.name->len,
|
||||
nv.name->base, (int)nv.value->len, nv.value->base);
|
||||
|
||||
rv = session_call_error_callback(
|
||||
session, NGHTTP2_ERR_HTTP_HEADER,
|
||||
"Invalid HTTP header field was received: frame type: "
|
||||
"%u, stream: %d, name: [%.*s], value: [%.*s]",
|
||||
frame->hd.type, frame->hd.stream_id, (int)nv.name->len,
|
||||
nv.name->base, (int)nv.value->len, nv.value->base);
|
||||
|
||||
if (nghttp2_is_fatal(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
rv = session_handle_invalid_stream2(
|
||||
session, subject_stream->stream_id, frame,
|
||||
NGHTTP2_ERR_HTTP_HEADER);
|
||||
if (nghttp2_is_fatal(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
|
||||
} else {
|
||||
if (rv2 != 0) {
|
||||
return rv2;
|
||||
@@ -3557,13 +3631,8 @@ static int inflate_header_block(nghttp2_session *session, nghttp2_frame *frame,
|
||||
return rv;
|
||||
}
|
||||
|
||||
rv =
|
||||
session_handle_invalid_stream2(session, subject_stream->stream_id,
|
||||
frame, NGHTTP2_ERR_HTTP_HEADER);
|
||||
if (nghttp2_is_fatal(rv)) {
|
||||
return rv;
|
||||
}
|
||||
return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
|
||||
return nghttp2_session_terminate_session(session,
|
||||
NGHTTP2_PROTOCOL_ERROR);
|
||||
}
|
||||
}
|
||||
if (rv == 0) {
|
||||
@@ -3676,27 +3745,7 @@ static int session_after_header_block_received(nghttp2_session *session) {
|
||||
}
|
||||
}
|
||||
if (rv != 0) {
|
||||
int32_t stream_id;
|
||||
|
||||
if (frame->hd.type == NGHTTP2_PUSH_PROMISE) {
|
||||
stream_id = frame->push_promise.promised_stream_id;
|
||||
} else {
|
||||
stream_id = frame->hd.stream_id;
|
||||
}
|
||||
|
||||
rv = session_handle_invalid_stream2(session, stream_id, frame,
|
||||
NGHTTP2_ERR_HTTP_MESSAGING);
|
||||
if (nghttp2_is_fatal(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (frame->hd.type == NGHTTP2_HEADERS &&
|
||||
(frame->hd.flags & NGHTTP2_FLAG_END_STREAM)) {
|
||||
nghttp2_stream_shutdown(stream, NGHTTP2_SHUT_RD);
|
||||
/* Don't call nghttp2_session_close_stream_if_shut_rdwr
|
||||
because RST_STREAM has been submitted. */
|
||||
}
|
||||
return 0;
|
||||
return nghttp2_session_terminate_session(session, NGHTTP2_PROTOCOL_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4032,8 +4081,7 @@ static int update_remote_initial_window_size_func(void *entry, void *ptr) {
|
||||
rv = nghttp2_stream_update_remote_initial_window_size(
|
||||
stream, arg->new_window_size, arg->old_window_size);
|
||||
if (rv != 0) {
|
||||
return nghttp2_session_add_rst_stream(arg->session, stream->stream_id,
|
||||
NGHTTP2_FLOW_CONTROL_ERROR);
|
||||
return NGHTTP2_ERR_FLOW_CONTROL;
|
||||
}
|
||||
|
||||
/* If window size gets positive, push deferred DATA frame to
|
||||
@@ -4059,6 +4107,8 @@ static int update_remote_initial_window_size_func(void *entry, void *ptr) {
|
||||
*
|
||||
* NGHTTP2_ERR_NOMEM
|
||||
* Out of memory.
|
||||
* NGHTTP2_ERR_FLOW_CONTROL
|
||||
* Window size gets out of range.
|
||||
*/
|
||||
static int
|
||||
session_update_remote_initial_window_size(nghttp2_session *session,
|
||||
@@ -4082,8 +4132,7 @@ static int update_local_initial_window_size_func(void *entry, void *ptr) {
|
||||
rv = nghttp2_stream_update_local_initial_window_size(
|
||||
stream, arg->new_window_size, arg->old_window_size);
|
||||
if (rv != 0) {
|
||||
return nghttp2_session_add_rst_stream(arg->session, stream->stream_id,
|
||||
NGHTTP2_FLOW_CONTROL_ERROR);
|
||||
return NGHTTP2_ERR_FLOW_CONTROL;
|
||||
}
|
||||
|
||||
if (stream->window_update_queued) {
|
||||
@@ -4117,6 +4166,8 @@ static int update_local_initial_window_size_func(void *entry, void *ptr) {
|
||||
*
|
||||
* NGHTTP2_ERR_NOMEM
|
||||
* Out of memory.
|
||||
* NGHTTP2_ERR_FLOW_CONTROL
|
||||
* Window size gets out of range.
|
||||
*/
|
||||
static int
|
||||
session_update_local_initial_window_size(nghttp2_session *session,
|
||||
@@ -4503,9 +4554,9 @@ int nghttp2_session_on_push_promise_received(nghttp2_session *session,
|
||||
session->max_incoming_reserved_streams) {
|
||||
/* Currently, client does not retain closed stream, so we don't
|
||||
check NGHTTP2_SHUT_RD condition here. */
|
||||
|
||||
rv = nghttp2_session_add_rst_stream(
|
||||
session, frame->push_promise.promised_stream_id, NGHTTP2_CANCEL);
|
||||
rv = session_handle_invalid_stream2(session,
|
||||
frame->push_promise.promised_stream_id,
|
||||
NULL, NGHTTP2_ERR_PUSH_CANCEL);
|
||||
if (rv != 0) {
|
||||
return rv;
|
||||
}
|
||||
@@ -4662,8 +4713,9 @@ static int session_on_stream_window_update_received(nghttp2_session *session,
|
||||
}
|
||||
if (NGHTTP2_MAX_WINDOW_SIZE - frame->window_update.window_size_increment <
|
||||
stream->remote_window_size) {
|
||||
return session_handle_invalid_stream(session, frame,
|
||||
NGHTTP2_ERR_FLOW_CONTROL);
|
||||
return session_handle_invalid_connection(
|
||||
session, frame, NGHTTP2_ERR_FLOW_CONTROL,
|
||||
"WINDOW_UPDATE: window size overflow");
|
||||
}
|
||||
stream->remote_window_size += frame->window_update.window_size_increment;
|
||||
|
||||
@@ -4893,16 +4945,7 @@ int nghttp2_session_on_data_received(nghttp2_session *session,
|
||||
if (session_enforce_http_messaging(session) &&
|
||||
(frame->hd.flags & NGHTTP2_FLAG_END_STREAM)) {
|
||||
if (nghttp2_http_on_remote_end_stream(stream) != 0) {
|
||||
rv = nghttp2_session_add_rst_stream(session, stream->stream_id,
|
||||
NGHTTP2_PROTOCOL_ERROR);
|
||||
if (nghttp2_is_fatal(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
nghttp2_stream_shutdown(stream, NGHTTP2_SHUT_RD);
|
||||
/* Don't call nghttp2_session_close_stream_if_shut_rdwr because
|
||||
RST_STREAM has been submitted. */
|
||||
return 0;
|
||||
return nghttp2_session_terminate_session(session, NGHTTP2_PROTOCOL_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4960,8 +5003,8 @@ int nghttp2_session_update_recv_stream_window_size(nghttp2_session *session,
|
||||
rv = adjust_recv_window_size(&stream->recv_window_size, delta_size,
|
||||
stream->local_window_size);
|
||||
if (rv != 0) {
|
||||
return nghttp2_session_add_rst_stream(session, stream->stream_id,
|
||||
NGHTTP2_FLOW_CONTROL_ERROR);
|
||||
return nghttp2_session_terminate_session(session,
|
||||
NGHTTP2_FLOW_CONTROL_ERROR);
|
||||
}
|
||||
/* We don't have to send WINDOW_UPDATE if the data received is the
|
||||
last chunk in the incoming stream. */
|
||||
@@ -5429,6 +5472,16 @@ nghttp2_ssize nghttp2_session_mem_recv2(nghttp2_session *session,
|
||||
if (rv == NGHTTP2_ERR_IGN_PAYLOAD) {
|
||||
DEBUGF("recv: DATA not allowed stream_id=%d\n",
|
||||
iframe->frame.hd.stream_id);
|
||||
|
||||
rv = session_update_glitch_ratelim(session);
|
||||
if (rv != 0) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (iframe->state == NGHTTP2_IB_IGN_ALL) {
|
||||
return (nghttp2_ssize)inlen;
|
||||
}
|
||||
|
||||
iframe->state = NGHTTP2_IB_IGN_DATA;
|
||||
break;
|
||||
}
|
||||
@@ -5454,6 +5507,20 @@ nghttp2_ssize nghttp2_session_mem_recv2(nghttp2_session *session,
|
||||
break;
|
||||
}
|
||||
|
||||
/* Empty DATA frame without END_STREAM flag set is
|
||||
suspicious. */
|
||||
if (iframe->payloadleft == 0 &&
|
||||
(iframe->frame.hd.flags & NGHTTP2_FLAG_END_STREAM) == 0) {
|
||||
rv = session_update_glitch_ratelim(session);
|
||||
if (rv != 0) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (iframe->state == NGHTTP2_IB_IGN_ALL) {
|
||||
return (nghttp2_ssize)inlen;
|
||||
}
|
||||
}
|
||||
|
||||
iframe->state = NGHTTP2_IB_READ_DATA;
|
||||
break;
|
||||
}
|
||||
@@ -5520,8 +5587,8 @@ nghttp2_ssize nghttp2_session_mem_recv2(nghttp2_session *session,
|
||||
}
|
||||
|
||||
if (rv == NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE) {
|
||||
rv = nghttp2_session_add_rst_stream(
|
||||
session, iframe->frame.hd.stream_id, NGHTTP2_INTERNAL_ERROR);
|
||||
rv = session_handle_invalid_stream2(
|
||||
session, iframe->frame.hd.stream_id, NULL, NGHTTP2_ERR_INTERNAL);
|
||||
if (nghttp2_is_fatal(rv)) {
|
||||
return rv;
|
||||
}
|
||||
@@ -5530,6 +5597,15 @@ nghttp2_ssize nghttp2_session_mem_recv2(nghttp2_session *session,
|
||||
}
|
||||
|
||||
if (rv == NGHTTP2_ERR_IGN_HEADER_BLOCK) {
|
||||
rv = session_update_glitch_ratelim(session);
|
||||
if (rv != 0) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (iframe->state == NGHTTP2_IB_IGN_ALL) {
|
||||
return (nghttp2_ssize)inlen;
|
||||
}
|
||||
|
||||
iframe->state = NGHTTP2_IB_IGN_HEADER_BLOCK;
|
||||
break;
|
||||
}
|
||||
@@ -5550,6 +5626,18 @@ nghttp2_ssize nghttp2_session_mem_recv2(nghttp2_session *session,
|
||||
break;
|
||||
}
|
||||
|
||||
/* This is deprecated RFC 7540 priorities mechanism which is
|
||||
very unpopular. We do not expect it is received so
|
||||
frequently. */
|
||||
rv = session_update_glitch_ratelim(session);
|
||||
if (rv != 0) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (iframe->state == NGHTTP2_IB_IGN_ALL) {
|
||||
return (nghttp2_ssize)inlen;
|
||||
}
|
||||
|
||||
iframe->state = NGHTTP2_IB_READ_NBYTE;
|
||||
|
||||
inbound_frame_set_mark(iframe, NGHTTP2_PRIORITY_SPECLEN);
|
||||
@@ -5566,7 +5654,7 @@ nghttp2_ssize nghttp2_session_mem_recv2(nghttp2_session *session,
|
||||
DEBUGF("recv: WINDOW_UPDATE\n");
|
||||
break;
|
||||
}
|
||||
#endif /* DEBUGBUILD */
|
||||
#endif /* defined(DEBUGBUILD) */
|
||||
|
||||
iframe->frame.hd.flags = NGHTTP2_FLAG_NONE;
|
||||
|
||||
@@ -5722,8 +5810,17 @@ nghttp2_ssize nghttp2_session_mem_recv2(nghttp2_session *session,
|
||||
if (check_ext_type_set(session->user_recv_ext_types,
|
||||
iframe->frame.hd.type)) {
|
||||
if (!session->callbacks.unpack_extension_callback) {
|
||||
/* Silently ignore unknown frame type. */
|
||||
/* Receiving too frequent unknown frames is suspicious. */
|
||||
rv = session_update_glitch_ratelim(session);
|
||||
if (rv != 0) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (iframe->state == NGHTTP2_IB_IGN_ALL) {
|
||||
return (nghttp2_ssize)inlen;
|
||||
}
|
||||
|
||||
/* Silently ignore unknown frame type. */
|
||||
busy = 1;
|
||||
|
||||
iframe->state = NGHTTP2_IB_IGN_PAYLOAD;
|
||||
@@ -5741,6 +5838,16 @@ nghttp2_ssize nghttp2_session_mem_recv2(nghttp2_session *session,
|
||||
case NGHTTP2_ALTSVC:
|
||||
if ((session->builtin_recv_ext_types & NGHTTP2_TYPEMASK_ALTSVC) ==
|
||||
0) {
|
||||
/* Receiving too frequent unknown frames is suspicious. */
|
||||
rv = session_update_glitch_ratelim(session);
|
||||
if (rv != 0) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (iframe->state == NGHTTP2_IB_IGN_ALL) {
|
||||
return (nghttp2_ssize)inlen;
|
||||
}
|
||||
|
||||
busy = 1;
|
||||
iframe->state = NGHTTP2_IB_IGN_PAYLOAD;
|
||||
break;
|
||||
@@ -5752,6 +5859,17 @@ nghttp2_ssize nghttp2_session_mem_recv2(nghttp2_session *session,
|
||||
iframe->frame.ext.payload = &iframe->ext_frame_payload.altsvc;
|
||||
|
||||
if (session->server) {
|
||||
/* Receiving too frequent ALTSVC from client is
|
||||
suspicious. */
|
||||
rv = session_update_glitch_ratelim(session);
|
||||
if (rv != 0) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (iframe->state == NGHTTP2_IB_IGN_ALL) {
|
||||
return (nghttp2_ssize)inlen;
|
||||
}
|
||||
|
||||
busy = 1;
|
||||
iframe->state = NGHTTP2_IB_IGN_PAYLOAD;
|
||||
break;
|
||||
@@ -5771,6 +5889,16 @@ nghttp2_ssize nghttp2_session_mem_recv2(nghttp2_session *session,
|
||||
break;
|
||||
case NGHTTP2_ORIGIN:
|
||||
if (!(session->builtin_recv_ext_types & NGHTTP2_TYPEMASK_ORIGIN)) {
|
||||
/* Receiving too frequent unknown frames is suspicious. */
|
||||
rv = session_update_glitch_ratelim(session);
|
||||
if (rv != 0) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (iframe->state == NGHTTP2_IB_IGN_ALL) {
|
||||
return (nghttp2_ssize)inlen;
|
||||
}
|
||||
|
||||
busy = 1;
|
||||
iframe->state = NGHTTP2_IB_IGN_PAYLOAD;
|
||||
break;
|
||||
@@ -5782,6 +5910,17 @@ nghttp2_ssize nghttp2_session_mem_recv2(nghttp2_session *session,
|
||||
|
||||
if (session->server || iframe->frame.hd.stream_id ||
|
||||
(iframe->frame.hd.flags & 0xf0)) {
|
||||
/* Receiving too frequent invalid frames is
|
||||
suspicious. */
|
||||
rv = session_update_glitch_ratelim(session);
|
||||
if (rv != 0) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (iframe->state == NGHTTP2_IB_IGN_ALL) {
|
||||
return (nghttp2_ssize)inlen;
|
||||
}
|
||||
|
||||
busy = 1;
|
||||
iframe->state = NGHTTP2_IB_IGN_PAYLOAD;
|
||||
break;
|
||||
@@ -5808,6 +5947,16 @@ nghttp2_ssize nghttp2_session_mem_recv2(nghttp2_session *session,
|
||||
case NGHTTP2_PRIORITY_UPDATE:
|
||||
if ((session->builtin_recv_ext_types &
|
||||
NGHTTP2_TYPEMASK_PRIORITY_UPDATE) == 0) {
|
||||
/* Receiving too frequent unknown frames is suspicious. */
|
||||
rv = session_update_glitch_ratelim(session);
|
||||
if (rv != 0) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (iframe->state == NGHTTP2_IB_IGN_ALL) {
|
||||
return (nghttp2_ssize)inlen;
|
||||
}
|
||||
|
||||
busy = 1;
|
||||
iframe->state = NGHTTP2_IB_IGN_PAYLOAD;
|
||||
break;
|
||||
@@ -5835,6 +5984,17 @@ nghttp2_ssize nghttp2_session_mem_recv2(nghttp2_session *session,
|
||||
break;
|
||||
}
|
||||
|
||||
/* Receiving too frequent PRIORITY_UPDATE is
|
||||
suspicious. */
|
||||
rv = session_update_glitch_ratelim(session);
|
||||
if (rv != 0) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (iframe->state == NGHTTP2_IB_IGN_ALL) {
|
||||
return (nghttp2_ssize)inlen;
|
||||
}
|
||||
|
||||
if (iframe->payloadleft > sizeof(iframe->raw_sbuf)) {
|
||||
busy = 1;
|
||||
iframe->state = NGHTTP2_IB_IGN_PAYLOAD;
|
||||
@@ -5848,6 +6008,16 @@ nghttp2_ssize nghttp2_session_mem_recv2(nghttp2_session *session,
|
||||
|
||||
break;
|
||||
default:
|
||||
/* Receiving too frequent unknown frames is suspicious. */
|
||||
rv = session_update_glitch_ratelim(session);
|
||||
if (rv != 0) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (iframe->state == NGHTTP2_IB_IGN_ALL) {
|
||||
return (nghttp2_ssize)inlen;
|
||||
}
|
||||
|
||||
busy = 1;
|
||||
|
||||
iframe->state = NGHTTP2_IB_IGN_PAYLOAD;
|
||||
@@ -5934,8 +6104,8 @@ nghttp2_ssize nghttp2_session_mem_recv2(nghttp2_session *session,
|
||||
}
|
||||
|
||||
if (rv == NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE) {
|
||||
rv = nghttp2_session_add_rst_stream(
|
||||
session, iframe->frame.hd.stream_id, NGHTTP2_INTERNAL_ERROR);
|
||||
rv = session_handle_invalid_stream2(
|
||||
session, iframe->frame.hd.stream_id, NULL, NGHTTP2_ERR_INTERNAL);
|
||||
if (nghttp2_is_fatal(rv)) {
|
||||
return rv;
|
||||
}
|
||||
@@ -5944,6 +6114,15 @@ nghttp2_ssize nghttp2_session_mem_recv2(nghttp2_session *session,
|
||||
}
|
||||
|
||||
if (rv == NGHTTP2_ERR_IGN_HEADER_BLOCK) {
|
||||
rv = session_update_glitch_ratelim(session);
|
||||
if (rv != 0) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (iframe->state == NGHTTP2_IB_IGN_ALL) {
|
||||
return (nghttp2_ssize)inlen;
|
||||
}
|
||||
|
||||
iframe->state = NGHTTP2_IB_IGN_HEADER_BLOCK;
|
||||
break;
|
||||
}
|
||||
@@ -6009,9 +6188,9 @@ nghttp2_ssize nghttp2_session_mem_recv2(nghttp2_session *session,
|
||||
}
|
||||
|
||||
if (rv == NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE) {
|
||||
rv = nghttp2_session_add_rst_stream(
|
||||
session, iframe->frame.push_promise.promised_stream_id,
|
||||
NGHTTP2_INTERNAL_ERROR);
|
||||
rv = session_handle_invalid_stream2(
|
||||
session, iframe->frame.push_promise.promised_stream_id, NULL,
|
||||
NGHTTP2_ERR_INTERNAL);
|
||||
if (nghttp2_is_fatal(rv)) {
|
||||
return rv;
|
||||
}
|
||||
@@ -6136,7 +6315,7 @@ nghttp2_ssize nghttp2_session_mem_recv2(nghttp2_session *session,
|
||||
} else {
|
||||
DEBUGF("recv: [IB_IGN_HEADER_BLOCK]\n");
|
||||
}
|
||||
#endif /* DEBUGBUILD */
|
||||
#endif /* defined(DEBUGBUILD) */
|
||||
|
||||
readlen = inbound_frame_payload_readlen(iframe, in, last);
|
||||
|
||||
@@ -6189,12 +6368,12 @@ nghttp2_ssize nghttp2_session_mem_recv2(nghttp2_session *session,
|
||||
iframe->payloadleft -= hd_proclen;
|
||||
|
||||
/* Use promised stream ID for PUSH_PROMISE */
|
||||
rv = nghttp2_session_add_rst_stream(
|
||||
rv = session_handle_invalid_stream2(
|
||||
session,
|
||||
iframe->frame.hd.type == NGHTTP2_PUSH_PROMISE
|
||||
? iframe->frame.push_promise.promised_stream_id
|
||||
: iframe->frame.hd.stream_id,
|
||||
NGHTTP2_INTERNAL_ERROR);
|
||||
NULL, NGHTTP2_ERR_INTERNAL);
|
||||
if (nghttp2_is_fatal(rv)) {
|
||||
return rv;
|
||||
}
|
||||
@@ -6241,6 +6420,10 @@ nghttp2_ssize nghttp2_session_mem_recv2(nghttp2_session *session,
|
||||
if (nghttp2_is_fatal(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (iframe->state == NGHTTP2_IB_IGN_ALL) {
|
||||
return (nghttp2_ssize)inlen;
|
||||
}
|
||||
}
|
||||
session_inbound_frame_reset(session);
|
||||
|
||||
@@ -6364,7 +6547,7 @@ nghttp2_ssize nghttp2_session_mem_recv2(nghttp2_session *session,
|
||||
} else {
|
||||
fprintf(stderr, "recv: [IB_IGN_CONTINUATION]\n");
|
||||
}
|
||||
#endif /* DEBUGBUILD */
|
||||
#endif /* defined(DEBUGBUILD) */
|
||||
|
||||
if (++session->num_continuations > session->max_continuations) {
|
||||
return NGHTTP2_ERR_TOO_MANY_CONTINUATIONS;
|
||||
@@ -6466,6 +6649,10 @@ nghttp2_ssize nghttp2_session_mem_recv2(nghttp2_session *session,
|
||||
if (nghttp2_is_fatal(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (iframe->state == NGHTTP2_IB_IGN_ALL) {
|
||||
return (nghttp2_ssize)inlen;
|
||||
}
|
||||
}
|
||||
|
||||
busy = 1;
|
||||
@@ -6482,6 +6669,20 @@ nghttp2_ssize nghttp2_session_mem_recv2(nghttp2_session *session,
|
||||
|
||||
iframe->frame.data.padlen = (size_t)padlen;
|
||||
|
||||
/* Empty DATA frame without END_STREAM flag set is
|
||||
suspicious. */
|
||||
if (iframe->payloadleft == 0 &&
|
||||
(iframe->frame.hd.flags & NGHTTP2_FLAG_END_STREAM) == 0) {
|
||||
rv = session_update_glitch_ratelim(session);
|
||||
if (rv != 0) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (iframe->state == NGHTTP2_IB_IGN_ALL) {
|
||||
return (nghttp2_ssize)inlen;
|
||||
}
|
||||
}
|
||||
|
||||
iframe->state = NGHTTP2_IB_READ_DATA;
|
||||
|
||||
break;
|
||||
@@ -6524,6 +6725,10 @@ nghttp2_ssize nghttp2_session_mem_recv2(nghttp2_session *session,
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (iframe->state == NGHTTP2_IB_IGN_ALL) {
|
||||
return (nghttp2_ssize)inlen;
|
||||
}
|
||||
|
||||
data_readlen =
|
||||
inbound_frame_effective_readlen(iframe, iframe->payloadleft, readlen);
|
||||
|
||||
@@ -6553,28 +6758,13 @@ nghttp2_ssize nghttp2_session_mem_recv2(nghttp2_session *session,
|
||||
if (data_readlen > 0) {
|
||||
if (session_enforce_http_messaging(session)) {
|
||||
if (nghttp2_http_on_data_chunk(stream, (size_t)data_readlen) != 0) {
|
||||
if (session->opt_flags & NGHTTP2_OPTMASK_NO_AUTO_WINDOW_UPDATE) {
|
||||
/* Consume all data for connection immediately here */
|
||||
rv = session_update_connection_consumed_size(
|
||||
session, (size_t)data_readlen);
|
||||
|
||||
if (nghttp2_is_fatal(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (iframe->state == NGHTTP2_IB_IGN_DATA) {
|
||||
return (nghttp2_ssize)inlen;
|
||||
}
|
||||
}
|
||||
|
||||
rv = nghttp2_session_add_rst_stream(
|
||||
session, iframe->frame.hd.stream_id, NGHTTP2_PROTOCOL_ERROR);
|
||||
rv = nghttp2_session_terminate_session(session,
|
||||
NGHTTP2_PROTOCOL_ERROR);
|
||||
if (nghttp2_is_fatal(rv)) {
|
||||
return rv;
|
||||
}
|
||||
busy = 1;
|
||||
iframe->state = NGHTTP2_IB_IGN_DATA;
|
||||
break;
|
||||
|
||||
return (nghttp2_ssize)inlen;
|
||||
}
|
||||
}
|
||||
if (session->callbacks.on_data_chunk_recv_callback) {
|
||||
@@ -6601,6 +6791,10 @@ nghttp2_ssize nghttp2_session_mem_recv2(nghttp2_session *session,
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (iframe->state == NGHTTP2_IB_IGN_ALL) {
|
||||
return (nghttp2_ssize)inlen;
|
||||
}
|
||||
|
||||
session_inbound_frame_reset(session);
|
||||
|
||||
break;
|
||||
@@ -7715,7 +7909,7 @@ int32_t nghttp2_session_get_last_proc_stream_id(nghttp2_session *session) {
|
||||
nghttp2_stream *nghttp2_session_find_stream(nghttp2_session *session,
|
||||
int32_t stream_id) {
|
||||
if (stream_id == 0) {
|
||||
return &root;
|
||||
return &nghttp2_stream_root;
|
||||
}
|
||||
|
||||
return nghttp2_session_get_stream_raw(session, stream_id);
|
||||
@@ -7724,7 +7918,7 @@ nghttp2_stream *nghttp2_session_find_stream(nghttp2_session *session,
|
||||
nghttp2_stream *nghttp2_session_get_root_stream(nghttp2_session *session) {
|
||||
(void)session;
|
||||
|
||||
return &root;
|
||||
return &nghttp2_stream_root;
|
||||
}
|
||||
|
||||
int nghttp2_session_check_server_session(nghttp2_session *session) {
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif /* HAVE_CONFIG_H */
|
||||
#endif /* defined(HAVE_CONFIG_H) */
|
||||
|
||||
#include <nghttp2/nghttp2.h>
|
||||
#include "nghttp2_map.h"
|
||||
@@ -45,7 +45,7 @@
|
||||
preface handling. */
|
||||
extern int nghttp2_enable_strict_preface;
|
||||
|
||||
extern nghttp2_stream root;
|
||||
extern nghttp2_stream nghttp2_stream_root;
|
||||
|
||||
/*
|
||||
* Option flags.
|
||||
@@ -106,6 +106,10 @@ typedef struct {
|
||||
#define NGHTTP2_DEFAULT_STREAM_RESET_BURST 1000
|
||||
#define NGHTTP2_DEFAULT_STREAM_RESET_RATE 33
|
||||
|
||||
/* The default values for glitch rate limiter. */
|
||||
#define NGHTTP2_DEFAULT_GLITCH_BURST 1000
|
||||
#define NGHTTP2_DEFAULT_GLITCH_RATE 33
|
||||
|
||||
/* The default max number of CONTINUATION frames following an incoming
|
||||
HEADER frame. */
|
||||
#define NGHTTP2_DEFAULT_MAX_CONTINUATIONS 8
|
||||
@@ -229,6 +233,8 @@ struct nghttp2_session {
|
||||
/* Stream reset rate limiter. If receiving excessive amount of
|
||||
stream resets, GOAWAY will be sent. */
|
||||
nghttp2_ratelim stream_reset_ratelim;
|
||||
/* Rate limiter for all kinds of glitches. */
|
||||
nghttp2_ratelim glitch_ratelim;
|
||||
/* Sequential number across all streams to process streams in
|
||||
FIFO. */
|
||||
uint64_t stream_seq;
|
||||
@@ -402,6 +408,13 @@ int nghttp2_session_is_my_stream_id(nghttp2_session *session,
|
||||
int nghttp2_session_add_item(nghttp2_session *session,
|
||||
nghttp2_outbound_item *item);
|
||||
|
||||
/*
|
||||
* This function wraps around nghttp2_session_add_rst_stream_continue
|
||||
* with continue_without_stream = 1.
|
||||
*/
|
||||
int nghttp2_session_add_rst_stream(nghttp2_session *session, int32_t stream_id,
|
||||
uint32_t error_code);
|
||||
|
||||
/*
|
||||
* Adds RST_STREAM frame for the stream |stream_id| with the error
|
||||
* code |error_code|. This is a convenient function built on top of
|
||||
@@ -409,7 +422,9 @@ int nghttp2_session_add_item(nghttp2_session *session,
|
||||
*
|
||||
* This function simply returns 0 without adding RST_STREAM frame if
|
||||
* given stream is in NGHTTP2_STREAM_CLOSING state, because multiple
|
||||
* RST_STREAM for a stream is redundant.
|
||||
* RST_STREAM for a stream is redundant. It also returns 0 without
|
||||
* adding the frame if |continue_without_stream| is nonzero, and
|
||||
* stream was already gone.
|
||||
*
|
||||
* This function returns 0 if it succeeds, or one of the following
|
||||
* negative error codes:
|
||||
@@ -417,8 +432,10 @@ int nghttp2_session_add_item(nghttp2_session *session,
|
||||
* NGHTTP2_ERR_NOMEM
|
||||
* Out of memory.
|
||||
*/
|
||||
int nghttp2_session_add_rst_stream(nghttp2_session *session, int32_t stream_id,
|
||||
uint32_t error_code);
|
||||
int nghttp2_session_add_rst_stream_continue(nghttp2_session *session,
|
||||
int32_t stream_id,
|
||||
uint32_t error_code,
|
||||
int continue_without_stream);
|
||||
|
||||
/*
|
||||
* Adds PING frame. This is a convenient function built on top of
|
||||
@@ -875,4 +892,4 @@ int nghttp2_session_update_recv_stream_window_size(nghttp2_session *session,
|
||||
size_t delta_size,
|
||||
int send_window_update);
|
||||
|
||||
#endif /* NGHTTP2_SESSION_H */
|
||||
#endif /* !defined(NGHTTP2_SESSION_H) */
|
||||
|
||||
@@ -151,7 +151,7 @@ void nghttp2_stream_promise_fulfilled(nghttp2_stream *stream) {
|
||||
}
|
||||
|
||||
nghttp2_stream_proto_state nghttp2_stream_get_state(nghttp2_stream *stream) {
|
||||
if (stream == &root) {
|
||||
if (stream == &nghttp2_stream_root) {
|
||||
return NGHTTP2_STREAM_STATE_IDLE;
|
||||
}
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif /* HAVE_CONFIG_H */
|
||||
#endif /* defined(HAVE_CONFIG_H) */
|
||||
|
||||
#include <nghttp2/nghttp2.h>
|
||||
#include "nghttp2_outbound_item.h"
|
||||
@@ -294,4 +294,4 @@ void nghttp2_stream_attach_item(nghttp2_stream *stream,
|
||||
*/
|
||||
void nghttp2_stream_detach_item(nghttp2_stream *stream);
|
||||
|
||||
#endif /* NGHTTP2_STREAM */
|
||||
#endif /* !defined(NGHTTP2_STREAM_H) */
|
||||
|
||||
@@ -185,7 +185,8 @@ int nghttp2_submit_rst_stream(nghttp2_session *session, uint8_t flags,
|
||||
return NGHTTP2_ERR_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
return nghttp2_session_add_rst_stream(session, stream_id, error_code);
|
||||
return nghttp2_session_add_rst_stream_continue(
|
||||
session, stream_id, error_code, /* continue_without_stream = */ 0);
|
||||
}
|
||||
|
||||
int nghttp2_submit_goaway(nghttp2_session *session, uint8_t flags,
|
||||
@@ -486,7 +487,7 @@ int nghttp2_submit_altsvc(nghttp2_session *session, uint8_t flags,
|
||||
return 0;
|
||||
|
||||
fail_item_malloc:
|
||||
free(buf);
|
||||
nghttp2_mem_free(mem, buf);
|
||||
|
||||
return rv;
|
||||
}
|
||||
@@ -569,7 +570,7 @@ int nghttp2_submit_origin(nghttp2_session *session, uint8_t flags,
|
||||
return 0;
|
||||
|
||||
fail_item_malloc:
|
||||
free(ov_copy);
|
||||
nghttp2_mem_free(mem, ov_copy);
|
||||
|
||||
return rv;
|
||||
}
|
||||
@@ -641,7 +642,7 @@ int nghttp2_submit_priority_update(nghttp2_session *session, uint8_t flags,
|
||||
return 0;
|
||||
|
||||
fail_item_malloc:
|
||||
free(buf);
|
||||
nghttp2_mem_free(mem, buf);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif /* HAVE_CONFIG_H */
|
||||
#endif /* defined(HAVE_CONFIG_H) */
|
||||
|
||||
#include <nghttp2/nghttp2.h>
|
||||
|
||||
@@ -37,4 +37,4 @@ int nghttp2_submit_data_shared(nghttp2_session *session, uint8_t flags,
|
||||
int32_t stream_id,
|
||||
const nghttp2_data_provider_wrap *dpw);
|
||||
|
||||
#endif /* NGHTTP2_SUBMIT_H */
|
||||
#endif /* !defined(NGHTTP2_SUBMIT_H) */
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
|
||||
#ifdef HAVE_WINDOWS_H
|
||||
# include <windows.h>
|
||||
#endif /* HAVE_WINDOWS_H */
|
||||
#endif /* defined(HAVE_WINDOWS_H) */
|
||||
|
||||
#include <time.h>
|
||||
|
||||
@@ -40,12 +40,11 @@ static uint64_t time_now_sec(void) {
|
||||
|
||||
return (uint64_t)t;
|
||||
}
|
||||
#endif /* !HAVE_GETTICKCOUNT64 || __CYGWIN__ */
|
||||
#endif /* !defined(HAVE_GETTICKCOUNT64) || defined(__CYGWIN__) */
|
||||
|
||||
#if defined(HAVE_GETTICKCOUNT64) && !defined(__CYGWIN__)
|
||||
uint64_t nghttp2_time_now_sec(void) { return GetTickCount64() / 1000; }
|
||||
#elif defined(HAVE_CLOCK_GETTIME) && defined(HAVE_DECL_CLOCK_MONOTONIC) && \
|
||||
HAVE_DECL_CLOCK_MONOTONIC
|
||||
#elif defined(HAVE_CLOCK_GETTIME) && HAVE_DECL_CLOCK_MONOTONIC
|
||||
uint64_t nghttp2_time_now_sec(void) {
|
||||
struct timespec tp;
|
||||
int rv = clock_gettime(CLOCK_MONOTONIC, &tp);
|
||||
@@ -56,8 +55,8 @@ uint64_t nghttp2_time_now_sec(void) {
|
||||
|
||||
return (uint64_t)tp.tv_sec;
|
||||
}
|
||||
#else /* (!HAVE_CLOCK_GETTIME || !HAVE_DECL_CLOCK_MONOTONIC) && \
|
||||
(!HAVE_GETTICKCOUNT64 || __CYGWIN__)) */
|
||||
#else /* (!defined(HAVE_GETTICKCOUNT64) || !defined(__CYGWIN__)) && \
|
||||
(!defined(HAVE_CLOCK_GETTIME) || !HAVE_DECL_CLOCK_MONOTONIC) */
|
||||
uint64_t nghttp2_time_now_sec(void) { return time_now_sec(); }
|
||||
#endif /* (!HAVE_CLOCK_GETTIME || !HAVE_DECL_CLOCK_MONOTONIC) && \
|
||||
(!HAVE_GETTICKCOUNT64 || __CYGWIN__)) */
|
||||
#endif /* (!defined(HAVE_GETTICKCOUNT64) || !defined(__CYGWIN__)) && \
|
||||
(!defined(HAVE_CLOCK_GETTIME) || !HAVE_DECL_CLOCK_MONOTONIC) */
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif /* HAVE_CONFIG_H */
|
||||
#endif /* defined(HAVE_CONFIG_H) */
|
||||
|
||||
#include <nghttp2/nghttp2.h>
|
||||
|
||||
@@ -35,4 +35,4 @@
|
||||
timepoint. If it is unable to get seconds, it returns 0. */
|
||||
uint64_t nghttp2_time_now_sec(void);
|
||||
|
||||
#endif /* NGHTTP2_TIME_H */
|
||||
#endif /* !defined(NGHTTP2_TIME_H) */
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
*/
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif /* HAVE_CONFIG_H */
|
||||
#endif /* defined(HAVE_CONFIG_H) */
|
||||
|
||||
#include <nghttp2/nghttp2.h>
|
||||
|
||||
|
||||
27
mkhufftbl.py
27
mkhufftbl.py
@@ -356,8 +356,8 @@ def _build_transition_table(ctx, node):
|
||||
def huffman_tree_build_transition_table(ctx):
|
||||
_build_transition_table(ctx, ctx.root)
|
||||
|
||||
NGHTTP2_HUFF_ACCEPTED = 1 << 14
|
||||
NGHTTP2_HUFF_SYM = 1 << 15
|
||||
NGHTTP2_HUFF_ACCEPTED = 1
|
||||
NGHTTP2_HUFF_SYM = 1 << 1
|
||||
|
||||
def _print_transition_table(node):
|
||||
if node.term is not None:
|
||||
@@ -381,7 +381,7 @@ 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)
|
||||
@@ -390,22 +390,10 @@ 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},')
|
||||
|
||||
for _ in range(16):
|
||||
print(' {0x100, 0, 0},')
|
||||
|
||||
print('},')
|
||||
|
||||
if __name__ == '__main__':
|
||||
@@ -458,6 +446,7 @@ enum {{
|
||||
print('''\
|
||||
typedef struct {
|
||||
uint16_t fstate;
|
||||
uint8_t flags;
|
||||
uint8_t sym;
|
||||
} nghttp2_huff_decode;
|
||||
''')
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
# EXTRA_DIST = README.rst
|
||||
install(
|
||||
PROGRAMS fetch-ocsp-response
|
||||
DESTINATION "${CMAKE_INSTALL_DATADIR}/${CMAKE_PROJECT_NAME}"
|
||||
)
|
||||
@@ -1,25 +0,0 @@
|
||||
# nghttp2 - HTTP/2 C Library
|
||||
|
||||
# Copyright (c) 2015 Tatsuhiro Tsujikawa
|
||||
|
||||
# Permission is hereby granted, free of charge, to any person obtaining
|
||||
# a copy of this software and associated documentation files (the
|
||||
# "Software"), to deal in the Software without restriction, including
|
||||
# without limitation the rights to use, copy, modify, merge, publish,
|
||||
# distribute, sublicense, and/or sell copies of the Software, and to
|
||||
# permit persons to whom the Software is furnished to do so, subject to
|
||||
# the following conditions:
|
||||
|
||||
# The above copyright notice and this permission notice shall be
|
||||
# included in all copies or substantial portions of the Software.
|
||||
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
EXTRA_DIST = README.rst CMakeLists.txt
|
||||
dist_pkgdata_SCRIPTS = fetch-ocsp-response
|
||||
@@ -1,10 +0,0 @@
|
||||
fetch-ocsp-response is a Python script which performs OCSP query and
|
||||
get response. It uses openssl command under the hood. nghttpx uses
|
||||
it to enable OCSP stapling feature.
|
||||
|
||||
fetch-ocsp-response is a translation from original fetch-ocsp-response
|
||||
written in Perl and which has been developed as part of h2o project
|
||||
(https://github.com/h2o/h2o).
|
||||
|
||||
fetch-ocsp-response is usually installed under $(pkgdatadir), which is
|
||||
$(prefix)/share/nghttp2.
|
||||
@@ -1,253 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# nghttp2 - HTTP/2 C Library
|
||||
|
||||
# Copyright (c) 2015 Tatsuhiro Tsujikawa
|
||||
|
||||
# Permission is hereby granted, free of charge, to any person obtaining
|
||||
# a copy of this software and associated documentation files (the
|
||||
# "Software"), to deal in the Software without restriction, including
|
||||
# without limitation the rights to use, copy, modify, merge, publish,
|
||||
# distribute, sublicense, and/or sell copies of the Software, and to
|
||||
# permit persons to whom the Software is furnished to do so, subject to
|
||||
# the following conditions:
|
||||
|
||||
# The above copyright notice and this permission notice shall be
|
||||
# included in all copies or substantial portions of the Software.
|
||||
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
# This program was translated from the program originally developed by
|
||||
# h2o project (https://github.com/h2o/h2o), written in Perl. It had
|
||||
# the following copyright notice:
|
||||
|
||||
# Copyright (c) 2015 DeNA Co., Ltd.
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to
|
||||
# deal in the Software without restriction, including without limitation the
|
||||
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
# sell copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in
|
||||
# all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
# IN THE SOFTWARE.
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import argparse
|
||||
import io
|
||||
import os
|
||||
import os.path
|
||||
import re
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
import tempfile
|
||||
|
||||
# make this program work for both Python 3 and Python 2.
|
||||
try:
|
||||
from urllib.parse import urlparse
|
||||
stdout_bwrite = sys.stdout.buffer.write
|
||||
except ImportError:
|
||||
from urlparse import urlparse
|
||||
stdout_bwrite = sys.stdout.write
|
||||
|
||||
|
||||
def die(msg):
|
||||
sys.stderr.write(msg)
|
||||
sys.stderr.write('\n')
|
||||
sys.exit(255)
|
||||
|
||||
|
||||
def tempfail(msg):
|
||||
sys.stderr.write(msg)
|
||||
sys.stderr.write('\n')
|
||||
sys.exit(os.EX_TEMPFAIL)
|
||||
|
||||
|
||||
def run_openssl(args, allow_tempfail=False):
|
||||
buf = io.BytesIO()
|
||||
try:
|
||||
p = subprocess.Popen(args, stdout=subprocess.PIPE)
|
||||
except Exception as e:
|
||||
die('failed to invoke {}:{}'.format(args, e))
|
||||
try:
|
||||
while True:
|
||||
data = p.stdout.read()
|
||||
if len(data) == 0:
|
||||
break
|
||||
buf.write(data)
|
||||
if p.wait() != 0:
|
||||
raise Exception('nonzero return code {}'.format(p.returncode))
|
||||
return buf.getvalue()
|
||||
except Exception as e:
|
||||
msg = 'OpenSSL exited abnormally: {}:{}'.format(args, e)
|
||||
tempfail(msg) if allow_tempfail else die(msg)
|
||||
|
||||
|
||||
def read_file(path):
|
||||
with open(path, 'rb') as f:
|
||||
return f.read()
|
||||
|
||||
|
||||
def write_file(path, data):
|
||||
with open(path, 'wb') as f:
|
||||
f.write(data)
|
||||
|
||||
|
||||
def detect_openssl_version(cmd):
|
||||
return run_openssl([cmd, 'version']).decode('utf-8').strip()
|
||||
|
||||
|
||||
def extract_ocsp_uri(cmd, cert_fn):
|
||||
# obtain ocsp uri
|
||||
ocsp_uri = run_openssl(
|
||||
[cmd, 'x509', '-in', cert_fn, '-noout',
|
||||
'-ocsp_uri']).decode('utf-8').strip()
|
||||
|
||||
if not re.match(r'^https?://', ocsp_uri):
|
||||
die('failed to extract ocsp URI from {}'.format(cert_fn))
|
||||
|
||||
return ocsp_uri
|
||||
|
||||
|
||||
def save_issuer_certificate(issuer_fn, cert_fn):
|
||||
# save issuer certificate
|
||||
chain = read_file(cert_fn).decode('utf-8')
|
||||
m = re.match(
|
||||
r'.*?-----END CERTIFICATE-----.*?(-----BEGIN CERTIFICATE-----.*?-----END CERTIFICATE-----)',
|
||||
chain, re.DOTALL)
|
||||
if not m:
|
||||
die('--issuer option was not used, and failed to extract issuer certificate from the certificate')
|
||||
write_file(issuer_fn, (m.group(1) + '\n').encode('utf-8'))
|
||||
|
||||
|
||||
def send_and_receive_ocsp(respder_fn, cmd, cert_fn, issuer_fn, ocsp_uri,
|
||||
ocsp_host, openssl_version):
|
||||
# obtain response (without verification)
|
||||
sys.stderr.write('sending OCSP request to {}\n'.format(ocsp_uri))
|
||||
args = [
|
||||
cmd, 'ocsp', '-issuer', issuer_fn, '-cert', cert_fn, '-url', ocsp_uri,
|
||||
'-noverify', '-respout', respder_fn
|
||||
]
|
||||
ver = openssl_version.lower()
|
||||
if ver.startswith('openssl 1.0.') or ver.startswith('libressl '):
|
||||
args.extend(['-header', 'Host', ocsp_host])
|
||||
resp = run_openssl(args, allow_tempfail=True)
|
||||
return resp.decode('utf-8')
|
||||
|
||||
|
||||
def verify_response(cmd, tempdir, issuer_fn, respder_fn):
|
||||
# verify the response
|
||||
sys.stderr.write('verifying the response signature\n')
|
||||
|
||||
verify_fn = os.path.join(tempdir, 'verify.out')
|
||||
|
||||
# try from exotic options
|
||||
allextra = [
|
||||
# for comodo
|
||||
['-VAfile', issuer_fn],
|
||||
# these options are only available in OpenSSL >= 1.0.2
|
||||
['-partial_chain', '-trusted_first', '-CAfile', issuer_fn],
|
||||
# for OpenSSL <= 1.0.1
|
||||
['-CAfile', issuer_fn],
|
||||
]
|
||||
|
||||
for extra in allextra:
|
||||
with open(verify_fn, 'w+b') as f:
|
||||
args = [cmd, 'ocsp', '-respin', respder_fn]
|
||||
args.extend(extra)
|
||||
p = subprocess.Popen(args, stdout=f, stderr=f)
|
||||
if p.wait() == 0:
|
||||
# OpenSSL <= 1.0.1, openssl ocsp still returns exit
|
||||
# code 0 even if verification was failed. So check
|
||||
# the error message in stderr output.
|
||||
f.seek(0)
|
||||
if f.read().decode('utf-8').find(
|
||||
'Response Verify Failure') != -1:
|
||||
continue
|
||||
sys.stderr.write('verify OK (used: {})\n'.format(extra))
|
||||
return True
|
||||
|
||||
sys.stderr.write(read_file(verify_fn).decode('utf-8'))
|
||||
return False
|
||||
|
||||
|
||||
def fetch_ocsp_response(cmd, cert_fn, tempdir, issuer_fn=None):
|
||||
openssl_version = detect_openssl_version(cmd)
|
||||
|
||||
sys.stderr.write(
|
||||
'fetch-ocsp-response (using {})\n'.format(openssl_version))
|
||||
|
||||
ocsp_uri = extract_ocsp_uri(cmd, cert_fn)
|
||||
ocsp_host = urlparse(ocsp_uri).netloc
|
||||
|
||||
if not issuer_fn:
|
||||
issuer_fn = os.path.join(tempdir, 'issuer.crt')
|
||||
save_issuer_certificate(issuer_fn, cert_fn)
|
||||
|
||||
respder_fn = os.path.join(tempdir, 'resp.der')
|
||||
resp = send_and_receive_ocsp(
|
||||
respder_fn, cmd, cert_fn, issuer_fn, ocsp_uri, ocsp_host,
|
||||
openssl_version)
|
||||
|
||||
sys.stderr.write('{}\n'.format(resp))
|
||||
|
||||
# OpenSSL 1.0.2 still returns exit code 0 even if ocsp responder
|
||||
# returned error status (e.g., trylater(3))
|
||||
if resp.find('Responder Error:') != -1:
|
||||
raise Exception('responder returned error')
|
||||
|
||||
if not verify_response(cmd, tempdir, issuer_fn, respder_fn):
|
||||
tempfail('failed to verify the response')
|
||||
|
||||
# success
|
||||
res = read_file(respder_fn)
|
||||
stdout_bwrite(res)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
parser = argparse.ArgumentParser(
|
||||
description=
|
||||
'''The command issues an OCSP request for given server certificate, verifies the response and prints the resulting DER.''',
|
||||
epilog=
|
||||
'''The command exits 0 if successful, or 75 (EX_TEMPFAIL) on temporary error. Other exit codes may be returned in case of hard errors.''')
|
||||
parser.add_argument(
|
||||
'--issuer',
|
||||
metavar='FILE',
|
||||
help=
|
||||
'issuer certificate (if omitted, is extracted from the certificate chain)')
|
||||
parser.add_argument('--openssl',
|
||||
metavar='CMD',
|
||||
help='openssl command to use (default: "openssl")',
|
||||
default='openssl')
|
||||
parser.add_argument('certificate',
|
||||
help='path to certificate file to validate')
|
||||
args = parser.parse_args()
|
||||
|
||||
tempdir = None
|
||||
try:
|
||||
# Python3.2 has tempfile.TemporaryDirectory, which has nice
|
||||
# feature to delete its tree by cleanup() function. We have
|
||||
# to support Python2.7, so we have to do this manually.
|
||||
tempdir = tempfile.mkdtemp()
|
||||
fetch_ocsp_response(args.openssl, args.certificate, tempdir,
|
||||
args.issuer)
|
||||
finally:
|
||||
if tempdir:
|
||||
shutil.rmtree(tempdir)
|
||||
@@ -16,7 +16,9 @@ include_directories(
|
||||
${LIBNGHTTP3_INCLUDE_DIRS}
|
||||
${LIBNGTCP2_INCLUDE_DIRS}
|
||||
${LIBNGTCP2_CRYPTO_QUICTLS_INCLUDE_DIRS}
|
||||
${LIBNGTCP2_CRYPTO_LIBRESSL_INCLUDE_DIRS}
|
||||
${LIBNGTCP2_CRYPTO_WOLFSSL_INCLUDE_DIRS}
|
||||
${LIBNGTCP2_CRYPTO_OSSL_INCLUDE_DIRS}
|
||||
${OPENSSL_INCLUDE_DIRS}
|
||||
${WOLFSSL_INCLUDE_DIRS}
|
||||
${LIBCARES_INCLUDE_DIRS}
|
||||
@@ -36,7 +38,9 @@ link_libraries(
|
||||
${LIBNGHTTP3_LIBRARIES}
|
||||
${LIBNGTCP2_LIBRARIES}
|
||||
${LIBNGTCP2_CRYPTO_QUICTLS_LIBRARIES}
|
||||
${LIBNGTCP2_CRYPTO_LIBRESSL_LIBRARIES}
|
||||
${LIBNGTCP2_CRYPTO_WOLFSSL_LIBRARIES}
|
||||
${LIBNGTCP2_CRYPTO_OSSL_LIBRARIES}
|
||||
${OPENSSL_LIBRARIES}
|
||||
${WOLFSSL_LIBRARIES}
|
||||
${LIBCARES_LIBRARIES}
|
||||
@@ -85,7 +89,6 @@ if(ENABLE_APP)
|
||||
list(APPEND H2LOAD_SOURCES
|
||||
h2load_http3_session.cc
|
||||
h2load_quic.cc
|
||||
quic.cc
|
||||
)
|
||||
endif()
|
||||
|
||||
@@ -125,7 +128,6 @@ if(ENABLE_APP)
|
||||
shrpx_api_downstream_connection.cc
|
||||
shrpx_health_monitor_downstream_connection.cc
|
||||
shrpx_null_downstream_connection.cc
|
||||
shrpx_exec.cc
|
||||
shrpx_dns_resolver.cc
|
||||
shrpx_dual_dns_resolver.cc
|
||||
shrpx_dns_tracker.cc
|
||||
@@ -147,7 +149,6 @@ if(ENABLE_APP)
|
||||
shrpx_quic_connection_handler.cc
|
||||
shrpx_http3_upstream.cc
|
||||
http3.cc
|
||||
quic.cc
|
||||
siphash.cc
|
||||
)
|
||||
endif()
|
||||
@@ -248,6 +249,7 @@ if(ENABLE_HPACK_TOOLS)
|
||||
comp_helper.c
|
||||
util.cc
|
||||
timegm.c
|
||||
tls.cc
|
||||
)
|
||||
add_executable(inflatehd ${inflatehd_SOURCES})
|
||||
add_executable(deflatehd ${deflatehd_SOURCES})
|
||||
|
||||
@@ -39,30 +39,28 @@ HtmlParser::HtmlParser(const std::string &base_uri)
|
||||
HtmlParser::~HtmlParser() { htmlFreeParserCtxt(parser_ctx_); }
|
||||
|
||||
namespace {
|
||||
StringRef get_attr(const xmlChar **attrs, const StringRef &name) {
|
||||
std::string_view get_attr(const xmlChar **attrs, const std::string_view &name) {
|
||||
if (attrs == nullptr) {
|
||||
return StringRef{};
|
||||
return ""sv;
|
||||
}
|
||||
for (; *attrs; attrs += 2) {
|
||||
if (util::strieq(
|
||||
StringRef{attrs[0], strlen(reinterpret_cast<const char *>(attrs[0]))},
|
||||
name)) {
|
||||
return StringRef{attrs[1],
|
||||
strlen(reinterpret_cast<const char *>(attrs[1]))};
|
||||
if (util::strieq(std::string_view{reinterpret_cast<const char *>(attrs[0])},
|
||||
name)) {
|
||||
return std::string_view{reinterpret_cast<const char *>(attrs[1])};
|
||||
}
|
||||
}
|
||||
return StringRef{};
|
||||
return ""sv;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
namespace {
|
||||
ResourceType
|
||||
get_resource_type_for_preload_as(const StringRef &attribute_value) {
|
||||
if (util::strieq("image"_sr, attribute_value)) {
|
||||
get_resource_type_for_preload_as(const std::string_view &attribute_value) {
|
||||
if (util::strieq("image"sv, attribute_value)) {
|
||||
return REQ_IMG;
|
||||
} else if (util::strieq("style"_sr, attribute_value)) {
|
||||
} else if (util::strieq("style"sv, attribute_value)) {
|
||||
return REQ_CSS;
|
||||
} else if (util::strieq("script"_sr, attribute_value)) {
|
||||
} else if (util::strieq("script"sv, attribute_value)) {
|
||||
return REQ_UNBLOCK_JS;
|
||||
} else {
|
||||
return REQ_OTHERS;
|
||||
@@ -71,7 +69,7 @@ get_resource_type_for_preload_as(const StringRef &attribute_value) {
|
||||
} // namespace
|
||||
|
||||
namespace {
|
||||
void add_link(ParserData *parser_data, const StringRef &uri,
|
||||
void add_link(ParserData *parser_data, const std::string_view &uri,
|
||||
ResourceType res_type) {
|
||||
auto u = xmlBuildURI(
|
||||
reinterpret_cast<const xmlChar *>(uri.data()),
|
||||
@@ -88,37 +86,36 @@ namespace {
|
||||
void start_element_func(void *user_data, const xmlChar *src_name,
|
||||
const xmlChar **attrs) {
|
||||
auto parser_data = static_cast<ParserData *>(user_data);
|
||||
auto name =
|
||||
StringRef{src_name, strlen(reinterpret_cast<const char *>(src_name))};
|
||||
if (util::strieq("head"_sr, name)) {
|
||||
auto name = std::string_view{reinterpret_cast<const char *>(src_name)};
|
||||
if (util::strieq("head"sv, name)) {
|
||||
++parser_data->inside_head;
|
||||
}
|
||||
if (util::strieq("link"_sr, name)) {
|
||||
auto rel_attr = get_attr(attrs, "rel"_sr);
|
||||
auto href_attr = get_attr(attrs, "href"_sr);
|
||||
if (util::strieq("link"sv, name)) {
|
||||
auto rel_attr = get_attr(attrs, "rel"sv);
|
||||
auto href_attr = get_attr(attrs, "href"sv);
|
||||
if (rel_attr.empty() || href_attr.empty()) {
|
||||
return;
|
||||
}
|
||||
if (util::strieq("shortcut icon"_sr, rel_attr)) {
|
||||
if (util::strieq("shortcut icon"sv, rel_attr)) {
|
||||
add_link(parser_data, href_attr, REQ_OTHERS);
|
||||
} else if (util::strieq("stylesheet"_sr, rel_attr)) {
|
||||
} else if (util::strieq("stylesheet"sv, rel_attr)) {
|
||||
add_link(parser_data, href_attr, REQ_CSS);
|
||||
} else if (util::strieq("preload"_sr, rel_attr)) {
|
||||
auto as_attr = get_attr(attrs, "as"_sr);
|
||||
} else if (util::strieq("preload"sv, rel_attr)) {
|
||||
auto as_attr = get_attr(attrs, "as"sv);
|
||||
if (as_attr.empty()) {
|
||||
return;
|
||||
}
|
||||
add_link(parser_data, href_attr,
|
||||
get_resource_type_for_preload_as(as_attr));
|
||||
}
|
||||
} else if (util::strieq("img"_sr, name)) {
|
||||
auto src_attr = get_attr(attrs, "src"_sr);
|
||||
} else if (util::strieq("img"sv, name)) {
|
||||
auto src_attr = get_attr(attrs, "src"sv);
|
||||
if (src_attr.empty()) {
|
||||
return;
|
||||
}
|
||||
add_link(parser_data, src_attr, REQ_IMG);
|
||||
} else if (util::strieq("script"_sr, name)) {
|
||||
auto src_attr = get_attr(attrs, "src"_sr);
|
||||
} else if (util::strieq("script"sv, name)) {
|
||||
auto src_attr = get_attr(attrs, "src"sv);
|
||||
if (src_attr.empty()) {
|
||||
return;
|
||||
}
|
||||
@@ -134,9 +131,8 @@ void start_element_func(void *user_data, const xmlChar *src_name,
|
||||
namespace {
|
||||
void end_element_func(void *user_data, const xmlChar *name) {
|
||||
auto parser_data = static_cast<ParserData *>(user_data);
|
||||
if (util::strieq(
|
||||
"head"_sr,
|
||||
StringRef{name, strlen(reinterpret_cast<const char *>(name))})) {
|
||||
if (util::strieq("head"sv,
|
||||
std::string_view{reinterpret_cast<const char *>(name)})) {
|
||||
--parser_data->inside_head;
|
||||
}
|
||||
}
|
||||
@@ -181,9 +177,9 @@ xmlSAXHandler saxHandler = {
|
||||
|
||||
int HtmlParser::parse_chunk(const char *chunk, size_t size, int fin) {
|
||||
if (!parser_ctx_) {
|
||||
parser_ctx_ =
|
||||
htmlCreatePushParserCtxt(&saxHandler, &parser_data_, chunk, size,
|
||||
base_uri_.c_str(), XML_CHAR_ENCODING_NONE);
|
||||
parser_ctx_ = htmlCreatePushParserCtxt(
|
||||
&saxHandler, &parser_data_, chunk, static_cast<int>(size),
|
||||
base_uri_.c_str(), XML_CHAR_ENCODING_NONE);
|
||||
if (!parser_ctx_) {
|
||||
return -1;
|
||||
} else {
|
||||
@@ -199,7 +195,7 @@ int HtmlParser::parse_chunk(const char *chunk, size_t size, int fin) {
|
||||
}
|
||||
|
||||
int HtmlParser::parse_chunk_internal(const char *chunk, size_t size, int fin) {
|
||||
int rv = htmlParseChunk(parser_ctx_, chunk, size, fin);
|
||||
int rv = htmlParseChunk(parser_ctx_, chunk, static_cast<int>(size), fin);
|
||||
if (rv == 0) {
|
||||
return 0;
|
||||
} else {
|
||||
|
||||
@@ -31,10 +31,8 @@
|
||||
#include <string>
|
||||
|
||||
#ifdef HAVE_LIBXML2
|
||||
|
||||
# include <libxml/HTMLparser.h>
|
||||
|
||||
#endif // HAVE_LIBXML2
|
||||
#endif // defined(HAVE_LIBXML2)
|
||||
|
||||
namespace nghttp2 {
|
||||
|
||||
@@ -72,7 +70,7 @@ private:
|
||||
ParserData parser_data_;
|
||||
};
|
||||
|
||||
#else // !HAVE_LIBXML2
|
||||
#else // !defined(HAVE_LIBXML2)
|
||||
|
||||
class HtmlParser {
|
||||
public:
|
||||
@@ -87,8 +85,8 @@ private:
|
||||
std::vector<std::pair<std::string, ResourceType>> links_;
|
||||
};
|
||||
|
||||
#endif // !HAVE_LIBXML2
|
||||
#endif // !defined(HAVE_LIBXML2)
|
||||
|
||||
} // namespace nghttp2
|
||||
|
||||
#endif // HTML_PARSER_H
|
||||
#endif // !defined(HTML_PARSER_H)
|
||||
|
||||
@@ -27,26 +27,26 @@
|
||||
#include <sys/stat.h>
|
||||
#ifdef HAVE_SYS_SOCKET_H
|
||||
# include <sys/socket.h>
|
||||
#endif // HAVE_SYS_SOCKET_H
|
||||
#endif // defined(HAVE_SYS_SOCKET_H)
|
||||
#ifdef HAVE_NETDB_H
|
||||
# include <netdb.h>
|
||||
#endif // HAVE_NETDB_H
|
||||
#endif // defined(HAVE_NETDB_H)
|
||||
#ifdef HAVE_UNISTD_H
|
||||
# include <unistd.h>
|
||||
#endif // HAVE_UNISTD_H
|
||||
#endif // defined(HAVE_UNISTD_H)
|
||||
#ifdef HAVE_FCNTL_H
|
||||
# include <fcntl.h>
|
||||
#endif // HAVE_FCNTL_H
|
||||
#endif // defined(HAVE_FCNTL_H)
|
||||
#ifdef HAVE_NETINET_IN_H
|
||||
# include <netinet/in.h>
|
||||
#endif // HAVE_NETINET_IN_H
|
||||
#endif // defined(HAVE_NETINET_IN_H)
|
||||
#include <netinet/tcp.h>
|
||||
#ifdef HAVE_ARPA_INET_H
|
||||
# include <arpa/inet.h>
|
||||
#endif // HAVE_ARPA_INET_H
|
||||
#endif // defined(HAVE_ARPA_INET_H)
|
||||
|
||||
#include <cassert>
|
||||
#include <set>
|
||||
#include <unordered_set>
|
||||
#include <iostream>
|
||||
#include <thread>
|
||||
#include <mutex>
|
||||
@@ -58,13 +58,13 @@
|
||||
# include <wolfssl/options.h>
|
||||
# include <wolfssl/openssl/err.h>
|
||||
# include <wolfssl/openssl/dh.h>
|
||||
#else // !NGHTTP2_OPENSSL_IS_WOLFSSL
|
||||
#else // !defined(NGHTTP2_OPENSSL_IS_WOLFSSL)
|
||||
# include <openssl/err.h>
|
||||
# include <openssl/dh.h>
|
||||
# if OPENSSL_3_0_0_API
|
||||
# include <openssl/decoder.h>
|
||||
# endif // OPENSSL_3_0_0_API
|
||||
#endif // !NGHTTP2_OPENSSL_IS_WOLFSSL
|
||||
#endif // !defined(NGHTTP2_OPENSSL_IS_WOLFSSL)
|
||||
|
||||
#include <zlib.h>
|
||||
|
||||
@@ -76,16 +76,17 @@
|
||||
|
||||
#ifndef O_BINARY
|
||||
# define O_BINARY (0)
|
||||
#endif // O_BINARY
|
||||
#endif // !defined(O_BINARY)
|
||||
|
||||
using namespace std::chrono_literals;
|
||||
using namespace std::string_literals;
|
||||
|
||||
namespace nghttp2 {
|
||||
|
||||
namespace {
|
||||
// TODO could be constexpr
|
||||
constexpr auto DEFAULT_HTML = "index.html"_sr;
|
||||
constexpr auto NGHTTPD_SERVER = "nghttpd nghttp2/" NGHTTP2_VERSION ""_sr;
|
||||
constexpr auto DEFAULT_HTML = "index.html"sv;
|
||||
constexpr auto NGHTTPD_SERVER = "nghttpd nghttp2/" NGHTTP2_VERSION ""sv;
|
||||
} // namespace
|
||||
|
||||
namespace {
|
||||
@@ -101,6 +102,7 @@ void print_session_id(int64_t id) { std::cout << "[id=" << id << "] "; }
|
||||
|
||||
Config::Config()
|
||||
: mime_types_file("/etc/mime.types"),
|
||||
groups("X25519:P-256:P-384:P-521"sv),
|
||||
stream_read_timeout(1_min),
|
||||
stream_write_timeout(1_min),
|
||||
data_ptr(nullptr),
|
||||
@@ -250,7 +252,9 @@ public:
|
||||
option_(nullptr),
|
||||
next_session_id_(1),
|
||||
tstamp_cached_(ev_now(loop)),
|
||||
cached_date_(util::http_date(tstamp_cached_)) {
|
||||
cached_date_(
|
||||
util::format_http_date(std::chrono::system_clock::from_time_t(
|
||||
static_cast<time_t>(tstamp_cached_)))) {
|
||||
nghttp2_session_callbacks_new(&callbacks_);
|
||||
|
||||
fill_callback(callbacks_, config_);
|
||||
@@ -259,7 +263,7 @@ public:
|
||||
|
||||
if (config_->encoder_header_table_size != -1) {
|
||||
nghttp2_option_set_max_deflate_dynamic_table_size(
|
||||
option_, config_->encoder_header_table_size);
|
||||
option_, as_unsigned(config_->encoder_header_table_size));
|
||||
}
|
||||
|
||||
ev_timer_init(&release_fd_timer_, release_fd_cb, 0., RELEASE_FD_TIMEOUT);
|
||||
@@ -326,7 +330,11 @@ public:
|
||||
}
|
||||
add_handler(handler.release());
|
||||
}
|
||||
void update_cached_date() { cached_date_ = util::http_date(tstamp_cached_); }
|
||||
void update_cached_date() {
|
||||
cached_date_ =
|
||||
util::format_http_date(std::chrono::system_clock::from_time_t(
|
||||
static_cast<time_t>(tstamp_cached_)));
|
||||
}
|
||||
const std::string &get_cached_date() {
|
||||
auto t = ev_now(loop_);
|
||||
if (t != tstamp_cached_) {
|
||||
@@ -370,19 +378,13 @@ public:
|
||||
return nullptr;
|
||||
}
|
||||
FileEntry *cache_fd(const std::string &path, const FileEntry &ent) {
|
||||
#ifdef HAVE_STD_MAP_EMPLACE
|
||||
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, std::make_unique<FileEntry>(ent)));
|
||||
#endif // !HAVE_STD_MAP_EMPLACE
|
||||
auto &res = (*rv).second;
|
||||
res->it = rv;
|
||||
fd_cache_lru_.append(res.get());
|
||||
|
||||
while (fd_cache_.size() > FILE_ENTRY_EVICT_THRES) {
|
||||
auto ent = fd_cache_lru_.head;
|
||||
auto ent = fd_cache_lru_.front();
|
||||
if (ent->usecount) {
|
||||
break;
|
||||
}
|
||||
@@ -407,7 +409,8 @@ public:
|
||||
// cache. The timer will be started when there is no handler.
|
||||
}
|
||||
void release_unused_fd() {
|
||||
for (auto i = std::begin(fd_cache_); i != std::end(fd_cache_);) {
|
||||
for (auto i = std::ranges::begin(fd_cache_);
|
||||
i != std::ranges::end(fd_cache_);) {
|
||||
auto &ent = (*i).second;
|
||||
if (ent->usecount != 0) {
|
||||
++i;
|
||||
@@ -423,10 +426,10 @@ public:
|
||||
bool handlers_empty() const { return handlers_.empty(); }
|
||||
|
||||
private:
|
||||
std::set<Http2Handler *> handlers_;
|
||||
std::unordered_set<Http2Handler *> handlers_;
|
||||
// cache for file descriptors to read file.
|
||||
std::multimap<std::string, std::unique_ptr<FileEntry>> fd_cache_;
|
||||
DList<FileEntry> fd_cache_lru_;
|
||||
std::unordered_multimap<std::string, std::unique_ptr<FileEntry>> fd_cache_;
|
||||
SList<FileEntry, &FileEntry::slent> fd_cache_lru_;
|
||||
HttpServer *sv_;
|
||||
struct ev_loop *loop_;
|
||||
const Config *config_;
|
||||
@@ -615,16 +618,16 @@ int Http2Handler::fill_wb() {
|
||||
|
||||
if (datalen < 0) {
|
||||
std::cerr << "nghttp2_session_mem_send2() returned error: "
|
||||
<< nghttp2_strerror(datalen) << std::endl;
|
||||
<< nghttp2_strerror(static_cast<int>(datalen)) << std::endl;
|
||||
return -1;
|
||||
}
|
||||
if (datalen == 0) {
|
||||
break;
|
||||
}
|
||||
auto n = wb_.write(data, datalen);
|
||||
auto n = wb_.write(data, as_unsigned(datalen));
|
||||
if (n < static_cast<decltype(n)>(datalen)) {
|
||||
data_pending_ = data + n;
|
||||
data_pendinglen_ = datalen - n;
|
||||
data_pendinglen_ = as_unsigned(datalen) - n;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -632,7 +635,6 @@ int Http2Handler::fill_wb() {
|
||||
}
|
||||
|
||||
int Http2Handler::read_clear() {
|
||||
int rv;
|
||||
std::array<uint8_t, 8_k> buf;
|
||||
|
||||
ssize_t nread;
|
||||
@@ -649,14 +651,15 @@ int Http2Handler::read_clear() {
|
||||
}
|
||||
|
||||
if (get_config()->hexdump) {
|
||||
util::hexdump(stdout, buf.data(), nread);
|
||||
util::hexdump(stdout, buf.data(), as_unsigned(nread));
|
||||
}
|
||||
|
||||
rv = nghttp2_session_mem_recv2(session_, buf.data(), nread);
|
||||
if (rv < 0) {
|
||||
if (rv != NGHTTP2_ERR_BAD_CLIENT_MAGIC) {
|
||||
auto nrecv =
|
||||
nghttp2_session_mem_recv2(session_, buf.data(), as_unsigned(nread));
|
||||
if (nrecv < 0) {
|
||||
if (nrecv != NGHTTP2_ERR_BAD_CLIENT_MAGIC) {
|
||||
std::cerr << "nghttp2_session_mem_recv2() returned error: "
|
||||
<< nghttp2_strerror(rv) << std::endl;
|
||||
<< nghttp2_strerror(static_cast<int>(nrecv)) << std::endl;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
@@ -679,7 +682,7 @@ int Http2Handler::write_clear() {
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
wb_.drain(nwrite);
|
||||
wb_.drain(as_unsigned(nwrite));
|
||||
continue;
|
||||
}
|
||||
wb_.reset();
|
||||
@@ -770,17 +773,17 @@ int Http2Handler::read_tls() {
|
||||
}
|
||||
}
|
||||
|
||||
auto nread = rv;
|
||||
auto nread = static_cast<size_t>(rv);
|
||||
|
||||
if (get_config()->hexdump) {
|
||||
util::hexdump(stdout, buf.data(), nread);
|
||||
}
|
||||
|
||||
rv = nghttp2_session_mem_recv2(session_, buf.data(), nread);
|
||||
if (rv < 0) {
|
||||
if (rv != NGHTTP2_ERR_BAD_CLIENT_MAGIC) {
|
||||
auto nrecv = nghttp2_session_mem_recv2(session_, buf.data(), nread);
|
||||
if (nrecv < 0) {
|
||||
if (nrecv != NGHTTP2_ERR_BAD_CLIENT_MAGIC) {
|
||||
std::cerr << "nghttp2_session_mem_recv2() returned error: "
|
||||
<< nghttp2_strerror(rv) << std::endl;
|
||||
<< nghttp2_strerror(static_cast<int>(nrecv)) << std::endl;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
@@ -800,7 +803,7 @@ int Http2Handler::write_tls() {
|
||||
|
||||
for (;;) {
|
||||
if (wb_.rleft() > 0) {
|
||||
auto rv = SSL_write(ssl_, wb_.pos, wb_.rleft());
|
||||
auto rv = SSL_write(ssl_, wb_.pos, static_cast<int>(wb_.rleft()));
|
||||
|
||||
if (rv <= 0) {
|
||||
auto err = SSL_get_error(ssl_, rv);
|
||||
@@ -816,7 +819,7 @@ int Http2Handler::write_tls() {
|
||||
}
|
||||
}
|
||||
|
||||
wb_.drain(rv);
|
||||
wb_.drain(static_cast<size_t>(rv));
|
||||
continue;
|
||||
}
|
||||
wb_.reset();
|
||||
@@ -861,14 +864,14 @@ int Http2Handler::connection_made() {
|
||||
size_t niv = 2;
|
||||
|
||||
entry[0].settings_id = NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS;
|
||||
entry[0].value = config->max_concurrent_streams;
|
||||
entry[0].value = static_cast<uint32_t>(config->max_concurrent_streams);
|
||||
|
||||
entry[1].settings_id = NGHTTP2_SETTINGS_NO_RFC7540_PRIORITIES;
|
||||
entry[1].value = 1;
|
||||
|
||||
if (config->header_table_size >= 0) {
|
||||
entry[niv].settings_id = NGHTTP2_SETTINGS_HEADER_TABLE_SIZE;
|
||||
entry[niv].value = config->header_table_size;
|
||||
entry[niv].value = static_cast<uint32_t>(config->header_table_size);
|
||||
++niv;
|
||||
}
|
||||
|
||||
@@ -905,7 +908,7 @@ int Http2Handler::verify_alpn_result() {
|
||||
// Check the negotiated protocol in ALPN
|
||||
SSL_get0_alpn_selected(ssl_, &next_proto, &next_proto_len);
|
||||
if (next_proto) {
|
||||
auto proto = StringRef{next_proto, next_proto_len};
|
||||
auto proto = as_string_view(next_proto, next_proto_len);
|
||||
if (sessions_->get_config()->verbose) {
|
||||
std::cout << "The negotiated protocol: " << proto << std::endl;
|
||||
}
|
||||
@@ -921,16 +924,17 @@ int Http2Handler::verify_alpn_result() {
|
||||
return -1;
|
||||
}
|
||||
|
||||
int Http2Handler::submit_file_response(const StringRef &status, Stream *stream,
|
||||
time_t last_modified, off_t file_length,
|
||||
int Http2Handler::submit_file_response(const std::string_view &status,
|
||||
Stream *stream, time_t last_modified,
|
||||
off_t file_length,
|
||||
const std::string *content_type,
|
||||
nghttp2_data_provider2 *data_prd) {
|
||||
std::string last_modified_str;
|
||||
auto nva = std::to_array({
|
||||
http2::make_field(":status"_sr, status),
|
||||
http2::make_field("server"_sr, NGHTTPD_SERVER),
|
||||
http2::make_field("cache-control"_sr, "max-age=3600"_sr),
|
||||
http2::make_field_v("date"_sr, sessions_->get_cached_date()),
|
||||
http2::make_field(":status"sv, status),
|
||||
http2::make_field("server"sv, NGHTTPD_SERVER),
|
||||
http2::make_field("cache-control"sv, "max-age=3600"sv),
|
||||
http2::make_field_v("date"sv, sessions_->get_cached_date()),
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
@@ -939,37 +943,38 @@ int Http2Handler::submit_file_response(const StringRef &status, Stream *stream,
|
||||
size_t nvlen = 4;
|
||||
if (!get_config()->no_content_length) {
|
||||
nva[nvlen++] = http2::make_field(
|
||||
"content-length"_sr,
|
||||
util::make_string_ref_uint(stream->balloc, file_length));
|
||||
"content-length"sv,
|
||||
util::make_string_ref_uint(stream->balloc, as_unsigned(file_length)));
|
||||
}
|
||||
if (last_modified != 0) {
|
||||
last_modified_str = util::http_date(last_modified);
|
||||
nva[nvlen++] = http2::make_field_v("last-modified"_sr, last_modified_str);
|
||||
last_modified_str = util::format_http_date(
|
||||
std::chrono::system_clock::from_time_t(last_modified));
|
||||
nva[nvlen++] = http2::make_field_v("last-modified"sv, last_modified_str);
|
||||
}
|
||||
if (content_type) {
|
||||
nva[nvlen++] = http2::make_field_v("content-type"_sr, *content_type);
|
||||
nva[nvlen++] = http2::make_field_v("content-type"sv, *content_type);
|
||||
}
|
||||
auto &trailer_names = get_config()->trailer_names;
|
||||
if (!trailer_names.empty()) {
|
||||
nva[nvlen++] = http2::make_field("trailer"_sr, trailer_names);
|
||||
nva[nvlen++] = http2::make_field("trailer"sv, trailer_names);
|
||||
}
|
||||
return nghttp2_submit_response2(session_, stream->stream_id, nva.data(),
|
||||
nvlen, data_prd);
|
||||
}
|
||||
|
||||
int Http2Handler::submit_response(const StringRef &status, int32_t stream_id,
|
||||
const HeaderRefs &headers,
|
||||
int Http2Handler::submit_response(const std::string_view &status,
|
||||
int32_t stream_id, const HeaderRefs &headers,
|
||||
nghttp2_data_provider2 *data_prd) {
|
||||
auto nva = std::vector<nghttp2_nv>();
|
||||
nva.reserve(4 + headers.size());
|
||||
nva.push_back(http2::make_field(":status"_sr, status));
|
||||
nva.push_back(http2::make_field("server"_sr, NGHTTPD_SERVER));
|
||||
nva.push_back(http2::make_field_v("date"_sr, sessions_->get_cached_date()));
|
||||
nva.push_back(http2::make_field(":status"sv, status));
|
||||
nva.push_back(http2::make_field("server"sv, NGHTTPD_SERVER));
|
||||
nva.push_back(http2::make_field_v("date"sv, sessions_->get_cached_date()));
|
||||
|
||||
if (data_prd) {
|
||||
auto &trailer_names = get_config()->trailer_names;
|
||||
if (!trailer_names.empty()) {
|
||||
nva.push_back(http2::make_field("trailer"_sr, trailer_names));
|
||||
nva.push_back(http2::make_field("trailer"sv, trailer_names));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -982,12 +987,13 @@ int Http2Handler::submit_response(const StringRef &status, int32_t stream_id,
|
||||
return r;
|
||||
}
|
||||
|
||||
int Http2Handler::submit_response(const StringRef &status, int32_t stream_id,
|
||||
int Http2Handler::submit_response(const std::string_view &status,
|
||||
int32_t stream_id,
|
||||
nghttp2_data_provider2 *data_prd) {
|
||||
auto nva = std::to_array({
|
||||
http2::make_field(":status"_sr, status),
|
||||
http2::make_field("server"_sr, NGHTTPD_SERVER),
|
||||
http2::make_field_v("date"_sr, sessions_->get_cached_date()),
|
||||
http2::make_field(":status"sv, status),
|
||||
http2::make_field("server"sv, NGHTTPD_SERVER),
|
||||
http2::make_field_v("date"sv, sessions_->get_cached_date()),
|
||||
{},
|
||||
});
|
||||
size_t nvlen = 3;
|
||||
@@ -995,7 +1001,7 @@ int Http2Handler::submit_response(const StringRef &status, int32_t stream_id,
|
||||
if (data_prd) {
|
||||
auto &trailer_names = get_config()->trailer_names;
|
||||
if (!trailer_names.empty()) {
|
||||
nva[nvlen++] = http2::make_field("trailer"_sr, trailer_names);
|
||||
nva[nvlen++] = http2::make_field("trailer"sv, trailer_names);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1005,25 +1011,25 @@ int Http2Handler::submit_response(const StringRef &status, int32_t stream_id,
|
||||
|
||||
int Http2Handler::submit_non_final_response(const std::string &status,
|
||||
int32_t stream_id) {
|
||||
auto nva = std::to_array({http2::make_field_v(":status"_sr, status)});
|
||||
auto nva = std::to_array({http2::make_field_v(":status"sv, status)});
|
||||
return nghttp2_submit_headers(session_, NGHTTP2_FLAG_NONE, stream_id, nullptr,
|
||||
nva.data(), nva.size(), nullptr);
|
||||
}
|
||||
|
||||
int Http2Handler::submit_push_promise(Stream *stream,
|
||||
const StringRef &push_path) {
|
||||
const std::string_view &push_path) {
|
||||
auto authority = stream->header.authority;
|
||||
|
||||
if (authority.empty()) {
|
||||
authority = stream->header.host;
|
||||
}
|
||||
|
||||
auto scheme = get_config()->no_tls ? "http"_sr : "https"_sr;
|
||||
auto scheme = get_config()->no_tls ? "http"sv : "https"sv;
|
||||
|
||||
auto nva = std::to_array({http2::make_field(":method"_sr, "GET"_sr),
|
||||
http2::make_field(":path"_sr, push_path),
|
||||
http2::make_field(":scheme"_sr, scheme),
|
||||
http2::make_field(":authority"_sr, authority)});
|
||||
auto nva = std::to_array({http2::make_field(":method"sv, "GET"sv),
|
||||
http2::make_field(":path"sv, push_path),
|
||||
http2::make_field(":scheme"sv, scheme),
|
||||
http2::make_field(":authority"sv, authority)});
|
||||
|
||||
auto promised_stream_id = nghttp2_submit_push_promise(
|
||||
session_, NGHTTP2_FLAG_END_HEADERS, stream->stream_id, nva.data(),
|
||||
@@ -1036,7 +1042,7 @@ int Http2Handler::submit_push_promise(Stream *stream,
|
||||
auto promised_stream = std::make_unique<Stream>(this, promised_stream_id);
|
||||
|
||||
auto &promised_header = promised_stream->header;
|
||||
promised_header.method = "GET"_sr;
|
||||
promised_header.method = "GET"sv;
|
||||
promised_header.path = push_path;
|
||||
promised_header.scheme = scheme;
|
||||
promised_header.authority =
|
||||
@@ -1066,7 +1072,7 @@ void Http2Handler::remove_stream(int32_t stream_id) {
|
||||
|
||||
Stream *Http2Handler::get_stream(int32_t stream_id) {
|
||||
auto itr = id2stream_.find(stream_id);
|
||||
if (itr == std::end(id2stream_)) {
|
||||
if (itr == std::ranges::end(id2stream_)) {
|
||||
return nullptr;
|
||||
} else {
|
||||
return (*itr).second.get();
|
||||
@@ -1148,12 +1154,12 @@ void prepare_status_response(Stream *stream, Http2Handler *hd, int status) {
|
||||
|
||||
HeaderRefs headers;
|
||||
headers.reserve(2);
|
||||
headers.emplace_back("content-type"_sr, "text/html; charset=UTF-8"_sr);
|
||||
headers.emplace_back("content-type"sv, "text/html; charset=UTF-8"sv);
|
||||
headers.emplace_back(
|
||||
"content-length"_sr,
|
||||
util::make_string_ref_uint(stream->balloc, file_ent->length));
|
||||
hd->submit_response(StringRef{status_page->status}, stream->stream_id,
|
||||
headers, &data_prd);
|
||||
"content-length"sv,
|
||||
util::make_string_ref_uint(stream->balloc, as_unsigned(file_ent->length)));
|
||||
hd->submit_response(status_page->status, stream->stream_id, headers,
|
||||
&data_prd);
|
||||
}
|
||||
} // namespace
|
||||
|
||||
@@ -1174,13 +1180,14 @@ void prepare_echo_response(Stream *stream, Http2Handler *hd) {
|
||||
data_prd.read_callback = file_read_callback;
|
||||
|
||||
HeaderRefs headers;
|
||||
headers.emplace_back("nghttpd-response"_sr, "echo"_sr);
|
||||
headers.emplace_back("nghttpd-response"sv, "echo"sv);
|
||||
if (!hd->get_config()->no_content_length) {
|
||||
headers.emplace_back("content-length"_sr,
|
||||
util::make_string_ref_uint(stream->balloc, length));
|
||||
headers.emplace_back(
|
||||
"content-length"sv,
|
||||
util::make_string_ref_uint(stream->balloc, as_unsigned(length)));
|
||||
}
|
||||
|
||||
hd->submit_response("200"_sr, stream->stream_id, headers, &data_prd);
|
||||
hd->submit_response("200"sv, stream->stream_id, headers, &data_prd);
|
||||
}
|
||||
} // namespace
|
||||
|
||||
@@ -1206,7 +1213,7 @@ bool prepare_upload_temp_store(Stream *stream, Http2Handler *hd) {
|
||||
|
||||
namespace {
|
||||
void prepare_redirect_response(Stream *stream, Http2Handler *hd,
|
||||
const StringRef &path, int status) {
|
||||
const std::string_view &path, int status) {
|
||||
auto scheme = stream->header.scheme;
|
||||
|
||||
auto authority = stream->header.authority;
|
||||
@@ -1215,15 +1222,14 @@ void prepare_redirect_response(Stream *stream, Http2Handler *hd,
|
||||
}
|
||||
|
||||
auto location =
|
||||
concat_string_ref(stream->balloc, scheme, "://"_sr, authority, path);
|
||||
concat_string_ref(stream->balloc, scheme, "://"sv, authority, path);
|
||||
|
||||
auto headers = HeaderRefs{{"location"_sr, location}};
|
||||
auto headers = HeaderRefs{{"location"sv, location}};
|
||||
|
||||
auto sessions = hd->get_sessions();
|
||||
auto status_page = sessions->get_server()->get_status_page(status);
|
||||
|
||||
hd->submit_response(StringRef{status_page->status}, stream->stream_id,
|
||||
headers, nullptr);
|
||||
hd->submit_response(status_page->status, stream->stream_id, headers, nullptr);
|
||||
}
|
||||
} // namespace
|
||||
|
||||
@@ -1246,34 +1252,32 @@ void prepare_response(Stream *stream, Http2Handler *hd,
|
||||
last_mod = util::parse_http_date(ims);
|
||||
}
|
||||
|
||||
StringRef raw_path, raw_query;
|
||||
auto query_pos = std::find(std::begin(reqpath), std::end(reqpath), '?');
|
||||
if (query_pos != std::end(reqpath)) {
|
||||
std::string_view raw_path, raw_query;
|
||||
auto query_pos = std::ranges::find(reqpath, '?');
|
||||
if (query_pos != std::ranges::end(reqpath)) {
|
||||
// Do not response to this request to allow clients to test timeouts.
|
||||
if ("nghttpd_do_not_respond_to_req=yes"_sr ==
|
||||
StringRef{query_pos, std::end(reqpath)}) {
|
||||
if ("nghttpd_do_not_respond_to_req=yes"sv ==
|
||||
std::string_view{query_pos, std::ranges::end(reqpath)}) {
|
||||
return;
|
||||
}
|
||||
raw_path = StringRef{std::begin(reqpath), query_pos};
|
||||
raw_query = StringRef{query_pos, std::end(reqpath)};
|
||||
raw_path = std::string_view{std::ranges::begin(reqpath), query_pos};
|
||||
raw_query = std::string_view{query_pos, std::ranges::end(reqpath)};
|
||||
} else {
|
||||
raw_path = reqpath;
|
||||
}
|
||||
|
||||
auto sessions = hd->get_sessions();
|
||||
|
||||
StringRef path;
|
||||
if (std::find(std::begin(raw_path), std::end(raw_path), '%') ==
|
||||
std::end(raw_path)) {
|
||||
path = raw_path;
|
||||
} else {
|
||||
std::string_view path;
|
||||
if (util::contains(raw_path, '%')) {
|
||||
path = util::percent_decode(stream->balloc, raw_path);
|
||||
} else {
|
||||
path = raw_path;
|
||||
}
|
||||
|
||||
path = http2::path_join(stream->balloc, StringRef{}, StringRef{}, path,
|
||||
StringRef{});
|
||||
path = http2::path_join(stream->balloc, ""sv, ""sv, path, ""sv);
|
||||
|
||||
if (std::find(std::begin(path), std::end(path), '\\') != std::end(path)) {
|
||||
if (util::contains(path, '\\')) {
|
||||
if (stream->file_ent) {
|
||||
sessions->release_fd(stream->file_ent);
|
||||
stream->file_ent = nullptr;
|
||||
@@ -1284,9 +1288,9 @@ void prepare_response(Stream *stream, Http2Handler *hd,
|
||||
|
||||
if (!hd->get_config()->push.empty()) {
|
||||
auto push_itr = hd->get_config()->push.find(std::string{path});
|
||||
if (allow_push && push_itr != std::end(hd->get_config()->push)) {
|
||||
if (allow_push && push_itr != std::ranges::end(hd->get_config()->push)) {
|
||||
for (auto &push_path : (*push_itr).second) {
|
||||
rv = hd->submit_push_promise(stream, StringRef{push_path});
|
||||
rv = hd->submit_push_promise(stream, push_path);
|
||||
if (rv != 0) {
|
||||
std::cerr << "nghttp2_submit_push_promise() returned error: "
|
||||
<< nghttp2_strerror(rv) << std::endl;
|
||||
@@ -1309,10 +1313,10 @@ void prepare_response(Stream *stream, Http2Handler *hd,
|
||||
auto p = &file_path[0];
|
||||
|
||||
auto &htdocs = hd->get_config()->htdocs;
|
||||
p = std::copy(std::begin(htdocs), std::end(htdocs), p);
|
||||
p = std::copy(std::begin(path), std::end(path), p);
|
||||
p = std::ranges::copy(htdocs, p).out;
|
||||
p = std::ranges::copy(path, p).out;
|
||||
if (trailing_slash) {
|
||||
std::copy(std::begin(DEFAULT_HTML), std::end(DEFAULT_HTML), p);
|
||||
std::ranges::copy(DEFAULT_HTML, p);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1345,7 +1349,7 @@ void prepare_response(Stream *stream, Http2Handler *hd,
|
||||
close(file);
|
||||
|
||||
auto reqpath =
|
||||
concat_string_ref(stream->balloc, raw_path, "/"_sr, raw_query);
|
||||
concat_string_ref(stream->balloc, raw_path, "/"sv, raw_query);
|
||||
|
||||
prepare_redirect_response(stream, hd, reqpath, 301);
|
||||
|
||||
@@ -1362,7 +1366,7 @@ void prepare_response(Stream *stream, Http2Handler *hd,
|
||||
|
||||
const auto &mime_types = hd->get_config()->mime_types;
|
||||
auto content_type_itr = mime_types.find(ext);
|
||||
if (content_type_itr != std::end(mime_types)) {
|
||||
if (content_type_itr != std::ranges::end(mime_types)) {
|
||||
content_type = &(*content_type_itr).second;
|
||||
}
|
||||
}
|
||||
@@ -1375,15 +1379,15 @@ void prepare_response(Stream *stream, Http2Handler *hd,
|
||||
stream->file_ent = file_ent;
|
||||
|
||||
if (last_mod_found && file_ent->mtime <= last_mod) {
|
||||
hd->submit_response("304"_sr, stream->stream_id, nullptr);
|
||||
hd->submit_response("304"sv, stream->stream_id, nullptr);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
auto method = stream->header.method;
|
||||
if (method == "HEAD"_sr) {
|
||||
hd->submit_file_response("200"_sr, stream, file_ent->mtime,
|
||||
file_ent->length, file_ent->content_type, nullptr);
|
||||
if (method == "HEAD"sv) {
|
||||
hd->submit_file_response("200"sv, stream, file_ent->mtime, file_ent->length,
|
||||
file_ent->content_type, nullptr);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1394,7 +1398,7 @@ void prepare_response(Stream *stream, Http2Handler *hd,
|
||||
data_prd.source.fd = file_ent->fd;
|
||||
data_prd.read_callback = file_read_callback;
|
||||
|
||||
hd->submit_file_response("200"_sr, stream, file_ent->mtime, file_ent->length,
|
||||
hd->submit_file_response("200"sv, stream, file_ent->mtime, file_ent->length,
|
||||
file_ent->content_type, &data_prd);
|
||||
}
|
||||
} // namespace
|
||||
@@ -1429,43 +1433,43 @@ int on_header_callback2(nghttp2_session *session, const nghttp2_frame *frame,
|
||||
|
||||
stream->header_buffer_size += namebuf.len + valuebuf.len;
|
||||
|
||||
auto token = http2::lookup_token(StringRef{namebuf.base, namebuf.len});
|
||||
auto token = http2::lookup_token(as_string_view(namebuf.base, namebuf.len));
|
||||
|
||||
auto &header = stream->header;
|
||||
|
||||
switch (token) {
|
||||
case http2::HD__METHOD:
|
||||
header.method = StringRef{valuebuf.base, valuebuf.len};
|
||||
header.method = as_string_view(valuebuf.base, valuebuf.len);
|
||||
header.rcbuf.method = value;
|
||||
nghttp2_rcbuf_incref(value);
|
||||
break;
|
||||
case http2::HD__SCHEME:
|
||||
header.scheme = StringRef{valuebuf.base, valuebuf.len};
|
||||
header.scheme = as_string_view(valuebuf.base, valuebuf.len);
|
||||
header.rcbuf.scheme = value;
|
||||
nghttp2_rcbuf_incref(value);
|
||||
break;
|
||||
case http2::HD__AUTHORITY:
|
||||
header.authority = StringRef{valuebuf.base, valuebuf.len};
|
||||
header.authority = as_string_view(valuebuf.base, valuebuf.len);
|
||||
header.rcbuf.authority = value;
|
||||
nghttp2_rcbuf_incref(value);
|
||||
break;
|
||||
case http2::HD_HOST:
|
||||
header.host = StringRef{valuebuf.base, valuebuf.len};
|
||||
header.host = as_string_view(valuebuf.base, valuebuf.len);
|
||||
header.rcbuf.host = value;
|
||||
nghttp2_rcbuf_incref(value);
|
||||
break;
|
||||
case http2::HD__PATH:
|
||||
header.path = StringRef{valuebuf.base, valuebuf.len};
|
||||
header.path = as_string_view(valuebuf.base, valuebuf.len);
|
||||
header.rcbuf.path = value;
|
||||
nghttp2_rcbuf_incref(value);
|
||||
break;
|
||||
case http2::HD_IF_MODIFIED_SINCE:
|
||||
header.ims = StringRef{valuebuf.base, valuebuf.len};
|
||||
header.ims = as_string_view(valuebuf.base, valuebuf.len);
|
||||
header.rcbuf.ims = value;
|
||||
nghttp2_rcbuf_incref(value);
|
||||
break;
|
||||
case http2::HD_EXPECT:
|
||||
header.expect = StringRef{valuebuf.base, valuebuf.len};
|
||||
header.expect = as_string_view(valuebuf.base, valuebuf.len);
|
||||
header.rcbuf.expect = value;
|
||||
nghttp2_rcbuf_incref(value);
|
||||
break;
|
||||
@@ -1531,13 +1535,13 @@ int hd_on_frame_recv_callback(nghttp2_session *session,
|
||||
if (frame->headers.cat == NGHTTP2_HCAT_REQUEST) {
|
||||
auto expect100 = stream->header.expect;
|
||||
|
||||
if (util::strieq("100-continue"_sr, expect100)) {
|
||||
if (util::strieq("100-continue"sv, expect100)) {
|
||||
hd->submit_non_final_response("100", frame->hd.stream_id);
|
||||
}
|
||||
|
||||
auto method = stream->header.method;
|
||||
if (hd->get_config()->echo_upload &&
|
||||
(method == "POST"_sr || method == "PUT"_sr)) {
|
||||
(method == "POST"sv || method == "PUT"sv)) {
|
||||
if (!prepare_upload_temp_store(stream, hd)) {
|
||||
hd->submit_rst_stream(stream, NGHTTP2_INTERNAL_ERROR);
|
||||
return 0;
|
||||
@@ -1649,10 +1653,10 @@ int send_data_callback(nghttp2_session *session, nghttp2_frame *frame,
|
||||
|
||||
auto p = wb->last;
|
||||
|
||||
p = std::copy_n(framehd, 9, p);
|
||||
p = std::ranges::copy_n(framehd, 9, p).out;
|
||||
|
||||
if (padlen) {
|
||||
*p++ = padlen - 1;
|
||||
*p++ = static_cast<uint8_t>(padlen - 1);
|
||||
}
|
||||
|
||||
while (length) {
|
||||
@@ -1669,12 +1673,12 @@ int send_data_callback(nghttp2_session *session, nghttp2_frame *frame,
|
||||
}
|
||||
|
||||
stream->body_offset += nread;
|
||||
length -= nread;
|
||||
length -= as_unsigned(nread);
|
||||
p += nread;
|
||||
}
|
||||
|
||||
if (padlen) {
|
||||
std::fill(p, p + padlen - 1, 0);
|
||||
std::ranges::fill(p, p + padlen - 1, 0);
|
||||
p += padlen - 1;
|
||||
}
|
||||
|
||||
@@ -1689,7 +1693,8 @@ nghttp2_ssize select_padding_callback(nghttp2_session *session,
|
||||
const nghttp2_frame *frame,
|
||||
size_t max_payload, void *user_data) {
|
||||
auto hd = static_cast<Http2Handler *>(user_data);
|
||||
return std::min(max_payload, frame->hd.length + hd->get_config()->padding);
|
||||
return as_signed(
|
||||
std::min(max_payload, frame->hd.length + hd->get_config()->padding));
|
||||
}
|
||||
} // namespace
|
||||
|
||||
@@ -1715,7 +1720,7 @@ int on_data_chunk_recv_callback(nghttp2_session *session, uint8_t flags,
|
||||
hd->submit_rst_stream(stream, NGHTTP2_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
len -= n;
|
||||
len -= as_unsigned(n);
|
||||
data += n;
|
||||
}
|
||||
}
|
||||
@@ -1777,6 +1782,8 @@ void fill_callback(nghttp2_session_callbacks *callbacks, const Config *config) {
|
||||
nghttp2_session_callbacks_set_select_padding_callback2(
|
||||
callbacks, select_padding_callback);
|
||||
}
|
||||
|
||||
nghttp2_session_callbacks_set_rand_callback(callbacks, util::secure_random);
|
||||
}
|
||||
} // namespace
|
||||
|
||||
@@ -1817,12 +1824,12 @@ void run_worker(Worker *worker) {
|
||||
|
||||
#ifdef NGHTTP2_OPENSSL_IS_WOLFSSL
|
||||
wc_ecc_fp_free();
|
||||
#endif // NGHTTP2_OPENSSL_IS_WOLFSSL
|
||||
#endif // defined(NGHTTP2_OPENSSL_IS_WOLFSSL)
|
||||
}
|
||||
} // namespace
|
||||
|
||||
namespace {
|
||||
int get_ev_loop_flags() {
|
||||
unsigned int get_ev_loop_flags() {
|
||||
if (ev_supported_backends() & ~ev_recommended_backends() & EVBACKEND_KQUEUE) {
|
||||
return ev_recommended_backends() | EVBACKEND_KQUEUE;
|
||||
}
|
||||
@@ -1902,15 +1909,15 @@ public:
|
||||
for (;;) {
|
||||
#ifdef HAVE_ACCEPT4
|
||||
auto fd = accept4(fd_, nullptr, nullptr, SOCK_NONBLOCK);
|
||||
#else // !HAVE_ACCEPT4
|
||||
#else // !defined(HAVE_ACCEPT4)
|
||||
auto fd = accept(fd_, nullptr, nullptr);
|
||||
#endif // !HAVE_ACCEPT4
|
||||
#endif // !defined(HAVE_ACCEPT4)
|
||||
if (fd == -1) {
|
||||
break;
|
||||
}
|
||||
#ifndef HAVE_ACCEPT4
|
||||
util::make_socket_nonblocking(fd);
|
||||
#endif // !HAVE_ACCEPT4
|
||||
#endif // !defined(HAVE_ACCEPT4)
|
||||
acceptor_->accept_connection(fd);
|
||||
}
|
||||
}
|
||||
@@ -1930,7 +1937,7 @@ void acceptcb(struct ev_loop *loop, ev_io *w, int revents) {
|
||||
} // namespace
|
||||
|
||||
namespace {
|
||||
FileEntry make_status_body(int status, uint16_t port) {
|
||||
FileEntry make_status_body(uint32_t status, uint16_t port) {
|
||||
BlockAllocator balloc(1024, 1024);
|
||||
|
||||
auto status_string = http2::stringify_status(balloc, status);
|
||||
@@ -2012,13 +2019,15 @@ int start_listen(HttpServer *sv, struct ev_loop *loop, Sessions *sessions,
|
||||
std::shared_ptr<AcceptHandler> acceptor;
|
||||
auto service = util::utos(config->port);
|
||||
|
||||
addrinfo hints{};
|
||||
hints.ai_family = AF_UNSPEC;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
hints.ai_flags = AI_PASSIVE;
|
||||
addrinfo hints{
|
||||
.ai_flags = AI_PASSIVE
|
||||
#ifdef AI_ADDRCONFIG
|
||||
hints.ai_flags |= AI_ADDRCONFIG;
|
||||
#endif // AI_ADDRCONFIG
|
||||
| AI_ADDRCONFIG
|
||||
#endif // defined(AI_ADDRCONFIG)
|
||||
,
|
||||
.ai_family = AF_UNSPEC,
|
||||
.ai_socktype = SOCK_STREAM,
|
||||
};
|
||||
|
||||
if (!config->address.empty()) {
|
||||
addr = config->address.c_str();
|
||||
@@ -2051,7 +2060,7 @@ int start_listen(HttpServer *sv, struct ev_loop *loop, Sessions *sessions,
|
||||
continue;
|
||||
}
|
||||
}
|
||||
#endif // IPV6_V6ONLY
|
||||
#endif // defined(IPV6_V6ONLY)
|
||||
if (bind(fd, rp->ai_addr, rp->ai_addrlen) == 0 && listen(fd, 1000) == 0) {
|
||||
if (!acceptor) {
|
||||
acceptor = std::make_shared<AcceptHandler>(sv, sessions, config);
|
||||
@@ -2103,7 +2112,6 @@ int alpn_select_proto_cb(SSL *ssl, const unsigned char **out,
|
||||
|
||||
int HttpServer::run() {
|
||||
SSL_CTX *ssl_ctx = nullptr;
|
||||
std::vector<unsigned char> next_proto;
|
||||
|
||||
if (!config_->no_tls) {
|
||||
ssl_ctx = SSL_CTX_new(TLS_server_method());
|
||||
@@ -2112,17 +2120,17 @@ int HttpServer::run() {
|
||||
return -1;
|
||||
}
|
||||
|
||||
auto ssl_opts = (SSL_OP_ALL & ~SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS) |
|
||||
SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_COMPRESSION |
|
||||
SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION |
|
||||
SSL_OP_SINGLE_ECDH_USE | SSL_OP_NO_TICKET |
|
||||
SSL_OP_CIPHER_SERVER_PREFERENCE;
|
||||
auto ssl_opts = static_cast<nghttp2_ssl_op_type>(
|
||||
(SSL_OP_ALL & ~SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS) | SSL_OP_NO_SSLv2 |
|
||||
SSL_OP_NO_SSLv3 | SSL_OP_NO_COMPRESSION |
|
||||
SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION | SSL_OP_SINGLE_ECDH_USE |
|
||||
SSL_OP_NO_TICKET | SSL_OP_CIPHER_SERVER_PREFERENCE);
|
||||
|
||||
#ifdef SSL_OP_ENABLE_KTLS
|
||||
if (config_->ktls) {
|
||||
ssl_opts |= SSL_OP_ENABLE_KTLS;
|
||||
}
|
||||
#endif // SSL_OP_ENABLE_KTLS
|
||||
#endif // defined(SSL_OP_ENABLE_KTLS)
|
||||
|
||||
SSL_CTX_set_options(ssl_ctx, ssl_opts);
|
||||
SSL_CTX_set_mode(ssl_ctx, SSL_MODE_AUTO_RETRY);
|
||||
@@ -2147,19 +2155,17 @@ int HttpServer::run() {
|
||||
std::cerr << ERR_error_string(ERR_get_error(), nullptr) << std::endl;
|
||||
return -1;
|
||||
}
|
||||
#endif // NGHTTP2_OPENSSL_IS_WOLFSSL
|
||||
#endif // defined(NGHTTP2_OPENSSL_IS_WOLFSSL)
|
||||
|
||||
const unsigned char sid_ctx[] = "nghttpd";
|
||||
SSL_CTX_set_session_id_context(ssl_ctx, sid_ctx, sizeof(sid_ctx) - 1);
|
||||
SSL_CTX_set_session_cache_mode(ssl_ctx, SSL_SESS_CACHE_SERVER);
|
||||
|
||||
#ifndef OPENSSL_NO_EC
|
||||
if (SSL_CTX_set1_curves_list(ssl_ctx, "P-256") != 1) {
|
||||
std::cerr << "SSL_CTX_set1_curves_list failed: "
|
||||
if (SSL_CTX_set1_groups_list(ssl_ctx, config_->groups.data()) != 1) {
|
||||
std::cerr << "SSL_CTX_set1_groups_list failed: "
|
||||
<< ERR_error_string(ERR_get_error(), nullptr);
|
||||
return -1;
|
||||
}
|
||||
#endif // OPENSSL_NO_EC
|
||||
|
||||
if (!config_->dh_param_file.empty()) {
|
||||
// Read DH parameters from file
|
||||
@@ -2223,8 +2229,6 @@ int HttpServer::run() {
|
||||
verify_callback);
|
||||
}
|
||||
|
||||
next_proto = util::get_default_alpn();
|
||||
|
||||
// ALPN selection callback
|
||||
SSL_CTX_set_alpn_select_cb(ssl_ctx, alpn_select_proto_cb, this);
|
||||
|
||||
@@ -2235,7 +2239,13 @@ int HttpServer::run() {
|
||||
std::cerr << "SSL_CTX_add_cert_compression_alg failed." << std::endl;
|
||||
return -1;
|
||||
}
|
||||
#endif // NGHTTP2_OPENSSL_IS_BORINGSSL && HAVE_LIBBROTLI
|
||||
#endif // defined(NGHTTP2_OPENSSL_IS_BORINGSSL) &&
|
||||
// defined(HAVE_LIBBROTLI)
|
||||
|
||||
if (tls::setup_keylog_callback(ssl_ctx) != 0) {
|
||||
std::cerr << "Failed to setup keylog" << std::endl;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
auto loop = EV_DEFAULT;
|
||||
|
||||
@@ -34,17 +34,18 @@
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <unordered_map>
|
||||
#include <memory>
|
||||
#include <string_view>
|
||||
|
||||
#include "ssl_compat.h"
|
||||
|
||||
#ifdef NGHTTP2_OPENSSL_IS_WOLFSSL
|
||||
# include <wolfssl/options.h>
|
||||
# include <wolfssl/openssl/ssl.h>
|
||||
#else // !NGHTTP2_OPENSSL_IS_WOLFSSL
|
||||
#else // !defined(NGHTTP2_OPENSSL_IS_WOLFSSL)
|
||||
# include <openssl/ssl.h>
|
||||
#endif // !NGHTTP2_OPENSSL_IS_WOLFSSL
|
||||
#endif // !defined(NGHTTP2_OPENSSL_IS_WOLFSSL)
|
||||
|
||||
#include <ev.h>
|
||||
|
||||
@@ -59,8 +60,8 @@
|
||||
namespace nghttp2 {
|
||||
|
||||
struct Config {
|
||||
std::map<std::string, std::vector<std::string>> push;
|
||||
std::map<std::string, std::string> mime_types;
|
||||
std::unordered_map<std::string, std::vector<std::string>> push;
|
||||
std::unordered_map<std::string, std::string> mime_types;
|
||||
Headers trailer;
|
||||
std::string trailer_names;
|
||||
std::string htdocs;
|
||||
@@ -70,6 +71,7 @@ struct Config {
|
||||
std::string dh_param_file;
|
||||
std::string address;
|
||||
std::string mime_types_file;
|
||||
std::string_view groups;
|
||||
ev_tstamp stream_read_timeout;
|
||||
ev_tstamp stream_write_timeout;
|
||||
void *data_ptr;
|
||||
@@ -107,31 +109,29 @@ struct FileEntry {
|
||||
mtime(mtime),
|
||||
last_valid(last_valid),
|
||||
content_type(content_type),
|
||||
dlnext(nullptr),
|
||||
dlprev(nullptr),
|
||||
fd(fd),
|
||||
usecount(1),
|
||||
stale(stale) {}
|
||||
std::string path;
|
||||
std::multimap<std::string, std::unique_ptr<FileEntry>>::iterator it;
|
||||
std::unordered_multimap<std::string, std::unique_ptr<FileEntry>>::iterator it;
|
||||
int64_t length;
|
||||
int64_t mtime;
|
||||
std::chrono::steady_clock::time_point last_valid;
|
||||
const std::string *content_type;
|
||||
FileEntry *dlnext, *dlprev;
|
||||
SListEntry<FileEntry> slent;
|
||||
int fd;
|
||||
int usecount;
|
||||
bool stale;
|
||||
};
|
||||
|
||||
struct RequestHeader {
|
||||
StringRef method;
|
||||
StringRef scheme;
|
||||
StringRef authority;
|
||||
StringRef host;
|
||||
StringRef path;
|
||||
StringRef ims;
|
||||
StringRef expect;
|
||||
std::string_view method;
|
||||
std::string_view scheme;
|
||||
std::string_view authority;
|
||||
std::string_view host;
|
||||
std::string_view path;
|
||||
std::string_view ims;
|
||||
std::string_view expect;
|
||||
|
||||
struct {
|
||||
nghttp2_rcbuf *method;
|
||||
@@ -176,21 +176,21 @@ public:
|
||||
int connection_made();
|
||||
int verify_alpn_result();
|
||||
|
||||
int submit_file_response(const StringRef &status, Stream *stream,
|
||||
int submit_file_response(const std::string_view &status, Stream *stream,
|
||||
time_t last_modified, off_t file_length,
|
||||
const std::string *content_type,
|
||||
nghttp2_data_provider2 *data_prd);
|
||||
|
||||
int submit_response(const StringRef &status, int32_t stream_id,
|
||||
int submit_response(const std::string_view &status, int32_t stream_id,
|
||||
nghttp2_data_provider2 *data_prd);
|
||||
|
||||
int submit_response(const StringRef &status, int32_t stream_id,
|
||||
int submit_response(const std::string_view &status, int32_t stream_id,
|
||||
const HeaderRefs &headers,
|
||||
nghttp2_data_provider2 *data_prd);
|
||||
|
||||
int submit_non_final_response(const std::string &status, int32_t stream_id);
|
||||
|
||||
int submit_push_promise(Stream *stream, const StringRef &push_path);
|
||||
int submit_push_promise(Stream *stream, const std::string_view &push_path);
|
||||
|
||||
int submit_rst_stream(Stream *stream, uint32_t error_code);
|
||||
|
||||
@@ -221,7 +221,7 @@ private:
|
||||
ev_io wev_;
|
||||
ev_io rev_;
|
||||
ev_timer settings_timerev_;
|
||||
std::map<int32_t, std::unique_ptr<Stream>> id2stream_;
|
||||
std::unordered_map<int32_t, std::unique_ptr<Stream>> id2stream_;
|
||||
WriteBuf wb_;
|
||||
std::function<int(Http2Handler &)> read_, write_;
|
||||
int64_t session_id_;
|
||||
@@ -258,4 +258,4 @@ nghttp2_ssize file_read_callback(nghttp2_session *session, int32_t stream_id,
|
||||
|
||||
} // namespace nghttp2
|
||||
|
||||
#endif // HTTP_SERVER_H
|
||||
#endif // !defined(HTTP_SERVER_H)
|
||||
|
||||
@@ -47,7 +47,9 @@ AM_CPPFLAGS = \
|
||||
@LIBNGHTTP3_CFLAGS@ \
|
||||
@LIBNGTCP2_CRYPTO_WOLFSSL_CFLAGS@ \
|
||||
@LIBNGTCP2_CRYPTO_QUICTLS_CFLAGS@ \
|
||||
@LIBNGTCP2_CRYPTO_LIBRESSL_CFLAGS@ \
|
||||
@LIBNGTCP2_CRYPTO_BORINGSSL_CFLAGS@ \
|
||||
@LIBNGTCP2_CRYPTO_OSSL_CFLAGS@ \
|
||||
@LIBNGTCP2_CFLAGS@ \
|
||||
@WOLFSSL_CFLAGS@ \
|
||||
@OPENSSL_CFLAGS@ \
|
||||
@@ -70,7 +72,9 @@ LDADD = $(top_builddir)/lib/libnghttp2.la \
|
||||
@LIBNGHTTP3_LIBS@ \
|
||||
@LIBNGTCP2_CRYPTO_WOLFSSL_LIBS@ \
|
||||
@LIBNGTCP2_CRYPTO_QUICTLS_LIBS@ \
|
||||
@LIBNGTCP2_CRYPTO_LIBRESSL_LIBS@ \
|
||||
@LIBNGTCP2_CRYPTO_BORINGSSL_LIBS@ \
|
||||
@LIBNGTCP2_CRYPTO_OSSL_LIBS@ \
|
||||
@LIBNGTCP2_LIBS@ \
|
||||
@WOLFSSL_LIBS@ \
|
||||
@OPENSSL_LIBS@ \
|
||||
@@ -121,8 +125,7 @@ h2load_SOURCES = util.cc util.h \
|
||||
if ENABLE_HTTP3
|
||||
h2load_SOURCES += \
|
||||
h2load_http3_session.cc h2load_http3_session.h \
|
||||
h2load_quic.cc h2load_quic.h \
|
||||
quic.cc quic.h
|
||||
h2load_quic.cc h2load_quic.h
|
||||
endif # ENABLE_HTTP3
|
||||
|
||||
NGHTTPX_SRCS = \
|
||||
@@ -166,7 +169,6 @@ NGHTTPX_SRCS = \
|
||||
shrpx_health_monitor_downstream_connection.cc \
|
||||
shrpx_health_monitor_downstream_connection.h \
|
||||
shrpx_null_downstream_connection.cc shrpx_null_downstream_connection.h \
|
||||
shrpx_exec.cc shrpx_exec.h \
|
||||
shrpx_dns_resolver.cc shrpx_dns_resolver.h \
|
||||
shrpx_dual_dns_resolver.cc shrpx_dual_dns_resolver.h \
|
||||
shrpx_dns_tracker.cc shrpx_dns_tracker.h \
|
||||
@@ -189,7 +191,6 @@ NGHTTPX_SRCS += \
|
||||
shrpx_quic_connection_handler.cc shrpx_quic_connection_handler.h \
|
||||
shrpx_http3_upstream.cc shrpx_http3_upstream.h \
|
||||
http3.cc http3.h \
|
||||
quic.cc quic.h \
|
||||
siphash.cc siphash.h
|
||||
endif # ENABLE_HTTP3
|
||||
|
||||
@@ -261,7 +262,8 @@ bin_PROGRAMS += inflatehd deflatehd
|
||||
HPACK_TOOLS_COMMON_SRCS = \
|
||||
comp_helper.c comp_helper.h \
|
||||
util.cc util.h \
|
||||
timegm.c timegm.h
|
||||
timegm.c timegm.h \
|
||||
tls.cc tls.h
|
||||
|
||||
inflatehd_SOURCES = inflatehd.cc $(HPACK_TOOLS_COMMON_SRCS)
|
||||
|
||||
|
||||
@@ -29,11 +29,12 @@
|
||||
|
||||
#ifndef _WIN32
|
||||
# include <sys/uio.h>
|
||||
#endif // !_WIN32
|
||||
#endif // !defined(_WIN32)
|
||||
|
||||
#include <cassert>
|
||||
#include <utility>
|
||||
#include <span>
|
||||
#include <algorithm>
|
||||
|
||||
#include "template.h"
|
||||
|
||||
@@ -179,7 +180,7 @@ struct BlockAllocator {
|
||||
auto nalloclen = std::max(size + 1, alloclen * 2);
|
||||
|
||||
auto res = alloc(nalloclen);
|
||||
std::copy_n(p, alloclen, static_cast<uint8_t *>(res));
|
||||
std::ranges::copy_n(p, as_signed(alloclen), static_cast<uint8_t *>(res));
|
||||
|
||||
return res;
|
||||
}
|
||||
@@ -195,29 +196,37 @@ struct BlockAllocator {
|
||||
size_t isolation_threshold;
|
||||
};
|
||||
|
||||
// Makes a copy of |src|. The resulting string will be
|
||||
// NULL-terminated.
|
||||
template <typename BlockAllocator>
|
||||
StringRef make_string_ref(BlockAllocator &alloc, const StringRef &src) {
|
||||
auto dst = static_cast<uint8_t *>(alloc.alloc(src.size() + 1));
|
||||
auto p = dst;
|
||||
p = std::copy(std::begin(src), std::end(src), p);
|
||||
// Makes a copy of a range [|first|, |last|). The resulting string
|
||||
// will be NULL-terminated.
|
||||
template <std::input_iterator I>
|
||||
std::string_view make_string_ref(BlockAllocator &alloc, I first, I last) {
|
||||
auto dst = static_cast<char *>(
|
||||
alloc.alloc(static_cast<size_t>(std::ranges::distance(first, last) + 1)));
|
||||
auto p = std::ranges::copy(first, last, dst).out;
|
||||
*p = '\0';
|
||||
return StringRef{dst, src.size()};
|
||||
|
||||
return std::string_view{dst, p};
|
||||
}
|
||||
|
||||
// Makes a copy of |r| as std::string_view. The resulting string will be
|
||||
// NULL-terminated.
|
||||
template <std::ranges::input_range R>
|
||||
requires(!std::is_array_v<std::remove_cvref_t<R>>)
|
||||
std::string_view make_string_ref(BlockAllocator &alloc, R &&r) {
|
||||
return make_string_ref(alloc, std::ranges::begin(r), std::ranges::end(r));
|
||||
}
|
||||
|
||||
// private function used in concat_string_ref. this is the base
|
||||
// function of concat_string_ref_count().
|
||||
inline constexpr size_t concat_string_ref_count(size_t acc) { return acc; }
|
||||
constexpr size_t concat_string_ref_count(size_t acc) { return acc; }
|
||||
|
||||
// private function used in concat_string_ref. This function counts
|
||||
// the sum of length of given arguments. The calculated length is
|
||||
// accumulated, and passed to the next function.
|
||||
template <typename... Args>
|
||||
constexpr size_t concat_string_ref_count(size_t acc, const StringRef &value,
|
||||
Args &&...args) {
|
||||
return concat_string_ref_count(acc + value.size(),
|
||||
std::forward<Args>(args)...);
|
||||
template <std::ranges::input_range R, std::ranges::input_range... Args>
|
||||
requires(!std::is_array_v<std::remove_cvref_t<R>>)
|
||||
constexpr size_t concat_string_ref_count(size_t acc, R &&r, Args &&...args) {
|
||||
return concat_string_ref_count(acc + std::ranges::size(r), args...);
|
||||
}
|
||||
|
||||
// private function used in concat_string_ref. this is the base
|
||||
@@ -228,23 +237,23 @@ inline uint8_t *concat_string_ref_copy(uint8_t *p) { return p; }
|
||||
// given strings into |p|. |p| is incremented by the copied length,
|
||||
// and returned. In the end, return value points to the location one
|
||||
// beyond the last byte written.
|
||||
template <typename... Args>
|
||||
uint8_t *concat_string_ref_copy(uint8_t *p, const StringRef &value,
|
||||
Args &&...args) {
|
||||
p = std::copy(std::begin(value), std::end(value), p);
|
||||
return concat_string_ref_copy(p, std::forward<Args>(args)...);
|
||||
template <std::ranges::input_range R, std::ranges::input_range... Args>
|
||||
requires(!std::is_array_v<std::remove_cvref_t<R>>)
|
||||
uint8_t *concat_string_ref_copy(uint8_t *p, R &&r, Args &&...args) {
|
||||
return concat_string_ref_copy(std::ranges::copy(std::forward<R>(r), p).out,
|
||||
std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
// Returns the string which is the concatenation of |args| in the
|
||||
// given order. The resulting string will be NULL-terminated.
|
||||
template <typename BlockAllocator, typename... Args>
|
||||
StringRef concat_string_ref(BlockAllocator &alloc, Args &&...args) {
|
||||
size_t len = concat_string_ref_count(0, std::forward<Args>(args)...);
|
||||
template <std::ranges::input_range... Args>
|
||||
std::string_view concat_string_ref(BlockAllocator &alloc, Args &&...args) {
|
||||
auto len = concat_string_ref_count(0, args...);
|
||||
auto dst = static_cast<uint8_t *>(alloc.alloc(len + 1));
|
||||
auto p = dst;
|
||||
p = concat_string_ref_copy(p, std::forward<Args>(args)...);
|
||||
*p = '\0';
|
||||
return StringRef{dst, len};
|
||||
return as_string_view(dst, p);
|
||||
}
|
||||
|
||||
// Returns the string which is the concatenation of |value| and |args|
|
||||
@@ -253,30 +262,30 @@ StringRef concat_string_ref(BlockAllocator &alloc, Args &&...args) {
|
||||
// obtained from alloc.alloc() or alloc.realloc(), and attempts to use
|
||||
// unused memory region by using alloc.realloc(). If value is empty,
|
||||
// then just call concat_string_ref().
|
||||
template <typename BlockAllocator, typename... Args>
|
||||
StringRef realloc_concat_string_ref(BlockAllocator &alloc,
|
||||
const StringRef &value, Args &&...args) {
|
||||
template <std::ranges::input_range... Args>
|
||||
std::string_view realloc_concat_string_ref(BlockAllocator &alloc,
|
||||
const std::string_view &value,
|
||||
Args &&...args) {
|
||||
if (value.empty()) {
|
||||
return concat_string_ref(alloc, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
auto len =
|
||||
value.size() + concat_string_ref_count(0, std::forward<Args>(args)...);
|
||||
auto dst = static_cast<uint8_t *>(
|
||||
alloc.realloc(const_cast<uint8_t *>(value.byte()), len + 1));
|
||||
auto len = value.size() + concat_string_ref_count(0, args...);
|
||||
auto dst = static_cast<uint8_t *>(alloc.realloc(
|
||||
const_cast<uint8_t *>(reinterpret_cast<const uint8_t *>(value.data())),
|
||||
len + 1));
|
||||
auto p = dst + value.size();
|
||||
p = concat_string_ref_copy(p, std::forward<Args>(args)...);
|
||||
*p = '\0';
|
||||
|
||||
return StringRef{dst, len};
|
||||
return as_string_view(dst, p);
|
||||
}
|
||||
|
||||
// Makes an uninitialized buffer with given size.
|
||||
template <typename BlockAllocator>
|
||||
std::span<uint8_t> make_byte_ref(BlockAllocator &alloc, size_t size) {
|
||||
inline std::span<uint8_t> make_byte_ref(BlockAllocator &alloc, size_t size) {
|
||||
return {static_cast<uint8_t *>(alloc.alloc(size)), size};
|
||||
}
|
||||
|
||||
} // namespace nghttp2
|
||||
|
||||
#endif // ALLOCATOR_H
|
||||
#endif // !defined(ALLOCATOR_H)
|
||||
|
||||
@@ -25,19 +25,19 @@
|
||||
#include <sys/types.h>
|
||||
#ifdef HAVE_SYS_SOCKET_H
|
||||
# include <sys/socket.h>
|
||||
#endif // HAVE_SYS_SOCKET_H
|
||||
#endif // defined(HAVE_SYS_SOCKET_H)
|
||||
#ifdef HAVE_NETDB_H
|
||||
# include <netdb.h>
|
||||
#endif // HAVE_NETDB_H
|
||||
#endif // defined(HAVE_NETDB_H)
|
||||
#ifdef HAVE_UNISTD_H
|
||||
# include <unistd.h>
|
||||
#endif // HAVE_UNISTD_H
|
||||
#endif // defined(HAVE_UNISTD_H)
|
||||
#ifdef HAVE_FCNTL_H
|
||||
# include <fcntl.h>
|
||||
#endif // HAVE_FCNTL_H
|
||||
#endif // defined(HAVE_FCNTL_H)
|
||||
#ifdef HAVE_NETINET_IN_H
|
||||
# include <netinet/in.h>
|
||||
#endif // HAVE_NETINET_IN_H
|
||||
#endif // defined(HAVE_NETINET_IN_H)
|
||||
#include <netinet/tcp.h>
|
||||
#include <poll.h>
|
||||
|
||||
@@ -49,7 +49,6 @@
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <set>
|
||||
#include <iomanip>
|
||||
#include <fstream>
|
||||
|
||||
@@ -329,7 +328,7 @@ void print_frame(print_type ptype, const nghttp2_frame *frame) {
|
||||
case NGHTTP2_PING:
|
||||
print_frame_attr_indent();
|
||||
fprintf(outfile, "(opaque_data=%s)\n",
|
||||
util::format_hex(frame->ping.opaque_data).c_str());
|
||||
util::format_hex(std::span{frame->ping.opaque_data}).c_str());
|
||||
break;
|
||||
case NGHTTP2_GOAWAY:
|
||||
print_frame_attr_indent();
|
||||
|
||||
@@ -31,10 +31,9 @@
|
||||
#include <cstdlib>
|
||||
#ifdef HAVE_SYS_TIME_H
|
||||
# include <sys/time.h>
|
||||
#endif // HAVE_SYS_TIME_H
|
||||
#endif // defined(HAVE_SYS_TIME_H)
|
||||
#include <poll.h>
|
||||
|
||||
#include <map>
|
||||
#include <chrono>
|
||||
|
||||
#include <nghttp2/nghttp2.h>
|
||||
@@ -92,4 +91,4 @@ void set_output(FILE *file);
|
||||
|
||||
} // namespace nghttp2
|
||||
|
||||
#endif // APP_HELPER_H
|
||||
#endif // !defined(APP_HELPER_H)
|
||||
|
||||
221
src/base64.h
221
src/base64.h
@@ -36,152 +36,140 @@ namespace nghttp2 {
|
||||
|
||||
namespace base64 {
|
||||
|
||||
namespace {
|
||||
constexpr char B64_CHARS[] = {
|
||||
inline constexpr char B64_CHARS[] = {
|
||||
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
|
||||
'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
|
||||
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
|
||||
'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
|
||||
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/',
|
||||
};
|
||||
} // namespace
|
||||
|
||||
template <typename InputIt> std::string encode(InputIt first, InputIt last) {
|
||||
std::string res;
|
||||
size_t len = last - first;
|
||||
if (len == 0) {
|
||||
return res;
|
||||
}
|
||||
size_t r = len % 3;
|
||||
res.resize((len + 2) / 3 * 4);
|
||||
auto j = last - r;
|
||||
auto p = std::begin(res);
|
||||
while (first != j) {
|
||||
uint32_t n = static_cast<uint8_t>(*first++) << 16;
|
||||
n += static_cast<uint8_t>(*first++) << 8;
|
||||
n += static_cast<uint8_t>(*first++);
|
||||
*p++ = B64_CHARS[n >> 18];
|
||||
*p++ = B64_CHARS[(n >> 12) & 0x3fu];
|
||||
*p++ = B64_CHARS[(n >> 6) & 0x3fu];
|
||||
*p++ = B64_CHARS[n & 0x3fu];
|
||||
}
|
||||
|
||||
if (r == 2) {
|
||||
uint32_t n = static_cast<uint8_t>(*first++) << 16;
|
||||
n += static_cast<uint8_t>(*first++) << 8;
|
||||
*p++ = B64_CHARS[n >> 18];
|
||||
*p++ = B64_CHARS[(n >> 12) & 0x3fu];
|
||||
*p++ = B64_CHARS[(n >> 6) & 0x3fu];
|
||||
*p++ = '=';
|
||||
} else if (r == 1) {
|
||||
uint32_t n = static_cast<uint8_t>(*first++) << 16;
|
||||
*p++ = B64_CHARS[n >> 18];
|
||||
*p++ = B64_CHARS[(n >> 12) & 0x3fu];
|
||||
*p++ = '=';
|
||||
*p++ = '=';
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
constexpr size_t encode_length(size_t n) { return (n + 2) / 3 * 4; }
|
||||
|
||||
template <typename InputIt, typename OutputIt>
|
||||
OutputIt encode(InputIt first, InputIt last, OutputIt d_first) {
|
||||
size_t len = last - first;
|
||||
template <std::input_iterator I, std::weakly_incrementable O>
|
||||
requires(std::indirectly_writable<O, char>)
|
||||
constexpr O encode(I first, I last, O result) {
|
||||
using result_type = std::iter_value_t<O>;
|
||||
|
||||
auto len = std::ranges::distance(first, last);
|
||||
if (len == 0) {
|
||||
return d_first;
|
||||
}
|
||||
auto r = len % 3;
|
||||
auto j = last - r;
|
||||
auto p = d_first;
|
||||
while (first != j) {
|
||||
uint32_t n = static_cast<uint8_t>(*first++) << 16;
|
||||
n += static_cast<uint8_t>(*first++) << 8;
|
||||
n += static_cast<uint8_t>(*first++);
|
||||
*p++ = B64_CHARS[n >> 18];
|
||||
*p++ = B64_CHARS[(n >> 12) & 0x3fu];
|
||||
*p++ = B64_CHARS[(n >> 6) & 0x3fu];
|
||||
*p++ = B64_CHARS[n & 0x3fu];
|
||||
return result;
|
||||
}
|
||||
|
||||
switch (r) {
|
||||
auto p = result;
|
||||
|
||||
for (;;) {
|
||||
len = std::ranges::distance(first, last);
|
||||
if (len < 3) {
|
||||
break;
|
||||
}
|
||||
|
||||
auto n = static_cast<uint32_t>(static_cast<uint8_t>(*first++) << 16);
|
||||
n += static_cast<uint32_t>(static_cast<uint8_t>(*first++) << 8);
|
||||
n += static_cast<uint8_t>(*first++);
|
||||
*p++ = static_cast<result_type>(B64_CHARS[n >> 18]);
|
||||
*p++ = static_cast<result_type>(B64_CHARS[(n >> 12) & 0x3fu]);
|
||||
*p++ = static_cast<result_type>(B64_CHARS[(n >> 6) & 0x3fu]);
|
||||
*p++ = static_cast<result_type>(B64_CHARS[n & 0x3fu]);
|
||||
}
|
||||
|
||||
switch (len) {
|
||||
case 2: {
|
||||
uint32_t n = static_cast<uint8_t>(*first++) << 16;
|
||||
n += static_cast<uint8_t>(*first++) << 8;
|
||||
*p++ = B64_CHARS[n >> 18];
|
||||
*p++ = B64_CHARS[(n >> 12) & 0x3fu];
|
||||
*p++ = B64_CHARS[(n >> 6) & 0x3fu];
|
||||
auto n = static_cast<uint32_t>(static_cast<uint8_t>(*first++) << 16);
|
||||
n += static_cast<uint32_t>(static_cast<uint8_t>(*first++) << 8);
|
||||
*p++ = static_cast<result_type>(B64_CHARS[n >> 18]);
|
||||
*p++ = static_cast<result_type>(B64_CHARS[(n >> 12) & 0x3fu]);
|
||||
*p++ = static_cast<result_type>(B64_CHARS[(n >> 6) & 0x3fu]);
|
||||
*p++ = '=';
|
||||
break;
|
||||
}
|
||||
case 1: {
|
||||
uint32_t n = static_cast<uint8_t>(*first++) << 16;
|
||||
*p++ = B64_CHARS[n >> 18];
|
||||
*p++ = B64_CHARS[(n >> 12) & 0x3fu];
|
||||
auto n = static_cast<uint32_t>(static_cast<uint8_t>(*first++) << 16);
|
||||
*p++ = static_cast<result_type>(B64_CHARS[n >> 18]);
|
||||
*p++ = static_cast<result_type>(B64_CHARS[(n >> 12) & 0x3fu]);
|
||||
*p++ = '=';
|
||||
*p++ = '=';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
template <typename InputIt>
|
||||
InputIt next_decode_input(InputIt first, InputIt last, const int *tbl) {
|
||||
for (; first != last; ++first) {
|
||||
if (tbl[static_cast<size_t>(*first)] != -1 || *first == '=') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return first;
|
||||
template <std::ranges::input_range R, std::weakly_incrementable O>
|
||||
requires(std::indirectly_writable<O, char> &&
|
||||
!std::is_array_v<std::remove_cvref_t<R>>)
|
||||
constexpr O encode(R &&r, O result) {
|
||||
return encode(std::ranges::begin(r), std::ranges::end(r), std::move(result));
|
||||
}
|
||||
|
||||
template <typename InputIt, typename OutputIt>
|
||||
OutputIt decode(InputIt first, InputIt last, OutputIt d_first) {
|
||||
static constexpr int INDEX_TABLE[] = {
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, 62, -1, -1, -1, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60,
|
||||
61, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
|
||||
11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1,
|
||||
-1, -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42,
|
||||
43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1};
|
||||
assert(std::distance(first, last) % 4 == 0);
|
||||
auto p = d_first;
|
||||
template <std::ranges::input_range R>
|
||||
requires(!std::is_array_v<std::remove_cvref_t<R>>)
|
||||
constexpr std::string encode(R &&r) {
|
||||
std::string res;
|
||||
auto len = std::ranges::size(r);
|
||||
if (len == 0) {
|
||||
return res;
|
||||
}
|
||||
|
||||
res.resize((len + 2) / 3 * 4);
|
||||
|
||||
encode(std::forward<R>(r), std::ranges::begin(res));
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
inline constexpr int B64_INDEX_TABLE[] = {
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, 62, -1, -1, -1, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60,
|
||||
61, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
|
||||
11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1,
|
||||
-1, -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42,
|
||||
43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1};
|
||||
|
||||
template <std::input_iterator I, std::weakly_incrementable O>
|
||||
requires(std::indirectly_writable<O, uint8_t>)
|
||||
constexpr O decode(I first, I last, O result) {
|
||||
using result_type = std::iter_value_t<O>;
|
||||
|
||||
assert(std::ranges::distance(first, last) % 4 == 0);
|
||||
auto p = result;
|
||||
for (; first != last;) {
|
||||
uint32_t n = 0;
|
||||
for (int i = 1; i <= 4; ++i, ++first) {
|
||||
auto idx = INDEX_TABLE[static_cast<size_t>(*first)];
|
||||
auto idx = B64_INDEX_TABLE[static_cast<size_t>(*first)];
|
||||
if (idx == -1) {
|
||||
if (i <= 2) {
|
||||
return d_first;
|
||||
return result;
|
||||
}
|
||||
if (i == 3) {
|
||||
if (*first == '=' && *(first + 1) == '=' && first + 2 == last) {
|
||||
*p++ = n >> 16;
|
||||
if (*first == '=' && *std::ranges::next(first, 1) == '=' &&
|
||||
std::ranges::next(first, 2) == last) {
|
||||
*p++ = static_cast<result_type>(n >> 16);
|
||||
return p;
|
||||
}
|
||||
return d_first;
|
||||
return result;
|
||||
}
|
||||
if (*first == '=' && first + 1 == last) {
|
||||
*p++ = n >> 16;
|
||||
if (*first == '=' && std::ranges::next(first, 1) == last) {
|
||||
*p++ = static_cast<result_type>(n >> 16);
|
||||
*p++ = n >> 8 & 0xffu;
|
||||
return p;
|
||||
}
|
||||
return d_first;
|
||||
return result;
|
||||
}
|
||||
|
||||
n += idx << (24 - i * 6);
|
||||
n += static_cast<uint32_t>(idx) << (24 - i * 6);
|
||||
}
|
||||
|
||||
*p++ = n >> 16;
|
||||
*p++ = static_cast<result_type>(n >> 16);
|
||||
*p++ = n >> 8 & 0xffu;
|
||||
*p++ = n & 0xffu;
|
||||
}
|
||||
@@ -189,37 +177,24 @@ OutputIt decode(InputIt first, InputIt last, OutputIt d_first) {
|
||||
return p;
|
||||
}
|
||||
|
||||
template <typename InputIt> std::string decode(InputIt first, InputIt last) {
|
||||
auto len = std::distance(first, last);
|
||||
if (len % 4 != 0) {
|
||||
return "";
|
||||
}
|
||||
std::string res;
|
||||
res.resize(len / 4 * 3);
|
||||
|
||||
res.erase(decode(first, last, std::begin(res)), std::end(res));
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
template <typename InputIt>
|
||||
std::span<const uint8_t> decode(BlockAllocator &balloc, InputIt first,
|
||||
InputIt last) {
|
||||
auto len = std::distance(first, last);
|
||||
template <std::ranges::input_range R>
|
||||
requires(!std::is_array_v<std::remove_cvref_t<R>>)
|
||||
std::span<const uint8_t> decode(BlockAllocator &balloc, R &&r) {
|
||||
auto len = std::ranges::size(r);
|
||||
if (len % 4 != 0) {
|
||||
return {};
|
||||
}
|
||||
auto iov = make_byte_ref(balloc, len / 4 * 3 + 1);
|
||||
auto p = std::begin(iov);
|
||||
auto p = std::ranges::begin(iov);
|
||||
|
||||
p = decode(first, last, p);
|
||||
p = decode(std::ranges::begin(r), std::ranges::end(r), p);
|
||||
*p = '\0';
|
||||
|
||||
return {std::begin(iov), p};
|
||||
return {std::ranges::begin(iov), p};
|
||||
}
|
||||
|
||||
} // namespace base64
|
||||
|
||||
} // namespace nghttp2
|
||||
|
||||
#endif // BASE64_H
|
||||
#endif // !defined(BASE64_H)
|
||||
|
||||
@@ -52,22 +52,22 @@ const MunitSuite base64_suite{
|
||||
void test_base64_encode(void) {
|
||||
{
|
||||
std::string in = "\xff";
|
||||
auto out = base64::encode(std::begin(in), std::end(in));
|
||||
auto out = base64::encode(in);
|
||||
assert_stdstring_equal("/w==", out);
|
||||
}
|
||||
{
|
||||
std::string in = "\xff\xfe";
|
||||
auto out = base64::encode(std::begin(in), std::end(in));
|
||||
auto out = base64::encode(in);
|
||||
assert_stdstring_equal("//4=", out);
|
||||
}
|
||||
{
|
||||
std::string in = "\xff\xfe\xfd";
|
||||
auto out = base64::encode(std::begin(in), std::end(in));
|
||||
auto out = base64::encode(in);
|
||||
assert_stdstring_equal("//79", out);
|
||||
}
|
||||
{
|
||||
std::string in = "\xff\xfe\xfd\xfc";
|
||||
auto out = base64::encode(std::begin(in), std::end(in));
|
||||
auto out = base64::encode(in);
|
||||
assert_stdstring_equal("//79/A==", out);
|
||||
}
|
||||
}
|
||||
@@ -76,66 +76,43 @@ void test_base64_decode(void) {
|
||||
BlockAllocator balloc(4096, 4096);
|
||||
{
|
||||
auto in = "/w=="sv;
|
||||
auto out = base64::decode(std::begin(in), std::end(in));
|
||||
assert_stdsv_equal("\xff"sv, out);
|
||||
assert_stdsv_equal("\xff"sv, StringRef{base64::decode(
|
||||
balloc, std::begin(in), std::end(in))});
|
||||
assert_stdsv_equal("\xff"sv, as_string_view(base64::decode(balloc, in)));
|
||||
}
|
||||
{
|
||||
auto in = "//4="sv;
|
||||
auto out = base64::decode(std::begin(in), std::end(in));
|
||||
assert_stdsv_equal("\xff\xfe"sv, out);
|
||||
assert_stdsv_equal("\xff\xfe"sv, StringRef{base64::decode(
|
||||
balloc, std::begin(in), std::end(in))});
|
||||
assert_stdsv_equal("\xff\xfe"sv,
|
||||
as_string_view(base64::decode(balloc, in)));
|
||||
}
|
||||
{
|
||||
auto in = "//79"sv;
|
||||
auto out = base64::decode(std::begin(in), std::end(in));
|
||||
assert_stdsv_equal("\xff\xfe\xfd"sv, out);
|
||||
assert_stdsv_equal(
|
||||
"\xff\xfe\xfd"sv,
|
||||
StringRef{base64::decode(balloc, std::begin(in), std::end(in))});
|
||||
assert_stdsv_equal("\xff\xfe\xfd"sv,
|
||||
as_string_view(base64::decode(balloc, in)));
|
||||
}
|
||||
{
|
||||
auto in = "//79/A=="sv;
|
||||
auto out = base64::decode(std::begin(in), std::end(in));
|
||||
assert_stdsv_equal("\xff\xfe\xfd\xfc"sv, out);
|
||||
assert_stdsv_equal(
|
||||
"\xff\xfe\xfd\xfc"sv,
|
||||
StringRef{base64::decode(balloc, std::begin(in), std::end(in))});
|
||||
assert_stdsv_equal("\xff\xfe\xfd\xfc"sv,
|
||||
as_string_view(base64::decode(balloc, in)));
|
||||
}
|
||||
{
|
||||
// we check the number of valid input must be multiples of 4
|
||||
auto in = "//79="sv;
|
||||
auto out = base64::decode(std::begin(in), std::end(in));
|
||||
assert_stdsv_equal(""sv, out);
|
||||
assert_stdsv_equal(
|
||||
""sv, StringRef{base64::decode(balloc, std::begin(in), std::end(in))});
|
||||
assert_stdsv_equal(""sv, as_string_view(base64::decode(balloc, in)));
|
||||
}
|
||||
{
|
||||
// ending invalid character at the boundary of multiples of 4 is
|
||||
// bad
|
||||
auto in = "bmdodHRw\n"sv;
|
||||
auto out = base64::decode(std::begin(in), std::end(in));
|
||||
assert_stdsv_equal("", out);
|
||||
assert_stdsv_equal(
|
||||
""sv, StringRef{base64::decode(balloc, std::begin(in), std::end(in))});
|
||||
assert_stdsv_equal(""sv, as_string_view(base64::decode(balloc, in)));
|
||||
}
|
||||
{
|
||||
// after seeing '=', subsequent input must be also '='.
|
||||
auto in = "//79/A=A"sv;
|
||||
auto out = base64::decode(std::begin(in), std::end(in));
|
||||
assert_stdsv_equal(""sv, out);
|
||||
assert_stdsv_equal(
|
||||
""sv, StringRef{base64::decode(balloc, std::begin(in), std::end(in))});
|
||||
assert_stdsv_equal(""sv, as_string_view(base64::decode(balloc, in)));
|
||||
}
|
||||
{
|
||||
// additional '=' at the end is bad
|
||||
auto in = "//79/A======"sv;
|
||||
auto out = base64::decode(std::begin(in), std::end(in));
|
||||
assert_stdsv_equal(""sv, out);
|
||||
assert_stdsv_equal(
|
||||
""sv, StringRef{base64::decode(balloc, std::begin(in), std::end(in))});
|
||||
assert_stdsv_equal(""sv, as_string_view(base64::decode(balloc, in)));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user