mirror of
https://github.com/nghttp2/nghttp2.git
synced 2025-12-08 02:58:53 +08:00
Compare commits
440 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d13a575837 | ||
|
|
001833c5a4 | ||
|
|
38fb5c2b3f | ||
|
|
3e767d3003 | ||
|
|
f4fc77028d | ||
|
|
8573f53b18 | ||
|
|
a1034c7866 | ||
|
|
f1deade196 | ||
|
|
0ecc418f37 | ||
|
|
d105d660ca | ||
|
|
517ffb3917 | ||
|
|
76cd830b8a | ||
|
|
3f9a980ecb | ||
|
|
c411e30075 | ||
|
|
b691353b0c | ||
|
|
d68048165b | ||
|
|
f0d827f242 | ||
|
|
960c8b3a3a | ||
|
|
ee96f61293 | ||
|
|
db71b2a64c | ||
|
|
70ce073eff | ||
|
|
6d429874b0 | ||
|
|
422167b88b | ||
|
|
f65cfa8da2 | ||
|
|
e3e33a5867 | ||
|
|
f3cdd7a348 | ||
|
|
ad79597416 | ||
|
|
fc1b4a510d | ||
|
|
49ee93f7a4 | ||
|
|
49b7dbde8a | ||
|
|
6619a6f945 | ||
|
|
0d21d59a38 | ||
|
|
1d765368f0 | ||
|
|
f3f10ca1f5 | ||
|
|
34433fdcb3 | ||
|
|
ae678f4f30 | ||
|
|
0caf2a8444 | ||
|
|
f564c30096 | ||
|
|
17a211f45a | ||
|
|
26708239aa | ||
|
|
3d13ef9f06 | ||
|
|
77ac52137f | ||
|
|
82276389fc | ||
|
|
69e2d4d78f | ||
|
|
d51fc54f16 | ||
|
|
481f876653 | ||
|
|
a748575149 | ||
|
|
3b63158b7b | ||
|
|
e7909d76b8 | ||
|
|
9bcc5c25b3 | ||
|
|
2585cc353f | ||
|
|
6d4b2c7dbf | ||
|
|
e6f3901b51 | ||
|
|
b4313ea7a0 | ||
|
|
58c1b7c37a | ||
|
|
c013b36695 | ||
|
|
943fba4590 | ||
|
|
062bc696bc | ||
|
|
b49ce3dfda | ||
|
|
b9890d6797 | ||
|
|
8c6cc0f3b3 | ||
|
|
ee0f4fbce0 | ||
|
|
44724b0750 | ||
|
|
122ae428ad | ||
|
|
375753fdd1 | ||
|
|
4bd5bebc46 | ||
|
|
cab280a576 | ||
|
|
a7f588189f | ||
|
|
dc969cc7f9 | ||
|
|
7d2f75abcf | ||
|
|
18fafddb06 | ||
|
|
6d281826b3 | ||
|
|
dbff91a4f7 | ||
|
|
1fbd73c51a | ||
|
|
db75062d2c | ||
|
|
37f1f978f7 | ||
|
|
08cd3bf619 | ||
|
|
c1c0fa6a3f | ||
|
|
83cca7bc14 | ||
|
|
94d7782d32 | ||
|
|
137d28ac13 | ||
|
|
446cf420e7 | ||
|
|
54b5029886 | ||
|
|
8ce9fbe425 | ||
|
|
bdb812af16 | ||
|
|
41de3e6e65 | ||
|
|
3972c62250 | ||
|
|
ac53ec86aa | ||
|
|
38327104b2 | ||
|
|
4ec8adda6f | ||
|
|
99de5c18a3 | ||
|
|
d43987add7 | ||
|
|
9c61b97a4e | ||
|
|
eb865a6b26 | ||
|
|
9260e53410 | ||
|
|
3b91cd95ea | ||
|
|
7523afe753 | ||
|
|
88bdba7064 | ||
|
|
cccece45f8 | ||
|
|
c35c119ef0 | ||
|
|
3793fcf9d8 | ||
|
|
b8b2efb590 | ||
|
|
609d587397 | ||
|
|
b8f0d17f2f | ||
|
|
0235798136 | ||
|
|
acd8d16bd9 | ||
|
|
35e1ca2039 | ||
|
|
85644ebe3a | ||
|
|
6e2e06ac03 | ||
|
|
6e53efc060 | ||
|
|
dcc5d44094 | ||
|
|
8b567c597a | ||
|
|
d76b8331d1 | ||
|
|
0655cb3be4 | ||
|
|
7a88a0d019 | ||
|
|
086103193a | ||
|
|
d71a4668c6 | ||
|
|
00201ecd8f | ||
|
|
605d9fdd68 | ||
|
|
749e1d8bd2 | ||
|
|
c68456cc68 | ||
|
|
fe06364011 | ||
|
|
68f71ad5fb | ||
|
|
f15e3713ad | ||
|
|
b0b14bf5b6 | ||
|
|
d32324658a | ||
|
|
c9c4f0bb18 | ||
|
|
4c74be62e3 | ||
|
|
fbcb9154fc | ||
|
|
7a507f9a61 | ||
|
|
241b1973cb | ||
|
|
e8c45f4bfd | ||
|
|
5483edded8 | ||
|
|
edd2070a11 | ||
|
|
cd7d5166f1 | ||
|
|
6e57c13727 | ||
|
|
a2f8f75145 | ||
|
|
4dea77ce39 | ||
|
|
ab4b37afab | ||
|
|
c97376d456 | ||
|
|
b3bb189cb8 | ||
|
|
408149ce5e | ||
|
|
f35defd57a | ||
|
|
97c4b72b6a | ||
|
|
9277c1ab40 | ||
|
|
cd993a9648 | ||
|
|
d5cf5621d7 | ||
|
|
f08e3393cb | ||
|
|
8c885ca0f4 | ||
|
|
eecff14cf2 | ||
|
|
2a52b95773 | ||
|
|
e98df05432 | ||
|
|
d242dc8bd5 | ||
|
|
58ba3b178b | ||
|
|
4c24629854 | ||
|
|
bf06b48368 | ||
|
|
c4d150dec6 | ||
|
|
fc2ee9f41e | ||
|
|
bbddd550c6 | ||
|
|
78ab8b1330 | ||
|
|
5acd3c75f7 | ||
|
|
29b87d5434 | ||
|
|
39cc6fd8b2 | ||
|
|
ab30dbaf00 | ||
|
|
a50f408acf | ||
|
|
bb0f2e822d | ||
|
|
c3fe715be2 | ||
|
|
747e9e676d | ||
|
|
d1025ea7e6 | ||
|
|
4bda611ee4 | ||
|
|
ffea7c8793 | ||
|
|
7d516c23c2 | ||
|
|
fe9a989a39 | ||
|
|
9c30ba7f35 | ||
|
|
a46950e972 | ||
|
|
7c644e4982 | ||
|
|
945940e131 | ||
|
|
be512f8298 | ||
|
|
061998e6cf | ||
|
|
ceccba0997 | ||
|
|
a7379389f1 | ||
|
|
9fbde38571 | ||
|
|
c8e149994e | ||
|
|
566737ccc8 | ||
|
|
f28d385e78 | ||
|
|
208b3caa0f | ||
|
|
7ebd0a84ec | ||
|
|
b922740e56 | ||
|
|
d8bb6d2afe | ||
|
|
a35f3d16db | ||
|
|
be76c13da8 | ||
|
|
b8a307ec63 | ||
|
|
ebb92d2ff7 | ||
|
|
ce39c2ade0 | ||
|
|
3cf262f231 | ||
|
|
ac2e671d80 | ||
|
|
86049b7af2 | ||
|
|
99e7413938 | ||
|
|
c5e087b103 | ||
|
|
fb65839653 | ||
|
|
1da27af832 | ||
|
|
c29ac85281 | ||
|
|
1b5fe4a477 | ||
|
|
cdf01d1af8 | ||
|
|
2e54284906 | ||
|
|
b13c97f04f | ||
|
|
c817b2a3e0 | ||
|
|
a354577eff | ||
|
|
09a95983b9 | ||
|
|
25d6df290e | ||
|
|
bd9edc8e76 | ||
|
|
b28998694b | ||
|
|
0b5008eee3 | ||
|
|
a6d128836d | ||
|
|
ea4e5cec19 | ||
|
|
bfeb1ee182 | ||
|
|
2b28011c86 | ||
|
|
66c5ea2216 | ||
|
|
66abd8cbd3 | ||
|
|
a142e81994 | ||
|
|
97b7012ccd | ||
|
|
39d293551a | ||
|
|
fe56b875b4 | ||
|
|
d1035d439a | ||
|
|
532791209e | ||
|
|
ed0b7864d7 | ||
|
|
d2ca281ca1 | ||
|
|
3792c573cd | ||
|
|
ab8ee3fbce | ||
|
|
c2cfab6d9c | ||
|
|
a99667350e | ||
|
|
053703eeab | ||
|
|
3a4e26247b | ||
|
|
a25f19560c | ||
|
|
2af27bb921 | ||
|
|
731c7c0f92 | ||
|
|
b487cf1d19 | ||
|
|
41a2f6de00 | ||
|
|
075254e5a0 | ||
|
|
3daa0de1e6 | ||
|
|
972e372402 | ||
|
|
65c91ba729 | ||
|
|
3ffade5f8a | ||
|
|
33ad4cc2b8 | ||
|
|
f029a09cef | ||
|
|
9468b16f1e | ||
|
|
d4b19d7a5a | ||
|
|
632292731f | ||
|
|
89500e2ab3 | ||
|
|
bc1c6c07b3 | ||
|
|
2fdb959ea1 | ||
|
|
93c4d8bc34 | ||
|
|
504633eadd | ||
|
|
3884aa166e | ||
|
|
ec7abfeabb | ||
|
|
de79d05ad9 | ||
|
|
8b4fd9bd13 | ||
|
|
be8a327258 | ||
|
|
58c1e2bb55 | ||
|
|
5d0a2f5fdb | ||
|
|
4f5a769d01 | ||
|
|
8df2c0090d | ||
|
|
c92aabb6e6 | ||
|
|
c00c44abbe | ||
|
|
92582ce519 | ||
|
|
1291b76986 | ||
|
|
6d291e98e0 | ||
|
|
68498a307c | ||
|
|
a7d73d90db | ||
|
|
69fd5b557d | ||
|
|
3792abd447 | ||
|
|
d55323e575 | ||
|
|
96104d0895 | ||
|
|
2f7dd5ec65 | ||
|
|
8c0fe8f93f | ||
|
|
85ccbd4f95 | ||
|
|
f3b142293c | ||
|
|
4b34dd1965 | ||
|
|
4ae7fe91d6 | ||
|
|
41ac5f7e4e | ||
|
|
343dbafe7d | ||
|
|
5003886591 | ||
|
|
f7de260969 | ||
|
|
69daeb040c | ||
|
|
fdc53b1a76 | ||
|
|
b6247f5391 | ||
|
|
40983f461e | ||
|
|
80ba5ad341 | ||
|
|
0f3a369e12 | ||
|
|
d9edee47aa | ||
|
|
a65b0acd9e | ||
|
|
67c2c481ea | ||
|
|
57c1db3db4 | ||
|
|
cc963b4862 | ||
|
|
2bccc5cf70 | ||
|
|
93404696ac | ||
|
|
a0fc33ecd5 | ||
|
|
4c250df318 | ||
|
|
53fa55655d | ||
|
|
a3e943138a | ||
|
|
f2fd137715 | ||
|
|
830b3b10b0 | ||
|
|
c5ac2f221d | ||
|
|
caaa3fa293 | ||
|
|
1a8456e8ff | ||
|
|
dd2b3c3f26 | ||
|
|
4af5fc041a | ||
|
|
0509a14c0f | ||
|
|
c9c188ceca | ||
|
|
3982bde360 | ||
|
|
aca43d8726 | ||
|
|
d4f07f2096 | ||
|
|
a193fb96b8 | ||
|
|
6d94f9ee16 | ||
|
|
da35daab51 | ||
|
|
48168eacdb | ||
|
|
a27d535f47 | ||
|
|
3a173dcc1f | ||
|
|
619dd15e9a | ||
|
|
6bdeed14fd | ||
|
|
683c1ab16d | ||
|
|
278b2cd004 | ||
|
|
e2b2a5a8d6 | ||
|
|
837f0c67c7 | ||
|
|
fe1b963d38 | ||
|
|
3bce84c0a0 | ||
|
|
d002e9631c | ||
|
|
1348b850bc | ||
|
|
4998cfcf29 | ||
|
|
49d36209bf | ||
|
|
d537e16a47 | ||
|
|
04a14ee3e2 | ||
|
|
7209bff091 | ||
|
|
05b63f6126 | ||
|
|
20058af7ae | ||
|
|
9ae86f6198 | ||
|
|
ad199fe46d | ||
|
|
e6713e850e | ||
|
|
1544abac7a | ||
|
|
87b3e5abec | ||
|
|
5ba03f63c6 | ||
|
|
684397a675 | ||
|
|
361e5d3066 | ||
|
|
c306390c93 | ||
|
|
66364abf73 | ||
|
|
5d68d1dc7a | ||
|
|
6c01530ff3 | ||
|
|
69e15e8371 | ||
|
|
41857be937 | ||
|
|
51e9d0c08f | ||
|
|
841d602fc8 | ||
|
|
35d76d2278 | ||
|
|
add1bcd1dc | ||
|
|
db800f73f1 | ||
|
|
39d093fc45 | ||
|
|
a30fb9917e | ||
|
|
4065f9801d | ||
|
|
25898e4216 | ||
|
|
9354d4a84f | ||
|
|
2bbbbe207e | ||
|
|
826a2a7b63 | ||
|
|
4bfb33bdb4 | ||
|
|
1b70b8ca3a | ||
|
|
09936f47a0 | ||
|
|
ed9a438b62 | ||
|
|
8b26ad55c3 | ||
|
|
7945e4d398 | ||
|
|
9d030c16fa | ||
|
|
147544bbaa | ||
|
|
6cf162b42d | ||
|
|
15a9562697 | ||
|
|
21d6bee5aa | ||
|
|
90f765f516 | ||
|
|
d5e9b2efef | ||
|
|
5e81e58f3f | ||
|
|
ba81277614 | ||
|
|
124e654af4 | ||
|
|
9fb3cffefe | ||
|
|
f4bdc2a23d | ||
|
|
c7c8b50443 | ||
|
|
86d12faf4d | ||
|
|
d07a3d2a24 | ||
|
|
5d2b75964f | ||
|
|
4c0d4f769f | ||
|
|
ebd2555fcc | ||
|
|
9b0114e4c9 | ||
|
|
eaedf85f3e | ||
|
|
ce6b91e4de | ||
|
|
6b54081dc6 | ||
|
|
ef947bd339 | ||
|
|
ccd6ac458f | ||
|
|
884641836b | ||
|
|
bd9d408f53 | ||
|
|
c7dd68015c | ||
|
|
42579964b9 | ||
|
|
241379ef2b | ||
|
|
78d85a459c | ||
|
|
ddbf49bc7e | ||
|
|
2643b6b0c0 | ||
|
|
e2bc59bec9 | ||
|
|
28dc67e2c2 | ||
|
|
f2beef8675 | ||
|
|
c00452b686 | ||
|
|
09832b9672 | ||
|
|
8e01a772ae | ||
|
|
f8670c565c | ||
|
|
d3e7e9554c | ||
|
|
35e15efd37 | ||
|
|
54a5d271d3 | ||
|
|
ba74559c04 | ||
|
|
3209a0b6c7 | ||
|
|
723f131f76 | ||
|
|
164ebe22bf | ||
|
|
ec362f77e4 | ||
|
|
c7536993cf | ||
|
|
c16e5ad42e | ||
|
|
56b762fa55 | ||
|
|
0117e7f6fc | ||
|
|
2a37feb1eb | ||
|
|
475c7ed2eb | ||
|
|
ee1ca9cd10 | ||
|
|
d555153e51 | ||
|
|
e14ddc840e | ||
|
|
013e46b138 | ||
|
|
df5f1ee67b | ||
|
|
4e9bca7218 | ||
|
|
e8bfe253ae | ||
|
|
9585d54b31 | ||
|
|
b25f9cc7d4 | ||
|
|
bd92902560 | ||
|
|
10a77ce888 | ||
|
|
81c199dd9b | ||
|
|
3b82572b9e | ||
|
|
9d85ab415f | ||
|
|
d0358c0063 | ||
|
|
e103726f4d | ||
|
|
4262c90148 | ||
|
|
bf8f419ca9 | ||
|
|
cccb6ad2c9 | ||
|
|
775e4f1bad |
@@ -3,10 +3,30 @@ Language: Cpp
|
|||||||
AccessModifierOffset: -2
|
AccessModifierOffset: -2
|
||||||
AlignAfterOpenBracket: Align
|
AlignAfterOpenBracket: Align
|
||||||
AlignArrayOfStructures: None
|
AlignArrayOfStructures: None
|
||||||
AlignConsecutiveMacros: None
|
AlignConsecutiveAssignments:
|
||||||
AlignConsecutiveAssignments: None
|
Enabled: false
|
||||||
AlignConsecutiveBitFields: None
|
AcrossEmptyLines: false
|
||||||
AlignConsecutiveDeclarations: None
|
AcrossComments: false
|
||||||
|
AlignCompound: false
|
||||||
|
PadOperators: true
|
||||||
|
AlignConsecutiveBitFields:
|
||||||
|
Enabled: false
|
||||||
|
AcrossEmptyLines: false
|
||||||
|
AcrossComments: false
|
||||||
|
AlignCompound: false
|
||||||
|
PadOperators: true
|
||||||
|
AlignConsecutiveDeclarations:
|
||||||
|
Enabled: false
|
||||||
|
AcrossEmptyLines: false
|
||||||
|
AcrossComments: false
|
||||||
|
AlignCompound: false
|
||||||
|
PadOperators: true
|
||||||
|
AlignConsecutiveMacros:
|
||||||
|
Enabled: false
|
||||||
|
AcrossEmptyLines: false
|
||||||
|
AcrossComments: false
|
||||||
|
AlignCompound: false
|
||||||
|
PadOperators: true
|
||||||
AlignEscapedNewlines: Right
|
AlignEscapedNewlines: Right
|
||||||
AlignOperands: Align
|
AlignOperands: Align
|
||||||
AlignTrailingComments: true
|
AlignTrailingComments: true
|
||||||
@@ -47,7 +67,7 @@ BraceWrapping:
|
|||||||
SplitEmptyRecord: true
|
SplitEmptyRecord: true
|
||||||
SplitEmptyNamespace: true
|
SplitEmptyNamespace: true
|
||||||
BreakBeforeBinaryOperators: None
|
BreakBeforeBinaryOperators: None
|
||||||
BreakBeforeConceptDeclarations: true
|
BreakBeforeConceptDeclarations: Always
|
||||||
BreakBeforeBraces: Attach
|
BreakBeforeBraces: Attach
|
||||||
BreakBeforeInheritanceComma: false
|
BreakBeforeInheritanceComma: false
|
||||||
BreakInheritanceList: BeforeColon
|
BreakInheritanceList: BeforeColon
|
||||||
@@ -102,9 +122,10 @@ IndentCaseBlocks: false
|
|||||||
IndentGotoLabels: true
|
IndentGotoLabels: true
|
||||||
IndentPPDirectives: AfterHash
|
IndentPPDirectives: AfterHash
|
||||||
IndentExternBlock: AfterExternBlock
|
IndentExternBlock: AfterExternBlock
|
||||||
IndentRequires: false
|
IndentRequiresClause: false
|
||||||
IndentWidth: 2
|
IndentWidth: 2
|
||||||
IndentWrappedFunctionNames: false
|
IndentWrappedFunctionNames: false
|
||||||
|
InsertBraces: false
|
||||||
InsertTrailingCommas: None
|
InsertTrailingCommas: None
|
||||||
JavaScriptQuotes: Leave
|
JavaScriptQuotes: Leave
|
||||||
JavaScriptWrapImports: true
|
JavaScriptWrapImports: true
|
||||||
@@ -134,6 +155,7 @@ PPIndentWidth: -1
|
|||||||
ReferenceAlignment: Pointer
|
ReferenceAlignment: Pointer
|
||||||
ReflowComments: true
|
ReflowComments: true
|
||||||
RemoveBracesLLVM: false
|
RemoveBracesLLVM: false
|
||||||
|
RequiresClausePosition: OwnLine
|
||||||
SeparateDefinitionBlocks: Leave
|
SeparateDefinitionBlocks: Leave
|
||||||
ShortNamespaceLines: 1
|
ShortNamespaceLines: 1
|
||||||
SortIncludes: Never
|
SortIncludes: Never
|
||||||
@@ -155,6 +177,8 @@ SpaceBeforeParensOptions:
|
|||||||
AfterFunctionDeclarationName: false
|
AfterFunctionDeclarationName: false
|
||||||
AfterIfMacros: true
|
AfterIfMacros: true
|
||||||
AfterOverloadedOperator: false
|
AfterOverloadedOperator: false
|
||||||
|
AfterRequiresInClause: false
|
||||||
|
AfterRequiresInExpression: false
|
||||||
BeforeNonEmptyParentheses: false
|
BeforeNonEmptyParentheses: false
|
||||||
SpaceAroundPointerQualifiers: Default
|
SpaceAroundPointerQualifiers: Default
|
||||||
SpaceBeforeRangeBasedForLoopColon: true
|
SpaceBeforeRangeBasedForLoopColon: true
|
||||||
|
|||||||
4
.github/dependabot.yml
vendored
4
.github/dependabot.yml
vendored
@@ -4,3 +4,7 @@ updates:
|
|||||||
directory: "/"
|
directory: "/"
|
||||||
schedule:
|
schedule:
|
||||||
interval: "weekly"
|
interval: "weekly"
|
||||||
|
- package-ecosystem: "gomod"
|
||||||
|
directory: "/"
|
||||||
|
schedule:
|
||||||
|
interval: "weekly"
|
||||||
|
|||||||
387
.github/workflows/build.yml
vendored
387
.github/workflows/build.yml
vendored
@@ -5,75 +5,87 @@ on: [push, pull_request]
|
|||||||
permissions: read-all
|
permissions: read-all
|
||||||
|
|
||||||
env:
|
env:
|
||||||
LIBBPF_VERSION: v1.2.2
|
LIBBPF_VERSION: v1.3.0
|
||||||
OPENSSL1_VERSION: 1_1_1w+quic
|
OPENSSL1_VERSION: 1_1_1w+quic
|
||||||
OPENSSL3_VERSION: 3.1.2+quic
|
OPENSSL3_VERSION: 3.1.5+quic
|
||||||
BORINGSSL_VERSION: 6ca49385b168f47a50e7172d82a590b218f55e4d
|
BORINGSSL_VERSION: 6ab7c1482bf4cdc91c87bc512aaf68ffb18975ec
|
||||||
NGHTTP3_VERSION: v0.15.0
|
AWSLC_VERSION: v1.26.0
|
||||||
NGTCP2_VERSION: v0.19.1
|
NGHTTP3_VERSION: v1.3.0
|
||||||
|
NGTCP2_VERSION: v1.5.0
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build-cache:
|
build-cache:
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
os: [ubuntu-22.04, macos-12]
|
os: [ubuntu-22.04, macos-13, macos-14]
|
||||||
|
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
- name: Restore libbpf cache
|
- name: Restore libbpf cache
|
||||||
id: cache-libbpf
|
id: cache-libbpf
|
||||||
uses: actions/cache@v3
|
uses: actions/cache@v4
|
||||||
if: runner.os == 'Linux'
|
if: runner.os == 'Linux'
|
||||||
with:
|
with:
|
||||||
path: libbpf/build
|
path: libbpf/build
|
||||||
key: ${{ runner.os }}-libbpf-${{ env.LIBBPF_VERSION }}
|
key: ${{ matrix.os }}-libbpf-${{ env.LIBBPF_VERSION }}
|
||||||
- name: Restore OpenSSL v1.1.1 cache
|
- name: Restore OpenSSL v1.1.1 cache
|
||||||
id: cache-openssl1
|
id: cache-openssl1
|
||||||
uses: actions/cache@v3
|
uses: actions/cache@v4
|
||||||
with:
|
with:
|
||||||
path: openssl1/build
|
path: openssl1/build
|
||||||
key: ${{ runner.os }}-openssl-${{ env.OPENSSL1_VERSION }}
|
key: ${{ matrix.os }}-openssl-${{ env.OPENSSL1_VERSION }}
|
||||||
- name: Restore OpenSSL v3.x cache
|
- name: Restore OpenSSL v3.x cache
|
||||||
id: cache-openssl3
|
id: cache-openssl3
|
||||||
uses: actions/cache@v3
|
uses: actions/cache@v4
|
||||||
with:
|
with:
|
||||||
path: openssl3/build
|
path: openssl3/build
|
||||||
key: ${{ runner.os }}-openssl-${{ env.OPENSSL3_VERSION }}
|
key: ${{ matrix.os }}-openssl-${{ env.OPENSSL3_VERSION }}
|
||||||
- name: Restore BoringSSL cache
|
- name: Restore BoringSSL cache
|
||||||
id: cache-boringssl
|
id: cache-boringssl
|
||||||
uses: actions/cache@v3
|
uses: actions/cache@v4
|
||||||
with:
|
with:
|
||||||
path: |
|
path: |
|
||||||
boringssl/build/crypto/libcrypto.a
|
boringssl/build/crypto/libcrypto.a
|
||||||
boringssl/build/ssl/libssl.a
|
boringssl/build/ssl/libssl.a
|
||||||
boringssl/include
|
boringssl/include
|
||||||
key: ${{ runner.os }}-boringssl-${{ env.BORINGSSL_VERSION }}
|
key: ${{ matrix.os }}-boringssl-${{ env.BORINGSSL_VERSION }}
|
||||||
|
- name: Restore aws-lc cache
|
||||||
|
id: cache-awslc
|
||||||
|
uses: actions/cache@v4
|
||||||
|
with:
|
||||||
|
path: |
|
||||||
|
aws-lc/build/crypto/libcrypto.a
|
||||||
|
aws-lc/build/ssl/libssl.a
|
||||||
|
aws-lc/include
|
||||||
|
key: ${{ matrix.os }}-awslc-${{ env.AWSLC_VERSION }}
|
||||||
- name: Restore nghttp3 cache
|
- name: Restore nghttp3 cache
|
||||||
id: cache-nghttp3
|
id: cache-nghttp3
|
||||||
uses: actions/cache@v3
|
uses: actions/cache@v4
|
||||||
with:
|
with:
|
||||||
path: nghttp3/build
|
path: nghttp3/build
|
||||||
key: ${{ runner.os }}-nghttp3-${{ env.NGHTTP3_VERSION }}
|
key: ${{ matrix.os }}-nghttp3-${{ env.NGHTTP3_VERSION }}
|
||||||
- name: Restore ngtcp2 + quictls/openssl v1.1.1 cache
|
- name: Restore ngtcp2 + quictls/openssl v1.1.1 cache
|
||||||
id: cache-ngtcp2-openssl1
|
id: cache-ngtcp2-openssl1
|
||||||
uses: actions/cache@v3
|
uses: actions/cache@v4
|
||||||
with:
|
with:
|
||||||
path: ngtcp2-openssl1/build
|
path: ngtcp2-openssl1/build
|
||||||
key: ${{ runner.os }}-ngtcp2-${{ env.NGTCP2_VERSION }}-openssl-${{ env.OPENSSL1_VERSION }}
|
key: ${{ matrix.os }}-ngtcp2-${{ env.NGTCP2_VERSION }}-openssl-${{ env.OPENSSL1_VERSION }}
|
||||||
- name: Restore ngtcp2 + quictls/openssl v3.x cache
|
- name: Restore ngtcp2 + quictls/openssl v3.x cache
|
||||||
id: cache-ngtcp2-openssl3
|
id: cache-ngtcp2-openssl3
|
||||||
uses: actions/cache@v3
|
uses: actions/cache@v4
|
||||||
with:
|
with:
|
||||||
path: ngtcp2-openssl3/build
|
path: ngtcp2-openssl3/build
|
||||||
key: ${{ runner.os }}-ngtcp2-${{ env.NGTCP2_VERSION }}-openssl-${{ env.OPENSSL3_VERSION }}
|
key: ${{ matrix.os }}-ngtcp2-${{ env.NGTCP2_VERSION }}-openssl-${{ env.OPENSSL3_VERSION }}
|
||||||
- id: settings
|
- id: settings
|
||||||
if: |
|
if: |
|
||||||
(steps.cache-libbpf.outputs.cache-hit != 'true' && runner.os == 'Linux') ||
|
(steps.cache-libbpf.outputs.cache-hit != 'true' && runner.os == 'Linux') ||
|
||||||
steps.cache-openssl1.outputs.cache-hit != 'true' ||
|
steps.cache-openssl1.outputs.cache-hit != 'true' ||
|
||||||
steps.cache-openssl3.outputs.cache-hit != 'true' ||
|
steps.cache-openssl3.outputs.cache-hit != 'true' ||
|
||||||
steps.cache-boringssl.outputs.cache-hit != 'true' ||
|
steps.cache-boringssl.outputs.cache-hit != 'true' ||
|
||||||
|
steps.cache-awslc.outputs.cache-hit != 'true' ||
|
||||||
steps.cache-nghttp3.outputs.cache-hit != 'true' ||
|
steps.cache-nghttp3.outputs.cache-hit != 'true' ||
|
||||||
steps.cache-ngtcp2-openssl1.outputs.cache-hit != 'true' ||
|
steps.cache-ngtcp2-openssl1.outputs.cache-hit != 'true' ||
|
||||||
steps.cache-ngtcp2-openssl3.outputs.cache-hit != 'true'
|
steps.cache-ngtcp2-openssl3.outputs.cache-hit != 'true'
|
||||||
@@ -82,9 +94,10 @@ jobs:
|
|||||||
- name: Linux setup
|
- name: Linux setup
|
||||||
if: runner.os == 'Linux' && steps.settings.outputs.needs-build == 'true'
|
if: runner.os == 'Linux' && steps.settings.outputs.needs-build == 'true'
|
||||||
run: |
|
run: |
|
||||||
|
sudo apt-get update
|
||||||
sudo apt-get install \
|
sudo apt-get install \
|
||||||
g++-12 \
|
g++-12 \
|
||||||
clang-14 \
|
clang-15 \
|
||||||
autoconf \
|
autoconf \
|
||||||
automake \
|
automake \
|
||||||
autotools-dev \
|
autotools-dev \
|
||||||
@@ -104,13 +117,13 @@ jobs:
|
|||||||
- name: Build libbpf
|
- name: Build libbpf
|
||||||
if: steps.cache-libbpf.outputs.cache-hit != 'true' && runner.os == 'Linux'
|
if: steps.cache-libbpf.outputs.cache-hit != 'true' && runner.os == 'Linux'
|
||||||
run: |
|
run: |
|
||||||
git clone -b ${{ env.LIBBPF_VERSION }} https://github.com/libbpf/libbpf
|
git clone --recursive -b ${{ env.LIBBPF_VERSION }} https://github.com/libbpf/libbpf
|
||||||
cd libbpf
|
cd libbpf
|
||||||
make -C src install PREFIX=$PWD/build
|
make -C src install PREFIX=$PWD/build
|
||||||
- name: Build quictls/openssl v1.1.1
|
- name: Build quictls/openssl v1.1.1
|
||||||
if: steps.cache-openssl1.outputs.cache-hit != 'true'
|
if: steps.cache-openssl1.outputs.cache-hit != 'true'
|
||||||
run: |
|
run: |
|
||||||
git clone --depth 1 -b OpenSSL_${{ env.OPENSSL1_VERSION }} https://github.com/quictls/openssl openssl1
|
git clone --recursive --depth 1 -b OpenSSL_${{ env.OPENSSL1_VERSION }} https://github.com/quictls/openssl openssl1
|
||||||
cd openssl1
|
cd openssl1
|
||||||
./config --prefix=$PWD/build
|
./config --prefix=$PWD/build
|
||||||
make -j"$(nproc 2> /dev/null || sysctl -n hw.ncpu)"
|
make -j"$(nproc 2> /dev/null || sysctl -n hw.ncpu)"
|
||||||
@@ -118,7 +131,7 @@ jobs:
|
|||||||
- name: Build quictls/openssl v3.x
|
- name: Build quictls/openssl v3.x
|
||||||
if: steps.cache-openssl3.outputs.cache-hit != 'true'
|
if: steps.cache-openssl3.outputs.cache-hit != 'true'
|
||||||
run: |
|
run: |
|
||||||
git clone --depth 1 -b openssl-${{ env.OPENSSL3_VERSION }} https://github.com/quictls/openssl openssl3
|
git clone --recursive --depth 1 -b openssl-${{ env.OPENSSL3_VERSION }} https://github.com/quictls/openssl openssl3
|
||||||
cd openssl3
|
cd openssl3
|
||||||
./config enable-ktls --prefix=$PWD/build --libdir=$PWD/build/lib
|
./config enable-ktls --prefix=$PWD/build --libdir=$PWD/build/lib
|
||||||
make -j"$(nproc 2> /dev/null || sysctl -n hw.ncpu)"
|
make -j"$(nproc 2> /dev/null || sysctl -n hw.ncpu)"
|
||||||
@@ -126,26 +139,36 @@ jobs:
|
|||||||
- name: Build BoringSSL
|
- name: Build BoringSSL
|
||||||
if: steps.cache-boringssl.outputs.cache-hit != 'true'
|
if: steps.cache-boringssl.outputs.cache-hit != 'true'
|
||||||
run: |
|
run: |
|
||||||
git clone https://boringssl.googlesource.com/boringssl
|
mkdir boringssl
|
||||||
cd boringssl
|
cd boringssl
|
||||||
|
git init
|
||||||
|
git remote add origin https://boringssl.googlesource.com/boringssl
|
||||||
|
git fetch origin --depth 1 ${{ env.BORINGSSL_VERSION }}
|
||||||
git checkout ${{ env.BORINGSSL_VERSION }}
|
git checkout ${{ env.BORINGSSL_VERSION }}
|
||||||
mkdir build
|
mkdir build
|
||||||
cd build
|
cd build
|
||||||
cmake -DCMAKE_POSITION_INDEPENDENT_CODE=ON ..
|
cmake -DCMAKE_POSITION_INDEPENDENT_CODE=ON ..
|
||||||
make -j"$(nproc 2> /dev/null || sysctl -n hw.ncpu)"
|
make -j"$(nproc 2> /dev/null || sysctl -n hw.ncpu)"
|
||||||
|
- name: Build aws-lc
|
||||||
|
if: steps.cache-awslc.outputs.cache-hit != 'true'
|
||||||
|
run: |
|
||||||
|
git clone --recursive --depth 1 -b "${AWSLC_VERSION}" https://github.com/aws/aws-lc
|
||||||
|
cd aws-lc
|
||||||
|
cmake -B build -DDISABLE_GO=ON
|
||||||
|
make -j"$(nproc 2> /dev/null || sysctl -n hw.ncpu)" -C build
|
||||||
- name: Build nghttp3
|
- name: Build nghttp3
|
||||||
if: steps.cache-nghttp3.outputs.cache-hit != 'true'
|
if: steps.cache-nghttp3.outputs.cache-hit != 'true'
|
||||||
run: |
|
run: |
|
||||||
git clone --depth 1 -b ${{ env.NGHTTP3_VERSION}} https://github.com/ngtcp2/nghttp3
|
git clone --recursive --depth 1 -b ${{ env.NGHTTP3_VERSION}} https://github.com/ngtcp2/nghttp3
|
||||||
cd nghttp3
|
cd nghttp3
|
||||||
autoreconf -i
|
autoreconf -i
|
||||||
./configure --prefix=$PWD/build --enable-lib-only
|
./configure --prefix=$PWD/build --enable-lib-only
|
||||||
make -j"$(nproc 2> /dev/null || sysctl -n hw.ncpu)" check
|
make -j"$(nproc 2> /dev/null || sysctl -n hw.ncpu)" check
|
||||||
make install
|
make install
|
||||||
- name: Build ngtcp2 + quictls/openssl v1.1.1
|
- name: Build ngtcp2 + quictls/openssl v1.1.1 + BoringSSL
|
||||||
if: steps.cache-ngtcp2-openssl1.outputs.cache-hit != 'true'
|
if: steps.cache-ngtcp2-openssl1.outputs.cache-hit != 'true'
|
||||||
run: |
|
run: |
|
||||||
git clone --depth 1 -b ${{ env.NGTCP2_VERSION }} https://github.com/ngtcp2/ngtcp2 ngtcp2-openssl1
|
git clone --recursive --depth 1 -b ${{ env.NGTCP2_VERSION }} https://github.com/ngtcp2/ngtcp2 ngtcp2-openssl1
|
||||||
cd ngtcp2-openssl1
|
cd ngtcp2-openssl1
|
||||||
autoreconf -i
|
autoreconf -i
|
||||||
./configure --prefix=$PWD/build --enable-lib-only \
|
./configure --prefix=$PWD/build --enable-lib-only \
|
||||||
@@ -155,16 +178,16 @@ jobs:
|
|||||||
--with-boringssl
|
--with-boringssl
|
||||||
make -j"$(nproc 2> /dev/null || sysctl -n hw.ncpu)" check
|
make -j"$(nproc 2> /dev/null || sysctl -n hw.ncpu)" check
|
||||||
make install
|
make install
|
||||||
- name: Build ngtcp2 + quictls/openssl v3.x
|
- name: Build ngtcp2 + quictls/openssl v3.x + aws-lc
|
||||||
if: steps.cache-ngtcp2-openssl3.outputs.cache-hit != 'true'
|
if: steps.cache-ngtcp2-openssl3.outputs.cache-hit != 'true'
|
||||||
run: |
|
run: |
|
||||||
git clone --depth 1 -b ${{ env.NGTCP2_VERSION }} https://github.com/ngtcp2/ngtcp2 ngtcp2-openssl3
|
git clone --recursive --depth 1 -b ${{ env.NGTCP2_VERSION }} https://github.com/ngtcp2/ngtcp2 ngtcp2-openssl3
|
||||||
cd ngtcp2-openssl3
|
cd ngtcp2-openssl3
|
||||||
autoreconf -i
|
autoreconf -i
|
||||||
./configure --prefix=$PWD/build --enable-lib-only \
|
./configure --prefix=$PWD/build --enable-lib-only \
|
||||||
PKG_CONFIG_PATH="../openssl3/build/lib/pkgconfig" \
|
PKG_CONFIG_PATH="../openssl3/build/lib/pkgconfig" \
|
||||||
BORINGSSL_CFLAGS="-I$PWD/../boringssl/include/" \
|
BORINGSSL_CFLAGS="-I$PWD/../aws-lc/include/" \
|
||||||
BORINGSSL_LIBS="-L$PWD/../boringssl/build/ssl -lssl -L$PWD/../boringssl/build/crypto -lcrypto" \
|
BORINGSSL_LIBS="-L$PWD/../aws-lc/build/ssl -lssl -L$PWD/../aws-lc/build/crypto -lcrypto" \
|
||||||
--with-boringssl
|
--with-boringssl
|
||||||
make -j"$(nproc 2> /dev/null || sysctl -n hw.ncpu)" check
|
make -j"$(nproc 2> /dev/null || sysctl -n hw.ncpu)" check
|
||||||
make install
|
make install
|
||||||
@@ -175,45 +198,71 @@ jobs:
|
|||||||
|
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
os: [ubuntu-22.04, macos-12]
|
os: [ubuntu-22.04, macos-13, macos-14]
|
||||||
compiler: [gcc, clang]
|
compiler: [gcc, clang]
|
||||||
buildtool: [autotools, cmake]
|
buildtool: [autotools, cmake]
|
||||||
http3: [http3, no-http3]
|
http3: [http3, no-http3]
|
||||||
openssl: [openssl1, openssl3, boringssl]
|
openssl: [openssl1, openssl3, boringssl, awslc]
|
||||||
exclude:
|
exclude:
|
||||||
- os: macos-12
|
- os: macos-13
|
||||||
|
openssl: openssl3
|
||||||
|
- os: macos-14
|
||||||
openssl: openssl3
|
openssl: openssl3
|
||||||
- http3: no-http3
|
- http3: no-http3
|
||||||
openssl: openssl3
|
openssl: openssl3
|
||||||
- os: macos-12
|
- os: macos-13
|
||||||
|
compiler: gcc
|
||||||
|
- os: macos-14
|
||||||
compiler: gcc
|
compiler: gcc
|
||||||
- # disable macos cmake because of include path issue
|
- # disable macos cmake because of include path issue
|
||||||
os: macos-12
|
os: macos-13
|
||||||
buildtool: cmake
|
buildtool: cmake
|
||||||
- os: macos-12
|
- # disable macos cmake because of include path issue
|
||||||
|
os: macos-14
|
||||||
|
buildtool: cmake
|
||||||
|
- os: macos-13
|
||||||
|
openssl: boringssl
|
||||||
|
- os: macos-14
|
||||||
openssl: boringssl
|
openssl: boringssl
|
||||||
- openssl: boringssl
|
- openssl: boringssl
|
||||||
buildtool: cmake
|
buildtool: cmake
|
||||||
- openssl: boringssl
|
- openssl: boringssl
|
||||||
compiler: gcc
|
compiler: gcc
|
||||||
|
- os: macos-13
|
||||||
|
openssl: awslc
|
||||||
|
- os: macos-14
|
||||||
|
openssl: awslc
|
||||||
|
- openssl: awslc
|
||||||
|
buildtool: cmake
|
||||||
|
- openssl: awslc
|
||||||
|
compiler: gcc
|
||||||
|
include:
|
||||||
|
- os: ubuntu-22.04
|
||||||
|
compiler: clang
|
||||||
|
buildtool: distcheck
|
||||||
|
http3: http3
|
||||||
|
openssl: awslc
|
||||||
|
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
submodules: recursive
|
||||||
- name: Linux setup
|
- name: Linux setup
|
||||||
if: runner.os == 'Linux'
|
if: runner.os == 'Linux'
|
||||||
run: |
|
run: |
|
||||||
|
sudo apt-get update
|
||||||
sudo apt-get install \
|
sudo apt-get install \
|
||||||
g++-12 \
|
g++-12 \
|
||||||
clang-14 \
|
clang-15 \
|
||||||
autoconf \
|
autoconf \
|
||||||
automake \
|
automake \
|
||||||
autotools-dev \
|
autotools-dev \
|
||||||
libtool \
|
libtool \
|
||||||
pkg-config \
|
pkg-config \
|
||||||
zlib1g-dev \
|
zlib1g-dev \
|
||||||
libcunit1-dev \
|
|
||||||
libssl-dev \
|
libssl-dev \
|
||||||
libxml2-dev \
|
libxml2-dev \
|
||||||
libev-dev \
|
libev-dev \
|
||||||
@@ -222,10 +271,17 @@ jobs:
|
|||||||
libjemalloc-dev \
|
libjemalloc-dev \
|
||||||
libc-ares-dev \
|
libc-ares-dev \
|
||||||
libelf-dev \
|
libelf-dev \
|
||||||
|
libbrotli-dev \
|
||||||
cmake \
|
cmake \
|
||||||
cmake-data
|
cmake-data
|
||||||
echo 'CPPFLAGS=-fsanitize=address,undefined -fno-sanitize-recover=undefined -g' >> $GITHUB_ENV
|
echo 'CPPFLAGS=-fsanitize=address,undefined -fno-sanitize-recover=undefined -g' >> $GITHUB_ENV
|
||||||
echo 'LDFLAGS=-fsanitize=address,undefined -fno-sanitize-recover=undefined' >> $GITHUB_ENV
|
echo 'LDFLAGS=-fsanitize=address,undefined -fno-sanitize-recover=undefined' >> $GITHUB_ENV
|
||||||
|
|
||||||
|
# https://github.com/actions/runner-images/issues/9491#issuecomment-1989718917
|
||||||
|
# Asan in llvm 14 provided in ubuntu 22.04 is incompatible with
|
||||||
|
# high-entropy ASLR in much newer kernels that GitHub runners are
|
||||||
|
# using leading to random crashes: https://reviews.llvm.org/D148280
|
||||||
|
sudo sysctl vm.mmap_rnd_bits=28
|
||||||
- name: MacOS setup
|
- name: MacOS setup
|
||||||
if: runner.os == 'macOS'
|
if: runner.os == 'macOS'
|
||||||
run: |
|
run: |
|
||||||
@@ -233,8 +289,8 @@ jobs:
|
|||||||
libev \
|
libev \
|
||||||
libevent \
|
libevent \
|
||||||
c-ares \
|
c-ares \
|
||||||
cunit \
|
|
||||||
libressl \
|
libressl \
|
||||||
|
brotli \
|
||||||
autoconf \
|
autoconf \
|
||||||
automake \
|
automake \
|
||||||
pkg-config \
|
pkg-config \
|
||||||
@@ -243,8 +299,8 @@ jobs:
|
|||||||
- name: Setup clang (Linux)
|
- name: Setup clang (Linux)
|
||||||
if: runner.os == 'Linux' && matrix.compiler == 'clang'
|
if: runner.os == 'Linux' && matrix.compiler == 'clang'
|
||||||
run: |
|
run: |
|
||||||
echo 'CC=clang-14' >> $GITHUB_ENV
|
echo 'CC=clang-15' >> $GITHUB_ENV
|
||||||
echo 'CXX=clang++-14' >> $GITHUB_ENV
|
echo 'CXX=clang++-15' >> $GITHUB_ENV
|
||||||
- name: Setup clang (MacOS)
|
- name: Setup clang (MacOS)
|
||||||
if: runner.os == 'macOS' && matrix.compiler == 'clang'
|
if: runner.os == 'macOS' && matrix.compiler == 'clang'
|
||||||
run: |
|
run: |
|
||||||
@@ -255,17 +311,19 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
echo 'CC=gcc-12' >> $GITHUB_ENV
|
echo 'CC=gcc-12' >> $GITHUB_ENV
|
||||||
echo 'CXX=g++-12' >> $GITHUB_ENV
|
echo 'CXX=g++-12' >> $GITHUB_ENV
|
||||||
|
# g++-12 is known to produce false positive warnings.
|
||||||
|
echo 'CXXFLAGS=-Wno-restrict' >> $GITHUB_ENV
|
||||||
- name: Setup gcc (MacOS)
|
- name: Setup gcc (MacOS)
|
||||||
if: runner.os == 'macOS' && matrix.compiler == 'gcc'
|
if: runner.os == 'macOS' && matrix.compiler == 'gcc'
|
||||||
run: |
|
run: |
|
||||||
echo 'CC=gcc' >> $GITHUB_ENV
|
echo 'CC=gcc' >> $GITHUB_ENV
|
||||||
echo 'CXX=g++' >> $GITHUB_ENV
|
echo 'CXX=g++' >> $GITHUB_ENV
|
||||||
- name: Restore libbpf cache
|
- name: Restore libbpf cache
|
||||||
uses: actions/cache/restore@v3
|
uses: actions/cache/restore@v4
|
||||||
if: matrix.http3 == 'http3' && matrix.compiler == 'clang' && runner.os == 'Linux'
|
if: matrix.http3 == 'http3' && matrix.compiler == 'clang' && runner.os == 'Linux'
|
||||||
with:
|
with:
|
||||||
path: libbpf/build
|
path: libbpf/build
|
||||||
key: ${{ runner.os }}-libbpf-${{ env.LIBBPF_VERSION }}
|
key: ${{ matrix.os }}-libbpf-${{ env.LIBBPF_VERSION }}
|
||||||
fail-on-cache-miss: true
|
fail-on-cache-miss: true
|
||||||
- name: Set libbpf variables
|
- name: Set libbpf variables
|
||||||
if: matrix.http3 == 'http3' && matrix.compiler == 'clang' && runner.os == 'Linux'
|
if: matrix.http3 == 'http3' && matrix.compiler == 'clang' && runner.os == 'Linux'
|
||||||
@@ -277,35 +335,67 @@ jobs:
|
|||||||
|
|
||||||
echo 'EXTRA_AUTOTOOLS_OPTS='"$EXTRA_AUTOTOOLS_OPTS" >> $GITHUB_ENV
|
echo 'EXTRA_AUTOTOOLS_OPTS='"$EXTRA_AUTOTOOLS_OPTS" >> $GITHUB_ENV
|
||||||
echo 'EXTRA_CMAKE_OPTS='"$EXTRA_CMAKE_OPTS" >> $GITHUB_ENV
|
echo 'EXTRA_CMAKE_OPTS='"$EXTRA_CMAKE_OPTS" >> $GITHUB_ENV
|
||||||
|
- name: Setup libev variables
|
||||||
|
if: matrix.os == 'macos-14'
|
||||||
|
run: |
|
||||||
|
LIBEV_CFLAGS="-I/opt/homebrew/Cellar/libev/4.33/include"
|
||||||
|
LIBEV_LIBS="-L/opt/homebrew/Cellar/libev/4.33/lib -lev"
|
||||||
|
|
||||||
|
echo 'LIBEV_CFLAGS='"$LIBEV_CFLAGS" >> $GITHUB_ENV
|
||||||
|
echo 'LIBEV_LIBS='"$LIBEV_LIBS" >> $GITHUB_ENV
|
||||||
- name: Restore quictls/openssl v1.1.1 cache
|
- name: Restore quictls/openssl v1.1.1 cache
|
||||||
uses: actions/cache/restore@v3
|
uses: actions/cache/restore@v4
|
||||||
if: matrix.http3 == 'http3' && matrix.openssl == 'openssl1'
|
if: matrix.openssl == 'openssl1'
|
||||||
with:
|
with:
|
||||||
path: openssl1/build
|
path: openssl1/build
|
||||||
key: ${{ runner.os }}-openssl-${{ env.OPENSSL1_VERSION }}
|
key: ${{ matrix.os }}-openssl-${{ env.OPENSSL1_VERSION }}
|
||||||
fail-on-cache-miss: true
|
fail-on-cache-miss: true
|
||||||
- name: Restore quictls/openssl v3.x cache
|
- name: Restore quictls/openssl v3.x cache
|
||||||
uses: actions/cache/restore@v3
|
uses: actions/cache/restore@v4
|
||||||
if: matrix.http3 == 'http3' && matrix.openssl == 'openssl3'
|
if: matrix.openssl == 'openssl3'
|
||||||
with:
|
with:
|
||||||
path: openssl3/build
|
path: openssl3/build
|
||||||
key: ${{ runner.os }}-openssl-${{ env.OPENSSL3_VERSION }}
|
key: ${{ matrix.os }}-openssl-${{ env.OPENSSL3_VERSION }}
|
||||||
fail-on-cache-miss: true
|
fail-on-cache-miss: true
|
||||||
- name: Restore BoringSSL cache
|
- name: Restore BoringSSL cache
|
||||||
uses: actions/cache/restore@v3
|
uses: actions/cache/restore@v4
|
||||||
if: matrix.openssl == 'boringssl'
|
if: matrix.openssl == 'boringssl'
|
||||||
with:
|
with:
|
||||||
path: |
|
path: |
|
||||||
boringssl/build/crypto/libcrypto.a
|
boringssl/build/crypto/libcrypto.a
|
||||||
boringssl/build/ssl/libssl.a
|
boringssl/build/ssl/libssl.a
|
||||||
boringssl/include
|
boringssl/include
|
||||||
key: ${{ runner.os }}-boringssl-${{ env.BORINGSSL_VERSION }}
|
key: ${{ matrix.os }}-boringssl-${{ env.BORINGSSL_VERSION }}
|
||||||
|
fail-on-cache-miss: true
|
||||||
|
- name: Restore aws-lc cache
|
||||||
|
uses: actions/cache/restore@v4
|
||||||
|
if: matrix.openssl == 'awslc'
|
||||||
|
with:
|
||||||
|
path: |
|
||||||
|
aws-lc/build/crypto/libcrypto.a
|
||||||
|
aws-lc/build/ssl/libssl.a
|
||||||
|
aws-lc/include
|
||||||
|
key: ${{ matrix.os }}-awslc-${{ env.AWSLC_VERSION }}
|
||||||
fail-on-cache-miss: true
|
fail-on-cache-miss: true
|
||||||
- name: Set BoringSSL variables
|
- name: Set BoringSSL variables
|
||||||
if: matrix.openssl == 'boringssl'
|
if: matrix.openssl == 'boringssl'
|
||||||
run: |
|
run: |
|
||||||
cd boringssl
|
cd boringssl
|
||||||
|
|
||||||
|
OPENSSL_CFLAGS="-I$PWD/include/"
|
||||||
|
OPENSSL_LIBS="-L$PWD/build/ssl -lssl -L$PWD/build/crypto -lcrypto -pthread"
|
||||||
|
EXTRA_AUTOTOOLS_OPTS="$EXTRA_AUTOTOOLS_OPTS --without-neverbleed --without-jemalloc --disable-examples"
|
||||||
|
|
||||||
|
echo 'OPENSSL_CFLAGS='"$OPENSSL_CFLAGS" >> $GITHUB_ENV
|
||||||
|
echo 'OPENSSL_LIBS='"$OPENSSL_LIBS" >> $GITHUB_ENV
|
||||||
|
echo 'BORINGSSL_CFLAGS='"$OPENSSL_CFLAGS" >> $GITHUB_ENV
|
||||||
|
echo 'BORINGSSL_LIBS='"$OPENSSL_LIBS" >> $GITHUB_ENV
|
||||||
|
echo 'EXTRA_AUTOTOOLS_OPTS='"$EXTRA_AUTOTOOLS_OPTS" >> $GITHUB_ENV
|
||||||
|
- name: Set aws-lc variables
|
||||||
|
if: matrix.openssl == 'awslc'
|
||||||
|
run: |
|
||||||
|
cd aws-lc
|
||||||
|
|
||||||
OPENSSL_CFLAGS="-I$PWD/include/"
|
OPENSSL_CFLAGS="-I$PWD/include/"
|
||||||
OPENSSL_LIBS="-L$PWD/build/ssl -lssl -L$PWD/build/crypto -lcrypto -pthread"
|
OPENSSL_LIBS="-L$PWD/build/ssl -lssl -L$PWD/build/crypto -lcrypto -pthread"
|
||||||
EXTRA_AUTOTOOLS_OPTS="$EXTRA_AUTOTOOLS_OPTS --without-neverbleed --without-jemalloc"
|
EXTRA_AUTOTOOLS_OPTS="$EXTRA_AUTOTOOLS_OPTS --without-neverbleed --without-jemalloc"
|
||||||
@@ -316,26 +406,34 @@ jobs:
|
|||||||
echo 'BORINGSSL_LIBS='"$OPENSSL_LIBS" >> $GITHUB_ENV
|
echo 'BORINGSSL_LIBS='"$OPENSSL_LIBS" >> $GITHUB_ENV
|
||||||
echo 'EXTRA_AUTOTOOLS_OPTS='"$EXTRA_AUTOTOOLS_OPTS" >> $GITHUB_ENV
|
echo 'EXTRA_AUTOTOOLS_OPTS='"$EXTRA_AUTOTOOLS_OPTS" >> $GITHUB_ENV
|
||||||
- name: Restore nghttp3 cache
|
- name: Restore nghttp3 cache
|
||||||
uses: actions/cache/restore@v3
|
uses: actions/cache/restore@v4
|
||||||
if: matrix.http3 == 'http3'
|
if: matrix.http3 == 'http3'
|
||||||
with:
|
with:
|
||||||
path: nghttp3/build
|
path: nghttp3/build
|
||||||
key: ${{ runner.os }}-nghttp3-${{ env.NGHTTP3_VERSION }}
|
key: ${{ matrix.os }}-nghttp3-${{ env.NGHTTP3_VERSION }}
|
||||||
fail-on-cache-miss: true
|
fail-on-cache-miss: true
|
||||||
- name: Restore ngtcp2 + quictls/openssl v1.1.1 cache
|
- name: Restore ngtcp2 + quictls/openssl v1.1.1 cache + BoringSSL
|
||||||
uses: actions/cache/restore@v3
|
uses: actions/cache/restore@v4
|
||||||
if: matrix.http3 == 'http3' && (matrix.openssl == 'openssl1' || matrix.openssl == 'boringssl')
|
if: matrix.http3 == 'http3' && (matrix.openssl == 'openssl1' || matrix.openssl == 'boringssl')
|
||||||
with:
|
with:
|
||||||
path: ngtcp2-openssl1/build
|
path: ngtcp2-openssl1/build
|
||||||
key: ${{ runner.os }}-ngtcp2-${{ env.NGTCP2_VERSION }}-openssl-${{ env.OPENSSL1_VERSION }}
|
key: ${{ matrix.os }}-ngtcp2-${{ env.NGTCP2_VERSION }}-openssl-${{ env.OPENSSL1_VERSION }}
|
||||||
fail-on-cache-miss: true
|
fail-on-cache-miss: true
|
||||||
- name: Restore ngtcp2 + quictls/openssl v3.x cache
|
- name: Restore ngtcp2 + quictls/openssl v3.x cache + aws-lc
|
||||||
uses: actions/cache/restore@v3
|
uses: actions/cache/restore@v4
|
||||||
if: matrix.http3 == 'http3' && matrix.openssl == 'openssl3'
|
if: matrix.http3 == 'http3' && (matrix.openssl == 'openssl3' || matrix.openssl == 'awslc')
|
||||||
with:
|
with:
|
||||||
path: ngtcp2-openssl3/build
|
path: ngtcp2-openssl3/build
|
||||||
key: ${{ runner.os }}-ngtcp2-${{ env.NGTCP2_VERSION }}-openssl-${{ env.OPENSSL3_VERSION }}
|
key: ${{ matrix.os }}-ngtcp2-${{ env.NGTCP2_VERSION }}-openssl-${{ env.OPENSSL3_VERSION }}
|
||||||
fail-on-cache-miss: true
|
fail-on-cache-miss: true
|
||||||
|
- name: Setup extra environment variables
|
||||||
|
if: matrix.http3 == 'no-http3'
|
||||||
|
run: |
|
||||||
|
PKG_CONFIG_PATH="$PWD/openssl1/build/lib/pkgconfig:$PWD/openssl3/build/lib/pkgconfig"
|
||||||
|
LDFLAGS="$LDFLAGS -Wl,-rpath,$PWD/openssl1/build/lib -Wl,-rpath,$PWD/openssl3/build/lib"
|
||||||
|
|
||||||
|
echo 'PKG_CONFIG_PATH='"$PKG_CONFIG_PATH" >> $GITHUB_ENV
|
||||||
|
echo 'LDFLAGS='"$LDFLAGS" >> $GITHUB_ENV
|
||||||
- name: Setup extra environment variables for HTTP/3
|
- name: Setup extra environment variables for HTTP/3
|
||||||
if: matrix.http3 == 'http3'
|
if: matrix.http3 == 'http3'
|
||||||
run: |
|
run: |
|
||||||
@@ -348,63 +446,69 @@ jobs:
|
|||||||
echo 'LDFLAGS='"$LDFLAGS" >> $GITHUB_ENV
|
echo 'LDFLAGS='"$LDFLAGS" >> $GITHUB_ENV
|
||||||
echo 'EXTRA_AUTOTOOLS_OPTS='"$EXTRA_AUTOTOOLS_OPTS" >> $GITHUB_ENV
|
echo 'EXTRA_AUTOTOOLS_OPTS='"$EXTRA_AUTOTOOLS_OPTS" >> $GITHUB_ENV
|
||||||
echo 'EXTRA_CMAKE_OPTS='"$EXTRA_CMAKE_OPTS" >> $GITHUB_ENV
|
echo 'EXTRA_CMAKE_OPTS='"$EXTRA_CMAKE_OPTS" >> $GITHUB_ENV
|
||||||
- name: Setup git submodules
|
|
||||||
run: |
|
|
||||||
git submodule update --init
|
|
||||||
- name: Configure autotools
|
- name: Configure autotools
|
||||||
run: |
|
run: |
|
||||||
autoreconf -i
|
autoreconf -i
|
||||||
./configure
|
./configure
|
||||||
|
- name: Make distribution and unpack
|
||||||
|
if: matrix.buildtool != 'distcheck'
|
||||||
|
run: |
|
||||||
|
make dist
|
||||||
|
VERSION=$(grep PACKAGE_VERSION config.h | cut -d' ' -f3 | tr -d '"')
|
||||||
|
tar xf nghttp2-$VERSION.tar.gz
|
||||||
|
cd nghttp2-$VERSION
|
||||||
|
echo 'NGHTTP2_BUILD_DIR='"$PWD" >> $GITHUB_ENV
|
||||||
- name: Configure cmake (Linux)
|
- name: Configure cmake (Linux)
|
||||||
if: matrix.buildtool == 'cmake' && runner.os == 'Linux'
|
if: matrix.buildtool == 'cmake' && runner.os == 'Linux'
|
||||||
run: |
|
run: |
|
||||||
make dist
|
cd $NGHTTP2_BUILD_DIR
|
||||||
VERSION=$(grep PACKAGE_VERSION config.h | cut -d' ' -f3 | tr -d '"')
|
|
||||||
tar xf nghttp2-$VERSION.tar.gz
|
|
||||||
cd nghttp2-$VERSION
|
|
||||||
echo 'NGHTTP2_CMAKE_DIR='"$PWD" >> $GITHUB_ENV
|
|
||||||
|
|
||||||
cmake -DENABLE_WERROR=1 -DWITH_MRUBY=1 -DWITH_NEVERBLEED=1 -DENABLE_APP=1 $EXTRA_CMAKE_OPTS -DCPPFLAGS="$CPPFLAGS" -DLDFLAGS="$LDFLAGS" .
|
cmake -DENABLE_WERROR=1 -DWITH_MRUBY=1 -DWITH_NEVERBLEED=1 -DENABLE_APP=1 $EXTRA_CMAKE_OPTS -DCPPFLAGS="$CPPFLAGS" -DLDFLAGS="$LDFLAGS" -DBUILD_STATIC_LIBS=ON -DBUILD_TESTING=ON .
|
||||||
- name: Configure cmake (MacOS)
|
- name: Configure cmake (MacOS)
|
||||||
if: matrix.buildtool == 'cmake' && runner.os == 'macOS'
|
if: matrix.buildtool == 'cmake' && runner.os == 'macOS'
|
||||||
run: |
|
run: |
|
||||||
make dist
|
|
||||||
VERSION=$(grep PACKAGE_VERSION config.h | cut -d' ' -f3 | tr -d '"')
|
|
||||||
tar xf nghttp2-$VERSION.tar.gz
|
|
||||||
cd nghttp2-$VERSION
|
|
||||||
echo 'NGHTTP2_CMAKE_DIR='"$PWD" >> $GITHUB_ENV
|
|
||||||
|
|
||||||
# This fixes infamous 'stdio.h not found' error.
|
# This fixes infamous 'stdio.h not found' error.
|
||||||
echo 'SDKROOT='"$(xcrun --sdk macosx --show-sdk-path)" >> $GITHUB_ENV
|
echo 'SDKROOT='"$(xcrun --sdk macosx --show-sdk-path)" >> $GITHUB_ENV
|
||||||
|
|
||||||
cmake -DENABLE_WERROR=1 -DWITH_MRUBY=1 -DENABLE_APP=1 $EXTRA_CMAKE_OPTS -DCPPFLAGS="$CPPFLAGS" -DLDFLAGS="$LDFLAGS" .
|
cd $NGHTTP2_BUILD_DIR
|
||||||
|
|
||||||
|
cmake -DENABLE_WERROR=1 -DWITH_MRUBY=1 -DENABLE_APP=1 $EXTRA_CMAKE_OPTS -DCPPFLAGS="$CPPFLAGS" -DLDFLAGS="$LDFLAGS" -DBUILD_STATIC_LIBS=ON -DBUILD_TESTING=ON .
|
||||||
- name: Build nghttp2 with autotools (Linux)
|
- name: Build nghttp2 with autotools (Linux)
|
||||||
if: matrix.buildtool == 'autotools' && runner.os == 'Linux'
|
if: matrix.buildtool == 'autotools' && runner.os == 'Linux'
|
||||||
run: |
|
run: |
|
||||||
make -j"$(nproc)" distcheck \
|
cd $NGHTTP2_BUILD_DIR
|
||||||
DISTCHECK_CONFIGURE_FLAGS="--with-mruby --with-neverbleed --with-libev --enable-werror $EXTRA_AUTOTOOLS_OPTS CPPFLAGS=\"$CPPFLAGS\" LDFLAGS=\"$LDFLAGS\""
|
|
||||||
|
./configure --with-mruby --with-neverbleed --with-libev --with-libbrotlienc --with-libbrotlidec --enable-werror $EXTRA_AUTOTOOLS_OPTS
|
||||||
|
make -j"$(nproc)" check
|
||||||
- name: Build nghttp2 with autotools (MacOS)
|
- name: Build nghttp2 with autotools (MacOS)
|
||||||
if: matrix.buildtool == 'autotools' && runner.os == 'macOS'
|
if: matrix.buildtool == 'autotools' && runner.os == 'macOS'
|
||||||
run: |
|
run: |
|
||||||
make -j"$(sysctl -n hw.ncpu)" distcheck \
|
cd $NGHTTP2_BUILD_DIR
|
||||||
DISTCHECK_CONFIGURE_FLAGS="--with-mruby --with-libev --enable-werror $EXTRA_AUTOTOOLS_OPTS CPPFLAGS=\"$CPPFLAGS\" LDFLAGS=\"$LDFLAGS\""
|
|
||||||
|
./configure --with-mruby --with-libev --with-libbrotlienc --with-libbrotlidec --enable-werror $EXTRA_AUTOTOOLS_OPTS
|
||||||
|
make -j"$(sysctl -n hw.ncpu)" check
|
||||||
|
- name: Build nghttp2 with autotools (distcheck)
|
||||||
|
if: matrix.buildtool == 'distcheck'
|
||||||
|
run: |
|
||||||
|
make -j"$(nproc)" distcheck \
|
||||||
|
DISTCHECK_CONFIGURE_FLAGS="--with-mruby --with-neverbleed --with-libev --with-libbrotlienc --with-libbrotlidec --enable-werror $EXTRA_AUTOTOOLS_OPTS CPPFLAGS=\"$CPPFLAGS\" LDFLAGS=\"$LDFLAGS\""
|
||||||
- name: Build nghttp2 with cmake
|
- name: Build nghttp2 with cmake
|
||||||
if: matrix.buildtool == 'cmake'
|
if: matrix.buildtool == 'cmake'
|
||||||
run: |
|
run: |
|
||||||
cd $NGHTTP2_CMAKE_DIR
|
cd $NGHTTP2_BUILD_DIR
|
||||||
make -j"$(nproc 2> /dev/null || sysctl -n hw.ncpu)"
|
make -j"$(nproc 2> /dev/null || sysctl -n hw.ncpu)"
|
||||||
make -j"$(nproc 2> /dev/null || sysctl -n hw.ncpu)" check
|
make -j"$(nproc 2> /dev/null || sysctl -n hw.ncpu)" check
|
||||||
- uses: actions/setup-go@v4
|
- uses: actions/setup-go@v5
|
||||||
if: matrix.buildtool == 'cmake'
|
if: matrix.buildtool != 'distcheck'
|
||||||
with:
|
with:
|
||||||
go-version-file: go.mod
|
go-version-file: go.mod
|
||||||
- name: Integration test
|
- name: Integration test
|
||||||
# Integration tests for nghttpx; autotools erases build
|
# Integration tests for nghttpx; autotools erases build
|
||||||
# artifacts.
|
# artifacts.
|
||||||
if: matrix.buildtool == 'cmake'
|
if: matrix.buildtool != 'distcheck'
|
||||||
run: |
|
run: |
|
||||||
cd $NGHTTP2_CMAKE_DIR/integration-tests
|
cd $NGHTTP2_BUILD_DIR/integration-tests
|
||||||
make itprep it
|
make it
|
||||||
|
|
||||||
build-cross:
|
build-cross:
|
||||||
strategy:
|
strategy:
|
||||||
@@ -417,7 +521,10 @@ jobs:
|
|||||||
HOST: ${{ matrix.host }}
|
HOST: ${{ matrix.host }}
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
submodules: recursive
|
||||||
- name: Linux setup
|
- name: Linux setup
|
||||||
run: |
|
run: |
|
||||||
sudo dpkg --add-architecture i386
|
sudo dpkg --add-architecture i386
|
||||||
@@ -430,20 +537,11 @@ jobs:
|
|||||||
libtool \
|
libtool \
|
||||||
pkg-config \
|
pkg-config \
|
||||||
wine
|
wine
|
||||||
- name: Build CUnit
|
|
||||||
run: |
|
|
||||||
curl -LO https://jaist.dl.sourceforge.net/project/cunit/CUnit/2.1-3/CUnit-2.1-3.tar.bz2
|
|
||||||
tar xf CUnit-2.1-3.tar.bz2
|
|
||||||
cd CUnit-2.1-3
|
|
||||||
./bootstrap
|
|
||||||
./configure --disable-shared --host="$HOST" --prefix="$PWD/build"
|
|
||||||
make -j$(nproc) install
|
|
||||||
- name: Configure autotools
|
- name: Configure autotools
|
||||||
run: |
|
run: |
|
||||||
autoreconf -i && \
|
autoreconf -i && \
|
||||||
./configure --enable-werror --enable-lib-only --with-cunit \
|
./configure --enable-werror --enable-lib-only --host="$HOST" \
|
||||||
--host="$HOST" PKG_CONFIG_PATH="$PWD/CUnit-2.1-3/build/lib/pkgconfig" \
|
CFLAGS="-g -O2 -D_WIN32_WINNT=0x0600" LIBS="-pthread"
|
||||||
CFLAGS="-g -O2 -D_WIN32_WINNT=0x0600"
|
|
||||||
- name: Build nghttp2
|
- name: Build nghttp2
|
||||||
run: |
|
run: |
|
||||||
make -j$(nproc)
|
make -j$(nproc)
|
||||||
@@ -451,6 +549,7 @@ jobs:
|
|||||||
- name: Run tests
|
- name: Run tests
|
||||||
if: matrix.host == 'x86_64-w64-mingw32'
|
if: matrix.host == 'x86_64-w64-mingw32'
|
||||||
run: |
|
run: |
|
||||||
|
export WINEPATH=/usr/x86_64-w64-mingw32/lib
|
||||||
cd tests
|
cd tests
|
||||||
wine main.exe
|
wine main.exe
|
||||||
|
|
||||||
@@ -467,16 +566,84 @@ jobs:
|
|||||||
runs-on: windows-latest
|
runs-on: windows-latest
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- name: Checkout
|
||||||
- uses: microsoft/setup-msbuild@v1
|
uses: actions/checkout@v4
|
||||||
- run: |
|
with:
|
||||||
vcpkg --triplet=${{ matrix.arch }}-windows install cunit
|
submodules: recursive
|
||||||
|
- uses: microsoft/setup-msbuild@v2
|
||||||
- name: Configure cmake
|
- name: Configure cmake
|
||||||
run: |
|
run: cmake -B build -DCMAKE_TOOLCHAIN_FILE=C:/vcpkg/scripts/buildsystems/vcpkg.cmake -DCMAKE_GENERATOR_PLATFORM=${{ matrix.platform }} -DVCPKG_TARGET_TRIPLET=${{ matrix.arch}}-windows -DBUILD_STATIC_LIBS=ON -DBUILD_TESTING=ON
|
||||||
mkdir build
|
|
||||||
cd build
|
|
||||||
cmake -DCMAKE_TOOLCHAIN_FILE=C:/vcpkg/scripts/buildsystems/vcpkg.cmake -DCMAKE_GENERATOR_PLATFORM=${{ matrix.platform }} -DVCPKG_TARGET_TRIPLET=${{ matrix.arch}}-windows ..
|
|
||||||
- name: Build nghttp2
|
- name: Build nghttp2
|
||||||
run: |
|
run: |
|
||||||
cmake --build build
|
cmake --build build
|
||||||
cmake --build build --target check
|
cmake --build build --target check
|
||||||
|
|
||||||
|
release:
|
||||||
|
if: github.ref_type == 'tag'
|
||||||
|
|
||||||
|
needs:
|
||||||
|
- build
|
||||||
|
- build-cross
|
||||||
|
- build-windows
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
|
||||||
|
runs-on: ubuntu-22.04
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
submodules: recursive
|
||||||
|
- name: Make artifacts
|
||||||
|
run: |
|
||||||
|
ver='${{ github.ref_name }}'
|
||||||
|
|
||||||
|
prev_ver=$(git tag --sort v:refname | grep -v -F "${ver}" | \
|
||||||
|
grep 'v[0-9]\+\.[0-9]\+\.0' | tail -n1)
|
||||||
|
|
||||||
|
echo -n "$GPG_KEY" | gpg --batch --pinentry-mode loopback --import
|
||||||
|
./makerelease.sh "${ver}" "${prev_ver}"
|
||||||
|
env:
|
||||||
|
GPG_KEY: ${{ secrets.GPG_KEY }}
|
||||||
|
GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }}
|
||||||
|
- name: Make release
|
||||||
|
uses: actions/github-script@v7
|
||||||
|
with:
|
||||||
|
script: |
|
||||||
|
const fs = require('fs')
|
||||||
|
|
||||||
|
let ver = '${{ github.ref_name }}'
|
||||||
|
|
||||||
|
let {data: release} = await github.rest.repos.createRelease({
|
||||||
|
owner: context.repo.owner,
|
||||||
|
repo: context.repo.repo,
|
||||||
|
tag_name: ver,
|
||||||
|
name: `nghttp2 ${ver}`,
|
||||||
|
draft: true,
|
||||||
|
generate_release_notes: true,
|
||||||
|
discussion_category_name: 'Announcements',
|
||||||
|
})
|
||||||
|
|
||||||
|
let v = ver.substring(1)
|
||||||
|
|
||||||
|
let files = [
|
||||||
|
'checksums.txt',
|
||||||
|
`nghttp2-${v}.tar.bz2`,
|
||||||
|
`nghttp2-${v}.tar.bz2.asc`,
|
||||||
|
`nghttp2-${v}.tar.gz`,
|
||||||
|
`nghttp2-${v}.tar.gz.asc`,
|
||||||
|
`nghttp2-${v}.tar.xz`,
|
||||||
|
`nghttp2-${v}.tar.xz.asc`,
|
||||||
|
]
|
||||||
|
|
||||||
|
await Promise.all(files.map(elem =>
|
||||||
|
github.rest.repos.uploadReleaseAsset({
|
||||||
|
owner: context.repo.owner,
|
||||||
|
repo: context.repo.repo,
|
||||||
|
release_id: release.id,
|
||||||
|
name: elem,
|
||||||
|
data: fs.readFileSync(elem),
|
||||||
|
})
|
||||||
|
))
|
||||||
|
|||||||
24
.github/workflows/docker.yaml
vendored
Normal file
24
.github/workflows/docker.yaml
vendored
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
name: docker-build
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
paths:
|
||||||
|
- docker/Dockerfile
|
||||||
|
branches:
|
||||||
|
- '**'
|
||||||
|
|
||||||
|
permissions: read-all
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-22.04
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- name: Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v3
|
||||||
|
- name: Build
|
||||||
|
uses: docker/build-push-action@v5
|
||||||
|
with:
|
||||||
|
context: docker
|
||||||
|
build-args: NGHTTP2_BRANCH=${{ github.ref_name }}
|
||||||
9
.github/workflows/fuzz.yml
vendored
9
.github/workflows/fuzz.yml
vendored
@@ -5,6 +5,13 @@ jobs:
|
|||||||
Fuzzing:
|
Fuzzing:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
|
- name: LLVM workaround
|
||||||
|
run: |
|
||||||
|
# https://github.com/actions/runner-images/issues/9491#issuecomment-1989718917
|
||||||
|
# Asan in llvm 14 provided in ubuntu 22.04 is incompatible with
|
||||||
|
# high-entropy ASLR in much newer kernels that GitHub runners are
|
||||||
|
# using leading to random crashes: https://reviews.llvm.org/D148280
|
||||||
|
sudo sysctl vm.mmap_rnd_bits=28
|
||||||
- name: Build Fuzzers
|
- name: Build Fuzzers
|
||||||
uses: google/oss-fuzz/infra/cifuzz/actions/build_fuzzers@master
|
uses: google/oss-fuzz/infra/cifuzz/actions/build_fuzzers@master
|
||||||
with:
|
with:
|
||||||
@@ -17,7 +24,7 @@ jobs:
|
|||||||
fuzz-seconds: 600
|
fuzz-seconds: 600
|
||||||
dry-run: false
|
dry-run: false
|
||||||
- name: Upload Crash
|
- name: Upload Crash
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v4
|
||||||
if: failure()
|
if: failure()
|
||||||
with:
|
with:
|
||||||
name: artifacts
|
name: artifacts
|
||||||
|
|||||||
20
.github/workflows/stale.yaml
vendored
Normal file
20
.github/workflows/stale.yaml
vendored
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
name: 'Close stale issues'
|
||||||
|
|
||||||
|
on:
|
||||||
|
schedule:
|
||||||
|
- cron: '30 1 * * *'
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
issues: write
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
stale:
|
||||||
|
runs-on: ubuntu-22.04
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/stale@v9
|
||||||
|
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
|
||||||
|
days-before-close: 7
|
||||||
|
exempt-all-milestones: true
|
||||||
8
.gitignore
vendored
8
.gitignore
vendored
@@ -42,6 +42,7 @@ rules.ninja
|
|||||||
lib*.so
|
lib*.so
|
||||||
lib*.so.*
|
lib*.so.*
|
||||||
lib*.a
|
lib*.a
|
||||||
|
|
||||||
# generated by "make test" with cmake
|
# generated by "make test" with cmake
|
||||||
Testing/
|
Testing/
|
||||||
|
|
||||||
@@ -54,3 +55,10 @@ _VC_ROOT/
|
|||||||
.depend.MSVC
|
.depend.MSVC
|
||||||
*.pyd
|
*.pyd
|
||||||
*.egg-info/
|
*.egg-info/
|
||||||
|
|
||||||
|
# Build Directories
|
||||||
|
build/
|
||||||
|
|
||||||
|
# IDEs
|
||||||
|
cmake-*
|
||||||
|
.idea/
|
||||||
|
|||||||
3
.gitmodules
vendored
3
.gitmodules
vendored
@@ -5,3 +5,6 @@
|
|||||||
path = third-party/neverbleed
|
path = third-party/neverbleed
|
||||||
url = https://github.com/tatsuhiro-t/neverbleed.git
|
url = https://github.com/tatsuhiro-t/neverbleed.git
|
||||||
branch = nghttp2
|
branch = nghttp2
|
||||||
|
[submodule "tests/munit"]
|
||||||
|
path = tests/munit
|
||||||
|
url = https://github.com/ngtcp2/munit
|
||||||
|
|||||||
9
AUTHORS
9
AUTHORS
@@ -17,8 +17,10 @@ github issues [2].
|
|||||||
Adam Gołębiowski
|
Adam Gołębiowski
|
||||||
Alek Storm
|
Alek Storm
|
||||||
Alex Nalivko
|
Alex Nalivko
|
||||||
|
Alexandr Vlasov
|
||||||
Alexandros Konstantinakis-Karmis
|
Alexandros Konstantinakis-Karmis
|
||||||
Alexis La Goutte
|
Alexis La Goutte
|
||||||
|
Alyssa Ross
|
||||||
Amir Livneh
|
Amir Livneh
|
||||||
Amir Pakdel
|
Amir Pakdel
|
||||||
Anders Bakken
|
Anders Bakken
|
||||||
@@ -28,10 +30,12 @@ Andy Davies
|
|||||||
Angus Gratton
|
Angus Gratton
|
||||||
Anna Henningsen
|
Anna Henningsen
|
||||||
Ant Bryan
|
Ant Bryan
|
||||||
|
Anthony Alayo
|
||||||
Asra Ali
|
Asra Ali
|
||||||
Benedikt Christoph Wolters
|
Benedikt Christoph Wolters
|
||||||
Benjamin Peterson
|
Benjamin Peterson
|
||||||
Bernard Spil
|
Bernard Spil
|
||||||
|
Bernhard Walle
|
||||||
Brendan Heinonen
|
Brendan Heinonen
|
||||||
Brian Card
|
Brian Card
|
||||||
Brian Suh
|
Brian Suh
|
||||||
@@ -42,6 +46,7 @@ Dave Reisner
|
|||||||
David Beitey
|
David Beitey
|
||||||
David Korczynski
|
David Korczynski
|
||||||
David Weekly
|
David Weekly
|
||||||
|
Deel
|
||||||
Dimitris Apostolou
|
Dimitris Apostolou
|
||||||
Dmitri Tikhonov
|
Dmitri Tikhonov
|
||||||
Dmitriy Vetutnev
|
Dmitriy Vetutnev
|
||||||
@@ -69,6 +74,8 @@ Jay Satiro
|
|||||||
Jeff 'Raid' Baitis
|
Jeff 'Raid' Baitis
|
||||||
Jianqing Wang
|
Jianqing Wang
|
||||||
Jim Morrison
|
Jim Morrison
|
||||||
|
Jiwoo Park
|
||||||
|
Jonas Kvinge
|
||||||
Josh Braegger
|
Josh Braegger
|
||||||
José F. Calcerrada
|
José F. Calcerrada
|
||||||
Kamil Dudka
|
Kamil Dudka
|
||||||
@@ -109,6 +116,7 @@ Rudi Heitbaum
|
|||||||
Ryo Ota
|
Ryo Ota
|
||||||
Scott Mitchell
|
Scott Mitchell
|
||||||
Sebastiaan Deckers
|
Sebastiaan Deckers
|
||||||
|
Sergey Fedorov
|
||||||
Shelley Vohr
|
Shelley Vohr
|
||||||
Simon Frankenberger
|
Simon Frankenberger
|
||||||
Simone Basso
|
Simone Basso
|
||||||
@@ -142,6 +150,7 @@ dalf
|
|||||||
dawg
|
dawg
|
||||||
es
|
es
|
||||||
fangdingjun
|
fangdingjun
|
||||||
|
hrxi
|
||||||
jwchoi
|
jwchoi
|
||||||
kumagi
|
kumagi
|
||||||
lhuang04
|
lhuang04
|
||||||
|
|||||||
140
CMakeLists.txt
140
CMakeLists.txt
@@ -22,15 +22,15 @@
|
|||||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
cmake_minimum_required(VERSION 3.0)
|
cmake_minimum_required(VERSION 3.14)
|
||||||
# XXX using 1.8.90 instead of 1.9.0-DEV
|
# XXX using 1.8.90 instead of 1.9.0-DEV
|
||||||
project(nghttp2 VERSION 1.57.0)
|
project(nghttp2 VERSION 1.62.1)
|
||||||
|
|
||||||
# See versioning rule:
|
# See versioning rule:
|
||||||
# https://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html
|
# https://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html
|
||||||
set(LT_CURRENT 39)
|
set(LT_CURRENT 42)
|
||||||
set(LT_REVISION 0)
|
set(LT_REVISION 1)
|
||||||
set(LT_AGE 25)
|
set(LT_AGE 28)
|
||||||
|
|
||||||
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH})
|
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH})
|
||||||
include(Version)
|
include(Version)
|
||||||
@@ -51,23 +51,29 @@ if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
include(GNUInstallDirs)
|
include(GNUInstallDirs)
|
||||||
|
include(CMakeDependentOption)
|
||||||
|
|
||||||
# For documentation
|
# For documentation
|
||||||
find_package(Python3 COMPONENTS Interpreter)
|
find_package(Python3 COMPONENTS Interpreter)
|
||||||
|
|
||||||
# Auto-detection of features that can be toggled
|
# Auto-detection of features that can be toggled
|
||||||
find_package(OpenSSL 1.0.1)
|
if(NOT ENABLE_LIB_ONLY)
|
||||||
find_package(Libev 4.11)
|
find_package(Libev 4.11)
|
||||||
find_package(Libcares 1.7.5)
|
find_package(Libcares 1.7.5)
|
||||||
find_package(ZLIB 1.2.3)
|
find_package(ZLIB 1.2.3)
|
||||||
find_package(Libngtcp2 0.0.0)
|
find_package(Libbrotlienc 1.0.9)
|
||||||
find_package(Libngtcp2_crypto_quictls 0.0.0)
|
find_package(Libbrotlidec 1.0.9)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
find_package(OpenSSL 1.1.1)
|
||||||
|
find_package(Libngtcp2 1.0.0)
|
||||||
|
find_package(Libngtcp2_crypto_quictls 1.0.0)
|
||||||
if(LIBNGTCP2_CRYPTO_QUICTLS_FOUND)
|
if(LIBNGTCP2_CRYPTO_QUICTLS_FOUND)
|
||||||
set(HAVE_LIBNGTCP2_CRYPTO_QUICTLS 1)
|
set(HAVE_LIBNGTCP2_CRYPTO_QUICTLS 1)
|
||||||
endif()
|
endif()
|
||||||
find_package(Libnghttp3 0.0.0)
|
find_package(Libnghttp3 1.1.0)
|
||||||
if(WITH_LIBBPF)
|
if(WITH_LIBBPF)
|
||||||
find_package(Libbpf 0.4.0)
|
find_package(Libbpf 0.7.0)
|
||||||
if(NOT LIBBPF_FOUND)
|
if(NOT LIBBPF_FOUND)
|
||||||
message(FATAL_ERROR "libbpf was requested (WITH_LIBBPF=1) but not found.")
|
message(FATAL_ERROR "libbpf was requested (WITH_LIBBPF=1) but not found.")
|
||||||
endif()
|
endif()
|
||||||
@@ -118,7 +124,7 @@ else()
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
include(ExtractValidFlags)
|
include(ExtractValidFlags)
|
||||||
foreach(_cxx1x_flag -std=c++14)
|
foreach(_cxx1x_flag -std=c++20)
|
||||||
extract_valid_cxx_flags(_cxx1x_flag_supported ${_cxx1x_flag})
|
extract_valid_cxx_flags(_cxx1x_flag_supported ${_cxx1x_flag})
|
||||||
if(_cxx1x_flag_supported)
|
if(_cxx1x_flag_supported)
|
||||||
set(CXX1XCXXFLAGS ${_cxx1x_flag})
|
set(CXX1XCXXFLAGS ${_cxx1x_flag})
|
||||||
@@ -162,12 +168,8 @@ endif()
|
|||||||
# XXX shouldn't ${CMAKE_DL_LIBS} be appended to OPENSSL_LIBRARIES instead of
|
# XXX shouldn't ${CMAKE_DL_LIBS} be appended to OPENSSL_LIBRARIES instead of
|
||||||
# APP_LIBRARIES if it is really specific to OpenSSL?
|
# APP_LIBRARIES if it is really specific to OpenSSL?
|
||||||
|
|
||||||
find_package(CUnit 2.1)
|
|
||||||
enable_testing()
|
enable_testing()
|
||||||
set(HAVE_CUNIT ${CUNIT_FOUND})
|
add_custom_target(check COMMAND ${CMAKE_CTEST_COMMAND})
|
||||||
if(HAVE_CUNIT)
|
|
||||||
add_custom_target(check COMMAND ${CMAKE_CTEST_COMMAND})
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# openssl (for src)
|
# openssl (for src)
|
||||||
include(CheckSymbolExists)
|
include(CheckSymbolExists)
|
||||||
@@ -180,9 +182,11 @@ if(OPENSSL_FOUND)
|
|||||||
if(WIN32)
|
if(WIN32)
|
||||||
set(CMAKE_REQUIRED_LIBRARIES "${CMAKE_REQUIRED_LIBRARIES}" "ws2_32" "bcrypt")
|
set(CMAKE_REQUIRED_LIBRARIES "${CMAKE_REQUIRED_LIBRARIES}" "ws2_32" "bcrypt")
|
||||||
endif()
|
endif()
|
||||||
check_symbol_exists(SSL_is_quic "openssl/ssl.h" HAVE_SSL_IS_QUIC)
|
if(ENABLE_HTTP3)
|
||||||
if(NOT HAVE_SSL_IS_QUIC)
|
check_symbol_exists(SSL_provide_quic_data "openssl/ssl.h" HAVE_SSL_PROVIDE_QUIC_DATA)
|
||||||
message(WARNING "OpenSSL in ${OPENSSL_LIBRARIES} does not have SSL_is_quic. HTTP/3 support cannot be enabled")
|
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")
|
||||||
|
endif()
|
||||||
endif()
|
endif()
|
||||||
cmake_pop_check_state()
|
cmake_pop_check_state()
|
||||||
else()
|
else()
|
||||||
@@ -219,6 +223,13 @@ endif()
|
|||||||
# jemalloc
|
# jemalloc
|
||||||
set(HAVE_JEMALLOC ${JEMALLOC_FOUND})
|
set(HAVE_JEMALLOC ${JEMALLOC_FOUND})
|
||||||
|
|
||||||
|
# libbrotli (for src)
|
||||||
|
set(HAVE_LIBBROTLIENC ${LIBBROTLIENC_FOUND})
|
||||||
|
set(HAVE_LIBBROTLIDEC ${LIBBROTLIDEC_FOUND})
|
||||||
|
if(LIBBROTLIENC_FOUND AND LIBBROTLIDEC_FOUND)
|
||||||
|
set(HAVE_LIBBROTLI 1)
|
||||||
|
endif()
|
||||||
|
|
||||||
# libbpf (for bpf)
|
# libbpf (for bpf)
|
||||||
set(HAVE_LIBBPF ${LIBBPF_FOUND})
|
set(HAVE_LIBBPF ${LIBBPF_FOUND})
|
||||||
if(LIBBPF_FOUND)
|
if(LIBBPF_FOUND)
|
||||||
@@ -240,7 +251,7 @@ endif()
|
|||||||
|
|
||||||
# HTTP/3 requires quictls/openssl, libngtcp2, libngtcp2_crypto_quictls
|
# HTTP/3 requires quictls/openssl, libngtcp2, libngtcp2_crypto_quictls
|
||||||
# and libnghttp3.
|
# and libnghttp3.
|
||||||
if(ENABLE_HTTP3 AND NOT (HAVE_SSL_IS_QUIC AND LIBNGTCP2_FOUND AND LIBNGTCP2_CRYPTO_QUICTLS_FOUND AND LIBNGHTTP3_FOUND))
|
if(ENABLE_HTTP3 AND NOT (HAVE_SSL_PROVIDE_QUIC_DATA AND LIBNGTCP2_FOUND AND LIBNGTCP2_CRYPTO_QUICTLS_FOUND AND LIBNGHTTP3_FOUND))
|
||||||
message(FATAL_ERROR "HTTP/3 was requested (ENABLE_HTTP3=1) but dependencies are not met.")
|
message(FATAL_ERROR "HTTP/3 was requested (ENABLE_HTTP3=1) but dependencies are not met.")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
@@ -277,10 +288,9 @@ check_include_file("netinet/ip.h" HAVE_NETINET_IP_H)
|
|||||||
check_include_file("pwd.h" HAVE_PWD_H)
|
check_include_file("pwd.h" HAVE_PWD_H)
|
||||||
check_include_file("sys/socket.h" HAVE_SYS_SOCKET_H)
|
check_include_file("sys/socket.h" HAVE_SYS_SOCKET_H)
|
||||||
check_include_file("sys/time.h" HAVE_SYS_TIME_H)
|
check_include_file("sys/time.h" HAVE_SYS_TIME_H)
|
||||||
check_include_file("sysinfoapi.h" HAVE_SYSINFOAPI_H)
|
|
||||||
check_include_file("syslog.h" HAVE_SYSLOG_H)
|
check_include_file("syslog.h" HAVE_SYSLOG_H)
|
||||||
check_include_file("time.h" HAVE_TIME_H)
|
|
||||||
check_include_file("unistd.h" HAVE_UNISTD_H)
|
check_include_file("unistd.h" HAVE_UNISTD_H)
|
||||||
|
check_include_file("windows.h" HAVE_WINDOWS_H)
|
||||||
|
|
||||||
include(CheckTypeSize)
|
include(CheckTypeSize)
|
||||||
# Checks for typedefs, structures, and compiler characteristics.
|
# Checks for typedefs, structures, and compiler characteristics.
|
||||||
@@ -310,10 +320,6 @@ endif()
|
|||||||
include(CheckStructHasMember)
|
include(CheckStructHasMember)
|
||||||
check_struct_has_member("struct tm" tm_gmtoff time.h HAVE_STRUCT_TM_TM_GMTOFF)
|
check_struct_has_member("struct tm" tm_gmtoff time.h HAVE_STRUCT_TM_TM_GMTOFF)
|
||||||
|
|
||||||
# Check size of pointer to decide we need 8 bytes alignment adjustment.
|
|
||||||
check_type_size("int *" SIZEOF_INT_P)
|
|
||||||
check_type_size("time_t" SIZEOF_TIME_T)
|
|
||||||
|
|
||||||
# Checks for library functions.
|
# Checks for library functions.
|
||||||
include(CheckFunctionExists)
|
include(CheckFunctionExists)
|
||||||
check_function_exists(_Exit HAVE__EXIT)
|
check_function_exists(_Exit HAVE__EXIT)
|
||||||
@@ -334,6 +340,8 @@ if(NOT HAVE_DECL_INITGROUPS AND HAVE_UNISTD_H)
|
|||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
check_symbol_exists(CLOCK_MONOTONIC "time.h" HAVE_DECL_CLOCK_MONOTONIC)
|
||||||
|
|
||||||
set(WARNCFLAGS)
|
set(WARNCFLAGS)
|
||||||
set(WARNCXXFLAGS)
|
set(WARNCXXFLAGS)
|
||||||
if(CMAKE_C_COMPILER_ID MATCHES "MSVC")
|
if(CMAKE_C_COMPILER_ID MATCHES "MSVC")
|
||||||
@@ -343,65 +351,12 @@ if(CMAKE_C_COMPILER_ID MATCHES "MSVC")
|
|||||||
endif()
|
endif()
|
||||||
else()
|
else()
|
||||||
if(ENABLE_WERROR)
|
if(ENABLE_WERROR)
|
||||||
extract_valid_c_flags(WARNCFLAGS -Werror)
|
set(WARNCFLAGS "-Werror")
|
||||||
extract_valid_c_flags(WARNCXXFLAGS -Werror)
|
set(WARNCXXFLAGS "-Werror")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# For C compiler
|
include(PickyWarningsC)
|
||||||
extract_valid_c_flags(WARNCFLAGS
|
include(PickyWarningsCXX)
|
||||||
-Wall
|
|
||||||
-Wextra
|
|
||||||
-Wmissing-prototypes
|
|
||||||
-Wstrict-prototypes
|
|
||||||
-Wmissing-declarations
|
|
||||||
-Wpointer-arith
|
|
||||||
-Wdeclaration-after-statement
|
|
||||||
-Wformat-security
|
|
||||||
-Wwrite-strings
|
|
||||||
-Wshadow
|
|
||||||
-Winline
|
|
||||||
-Wnested-externs
|
|
||||||
-Wfloat-equal
|
|
||||||
-Wundef
|
|
||||||
-Wendif-labels
|
|
||||||
-Wempty-body
|
|
||||||
-Wcast-align
|
|
||||||
-Wclobbered
|
|
||||||
-Wvla
|
|
||||||
-Wpragmas
|
|
||||||
-Wunreachable-code
|
|
||||||
-Waddress
|
|
||||||
-Wattributes
|
|
||||||
-Wdiv-by-zero
|
|
||||||
-Wshorten-64-to-32
|
|
||||||
|
|
||||||
-Wconversion
|
|
||||||
-Wextended-offsetof
|
|
||||||
-Wformat-nonliteral
|
|
||||||
-Wlanguage-extension-token
|
|
||||||
-Wmissing-field-initializers
|
|
||||||
-Wmissing-noreturn
|
|
||||||
-Wmissing-variable-declarations
|
|
||||||
# Not used because we cannot change public structs
|
|
||||||
# -Wpadded
|
|
||||||
-Wsign-conversion
|
|
||||||
# Not used because this basically disallows default case
|
|
||||||
# -Wswitch-enum
|
|
||||||
-Wunreachable-code-break
|
|
||||||
-Wunused-macros
|
|
||||||
-Wunused-parameter
|
|
||||||
-Wredundant-decls
|
|
||||||
# Only work with Clang for the moment
|
|
||||||
-Wheader-guard
|
|
||||||
# This is required because we pass format string as "const char*.
|
|
||||||
-Wno-format-nonliteral
|
|
||||||
)
|
|
||||||
|
|
||||||
extract_valid_cxx_flags(WARNCXXFLAGS
|
|
||||||
# For C++ compiler
|
|
||||||
-Wall
|
|
||||||
-Wformat-security
|
|
||||||
)
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(ENABLE_STATIC_CRT)
|
if(ENABLE_STATIC_CRT)
|
||||||
@@ -480,9 +435,11 @@ add_subdirectory(lib)
|
|||||||
add_subdirectory(third-party)
|
add_subdirectory(third-party)
|
||||||
add_subdirectory(src)
|
add_subdirectory(src)
|
||||||
add_subdirectory(examples)
|
add_subdirectory(examples)
|
||||||
add_subdirectory(tests)
|
if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME AND BUILD_TESTING)
|
||||||
#add_subdirectory(tests/testdata)
|
add_subdirectory(tests)
|
||||||
add_subdirectory(integration-tests)
|
#add_subdirectory(tests/testdata)
|
||||||
|
add_subdirectory(integration-tests)
|
||||||
|
endif()
|
||||||
if(ENABLE_DOC)
|
if(ENABLE_DOC)
|
||||||
add_subdirectory(doc)
|
add_subdirectory(doc)
|
||||||
endif()
|
endif()
|
||||||
@@ -506,12 +463,13 @@ message(STATUS "summary of build options:
|
|||||||
CXXFLAGS: ${CMAKE_CXX_FLAGS_${_build_type}} ${CMAKE_CXX_FLAGS}
|
CXXFLAGS: ${CMAKE_CXX_FLAGS_${_build_type}} ${CMAKE_CXX_FLAGS}
|
||||||
WARNCFLAGS: ${WARNCFLAGS}
|
WARNCFLAGS: ${WARNCFLAGS}
|
||||||
CXX1XCXXFLAGS: ${CXX1XCXXFLAGS}
|
CXX1XCXXFLAGS: ${CXX1XCXXFLAGS}
|
||||||
|
WARNCXXFLAGS: ${WARNCXXFLAGS}
|
||||||
Python:
|
Python:
|
||||||
Python: ${Python3_EXECUTABLE}
|
Python: ${Python3_EXECUTABLE}
|
||||||
Python3_VERSION: ${Python3_VERSION}
|
Python3_VERSION: ${Python3_VERSION}
|
||||||
Test:
|
Test:
|
||||||
CUnit: ${HAVE_CUNIT} (LIBS='${CUNIT_LIBRARIES}')
|
|
||||||
Failmalloc: ${ENABLE_FAILMALLOC}
|
Failmalloc: ${ENABLE_FAILMALLOC}
|
||||||
|
Build Test: ${BUILD_TESTING}
|
||||||
Libs:
|
Libs:
|
||||||
OpenSSL: ${HAVE_OPENSSL} (LIBS='${OPENSSL_LIBRARIES}')
|
OpenSSL: ${HAVE_OPENSSL} (LIBS='${OPENSSL_LIBRARIES}')
|
||||||
Libxml2: ${HAVE_LIBXML2} (LIBS='${LIBXML2_LIBRARIES}')
|
Libxml2: ${HAVE_LIBXML2} (LIBS='${LIBXML2_LIBRARIES}')
|
||||||
@@ -526,6 +484,8 @@ message(STATUS "summary of build options:
|
|||||||
Jemalloc: ${HAVE_JEMALLOC} (LIBS='${JEMALLOC_LIBRARIES}')
|
Jemalloc: ${HAVE_JEMALLOC} (LIBS='${JEMALLOC_LIBRARIES}')
|
||||||
Zlib: ${HAVE_ZLIB} (LIBS='${ZLIB_LIBRARIES}')
|
Zlib: ${HAVE_ZLIB} (LIBS='${ZLIB_LIBRARIES}')
|
||||||
Systemd: ${HAVE_SYSTEMD} (LIBS='${SYSTEMD_LIBRARIES}')
|
Systemd: ${HAVE_SYSTEMD} (LIBS='${SYSTEMD_LIBRARIES}')
|
||||||
|
Libbrotlienc: ${HAVE_LIBBROTLIENC} (LIBS='${LIBBROTLIENC_LIBRARIES}')
|
||||||
|
Libbrotlidec: ${HAVE_LIBBROTLIDEC} (LIBS='${LIBBROTLIDEC_LIBRARIES}')
|
||||||
Third-party:
|
Third-party:
|
||||||
http-parser: ${ENABLE_THIRD_PARTY}
|
http-parser: ${ENABLE_THIRD_PARTY}
|
||||||
MRuby: ${HAVE_MRUBY}
|
MRuby: ${HAVE_MRUBY}
|
||||||
|
|||||||
@@ -11,11 +11,12 @@ option(ENABLE_EXAMPLES "Build examples"
|
|||||||
${ENABLE_EXAMPLES_DEFAULT})
|
${ENABLE_EXAMPLES_DEFAULT})
|
||||||
option(ENABLE_FAILMALLOC "Build failmalloc test program" ON)
|
option(ENABLE_FAILMALLOC "Build failmalloc test program" ON)
|
||||||
option(ENABLE_LIB_ONLY "Build libnghttp2 only. This is a short hand for -DENABLE_APP=0 -DENABLE_EXAMPLES=0 -DENABLE_HPACK_TOOLS=0")
|
option(ENABLE_LIB_ONLY "Build libnghttp2 only. This is a short hand for -DENABLE_APP=0 -DENABLE_EXAMPLES=0 -DENABLE_HPACK_TOOLS=0")
|
||||||
option(ENABLE_STATIC_LIB "Build libnghttp2 in static mode also")
|
option(BUILD_SHARED_LIBS "Build libnghttp2 as a shared library" ON)
|
||||||
option(ENABLE_SHARED_LIB "Build libnghttp2 as a shared library" ON)
|
option(BUILD_STATIC_LIBS "Build libnghttp2 in static mode also" OFF)
|
||||||
option(ENABLE_STATIC_CRT "Build libnghttp2 against the MS LIBCMT[d]")
|
option(ENABLE_STATIC_CRT "Build libnghttp2 against the MS LIBCMT[d]")
|
||||||
option(ENABLE_HTTP3 "Enable HTTP/3 support" OFF)
|
option(ENABLE_HTTP3 "Enable HTTP/3 support" OFF)
|
||||||
option(ENABLE_DOC "Build documentation" ON)
|
option(ENABLE_DOC "Build documentation" ON)
|
||||||
|
cmake_dependent_option(BUILD_TESTING "Enable tests" ON "BUILD_STATIC_LIBS" OFF)
|
||||||
|
|
||||||
option(WITH_LIBXML2 "Use libxml2"
|
option(WITH_LIBXML2 "Use libxml2"
|
||||||
${WITH_LIBXML2_DEFAULT})
|
${WITH_LIBXML2_DEFAULT})
|
||||||
|
|||||||
@@ -35,7 +35,6 @@ EXTRA_DIST = nghttpx.conf.sample proxy.pac.sample android-config android-env \
|
|||||||
cmake/ExtractValidFlags.cmake \
|
cmake/ExtractValidFlags.cmake \
|
||||||
cmake/FindJemalloc.cmake \
|
cmake/FindJemalloc.cmake \
|
||||||
cmake/FindLibev.cmake \
|
cmake/FindLibev.cmake \
|
||||||
cmake/FindCUnit.cmake \
|
|
||||||
cmake/Version.cmake \
|
cmake/Version.cmake \
|
||||||
cmake/FindLibevent.cmake \
|
cmake/FindLibevent.cmake \
|
||||||
cmake/FindJansson.cmake \
|
cmake/FindJansson.cmake \
|
||||||
@@ -44,7 +43,11 @@ EXTRA_DIST = nghttpx.conf.sample proxy.pac.sample android-config android-env \
|
|||||||
cmake/FindLibbpf.cmake \
|
cmake/FindLibbpf.cmake \
|
||||||
cmake/FindLibnghttp3.cmake \
|
cmake/FindLibnghttp3.cmake \
|
||||||
cmake/FindLibngtcp2.cmake \
|
cmake/FindLibngtcp2.cmake \
|
||||||
cmake/FindLibngtcp2_crypto_quictls.cmake
|
cmake/FindLibngtcp2_crypto_quictls.cmake \
|
||||||
|
cmake/FindLibbrotlienc.cmake \
|
||||||
|
cmake/FindLibbrotlidec.cmake \
|
||||||
|
cmake/PickyWarningsC.cmake \
|
||||||
|
cmake/PickyWarningsCXX.cmake
|
||||||
|
|
||||||
.PHONY: clang-format
|
.PHONY: clang-format
|
||||||
|
|
||||||
|
|||||||
117
README.rst
117
README.rst
@@ -29,10 +29,10 @@ Public Test Server
|
|||||||
The following endpoints are available to try out our nghttp2
|
The following endpoints are available to try out our nghttp2
|
||||||
implementation.
|
implementation.
|
||||||
|
|
||||||
* https://nghttp2.org/ (TLS + ALPN/NPN and HTTP/3)
|
* https://nghttp2.org/ (TLS + ALPN and HTTP/3)
|
||||||
|
|
||||||
This endpoint supports ``h2``, ``h2-16``, ``h2-14``, and
|
This endpoint supports ``h2``, ``h2-16``, ``h2-14``, and
|
||||||
``http/1.1`` via ALPN/NPN and requires TLSv1.2 for HTTP/2
|
``http/1.1`` via ALPN and requires TLSv1.2 for HTTP/2
|
||||||
connection.
|
connection.
|
||||||
|
|
||||||
It also supports HTTP/3.
|
It also supports HTTP/3.
|
||||||
@@ -48,11 +48,6 @@ The following package is required to build the libnghttp2 library:
|
|||||||
|
|
||||||
* pkg-config >= 0.20
|
* pkg-config >= 0.20
|
||||||
|
|
||||||
To build and run the unit test programs, the following package is
|
|
||||||
required:
|
|
||||||
|
|
||||||
* cunit >= 2.1
|
|
||||||
|
|
||||||
To build the documentation, you need to install:
|
To build the documentation, you need to install:
|
||||||
|
|
||||||
* sphinx (http://sphinx-doc.org/)
|
* sphinx (http://sphinx-doc.org/)
|
||||||
@@ -66,15 +61,12 @@ To build and run the application programs (``nghttp``, ``nghttpd``,
|
|||||||
``nghttpx`` and ``h2load``) in the ``src`` directory, the following packages
|
``nghttpx`` and ``h2load``) in the ``src`` directory, the following packages
|
||||||
are required:
|
are required:
|
||||||
|
|
||||||
* OpenSSL >= 1.0.1
|
* OpenSSL >= 1.1.1; or LibreSSL >= 3.8.1; or aws-lc >= 1.19.0; or
|
||||||
|
BoringSSL
|
||||||
* libev >= 4.11
|
* libev >= 4.11
|
||||||
* zlib >= 1.2.3
|
* zlib >= 1.2.3
|
||||||
* libc-ares >= 1.7.5
|
* libc-ares >= 1.7.5
|
||||||
|
|
||||||
ALPN support requires OpenSSL >= 1.0.2 (released 22 January 2015).
|
|
||||||
LibreSSL >= 2.2.0 can be used instead of OpenSSL, but OpenSSL has more
|
|
||||||
features than LibreSSL at the time of this writing.
|
|
||||||
|
|
||||||
To enable ``-a`` option (getting linked assets from the downloaded
|
To enable ``-a`` option (getting linked assets from the downloaded
|
||||||
resource) in ``nghttp``, the following package is required:
|
resource) in ``nghttp``, the following package is required:
|
||||||
|
|
||||||
@@ -103,10 +95,15 @@ To mitigate heap fragmentation in long running server programs
|
|||||||
Alpine Linux currently does not support malloc replacement
|
Alpine Linux currently does not support malloc replacement
|
||||||
due to musl limitations. See details in issue `#762 <https://github.com/nghttp2/nghttp2/issues/762>`_.
|
due to musl limitations. See details in issue `#762 <https://github.com/nghttp2/nghttp2/issues/762>`_.
|
||||||
|
|
||||||
|
For BoringSSL or aws-lc build, to enable :rfc:`8879` TLS Certificate
|
||||||
|
Compression in applications, the following library is required:
|
||||||
|
|
||||||
|
* libbrotli-dev >= 1.0.9
|
||||||
|
|
||||||
To enable mruby support for nghttpx, `mruby
|
To enable mruby support for nghttpx, `mruby
|
||||||
<https://github.com/mruby/mruby>`_ is required. We need to build
|
<https://github.com/mruby/mruby>`_ is required. We need to build
|
||||||
mruby with C++ ABI explicitly turned on, and probably need other
|
mruby with C++ ABI explicitly turned on, and probably need other
|
||||||
mrgems, mruby is manged by git submodule under third-party/mruby
|
mrgems, mruby is managed by git submodule under third-party/mruby
|
||||||
directory. Currently, mruby support for nghttpx is disabled by
|
directory. Currently, mruby support for nghttpx is disabled by
|
||||||
default. To enable mruby support, use ``--with-mruby`` configure
|
default. To enable mruby support, use ``--with-mruby`` configure
|
||||||
option. Note that at the time of this writing, libmruby-dev and mruby
|
option. Note that at the time of this writing, libmruby-dev and mruby
|
||||||
@@ -118,20 +115,21 @@ required:
|
|||||||
* bison
|
* bison
|
||||||
|
|
||||||
nghttpx supports `neverbleed <https://github.com/h2o/neverbleed>`_,
|
nghttpx supports `neverbleed <https://github.com/h2o/neverbleed>`_,
|
||||||
privilege separation engine for OpenSSL / LibreSSL. In short, it
|
privilege separation engine for OpenSSL. In short, it minimizes the
|
||||||
minimizes the risk of private key leakage when serious bug like
|
risk of private key leakage when serious bug like Heartbleed is
|
||||||
Heartbleed is exploited. The neverbleed is disabled by default. To
|
exploited. The neverbleed is disabled by default. To enable it, use
|
||||||
enable it, use ``--with-neverbleed`` configure option.
|
``--with-neverbleed`` configure option.
|
||||||
|
|
||||||
To enable the experimental HTTP/3 support for h2load and nghttpx, the
|
To enable the experimental HTTP/3 support for h2load and nghttpx, the
|
||||||
following libraries are required:
|
following libraries are required:
|
||||||
|
|
||||||
* `OpenSSL with QUIC support
|
* `OpenSSL with QUIC support
|
||||||
<https://github.com/quictls/openssl/tree/OpenSSL_1_1_1w+quic>`_; or
|
<https://github.com/quictls/openssl/tree/OpenSSL_1_1_1w+quic>`_; or
|
||||||
|
LibreSSL (does not support 0RTT); or aws-lc; or
|
||||||
`BoringSSL <https://boringssl.googlesource.com/boringssl/>`_ (commit
|
`BoringSSL <https://boringssl.googlesource.com/boringssl/>`_ (commit
|
||||||
6ca49385b168f47a50e7172d82a590b218f55e4d)
|
6ab7c1482bf4cdc91c87bc512aaf68ffb18975ec)
|
||||||
* `ngtcp2 <https://github.com/ngtcp2/ngtcp2>`_ 0.19.x
|
* `ngtcp2 <https://github.com/ngtcp2/ngtcp2>`_ >= 1.4.0
|
||||||
* `nghttp3 <https://github.com/ngtcp2/nghttp3>`_ 0.15.x
|
* `nghttp3 <https://github.com/ngtcp2/nghttp3>`_ >= 1.1.0
|
||||||
|
|
||||||
Use ``--enable-http3`` configure option to enable HTTP/3 feature for
|
Use ``--enable-http3`` configure option to enable HTTP/3 feature for
|
||||||
h2load and nghttpx.
|
h2load and nghttpx.
|
||||||
@@ -146,14 +144,14 @@ Use ``--with-libbpf`` configure option to build eBPF program.
|
|||||||
libelf-dev is needed to build libbpf.
|
libelf-dev is needed to build libbpf.
|
||||||
|
|
||||||
For Ubuntu 20.04, you can build libbpf from `the source code
|
For Ubuntu 20.04, you can build libbpf from `the source code
|
||||||
<https://github.com/libbpf/libbpf/releases/tag/v1.2.2>`_. nghttpx
|
<https://github.com/libbpf/libbpf/releases/tag/v1.3.0>`_. nghttpx
|
||||||
requires eBPF program for reloading its configuration and hot swapping
|
requires eBPF program for reloading its configuration and hot swapping
|
||||||
its executable.
|
its executable.
|
||||||
|
|
||||||
Compiling libnghttp2 C source code requires a C99 compiler. gcc 4.8
|
Compiling libnghttp2 C source code requires a C99 compiler. gcc 4.8
|
||||||
is known to be adequate. In order to compile the C++ source code, gcc
|
is known to be adequate. In order to compile the C++ source code,
|
||||||
>= 6.0 or clang >= 6.0 is required. C++ source code requires C++14
|
C++20 compliant compiler is required. At least g++ >= 1.12 and
|
||||||
language features.
|
clang++ >= 1.15 are known to work.
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|
|
||||||
@@ -207,7 +205,7 @@ required packages:
|
|||||||
|
|
||||||
sudo apt-get install g++ clang make binutils autoconf automake \
|
sudo apt-get install g++ clang make binutils autoconf automake \
|
||||||
autotools-dev libtool pkg-config \
|
autotools-dev libtool pkg-config \
|
||||||
zlib1g-dev libcunit1-dev libssl-dev libxml2-dev libev-dev \
|
zlib1g-dev libssl-dev libxml2-dev libev-dev \
|
||||||
libevent-dev libjansson-dev \
|
libevent-dev libjansson-dev \
|
||||||
libc-ares-dev libjemalloc-dev libsystemd-dev \
|
libc-ares-dev libjemalloc-dev libsystemd-dev \
|
||||||
ruby-dev bison libelf-dev
|
ruby-dev bison libelf-dev
|
||||||
@@ -339,23 +337,24 @@ connections alive during reload.
|
|||||||
|
|
||||||
The detailed steps to build HTTP/3 enabled h2load and nghttpx follow.
|
The detailed steps to build HTTP/3 enabled h2load and nghttpx follow.
|
||||||
|
|
||||||
Build custom OpenSSL:
|
Build aws-lc:
|
||||||
|
|
||||||
.. code-block:: text
|
.. code-block:: text
|
||||||
|
|
||||||
$ git clone --depth 1 -b OpenSSL_1_1_1w+quic https://github.com/quictls/openssl
|
$ git clone --depth 1 -b v1.26.0 https://github.com/aws/aws-lc
|
||||||
$ cd openssl
|
$ cd aws-lc
|
||||||
$ ./config --prefix=$PWD/build --openssldir=/etc/ssl
|
$ cmake -B build -DDISABLE_GO=ON --install-prefix=$PWD/opt
|
||||||
$ make -j$(nproc)
|
$ make -j$(nproc) -C build
|
||||||
$ make install_sw
|
$ cmake --install build
|
||||||
$ cd ..
|
$ cd ..
|
||||||
|
|
||||||
Build nghttp3:
|
Build nghttp3:
|
||||||
|
|
||||||
.. code-block:: text
|
.. code-block:: text
|
||||||
|
|
||||||
$ git clone --depth 1 -b v0.15.0 https://github.com/ngtcp2/nghttp3
|
$ git clone --depth 1 -b v1.3.0 https://github.com/ngtcp2/nghttp3
|
||||||
$ cd nghttp3
|
$ cd nghttp3
|
||||||
|
$ git submodule update --init --depth 1
|
||||||
$ autoreconf -i
|
$ autoreconf -i
|
||||||
$ ./configure --prefix=$PWD/build --enable-lib-only
|
$ ./configure --prefix=$PWD/build --enable-lib-only
|
||||||
$ make -j$(nproc)
|
$ make -j$(nproc)
|
||||||
@@ -366,11 +365,13 @@ Build ngtcp2:
|
|||||||
|
|
||||||
.. code-block:: text
|
.. code-block:: text
|
||||||
|
|
||||||
$ git clone --depth 1 -b v0.19.1 https://github.com/ngtcp2/ngtcp2
|
$ git clone --depth 1 -b v1.5.0 https://github.com/ngtcp2/ngtcp2
|
||||||
$ cd ngtcp2
|
$ cd ngtcp2
|
||||||
|
$ git submodule update --init --depth 1
|
||||||
$ autoreconf -i
|
$ autoreconf -i
|
||||||
$ ./configure --prefix=$PWD/build --enable-lib-only \
|
$ ./configure --prefix=$PWD/build --enable-lib-only --with-boringssl \
|
||||||
PKG_CONFIG_PATH="$PWD/../openssl/build/lib/pkgconfig"
|
BORINGSSL_CFLAGS="-I$PWD/../aws-lc/opt/include" \
|
||||||
|
BORINGSSL_LIBS="-L$PWD/../aws-lc/opt/lib -lssl -lcrypto"
|
||||||
$ make -j$(nproc)
|
$ make -j$(nproc)
|
||||||
$ make install
|
$ make install
|
||||||
$ cd ..
|
$ cd ..
|
||||||
@@ -380,7 +381,7 @@ from source:
|
|||||||
|
|
||||||
.. code-block:: text
|
.. code-block:: text
|
||||||
|
|
||||||
$ git clone --depth 1 -b v1.2.2 https://github.com/libbpf/libbpf
|
$ git clone --depth 1 -b v1.3.0 https://github.com/libbpf/libbpf
|
||||||
$ cd libbpf
|
$ cd libbpf
|
||||||
$ PREFIX=$PWD/build make -C src install
|
$ PREFIX=$PWD/build make -C src install
|
||||||
$ cd ..
|
$ cd ..
|
||||||
@@ -393,10 +394,10 @@ Build nghttp2:
|
|||||||
$ cd nghttp2
|
$ cd nghttp2
|
||||||
$ git submodule update --init
|
$ git submodule update --init
|
||||||
$ autoreconf -i
|
$ autoreconf -i
|
||||||
$ ./configure --with-mruby --with-neverbleed --enable-http3 --with-libbpf \
|
$ ./configure --with-mruby --enable-http3 --with-libbpf \
|
||||||
CC=clang-14 CXX=clang++-14 \
|
CC=clang-15 CXX=clang++-15 \
|
||||||
PKG_CONFIG_PATH="$PWD/../openssl/build/lib/pkgconfig:$PWD/../nghttp3/build/lib/pkgconfig:$PWD/../ngtcp2/build/lib/pkgconfig:$PWD/../libbpf/build/lib64/pkgconfig" \
|
PKG_CONFIG_PATH="$PWD/../aws-lc/opt/lib/pkgconfig:$PWD/../nghttp3/build/lib/pkgconfig:$PWD/../ngtcp2/build/lib/pkgconfig:$PWD/../libbpf/build/lib64/pkgconfig" \
|
||||||
LDFLAGS="$LDFLAGS -Wl,-rpath,$PWD/../openssl/build/lib -Wl,-rpath,$PWD/../libbpf/build/lib64"
|
LDFLAGS="$LDFLAGS -Wl,-rpath,$PWD/../aws-lc/opt/lib -Wl,-rpath,$PWD/../libbpf/build/lib64"
|
||||||
$ make -j$(nproc)
|
$ make -j$(nproc)
|
||||||
|
|
||||||
The eBPF program ``reuseport_kern.o`` should be found under bpf
|
The eBPF program ``reuseport_kern.o`` should be found under bpf
|
||||||
@@ -481,7 +482,7 @@ Previously nghttp2 library did not send client magic, which is first
|
|||||||
24 bytes byte string of client connection preface, and client
|
24 bytes byte string of client connection preface, and client
|
||||||
applications have to send it by themselves. Since v1.0.0, client
|
applications have to send it by themselves. Since v1.0.0, client
|
||||||
magic is sent by library via first call of ``nghttp2_session_send()``
|
magic is sent by library via first call of ``nghttp2_session_send()``
|
||||||
or ``nghttp2_session_mem_send()``.
|
or ``nghttp2_session_mem_send2()``.
|
||||||
|
|
||||||
The client applications which send client magic must remove the
|
The client applications which send client magic must remove the
|
||||||
relevant code.
|
relevant code.
|
||||||
@@ -539,7 +540,7 @@ nghttp - client
|
|||||||
+++++++++++++++
|
+++++++++++++++
|
||||||
|
|
||||||
``nghttp`` is a HTTP/2 client. It can connect to the HTTP/2 server
|
``nghttp`` is a HTTP/2 client. It can connect to the HTTP/2 server
|
||||||
with prior knowledge, HTTP Upgrade and NPN/ALPN TLS extension.
|
with prior knowledge, HTTP Upgrade and ALPN TLS extension.
|
||||||
|
|
||||||
It has verbose output mode for framing information. Here is sample
|
It has verbose output mode for framing information. Here is sample
|
||||||
output from ``nghttp`` client:
|
output from ``nghttp`` client:
|
||||||
@@ -765,8 +766,8 @@ nghttpd - server
|
|||||||
By default, it uses SSL/TLS connection. Use ``--no-tls`` option to
|
By default, it uses SSL/TLS connection. Use ``--no-tls`` option to
|
||||||
disable it.
|
disable it.
|
||||||
|
|
||||||
``nghttpd`` only accepts HTTP/2 connections via NPN/ALPN or direct
|
``nghttpd`` only accepts HTTP/2 connections via ALPN or direct HTTP/2
|
||||||
HTTP/2 connections. No HTTP Upgrade is supported.
|
connections. No HTTP Upgrade is supported.
|
||||||
|
|
||||||
The ``-p`` option allows users to configure server push.
|
The ``-p`` option allows users to configure server push.
|
||||||
|
|
||||||
@@ -847,7 +848,7 @@ to know how to migrate from earlier releases.
|
|||||||
``nghttpx`` implements `important performance-oriented features
|
``nghttpx`` implements `important performance-oriented features
|
||||||
<https://istlsfastyet.com/#server-performance>`_ in TLS, such as
|
<https://istlsfastyet.com/#server-performance>`_ in TLS, such as
|
||||||
session IDs, session tickets (with automatic key rotation), OCSP
|
session IDs, session tickets (with automatic key rotation), OCSP
|
||||||
stapling, dynamic record sizing, ALPN/NPN, forward secrecy and HTTP/2.
|
stapling, dynamic record sizing, ALPN, forward secrecy and HTTP/2.
|
||||||
``nghttpx`` also offers the functionality to share session cache and
|
``nghttpx`` also offers the functionality to share session cache and
|
||||||
ticket keys among multiple ``nghttpx`` instances via memcached.
|
ticket keys among multiple ``nghttpx`` instances via memcached.
|
||||||
|
|
||||||
@@ -974,12 +975,15 @@ threads to avoid saturating a single core on client side.
|
|||||||
servers.
|
servers.
|
||||||
|
|
||||||
If the experimental HTTP/3 is enabled, h2load can send requests to
|
If the experimental HTTP/3 is enabled, h2load can send requests to
|
||||||
HTTP/3 server. To do this, specify ``h3`` to ``--npn-list`` option
|
HTTP/3 server. To do this, specify ``h3`` to ``--alpn-list`` option
|
||||||
like so:
|
like so:
|
||||||
|
|
||||||
.. code-block:: text
|
.. code-block:: text
|
||||||
|
|
||||||
$ h2load --npn-list h3 https://127.0.0.1:4433
|
$ h2load --alpn-list h3 https://127.0.0.1:4433
|
||||||
|
|
||||||
|
For nghttp2 v1.58 or earlier, use ``--npn-list`` instead of
|
||||||
|
``--alpn-list``.
|
||||||
|
|
||||||
HPACK tools
|
HPACK tools
|
||||||
-----------
|
-----------
|
||||||
@@ -1445,23 +1449,10 @@ See `Contribution Guidelines
|
|||||||
<https://nghttp2.org/documentation/contribute.html>`_ for more
|
<https://nghttp2.org/documentation/contribute.html>`_ for more
|
||||||
details.
|
details.
|
||||||
|
|
||||||
Reporting vulnerability
|
Versioning
|
||||||
-----------------------
|
----------
|
||||||
|
|
||||||
If you find a vulnerability in our software, please send the email to
|
In general, we follow `Semantic Versioning <http://semver.org/>`_.
|
||||||
"tatsuhiro.t at gmail dot com" about its details instead of submitting
|
|
||||||
issues on github issue page. It is a standard practice not to
|
|
||||||
disclose vulnerability information publicly until a fixed version is
|
|
||||||
released, or mitigation is worked out.
|
|
||||||
|
|
||||||
In the future, we may setup a dedicated mail address for this purpose.
|
|
||||||
|
|
||||||
Release schedule
|
|
||||||
----------------
|
|
||||||
|
|
||||||
In general, we follow `Semantic Versioning <http://semver.org/>`_. We
|
|
||||||
release MINOR version update every month, and usually we ship it
|
|
||||||
around 25th day of every month.
|
|
||||||
|
|
||||||
We may release PATCH releases between the regular releases, mainly for
|
We may release PATCH releases between the regular releases, mainly for
|
||||||
severe security bug fixes.
|
severe security bug fixes.
|
||||||
|
|||||||
31
SECURITY.md
Normal file
31
SECURITY.md
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
# Security Process
|
||||||
|
|
||||||
|
If you find a vulnerability in our software, please report it via
|
||||||
|
GitHub "Private vulnerability reporting" feature at
|
||||||
|
https://github.com/nghttp2/nghttp2/security instead of submitting
|
||||||
|
issues on github issue page. It is a standard practice not to
|
||||||
|
disclose vulnerability information publicly until a fixed version is
|
||||||
|
released, or mitigation is worked out.
|
||||||
|
|
||||||
|
If we identify that the reported issue is really a vulnerability, we
|
||||||
|
open a new security advisory draft using [GitHub security
|
||||||
|
feature](https://github.com/nghttp2/nghttp2/security) and discuss the
|
||||||
|
mitigation and bug fixes there. The fixes are committed to the
|
||||||
|
private repository.
|
||||||
|
|
||||||
|
We write the security advisory and get CVE number from GitHub
|
||||||
|
privately. We also discuss the disclosure date to the public.
|
||||||
|
|
||||||
|
We make a new release with the fix at the same time when the
|
||||||
|
vulnerability is disclosed to public.
|
||||||
|
|
||||||
|
At least 7 days before the public disclosure date, we open a new issue
|
||||||
|
on [nghttp2 issue tracker](https://github.com/nghttp2/nghttp2/issues)
|
||||||
|
which notifies that the upcoming release will have a security fix.
|
||||||
|
The `SECURITY` label is attached to this kind of issue. The issue is
|
||||||
|
not opened if a vulnerability is already disclosed, and it is publicly
|
||||||
|
known that nghttp2 is affected by that.
|
||||||
|
|
||||||
|
Before few hours of new release, we merge the fixes to the master
|
||||||
|
branch (and/or a release branch if necessary) and make a new release.
|
||||||
|
Security advisory is disclosed on GitHub.
|
||||||
@@ -42,11 +42,6 @@
|
|||||||
License is Public Domain. Commit hash:
|
License is Public Domain. Commit hash:
|
||||||
12e7744b4919e9d55de75b7ab566326a1c8e7a67 */
|
12e7744b4919e9d55de75b7ab566326a1c8e7a67 */
|
||||||
|
|
||||||
#define AES_BLOCKLEN \
|
|
||||||
16 /* Block length in bytes - AES is 128b block \
|
|
||||||
only */
|
|
||||||
|
|
||||||
#define AES_KEYLEN 16 /* Key length in bytes */
|
|
||||||
#define AES_keyExpSize 176
|
#define AES_keyExpSize 176
|
||||||
|
|
||||||
struct AES_ctx {
|
struct AES_ctx {
|
||||||
@@ -57,7 +52,6 @@ struct AES_ctx {
|
|||||||
in AES. Value=4 */
|
in AES. Value=4 */
|
||||||
#define Nb 4
|
#define Nb 4
|
||||||
|
|
||||||
#define Nk 4 /* The number of 32 bit words in a key. */
|
|
||||||
#define Nr 10 /* The number of rounds in AES Cipher. */
|
#define Nr 10 /* The number of rounds in AES Cipher. */
|
||||||
|
|
||||||
/* state - array holding the intermediate results during
|
/* state - array holding the intermediate results during
|
||||||
@@ -68,31 +62,6 @@ typedef __u8 state_t[4][4];
|
|||||||
read-only storage instead of RAM The numbers below can be computed
|
read-only storage instead of RAM The numbers below can be computed
|
||||||
dynamically trading ROM for RAM - This can be useful in (embedded)
|
dynamically trading ROM for RAM - This can be useful in (embedded)
|
||||||
bootloader applications, where ROM is often limited. */
|
bootloader applications, where ROM is often limited. */
|
||||||
static const __u8 sbox[256] = {
|
|
||||||
/* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
|
|
||||||
0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b,
|
|
||||||
0xfe, 0xd7, 0xab, 0x76, 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0,
|
|
||||||
0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, 0xb7, 0xfd, 0x93, 0x26,
|
|
||||||
0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
|
|
||||||
0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2,
|
|
||||||
0xeb, 0x27, 0xb2, 0x75, 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0,
|
|
||||||
0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, 0x53, 0xd1, 0x00, 0xed,
|
|
||||||
0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
|
|
||||||
0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f,
|
|
||||||
0x50, 0x3c, 0x9f, 0xa8, 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5,
|
|
||||||
0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, 0xcd, 0x0c, 0x13, 0xec,
|
|
||||||
0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
|
|
||||||
0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14,
|
|
||||||
0xde, 0x5e, 0x0b, 0xdb, 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c,
|
|
||||||
0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, 0xe7, 0xc8, 0x37, 0x6d,
|
|
||||||
0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
|
|
||||||
0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f,
|
|
||||||
0x4b, 0xbd, 0x8b, 0x8a, 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e,
|
|
||||||
0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, 0xe1, 0xf8, 0x98, 0x11,
|
|
||||||
0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
|
|
||||||
0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f,
|
|
||||||
0xb0, 0x54, 0xbb, 0x16};
|
|
||||||
|
|
||||||
static const __u8 rsbox[256] = {
|
static const __u8 rsbox[256] = {
|
||||||
0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e,
|
0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e,
|
||||||
0x81, 0xf3, 0xd7, 0xfb, 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87,
|
0x81, 0xf3, 0xd7, 0xfb, 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87,
|
||||||
@@ -117,78 +86,6 @@ static const __u8 rsbox[256] = {
|
|||||||
0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63,
|
0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63,
|
||||||
0x55, 0x21, 0x0c, 0x7d};
|
0x55, 0x21, 0x0c, 0x7d};
|
||||||
|
|
||||||
/* The round constant word array, Rcon[i], contains the values given
|
|
||||||
by x to the power (i-1) being powers of x (x is denoted as {02}) in
|
|
||||||
the field GF(2^8) */
|
|
||||||
static const __u8 Rcon[11] = {0x8d, 0x01, 0x02, 0x04, 0x08, 0x10,
|
|
||||||
0x20, 0x40, 0x80, 0x1b, 0x36};
|
|
||||||
|
|
||||||
#define getSBoxValue(num) (sbox[(num)])
|
|
||||||
|
|
||||||
/* This function produces Nb(Nr+1) round keys. The round keys are used
|
|
||||||
in each round to decrypt the states. */
|
|
||||||
static void KeyExpansion(__u8 *RoundKey, const __u8 *Key) {
|
|
||||||
unsigned i, j, k;
|
|
||||||
__u8 tempa[4]; /* Used for the column/row operations */
|
|
||||||
|
|
||||||
/* The first round key is the key itself. */
|
|
||||||
for (i = 0; i < Nk; ++i) {
|
|
||||||
RoundKey[(i * 4) + 0] = Key[(i * 4) + 0];
|
|
||||||
RoundKey[(i * 4) + 1] = Key[(i * 4) + 1];
|
|
||||||
RoundKey[(i * 4) + 2] = Key[(i * 4) + 2];
|
|
||||||
RoundKey[(i * 4) + 3] = Key[(i * 4) + 3];
|
|
||||||
}
|
|
||||||
|
|
||||||
/* All other round keys are found from the previous round keys. */
|
|
||||||
for (i = Nk; i < Nb * (Nr + 1); ++i) {
|
|
||||||
{
|
|
||||||
k = (i - 1) * 4;
|
|
||||||
tempa[0] = RoundKey[k + 0];
|
|
||||||
tempa[1] = RoundKey[k + 1];
|
|
||||||
tempa[2] = RoundKey[k + 2];
|
|
||||||
tempa[3] = RoundKey[k + 3];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (i % Nk == 0) {
|
|
||||||
/* This function shifts the 4 bytes in a word to the left once.
|
|
||||||
[a0,a1,a2,a3] becomes [a1,a2,a3,a0] */
|
|
||||||
|
|
||||||
/* Function RotWord() */
|
|
||||||
{
|
|
||||||
const __u8 u8tmp = tempa[0];
|
|
||||||
tempa[0] = tempa[1];
|
|
||||||
tempa[1] = tempa[2];
|
|
||||||
tempa[2] = tempa[3];
|
|
||||||
tempa[3] = u8tmp;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* SubWord() is a function that takes a four-byte input word and
|
|
||||||
applies the S-box to each of the four bytes to produce an
|
|
||||||
output word. */
|
|
||||||
|
|
||||||
/* Function Subword() */
|
|
||||||
{
|
|
||||||
tempa[0] = getSBoxValue(tempa[0]);
|
|
||||||
tempa[1] = getSBoxValue(tempa[1]);
|
|
||||||
tempa[2] = getSBoxValue(tempa[2]);
|
|
||||||
tempa[3] = getSBoxValue(tempa[3]);
|
|
||||||
}
|
|
||||||
|
|
||||||
tempa[0] = tempa[0] ^ Rcon[i / Nk];
|
|
||||||
}
|
|
||||||
j = i * 4;
|
|
||||||
k = (i - Nk) * 4;
|
|
||||||
RoundKey[j + 0] = RoundKey[k + 0] ^ tempa[0];
|
|
||||||
RoundKey[j + 1] = RoundKey[k + 1] ^ tempa[1];
|
|
||||||
RoundKey[j + 2] = RoundKey[k + 2] ^ tempa[2];
|
|
||||||
RoundKey[j + 3] = RoundKey[k + 3] ^ tempa[3];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void AES_init_ctx(struct AES_ctx *ctx, const __u8 *key) {
|
|
||||||
KeyExpansion(ctx->RoundKey, key);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* This function adds the round key to state. The round key is added
|
/* This function adds the round key to state. The round key is added
|
||||||
to the state by an XOR function. */
|
to the state by an XOR function. */
|
||||||
static void AddRoundKey(__u8 round, state_t *state, const __u8 *RoundKey) {
|
static void AddRoundKey(__u8 round, state_t *state, const __u8 *RoundKey) {
|
||||||
@@ -428,7 +325,7 @@ struct {
|
|||||||
__uint(max_entries, 255);
|
__uint(max_entries, 255);
|
||||||
__type(key, __u64);
|
__type(key, __u64);
|
||||||
__type(value, __u32);
|
__type(value, __u32);
|
||||||
} cid_prefix_map SEC(".maps");
|
} worker_id_map SEC(".maps");
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
__uint(type, BPF_MAP_TYPE_REUSEPORT_SOCKARRAY);
|
__uint(type, BPF_MAP_TYPE_REUSEPORT_SOCKARRAY);
|
||||||
@@ -439,11 +336,18 @@ struct {
|
|||||||
|
|
||||||
struct {
|
struct {
|
||||||
__uint(type, BPF_MAP_TYPE_ARRAY);
|
__uint(type, BPF_MAP_TYPE_ARRAY);
|
||||||
__uint(max_entries, 3);
|
__uint(max_entries, 1);
|
||||||
__type(key, __u32);
|
__type(key, __u32);
|
||||||
__type(value, __u64);
|
__type(value, __u64);
|
||||||
} sk_info SEC(".maps");
|
} sk_info SEC(".maps");
|
||||||
|
|
||||||
|
struct {
|
||||||
|
__uint(type, BPF_MAP_TYPE_ARRAY);
|
||||||
|
__uint(max_entries, 1);
|
||||||
|
__type(key, __u32);
|
||||||
|
__type(value, struct AES_ctx);
|
||||||
|
} aes_key SEC(".maps");
|
||||||
|
|
||||||
typedef struct quic_hd {
|
typedef struct quic_hd {
|
||||||
__u8 *dcid;
|
__u8 *dcid;
|
||||||
__u32 dcidlen;
|
__u32 dcidlen;
|
||||||
@@ -451,11 +355,11 @@ typedef struct quic_hd {
|
|||||||
__u8 type;
|
__u8 type;
|
||||||
} quic_hd;
|
} quic_hd;
|
||||||
|
|
||||||
#define SV_DCIDLEN 20
|
#define SV_DCIDLEN 17
|
||||||
#define MAX_DCIDLEN 20
|
#define MAX_DCIDLEN 20
|
||||||
#define MIN_DCIDLEN 8
|
#define MIN_DCIDLEN 8
|
||||||
#define CID_PREFIXLEN 8
|
#define WORKER_IDLEN 8
|
||||||
#define CID_PREFIX_OFFSET 1
|
#define WORKER_ID_OFFSET 1
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
NGTCP2_PKT_INITIAL = 0x0,
|
NGTCP2_PKT_INITIAL = 0x0,
|
||||||
@@ -573,14 +477,39 @@ static __u32 sk_index_from_dcid(const quic_hd *qhd,
|
|||||||
SEC("sk_reuseport")
|
SEC("sk_reuseport")
|
||||||
int select_reuseport(struct sk_reuseport_md *reuse_md) {
|
int select_reuseport(struct sk_reuseport_md *reuse_md) {
|
||||||
__u32 sk_index, *psk_index;
|
__u32 sk_index, *psk_index;
|
||||||
__u64 *pnum_socks, *pkey;
|
__u64 *pnum_socks;
|
||||||
__u32 zero = 0, key_high_idx = 1, key_low_idx = 2;
|
__u32 zero = 0;
|
||||||
int rv;
|
int rv;
|
||||||
quic_hd qhd;
|
quic_hd qhd;
|
||||||
__u8 qpktbuf[6 + MAX_DCIDLEN];
|
__u8 qpktbuf[6 + MAX_DCIDLEN];
|
||||||
struct AES_ctx aes_ctx;
|
struct AES_ctx *aes_ctx;
|
||||||
__u8 key[AES_KEYLEN];
|
__u8 *worker_id;
|
||||||
__u8 *cid_prefix;
|
__u16 remote_port;
|
||||||
|
__u8 *data = reuse_md->data;
|
||||||
|
|
||||||
|
/* Packets less than 22 bytes never be a valid QUIC packet. */
|
||||||
|
if (reuse_md->len < sizeof(struct udphdr) + 22) {
|
||||||
|
return SK_DROP;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (reuse_md->data + sizeof(struct udphdr) > reuse_md->data_end) {
|
||||||
|
return SK_DROP;
|
||||||
|
}
|
||||||
|
|
||||||
|
remote_port = (data[0] << 8) + data[1];
|
||||||
|
|
||||||
|
switch (remote_port) {
|
||||||
|
case 1900:
|
||||||
|
case 5353:
|
||||||
|
case 11211:
|
||||||
|
case 20800:
|
||||||
|
case 27015:
|
||||||
|
return SK_DROP;
|
||||||
|
default:
|
||||||
|
if (remote_port < 1024) {
|
||||||
|
return SK_DROP;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (bpf_skb_load_bytes(reuse_md, sizeof(struct udphdr), qpktbuf,
|
if (bpf_skb_load_bytes(reuse_md, sizeof(struct udphdr), qpktbuf,
|
||||||
sizeof(qpktbuf)) != 0) {
|
sizeof(qpktbuf)) != 0) {
|
||||||
@@ -592,35 +521,24 @@ int select_reuseport(struct sk_reuseport_md *reuse_md) {
|
|||||||
return SK_DROP;
|
return SK_DROP;
|
||||||
}
|
}
|
||||||
|
|
||||||
pkey = bpf_map_lookup_elem(&sk_info, &key_high_idx);
|
aes_ctx = bpf_map_lookup_elem(&aes_key, &zero);
|
||||||
if (pkey == NULL) {
|
if (aes_ctx == NULL) {
|
||||||
return SK_DROP;
|
return SK_DROP;
|
||||||
}
|
}
|
||||||
|
|
||||||
__builtin_memcpy(key, pkey, sizeof(*pkey));
|
|
||||||
|
|
||||||
pkey = bpf_map_lookup_elem(&sk_info, &key_low_idx);
|
|
||||||
if (pkey == NULL) {
|
|
||||||
return SK_DROP;
|
|
||||||
}
|
|
||||||
|
|
||||||
__builtin_memcpy(key + sizeof(*pkey), pkey, sizeof(*pkey));
|
|
||||||
|
|
||||||
rv = parse_quic(&qhd, qpktbuf, qpktbuf + sizeof(qpktbuf));
|
rv = parse_quic(&qhd, qpktbuf, qpktbuf + sizeof(qpktbuf));
|
||||||
if (rv != 0) {
|
if (rv != 0) {
|
||||||
return SK_DROP;
|
return SK_DROP;
|
||||||
}
|
}
|
||||||
|
|
||||||
AES_init_ctx(&aes_ctx, key);
|
|
||||||
|
|
||||||
switch (qhd.type) {
|
switch (qhd.type) {
|
||||||
case NGTCP2_PKT_INITIAL:
|
case NGTCP2_PKT_INITIAL:
|
||||||
case NGTCP2_PKT_0RTT:
|
case NGTCP2_PKT_0RTT:
|
||||||
if (qhd.dcidlen == SV_DCIDLEN) {
|
if (qhd.dcidlen == SV_DCIDLEN) {
|
||||||
cid_prefix = qhd.dcid + CID_PREFIX_OFFSET;
|
worker_id = qhd.dcid + WORKER_ID_OFFSET;
|
||||||
AES_ECB_decrypt(&aes_ctx, cid_prefix);
|
AES_ECB_decrypt(aes_ctx, worker_id);
|
||||||
|
|
||||||
psk_index = bpf_map_lookup_elem(&cid_prefix_map, cid_prefix);
|
psk_index = bpf_map_lookup_elem(&worker_id_map, worker_id);
|
||||||
if (psk_index != NULL) {
|
if (psk_index != NULL) {
|
||||||
sk_index = *psk_index;
|
sk_index = *psk_index;
|
||||||
|
|
||||||
@@ -637,10 +555,10 @@ int select_reuseport(struct sk_reuseport_md *reuse_md) {
|
|||||||
return SK_DROP;
|
return SK_DROP;
|
||||||
}
|
}
|
||||||
|
|
||||||
cid_prefix = qhd.dcid + CID_PREFIX_OFFSET;
|
worker_id = qhd.dcid + WORKER_ID_OFFSET;
|
||||||
AES_ECB_decrypt(&aes_ctx, cid_prefix);
|
AES_ECB_decrypt(aes_ctx, worker_id);
|
||||||
|
|
||||||
psk_index = bpf_map_lookup_elem(&cid_prefix_map, cid_prefix);
|
psk_index = bpf_map_lookup_elem(&worker_id_map, worker_id);
|
||||||
if (psk_index == NULL) {
|
if (psk_index == NULL) {
|
||||||
sk_index = sk_index_from_dcid(&qhd, reuse_md, *pnum_socks);
|
sk_index = sk_index_from_dcid(&qhd, reuse_md, *pnum_socks);
|
||||||
|
|
||||||
|
|||||||
@@ -1,40 +0,0 @@
|
|||||||
# - Try to find cunit
|
|
||||||
# Once done this will define
|
|
||||||
# CUNIT_FOUND - System has cunit
|
|
||||||
# CUNIT_INCLUDE_DIRS - The cunit include directories
|
|
||||||
# CUNIT_LIBRARIES - The libraries needed to use cunit
|
|
||||||
|
|
||||||
find_package(PkgConfig QUIET)
|
|
||||||
pkg_check_modules(PC_CUNIT QUIET cunit)
|
|
||||||
|
|
||||||
find_path(CUNIT_INCLUDE_DIR
|
|
||||||
NAMES CUnit/CUnit.h
|
|
||||||
HINTS ${PC_CUNIT_INCLUDE_DIRS}
|
|
||||||
)
|
|
||||||
find_library(CUNIT_LIBRARY
|
|
||||||
NAMES cunit
|
|
||||||
HINTS ${PC_CUNIT_LIBRARY_DIRS}
|
|
||||||
)
|
|
||||||
|
|
||||||
if(CUNIT_INCLUDE_DIR)
|
|
||||||
set(_version_regex "^#define[ \t]+CU_VERSION[ \t]+\"([^\"]+)\".*")
|
|
||||||
file(STRINGS "${CUNIT_INCLUDE_DIR}/CUnit/CUnit.h"
|
|
||||||
CUNIT_VERSION REGEX "${_version_regex}")
|
|
||||||
string(REGEX REPLACE "${_version_regex}" "\\1"
|
|
||||||
CUNIT_VERSION "${CUNIT_VERSION}")
|
|
||||||
unset(_version_regex)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
include(FindPackageHandleStandardArgs)
|
|
||||||
# handle the QUIETLY and REQUIRED arguments and set CUNIT_FOUND to TRUE
|
|
||||||
# if all listed variables are TRUE and the requested version matches.
|
|
||||||
find_package_handle_standard_args(CUnit REQUIRED_VARS
|
|
||||||
CUNIT_LIBRARY CUNIT_INCLUDE_DIR
|
|
||||||
VERSION_VAR CUNIT_VERSION)
|
|
||||||
|
|
||||||
if(CUNIT_FOUND)
|
|
||||||
set(CUNIT_LIBRARIES ${CUNIT_LIBRARY})
|
|
||||||
set(CUNIT_INCLUDE_DIRS ${CUNIT_INCLUDE_DIR})
|
|
||||||
endif()
|
|
||||||
|
|
||||||
mark_as_advanced(CUNIT_INCLUDE_DIR CUNIT_LIBRARY)
|
|
||||||
36
cmake/FindLibbrotlidec.cmake
Normal file
36
cmake/FindLibbrotlidec.cmake
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
# - Try to find libbrotlidec
|
||||||
|
# Once done this will define
|
||||||
|
# LIBBROTLIDEC_FOUND - System has libbrotlidec
|
||||||
|
# LIBBROTLIDEC_INCLUDE_DIRS - The libbrotlidec include directories
|
||||||
|
# LIBBROTLIDEC_LIBRARIES - The libraries needed to use libbrotlidec
|
||||||
|
|
||||||
|
find_package(PkgConfig QUIET)
|
||||||
|
pkg_check_modules(PC_LIBBROTLIDEC QUIET libbrotlidec)
|
||||||
|
|
||||||
|
find_path(LIBBROTLIDEC_INCLUDE_DIR
|
||||||
|
NAMES brotli/decode.h
|
||||||
|
HINTS ${PC_LIBBROTLIDEC_INCLUDE_DIRS}
|
||||||
|
)
|
||||||
|
find_library(LIBBROTLIDEC_LIBRARY
|
||||||
|
NAMES brotlidec
|
||||||
|
HINTS ${PC_LIBBROTLIDEC_LIBRARY_DIRS}
|
||||||
|
)
|
||||||
|
|
||||||
|
if(PC_LIBBROTLIDEC_FOUND)
|
||||||
|
set(LIBBROTLIDEC_VERSION ${PC_LIBBROTLIDEC_VERSION})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
include(FindPackageHandleStandardArgs)
|
||||||
|
# handle the QUIETLY and REQUIRED arguments and set LIBBROTLIDEC_FOUND
|
||||||
|
# to TRUE if all listed variables are TRUE and the requested version
|
||||||
|
# matches.
|
||||||
|
find_package_handle_standard_args(Libbrotlidec REQUIRED_VARS
|
||||||
|
LIBBROTLIDEC_LIBRARY LIBBROTLIDEC_INCLUDE_DIR
|
||||||
|
VERSION_VAR LIBBROTLIDEC_VERSION)
|
||||||
|
|
||||||
|
if(LIBBROTLIDEC_FOUND)
|
||||||
|
set(LIBBROTLIDEC_LIBRARIES ${LIBBROTLIDEC_LIBRARY})
|
||||||
|
set(LIBBROTLIDEC_INCLUDE_DIRS ${LIBBROTLIDEC_INCLUDE_DIR})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
mark_as_advanced(LIBBROTLIDEC_INCLUDE_DIR LIBBROTLIDEC_LIBRARY)
|
||||||
36
cmake/FindLibbrotlienc.cmake
Normal file
36
cmake/FindLibbrotlienc.cmake
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
# - Try to find libbrotlienc
|
||||||
|
# Once done this will define
|
||||||
|
# LIBBROTLIENC_FOUND - System has libbrotlienc
|
||||||
|
# LIBBROTLIENC_INCLUDE_DIRS - The libbrotlienc include directories
|
||||||
|
# LIBBROTLIENC_LIBRARIES - The libraries needed to use libbrotlienc
|
||||||
|
|
||||||
|
find_package(PkgConfig QUIET)
|
||||||
|
pkg_check_modules(PC_LIBBROTLIENC QUIET libbrotlienc)
|
||||||
|
|
||||||
|
find_path(LIBBROTLIENC_INCLUDE_DIR
|
||||||
|
NAMES brotli/encode.h
|
||||||
|
HINTS ${PC_LIBBROTLIENC_INCLUDE_DIRS}
|
||||||
|
)
|
||||||
|
find_library(LIBBROTLIENC_LIBRARY
|
||||||
|
NAMES brotlienc
|
||||||
|
HINTS ${PC_LIBBROTLIENC_LIBRARY_DIRS}
|
||||||
|
)
|
||||||
|
|
||||||
|
if(PC_LIBBROTLIENC_FOUND)
|
||||||
|
set(LIBBROTLIENC_VERSION ${PC_LIBBROTLIENC_VERSION})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
include(FindPackageHandleStandardArgs)
|
||||||
|
# handle the QUIETLY and REQUIRED arguments and set LIBBROTLIENC_FOUND
|
||||||
|
# to TRUE if all listed variables are TRUE and the requested version
|
||||||
|
# matches.
|
||||||
|
find_package_handle_standard_args(Libbrotlienc REQUIRED_VARS
|
||||||
|
LIBBROTLIENC_LIBRARY LIBBROTLIENC_INCLUDE_DIR
|
||||||
|
VERSION_VAR LIBBROTLIENC_VERSION)
|
||||||
|
|
||||||
|
if(LIBBROTLIENC_FOUND)
|
||||||
|
set(LIBBROTLIENC_LIBRARIES ${LIBBROTLIENC_LIBRARY})
|
||||||
|
set(LIBBROTLIENC_INCLUDE_DIRS ${LIBBROTLIENC_INCLUDE_DIR})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
mark_as_advanced(LIBBROTLIENC_INCLUDE_DIR LIBBROTLIENC_LIBRARY)
|
||||||
162
cmake/PickyWarningsC.cmake
Normal file
162
cmake/PickyWarningsC.cmake
Normal file
@@ -0,0 +1,162 @@
|
|||||||
|
# nghttp2
|
||||||
|
#
|
||||||
|
# Copyright (c) 2023 nghttp2 contributors
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
|
||||||
|
# C
|
||||||
|
|
||||||
|
include(CheckCCompilerFlag)
|
||||||
|
|
||||||
|
if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX OR CMAKE_C_COMPILER_ID MATCHES "Clang")
|
||||||
|
|
||||||
|
# https://clang.llvm.org/docs/DiagnosticsReference.html
|
||||||
|
# https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html
|
||||||
|
|
||||||
|
# WPICKY_ENABLE = Options we want to enable as-is.
|
||||||
|
# WPICKY_DETECT = Options we want to test first and enable if available.
|
||||||
|
|
||||||
|
# Prefer the -Wextra alias with clang.
|
||||||
|
if(CMAKE_C_COMPILER_ID MATCHES "Clang")
|
||||||
|
set(WPICKY_ENABLE "-Wextra")
|
||||||
|
else()
|
||||||
|
set(WPICKY_ENABLE "-W")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
list(APPEND WPICKY_ENABLE
|
||||||
|
-Wall
|
||||||
|
)
|
||||||
|
|
||||||
|
# ----------------------------------
|
||||||
|
# Add new options here, if in doubt:
|
||||||
|
# ----------------------------------
|
||||||
|
set(WPICKY_DETECT
|
||||||
|
)
|
||||||
|
|
||||||
|
# Assume these options always exist with both clang and gcc.
|
||||||
|
# Require clang 3.0 / gcc 2.95 or later.
|
||||||
|
list(APPEND WPICKY_ENABLE
|
||||||
|
-Wconversion # clang 3.0 gcc 2.95
|
||||||
|
-Winline # clang 1.0 gcc 1.0
|
||||||
|
-Wmissing-declarations # clang 1.0 gcc 2.7
|
||||||
|
-Wmissing-prototypes # clang 1.0 gcc 1.0
|
||||||
|
-Wnested-externs # clang 1.0 gcc 2.7
|
||||||
|
-Wpointer-arith # clang 1.0 gcc 1.4
|
||||||
|
-Wshadow # clang 1.0 gcc 2.95
|
||||||
|
-Wundef # clang 1.0 gcc 2.95
|
||||||
|
-Wwrite-strings # clang 1.0 gcc 1.4
|
||||||
|
)
|
||||||
|
|
||||||
|
# Always enable with clang, version dependent with gcc
|
||||||
|
set(WPICKY_COMMON_OLD
|
||||||
|
-Waddress # clang 3.0 gcc 4.3
|
||||||
|
-Wattributes # clang 3.0 gcc 4.1
|
||||||
|
-Wcast-align # clang 1.0 gcc 4.2
|
||||||
|
-Wdeclaration-after-statement # clang 1.0 gcc 3.4
|
||||||
|
-Wdiv-by-zero # clang 3.0 gcc 4.1
|
||||||
|
-Wempty-body # clang 3.0 gcc 4.3
|
||||||
|
-Wendif-labels # clang 1.0 gcc 3.3
|
||||||
|
-Wfloat-equal # clang 1.0 gcc 2.96 (3.0)
|
||||||
|
-Wformat-nonliteral # clang 3.0 gcc 4.1
|
||||||
|
-Wformat-security # clang 3.0 gcc 4.1
|
||||||
|
-Wmissing-field-initializers # clang 3.0 gcc 4.1
|
||||||
|
-Wmissing-noreturn # clang 3.0 gcc 4.1
|
||||||
|
-Wno-format-nonliteral # clang 1.0 gcc 2.96 (3.0) # This is required because we pass format string as "const char*"
|
||||||
|
# -Wpadded # clang 3.0 gcc 4.1 # Not used because we cannot change public structs
|
||||||
|
-Wredundant-decls # clang 3.0 gcc 4.1
|
||||||
|
-Wsign-conversion # clang 3.0 gcc 4.3
|
||||||
|
-Wstrict-prototypes # clang 1.0 gcc 3.3
|
||||||
|
# -Wswitch-enum # clang 3.0 gcc 4.1 # Not used because this basically disallows default case
|
||||||
|
-Wunreachable-code # clang 3.0 gcc 4.1
|
||||||
|
-Wunused-parameter # clang 3.0 gcc 4.1
|
||||||
|
-Wvla # clang 2.8 gcc 4.3
|
||||||
|
)
|
||||||
|
|
||||||
|
set(WPICKY_COMMON
|
||||||
|
-Wpragmas # clang 3.5 gcc 4.1 appleclang 6.0
|
||||||
|
)
|
||||||
|
|
||||||
|
if(CMAKE_C_COMPILER_ID MATCHES "Clang")
|
||||||
|
list(APPEND WPICKY_ENABLE
|
||||||
|
${WPICKY_COMMON_OLD}
|
||||||
|
-Wshorten-64-to-32 # clang 1.0
|
||||||
|
-Wlanguage-extension-token # clang 3.0
|
||||||
|
)
|
||||||
|
# Enable based on compiler version
|
||||||
|
if((CMAKE_C_COMPILER_ID STREQUAL "Clang" AND NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 3.6) OR
|
||||||
|
(CMAKE_C_COMPILER_ID STREQUAL "AppleClang" AND NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 6.3))
|
||||||
|
list(APPEND WPICKY_ENABLE
|
||||||
|
${WPICKY_COMMON}
|
||||||
|
-Wunreachable-code-break # clang 3.5 appleclang 6.0
|
||||||
|
-Wheader-guard # clang 3.4 appleclang 5.1
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
if((CMAKE_C_COMPILER_ID STREQUAL "Clang" AND NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 3.9) OR
|
||||||
|
(CMAKE_C_COMPILER_ID STREQUAL "AppleClang" AND NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 8.3))
|
||||||
|
list(APPEND WPICKY_ENABLE
|
||||||
|
-Wmissing-variable-declarations # clang 3.2 appleclang 4.6
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
if((CMAKE_C_COMPILER_ID STREQUAL "Clang" AND NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 5.0) OR
|
||||||
|
(CMAKE_C_COMPILER_ID STREQUAL "AppleClang" AND NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 9.4))
|
||||||
|
list(APPEND WPICKY_ENABLE
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
if((CMAKE_C_COMPILER_ID STREQUAL "Clang" AND NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 7.0) OR
|
||||||
|
(CMAKE_C_COMPILER_ID STREQUAL "AppleClang" AND NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 10.3))
|
||||||
|
list(APPEND WPICKY_ENABLE
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
else() # gcc
|
||||||
|
list(APPEND WPICKY_DETECT
|
||||||
|
${WPICKY_COMMON}
|
||||||
|
)
|
||||||
|
# Enable based on compiler version
|
||||||
|
if(NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 4.3)
|
||||||
|
list(APPEND WPICKY_ENABLE
|
||||||
|
${WPICKY_COMMON_OLD}
|
||||||
|
-Wclobbered # gcc 4.3
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
#
|
||||||
|
|
||||||
|
unset(_wpicky)
|
||||||
|
|
||||||
|
foreach(_CCOPT IN LISTS WPICKY_ENABLE)
|
||||||
|
set(_wpicky "${_wpicky} ${_CCOPT}")
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
foreach(_CCOPT IN LISTS WPICKY_DETECT)
|
||||||
|
# surprisingly, CHECK_C_COMPILER_FLAG needs a new variable to store each new
|
||||||
|
# test result in.
|
||||||
|
string(MAKE_C_IDENTIFIER "OPT${_CCOPT}" _optvarname)
|
||||||
|
# GCC only warns about unknown -Wno- options if there are also other diagnostic messages,
|
||||||
|
# so test for the positive form instead
|
||||||
|
string(REPLACE "-Wno-" "-W" _CCOPT_ON "${_CCOPT}")
|
||||||
|
check_c_compiler_flag(${_CCOPT_ON} ${_optvarname})
|
||||||
|
if(${_optvarname})
|
||||||
|
set(_wpicky "${_wpicky} ${_CCOPT}")
|
||||||
|
endif()
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
set(WARNCFLAGS "${WARNCFLAGS} ${_wpicky}")
|
||||||
|
endif()
|
||||||
117
cmake/PickyWarningsCXX.cmake
Normal file
117
cmake/PickyWarningsCXX.cmake
Normal file
@@ -0,0 +1,117 @@
|
|||||||
|
# nghttp2
|
||||||
|
#
|
||||||
|
# Copyright (c) 2023 nghttp2 contributors
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
|
||||||
|
# C++
|
||||||
|
|
||||||
|
include(CheckCXXCompilerFlag)
|
||||||
|
|
||||||
|
if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||||
|
|
||||||
|
# https://clang.llvm.org/docs/DiagnosticsReference.html
|
||||||
|
# https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html
|
||||||
|
|
||||||
|
# WPICKY_ENABLE = Options we want to enable as-is.
|
||||||
|
# WPICKY_DETECT = Options we want to test first and enable if available.
|
||||||
|
|
||||||
|
set(WPICKY_ENABLE "-Wall")
|
||||||
|
|
||||||
|
# ----------------------------------
|
||||||
|
# Add new options here, if in doubt:
|
||||||
|
# ----------------------------------
|
||||||
|
set(WPICKY_DETECT
|
||||||
|
)
|
||||||
|
|
||||||
|
# Assume these options always exist with both clang and gcc.
|
||||||
|
# Require clang 3.0 / gcc 2.95 or later.
|
||||||
|
list(APPEND WPICKY_ENABLE
|
||||||
|
)
|
||||||
|
|
||||||
|
# Always enable with clang, version dependent with gcc
|
||||||
|
set(WPICKY_COMMON_OLD
|
||||||
|
-Wformat-security # clang 3.0 gcc 4.1
|
||||||
|
)
|
||||||
|
|
||||||
|
set(WPICKY_COMMON
|
||||||
|
)
|
||||||
|
|
||||||
|
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||||
|
list(APPEND WPICKY_ENABLE
|
||||||
|
${WPICKY_COMMON_OLD}
|
||||||
|
)
|
||||||
|
# Enable based on compiler version
|
||||||
|
if((CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 3.6) OR
|
||||||
|
(CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang" AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 6.3))
|
||||||
|
list(APPEND WPICKY_ENABLE
|
||||||
|
${WPICKY_COMMON}
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
if((CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 3.9) OR
|
||||||
|
(CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang" AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 8.3))
|
||||||
|
list(APPEND WPICKY_ENABLE
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
if((CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 5.0) OR
|
||||||
|
(CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang" AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 9.4))
|
||||||
|
list(APPEND WPICKY_ENABLE
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
if((CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 7.0) OR
|
||||||
|
(CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang" AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 10.3))
|
||||||
|
list(APPEND WPICKY_ENABLE
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
else() # gcc
|
||||||
|
list(APPEND WPICKY_DETECT
|
||||||
|
${WPICKY_COMMON}
|
||||||
|
)
|
||||||
|
# Enable based on compiler version
|
||||||
|
if(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.3)
|
||||||
|
list(APPEND WPICKY_ENABLE
|
||||||
|
${WPICKY_COMMON_OLD}
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
#
|
||||||
|
|
||||||
|
unset(_wpicky)
|
||||||
|
|
||||||
|
foreach(_CCOPT IN LISTS WPICKY_ENABLE)
|
||||||
|
set(_wpicky "${_wpicky} ${_CCOPT}")
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
foreach(_CCOPT IN LISTS WPICKY_DETECT)
|
||||||
|
# surprisingly, CHECK_CXX_COMPILER_FLAG needs a new variable to store each new
|
||||||
|
# test result in.
|
||||||
|
string(MAKE_C_IDENTIFIER "OPT${_CCOPT}" _optvarname)
|
||||||
|
# GCC only warns about unknown -Wno- options if there are also other diagnostic messages,
|
||||||
|
# so test for the positive form instead
|
||||||
|
string(REPLACE "-Wno-" "-W" _CCOPT_ON "${_CCOPT}")
|
||||||
|
check_cxx_compiler_flag(${_CCOPT_ON} ${_optvarname})
|
||||||
|
if(${_optvarname})
|
||||||
|
set(_wpicky "${_wpicky} ${_CCOPT}")
|
||||||
|
endif()
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
set(WARNCXXFLAGS "${WARNCXXFLAGS} ${_wpicky}")
|
||||||
|
endif()
|
||||||
@@ -19,12 +19,6 @@
|
|||||||
/* Define to 1 if you have `neverbleed` library. */
|
/* Define to 1 if you have `neverbleed` library. */
|
||||||
#cmakedefine HAVE_NEVERBLEED 1
|
#cmakedefine HAVE_NEVERBLEED 1
|
||||||
|
|
||||||
/* sizeof(int *) */
|
|
||||||
#cmakedefine SIZEOF_INT_P @SIZEOF_INT_P@
|
|
||||||
|
|
||||||
/* sizeof(time_t) */
|
|
||||||
#cmakedefine SIZEOF_TIME_T @SIZEOF_TIME_T@
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `_Exit` function. */
|
/* Define to 1 if you have the `_Exit` function. */
|
||||||
#cmakedefine HAVE__EXIT 1
|
#cmakedefine HAVE__EXIT 1
|
||||||
|
|
||||||
@@ -43,6 +37,9 @@
|
|||||||
/* Define to 1 if you have the `initgroups` function. */
|
/* Define to 1 if you have the `initgroups` function. */
|
||||||
#cmakedefine01 HAVE_DECL_INITGROUPS
|
#cmakedefine01 HAVE_DECL_INITGROUPS
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `CLOCK_MONOTONIC` defined. */
|
||||||
|
#cmakedefine01 HAVE_DECL_CLOCK_MONOTONIC
|
||||||
|
|
||||||
/* Define to 1 to enable debug output. */
|
/* Define to 1 to enable debug output. */
|
||||||
#cmakedefine DEBUGBUILD 1
|
#cmakedefine DEBUGBUILD 1
|
||||||
|
|
||||||
@@ -79,18 +76,15 @@
|
|||||||
/* Define to 1 if you have the <sys/time.h> header file. */
|
/* Define to 1 if you have the <sys/time.h> header file. */
|
||||||
#cmakedefine HAVE_SYS_TIME_H 1
|
#cmakedefine HAVE_SYS_TIME_H 1
|
||||||
|
|
||||||
/* Define to 1 if you have the <sysinfoapi.h> header file. */
|
|
||||||
#cmakedefine HAVE_SYSINFOAPI_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <syslog.h> header file. */
|
/* Define to 1 if you have the <syslog.h> header file. */
|
||||||
#cmakedefine HAVE_SYSLOG_H 1
|
#cmakedefine HAVE_SYSLOG_H 1
|
||||||
|
|
||||||
/* Define to 1 if you have the <time.h> header file. */
|
|
||||||
#cmakedefine HAVE_TIME_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <unistd.h> header file. */
|
/* Define to 1 if you have the <unistd.h> header file. */
|
||||||
#cmakedefine HAVE_UNISTD_H 1
|
#cmakedefine HAVE_UNISTD_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <windows.h> header file. */
|
||||||
|
#cmakedefine HAVE_WINDOWS_H 1
|
||||||
|
|
||||||
/* Define to 1 if HTTP/3 is enabled. */
|
/* Define to 1 if HTTP/3 is enabled. */
|
||||||
#cmakedefine ENABLE_HTTP3 1
|
#cmakedefine ENABLE_HTTP3 1
|
||||||
|
|
||||||
@@ -105,3 +99,6 @@
|
|||||||
|
|
||||||
/* Define to 1 if you have `libev` library. */
|
/* Define to 1 if you have `libev` library. */
|
||||||
#cmakedefine HAVE_LIBEV 1
|
#cmakedefine HAVE_LIBEV 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have `libbrotlienc` and `libbrotlidec` libraries. */
|
||||||
|
#cmakedefine HAVE_LIBBROTLI 1
|
||||||
|
|||||||
179
configure.ac
179
configure.ac
@@ -25,7 +25,7 @@ dnl Do not change user variables!
|
|||||||
dnl https://www.gnu.org/software/automake/manual/html_node/Flag-Variables-Ordering.html
|
dnl https://www.gnu.org/software/automake/manual/html_node/Flag-Variables-Ordering.html
|
||||||
|
|
||||||
AC_PREREQ(2.61)
|
AC_PREREQ(2.61)
|
||||||
AC_INIT([nghttp2], [1.57.0], [t-tujikawa@users.sourceforge.net])
|
AC_INIT([nghttp2], [1.62.1], [t-tujikawa@users.sourceforge.net])
|
||||||
AC_CONFIG_AUX_DIR([.])
|
AC_CONFIG_AUX_DIR([.])
|
||||||
AC_CONFIG_MACRO_DIR([m4])
|
AC_CONFIG_MACRO_DIR([m4])
|
||||||
AC_CONFIG_HEADERS([config.h])
|
AC_CONFIG_HEADERS([config.h])
|
||||||
@@ -38,15 +38,15 @@ AC_CANONICAL_BUILD
|
|||||||
AC_CANONICAL_HOST
|
AC_CANONICAL_HOST
|
||||||
AC_CANONICAL_TARGET
|
AC_CANONICAL_TARGET
|
||||||
|
|
||||||
AM_INIT_AUTOMAKE([subdir-objects])
|
AM_INIT_AUTOMAKE([subdir-objects tar-pax])
|
||||||
|
|
||||||
m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
|
m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
|
||||||
|
|
||||||
dnl See versioning rule:
|
dnl See versioning rule:
|
||||||
dnl https://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html
|
dnl https://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html
|
||||||
AC_SUBST(LT_CURRENT, 39)
|
AC_SUBST(LT_CURRENT, 42)
|
||||||
AC_SUBST(LT_REVISION, 0)
|
AC_SUBST(LT_REVISION, 1)
|
||||||
AC_SUBST(LT_AGE, 25)
|
AC_SUBST(LT_AGE, 28)
|
||||||
|
|
||||||
major=`echo $PACKAGE_VERSION |cut -d. -f1 | sed -e "s/[^0-9]//g"`
|
major=`echo $PACKAGE_VERSION |cut -d. -f1 | sed -e "s/[^0-9]//g"`
|
||||||
minor=`echo $PACKAGE_VERSION |cut -d. -f2 | sed -e "s/[^0-9]//g"`
|
minor=`echo $PACKAGE_VERSION |cut -d. -f2 | sed -e "s/[^0-9]//g"`
|
||||||
@@ -137,11 +137,6 @@ AC_ARG_WITH([libev],
|
|||||||
[Use libev [default=check]])],
|
[Use libev [default=check]])],
|
||||||
[request_libev=$withval], [request_libev=check])
|
[request_libev=$withval], [request_libev=check])
|
||||||
|
|
||||||
AC_ARG_WITH([cunit],
|
|
||||||
[AS_HELP_STRING([--with-cunit],
|
|
||||||
[Use cunit [default=check]])],
|
|
||||||
[request_cunit=$withval], [request_cunit=check])
|
|
||||||
|
|
||||||
AC_ARG_WITH([jemalloc],
|
AC_ARG_WITH([jemalloc],
|
||||||
[AS_HELP_STRING([--with-jemalloc],
|
[AS_HELP_STRING([--with-jemalloc],
|
||||||
[Use jemalloc [default=check]])],
|
[Use jemalloc [default=check]])],
|
||||||
@@ -177,6 +172,16 @@ AC_ARG_WITH([libbpf],
|
|||||||
[Use libbpf [default=no]])],
|
[Use libbpf [default=no]])],
|
||||||
[request_libbpf=$withval], [request_libbpf=no])
|
[request_libbpf=$withval], [request_libbpf=no])
|
||||||
|
|
||||||
|
AC_ARG_WITH([libbrotlienc],
|
||||||
|
[AS_HELP_STRING([--with-libbrotlienc],
|
||||||
|
[Use libbrotlienc [default=no]])],
|
||||||
|
[request_libbrotlienc=$withval], [request_libbrotlienc=no])
|
||||||
|
|
||||||
|
AC_ARG_WITH([libbrotlidec],
|
||||||
|
[AS_HELP_STRING([--with-libbrotlidec],
|
||||||
|
[Use libbrotlidec [default=no]])],
|
||||||
|
[request_libbrotlidec=$withval], [request_libbrotlidec=no])
|
||||||
|
|
||||||
dnl Define variables
|
dnl Define variables
|
||||||
AC_ARG_VAR([LIBEV_CFLAGS], [C compiler flags for libev, skipping any checks])
|
AC_ARG_VAR([LIBEV_CFLAGS], [C compiler flags for libev, skipping any checks])
|
||||||
AC_ARG_VAR([LIBEV_LIBS], [linker flags for libev, skipping any checks])
|
AC_ARG_VAR([LIBEV_LIBS], [linker flags for libev, skipping any checks])
|
||||||
@@ -233,7 +238,7 @@ fi
|
|||||||
save_CXXFLAGS="$CXXFLAGS"
|
save_CXXFLAGS="$CXXFLAGS"
|
||||||
CXXFLAGS=
|
CXXFLAGS=
|
||||||
|
|
||||||
AX_CXX_COMPILE_STDCXX([14], [noext], [optional])
|
AX_CXX_COMPILE_STDCXX([20], [], [optional])
|
||||||
|
|
||||||
CXX1XCXXFLAGS="$CXXFLAGS"
|
CXX1XCXXFLAGS="$CXXFLAGS"
|
||||||
CXXFLAGS="$save_CXXFLAGS"
|
CXXFLAGS="$save_CXXFLAGS"
|
||||||
@@ -278,21 +283,20 @@ std::map<int, int>().emplace(1, 2);
|
|||||||
[have_std_map_emplace=no
|
[have_std_map_emplace=no
|
||||||
AC_MSG_RESULT([no])])
|
AC_MSG_RESULT([no])])
|
||||||
|
|
||||||
# Check that std::atomic_* overloads for std::shared_ptr are
|
# Check that std::atomic<std::shared_ptr<T>> is supported.
|
||||||
# available.
|
AC_MSG_CHECKING([whether std::atomic<std::shared_ptr<T>> is supported])
|
||||||
AC_MSG_CHECKING([whether std::atomic_* overloads for std::shared_ptr are available])
|
|
||||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM(
|
AC_COMPILE_IFELSE([AC_LANG_PROGRAM(
|
||||||
[[
|
[[
|
||||||
#include <memory>
|
#include <memory>
|
||||||
]],
|
]],
|
||||||
[[
|
[[
|
||||||
auto a = std::make_shared<int>(1000000007);
|
auto a = std::atomic<std::shared_ptr<int>>(std::make_shared<int>(1000000007));
|
||||||
auto p = std::atomic_load(&a);
|
auto p = a.load();
|
||||||
++*p;
|
++*p;
|
||||||
std::atomic_store(&a, p);
|
a.store(p);
|
||||||
]])],
|
]])],
|
||||||
[AC_DEFINE([HAVE_ATOMIC_STD_SHARED_PTR], [1],
|
[AC_DEFINE([HAVE_ATOMIC_STD_SHARED_PTR], [1],
|
||||||
[Define to 1 if you have the std::atomic_* overloads for std::shared_ptr.])
|
[Define to 1 if you have the std::atomic<std::shared_ptr<T>> is supported.])
|
||||||
have_atomic_std_shared_ptr=yes
|
have_atomic_std_shared_ptr=yes
|
||||||
AC_MSG_RESULT([yes])],
|
AC_MSG_RESULT([yes])],
|
||||||
[have_atomic_std_shared_ptr=no
|
[have_atomic_std_shared_ptr=no
|
||||||
@@ -377,43 +381,6 @@ case "${host_os}" in
|
|||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
# cunit
|
|
||||||
have_cunit=no
|
|
||||||
if test "x${request_cunit}" != "xno"; then
|
|
||||||
PKG_CHECK_MODULES([CUNIT], [cunit >= 2.1], [have_cunit=yes], [have_cunit=no])
|
|
||||||
# If pkg-config does not find cunit, check it using AC_CHECK_LIB. We
|
|
||||||
# do this because Debian (Ubuntu) lacks pkg-config file for cunit.
|
|
||||||
if test "x${have_cunit}" = "xno"; then
|
|
||||||
AC_MSG_WARN([${CUNIT_PKG_ERRORS}])
|
|
||||||
AC_CHECK_LIB([cunit], [CU_initialize_registry],
|
|
||||||
[have_cunit=yes], [have_cunit=no])
|
|
||||||
if test "x${have_cunit}" = "xyes"; then
|
|
||||||
CUNIT_LIBS="-lcunit"
|
|
||||||
CUNIT_CFLAGS=""
|
|
||||||
AC_SUBST([CUNIT_LIBS])
|
|
||||||
AC_SUBST([CUNIT_CFLAGS])
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
if test "x${have_cunit}" = "xyes"; then
|
|
||||||
# cunit in Mac OS X requires ncurses. Note that in Mac OS X, test
|
|
||||||
# program can be built without -lncurses, but it emits runtime
|
|
||||||
# error.
|
|
||||||
case "${build}" in
|
|
||||||
*-apple-darwin*)
|
|
||||||
CUNIT_LIBS="$CUNIT_LIBS -lncurses"
|
|
||||||
AC_SUBST([CUNIT_LIBS])
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
if test "x${request_cunit}" = "xyes" &&
|
|
||||||
test "x${have_cunit}" != "xyes"; then
|
|
||||||
AC_MSG_ERROR([cunit was requested (--with-cunit) but not found])
|
|
||||||
fi
|
|
||||||
|
|
||||||
AM_CONDITIONAL([HAVE_CUNIT], [ test "x${have_cunit}" = "xyes" ])
|
|
||||||
|
|
||||||
# libev (for src)
|
# libev (for src)
|
||||||
have_libev=no
|
have_libev=no
|
||||||
if test "x${request_libev}" != "xno"; then
|
if test "x${request_libev}" != "xno"; then
|
||||||
@@ -447,27 +414,30 @@ fi
|
|||||||
# openssl (for src)
|
# openssl (for src)
|
||||||
have_openssl=no
|
have_openssl=no
|
||||||
if test "x${request_openssl}" != "xno"; then
|
if test "x${request_openssl}" != "xno"; then
|
||||||
PKG_CHECK_MODULES([OPENSSL], [openssl >= 1.0.1],
|
PKG_CHECK_MODULES([OPENSSL], [openssl >= 1.1.1],
|
||||||
[have_openssl=yes], [have_openssl=no])
|
[have_openssl=yes], [have_openssl=no])
|
||||||
if test "x${have_openssl}" = "xno"; then
|
if test "x${have_openssl}" = "xno"; then
|
||||||
AC_MSG_NOTICE($OPENSSL_PKG_ERRORS)
|
AC_MSG_NOTICE($OPENSSL_PKG_ERRORS)
|
||||||
else
|
else
|
||||||
save_CFLAGS="$CFLAGS"
|
# Use C++ compiler because boringssl needs C++ runtime.
|
||||||
|
AC_LANG_PUSH(C++)
|
||||||
|
|
||||||
|
save_CXXFLAGS="$CXXFLAGS"
|
||||||
save_LIBS="$LIBS"
|
save_LIBS="$LIBS"
|
||||||
CFLAGS="$OPENSSL_CFLAGS $CFLAGS"
|
CXXFLAGS="$OPENSSL_CFLAGS $CXXFLAGS"
|
||||||
LIBS="$OPENSSL_LIBS $LIBS"
|
LIBS="$OPENSSL_LIBS $LIBS"
|
||||||
|
|
||||||
# quictls/openssl has SSL_is_quic.
|
# quictls/openssl has SSL_provide_quic_data. boringssl also has
|
||||||
have_ssl_is_quic=no
|
# it. We will deal with it later.
|
||||||
AC_MSG_CHECKING([for SSL_is_quic])
|
have_ssl_provide_quic_data=no
|
||||||
|
AC_MSG_CHECKING([for SSL_provide_quic_data])
|
||||||
AC_LINK_IFELSE([AC_LANG_PROGRAM([[
|
AC_LINK_IFELSE([AC_LANG_PROGRAM([[
|
||||||
#include <openssl/ssl.h>
|
#include <openssl/ssl.h>
|
||||||
]], [[
|
]], [[
|
||||||
SSL *ssl = NULL;
|
SSL_provide_quic_data(NULL, (ssl_encryption_level_t)0, NULL, 0);
|
||||||
SSL_is_quic(ssl);
|
|
||||||
]])],
|
]])],
|
||||||
[AC_MSG_RESULT([yes]); have_ssl_is_quic=yes],
|
[AC_MSG_RESULT([yes]); have_ssl_provide_quic_data=yes],
|
||||||
[AC_MSG_RESULT([no]); have_ssl_is_quic=no])
|
[AC_MSG_RESULT([no]); have_ssl_provide_quic_data=no])
|
||||||
|
|
||||||
# boringssl has SSL_set_quic_early_data_context.
|
# boringssl has SSL_set_quic_early_data_context.
|
||||||
AC_MSG_CHECKING([for SSL_set_quic_early_data_context])
|
AC_MSG_CHECKING([for SSL_set_quic_early_data_context])
|
||||||
@@ -480,8 +450,10 @@ if test "x${request_openssl}" != "xno"; then
|
|||||||
[AC_MSG_RESULT([yes]); have_boringssl_quic=yes],
|
[AC_MSG_RESULT([yes]); have_boringssl_quic=yes],
|
||||||
[AC_MSG_RESULT([no]); have_boringssl_quic=no])
|
[AC_MSG_RESULT([no]); have_boringssl_quic=no])
|
||||||
|
|
||||||
CFLAGS="$save_CFLAGS"
|
CXXFLAGS="$save_CXXFLAGS"
|
||||||
LIBS="$save_LIBS"
|
LIBS="$save_LIBS"
|
||||||
|
|
||||||
|
AC_LANG_POP()
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -493,7 +465,7 @@ fi
|
|||||||
# c-ares (for src)
|
# c-ares (for src)
|
||||||
have_libcares=no
|
have_libcares=no
|
||||||
if test "x${request_libcares}" != "xno"; then
|
if test "x${request_libcares}" != "xno"; then
|
||||||
PKG_CHECK_MODULES([LIBCARES], [libcares >= 1.7.5], [have_libcares=yes],
|
PKG_CHECK_MODULES([LIBCARES], [libcares >= 1.16.0], [have_libcares=yes],
|
||||||
[have_libcares=no])
|
[have_libcares=no])
|
||||||
if test "x${have_libcares}" = "xno"; then
|
if test "x${have_libcares}" = "xno"; then
|
||||||
AC_MSG_NOTICE($LIBCARES_PKG_ERRORS)
|
AC_MSG_NOTICE($LIBCARES_PKG_ERRORS)
|
||||||
@@ -508,7 +480,7 @@ fi
|
|||||||
# ngtcp2 (for src)
|
# ngtcp2 (for src)
|
||||||
have_libngtcp2=no
|
have_libngtcp2=no
|
||||||
if test "x${request_libngtcp2}" != "xno"; then
|
if test "x${request_libngtcp2}" != "xno"; then
|
||||||
PKG_CHECK_MODULES([LIBNGTCP2], [libngtcp2 >= 0.19.0], [have_libngtcp2=yes],
|
PKG_CHECK_MODULES([LIBNGTCP2], [libngtcp2 >= 1.4.0], [have_libngtcp2=yes],
|
||||||
[have_libngtcp2=no])
|
[have_libngtcp2=no])
|
||||||
if test "x${have_libngtcp2}" = "xno"; then
|
if test "x${have_libngtcp2}" = "xno"; then
|
||||||
AC_MSG_NOTICE($LIBNGTCP2_PKG_ERRORS)
|
AC_MSG_NOTICE($LIBNGTCP2_PKG_ERRORS)
|
||||||
@@ -522,10 +494,11 @@ fi
|
|||||||
|
|
||||||
# ngtcp2_crypto_quictls (for src)
|
# ngtcp2_crypto_quictls (for src)
|
||||||
have_libngtcp2_crypto_quictls=no
|
have_libngtcp2_crypto_quictls=no
|
||||||
if test "x${have_ssl_is_quic}" = "xyes" &&
|
if test "x${have_ssl_provide_quic_data}" = "xyes" &&
|
||||||
|
test "x${have_boringssl_quic}" != "xyes" &&
|
||||||
test "x${request_libngtcp2}" != "xno"; then
|
test "x${request_libngtcp2}" != "xno"; then
|
||||||
PKG_CHECK_MODULES([LIBNGTCP2_CRYPTO_QUICTLS],
|
PKG_CHECK_MODULES([LIBNGTCP2_CRYPTO_QUICTLS],
|
||||||
[libngtcp2_crypto_quictls >= 0.19.0],
|
[libngtcp2_crypto_quictls >= 1.0.0],
|
||||||
[have_libngtcp2_crypto_quictls=yes],
|
[have_libngtcp2_crypto_quictls=yes],
|
||||||
[have_libngtcp2_crypto_quictls=no])
|
[have_libngtcp2_crypto_quictls=no])
|
||||||
if test "x${have_libngtcp2_crypto_quictls}" = "xno"; then
|
if test "x${have_libngtcp2_crypto_quictls}" = "xno"; then
|
||||||
@@ -536,7 +509,8 @@ if test "x${have_ssl_is_quic}" = "xyes" &&
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if test "x${have_ssl_is_quic}" = "xyes" &&
|
if test "x${have_ssl_provide_quic_data}" = "xyes" &&
|
||||||
|
test "x${have_boringssl_quic}" != "xyes" &&
|
||||||
test "x${request_libngtcp2}" = "xyes" &&
|
test "x${request_libngtcp2}" = "xyes" &&
|
||||||
test "x${have_libngtcp2_crypto_quictls}" != "xyes"; then
|
test "x${have_libngtcp2_crypto_quictls}" != "xyes"; then
|
||||||
AC_MSG_ERROR([libngtcp2_crypto_quictls was requested (--with-libngtcp2) but not found])
|
AC_MSG_ERROR([libngtcp2_crypto_quictls was requested (--with-libngtcp2) but not found])
|
||||||
@@ -567,7 +541,7 @@ fi
|
|||||||
# nghttp3 (for src)
|
# nghttp3 (for src)
|
||||||
have_libnghttp3=no
|
have_libnghttp3=no
|
||||||
if test "x${request_libnghttp3}" != "xno"; then
|
if test "x${request_libnghttp3}" != "xno"; then
|
||||||
PKG_CHECK_MODULES([LIBNGHTTP3], [libnghttp3 >= 0.15.0], [have_libnghttp3=yes],
|
PKG_CHECK_MODULES([LIBNGHTTP3], [libnghttp3 >= 1.1.0], [have_libnghttp3=yes],
|
||||||
[have_libnghttp3=no])
|
[have_libnghttp3=no])
|
||||||
if test "x${have_libnghttp3}" = "xno"; then
|
if test "x${have_libnghttp3}" = "xno"; then
|
||||||
AC_MSG_NOTICE($LIBNGHTTP3_PKG_ERRORS)
|
AC_MSG_NOTICE($LIBNGHTTP3_PKG_ERRORS)
|
||||||
@@ -624,6 +598,47 @@ fi
|
|||||||
|
|
||||||
AM_CONDITIONAL([HAVE_LIBBPF], [ test "x${have_libbpf}" = "xyes" ])
|
AM_CONDITIONAL([HAVE_LIBBPF], [ test "x${have_libbpf}" = "xyes" ])
|
||||||
|
|
||||||
|
# libbrotlienc (for src)
|
||||||
|
have_libbrotlienc=no
|
||||||
|
if test "x${request_libbrotlienc}" != "xno"; then
|
||||||
|
PKG_CHECK_MODULES([LIBBROTLIENC], [libbrotlienc >= 1.0.9],
|
||||||
|
[have_libbrotlienc=yes],
|
||||||
|
[have_libbrotlienc=no])
|
||||||
|
if test "x${have_libbrotlienc}" = "xno"; then
|
||||||
|
AC_MSG_NOTICE($LIBBROTLIENC_PKG_ERRORS)
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test "x${request_libbrotlienc}" = "xyes" &&
|
||||||
|
test "x${have_libbrotlienc}" != "xyes"; then
|
||||||
|
AC_MSG_ERROR([libbrotlienc was requested (--with-libbrotlienc) but not found])
|
||||||
|
fi
|
||||||
|
|
||||||
|
# libbrotlidec (for src)
|
||||||
|
have_libbrotlidec=no
|
||||||
|
if test "x${request_libbrotlidec}" != "xno"; then
|
||||||
|
PKG_CHECK_MODULES([LIBBROTLIDEC], [libbrotlidec >= 1.0.9],
|
||||||
|
[have_libbrotlidec=yes],
|
||||||
|
[have_libbrotlidec=no])
|
||||||
|
if test "x${have_libbrotlidec}" = "xno"; then
|
||||||
|
AC_MSG_NOTICE($LIBBROTLIDEC_PKG_ERRORS)
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test "x${request_libbrotlidec}" = "xyes" &&
|
||||||
|
test "x${have_libbrotlidec}" != "xyes"; then
|
||||||
|
AC_MSG_ERROR([libbrotlidec was requested (--with-libbrotlidec) but not found])
|
||||||
|
fi
|
||||||
|
|
||||||
|
have_libbrotli=no
|
||||||
|
if test "x${have_libbrotlienc}" = "xyes" &&
|
||||||
|
test "x${have_libbrotlidec}" = "xyes"; then
|
||||||
|
have_libbrotli=yes
|
||||||
|
|
||||||
|
AC_DEFINE([HAVE_LIBBROTLI], [1],
|
||||||
|
[Define to 1 if you have `libbrotlienc` and `libbrotlidec` libraries.])
|
||||||
|
fi
|
||||||
|
|
||||||
# libevent_openssl (for examples)
|
# libevent_openssl (for examples)
|
||||||
# 2.0.8 is required because we use evconnlistener_set_error_cb()
|
# 2.0.8 is required because we use evconnlistener_set_error_cb()
|
||||||
have_libevent_openssl=no
|
have_libevent_openssl=no
|
||||||
@@ -752,8 +767,6 @@ AM_CONDITIONAL([ENABLE_APP], [ test "x${enable_app}" = "xyes" ])
|
|||||||
# Check HTTP/3 support
|
# Check HTTP/3 support
|
||||||
enable_http3=no
|
enable_http3=no
|
||||||
if test "x${request_http3}" != "xno" &&
|
if test "x${request_http3}" != "xno" &&
|
||||||
(test "x${have_ssl_is_quic}" = "xyes" ||
|
|
||||||
test "x${have_boringssl_quic}" = "xyes") &&
|
|
||||||
test "x${have_libngtcp2}" = "xyes" &&
|
test "x${have_libngtcp2}" = "xyes" &&
|
||||||
(test "x${have_libngtcp2_crypto_quictls}" = "xyes" ||
|
(test "x${have_libngtcp2_crypto_quictls}" = "xyes" ||
|
||||||
test "x${have_libngtcp2_crypto_boringssl}" = "xyes") &&
|
test "x${have_libngtcp2_crypto_boringssl}" = "xyes") &&
|
||||||
@@ -855,10 +868,9 @@ AC_CHECK_HEADERS([ \
|
|||||||
string.h \
|
string.h \
|
||||||
sys/socket.h \
|
sys/socket.h \
|
||||||
sys/time.h \
|
sys/time.h \
|
||||||
sysinfoapi.h \
|
|
||||||
syslog.h \
|
syslog.h \
|
||||||
time.h \
|
|
||||||
unistd.h \
|
unistd.h \
|
||||||
|
windows.h \
|
||||||
])
|
])
|
||||||
|
|
||||||
# Checks for typedefs, structures, and compiler characteristics.
|
# Checks for typedefs, structures, and compiler characteristics.
|
||||||
@@ -908,12 +920,6 @@ if test "x$have_struct_tm_tm_gmtoff" = "xyes"; then
|
|||||||
[Define to 1 if you have `struct tm.tm_gmtoff` member.])
|
[Define to 1 if you have `struct tm.tm_gmtoff` member.])
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Check size of pointer to decide we need 8 bytes alignment
|
|
||||||
# adjustment.
|
|
||||||
AC_CHECK_SIZEOF([int *])
|
|
||||||
|
|
||||||
AC_CHECK_SIZEOF([time_t])
|
|
||||||
|
|
||||||
# Checks for library functions.
|
# Checks for library functions.
|
||||||
|
|
||||||
# Don't check malloc, since it does not play nicely with C++ stdlib
|
# Don't check malloc, since it does not play nicely with C++ stdlib
|
||||||
@@ -959,7 +965,7 @@ AC_CHECK_FUNC([timerfd_create],
|
|||||||
AC_MSG_CHECKING([checking for GetTickCount64])
|
AC_MSG_CHECKING([checking for GetTickCount64])
|
||||||
AC_LINK_IFELSE([AC_LANG_PROGRAM(
|
AC_LINK_IFELSE([AC_LANG_PROGRAM(
|
||||||
[[
|
[[
|
||||||
#include <sysinfoapi.h>
|
#include <windows.h>
|
||||||
]],
|
]],
|
||||||
[[
|
[[
|
||||||
GetTickCount64();
|
GetTickCount64();
|
||||||
@@ -985,6 +991,10 @@ AC_CHECK_DECLS([initgroups], [], [], [[
|
|||||||
#include <grp.h>
|
#include <grp.h>
|
||||||
]])
|
]])
|
||||||
|
|
||||||
|
AC_CHECK_DECLS([CLOCK_MONOTONIC], [], [], [[
|
||||||
|
#include <time.h>
|
||||||
|
]])
|
||||||
|
|
||||||
save_CFLAGS=$CFLAGS
|
save_CFLAGS=$CFLAGS
|
||||||
save_CXXFLAGS=$CXXFLAGS
|
save_CXXFLAGS=$CXXFLAGS
|
||||||
|
|
||||||
@@ -1158,7 +1168,6 @@ AC_MSG_NOTICE([summary of build options:
|
|||||||
Python: ${PYTHON}
|
Python: ${PYTHON}
|
||||||
PYTHON_VERSION: ${PYTHON_VERSION}
|
PYTHON_VERSION: ${PYTHON_VERSION}
|
||||||
Test:
|
Test:
|
||||||
CUnit: ${have_cunit} (CFLAGS='${CUNIT_CFLAGS}' LIBS='${CUNIT_LIBS}')
|
|
||||||
Failmalloc: ${enable_failmalloc}
|
Failmalloc: ${enable_failmalloc}
|
||||||
Libs:
|
Libs:
|
||||||
OpenSSL: ${have_openssl} (CFLAGS='${OPENSSL_CFLAGS}' LIBS='${OPENSSL_LIBS}')
|
OpenSSL: ${have_openssl} (CFLAGS='${OPENSSL_CFLAGS}' LIBS='${OPENSSL_LIBS}')
|
||||||
@@ -1175,6 +1184,8 @@ AC_MSG_NOTICE([summary of build options:
|
|||||||
Jemalloc: ${have_jemalloc} (CFLAGS='${JEMALLOC_CFLAGS}' LIBS='${JEMALLOC_LIBS}')
|
Jemalloc: ${have_jemalloc} (CFLAGS='${JEMALLOC_CFLAGS}' LIBS='${JEMALLOC_LIBS}')
|
||||||
Zlib: ${have_zlib} (CFLAGS='${ZLIB_CFLAGS}' LIBS='${ZLIB_LIBS}')
|
Zlib: ${have_zlib} (CFLAGS='${ZLIB_CFLAGS}' LIBS='${ZLIB_LIBS}')
|
||||||
Systemd: ${have_libsystemd} (CFLAGS='${SYSTEMD_CFLAGS}' LIBS='${SYSTEMD_LIBS}')
|
Systemd: ${have_libsystemd} (CFLAGS='${SYSTEMD_CFLAGS}' LIBS='${SYSTEMD_LIBS}')
|
||||||
|
Libbrotlienc: ${have_libbrotlienc} (CFLAGS="${LIBBROTLIENC_CFLAGS}' LIBS='${LIBBROTLIENC_LIBS}')
|
||||||
|
Libbrotlidec: ${have_libbrotlidec} (CFLAGS="${LIBBROTLIDEC_CFLAGS}' LIBS='${LIBBROTLIDEC_LIBS}')
|
||||||
Third-party:
|
Third-party:
|
||||||
http-parser: ${enable_third_party}
|
http-parser: ${enable_third_party}
|
||||||
MRuby: ${have_mruby} (CFLAGS='${LIBMRUBY_CFLAGS}' LIBS='${LIBMRUBY_LIBS}')
|
MRuby: ${have_mruby} (CFLAGS='${LIBMRUBY_CFLAGS}' LIBS='${LIBMRUBY_LIBS}')
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ APIDOCS= \
|
|||||||
nghttp2_check_header_value_rfc9113.rst \
|
nghttp2_check_header_value_rfc9113.rst \
|
||||||
nghttp2_check_method.rst \
|
nghttp2_check_method.rst \
|
||||||
nghttp2_check_path.rst \
|
nghttp2_check_path.rst \
|
||||||
|
nghttp2_extpri_parse_priority.rst \
|
||||||
nghttp2_hd_deflate_bound.rst \
|
nghttp2_hd_deflate_bound.rst \
|
||||||
nghttp2_hd_deflate_change_table_size.rst \
|
nghttp2_hd_deflate_change_table_size.rst \
|
||||||
nghttp2_hd_deflate_del.rst \
|
nghttp2_hd_deflate_del.rst \
|
||||||
@@ -41,7 +42,9 @@ APIDOCS= \
|
|||||||
nghttp2_hd_deflate_get_num_table_entries.rst \
|
nghttp2_hd_deflate_get_num_table_entries.rst \
|
||||||
nghttp2_hd_deflate_get_table_entry.rst \
|
nghttp2_hd_deflate_get_table_entry.rst \
|
||||||
nghttp2_hd_deflate_hd.rst \
|
nghttp2_hd_deflate_hd.rst \
|
||||||
|
nghttp2_hd_deflate_hd2.rst \
|
||||||
nghttp2_hd_deflate_hd_vec.rst \
|
nghttp2_hd_deflate_hd_vec.rst \
|
||||||
|
nghttp2_hd_deflate_hd_vec2.rst \
|
||||||
nghttp2_hd_deflate_new.rst \
|
nghttp2_hd_deflate_new.rst \
|
||||||
nghttp2_hd_deflate_new2.rst \
|
nghttp2_hd_deflate_new2.rst \
|
||||||
nghttp2_hd_inflate_change_table_size.rst \
|
nghttp2_hd_inflate_change_table_size.rst \
|
||||||
@@ -53,6 +56,7 @@ APIDOCS= \
|
|||||||
nghttp2_hd_inflate_get_table_entry.rst \
|
nghttp2_hd_inflate_get_table_entry.rst \
|
||||||
nghttp2_hd_inflate_hd.rst \
|
nghttp2_hd_inflate_hd.rst \
|
||||||
nghttp2_hd_inflate_hd2.rst \
|
nghttp2_hd_inflate_hd2.rst \
|
||||||
|
nghttp2_hd_inflate_hd3.rst \
|
||||||
nghttp2_hd_inflate_new.rst \
|
nghttp2_hd_inflate_new.rst \
|
||||||
nghttp2_hd_inflate_new2.rst \
|
nghttp2_hd_inflate_new2.rst \
|
||||||
nghttp2_http2_strerror.rst \
|
nghttp2_http2_strerror.rst \
|
||||||
@@ -73,10 +77,12 @@ APIDOCS= \
|
|||||||
nghttp2_option_set_peer_max_concurrent_streams.rst \
|
nghttp2_option_set_peer_max_concurrent_streams.rst \
|
||||||
nghttp2_option_set_server_fallback_rfc7540_priorities.rst \
|
nghttp2_option_set_server_fallback_rfc7540_priorities.rst \
|
||||||
nghttp2_option_set_user_recv_extension_type.rst \
|
nghttp2_option_set_user_recv_extension_type.rst \
|
||||||
|
nghttp2_option_set_max_continuations.rst \
|
||||||
nghttp2_option_set_max_outbound_ack.rst \
|
nghttp2_option_set_max_outbound_ack.rst \
|
||||||
nghttp2_option_set_max_settings.rst \
|
nghttp2_option_set_max_settings.rst \
|
||||||
nghttp2_option_set_stream_reset_rate_limit.rst \
|
nghttp2_option_set_stream_reset_rate_limit.rst \
|
||||||
nghttp2_pack_settings_payload.rst \
|
nghttp2_pack_settings_payload.rst \
|
||||||
|
nghttp2_pack_settings_payload2.rst \
|
||||||
nghttp2_priority_spec_check_default.rst \
|
nghttp2_priority_spec_check_default.rst \
|
||||||
nghttp2_priority_spec_default_init.rst \
|
nghttp2_priority_spec_default_init.rst \
|
||||||
nghttp2_priority_spec_init.rst \
|
nghttp2_priority_spec_init.rst \
|
||||||
@@ -85,10 +91,12 @@ APIDOCS= \
|
|||||||
nghttp2_rcbuf_incref.rst \
|
nghttp2_rcbuf_incref.rst \
|
||||||
nghttp2_rcbuf_is_static.rst \
|
nghttp2_rcbuf_is_static.rst \
|
||||||
nghttp2_select_next_protocol.rst \
|
nghttp2_select_next_protocol.rst \
|
||||||
|
nghttp2_select_alpn.rst \
|
||||||
nghttp2_session_callbacks_del.rst \
|
nghttp2_session_callbacks_del.rst \
|
||||||
nghttp2_session_callbacks_new.rst \
|
nghttp2_session_callbacks_new.rst \
|
||||||
nghttp2_session_callbacks_set_before_frame_send_callback.rst \
|
nghttp2_session_callbacks_set_before_frame_send_callback.rst \
|
||||||
nghttp2_session_callbacks_set_data_source_read_length_callback.rst \
|
nghttp2_session_callbacks_set_data_source_read_length_callback.rst \
|
||||||
|
nghttp2_session_callbacks_set_data_source_read_length_callback2.rst \
|
||||||
nghttp2_session_callbacks_set_error_callback.rst \
|
nghttp2_session_callbacks_set_error_callback.rst \
|
||||||
nghttp2_session_callbacks_set_error_callback2.rst \
|
nghttp2_session_callbacks_set_error_callback2.rst \
|
||||||
nghttp2_session_callbacks_set_on_begin_frame_callback.rst \
|
nghttp2_session_callbacks_set_on_begin_frame_callback.rst \
|
||||||
@@ -105,9 +113,13 @@ APIDOCS= \
|
|||||||
nghttp2_session_callbacks_set_on_invalid_header_callback2.rst \
|
nghttp2_session_callbacks_set_on_invalid_header_callback2.rst \
|
||||||
nghttp2_session_callbacks_set_on_stream_close_callback.rst \
|
nghttp2_session_callbacks_set_on_stream_close_callback.rst \
|
||||||
nghttp2_session_callbacks_set_pack_extension_callback.rst \
|
nghttp2_session_callbacks_set_pack_extension_callback.rst \
|
||||||
|
nghttp2_session_callbacks_set_pack_extension_callback2.rst \
|
||||||
nghttp2_session_callbacks_set_recv_callback.rst \
|
nghttp2_session_callbacks_set_recv_callback.rst \
|
||||||
|
nghttp2_session_callbacks_set_recv_callback2.rst \
|
||||||
nghttp2_session_callbacks_set_select_padding_callback.rst \
|
nghttp2_session_callbacks_set_select_padding_callback.rst \
|
||||||
|
nghttp2_session_callbacks_set_select_padding_callback2.rst \
|
||||||
nghttp2_session_callbacks_set_send_callback.rst \
|
nghttp2_session_callbacks_set_send_callback.rst \
|
||||||
|
nghttp2_session_callbacks_set_send_callback2.rst \
|
||||||
nghttp2_session_callbacks_set_send_data_callback.rst \
|
nghttp2_session_callbacks_set_send_data_callback.rst \
|
||||||
nghttp2_session_callbacks_set_unpack_extension_callback.rst \
|
nghttp2_session_callbacks_set_unpack_extension_callback.rst \
|
||||||
nghttp2_session_change_extpri_stream_priority.rst \
|
nghttp2_session_change_extpri_stream_priority.rst \
|
||||||
@@ -125,6 +137,7 @@ APIDOCS= \
|
|||||||
nghttp2_session_find_stream.rst \
|
nghttp2_session_find_stream.rst \
|
||||||
nghttp2_session_get_effective_local_window_size.rst \
|
nghttp2_session_get_effective_local_window_size.rst \
|
||||||
nghttp2_session_get_effective_recv_data_length.rst \
|
nghttp2_session_get_effective_recv_data_length.rst \
|
||||||
|
nghttp2_session_get_extpri_stream_priority.rst \
|
||||||
nghttp2_session_get_hd_deflate_dynamic_table_size.rst \
|
nghttp2_session_get_hd_deflate_dynamic_table_size.rst \
|
||||||
nghttp2_session_get_hd_inflate_dynamic_table_size.rst \
|
nghttp2_session_get_hd_inflate_dynamic_table_size.rst \
|
||||||
nghttp2_session_get_last_proc_stream_id.rst \
|
nghttp2_session_get_last_proc_stream_id.rst \
|
||||||
@@ -143,7 +156,9 @@ APIDOCS= \
|
|||||||
nghttp2_session_get_stream_remote_window_size.rst \
|
nghttp2_session_get_stream_remote_window_size.rst \
|
||||||
nghttp2_session_get_stream_user_data.rst \
|
nghttp2_session_get_stream_user_data.rst \
|
||||||
nghttp2_session_mem_recv.rst \
|
nghttp2_session_mem_recv.rst \
|
||||||
|
nghttp2_session_mem_recv2.rst \
|
||||||
nghttp2_session_mem_send.rst \
|
nghttp2_session_mem_send.rst \
|
||||||
|
nghttp2_session_mem_send2.rst \
|
||||||
nghttp2_session_recv.rst \
|
nghttp2_session_recv.rst \
|
||||||
nghttp2_session_resume_data.rst \
|
nghttp2_session_resume_data.rst \
|
||||||
nghttp2_session_send.rst \
|
nghttp2_session_send.rst \
|
||||||
@@ -171,6 +186,7 @@ APIDOCS= \
|
|||||||
nghttp2_strerror.rst \
|
nghttp2_strerror.rst \
|
||||||
nghttp2_submit_altsvc.rst \
|
nghttp2_submit_altsvc.rst \
|
||||||
nghttp2_submit_data.rst \
|
nghttp2_submit_data.rst \
|
||||||
|
nghttp2_submit_data2.rst \
|
||||||
nghttp2_submit_extension.rst \
|
nghttp2_submit_extension.rst \
|
||||||
nghttp2_submit_goaway.rst \
|
nghttp2_submit_goaway.rst \
|
||||||
nghttp2_submit_headers.rst \
|
nghttp2_submit_headers.rst \
|
||||||
@@ -180,7 +196,9 @@ APIDOCS= \
|
|||||||
nghttp2_submit_priority_update.rst \
|
nghttp2_submit_priority_update.rst \
|
||||||
nghttp2_submit_push_promise.rst \
|
nghttp2_submit_push_promise.rst \
|
||||||
nghttp2_submit_request.rst \
|
nghttp2_submit_request.rst \
|
||||||
|
nghttp2_submit_request2.rst \
|
||||||
nghttp2_submit_response.rst \
|
nghttp2_submit_response.rst \
|
||||||
|
nghttp2_submit_response2.rst \
|
||||||
nghttp2_submit_rst_stream.rst \
|
nghttp2_submit_rst_stream.rst \
|
||||||
nghttp2_submit_settings.rst \
|
nghttp2_submit_settings.rst \
|
||||||
nghttp2_submit_shutdown_notice.rst \
|
nghttp2_submit_shutdown_notice.rst \
|
||||||
@@ -209,7 +227,6 @@ EXTRA_DIST = \
|
|||||||
sources/h2load-howto.rst \
|
sources/h2load-howto.rst \
|
||||||
sources/building-android-binary.rst \
|
sources/building-android-binary.rst \
|
||||||
sources/contribute.rst \
|
sources/contribute.rst \
|
||||||
sources/security.rst \
|
|
||||||
_exts/rubydomain/LICENSE.rubydomain \
|
_exts/rubydomain/LICENSE.rubydomain \
|
||||||
_exts/rubydomain/__init__.py \
|
_exts/rubydomain/__init__.py \
|
||||||
_exts/rubydomain/rubydomain.py \
|
_exts/rubydomain/rubydomain.py \
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ The example follows::
|
|||||||
* Callback function invoked when |session| wants to send data to
|
* Callback function invoked when |session| wants to send data to
|
||||||
* remote peer.
|
* remote peer.
|
||||||
*/
|
*/
|
||||||
typedef ssize_t (*nghttp2_send_callback)
|
typedef nghttp2_ssize (*nghttp2_send_callback2)
|
||||||
(nghttp2_session *session,
|
(nghttp2_session *session,
|
||||||
const uint8_t *data, size_t length, int flags, void *user_data);
|
const uint8_t *data, size_t length, int flags, void *user_data);
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ _h2load()
|
|||||||
_get_comp_words_by_ref cur prev
|
_get_comp_words_by_ref cur prev
|
||||||
case $cur in
|
case $cur in
|
||||||
-*)
|
-*)
|
||||||
COMPREPLY=( $( compgen -W '--requests --clients --threads --input-file --max-concurrent-streams --max-frame-size --window-bits --connection-window-bits --header --ciphers --tls13-ciphers --no-tls-proto --data --rate --rate-period --duration --warm-up-time --connection-active-timeout --connection-inactivity-timeout --timing-script-file --base-uri --npn-list --h1 --header-table-size --encoder-header-table-size --log-file --qlog-file-base --connect-to --rps --groups --no-udp-gso --max-udp-payload-size --ktls --verbose --version --help ' -- "$cur" ) )
|
COMPREPLY=( $( compgen -W '--requests --clients --threads --input-file --max-concurrent-streams --max-frame-size --window-bits --connection-window-bits --header --ciphers --tls13-ciphers --no-tls-proto --data --rate --rate-period --duration --warm-up-time --connection-active-timeout --connection-inactivity-timeout --timing-script-file --base-uri --alpn-list --h1 --header-table-size --encoder-header-table-size --log-file --qlog-file-base --connect-to --rps --groups --no-udp-gso --max-udp-payload-size --ktls --sni --verbose --version --help ' -- "$cur" ) )
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
_filedir
|
_filedir
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ _nghttpx()
|
|||||||
_get_comp_words_by_ref cur prev
|
_get_comp_words_by_ref cur prev
|
||||||
case $cur in
|
case $cur in
|
||||||
-*)
|
-*)
|
||||||
COMPREPLY=( $( compgen -W '--backend --frontend --backlog --backend-address-family --backend-http-proxy-uri --workers --single-thread --read-rate --read-burst --write-rate --write-burst --worker-read-rate --worker-read-burst --worker-write-rate --worker-write-burst --worker-frontend-connections --backend-connections-per-host --backend-connections-per-frontend --rlimit-nofile --rlimit-memlock --backend-request-buffer --backend-response-buffer --fastopen --no-kqueue --frontend-http2-read-timeout --frontend-http3-read-timeout --frontend-read-timeout --frontend-write-timeout --frontend-keep-alive-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 --npn-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 --ecdh-curves --insecure --cacert --private-key-passwd-file --subcert --dh-param-file --alpn-list --verify-client --verify-client-cacert --verify-client-tolerate-expired --client-private-key-file --client-cert-file --tls-min-proto-version --tls-max-proto-version --tls-ticket-key-file --tls-ticket-key-memcached --tls-ticket-key-memcached-address-family --tls-ticket-key-memcached-interval --tls-ticket-key-memcached-max-retry --tls-ticket-key-memcached-max-fail --tls-ticket-key-cipher --tls-ticket-key-memcached-cert-file --tls-ticket-key-memcached-private-key-file --fetch-ocsp-response-file --ocsp-update-interval --ocsp-startup --no-verify-ocsp --no-ocsp --tls-session-cache-memcached --tls-session-cache-memcached-address-family --tls-session-cache-memcached-cert-file --tls-session-cache-memcached-private-key-file --tls-dyn-rec-warmup-threshold --tls-dyn-rec-idle-timeout --no-http2-cipher-block-list --client-no-http2-cipher-block-list --tls-sct-dir --psk-secrets --client-psk-secrets --tls-no-postpone-early-data --tls-max-early-data --tls-ktls --frontend-http2-max-concurrent-streams --backend-http2-max-concurrent-streams --frontend-http2-window-size --frontend-http2-connection-window-size --backend-http2-window-size --backend-http2-connection-window-size --http2-no-cookie-crumbling --padding --no-server-push --frontend-http2-optimize-write-buffer-size --frontend-http2-optimize-window-size --frontend-http2-encoder-dynamic-table-size --frontend-http2-decoder-dynamic-table-size --backend-http2-encoder-dynamic-table-size --backend-http2-decoder-dynamic-table-size --http2-proxy --log-level --accesslog-file --accesslog-syslog --accesslog-format --accesslog-write-early --errorlog-file --errorlog-syslog --syslog-facility --add-x-forwarded-for --strip-incoming-x-forwarded-for --no-add-x-forwarded-proto --no-strip-incoming-x-forwarded-proto --add-forwarded --strip-incoming-forwarded --forwarded-by --forwarded-for --no-via --no-strip-incoming-early-data --no-location-rewrite --host-rewrite --altsvc --http2-altsvc --add-request-header --add-response-header --request-header-field-buffer --max-request-header-fields --response-header-field-buffer --max-response-header-fields --error-page --server-name --no-server-rewrite --redirect-https-port --require-http-scheme --api-max-request-body --dns-cache-timeout --dns-lookup-timeout --dns-max-try --frontend-max-requests --frontend-http2-dump-request-header --frontend-http2-dump-response-header --frontend-frame-debug --daemon --pid-file --user --single-process --max-worker-processes --worker-process-grace-shutdown-period --mruby-file --ignore-per-pattern-mruby-error --frontend-quic-idle-timeout --frontend-quic-debug-log --quic-bpf-program-file --frontend-quic-early-data --frontend-quic-qlog-dir --frontend-quic-require-token --frontend-quic-congestion-controller --frontend-quic-secret-file --quic-server-id --frontend-quic-initial-rtt --no-quic-bpf --frontend-http3-window-size --frontend-http3-connection-window-size --frontend-http3-max-window-size --frontend-http3-max-connection-window-size --frontend-http3-max-concurrent-streams --conf --include --version --help ' -- "$cur" ) )
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
_filedir
|
_filedir
|
||||||
|
|||||||
19
doc/h2load.1
19
doc/h2load.1
@@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
|||||||
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
||||||
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
|
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
|
||||||
..
|
..
|
||||||
.TH "H2LOAD" "1" "Oct 10, 2023" "1.57.0" "nghttp2"
|
.TH "H2LOAD" "1" "May 19, 2024" "1.62.1" "nghttp2"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
h2load \- HTTP/2 benchmarking tool
|
h2load \- HTTP/2 benchmarking tool
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
@@ -255,20 +255,19 @@ input files as usual.
|
|||||||
.UNINDENT
|
.UNINDENT
|
||||||
.INDENT 0.0
|
.INDENT 0.0
|
||||||
.TP
|
.TP
|
||||||
.B \-\-npn\-list=<LIST>
|
.B \-\-alpn\-list=<LIST>
|
||||||
Comma delimited list of ALPN protocol identifier sorted
|
Comma delimited list of ALPN protocol identifier sorted
|
||||||
in the order of preference. That means most desirable
|
in the order of preference. That means most desirable
|
||||||
protocol comes first. This is used in both ALPN and
|
protocol comes first. The parameter must be delimited
|
||||||
NPN. The parameter must be delimited by a single comma
|
by a single comma only and any white spaces are treated
|
||||||
only and any white spaces are treated as a part of
|
as a part of protocol string.
|
||||||
protocol string.
|
|
||||||
.sp
|
.sp
|
||||||
Default: \fBh2,h2\-16,h2\-14,http/1.1\fP
|
Default: \fBh2,h2\-16,h2\-14,http/1.1\fP
|
||||||
.UNINDENT
|
.UNINDENT
|
||||||
.INDENT 0.0
|
.INDENT 0.0
|
||||||
.TP
|
.TP
|
||||||
.B \-\-h1
|
.B \-\-h1
|
||||||
Short hand for \fI\%\-\-npn\-list\fP=http/1.1
|
Short hand for \fI\%\-\-alpn\-list\fP=http/1.1
|
||||||
\fI\%\-\-no\-tls\-proto\fP=http/1.1, which effectively force
|
\fI\%\-\-no\-tls\-proto\fP=http/1.1, which effectively force
|
||||||
http/1.1 for both http and https URI.
|
http/1.1 for both http and https URI.
|
||||||
.UNINDENT
|
.UNINDENT
|
||||||
@@ -345,6 +344,12 @@ Enable ktls.
|
|||||||
.UNINDENT
|
.UNINDENT
|
||||||
.INDENT 0.0
|
.INDENT 0.0
|
||||||
.TP
|
.TP
|
||||||
|
.B \-\-sni=<DNSNAME>
|
||||||
|
Send <DNSNAME> in TLS SNI, overriding the host name
|
||||||
|
specified in URI.
|
||||||
|
.UNINDENT
|
||||||
|
.INDENT 0.0
|
||||||
|
.TP
|
||||||
.B \-v, \-\-verbose
|
.B \-v, \-\-verbose
|
||||||
Output debug information.
|
Output debug information.
|
||||||
.UNINDENT
|
.UNINDENT
|
||||||
|
|||||||
@@ -213,20 +213,19 @@ OPTIONS
|
|||||||
the first URI appeared in the command line or inside
|
the first URI appeared in the command line or inside
|
||||||
input files as usual.
|
input files as usual.
|
||||||
|
|
||||||
.. option:: --npn-list=<LIST>
|
.. option:: --alpn-list=<LIST>
|
||||||
|
|
||||||
Comma delimited list of ALPN protocol identifier sorted
|
Comma delimited list of ALPN protocol identifier sorted
|
||||||
in the order of preference. That means most desirable
|
in the order of preference. That means most desirable
|
||||||
protocol comes first. This is used in both ALPN and
|
protocol comes first. The parameter must be delimited
|
||||||
NPN. The parameter must be delimited by a single comma
|
by a single comma only and any white spaces are treated
|
||||||
only and any white spaces are treated as a part of
|
as a part of protocol string.
|
||||||
protocol string.
|
|
||||||
|
|
||||||
Default: ``h2,h2-16,h2-14,http/1.1``
|
Default: ``h2,h2-16,h2-14,http/1.1``
|
||||||
|
|
||||||
.. option:: --h1
|
.. option:: --h1
|
||||||
|
|
||||||
Short hand for :option:`--npn-list`\=http/1.1
|
Short hand for :option:`--alpn-list`\=http/1.1
|
||||||
:option:`--no-tls-proto`\=http/1.1, which effectively force
|
:option:`--no-tls-proto`\=http/1.1, which effectively force
|
||||||
http/1.1 for both http and https URI.
|
http/1.1 for both http and https URI.
|
||||||
|
|
||||||
@@ -291,6 +290,11 @@ OPTIONS
|
|||||||
|
|
||||||
Enable ktls.
|
Enable ktls.
|
||||||
|
|
||||||
|
.. option:: --sni=<DNSNAME>
|
||||||
|
|
||||||
|
Send <DNSNAME> in TLS SNI, overriding the host name
|
||||||
|
specified in URI.
|
||||||
|
|
||||||
.. option:: -v, --verbose
|
.. option:: -v, --verbose
|
||||||
|
|
||||||
Output debug information.
|
Output debug information.
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
|||||||
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
||||||
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
|
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
|
||||||
..
|
..
|
||||||
.TH "NGHTTP" "1" "Oct 10, 2023" "1.57.0" "nghttp2"
|
.TH "NGHTTP" "1" "May 19, 2024" "1.62.1" "nghttp2"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
nghttp \- HTTP/2 client
|
nghttp \- HTTP/2 client
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
|||||||
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
||||||
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
|
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
|
||||||
..
|
..
|
||||||
.TH "NGHTTPD" "1" "Oct 10, 2023" "1.57.0" "nghttp2"
|
.TH "NGHTTPD" "1" "May 19, 2024" "1.62.1" "nghttp2"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
nghttpd \- HTTP/2 server
|
nghttpd \- HTTP/2 server
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
|||||||
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
||||||
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
|
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
|
||||||
..
|
..
|
||||||
.TH "NGHTTPX" "1" "Oct 10, 2023" "1.57.0" "nghttp2"
|
.TH "NGHTTPX" "1" "May 19, 2024" "1.62.1" "nghttp2"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
nghttpx \- HTTP/2 proxy
|
nghttpx \- HTTP/2 proxy
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
@@ -371,7 +371,7 @@ Default: \fBauto\fP
|
|||||||
.TP
|
.TP
|
||||||
.B \-\-backend\-http\-proxy\-uri=<URI>
|
.B \-\-backend\-http\-proxy\-uri=<URI>
|
||||||
Specify proxy URI in the form
|
Specify proxy URI in the form
|
||||||
\fI\%http:/\fP/[<USER>:<PASS>@]<PROXY>:<PORT>. If a proxy
|
\X'tty: link http:/'\fI\%http:/\fP\X'tty: link'/[<USER>:<PASS>@]<PROXY>:<PORT>. If a proxy
|
||||||
requires authentication, specify <USER> and <PASS>.
|
requires authentication, specify <USER> and <PASS>.
|
||||||
Note that they must be properly percent\-encoded. This
|
Note that they must be properly percent\-encoded. This
|
||||||
proxy is used when the backend connection is HTTP/2.
|
proxy is used when the backend connection is HTTP/2.
|
||||||
@@ -555,27 +555,24 @@ this option will be simply ignored.
|
|||||||
.SS Timeout
|
.SS Timeout
|
||||||
.INDENT 0.0
|
.INDENT 0.0
|
||||||
.TP
|
.TP
|
||||||
.B \-\-frontend\-http2\-read\-timeout=<DURATION>
|
.B \-\-frontend\-http2\-idle\-timeout=<DURATION>
|
||||||
Specify read timeout for HTTP/2 frontend connection.
|
Specify idle timeout for HTTP/2 frontend connection. If
|
||||||
|
no active streams exist for this duration, connection is
|
||||||
|
closed.
|
||||||
.sp
|
.sp
|
||||||
Default: \fB3m\fP
|
Default: \fB3m\fP
|
||||||
.UNINDENT
|
.UNINDENT
|
||||||
.INDENT 0.0
|
.INDENT 0.0
|
||||||
.TP
|
.TP
|
||||||
.B \-\-frontend\-http3\-read\-timeout=<DURATION>
|
.B \-\-frontend\-http3\-idle\-timeout=<DURATION>
|
||||||
Specify read timeout for HTTP/3 frontend connection.
|
Specify idle timeout for HTTP/3 frontend connection. If
|
||||||
|
no active streams exist for this duration, connection is
|
||||||
|
closed.
|
||||||
.sp
|
.sp
|
||||||
Default: \fB3m\fP
|
Default: \fB3m\fP
|
||||||
.UNINDENT
|
.UNINDENT
|
||||||
.INDENT 0.0
|
.INDENT 0.0
|
||||||
.TP
|
.TP
|
||||||
.B \-\-frontend\-read\-timeout=<DURATION>
|
|
||||||
Specify read timeout for HTTP/1.1 frontend connection.
|
|
||||||
.sp
|
|
||||||
Default: \fB1m\fP
|
|
||||||
.UNINDENT
|
|
||||||
.INDENT 0.0
|
|
||||||
.TP
|
|
||||||
.B \-\-frontend\-write\-timeout=<DURATION>
|
.B \-\-frontend\-write\-timeout=<DURATION>
|
||||||
Specify write timeout for all frontend connections.
|
Specify write timeout for all frontend connections.
|
||||||
.sp
|
.sp
|
||||||
@@ -591,6 +588,17 @@ Default: \fB1m\fP
|
|||||||
.UNINDENT
|
.UNINDENT
|
||||||
.INDENT 0.0
|
.INDENT 0.0
|
||||||
.TP
|
.TP
|
||||||
|
.B \-\-frontend\-header\-timeout=<DURATION>
|
||||||
|
Specify duration that the server waits for an HTTP
|
||||||
|
request header fields to be received completely. On
|
||||||
|
timeout, HTTP/1 and HTTP/2 connections are closed. For
|
||||||
|
HTTP/3, the stream is shutdown, and the connection
|
||||||
|
itself is left intact.
|
||||||
|
.sp
|
||||||
|
Default: \fB1m\fP
|
||||||
|
.UNINDENT
|
||||||
|
.INDENT 0.0
|
||||||
|
.TP
|
||||||
.B \-\-stream\-read\-timeout=<DURATION>
|
.B \-\-stream\-read\-timeout=<DURATION>
|
||||||
Specify read timeout for HTTP/2 streams. 0 means no
|
Specify read timeout for HTTP/2 streams. 0 means no
|
||||||
timeout.
|
timeout.
|
||||||
@@ -783,13 +791,12 @@ available.
|
|||||||
.UNINDENT
|
.UNINDENT
|
||||||
.INDENT 0.0
|
.INDENT 0.0
|
||||||
.TP
|
.TP
|
||||||
.B \-\-npn\-list=<LIST>
|
.B \-\-alpn\-list=<LIST>
|
||||||
Comma delimited list of ALPN protocol identifier sorted
|
Comma delimited list of ALPN protocol identifier sorted
|
||||||
in the order of preference. That means most desirable
|
in the order of preference. That means most desirable
|
||||||
protocol comes first. This is used in both ALPN and
|
protocol comes first. The parameter must be delimited
|
||||||
NPN. The parameter must be delimited by a single comma
|
by a single comma only and any white spaces are treated
|
||||||
only and any white spaces are treated as a part of
|
as a part of protocol string.
|
||||||
protocol string.
|
|
||||||
.sp
|
.sp
|
||||||
Default: \fBh2,h2\-16,h2\-14,http/1.1\fP
|
Default: \fBh2,h2\-16,h2\-14,http/1.1\fP
|
||||||
.UNINDENT
|
.UNINDENT
|
||||||
@@ -1050,7 +1057,7 @@ Default: \fB1s\fP
|
|||||||
.B \-\-no\-http2\-cipher\-block\-list
|
.B \-\-no\-http2\-cipher\-block\-list
|
||||||
Allow block listed cipher suite on frontend HTTP/2
|
Allow block listed cipher suite on frontend HTTP/2
|
||||||
connection. See
|
connection. See
|
||||||
\fI\%https://tools.ietf.org/html/rfc7540#appendix\-A\fP for the
|
\X'tty: link https://tools.ietf.org/html/rfc7540#appendix-A'\fI\%https://tools.ietf.org/html/rfc7540#appendix\-A\fP\X'tty: link' for the
|
||||||
complete HTTP/2 cipher suites block list.
|
complete HTTP/2 cipher suites block list.
|
||||||
.UNINDENT
|
.UNINDENT
|
||||||
.INDENT 0.0
|
.INDENT 0.0
|
||||||
@@ -1058,7 +1065,7 @@ complete HTTP/2 cipher suites block list.
|
|||||||
.B \-\-client\-no\-http2\-cipher\-block\-list
|
.B \-\-client\-no\-http2\-cipher\-block\-list
|
||||||
Allow block listed cipher suite on backend HTTP/2
|
Allow block listed cipher suite on backend HTTP/2
|
||||||
connection. See
|
connection. See
|
||||||
\fI\%https://tools.ietf.org/html/rfc7540#appendix\-A\fP for the
|
\X'tty: link https://tools.ietf.org/html/rfc7540#appendix-A'\fI\%https://tools.ietf.org/html/rfc7540#appendix\-A\fP\X'tty: link' for the
|
||||||
complete HTTP/2 cipher suites block list.
|
complete HTTP/2 cipher suites block list.
|
||||||
.UNINDENT
|
.UNINDENT
|
||||||
.INDENT 0.0
|
.INDENT 0.0
|
||||||
@@ -1834,8 +1841,8 @@ NEW_TOKEN frame in the previous connection.
|
|||||||
.TP
|
.TP
|
||||||
.B \-\-frontend\-quic\-congestion\-controller=<CC>
|
.B \-\-frontend\-quic\-congestion\-controller=<CC>
|
||||||
Specify a congestion controller algorithm for a frontend
|
Specify a congestion controller algorithm for a frontend
|
||||||
QUIC connection. <CC> should be one of \(dqcubic\(dq, \(dqbbr\(dq,
|
QUIC connection. <CC> should be either \(dqcubic\(dq or
|
||||||
and \(dqbbrv2\(dq.
|
\(dqbbr\(dq.
|
||||||
.sp
|
.sp
|
||||||
Default: \fBcubic\fP
|
Default: \fBcubic\fP
|
||||||
.UNINDENT
|
.UNINDENT
|
||||||
@@ -1847,12 +1854,12 @@ as QUIC keying materials. It is used to derive keys for
|
|||||||
encrypting tokens and Connection IDs. It is not used to
|
encrypting tokens and Connection IDs. It is not used to
|
||||||
encrypt QUIC packets. Each line of this file must
|
encrypt QUIC packets. Each line of this file must
|
||||||
contain exactly 136 bytes hex\-encoded string (when
|
contain exactly 136 bytes hex\-encoded string (when
|
||||||
decoded the byte string is 68 bytes long). The first 2
|
decoded the byte string is 68 bytes long). The first 3
|
||||||
bits of decoded byte string are used to identify the
|
bits of decoded byte string are used to identify the
|
||||||
keying material. An empty line or a line which starts
|
keying material. An empty line or a line which starts
|
||||||
\(aq#\(aq is ignored. The file can contain more than one
|
\(aq#\(aq is ignored. The file can contain more than one
|
||||||
keying materials. Because the identifier is 2 bits, at
|
keying materials. Because the identifier is 3 bits, at
|
||||||
most 4 keying materials are read and the remaining data
|
most 8 keying materials are read and the remaining data
|
||||||
is discarded. The first keying material in the file is
|
is discarded. The first keying material in the file is
|
||||||
primarily used for encryption and decryption for new
|
primarily used for encryption and decryption for new
|
||||||
connection. The other ones are used to decrypt data for
|
connection. The other ones are used to decrypt data for
|
||||||
@@ -2109,9 +2116,9 @@ than main process.
|
|||||||
.SH SERVER PUSH
|
.SH SERVER PUSH
|
||||||
.sp
|
.sp
|
||||||
nghttpx supports HTTP/2 server push in default mode with Link header
|
nghttpx supports HTTP/2 server push in default mode with Link header
|
||||||
field. nghttpx looks for Link header field (\fI\%RFC 5988\fP) in response headers from
|
field. nghttpx looks for Link header field (\X'tty: link http://tools.ietf.org/html/rfc5988'\fI\%RFC 5988\fP\X'tty: link') in response headers from
|
||||||
backend server and extracts URI\-reference with parameter
|
backend server and extracts URI\-reference with parameter
|
||||||
\fBrel=preload\fP (see \fI\%preload\fP)
|
\fBrel=preload\fP (see \X'tty: link http://w3c.github.io/preload/#interoperability-with-http-link-header'\fI\%preload\fP\X'tty: link')
|
||||||
and pushes those URIs to the frontend client. Here is a sample Link
|
and pushes those URIs to the frontend client. Here is a sample Link
|
||||||
header field to initiate server push:
|
header field to initiate server push:
|
||||||
.INDENT 0.0
|
.INDENT 0.0
|
||||||
@@ -2157,7 +2164,7 @@ delete the socket and continues to use it.
|
|||||||
.sp
|
.sp
|
||||||
OCSP query is done using external Python script
|
OCSP query is done using external Python script
|
||||||
\fBfetch\-ocsp\-response\fP, which has been originally developed in Perl
|
\fBfetch\-ocsp\-response\fP, which has been originally developed in Perl
|
||||||
as part of h2o project (\fI\%https://github.com/h2o/h2o\fP), and was
|
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.
|
translated into Python.
|
||||||
.sp
|
.sp
|
||||||
The script file is usually installed under
|
The script file is usually installed under
|
||||||
@@ -2253,15 +2260,15 @@ automatically. To rotate key, one has to restart nghttpx (see
|
|||||||
SIGNALS).
|
SIGNALS).
|
||||||
.SH CERTIFICATE TRANSPARENCY
|
.SH CERTIFICATE TRANSPARENCY
|
||||||
.sp
|
.sp
|
||||||
nghttpx supports TLS \fBsigned_certificate_timestamp\fP extension (\fI\%RFC
|
nghttpx supports TLS \fBsigned_certificate_timestamp\fP extension (\X'tty: link https://tools.ietf.org/html/rfc6962'\fI\%RFC
|
||||||
6962\fP). The relevant options
|
6962\fP\X'tty: link'). The relevant options
|
||||||
are \fI\%\-\-tls\-sct\-dir\fP and \fBsct\-dir\fP parameter in
|
are \fI\%\-\-tls\-sct\-dir\fP and \fBsct\-dir\fP parameter in
|
||||||
\fI\%\-\-subcert\fP\&. They takes a directory, and nghttpx reads all
|
\fI\%\-\-subcert\fP\&. They takes a directory, and nghttpx reads all
|
||||||
files whose extension is \fB\&.sct\fP under the directory. The \fB*.sct\fP
|
files whose extension is \fB\&.sct\fP under the directory. The \fB*.sct\fP
|
||||||
files are encoded as \fBSignedCertificateTimestamp\fP struct described
|
files are encoded as \fBSignedCertificateTimestamp\fP struct described
|
||||||
in \fI\%section 3.2 of RFC 69662\fP\&. This format is
|
in \X'tty: link https://tools.ietf.org/html/rfc6962#section-3.2'\fI\%section 3.2 of RFC 69662\fP\X'tty: link'\&. This format is
|
||||||
the same one used by \fI\%nginx\-ct\fP and \fI\%mod_ssl_ct\fP\&.
|
the same one used by \X'tty: link https://github.com/grahamedgecombe/nginx-ct'\fI\%nginx\-ct\fP\X'tty: link' and \X'tty: link https://httpd.apache.org/docs/trunk/mod/mod_ssl_ct.html'\fI\%mod_ssl_ct\fP\X'tty: link'\&.
|
||||||
\fI\%ct\-submit\fP can be
|
\X'tty: link https://github.com/grahamedgecombe/ct-submit'\fI\%ct\-submit\fP\X'tty: link' can be
|
||||||
used to submit certificates to log servers, and obtain the
|
used to submit certificates to log servers, and obtain the
|
||||||
\fBSignedCertificateTimestamp\fP struct which can be used with nghttpx.
|
\fBSignedCertificateTimestamp\fP struct which can be used with nghttpx.
|
||||||
.SH MRUBY SCRIPTING
|
.SH MRUBY SCRIPTING
|
||||||
@@ -2505,7 +2512,7 @@ On assignment, copy of given value is assigned. The path does
|
|||||||
not include authority component of URI. This may include
|
not include authority component of URI. This may include
|
||||||
query component. nghttpx makes certain normalization for
|
query component. nghttpx makes certain normalization for
|
||||||
path. It decodes percent\-encoding for unreserved characters
|
path. It decodes percent\-encoding for unreserved characters
|
||||||
(see \fI\%https://tools.ietf.org/html/rfc3986#section\-2.3\fP), and
|
(see \X'tty: link https://tools.ietf.org/html/rfc3986#section-2.3'\fI\%https://tools.ietf.org/html/rfc3986#section\-2.3\fP\X'tty: link'), and
|
||||||
resolves \(dq..\(dq and \(dq.\(dq. But it may leave characters which
|
resolves \(dq..\(dq and \(dq.\(dq. But it may leave characters which
|
||||||
should be percent\-encoded as is. So be careful when comparing
|
should be percent\-encoded as is. So be careful when comparing
|
||||||
path against desired string.
|
path against desired string.
|
||||||
|
|||||||
@@ -522,24 +522,22 @@ Performance
|
|||||||
Timeout
|
Timeout
|
||||||
~~~~~~~
|
~~~~~~~
|
||||||
|
|
||||||
.. option:: --frontend-http2-read-timeout=<DURATION>
|
.. option:: --frontend-http2-idle-timeout=<DURATION>
|
||||||
|
|
||||||
Specify read timeout for HTTP/2 frontend connection.
|
Specify idle timeout for HTTP/2 frontend connection. If
|
||||||
|
no active streams exist for this duration, connection is
|
||||||
|
closed.
|
||||||
|
|
||||||
Default: ``3m``
|
Default: ``3m``
|
||||||
|
|
||||||
.. option:: --frontend-http3-read-timeout=<DURATION>
|
.. option:: --frontend-http3-idle-timeout=<DURATION>
|
||||||
|
|
||||||
Specify read timeout for HTTP/3 frontend connection.
|
Specify idle timeout for HTTP/3 frontend connection. If
|
||||||
|
no active streams exist for this duration, connection is
|
||||||
|
closed.
|
||||||
|
|
||||||
Default: ``3m``
|
Default: ``3m``
|
||||||
|
|
||||||
.. option:: --frontend-read-timeout=<DURATION>
|
|
||||||
|
|
||||||
Specify read timeout for HTTP/1.1 frontend connection.
|
|
||||||
|
|
||||||
Default: ``1m``
|
|
||||||
|
|
||||||
.. option:: --frontend-write-timeout=<DURATION>
|
.. option:: --frontend-write-timeout=<DURATION>
|
||||||
|
|
||||||
Specify write timeout for all frontend connections.
|
Specify write timeout for all frontend connections.
|
||||||
@@ -553,6 +551,16 @@ Timeout
|
|||||||
|
|
||||||
Default: ``1m``
|
Default: ``1m``
|
||||||
|
|
||||||
|
.. option:: --frontend-header-timeout=<DURATION>
|
||||||
|
|
||||||
|
Specify duration that the server waits for an HTTP
|
||||||
|
request header fields to be received completely. On
|
||||||
|
timeout, HTTP/1 and HTTP/2 connections are closed. For
|
||||||
|
HTTP/3, the stream is shutdown, and the connection
|
||||||
|
itself is left intact.
|
||||||
|
|
||||||
|
Default: ``1m``
|
||||||
|
|
||||||
.. option:: --stream-read-timeout=<DURATION>
|
.. option:: --stream-read-timeout=<DURATION>
|
||||||
|
|
||||||
Specify read timeout for HTTP/2 streams. 0 means no
|
Specify read timeout for HTTP/2 streams. 0 means no
|
||||||
@@ -728,14 +736,13 @@ SSL/TLS
|
|||||||
Without this option, DHE cipher suites are not
|
Without this option, DHE cipher suites are not
|
||||||
available.
|
available.
|
||||||
|
|
||||||
.. option:: --npn-list=<LIST>
|
.. option:: --alpn-list=<LIST>
|
||||||
|
|
||||||
Comma delimited list of ALPN protocol identifier sorted
|
Comma delimited list of ALPN protocol identifier sorted
|
||||||
in the order of preference. That means most desirable
|
in the order of preference. That means most desirable
|
||||||
protocol comes first. This is used in both ALPN and
|
protocol comes first. The parameter must be delimited
|
||||||
NPN. The parameter must be delimited by a single comma
|
by a single comma only and any white spaces are treated
|
||||||
only and any white spaces are treated as a part of
|
as a part of protocol string.
|
||||||
protocol string.
|
|
||||||
|
|
||||||
Default: ``h2,h2-16,h2-14,http/1.1``
|
Default: ``h2,h2-16,h2-14,http/1.1``
|
||||||
|
|
||||||
@@ -1675,8 +1682,8 @@ HTTP/3 and QUIC
|
|||||||
.. option:: --frontend-quic-congestion-controller=<CC>
|
.. option:: --frontend-quic-congestion-controller=<CC>
|
||||||
|
|
||||||
Specify a congestion controller algorithm for a frontend
|
Specify a congestion controller algorithm for a frontend
|
||||||
QUIC connection. <CC> should be one of "cubic", "bbr",
|
QUIC connection. <CC> should be either "cubic" or
|
||||||
and "bbrv2".
|
"bbr".
|
||||||
|
|
||||||
Default: ``cubic``
|
Default: ``cubic``
|
||||||
|
|
||||||
@@ -1687,12 +1694,12 @@ HTTP/3 and QUIC
|
|||||||
encrypting tokens and Connection IDs. It is not used to
|
encrypting tokens and Connection IDs. It is not used to
|
||||||
encrypt QUIC packets. Each line of this file must
|
encrypt QUIC packets. Each line of this file must
|
||||||
contain exactly 136 bytes hex-encoded string (when
|
contain exactly 136 bytes hex-encoded string (when
|
||||||
decoded the byte string is 68 bytes long). The first 2
|
decoded the byte string is 68 bytes long). The first 3
|
||||||
bits of decoded byte string are used to identify the
|
bits of decoded byte string are used to identify the
|
||||||
keying material. An empty line or a line which starts
|
keying material. An empty line or a line which starts
|
||||||
'#' is ignored. The file can contain more than one
|
'#' is ignored. The file can contain more than one
|
||||||
keying materials. Because the identifier is 2 bits, at
|
keying materials. Because the identifier is 3 bits, at
|
||||||
most 4 keying materials are read and the remaining data
|
most 8 keying materials are read and the remaining data
|
||||||
is discarded. The first keying material in the file is
|
is discarded. The first keying material in the file is
|
||||||
primarily used for encryption and decryption for new
|
primarily used for encryption and decryption for new
|
||||||
connection. The other ones are used to decrypt data for
|
connection. The other ones are used to decrypt data for
|
||||||
|
|||||||
@@ -40,28 +40,28 @@ most event-based architecture applications use is single thread per
|
|||||||
core, and handling one connection I/O is done by single thread.
|
core, and handling one connection I/O is done by single thread.
|
||||||
|
|
||||||
To feed input to :type:`nghttp2_session` object, one can use
|
To feed input to :type:`nghttp2_session` object, one can use
|
||||||
`nghttp2_session_recv()` or `nghttp2_session_mem_recv()` functions.
|
`nghttp2_session_recv()` or `nghttp2_session_mem_recv2()` functions.
|
||||||
They behave similarly, and the difference is that
|
They behave similarly, and the difference is that
|
||||||
`nghttp2_session_recv()` will use :type:`nghttp2_read_callback` to get
|
`nghttp2_session_recv()` will use :type:`nghttp2_read_callback` to get
|
||||||
input. On the other hand, `nghttp2_session_mem_recv()` will take
|
input. On the other hand, `nghttp2_session_mem_recv2()` will take
|
||||||
input as its parameter. If in doubt, use `nghttp2_session_mem_recv()`
|
input as its parameter. If in doubt, use
|
||||||
since it is simpler, and could be faster since it avoids calling
|
`nghttp2_session_mem_recv2()` since it is simpler, and could be faster
|
||||||
callback function.
|
since it avoids calling callback function.
|
||||||
|
|
||||||
To get output from :type:`nghttp2_session` object, one can use
|
To get output from :type:`nghttp2_session` object, one can use
|
||||||
`nghttp2_session_send()` or `nghttp2_session_mem_send()`. The
|
`nghttp2_session_send()` or `nghttp2_session_mem_send2()`. The
|
||||||
difference between them is that the former uses
|
difference between them is that the former uses
|
||||||
:type:`nghttp2_send_callback` to pass output to an application. On
|
:type:`nghttp2_send_callback` to pass output to an application. On
|
||||||
the other hand, the latter returns the output to the caller. If in
|
the other hand, the latter returns the output to the caller. If in
|
||||||
doubt, use `nghttp2_session_mem_send()` since it is simpler. But
|
doubt, use `nghttp2_session_mem_send2()` since it is simpler. But
|
||||||
`nghttp2_session_send()` might be easier to use if the output buffer
|
`nghttp2_session_send()` might be easier to use if the output buffer
|
||||||
an application has is fixed sized.
|
an application has is fixed sized.
|
||||||
|
|
||||||
In general, an application should call `nghttp2_session_mem_send()`
|
In general, an application should call `nghttp2_session_mem_send2()`
|
||||||
when it gets input from underlying connection. Since there is great
|
when it gets input from underlying connection. Since there is great
|
||||||
chance to get something pushed into transmission queue while the call
|
chance to get something pushed into transmission queue while the call
|
||||||
of `nghttp2_session_mem_send()`, it is recommended to call
|
of `nghttp2_session_mem_send2()`, it is recommended to call
|
||||||
`nghttp2_session_mem_recv()` after `nghttp2_session_mem_send()`.
|
`nghttp2_session_mem_recv2()` after `nghttp2_session_mem_send2()`.
|
||||||
|
|
||||||
There is a question when we are safe to close HTTP/2 session without
|
There is a question when we are safe to close HTTP/2 session without
|
||||||
waiting for the closure of underlying connection. We offer 2 API
|
waiting for the closure of underlying connection. We offer 2 API
|
||||||
@@ -70,7 +70,7 @@ calls for this: `nghttp2_session_want_read()` and
|
|||||||
can destroy :type:`nghttp2_session`, and then close the underlying
|
can destroy :type:`nghttp2_session`, and then close the underlying
|
||||||
connection. But make sure that the buffered output has been
|
connection. But make sure that the buffered output has been
|
||||||
transmitted to the peer before closing the connection when
|
transmitted to the peer before closing the connection when
|
||||||
`nghttp2_session_mem_send()` is used, since
|
`nghttp2_session_mem_send2()` is used, since
|
||||||
`nghttp2_session_want_write()` does not take into account the
|
`nghttp2_session_want_write()` does not take into account the
|
||||||
transmission of the buffered data outside of :type:`nghttp2_session`.
|
transmission of the buffered data outside of :type:`nghttp2_session`.
|
||||||
|
|
||||||
@@ -87,18 +87,18 @@ The header files are also available online: :doc:`nghttp2.h` and
|
|||||||
Remarks
|
Remarks
|
||||||
-------
|
-------
|
||||||
|
|
||||||
Do not call `nghttp2_session_send()`, `nghttp2_session_mem_send()`,
|
Do not call `nghttp2_session_send()`, `nghttp2_session_mem_send2()`,
|
||||||
`nghttp2_session_recv()` or `nghttp2_session_mem_recv()` from the
|
`nghttp2_session_recv()` or `nghttp2_session_mem_recv2()` from the
|
||||||
nghttp2 callback functions directly or indirectly. It will lead to the
|
nghttp2 callback functions directly or indirectly. It will lead to the
|
||||||
crash. You can submit requests or frames in the callbacks then call
|
crash. You can submit requests or frames in the callbacks then call
|
||||||
these functions outside the callbacks.
|
these functions outside the callbacks.
|
||||||
|
|
||||||
`nghttp2_session_send()` and `nghttp2_session_mem_send()` send first
|
`nghttp2_session_send()` and `nghttp2_session_mem_send2()` send first
|
||||||
24 bytes of client magic string (MAGIC)
|
24 bytes of client magic string (MAGIC)
|
||||||
(:macro:`NGHTTP2_CLIENT_MAGIC`) on client configuration. The
|
(:macro:`NGHTTP2_CLIENT_MAGIC`) on client configuration. The
|
||||||
applications are responsible to send SETTINGS frame as part of
|
applications are responsible to send SETTINGS frame as part of
|
||||||
connection preface using `nghttp2_submit_settings()`. Similarly,
|
connection preface using `nghttp2_submit_settings()`. Similarly,
|
||||||
`nghttp2_session_recv()` and `nghttp2_session_mem_recv()` consume
|
`nghttp2_session_recv()` and `nghttp2_session_mem_recv2()` consume
|
||||||
MAGIC on server configuration unless
|
MAGIC on server configuration unless
|
||||||
`nghttp2_option_set_no_recv_client_magic()` is used with nonzero
|
`nghttp2_option_set_no_recv_client_magic()` is used with nonzero
|
||||||
option value.
|
option value.
|
||||||
@@ -222,7 +222,7 @@ above, the following code does not work:
|
|||||||
|
|
||||||
.. code-block:: c
|
.. code-block:: c
|
||||||
|
|
||||||
nghttp2_submit_response(...)
|
nghttp2_submit_response2(...)
|
||||||
nghttp2_submit_rst_stream(...)
|
nghttp2_submit_rst_stream(...)
|
||||||
|
|
||||||
RST_STREAM cancels HEADERS (and DATA), and just RST_STREAM is sent.
|
RST_STREAM cancels HEADERS (and DATA), and just RST_STREAM is sent.
|
||||||
@@ -258,7 +258,7 @@ For example, we will illustrate how to send `ALTSVC
|
|||||||
const char *field;
|
const char *field;
|
||||||
} alt_svc;
|
} alt_svc;
|
||||||
|
|
||||||
ssize_t pack_extension_callback(nghttp2_session *session, uint8_t *buf,
|
nghttp2_ssize pack_extension_callback(nghttp2_session *session, uint8_t *buf,
|
||||||
size_t len, const nghttp2_frame *frame,
|
size_t len, const nghttp2_frame *frame,
|
||||||
void *user_data) {
|
void *user_data) {
|
||||||
const alt_svc *altsvc = (const alt_svc *)frame->ext.payload;
|
const alt_svc *altsvc = (const alt_svc *)frame->ext.payload;
|
||||||
@@ -497,8 +497,8 @@ order to receive and process PRIORITY_UPDATE frame, server has to call
|
|||||||
NGHTTP2_PRIORITY_UPDATE)`` (see the above section), and pass the
|
NGHTTP2_PRIORITY_UPDATE)`` (see the above section), and pass the
|
||||||
option to `nghttp2_session_server_new2()` or
|
option to `nghttp2_session_server_new2()` or
|
||||||
`nghttp2_session_server_new3()` to create a server session. Client
|
`nghttp2_session_server_new3()` to create a server session. Client
|
||||||
can send Priority header field via `nghttp2_submit_request()`. It can
|
can send Priority header field via `nghttp2_submit_request2()`. It
|
||||||
also send PRIORITY_UPDATE frame via
|
can also send PRIORITY_UPDATE frame via
|
||||||
`nghttp2_submit_priority_update()`. Server processes Priority header
|
`nghttp2_submit_priority_update()`. Server processes Priority header
|
||||||
field in a request header field and updates the stream priority unless
|
field in a request header field and updates the stream priority unless
|
||||||
HTTP messaging rule enforcement is disabled (see
|
HTTP messaging rule enforcement is disabled (see
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
.. include:: ../doc/sources/security.rst
|
|
||||||
@@ -26,7 +26,7 @@ Coding style
|
|||||||
We use clang-format to format source code consistently. The
|
We use clang-format to format source code consistently. The
|
||||||
clang-format configuration file .clang-format is located at the root
|
clang-format configuration file .clang-format is located at the root
|
||||||
directory. Since clang-format produces slightly different results
|
directory. Since clang-format produces slightly different results
|
||||||
between versions, we currently use clang-format-14.
|
between versions, we currently use clang-format-15.
|
||||||
|
|
||||||
To detect any violation to the coding style, we recommend to setup git
|
To detect any violation to the coding style, we recommend to setup git
|
||||||
pre-commit hook to check coding style of the changes you introduced.
|
pre-commit hook to check coding style of the changes you introduced.
|
||||||
|
|||||||
@@ -30,8 +30,8 @@ In order to set benchmark settings, specify following 3 options.
|
|||||||
:option:`-m`
|
:option:`-m`
|
||||||
The max concurrent streams to issue per client. Default: 1
|
The max concurrent streams to issue per client. Default: 1
|
||||||
|
|
||||||
For SSL/TLS connection, the protocol will be negotiated via ALPN/NPN.
|
For SSL/TLS connection, the protocol will be negotiated via ALPN. You
|
||||||
You can set specific protocols in :option:`--npn-list` option. For
|
can set specific protocols in :option:`--alpn-list` option. For
|
||||||
cleartext connection, the default protocol is HTTP/2. To change the
|
cleartext connection, the default protocol is HTTP/2. To change the
|
||||||
protocol in cleartext connection, use :option:`--no-tls-proto` option.
|
protocol in cleartext connection, use :option:`--no-tls-proto` option.
|
||||||
For convenience, :option:`--h1` option forces HTTP/1.1 for both
|
For convenience, :option:`--h1` option forces HTTP/1.1 for both
|
||||||
@@ -139,4 +139,4 @@ h2load supports HTTP/3 if it is built with HTTP/3 enabled. HTTP/3
|
|||||||
support is experimental.
|
support is experimental.
|
||||||
|
|
||||||
In order to send HTTP/3 request, specify ``h3`` to
|
In order to send HTTP/3 request, specify ``h3`` to
|
||||||
:option:`--npn-list`.
|
:option:`--alpn-list`.
|
||||||
|
|||||||
@@ -18,7 +18,6 @@ Contents:
|
|||||||
|
|
||||||
package_README
|
package_README
|
||||||
contribute
|
contribute
|
||||||
security
|
|
||||||
building-android-binary
|
building-android-binary
|
||||||
tutorial-client
|
tutorial-client
|
||||||
tutorial-server
|
tutorial-server
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ known as "HTTP/2 router".
|
|||||||
By default, frontend connection is encrypted using SSL/TLS. So
|
By default, frontend connection is encrypted using SSL/TLS. So
|
||||||
server's private key and certificate must be supplied to the command
|
server's private key and certificate must be supplied to the command
|
||||||
line (or through configuration file). In this case, the frontend
|
line (or through configuration file). In this case, the frontend
|
||||||
protocol selection will be done via ALPN or NPN.
|
protocol selection will be done via ALPN.
|
||||||
|
|
||||||
To turn off encryption on frontend connection, use ``no-tls`` keyword
|
To turn off encryption on frontend connection, use ``no-tls`` keyword
|
||||||
in :option:`--frontend` option. HTTP/2 and HTTP/1 are available on
|
in :option:`--frontend` option. HTTP/2 and HTTP/1 are available on
|
||||||
@@ -546,8 +546,8 @@ keys in order to keep the existing connections alive during reload.
|
|||||||
The construction of Connection ID closely follows Block Cipher CID
|
The construction of Connection ID closely follows Block Cipher CID
|
||||||
Algorithm described in `QUIC-LB draft
|
Algorithm described in `QUIC-LB draft
|
||||||
<https://datatracker.ietf.org/doc/html/draft-ietf-quic-load-balancers>`_.
|
<https://datatracker.ietf.org/doc/html/draft-ietf-quic-load-balancers>`_.
|
||||||
A Connection ID that nghttpx generates is always 20 bytes long. It
|
A Connection ID that nghttpx generates is always 17 bytes long. It
|
||||||
uses first 2 bits as a configuration ID. The remaining bits in the
|
uses first 3 bits as a configuration ID. The remaining bits in the
|
||||||
first byte are reserved and random. The next 4 bytes are server ID.
|
first byte are reserved and random. The next 4 bytes are server ID.
|
||||||
The next 4 bytes are used to route UDP datagram to a correct
|
The next 4 bytes are used to route UDP datagram to a correct
|
||||||
``SO_REUSEPORT`` socket. The remaining bytes are randomly generated.
|
``SO_REUSEPORT`` socket. The remaining bytes are randomly generated.
|
||||||
|
|||||||
@@ -1,38 +0,0 @@
|
|||||||
Security Process
|
|
||||||
================
|
|
||||||
|
|
||||||
If you find a vulnerability in our software, please send the email to
|
|
||||||
"tatsuhiro.t at gmail dot com" about its details instead of submitting
|
|
||||||
issues on github issue page. It is a standard practice not to
|
|
||||||
disclose vulnerability information publicly until a fixed version is
|
|
||||||
released, or mitigation is worked out. In the future, we may setup a
|
|
||||||
dedicated mail address for this purpose.
|
|
||||||
|
|
||||||
If we identify that the reported issue is really a vulnerability, we
|
|
||||||
open a new security advisory draft using `GitHub security feature
|
|
||||||
<https://github.com/nghttp2/nghttp2/security>`_ and discuss the
|
|
||||||
mitigation and bug fixes there. The fixes are committed to the
|
|
||||||
private repository.
|
|
||||||
|
|
||||||
We write the security advisory and get CVE number from GitHub
|
|
||||||
privately. We also discuss the disclosure date to the public.
|
|
||||||
|
|
||||||
We make a new release with the fix at the same time when the
|
|
||||||
vulnerability is disclosed to public.
|
|
||||||
|
|
||||||
At least 7 days before the public disclosure date, we will post
|
|
||||||
security advisory (which includes all the details of the vulnerability
|
|
||||||
and the possible mitigation strategies) and the patches to fix the
|
|
||||||
issue to `distros@openwall
|
|
||||||
<https://oss-security.openwall.org/wiki/mailing-lists/distros>`_
|
|
||||||
mailing list. We also open a new issue on `nghttp2 issue tracker
|
|
||||||
<https://github.com/nghttp2/nghttp2/issues>`_ which notifies that the
|
|
||||||
upcoming release will have a security fix. The ``SECURITY`` label is
|
|
||||||
attached to this kind of issue.
|
|
||||||
|
|
||||||
Before few hours of new release, we merge the fixes to the master
|
|
||||||
branch (and/or a release branch if necessary) and make a new release.
|
|
||||||
Security advisory is disclosed on GitHub. We also post the
|
|
||||||
vulnerability information to `oss-security
|
|
||||||
<https://oss-security.openwall.org/wiki/mailing-lists/oss-security>`_
|
|
||||||
mailing list.
|
|
||||||
@@ -18,34 +18,8 @@ note that nghttp2 itself does not depend on libevent.
|
|||||||
|
|
||||||
The client starts with some libevent and OpenSSL setup in the
|
The client starts with some libevent and OpenSSL setup in the
|
||||||
``main()`` and ``run()`` functions. This setup isn't specific to
|
``main()`` and ``run()`` functions. This setup isn't specific to
|
||||||
nghttp2, but one thing you should look at is setup of the NPN
|
nghttp2, but one thing you should look at is setup of ALPN. Client
|
||||||
callback. The NPN callback is used by the client to select the next
|
tells application protocols that it supports to server via ALPN::
|
||||||
application protocol over TLS. In this tutorial, we use the
|
|
||||||
`nghttp2_select_next_protocol()` helper function to select the HTTP/2
|
|
||||||
protocol the library supports::
|
|
||||||
|
|
||||||
static int select_next_proto_cb(SSL *ssl _U_, unsigned char **out,
|
|
||||||
unsigned char *outlen, const unsigned char *in,
|
|
||||||
unsigned int inlen, void *arg _U_) {
|
|
||||||
if (nghttp2_select_next_protocol(out, outlen, in, inlen) <= 0) {
|
|
||||||
errx(1, "Server did not advertise " NGHTTP2_PROTO_VERSION_ID);
|
|
||||||
}
|
|
||||||
return SSL_TLSEXT_ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
If you are following TLS related RFC, you know that NPN is not the
|
|
||||||
standardized way to negotiate HTTP/2. NPN itself is not event
|
|
||||||
published as RFC. The standard way to negotiate HTTP/2 is ALPN,
|
|
||||||
Application-Layer Protocol Negotiation Extension, defined in `RFC 7301
|
|
||||||
<https://tools.ietf.org/html/rfc7301>`_. The one caveat of ALPN is
|
|
||||||
that OpenSSL >= 1.0.2 is required. We use macro to enable/disable
|
|
||||||
ALPN support depending on OpenSSL version. OpenSSL's ALPN
|
|
||||||
implementation does not require callback function like the above. But
|
|
||||||
we have to instruct OpenSSL SSL_CTX to use ALPN, which we'll talk
|
|
||||||
about soon.
|
|
||||||
|
|
||||||
The callback is added to the SSL_CTX object using
|
|
||||||
``SSL_CTX_set_next_proto_select_cb()``::
|
|
||||||
|
|
||||||
static SSL_CTX *create_ssl_ctx(void) {
|
static SSL_CTX *create_ssl_ctx(void) {
|
||||||
SSL_CTX *ssl_ctx;
|
SSL_CTX *ssl_ctx;
|
||||||
@@ -58,11 +32,8 @@ The callback is added to the SSL_CTX object using
|
|||||||
SSL_OP_ALL | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 |
|
SSL_OP_ALL | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 |
|
||||||
SSL_OP_NO_COMPRESSION |
|
SSL_OP_NO_COMPRESSION |
|
||||||
SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION);
|
SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION);
|
||||||
SSL_CTX_set_next_proto_select_cb(ssl_ctx, select_next_proto_cb, NULL);
|
|
||||||
|
|
||||||
#if OPENSSL_VERSION_NUMBER >= 0x10002000L
|
|
||||||
SSL_CTX_set_alpn_protos(ssl_ctx, (const unsigned char *)"\x02h2", 3);
|
SSL_CTX_set_alpn_protos(ssl_ctx, (const unsigned char *)"\x02h2", 3);
|
||||||
#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L
|
|
||||||
|
|
||||||
return ssl_ctx;
|
return ssl_ctx;
|
||||||
}
|
}
|
||||||
@@ -155,12 +126,7 @@ underlying network socket::
|
|||||||
|
|
||||||
ssl = bufferevent_openssl_get_ssl(session_data->bev);
|
ssl = bufferevent_openssl_get_ssl(session_data->bev);
|
||||||
|
|
||||||
SSL_get0_next_proto_negotiated(ssl, &alpn, &alpnlen);
|
|
||||||
#if OPENSSL_VERSION_NUMBER >= 0x10002000L
|
|
||||||
if (alpn == NULL) {
|
|
||||||
SSL_get0_alpn_selected(ssl, &alpn, &alpnlen);
|
SSL_get0_alpn_selected(ssl, &alpn, &alpnlen);
|
||||||
}
|
|
||||||
#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L
|
|
||||||
|
|
||||||
if (alpn == NULL || alpnlen != 2 || memcmp("h2", alpn, 2) != 0) {
|
if (alpn == NULL || alpnlen != 2 || memcmp("h2", alpn, 2) != 0) {
|
||||||
fprintf(stderr, "h2 is not negotiated\n");
|
fprintf(stderr, "h2 is not negotiated\n");
|
||||||
@@ -205,7 +171,7 @@ session object and several callbacks::
|
|||||||
|
|
||||||
nghttp2_session_callbacks_new(&callbacks);
|
nghttp2_session_callbacks_new(&callbacks);
|
||||||
|
|
||||||
nghttp2_session_callbacks_set_send_callback(callbacks, send_callback);
|
nghttp2_session_callbacks_set_send_callback2(callbacks, send_callback);
|
||||||
|
|
||||||
nghttp2_session_callbacks_set_on_frame_recv_callback(callbacks,
|
nghttp2_session_callbacks_set_on_frame_recv_callback(callbacks,
|
||||||
on_frame_recv_callback);
|
on_frame_recv_callback);
|
||||||
@@ -280,7 +246,7 @@ HTTP request in the ``submit_request()`` function::
|
|||||||
MAKE_NV(":path", stream_data->path, stream_data->pathlen)};
|
MAKE_NV(":path", stream_data->path, stream_data->pathlen)};
|
||||||
fprintf(stderr, "Request headers:\n");
|
fprintf(stderr, "Request headers:\n");
|
||||||
print_headers(stderr, hdrs, ARRLEN(hdrs));
|
print_headers(stderr, hdrs, ARRLEN(hdrs));
|
||||||
stream_id = nghttp2_submit_request(session_data->session, NULL, hdrs,
|
stream_id = nghttp2_submit_request2(session_data->session, NULL, hdrs,
|
||||||
ARRLEN(hdrs), NULL, stream_data);
|
ARRLEN(hdrs), NULL, stream_data);
|
||||||
if (stream_id < 0) {
|
if (stream_id < 0) {
|
||||||
errx(1, "Could not submit HTTP request: %s", nghttp2_strerror(stream_id));
|
errx(1, "Could not submit HTTP request: %s", nghttp2_strerror(stream_id));
|
||||||
@@ -292,11 +258,11 @@ HTTP request in the ``submit_request()`` function::
|
|||||||
We build the HTTP request header fields in ``hdrs``, which is an array
|
We build the HTTP request header fields in ``hdrs``, which is an array
|
||||||
of :type:`nghttp2_nv`. There are four header fields to be sent:
|
of :type:`nghttp2_nv`. There are four header fields to be sent:
|
||||||
``:method``, ``:scheme``, ``:authority``, and ``:path``. To queue the
|
``:method``, ``:scheme``, ``:authority``, and ``:path``. To queue the
|
||||||
HTTP request, we call `nghttp2_submit_request()`. The ``stream_data``
|
HTTP request, we call `nghttp2_submit_request2()`. The ``stream_data``
|
||||||
is passed via the *stream_user_data* parameter, which is helpfully
|
is passed via the *stream_user_data* parameter, which is helpfully
|
||||||
later passed back to callback functions.
|
later passed back to callback functions.
|
||||||
|
|
||||||
`nghttp2_submit_request()` returns the newly assigned stream ID for
|
`nghttp2_submit_request2()` returns the newly assigned stream ID for
|
||||||
the request.
|
the request.
|
||||||
|
|
||||||
The next bufferevent callback is ``readcb()``, which is invoked when
|
The next bufferevent callback is ``readcb()``, which is invoked when
|
||||||
@@ -304,12 +270,12 @@ data is available to read from the bufferevent input buffer::
|
|||||||
|
|
||||||
static void readcb(struct bufferevent *bev, void *ptr) {
|
static void readcb(struct bufferevent *bev, void *ptr) {
|
||||||
http2_session_data *session_data = (http2_session_data *)ptr;
|
http2_session_data *session_data = (http2_session_data *)ptr;
|
||||||
ssize_t readlen;
|
nghttp2_ssize readlen;
|
||||||
struct evbuffer *input = bufferevent_get_input(bev);
|
struct evbuffer *input = bufferevent_get_input(bev);
|
||||||
size_t datalen = evbuffer_get_length(input);
|
size_t datalen = evbuffer_get_length(input);
|
||||||
unsigned char *data = evbuffer_pullup(input, -1);
|
unsigned char *data = evbuffer_pullup(input, -1);
|
||||||
|
|
||||||
readlen = nghttp2_session_mem_recv(session_data->session, data, datalen);
|
readlen = nghttp2_session_mem_recv2(session_data->session, data, datalen);
|
||||||
if (readlen < 0) {
|
if (readlen < 0) {
|
||||||
warnx("Fatal error: %s", nghttp2_strerror((int)readlen));
|
warnx("Fatal error: %s", nghttp2_strerror((int)readlen));
|
||||||
delete_http2_session_data(session_data);
|
delete_http2_session_data(session_data);
|
||||||
@@ -327,8 +293,8 @@ data is available to read from the bufferevent input buffer::
|
|||||||
}
|
}
|
||||||
|
|
||||||
In this function we feed all unprocessed, received data to the nghttp2
|
In this function we feed all unprocessed, received data to the nghttp2
|
||||||
session object using the `nghttp2_session_mem_recv()` function.
|
session object using the `nghttp2_session_mem_recv2()` function.
|
||||||
`nghttp2_session_mem_recv()` processes the received data and may
|
`nghttp2_session_mem_recv2()` processes the received data and may
|
||||||
invoke nghttp2 callbacks and queue frames for transmission. Since
|
invoke nghttp2 callbacks and queue frames for transmission. Since
|
||||||
there may be pending frames for transmission, we call immediately
|
there may be pending frames for transmission, we call immediately
|
||||||
``session_send()`` to send them. ``session_send()`` is defined as
|
``session_send()`` to send them. ``session_send()`` is defined as
|
||||||
@@ -347,15 +313,16 @@ follows::
|
|||||||
|
|
||||||
The `nghttp2_session_send()` function serializes pending frames into
|
The `nghttp2_session_send()` function serializes pending frames into
|
||||||
wire format and calls the ``send_callback()`` function to send them.
|
wire format and calls the ``send_callback()`` function to send them.
|
||||||
``send_callback()`` has type :type:`nghttp2_send_callback` and is
|
``send_callback()`` has type :type:`nghttp2_send_callback2` and is
|
||||||
defined as::
|
defined as::
|
||||||
|
|
||||||
static ssize_t send_callback(nghttp2_session *session _U_, const uint8_t *data,
|
static nghttp2_ssize send_callback(nghttp2_session *session _U_,
|
||||||
size_t length, int flags _U_, void *user_data) {
|
const uint8_t *data, size_t length,
|
||||||
|
int flags _U_, void *user_data) {
|
||||||
http2_session_data *session_data = (http2_session_data *)user_data;
|
http2_session_data *session_data = (http2_session_data *)user_data;
|
||||||
struct bufferevent *bev = session_data->bev;
|
struct bufferevent *bev = session_data->bev;
|
||||||
bufferevent_write(bev, data, length);
|
bufferevent_write(bev, data, length);
|
||||||
return (ssize_t)length;
|
return (nghttp2_ssize)length;
|
||||||
}
|
}
|
||||||
|
|
||||||
Since we use bufferevent to abstract network I/O, we just write the
|
Since we use bufferevent to abstract network I/O, we just write the
|
||||||
|
|||||||
@@ -24,9 +24,9 @@ deflater object for the dynamic header table. If in doubt, just
|
|||||||
specify 4096 here, which is the default upper bound of dynamic header
|
specify 4096 here, which is the default upper bound of dynamic header
|
||||||
table buffer size.
|
table buffer size.
|
||||||
|
|
||||||
To encode header fields, use the `nghttp2_hd_deflate_hd()` function::
|
To encode header fields, use the `nghttp2_hd_deflate_hd2()` function::
|
||||||
|
|
||||||
ssize_t nghttp2_hd_deflate_hd(nghttp2_hd_deflater *deflater,
|
nghttp2_ssize nghttp2_hd_deflate_hd2(nghttp2_hd_deflater *deflater,
|
||||||
uint8_t *buf, size_t buflen,
|
uint8_t *buf, size_t buflen,
|
||||||
const nghttp2_nv *nva, size_t nvlen);
|
const nghttp2_nv *nva, size_t nvlen);
|
||||||
|
|
||||||
@@ -44,7 +44,7 @@ cookies), set the :macro:`NGHTTP2_NV_FLAG_NO_INDEX` flag in
|
|||||||
sensitive header fields by compression based attacks: This is achieved
|
sensitive header fields by compression based attacks: This is achieved
|
||||||
by not inserting the header field into the dynamic header table.
|
by not inserting the header field into the dynamic header table.
|
||||||
|
|
||||||
`nghttp2_hd_deflate_hd()` processes all headers given in *nva*. The
|
`nghttp2_hd_deflate_hd2()` processes all headers given in *nva*. The
|
||||||
*nva* must include all request or response header fields to be sent in
|
*nva* must include all request or response header fields to be sent in
|
||||||
one HEADERS (or optionally following (multiple) CONTINUATION
|
one HEADERS (or optionally following (multiple) CONTINUATION
|
||||||
frame(s)). The *buf* must have enough space to store the encoded
|
frame(s)). The *buf* must have enough space to store the encoded
|
||||||
@@ -55,13 +55,13 @@ of the encoded result length, use `nghttp2_hd_deflate_bound()`::
|
|||||||
const nghttp2_nv *nva, size_t nvlen);
|
const nghttp2_nv *nva, size_t nvlen);
|
||||||
|
|
||||||
Pass this function the same parameters (*deflater*, *nva*, and
|
Pass this function the same parameters (*deflater*, *nva*, and
|
||||||
*nvlen*) which will be passed to `nghttp2_hd_deflate_hd()`.
|
*nvlen*) which will be passed to `nghttp2_hd_deflate_hd2()`.
|
||||||
|
|
||||||
Subsequent calls to `nghttp2_hd_deflate_hd()` will use the current
|
Subsequent calls to `nghttp2_hd_deflate_hd2()` will use the current
|
||||||
encoder state and perform differential encoding, which yields HPAC's
|
encoder state and perform differential encoding, which yields HPAC's
|
||||||
fundamental compression gain.
|
fundamental compression gain.
|
||||||
|
|
||||||
If `nghttp2_hd_deflate_hd()` fails, the failure is fatal and any
|
If `nghttp2_hd_deflate_hd2()` fails, the failure is fatal and any
|
||||||
further calls with the same deflater object will fail. Thus it's very
|
further calls with the same deflater object will fail. Thus it's very
|
||||||
important to use `nghttp2_hd_deflate_bound()` to determine the
|
important to use `nghttp2_hd_deflate_bound()` to determine the
|
||||||
required size of the output buffer.
|
required size of the output buffer.
|
||||||
@@ -78,14 +78,14 @@ header data. To initialize the object, use
|
|||||||
|
|
||||||
int nghttp2_hd_inflate_new(nghttp2_hd_inflater **inflater_ptr);
|
int nghttp2_hd_inflate_new(nghttp2_hd_inflater **inflater_ptr);
|
||||||
|
|
||||||
To inflate header data, use `nghttp2_hd_inflate_hd2()`::
|
To inflate header data, use `nghttp2_hd_inflate_hd3()`::
|
||||||
|
|
||||||
ssize_t nghttp2_hd_inflate_hd2(nghttp2_hd_inflater *inflater,
|
nghttp2_ssize nghttp2_hd_inflate_hd3(nghttp2_hd_inflater *inflater,
|
||||||
nghttp2_nv *nv_out, int *inflate_flags,
|
nghttp2_nv *nv_out, int *inflate_flags,
|
||||||
const uint8_t *in, size_t inlen,
|
const uint8_t *in, size_t inlen,
|
||||||
int in_final);
|
int in_final);
|
||||||
|
|
||||||
`nghttp2_hd_inflate_hd2()` reads a stream of bytes and outputs a
|
`nghttp2_hd_inflate_hd3()` reads a stream of bytes and outputs a
|
||||||
single header field at a time. Multiple calls are normally required to
|
single header field at a time. Multiple calls are normally required to
|
||||||
read a full stream of bytes and output all of the header fields.
|
read a full stream of bytes and output all of the header fields.
|
||||||
|
|
||||||
@@ -119,7 +119,7 @@ If *in_final* is zero and the :macro:`NGHTTP2_HD_INFLATE_EMIT` flag is
|
|||||||
not set, it indicates that all given data was processed. The caller
|
not set, it indicates that all given data was processed. The caller
|
||||||
is required to pass additional data.
|
is required to pass additional data.
|
||||||
|
|
||||||
Example usage of `nghttp2_hd_inflate_hd2()` is shown in the
|
Example usage of `nghttp2_hd_inflate_hd3()` is shown in the
|
||||||
`inflate_header_block()` function in `deflate.c`_.
|
`inflate_header_block()` function in `deflate.c`_.
|
||||||
|
|
||||||
Finally, to delete a :type:`nghttp2_hd_inflater` object, use
|
Finally, to delete a :type:`nghttp2_hd_inflater` object, use
|
||||||
|
|||||||
@@ -21,41 +21,18 @@ note that nghttp2 itself does not depend on libevent.
|
|||||||
|
|
||||||
The server starts with some libevent and OpenSSL setup in the
|
The server starts with some libevent and OpenSSL setup in the
|
||||||
``main()`` and ``run()`` functions. This setup isn't specific to
|
``main()`` and ``run()`` functions. This setup isn't specific to
|
||||||
nghttp2, but one thing you should look at is setup of the NPN
|
nghttp2, but one thing you should look at is setup of ALPN callback.
|
||||||
callback. The NPN callback is used by the server to advertise which
|
The ALPN callback is used by the server to select application
|
||||||
application protocols the server supports to a client. In this
|
protocols offered by client. In ALPN, client sends the list of
|
||||||
example program, when creating the ``SSL_CTX`` object, we store the
|
supported application protocols, and server selects one of them. We
|
||||||
application protocol name in the wire format of NPN in a statically
|
provide the callback for it::
|
||||||
allocated buffer. This is safe because we only create one ``SSL_CTX``
|
|
||||||
object in the program's entire lifetime.
|
|
||||||
|
|
||||||
If you are following TLS related RFC, you know that NPN is not the
|
|
||||||
standardized way to negotiate HTTP/2. NPN itself is not even
|
|
||||||
published as RFC. The standard way to negotiate HTTP/2 is ALPN,
|
|
||||||
Application-Layer Protocol Negotiation Extension, defined in `RFC 7301
|
|
||||||
<https://tools.ietf.org/html/rfc7301>`_. The one caveat of ALPN is
|
|
||||||
that OpenSSL >= 1.0.2 is required. We use macro to enable/disable
|
|
||||||
ALPN support depending on OpenSSL version. In ALPN, client sends the
|
|
||||||
list of supported application protocols, and server selects one of
|
|
||||||
them. We provide the callback for it::
|
|
||||||
|
|
||||||
static unsigned char next_proto_list[256];
|
|
||||||
static size_t next_proto_list_len;
|
|
||||||
|
|
||||||
static int next_proto_cb(SSL *s _U_, const unsigned char **data,
|
|
||||||
unsigned int *len, void *arg _U_) {
|
|
||||||
*data = next_proto_list;
|
|
||||||
*len = (unsigned int)next_proto_list_len;
|
|
||||||
return SSL_TLSEXT_ERR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if OPENSSL_VERSION_NUMBER >= 0x10002000L
|
|
||||||
static int alpn_select_proto_cb(SSL *ssl _U_, const unsigned char **out,
|
static int alpn_select_proto_cb(SSL *ssl _U_, const unsigned char **out,
|
||||||
unsigned char *outlen, const unsigned char *in,
|
unsigned char *outlen, const unsigned char *in,
|
||||||
unsigned int inlen, void *arg _U_) {
|
unsigned int inlen, void *arg _U_) {
|
||||||
int rv;
|
int rv;
|
||||||
|
|
||||||
rv = nghttp2_select_next_protocol((unsigned char **)out, outlen, in, inlen);
|
rv = nghttp2_select_alpn(out, outlen, in, inlen);
|
||||||
|
|
||||||
if (rv != 1) {
|
if (rv != 1) {
|
||||||
return SSL_TLSEXT_ERR_NOACK;
|
return SSL_TLSEXT_ERR_NOACK;
|
||||||
@@ -63,7 +40,6 @@ them. We provide the callback for it::
|
|||||||
|
|
||||||
return SSL_TLSEXT_ERR_OK;
|
return SSL_TLSEXT_ERR_OK;
|
||||||
}
|
}
|
||||||
#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L
|
|
||||||
|
|
||||||
static SSL_CTX *create_ssl_ctx(const char *key_file, const char *cert_file) {
|
static SSL_CTX *create_ssl_ctx(const char *key_file, const char *cert_file) {
|
||||||
SSL_CTX *ssl_ctx;
|
SSL_CTX *ssl_ctx;
|
||||||
@@ -73,33 +49,14 @@ them. We provide the callback for it::
|
|||||||
|
|
||||||
...
|
...
|
||||||
|
|
||||||
next_proto_list[0] = NGHTTP2_PROTO_VERSION_ID_LEN;
|
|
||||||
memcpy(&next_proto_list[1], NGHTTP2_PROTO_VERSION_ID,
|
|
||||||
NGHTTP2_PROTO_VERSION_ID_LEN);
|
|
||||||
next_proto_list_len = 1 + NGHTTP2_PROTO_VERSION_ID_LEN;
|
|
||||||
|
|
||||||
SSL_CTX_set_next_protos_advertised_cb(ssl_ctx, next_proto_cb, NULL);
|
|
||||||
|
|
||||||
#if OPENSSL_VERSION_NUMBER >= 0x10002000L
|
|
||||||
SSL_CTX_set_alpn_select_cb(ssl_ctx, alpn_select_proto_cb, NULL);
|
SSL_CTX_set_alpn_select_cb(ssl_ctx, alpn_select_proto_cb, NULL);
|
||||||
#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L
|
|
||||||
|
|
||||||
return ssl_ctx;
|
return ssl_ctx;
|
||||||
}
|
}
|
||||||
|
|
||||||
The wire format of NPN is a sequence of length prefixed strings, with
|
In ``alpn_select_proto_cb()``, we use `nghttp2_select_alpn()` to
|
||||||
exactly one byte used to specify the length of each protocol
|
select application protocol. The `nghttp2_select_alpn()` returns 1
|
||||||
identifier. In this tutorial, we advertise the specific HTTP/2
|
only if it selected h2 (ALPN identifier for HTTP/2), and out
|
||||||
protocol version the current nghttp2 library supports, which is
|
|
||||||
exported in the identifier :macro:`NGHTTP2_PROTO_VERSION_ID`. The
|
|
||||||
``next_proto_cb()`` function is the server-side NPN callback. In the
|
|
||||||
OpenSSL implementation, we just assign the pointer to the NPN buffers
|
|
||||||
we filled in earlier. The NPN callback function is set to the
|
|
||||||
``SSL_CTX`` object using ``SSL_CTX_set_next_protos_advertised_cb()``.
|
|
||||||
|
|
||||||
In ``alpn_select_proto_cb()``, we use `nghttp2_select_next_protocol()`
|
|
||||||
to select application protocol. The `nghttp2_select_next_protocol()`
|
|
||||||
returns 1 only if it selected h2 (ALPN identifier for HTTP/2), and out
|
|
||||||
parameters were assigned accordingly.
|
parameters were assigned accordingly.
|
||||||
|
|
||||||
Next, let's take a look at the main structures used by the example
|
Next, let's take a look at the main structures used by the example
|
||||||
@@ -213,12 +170,7 @@ underlying network socket::
|
|||||||
|
|
||||||
ssl = bufferevent_openssl_get_ssl(session_data->bev);
|
ssl = bufferevent_openssl_get_ssl(session_data->bev);
|
||||||
|
|
||||||
SSL_get0_next_proto_negotiated(ssl, &alpn, &alpnlen);
|
|
||||||
#if OPENSSL_VERSION_NUMBER >= 0x10002000L
|
|
||||||
if (alpn == NULL) {
|
|
||||||
SSL_get0_alpn_selected(ssl, &alpn, &alpnlen);
|
SSL_get0_alpn_selected(ssl, &alpn, &alpnlen);
|
||||||
}
|
|
||||||
#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L
|
|
||||||
|
|
||||||
if (alpn == NULL || alpnlen != 2 || memcmp("h2", alpn, 2) != 0) {
|
if (alpn == NULL || alpnlen != 2 || memcmp("h2", alpn, 2) != 0) {
|
||||||
fprintf(stderr, "%s h2 is not negotiated\n", session_data->client_addr);
|
fprintf(stderr, "%s h2 is not negotiated\n", session_data->client_addr);
|
||||||
@@ -268,7 +220,7 @@ session object and several callbacks::
|
|||||||
|
|
||||||
nghttp2_session_callbacks_new(&callbacks);
|
nghttp2_session_callbacks_new(&callbacks);
|
||||||
|
|
||||||
nghttp2_session_callbacks_set_send_callback(callbacks, send_callback);
|
nghttp2_session_callbacks_set_send_callback2(callbacks, send_callback);
|
||||||
|
|
||||||
nghttp2_session_callbacks_set_on_frame_recv_callback(callbacks,
|
nghttp2_session_callbacks_set_on_frame_recv_callback(callbacks,
|
||||||
on_frame_recv_callback);
|
on_frame_recv_callback);
|
||||||
@@ -323,12 +275,12 @@ this pending data. To process the received data, we call the
|
|||||||
``session_recv()`` function::
|
``session_recv()`` function::
|
||||||
|
|
||||||
static int session_recv(http2_session_data *session_data) {
|
static int session_recv(http2_session_data *session_data) {
|
||||||
ssize_t readlen;
|
nghttp2_ssize readlen;
|
||||||
struct evbuffer *input = bufferevent_get_input(session_data->bev);
|
struct evbuffer *input = bufferevent_get_input(session_data->bev);
|
||||||
size_t datalen = evbuffer_get_length(input);
|
size_t datalen = evbuffer_get_length(input);
|
||||||
unsigned char *data = evbuffer_pullup(input, -1);
|
unsigned char *data = evbuffer_pullup(input, -1);
|
||||||
|
|
||||||
readlen = nghttp2_session_mem_recv(session_data->session, data, datalen);
|
readlen = nghttp2_session_mem_recv2(session_data->session, data, datalen);
|
||||||
if (readlen < 0) {
|
if (readlen < 0) {
|
||||||
warnx("Fatal error: %s", nghttp2_strerror((int)readlen));
|
warnx("Fatal error: %s", nghttp2_strerror((int)readlen));
|
||||||
return -1;
|
return -1;
|
||||||
@@ -344,9 +296,9 @@ this pending data. To process the received data, we call the
|
|||||||
}
|
}
|
||||||
|
|
||||||
In this function, we feed all unprocessed but already received data to
|
In this function, we feed all unprocessed but already received data to
|
||||||
the nghttp2 session object using the `nghttp2_session_mem_recv()`
|
the nghttp2 session object using the `nghttp2_session_mem_recv2()`
|
||||||
function. The `nghttp2_session_mem_recv()` function processes the data
|
function. The `nghttp2_session_mem_recv2()` function processes the
|
||||||
and may both invoke the previously setup callbacks and also queue
|
data and may both invoke the previously setup callbacks and also queue
|
||||||
outgoing frames. To send any pending outgoing frames, we immediately
|
outgoing frames. To send any pending outgoing frames, we immediately
|
||||||
call ``session_send()``.
|
call ``session_send()``.
|
||||||
|
|
||||||
@@ -364,11 +316,12 @@ The ``session_send()`` function is defined as follows::
|
|||||||
|
|
||||||
The `nghttp2_session_send()` function serializes the frame into wire
|
The `nghttp2_session_send()` function serializes the frame into wire
|
||||||
format and calls the ``send_callback()``, which is of type
|
format and calls the ``send_callback()``, which is of type
|
||||||
:type:`nghttp2_send_callback`. The ``send_callback()`` is defined as
|
:type:`nghttp2_send_callback2`. The ``send_callback()`` is defined as
|
||||||
follows::
|
follows::
|
||||||
|
|
||||||
static ssize_t send_callback(nghttp2_session *session _U_, const uint8_t *data,
|
static nghttp2_ssize send_callback(nghttp2_session *session _U_,
|
||||||
size_t length, int flags _U_, void *user_data) {
|
const uint8_t *data, size_t length,
|
||||||
|
int flags _U_, void *user_data) {
|
||||||
http2_session_data *session_data = (http2_session_data *)user_data;
|
http2_session_data *session_data = (http2_session_data *)user_data;
|
||||||
struct bufferevent *bev = session_data->bev;
|
struct bufferevent *bev = session_data->bev;
|
||||||
/* Avoid excessive buffering in server side. */
|
/* Avoid excessive buffering in server side. */
|
||||||
@@ -377,7 +330,7 @@ follows::
|
|||||||
return NGHTTP2_ERR_WOULDBLOCK;
|
return NGHTTP2_ERR_WOULDBLOCK;
|
||||||
}
|
}
|
||||||
bufferevent_write(bev, data, length);
|
bufferevent_write(bev, data, length);
|
||||||
return (ssize_t)length;
|
return (nghttp2_ssize)length;
|
||||||
}
|
}
|
||||||
|
|
||||||
Since we use bufferevent to abstract network I/O, we just write the
|
Since we use bufferevent to abstract network I/O, we just write the
|
||||||
@@ -557,11 +510,11 @@ Sending the file content is performed by the ``send_response()`` function::
|
|||||||
static int send_response(nghttp2_session *session, int32_t stream_id,
|
static int send_response(nghttp2_session *session, int32_t stream_id,
|
||||||
nghttp2_nv *nva, size_t nvlen, int fd) {
|
nghttp2_nv *nva, size_t nvlen, int fd) {
|
||||||
int rv;
|
int rv;
|
||||||
nghttp2_data_provider data_prd;
|
nghttp2_data_provider2 data_prd;
|
||||||
data_prd.source.fd = fd;
|
data_prd.source.fd = fd;
|
||||||
data_prd.read_callback = file_read_callback;
|
data_prd.read_callback = file_read_callback;
|
||||||
|
|
||||||
rv = nghttp2_submit_response(session, stream_id, nva, nvlen, &data_prd);
|
rv = nghttp2_submit_response2(session, stream_id, nva, nvlen, &data_prd);
|
||||||
if (rv != 0) {
|
if (rv != 0) {
|
||||||
warnx("Fatal error: %s", nghttp2_strerror(rv));
|
warnx("Fatal error: %s", nghttp2_strerror(rv));
|
||||||
return -1;
|
return -1;
|
||||||
@@ -569,7 +522,7 @@ Sending the file content is performed by the ``send_response()`` function::
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
nghttp2 uses the :type:`nghttp2_data_provider` structure to send the
|
nghttp2 uses the :type:`nghttp2_data_provider2` structure to send the
|
||||||
entity body to the remote peer. The ``source`` member of this
|
entity body to the remote peer. The ``source`` member of this
|
||||||
structure is a union, which can be either a void pointer or an int
|
structure is a union, which can be either a void pointer or an int
|
||||||
(which is intended to be used as file descriptor). In this example
|
(which is intended to be used as file descriptor). In this example
|
||||||
@@ -577,7 +530,7 @@ server, we use it as a file descriptor. We also set the
|
|||||||
``file_read_callback()`` callback function to read the contents of the
|
``file_read_callback()`` callback function to read the contents of the
|
||||||
file::
|
file::
|
||||||
|
|
||||||
static ssize_t file_read_callback(nghttp2_session *session _U_,
|
static nghttp2_ssize file_read_callback(nghttp2_session *session _U_,
|
||||||
int32_t stream_id _U_, uint8_t *buf,
|
int32_t stream_id _U_, uint8_t *buf,
|
||||||
size_t length, uint32_t *data_flags,
|
size_t length, uint32_t *data_flags,
|
||||||
nghttp2_data_source *source,
|
nghttp2_data_source *source,
|
||||||
@@ -592,7 +545,7 @@ file::
|
|||||||
if (r == 0) {
|
if (r == 0) {
|
||||||
*data_flags |= NGHTTP2_DATA_FLAG_EOF;
|
*data_flags |= NGHTTP2_DATA_FLAG_EOF;
|
||||||
}
|
}
|
||||||
return r;
|
return (nghttp2_ssize)r;
|
||||||
}
|
}
|
||||||
|
|
||||||
If an error occurs while reading the file, we return
|
If an error occurs while reading the file, we return
|
||||||
@@ -601,8 +554,8 @@ library to send RST_STREAM to the stream. When all data has been
|
|||||||
read, the :macro:`NGHTTP2_DATA_FLAG_EOF` flag is set to signal nghttp2
|
read, the :macro:`NGHTTP2_DATA_FLAG_EOF` flag is set to signal nghttp2
|
||||||
that we have finished reading the file.
|
that we have finished reading the file.
|
||||||
|
|
||||||
The `nghttp2_submit_response()` function is used to send the response to the
|
The `nghttp2_submit_response2()` function is used to send the response
|
||||||
remote peer.
|
to the remote peer.
|
||||||
|
|
||||||
The ``on_stream_close_callback()`` function is invoked when the stream
|
The ``on_stream_close_callback()`` function is invoked when the stream
|
||||||
is about to close::
|
is about to close::
|
||||||
|
|||||||
@@ -1,21 +1,23 @@
|
|||||||
FROM debian:12 as build
|
FROM debian:12 as build
|
||||||
|
|
||||||
|
ARG NGHTTP2_BRANCH=master
|
||||||
|
|
||||||
RUN apt-get update && \
|
RUN apt-get update && \
|
||||||
apt-get install -y --no-install-recommends \
|
DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
|
||||||
git clang make binutils autoconf automake autotools-dev libtool \
|
git clang make binutils autoconf automake autotools-dev libtool \
|
||||||
pkg-config \
|
pkg-config cmake cmake-data \
|
||||||
zlib1g-dev libev-dev libjemalloc-dev ruby-dev libc-ares-dev bison \
|
zlib1g-dev libev-dev libjemalloc-dev ruby-dev libc-ares-dev bison \
|
||||||
libelf-dev
|
libelf-dev libbrotli-dev
|
||||||
|
|
||||||
RUN git clone --depth 1 -b OpenSSL_1_1_1w+quic https://github.com/quictls/openssl && \
|
RUN git clone --recursive --depth 1 -b v1.26.0 https://github.com/aws/aws-lc && \
|
||||||
cd openssl && \
|
cd aws-lc && \
|
||||||
./config --openssldir=/etc/ssl && \
|
cmake -B build -DDISABLE_GO=ON && \
|
||||||
make -j$(nproc) && \
|
make -j$(nproc) -C build && \
|
||||||
make install_sw && \
|
cmake --install build && \
|
||||||
cd .. && \
|
cd .. && \
|
||||||
rm -rf openssl
|
rm -rf aws-lc
|
||||||
|
|
||||||
RUN git clone --depth 1 -b v0.15.0 https://github.com/ngtcp2/nghttp3 && \
|
RUN git clone --recursive --depth 1 -b v1.3.0 https://github.com/ngtcp2/nghttp3 && \
|
||||||
cd nghttp3 && \
|
cd nghttp3 && \
|
||||||
autoreconf -i && \
|
autoreconf -i && \
|
||||||
./configure --enable-lib-only && \
|
./configure --enable-lib-only && \
|
||||||
@@ -24,55 +26,57 @@ RUN git clone --depth 1 -b v0.15.0 https://github.com/ngtcp2/nghttp3 && \
|
|||||||
cd .. && \
|
cd .. && \
|
||||||
rm -rf nghttp3
|
rm -rf nghttp3
|
||||||
|
|
||||||
RUN git clone --depth 1 -b v0.19.1 https://github.com/ngtcp2/ngtcp2 && \
|
RUN git clone --recursive --depth 1 -b v1.5.0 https://github.com/ngtcp2/ngtcp2 && \
|
||||||
cd ngtcp2 && \
|
cd ngtcp2 && \
|
||||||
autoreconf -i && \
|
autoreconf -i && \
|
||||||
./configure --enable-lib-only \
|
./configure --enable-lib-only --with-boringssl \
|
||||||
LIBTOOL_LDFLAGS="-static-libtool-libs" \
|
LIBTOOL_LDFLAGS="-static-libtool-libs" \
|
||||||
OPENSSL_LIBS="-l:libssl.a -l:libcrypto.a -ldl -lpthread" \
|
BORINGSSL_LIBS="-l:libssl.a -l:libcrypto.a" \
|
||||||
PKG_CONFIG_PATH="/usr/local/lib64/pkgconfig" && \
|
PKG_CONFIG_PATH="/usr/local/lib64/pkgconfig" && \
|
||||||
make -j$(nproc) && \
|
make -j$(nproc) && \
|
||||||
make install-strip && \
|
make install-strip && \
|
||||||
cd .. && \
|
cd .. && \
|
||||||
rm -rf ngtcp2
|
rm -rf ngtcp2
|
||||||
|
|
||||||
RUN git clone --depth 1 -b v1.2.2 https://github.com/libbpf/libbpf && \
|
RUN git clone --depth 1 -b v1.3.0 https://github.com/libbpf/libbpf && \
|
||||||
cd libbpf && \
|
cd libbpf && \
|
||||||
PREFIX=/usr/local make -C src install && \
|
PREFIX=/usr/local make -C src install && \
|
||||||
cd .. && \
|
cd .. && \
|
||||||
rm -rf libbpf
|
rm -rf libbpf
|
||||||
|
|
||||||
RUN git clone --depth 1 https://github.com/nghttp2/nghttp2.git && \
|
RUN git clone --recursive --depth 1 -b $NGHTTP2_BRANCH https://github.com/nghttp2/nghttp2 && \
|
||||||
cd nghttp2 && \
|
cd nghttp2 && \
|
||||||
git submodule update --init && \
|
|
||||||
autoreconf -i && \
|
autoreconf -i && \
|
||||||
./configure --disable-examples --disable-hpack-tools \
|
./configure --disable-examples --disable-hpack-tools \
|
||||||
--with-mruby --with-neverbleed \
|
--with-mruby \
|
||||||
--enable-http3 --with-libbpf \
|
--enable-http3 --with-libbpf \
|
||||||
|
--with-libbrotlienc --with-libbrotlidec \
|
||||||
CC=clang CXX=clang++ \
|
CC=clang CXX=clang++ \
|
||||||
LIBTOOL_LDFLAGS="-static-libtool-libs" \
|
LIBTOOL_LDFLAGS="-static-libtool-libs" \
|
||||||
OPENSSL_LIBS="-l:libssl.a -l:libcrypto.a -ldl -pthread" \
|
OPENSSL_LIBS="-l:libssl.a -l:libcrypto.a" \
|
||||||
LIBEV_LIBS="-l:libev.a" \
|
LIBEV_LIBS="-l:libev.a" \
|
||||||
JEMALLOC_LIBS="-l:libjemalloc.a" \
|
JEMALLOC_LIBS="-l:libjemalloc.a" \
|
||||||
LIBCARES_LIBS="-l:libcares.a" \
|
LIBCARES_LIBS="-l:libcares.a" \
|
||||||
ZLIB_LIBS="-l:libz.a" \
|
ZLIB_LIBS="-l:libz.a" \
|
||||||
LIBBPF_LIBS="-L/usr/local/lib64 -l:libbpf.a -l:libelf.a" \
|
LIBBPF_LIBS="-L/usr/local/lib64 -l:libbpf.a -l:libelf.a" \
|
||||||
|
LIBBROTLIENC_LIBS="-l:libbrotlienc.a -l:libbrotlicommon.a" \
|
||||||
|
LIBBROTLIDEC_LIBS="-l:libbrotlidec.a -l:libbrotlicommon.a" \
|
||||||
LDFLAGS="-static-libgcc -static-libstdc++" \
|
LDFLAGS="-static-libgcc -static-libstdc++" \
|
||||||
PKG_CONFIG_PATH="/usr/local/lib64/pkgconfig" && \
|
PKG_CONFIG_PATH="/usr/local/lib64/pkgconfig" && \
|
||||||
make -j$(nproc) install-strip && \
|
make -j$(nproc) install-strip && \
|
||||||
cd .. && \
|
cd .. && \
|
||||||
rm -rf nghttp2
|
rm -rf nghttp2
|
||||||
|
|
||||||
FROM gcr.io/distroless/base-debian12
|
FROM gcr.io/distroless/base-nossl-debian12
|
||||||
|
|
||||||
COPY --from=build \
|
COPY --from=build --link \
|
||||||
/usr/local/share/nghttp2/ \
|
/usr/local/share/nghttp2/ \
|
||||||
/usr/local/share/nghttp2/
|
/usr/local/share/nghttp2/
|
||||||
COPY --from=build \
|
COPY --from=build --link \
|
||||||
/usr/local/bin/h2load \
|
/usr/local/bin/h2load \
|
||||||
/usr/local/bin/nghttpx \
|
/usr/local/bin/nghttpx \
|
||||||
/usr/local/bin/nghttp \
|
/usr/local/bin/nghttp \
|
||||||
/usr/local/bin/nghttpd \
|
/usr/local/bin/nghttpd \
|
||||||
/usr/local/bin/
|
/usr/local/bin/
|
||||||
COPY --from=build /usr/local/lib/nghttp2/reuseport_kern.o \
|
COPY --from=build --link /usr/local/lib/nghttp2/reuseport_kern.o \
|
||||||
/usr/local/lib/nghttp2/
|
/usr/local/lib/nghttp2/
|
||||||
|
|||||||
@@ -56,6 +56,7 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
||||||
|
#define NGHTTP2_NO_SSIZE_T
|
||||||
#include <nghttp2/nghttp2.h>
|
#include <nghttp2/nghttp2.h>
|
||||||
|
|
||||||
#include <openssl/ssl.h>
|
#include <openssl/ssl.h>
|
||||||
@@ -154,13 +155,14 @@ static void diec(const char *func, int error_code) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The implementation of nghttp2_send_callback type. Here we write
|
* The implementation of nghttp2_send_callback2 type. Here we write
|
||||||
* |data| with size |length| to the network and return the number of
|
* |data| with size |length| to the network and return the number of
|
||||||
* bytes actually written. See the documentation of
|
* bytes actually written. See the documentation of
|
||||||
* nghttp2_send_callback for the details.
|
* nghttp2_send_callback for the details.
|
||||||
*/
|
*/
|
||||||
static ssize_t send_callback(nghttp2_session *session, const uint8_t *data,
|
static nghttp2_ssize send_callback(nghttp2_session *session,
|
||||||
size_t length, int flags, void *user_data) {
|
const uint8_t *data, size_t length,
|
||||||
|
int flags, void *user_data) {
|
||||||
struct Connection *connection;
|
struct Connection *connection;
|
||||||
int rv;
|
int rv;
|
||||||
(void)session;
|
(void)session;
|
||||||
@@ -184,12 +186,13 @@ static ssize_t send_callback(nghttp2_session *session, const uint8_t *data,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The implementation of nghttp2_recv_callback type. Here we read data
|
* The implementation of nghttp2_recv_callback2 type. Here we read
|
||||||
* from the network and write them in |buf|. The capacity of |buf| is
|
* data from the network and write them in |buf|. The capacity of
|
||||||
* |length| bytes. Returns the number of bytes stored in |buf|. See
|
* |buf| is |length| bytes. Returns the number of bytes stored in
|
||||||
* the documentation of nghttp2_recv_callback for the details.
|
* |buf|. See the documentation of nghttp2_recv_callback for the
|
||||||
|
* details.
|
||||||
*/
|
*/
|
||||||
static ssize_t recv_callback(nghttp2_session *session, uint8_t *buf,
|
static nghttp2_ssize recv_callback(nghttp2_session *session, uint8_t *buf,
|
||||||
size_t length, int flags, void *user_data) {
|
size_t length, int flags, void *user_data) {
|
||||||
struct Connection *connection;
|
struct Connection *connection;
|
||||||
int rv;
|
int rv;
|
||||||
@@ -328,9 +331,9 @@ static int on_data_chunk_recv_callback(nghttp2_session *session, uint8_t flags,
|
|||||||
* recv_callback is also required.
|
* recv_callback is also required.
|
||||||
*/
|
*/
|
||||||
static void setup_nghttp2_callbacks(nghttp2_session_callbacks *callbacks) {
|
static void setup_nghttp2_callbacks(nghttp2_session_callbacks *callbacks) {
|
||||||
nghttp2_session_callbacks_set_send_callback(callbacks, send_callback);
|
nghttp2_session_callbacks_set_send_callback2(callbacks, send_callback);
|
||||||
|
|
||||||
nghttp2_session_callbacks_set_recv_callback(callbacks, recv_callback);
|
nghttp2_session_callbacks_set_recv_callback2(callbacks, recv_callback);
|
||||||
|
|
||||||
nghttp2_session_callbacks_set_on_frame_send_callback(callbacks,
|
nghttp2_session_callbacks_set_on_frame_send_callback(callbacks,
|
||||||
on_frame_send_callback);
|
on_frame_send_callback);
|
||||||
@@ -345,29 +348,6 @@ static void setup_nghttp2_callbacks(nghttp2_session_callbacks *callbacks) {
|
|||||||
callbacks, on_data_chunk_recv_callback);
|
callbacks, on_data_chunk_recv_callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef OPENSSL_NO_NEXTPROTONEG
|
|
||||||
/*
|
|
||||||
* Callback function for TLS NPN. Since this program only supports
|
|
||||||
* HTTP/2 protocol, if server does not offer HTTP/2 the nghttp2
|
|
||||||
* library supports, we terminate program.
|
|
||||||
*/
|
|
||||||
static int select_next_proto_cb(SSL *ssl, unsigned char **out,
|
|
||||||
unsigned char *outlen, const unsigned char *in,
|
|
||||||
unsigned int inlen, void *arg) {
|
|
||||||
int rv;
|
|
||||||
(void)ssl;
|
|
||||||
(void)arg;
|
|
||||||
|
|
||||||
/* nghttp2_select_next_protocol() selects HTTP/2 protocol the
|
|
||||||
nghttp2 library supports. */
|
|
||||||
rv = nghttp2_select_next_protocol(out, outlen, in, inlen);
|
|
||||||
if (rv <= 0) {
|
|
||||||
die("Server did not advertise HTTP/2 protocol");
|
|
||||||
}
|
|
||||||
return SSL_TLSEXT_ERR_OK;
|
|
||||||
}
|
|
||||||
#endif /* !OPENSSL_NO_NEXTPROTONEG */
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Setup SSL/TLS context.
|
* Setup SSL/TLS context.
|
||||||
*/
|
*/
|
||||||
@@ -376,14 +356,8 @@ static void init_ssl_ctx(SSL_CTX *ssl_ctx) {
|
|||||||
SSL_CTX_set_options(ssl_ctx, SSL_OP_ALL | SSL_OP_NO_SSLv2);
|
SSL_CTX_set_options(ssl_ctx, SSL_OP_ALL | SSL_OP_NO_SSLv2);
|
||||||
SSL_CTX_set_mode(ssl_ctx, SSL_MODE_AUTO_RETRY);
|
SSL_CTX_set_mode(ssl_ctx, SSL_MODE_AUTO_RETRY);
|
||||||
SSL_CTX_set_mode(ssl_ctx, SSL_MODE_RELEASE_BUFFERS);
|
SSL_CTX_set_mode(ssl_ctx, SSL_MODE_RELEASE_BUFFERS);
|
||||||
/* Set NPN callback */
|
|
||||||
#ifndef OPENSSL_NO_NEXTPROTONEG
|
|
||||||
SSL_CTX_set_next_proto_select_cb(ssl_ctx, select_next_proto_cb, NULL);
|
|
||||||
#endif /* !OPENSSL_NO_NEXTPROTONEG */
|
|
||||||
|
|
||||||
#if OPENSSL_VERSION_NUMBER >= 0x10002000L
|
|
||||||
SSL_CTX_set_alpn_protos(ssl_ctx, (const unsigned char *)"\x02h2", 3);
|
SSL_CTX_set_alpn_protos(ssl_ctx, (const unsigned char *)"\x02h2", 3);
|
||||||
#endif /* OPENSSL_VERSION_NUMBER >= 0x10002000L */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ssl_handshake(SSL *ssl, int fd) {
|
static void ssl_handshake(SSL *ssl, int fd) {
|
||||||
@@ -487,7 +461,7 @@ static void submit_request(struct Connection *connection, struct Request *req) {
|
|||||||
MAKE_NV("accept", "*/*"),
|
MAKE_NV("accept", "*/*"),
|
||||||
MAKE_NV("user-agent", "nghttp2/" NGHTTP2_VERSION)};
|
MAKE_NV("user-agent", "nghttp2/" NGHTTP2_VERSION)};
|
||||||
|
|
||||||
stream_id = nghttp2_submit_request(connection->session, NULL, nva,
|
stream_id = nghttp2_submit_request2(connection->session, NULL, nva,
|
||||||
sizeof(nva) / sizeof(nva[0]), NULL, req);
|
sizeof(nva) / sizeof(nva[0]), NULL, req);
|
||||||
|
|
||||||
if (stream_id < 0) {
|
if (stream_id < 0) {
|
||||||
@@ -719,19 +693,6 @@ int main(int argc, char **argv) {
|
|||||||
act.sa_handler = SIG_IGN;
|
act.sa_handler = SIG_IGN;
|
||||||
sigaction(SIGPIPE, &act, 0);
|
sigaction(SIGPIPE, &act, 0);
|
||||||
|
|
||||||
#if OPENSSL_VERSION_NUMBER >= 0x1010000fL
|
|
||||||
/* No explicit initialization is required. */
|
|
||||||
#elif defined(OPENSSL_IS_BORINGSSL)
|
|
||||||
CRYPTO_library_init();
|
|
||||||
#else /* !(OPENSSL_VERSION_NUMBER >= 0x1010000fL) && \
|
|
||||||
!defined(OPENSSL_IS_BORINGSSL) */
|
|
||||||
OPENSSL_config(NULL);
|
|
||||||
SSL_load_error_strings();
|
|
||||||
SSL_library_init();
|
|
||||||
OpenSSL_add_all_algorithms();
|
|
||||||
#endif /* !(OPENSSL_VERSION_NUMBER >= 0x1010000fL) && \
|
|
||||||
!defined(OPENSSL_IS_BORINGSSL) */
|
|
||||||
|
|
||||||
rv = parse_uri(&uri, argv[1]);
|
rv = parse_uri(&uri, argv[1]);
|
||||||
if (rv != 0) {
|
if (rv != 0) {
|
||||||
die("parse_uri failed");
|
die("parse_uri failed");
|
||||||
|
|||||||
@@ -29,6 +29,7 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
#define NGHTTP2_NO_SSIZE_T
|
||||||
#include <nghttp2/nghttp2.h>
|
#include <nghttp2/nghttp2.h>
|
||||||
|
|
||||||
#define MAKE_NV(K, V) \
|
#define MAKE_NV(K, V) \
|
||||||
@@ -93,7 +94,7 @@ int main(void) {
|
|||||||
static void deflate(nghttp2_hd_deflater *deflater,
|
static void deflate(nghttp2_hd_deflater *deflater,
|
||||||
nghttp2_hd_inflater *inflater, const nghttp2_nv *const nva,
|
nghttp2_hd_inflater *inflater, const nghttp2_nv *const nva,
|
||||||
size_t nvlen) {
|
size_t nvlen) {
|
||||||
ssize_t rv;
|
nghttp2_ssize rv;
|
||||||
uint8_t *buf;
|
uint8_t *buf;
|
||||||
size_t buflen;
|
size_t buflen;
|
||||||
size_t outlen;
|
size_t outlen;
|
||||||
@@ -118,10 +119,10 @@ static void deflate(nghttp2_hd_deflater *deflater,
|
|||||||
buflen = nghttp2_hd_deflate_bound(deflater, nva, nvlen);
|
buflen = nghttp2_hd_deflate_bound(deflater, nva, nvlen);
|
||||||
buf = malloc(buflen);
|
buf = malloc(buflen);
|
||||||
|
|
||||||
rv = nghttp2_hd_deflate_hd(deflater, buf, buflen, nva, nvlen);
|
rv = nghttp2_hd_deflate_hd2(deflater, buf, buflen, nva, nvlen);
|
||||||
|
|
||||||
if (rv < 0) {
|
if (rv < 0) {
|
||||||
fprintf(stderr, "nghttp2_hd_deflate_hd() failed with error: %s\n",
|
fprintf(stderr, "nghttp2_hd_deflate_hd2() failed with error: %s\n",
|
||||||
nghttp2_strerror((int)rv));
|
nghttp2_strerror((int)rv));
|
||||||
|
|
||||||
free(buf);
|
free(buf);
|
||||||
@@ -166,17 +167,18 @@ static void deflate(nghttp2_hd_deflater *deflater,
|
|||||||
|
|
||||||
int inflate_header_block(nghttp2_hd_inflater *inflater, uint8_t *in,
|
int inflate_header_block(nghttp2_hd_inflater *inflater, uint8_t *in,
|
||||||
size_t inlen, int final) {
|
size_t inlen, int final) {
|
||||||
ssize_t rv;
|
nghttp2_ssize rv;
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
nghttp2_nv nv;
|
nghttp2_nv nv;
|
||||||
int inflate_flags = 0;
|
int inflate_flags = 0;
|
||||||
size_t proclen;
|
size_t proclen;
|
||||||
|
|
||||||
rv = nghttp2_hd_inflate_hd(inflater, &nv, &inflate_flags, in, inlen, final);
|
rv =
|
||||||
|
nghttp2_hd_inflate_hd3(inflater, &nv, &inflate_flags, in, inlen, final);
|
||||||
|
|
||||||
if (rv < 0) {
|
if (rv < 0) {
|
||||||
fprintf(stderr, "inflate failed with error code %zd", rv);
|
fprintf(stderr, "inflate failed with error code %td", rv);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -63,6 +63,7 @@ char *strndup(const char *s, size_t size);
|
|||||||
#include <event2/bufferevent_ssl.h>
|
#include <event2/bufferevent_ssl.h>
|
||||||
#include <event2/dns.h>
|
#include <event2/dns.h>
|
||||||
|
|
||||||
|
#define NGHTTP2_NO_SSIZE_T
|
||||||
#include <nghttp2/nghttp2.h>
|
#include <nghttp2/nghttp2.h>
|
||||||
|
|
||||||
#include "url-parser/url_parser.h"
|
#include "url-parser/url_parser.h"
|
||||||
@@ -196,18 +197,19 @@ static void print_headers(FILE *f, nghttp2_nv *nva, size_t nvlen) {
|
|||||||
fprintf(f, "\n");
|
fprintf(f, "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* nghttp2_send_callback. Here we transmit the |data|, |length| bytes,
|
/* nghttp2_send_callback2. Here we transmit the |data|, |length|
|
||||||
to the network. Because we are using libevent bufferevent, we just
|
bytes, to the network. Because we are using libevent bufferevent,
|
||||||
write those bytes into bufferevent buffer. */
|
we just write those bytes into bufferevent buffer. */
|
||||||
static ssize_t send_callback(nghttp2_session *session, const uint8_t *data,
|
static nghttp2_ssize send_callback(nghttp2_session *session,
|
||||||
size_t length, int flags, void *user_data) {
|
const uint8_t *data, size_t length,
|
||||||
|
int flags, void *user_data) {
|
||||||
http2_session_data *session_data = (http2_session_data *)user_data;
|
http2_session_data *session_data = (http2_session_data *)user_data;
|
||||||
struct bufferevent *bev = session_data->bev;
|
struct bufferevent *bev = session_data->bev;
|
||||||
(void)session;
|
(void)session;
|
||||||
(void)flags;
|
(void)flags;
|
||||||
|
|
||||||
bufferevent_write(bev, data, length);
|
bufferevent_write(bev, data, length);
|
||||||
return (ssize_t)length;
|
return (nghttp2_ssize)length;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* nghttp2_on_header_callback: Called when nghttp2 library emits
|
/* nghttp2_on_header_callback: Called when nghttp2 library emits
|
||||||
@@ -308,23 +310,6 @@ static int on_stream_close_callback(nghttp2_session *session, int32_t stream_id,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef OPENSSL_NO_NEXTPROTONEG
|
|
||||||
/* NPN TLS extension client callback. We check that server advertised
|
|
||||||
the HTTP/2 protocol the nghttp2 library supports. If not, exit
|
|
||||||
the program. */
|
|
||||||
static int select_next_proto_cb(SSL *ssl, unsigned char **out,
|
|
||||||
unsigned char *outlen, const unsigned char *in,
|
|
||||||
unsigned int inlen, void *arg) {
|
|
||||||
(void)ssl;
|
|
||||||
(void)arg;
|
|
||||||
|
|
||||||
if (nghttp2_select_next_protocol(out, outlen, in, inlen) <= 0) {
|
|
||||||
errx(1, "Server did not advertise " NGHTTP2_PROTO_VERSION_ID);
|
|
||||||
}
|
|
||||||
return SSL_TLSEXT_ERR_OK;
|
|
||||||
}
|
|
||||||
#endif /* !OPENSSL_NO_NEXTPROTONEG */
|
|
||||||
|
|
||||||
/* Create SSL_CTX. */
|
/* Create SSL_CTX. */
|
||||||
static SSL_CTX *create_ssl_ctx(void) {
|
static SSL_CTX *create_ssl_ctx(void) {
|
||||||
SSL_CTX *ssl_ctx;
|
SSL_CTX *ssl_ctx;
|
||||||
@@ -337,13 +322,8 @@ static SSL_CTX *create_ssl_ctx(void) {
|
|||||||
SSL_OP_ALL | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 |
|
SSL_OP_ALL | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 |
|
||||||
SSL_OP_NO_COMPRESSION |
|
SSL_OP_NO_COMPRESSION |
|
||||||
SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION);
|
SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION);
|
||||||
#ifndef OPENSSL_NO_NEXTPROTONEG
|
|
||||||
SSL_CTX_set_next_proto_select_cb(ssl_ctx, select_next_proto_cb, NULL);
|
|
||||||
#endif /* !OPENSSL_NO_NEXTPROTONEG */
|
|
||||||
|
|
||||||
#if OPENSSL_VERSION_NUMBER >= 0x10002000L
|
|
||||||
SSL_CTX_set_alpn_protos(ssl_ctx, (const unsigned char *)"\x02h2", 3);
|
SSL_CTX_set_alpn_protos(ssl_ctx, (const unsigned char *)"\x02h2", 3);
|
||||||
#endif /* OPENSSL_VERSION_NUMBER >= 0x10002000L */
|
|
||||||
|
|
||||||
return ssl_ctx;
|
return ssl_ctx;
|
||||||
}
|
}
|
||||||
@@ -364,7 +344,7 @@ static void initialize_nghttp2_session(http2_session_data *session_data) {
|
|||||||
|
|
||||||
nghttp2_session_callbacks_new(&callbacks);
|
nghttp2_session_callbacks_new(&callbacks);
|
||||||
|
|
||||||
nghttp2_session_callbacks_set_send_callback(callbacks, send_callback);
|
nghttp2_session_callbacks_set_send_callback2(callbacks, send_callback);
|
||||||
|
|
||||||
nghttp2_session_callbacks_set_on_frame_recv_callback(callbacks,
|
nghttp2_session_callbacks_set_on_frame_recv_callback(callbacks,
|
||||||
on_frame_recv_callback);
|
on_frame_recv_callback);
|
||||||
@@ -425,7 +405,7 @@ static void submit_request(http2_session_data *session_data) {
|
|||||||
MAKE_NV(":path", stream_data->path, stream_data->pathlen)};
|
MAKE_NV(":path", stream_data->path, stream_data->pathlen)};
|
||||||
fprintf(stderr, "Request headers:\n");
|
fprintf(stderr, "Request headers:\n");
|
||||||
print_headers(stderr, hdrs, ARRLEN(hdrs));
|
print_headers(stderr, hdrs, ARRLEN(hdrs));
|
||||||
stream_id = nghttp2_submit_request(session_data->session, NULL, hdrs,
|
stream_id = nghttp2_submit_request2(session_data->session, NULL, hdrs,
|
||||||
ARRLEN(hdrs), NULL, stream_data);
|
ARRLEN(hdrs), NULL, stream_data);
|
||||||
if (stream_id < 0) {
|
if (stream_id < 0) {
|
||||||
errx(1, "Could not submit HTTP request: %s", nghttp2_strerror(stream_id));
|
errx(1, "Could not submit HTTP request: %s", nghttp2_strerror(stream_id));
|
||||||
@@ -453,12 +433,12 @@ static int session_send(http2_session_data *session_data) {
|
|||||||
context. To send them, we call session_send() in the end. */
|
context. To send them, we call session_send() in the end. */
|
||||||
static void readcb(struct bufferevent *bev, void *ptr) {
|
static void readcb(struct bufferevent *bev, void *ptr) {
|
||||||
http2_session_data *session_data = (http2_session_data *)ptr;
|
http2_session_data *session_data = (http2_session_data *)ptr;
|
||||||
ssize_t readlen;
|
nghttp2_ssize readlen;
|
||||||
struct evbuffer *input = bufferevent_get_input(bev);
|
struct evbuffer *input = bufferevent_get_input(bev);
|
||||||
size_t datalen = evbuffer_get_length(input);
|
size_t datalen = evbuffer_get_length(input);
|
||||||
unsigned char *data = evbuffer_pullup(input, -1);
|
unsigned char *data = evbuffer_pullup(input, -1);
|
||||||
|
|
||||||
readlen = nghttp2_session_mem_recv(session_data->session, data, datalen);
|
readlen = nghttp2_session_mem_recv2(session_data->session, data, datalen);
|
||||||
if (readlen < 0) {
|
if (readlen < 0) {
|
||||||
warnx("Fatal error: %s", nghttp2_strerror((int)readlen));
|
warnx("Fatal error: %s", nghttp2_strerror((int)readlen));
|
||||||
delete_http2_session_data(session_data);
|
delete_http2_session_data(session_data);
|
||||||
@@ -508,14 +488,9 @@ static void eventcb(struct bufferevent *bev, short events, void *ptr) {
|
|||||||
|
|
||||||
ssl = bufferevent_openssl_get_ssl(session_data->bev);
|
ssl = bufferevent_openssl_get_ssl(session_data->bev);
|
||||||
|
|
||||||
#ifndef OPENSSL_NO_NEXTPROTONEG
|
|
||||||
SSL_get0_next_proto_negotiated(ssl, &alpn, &alpnlen);
|
|
||||||
#endif /* !OPENSSL_NO_NEXTPROTONEG */
|
|
||||||
#if OPENSSL_VERSION_NUMBER >= 0x10002000L
|
|
||||||
if (alpn == NULL) {
|
if (alpn == NULL) {
|
||||||
SSL_get0_alpn_selected(ssl, &alpn, &alpnlen);
|
SSL_get0_alpn_selected(ssl, &alpn, &alpnlen);
|
||||||
}
|
}
|
||||||
#endif /* OPENSSL_VERSION_NUMBER >= 0x10002000L */
|
|
||||||
|
|
||||||
if (alpn == NULL || alpnlen != 2 || memcmp("h2", alpn, 2) != 0) {
|
if (alpn == NULL || alpnlen != 2 || memcmp("h2", alpn, 2) != 0) {
|
||||||
fprintf(stderr, "h2 is not negotiated\n");
|
fprintf(stderr, "h2 is not negotiated\n");
|
||||||
@@ -617,19 +592,6 @@ int main(int argc, char **argv) {
|
|||||||
act.sa_handler = SIG_IGN;
|
act.sa_handler = SIG_IGN;
|
||||||
sigaction(SIGPIPE, &act, NULL);
|
sigaction(SIGPIPE, &act, NULL);
|
||||||
|
|
||||||
#if OPENSSL_VERSION_NUMBER >= 0x1010000fL
|
|
||||||
/* No explicit initialization is required. */
|
|
||||||
#elif defined(OPENSSL_IS_BORINGSSL)
|
|
||||||
CRYPTO_library_init();
|
|
||||||
#else /* !(OPENSSL_VERSION_NUMBER >= 0x1010000fL) && \
|
|
||||||
!defined(OPENSSL_IS_BORINGSSL) */
|
|
||||||
OPENSSL_config(NULL);
|
|
||||||
SSL_load_error_strings();
|
|
||||||
SSL_library_init();
|
|
||||||
OpenSSL_add_all_algorithms();
|
|
||||||
#endif /* !(OPENSSL_VERSION_NUMBER >= 0x1010000fL) && \
|
|
||||||
!defined(OPENSSL_IS_BORINGSSL) */
|
|
||||||
|
|
||||||
run(argv[1]);
|
run(argv[1]);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -71,6 +71,7 @@
|
|||||||
#include <event2/bufferevent_ssl.h>
|
#include <event2/bufferevent_ssl.h>
|
||||||
#include <event2/listener.h>
|
#include <event2/listener.h>
|
||||||
|
|
||||||
|
#define NGHTTP2_NO_SSIZE_T
|
||||||
#include <nghttp2/nghttp2.h>
|
#include <nghttp2/nghttp2.h>
|
||||||
|
|
||||||
#define OUTPUT_WOULDBLOCK_THRESHOLD (1 << 16)
|
#define OUTPUT_WOULDBLOCK_THRESHOLD (1 << 16)
|
||||||
@@ -106,22 +107,6 @@ struct app_context {
|
|||||||
struct event_base *evbase;
|
struct event_base *evbase;
|
||||||
};
|
};
|
||||||
|
|
||||||
static unsigned char next_proto_list[256];
|
|
||||||
static size_t next_proto_list_len;
|
|
||||||
|
|
||||||
#ifndef OPENSSL_NO_NEXTPROTONEG
|
|
||||||
static int next_proto_cb(SSL *ssl, const unsigned char **data,
|
|
||||||
unsigned int *len, void *arg) {
|
|
||||||
(void)ssl;
|
|
||||||
(void)arg;
|
|
||||||
|
|
||||||
*data = next_proto_list;
|
|
||||||
*len = (unsigned int)next_proto_list_len;
|
|
||||||
return SSL_TLSEXT_ERR_OK;
|
|
||||||
}
|
|
||||||
#endif /* !OPENSSL_NO_NEXTPROTONEG */
|
|
||||||
|
|
||||||
#if OPENSSL_VERSION_NUMBER >= 0x10002000L
|
|
||||||
static int alpn_select_proto_cb(SSL *ssl, const unsigned char **out,
|
static int alpn_select_proto_cb(SSL *ssl, const unsigned char **out,
|
||||||
unsigned char *outlen, const unsigned char *in,
|
unsigned char *outlen, const unsigned char *in,
|
||||||
unsigned int inlen, void *arg) {
|
unsigned int inlen, void *arg) {
|
||||||
@@ -129,7 +114,7 @@ static int alpn_select_proto_cb(SSL *ssl, const unsigned char **out,
|
|||||||
(void)ssl;
|
(void)ssl;
|
||||||
(void)arg;
|
(void)arg;
|
||||||
|
|
||||||
rv = nghttp2_select_next_protocol((unsigned char **)out, outlen, in, inlen);
|
rv = nghttp2_select_alpn(out, outlen, in, inlen);
|
||||||
|
|
||||||
if (rv != 1) {
|
if (rv != 1) {
|
||||||
return SSL_TLSEXT_ERR_NOACK;
|
return SSL_TLSEXT_ERR_NOACK;
|
||||||
@@ -137,7 +122,6 @@ static int alpn_select_proto_cb(SSL *ssl, const unsigned char **out,
|
|||||||
|
|
||||||
return SSL_TLSEXT_ERR_OK;
|
return SSL_TLSEXT_ERR_OK;
|
||||||
}
|
}
|
||||||
#endif /* OPENSSL_VERSION_NUMBER >= 0x10002000L */
|
|
||||||
|
|
||||||
/* Create SSL_CTX. */
|
/* Create SSL_CTX. */
|
||||||
static SSL_CTX *create_ssl_ctx(const char *key_file, const char *cert_file) {
|
static SSL_CTX *create_ssl_ctx(const char *key_file, const char *cert_file) {
|
||||||
@@ -177,18 +161,7 @@ static SSL_CTX *create_ssl_ctx(const char *key_file, const char *cert_file) {
|
|||||||
errx(1, "Could not read certificate file %s", cert_file);
|
errx(1, "Could not read certificate file %s", cert_file);
|
||||||
}
|
}
|
||||||
|
|
||||||
next_proto_list[0] = NGHTTP2_PROTO_VERSION_ID_LEN;
|
|
||||||
memcpy(&next_proto_list[1], NGHTTP2_PROTO_VERSION_ID,
|
|
||||||
NGHTTP2_PROTO_VERSION_ID_LEN);
|
|
||||||
next_proto_list_len = 1 + NGHTTP2_PROTO_VERSION_ID_LEN;
|
|
||||||
|
|
||||||
#ifndef OPENSSL_NO_NEXTPROTONEG
|
|
||||||
SSL_CTX_set_next_protos_advertised_cb(ssl_ctx, next_proto_cb, NULL);
|
|
||||||
#endif /* !OPENSSL_NO_NEXTPROTONEG */
|
|
||||||
|
|
||||||
#if OPENSSL_VERSION_NUMBER >= 0x10002000L
|
|
||||||
SSL_CTX_set_alpn_select_cb(ssl_ctx, alpn_select_proto_cb, NULL);
|
SSL_CTX_set_alpn_select_cb(ssl_ctx, alpn_select_proto_cb, NULL);
|
||||||
#endif /* OPENSSL_VERSION_NUMBER >= 0x10002000L */
|
|
||||||
|
|
||||||
return ssl_ctx;
|
return ssl_ctx;
|
||||||
}
|
}
|
||||||
@@ -305,16 +278,16 @@ static int session_send(http2_session_data *session_data) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Read the data in the bufferevent and feed them into nghttp2 library
|
/* Read the data in the bufferevent and feed them into nghttp2 library
|
||||||
function. Invocation of nghttp2_session_mem_recv() may make
|
function. Invocation of nghttp2_session_mem_recv2() may make
|
||||||
additional pending frames, so call session_send() at the end of the
|
additional pending frames, so call session_send() at the end of the
|
||||||
function. */
|
function. */
|
||||||
static int session_recv(http2_session_data *session_data) {
|
static int session_recv(http2_session_data *session_data) {
|
||||||
ssize_t readlen;
|
nghttp2_ssize readlen;
|
||||||
struct evbuffer *input = bufferevent_get_input(session_data->bev);
|
struct evbuffer *input = bufferevent_get_input(session_data->bev);
|
||||||
size_t datalen = evbuffer_get_length(input);
|
size_t datalen = evbuffer_get_length(input);
|
||||||
unsigned char *data = evbuffer_pullup(input, -1);
|
unsigned char *data = evbuffer_pullup(input, -1);
|
||||||
|
|
||||||
readlen = nghttp2_session_mem_recv(session_data->session, data, datalen);
|
readlen = nghttp2_session_mem_recv2(session_data->session, data, datalen);
|
||||||
if (readlen < 0) {
|
if (readlen < 0) {
|
||||||
warnx("Fatal error: %s", nghttp2_strerror((int)readlen));
|
warnx("Fatal error: %s", nghttp2_strerror((int)readlen));
|
||||||
return -1;
|
return -1;
|
||||||
@@ -329,8 +302,9 @@ static int session_recv(http2_session_data *session_data) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ssize_t send_callback(nghttp2_session *session, const uint8_t *data,
|
static nghttp2_ssize send_callback(nghttp2_session *session,
|
||||||
size_t length, int flags, void *user_data) {
|
const uint8_t *data, size_t length,
|
||||||
|
int flags, void *user_data) {
|
||||||
http2_session_data *session_data = (http2_session_data *)user_data;
|
http2_session_data *session_data = (http2_session_data *)user_data;
|
||||||
struct bufferevent *bev = session_data->bev;
|
struct bufferevent *bev = session_data->bev;
|
||||||
(void)session;
|
(void)session;
|
||||||
@@ -342,7 +316,7 @@ static ssize_t send_callback(nghttp2_session *session, const uint8_t *data,
|
|||||||
return NGHTTP2_ERR_WOULDBLOCK;
|
return NGHTTP2_ERR_WOULDBLOCK;
|
||||||
}
|
}
|
||||||
bufferevent_write(bev, data, length);
|
bufferevent_write(bev, data, length);
|
||||||
return (ssize_t)length;
|
return (nghttp2_ssize)length;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Returns nonzero if the string |s| ends with the substring |sub| */
|
/* Returns nonzero if the string |s| ends with the substring |sub| */
|
||||||
@@ -398,9 +372,9 @@ static char *percent_decode(const uint8_t *value, size_t valuelen) {
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ssize_t file_read_callback(nghttp2_session *session, int32_t stream_id,
|
static nghttp2_ssize file_read_callback(nghttp2_session *session,
|
||||||
uint8_t *buf, size_t length,
|
int32_t stream_id, uint8_t *buf,
|
||||||
uint32_t *data_flags,
|
size_t length, uint32_t *data_flags,
|
||||||
nghttp2_data_source *source,
|
nghttp2_data_source *source,
|
||||||
void *user_data) {
|
void *user_data) {
|
||||||
int fd = source->fd;
|
int fd = source->fd;
|
||||||
@@ -417,17 +391,17 @@ static ssize_t file_read_callback(nghttp2_session *session, int32_t stream_id,
|
|||||||
if (r == 0) {
|
if (r == 0) {
|
||||||
*data_flags |= NGHTTP2_DATA_FLAG_EOF;
|
*data_flags |= NGHTTP2_DATA_FLAG_EOF;
|
||||||
}
|
}
|
||||||
return r;
|
return (nghttp2_ssize)r;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int send_response(nghttp2_session *session, int32_t stream_id,
|
static int send_response(nghttp2_session *session, int32_t stream_id,
|
||||||
nghttp2_nv *nva, size_t nvlen, int fd) {
|
nghttp2_nv *nva, size_t nvlen, int fd) {
|
||||||
int rv;
|
int rv;
|
||||||
nghttp2_data_provider data_prd;
|
nghttp2_data_provider2 data_prd;
|
||||||
data_prd.source.fd = fd;
|
data_prd.source.fd = fd;
|
||||||
data_prd.read_callback = file_read_callback;
|
data_prd.read_callback = file_read_callback;
|
||||||
|
|
||||||
rv = nghttp2_submit_response(session, stream_id, nva, nvlen, &data_prd);
|
rv = nghttp2_submit_response2(session, stream_id, nva, nvlen, &data_prd);
|
||||||
if (rv != 0) {
|
if (rv != 0) {
|
||||||
warnx("Fatal error: %s", nghttp2_strerror(rv));
|
warnx("Fatal error: %s", nghttp2_strerror(rv));
|
||||||
return -1;
|
return -1;
|
||||||
@@ -618,7 +592,7 @@ static void initialize_nghttp2_session(http2_session_data *session_data) {
|
|||||||
|
|
||||||
nghttp2_session_callbacks_new(&callbacks);
|
nghttp2_session_callbacks_new(&callbacks);
|
||||||
|
|
||||||
nghttp2_session_callbacks_set_send_callback(callbacks, send_callback);
|
nghttp2_session_callbacks_set_send_callback2(callbacks, send_callback);
|
||||||
|
|
||||||
nghttp2_session_callbacks_set_on_frame_recv_callback(callbacks,
|
nghttp2_session_callbacks_set_on_frame_recv_callback(callbacks,
|
||||||
on_frame_recv_callback);
|
on_frame_recv_callback);
|
||||||
@@ -702,14 +676,7 @@ static void eventcb(struct bufferevent *bev, short events, void *ptr) {
|
|||||||
|
|
||||||
ssl = bufferevent_openssl_get_ssl(session_data->bev);
|
ssl = bufferevent_openssl_get_ssl(session_data->bev);
|
||||||
|
|
||||||
#ifndef OPENSSL_NO_NEXTPROTONEG
|
|
||||||
SSL_get0_next_proto_negotiated(ssl, &alpn, &alpnlen);
|
|
||||||
#endif /* !OPENSSL_NO_NEXTPROTONEG */
|
|
||||||
#if OPENSSL_VERSION_NUMBER >= 0x10002000L
|
|
||||||
if (alpn == NULL) {
|
|
||||||
SSL_get0_alpn_selected(ssl, &alpn, &alpnlen);
|
SSL_get0_alpn_selected(ssl, &alpn, &alpnlen);
|
||||||
}
|
|
||||||
#endif /* OPENSSL_VERSION_NUMBER >= 0x10002000L */
|
|
||||||
|
|
||||||
if (alpn == NULL || alpnlen != 2 || memcmp("h2", alpn, 2) != 0) {
|
if (alpn == NULL || alpnlen != 2 || memcmp("h2", alpn, 2) != 0) {
|
||||||
fprintf(stderr, "%s h2 is not negotiated\n", session_data->client_addr);
|
fprintf(stderr, "%s h2 is not negotiated\n", session_data->client_addr);
|
||||||
@@ -817,19 +784,6 @@ int main(int argc, char **argv) {
|
|||||||
act.sa_handler = SIG_IGN;
|
act.sa_handler = SIG_IGN;
|
||||||
sigaction(SIGPIPE, &act, NULL);
|
sigaction(SIGPIPE, &act, NULL);
|
||||||
|
|
||||||
#if OPENSSL_VERSION_NUMBER >= 0x1010000fL
|
|
||||||
/* No explicit initialization is required. */
|
|
||||||
#elif defined(OPENSSL_IS_BORINGSSL)
|
|
||||||
CRYPTO_library_init();
|
|
||||||
#else /* !(OPENSSL_VERSION_NUMBER >= 0x1010000fL) && \
|
|
||||||
!defined(OPENSSL_IS_BORINGSSL) */
|
|
||||||
OPENSSL_config(NULL);
|
|
||||||
SSL_load_error_strings();
|
|
||||||
SSL_library_init();
|
|
||||||
OpenSSL_add_all_algorithms();
|
|
||||||
#endif /* !(OPENSSL_VERSION_NUMBER >= 0x1010000fL) && \
|
|
||||||
!defined(OPENSSL_IS_BORINGSSL) */
|
|
||||||
|
|
||||||
run(argv[1], argv[2], argv[3]);
|
run(argv[1], argv[2], argv[3]);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ namespace {
|
|||||||
void send_pending(nghttp2_session *session) {
|
void send_pending(nghttp2_session *session) {
|
||||||
for (;;) {
|
for (;;) {
|
||||||
const uint8_t *data;
|
const uint8_t *data;
|
||||||
auto n = nghttp2_session_mem_send(session, &data);
|
auto n = nghttp2_session_mem_send2(session, &data);
|
||||||
if (n == 0) {
|
if (n == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -70,7 +70,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
|
|||||||
nghttp2_settings_entry iv{NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS, 100};
|
nghttp2_settings_entry iv{NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS, 100};
|
||||||
nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, &iv, 1);
|
nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, &iv, 1);
|
||||||
send_pending(session);
|
send_pending(session);
|
||||||
nghttp2_session_mem_recv(session, data, size);
|
nghttp2_session_mem_recv2(session, data, size);
|
||||||
send_pending(session);
|
send_pending(session);
|
||||||
|
|
||||||
nghttp2_session_del(session);
|
nghttp2_session_del(session);
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ namespace {
|
|||||||
void send_pending(nghttp2_session *session) {
|
void send_pending(nghttp2_session *session) {
|
||||||
for (;;) {
|
for (;;) {
|
||||||
const uint8_t *data;
|
const uint8_t *data;
|
||||||
auto n = nghttp2_session_mem_send(session, &data);
|
auto n = nghttp2_session_mem_send2(session, &data);
|
||||||
if (n == 0) {
|
if (n == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -87,7 +87,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
|
|||||||
send_pending(session);
|
send_pending(session);
|
||||||
|
|
||||||
std::vector<uint8_t> d = data_provider.ConsumeRemainingBytes<uint8_t>();
|
std::vector<uint8_t> d = data_provider.ConsumeRemainingBytes<uint8_t>();
|
||||||
nghttp2_session_mem_recv(session, d.data(), d.size());
|
nghttp2_session_mem_recv2(session, d.data(), d.size());
|
||||||
|
|
||||||
send_pending(session);
|
send_pending(session);
|
||||||
|
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ HEADERS = [
|
|||||||
"early-data",
|
"early-data",
|
||||||
"sec-websocket-accept",
|
"sec-websocket-accept",
|
||||||
"sec-websocket-key",
|
"sec-websocket-key",
|
||||||
|
"priority",
|
||||||
# disallowed h1 headers
|
# disallowed h1 headers
|
||||||
'connection',
|
'connection',
|
||||||
'keep-alive',
|
'keep-alive',
|
||||||
|
|||||||
@@ -200,6 +200,10 @@ OPTIONS = [
|
|||||||
"frontend-quic-initial-rtt",
|
"frontend-quic-initial-rtt",
|
||||||
"require-http-scheme",
|
"require-http-scheme",
|
||||||
"tls-ktls",
|
"tls-ktls",
|
||||||
|
"alpn-list",
|
||||||
|
"frontend-header-timeout",
|
||||||
|
"frontend-http2-idle-timeout",
|
||||||
|
"frontend-http3-idle-timeout",
|
||||||
]
|
]
|
||||||
|
|
||||||
LOGVARS = [
|
LOGVARS = [
|
||||||
@@ -237,5 +241,5 @@ LOGVARS = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
gentokenlookup(OPTIONS, 'SHRPX_OPTID_', value_type='char', comp_fun='util::strieq_l')
|
gentokenlookup(OPTIONS, 'SHRPX_OPTID_', comp_fun='util::strieq')
|
||||||
gentokenlookup(LOGVARS, 'LogFragmentType::', value_type='char', comp_fun='util::strieq_l', return_type='LogFragmentType', fail_value='LogFragmentType::NONE')
|
gentokenlookup(LOGVARS, 'LogFragmentType::', comp_fun='util::strieq', return_type='LogFragmentType', fail_value='LogFragmentType::NONE')
|
||||||
|
|||||||
@@ -33,10 +33,10 @@ enum {''')
|
|||||||
{}MAXIDX,
|
{}MAXIDX,
|
||||||
}};'''.format(prefix))
|
}};'''.format(prefix))
|
||||||
|
|
||||||
def gen_index_header(tokens, prefix, value_type, comp_fun, return_type, fail_value):
|
def gen_index_header(tokens, prefix, comp_fun, return_type, fail_value):
|
||||||
print('''\
|
print('''\
|
||||||
{} lookup_token(const {} *name, size_t namelen) {{
|
{} lookup_token(const StringRef &name) {{
|
||||||
switch (namelen) {{'''.format(return_type, value_type))
|
switch (name.size()) {{'''.format(return_type))
|
||||||
b = build_header(tokens)
|
b = build_header(tokens)
|
||||||
for size in sorted(b.keys()):
|
for size in sorted(b.keys()):
|
||||||
ents = b[size]
|
ents = b[size]
|
||||||
@@ -50,7 +50,7 @@ def gen_index_header(tokens, prefix, value_type, comp_fun, return_type, fail_val
|
|||||||
case '{}':'''.format(c))
|
case '{}':'''.format(c))
|
||||||
for k in headers:
|
for k in headers:
|
||||||
print('''\
|
print('''\
|
||||||
if ({}("{}", name, {})) {{
|
if ({}("{}"_sr, name, {})) {{
|
||||||
return {};
|
return {};
|
||||||
}}'''.format(comp_fun, k[:-1], size - 1, to_enum_hd(k, prefix)))
|
}}'''.format(comp_fun, k[:-1], size - 1, to_enum_hd(k, prefix)))
|
||||||
print('''\
|
print('''\
|
||||||
@@ -63,7 +63,7 @@ def gen_index_header(tokens, prefix, value_type, comp_fun, return_type, fail_val
|
|||||||
return {};
|
return {};
|
||||||
}}'''.format(fail_value))
|
}}'''.format(fail_value))
|
||||||
|
|
||||||
def gentokenlookup(tokens, prefix, value_type='uint8_t', comp_fun='util::streq_l', return_type='int', fail_value='-1'):
|
def gentokenlookup(tokens, prefix, comp_fun='util::streq', return_type='int', fail_value='-1'):
|
||||||
gen_enum(tokens, prefix)
|
gen_enum(tokens, prefix)
|
||||||
print()
|
print()
|
||||||
gen_index_header(tokens, prefix, value_type, comp_fun, return_type, fail_value)
|
gen_index_header(tokens, prefix, comp_fun, return_type, fail_value)
|
||||||
|
|||||||
28
go.mod
28
go.mod
@@ -1,26 +1,24 @@
|
|||||||
module github.com/nghttp2/nghttp2
|
module github.com/nghttp2/nghttp2
|
||||||
|
|
||||||
go 1.20
|
go 1.21.1
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/bradfitz/gomemcache v0.0.0-20230124162541-5f7a7d875746
|
github.com/bradfitz/gomemcache v0.0.0-20230905024940-24af94b03874
|
||||||
github.com/quic-go/quic-go v0.35.1
|
github.com/quic-go/quic-go v0.43.1
|
||||||
github.com/tatsuhiro-t/go-nghttp2 v0.0.0-20150408091349-4742878d9c90
|
github.com/tatsuhiro-t/go-nghttp2 v0.0.0-20240121064059-46ccb0a462a8
|
||||||
golang.org/x/net v0.15.0
|
golang.org/x/net v0.24.0
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 // indirect
|
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect
|
||||||
github.com/golang/mock v1.6.0 // indirect
|
|
||||||
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 // indirect
|
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 // indirect
|
||||||
github.com/onsi/ginkgo/v2 v2.2.0 // indirect
|
github.com/onsi/ginkgo/v2 v2.9.5 // indirect
|
||||||
github.com/quic-go/qpack v0.4.0 // indirect
|
github.com/quic-go/qpack v0.4.0 // indirect
|
||||||
github.com/quic-go/qtls-go1-19 v0.3.2 // indirect
|
go.uber.org/mock v0.4.0 // indirect
|
||||||
github.com/quic-go/qtls-go1-20 v0.2.2 // indirect
|
golang.org/x/crypto v0.22.0 // indirect
|
||||||
golang.org/x/crypto v0.13.0 // indirect
|
|
||||||
golang.org/x/exp v0.0.0-20221205204356-47842c84f3db // indirect
|
golang.org/x/exp v0.0.0-20221205204356-47842c84f3db // indirect
|
||||||
golang.org/x/mod v0.8.0 // indirect
|
golang.org/x/mod v0.11.0 // indirect
|
||||||
golang.org/x/sys v0.12.0 // indirect
|
golang.org/x/sys v0.19.0 // indirect
|
||||||
golang.org/x/text v0.13.0 // indirect
|
golang.org/x/text v0.14.0 // indirect
|
||||||
golang.org/x/tools v0.6.0 // indirect
|
golang.org/x/tools v0.9.1 // indirect
|
||||||
)
|
)
|
||||||
|
|||||||
97
go.sum
97
go.sum
@@ -1,78 +1,59 @@
|
|||||||
github.com/bradfitz/gomemcache v0.0.0-20230124162541-5f7a7d875746 h1:wAIE/kN63Oig1DdOzN7O+k4AbFh2cCJoKMFXrwRJtzk=
|
github.com/bradfitz/gomemcache v0.0.0-20230905024940-24af94b03874 h1:N7oVaKyGp8bttX0bfZGmcGkjz7DLQXhAn3DNd3T0ous=
|
||||||
github.com/bradfitz/gomemcache v0.0.0-20230124162541-5f7a7d875746/go.mod h1:H0wQNHz2YrLsuXOZozoeDmnHXkNCRmMW0gwFWDfEZDA=
|
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/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/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/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.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 h1:p104kn46Q8WdvHunIJ9dAyjPVtrBPhSr3KT2yUst43I=
|
github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ=
|
||||||
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
|
github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||||
github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc=
|
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI=
|
||||||
github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs=
|
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls=
|
||||||
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
|
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
|
||||||
github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg=
|
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||||
|
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
||||||
|
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||||
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 h1:yAJXTCF9TqKcTiHJAE8dj7HMvPfh66eeA2JYW7eFpSE=
|
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 h1:yAJXTCF9TqKcTiHJAE8dj7HMvPfh66eeA2JYW7eFpSE=
|
||||||
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
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/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||||
github.com/onsi/ginkgo/v2 v2.2.0 h1:3ZNA3L1c5FYDFTTxbFeVGGD8jYvjYauHD30YgLxVsNI=
|
github.com/onsi/ginkgo/v2 v2.9.5 h1:+6Hr4uxzP4XIUyAkg61dWBw8lb/gc4/X5luuxN/EC+Q=
|
||||||
github.com/onsi/ginkgo/v2 v2.2.0/go.mod h1:MEH45j8TBi6u9BMogfbp0stKC5cdGjumZj5Y7AG4VIk=
|
github.com/onsi/ginkgo/v2 v2.9.5/go.mod h1:tvAoo1QUJwNEU2ITftXTpR7R1RbCzoZUOs3RonqW57k=
|
||||||
github.com/onsi/gomega v1.20.1 h1:PA/3qinGoukvymdIDV8pii6tiZgC8kbmJO6Z5+b002Q=
|
github.com/onsi/gomega v1.27.6 h1:ENqfyGeS5AX/rlXDd/ETokDz93u0YufY1Pgxuy/PvWE=
|
||||||
|
github.com/onsi/gomega v1.27.6/go.mod h1:PIQNjfQwkP3aQAH7lf7j87O/5FiNr+ZR8+ipb+qQlhg=
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/quic-go/qpack v0.4.0 h1:Cr9BXA1sQS2SmDUWjSofMPNKmvF6IiIfDRmgU0w1ZCo=
|
github.com/quic-go/qpack v0.4.0 h1:Cr9BXA1sQS2SmDUWjSofMPNKmvF6IiIfDRmgU0w1ZCo=
|
||||||
github.com/quic-go/qpack v0.4.0/go.mod h1:UZVnYIfi5GRk+zI9UMaCPsmZ2xKJP7XBUvVyT1Knj9A=
|
github.com/quic-go/qpack v0.4.0/go.mod h1:UZVnYIfi5GRk+zI9UMaCPsmZ2xKJP7XBUvVyT1Knj9A=
|
||||||
github.com/quic-go/qtls-go1-19 v0.3.2 h1:tFxjCFcTQzK+oMxG6Zcvp4Dq8dx4yD3dDiIiyc86Z5U=
|
github.com/quic-go/quic-go v0.43.1 h1:fLiMNfQVe9q2JvSsiXo4fXOEguXHGGl9+6gLp4RPeZQ=
|
||||||
github.com/quic-go/qtls-go1-19 v0.3.2/go.mod h1:ySOI96ew8lnoKPtSqx2BlI5wCpUVPT05RMAlajtnyOI=
|
github.com/quic-go/quic-go v0.43.1/go.mod h1:132kz4kL3F9vxhW3CtQJLDVwcFe5wdWeJXXijhsO57M=
|
||||||
github.com/quic-go/qtls-go1-20 v0.2.2 h1:WLOPx6OY/hxtTxKV1Zrq20FtXtDEkeY00CGQm8GEa3E=
|
|
||||||
github.com/quic-go/qtls-go1-20 v0.2.2/go.mod h1:JKtK6mjbAVcUTN/9jZpvLbGxvdWIKS8uT7EiStoU1SM=
|
|
||||||
github.com/quic-go/quic-go v0.35.1 h1:b0kzj6b/cQAf05cT0CkQubHM31wiA+xH3IBkxP62poo=
|
|
||||||
github.com/quic-go/quic-go v0.35.1/go.mod h1:+4CVgVppm0FNjpG3UcX8Joi/frKOH7/ciD5yGcwOO1g=
|
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4=
|
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
|
||||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
github.com/tatsuhiro-t/go-nghttp2 v0.0.0-20150408091349-4742878d9c90 h1:ccVm9C6f5YMcVv6t9MXahIDkqVvzD6vklkJTIE4D2nY=
|
github.com/tatsuhiro-t/go-nghttp2 v0.0.0-20240121064059-46ccb0a462a8 h1:zKJxuRe+a0O34V81GAZWOrotuU6mveT30QLjJ7OPMMg=
|
||||||
github.com/tatsuhiro-t/go-nghttp2 v0.0.0-20150408091349-4742878d9c90/go.mod h1:YZhsh86DfZgAShPKeg1eBLVrmuQxWcR9H4TdpgNvSnw=
|
github.com/tatsuhiro-t/go-nghttp2 v0.0.0-20240121064059-46ccb0a462a8/go.mod h1:gTqc3Q4boc+cKRlSFywTYdX9t6VGRcsThlNIWwaL3Dc=
|
||||||
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
go.uber.org/mock v0.4.0 h1:VcM4ZOtdbR4f6VXfiOpwpVJDL6lCReaZ6mw31wqh7KU=
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
go.uber.org/mock v0.4.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc=
|
||||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30=
|
||||||
golang.org/x/crypto v0.13.0 h1:mvySKfSWJ+UKUii46M40LOvyWfN0s2U+46/jDd0e6Ck=
|
golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M=
|
||||||
golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
|
|
||||||
golang.org/x/exp v0.0.0-20221205204356-47842c84f3db h1:D/cFflL63o2KSLJIwjlcIt8PR064j/xsmdEJL/YvY/o=
|
golang.org/x/exp v0.0.0-20221205204356-47842c84f3db h1:D/cFflL63o2KSLJIwjlcIt8PR064j/xsmdEJL/YvY/o=
|
||||||
golang.org/x/exp v0.0.0-20221205204356-47842c84f3db/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc=
|
golang.org/x/exp v0.0.0-20221205204356-47842c84f3db/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc=
|
||||||
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
golang.org/x/mod v0.11.0 h1:bUO06HqtnRcc/7l71XBe4WcqTZ+3AH1J59zWDDwLKgU=
|
||||||
golang.org/x/mod v0.8.0 h1:LUYupSeNrTNCGzR/hVBk2NHZO4hXcVaW1k4Qx7rjPx8=
|
golang.org/x/mod v0.11.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||||
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w=
|
||||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8=
|
||||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
|
||||||
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
|
||||||
golang.org/x/net v0.15.0 h1:ugBLEUaxABaB5AJqW9enI0ACdci2RUd4eP51NTBvuJ8=
|
|
||||||
golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
|
|
||||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
|
||||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
|
||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
|
||||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o=
|
||||||
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
|
||||||
golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o=
|
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||||
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/tools v0.9.1 h1:8WMNJAz3zrtPmnYC7ISf5dEn3MT0gY7jBJfw27yrrLo=
|
||||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/tools v0.9.1/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc=
|
||||||
golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k=
|
|
||||||
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
|
||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
|
||||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
|
||||||
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
|
||||||
golang.org/x/tools v0.6.0 h1:BOw41kyTf3PuCW1pVQf8+Cyg8pMlkYB1oo9iJ6D/lKM=
|
|
||||||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
|
||||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
|
||||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
|
||||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
|
||||||
google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw=
|
google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw=
|
||||||
|
google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
|
||||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ set(GO_FILES
|
|||||||
nghttpx_http1_test.go
|
nghttpx_http1_test.go
|
||||||
nghttpx_http2_test.go
|
nghttpx_http2_test.go
|
||||||
server_tester.go
|
server_tester.go
|
||||||
|
server_tester_http3.go
|
||||||
)
|
)
|
||||||
|
|
||||||
# XXX unused
|
# XXX unused
|
||||||
@@ -18,12 +19,6 @@ set(EXTRA_DIST
|
|||||||
resp-return.rb
|
resp-return.rb
|
||||||
)
|
)
|
||||||
|
|
||||||
add_custom_target(itprep
|
|
||||||
COMMAND go get -d -v golang.org/x/net/http2
|
|
||||||
COMMAND go get -d -v github.com/tatsuhiro-t/go-nghttp2
|
|
||||||
COMMAND go get -d -v golang.org/x/net/websocket
|
|
||||||
)
|
|
||||||
|
|
||||||
# 'go test' requires both config.go and the test files in the same directory.
|
# 'go test' requires both config.go and the test files in the same directory.
|
||||||
# For out-of-tree builds, config.go is normally not placed next to the source
|
# For out-of-tree builds, config.go is normally not placed next to the source
|
||||||
# files, so copy the tests to the build directory as a workaround.
|
# files, so copy the tests to the build directory as a workaround.
|
||||||
@@ -40,7 +35,11 @@ if(NOT CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_CURRENT_BINARY_DIR)
|
|||||||
endforeach()
|
endforeach()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(ENABLE_HTTP3)
|
||||||
|
set(GO_TEST_TAGS quic)
|
||||||
|
endif()
|
||||||
|
|
||||||
add_custom_target(it
|
add_custom_target(it
|
||||||
COMMAND sh setenv go test -v
|
COMMAND sh setenv go test -v --tags=${GO_TEST_TAGS}
|
||||||
DEPENDS ${GO_BUILD_FILES}
|
DEPENDS ${GO_BUILD_FILES}
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -25,7 +25,8 @@ GO_FILES = \
|
|||||||
nghttpx_http1_test.go \
|
nghttpx_http1_test.go \
|
||||||
nghttpx_http2_test.go \
|
nghttpx_http2_test.go \
|
||||||
nghttpx_http3_test.go \
|
nghttpx_http3_test.go \
|
||||||
server_tester.go
|
server_tester.go \
|
||||||
|
server_tester_http3.go
|
||||||
|
|
||||||
EXTRA_DIST = \
|
EXTRA_DIST = \
|
||||||
CMakeLists.txt \
|
CMakeLists.txt \
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ func TestH1H1PlainGETClose(t *testing.T) {
|
|||||||
// 501 status code
|
// 501 status code
|
||||||
func TestH1H1InvalidMethod(t *testing.T) {
|
func TestH1H1InvalidMethod(t *testing.T) {
|
||||||
opts := options{
|
opts := options{
|
||||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
handler: func(http.ResponseWriter, *http.Request) {
|
||||||
t.Errorf("server should not forward this request")
|
t.Errorf("server should not forward this request")
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -82,7 +82,7 @@ func TestH1H1InvalidMethod(t *testing.T) {
|
|||||||
// contains multiple Content-Length header fields.
|
// contains multiple Content-Length header fields.
|
||||||
func TestH1H1MultipleRequestCL(t *testing.T) {
|
func TestH1H1MultipleRequestCL(t *testing.T) {
|
||||||
opts := options{
|
opts := options{
|
||||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
handler: func(http.ResponseWriter, *http.Request) {
|
||||||
t.Errorf("server should not forward bad request")
|
t.Errorf("server should not forward bad request")
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -255,7 +255,7 @@ func TestH1H1HostRewrite(t *testing.T) {
|
|||||||
// characters in host header field.
|
// characters in host header field.
|
||||||
func TestH1H1BadHost(t *testing.T) {
|
func TestH1H1BadHost(t *testing.T) {
|
||||||
opts := options{
|
opts := options{
|
||||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
handler: func(http.ResponseWriter, *http.Request) {
|
||||||
t.Errorf("server should not forward this request")
|
t.Errorf("server should not forward this request")
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -281,7 +281,7 @@ func TestH1H1BadHost(t *testing.T) {
|
|||||||
// bad characters in authority component of requset URI.
|
// bad characters in authority component of requset URI.
|
||||||
func TestH1H1BadAuthority(t *testing.T) {
|
func TestH1H1BadAuthority(t *testing.T) {
|
||||||
opts := options{
|
opts := options{
|
||||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
handler: func(http.ResponseWriter, *http.Request) {
|
||||||
t.Errorf("server should not forward this request")
|
t.Errorf("server should not forward this request")
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -307,7 +307,7 @@ func TestH1H1BadAuthority(t *testing.T) {
|
|||||||
// bad characters in scheme component of requset URI.
|
// bad characters in scheme component of requset URI.
|
||||||
func TestH1H1BadScheme(t *testing.T) {
|
func TestH1H1BadScheme(t *testing.T) {
|
||||||
opts := options{
|
opts := options{
|
||||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
handler: func(http.ResponseWriter, *http.Request) {
|
||||||
t.Errorf("server should not forward this request")
|
t.Errorf("server should not forward this request")
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -394,7 +394,7 @@ func TestH1H1HTTP10NoHostRewrite(t *testing.T) {
|
|||||||
// backend.
|
// backend.
|
||||||
func TestH1H1RequestTrailer(t *testing.T) {
|
func TestH1H1RequestTrailer(t *testing.T) {
|
||||||
opts := options{
|
opts := options{
|
||||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
handler: func(_ http.ResponseWriter, r *http.Request) {
|
||||||
buf := make([]byte, 4096)
|
buf := make([]byte, 4096)
|
||||||
for {
|
for {
|
||||||
_, err := r.Body.Read(buf)
|
_, err := r.Body.Read(buf)
|
||||||
@@ -436,7 +436,7 @@ func TestH1H1HeaderFieldBufferPath(t *testing.T) {
|
|||||||
// limit.
|
// limit.
|
||||||
opts := options{
|
opts := options{
|
||||||
args: []string{"--request-header-field-buffer=100"},
|
args: []string{"--request-header-field-buffer=100"},
|
||||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
handler: func(http.ResponseWriter, *http.Request) {
|
||||||
t.Fatal("execution path should not be here")
|
t.Fatal("execution path should not be here")
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -460,7 +460,7 @@ func TestH1H1HeaderFieldBufferPath(t *testing.T) {
|
|||||||
func TestH1H1HeaderFieldBuffer(t *testing.T) {
|
func TestH1H1HeaderFieldBuffer(t *testing.T) {
|
||||||
opts := options{
|
opts := options{
|
||||||
args: []string{"--request-header-field-buffer=10"},
|
args: []string{"--request-header-field-buffer=10"},
|
||||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
handler: func(http.ResponseWriter, *http.Request) {
|
||||||
t.Fatal("execution path should not be here")
|
t.Fatal("execution path should not be here")
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -483,7 +483,7 @@ func TestH1H1HeaderFieldBuffer(t *testing.T) {
|
|||||||
func TestH1H1HeaderFields(t *testing.T) {
|
func TestH1H1HeaderFields(t *testing.T) {
|
||||||
opts := options{
|
opts := options{
|
||||||
args: []string{"--max-request-header-fields=1"},
|
args: []string{"--max-request-header-fields=1"},
|
||||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
handler: func(http.ResponseWriter, *http.Request) {
|
||||||
t.Fatal("execution path should not be here")
|
t.Fatal("execution path should not be here")
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -533,7 +533,7 @@ func TestH1H1Websocket(t *testing.T) {
|
|||||||
func TestH1H1ReqPhaseSetHeader(t *testing.T) {
|
func TestH1H1ReqPhaseSetHeader(t *testing.T) {
|
||||||
opts := options{
|
opts := options{
|
||||||
args: []string{"--mruby-file=" + testDir + "/req-set-header.rb"},
|
args: []string{"--mruby-file=" + testDir + "/req-set-header.rb"},
|
||||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
handler: func(_ http.ResponseWriter, r *http.Request) {
|
||||||
if got, want := r.Header.Get("User-Agent"), "mruby"; got != want {
|
if got, want := r.Header.Get("User-Agent"), "mruby"; got != want {
|
||||||
t.Errorf("User-Agent = %v; want %v", got, want)
|
t.Errorf("User-Agent = %v; want %v", got, want)
|
||||||
}
|
}
|
||||||
@@ -559,7 +559,7 @@ func TestH1H1ReqPhaseSetHeader(t *testing.T) {
|
|||||||
func TestH1H1ReqPhaseReturn(t *testing.T) {
|
func TestH1H1ReqPhaseReturn(t *testing.T) {
|
||||||
opts := options{
|
opts := options{
|
||||||
args: []string{"--mruby-file=" + testDir + "/req-return.rb"},
|
args: []string{"--mruby-file=" + testDir + "/req-return.rb"},
|
||||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
handler: func(http.ResponseWriter, *http.Request) {
|
||||||
t.Fatalf("request should not be forwarded")
|
t.Fatalf("request should not be forwarded")
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -599,7 +599,7 @@ func TestH1H1ReqPhaseReturn(t *testing.T) {
|
|||||||
func TestH1H1ReqPhaseReturnCONNECTMethod(t *testing.T) {
|
func TestH1H1ReqPhaseReturnCONNECTMethod(t *testing.T) {
|
||||||
opts := options{
|
opts := options{
|
||||||
args: []string{"--mruby-file=" + testDir + "/req-return.rb"},
|
args: []string{"--mruby-file=" + testDir + "/req-return.rb"},
|
||||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
handler: func(http.ResponseWriter, *http.Request) {
|
||||||
t.Fatalf("request should not be forwarded")
|
t.Fatalf("request should not be forwarded")
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -884,7 +884,7 @@ func TestH1H1CONNECTMethodFailure(t *testing.T) {
|
|||||||
func TestH1H2NoHost(t *testing.T) {
|
func TestH1H2NoHost(t *testing.T) {
|
||||||
opts := options{
|
opts := options{
|
||||||
args: []string{"--http2-bridge"},
|
args: []string{"--http2-bridge"},
|
||||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
handler: func(http.ResponseWriter, *http.Request) {
|
||||||
t.Errorf("server should not forward bad request")
|
t.Errorf("server should not forward bad request")
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -978,7 +978,7 @@ func TestH1H2HTTP10NoHostRewrite(t *testing.T) {
|
|||||||
func TestH1H2CrumbleCookie(t *testing.T) {
|
func TestH1H2CrumbleCookie(t *testing.T) {
|
||||||
opts := options{
|
opts := options{
|
||||||
args: []string{"--http2-bridge"},
|
args: []string{"--http2-bridge"},
|
||||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
handler: func(_ http.ResponseWriter, r *http.Request) {
|
||||||
if got, want := r.Header.Get("Cookie"), "alpha; bravo; charlie"; got != want {
|
if got, want := r.Header.Get("Cookie"), "alpha; bravo; charlie"; got != want {
|
||||||
t.Errorf("Cookie: %v; want %v", got, want)
|
t.Errorf("Cookie: %v; want %v", got, want)
|
||||||
}
|
}
|
||||||
@@ -1006,7 +1006,7 @@ func TestH1H2CrumbleCookie(t *testing.T) {
|
|||||||
func TestH1H2GenerateVia(t *testing.T) {
|
func TestH1H2GenerateVia(t *testing.T) {
|
||||||
opts := options{
|
opts := options{
|
||||||
args: []string{"--http2-bridge"},
|
args: []string{"--http2-bridge"},
|
||||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
handler: func(_ http.ResponseWriter, r *http.Request) {
|
||||||
if got, want := r.Header.Get("Via"), "1.1 nghttpx"; got != want {
|
if got, want := r.Header.Get("Via"), "1.1 nghttpx"; got != want {
|
||||||
t.Errorf("Via: %v; want %v", got, want)
|
t.Errorf("Via: %v; want %v", got, want)
|
||||||
}
|
}
|
||||||
@@ -1092,7 +1092,7 @@ func TestH1H2ReqPhaseReturn(t *testing.T) {
|
|||||||
"--http2-bridge",
|
"--http2-bridge",
|
||||||
"--mruby-file=" + testDir + "/req-return.rb",
|
"--mruby-file=" + testDir + "/req-return.rb",
|
||||||
},
|
},
|
||||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
handler: func(http.ResponseWriter, *http.Request) {
|
||||||
t.Fatalf("request should not be forwarded")
|
t.Fatalf("request should not be forwarded")
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -1172,7 +1172,7 @@ func TestH1H2RespPhaseReturn(t *testing.T) {
|
|||||||
func TestH1H2TE(t *testing.T) {
|
func TestH1H2TE(t *testing.T) {
|
||||||
opts := options{
|
opts := options{
|
||||||
args: []string{"--http2-bridge"},
|
args: []string{"--http2-bridge"},
|
||||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
handler: func(_ http.ResponseWriter, r *http.Request) {
|
||||||
if got, want := r.Header.Get("te"), "trailers"; got != want {
|
if got, want := r.Header.Get("te"), "trailers"; got != want {
|
||||||
t.Errorf("te: %v; want %v", got, want)
|
t.Errorf("te: %v; want %v", got, want)
|
||||||
}
|
}
|
||||||
@@ -1200,7 +1200,7 @@ func TestH1H2TE(t *testing.T) {
|
|||||||
func TestH1APIBackendconfig(t *testing.T) {
|
func TestH1APIBackendconfig(t *testing.T) {
|
||||||
opts := options{
|
opts := options{
|
||||||
args: []string{"-f127.0.0.1,3010;api;no-tls"},
|
args: []string{"-f127.0.0.1,3010;api;no-tls"},
|
||||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
handler: func(http.ResponseWriter, *http.Request) {
|
||||||
t.Fatalf("request should not be forwarded")
|
t.Fatalf("request should not be forwarded")
|
||||||
},
|
},
|
||||||
connectPort: 3010,
|
connectPort: 3010,
|
||||||
@@ -1242,7 +1242,7 @@ backend=127.0.0.1,3011
|
|||||||
func TestH1APIBackendconfigQuery(t *testing.T) {
|
func TestH1APIBackendconfigQuery(t *testing.T) {
|
||||||
opts := options{
|
opts := options{
|
||||||
args: []string{"-f127.0.0.1,3010;api;no-tls"},
|
args: []string{"-f127.0.0.1,3010;api;no-tls"},
|
||||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
handler: func(http.ResponseWriter, *http.Request) {
|
||||||
t.Fatalf("request should not be forwarded")
|
t.Fatalf("request should not be forwarded")
|
||||||
},
|
},
|
||||||
connectPort: 3010,
|
connectPort: 3010,
|
||||||
@@ -1284,7 +1284,7 @@ backend=127.0.0.1,3011
|
|||||||
func TestH1APIBackendconfigBadMethod(t *testing.T) {
|
func TestH1APIBackendconfigBadMethod(t *testing.T) {
|
||||||
opts := options{
|
opts := options{
|
||||||
args: []string{"-f127.0.0.1,3010;api;no-tls"},
|
args: []string{"-f127.0.0.1,3010;api;no-tls"},
|
||||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
handler: func(http.ResponseWriter, *http.Request) {
|
||||||
t.Fatalf("request should not be forwarded")
|
t.Fatalf("request should not be forwarded")
|
||||||
},
|
},
|
||||||
connectPort: 3010,
|
connectPort: 3010,
|
||||||
@@ -1325,7 +1325,7 @@ backend=127.0.0.1,3011
|
|||||||
func TestH1APIConfigrevision(t *testing.T) {
|
func TestH1APIConfigrevision(t *testing.T) {
|
||||||
opts := options{
|
opts := options{
|
||||||
args: []string{"-f127.0.0.1,3010;api;no-tls"},
|
args: []string{"-f127.0.0.1,3010;api;no-tls"},
|
||||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
handler: func(http.ResponseWriter, *http.Request) {
|
||||||
t.Fatalf("request should not be forwarded")
|
t.Fatalf("request should not be forwarded")
|
||||||
},
|
},
|
||||||
connectPort: 3010,
|
connectPort: 3010,
|
||||||
@@ -1368,7 +1368,7 @@ func TestH1APIConfigrevision(t *testing.T) {
|
|||||||
func TestH1APINotFound(t *testing.T) {
|
func TestH1APINotFound(t *testing.T) {
|
||||||
opts := options{
|
opts := options{
|
||||||
args: []string{"-f127.0.0.1,3010;api;no-tls"},
|
args: []string{"-f127.0.0.1,3010;api;no-tls"},
|
||||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
handler: func(http.ResponseWriter, *http.Request) {
|
||||||
t.Fatalf("request should not be forwarded")
|
t.Fatalf("request should not be forwarded")
|
||||||
},
|
},
|
||||||
connectPort: 3010,
|
connectPort: 3010,
|
||||||
@@ -1409,7 +1409,7 @@ backend=127.0.0.1,3011
|
|||||||
func TestH1Healthmon(t *testing.T) {
|
func TestH1Healthmon(t *testing.T) {
|
||||||
opts := options{
|
opts := options{
|
||||||
args: []string{"-f127.0.0.1,3011;healthmon;no-tls"},
|
args: []string{"-f127.0.0.1,3011;healthmon;no-tls"},
|
||||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
handler: func(http.ResponseWriter, *http.Request) {
|
||||||
t.Fatalf("request should not be forwarded")
|
t.Fatalf("request should not be forwarded")
|
||||||
},
|
},
|
||||||
connectPort: 3011,
|
connectPort: 3011,
|
||||||
@@ -1434,7 +1434,7 @@ func TestH1Healthmon(t *testing.T) {
|
|||||||
func TestH1ResponseBeforeRequestEnd(t *testing.T) {
|
func TestH1ResponseBeforeRequestEnd(t *testing.T) {
|
||||||
opts := options{
|
opts := options{
|
||||||
args: []string{"--mruby-file=" + testDir + "/req-return.rb"},
|
args: []string{"--mruby-file=" + testDir + "/req-return.rb"},
|
||||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
handler: func(http.ResponseWriter, *http.Request) {
|
||||||
t.Fatal("request should not be forwarded")
|
t.Fatal("request should not be forwarded")
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -1462,7 +1462,7 @@ func TestH1ResponseBeforeRequestEnd(t *testing.T) {
|
|||||||
// if the backend chunked encoded response ends prematurely.
|
// if the backend chunked encoded response ends prematurely.
|
||||||
func TestH1H1ChunkedEndsPrematurely(t *testing.T) {
|
func TestH1H1ChunkedEndsPrematurely(t *testing.T) {
|
||||||
opts := options{
|
opts := options{
|
||||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
handler: func(w http.ResponseWriter, _ *http.Request) {
|
||||||
hj, ok := w.(http.Hijacker)
|
hj, ok := w.(http.Hijacker)
|
||||||
if !ok {
|
if !ok {
|
||||||
http.Error(w, "Could not hijack the connection", http.StatusInternalServerError)
|
http.Error(w, "Could not hijack the connection", http.StatusInternalServerError)
|
||||||
@@ -1490,3 +1490,142 @@ func TestH1H1ChunkedEndsPrematurely(t *testing.T) {
|
|||||||
t.Fatal("st.http1() should fail")
|
t.Fatal("st.http1() should fail")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TestH1H1RequestMalformedTransferEncoding tests that server rejects
|
||||||
|
// request which contains malformed transfer-encoding.
|
||||||
|
func TestH1H1RequestMalformedTransferEncoding(t *testing.T) {
|
||||||
|
opts := options{
|
||||||
|
handler: func(http.ResponseWriter, *http.Request) {
|
||||||
|
t.Errorf("server should not forward bad request")
|
||||||
|
},
|
||||||
|
}
|
||||||
|
st := newServerTester(t, opts)
|
||||||
|
defer st.Close()
|
||||||
|
|
||||||
|
if _, err := io.WriteString(st.conn, fmt.Sprintf("GET / HTTP/1.1\r\nHost: %v\r\nTest-Case: TestH1H1RequestMalformedTransferEncoding\r\nTransfer-Encoding: ,chunked\r\n\r\n",
|
||||||
|
st.authority)); err != nil {
|
||||||
|
t.Fatalf("Error io.WriteString() = %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := http.ReadResponse(bufio.NewReader(st.conn), nil)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Error http.ReadResponse() = %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
if got, want := resp.StatusCode, http.StatusBadRequest; got != want {
|
||||||
|
t.Errorf("status: %v; want %v", got, want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestH1H1ResponseMalformedTransferEncoding tests a request fails if
|
||||||
|
// its response contains malformed transfer-encoding.
|
||||||
|
func TestH1H1ResponseMalformedTransferEncoding(t *testing.T) {
|
||||||
|
opts := options{
|
||||||
|
handler: func(w http.ResponseWriter, _ *http.Request) {
|
||||||
|
hj, ok := w.(http.Hijacker)
|
||||||
|
if !ok {
|
||||||
|
http.Error(w, "Could not hijack the connection", http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
conn, bufrw, err := hj.Hijack()
|
||||||
|
if err != nil {
|
||||||
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer conn.Close()
|
||||||
|
if _, err := bufrw.WriteString("HTTP/1.1 200\r\nTransfer-Encoding: ,chunked\r\n\r\n"); err != nil {
|
||||||
|
t.Fatalf("Error bufrw.WriteString() = %v", err)
|
||||||
|
}
|
||||||
|
bufrw.Flush()
|
||||||
|
},
|
||||||
|
}
|
||||||
|
st := newServerTester(t, opts)
|
||||||
|
defer st.Close()
|
||||||
|
|
||||||
|
res, err := st.http1(requestParam{
|
||||||
|
name: "TestH1H1ResponseMalformedTransferEncoding",
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Error st.http1() = %v", err)
|
||||||
|
}
|
||||||
|
if got, want := res.status, http.StatusBadGateway; got != want {
|
||||||
|
t.Errorf("res.status: %v; want %v", got, want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestH1H1ResponseUnknownTransferEncoding tests a request succeeds if
|
||||||
|
// its response contains unknown transfer-encoding.
|
||||||
|
func TestH1H1ResponseUnknownTransferEncoding(t *testing.T) {
|
||||||
|
opts := options{
|
||||||
|
handler: func(w http.ResponseWriter, _ *http.Request) {
|
||||||
|
hj, ok := w.(http.Hijacker)
|
||||||
|
if !ok {
|
||||||
|
http.Error(w, "Could not hijack the connection", http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
conn, bufrw, err := hj.Hijack()
|
||||||
|
if err != nil {
|
||||||
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer conn.Close()
|
||||||
|
if _, err := bufrw.WriteString("HTTP/1.1 200\r\nTransfer-Encoding: foo\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, fmt.Sprintf("GET / HTTP/1.1\r\nHost: %v\r\nTest-Case: TestH1H1ResponseUnknownTransferEncoding\r\n\r\n",
|
||||||
|
st.authority)); err != nil {
|
||||||
|
t.Fatalf("Error: io.WriteString() = %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
r := bufio.NewReader(st.conn)
|
||||||
|
|
||||||
|
resp := make([]byte, 4096)
|
||||||
|
|
||||||
|
resplen, err := r.Read(resp)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Error: r.Read() = %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
resp = resp[:resplen]
|
||||||
|
|
||||||
|
const expect = "HTTP/1.1 200 OK\r\nTransfer-Encoding: foo\r\nConnection: close\r\nServer: nghttpx\r\nVia: 1.1 nghttpx\r\n\r\n"
|
||||||
|
|
||||||
|
if got, want := string(resp), expect; got != want {
|
||||||
|
t.Errorf("resp = %v, want %v", got, want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestH1H1RequestHTTP10TransferEncoding tests that server rejects
|
||||||
|
// HTTP/1.0 request which contains transfer-encoding.
|
||||||
|
func TestH1H1RequestHTTP10TransferEncoding(t *testing.T) {
|
||||||
|
opts := options{
|
||||||
|
handler: func(http.ResponseWriter, *http.Request) {
|
||||||
|
t.Errorf("server should not forward bad request")
|
||||||
|
},
|
||||||
|
}
|
||||||
|
st := newServerTester(t, opts)
|
||||||
|
defer st.Close()
|
||||||
|
|
||||||
|
if _, err := io.WriteString(st.conn, "GET / HTTP/1.0\r\nTest-Case: TestH1H1RequestHTTP10TransferEncoding\r\nTransfer-Encoding: chunked\r\n\r\n"); err != nil {
|
||||||
|
t.Fatalf("Error io.WriteString() = %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := http.ReadResponse(bufio.NewReader(st.conn), nil)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Error http.ReadResponse() = %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
if got, want := resp.StatusCode, http.StatusBadRequest; got != want {
|
||||||
|
t.Errorf("status: %v; want %v", got, want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ func TestH2H1PlainGET(t *testing.T) {
|
|||||||
func TestH2H1AddXfp(t *testing.T) {
|
func TestH2H1AddXfp(t *testing.T) {
|
||||||
opts := options{
|
opts := options{
|
||||||
args: []string{"--no-strip-incoming-x-forwarded-proto"},
|
args: []string{"--no-strip-incoming-x-forwarded-proto"},
|
||||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
handler: func(_ http.ResponseWriter, r *http.Request) {
|
||||||
xfp := r.Header.Get("X-Forwarded-Proto")
|
xfp := r.Header.Get("X-Forwarded-Proto")
|
||||||
if got, want := xfp, "foo, http"; got != want {
|
if got, want := xfp, "foo, http"; got != want {
|
||||||
t.Errorf("X-Forwarded-Proto = %q; want %q", got, want)
|
t.Errorf("X-Forwarded-Proto = %q; want %q", got, want)
|
||||||
@@ -72,7 +72,7 @@ func TestH2H1NoAddXfp(t *testing.T) {
|
|||||||
"--no-add-x-forwarded-proto",
|
"--no-add-x-forwarded-proto",
|
||||||
"--no-strip-incoming-x-forwarded-proto",
|
"--no-strip-incoming-x-forwarded-proto",
|
||||||
},
|
},
|
||||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
handler: func(_ http.ResponseWriter, r *http.Request) {
|
||||||
xfp := r.Header.Get("X-Forwarded-Proto")
|
xfp := r.Header.Get("X-Forwarded-Proto")
|
||||||
if got, want := xfp, "foo"; got != want {
|
if got, want := xfp, "foo"; got != want {
|
||||||
t.Errorf("X-Forwarded-Proto = %q; want %q", got, want)
|
t.Errorf("X-Forwarded-Proto = %q; want %q", got, want)
|
||||||
@@ -100,7 +100,7 @@ func TestH2H1NoAddXfp(t *testing.T) {
|
|||||||
// x-forwarded-proto header field.
|
// x-forwarded-proto header field.
|
||||||
func TestH2H1StripXfp(t *testing.T) {
|
func TestH2H1StripXfp(t *testing.T) {
|
||||||
opts := options{
|
opts := options{
|
||||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
handler: func(_ http.ResponseWriter, r *http.Request) {
|
||||||
xfp := r.Header.Get("X-Forwarded-Proto")
|
xfp := r.Header.Get("X-Forwarded-Proto")
|
||||||
if got, want := xfp, "http"; got != want {
|
if got, want := xfp, "http"; got != want {
|
||||||
t.Errorf("X-Forwarded-Proto = %q; want %q", got, want)
|
t.Errorf("X-Forwarded-Proto = %q; want %q", got, want)
|
||||||
@@ -129,7 +129,7 @@ func TestH2H1StripXfp(t *testing.T) {
|
|||||||
func TestH2H1StripNoAddXfp(t *testing.T) {
|
func TestH2H1StripNoAddXfp(t *testing.T) {
|
||||||
opts := options{
|
opts := options{
|
||||||
args: []string{"--no-add-x-forwarded-proto"},
|
args: []string{"--no-add-x-forwarded-proto"},
|
||||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
handler: func(_ http.ResponseWriter, r *http.Request) {
|
||||||
if got, found := r.Header["X-Forwarded-Proto"]; found {
|
if got, found := r.Header["X-Forwarded-Proto"]; found {
|
||||||
t.Errorf("X-Forwarded-Proto = %q; want nothing", got)
|
t.Errorf("X-Forwarded-Proto = %q; want nothing", got)
|
||||||
}
|
}
|
||||||
@@ -157,7 +157,7 @@ func TestH2H1StripNoAddXfp(t *testing.T) {
|
|||||||
func TestH2H1AddXff(t *testing.T) {
|
func TestH2H1AddXff(t *testing.T) {
|
||||||
opts := options{
|
opts := options{
|
||||||
args: []string{"--add-x-forwarded-for"},
|
args: []string{"--add-x-forwarded-for"},
|
||||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
handler: func(_ http.ResponseWriter, r *http.Request) {
|
||||||
xff := r.Header.Get("X-Forwarded-For")
|
xff := r.Header.Get("X-Forwarded-For")
|
||||||
want := "127.0.0.1"
|
want := "127.0.0.1"
|
||||||
if xff != want {
|
if xff != want {
|
||||||
@@ -184,7 +184,7 @@ func TestH2H1AddXff(t *testing.T) {
|
|||||||
func TestH2H1AddXff2(t *testing.T) {
|
func TestH2H1AddXff2(t *testing.T) {
|
||||||
opts := options{
|
opts := options{
|
||||||
args: []string{"--add-x-forwarded-for"},
|
args: []string{"--add-x-forwarded-for"},
|
||||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
handler: func(_ http.ResponseWriter, r *http.Request) {
|
||||||
xff := r.Header.Get("X-Forwarded-For")
|
xff := r.Header.Get("X-Forwarded-For")
|
||||||
want := "host, 127.0.0.1"
|
want := "host, 127.0.0.1"
|
||||||
if xff != want {
|
if xff != want {
|
||||||
@@ -214,7 +214,7 @@ func TestH2H1AddXff2(t *testing.T) {
|
|||||||
func TestH2H1StripXff(t *testing.T) {
|
func TestH2H1StripXff(t *testing.T) {
|
||||||
opts := options{
|
opts := options{
|
||||||
args: []string{"--strip-incoming-x-forwarded-for"},
|
args: []string{"--strip-incoming-x-forwarded-for"},
|
||||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
handler: func(_ http.ResponseWriter, r *http.Request) {
|
||||||
if xff, found := r.Header["X-Forwarded-For"]; found {
|
if xff, found := r.Header["X-Forwarded-For"]; found {
|
||||||
t.Errorf("X-Forwarded-For = %v; want nothing", xff)
|
t.Errorf("X-Forwarded-For = %v; want nothing", xff)
|
||||||
}
|
}
|
||||||
@@ -245,7 +245,7 @@ func TestH2H1StripAddXff(t *testing.T) {
|
|||||||
"--strip-incoming-x-forwarded-for",
|
"--strip-incoming-x-forwarded-for",
|
||||||
"--add-x-forwarded-for",
|
"--add-x-forwarded-for",
|
||||||
},
|
},
|
||||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
handler: func(_ http.ResponseWriter, r *http.Request) {
|
||||||
xff := r.Header.Get("X-Forwarded-For")
|
xff := r.Header.Get("X-Forwarded-For")
|
||||||
want := "127.0.0.1"
|
want := "127.0.0.1"
|
||||||
if xff != want {
|
if xff != want {
|
||||||
@@ -275,7 +275,7 @@ func TestH2H1StripAddXff(t *testing.T) {
|
|||||||
func TestH2H1AddForwardedObfuscated(t *testing.T) {
|
func TestH2H1AddForwardedObfuscated(t *testing.T) {
|
||||||
opts := options{
|
opts := options{
|
||||||
args: []string{"--add-forwarded=by,for,host,proto"},
|
args: []string{"--add-forwarded=by,for,host,proto"},
|
||||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
handler: func(_ http.ResponseWriter, r *http.Request) {
|
||||||
pattern := fmt.Sprintf(`by=_[^;]+;for=_[^;]+;host="127\.0\.0\.1:%v";proto=http`, serverPort)
|
pattern := fmt.Sprintf(`by=_[^;]+;for=_[^;]+;host="127\.0\.0\.1:%v";proto=http`, serverPort)
|
||||||
validFwd := regexp.MustCompile(pattern)
|
validFwd := regexp.MustCompile(pattern)
|
||||||
got := r.Header.Get("Forwarded")
|
got := r.Header.Get("Forwarded")
|
||||||
@@ -304,7 +304,7 @@ func TestH2H1AddForwardedObfuscated(t *testing.T) {
|
|||||||
func TestH2H1AddForwardedByIP(t *testing.T) {
|
func TestH2H1AddForwardedByIP(t *testing.T) {
|
||||||
opts := options{
|
opts := options{
|
||||||
args: []string{"--add-forwarded=by,for", "--forwarded-by=ip"},
|
args: []string{"--add-forwarded=by,for", "--forwarded-by=ip"},
|
||||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
handler: func(_ http.ResponseWriter, r *http.Request) {
|
||||||
pattern := fmt.Sprintf(`by="127\.0\.0\.1:%v";for=_[^;]+`, serverPort)
|
pattern := fmt.Sprintf(`by="127\.0\.0\.1:%v";for=_[^;]+`, serverPort)
|
||||||
validFwd := regexp.MustCompile(pattern)
|
validFwd := regexp.MustCompile(pattern)
|
||||||
if got := r.Header.Get("Forwarded"); !validFwd.MatchString(got) {
|
if got := r.Header.Get("Forwarded"); !validFwd.MatchString(got) {
|
||||||
@@ -335,7 +335,7 @@ func TestH2H1AddForwardedForIP(t *testing.T) {
|
|||||||
"--forwarded-by=_alpha",
|
"--forwarded-by=_alpha",
|
||||||
"--forwarded-for=ip",
|
"--forwarded-for=ip",
|
||||||
},
|
},
|
||||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
handler: func(_ http.ResponseWriter, r *http.Request) {
|
||||||
want := fmt.Sprintf(`by=_alpha;for=127.0.0.1;host="127.0.0.1:%v";proto=http`, serverPort)
|
want := fmt.Sprintf(`by=_alpha;for=127.0.0.1;host="127.0.0.1:%v";proto=http`, serverPort)
|
||||||
if got := r.Header.Get("Forwarded"); got != want {
|
if got := r.Header.Get("Forwarded"); got != want {
|
||||||
t.Errorf("Forwarded = %v; want %v", got, want)
|
t.Errorf("Forwarded = %v; want %v", got, want)
|
||||||
@@ -362,7 +362,7 @@ func TestH2H1AddForwardedForIP(t *testing.T) {
|
|||||||
func TestH2H1AddForwardedMerge(t *testing.T) {
|
func TestH2H1AddForwardedMerge(t *testing.T) {
|
||||||
opts := options{
|
opts := options{
|
||||||
args: []string{"--add-forwarded=proto"},
|
args: []string{"--add-forwarded=proto"},
|
||||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
handler: func(_ http.ResponseWriter, r *http.Request) {
|
||||||
if got, want := r.Header.Get("Forwarded"), `host=foo, proto=http`; got != want {
|
if got, want := r.Header.Get("Forwarded"), `host=foo, proto=http`; got != want {
|
||||||
t.Errorf("Forwarded = %v; want %v", got, want)
|
t.Errorf("Forwarded = %v; want %v", got, want)
|
||||||
}
|
}
|
||||||
@@ -394,7 +394,7 @@ func TestH2H1AddForwardedStrip(t *testing.T) {
|
|||||||
"--strip-incoming-forwarded",
|
"--strip-incoming-forwarded",
|
||||||
"--add-forwarded=proto",
|
"--add-forwarded=proto",
|
||||||
},
|
},
|
||||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
handler: func(_ http.ResponseWriter, r *http.Request) {
|
||||||
if got, want := r.Header.Get("Forwarded"), `proto=http`; got != want {
|
if got, want := r.Header.Get("Forwarded"), `proto=http`; got != want {
|
||||||
t.Errorf("Forwarded = %v; want %v", got, want)
|
t.Errorf("Forwarded = %v; want %v", got, want)
|
||||||
}
|
}
|
||||||
@@ -422,7 +422,7 @@ func TestH2H1AddForwardedStrip(t *testing.T) {
|
|||||||
func TestH2H1StripForwarded(t *testing.T) {
|
func TestH2H1StripForwarded(t *testing.T) {
|
||||||
opts := options{
|
opts := options{
|
||||||
args: []string{"--strip-incoming-forwarded"},
|
args: []string{"--strip-incoming-forwarded"},
|
||||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
handler: func(_ http.ResponseWriter, r *http.Request) {
|
||||||
if got, found := r.Header["Forwarded"]; found {
|
if got, found := r.Header["Forwarded"]; found {
|
||||||
t.Errorf("Forwarded = %v; want nothing", got)
|
t.Errorf("Forwarded = %v; want nothing", got)
|
||||||
}
|
}
|
||||||
@@ -454,7 +454,7 @@ func TestH2H1AddForwardedStatic(t *testing.T) {
|
|||||||
"--add-forwarded=by,for",
|
"--add-forwarded=by,for",
|
||||||
"--forwarded-by=_alpha",
|
"--forwarded-by=_alpha",
|
||||||
},
|
},
|
||||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
handler: func(_ http.ResponseWriter, r *http.Request) {
|
||||||
pattern := `by=_alpha;for=_[^;]+`
|
pattern := `by=_alpha;for=_[^;]+`
|
||||||
validFwd := regexp.MustCompile(pattern)
|
validFwd := regexp.MustCompile(pattern)
|
||||||
if got := r.Header.Get("Forwarded"); !validFwd.MatchString(got) {
|
if got := r.Header.Get("Forwarded"); !validFwd.MatchString(got) {
|
||||||
@@ -480,7 +480,7 @@ func TestH2H1AddForwardedStatic(t *testing.T) {
|
|||||||
// from backend server.
|
// from backend server.
|
||||||
func TestH2H1GenerateVia(t *testing.T) {
|
func TestH2H1GenerateVia(t *testing.T) {
|
||||||
opts := options{
|
opts := options{
|
||||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
handler: func(_ http.ResponseWriter, r *http.Request) {
|
||||||
if got, want := r.Header.Get("Via"), "2 nghttpx"; got != want {
|
if got, want := r.Header.Get("Via"), "2 nghttpx"; got != want {
|
||||||
t.Errorf("Via: %v; want %v", got, want)
|
t.Errorf("Via: %v; want %v", got, want)
|
||||||
}
|
}
|
||||||
@@ -639,7 +639,7 @@ func TestH2H1BadRequestCL(t *testing.T) {
|
|||||||
// response body size.
|
// response body size.
|
||||||
func TestH2H1BadResponseCL(t *testing.T) {
|
func TestH2H1BadResponseCL(t *testing.T) {
|
||||||
opts := options{
|
opts := options{
|
||||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
handler: func(w http.ResponseWriter, _ *http.Request) {
|
||||||
// we set content-length: 1024, but only send 3 bytes.
|
// we set content-length: 1024, but only send 3 bytes.
|
||||||
w.Header().Add("Content-Length", "1024")
|
w.Header().Add("Content-Length", "1024")
|
||||||
if _, err := w.Write([]byte("foo")); err != nil {
|
if _, err := w.Write([]byte("foo")); err != nil {
|
||||||
@@ -667,7 +667,7 @@ func TestH2H1BadResponseCL(t *testing.T) {
|
|||||||
// works.
|
// works.
|
||||||
func TestH2H1LocationRewrite(t *testing.T) {
|
func TestH2H1LocationRewrite(t *testing.T) {
|
||||||
opts := options{
|
opts := options{
|
||||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
handler: func(w http.ResponseWriter, _ *http.Request) {
|
||||||
// TODO we cannot get st.ts's port number
|
// TODO we cannot get st.ts's port number
|
||||||
// here.. 8443 is just a place holder. We
|
// here.. 8443 is just a place holder. We
|
||||||
// ignore it on rewrite.
|
// ignore it on rewrite.
|
||||||
@@ -693,7 +693,7 @@ func TestH2H1LocationRewrite(t *testing.T) {
|
|||||||
// TestH2H1ChunkedRequestBody tests that chunked request body works.
|
// TestH2H1ChunkedRequestBody tests that chunked request body works.
|
||||||
func TestH2H1ChunkedRequestBody(t *testing.T) {
|
func TestH2H1ChunkedRequestBody(t *testing.T) {
|
||||||
opts := options{
|
opts := options{
|
||||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
handler: func(_ http.ResponseWriter, r *http.Request) {
|
||||||
want := "[chunked]"
|
want := "[chunked]"
|
||||||
if got := fmt.Sprint(r.TransferEncoding); got != want {
|
if got := fmt.Sprint(r.TransferEncoding); got != want {
|
||||||
t.Errorf("Transfer-Encoding: %v; want %v", got, want)
|
t.Errorf("Transfer-Encoding: %v; want %v", got, want)
|
||||||
@@ -728,7 +728,7 @@ func TestH2H1ChunkedRequestBody(t *testing.T) {
|
|||||||
// multiple Content-Length request header fields.
|
// multiple Content-Length request header fields.
|
||||||
func TestH2H1MultipleRequestCL(t *testing.T) {
|
func TestH2H1MultipleRequestCL(t *testing.T) {
|
||||||
opts := options{
|
opts := options{
|
||||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
handler: func(http.ResponseWriter, *http.Request) {
|
||||||
t.Errorf("server should not forward bad request")
|
t.Errorf("server should not forward bad request")
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -754,7 +754,7 @@ func TestH2H1MultipleRequestCL(t *testing.T) {
|
|||||||
// Content-Length which cannot be parsed as a number.
|
// Content-Length which cannot be parsed as a number.
|
||||||
func TestH2H1InvalidRequestCL(t *testing.T) {
|
func TestH2H1InvalidRequestCL(t *testing.T) {
|
||||||
opts := options{
|
opts := options{
|
||||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
handler: func(http.ResponseWriter, *http.Request) {
|
||||||
t.Errorf("server should not forward bad request")
|
t.Errorf("server should not forward bad request")
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -800,7 +800,7 @@ func TestH2H1InvalidRequestCL(t *testing.T) {
|
|||||||
// 501.
|
// 501.
|
||||||
func TestH2H1InvalidMethod(t *testing.T) {
|
func TestH2H1InvalidMethod(t *testing.T) {
|
||||||
opts := options{
|
opts := options{
|
||||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
handler: func(http.ResponseWriter, *http.Request) {
|
||||||
t.Errorf("server should not forward this request")
|
t.Errorf("server should not forward this request")
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -823,7 +823,7 @@ func TestH2H1InvalidMethod(t *testing.T) {
|
|||||||
// bad characters in :authority header field.
|
// bad characters in :authority header field.
|
||||||
func TestH2H1BadAuthority(t *testing.T) {
|
func TestH2H1BadAuthority(t *testing.T) {
|
||||||
opts := options{
|
opts := options{
|
||||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
handler: func(http.ResponseWriter, *http.Request) {
|
||||||
t.Errorf("server should not forward this request")
|
t.Errorf("server should not forward this request")
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -846,7 +846,7 @@ func TestH2H1BadAuthority(t *testing.T) {
|
|||||||
// bad characters in :scheme header field.
|
// bad characters in :scheme header field.
|
||||||
func TestH2H1BadScheme(t *testing.T) {
|
func TestH2H1BadScheme(t *testing.T) {
|
||||||
opts := options{
|
opts := options{
|
||||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
handler: func(http.ResponseWriter, *http.Request) {
|
||||||
t.Errorf("server should not forward this request")
|
t.Errorf("server should not forward this request")
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -869,7 +869,7 @@ func TestH2H1BadScheme(t *testing.T) {
|
|||||||
// request is assembled into 1 when forwarding to HTTP/1 backend link.
|
// request is assembled into 1 when forwarding to HTTP/1 backend link.
|
||||||
func TestH2H1AssembleCookies(t *testing.T) {
|
func TestH2H1AssembleCookies(t *testing.T) {
|
||||||
opts := options{
|
opts := options{
|
||||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
handler: func(_ http.ResponseWriter, r *http.Request) {
|
||||||
if got, want := r.Header.Get("Cookie"), "alpha; bravo; charlie"; got != want {
|
if got, want := r.Header.Get("Cookie"), "alpha; bravo; charlie"; got != want {
|
||||||
t.Errorf("Cookie: %v; want %v", got, want)
|
t.Errorf("Cookie: %v; want %v", got, want)
|
||||||
}
|
}
|
||||||
@@ -918,7 +918,7 @@ func TestH2H1TETrailers(t *testing.T) {
|
|||||||
// field contains gzip.
|
// field contains gzip.
|
||||||
func TestH2H1TEGzip(t *testing.T) {
|
func TestH2H1TEGzip(t *testing.T) {
|
||||||
opts := options{
|
opts := options{
|
||||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
handler: func(http.ResponseWriter, *http.Request) {
|
||||||
t.Error("server should not forward bad request")
|
t.Error("server should not forward bad request")
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -967,7 +967,7 @@ func TestH2H1SNI(t *testing.T) {
|
|||||||
// connection is encrypted.
|
// connection is encrypted.
|
||||||
func TestH2H1TLSXfp(t *testing.T) {
|
func TestH2H1TLSXfp(t *testing.T) {
|
||||||
opts := options{
|
opts := options{
|
||||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
handler: func(_ http.ResponseWriter, r *http.Request) {
|
||||||
if got, want := r.Header.Get("x-forwarded-proto"), "http"; got != want {
|
if got, want := r.Header.Get("x-forwarded-proto"), "http"; got != want {
|
||||||
t.Errorf("x-forwarded-proto: want %v; got %v", want, got)
|
t.Errorf("x-forwarded-proto: want %v; got %v", want, got)
|
||||||
}
|
}
|
||||||
@@ -1028,7 +1028,7 @@ func TestH2H1ServerPush(t *testing.T) {
|
|||||||
// backend.
|
// backend.
|
||||||
func TestH2H1RequestTrailer(t *testing.T) {
|
func TestH2H1RequestTrailer(t *testing.T) {
|
||||||
opts := options{
|
opts := options{
|
||||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
handler: func(_ http.ResponseWriter, r *http.Request) {
|
||||||
buf := make([]byte, 4096)
|
buf := make([]byte, 4096)
|
||||||
for {
|
for {
|
||||||
_, err := r.Body.Read(buf)
|
_, err := r.Body.Read(buf)
|
||||||
@@ -1067,7 +1067,7 @@ func TestH2H1RequestTrailer(t *testing.T) {
|
|||||||
func TestH2H1HeaderFieldBuffer(t *testing.T) {
|
func TestH2H1HeaderFieldBuffer(t *testing.T) {
|
||||||
opts := options{
|
opts := options{
|
||||||
args: []string{"--request-header-field-buffer=10"},
|
args: []string{"--request-header-field-buffer=10"},
|
||||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
handler: func(http.ResponseWriter, *http.Request) {
|
||||||
t.Fatal("execution path should not be here")
|
t.Fatal("execution path should not be here")
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -1090,7 +1090,7 @@ func TestH2H1HeaderFieldBuffer(t *testing.T) {
|
|||||||
func TestH2H1HeaderFields(t *testing.T) {
|
func TestH2H1HeaderFields(t *testing.T) {
|
||||||
opts := options{
|
opts := options{
|
||||||
args: []string{"--max-request-header-fields=1"},
|
args: []string{"--max-request-header-fields=1"},
|
||||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
handler: func(http.ResponseWriter, *http.Request) {
|
||||||
t.Fatal("execution path should not be here")
|
t.Fatal("execution path should not be here")
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -1115,7 +1115,7 @@ func TestH2H1HeaderFields(t *testing.T) {
|
|||||||
func TestH2H1ReqPhaseSetHeader(t *testing.T) {
|
func TestH2H1ReqPhaseSetHeader(t *testing.T) {
|
||||||
opts := options{
|
opts := options{
|
||||||
args: []string{"--mruby-file=" + testDir + "/req-set-header.rb"},
|
args: []string{"--mruby-file=" + testDir + "/req-set-header.rb"},
|
||||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
handler: func(_ http.ResponseWriter, r *http.Request) {
|
||||||
if got, want := r.Header.Get("User-Agent"), "mruby"; got != want {
|
if got, want := r.Header.Get("User-Agent"), "mruby"; got != want {
|
||||||
t.Errorf("User-Agent = %v; want %v", got, want)
|
t.Errorf("User-Agent = %v; want %v", got, want)
|
||||||
}
|
}
|
||||||
@@ -1141,7 +1141,7 @@ func TestH2H1ReqPhaseSetHeader(t *testing.T) {
|
|||||||
func TestH2H1ReqPhaseReturn(t *testing.T) {
|
func TestH2H1ReqPhaseReturn(t *testing.T) {
|
||||||
opts := options{
|
opts := options{
|
||||||
args: []string{"--mruby-file=" + testDir + "/req-return.rb"},
|
args: []string{"--mruby-file=" + testDir + "/req-return.rb"},
|
||||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
handler: func(http.ResponseWriter, *http.Request) {
|
||||||
t.Fatalf("request should not be forwarded")
|
t.Fatalf("request should not be forwarded")
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -1284,7 +1284,7 @@ func TestH2H1ProxyProtocolV1ForwardedForObfuscated(t *testing.T) {
|
|||||||
"--add-forwarded=for",
|
"--add-forwarded=for",
|
||||||
"--forwarded-for=obfuscated",
|
"--forwarded-for=obfuscated",
|
||||||
},
|
},
|
||||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
handler: func(_ http.ResponseWriter, r *http.Request) {
|
||||||
if got := r.Header.Get("Forwarded"); !validFwd.MatchString(got) {
|
if got := r.Header.Get("Forwarded"); !validFwd.MatchString(got) {
|
||||||
t.Errorf("Forwarded: %v; want pattern %v", got, pattern)
|
t.Errorf("Forwarded: %v; want pattern %v", got, pattern)
|
||||||
}
|
}
|
||||||
@@ -1321,7 +1321,7 @@ func TestH2H1ProxyProtocolV1TCP4(t *testing.T) {
|
|||||||
"--add-forwarded=for",
|
"--add-forwarded=for",
|
||||||
"--forwarded-for=ip",
|
"--forwarded-for=ip",
|
||||||
},
|
},
|
||||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
handler: func(_ http.ResponseWriter, r *http.Request) {
|
||||||
if got, want := r.Header.Get("X-Forwarded-For"), "192.168.0.2"; got != want {
|
if got, want := r.Header.Get("X-Forwarded-For"), "192.168.0.2"; got != want {
|
||||||
t.Errorf("X-Forwarded-For: %v; want %v", got, want)
|
t.Errorf("X-Forwarded-For: %v; want %v", got, want)
|
||||||
}
|
}
|
||||||
@@ -1361,7 +1361,7 @@ func TestH2H1ProxyProtocolV1TCP6(t *testing.T) {
|
|||||||
"--add-forwarded=for",
|
"--add-forwarded=for",
|
||||||
"--forwarded-for=ip",
|
"--forwarded-for=ip",
|
||||||
},
|
},
|
||||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
handler: func(_ http.ResponseWriter, r *http.Request) {
|
||||||
if got, want := r.Header.Get("X-Forwarded-For"), "2001:0db8:85a3:0000:0000:8a2e:0370:7334"; got != want {
|
if got, want := r.Header.Get("X-Forwarded-For"), "2001:0db8:85a3:0000:0000:8a2e:0370:7334"; got != want {
|
||||||
t.Errorf("X-Forwarded-For: %v; want %v", got, want)
|
t.Errorf("X-Forwarded-For: %v; want %v", got, want)
|
||||||
}
|
}
|
||||||
@@ -1401,7 +1401,7 @@ func TestH2H1ProxyProtocolV1TCP4TLS(t *testing.T) {
|
|||||||
"--add-forwarded=for",
|
"--add-forwarded=for",
|
||||||
"--forwarded-for=ip",
|
"--forwarded-for=ip",
|
||||||
},
|
},
|
||||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
handler: func(_ http.ResponseWriter, r *http.Request) {
|
||||||
if got, want := r.Header.Get("X-Forwarded-For"), "192.168.0.2"; got != want {
|
if got, want := r.Header.Get("X-Forwarded-For"), "192.168.0.2"; got != want {
|
||||||
t.Errorf("X-Forwarded-For: %v; want %v", got, want)
|
t.Errorf("X-Forwarded-For: %v; want %v", got, want)
|
||||||
}
|
}
|
||||||
@@ -1439,7 +1439,7 @@ func TestH2H1ProxyProtocolV1TCP6TLS(t *testing.T) {
|
|||||||
"--add-forwarded=for",
|
"--add-forwarded=for",
|
||||||
"--forwarded-for=ip",
|
"--forwarded-for=ip",
|
||||||
},
|
},
|
||||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
handler: func(_ http.ResponseWriter, r *http.Request) {
|
||||||
if got, want := r.Header.Get("X-Forwarded-For"), "2001:0db8:85a3:0000:0000:8a2e:0370:7334"; got != want {
|
if got, want := r.Header.Get("X-Forwarded-For"), "2001:0db8:85a3:0000:0000:8a2e:0370:7334"; got != want {
|
||||||
t.Errorf("X-Forwarded-For: %v; want %v", got, want)
|
t.Errorf("X-Forwarded-For: %v; want %v", got, want)
|
||||||
}
|
}
|
||||||
@@ -1476,7 +1476,7 @@ func TestH2H1ProxyProtocolV1Unknown(t *testing.T) {
|
|||||||
"--add-forwarded=for",
|
"--add-forwarded=for",
|
||||||
"--forwarded-for=ip",
|
"--forwarded-for=ip",
|
||||||
},
|
},
|
||||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
handler: func(_ http.ResponseWriter, r *http.Request) {
|
||||||
if got, notWant := r.Header.Get("X-Forwarded-For"), "192.168.0.2"; got == notWant {
|
if got, notWant := r.Header.Get("X-Forwarded-For"), "192.168.0.2"; got == notWant {
|
||||||
t.Errorf("X-Forwarded-For: %v; want something else", got)
|
t.Errorf("X-Forwarded-For: %v; want something else", got)
|
||||||
}
|
}
|
||||||
@@ -1881,7 +1881,7 @@ func TestH2H1ProxyProtocolV2TCP4(t *testing.T) {
|
|||||||
"--add-forwarded=for",
|
"--add-forwarded=for",
|
||||||
"--forwarded-for=ip",
|
"--forwarded-for=ip",
|
||||||
},
|
},
|
||||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
handler: func(_ http.ResponseWriter, r *http.Request) {
|
||||||
if got, want := r.Header.Get("X-Forwarded-For"), "192.168.0.2"; got != want {
|
if got, want := r.Header.Get("X-Forwarded-For"), "192.168.0.2"; got != want {
|
||||||
t.Errorf("X-Forwarded-For: %v; want %v", got, want)
|
t.Errorf("X-Forwarded-For: %v; want %v", got, want)
|
||||||
}
|
}
|
||||||
@@ -1937,7 +1937,7 @@ func TestH2H1ProxyProtocolV2TCP6(t *testing.T) {
|
|||||||
"--add-forwarded=for",
|
"--add-forwarded=for",
|
||||||
"--forwarded-for=ip",
|
"--forwarded-for=ip",
|
||||||
},
|
},
|
||||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
handler: func(_ http.ResponseWriter, r *http.Request) {
|
||||||
if got, want := r.Header.Get("X-Forwarded-For"), "2001:db8:85a3::8a2e:370:7334"; got != want {
|
if got, want := r.Header.Get("X-Forwarded-For"), "2001:db8:85a3::8a2e:370:7334"; got != want {
|
||||||
t.Errorf("X-Forwarded-For: %v; want %v", got, want)
|
t.Errorf("X-Forwarded-For: %v; want %v", got, want)
|
||||||
}
|
}
|
||||||
@@ -2009,7 +2009,7 @@ func TestH2H1ProxyProtocolV2TCP4TLS(t *testing.T) {
|
|||||||
"--add-forwarded=for",
|
"--add-forwarded=for",
|
||||||
"--forwarded-for=ip",
|
"--forwarded-for=ip",
|
||||||
},
|
},
|
||||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
handler: func(_ http.ResponseWriter, r *http.Request) {
|
||||||
if got, want := r.Header.Get("X-Forwarded-For"), "192.168.0.2"; got != want {
|
if got, want := r.Header.Get("X-Forwarded-For"), "192.168.0.2"; got != want {
|
||||||
t.Errorf("X-Forwarded-For: %v; want %v", got, want)
|
t.Errorf("X-Forwarded-For: %v; want %v", got, want)
|
||||||
}
|
}
|
||||||
@@ -2063,7 +2063,7 @@ func TestH2H1ProxyProtocolV2TCP6TLS(t *testing.T) {
|
|||||||
"--add-forwarded=for",
|
"--add-forwarded=for",
|
||||||
"--forwarded-for=ip",
|
"--forwarded-for=ip",
|
||||||
},
|
},
|
||||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
handler: func(_ http.ResponseWriter, r *http.Request) {
|
||||||
if got, want := r.Header.Get("X-Forwarded-For"), "2001:db8:85a3::8a2e:370:7334"; got != want {
|
if got, want := r.Header.Get("X-Forwarded-For"), "2001:db8:85a3::8a2e:370:7334"; got != want {
|
||||||
t.Errorf("X-Forwarded-For: %v; want %v", got, want)
|
t.Errorf("X-Forwarded-For: %v; want %v", got, want)
|
||||||
}
|
}
|
||||||
@@ -2100,7 +2100,7 @@ func TestH2H1ProxyProtocolV2Local(t *testing.T) {
|
|||||||
"--add-forwarded=for",
|
"--add-forwarded=for",
|
||||||
"--forwarded-for=ip",
|
"--forwarded-for=ip",
|
||||||
},
|
},
|
||||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
handler: func(_ http.ResponseWriter, r *http.Request) {
|
||||||
if got, want := r.Header.Get("X-Forwarded-For"), "127.0.0.1"; got != want {
|
if got, want := r.Header.Get("X-Forwarded-For"), "127.0.0.1"; got != want {
|
||||||
t.Errorf("X-Forwarded-For: %v; want %v", got, want)
|
t.Errorf("X-Forwarded-For: %v; want %v", got, want)
|
||||||
}
|
}
|
||||||
@@ -2193,7 +2193,7 @@ func TestH2H1ProxyProtocolV2Unix(t *testing.T) {
|
|||||||
"--add-forwarded=for",
|
"--add-forwarded=for",
|
||||||
"--forwarded-for=ip",
|
"--forwarded-for=ip",
|
||||||
},
|
},
|
||||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
handler: func(_ http.ResponseWriter, r *http.Request) {
|
||||||
if got, want := r.Header.Get("X-Forwarded-For"), "127.0.0.1"; got != want {
|
if got, want := r.Header.Get("X-Forwarded-For"), "127.0.0.1"; got != want {
|
||||||
t.Errorf("X-Forwarded-For: %v; want %v", got, want)
|
t.Errorf("X-Forwarded-For: %v; want %v", got, want)
|
||||||
}
|
}
|
||||||
@@ -2248,7 +2248,7 @@ func TestH2H1ProxyProtocolV2Unspec(t *testing.T) {
|
|||||||
"--add-forwarded=for",
|
"--add-forwarded=for",
|
||||||
"--forwarded-for=ip",
|
"--forwarded-for=ip",
|
||||||
},
|
},
|
||||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
handler: func(_ http.ResponseWriter, r *http.Request) {
|
||||||
if got, want := r.Header.Get("X-Forwarded-For"), "127.0.0.1"; got != want {
|
if got, want := r.Header.Get("X-Forwarded-For"), "127.0.0.1"; got != want {
|
||||||
t.Errorf("X-Forwarded-For: %v; want %v", got, want)
|
t.Errorf("X-Forwarded-For: %v; want %v", got, want)
|
||||||
}
|
}
|
||||||
@@ -2383,7 +2383,7 @@ func TestH2H1HTTPSRedirectPort(t *testing.T) {
|
|||||||
// transfer-encoding is valid.
|
// transfer-encoding is valid.
|
||||||
func TestH2H1Code204(t *testing.T) {
|
func TestH2H1Code204(t *testing.T) {
|
||||||
opts := options{
|
opts := options{
|
||||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
handler: func(w http.ResponseWriter, _ *http.Request) {
|
||||||
w.WriteHeader(http.StatusNoContent)
|
w.WriteHeader(http.StatusNoContent)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -2406,7 +2406,7 @@ func TestH2H1Code204(t *testing.T) {
|
|||||||
// is allowed.
|
// is allowed.
|
||||||
func TestH2H1Code204CL0(t *testing.T) {
|
func TestH2H1Code204CL0(t *testing.T) {
|
||||||
opts := options{
|
opts := options{
|
||||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
handler: func(w http.ResponseWriter, _ *http.Request) {
|
||||||
hj, ok := w.(http.Hijacker)
|
hj, ok := w.(http.Hijacker)
|
||||||
if !ok {
|
if !ok {
|
||||||
http.Error(w, "Could not hijack the connection", http.StatusInternalServerError)
|
http.Error(w, "Could not hijack the connection", http.StatusInternalServerError)
|
||||||
@@ -2447,7 +2447,7 @@ func TestH2H1Code204CL0(t *testing.T) {
|
|||||||
// content-length is not allowed.
|
// content-length is not allowed.
|
||||||
func TestH2H1Code204CLNonzero(t *testing.T) {
|
func TestH2H1Code204CLNonzero(t *testing.T) {
|
||||||
opts := options{
|
opts := options{
|
||||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
handler: func(w http.ResponseWriter, _ *http.Request) {
|
||||||
hj, ok := w.(http.Hijacker)
|
hj, ok := w.(http.Hijacker)
|
||||||
if !ok {
|
if !ok {
|
||||||
http.Error(w, "Could not hijack the connection", http.StatusInternalServerError)
|
http.Error(w, "Could not hijack the connection", http.StatusInternalServerError)
|
||||||
@@ -2484,7 +2484,7 @@ func TestH2H1Code204CLNonzero(t *testing.T) {
|
|||||||
// not allowed.
|
// not allowed.
|
||||||
func TestH2H1Code204TE(t *testing.T) {
|
func TestH2H1Code204TE(t *testing.T) {
|
||||||
opts := options{
|
opts := options{
|
||||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
handler: func(w http.ResponseWriter, _ *http.Request) {
|
||||||
hj, ok := w.(http.Hijacker)
|
hj, ok := w.(http.Hijacker)
|
||||||
if !ok {
|
if !ok {
|
||||||
http.Error(w, "Could not hijack the connection", http.StatusInternalServerError)
|
http.Error(w, "Could not hijack the connection", http.StatusInternalServerError)
|
||||||
@@ -2659,7 +2659,7 @@ func TestH2H1GracefulShutdown(t *testing.T) {
|
|||||||
func TestH2H2MultipleResponseCL(t *testing.T) {
|
func TestH2H2MultipleResponseCL(t *testing.T) {
|
||||||
opts := options{
|
opts := options{
|
||||||
args: []string{"--http2-bridge"},
|
args: []string{"--http2-bridge"},
|
||||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
handler: func(w http.ResponseWriter, _ *http.Request) {
|
||||||
w.Header().Add("content-length", "1")
|
w.Header().Add("content-length", "1")
|
||||||
w.Header().Add("content-length", "1")
|
w.Header().Add("content-length", "1")
|
||||||
},
|
},
|
||||||
@@ -2684,7 +2684,7 @@ func TestH2H2MultipleResponseCL(t *testing.T) {
|
|||||||
func TestH2H2InvalidResponseCL(t *testing.T) {
|
func TestH2H2InvalidResponseCL(t *testing.T) {
|
||||||
opts := options{
|
opts := options{
|
||||||
args: []string{"--http2-bridge"},
|
args: []string{"--http2-bridge"},
|
||||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
handler: func(w http.ResponseWriter, _ *http.Request) {
|
||||||
w.Header().Add("content-length", "")
|
w.Header().Add("content-length", "")
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -2783,7 +2783,7 @@ func TestH2H2NoHostRewrite(t *testing.T) {
|
|||||||
func TestH2H2TLSXfp(t *testing.T) {
|
func TestH2H2TLSXfp(t *testing.T) {
|
||||||
opts := options{
|
opts := options{
|
||||||
args: []string{"--http2-bridge"},
|
args: []string{"--http2-bridge"},
|
||||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
handler: func(_ http.ResponseWriter, r *http.Request) {
|
||||||
if got, want := r.Header.Get("x-forwarded-proto"), "http"; got != want {
|
if got, want := r.Header.Get("x-forwarded-proto"), "http"; got != want {
|
||||||
t.Errorf("x-forwarded-proto: want %v; got %v", want, got)
|
t.Errorf("x-forwarded-proto: want %v; got %v", want, got)
|
||||||
}
|
}
|
||||||
@@ -2812,7 +2812,7 @@ func TestH2H2AddXfp(t *testing.T) {
|
|||||||
"--http2-bridge",
|
"--http2-bridge",
|
||||||
"--no-strip-incoming-x-forwarded-proto",
|
"--no-strip-incoming-x-forwarded-proto",
|
||||||
},
|
},
|
||||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
handler: func(_ http.ResponseWriter, r *http.Request) {
|
||||||
xfp := r.Header.Get("X-Forwarded-Proto")
|
xfp := r.Header.Get("X-Forwarded-Proto")
|
||||||
if got, want := xfp, "foo, http"; got != want {
|
if got, want := xfp, "foo, http"; got != want {
|
||||||
t.Errorf("X-Forwarded-Proto = %q; want %q", got, want)
|
t.Errorf("X-Forwarded-Proto = %q; want %q", got, want)
|
||||||
@@ -2846,7 +2846,7 @@ func TestH2H2NoAddXfp(t *testing.T) {
|
|||||||
"--no-add-x-forwarded-proto",
|
"--no-add-x-forwarded-proto",
|
||||||
"--no-strip-incoming-x-forwarded-proto",
|
"--no-strip-incoming-x-forwarded-proto",
|
||||||
},
|
},
|
||||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
handler: func(_ http.ResponseWriter, r *http.Request) {
|
||||||
xfp := r.Header.Get("X-Forwarded-Proto")
|
xfp := r.Header.Get("X-Forwarded-Proto")
|
||||||
if got, want := xfp, "foo"; got != want {
|
if got, want := xfp, "foo"; got != want {
|
||||||
t.Errorf("X-Forwarded-Proto = %q; want %q", got, want)
|
t.Errorf("X-Forwarded-Proto = %q; want %q", got, want)
|
||||||
@@ -2876,7 +2876,7 @@ func TestH2H2NoAddXfp(t *testing.T) {
|
|||||||
func TestH2H2StripXfp(t *testing.T) {
|
func TestH2H2StripXfp(t *testing.T) {
|
||||||
opts := options{
|
opts := options{
|
||||||
args: []string{"--http2-bridge"},
|
args: []string{"--http2-bridge"},
|
||||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
handler: func(_ http.ResponseWriter, r *http.Request) {
|
||||||
xfp := r.Header.Get("X-Forwarded-Proto")
|
xfp := r.Header.Get("X-Forwarded-Proto")
|
||||||
if got, want := xfp, "http"; got != want {
|
if got, want := xfp, "http"; got != want {
|
||||||
t.Errorf("X-Forwarded-Proto = %q; want %q", got, want)
|
t.Errorf("X-Forwarded-Proto = %q; want %q", got, want)
|
||||||
@@ -2906,7 +2906,7 @@ func TestH2H2StripXfp(t *testing.T) {
|
|||||||
func TestH2H2StripNoAddXfp(t *testing.T) {
|
func TestH2H2StripNoAddXfp(t *testing.T) {
|
||||||
opts := options{
|
opts := options{
|
||||||
args: []string{"--http2-bridge", "--no-add-x-forwarded-proto"},
|
args: []string{"--http2-bridge", "--no-add-x-forwarded-proto"},
|
||||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
handler: func(_ http.ResponseWriter, r *http.Request) {
|
||||||
if got, found := r.Header["X-Forwarded-Proto"]; found {
|
if got, found := r.Header["X-Forwarded-Proto"]; found {
|
||||||
t.Errorf("X-Forwarded-Proto = %q; want nothing", got)
|
t.Errorf("X-Forwarded-Proto = %q; want nothing", got)
|
||||||
}
|
}
|
||||||
@@ -2935,7 +2935,7 @@ func TestH2H2StripNoAddXfp(t *testing.T) {
|
|||||||
func TestH2H2AddXff(t *testing.T) {
|
func TestH2H2AddXff(t *testing.T) {
|
||||||
opts := options{
|
opts := options{
|
||||||
args: []string{"--http2-bridge", "--add-x-forwarded-for"},
|
args: []string{"--http2-bridge", "--add-x-forwarded-for"},
|
||||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
handler: func(_ http.ResponseWriter, r *http.Request) {
|
||||||
xff := r.Header.Get("X-Forwarded-For")
|
xff := r.Header.Get("X-Forwarded-For")
|
||||||
want := "127.0.0.1"
|
want := "127.0.0.1"
|
||||||
if xff != want {
|
if xff != want {
|
||||||
@@ -2963,7 +2963,7 @@ func TestH2H2AddXff(t *testing.T) {
|
|||||||
func TestH2H2AddXff2(t *testing.T) {
|
func TestH2H2AddXff2(t *testing.T) {
|
||||||
opts := options{
|
opts := options{
|
||||||
args: []string{"--http2-bridge", "--add-x-forwarded-for"},
|
args: []string{"--http2-bridge", "--add-x-forwarded-for"},
|
||||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
handler: func(_ http.ResponseWriter, r *http.Request) {
|
||||||
xff := r.Header.Get("X-Forwarded-For")
|
xff := r.Header.Get("X-Forwarded-For")
|
||||||
want := "host, 127.0.0.1"
|
want := "host, 127.0.0.1"
|
||||||
if xff != want {
|
if xff != want {
|
||||||
@@ -2997,7 +2997,7 @@ func TestH2H2StripXff(t *testing.T) {
|
|||||||
"--http2-bridge",
|
"--http2-bridge",
|
||||||
"--strip-incoming-x-forwarded-for",
|
"--strip-incoming-x-forwarded-for",
|
||||||
},
|
},
|
||||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
handler: func(_ http.ResponseWriter, r *http.Request) {
|
||||||
if xff, found := r.Header["X-Forwarded-For"]; found {
|
if xff, found := r.Header["X-Forwarded-For"]; found {
|
||||||
t.Errorf("X-Forwarded-For = %v; want nothing", xff)
|
t.Errorf("X-Forwarded-For = %v; want nothing", xff)
|
||||||
}
|
}
|
||||||
@@ -3030,7 +3030,7 @@ func TestH2H2StripAddXff(t *testing.T) {
|
|||||||
"--strip-incoming-x-forwarded-for",
|
"--strip-incoming-x-forwarded-for",
|
||||||
"--add-x-forwarded-for",
|
"--add-x-forwarded-for",
|
||||||
},
|
},
|
||||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
handler: func(_ http.ResponseWriter, r *http.Request) {
|
||||||
xff := r.Header.Get("X-Forwarded-For")
|
xff := r.Header.Get("X-Forwarded-For")
|
||||||
want := "127.0.0.1"
|
want := "127.0.0.1"
|
||||||
if xff != want {
|
if xff != want {
|
||||||
@@ -3065,7 +3065,7 @@ func TestH2H2AddForwarded(t *testing.T) {
|
|||||||
"--add-forwarded=by,for,host,proto",
|
"--add-forwarded=by,for,host,proto",
|
||||||
"--forwarded-by=_alpha",
|
"--forwarded-by=_alpha",
|
||||||
},
|
},
|
||||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
handler: func(_ http.ResponseWriter, r *http.Request) {
|
||||||
pattern := fmt.Sprintf(`by=_alpha;for=_[^;]+;host="127\.0\.0\.1:%v";proto=https`, serverPort)
|
pattern := fmt.Sprintf(`by=_alpha;for=_[^;]+;host="127\.0\.0\.1:%v";proto=https`, serverPort)
|
||||||
validFwd := regexp.MustCompile(pattern)
|
validFwd := regexp.MustCompile(pattern)
|
||||||
if got := r.Header.Get("Forwarded"); !validFwd.MatchString(got) {
|
if got := r.Header.Get("Forwarded"); !validFwd.MatchString(got) {
|
||||||
@@ -3099,7 +3099,7 @@ func TestH2H2AddForwardedMerge(t *testing.T) {
|
|||||||
"--add-forwarded=by,host,proto",
|
"--add-forwarded=by,host,proto",
|
||||||
"--forwarded-by=_alpha",
|
"--forwarded-by=_alpha",
|
||||||
},
|
},
|
||||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
handler: func(_ http.ResponseWriter, r *http.Request) {
|
||||||
want := fmt.Sprintf(`host=foo, by=_alpha;host="127.0.0.1:%v";proto=https`, serverPort)
|
want := fmt.Sprintf(`host=foo, by=_alpha;host="127.0.0.1:%v";proto=https`, serverPort)
|
||||||
if got := r.Header.Get("Forwarded"); got != want {
|
if got := r.Header.Get("Forwarded"); got != want {
|
||||||
t.Errorf("Forwarded = %v; want %v", got, want)
|
t.Errorf("Forwarded = %v; want %v", got, want)
|
||||||
@@ -3136,7 +3136,7 @@ func TestH2H2AddForwardedStrip(t *testing.T) {
|
|||||||
"--add-forwarded=by,host,proto",
|
"--add-forwarded=by,host,proto",
|
||||||
"--forwarded-by=_alpha",
|
"--forwarded-by=_alpha",
|
||||||
},
|
},
|
||||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
handler: func(_ http.ResponseWriter, r *http.Request) {
|
||||||
want := fmt.Sprintf(`by=_alpha;host="127.0.0.1:%v";proto=https`, serverPort)
|
want := fmt.Sprintf(`by=_alpha;host="127.0.0.1:%v";proto=https`, serverPort)
|
||||||
if got := r.Header.Get("Forwarded"); got != want {
|
if got := r.Header.Get("Forwarded"); got != want {
|
||||||
t.Errorf("Forwarded = %v; want %v", got, want)
|
t.Errorf("Forwarded = %v; want %v", got, want)
|
||||||
@@ -3167,7 +3167,7 @@ func TestH2H2AddForwardedStrip(t *testing.T) {
|
|||||||
func TestH2H2StripForwarded(t *testing.T) {
|
func TestH2H2StripForwarded(t *testing.T) {
|
||||||
opts := options{
|
opts := options{
|
||||||
args: []string{"--http2-bridge", "--strip-incoming-forwarded"},
|
args: []string{"--http2-bridge", "--strip-incoming-forwarded"},
|
||||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
handler: func(_ http.ResponseWriter, r *http.Request) {
|
||||||
if got, found := r.Header["Forwarded"]; found {
|
if got, found := r.Header["Forwarded"]; found {
|
||||||
t.Errorf("Forwarded = %v; want nothing", got)
|
t.Errorf("Forwarded = %v; want nothing", got)
|
||||||
}
|
}
|
||||||
@@ -3200,7 +3200,7 @@ func TestH2H2ReqPhaseReturn(t *testing.T) {
|
|||||||
"--http2-bridge",
|
"--http2-bridge",
|
||||||
"--mruby-file=" + testDir + "/req-return.rb",
|
"--mruby-file=" + testDir + "/req-return.rb",
|
||||||
},
|
},
|
||||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
handler: func(http.ResponseWriter, *http.Request) {
|
||||||
t.Fatalf("request should not be forwarded")
|
t.Fatalf("request should not be forwarded")
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -3322,7 +3322,7 @@ func TestH2H2DNS(t *testing.T) {
|
|||||||
func TestH2H2Code204(t *testing.T) {
|
func TestH2H2Code204(t *testing.T) {
|
||||||
opts := options{
|
opts := options{
|
||||||
args: []string{"--http2-bridge"},
|
args: []string{"--http2-bridge"},
|
||||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
handler: func(w http.ResponseWriter, _ *http.Request) {
|
||||||
w.WriteHeader(http.StatusNoContent)
|
w.WriteHeader(http.StatusNoContent)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -3346,7 +3346,7 @@ func TestH2H2Code204(t *testing.T) {
|
|||||||
func TestH2APIBackendconfig(t *testing.T) {
|
func TestH2APIBackendconfig(t *testing.T) {
|
||||||
opts := options{
|
opts := options{
|
||||||
args: []string{"-f127.0.0.1,3010;api;no-tls"},
|
args: []string{"-f127.0.0.1,3010;api;no-tls"},
|
||||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
handler: func(http.ResponseWriter, *http.Request) {
|
||||||
t.Fatalf("request should not be forwarded")
|
t.Fatalf("request should not be forwarded")
|
||||||
},
|
},
|
||||||
connectPort: 3010,
|
connectPort: 3010,
|
||||||
@@ -3388,7 +3388,7 @@ backend=127.0.0.1,3011
|
|||||||
func TestH2APIBackendconfigQuery(t *testing.T) {
|
func TestH2APIBackendconfigQuery(t *testing.T) {
|
||||||
opts := options{
|
opts := options{
|
||||||
args: []string{"-f127.0.0.1,3010;api;no-tls"},
|
args: []string{"-f127.0.0.1,3010;api;no-tls"},
|
||||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
handler: func(http.ResponseWriter, *http.Request) {
|
||||||
t.Fatalf("request should not be forwarded")
|
t.Fatalf("request should not be forwarded")
|
||||||
},
|
},
|
||||||
connectPort: 3010,
|
connectPort: 3010,
|
||||||
@@ -3430,7 +3430,7 @@ backend=127.0.0.1,3011
|
|||||||
func TestH2APIBackendconfigBadMethod(t *testing.T) {
|
func TestH2APIBackendconfigBadMethod(t *testing.T) {
|
||||||
opts := options{
|
opts := options{
|
||||||
args: []string{"-f127.0.0.1,3010;api;no-tls"},
|
args: []string{"-f127.0.0.1,3010;api;no-tls"},
|
||||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
handler: func(http.ResponseWriter, *http.Request) {
|
||||||
t.Fatalf("request should not be forwarded")
|
t.Fatalf("request should not be forwarded")
|
||||||
},
|
},
|
||||||
connectPort: 3010,
|
connectPort: 3010,
|
||||||
@@ -3471,7 +3471,7 @@ backend=127.0.0.1,3011
|
|||||||
func TestH2APIConfigrevision(t *testing.T) {
|
func TestH2APIConfigrevision(t *testing.T) {
|
||||||
opts := options{
|
opts := options{
|
||||||
args: []string{"-f127.0.0.1,3010;api;no-tls"},
|
args: []string{"-f127.0.0.1,3010;api;no-tls"},
|
||||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
handler: func(http.ResponseWriter, *http.Request) {
|
||||||
t.Fatalf("request should not be forwarded")
|
t.Fatalf("request should not be forwarded")
|
||||||
},
|
},
|
||||||
connectPort: 3010,
|
connectPort: 3010,
|
||||||
@@ -3514,7 +3514,7 @@ func TestH2APIConfigrevision(t *testing.T) {
|
|||||||
func TestH2APINotFound(t *testing.T) {
|
func TestH2APINotFound(t *testing.T) {
|
||||||
opts := options{
|
opts := options{
|
||||||
args: []string{"-f127.0.0.1,3010;api;no-tls"},
|
args: []string{"-f127.0.0.1,3010;api;no-tls"},
|
||||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
handler: func(http.ResponseWriter, *http.Request) {
|
||||||
t.Fatalf("request should not be forwarded")
|
t.Fatalf("request should not be forwarded")
|
||||||
},
|
},
|
||||||
connectPort: 3010,
|
connectPort: 3010,
|
||||||
@@ -3555,7 +3555,7 @@ backend=127.0.0.1,3011
|
|||||||
func TestH2Healthmon(t *testing.T) {
|
func TestH2Healthmon(t *testing.T) {
|
||||||
opts := options{
|
opts := options{
|
||||||
args: []string{"-f127.0.0.1,3011;healthmon;no-tls"},
|
args: []string{"-f127.0.0.1,3011;healthmon;no-tls"},
|
||||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
handler: func(http.ResponseWriter, *http.Request) {
|
||||||
t.Fatalf("request should not be forwarded")
|
t.Fatalf("request should not be forwarded")
|
||||||
},
|
},
|
||||||
connectPort: 3011,
|
connectPort: 3011,
|
||||||
@@ -3580,7 +3580,7 @@ func TestH2Healthmon(t *testing.T) {
|
|||||||
func TestH2ResponseBeforeRequestEnd(t *testing.T) {
|
func TestH2ResponseBeforeRequestEnd(t *testing.T) {
|
||||||
opts := options{
|
opts := options{
|
||||||
args: []string{"--mruby-file=" + testDir + "/req-return.rb"},
|
args: []string{"--mruby-file=" + testDir + "/req-return.rb"},
|
||||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
handler: func(http.ResponseWriter, *http.Request) {
|
||||||
t.Fatal("request should not be forwarded")
|
t.Fatal("request should not be forwarded")
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -3603,7 +3603,7 @@ func TestH2ResponseBeforeRequestEnd(t *testing.T) {
|
|||||||
// backend chunked encoded response ends prematurely.
|
// backend chunked encoded response ends prematurely.
|
||||||
func TestH2H1ChunkedEndsPrematurely(t *testing.T) {
|
func TestH2H1ChunkedEndsPrematurely(t *testing.T) {
|
||||||
opts := options{
|
opts := options{
|
||||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
handler: func(w http.ResponseWriter, _ *http.Request) {
|
||||||
hj, ok := w.(http.Hijacker)
|
hj, ok := w.(http.Hijacker)
|
||||||
if !ok {
|
if !ok {
|
||||||
http.Error(w, "Could not hijack the connection", http.StatusInternalServerError)
|
http.Error(w, "Could not hijack the connection", http.StatusInternalServerError)
|
||||||
@@ -3641,7 +3641,7 @@ func TestH2H1ChunkedEndsPrematurely(t *testing.T) {
|
|||||||
func TestH2H1RequireHTTPSchemeHTTPSWithoutEncryption(t *testing.T) {
|
func TestH2H1RequireHTTPSchemeHTTPSWithoutEncryption(t *testing.T) {
|
||||||
opts := options{
|
opts := options{
|
||||||
args: []string{"--require-http-scheme"},
|
args: []string{"--require-http-scheme"},
|
||||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
handler: func(http.ResponseWriter, *http.Request) {
|
||||||
t.Errorf("server should not forward this request")
|
t.Errorf("server should not forward this request")
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -3666,7 +3666,7 @@ func TestH2H1RequireHTTPSchemeHTTPSWithoutEncryption(t *testing.T) {
|
|||||||
func TestH2H1RequireHTTPSchemeHTTPWithEncryption(t *testing.T) {
|
func TestH2H1RequireHTTPSchemeHTTPWithEncryption(t *testing.T) {
|
||||||
opts := options{
|
opts := options{
|
||||||
args: []string{"--require-http-scheme"},
|
args: []string{"--require-http-scheme"},
|
||||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
handler: func(http.ResponseWriter, *http.Request) {
|
||||||
t.Errorf("server should not forward this request")
|
t.Errorf("server should not forward this request")
|
||||||
},
|
},
|
||||||
tls: true,
|
tls: true,
|
||||||
@@ -3693,7 +3693,7 @@ func TestH2H1RequireHTTPSchemeHTTPWithEncryption(t *testing.T) {
|
|||||||
func TestH2H1RequireHTTPSchemeUnknownSchemeWithoutEncryption(t *testing.T) {
|
func TestH2H1RequireHTTPSchemeUnknownSchemeWithoutEncryption(t *testing.T) {
|
||||||
opts := options{
|
opts := options{
|
||||||
args: []string{"--require-http-scheme"},
|
args: []string{"--require-http-scheme"},
|
||||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
handler: func(http.ResponseWriter, *http.Request) {
|
||||||
t.Errorf("server should not forward this request")
|
t.Errorf("server should not forward this request")
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -3718,7 +3718,7 @@ func TestH2H1RequireHTTPSchemeUnknownSchemeWithoutEncryption(t *testing.T) {
|
|||||||
func TestH2H1RequireHTTPSchemeUnknownSchemeWithEncryption(t *testing.T) {
|
func TestH2H1RequireHTTPSchemeUnknownSchemeWithEncryption(t *testing.T) {
|
||||||
opts := options{
|
opts := options{
|
||||||
args: []string{"--require-http-scheme"},
|
args: []string{"--require-http-scheme"},
|
||||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
handler: func(http.ResponseWriter, *http.Request) {
|
||||||
t.Errorf("server should not forward this request")
|
t.Errorf("server should not forward this request")
|
||||||
},
|
},
|
||||||
tls: true,
|
tls: true,
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ func TestH3H1RequestBody(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
opts := options{
|
opts := options{
|
||||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
handler: func(_ http.ResponseWriter, r *http.Request) {
|
||||||
buf := make([]byte, 4096)
|
buf := make([]byte, 4096)
|
||||||
buflen := 0
|
buflen := 0
|
||||||
p := buf
|
p := buf
|
||||||
@@ -92,7 +92,7 @@ func TestH3H1RequestBody(t *testing.T) {
|
|||||||
// and from backend server.
|
// and from backend server.
|
||||||
func TestH3H1GenerateVia(t *testing.T) {
|
func TestH3H1GenerateVia(t *testing.T) {
|
||||||
opts := options{
|
opts := options{
|
||||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
handler: func(_ http.ResponseWriter, r *http.Request) {
|
||||||
if got, want := r.Header.Get("Via"), "3 nghttpx"; got != want {
|
if got, want := r.Header.Get("Via"), "3 nghttpx"; got != want {
|
||||||
t.Errorf("Via: %v; want %v", got, want)
|
t.Errorf("Via: %v; want %v", got, want)
|
||||||
}
|
}
|
||||||
@@ -177,7 +177,7 @@ func TestH3H1NoVia(t *testing.T) {
|
|||||||
// response body size.
|
// response body size.
|
||||||
func TestH3H1BadResponseCL(t *testing.T) {
|
func TestH3H1BadResponseCL(t *testing.T) {
|
||||||
opts := options{
|
opts := options{
|
||||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
handler: func(w http.ResponseWriter, _ *http.Request) {
|
||||||
// we set content-length: 1024, but only send 3 bytes.
|
// we set content-length: 1024, but only send 3 bytes.
|
||||||
w.Header().Add("Content-Length", "1024")
|
w.Header().Add("Content-Length", "1024")
|
||||||
if _, err := w.Write([]byte("foo")); err != nil {
|
if _, err := w.Write([]byte("foo")); err != nil {
|
||||||
@@ -256,7 +256,7 @@ func TestH3H2ReqPhaseReturn(t *testing.T) {
|
|||||||
"--http2-bridge",
|
"--http2-bridge",
|
||||||
"--mruby-file=" + testDir + "/req-return.rb",
|
"--mruby-file=" + testDir + "/req-return.rb",
|
||||||
},
|
},
|
||||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
handler: func(http.ResponseWriter, *http.Request) {
|
||||||
t.Fatalf("request should not be forwarded")
|
t.Fatalf("request should not be forwarded")
|
||||||
},
|
},
|
||||||
quic: true,
|
quic: true,
|
||||||
@@ -338,7 +338,7 @@ func TestH3H2RespPhaseReturn(t *testing.T) {
|
|||||||
func TestH3ResponseBeforeRequestEnd(t *testing.T) {
|
func TestH3ResponseBeforeRequestEnd(t *testing.T) {
|
||||||
opts := options{
|
opts := options{
|
||||||
args: []string{"--mruby-file=" + testDir + "/req-return.rb"},
|
args: []string{"--mruby-file=" + testDir + "/req-return.rb"},
|
||||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
handler: func(http.ResponseWriter, *http.Request) {
|
||||||
t.Fatal("request should not be forwarded")
|
t.Fatal("request should not be forwarded")
|
||||||
},
|
},
|
||||||
quic: true,
|
quic: true,
|
||||||
@@ -362,7 +362,7 @@ func TestH3ResponseBeforeRequestEnd(t *testing.T) {
|
|||||||
// backend chunked encoded response ends prematurely.
|
// backend chunked encoded response ends prematurely.
|
||||||
func TestH3H1ChunkedEndsPrematurely(t *testing.T) {
|
func TestH3H1ChunkedEndsPrematurely(t *testing.T) {
|
||||||
opts := options{
|
opts := options{
|
||||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
handler: func(w http.ResponseWriter, _ *http.Request) {
|
||||||
hj, ok := w.(http.Hijacker)
|
hj, ok := w.(http.Hijacker)
|
||||||
if !ok {
|
if !ok {
|
||||||
http.Error(w, "Could not hijack the connection", http.StatusInternalServerError)
|
http.Error(w, "Could not hijack the connection", http.StatusInternalServerError)
|
||||||
|
|||||||
@@ -22,7 +22,6 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/quic-go/quic-go/http3"
|
|
||||||
"github.com/tatsuhiro-t/go-nghttp2"
|
"github.com/tatsuhiro-t/go-nghttp2"
|
||||||
"golang.org/x/net/http2"
|
"golang.org/x/net/http2"
|
||||||
"golang.org/x/net/http2/hpack"
|
"golang.org/x/net/http2/hpack"
|
||||||
@@ -390,81 +389,6 @@ func (st *serverTester) websocket(rp requestParam) *serverResponse {
|
|||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
func (st *serverTester) http3(rp requestParam) (*serverResponse, error) {
|
|
||||||
rt := &http3.RoundTripper{
|
|
||||||
TLSClientConfig: &tls.Config{
|
|
||||||
InsecureSkipVerify: true,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
defer rt.Close()
|
|
||||||
|
|
||||||
c := &http.Client{
|
|
||||||
Transport: rt,
|
|
||||||
}
|
|
||||||
|
|
||||||
method := "GET"
|
|
||||||
if rp.method != "" {
|
|
||||||
method = rp.method
|
|
||||||
}
|
|
||||||
|
|
||||||
var body io.Reader
|
|
||||||
|
|
||||||
if rp.body != nil {
|
|
||||||
body = bytes.NewBuffer(rp.body)
|
|
||||||
}
|
|
||||||
|
|
||||||
reqURL := st.url
|
|
||||||
|
|
||||||
if rp.path != "" {
|
|
||||||
u, err := url.Parse(st.url)
|
|
||||||
if err != nil {
|
|
||||||
st.t.Fatalf("Error parsing URL from st.url %v: %v", st.url, err)
|
|
||||||
}
|
|
||||||
u.Path = ""
|
|
||||||
u.RawQuery = ""
|
|
||||||
reqURL = u.String() + rp.path
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
|
|
||||||
defer cancel()
|
|
||||||
|
|
||||||
req, err := http.NewRequestWithContext(ctx, method, reqURL, body)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, h := range rp.header {
|
|
||||||
req.Header.Add(h.Name, h.Value)
|
|
||||||
}
|
|
||||||
|
|
||||||
req.Header.Add("Test-Case", rp.name)
|
|
||||||
|
|
||||||
// TODO http3 package does not support trailer at the time of
|
|
||||||
// this writing.
|
|
||||||
|
|
||||||
resp, err := c.Do(req)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
defer resp.Body.Close()
|
|
||||||
|
|
||||||
respBody, err := io.ReadAll(resp.Body)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
res := &serverResponse{
|
|
||||||
status: resp.StatusCode,
|
|
||||||
header: resp.Header,
|
|
||||||
body: respBody,
|
|
||||||
connClose: resp.Close,
|
|
||||||
}
|
|
||||||
|
|
||||||
return res, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (st *serverTester) http1(rp requestParam) (*serverResponse, error) {
|
func (st *serverTester) http1(rp requestParam) (*serverResponse, error) {
|
||||||
method := "GET"
|
method := "GET"
|
||||||
if rp.method != "" {
|
if rp.method != "" {
|
||||||
@@ -728,7 +652,7 @@ type serverResponse struct {
|
|||||||
errCode http2.ErrCode // error code received in HTTP/2 RST_STREAM or GOAWAY
|
errCode http2.ErrCode // error code received in HTTP/2 RST_STREAM or GOAWAY
|
||||||
connErr bool // true if HTTP/2 connection error
|
connErr bool // true if HTTP/2 connection error
|
||||||
connClose bool // Connection: close is included in response header in HTTP/1 test
|
connClose bool // Connection: close is included in response header in HTTP/1 test
|
||||||
reqHeader http.Header // http request header, currently only sotres pushed request header
|
reqHeader http.Header // http request header, currently only stores pushed request header
|
||||||
pushResponse []*serverResponse // pushed response
|
pushResponse []*serverResponse // pushed response
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
90
integration-tests/server_tester_http3.go
Normal file
90
integration-tests/server_tester_http3.go
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
//go:build quic
|
||||||
|
|
||||||
|
package nghttp2
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"context"
|
||||||
|
"crypto/tls"
|
||||||
|
"io"
|
||||||
|
"net/http"
|
||||||
|
"net/url"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/quic-go/quic-go/http3"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (st *serverTester) http3(rp requestParam) (*serverResponse, error) {
|
||||||
|
rt := &http3.RoundTripper{
|
||||||
|
TLSClientConfig: &tls.Config{
|
||||||
|
InsecureSkipVerify: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
defer rt.Close()
|
||||||
|
|
||||||
|
c := &http.Client{
|
||||||
|
Transport: rt,
|
||||||
|
}
|
||||||
|
|
||||||
|
method := "GET"
|
||||||
|
if rp.method != "" {
|
||||||
|
method = rp.method
|
||||||
|
}
|
||||||
|
|
||||||
|
var body io.Reader
|
||||||
|
|
||||||
|
if rp.body != nil {
|
||||||
|
body = bytes.NewBuffer(rp.body)
|
||||||
|
}
|
||||||
|
|
||||||
|
reqURL := st.url
|
||||||
|
|
||||||
|
if rp.path != "" {
|
||||||
|
u, err := url.Parse(st.url)
|
||||||
|
if err != nil {
|
||||||
|
st.t.Fatalf("Error parsing URL from st.url %v: %v", st.url, err)
|
||||||
|
}
|
||||||
|
u.Path = ""
|
||||||
|
u.RawQuery = ""
|
||||||
|
reqURL = u.String() + rp.path
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
req, err := http.NewRequestWithContext(ctx, method, reqURL, body)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, h := range rp.header {
|
||||||
|
req.Header.Add(h.Name, h.Value)
|
||||||
|
}
|
||||||
|
|
||||||
|
req.Header.Add("Test-Case", rp.name)
|
||||||
|
|
||||||
|
// TODO http3 package does not support trailer at the time of
|
||||||
|
// this writing.
|
||||||
|
|
||||||
|
resp, err := c.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
respBody, err := io.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
res := &serverResponse{
|
||||||
|
status: resp.StatusCode,
|
||||||
|
header: resp.Header,
|
||||||
|
body: respBody,
|
||||||
|
connClose: resp.Close,
|
||||||
|
}
|
||||||
|
|
||||||
|
return res, nil
|
||||||
|
}
|
||||||
@@ -9,5 +9,6 @@ export CGO_CFLAGS="-I@abs_top_srcdir@/lib/includes -I@abs_top_builddir@/lib/incl
|
|||||||
export CGO_CPPFLAGS="@CPPFLAGS@"
|
export CGO_CPPFLAGS="@CPPFLAGS@"
|
||||||
export CGO_LDFLAGS="-L$libdir @LDFLAGS@"
|
export CGO_LDFLAGS="-L$libdir @LDFLAGS@"
|
||||||
export LD_LIBRARY_PATH="$libdir"
|
export LD_LIBRARY_PATH="$libdir"
|
||||||
|
export DYLD_LIBRARY_PATH="$libdir"
|
||||||
export GODEBUG=cgocheck=0
|
export GODEBUG=cgocheck=0
|
||||||
"$@"
|
"$@"
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ set(NGHTTP2_SOURCES
|
|||||||
nghttp2_stream.c nghttp2_outbound_item.c
|
nghttp2_stream.c nghttp2_outbound_item.c
|
||||||
nghttp2_session.c nghttp2_submit.c
|
nghttp2_session.c nghttp2_submit.c
|
||||||
nghttp2_helper.c
|
nghttp2_helper.c
|
||||||
nghttp2_npn.c
|
nghttp2_alpn.c
|
||||||
nghttp2_hd.c nghttp2_hd_huffman.c nghttp2_hd_huffman_data.c
|
nghttp2_hd.c nghttp2_hd_huffman.c nghttp2_hd_huffman_data.c
|
||||||
nghttp2_version.c
|
nghttp2_version.c
|
||||||
nghttp2_priority_spec.c
|
nghttp2_priority_spec.c
|
||||||
@@ -31,6 +31,12 @@ set(NGHTTP2_SOURCES
|
|||||||
)
|
)
|
||||||
|
|
||||||
set(NGHTTP2_RES "")
|
set(NGHTTP2_RES "")
|
||||||
|
set(STATIC_LIB "nghttp2_static")
|
||||||
|
set(SHARED_LIB "nghttp2")
|
||||||
|
|
||||||
|
if(BUILD_SHARED_LIBS AND BUILD_STATIC_LIBS AND MSVC AND NOT STATIC_LIB_SUFFIX)
|
||||||
|
set(STATIC_LIB_SUFFIX "_static")
|
||||||
|
endif()
|
||||||
|
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
configure_file(
|
configure_file(
|
||||||
@@ -41,40 +47,61 @@ if(WIN32)
|
|||||||
set(NGHTTP2_RES ${CMAKE_CURRENT_BINARY_DIR}/version.rc)
|
set(NGHTTP2_RES ${CMAKE_CURRENT_BINARY_DIR}/version.rc)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
set(EXPORT_SET "${PROJECT_NAME}-targets")
|
||||||
|
|
||||||
# Public shared library
|
# Public shared library
|
||||||
if(ENABLE_SHARED_LIB)
|
if(BUILD_SHARED_LIBS)
|
||||||
add_library(nghttp2 SHARED ${NGHTTP2_SOURCES} ${NGHTTP2_RES})
|
add_library(${SHARED_LIB} SHARED ${NGHTTP2_SOURCES} ${NGHTTP2_RES})
|
||||||
set_target_properties(nghttp2 PROPERTIES
|
|
||||||
|
set_target_properties(${SHARED_LIB} PROPERTIES
|
||||||
COMPILE_FLAGS "${WARNCFLAGS}"
|
COMPILE_FLAGS "${WARNCFLAGS}"
|
||||||
VERSION ${LT_VERSION} SOVERSION ${LT_SOVERSION}
|
VERSION ${LT_VERSION} SOVERSION ${LT_SOVERSION}
|
||||||
C_VISIBILITY_PRESET hidden
|
C_VISIBILITY_PRESET hidden
|
||||||
)
|
)
|
||||||
target_include_directories(nghttp2 INTERFACE
|
|
||||||
"${CMAKE_CURRENT_BINARY_DIR}/includes"
|
target_include_directories(${SHARED_LIB} INTERFACE
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/includes"
|
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/includes>
|
||||||
|
$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}/includes>
|
||||||
|
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
|
||||||
)
|
)
|
||||||
|
|
||||||
install(TARGETS nghttp2
|
install(TARGETS ${SHARED_LIB} EXPORT ${EXPORT_SET})
|
||||||
ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}"
|
list(APPEND nghttp2_exports ${SHARED_LIB})
|
||||||
LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}"
|
|
||||||
RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}")
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(HAVE_CUNIT OR ENABLE_STATIC_LIB)
|
# Static library (for unittests because of symbol visibility)
|
||||||
# Static library (for unittests because of symbol visibility)
|
if(BUILD_STATIC_LIBS)
|
||||||
add_library(nghttp2_static STATIC ${NGHTTP2_SOURCES})
|
add_library(${STATIC_LIB} STATIC ${NGHTTP2_SOURCES})
|
||||||
set_target_properties(nghttp2_static PROPERTIES
|
|
||||||
|
set_target_properties(${STATIC_LIB} PROPERTIES
|
||||||
COMPILE_FLAGS "${WARNCFLAGS}"
|
COMPILE_FLAGS "${WARNCFLAGS}"
|
||||||
VERSION ${LT_VERSION} SOVERSION ${LT_SOVERSION}
|
VERSION ${LT_VERSION} SOVERSION ${LT_SOVERSION}
|
||||||
ARCHIVE_OUTPUT_NAME nghttp2${STATIC_LIB_SUFFIX}
|
ARCHIVE_OUTPUT_NAME nghttp2${STATIC_LIB_SUFFIX}
|
||||||
)
|
)
|
||||||
target_compile_definitions(nghttp2_static PUBLIC "-DNGHTTP2_STATICLIB")
|
|
||||||
if(ENABLE_STATIC_LIB)
|
target_include_directories(${STATIC_LIB} INTERFACE
|
||||||
install(TARGETS nghttp2_static
|
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/includes>
|
||||||
DESTINATION "${CMAKE_INSTALL_LIBDIR}")
|
$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}/includes>
|
||||||
endif()
|
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
|
||||||
|
)
|
||||||
|
|
||||||
|
target_compile_definitions(${STATIC_LIB} PUBLIC "-DNGHTTP2_STATICLIB")
|
||||||
|
|
||||||
|
install(TARGETS ${STATIC_LIB} EXPORT ${EXPORT_SET})
|
||||||
|
list(APPEND nghttp2_exports ${STATIC_LIB})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(BUILD_SHARED_LIBS)
|
||||||
|
set(LIB_SELECTED ${SHARED_LIB})
|
||||||
|
else()
|
||||||
|
set(LIB_SELECTED ${STATIC_LIB})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
add_library(${PROJECT_NAME}::nghttp2 ALIAS ${LIB_SELECTED})
|
||||||
|
|
||||||
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/libnghttp2.pc"
|
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/libnghttp2.pc"
|
||||||
DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig")
|
DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig")
|
||||||
|
|
||||||
|
install(EXPORT ${EXPORT_SET}
|
||||||
|
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}
|
||||||
|
NAMESPACE ${PROJECT_NAME}::)
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ OBJECTS = nghttp2_pq.c nghttp2_map.c nghttp2_queue.c \
|
|||||||
nghttp2_stream.c nghttp2_outbound_item.c \
|
nghttp2_stream.c nghttp2_outbound_item.c \
|
||||||
nghttp2_session.c nghttp2_submit.c \
|
nghttp2_session.c nghttp2_submit.c \
|
||||||
nghttp2_helper.c \
|
nghttp2_helper.c \
|
||||||
nghttp2_npn.c \
|
nghttp2_alpn.c \
|
||||||
nghttp2_hd.c nghttp2_hd_huffman.c nghttp2_hd_huffman_data.c \
|
nghttp2_hd.c nghttp2_hd_huffman.c nghttp2_hd_huffman_data.c \
|
||||||
nghttp2_version.c \
|
nghttp2_version.c \
|
||||||
nghttp2_priority_spec.c \
|
nghttp2_priority_spec.c \
|
||||||
@@ -60,7 +60,7 @@ HFILES = nghttp2_pq.h nghttp2_int.h nghttp2_map.h nghttp2_queue.h \
|
|||||||
nghttp2_frame.h \
|
nghttp2_frame.h \
|
||||||
nghttp2_buf.h \
|
nghttp2_buf.h \
|
||||||
nghttp2_session.h nghttp2_helper.h nghttp2_stream.h nghttp2_int.h \
|
nghttp2_session.h nghttp2_helper.h nghttp2_stream.h nghttp2_int.h \
|
||||||
nghttp2_npn.h \
|
nghttp2_alpn.h \
|
||||||
nghttp2_submit.h nghttp2_outbound_item.h \
|
nghttp2_submit.h nghttp2_outbound_item.h \
|
||||||
nghttp2_net.h \
|
nghttp2_net.h \
|
||||||
nghttp2_hd.h nghttp2_hd_huffman.h \
|
nghttp2_hd.h nghttp2_hd_huffman.h \
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ NGHTTP2_SRC := nghttp2_pq.c \
|
|||||||
nghttp2_session.c \
|
nghttp2_session.c \
|
||||||
nghttp2_submit.c \
|
nghttp2_submit.c \
|
||||||
nghttp2_helper.c \
|
nghttp2_helper.c \
|
||||||
nghttp2_npn.c \
|
nghttp2_alpn.c \
|
||||||
nghttp2_hd.c \
|
nghttp2_hd.c \
|
||||||
nghttp2_hd_huffman.c \
|
nghttp2_hd_huffman.c \
|
||||||
nghttp2_hd_huffman_data.c \
|
nghttp2_hd_huffman_data.c \
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -22,11 +22,11 @@
|
|||||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
#include "nghttp2_npn.h"
|
#include "nghttp2_alpn.h"
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
static int select_next_protocol(unsigned char **out, unsigned char *outlen,
|
static int select_alpn(const unsigned char **out, unsigned char *outlen,
|
||||||
const unsigned char *in, unsigned int inlen,
|
const unsigned char *in, unsigned int inlen,
|
||||||
const char *key, unsigned int keylen) {
|
const char *key, unsigned int keylen) {
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
@@ -45,11 +45,24 @@ static int select_next_protocol(unsigned char **out, unsigned char *outlen,
|
|||||||
|
|
||||||
int nghttp2_select_next_protocol(unsigned char **out, unsigned char *outlen,
|
int nghttp2_select_next_protocol(unsigned char **out, unsigned char *outlen,
|
||||||
const unsigned char *in, unsigned int inlen) {
|
const unsigned char *in, unsigned int inlen) {
|
||||||
if (select_next_protocol(out, outlen, in, inlen, NGHTTP2_PROTO_ALPN,
|
if (select_alpn((const unsigned char **)out, outlen, in, inlen,
|
||||||
|
NGHTTP2_PROTO_ALPN, NGHTTP2_PROTO_ALPN_LEN) == 0) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (select_alpn((const unsigned char **)out, outlen, in, inlen,
|
||||||
|
NGHTTP2_HTTP_1_1_ALPN, NGHTTP2_HTTP_1_1_ALPN_LEN) == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int nghttp2_select_alpn(const unsigned char **out, unsigned char *outlen,
|
||||||
|
const unsigned char *in, unsigned int inlen) {
|
||||||
|
if (select_alpn(out, outlen, in, inlen, NGHTTP2_PROTO_ALPN,
|
||||||
NGHTTP2_PROTO_ALPN_LEN) == 0) {
|
NGHTTP2_PROTO_ALPN_LEN) == 0) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
if (select_next_protocol(out, outlen, in, inlen, NGHTTP2_HTTP_1_1_ALPN,
|
if (select_alpn(out, outlen, in, inlen, NGHTTP2_HTTP_1_1_ALPN,
|
||||||
NGHTTP2_HTTP_1_1_ALPN_LEN) == 0) {
|
NGHTTP2_HTTP_1_1_ALPN_LEN) == 0) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -22,8 +22,8 @@
|
|||||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
#ifndef NGHTTP2_NPN_H
|
#ifndef NGHTTP2_ALPN_H
|
||||||
#define NGHTTP2_NPN_H
|
#define NGHTTP2_ALPN_H
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
# include <config.h>
|
# include <config.h>
|
||||||
@@ -31,4 +31,4 @@
|
|||||||
|
|
||||||
#include <nghttp2/nghttp2.h>
|
#include <nghttp2/nghttp2.h>
|
||||||
|
|
||||||
#endif /* NGHTTP2_NPN_H */
|
#endif /* NGHTTP2_ALPN_H */
|
||||||
@@ -61,7 +61,7 @@ int nghttp2_buf_reserve(nghttp2_buf *buf, size_t new_cap, nghttp2_mem *mem) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
new_cap = nghttp2_max(new_cap, cap * 2);
|
new_cap = nghttp2_max_size(new_cap, cap * 2);
|
||||||
|
|
||||||
ptr = nghttp2_mem_realloc(mem, buf->begin, new_cap);
|
ptr = nghttp2_mem_realloc(mem, buf->begin, new_cap);
|
||||||
if (ptr == NULL) {
|
if (ptr == NULL) {
|
||||||
@@ -343,7 +343,7 @@ int nghttp2_bufs_add(nghttp2_bufs *bufs, const void *data, size_t len) {
|
|||||||
while (len) {
|
while (len) {
|
||||||
buf = &bufs->cur->buf;
|
buf = &bufs->cur->buf;
|
||||||
|
|
||||||
nwrite = nghttp2_min(nghttp2_buf_avail(buf), len);
|
nwrite = nghttp2_min_size(nghttp2_buf_avail(buf), len);
|
||||||
if (nwrite == 0) {
|
if (nwrite == 0) {
|
||||||
rv = bufs_alloc_chain(bufs);
|
rv = bufs_alloc_chain(bufs);
|
||||||
if (rv != 0) {
|
if (rv != 0) {
|
||||||
@@ -430,7 +430,7 @@ int nghttp2_bufs_orb_hold(nghttp2_bufs *bufs, uint8_t b) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t nghttp2_bufs_remove(nghttp2_bufs *bufs, uint8_t **out) {
|
nghttp2_ssize nghttp2_bufs_remove(nghttp2_bufs *bufs, uint8_t **out) {
|
||||||
size_t len;
|
size_t len;
|
||||||
nghttp2_buf_chain *chain;
|
nghttp2_buf_chain *chain;
|
||||||
nghttp2_buf *buf;
|
nghttp2_buf *buf;
|
||||||
@@ -462,7 +462,7 @@ ssize_t nghttp2_bufs_remove(nghttp2_bufs *bufs, uint8_t **out) {
|
|||||||
|
|
||||||
*out = res;
|
*out = res;
|
||||||
|
|
||||||
return (ssize_t)len;
|
return (nghttp2_ssize)len;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t nghttp2_bufs_remove_copy(nghttp2_bufs *bufs, uint8_t *out) {
|
size_t nghttp2_bufs_remove_copy(nghttp2_bufs *bufs, uint8_t *out) {
|
||||||
|
|||||||
@@ -349,7 +349,7 @@ int nghttp2_bufs_orb_hold(nghttp2_bufs *bufs, uint8_t b);
|
|||||||
* NGHTTP2_ERR_NOMEM
|
* NGHTTP2_ERR_NOMEM
|
||||||
* Out of memory
|
* Out of memory
|
||||||
*/
|
*/
|
||||||
ssize_t nghttp2_bufs_remove(nghttp2_bufs *bufs, uint8_t **out);
|
nghttp2_ssize nghttp2_bufs_remove(nghttp2_bufs *bufs, uint8_t **out);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copies all data stored in |bufs| to |out|. This function assumes
|
* Copies all data stored in |bufs| to |out|. This function assumes
|
||||||
|
|||||||
@@ -45,11 +45,21 @@ void nghttp2_session_callbacks_set_send_callback(
|
|||||||
cbs->send_callback = send_callback;
|
cbs->send_callback = send_callback;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void nghttp2_session_callbacks_set_send_callback2(
|
||||||
|
nghttp2_session_callbacks *cbs, nghttp2_send_callback2 send_callback) {
|
||||||
|
cbs->send_callback2 = send_callback;
|
||||||
|
}
|
||||||
|
|
||||||
void nghttp2_session_callbacks_set_recv_callback(
|
void nghttp2_session_callbacks_set_recv_callback(
|
||||||
nghttp2_session_callbacks *cbs, nghttp2_recv_callback recv_callback) {
|
nghttp2_session_callbacks *cbs, nghttp2_recv_callback recv_callback) {
|
||||||
cbs->recv_callback = recv_callback;
|
cbs->recv_callback = recv_callback;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void nghttp2_session_callbacks_set_recv_callback2(
|
||||||
|
nghttp2_session_callbacks *cbs, nghttp2_recv_callback2 recv_callback) {
|
||||||
|
cbs->recv_callback2 = recv_callback;
|
||||||
|
}
|
||||||
|
|
||||||
void nghttp2_session_callbacks_set_on_frame_recv_callback(
|
void nghttp2_session_callbacks_set_on_frame_recv_callback(
|
||||||
nghttp2_session_callbacks *cbs,
|
nghttp2_session_callbacks *cbs,
|
||||||
nghttp2_on_frame_recv_callback on_frame_recv_callback) {
|
nghttp2_on_frame_recv_callback on_frame_recv_callback) {
|
||||||
@@ -128,12 +138,24 @@ void nghttp2_session_callbacks_set_select_padding_callback(
|
|||||||
cbs->select_padding_callback = select_padding_callback;
|
cbs->select_padding_callback = select_padding_callback;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void nghttp2_session_callbacks_set_select_padding_callback2(
|
||||||
|
nghttp2_session_callbacks *cbs,
|
||||||
|
nghttp2_select_padding_callback2 select_padding_callback) {
|
||||||
|
cbs->select_padding_callback2 = select_padding_callback;
|
||||||
|
}
|
||||||
|
|
||||||
void nghttp2_session_callbacks_set_data_source_read_length_callback(
|
void nghttp2_session_callbacks_set_data_source_read_length_callback(
|
||||||
nghttp2_session_callbacks *cbs,
|
nghttp2_session_callbacks *cbs,
|
||||||
nghttp2_data_source_read_length_callback data_source_read_length_callback) {
|
nghttp2_data_source_read_length_callback data_source_read_length_callback) {
|
||||||
cbs->read_length_callback = data_source_read_length_callback;
|
cbs->read_length_callback = data_source_read_length_callback;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void nghttp2_session_callbacks_set_data_source_read_length_callback2(
|
||||||
|
nghttp2_session_callbacks *cbs, nghttp2_data_source_read_length_callback2
|
||||||
|
data_source_read_length_callback) {
|
||||||
|
cbs->read_length_callback2 = data_source_read_length_callback;
|
||||||
|
}
|
||||||
|
|
||||||
void nghttp2_session_callbacks_set_on_begin_frame_callback(
|
void nghttp2_session_callbacks_set_on_begin_frame_callback(
|
||||||
nghttp2_session_callbacks *cbs,
|
nghttp2_session_callbacks *cbs,
|
||||||
nghttp2_on_begin_frame_callback on_begin_frame_callback) {
|
nghttp2_on_begin_frame_callback on_begin_frame_callback) {
|
||||||
@@ -152,6 +174,12 @@ void nghttp2_session_callbacks_set_pack_extension_callback(
|
|||||||
cbs->pack_extension_callback = pack_extension_callback;
|
cbs->pack_extension_callback = pack_extension_callback;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void nghttp2_session_callbacks_set_pack_extension_callback2(
|
||||||
|
nghttp2_session_callbacks *cbs,
|
||||||
|
nghttp2_pack_extension_callback2 pack_extension_callback) {
|
||||||
|
cbs->pack_extension_callback2 = pack_extension_callback;
|
||||||
|
}
|
||||||
|
|
||||||
void nghttp2_session_callbacks_set_unpack_extension_callback(
|
void nghttp2_session_callbacks_set_unpack_extension_callback(
|
||||||
nghttp2_session_callbacks *cbs,
|
nghttp2_session_callbacks *cbs,
|
||||||
nghttp2_unpack_extension_callback unpack_extension_callback) {
|
nghttp2_unpack_extension_callback unpack_extension_callback) {
|
||||||
|
|||||||
@@ -36,19 +36,33 @@
|
|||||||
*/
|
*/
|
||||||
struct nghttp2_session_callbacks {
|
struct nghttp2_session_callbacks {
|
||||||
/**
|
/**
|
||||||
* Callback function invoked when the session wants to send data to
|
* Deprecated. Use send_callback2 instead. Callback function
|
||||||
* the remote peer. This callback is not necessary if the
|
* invoked when the session wants to send data to the remote peer.
|
||||||
* application uses solely `nghttp2_session_mem_send()` to serialize
|
* This callback is not necessary if the application uses solely
|
||||||
* data to transmit.
|
* `nghttp2_session_mem_send()` to serialize data to transmit.
|
||||||
*/
|
*/
|
||||||
nghttp2_send_callback send_callback;
|
nghttp2_send_callback send_callback;
|
||||||
/**
|
/**
|
||||||
* Callback function invoked when the session wants to receive data
|
* Callback function invoked when the session wants to send data to
|
||||||
* from the remote peer. This callback is not necessary if the
|
* the remote peer. This callback is not necessary if the
|
||||||
* application uses solely `nghttp2_session_mem_recv()` to process
|
* application uses solely `nghttp2_session_mem_send2()` to
|
||||||
* received data.
|
* serialize data to transmit.
|
||||||
|
*/
|
||||||
|
nghttp2_send_callback2 send_callback2;
|
||||||
|
/**
|
||||||
|
* Deprecated. Use recv_callback2 instead. Callback function
|
||||||
|
* invoked when the session wants to receive data from the remote
|
||||||
|
* peer. This callback is not necessary if the application uses
|
||||||
|
* solely `nghttp2_session_mem_recv()` to process received data.
|
||||||
*/
|
*/
|
||||||
nghttp2_recv_callback recv_callback;
|
nghttp2_recv_callback recv_callback;
|
||||||
|
/**
|
||||||
|
* Callback function invoked when the session wants to receive data
|
||||||
|
* from the remote peer. This callback is not necessary if the
|
||||||
|
* application uses solely `nghttp2_session_mem_recv2()` to process
|
||||||
|
* received data.
|
||||||
|
*/
|
||||||
|
nghttp2_recv_callback2 recv_callback2;
|
||||||
/**
|
/**
|
||||||
* Callback function invoked by `nghttp2_session_recv()` when a
|
* Callback function invoked by `nghttp2_session_recv()` when a
|
||||||
* frame is received.
|
* frame is received.
|
||||||
@@ -100,22 +114,39 @@ struct nghttp2_session_callbacks {
|
|||||||
nghttp2_on_invalid_header_callback on_invalid_header_callback;
|
nghttp2_on_invalid_header_callback on_invalid_header_callback;
|
||||||
nghttp2_on_invalid_header_callback2 on_invalid_header_callback2;
|
nghttp2_on_invalid_header_callback2 on_invalid_header_callback2;
|
||||||
/**
|
/**
|
||||||
* Callback function invoked when the library asks application how
|
* Deprecated. Use select_padding_callback2 instead. Callback
|
||||||
* many padding bytes are required for the transmission of the given
|
* function invoked when the library asks application how many
|
||||||
|
* padding bytes are required for the transmission of the given
|
||||||
* frame.
|
* frame.
|
||||||
*/
|
*/
|
||||||
nghttp2_select_padding_callback select_padding_callback;
|
nghttp2_select_padding_callback select_padding_callback;
|
||||||
/**
|
/**
|
||||||
* The callback function used to determine the length allowed in
|
* Callback function invoked when the library asks application how
|
||||||
|
* many padding bytes are required for the transmission of the given
|
||||||
|
* frame.
|
||||||
|
*/
|
||||||
|
nghttp2_select_padding_callback2 select_padding_callback2;
|
||||||
|
/**
|
||||||
|
* Deprecated. Use read_length_callback2 instead. The callback
|
||||||
|
* function used to determine the length allowed in
|
||||||
* `nghttp2_data_source_read_callback()`
|
* `nghttp2_data_source_read_callback()`
|
||||||
*/
|
*/
|
||||||
nghttp2_data_source_read_length_callback read_length_callback;
|
nghttp2_data_source_read_length_callback read_length_callback;
|
||||||
|
/**
|
||||||
|
* The callback function used to determine the length allowed in
|
||||||
|
* `nghttp2_data_source_read_callback2()`
|
||||||
|
*/
|
||||||
|
nghttp2_data_source_read_length_callback2 read_length_callback2;
|
||||||
/**
|
/**
|
||||||
* Sets callback function invoked when a frame header is received.
|
* Sets callback function invoked when a frame header is received.
|
||||||
*/
|
*/
|
||||||
nghttp2_on_begin_frame_callback on_begin_frame_callback;
|
nghttp2_on_begin_frame_callback on_begin_frame_callback;
|
||||||
nghttp2_send_data_callback send_data_callback;
|
nghttp2_send_data_callback send_data_callback;
|
||||||
|
/**
|
||||||
|
* Deprecated. Use pack_extension_callback2 instead.
|
||||||
|
*/
|
||||||
nghttp2_pack_extension_callback pack_extension_callback;
|
nghttp2_pack_extension_callback pack_extension_callback;
|
||||||
|
nghttp2_pack_extension_callback2 pack_extension_callback2;
|
||||||
nghttp2_unpack_extension_callback unpack_extension_callback;
|
nghttp2_unpack_extension_callback unpack_extension_callback;
|
||||||
nghttp2_on_extension_chunk_recv_callback on_extension_chunk_recv_callback;
|
nghttp2_on_extension_chunk_recv_callback on_extension_chunk_recv_callback;
|
||||||
nghttp2_error_callback error_callback;
|
nghttp2_error_callback error_callback;
|
||||||
|
|||||||
@@ -24,6 +24,7 @@
|
|||||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
#include "nghttp2_extpri.h"
|
#include "nghttp2_extpri.h"
|
||||||
|
#include "nghttp2_http.h"
|
||||||
|
|
||||||
uint8_t nghttp2_extpri_to_uint8(const nghttp2_extpri *extpri) {
|
uint8_t nghttp2_extpri_to_uint8(const nghttp2_extpri *extpri) {
|
||||||
return (uint8_t)((uint32_t)extpri->inc << 7 | extpri->urgency);
|
return (uint8_t)((uint32_t)extpri->inc << 7 | extpri->urgency);
|
||||||
@@ -33,3 +34,8 @@ void nghttp2_extpri_from_uint8(nghttp2_extpri *extpri, uint8_t u8extpri) {
|
|||||||
extpri->urgency = nghttp2_extpri_uint8_urgency(u8extpri);
|
extpri->urgency = nghttp2_extpri_uint8_urgency(u8extpri);
|
||||||
extpri->inc = nghttp2_extpri_uint8_inc(u8extpri);
|
extpri->inc = nghttp2_extpri_uint8_inc(u8extpri);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int nghttp2_extpri_parse_priority(nghttp2_extpri *extpri, const uint8_t *value,
|
||||||
|
size_t len) {
|
||||||
|
return nghttp2_http_parse_priority(extpri, value, len);
|
||||||
|
}
|
||||||
|
|||||||
120
lib/nghttp2_hd.c
120
lib/nghttp2_hd.c
@@ -850,9 +850,10 @@ static size_t encode_length(uint8_t *buf, size_t n, size_t prefix) {
|
|||||||
* in the next call will be stored in |*shift_ptr|) and returns number
|
* in the next call will be stored in |*shift_ptr|) and returns number
|
||||||
* of bytes processed, or returns -1, indicating decoding error.
|
* of bytes processed, or returns -1, indicating decoding error.
|
||||||
*/
|
*/
|
||||||
static ssize_t decode_length(uint32_t *res, size_t *shift_ptr, int *fin,
|
static nghttp2_ssize decode_length(uint32_t *res, size_t *shift_ptr, int *fin,
|
||||||
uint32_t initial, size_t shift, const uint8_t *in,
|
uint32_t initial, size_t shift,
|
||||||
const uint8_t *last, size_t prefix) {
|
const uint8_t *in, const uint8_t *last,
|
||||||
|
size_t prefix) {
|
||||||
uint32_t k = (uint8_t)((1 << prefix) - 1);
|
uint32_t k = (uint8_t)((1 << prefix) - 1);
|
||||||
uint32_t n = initial;
|
uint32_t n = initial;
|
||||||
const uint8_t *start = in;
|
const uint8_t *start = in;
|
||||||
@@ -871,7 +872,7 @@ static ssize_t decode_length(uint32_t *res, size_t *shift_ptr, int *fin,
|
|||||||
|
|
||||||
if (++in == last) {
|
if (++in == last) {
|
||||||
*res = n;
|
*res = n;
|
||||||
return (ssize_t)(in - start);
|
return (nghttp2_ssize)(in - start);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -906,12 +907,12 @@ static ssize_t decode_length(uint32_t *res, size_t *shift_ptr, int *fin,
|
|||||||
|
|
||||||
if (in == last) {
|
if (in == last) {
|
||||||
*res = n;
|
*res = n;
|
||||||
return (ssize_t)(in - start);
|
return (nghttp2_ssize)(in - start);
|
||||||
}
|
}
|
||||||
|
|
||||||
*res = n;
|
*res = n;
|
||||||
*fin = 1;
|
*fin = 1;
|
||||||
return (ssize_t)(in + 1 - start);
|
return (nghttp2_ssize)(in + 1 - start);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int emit_table_size(nghttp2_bufs *bufs, size_t table_size) {
|
static int emit_table_size(nghttp2_bufs *bufs, size_t table_size) {
|
||||||
@@ -1164,7 +1165,7 @@ static int add_hd_table_incremental(nghttp2_hd_context *context,
|
|||||||
}
|
}
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
ssize_t index;
|
nghttp2_ssize index;
|
||||||
/* Nonzero if both name and value are matched. */
|
/* Nonzero if both name and value are matched. */
|
||||||
int name_value_match;
|
int name_value_match;
|
||||||
} search_result;
|
} search_result;
|
||||||
@@ -1213,8 +1214,8 @@ static search_result search_hd_table(nghttp2_hd_context *context,
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
res.index =
|
res.index = (nghttp2_ssize)(context->next_seq - 1 - ent->seq +
|
||||||
(ssize_t)(context->next_seq - 1 - ent->seq + NGHTTP2_STATIC_TABLE_LENGTH);
|
NGHTTP2_STATIC_TABLE_LENGTH);
|
||||||
res.name_value_match = exact_match;
|
res.name_value_match = exact_match;
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
@@ -1244,13 +1245,13 @@ static void hd_context_shrink_table_size(nghttp2_hd_context *context,
|
|||||||
|
|
||||||
int nghttp2_hd_deflate_change_table_size(
|
int nghttp2_hd_deflate_change_table_size(
|
||||||
nghttp2_hd_deflater *deflater, size_t settings_max_dynamic_table_size) {
|
nghttp2_hd_deflater *deflater, size_t settings_max_dynamic_table_size) {
|
||||||
size_t next_bufsize = nghttp2_min(settings_max_dynamic_table_size,
|
size_t next_bufsize = nghttp2_min_size(
|
||||||
deflater->deflate_hd_table_bufsize_max);
|
settings_max_dynamic_table_size, deflater->deflate_hd_table_bufsize_max);
|
||||||
|
|
||||||
deflater->ctx.hd_table_bufsize_max = next_bufsize;
|
deflater->ctx.hd_table_bufsize_max = next_bufsize;
|
||||||
|
|
||||||
deflater->min_hd_table_bufsize_max =
|
deflater->min_hd_table_bufsize_max =
|
||||||
nghttp2_min(deflater->min_hd_table_bufsize_max, next_bufsize);
|
nghttp2_min_size(deflater->min_hd_table_bufsize_max, next_bufsize);
|
||||||
|
|
||||||
deflater->notify_table_size_change = 1;
|
deflater->notify_table_size_change = 1;
|
||||||
|
|
||||||
@@ -1343,7 +1344,7 @@ static int deflate_nv(nghttp2_hd_deflater *deflater, nghttp2_bufs *bufs,
|
|||||||
const nghttp2_nv *nv) {
|
const nghttp2_nv *nv) {
|
||||||
int rv;
|
int rv;
|
||||||
search_result res;
|
search_result res;
|
||||||
ssize_t idx;
|
nghttp2_ssize idx;
|
||||||
int indexing_mode;
|
int indexing_mode;
|
||||||
int32_t token;
|
int32_t token;
|
||||||
nghttp2_mem *mem;
|
nghttp2_mem *mem;
|
||||||
@@ -1379,7 +1380,7 @@ static int deflate_nv(nghttp2_hd_deflater *deflater, nghttp2_bufs *bufs,
|
|||||||
|
|
||||||
if (res.name_value_match) {
|
if (res.name_value_match) {
|
||||||
|
|
||||||
DEBUGF("deflatehd: name/value match index=%zd\n", idx);
|
DEBUGF("deflatehd: name/value match index=%td\n", idx);
|
||||||
|
|
||||||
rv = emit_indexed_block(bufs, (size_t)idx);
|
rv = emit_indexed_block(bufs, (size_t)idx);
|
||||||
if (rv != 0) {
|
if (rv != 0) {
|
||||||
@@ -1390,7 +1391,7 @@ static int deflate_nv(nghttp2_hd_deflater *deflater, nghttp2_bufs *bufs,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (res.index != -1) {
|
if (res.index != -1) {
|
||||||
DEBUGF("deflatehd: name match index=%zd\n", res.index);
|
DEBUGF("deflatehd: name match index=%td\n", res.index);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (indexing_mode == NGHTTP2_HD_WITH_INDEXING) {
|
if (indexing_mode == NGHTTP2_HD_WITH_INDEXING) {
|
||||||
@@ -1491,6 +1492,12 @@ fail:
|
|||||||
ssize_t nghttp2_hd_deflate_hd(nghttp2_hd_deflater *deflater, uint8_t *buf,
|
ssize_t nghttp2_hd_deflate_hd(nghttp2_hd_deflater *deflater, uint8_t *buf,
|
||||||
size_t buflen, const nghttp2_nv *nv,
|
size_t buflen, const nghttp2_nv *nv,
|
||||||
size_t nvlen) {
|
size_t nvlen) {
|
||||||
|
return (ssize_t)nghttp2_hd_deflate_hd2(deflater, buf, buflen, nv, nvlen);
|
||||||
|
}
|
||||||
|
|
||||||
|
nghttp2_ssize nghttp2_hd_deflate_hd2(nghttp2_hd_deflater *deflater,
|
||||||
|
uint8_t *buf, size_t buflen,
|
||||||
|
const nghttp2_nv *nv, size_t nvlen) {
|
||||||
nghttp2_bufs bufs;
|
nghttp2_bufs bufs;
|
||||||
int rv;
|
int rv;
|
||||||
nghttp2_mem *mem;
|
nghttp2_mem *mem;
|
||||||
@@ -1517,12 +1524,18 @@ ssize_t nghttp2_hd_deflate_hd(nghttp2_hd_deflater *deflater, uint8_t *buf,
|
|||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (ssize_t)buflen;
|
return (nghttp2_ssize)buflen;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t nghttp2_hd_deflate_hd_vec(nghttp2_hd_deflater *deflater,
|
ssize_t nghttp2_hd_deflate_hd_vec(nghttp2_hd_deflater *deflater,
|
||||||
const nghttp2_vec *vec, size_t veclen,
|
const nghttp2_vec *vec, size_t veclen,
|
||||||
const nghttp2_nv *nv, size_t nvlen) {
|
const nghttp2_nv *nv, size_t nvlen) {
|
||||||
|
return (ssize_t)nghttp2_hd_deflate_hd_vec2(deflater, vec, veclen, nv, nvlen);
|
||||||
|
}
|
||||||
|
|
||||||
|
nghttp2_ssize nghttp2_hd_deflate_hd_vec2(nghttp2_hd_deflater *deflater,
|
||||||
|
const nghttp2_vec *vec, size_t veclen,
|
||||||
|
const nghttp2_nv *nv, size_t nvlen) {
|
||||||
nghttp2_bufs bufs;
|
nghttp2_bufs bufs;
|
||||||
int rv;
|
int rv;
|
||||||
nghttp2_mem *mem;
|
nghttp2_mem *mem;
|
||||||
@@ -1550,7 +1563,7 @@ ssize_t nghttp2_hd_deflate_hd_vec(nghttp2_hd_deflater *deflater,
|
|||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (ssize_t)buflen;
|
return (nghttp2_ssize)buflen;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t nghttp2_hd_deflate_bound(nghttp2_hd_deflater *deflater,
|
size_t nghttp2_hd_deflate_bound(nghttp2_hd_deflater *deflater,
|
||||||
@@ -1643,10 +1656,11 @@ static void hd_inflate_set_huffman_encoded(nghttp2_hd_inflater *inflater,
|
|||||||
* NGHTTP2_ERR_HEADER_COMP
|
* NGHTTP2_ERR_HEADER_COMP
|
||||||
* Integer decoding failed
|
* Integer decoding failed
|
||||||
*/
|
*/
|
||||||
static ssize_t hd_inflate_read_len(nghttp2_hd_inflater *inflater, int *rfin,
|
static nghttp2_ssize hd_inflate_read_len(nghttp2_hd_inflater *inflater,
|
||||||
const uint8_t *in, const uint8_t *last,
|
int *rfin, const uint8_t *in,
|
||||||
size_t prefix, size_t maxlen) {
|
const uint8_t *last, size_t prefix,
|
||||||
ssize_t rv;
|
size_t maxlen) {
|
||||||
|
nghttp2_ssize rv;
|
||||||
uint32_t out;
|
uint32_t out;
|
||||||
|
|
||||||
*rfin = 0;
|
*rfin = 0;
|
||||||
@@ -1684,10 +1698,10 @@ static ssize_t hd_inflate_read_len(nghttp2_hd_inflater *inflater, int *rfin,
|
|||||||
* NGHTTP2_ERR_HEADER_COMP
|
* NGHTTP2_ERR_HEADER_COMP
|
||||||
* Huffman decoding failed
|
* Huffman decoding failed
|
||||||
*/
|
*/
|
||||||
static ssize_t hd_inflate_read_huff(nghttp2_hd_inflater *inflater,
|
static nghttp2_ssize hd_inflate_read_huff(nghttp2_hd_inflater *inflater,
|
||||||
nghttp2_buf *buf, const uint8_t *in,
|
nghttp2_buf *buf, const uint8_t *in,
|
||||||
const uint8_t *last) {
|
const uint8_t *last) {
|
||||||
ssize_t readlen;
|
nghttp2_ssize readlen;
|
||||||
int fin = 0;
|
int fin = 0;
|
||||||
if ((size_t)(last - in) >= inflater->left) {
|
if ((size_t)(last - in) >= inflater->left) {
|
||||||
last = in + inflater->left;
|
last = in + inflater->left;
|
||||||
@@ -1721,14 +1735,15 @@ static ssize_t hd_inflate_read_huff(nghttp2_hd_inflater *inflater,
|
|||||||
* NGHTTP2_ERR_HEADER_COMP
|
* NGHTTP2_ERR_HEADER_COMP
|
||||||
* Header decompression failed
|
* Header decompression failed
|
||||||
*/
|
*/
|
||||||
static ssize_t hd_inflate_read(nghttp2_hd_inflater *inflater, nghttp2_buf *buf,
|
static nghttp2_ssize hd_inflate_read(nghttp2_hd_inflater *inflater,
|
||||||
const uint8_t *in, const uint8_t *last) {
|
nghttp2_buf *buf, const uint8_t *in,
|
||||||
size_t len = nghttp2_min((size_t)(last - in), inflater->left);
|
const uint8_t *last) {
|
||||||
|
size_t len = nghttp2_min_size((size_t)(last - in), inflater->left);
|
||||||
|
|
||||||
buf->last = nghttp2_cpymem(buf->last, in, len);
|
buf->last = nghttp2_cpymem(buf->last, in, len);
|
||||||
|
|
||||||
inflater->left -= len;
|
inflater->left -= len;
|
||||||
return (ssize_t)len;
|
return (nghttp2_ssize)len;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -1843,7 +1858,15 @@ ssize_t nghttp2_hd_inflate_hd(nghttp2_hd_inflater *inflater, nghttp2_nv *nv_out,
|
|||||||
ssize_t nghttp2_hd_inflate_hd2(nghttp2_hd_inflater *inflater,
|
ssize_t nghttp2_hd_inflate_hd2(nghttp2_hd_inflater *inflater,
|
||||||
nghttp2_nv *nv_out, int *inflate_flags,
|
nghttp2_nv *nv_out, int *inflate_flags,
|
||||||
const uint8_t *in, size_t inlen, int in_final) {
|
const uint8_t *in, size_t inlen, int in_final) {
|
||||||
ssize_t rv;
|
return (nghttp2_ssize)nghttp2_hd_inflate_hd3(inflater, nv_out, inflate_flags,
|
||||||
|
in, inlen, in_final);
|
||||||
|
}
|
||||||
|
|
||||||
|
nghttp2_ssize nghttp2_hd_inflate_hd3(nghttp2_hd_inflater *inflater,
|
||||||
|
nghttp2_nv *nv_out, int *inflate_flags,
|
||||||
|
const uint8_t *in, size_t inlen,
|
||||||
|
int in_final) {
|
||||||
|
nghttp2_ssize rv;
|
||||||
nghttp2_hd_nv hd_nv;
|
nghttp2_hd_nv hd_nv;
|
||||||
|
|
||||||
rv = nghttp2_hd_inflate_hd_nv(inflater, &hd_nv, inflate_flags, in, inlen,
|
rv = nghttp2_hd_inflate_hd_nv(inflater, &hd_nv, inflate_flags, in, inlen,
|
||||||
@@ -1866,11 +1889,11 @@ ssize_t nghttp2_hd_inflate_hd2(nghttp2_hd_inflater *inflater,
|
|||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t nghttp2_hd_inflate_hd_nv(nghttp2_hd_inflater *inflater,
|
nghttp2_ssize nghttp2_hd_inflate_hd_nv(nghttp2_hd_inflater *inflater,
|
||||||
nghttp2_hd_nv *nv_out, int *inflate_flags,
|
nghttp2_hd_nv *nv_out,
|
||||||
const uint8_t *in, size_t inlen,
|
int *inflate_flags, const uint8_t *in,
|
||||||
int in_final) {
|
size_t inlen, int in_final) {
|
||||||
ssize_t rv = 0;
|
nghttp2_ssize rv = 0;
|
||||||
const uint8_t *first = in;
|
const uint8_t *first = in;
|
||||||
const uint8_t *last = in + inlen;
|
const uint8_t *last = in + inlen;
|
||||||
int rfin = 0;
|
int rfin = 0;
|
||||||
@@ -1939,7 +1962,7 @@ ssize_t nghttp2_hd_inflate_hd_nv(nghttp2_hd_inflater *inflater,
|
|||||||
rfin = 0;
|
rfin = 0;
|
||||||
rv = hd_inflate_read_len(
|
rv = hd_inflate_read_len(
|
||||||
inflater, &rfin, in, last, 5,
|
inflater, &rfin, in, last, 5,
|
||||||
nghttp2_min(inflater->min_hd_table_bufsize_max,
|
nghttp2_min_size(inflater->min_hd_table_bufsize_max,
|
||||||
inflater->settings_hd_table_bufsize_max));
|
inflater->settings_hd_table_bufsize_max));
|
||||||
if (rv < 0) {
|
if (rv < 0) {
|
||||||
goto fail;
|
goto fail;
|
||||||
@@ -1992,7 +2015,7 @@ ssize_t nghttp2_hd_inflate_hd_nv(nghttp2_hd_inflater *inflater,
|
|||||||
|
|
||||||
inflater->state = NGHTTP2_HD_STATE_OPCODE;
|
inflater->state = NGHTTP2_HD_STATE_OPCODE;
|
||||||
*inflate_flags |= NGHTTP2_HD_INFLATE_EMIT;
|
*inflate_flags |= NGHTTP2_HD_INFLATE_EMIT;
|
||||||
return (ssize_t)(in - first);
|
return (nghttp2_ssize)(in - first);
|
||||||
} else {
|
} else {
|
||||||
inflater->index = inflater->left;
|
inflater->index = inflater->left;
|
||||||
--inflater->index;
|
--inflater->index;
|
||||||
@@ -2050,7 +2073,7 @@ ssize_t nghttp2_hd_inflate_hd_nv(nghttp2_hd_inflater *inflater,
|
|||||||
|
|
||||||
in += rv;
|
in += rv;
|
||||||
|
|
||||||
DEBUGF("inflatehd: %zd bytes read\n", rv);
|
DEBUGF("inflatehd: %td bytes read\n", rv);
|
||||||
|
|
||||||
if (inflater->left) {
|
if (inflater->left) {
|
||||||
DEBUGF("inflatehd: still %zu bytes to go\n", inflater->left);
|
DEBUGF("inflatehd: still %zu bytes to go\n", inflater->left);
|
||||||
@@ -2072,7 +2095,7 @@ ssize_t nghttp2_hd_inflate_hd_nv(nghttp2_hd_inflater *inflater,
|
|||||||
|
|
||||||
in += rv;
|
in += rv;
|
||||||
|
|
||||||
DEBUGF("inflatehd: %zd bytes read\n", rv);
|
DEBUGF("inflatehd: %td bytes read\n", rv);
|
||||||
if (inflater->left) {
|
if (inflater->left) {
|
||||||
DEBUGF("inflatehd: still %zu bytes to go\n", inflater->left);
|
DEBUGF("inflatehd: still %zu bytes to go\n", inflater->left);
|
||||||
|
|
||||||
@@ -2138,7 +2161,7 @@ ssize_t nghttp2_hd_inflate_hd_nv(nghttp2_hd_inflater *inflater,
|
|||||||
|
|
||||||
in += rv;
|
in += rv;
|
||||||
|
|
||||||
DEBUGF("inflatehd: %zd bytes read\n", rv);
|
DEBUGF("inflatehd: %td bytes read\n", rv);
|
||||||
|
|
||||||
if (inflater->left) {
|
if (inflater->left) {
|
||||||
DEBUGF("inflatehd: still %zu bytes to go\n", inflater->left);
|
DEBUGF("inflatehd: still %zu bytes to go\n", inflater->left);
|
||||||
@@ -2162,18 +2185,18 @@ ssize_t nghttp2_hd_inflate_hd_nv(nghttp2_hd_inflater *inflater,
|
|||||||
inflater->state = NGHTTP2_HD_STATE_OPCODE;
|
inflater->state = NGHTTP2_HD_STATE_OPCODE;
|
||||||
*inflate_flags |= NGHTTP2_HD_INFLATE_EMIT;
|
*inflate_flags |= NGHTTP2_HD_INFLATE_EMIT;
|
||||||
|
|
||||||
return (ssize_t)(in - first);
|
return (nghttp2_ssize)(in - first);
|
||||||
case NGHTTP2_HD_STATE_READ_VALUE:
|
case NGHTTP2_HD_STATE_READ_VALUE:
|
||||||
rv = hd_inflate_read(inflater, &inflater->valuebuf, in, last);
|
rv = hd_inflate_read(inflater, &inflater->valuebuf, in, last);
|
||||||
if (rv < 0) {
|
if (rv < 0) {
|
||||||
DEBUGF("inflatehd: value read failure %zd: %s\n", rv,
|
DEBUGF("inflatehd: value read failure %td: %s\n", rv,
|
||||||
nghttp2_strerror((int)rv));
|
nghttp2_strerror((int)rv));
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
in += rv;
|
in += rv;
|
||||||
|
|
||||||
DEBUGF("inflatehd: %zd bytes read\n", rv);
|
DEBUGF("inflatehd: %td bytes read\n", rv);
|
||||||
|
|
||||||
if (inflater->left) {
|
if (inflater->left) {
|
||||||
DEBUGF("inflatehd: still %zu bytes to go\n", inflater->left);
|
DEBUGF("inflatehd: still %zu bytes to go\n", inflater->left);
|
||||||
@@ -2196,7 +2219,7 @@ ssize_t nghttp2_hd_inflate_hd_nv(nghttp2_hd_inflater *inflater,
|
|||||||
inflater->state = NGHTTP2_HD_STATE_OPCODE;
|
inflater->state = NGHTTP2_HD_STATE_OPCODE;
|
||||||
*inflate_flags |= NGHTTP2_HD_INFLATE_EMIT;
|
*inflate_flags |= NGHTTP2_HD_INFLATE_EMIT;
|
||||||
|
|
||||||
return (ssize_t)(in - first);
|
return (nghttp2_ssize)(in - first);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2216,7 +2239,7 @@ ssize_t nghttp2_hd_inflate_hd_nv(nghttp2_hd_inflater *inflater,
|
|||||||
}
|
}
|
||||||
*inflate_flags |= NGHTTP2_HD_INFLATE_FINAL;
|
*inflate_flags |= NGHTTP2_HD_INFLATE_FINAL;
|
||||||
}
|
}
|
||||||
return (ssize_t)(in - first);
|
return (nghttp2_ssize)(in - first);
|
||||||
|
|
||||||
almost_ok:
|
almost_ok:
|
||||||
if (in_final) {
|
if (in_final) {
|
||||||
@@ -2226,10 +2249,10 @@ almost_ok:
|
|||||||
|
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
return (ssize_t)(in - first);
|
return (nghttp2_ssize)(in - first);
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
DEBUGF("inflatehd: error return %zd\n", rv);
|
DEBUGF("inflatehd: error return %td\n", rv);
|
||||||
|
|
||||||
inflater->ctx.bad = 1;
|
inflater->ctx.bad = 1;
|
||||||
return rv;
|
return rv;
|
||||||
@@ -2297,9 +2320,10 @@ int nghttp2_hd_emit_table_size(nghttp2_bufs *bufs, size_t table_size) {
|
|||||||
return emit_table_size(bufs, table_size);
|
return emit_table_size(bufs, table_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t nghttp2_hd_decode_length(uint32_t *res, size_t *shift_ptr, int *fin,
|
nghttp2_ssize nghttp2_hd_decode_length(uint32_t *res, size_t *shift_ptr,
|
||||||
uint32_t initial, size_t shift, uint8_t *in,
|
int *fin, uint32_t initial, size_t shift,
|
||||||
uint8_t *last, size_t prefix) {
|
uint8_t *in, uint8_t *last,
|
||||||
|
size_t prefix) {
|
||||||
return decode_length(res, shift_ptr, fin, initial, shift, in, last, prefix);
|
return decode_length(res, shift_ptr, fin, initial, shift, in, last, prefix);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -357,9 +357,10 @@ void nghttp2_hd_inflate_free(nghttp2_hd_inflater *inflater);
|
|||||||
* that return values and semantics are the same as
|
* that return values and semantics are the same as
|
||||||
* nghttp2_hd_inflate_hd().
|
* nghttp2_hd_inflate_hd().
|
||||||
*/
|
*/
|
||||||
ssize_t nghttp2_hd_inflate_hd_nv(nghttp2_hd_inflater *inflater,
|
nghttp2_ssize nghttp2_hd_inflate_hd_nv(nghttp2_hd_inflater *inflater,
|
||||||
nghttp2_hd_nv *nv_out, int *inflate_flags,
|
nghttp2_hd_nv *nv_out,
|
||||||
const uint8_t *in, size_t inlen, int in_final);
|
int *inflate_flags, const uint8_t *in,
|
||||||
|
size_t inlen, int in_final);
|
||||||
|
|
||||||
/* For unittesting purpose */
|
/* For unittesting purpose */
|
||||||
int nghttp2_hd_emit_indname_block(nghttp2_bufs *bufs, size_t index,
|
int nghttp2_hd_emit_indname_block(nghttp2_bufs *bufs, size_t index,
|
||||||
@@ -376,9 +377,10 @@ int nghttp2_hd_emit_table_size(nghttp2_bufs *bufs, size_t table_size);
|
|||||||
nghttp2_hd_nv nghttp2_hd_table_get(nghttp2_hd_context *context, size_t index);
|
nghttp2_hd_nv nghttp2_hd_table_get(nghttp2_hd_context *context, size_t index);
|
||||||
|
|
||||||
/* For unittesting purpose */
|
/* For unittesting purpose */
|
||||||
ssize_t nghttp2_hd_decode_length(uint32_t *res, size_t *shift_ptr, int *fin,
|
nghttp2_ssize nghttp2_hd_decode_length(uint32_t *res, size_t *shift_ptr,
|
||||||
uint32_t initial, size_t shift, uint8_t *in,
|
int *fin, uint32_t initial, size_t shift,
|
||||||
uint8_t *last, size_t prefix);
|
uint8_t *in, uint8_t *last,
|
||||||
|
size_t prefix);
|
||||||
|
|
||||||
/* Huffman encoding/decoding functions */
|
/* Huffman encoding/decoding functions */
|
||||||
|
|
||||||
@@ -427,7 +429,7 @@ void nghttp2_hd_huff_decode_context_init(nghttp2_hd_huff_decode_context *ctx);
|
|||||||
* NGHTTP2_ERR_HEADER_COMP
|
* NGHTTP2_ERR_HEADER_COMP
|
||||||
* Decoding process has failed.
|
* Decoding process has failed.
|
||||||
*/
|
*/
|
||||||
ssize_t nghttp2_hd_huff_decode(nghttp2_hd_huff_decode_context *ctx,
|
nghttp2_ssize nghttp2_hd_huff_decode(nghttp2_hd_huff_decode_context *ctx,
|
||||||
nghttp2_buf *buf, const uint8_t *src,
|
nghttp2_buf *buf, const uint8_t *src,
|
||||||
size_t srclen, int fin);
|
size_t srclen, int fin);
|
||||||
|
|
||||||
|
|||||||
@@ -107,7 +107,7 @@ void nghttp2_hd_huff_decode_context_init(nghttp2_hd_huff_decode_context *ctx) {
|
|||||||
ctx->fstate = NGHTTP2_HUFF_ACCEPTED;
|
ctx->fstate = NGHTTP2_HUFF_ACCEPTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t nghttp2_hd_huff_decode(nghttp2_hd_huff_decode_context *ctx,
|
nghttp2_ssize nghttp2_hd_huff_decode(nghttp2_hd_huff_decode_context *ctx,
|
||||||
nghttp2_buf *buf, const uint8_t *src,
|
nghttp2_buf *buf, const uint8_t *src,
|
||||||
size_t srclen, int final) {
|
size_t srclen, int final) {
|
||||||
const uint8_t *end = src + srclen;
|
const uint8_t *end = src + srclen;
|
||||||
@@ -116,7 +116,9 @@ ssize_t nghttp2_hd_huff_decode(nghttp2_hd_huff_decode_context *ctx,
|
|||||||
uint8_t c;
|
uint8_t c;
|
||||||
|
|
||||||
/* We use the decoding algorithm described in
|
/* We use the decoding algorithm described in
|
||||||
http://graphics.ics.uci.edu/pub/Prefix.pdf */
|
- http://graphics.ics.uci.edu/pub/Prefix.pdf [!!! NO LONGER VALID !!!]
|
||||||
|
- https://ics.uci.edu/~dan/pubs/Prefix.pdf
|
||||||
|
- https://github.com/nghttp2/nghttp2/files/15141264/Prefix.pdf */
|
||||||
for (; src != end;) {
|
for (; src != end;) {
|
||||||
c = *src++;
|
c = *src++;
|
||||||
t = &huff_decode_table[t->fstate & 0x1ff][c >> 4];
|
t = &huff_decode_table[t->fstate & 0x1ff][c >> 4];
|
||||||
@@ -136,7 +138,7 @@ ssize_t nghttp2_hd_huff_decode(nghttp2_hd_huff_decode_context *ctx,
|
|||||||
return NGHTTP2_ERR_HEADER_COMP;
|
return NGHTTP2_ERR_HEADER_COMP;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (ssize_t)srclen;
|
return (nghttp2_ssize)srclen;
|
||||||
}
|
}
|
||||||
|
|
||||||
int nghttp2_hd_huff_decode_failure_state(nghttp2_hd_huff_decode_context *ctx) {
|
int nghttp2_hd_huff_decode_failure_state(nghttp2_hd_huff_decode_context *ctx) {
|
||||||
|
|||||||
@@ -160,7 +160,7 @@ int nghttp2_adjust_local_window_size(int32_t *local_window_size_ptr,
|
|||||||
int32_t recv_reduction_delta;
|
int32_t recv_reduction_delta;
|
||||||
int32_t delta;
|
int32_t delta;
|
||||||
int32_t new_recv_window_size =
|
int32_t new_recv_window_size =
|
||||||
nghttp2_max(0, *recv_window_size_ptr) - *delta_ptr;
|
nghttp2_max_int32(0, *recv_window_size_ptr) - *delta_ptr;
|
||||||
|
|
||||||
if (new_recv_window_size >= 0) {
|
if (new_recv_window_size >= 0) {
|
||||||
*recv_window_size_ptr = new_recv_window_size;
|
*recv_window_size_ptr = new_recv_window_size;
|
||||||
@@ -177,7 +177,7 @@ int nghttp2_adjust_local_window_size(int32_t *local_window_size_ptr,
|
|||||||
*local_window_size_ptr += delta;
|
*local_window_size_ptr += delta;
|
||||||
/* If there is recv_reduction due to earlier window_size
|
/* If there is recv_reduction due to earlier window_size
|
||||||
reduction, we have to adjust it too. */
|
reduction, we have to adjust it too. */
|
||||||
recv_reduction_delta = nghttp2_min(*recv_reduction_ptr, delta);
|
recv_reduction_delta = nghttp2_min_int32(*recv_reduction_ptr, delta);
|
||||||
*recv_reduction_ptr -= recv_reduction_delta;
|
*recv_reduction_ptr -= recv_reduction_delta;
|
||||||
if (*recv_window_size_ptr < 0) {
|
if (*recv_window_size_ptr < 0) {
|
||||||
*recv_window_size_ptr += recv_reduction_delta;
|
*recv_window_size_ptr += recv_reduction_delta;
|
||||||
@@ -233,7 +233,7 @@ int nghttp2_increase_local_window_size(int32_t *local_window_size_ptr,
|
|||||||
*local_window_size_ptr += delta;
|
*local_window_size_ptr += delta;
|
||||||
/* If there is recv_reduction due to earlier window_size
|
/* If there is recv_reduction due to earlier window_size
|
||||||
reduction, we have to adjust it too. */
|
reduction, we have to adjust it too. */
|
||||||
recv_reduction_delta = nghttp2_min(*recv_reduction_ptr, delta);
|
recv_reduction_delta = nghttp2_min_int32(*recv_reduction_ptr, delta);
|
||||||
*recv_reduction_ptr -= recv_reduction_delta;
|
*recv_reduction_ptr -= recv_reduction_delta;
|
||||||
|
|
||||||
*recv_window_size_ptr += recv_reduction_delta;
|
*recv_window_size_ptr += recv_reduction_delta;
|
||||||
@@ -336,6 +336,8 @@ const char *nghttp2_strerror(int error_code) {
|
|||||||
"closed";
|
"closed";
|
||||||
case NGHTTP2_ERR_TOO_MANY_SETTINGS:
|
case NGHTTP2_ERR_TOO_MANY_SETTINGS:
|
||||||
return "SETTINGS frame contained more than the maximum allowed entries";
|
return "SETTINGS frame contained more than the maximum allowed entries";
|
||||||
|
case NGHTTP2_ERR_TOO_MANY_CONTINUATIONS:
|
||||||
|
return "Too many CONTINUATION frames following a HEADER frame";
|
||||||
default:
|
default:
|
||||||
return "Unknown error code";
|
return "Unknown error code";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,8 +35,31 @@
|
|||||||
#include <nghttp2/nghttp2.h>
|
#include <nghttp2/nghttp2.h>
|
||||||
#include "nghttp2_mem.h"
|
#include "nghttp2_mem.h"
|
||||||
|
|
||||||
#define nghttp2_min(A, B) ((A) < (B) ? (A) : (B))
|
#define nghttp2_max_def(SUFFIX, T) \
|
||||||
#define nghttp2_max(A, B) ((A) > (B) ? (A) : (B))
|
static inline T nghttp2_max_##SUFFIX(T a, T b) { return a < b ? b : a; }
|
||||||
|
|
||||||
|
nghttp2_max_def(int8, int8_t);
|
||||||
|
nghttp2_max_def(int16, int16_t);
|
||||||
|
nghttp2_max_def(int32, int32_t);
|
||||||
|
nghttp2_max_def(int64, int64_t);
|
||||||
|
nghttp2_max_def(uint8, uint8_t);
|
||||||
|
nghttp2_max_def(uint16, uint16_t);
|
||||||
|
nghttp2_max_def(uint32, uint32_t);
|
||||||
|
nghttp2_max_def(uint64, uint64_t);
|
||||||
|
nghttp2_max_def(size, size_t);
|
||||||
|
|
||||||
|
#define nghttp2_min_def(SUFFIX, T) \
|
||||||
|
static inline T nghttp2_min_##SUFFIX(T a, T b) { return a < b ? a : b; }
|
||||||
|
|
||||||
|
nghttp2_min_def(int8, int8_t);
|
||||||
|
nghttp2_min_def(int16, int16_t);
|
||||||
|
nghttp2_min_def(int32, int32_t);
|
||||||
|
nghttp2_min_def(int64, int64_t);
|
||||||
|
nghttp2_min_def(uint8, uint8_t);
|
||||||
|
nghttp2_min_def(uint16, uint16_t);
|
||||||
|
nghttp2_min_def(uint32, uint32_t);
|
||||||
|
nghttp2_min_def(uint64, uint64_t);
|
||||||
|
nghttp2_min_def(size, size_t);
|
||||||
|
|
||||||
#define lstreq(A, B, N) ((sizeof((A)) - 1) == (N) && memcmp((A), (B), (N)) == 0)
|
#define lstreq(A, B, N) ((sizeof((A)) - 1) == (N) && memcmp((A), (B), (N)) == 0)
|
||||||
|
|
||||||
|
|||||||
@@ -126,6 +126,7 @@ static void map_bucket_set_data(nghttp2_map_bucket *bkt, uint32_t hash,
|
|||||||
bkt->data = data;
|
bkt->data = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef WIN32
|
||||||
void nghttp2_map_print_distance(nghttp2_map *map) {
|
void nghttp2_map_print_distance(nghttp2_map *map) {
|
||||||
uint32_t i;
|
uint32_t i;
|
||||||
size_t idx;
|
size_t idx;
|
||||||
@@ -145,6 +146,7 @@ void nghttp2_map_print_distance(nghttp2_map *map) {
|
|||||||
distance(map->tablelen, map->tablelenbits, bkt, idx));
|
distance(map->tablelen, map->tablelenbits, bkt, idx));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif /* !WIN32 */
|
||||||
|
|
||||||
static int insert(nghttp2_map_bucket *table, uint32_t tablelen,
|
static int insert(nghttp2_map_bucket *table, uint32_t tablelen,
|
||||||
uint32_t tablelenbits, uint32_t hash,
|
uint32_t tablelenbits, uint32_t hash,
|
||||||
|
|||||||
@@ -131,6 +131,8 @@ size_t nghttp2_map_size(nghttp2_map *map);
|
|||||||
int nghttp2_map_each(nghttp2_map *map, int (*func)(void *data, void *ptr),
|
int nghttp2_map_each(nghttp2_map *map, int (*func)(void *data, void *ptr),
|
||||||
void *ptr);
|
void *ptr);
|
||||||
|
|
||||||
|
#ifndef WIN32
|
||||||
void nghttp2_map_print_distance(nghttp2_map *map);
|
void nghttp2_map_print_distance(nghttp2_map *map);
|
||||||
|
#endif /* !WIN32 */
|
||||||
|
|
||||||
#endif /* NGHTTP2_MAP_H */
|
#endif /* NGHTTP2_MAP_H */
|
||||||
|
|||||||
@@ -150,3 +150,8 @@ void nghttp2_option_set_stream_reset_rate_limit(nghttp2_option *option,
|
|||||||
option->stream_reset_burst = burst;
|
option->stream_reset_burst = burst;
|
||||||
option->stream_reset_rate = rate;
|
option->stream_reset_rate = rate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void nghttp2_option_set_max_continuations(nghttp2_option *option, size_t val) {
|
||||||
|
option->opt_set_mask |= NGHTTP2_OPT_MAX_CONTINUATIONS;
|
||||||
|
option->max_continuations = val;
|
||||||
|
}
|
||||||
|
|||||||
@@ -71,6 +71,7 @@ typedef enum {
|
|||||||
NGHTTP2_OPT_SERVER_FALLBACK_RFC7540_PRIORITIES = 1 << 13,
|
NGHTTP2_OPT_SERVER_FALLBACK_RFC7540_PRIORITIES = 1 << 13,
|
||||||
NGHTTP2_OPT_NO_RFC9113_LEADING_AND_TRAILING_WS_VALIDATION = 1 << 14,
|
NGHTTP2_OPT_NO_RFC9113_LEADING_AND_TRAILING_WS_VALIDATION = 1 << 14,
|
||||||
NGHTTP2_OPT_STREAM_RESET_RATE_LIMIT = 1 << 15,
|
NGHTTP2_OPT_STREAM_RESET_RATE_LIMIT = 1 << 15,
|
||||||
|
NGHTTP2_OPT_MAX_CONTINUATIONS = 1 << 16,
|
||||||
} nghttp2_option_flag;
|
} nghttp2_option_flag;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -98,6 +99,10 @@ struct nghttp2_option {
|
|||||||
* NGHTTP2_OPT_MAX_SETTINGS
|
* NGHTTP2_OPT_MAX_SETTINGS
|
||||||
*/
|
*/
|
||||||
size_t max_settings;
|
size_t max_settings;
|
||||||
|
/**
|
||||||
|
* NGHTTP2_OPT_MAX_CONTINUATIONS
|
||||||
|
*/
|
||||||
|
size_t max_continuations;
|
||||||
/**
|
/**
|
||||||
* Bitwise OR of nghttp2_option_flag to determine that which fields
|
* Bitwise OR of nghttp2_option_flag to determine that which fields
|
||||||
* are specified.
|
* are specified.
|
||||||
|
|||||||
@@ -27,6 +27,32 @@
|
|||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
nghttp2_data_provider_wrap *
|
||||||
|
nghttp2_data_provider_wrap_v1(nghttp2_data_provider_wrap *dpw,
|
||||||
|
const nghttp2_data_provider *data_prd) {
|
||||||
|
if (!data_prd) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
dpw->version = NGHTTP2_DATA_PROVIDER_V1;
|
||||||
|
dpw->data_prd.v1 = *data_prd;
|
||||||
|
|
||||||
|
return dpw;
|
||||||
|
}
|
||||||
|
|
||||||
|
nghttp2_data_provider_wrap *
|
||||||
|
nghttp2_data_provider_wrap_v2(nghttp2_data_provider_wrap *dpw,
|
||||||
|
const nghttp2_data_provider2 *data_prd) {
|
||||||
|
if (!data_prd) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
dpw->version = NGHTTP2_DATA_PROVIDER_V2;
|
||||||
|
dpw->data_prd.v2 = *data_prd;
|
||||||
|
|
||||||
|
return dpw;
|
||||||
|
}
|
||||||
|
|
||||||
void nghttp2_outbound_item_init(nghttp2_outbound_item *item) {
|
void nghttp2_outbound_item_init(nghttp2_outbound_item *item) {
|
||||||
item->cycle = 0;
|
item->cycle = 0;
|
||||||
item->qnext = NULL;
|
item->qnext = NULL;
|
||||||
|
|||||||
@@ -33,9 +33,32 @@
|
|||||||
#include "nghttp2_frame.h"
|
#include "nghttp2_frame.h"
|
||||||
#include "nghttp2_mem.h"
|
#include "nghttp2_mem.h"
|
||||||
|
|
||||||
|
#define NGHTTP2_DATA_PROVIDER_V1 1
|
||||||
|
#define NGHTTP2_DATA_PROVIDER_V2 2
|
||||||
|
|
||||||
|
typedef struct nghttp2_data_provider_wrap {
|
||||||
|
int version;
|
||||||
|
union {
|
||||||
|
struct {
|
||||||
|
nghttp2_data_source source;
|
||||||
|
void *read_callback;
|
||||||
|
};
|
||||||
|
nghttp2_data_provider v1;
|
||||||
|
nghttp2_data_provider2 v2;
|
||||||
|
} data_prd;
|
||||||
|
} nghttp2_data_provider_wrap;
|
||||||
|
|
||||||
|
nghttp2_data_provider_wrap *
|
||||||
|
nghttp2_data_provider_wrap_v1(nghttp2_data_provider_wrap *dpw,
|
||||||
|
const nghttp2_data_provider *data_prd);
|
||||||
|
|
||||||
|
nghttp2_data_provider_wrap *
|
||||||
|
nghttp2_data_provider_wrap_v2(nghttp2_data_provider_wrap *dpw,
|
||||||
|
const nghttp2_data_provider2 *data_prd);
|
||||||
|
|
||||||
/* struct used for HEADERS and PUSH_PROMISE frame */
|
/* struct used for HEADERS and PUSH_PROMISE frame */
|
||||||
typedef struct {
|
typedef struct {
|
||||||
nghttp2_data_provider data_prd;
|
nghttp2_data_provider_wrap dpw;
|
||||||
void *stream_user_data;
|
void *stream_user_data;
|
||||||
/* error code when request HEADERS is canceled by RST_STREAM while
|
/* error code when request HEADERS is canceled by RST_STREAM while
|
||||||
it is in queue. */
|
it is in queue. */
|
||||||
@@ -50,7 +73,7 @@ typedef struct {
|
|||||||
/**
|
/**
|
||||||
* The data to be sent for this DATA frame.
|
* The data to be sent for this DATA frame.
|
||||||
*/
|
*/
|
||||||
nghttp2_data_provider data_prd;
|
nghttp2_data_provider_wrap dpw;
|
||||||
/**
|
/**
|
||||||
* The flags of DATA frame. We use separate flags here and
|
* The flags of DATA frame. We use separate flags here and
|
||||||
* nghttp2_data frame. The latter contains flags actually sent to
|
* nghttp2_data frame. The latter contains flags actually sent to
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ int nghttp2_pq_push(nghttp2_pq *pq, nghttp2_pq_entry *item) {
|
|||||||
void *nq;
|
void *nq;
|
||||||
size_t ncapacity;
|
size_t ncapacity;
|
||||||
|
|
||||||
ncapacity = nghttp2_max(4, (pq->capacity * 2));
|
ncapacity = nghttp2_max_size(4, (pq->capacity * 2));
|
||||||
|
|
||||||
nq = nghttp2_mem_realloc(pq->mem, pq->q,
|
nq = nghttp2_mem_realloc(pq->mem, pq->q,
|
||||||
ncapacity * sizeof(nghttp2_pq_entry *));
|
ncapacity * sizeof(nghttp2_pq_entry *));
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ void nghttp2_ratelim_update(nghttp2_ratelim *rl, uint64_t tstamp) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
rl->val += gain;
|
rl->val += gain;
|
||||||
rl->val = nghttp2_min(rl->val, rl->burst);
|
rl->val = nghttp2_min_uint64(rl->val, rl->burst);
|
||||||
}
|
}
|
||||||
|
|
||||||
int nghttp2_ratelim_drain(nghttp2_ratelim *rl, uint64_t n) {
|
int nghttp2_ratelim_drain(nghttp2_ratelim *rl, uint64_t n) {
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -110,6 +110,10 @@ typedef struct {
|
|||||||
#define NGHTTP2_DEFAULT_STREAM_RESET_BURST 1000
|
#define NGHTTP2_DEFAULT_STREAM_RESET_BURST 1000
|
||||||
#define NGHTTP2_DEFAULT_STREAM_RESET_RATE 33
|
#define NGHTTP2_DEFAULT_STREAM_RESET_RATE 33
|
||||||
|
|
||||||
|
/* The default max number of CONTINUATION frames following an incoming
|
||||||
|
HEADER frame. */
|
||||||
|
#define NGHTTP2_DEFAULT_MAX_CONTINUATIONS 8
|
||||||
|
|
||||||
/* Internal state when receiving incoming frame */
|
/* Internal state when receiving incoming frame */
|
||||||
typedef enum {
|
typedef enum {
|
||||||
/* Receiving frame header */
|
/* Receiving frame header */
|
||||||
@@ -290,6 +294,12 @@ struct nghttp2_session {
|
|||||||
size_t max_send_header_block_length;
|
size_t max_send_header_block_length;
|
||||||
/* The maximum number of settings accepted per SETTINGS frame. */
|
/* The maximum number of settings accepted per SETTINGS frame. */
|
||||||
size_t max_settings;
|
size_t max_settings;
|
||||||
|
/* The maximum number of CONTINUATION frames following an incoming
|
||||||
|
HEADER frame. */
|
||||||
|
size_t max_continuations;
|
||||||
|
/* The number of CONTINUATION frames following an incoming HEADER
|
||||||
|
frame. This variable is reset when END_HEADERS flag is seen. */
|
||||||
|
size_t num_continuations;
|
||||||
/* Next Stream ID. Made unsigned int to detect >= (1 << 31). */
|
/* Next Stream ID. Made unsigned int to detect >= (1 << 31). */
|
||||||
uint32_t next_stream_id;
|
uint32_t next_stream_id;
|
||||||
/* The last stream ID this session initiated. For client session,
|
/* The last stream ID this session initiated. For client session,
|
||||||
|
|||||||
@@ -312,7 +312,7 @@ int32_t nghttp2_stream_dep_distributed_weight(nghttp2_stream *stream,
|
|||||||
int32_t weight) {
|
int32_t weight) {
|
||||||
weight = stream->weight * weight / stream->sum_dep_weight;
|
weight = stream->weight * weight / stream->sum_dep_weight;
|
||||||
|
|
||||||
return nghttp2_max(1, weight);
|
return nghttp2_max_int32(1, weight);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef STREAM_DEP_DEBUG
|
#ifdef STREAM_DEP_DEBUG
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ static int32_t submit_headers_shared(nghttp2_session *session, uint8_t flags,
|
|||||||
int32_t stream_id,
|
int32_t stream_id,
|
||||||
const nghttp2_priority_spec *pri_spec,
|
const nghttp2_priority_spec *pri_spec,
|
||||||
nghttp2_nv *nva_copy, size_t nvlen,
|
nghttp2_nv *nva_copy, size_t nvlen,
|
||||||
const nghttp2_data_provider *data_prd,
|
const nghttp2_data_provider_wrap *dpw,
|
||||||
void *stream_user_data) {
|
void *stream_user_data) {
|
||||||
int rv;
|
int rv;
|
||||||
uint8_t flags_copy;
|
uint8_t flags_copy;
|
||||||
@@ -87,8 +87,8 @@ static int32_t submit_headers_shared(nghttp2_session *session, uint8_t flags,
|
|||||||
|
|
||||||
nghttp2_outbound_item_init(item);
|
nghttp2_outbound_item_init(item);
|
||||||
|
|
||||||
if (data_prd != NULL && data_prd->read_callback != NULL) {
|
if (dpw != NULL && dpw->data_prd.read_callback != NULL) {
|
||||||
item->aux_data.headers.data_prd = *data_prd;
|
item->aux_data.headers.dpw = *dpw;
|
||||||
}
|
}
|
||||||
|
|
||||||
item->aux_data.headers.stream_user_data = stream_user_data;
|
item->aux_data.headers.stream_user_data = stream_user_data;
|
||||||
@@ -143,7 +143,7 @@ static int32_t submit_headers_shared_nva(nghttp2_session *session,
|
|||||||
uint8_t flags, int32_t stream_id,
|
uint8_t flags, int32_t stream_id,
|
||||||
const nghttp2_priority_spec *pri_spec,
|
const nghttp2_priority_spec *pri_spec,
|
||||||
const nghttp2_nv *nva, size_t nvlen,
|
const nghttp2_nv *nva, size_t nvlen,
|
||||||
const nghttp2_data_provider *data_prd,
|
const nghttp2_data_provider_wrap *dpw,
|
||||||
void *stream_user_data) {
|
void *stream_user_data) {
|
||||||
int rv;
|
int rv;
|
||||||
nghttp2_nv *nva_copy;
|
nghttp2_nv *nva_copy;
|
||||||
@@ -165,7 +165,7 @@ static int32_t submit_headers_shared_nva(nghttp2_session *session,
|
|||||||
}
|
}
|
||||||
|
|
||||||
return submit_headers_shared(session, flags, stream_id, ©_pri_spec,
|
return submit_headers_shared(session, flags, stream_id, ©_pri_spec,
|
||||||
nva_copy, nvlen, data_prd, stream_user_data);
|
nva_copy, nvlen, dpw, stream_user_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
int nghttp2_submit_trailer(nghttp2_session *session, int32_t stream_id,
|
int nghttp2_submit_trailer(nghttp2_session *session, int32_t stream_id,
|
||||||
@@ -411,10 +411,10 @@ int nghttp2_submit_window_update(nghttp2_session *session, uint8_t flags,
|
|||||||
if (window_size_increment > 0) {
|
if (window_size_increment > 0) {
|
||||||
if (stream_id == 0) {
|
if (stream_id == 0) {
|
||||||
session->consumed_size =
|
session->consumed_size =
|
||||||
nghttp2_max(0, session->consumed_size - window_size_increment);
|
nghttp2_max_int32(0, session->consumed_size - window_size_increment);
|
||||||
} else {
|
} else {
|
||||||
stream->consumed_size =
|
stream->consumed_size =
|
||||||
nghttp2_max(0, stream->consumed_size - window_size_increment);
|
nghttp2_max_int32(0, stream->consumed_size - window_size_increment);
|
||||||
}
|
}
|
||||||
|
|
||||||
return nghttp2_session_add_window_update(session, 0, stream_id,
|
return nghttp2_session_add_window_update(session, 0, stream_id,
|
||||||
@@ -740,9 +740,9 @@ fail_item_malloc:
|
|||||||
}
|
}
|
||||||
|
|
||||||
static uint8_t set_request_flags(const nghttp2_priority_spec *pri_spec,
|
static uint8_t set_request_flags(const nghttp2_priority_spec *pri_spec,
|
||||||
const nghttp2_data_provider *data_prd) {
|
const nghttp2_data_provider_wrap *dpw) {
|
||||||
uint8_t flags = NGHTTP2_FLAG_NONE;
|
uint8_t flags = NGHTTP2_FLAG_NONE;
|
||||||
if (data_prd == NULL || data_prd->read_callback == NULL) {
|
if (dpw == NULL || dpw->data_prd.read_callback == NULL) {
|
||||||
flags |= NGHTTP2_FLAG_END_STREAM;
|
flags |= NGHTTP2_FLAG_END_STREAM;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -753,10 +753,10 @@ static uint8_t set_request_flags(const nghttp2_priority_spec *pri_spec,
|
|||||||
return flags;
|
return flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t nghttp2_submit_request(nghttp2_session *session,
|
static int32_t submit_request_shared(nghttp2_session *session,
|
||||||
const nghttp2_priority_spec *pri_spec,
|
const nghttp2_priority_spec *pri_spec,
|
||||||
const nghttp2_nv *nva, size_t nvlen,
|
const nghttp2_nv *nva, size_t nvlen,
|
||||||
const nghttp2_data_provider *data_prd,
|
const nghttp2_data_provider_wrap *dpw,
|
||||||
void *stream_user_data) {
|
void *stream_user_data) {
|
||||||
uint8_t flags;
|
uint8_t flags;
|
||||||
int rv;
|
int rv;
|
||||||
@@ -775,23 +775,47 @@ int32_t nghttp2_submit_request(nghttp2_session *session,
|
|||||||
pri_spec = NULL;
|
pri_spec = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
flags = set_request_flags(pri_spec, data_prd);
|
flags = set_request_flags(pri_spec, dpw);
|
||||||
|
|
||||||
return submit_headers_shared_nva(session, flags, -1, pri_spec, nva, nvlen,
|
return submit_headers_shared_nva(session, flags, -1, pri_spec, nva, nvlen,
|
||||||
data_prd, stream_user_data);
|
dpw, stream_user_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint8_t set_response_flags(const nghttp2_data_provider *data_prd) {
|
int32_t nghttp2_submit_request(nghttp2_session *session,
|
||||||
|
const nghttp2_priority_spec *pri_spec,
|
||||||
|
const nghttp2_nv *nva, size_t nvlen,
|
||||||
|
const nghttp2_data_provider *data_prd,
|
||||||
|
void *stream_user_data) {
|
||||||
|
nghttp2_data_provider_wrap dpw;
|
||||||
|
|
||||||
|
return submit_request_shared(session, pri_spec, nva, nvlen,
|
||||||
|
nghttp2_data_provider_wrap_v1(&dpw, data_prd),
|
||||||
|
stream_user_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t nghttp2_submit_request2(nghttp2_session *session,
|
||||||
|
const nghttp2_priority_spec *pri_spec,
|
||||||
|
const nghttp2_nv *nva, size_t nvlen,
|
||||||
|
const nghttp2_data_provider2 *data_prd,
|
||||||
|
void *stream_user_data) {
|
||||||
|
nghttp2_data_provider_wrap dpw;
|
||||||
|
|
||||||
|
return submit_request_shared(session, pri_spec, nva, nvlen,
|
||||||
|
nghttp2_data_provider_wrap_v2(&dpw, data_prd),
|
||||||
|
stream_user_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint8_t set_response_flags(const nghttp2_data_provider_wrap *dpw) {
|
||||||
uint8_t flags = NGHTTP2_FLAG_NONE;
|
uint8_t flags = NGHTTP2_FLAG_NONE;
|
||||||
if (data_prd == NULL || data_prd->read_callback == NULL) {
|
if (dpw == NULL || dpw->data_prd.read_callback == NULL) {
|
||||||
flags |= NGHTTP2_FLAG_END_STREAM;
|
flags |= NGHTTP2_FLAG_END_STREAM;
|
||||||
}
|
}
|
||||||
return flags;
|
return flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
int nghttp2_submit_response(nghttp2_session *session, int32_t stream_id,
|
static int submit_response_shared(nghttp2_session *session, int32_t stream_id,
|
||||||
const nghttp2_nv *nva, size_t nvlen,
|
const nghttp2_nv *nva, size_t nvlen,
|
||||||
const nghttp2_data_provider *data_prd) {
|
const nghttp2_data_provider_wrap *dpw) {
|
||||||
uint8_t flags;
|
uint8_t flags;
|
||||||
|
|
||||||
if (stream_id <= 0) {
|
if (stream_id <= 0) {
|
||||||
@@ -802,14 +826,32 @@ int nghttp2_submit_response(nghttp2_session *session, int32_t stream_id,
|
|||||||
return NGHTTP2_ERR_PROTO;
|
return NGHTTP2_ERR_PROTO;
|
||||||
}
|
}
|
||||||
|
|
||||||
flags = set_response_flags(data_prd);
|
flags = set_response_flags(dpw);
|
||||||
return submit_headers_shared_nva(session, flags, stream_id, NULL, nva, nvlen,
|
return submit_headers_shared_nva(session, flags, stream_id, NULL, nva, nvlen,
|
||||||
data_prd, NULL);
|
dpw, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
int nghttp2_submit_data(nghttp2_session *session, uint8_t flags,
|
int nghttp2_submit_response(nghttp2_session *session, int32_t stream_id,
|
||||||
int32_t stream_id,
|
const nghttp2_nv *nva, size_t nvlen,
|
||||||
const nghttp2_data_provider *data_prd) {
|
const nghttp2_data_provider *data_prd) {
|
||||||
|
nghttp2_data_provider_wrap dpw;
|
||||||
|
|
||||||
|
return submit_response_shared(session, stream_id, nva, nvlen,
|
||||||
|
nghttp2_data_provider_wrap_v1(&dpw, data_prd));
|
||||||
|
}
|
||||||
|
|
||||||
|
int nghttp2_submit_response2(nghttp2_session *session, int32_t stream_id,
|
||||||
|
const nghttp2_nv *nva, size_t nvlen,
|
||||||
|
const nghttp2_data_provider2 *data_prd) {
|
||||||
|
nghttp2_data_provider_wrap dpw;
|
||||||
|
|
||||||
|
return submit_response_shared(session, stream_id, nva, nvlen,
|
||||||
|
nghttp2_data_provider_wrap_v2(&dpw, data_prd));
|
||||||
|
}
|
||||||
|
|
||||||
|
int nghttp2_submit_data_shared(nghttp2_session *session, uint8_t flags,
|
||||||
|
int32_t stream_id,
|
||||||
|
const nghttp2_data_provider_wrap *dpw) {
|
||||||
int rv;
|
int rv;
|
||||||
nghttp2_outbound_item *item;
|
nghttp2_outbound_item *item;
|
||||||
nghttp2_frame *frame;
|
nghttp2_frame *frame;
|
||||||
@@ -832,7 +874,7 @@ int nghttp2_submit_data(nghttp2_session *session, uint8_t flags,
|
|||||||
|
|
||||||
frame = &item->frame;
|
frame = &item->frame;
|
||||||
aux_data = &item->aux_data.data;
|
aux_data = &item->aux_data.data;
|
||||||
aux_data->data_prd = *data_prd;
|
aux_data->dpw = *dpw;
|
||||||
aux_data->eof = 0;
|
aux_data->eof = 0;
|
||||||
aux_data->flags = nflags;
|
aux_data->flags = nflags;
|
||||||
|
|
||||||
@@ -848,9 +890,37 @@ int nghttp2_submit_data(nghttp2_session *session, uint8_t flags,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int nghttp2_submit_data(nghttp2_session *session, uint8_t flags,
|
||||||
|
int32_t stream_id,
|
||||||
|
const nghttp2_data_provider *data_prd) {
|
||||||
|
nghttp2_data_provider_wrap dpw;
|
||||||
|
|
||||||
|
assert(data_prd);
|
||||||
|
|
||||||
|
return nghttp2_submit_data_shared(
|
||||||
|
session, flags, stream_id, nghttp2_data_provider_wrap_v1(&dpw, data_prd));
|
||||||
|
}
|
||||||
|
|
||||||
|
int nghttp2_submit_data2(nghttp2_session *session, uint8_t flags,
|
||||||
|
int32_t stream_id,
|
||||||
|
const nghttp2_data_provider2 *data_prd) {
|
||||||
|
nghttp2_data_provider_wrap dpw;
|
||||||
|
|
||||||
|
assert(data_prd);
|
||||||
|
|
||||||
|
return nghttp2_submit_data_shared(
|
||||||
|
session, flags, stream_id, nghttp2_data_provider_wrap_v2(&dpw, data_prd));
|
||||||
|
}
|
||||||
|
|
||||||
ssize_t nghttp2_pack_settings_payload(uint8_t *buf, size_t buflen,
|
ssize_t nghttp2_pack_settings_payload(uint8_t *buf, size_t buflen,
|
||||||
const nghttp2_settings_entry *iv,
|
const nghttp2_settings_entry *iv,
|
||||||
size_t niv) {
|
size_t niv) {
|
||||||
|
return (ssize_t)nghttp2_pack_settings_payload2(buf, buflen, iv, niv);
|
||||||
|
}
|
||||||
|
|
||||||
|
nghttp2_ssize nghttp2_pack_settings_payload2(uint8_t *buf, size_t buflen,
|
||||||
|
const nghttp2_settings_entry *iv,
|
||||||
|
size_t niv) {
|
||||||
if (!nghttp2_iv_check(iv, niv)) {
|
if (!nghttp2_iv_check(iv, niv)) {
|
||||||
return NGHTTP2_ERR_INVALID_ARGUMENT;
|
return NGHTTP2_ERR_INVALID_ARGUMENT;
|
||||||
}
|
}
|
||||||
@@ -859,7 +929,7 @@ ssize_t nghttp2_pack_settings_payload(uint8_t *buf, size_t buflen,
|
|||||||
return NGHTTP2_ERR_INSUFF_BUFSIZE;
|
return NGHTTP2_ERR_INSUFF_BUFSIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (ssize_t)nghttp2_frame_pack_settings_payload(buf, iv, niv);
|
return (nghttp2_ssize)nghttp2_frame_pack_settings_payload(buf, iv, niv);
|
||||||
}
|
}
|
||||||
|
|
||||||
int nghttp2_submit_extension(nghttp2_session *session, uint8_t type,
|
int nghttp2_submit_extension(nghttp2_session *session, uint8_t type,
|
||||||
@@ -875,7 +945,8 @@ int nghttp2_submit_extension(nghttp2_session *session, uint8_t type,
|
|||||||
return NGHTTP2_ERR_INVALID_ARGUMENT;
|
return NGHTTP2_ERR_INVALID_ARGUMENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!session->callbacks.pack_extension_callback) {
|
if (!session->callbacks.pack_extension_callback2 &&
|
||||||
|
!session->callbacks.pack_extension_callback) {
|
||||||
return NGHTTP2_ERR_INVALID_STATE;
|
return NGHTTP2_ERR_INVALID_STATE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -31,4 +31,10 @@
|
|||||||
|
|
||||||
#include <nghttp2/nghttp2.h>
|
#include <nghttp2/nghttp2.h>
|
||||||
|
|
||||||
|
typedef struct nghttp2_data_provider_wrap nghttp2_data_provider_wrap;
|
||||||
|
|
||||||
|
int nghttp2_submit_data_shared(nghttp2_session *session, uint8_t flags,
|
||||||
|
int32_t stream_id,
|
||||||
|
const nghttp2_data_provider_wrap *dpw);
|
||||||
|
|
||||||
#endif /* NGHTTP2_SUBMIT_H */
|
#endif /* NGHTTP2_SUBMIT_H */
|
||||||
|
|||||||
@@ -24,15 +24,13 @@
|
|||||||
*/
|
*/
|
||||||
#include "nghttp2_time.h"
|
#include "nghttp2_time.h"
|
||||||
|
|
||||||
#ifdef HAVE_TIME_H
|
#ifdef HAVE_WINDOWS_H
|
||||||
# include <time.h>
|
# include <windows.h>
|
||||||
#endif /* HAVE_TIME_H */
|
#endif /* HAVE_WINDOWS_H */
|
||||||
|
|
||||||
#ifdef HAVE_SYSINFOAPI_H
|
#include <time.h>
|
||||||
# include <sysinfoapi.h>
|
|
||||||
#endif /* HAVE_SYSINFOAPI_H */
|
|
||||||
|
|
||||||
#ifndef HAVE_GETTICKCOUNT64
|
#if !defined(HAVE_GETTICKCOUNT64) || defined(__CYGWIN__)
|
||||||
static uint64_t time_now_sec(void) {
|
static uint64_t time_now_sec(void) {
|
||||||
time_t t = time(NULL);
|
time_t t = time(NULL);
|
||||||
|
|
||||||
@@ -42,9 +40,12 @@ static uint64_t time_now_sec(void) {
|
|||||||
|
|
||||||
return (uint64_t)t;
|
return (uint64_t)t;
|
||||||
}
|
}
|
||||||
#endif /* HAVE_GETTICKCOUNT64 */
|
#endif /* !HAVE_GETTICKCOUNT64 || __CYGWIN__ */
|
||||||
|
|
||||||
#ifdef HAVE_CLOCK_GETTIME
|
#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
|
||||||
uint64_t nghttp2_time_now_sec(void) {
|
uint64_t nghttp2_time_now_sec(void) {
|
||||||
struct timespec tp;
|
struct timespec tp;
|
||||||
int rv = clock_gettime(CLOCK_MONOTONIC, &tp);
|
int rv = clock_gettime(CLOCK_MONOTONIC, &tp);
|
||||||
@@ -55,8 +56,8 @@ uint64_t nghttp2_time_now_sec(void) {
|
|||||||
|
|
||||||
return (uint64_t)tp.tv_sec;
|
return (uint64_t)tp.tv_sec;
|
||||||
}
|
}
|
||||||
#elif defined(HAVE_GETTICKCOUNT64)
|
#else /* (!HAVE_CLOCK_GETTIME || !HAVE_DECL_CLOCK_MONOTONIC) && \
|
||||||
uint64_t nghttp2_time_now_sec(void) { return GetTickCount64() / 1000; }
|
(!HAVE_GETTICKCOUNT64 || __CYGWIN__)) */
|
||||||
#else /* !HAVE_CLOCK_GETTIME && !HAVE_GETTICKCOUNT64 */
|
|
||||||
uint64_t nghttp2_time_now_sec(void) { return time_now_sec(); }
|
uint64_t nghttp2_time_now_sec(void) { return time_now_sec(); }
|
||||||
#endif /* !HAVE_CLOCK_GETTIME && !HAVE_GETTICKCOUNT64 */
|
#endif /* (!HAVE_CLOCK_GETTIME || !HAVE_DECL_CLOCK_MONOTONIC) && \
|
||||||
|
(!HAVE_GETTICKCOUNT64 || __CYGWIN__)) */
|
||||||
|
|||||||
@@ -10,13 +10,13 @@
|
|||||||
#
|
#
|
||||||
# Check for baseline language coverage in the compiler for the specified
|
# Check for baseline language coverage in the compiler for the specified
|
||||||
# version of the C++ standard. If necessary, add switches to CXX and
|
# version of the C++ standard. If necessary, add switches to CXX and
|
||||||
# CXXCPP to enable support. VERSION may be '11' (for the C++11 standard)
|
# CXXCPP to enable support. VERSION may be '11', '14', '17', or '20' for
|
||||||
# or '14' (for the C++14 standard).
|
# the respective C++ standard version.
|
||||||
#
|
#
|
||||||
# The second argument, if specified, indicates whether you insist on an
|
# The second argument, if specified, indicates whether you insist on an
|
||||||
# extended mode (e.g. -std=gnu++11) or a strict conformance mode (e.g.
|
# extended mode (e.g. -std=gnu++11) or a strict conformance mode (e.g.
|
||||||
# -std=c++11). If neither is specified, you get whatever works, with
|
# -std=c++11). If neither is specified, you get whatever works, with
|
||||||
# preference for an extended mode.
|
# preference for no added switch, and then for an extended mode.
|
||||||
#
|
#
|
||||||
# The third argument, if specified 'mandatory' or if left unspecified,
|
# The third argument, if specified 'mandatory' or if left unspecified,
|
||||||
# indicates that baseline support for the specified C++ standard is
|
# indicates that baseline support for the specified C++ standard is
|
||||||
@@ -34,13 +34,16 @@
|
|||||||
# Copyright (c) 2015 Paul Norman <penorman@mac.com>
|
# Copyright (c) 2015 Paul Norman <penorman@mac.com>
|
||||||
# Copyright (c) 2015 Moritz Klammler <moritz@klammler.eu>
|
# Copyright (c) 2015 Moritz Klammler <moritz@klammler.eu>
|
||||||
# Copyright (c) 2016, 2018 Krzesimir Nowak <qdlacz@gmail.com>
|
# Copyright (c) 2016, 2018 Krzesimir Nowak <qdlacz@gmail.com>
|
||||||
|
# Copyright (c) 2019 Enji Cooper <yaneurabeya@gmail.com>
|
||||||
|
# Copyright (c) 2020 Jason Merrill <jason@redhat.com>
|
||||||
|
# Copyright (c) 2021 Jörn Heusipp <osmanx@problemloesungsmaschine.de>
|
||||||
#
|
#
|
||||||
# Copying and distribution of this file, with or without modification, are
|
# Copying and distribution of this file, with or without modification, are
|
||||||
# permitted in any medium without royalty provided the copyright notice
|
# permitted in any medium without royalty provided the copyright notice
|
||||||
# and this notice are preserved. This file is offered as-is, without any
|
# and this notice are preserved. This file is offered as-is, without any
|
||||||
# warranty.
|
# warranty.
|
||||||
|
|
||||||
#serial 10
|
#serial 18
|
||||||
|
|
||||||
dnl This macro is based on the code from the AX_CXX_COMPILE_STDCXX_11 macro
|
dnl This macro is based on the code from the AX_CXX_COMPILE_STDCXX_11 macro
|
||||||
dnl (serial version number 13).
|
dnl (serial version number 13).
|
||||||
@@ -49,6 +52,7 @@ AC_DEFUN([AX_CXX_COMPILE_STDCXX], [dnl
|
|||||||
m4_if([$1], [11], [ax_cxx_compile_alternatives="11 0x"],
|
m4_if([$1], [11], [ax_cxx_compile_alternatives="11 0x"],
|
||||||
[$1], [14], [ax_cxx_compile_alternatives="14 1y"],
|
[$1], [14], [ax_cxx_compile_alternatives="14 1y"],
|
||||||
[$1], [17], [ax_cxx_compile_alternatives="17 1z"],
|
[$1], [17], [ax_cxx_compile_alternatives="17 1z"],
|
||||||
|
[$1], [20], [ax_cxx_compile_alternatives="20"],
|
||||||
[m4_fatal([invalid first argument `$1' to AX_CXX_COMPILE_STDCXX])])dnl
|
[m4_fatal([invalid first argument `$1' to AX_CXX_COMPILE_STDCXX])])dnl
|
||||||
m4_if([$2], [], [],
|
m4_if([$2], [], [],
|
||||||
[$2], [ext], [],
|
[$2], [ext], [],
|
||||||
@@ -61,6 +65,16 @@ AC_DEFUN([AX_CXX_COMPILE_STDCXX], [dnl
|
|||||||
AC_LANG_PUSH([C++])dnl
|
AC_LANG_PUSH([C++])dnl
|
||||||
ac_success=no
|
ac_success=no
|
||||||
|
|
||||||
|
m4_if([$2], [], [dnl
|
||||||
|
AC_CACHE_CHECK(whether $CXX supports C++$1 features by default,
|
||||||
|
ax_cv_cxx_compile_cxx$1,
|
||||||
|
[AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])],
|
||||||
|
[ax_cv_cxx_compile_cxx$1=yes],
|
||||||
|
[ax_cv_cxx_compile_cxx$1=no])])
|
||||||
|
if test x$ax_cv_cxx_compile_cxx$1 = xyes; then
|
||||||
|
ac_success=yes
|
||||||
|
fi])
|
||||||
|
|
||||||
m4_if([$2], [noext], [], [dnl
|
m4_if([$2], [noext], [], [dnl
|
||||||
if test x$ac_success = xno; then
|
if test x$ac_success = xno; then
|
||||||
for alternative in ${ax_cxx_compile_alternatives}; do
|
for alternative in ${ax_cxx_compile_alternatives}; do
|
||||||
@@ -90,9 +104,18 @@ AC_DEFUN([AX_CXX_COMPILE_STDCXX], [dnl
|
|||||||
dnl HP's aCC needs +std=c++11 according to:
|
dnl HP's aCC needs +std=c++11 according to:
|
||||||
dnl http://h21007.www2.hp.com/portal/download/files/unprot/aCxx/PDF_Release_Notes/769149-001.pdf
|
dnl http://h21007.www2.hp.com/portal/download/files/unprot/aCxx/PDF_Release_Notes/769149-001.pdf
|
||||||
dnl Cray's crayCC needs "-h std=c++11"
|
dnl Cray's crayCC needs "-h std=c++11"
|
||||||
|
dnl MSVC needs -std:c++NN for C++17 and later (default is C++14)
|
||||||
for alternative in ${ax_cxx_compile_alternatives}; do
|
for alternative in ${ax_cxx_compile_alternatives}; do
|
||||||
for switch in -std=c++${alternative} +std=c++${alternative} "-h std=c++${alternative}"; do
|
for switch in -std=c++${alternative} +std=c++${alternative} "-h std=c++${alternative}" MSVC; do
|
||||||
|
if test x"$switch" = xMSVC; then
|
||||||
|
dnl AS_TR_SH maps both `:` and `=` to `_` so -std:c++17 would collide
|
||||||
|
dnl with -std=c++17. We suffix the cache variable name with _MSVC to
|
||||||
|
dnl avoid this.
|
||||||
|
switch=-std:c++${alternative}
|
||||||
|
cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_${switch}_MSVC])
|
||||||
|
else
|
||||||
cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch])
|
cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch])
|
||||||
|
fi
|
||||||
AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch,
|
AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch,
|
||||||
$cachevar,
|
$cachevar,
|
||||||
[ac_save_CXX="$CXX"
|
[ac_save_CXX="$CXX"
|
||||||
@@ -139,7 +162,6 @@ m4_define([_AX_CXX_COMPILE_STDCXX_testbody_11],
|
|||||||
_AX_CXX_COMPILE_STDCXX_testbody_new_in_11
|
_AX_CXX_COMPILE_STDCXX_testbody_new_in_11
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
dnl Test body for checking C++14 support
|
dnl Test body for checking C++14 support
|
||||||
|
|
||||||
m4_define([_AX_CXX_COMPILE_STDCXX_testbody_14],
|
m4_define([_AX_CXX_COMPILE_STDCXX_testbody_14],
|
||||||
@@ -147,12 +169,24 @@ m4_define([_AX_CXX_COMPILE_STDCXX_testbody_14],
|
|||||||
_AX_CXX_COMPILE_STDCXX_testbody_new_in_14
|
_AX_CXX_COMPILE_STDCXX_testbody_new_in_14
|
||||||
)
|
)
|
||||||
|
|
||||||
|
dnl Test body for checking C++17 support
|
||||||
|
|
||||||
m4_define([_AX_CXX_COMPILE_STDCXX_testbody_17],
|
m4_define([_AX_CXX_COMPILE_STDCXX_testbody_17],
|
||||||
_AX_CXX_COMPILE_STDCXX_testbody_new_in_11
|
_AX_CXX_COMPILE_STDCXX_testbody_new_in_11
|
||||||
_AX_CXX_COMPILE_STDCXX_testbody_new_in_14
|
_AX_CXX_COMPILE_STDCXX_testbody_new_in_14
|
||||||
_AX_CXX_COMPILE_STDCXX_testbody_new_in_17
|
_AX_CXX_COMPILE_STDCXX_testbody_new_in_17
|
||||||
)
|
)
|
||||||
|
|
||||||
|
dnl Test body for checking C++20 support
|
||||||
|
|
||||||
|
m4_define([_AX_CXX_COMPILE_STDCXX_testbody_20],
|
||||||
|
_AX_CXX_COMPILE_STDCXX_testbody_new_in_11
|
||||||
|
_AX_CXX_COMPILE_STDCXX_testbody_new_in_14
|
||||||
|
_AX_CXX_COMPILE_STDCXX_testbody_new_in_17
|
||||||
|
_AX_CXX_COMPILE_STDCXX_testbody_new_in_20
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
dnl Tests for new features in C++11
|
dnl Tests for new features in C++11
|
||||||
|
|
||||||
m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_11], [[
|
m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_11], [[
|
||||||
@@ -164,7 +198,11 @@ m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_11], [[
|
|||||||
|
|
||||||
#error "This is not a C++ compiler"
|
#error "This is not a C++ compiler"
|
||||||
|
|
||||||
#elif __cplusplus < 201103L
|
// MSVC always sets __cplusplus to 199711L in older versions; newer versions
|
||||||
|
// only set it correctly if /Zc:__cplusplus is specified as well as a
|
||||||
|
// /std:c++NN switch:
|
||||||
|
// https://devblogs.microsoft.com/cppblog/msvc-now-correctly-reports-__cplusplus/
|
||||||
|
#elif __cplusplus < 201103L && !defined _MSC_VER
|
||||||
|
|
||||||
#error "This is not a C++11 compiler"
|
#error "This is not a C++11 compiler"
|
||||||
|
|
||||||
@@ -189,11 +227,13 @@ namespace cxx11
|
|||||||
|
|
||||||
struct Base
|
struct Base
|
||||||
{
|
{
|
||||||
|
virtual ~Base() {}
|
||||||
virtual void f() {}
|
virtual void f() {}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Derived : public Base
|
struct Derived : public Base
|
||||||
{
|
{
|
||||||
|
virtual ~Derived() override {}
|
||||||
virtual void f() override {}
|
virtual void f() override {}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -453,7 +493,7 @@ m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_14], [[
|
|||||||
|
|
||||||
#error "This is not a C++ compiler"
|
#error "This is not a C++ compiler"
|
||||||
|
|
||||||
#elif __cplusplus < 201402L
|
#elif __cplusplus < 201402L && !defined _MSC_VER
|
||||||
|
|
||||||
#error "This is not a C++14 compiler"
|
#error "This is not a C++14 compiler"
|
||||||
|
|
||||||
@@ -577,7 +617,7 @@ m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_17], [[
|
|||||||
|
|
||||||
#error "This is not a C++ compiler"
|
#error "This is not a C++ compiler"
|
||||||
|
|
||||||
#elif __cplusplus < 201703L
|
#elif __cplusplus < 201703L && !defined _MSC_VER
|
||||||
|
|
||||||
#error "This is not a C++17 compiler"
|
#error "This is not a C++17 compiler"
|
||||||
|
|
||||||
@@ -943,6 +983,36 @@ namespace cxx17
|
|||||||
|
|
||||||
} // namespace cxx17
|
} // namespace cxx17
|
||||||
|
|
||||||
#endif // __cplusplus < 201703L
|
#endif // __cplusplus < 201703L && !defined _MSC_VER
|
||||||
|
|
||||||
|
]])
|
||||||
|
|
||||||
|
|
||||||
|
dnl Tests for new features in C++20
|
||||||
|
|
||||||
|
m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_20], [[
|
||||||
|
|
||||||
|
#ifndef __cplusplus
|
||||||
|
|
||||||
|
#error "This is not a C++ compiler"
|
||||||
|
|
||||||
|
#elif __cplusplus < 202002L && !defined _MSC_VER
|
||||||
|
|
||||||
|
#error "This is not a C++20 compiler"
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#include <version>
|
||||||
|
|
||||||
|
namespace cxx20
|
||||||
|
{
|
||||||
|
|
||||||
|
// As C++20 supports feature test macros in the standard, there is no
|
||||||
|
// immediate need to actually test for feature availability on the
|
||||||
|
// Autoconf side.
|
||||||
|
|
||||||
|
} // namespace cxx20
|
||||||
|
|
||||||
|
#endif // __cplusplus < 202002L && !defined _MSC_VER
|
||||||
|
|
||||||
]])
|
]])
|
||||||
|
|||||||
@@ -6,18 +6,17 @@ PREV_TAG=$2
|
|||||||
git checkout refs/tags/$TAG
|
git checkout refs/tags/$TAG
|
||||||
git log --pretty=fuller --date=short refs/tags/$PREV_TAG..HEAD > ChangeLog
|
git log --pretty=fuller --date=short refs/tags/$PREV_TAG..HEAD > ChangeLog
|
||||||
|
|
||||||
git submodule update --init
|
|
||||||
|
|
||||||
autoreconf -i
|
autoreconf -i
|
||||||
./configure --with-mruby && \
|
./configure
|
||||||
make dist-bzip2 && make dist-gzip && make dist-xz || echo "error"
|
make dist-bzip2
|
||||||
|
make dist-gzip
|
||||||
|
make dist-xz
|
||||||
|
make distclean
|
||||||
|
|
||||||
rm -f checksums.txt
|
rm -f checksums.txt
|
||||||
|
|
||||||
VERSION=`echo -n $TAG | sed -E 's|^v([0-9]+\.[0-9]+\.[0-9]+)(-DEV)?$|\1|'`
|
VERSION=`echo -n $TAG | sed -E 's|^v([0-9]+\.[0-9]+\.[0-9]+(-[^.]+(\.[0-9]+)?)?)$|\1|'`
|
||||||
for f in nghttp2-$VERSION.tar.bz2 nghttp2-$VERSION.tar.gz nghttp2-$VERSION.tar.xz; do
|
for f in nghttp2-$VERSION.tar.bz2 nghttp2-$VERSION.tar.gz nghttp2-$VERSION.tar.xz; do
|
||||||
sha256sum $f >> checksums.txt
|
sha256sum $f >> checksums.txt
|
||||||
gpg --armor --detach-sign $f
|
echo -n "$GPG_PASSPHRASE" | gpg --batch --passphrase-fd 0 --pinentry-mode loopback --armor --detach-sign $f
|
||||||
done
|
done
|
||||||
|
|
||||||
make distclean
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python3
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
# nghttp2 - HTTP/2 C Library
|
# nghttp2 - HTTP/2 C Library
|
||||||
@@ -96,7 +96,7 @@ def run_openssl(args, allow_tempfail=False):
|
|||||||
raise Exception('nonzero return code {}'.format(p.returncode))
|
raise Exception('nonzero return code {}'.format(p.returncode))
|
||||||
return buf.getvalue()
|
return buf.getvalue()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
msg = 'OpenSSL exitted abnormally: {}:{}'.format(args, e)
|
msg = 'OpenSSL exited abnormally: {}:{}'.format(args, e)
|
||||||
tempfail(msg) if allow_tempfail else die(msg)
|
tempfail(msg) if allow_tempfail else die(msg)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -21,6 +21,8 @@ include_directories(
|
|||||||
${JANSSON_INCLUDE_DIRS}
|
${JANSSON_INCLUDE_DIRS}
|
||||||
${ZLIB_INCLUDE_DIRS}
|
${ZLIB_INCLUDE_DIRS}
|
||||||
${LIBBPF_INCLUDE_DIRS}
|
${LIBBPF_INCLUDE_DIRS}
|
||||||
|
${LIBBROTLIENC_INCLUDE_DIRS}
|
||||||
|
${LIBBROTLIDEC_INCLUDE_DIRS}
|
||||||
)
|
)
|
||||||
|
|
||||||
# XXX per-target?
|
# XXX per-target?
|
||||||
@@ -38,6 +40,8 @@ link_libraries(
|
|||||||
${ZLIB_LIBRARIES}
|
${ZLIB_LIBRARIES}
|
||||||
${APP_LIBRARIES}
|
${APP_LIBRARIES}
|
||||||
${LIBBPF_LIBRARIES}
|
${LIBBPF_LIBRARIES}
|
||||||
|
${LIBBROTLIENC_LIBRARIES}
|
||||||
|
${LIBBROTLIDEC_LIBRARIES}
|
||||||
)
|
)
|
||||||
|
|
||||||
if(ENABLE_APP)
|
if(ENABLE_APP)
|
||||||
@@ -163,8 +167,6 @@ if(ENABLE_APP)
|
|||||||
target_link_libraries(nghttpx_static neverbleed)
|
target_link_libraries(nghttpx_static neverbleed)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|
||||||
if(HAVE_CUNIT)
|
|
||||||
set(NGHTTPX_UNITTEST_SOURCES
|
set(NGHTTPX_UNITTEST_SOURCES
|
||||||
shrpx-unittest.cc
|
shrpx-unittest.cc
|
||||||
shrpx_tls_test.cc
|
shrpx_tls_test.cc
|
||||||
@@ -181,17 +183,20 @@ if(ENABLE_APP)
|
|||||||
memchunk_test.cc
|
memchunk_test.cc
|
||||||
template_test.cc
|
template_test.cc
|
||||||
base64_test.cc
|
base64_test.cc
|
||||||
|
${CMAKE_SOURCE_DIR}/tests/munit/munit.c
|
||||||
)
|
)
|
||||||
add_executable(nghttpx-unittest EXCLUDE_FROM_ALL
|
add_executable(nghttpx-unittest EXCLUDE_FROM_ALL
|
||||||
${NGHTTPX_UNITTEST_SOURCES}
|
${NGHTTPX_UNITTEST_SOURCES}
|
||||||
$<TARGET_OBJECTS:llhttp>
|
$<TARGET_OBJECTS:llhttp>
|
||||||
$<TARGET_OBJECTS:url-parser>
|
$<TARGET_OBJECTS:url-parser>
|
||||||
)
|
)
|
||||||
target_include_directories(nghttpx-unittest PRIVATE ${CUNIT_INCLUDE_DIRS})
|
target_include_directories(nghttpx-unittest PRIVATE
|
||||||
|
${CMAKE_SOURCE_DIR}/tests/munit
|
||||||
|
)
|
||||||
target_compile_definitions(nghttpx-unittest
|
target_compile_definitions(nghttpx-unittest
|
||||||
PRIVATE "-DNGHTTP2_SRC_DIR=\"${CMAKE_SOURCE_DIR}/src\""
|
PRIVATE "-DNGHTTP2_SRC_DIR=\"${CMAKE_SOURCE_DIR}/src\""
|
||||||
)
|
)
|
||||||
target_link_libraries(nghttpx-unittest nghttpx_static ${CUNIT_LIBRARIES})
|
target_link_libraries(nghttpx-unittest nghttpx_static)
|
||||||
if(HAVE_MRUBY)
|
if(HAVE_MRUBY)
|
||||||
target_link_libraries(nghttpx-unittest mruby-lib)
|
target_link_libraries(nghttpx-unittest mruby-lib)
|
||||||
endif()
|
endif()
|
||||||
@@ -201,7 +206,6 @@ if(ENABLE_APP)
|
|||||||
|
|
||||||
add_test(nghttpx-unittest nghttpx-unittest)
|
add_test(nghttpx-unittest nghttpx-unittest)
|
||||||
add_dependencies(check nghttpx-unittest)
|
add_dependencies(check nghttpx-unittest)
|
||||||
endif()
|
|
||||||
|
|
||||||
add_executable(nghttp ${NGHTTP_SOURCES} $<TARGET_OBJECTS:llhttp>
|
add_executable(nghttp ${NGHTTP_SOURCES} $<TARGET_OBJECTS:llhttp>
|
||||||
$<TARGET_OBJECTS:url-parser>
|
$<TARGET_OBJECTS:url-parser>
|
||||||
@@ -221,8 +225,7 @@ if(ENABLE_APP)
|
|||||||
$<TARGET_OBJECTS:url-parser>
|
$<TARGET_OBJECTS:url-parser>
|
||||||
)
|
)
|
||||||
|
|
||||||
install(TARGETS nghttp nghttpd nghttpx h2load
|
install(TARGETS nghttp nghttpd nghttpx h2load)
|
||||||
RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}")
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(ENABLE_HPACK_TOOLS)
|
if(ENABLE_HPACK_TOOLS)
|
||||||
@@ -238,6 +241,5 @@ if(ENABLE_HPACK_TOOLS)
|
|||||||
)
|
)
|
||||||
add_executable(inflatehd ${inflatehd_SOURCES})
|
add_executable(inflatehd ${inflatehd_SOURCES})
|
||||||
add_executable(deflatehd ${deflatehd_SOURCES})
|
add_executable(deflatehd ${deflatehd_SOURCES})
|
||||||
install(TARGETS inflatehd deflatehd
|
install(TARGETS inflatehd deflatehd)
|
||||||
RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}")
|
|
||||||
endif()
|
endif()
|
||||||
|
|||||||
@@ -58,11 +58,11 @@ StringRef get_attr(const xmlChar **attrs, const StringRef &name) {
|
|||||||
namespace {
|
namespace {
|
||||||
ResourceType
|
ResourceType
|
||||||
get_resource_type_for_preload_as(const StringRef &attribute_value) {
|
get_resource_type_for_preload_as(const StringRef &attribute_value) {
|
||||||
if (util::strieq_l("image", attribute_value)) {
|
if (util::strieq("image"_sr, attribute_value)) {
|
||||||
return REQ_IMG;
|
return REQ_IMG;
|
||||||
} else if (util::strieq_l("style", attribute_value)) {
|
} else if (util::strieq("style"_sr, attribute_value)) {
|
||||||
return REQ_CSS;
|
return REQ_CSS;
|
||||||
} else if (util::strieq_l("script", attribute_value)) {
|
} else if (util::strieq("script"_sr, attribute_value)) {
|
||||||
return REQ_UNBLOCK_JS;
|
return REQ_UNBLOCK_JS;
|
||||||
} else {
|
} else {
|
||||||
return REQ_OTHERS;
|
return REQ_OTHERS;
|
||||||
@@ -74,7 +74,7 @@ namespace {
|
|||||||
void add_link(ParserData *parser_data, const StringRef &uri,
|
void add_link(ParserData *parser_data, const StringRef &uri,
|
||||||
ResourceType res_type) {
|
ResourceType res_type) {
|
||||||
auto u = xmlBuildURI(
|
auto u = xmlBuildURI(
|
||||||
reinterpret_cast<const xmlChar *>(uri.c_str()),
|
reinterpret_cast<const xmlChar *>(uri.data()),
|
||||||
reinterpret_cast<const xmlChar *>(parser_data->base_uri.c_str()));
|
reinterpret_cast<const xmlChar *>(parser_data->base_uri.c_str()));
|
||||||
if (u) {
|
if (u) {
|
||||||
parser_data->links.push_back(
|
parser_data->links.push_back(
|
||||||
@@ -90,35 +90,35 @@ void start_element_func(void *user_data, const xmlChar *src_name,
|
|||||||
auto parser_data = static_cast<ParserData *>(user_data);
|
auto parser_data = static_cast<ParserData *>(user_data);
|
||||||
auto name =
|
auto name =
|
||||||
StringRef{src_name, strlen(reinterpret_cast<const char *>(src_name))};
|
StringRef{src_name, strlen(reinterpret_cast<const char *>(src_name))};
|
||||||
if (util::strieq_l("head", name)) {
|
if (util::strieq("head"_sr, name)) {
|
||||||
++parser_data->inside_head;
|
++parser_data->inside_head;
|
||||||
}
|
}
|
||||||
if (util::strieq_l("link", name)) {
|
if (util::strieq("link"_sr, name)) {
|
||||||
auto rel_attr = get_attr(attrs, StringRef::from_lit("rel"));
|
auto rel_attr = get_attr(attrs, "rel"_sr);
|
||||||
auto href_attr = get_attr(attrs, StringRef::from_lit("href"));
|
auto href_attr = get_attr(attrs, "href"_sr);
|
||||||
if (rel_attr.empty() || href_attr.empty()) {
|
if (rel_attr.empty() || href_attr.empty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (util::strieq_l("shortcut icon", rel_attr)) {
|
if (util::strieq("shortcut icon"_sr, rel_attr)) {
|
||||||
add_link(parser_data, href_attr, REQ_OTHERS);
|
add_link(parser_data, href_attr, REQ_OTHERS);
|
||||||
} else if (util::strieq_l("stylesheet", rel_attr)) {
|
} else if (util::strieq("stylesheet"_sr, rel_attr)) {
|
||||||
add_link(parser_data, href_attr, REQ_CSS);
|
add_link(parser_data, href_attr, REQ_CSS);
|
||||||
} else if (util::strieq_l("preload", rel_attr)) {
|
} else if (util::strieq("preload"_sr, rel_attr)) {
|
||||||
auto as_attr = get_attr(attrs, StringRef::from_lit("as"));
|
auto as_attr = get_attr(attrs, "as"_sr);
|
||||||
if (as_attr.empty()) {
|
if (as_attr.empty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
add_link(parser_data, href_attr,
|
add_link(parser_data, href_attr,
|
||||||
get_resource_type_for_preload_as(as_attr));
|
get_resource_type_for_preload_as(as_attr));
|
||||||
}
|
}
|
||||||
} else if (util::strieq_l("img", name)) {
|
} else if (util::strieq("img"_sr, name)) {
|
||||||
auto src_attr = get_attr(attrs, StringRef::from_lit("src"));
|
auto src_attr = get_attr(attrs, "src"_sr);
|
||||||
if (src_attr.empty()) {
|
if (src_attr.empty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
add_link(parser_data, src_attr, REQ_IMG);
|
add_link(parser_data, src_attr, REQ_IMG);
|
||||||
} else if (util::strieq_l("script", name)) {
|
} else if (util::strieq("script"_sr, name)) {
|
||||||
auto src_attr = get_attr(attrs, StringRef::from_lit("src"));
|
auto src_attr = get_attr(attrs, "src"_sr);
|
||||||
if (src_attr.empty()) {
|
if (src_attr.empty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -134,8 +134,8 @@ void start_element_func(void *user_data, const xmlChar *src_name,
|
|||||||
namespace {
|
namespace {
|
||||||
void end_element_func(void *user_data, const xmlChar *name) {
|
void end_element_func(void *user_data, const xmlChar *name) {
|
||||||
auto parser_data = static_cast<ParserData *>(user_data);
|
auto parser_data = static_cast<ParserData *>(user_data);
|
||||||
if (util::strieq_l(
|
if (util::strieq(
|
||||||
"head",
|
"head"_sr,
|
||||||
StringRef{name, strlen(reinterpret_cast<const char *>(name))})) {
|
StringRef{name, strlen(reinterpret_cast<const char *>(name))})) {
|
||||||
--parser_data->inside_head;
|
--parser_data->inside_head;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -78,9 +78,8 @@ namespace nghttp2 {
|
|||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
// TODO could be constexpr
|
// TODO could be constexpr
|
||||||
constexpr auto DEFAULT_HTML = StringRef::from_lit("index.html");
|
constexpr auto DEFAULT_HTML = "index.html"_sr;
|
||||||
constexpr auto NGHTTPD_SERVER =
|
constexpr auto NGHTTPD_SERVER = "nghttpd nghttp2/" NGHTTP2_VERSION ""_sr;
|
||||||
StringRef::from_lit("nghttpd nghttp2/" NGHTTP2_VERSION);
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
@@ -291,9 +290,7 @@ public:
|
|||||||
return ssl;
|
return ssl;
|
||||||
}
|
}
|
||||||
const Config *get_config() const { return config_; }
|
const Config *get_config() const { return config_; }
|
||||||
struct ev_loop *get_loop() const {
|
struct ev_loop *get_loop() const { return loop_; }
|
||||||
return loop_;
|
|
||||||
}
|
|
||||||
int64_t get_next_session_id() {
|
int64_t get_next_session_id() {
|
||||||
auto session_id = next_session_id_;
|
auto session_id = next_session_id_;
|
||||||
if (next_session_id_ == std::numeric_limits<int64_t>::max()) {
|
if (next_session_id_ == std::numeric_limits<int64_t>::max()) {
|
||||||
@@ -585,9 +582,7 @@ Http2Handler::~Http2Handler() {
|
|||||||
|
|
||||||
void Http2Handler::remove_self() { sessions_->remove_handler(this); }
|
void Http2Handler::remove_self() { sessions_->remove_handler(this); }
|
||||||
|
|
||||||
struct ev_loop *Http2Handler::get_loop() const {
|
struct ev_loop *Http2Handler::get_loop() const { return sessions_->get_loop(); }
|
||||||
return sessions_->get_loop();
|
|
||||||
}
|
|
||||||
|
|
||||||
Http2Handler::WriteBuf *Http2Handler::get_wb() { return &wb_; }
|
Http2Handler::WriteBuf *Http2Handler::get_wb() { return &wb_; }
|
||||||
|
|
||||||
@@ -611,10 +606,10 @@ int Http2Handler::fill_wb() {
|
|||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
const uint8_t *data;
|
const uint8_t *data;
|
||||||
auto datalen = nghttp2_session_mem_send(session_, &data);
|
auto datalen = nghttp2_session_mem_send2(session_, &data);
|
||||||
|
|
||||||
if (datalen < 0) {
|
if (datalen < 0) {
|
||||||
std::cerr << "nghttp2_session_mem_send() returned error: "
|
std::cerr << "nghttp2_session_mem_send2() returned error: "
|
||||||
<< nghttp2_strerror(datalen) << std::endl;
|
<< nghttp2_strerror(datalen) << std::endl;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -652,10 +647,10 @@ int Http2Handler::read_clear() {
|
|||||||
util::hexdump(stdout, buf.data(), nread);
|
util::hexdump(stdout, buf.data(), nread);
|
||||||
}
|
}
|
||||||
|
|
||||||
rv = nghttp2_session_mem_recv(session_, buf.data(), nread);
|
rv = nghttp2_session_mem_recv2(session_, buf.data(), nread);
|
||||||
if (rv < 0) {
|
if (rv < 0) {
|
||||||
if (rv != NGHTTP2_ERR_BAD_CLIENT_MAGIC) {
|
if (rv != NGHTTP2_ERR_BAD_CLIENT_MAGIC) {
|
||||||
std::cerr << "nghttp2_session_mem_recv() returned error: "
|
std::cerr << "nghttp2_session_mem_recv2() returned error: "
|
||||||
<< nghttp2_strerror(rv) << std::endl;
|
<< nghttp2_strerror(rv) << std::endl;
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
@@ -729,7 +724,7 @@ int Http2Handler::tls_handshake() {
|
|||||||
std::cerr << "SSL/TLS handshake completed" << std::endl;
|
std::cerr << "SSL/TLS handshake completed" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (verify_npn_result() != 0) {
|
if (verify_alpn_result() != 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -754,6 +749,7 @@ int Http2Handler::read_tls() {
|
|||||||
|
|
||||||
ERR_clear_error();
|
ERR_clear_error();
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
auto rv = SSL_read(ssl_, buf.data(), buf.size());
|
auto rv = SSL_read(ssl_, buf.data(), buf.size());
|
||||||
|
|
||||||
if (rv <= 0) {
|
if (rv <= 0) {
|
||||||
@@ -775,15 +771,20 @@ int Http2Handler::read_tls() {
|
|||||||
util::hexdump(stdout, buf.data(), nread);
|
util::hexdump(stdout, buf.data(), nread);
|
||||||
}
|
}
|
||||||
|
|
||||||
rv = nghttp2_session_mem_recv(session_, buf.data(), nread);
|
rv = nghttp2_session_mem_recv2(session_, buf.data(), nread);
|
||||||
if (rv < 0) {
|
if (rv < 0) {
|
||||||
if (rv != NGHTTP2_ERR_BAD_CLIENT_MAGIC) {
|
if (rv != NGHTTP2_ERR_BAD_CLIENT_MAGIC) {
|
||||||
std::cerr << "nghttp2_session_mem_recv() returned error: "
|
std::cerr << "nghttp2_session_mem_recv2() returned error: "
|
||||||
<< nghttp2_strerror(rv) << std::endl;
|
<< nghttp2_strerror(rv) << std::endl;
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (SSL_pending(ssl_) == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return write_(*this);
|
return write_(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -896,14 +897,11 @@ int Http2Handler::connection_made() {
|
|||||||
return on_write();
|
return on_write();
|
||||||
}
|
}
|
||||||
|
|
||||||
int Http2Handler::verify_npn_result() {
|
int Http2Handler::verify_alpn_result() {
|
||||||
const unsigned char *next_proto = nullptr;
|
const unsigned char *next_proto = nullptr;
|
||||||
unsigned int next_proto_len;
|
unsigned int next_proto_len;
|
||||||
// Check the negotiated protocol in NPN or ALPN
|
// Check the negotiated protocol in ALPN
|
||||||
#ifndef OPENSSL_NO_NEXTPROTONEG
|
SSL_get0_alpn_selected(ssl_, &next_proto, &next_proto_len);
|
||||||
SSL_get0_next_proto_negotiated(ssl_, &next_proto, &next_proto_len);
|
|
||||||
#endif // !OPENSSL_NO_NEXTPROTONEG
|
|
||||||
for (int i = 0; i < 2; ++i) {
|
|
||||||
if (next_proto) {
|
if (next_proto) {
|
||||||
auto proto = StringRef{next_proto, next_proto_len};
|
auto proto = StringRef{next_proto, next_proto_len};
|
||||||
if (sessions_->get_config()->verbose) {
|
if (sessions_->get_config()->verbose) {
|
||||||
@@ -912,14 +910,6 @@ int Http2Handler::verify_npn_result() {
|
|||||||
if (util::check_h2_is_selected(proto)) {
|
if (util::check_h2_is_selected(proto)) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
#if OPENSSL_VERSION_NUMBER >= 0x10002000L
|
|
||||||
SSL_get0_alpn_selected(ssl_, &next_proto, &next_proto_len);
|
|
||||||
#else // OPENSSL_VERSION_NUMBER < 0x10002000L
|
|
||||||
break;
|
|
||||||
#endif // OPENSSL_VERSION_NUMBER < 0x10002000L
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (sessions_->get_config()->verbose) {
|
if (sessions_->get_config()->verbose) {
|
||||||
std::cerr << "Client did not advertise HTTP/2 protocol."
|
std::cerr << "Client did not advertise HTTP/2 protocol."
|
||||||
@@ -932,81 +922,88 @@ int Http2Handler::verify_npn_result() {
|
|||||||
int Http2Handler::submit_file_response(const StringRef &status, Stream *stream,
|
int Http2Handler::submit_file_response(const StringRef &status, Stream *stream,
|
||||||
time_t last_modified, off_t file_length,
|
time_t last_modified, off_t file_length,
|
||||||
const std::string *content_type,
|
const std::string *content_type,
|
||||||
nghttp2_data_provider *data_prd) {
|
nghttp2_data_provider2 *data_prd) {
|
||||||
std::string last_modified_str;
|
std::string last_modified_str;
|
||||||
auto nva = make_array(http2::make_nv_ls_nocopy(":status", status),
|
auto nva = std::to_array({
|
||||||
http2::make_nv_ls_nocopy("server", NGHTTPD_SERVER),
|
http2::make_field(":status"_sr, status),
|
||||||
http2::make_nv_ll("cache-control", "max-age=3600"),
|
http2::make_field("server"_sr, NGHTTPD_SERVER),
|
||||||
http2::make_nv_ls("date", sessions_->get_cached_date()),
|
http2::make_field("cache-control"_sr, "max-age=3600"_sr),
|
||||||
http2::make_nv_ll("", ""), http2::make_nv_ll("", ""),
|
http2::make_field_v("date"_sr, sessions_->get_cached_date()),
|
||||||
http2::make_nv_ll("", ""), http2::make_nv_ll("", ""));
|
{},
|
||||||
|
{},
|
||||||
|
{},
|
||||||
|
{},
|
||||||
|
});
|
||||||
size_t nvlen = 4;
|
size_t nvlen = 4;
|
||||||
if (!get_config()->no_content_length) {
|
if (!get_config()->no_content_length) {
|
||||||
nva[nvlen++] = http2::make_nv_ls_nocopy(
|
nva[nvlen++] = http2::make_field(
|
||||||
"content-length",
|
"content-length"_sr,
|
||||||
util::make_string_ref_uint(stream->balloc, file_length));
|
util::make_string_ref_uint(stream->balloc, file_length));
|
||||||
}
|
}
|
||||||
if (last_modified != 0) {
|
if (last_modified != 0) {
|
||||||
last_modified_str = util::http_date(last_modified);
|
last_modified_str = util::http_date(last_modified);
|
||||||
nva[nvlen++] = http2::make_nv_ls("last-modified", last_modified_str);
|
nva[nvlen++] = http2::make_field_v("last-modified"_sr, last_modified_str);
|
||||||
}
|
}
|
||||||
if (content_type) {
|
if (content_type) {
|
||||||
nva[nvlen++] = http2::make_nv_ls("content-type", *content_type);
|
nva[nvlen++] = http2::make_field_v("content-type"_sr, *content_type);
|
||||||
}
|
}
|
||||||
auto &trailer_names = get_config()->trailer_names;
|
auto &trailer_names = get_config()->trailer_names;
|
||||||
if (!trailer_names.empty()) {
|
if (!trailer_names.empty()) {
|
||||||
nva[nvlen++] = http2::make_nv_ls_nocopy("trailer", trailer_names);
|
nva[nvlen++] = http2::make_field("trailer"_sr, trailer_names);
|
||||||
}
|
}
|
||||||
return nghttp2_submit_response(session_, stream->stream_id, nva.data(), nvlen,
|
return nghttp2_submit_response2(session_, stream->stream_id, nva.data(),
|
||||||
data_prd);
|
nvlen, data_prd);
|
||||||
}
|
}
|
||||||
|
|
||||||
int Http2Handler::submit_response(const StringRef &status, int32_t stream_id,
|
int Http2Handler::submit_response(const StringRef &status, int32_t stream_id,
|
||||||
const HeaderRefs &headers,
|
const HeaderRefs &headers,
|
||||||
nghttp2_data_provider *data_prd) {
|
nghttp2_data_provider2 *data_prd) {
|
||||||
auto nva = std::vector<nghttp2_nv>();
|
auto nva = std::vector<nghttp2_nv>();
|
||||||
nva.reserve(4 + headers.size());
|
nva.reserve(4 + headers.size());
|
||||||
nva.push_back(http2::make_nv_ls_nocopy(":status", status));
|
nva.push_back(http2::make_field(":status"_sr, status));
|
||||||
nva.push_back(http2::make_nv_ls_nocopy("server", NGHTTPD_SERVER));
|
nva.push_back(http2::make_field("server"_sr, NGHTTPD_SERVER));
|
||||||
nva.push_back(http2::make_nv_ls("date", sessions_->get_cached_date()));
|
nva.push_back(http2::make_field_v("date"_sr, sessions_->get_cached_date()));
|
||||||
|
|
||||||
if (data_prd) {
|
if (data_prd) {
|
||||||
auto &trailer_names = get_config()->trailer_names;
|
auto &trailer_names = get_config()->trailer_names;
|
||||||
if (!trailer_names.empty()) {
|
if (!trailer_names.empty()) {
|
||||||
nva.push_back(http2::make_nv_ls_nocopy("trailer", trailer_names));
|
nva.push_back(http2::make_field("trailer"_sr, trailer_names));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto &nv : headers) {
|
for (auto &nv : headers) {
|
||||||
nva.push_back(http2::make_nv_nocopy(nv.name, nv.value, nv.no_index));
|
nva.push_back(
|
||||||
|
http2::make_field(nv.name, nv.value, http2::no_index(nv.no_index)));
|
||||||
}
|
}
|
||||||
int r = nghttp2_submit_response(session_, stream_id, nva.data(), nva.size(),
|
int r = nghttp2_submit_response2(session_, stream_id, nva.data(), nva.size(),
|
||||||
data_prd);
|
data_prd);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Http2Handler::submit_response(const StringRef &status, int32_t stream_id,
|
int Http2Handler::submit_response(const StringRef &status, int32_t stream_id,
|
||||||
nghttp2_data_provider *data_prd) {
|
nghttp2_data_provider2 *data_prd) {
|
||||||
auto nva = make_array(http2::make_nv_ls_nocopy(":status", status),
|
auto nva = std::to_array({
|
||||||
http2::make_nv_ls_nocopy("server", NGHTTPD_SERVER),
|
http2::make_field(":status"_sr, status),
|
||||||
http2::make_nv_ls("date", sessions_->get_cached_date()),
|
http2::make_field("server"_sr, NGHTTPD_SERVER),
|
||||||
http2::make_nv_ll("", ""));
|
http2::make_field_v("date"_sr, sessions_->get_cached_date()),
|
||||||
|
{},
|
||||||
|
});
|
||||||
size_t nvlen = 3;
|
size_t nvlen = 3;
|
||||||
|
|
||||||
if (data_prd) {
|
if (data_prd) {
|
||||||
auto &trailer_names = get_config()->trailer_names;
|
auto &trailer_names = get_config()->trailer_names;
|
||||||
if (!trailer_names.empty()) {
|
if (!trailer_names.empty()) {
|
||||||
nva[nvlen++] = http2::make_nv_ls_nocopy("trailer", trailer_names);
|
nva[nvlen++] = http2::make_field("trailer"_sr, trailer_names);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nghttp2_submit_response(session_, stream_id, nva.data(), nvlen,
|
return nghttp2_submit_response2(session_, stream_id, nva.data(), nvlen,
|
||||||
data_prd);
|
data_prd);
|
||||||
}
|
}
|
||||||
|
|
||||||
int Http2Handler::submit_non_final_response(const std::string &status,
|
int Http2Handler::submit_non_final_response(const std::string &status,
|
||||||
int32_t stream_id) {
|
int32_t stream_id) {
|
||||||
auto nva = make_array(http2::make_nv_ls(":status", status));
|
auto nva = std::to_array({http2::make_field_v(":status"_sr, status)});
|
||||||
return nghttp2_submit_headers(session_, NGHTTP2_FLAG_NONE, stream_id, nullptr,
|
return nghttp2_submit_headers(session_, NGHTTP2_FLAG_NONE, stream_id, nullptr,
|
||||||
nva.data(), nva.size(), nullptr);
|
nva.data(), nva.size(), nullptr);
|
||||||
}
|
}
|
||||||
@@ -1019,13 +1016,12 @@ int Http2Handler::submit_push_promise(Stream *stream,
|
|||||||
authority = stream->header.host;
|
authority = stream->header.host;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto scheme = get_config()->no_tls ? StringRef::from_lit("http")
|
auto scheme = get_config()->no_tls ? "http"_sr : "https"_sr;
|
||||||
: StringRef::from_lit("https");
|
|
||||||
|
|
||||||
auto nva = make_array(http2::make_nv_ll(":method", "GET"),
|
auto nva = std::to_array({http2::make_field(":method"_sr, "GET"_sr),
|
||||||
http2::make_nv_ls_nocopy(":path", push_path),
|
http2::make_field(":path"_sr, push_path),
|
||||||
http2::make_nv_ls_nocopy(":scheme", scheme),
|
http2::make_field(":scheme"_sr, scheme),
|
||||||
http2::make_nv_ls_nocopy(":authority", authority));
|
http2::make_field(":authority"_sr, authority)});
|
||||||
|
|
||||||
auto promised_stream_id = nghttp2_submit_push_promise(
|
auto promised_stream_id = nghttp2_submit_push_promise(
|
||||||
session_, NGHTTP2_FLAG_END_HEADERS, stream->stream_id, nva.data(),
|
session_, NGHTTP2_FLAG_END_HEADERS, stream->stream_id, nva.data(),
|
||||||
@@ -1038,7 +1034,7 @@ int Http2Handler::submit_push_promise(Stream *stream,
|
|||||||
auto promised_stream = std::make_unique<Stream>(this, promised_stream_id);
|
auto promised_stream = std::make_unique<Stream>(this, promised_stream_id);
|
||||||
|
|
||||||
auto &promised_header = promised_stream->header;
|
auto &promised_header = promised_stream->header;
|
||||||
promised_header.method = StringRef::from_lit("GET");
|
promised_header.method = "GET"_sr;
|
||||||
promised_header.path = push_path;
|
promised_header.path = push_path;
|
||||||
promised_header.scheme = scheme;
|
promised_header.scheme = scheme;
|
||||||
promised_header.authority =
|
promised_header.authority =
|
||||||
@@ -1091,8 +1087,9 @@ void Http2Handler::terminate_session(uint32_t error_code) {
|
|||||||
nghttp2_session_terminate_session(session_, error_code);
|
nghttp2_session_terminate_session(session_, error_code);
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t file_read_callback(nghttp2_session *session, int32_t stream_id,
|
nghttp2_ssize file_read_callback(nghttp2_session *session, int32_t stream_id,
|
||||||
uint8_t *buf, size_t length, uint32_t *data_flags,
|
uint8_t *buf, size_t length,
|
||||||
|
uint32_t *data_flags,
|
||||||
nghttp2_data_source *source, void *user_data) {
|
nghttp2_data_source *source, void *user_data) {
|
||||||
int rv;
|
int rv;
|
||||||
auto hd = static_cast<Http2Handler *>(user_data);
|
auto hd = static_cast<Http2Handler *>(user_data);
|
||||||
@@ -1111,7 +1108,8 @@ ssize_t file_read_callback(nghttp2_session *session, int32_t stream_id,
|
|||||||
std::vector<nghttp2_nv> nva;
|
std::vector<nghttp2_nv> nva;
|
||||||
nva.reserve(config->trailer.size());
|
nva.reserve(config->trailer.size());
|
||||||
for (auto &kv : config->trailer) {
|
for (auto &kv : config->trailer) {
|
||||||
nva.push_back(http2::make_nv(kv.name, kv.value, kv.no_index));
|
nva.push_back(http2::make_field_nv(kv.name, kv.value,
|
||||||
|
http2::no_index(kv.no_index)));
|
||||||
}
|
}
|
||||||
rv = nghttp2_submit_trailer(session, stream_id, nva.data(), nva.size());
|
rv = nghttp2_submit_trailer(session, stream_id, nva.data(), nva.size());
|
||||||
if (rv != 0) {
|
if (rv != 0) {
|
||||||
@@ -1142,16 +1140,15 @@ void prepare_status_response(Stream *stream, Http2Handler *hd, int status) {
|
|||||||
|
|
||||||
// we don't set stream->file_ent since we don't want to expire it.
|
// we don't set stream->file_ent since we don't want to expire it.
|
||||||
stream->body_length = file_ent->length;
|
stream->body_length = file_ent->length;
|
||||||
nghttp2_data_provider data_prd;
|
nghttp2_data_provider2 data_prd;
|
||||||
data_prd.source.fd = file_ent->fd;
|
data_prd.source.fd = file_ent->fd;
|
||||||
data_prd.read_callback = file_read_callback;
|
data_prd.read_callback = file_read_callback;
|
||||||
|
|
||||||
HeaderRefs headers;
|
HeaderRefs headers;
|
||||||
headers.reserve(2);
|
headers.reserve(2);
|
||||||
headers.emplace_back(StringRef::from_lit("content-type"),
|
headers.emplace_back("content-type"_sr, "text/html; charset=UTF-8"_sr);
|
||||||
StringRef::from_lit("text/html; charset=UTF-8"));
|
|
||||||
headers.emplace_back(
|
headers.emplace_back(
|
||||||
StringRef::from_lit("content-length"),
|
"content-length"_sr,
|
||||||
util::make_string_ref_uint(stream->balloc, file_ent->length));
|
util::make_string_ref_uint(stream->balloc, file_ent->length));
|
||||||
hd->submit_response(StringRef{status_page->status}, stream->stream_id,
|
hd->submit_response(StringRef{status_page->status}, stream->stream_id,
|
||||||
headers, &data_prd);
|
headers, &data_prd);
|
||||||
@@ -1170,20 +1167,18 @@ void prepare_echo_response(Stream *stream, Http2Handler *hd) {
|
|||||||
hd->submit_rst_stream(stream, NGHTTP2_INTERNAL_ERROR);
|
hd->submit_rst_stream(stream, NGHTTP2_INTERNAL_ERROR);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
nghttp2_data_provider data_prd;
|
nghttp2_data_provider2 data_prd;
|
||||||
data_prd.source.fd = stream->file_ent->fd;
|
data_prd.source.fd = stream->file_ent->fd;
|
||||||
data_prd.read_callback = file_read_callback;
|
data_prd.read_callback = file_read_callback;
|
||||||
|
|
||||||
HeaderRefs headers;
|
HeaderRefs headers;
|
||||||
headers.emplace_back(StringRef::from_lit("nghttpd-response"),
|
headers.emplace_back("nghttpd-response"_sr, "echo"_sr);
|
||||||
StringRef::from_lit("echo"));
|
|
||||||
if (!hd->get_config()->no_content_length) {
|
if (!hd->get_config()->no_content_length) {
|
||||||
headers.emplace_back(StringRef::from_lit("content-length"),
|
headers.emplace_back("content-length"_sr,
|
||||||
util::make_string_ref_uint(stream->balloc, length));
|
util::make_string_ref_uint(stream->balloc, length));
|
||||||
}
|
}
|
||||||
|
|
||||||
hd->submit_response(StringRef::from_lit("200"), stream->stream_id, headers,
|
hd->submit_response("200"_sr, stream->stream_id, headers, &data_prd);
|
||||||
&data_prd);
|
|
||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
@@ -1217,10 +1212,10 @@ void prepare_redirect_response(Stream *stream, Http2Handler *hd,
|
|||||||
authority = stream->header.host;
|
authority = stream->header.host;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto location = concat_string_ref(
|
auto location =
|
||||||
stream->balloc, scheme, StringRef::from_lit("://"), authority, path);
|
concat_string_ref(stream->balloc, scheme, "://"_sr, authority, path);
|
||||||
|
|
||||||
auto headers = HeaderRefs{{StringRef::from_lit("location"), location}};
|
auto headers = HeaderRefs{{"location"_sr, location}};
|
||||||
|
|
||||||
auto sessions = hd->get_sessions();
|
auto sessions = hd->get_sessions();
|
||||||
auto status_page = sessions->get_server()->get_status_page(status);
|
auto status_page = sessions->get_server()->get_status_page(status);
|
||||||
@@ -1253,8 +1248,8 @@ void prepare_response(Stream *stream, Http2Handler *hd,
|
|||||||
auto query_pos = std::find(std::begin(reqpath), std::end(reqpath), '?');
|
auto query_pos = std::find(std::begin(reqpath), std::end(reqpath), '?');
|
||||||
if (query_pos != std::end(reqpath)) {
|
if (query_pos != std::end(reqpath)) {
|
||||||
// Do not response to this request to allow clients to test timeouts.
|
// Do not response to this request to allow clients to test timeouts.
|
||||||
if (util::streq_l("nghttpd_do_not_respond_to_req=yes",
|
if ("nghttpd_do_not_respond_to_req=yes"_sr ==
|
||||||
StringRef{query_pos, std::end(reqpath)})) {
|
StringRef{query_pos, std::end(reqpath)}) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
raw_path = StringRef{std::begin(reqpath), query_pos};
|
raw_path = StringRef{std::begin(reqpath), query_pos};
|
||||||
@@ -1286,7 +1281,7 @@ void prepare_response(Stream *stream, Http2Handler *hd,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!hd->get_config()->push.empty()) {
|
if (!hd->get_config()->push.empty()) {
|
||||||
auto push_itr = hd->get_config()->push.find(path.str());
|
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::end(hd->get_config()->push)) {
|
||||||
for (auto &push_path : (*push_itr).second) {
|
for (auto &push_path : (*push_itr).second) {
|
||||||
rv = hd->submit_push_promise(stream, StringRef{push_path});
|
rv = hd->submit_push_promise(stream, StringRef{push_path});
|
||||||
@@ -1347,8 +1342,8 @@ void prepare_response(Stream *stream, Http2Handler *hd,
|
|||||||
if (buf.st_mode & S_IFDIR) {
|
if (buf.st_mode & S_IFDIR) {
|
||||||
close(file);
|
close(file);
|
||||||
|
|
||||||
auto reqpath = concat_string_ref(stream->balloc, raw_path,
|
auto reqpath =
|
||||||
StringRef::from_lit("/"), raw_query);
|
concat_string_ref(stream->balloc, raw_path, "/"_sr, raw_query);
|
||||||
|
|
||||||
prepare_redirect_response(stream, hd, reqpath, 301);
|
prepare_redirect_response(stream, hd, reqpath, 301);
|
||||||
|
|
||||||
@@ -1378,28 +1373,27 @@ void prepare_response(Stream *stream, Http2Handler *hd,
|
|||||||
stream->file_ent = file_ent;
|
stream->file_ent = file_ent;
|
||||||
|
|
||||||
if (last_mod_found && file_ent->mtime <= last_mod) {
|
if (last_mod_found && file_ent->mtime <= last_mod) {
|
||||||
hd->submit_response(StringRef::from_lit("304"), stream->stream_id, nullptr);
|
hd->submit_response("304"_sr, stream->stream_id, nullptr);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto method = stream->header.method;
|
auto method = stream->header.method;
|
||||||
if (method == StringRef::from_lit("HEAD")) {
|
if (method == "HEAD"_sr) {
|
||||||
hd->submit_file_response(StringRef::from_lit("200"), stream,
|
hd->submit_file_response("200"_sr, stream, file_ent->mtime,
|
||||||
file_ent->mtime, file_ent->length,
|
file_ent->length, file_ent->content_type, nullptr);
|
||||||
file_ent->content_type, nullptr);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
stream->body_length = file_ent->length;
|
stream->body_length = file_ent->length;
|
||||||
|
|
||||||
nghttp2_data_provider data_prd;
|
nghttp2_data_provider2 data_prd;
|
||||||
|
|
||||||
data_prd.source.fd = file_ent->fd;
|
data_prd.source.fd = file_ent->fd;
|
||||||
data_prd.read_callback = file_read_callback;
|
data_prd.read_callback = file_read_callback;
|
||||||
|
|
||||||
hd->submit_file_response(StringRef::from_lit("200"), stream, file_ent->mtime,
|
hd->submit_file_response("200"_sr, stream, file_ent->mtime, file_ent->length,
|
||||||
file_ent->length, file_ent->content_type, &data_prd);
|
file_ent->content_type, &data_prd);
|
||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
@@ -1433,7 +1427,7 @@ int on_header_callback2(nghttp2_session *session, const nghttp2_frame *frame,
|
|||||||
|
|
||||||
stream->header_buffer_size += namebuf.len + valuebuf.len;
|
stream->header_buffer_size += namebuf.len + valuebuf.len;
|
||||||
|
|
||||||
auto token = http2::lookup_token(namebuf.base, namebuf.len);
|
auto token = http2::lookup_token(StringRef{namebuf.base, namebuf.len});
|
||||||
|
|
||||||
auto &header = stream->header;
|
auto &header = stream->header;
|
||||||
|
|
||||||
@@ -1536,14 +1530,13 @@ int hd_on_frame_recv_callback(nghttp2_session *session,
|
|||||||
|
|
||||||
auto expect100 = stream->header.expect;
|
auto expect100 = stream->header.expect;
|
||||||
|
|
||||||
if (util::strieq_l("100-continue", expect100)) {
|
if (util::strieq("100-continue"_sr, expect100)) {
|
||||||
hd->submit_non_final_response("100", frame->hd.stream_id);
|
hd->submit_non_final_response("100", frame->hd.stream_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto method = stream->header.method;
|
auto method = stream->header.method;
|
||||||
if (hd->get_config()->echo_upload &&
|
if (hd->get_config()->echo_upload &&
|
||||||
(method == StringRef::from_lit("POST") ||
|
(method == "POST"_sr || method == "PUT"_sr)) {
|
||||||
method == StringRef::from_lit("PUT"))) {
|
|
||||||
if (!prepare_upload_temp_store(stream, hd)) {
|
if (!prepare_upload_temp_store(stream, hd)) {
|
||||||
hd->submit_rst_stream(stream, NGHTTP2_INTERNAL_ERROR);
|
hd->submit_rst_stream(stream, NGHTTP2_INTERNAL_ERROR);
|
||||||
return 0;
|
return 0;
|
||||||
@@ -1691,9 +1684,9 @@ int send_data_callback(nghttp2_session *session, nghttp2_frame *frame,
|
|||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
ssize_t select_padding_callback(nghttp2_session *session,
|
nghttp2_ssize select_padding_callback(nghttp2_session *session,
|
||||||
const nghttp2_frame *frame, size_t max_payload,
|
const nghttp2_frame *frame,
|
||||||
void *user_data) {
|
size_t max_payload, void *user_data) {
|
||||||
auto hd = static_cast<Http2Handler *>(user_data);
|
auto hd = static_cast<Http2Handler *>(user_data);
|
||||||
return std::min(max_payload, frame->hd.length + hd->get_config()->padding);
|
return std::min(max_payload, frame->hd.length + hd->get_config()->padding);
|
||||||
}
|
}
|
||||||
@@ -1780,7 +1773,7 @@ void fill_callback(nghttp2_session_callbacks *callbacks, const Config *config) {
|
|||||||
send_data_callback);
|
send_data_callback);
|
||||||
|
|
||||||
if (config->padding) {
|
if (config->padding) {
|
||||||
nghttp2_session_callbacks_set_select_padding_callback(
|
nghttp2_session_callbacks_set_select_padding_callback2(
|
||||||
callbacks, select_padding_callback);
|
callbacks, select_padding_callback);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1996,18 +1989,6 @@ HttpServer::HttpServer(const Config *config) : config_(config) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef OPENSSL_NO_NEXTPROTONEG
|
|
||||||
namespace {
|
|
||||||
int next_proto_cb(SSL *s, const unsigned char **data, unsigned int *len,
|
|
||||||
void *arg) {
|
|
||||||
auto next_proto = static_cast<std::vector<unsigned char> *>(arg);
|
|
||||||
*data = next_proto->data();
|
|
||||||
*len = next_proto->size();
|
|
||||||
return SSL_TLSEXT_ERR_OK;
|
|
||||||
}
|
|
||||||
} // namespace
|
|
||||||
#endif // !OPENSSL_NO_NEXTPROTONEG
|
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
int verify_callback(int preverify_ok, X509_STORE_CTX *ctx) {
|
int verify_callback(int preverify_ok, X509_STORE_CTX *ctx) {
|
||||||
// We don't verify the client certificate. Just request it for the
|
// We don't verify the client certificate. Just request it for the
|
||||||
@@ -2093,7 +2074,6 @@ int start_listen(HttpServer *sv, struct ev_loop *loop, Sessions *sessions,
|
|||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
#if OPENSSL_VERSION_NUMBER >= 0x10002000L
|
|
||||||
namespace {
|
namespace {
|
||||||
int alpn_select_proto_cb(SSL *ssl, const unsigned char **out,
|
int alpn_select_proto_cb(SSL *ssl, const unsigned char **out,
|
||||||
unsigned char *outlen, const unsigned char *in,
|
unsigned char *outlen, const unsigned char *in,
|
||||||
@@ -2115,7 +2095,6 @@ int alpn_select_proto_cb(SSL *ssl, const unsigned char **out,
|
|||||||
return SSL_TLSEXT_ERR_OK;
|
return SSL_TLSEXT_ERR_OK;
|
||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L
|
|
||||||
|
|
||||||
int HttpServer::run() {
|
int HttpServer::run() {
|
||||||
SSL_CTX *ssl_ctx = nullptr;
|
SSL_CTX *ssl_ctx = nullptr;
|
||||||
@@ -2151,7 +2130,8 @@ int HttpServer::run() {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (SSL_CTX_set_cipher_list(ssl_ctx, tls::DEFAULT_CIPHER_LIST) == 0) {
|
if (SSL_CTX_set_cipher_list(ssl_ctx, tls::DEFAULT_CIPHER_LIST.data()) ==
|
||||||
|
0) {
|
||||||
std::cerr << ERR_error_string(ERR_get_error(), nullptr) << std::endl;
|
std::cerr << ERR_error_string(ERR_get_error(), nullptr) << std::endl;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -2161,22 +2141,11 @@ int HttpServer::run() {
|
|||||||
SSL_CTX_set_session_cache_mode(ssl_ctx, SSL_SESS_CACHE_SERVER);
|
SSL_CTX_set_session_cache_mode(ssl_ctx, SSL_SESS_CACHE_SERVER);
|
||||||
|
|
||||||
#ifndef OPENSSL_NO_EC
|
#ifndef OPENSSL_NO_EC
|
||||||
# if !LIBRESSL_LEGACY_API && OPENSSL_VERSION_NUMBER >= 0x10002000L
|
|
||||||
if (SSL_CTX_set1_curves_list(ssl_ctx, "P-256") != 1) {
|
if (SSL_CTX_set1_curves_list(ssl_ctx, "P-256") != 1) {
|
||||||
std::cerr << "SSL_CTX_set1_curves_list failed: "
|
std::cerr << "SSL_CTX_set1_curves_list failed: "
|
||||||
<< ERR_error_string(ERR_get_error(), nullptr);
|
<< ERR_error_string(ERR_get_error(), nullptr);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
# else // !(!LIBRESSL_LEGACY_API && OPENSSL_VERSION_NUMBER >= 0x10002000L)
|
|
||||||
auto ecdh = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
|
|
||||||
if (ecdh == nullptr) {
|
|
||||||
std::cerr << "EC_KEY_new_by_curv_name failed: "
|
|
||||||
<< ERR_error_string(ERR_get_error(), nullptr);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
SSL_CTX_set_tmp_ecdh(ssl_ctx, ecdh);
|
|
||||||
EC_KEY_free(ecdh);
|
|
||||||
# endif // !(!LIBRESSL_LEGACY_API && OPENSSL_VERSION_NUMBER >= 0x10002000L)
|
|
||||||
#endif // OPENSSL_NO_EC
|
#endif // OPENSSL_NO_EC
|
||||||
|
|
||||||
if (!config_->dh_param_file.empty()) {
|
if (!config_->dh_param_file.empty()) {
|
||||||
@@ -2243,13 +2212,17 @@ int HttpServer::run() {
|
|||||||
|
|
||||||
next_proto = util::get_default_alpn();
|
next_proto = util::get_default_alpn();
|
||||||
|
|
||||||
#ifndef OPENSSL_NO_NEXTPROTONEG
|
|
||||||
SSL_CTX_set_next_protos_advertised_cb(ssl_ctx, next_proto_cb, &next_proto);
|
|
||||||
#endif // !OPENSSL_NO_NEXTPROTONEG
|
|
||||||
#if OPENSSL_VERSION_NUMBER >= 0x10002000L
|
|
||||||
// ALPN selection callback
|
// ALPN selection callback
|
||||||
SSL_CTX_set_alpn_select_cb(ssl_ctx, alpn_select_proto_cb, this);
|
SSL_CTX_set_alpn_select_cb(ssl_ctx, alpn_select_proto_cb, this);
|
||||||
#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L
|
|
||||||
|
#if defined(NGHTTP2_OPENSSL_IS_BORINGSSL) && defined(HAVE_LIBBROTLI)
|
||||||
|
if (!SSL_CTX_add_cert_compression_alg(
|
||||||
|
ssl_ctx, nghttp2::tls::CERTIFICATE_COMPRESSION_ALGO_BROTLI,
|
||||||
|
nghttp2::tls::cert_compress, nghttp2::tls::cert_decompress)) {
|
||||||
|
std::cerr << "SSL_CTX_add_cert_compression_alg failed." << std::endl;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
#endif // NGHTTP2_OPENSSL_IS_BORINGSSL && HAVE_LIBBROTLI
|
||||||
}
|
}
|
||||||
|
|
||||||
auto loop = EV_DEFAULT;
|
auto loop = EV_DEFAULT;
|
||||||
@@ -2264,6 +2237,9 @@ int HttpServer::run() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ev_run(loop, 0);
|
ev_run(loop, 0);
|
||||||
|
|
||||||
|
SSL_CTX_free(ssl_ctx);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -41,6 +41,7 @@
|
|||||||
|
|
||||||
#include <ev.h>
|
#include <ev.h>
|
||||||
|
|
||||||
|
#define NGHTTP2_NO_SSIZE_T
|
||||||
#include <nghttp2/nghttp2.h>
|
#include <nghttp2/nghttp2.h>
|
||||||
|
|
||||||
#include "http2.h"
|
#include "http2.h"
|
||||||
@@ -167,19 +168,19 @@ public:
|
|||||||
int on_read();
|
int on_read();
|
||||||
int on_write();
|
int on_write();
|
||||||
int connection_made();
|
int connection_made();
|
||||||
int verify_npn_result();
|
int verify_alpn_result();
|
||||||
|
|
||||||
int submit_file_response(const StringRef &status, Stream *stream,
|
int submit_file_response(const StringRef &status, Stream *stream,
|
||||||
time_t last_modified, off_t file_length,
|
time_t last_modified, off_t file_length,
|
||||||
const std::string *content_type,
|
const std::string *content_type,
|
||||||
nghttp2_data_provider *data_prd);
|
nghttp2_data_provider2 *data_prd);
|
||||||
|
|
||||||
int submit_response(const StringRef &status, int32_t stream_id,
|
int submit_response(const StringRef &status, int32_t stream_id,
|
||||||
nghttp2_data_provider *data_prd);
|
nghttp2_data_provider2 *data_prd);
|
||||||
|
|
||||||
int submit_response(const StringRef &status, int32_t stream_id,
|
int submit_response(const StringRef &status, int32_t stream_id,
|
||||||
const HeaderRefs &headers,
|
const HeaderRefs &headers,
|
||||||
nghttp2_data_provider *data_prd);
|
nghttp2_data_provider2 *data_prd);
|
||||||
|
|
||||||
int submit_non_final_response(const std::string &status, int32_t stream_id);
|
int submit_non_final_response(const std::string &status, int32_t stream_id);
|
||||||
|
|
||||||
@@ -244,8 +245,9 @@ private:
|
|||||||
const Config *config_;
|
const Config *config_;
|
||||||
};
|
};
|
||||||
|
|
||||||
ssize_t file_read_callback(nghttp2_session *session, int32_t stream_id,
|
nghttp2_ssize file_read_callback(nghttp2_session *session, int32_t stream_id,
|
||||||
uint8_t *buf, size_t length, uint32_t *data_flags,
|
uint8_t *buf, size_t length,
|
||||||
|
uint32_t *data_flags,
|
||||||
nghttp2_data_source *source, void *user_data);
|
nghttp2_data_source *source, void *user_data);
|
||||||
|
|
||||||
} // namespace nghttp2
|
} // namespace nghttp2
|
||||||
|
|||||||
@@ -53,6 +53,8 @@ AM_CPPFLAGS = \
|
|||||||
@JANSSON_CFLAGS@ \
|
@JANSSON_CFLAGS@ \
|
||||||
@LIBBPF_CFLAGS@ \
|
@LIBBPF_CFLAGS@ \
|
||||||
@ZLIB_CFLAGS@ \
|
@ZLIB_CFLAGS@ \
|
||||||
|
@LIBBROTLIENC_CFLAGS@ \
|
||||||
|
@LIBBROTLIDEC_CFLAGS@ \
|
||||||
@EXTRA_DEFS@ \
|
@EXTRA_DEFS@ \
|
||||||
@DEFS@
|
@DEFS@
|
||||||
AM_LDFLAGS = @LIBTOOL_LDFLAGS@
|
AM_LDFLAGS = @LIBTOOL_LDFLAGS@
|
||||||
@@ -73,6 +75,8 @@ LDADD = $(top_builddir)/lib/libnghttp2.la \
|
|||||||
@JANSSON_LIBS@ \
|
@JANSSON_LIBS@ \
|
||||||
@LIBBPF_LIBS@ \
|
@LIBBPF_LIBS@ \
|
||||||
@ZLIB_LIBS@ \
|
@ZLIB_LIBS@ \
|
||||||
|
@LIBBROTLIENC_LIBS@ \
|
||||||
|
@LIBBROTLIDEC_LIBS@ \
|
||||||
@APPLDFLAGS@
|
@APPLDFLAGS@
|
||||||
|
|
||||||
if ENABLE_APP
|
if ENABLE_APP
|
||||||
@@ -203,7 +207,6 @@ libnghttpx_a_CPPFLAGS += -I${top_srcdir}/third-party/neverbleed
|
|||||||
nghttpx_LDADD += ${top_builddir}/third-party/libneverbleed.la
|
nghttpx_LDADD += ${top_builddir}/third-party/libneverbleed.la
|
||||||
endif # HAVE_NEVERBLEED
|
endif # HAVE_NEVERBLEED
|
||||||
|
|
||||||
if HAVE_CUNIT
|
|
||||||
check_PROGRAMS += nghttpx-unittest
|
check_PROGRAMS += nghttpx-unittest
|
||||||
nghttpx_unittest_SOURCES = shrpx-unittest.cc \
|
nghttpx_unittest_SOURCES = shrpx-unittest.cc \
|
||||||
shrpx_tls_test.cc shrpx_tls_test.h \
|
shrpx_tls_test.cc shrpx_tls_test.h \
|
||||||
@@ -219,10 +222,13 @@ nghttpx_unittest_SOURCES = shrpx-unittest.cc \
|
|||||||
buffer_test.cc buffer_test.h \
|
buffer_test.cc buffer_test.h \
|
||||||
memchunk_test.cc memchunk_test.h \
|
memchunk_test.cc memchunk_test.h \
|
||||||
template_test.cc template_test.h \
|
template_test.cc template_test.h \
|
||||||
base64_test.cc base64_test.h
|
base64_test.cc base64_test.h \
|
||||||
|
$(top_srcdir)/tests/munit/munit.c $(top_srcdir)/tests/munit/munit.h \
|
||||||
|
$(top_srcdir)/tests/munit/munitxx.h
|
||||||
nghttpx_unittest_CPPFLAGS = ${AM_CPPFLAGS} \
|
nghttpx_unittest_CPPFLAGS = ${AM_CPPFLAGS} \
|
||||||
|
-I$(top_srcdir)/tests/munit \
|
||||||
-DNGHTTP2_SRC_DIR=\"$(top_srcdir)/src\"
|
-DNGHTTP2_SRC_DIR=\"$(top_srcdir)/src\"
|
||||||
nghttpx_unittest_LDADD = libnghttpx.a ${LDADD} @CUNIT_LIBS@ @TESTLDADD@
|
nghttpx_unittest_LDADD = libnghttpx.a ${LDADD} @TESTLDADD@
|
||||||
|
|
||||||
if HAVE_MRUBY
|
if HAVE_MRUBY
|
||||||
nghttpx_unittest_CPPFLAGS += \
|
nghttpx_unittest_CPPFLAGS += \
|
||||||
@@ -237,7 +243,6 @@ nghttpx_unittest_LDADD += ${top_builddir}/third-party/libneverbleed.la
|
|||||||
endif # HAVE_NEVERBLEED
|
endif # HAVE_NEVERBLEED
|
||||||
|
|
||||||
TESTS += nghttpx-unittest
|
TESTS += nghttpx-unittest
|
||||||
endif # HAVE_CUNIT
|
|
||||||
|
|
||||||
endif # ENABLE_APP
|
endif # ENABLE_APP
|
||||||
|
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user