mirror of
https://github.com/nghttp2/nghttp2.git
synced 2025-12-06 18:18:52 +08:00
Compare commits
519 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 | ||
|
|
6f41cc7271 | ||
|
|
9b781ca734 | ||
|
|
aa0973caf5 | ||
|
|
72b4af6143 | ||
|
|
d40829b133 | ||
|
|
939506b68b | ||
|
|
e62ef924fb | ||
|
|
8bad736d48 | ||
|
|
e761014ca5 | ||
|
|
e6ca4ff173 | ||
|
|
62d58bdabc | ||
|
|
775e4f1bad | ||
|
|
e37fe5543f | ||
|
|
d54750b365 | ||
|
|
8ebe7b10fc | ||
|
|
5c1b0f261e | ||
|
|
0866ceffc7 | ||
|
|
3c6f94258f | ||
|
|
959a55f95f | ||
|
|
7d0d8775c9 | ||
|
|
52cb8c35c8 | ||
|
|
d19bc4bb67 | ||
|
|
1ee16fdeca | ||
|
|
b809beacab | ||
|
|
8cafb048be | ||
|
|
627b2408e5 | ||
|
|
0d36a2a050 | ||
|
|
06da18089f | ||
|
|
19697bd44a | ||
|
|
2e6c8ddd15 | ||
|
|
b7f9853968 | ||
|
|
80d05fe917 | ||
|
|
08c472230a | ||
|
|
47ecf35737 | ||
|
|
b48355b67e | ||
|
|
0f768bdaab | ||
|
|
05f93ca729 | ||
|
|
d70f0013d6 | ||
|
|
d5cb882e62 | ||
|
|
2a382a2ce9 | ||
|
|
c13b08f861 | ||
|
|
298f71ce4e | ||
|
|
4114507587 | ||
|
|
060d0ac455 | ||
|
|
9a3c345f60 | ||
|
|
98eb01aa3f | ||
|
|
de47400a48 | ||
|
|
871cf8e5a2 | ||
|
|
6ace578e5b | ||
|
|
7273ec17d3 | ||
|
|
07b69bb06f | ||
|
|
98df5b59e5 | ||
|
|
cdfb517528 | ||
|
|
b16d4e951e | ||
|
|
feb5ff560a | ||
|
|
ce385d3f55 | ||
|
|
82fc1163c6 | ||
|
|
79d2b7f931 | ||
|
|
4c1f1b0efc | ||
|
|
989d69be01 | ||
|
|
2143f46f45 | ||
|
|
5bbe86a713 | ||
|
|
3cc152a9a5 | ||
|
|
693372b695 | ||
|
|
43e6a01189 | ||
|
|
9dc39859fc | ||
|
|
5b350acc4c | ||
|
|
42140d3ade | ||
|
|
dfa2a59f99 | ||
|
|
5c11ad80c0 | ||
|
|
ee4de34a42 | ||
|
|
892a6162ab | ||
|
|
811b3554a7 | ||
|
|
e7f5940655 | ||
|
|
e4ad2921e5 | ||
|
|
7872401f73 | ||
|
|
2277f7cc68 | ||
|
|
2c955ab76b | ||
|
|
9fc1f85102 | ||
|
|
2571f78ce7 |
@@ -3,10 +3,30 @@ Language: Cpp
|
||||
AccessModifierOffset: -2
|
||||
AlignAfterOpenBracket: Align
|
||||
AlignArrayOfStructures: None
|
||||
AlignConsecutiveMacros: None
|
||||
AlignConsecutiveAssignments: None
|
||||
AlignConsecutiveBitFields: None
|
||||
AlignConsecutiveDeclarations: None
|
||||
AlignConsecutiveAssignments:
|
||||
Enabled: false
|
||||
AcrossEmptyLines: false
|
||||
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
|
||||
AlignOperands: Align
|
||||
AlignTrailingComments: true
|
||||
@@ -47,7 +67,7 @@ BraceWrapping:
|
||||
SplitEmptyRecord: true
|
||||
SplitEmptyNamespace: true
|
||||
BreakBeforeBinaryOperators: None
|
||||
BreakBeforeConceptDeclarations: true
|
||||
BreakBeforeConceptDeclarations: Always
|
||||
BreakBeforeBraces: Attach
|
||||
BreakBeforeInheritanceComma: false
|
||||
BreakInheritanceList: BeforeColon
|
||||
@@ -102,9 +122,10 @@ IndentCaseBlocks: false
|
||||
IndentGotoLabels: true
|
||||
IndentPPDirectives: AfterHash
|
||||
IndentExternBlock: AfterExternBlock
|
||||
IndentRequires: false
|
||||
IndentRequiresClause: false
|
||||
IndentWidth: 2
|
||||
IndentWrappedFunctionNames: false
|
||||
InsertBraces: false
|
||||
InsertTrailingCommas: None
|
||||
JavaScriptQuotes: Leave
|
||||
JavaScriptWrapImports: true
|
||||
@@ -134,6 +155,7 @@ PPIndentWidth: -1
|
||||
ReferenceAlignment: Pointer
|
||||
ReflowComments: true
|
||||
RemoveBracesLLVM: false
|
||||
RequiresClausePosition: OwnLine
|
||||
SeparateDefinitionBlocks: Leave
|
||||
ShortNamespaceLines: 1
|
||||
SortIncludes: Never
|
||||
@@ -155,6 +177,8 @@ SpaceBeforeParensOptions:
|
||||
AfterFunctionDeclarationName: false
|
||||
AfterIfMacros: true
|
||||
AfterOverloadedOperator: false
|
||||
AfterRequiresInClause: false
|
||||
AfterRequiresInExpression: false
|
||||
BeforeNonEmptyParentheses: false
|
||||
SpaceAroundPointerQualifiers: Default
|
||||
SpaceBeforeRangeBasedForLoopColon: true
|
||||
|
||||
10
.github/dependabot.yml
vendored
Normal file
10
.github/dependabot.yml
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: "github-actions"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
- package-ecosystem: "gomod"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
390
.github/workflows/build.yml
vendored
390
.github/workflows/build.yml
vendored
@@ -5,75 +5,87 @@ on: [push, pull_request]
|
||||
permissions: read-all
|
||||
|
||||
env:
|
||||
LIBBPF_VERSION: v1.2.0
|
||||
OPENSSL1_VERSION: 1_1_1u+quic
|
||||
OPENSSL3_VERSION: 3.1.0+quic
|
||||
BORINGSSL_VERSION: b0341041b03ea71d8371a9692aedae263fc06ee9
|
||||
NGHTTP3_VERSION: v0.12.0
|
||||
NGTCP2_VERSION: v0.16.0
|
||||
LIBBPF_VERSION: v1.3.0
|
||||
OPENSSL1_VERSION: 1_1_1w+quic
|
||||
OPENSSL3_VERSION: 3.1.5+quic
|
||||
BORINGSSL_VERSION: 6ab7c1482bf4cdc91c87bc512aaf68ffb18975ec
|
||||
AWSLC_VERSION: v1.26.0
|
||||
NGHTTP3_VERSION: v1.3.0
|
||||
NGTCP2_VERSION: v1.5.0
|
||||
|
||||
jobs:
|
||||
build-cache:
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-22.04, macos-11]
|
||||
os: [ubuntu-22.04, macos-13, macos-14]
|
||||
|
||||
runs-on: ${{ matrix.os }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
- name: Restore libbpf cache
|
||||
id: cache-libbpf
|
||||
uses: actions/cache@v3
|
||||
uses: actions/cache@v4
|
||||
if: runner.os == 'Linux'
|
||||
with:
|
||||
path: libbpf/build
|
||||
key: ${{ runner.os }}-libbpf-${{ env.LIBBPF_VERSION }}
|
||||
key: ${{ matrix.os }}-libbpf-${{ env.LIBBPF_VERSION }}
|
||||
- name: Restore OpenSSL v1.1.1 cache
|
||||
id: cache-openssl1
|
||||
uses: actions/cache@v3
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: openssl1/build
|
||||
key: ${{ runner.os }}-openssl-${{ env.OPENSSL1_VERSION }}
|
||||
key: ${{ matrix.os }}-openssl-${{ env.OPENSSL1_VERSION }}
|
||||
- name: Restore OpenSSL v3.x cache
|
||||
id: cache-openssl3
|
||||
uses: actions/cache@v3
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: openssl3/build
|
||||
key: ${{ runner.os }}-openssl-${{ env.OPENSSL3_VERSION }}
|
||||
key: ${{ matrix.os }}-openssl-${{ env.OPENSSL3_VERSION }}
|
||||
- name: Restore BoringSSL cache
|
||||
id: cache-boringssl
|
||||
uses: actions/cache@v3
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
boringssl/build/crypto/libcrypto.a
|
||||
boringssl/build/ssl/libssl.a
|
||||
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
|
||||
id: cache-nghttp3
|
||||
uses: actions/cache@v3
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
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
|
||||
id: cache-ngtcp2-openssl1
|
||||
uses: actions/cache@v3
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
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
|
||||
id: cache-ngtcp2-openssl3
|
||||
uses: actions/cache@v3
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
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
|
||||
if: |
|
||||
(steps.cache-libbpf.outputs.cache-hit != 'true' && runner.os == 'Linux') ||
|
||||
steps.cache-openssl1.outputs.cache-hit != 'true' ||
|
||||
steps.cache-openssl3.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-ngtcp2-openssl1.outputs.cache-hit != 'true' ||
|
||||
steps.cache-ngtcp2-openssl3.outputs.cache-hit != 'true'
|
||||
@@ -82,9 +94,10 @@ jobs:
|
||||
- name: Linux setup
|
||||
if: runner.os == 'Linux' && steps.settings.outputs.needs-build == 'true'
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install \
|
||||
g++-12 \
|
||||
clang-14 \
|
||||
clang-15 \
|
||||
autoconf \
|
||||
automake \
|
||||
autotools-dev \
|
||||
@@ -104,13 +117,13 @@ jobs:
|
||||
- name: Build libbpf
|
||||
if: steps.cache-libbpf.outputs.cache-hit != 'true' && runner.os == 'Linux'
|
||||
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
|
||||
make -C src install PREFIX=$PWD/build
|
||||
- name: Build quictls/openssl v1.1.1
|
||||
if: steps.cache-openssl1.outputs.cache-hit != 'true'
|
||||
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
|
||||
./config --prefix=$PWD/build
|
||||
make -j"$(nproc 2> /dev/null || sysctl -n hw.ncpu)"
|
||||
@@ -118,7 +131,7 @@ jobs:
|
||||
- name: Build quictls/openssl v3.x
|
||||
if: steps.cache-openssl3.outputs.cache-hit != 'true'
|
||||
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
|
||||
./config enable-ktls --prefix=$PWD/build --libdir=$PWD/build/lib
|
||||
make -j"$(nproc 2> /dev/null || sysctl -n hw.ncpu)"
|
||||
@@ -126,26 +139,36 @@ jobs:
|
||||
- name: Build BoringSSL
|
||||
if: steps.cache-boringssl.outputs.cache-hit != 'true'
|
||||
run: |
|
||||
git clone https://boringssl.googlesource.com/boringssl
|
||||
mkdir 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 }}
|
||||
mkdir build
|
||||
cd build
|
||||
cmake -DCMAKE_POSITION_INDEPENDENT_CODE=ON ..
|
||||
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
|
||||
if: steps.cache-nghttp3.outputs.cache-hit != 'true'
|
||||
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
|
||||
autoreconf -i
|
||||
./configure --prefix=$PWD/build --enable-lib-only
|
||||
make -j"$(nproc 2> /dev/null || sysctl -n hw.ncpu)" check
|
||||
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'
|
||||
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
|
||||
autoreconf -i
|
||||
./configure --prefix=$PWD/build --enable-lib-only \
|
||||
@@ -155,16 +178,16 @@ jobs:
|
||||
--with-boringssl
|
||||
make -j"$(nproc 2> /dev/null || sysctl -n hw.ncpu)" check
|
||||
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'
|
||||
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
|
||||
autoreconf -i
|
||||
./configure --prefix=$PWD/build --enable-lib-only \
|
||||
PKG_CONFIG_PATH="../openssl3/build/lib/pkgconfig" \
|
||||
BORINGSSL_CFLAGS="-I$PWD/../boringssl/include/" \
|
||||
BORINGSSL_LIBS="-L$PWD/../boringssl/build/ssl -lssl -L$PWD/../boringssl/build/crypto -lcrypto" \
|
||||
BORINGSSL_CFLAGS="-I$PWD/../aws-lc/include/" \
|
||||
BORINGSSL_LIBS="-L$PWD/../aws-lc/build/ssl -lssl -L$PWD/../aws-lc/build/crypto -lcrypto" \
|
||||
--with-boringssl
|
||||
make -j"$(nproc 2> /dev/null || sysctl -n hw.ncpu)" check
|
||||
make install
|
||||
@@ -175,45 +198,71 @@ jobs:
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-22.04, macos-11]
|
||||
os: [ubuntu-22.04, macos-13, macos-14]
|
||||
compiler: [gcc, clang]
|
||||
buildtool: [autotools, cmake]
|
||||
http3: [http3, no-http3]
|
||||
openssl: [openssl1, openssl3, boringssl]
|
||||
openssl: [openssl1, openssl3, boringssl, awslc]
|
||||
exclude:
|
||||
- os: macos-11
|
||||
- os: macos-13
|
||||
openssl: openssl3
|
||||
- os: macos-14
|
||||
openssl: openssl3
|
||||
- http3: no-http3
|
||||
openssl: openssl3
|
||||
- os: macos-11
|
||||
- os: macos-13
|
||||
compiler: gcc
|
||||
- os: macos-14
|
||||
compiler: gcc
|
||||
- # disable macos cmake because of include path issue
|
||||
os: macos-11
|
||||
os: macos-13
|
||||
buildtool: cmake
|
||||
- os: macos-11
|
||||
- # 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
|
||||
buildtool: cmake
|
||||
- openssl: boringssl
|
||||
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 }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
- name: Linux setup
|
||||
if: runner.os == 'Linux'
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install \
|
||||
g++-12 \
|
||||
clang-14 \
|
||||
clang-15 \
|
||||
autoconf \
|
||||
automake \
|
||||
autotools-dev \
|
||||
libtool \
|
||||
pkg-config \
|
||||
zlib1g-dev \
|
||||
libcunit1-dev \
|
||||
libssl-dev \
|
||||
libxml2-dev \
|
||||
libev-dev \
|
||||
@@ -222,10 +271,17 @@ jobs:
|
||||
libjemalloc-dev \
|
||||
libc-ares-dev \
|
||||
libelf-dev \
|
||||
libbrotli-dev \
|
||||
cmake \
|
||||
cmake-data
|
||||
echo 'CPPFLAGS=-fsanitize=address,undefined -fno-sanitize-recover=undefined -g' >> $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
|
||||
if: runner.os == 'macOS'
|
||||
run: |
|
||||
@@ -233,8 +289,8 @@ jobs:
|
||||
libev \
|
||||
libevent \
|
||||
c-ares \
|
||||
cunit \
|
||||
libressl \
|
||||
brotli \
|
||||
autoconf \
|
||||
automake \
|
||||
pkg-config \
|
||||
@@ -243,8 +299,8 @@ jobs:
|
||||
- name: Setup clang (Linux)
|
||||
if: runner.os == 'Linux' && matrix.compiler == 'clang'
|
||||
run: |
|
||||
echo 'CC=clang-14' >> $GITHUB_ENV
|
||||
echo 'CXX=clang++-14' >> $GITHUB_ENV
|
||||
echo 'CC=clang-15' >> $GITHUB_ENV
|
||||
echo 'CXX=clang++-15' >> $GITHUB_ENV
|
||||
- name: Setup clang (MacOS)
|
||||
if: runner.os == 'macOS' && matrix.compiler == 'clang'
|
||||
run: |
|
||||
@@ -255,17 +311,19 @@ jobs:
|
||||
run: |
|
||||
echo 'CC=gcc-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)
|
||||
if: runner.os == 'macOS' && matrix.compiler == 'gcc'
|
||||
run: |
|
||||
echo 'CC=gcc' >> $GITHUB_ENV
|
||||
echo 'CXX=g++' >> $GITHUB_ENV
|
||||
- name: Restore libbpf cache
|
||||
uses: actions/cache/restore@v3
|
||||
uses: actions/cache/restore@v4
|
||||
if: matrix.http3 == 'http3' && matrix.compiler == 'clang' && runner.os == 'Linux'
|
||||
with:
|
||||
path: libbpf/build
|
||||
key: ${{ runner.os }}-libbpf-${{ env.LIBBPF_VERSION }}
|
||||
key: ${{ matrix.os }}-libbpf-${{ env.LIBBPF_VERSION }}
|
||||
fail-on-cache-miss: true
|
||||
- name: Set libbpf variables
|
||||
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_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
|
||||
uses: actions/cache/restore@v3
|
||||
if: matrix.http3 == 'http3' && matrix.openssl == 'openssl1'
|
||||
uses: actions/cache/restore@v4
|
||||
if: matrix.openssl == 'openssl1'
|
||||
with:
|
||||
path: openssl1/build
|
||||
key: ${{ runner.os }}-openssl-${{ env.OPENSSL1_VERSION }}
|
||||
key: ${{ matrix.os }}-openssl-${{ env.OPENSSL1_VERSION }}
|
||||
fail-on-cache-miss: true
|
||||
- name: Restore quictls/openssl v3.x cache
|
||||
uses: actions/cache/restore@v3
|
||||
if: matrix.http3 == 'http3' && matrix.openssl == 'openssl3'
|
||||
uses: actions/cache/restore@v4
|
||||
if: matrix.openssl == 'openssl3'
|
||||
with:
|
||||
path: openssl3/build
|
||||
key: ${{ runner.os }}-openssl-${{ env.OPENSSL3_VERSION }}
|
||||
key: ${{ matrix.os }}-openssl-${{ env.OPENSSL3_VERSION }}
|
||||
fail-on-cache-miss: true
|
||||
- name: Restore BoringSSL cache
|
||||
uses: actions/cache/restore@v3
|
||||
uses: actions/cache/restore@v4
|
||||
if: matrix.openssl == 'boringssl'
|
||||
with:
|
||||
path: |
|
||||
boringssl/build/crypto/libcrypto.a
|
||||
boringssl/build/ssl/libssl.a
|
||||
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
|
||||
- name: Set BoringSSL variables
|
||||
if: matrix.openssl == 'boringssl'
|
||||
run: |
|
||||
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_LIBS="-L$PWD/build/ssl -lssl -L$PWD/build/crypto -lcrypto -pthread"
|
||||
EXTRA_AUTOTOOLS_OPTS="$EXTRA_AUTOTOOLS_OPTS --without-neverbleed --without-jemalloc"
|
||||
@@ -316,26 +406,34 @@ jobs:
|
||||
echo 'BORINGSSL_LIBS='"$OPENSSL_LIBS" >> $GITHUB_ENV
|
||||
echo 'EXTRA_AUTOTOOLS_OPTS='"$EXTRA_AUTOTOOLS_OPTS" >> $GITHUB_ENV
|
||||
- name: Restore nghttp3 cache
|
||||
uses: actions/cache/restore@v3
|
||||
uses: actions/cache/restore@v4
|
||||
if: matrix.http3 == 'http3'
|
||||
with:
|
||||
path: nghttp3/build
|
||||
key: ${{ runner.os }}-nghttp3-${{ env.NGHTTP3_VERSION }}
|
||||
key: ${{ matrix.os }}-nghttp3-${{ env.NGHTTP3_VERSION }}
|
||||
fail-on-cache-miss: true
|
||||
- name: Restore ngtcp2 + quictls/openssl v1.1.1 cache
|
||||
uses: actions/cache/restore@v3
|
||||
- name: Restore ngtcp2 + quictls/openssl v1.1.1 cache + BoringSSL
|
||||
uses: actions/cache/restore@v4
|
||||
if: matrix.http3 == 'http3' && (matrix.openssl == 'openssl1' || matrix.openssl == 'boringssl')
|
||||
with:
|
||||
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
|
||||
- name: Restore ngtcp2 + quictls/openssl v3.x cache
|
||||
uses: actions/cache/restore@v3
|
||||
if: matrix.http3 == 'http3' && matrix.openssl == 'openssl3'
|
||||
- name: Restore ngtcp2 + quictls/openssl v3.x cache + aws-lc
|
||||
uses: actions/cache/restore@v4
|
||||
if: matrix.http3 == 'http3' && (matrix.openssl == 'openssl3' || matrix.openssl == 'awslc')
|
||||
with:
|
||||
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
|
||||
- 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
|
||||
if: matrix.http3 == 'http3'
|
||||
run: |
|
||||
@@ -348,63 +446,69 @@ jobs:
|
||||
echo 'LDFLAGS='"$LDFLAGS" >> $GITHUB_ENV
|
||||
echo 'EXTRA_AUTOTOOLS_OPTS='"$EXTRA_AUTOTOOLS_OPTS" >> $GITHUB_ENV
|
||||
echo 'EXTRA_CMAKE_OPTS='"$EXTRA_CMAKE_OPTS" >> $GITHUB_ENV
|
||||
- name: Setup git submodules
|
||||
run: |
|
||||
git submodule update --init
|
||||
- name: Configure autotools
|
||||
run: |
|
||||
autoreconf -i
|
||||
./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)
|
||||
if: matrix.buildtool == 'cmake' && runner.os == 'Linux'
|
||||
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
|
||||
cd $NGHTTP2_BUILD_DIR
|
||||
|
||||
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)
|
||||
if: matrix.buildtool == 'cmake' && runner.os == 'macOS'
|
||||
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.
|
||||
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)
|
||||
if: matrix.buildtool == 'autotools' && runner.os == 'Linux'
|
||||
run: |
|
||||
make -j"$(nproc)" distcheck \
|
||||
DISTCHECK_CONFIGURE_FLAGS="--with-mruby --with-neverbleed --with-libev --enable-werror $EXTRA_AUTOTOOLS_OPTS CPPFLAGS=\"$CPPFLAGS\" LDFLAGS=\"$LDFLAGS\""
|
||||
cd $NGHTTP2_BUILD_DIR
|
||||
|
||||
./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)
|
||||
if: matrix.buildtool == 'autotools' && runner.os == 'macOS'
|
||||
run: |
|
||||
make -j"$(sysctl -n hw.ncpu)" distcheck \
|
||||
DISTCHECK_CONFIGURE_FLAGS="--with-mruby --with-libev --enable-werror $EXTRA_AUTOTOOLS_OPTS CPPFLAGS=\"$CPPFLAGS\" LDFLAGS=\"$LDFLAGS\""
|
||||
cd $NGHTTP2_BUILD_DIR
|
||||
|
||||
./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
|
||||
if: matrix.buildtool == 'cmake'
|
||||
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)" check
|
||||
- uses: actions/setup-go@v3
|
||||
if: matrix.buildtool == 'cmake'
|
||||
- uses: actions/setup-go@v5
|
||||
if: matrix.buildtool != 'distcheck'
|
||||
with:
|
||||
go-version: '1.19'
|
||||
go-version-file: go.mod
|
||||
- name: Integration test
|
||||
# Integration tests for nghttpx; autotools erases build
|
||||
# artifacts.
|
||||
if: matrix.buildtool == 'cmake'
|
||||
if: matrix.buildtool != 'distcheck'
|
||||
run: |
|
||||
cd $NGHTTP2_CMAKE_DIR/integration-tests
|
||||
make itprep it
|
||||
cd $NGHTTP2_BUILD_DIR/integration-tests
|
||||
make it
|
||||
|
||||
build-cross:
|
||||
strategy:
|
||||
@@ -417,7 +521,10 @@ jobs:
|
||||
HOST: ${{ matrix.host }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
- name: Linux setup
|
||||
run: |
|
||||
sudo dpkg --add-architecture i386
|
||||
@@ -430,19 +537,11 @@ jobs:
|
||||
libtool \
|
||||
pkg-config \
|
||||
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
|
||||
run: |
|
||||
autoreconf -i && \
|
||||
./configure --enable-werror --enable-lib-only --with-cunit \
|
||||
--host="$HOST" PKG_CONFIG_PATH="$PWD/CUnit-2.1-3/build/lib/pkgconfig"
|
||||
./configure --enable-werror --enable-lib-only --host="$HOST" \
|
||||
CFLAGS="-g -O2 -D_WIN32_WINNT=0x0600" LIBS="-pthread"
|
||||
- name: Build nghttp2
|
||||
run: |
|
||||
make -j$(nproc)
|
||||
@@ -450,6 +549,7 @@ jobs:
|
||||
- name: Run tests
|
||||
if: matrix.host == 'x86_64-w64-mingw32'
|
||||
run: |
|
||||
export WINEPATH=/usr/x86_64-w64-mingw32/lib
|
||||
cd tests
|
||||
wine main.exe
|
||||
|
||||
@@ -466,16 +566,84 @@ jobs:
|
||||
runs-on: windows-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: microsoft/setup-msbuild@v1
|
||||
- run: |
|
||||
vcpkg --triplet=${{ matrix.arch }}-windows install cunit
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
- uses: microsoft/setup-msbuild@v2
|
||||
- name: Configure cmake
|
||||
run: |
|
||||
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 ..
|
||||
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
|
||||
- name: Build nghttp2
|
||||
run: |
|
||||
cmake --build build
|
||||
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:
|
||||
runs-on: ubuntu-latest
|
||||
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
|
||||
uses: google/oss-fuzz/infra/cifuzz/actions/build_fuzzers@master
|
||||
with:
|
||||
@@ -17,7 +24,7 @@ jobs:
|
||||
fuzz-seconds: 600
|
||||
dry-run: false
|
||||
- name: Upload Crash
|
||||
uses: actions/upload-artifact@v1
|
||||
uses: actions/upload-artifact@v4
|
||||
if: failure()
|
||||
with:
|
||||
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*.a
|
||||
|
||||
# generated by "make test" with cmake
|
||||
Testing/
|
||||
|
||||
@@ -54,3 +55,10 @@ _VC_ROOT/
|
||||
.depend.MSVC
|
||||
*.pyd
|
||||
*.egg-info/
|
||||
|
||||
# Build Directories
|
||||
build/
|
||||
|
||||
# IDEs
|
||||
cmake-*
|
||||
.idea/
|
||||
|
||||
3
.gitmodules
vendored
3
.gitmodules
vendored
@@ -5,3 +5,6 @@
|
||||
path = third-party/neverbleed
|
||||
url = https://github.com/tatsuhiro-t/neverbleed.git
|
||||
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
|
||||
Alek Storm
|
||||
Alex Nalivko
|
||||
Alexandr Vlasov
|
||||
Alexandros Konstantinakis-Karmis
|
||||
Alexis La Goutte
|
||||
Alyssa Ross
|
||||
Amir Livneh
|
||||
Amir Pakdel
|
||||
Anders Bakken
|
||||
@@ -28,10 +30,12 @@ Andy Davies
|
||||
Angus Gratton
|
||||
Anna Henningsen
|
||||
Ant Bryan
|
||||
Anthony Alayo
|
||||
Asra Ali
|
||||
Benedikt Christoph Wolters
|
||||
Benjamin Peterson
|
||||
Bernard Spil
|
||||
Bernhard Walle
|
||||
Brendan Heinonen
|
||||
Brian Card
|
||||
Brian Suh
|
||||
@@ -42,6 +46,7 @@ Dave Reisner
|
||||
David Beitey
|
||||
David Korczynski
|
||||
David Weekly
|
||||
Deel
|
||||
Dimitris Apostolou
|
||||
Dmitri Tikhonov
|
||||
Dmitriy Vetutnev
|
||||
@@ -69,6 +74,8 @@ Jay Satiro
|
||||
Jeff 'Raid' Baitis
|
||||
Jianqing Wang
|
||||
Jim Morrison
|
||||
Jiwoo Park
|
||||
Jonas Kvinge
|
||||
Josh Braegger
|
||||
José F. Calcerrada
|
||||
Kamil Dudka
|
||||
@@ -109,6 +116,7 @@ Rudi Heitbaum
|
||||
Ryo Ota
|
||||
Scott Mitchell
|
||||
Sebastiaan Deckers
|
||||
Sergey Fedorov
|
||||
Shelley Vohr
|
||||
Simon Frankenberger
|
||||
Simone Basso
|
||||
@@ -142,6 +150,7 @@ dalf
|
||||
dawg
|
||||
es
|
||||
fangdingjun
|
||||
hrxi
|
||||
jwchoi
|
||||
kumagi
|
||||
lhuang04
|
||||
|
||||
151
CMakeLists.txt
151
CMakeLists.txt
@@ -22,15 +22,15 @@
|
||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
# 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
|
||||
project(nghttp2 VERSION 1.54.0)
|
||||
project(nghttp2 VERSION 1.62.1)
|
||||
|
||||
# See versioning rule:
|
||||
# https://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html
|
||||
set(LT_CURRENT 38)
|
||||
set(LT_REVISION 2)
|
||||
set(LT_AGE 24)
|
||||
set(LT_CURRENT 42)
|
||||
set(LT_REVISION 1)
|
||||
set(LT_AGE 28)
|
||||
|
||||
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH})
|
||||
include(Version)
|
||||
@@ -51,23 +51,29 @@ if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
|
||||
endif()
|
||||
|
||||
include(GNUInstallDirs)
|
||||
include(CMakeDependentOption)
|
||||
|
||||
# For documentation
|
||||
find_package(Python3 COMPONENTS Interpreter)
|
||||
|
||||
# Auto-detection of features that can be toggled
|
||||
find_package(OpenSSL 1.0.1)
|
||||
find_package(Libev 4.11)
|
||||
find_package(Libcares 1.7.5)
|
||||
find_package(ZLIB 1.2.3)
|
||||
find_package(Libngtcp2 0.0.0)
|
||||
find_package(Libngtcp2_crypto_openssl 0.0.0)
|
||||
if(LIBNGTCP2_CRYPTO_OPENSSL_FOUND)
|
||||
set(HAVE_LIBNGTCP2_CRYPTO_OPENSSL 1)
|
||||
if(NOT ENABLE_LIB_ONLY)
|
||||
find_package(Libev 4.11)
|
||||
find_package(Libcares 1.7.5)
|
||||
find_package(ZLIB 1.2.3)
|
||||
find_package(Libbrotlienc 1.0.9)
|
||||
find_package(Libbrotlidec 1.0.9)
|
||||
endif()
|
||||
find_package(Libnghttp3 0.0.0)
|
||||
|
||||
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)
|
||||
set(HAVE_LIBNGTCP2_CRYPTO_QUICTLS 1)
|
||||
endif()
|
||||
find_package(Libnghttp3 1.1.0)
|
||||
if(WITH_LIBBPF)
|
||||
find_package(Libbpf 0.4.0)
|
||||
find_package(Libbpf 0.7.0)
|
||||
if(NOT LIBBPF_FOUND)
|
||||
message(FATAL_ERROR "libbpf was requested (WITH_LIBBPF=1) but not found.")
|
||||
endif()
|
||||
@@ -118,7 +124,7 @@ else()
|
||||
endif()
|
||||
|
||||
include(ExtractValidFlags)
|
||||
foreach(_cxx1x_flag -std=c++14)
|
||||
foreach(_cxx1x_flag -std=c++20)
|
||||
extract_valid_cxx_flags(_cxx1x_flag_supported ${_cxx1x_flag})
|
||||
if(_cxx1x_flag_supported)
|
||||
set(CXX1XCXXFLAGS ${_cxx1x_flag})
|
||||
@@ -162,12 +168,8 @@ endif()
|
||||
# XXX shouldn't ${CMAKE_DL_LIBS} be appended to OPENSSL_LIBRARIES instead of
|
||||
# APP_LIBRARIES if it is really specific to OpenSSL?
|
||||
|
||||
find_package(CUnit 2.1)
|
||||
enable_testing()
|
||||
set(HAVE_CUNIT ${CUNIT_FOUND})
|
||||
if(HAVE_CUNIT)
|
||||
add_custom_target(check COMMAND ${CMAKE_CTEST_COMMAND})
|
||||
endif()
|
||||
add_custom_target(check COMMAND ${CMAKE_CTEST_COMMAND})
|
||||
|
||||
# openssl (for src)
|
||||
include(CheckSymbolExists)
|
||||
@@ -180,9 +182,11 @@ if(OPENSSL_FOUND)
|
||||
if(WIN32)
|
||||
set(CMAKE_REQUIRED_LIBRARIES "${CMAKE_REQUIRED_LIBRARIES}" "ws2_32" "bcrypt")
|
||||
endif()
|
||||
check_symbol_exists(SSL_is_quic "openssl/ssl.h" HAVE_SSL_IS_QUIC)
|
||||
if(NOT HAVE_SSL_IS_QUIC)
|
||||
message(WARNING "OpenSSL in ${OPENSSL_LIBRARIES} does not have SSL_is_quic. HTTP/3 support cannot be enabled")
|
||||
if(ENABLE_HTTP3)
|
||||
check_symbol_exists(SSL_provide_quic_data "openssl/ssl.h" HAVE_SSL_PROVIDE_QUIC_DATA)
|
||||
if(NOT HAVE_SSL_PROVIDE_QUIC_DATA)
|
||||
message(WARNING "OpenSSL in ${OPENSSL_LIBRARIES} does not have SSL_provide_quic_data. HTTP/3 support cannot be enabled")
|
||||
endif()
|
||||
endif()
|
||||
cmake_pop_check_state()
|
||||
else()
|
||||
@@ -219,6 +223,13 @@ endif()
|
||||
# jemalloc
|
||||
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)
|
||||
set(HAVE_LIBBPF ${LIBBPF_FOUND})
|
||||
if(LIBBPF_FOUND)
|
||||
@@ -238,9 +249,9 @@ if(ENABLE_APP AND NOT (ZLIB_FOUND AND OPENSSL_FOUND AND LIBEV_FOUND))
|
||||
message(FATAL_ERROR "Applications were requested (ENABLE_APP=1) but dependencies are not met.")
|
||||
endif()
|
||||
|
||||
# HTTP/3 requires quictls/openssl, libngtcp2, libngtcp2_crypto_openssl
|
||||
# HTTP/3 requires quictls/openssl, libngtcp2, libngtcp2_crypto_quictls
|
||||
# and libnghttp3.
|
||||
if(ENABLE_HTTP3 AND NOT (HAVE_SSL_IS_QUIC AND LIBNGTCP2_FOUND AND LIBNGTCP2_CRYPTO_OPENSSL_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.")
|
||||
endif()
|
||||
|
||||
@@ -273,12 +284,13 @@ check_include_file("inttypes.h" HAVE_INTTYPES_H)
|
||||
check_include_file("limits.h" HAVE_LIMITS_H)
|
||||
check_include_file("netdb.h" HAVE_NETDB_H)
|
||||
check_include_file("netinet/in.h" HAVE_NETINET_IN_H)
|
||||
check_include_file("netinet/ip.h" HAVE_NETINET_IP_H)
|
||||
check_include_file("pwd.h" HAVE_PWD_H)
|
||||
check_include_file("sys/socket.h" HAVE_SYS_SOCKET_H)
|
||||
check_include_file("sys/time.h" HAVE_SYS_TIME_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("windows.h" HAVE_WINDOWS_H)
|
||||
|
||||
include(CheckTypeSize)
|
||||
# Checks for typedefs, structures, and compiler characteristics.
|
||||
@@ -308,16 +320,15 @@ endif()
|
||||
include(CheckStructHasMember)
|
||||
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.
|
||||
include(CheckFunctionExists)
|
||||
check_function_exists(_Exit HAVE__EXIT)
|
||||
check_function_exists(accept4 HAVE_ACCEPT4)
|
||||
check_function_exists(clock_gettime HAVE_CLOCK_GETTIME)
|
||||
check_function_exists(mkostemp HAVE_MKOSTEMP)
|
||||
|
||||
check_symbol_exists(GetTickCount64 sysinfoapi.h HAVE_GETTICKCOUNT64)
|
||||
|
||||
include(CheckSymbolExists)
|
||||
# XXX does this correctly detect initgroups (un)availability on cygwin?
|
||||
check_symbol_exists(initgroups grp.h HAVE_DECL_INITGROUPS)
|
||||
@@ -329,6 +340,8 @@ if(NOT HAVE_DECL_INITGROUPS AND HAVE_UNISTD_H)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
check_symbol_exists(CLOCK_MONOTONIC "time.h" HAVE_DECL_CLOCK_MONOTONIC)
|
||||
|
||||
set(WARNCFLAGS)
|
||||
set(WARNCXXFLAGS)
|
||||
if(CMAKE_C_COMPILER_ID MATCHES "MSVC")
|
||||
@@ -338,65 +351,12 @@ if(CMAKE_C_COMPILER_ID MATCHES "MSVC")
|
||||
endif()
|
||||
else()
|
||||
if(ENABLE_WERROR)
|
||||
extract_valid_c_flags(WARNCFLAGS -Werror)
|
||||
extract_valid_c_flags(WARNCXXFLAGS -Werror)
|
||||
set(WARNCFLAGS "-Werror")
|
||||
set(WARNCXXFLAGS "-Werror")
|
||||
endif()
|
||||
|
||||
# For C compiler
|
||||
extract_valid_c_flags(WARNCFLAGS
|
||||
-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
|
||||
)
|
||||
include(PickyWarningsC)
|
||||
include(PickyWarningsCXX)
|
||||
endif()
|
||||
|
||||
if(ENABLE_STATIC_CRT)
|
||||
@@ -475,9 +435,11 @@ add_subdirectory(lib)
|
||||
add_subdirectory(third-party)
|
||||
add_subdirectory(src)
|
||||
add_subdirectory(examples)
|
||||
add_subdirectory(tests)
|
||||
#add_subdirectory(tests/testdata)
|
||||
add_subdirectory(integration-tests)
|
||||
if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME AND BUILD_TESTING)
|
||||
add_subdirectory(tests)
|
||||
#add_subdirectory(tests/testdata)
|
||||
add_subdirectory(integration-tests)
|
||||
endif()
|
||||
if(ENABLE_DOC)
|
||||
add_subdirectory(doc)
|
||||
endif()
|
||||
@@ -501,19 +463,20 @@ message(STATUS "summary of build options:
|
||||
CXXFLAGS: ${CMAKE_CXX_FLAGS_${_build_type}} ${CMAKE_CXX_FLAGS}
|
||||
WARNCFLAGS: ${WARNCFLAGS}
|
||||
CXX1XCXXFLAGS: ${CXX1XCXXFLAGS}
|
||||
WARNCXXFLAGS: ${WARNCXXFLAGS}
|
||||
Python:
|
||||
Python: ${Python3_EXECUTABLE}
|
||||
Python3_VERSION: ${Python3_VERSION}
|
||||
Test:
|
||||
CUnit: ${HAVE_CUNIT} (LIBS='${CUNIT_LIBRARIES}')
|
||||
Failmalloc: ${ENABLE_FAILMALLOC}
|
||||
Build Test: ${BUILD_TESTING}
|
||||
Libs:
|
||||
OpenSSL: ${HAVE_OPENSSL} (LIBS='${OPENSSL_LIBRARIES}')
|
||||
Libxml2: ${HAVE_LIBXML2} (LIBS='${LIBXML2_LIBRARIES}')
|
||||
Libev: ${HAVE_LIBEV} (LIBS='${LIBEV_LIBRARIES}')
|
||||
Libc-ares: ${HAVE_LIBCARES} (LIBS='${LIBCARES_LIBRARIES}')
|
||||
Libngtcp2: ${HAVE_LIBNGTCP2} (LIBS='${LIBNGTCP2_LIBRARIES}')
|
||||
Libngtcp2_crypto_openssl: ${HAVE_LIBNGTCP2_CRYPTO_OPENSSL} (LIBS='${LIBNGTCP2_CRYPTO_OPENSSL_LIBRARIES}')
|
||||
Libngtcp2_crypto_quictls: ${HAVE_LIBNGTCP2_CRYPTO_QUICTLS} (LIBS='${LIBNGTCP2_CRYPTO_QUICTLS_LIBRARIES}')
|
||||
Libnghttp3: ${HAVE_LIBNGHTTP3} (LIBS='${LIBNGHTTP3_LIBRARIES}')
|
||||
Libbpf: ${HAVE_LIBBPF} (LIBS='${LIBBPF_LIBRARIES}')
|
||||
Libevent(SSL): ${HAVE_LIBEVENT_OPENSSL} (LIBS='${LIBEVENT_OPENSSL_LIBRARIES}')
|
||||
@@ -521,6 +484,8 @@ message(STATUS "summary of build options:
|
||||
Jemalloc: ${HAVE_JEMALLOC} (LIBS='${JEMALLOC_LIBRARIES}')
|
||||
Zlib: ${HAVE_ZLIB} (LIBS='${ZLIB_LIBRARIES}')
|
||||
Systemd: ${HAVE_SYSTEMD} (LIBS='${SYSTEMD_LIBRARIES}')
|
||||
Libbrotlienc: ${HAVE_LIBBROTLIENC} (LIBS='${LIBBROTLIENC_LIBRARIES}')
|
||||
Libbrotlidec: ${HAVE_LIBBROTLIDEC} (LIBS='${LIBBROTLIDEC_LIBRARIES}')
|
||||
Third-party:
|
||||
http-parser: ${ENABLE_THIRD_PARTY}
|
||||
MRuby: ${HAVE_MRUBY}
|
||||
|
||||
@@ -11,11 +11,12 @@ option(ENABLE_EXAMPLES "Build examples"
|
||||
${ENABLE_EXAMPLES_DEFAULT})
|
||||
option(ENABLE_FAILMALLOC "Build failmalloc test program" ON)
|
||||
option(ENABLE_LIB_ONLY "Build libnghttp2 only. This is a short hand for -DENABLE_APP=0 -DENABLE_EXAMPLES=0 -DENABLE_HPACK_TOOLS=0")
|
||||
option(ENABLE_STATIC_LIB "Build libnghttp2 in static mode also")
|
||||
option(ENABLE_SHARED_LIB "Build libnghttp2 as a shared library" ON)
|
||||
option(BUILD_SHARED_LIBS "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_HTTP3 "Enable HTTP/3 support" OFF)
|
||||
option(ENABLE_DOC "Build documentation" ON)
|
||||
cmake_dependent_option(BUILD_TESTING "Enable tests" ON "BUILD_STATIC_LIBS" OFF)
|
||||
|
||||
option(WITH_LIBXML2 "Use libxml2"
|
||||
${WITH_LIBXML2_DEFAULT})
|
||||
|
||||
@@ -35,7 +35,6 @@ EXTRA_DIST = nghttpx.conf.sample proxy.pac.sample android-config android-env \
|
||||
cmake/ExtractValidFlags.cmake \
|
||||
cmake/FindJemalloc.cmake \
|
||||
cmake/FindLibev.cmake \
|
||||
cmake/FindCUnit.cmake \
|
||||
cmake/Version.cmake \
|
||||
cmake/FindLibevent.cmake \
|
||||
cmake/FindJansson.cmake \
|
||||
@@ -44,7 +43,11 @@ EXTRA_DIST = nghttpx.conf.sample proxy.pac.sample android-config android-env \
|
||||
cmake/FindLibbpf.cmake \
|
||||
cmake/FindLibnghttp3.cmake \
|
||||
cmake/FindLibngtcp2.cmake \
|
||||
cmake/FindLibngtcp2_crypto_openssl.cmake
|
||||
cmake/FindLibngtcp2_crypto_quictls.cmake \
|
||||
cmake/FindLibbrotlienc.cmake \
|
||||
cmake/FindLibbrotlidec.cmake \
|
||||
cmake/PickyWarningsC.cmake \
|
||||
cmake/PickyWarningsCXX.cmake
|
||||
|
||||
.PHONY: clang-format
|
||||
|
||||
@@ -55,5 +58,5 @@ clang-format:
|
||||
CLANGFORMAT=`git config --get clangformat.binary`; \
|
||||
test -z $${CLANGFORMAT} && CLANGFORMAT="clang-format"; \
|
||||
$${CLANGFORMAT} -i lib/*.{c,h} lib/includes/nghttp2/*.h \
|
||||
src/*.{c,cc,h} examples/*.{c,cc} \
|
||||
src/*.{c,cc,h} examples/*.c \
|
||||
tests/*.{c,h} bpf/*.c fuzz/*.cc
|
||||
|
||||
119
README.rst
119
README.rst
@@ -29,10 +29,10 @@ Public Test Server
|
||||
The following endpoints are available to try out our nghttp2
|
||||
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
|
||||
``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.
|
||||
|
||||
It also supports HTTP/3.
|
||||
@@ -48,11 +48,6 @@ The following package is required to build the libnghttp2 library:
|
||||
|
||||
* 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:
|
||||
|
||||
* 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
|
||||
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
|
||||
* zlib >= 1.2.3
|
||||
* 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
|
||||
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
|
||||
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
|
||||
<https://github.com/mruby/mruby>`_ is required. We need to build
|
||||
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
|
||||
default. To enable mruby support, use ``--with-mruby`` configure
|
||||
option. Note that at the time of this writing, libmruby-dev and mruby
|
||||
@@ -118,20 +115,21 @@ required:
|
||||
* bison
|
||||
|
||||
nghttpx supports `neverbleed <https://github.com/h2o/neverbleed>`_,
|
||||
privilege separation engine for OpenSSL / LibreSSL. In short, it
|
||||
minimizes the risk of private key leakage when serious bug like
|
||||
Heartbleed is exploited. The neverbleed is disabled by default. To
|
||||
enable it, use ``--with-neverbleed`` configure option.
|
||||
privilege separation engine for OpenSSL. In short, it minimizes the
|
||||
risk of private key leakage when serious bug like Heartbleed is
|
||||
exploited. The neverbleed is disabled by default. To enable it, use
|
||||
``--with-neverbleed`` configure option.
|
||||
|
||||
To enable the experimental HTTP/3 support for h2load and nghttpx, the
|
||||
following libraries are required:
|
||||
|
||||
* `OpenSSL with QUIC support
|
||||
<https://github.com/quictls/openssl/tree/OpenSSL_1_1_1u+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
|
||||
b0341041b03ea71d8371a9692aedae263fc06ee9)
|
||||
* `ngtcp2 <https://github.com/ngtcp2/ngtcp2>`_ 0.16.x
|
||||
* `nghttp3 <https://github.com/ngtcp2/nghttp3>`_ 0.12.x
|
||||
6ab7c1482bf4cdc91c87bc512aaf68ffb18975ec)
|
||||
* `ngtcp2 <https://github.com/ngtcp2/ngtcp2>`_ >= 1.4.0
|
||||
* `nghttp3 <https://github.com/ngtcp2/nghttp3>`_ >= 1.1.0
|
||||
|
||||
Use ``--enable-http3`` configure option to enable HTTP/3 feature for
|
||||
h2load and nghttpx.
|
||||
@@ -146,14 +144,14 @@ Use ``--with-libbpf`` configure option to build eBPF program.
|
||||
libelf-dev is needed to build libbpf.
|
||||
|
||||
For Ubuntu 20.04, you can build libbpf from `the source code
|
||||
<https://github.com/libbpf/libbpf/releases/tag/v1.2.0>`_. nghttpx
|
||||
<https://github.com/libbpf/libbpf/releases/tag/v1.3.0>`_. nghttpx
|
||||
requires eBPF program for reloading its configuration and hot swapping
|
||||
its executable.
|
||||
|
||||
Compiling libnghttp2 C source code requires a C99 compiler. gcc 4.8
|
||||
is known to be adequate. In order to compile the C++ source code, gcc
|
||||
>= 6.0 or clang >= 6.0 is required. C++ source code requires C++14
|
||||
language features.
|
||||
is known to be adequate. In order to compile the C++ source code,
|
||||
C++20 compliant compiler is required. At least g++ >= 1.12 and
|
||||
clang++ >= 1.15 are known to work.
|
||||
|
||||
.. note::
|
||||
|
||||
@@ -207,7 +205,7 @@ required packages:
|
||||
|
||||
sudo apt-get install g++ clang make binutils autoconf automake \
|
||||
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 \
|
||||
libc-ares-dev libjemalloc-dev libsystemd-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.
|
||||
|
||||
Build custom OpenSSL:
|
||||
Build aws-lc:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
$ git clone --depth 1 -b OpenSSL_1_1_1u+quic https://github.com/quictls/openssl
|
||||
$ cd openssl
|
||||
$ ./config --prefix=$PWD/build --openssldir=/etc/ssl
|
||||
$ make -j$(nproc)
|
||||
$ make install_sw
|
||||
$ git clone --depth 1 -b v1.26.0 https://github.com/aws/aws-lc
|
||||
$ cd aws-lc
|
||||
$ cmake -B build -DDISABLE_GO=ON --install-prefix=$PWD/opt
|
||||
$ make -j$(nproc) -C build
|
||||
$ cmake --install build
|
||||
$ cd ..
|
||||
|
||||
Build nghttp3:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
$ git clone --depth 1 -b v0.12.0 https://github.com/ngtcp2/nghttp3
|
||||
$ git clone --depth 1 -b v1.3.0 https://github.com/ngtcp2/nghttp3
|
||||
$ cd nghttp3
|
||||
$ git submodule update --init --depth 1
|
||||
$ autoreconf -i
|
||||
$ ./configure --prefix=$PWD/build --enable-lib-only
|
||||
$ make -j$(nproc)
|
||||
@@ -366,11 +365,13 @@ Build ngtcp2:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
$ git clone --depth 1 -b v0.16.0 https://github.com/ngtcp2/ngtcp2
|
||||
$ git clone --depth 1 -b v1.5.0 https://github.com/ngtcp2/ngtcp2
|
||||
$ cd ngtcp2
|
||||
$ git submodule update --init --depth 1
|
||||
$ autoreconf -i
|
||||
$ ./configure --prefix=$PWD/build --enable-lib-only \
|
||||
PKG_CONFIG_PATH="$PWD/../openssl/build/lib/pkgconfig"
|
||||
$ ./configure --prefix=$PWD/build --enable-lib-only --with-boringssl \
|
||||
BORINGSSL_CFLAGS="-I$PWD/../aws-lc/opt/include" \
|
||||
BORINGSSL_LIBS="-L$PWD/../aws-lc/opt/lib -lssl -lcrypto"
|
||||
$ make -j$(nproc)
|
||||
$ make install
|
||||
$ cd ..
|
||||
@@ -380,7 +381,7 @@ from source:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
$ git clone --depth 1 -b v1.2.0 https://github.com/libbpf/libbpf
|
||||
$ git clone --depth 1 -b v1.3.0 https://github.com/libbpf/libbpf
|
||||
$ cd libbpf
|
||||
$ PREFIX=$PWD/build make -C src install
|
||||
$ cd ..
|
||||
@@ -393,10 +394,10 @@ Build nghttp2:
|
||||
$ cd nghttp2
|
||||
$ git submodule update --init
|
||||
$ autoreconf -i
|
||||
$ ./configure --with-mruby --with-neverbleed --enable-http3 --with-libbpf \
|
||||
CC=clang-14 CXX=clang++-14 \
|
||||
PKG_CONFIG_PATH="$PWD/../openssl/build/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"
|
||||
$ ./configure --with-mruby --enable-http3 --with-libbpf \
|
||||
CC=clang-15 CXX=clang++-15 \
|
||||
PKG_CONFIG_PATH="$PWD/../aws-lc/opt/lib/pkgconfig:$PWD/../nghttp3/build/lib/pkgconfig:$PWD/../ngtcp2/build/lib/pkgconfig:$PWD/../libbpf/build/lib64/pkgconfig" \
|
||||
LDFLAGS="$LDFLAGS -Wl,-rpath,$PWD/../aws-lc/opt/lib -Wl,-rpath,$PWD/../libbpf/build/lib64"
|
||||
$ make -j$(nproc)
|
||||
|
||||
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
|
||||
applications have to send it by themselves. Since v1.0.0, client
|
||||
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
|
||||
relevant code.
|
||||
@@ -539,7 +540,7 @@ nghttp - client
|
||||
+++++++++++++++
|
||||
|
||||
``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
|
||||
output from ``nghttp`` client:
|
||||
@@ -765,8 +766,8 @@ nghttpd - server
|
||||
By default, it uses SSL/TLS connection. Use ``--no-tls`` option to
|
||||
disable it.
|
||||
|
||||
``nghttpd`` only accepts HTTP/2 connections via NPN/ALPN or direct
|
||||
HTTP/2 connections. No HTTP Upgrade is supported.
|
||||
``nghttpd`` only accepts HTTP/2 connections via ALPN or direct HTTP/2
|
||||
connections. No HTTP Upgrade is supported.
|
||||
|
||||
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
|
||||
<https://istlsfastyet.com/#server-performance>`_ in TLS, such as
|
||||
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
|
||||
ticket keys among multiple ``nghttpx`` instances via memcached.
|
||||
|
||||
@@ -974,12 +975,15 @@ threads to avoid saturating a single core on client side.
|
||||
servers.
|
||||
|
||||
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:
|
||||
|
||||
.. 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
|
||||
-----------
|
||||
@@ -1445,23 +1449,10 @@ See `Contribution Guidelines
|
||||
<https://nghttp2.org/documentation/contribute.html>`_ for more
|
||||
details.
|
||||
|
||||
Reporting vulnerability
|
||||
-----------------------
|
||||
Versioning
|
||||
----------
|
||||
|
||||
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.
|
||||
|
||||
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.
|
||||
In general, we follow `Semantic Versioning <http://semver.org/>`_.
|
||||
|
||||
We may release PATCH releases between the regular releases, mainly for
|
||||
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:
|
||||
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
|
||||
|
||||
struct AES_ctx {
|
||||
@@ -57,7 +52,6 @@ struct AES_ctx {
|
||||
in AES. Value=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. */
|
||||
|
||||
/* 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
|
||||
dynamically trading ROM for RAM - This can be useful in (embedded)
|
||||
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] = {
|
||||
0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e,
|
||||
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,
|
||||
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
|
||||
to the state by an XOR function. */
|
||||
static void AddRoundKey(__u8 round, state_t *state, const __u8 *RoundKey) {
|
||||
@@ -428,7 +325,7 @@ struct {
|
||||
__uint(max_entries, 255);
|
||||
__type(key, __u64);
|
||||
__type(value, __u32);
|
||||
} cid_prefix_map SEC(".maps");
|
||||
} worker_id_map SEC(".maps");
|
||||
|
||||
struct {
|
||||
__uint(type, BPF_MAP_TYPE_REUSEPORT_SOCKARRAY);
|
||||
@@ -439,11 +336,18 @@ struct {
|
||||
|
||||
struct {
|
||||
__uint(type, BPF_MAP_TYPE_ARRAY);
|
||||
__uint(max_entries, 3);
|
||||
__uint(max_entries, 1);
|
||||
__type(key, __u32);
|
||||
__type(value, __u64);
|
||||
} 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 {
|
||||
__u8 *dcid;
|
||||
__u32 dcidlen;
|
||||
@@ -451,11 +355,11 @@ typedef struct quic_hd {
|
||||
__u8 type;
|
||||
} quic_hd;
|
||||
|
||||
#define SV_DCIDLEN 20
|
||||
#define SV_DCIDLEN 17
|
||||
#define MAX_DCIDLEN 20
|
||||
#define MIN_DCIDLEN 8
|
||||
#define CID_PREFIXLEN 8
|
||||
#define CID_PREFIX_OFFSET 1
|
||||
#define WORKER_IDLEN 8
|
||||
#define WORKER_ID_OFFSET 1
|
||||
|
||||
enum {
|
||||
NGTCP2_PKT_INITIAL = 0x0,
|
||||
@@ -573,14 +477,39 @@ static __u32 sk_index_from_dcid(const quic_hd *qhd,
|
||||
SEC("sk_reuseport")
|
||||
int select_reuseport(struct sk_reuseport_md *reuse_md) {
|
||||
__u32 sk_index, *psk_index;
|
||||
__u64 *pnum_socks, *pkey;
|
||||
__u32 zero = 0, key_high_idx = 1, key_low_idx = 2;
|
||||
__u64 *pnum_socks;
|
||||
__u32 zero = 0;
|
||||
int rv;
|
||||
quic_hd qhd;
|
||||
__u8 qpktbuf[6 + MAX_DCIDLEN];
|
||||
struct AES_ctx aes_ctx;
|
||||
__u8 key[AES_KEYLEN];
|
||||
__u8 *cid_prefix;
|
||||
struct AES_ctx *aes_ctx;
|
||||
__u8 *worker_id;
|
||||
__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,
|
||||
sizeof(qpktbuf)) != 0) {
|
||||
@@ -592,35 +521,24 @@ int select_reuseport(struct sk_reuseport_md *reuse_md) {
|
||||
return SK_DROP;
|
||||
}
|
||||
|
||||
pkey = bpf_map_lookup_elem(&sk_info, &key_high_idx);
|
||||
if (pkey == NULL) {
|
||||
aes_ctx = bpf_map_lookup_elem(&aes_key, &zero);
|
||||
if (aes_ctx == NULL) {
|
||||
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));
|
||||
if (rv != 0) {
|
||||
return SK_DROP;
|
||||
}
|
||||
|
||||
AES_init_ctx(&aes_ctx, key);
|
||||
|
||||
switch (qhd.type) {
|
||||
case NGTCP2_PKT_INITIAL:
|
||||
case NGTCP2_PKT_0RTT:
|
||||
if (qhd.dcidlen == SV_DCIDLEN) {
|
||||
cid_prefix = qhd.dcid + CID_PREFIX_OFFSET;
|
||||
AES_ECB_decrypt(&aes_ctx, cid_prefix);
|
||||
worker_id = qhd.dcid + WORKER_ID_OFFSET;
|
||||
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) {
|
||||
sk_index = *psk_index;
|
||||
|
||||
@@ -637,10 +555,10 @@ int select_reuseport(struct sk_reuseport_md *reuse_md) {
|
||||
return SK_DROP;
|
||||
}
|
||||
|
||||
cid_prefix = qhd.dcid + CID_PREFIX_OFFSET;
|
||||
AES_ECB_decrypt(&aes_ctx, cid_prefix);
|
||||
worker_id = qhd.dcid + WORKER_ID_OFFSET;
|
||||
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) {
|
||||
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)
|
||||
@@ -1,43 +0,0 @@
|
||||
# - Try to find libngtcp2_crypto_openssl
|
||||
# Once done this will define
|
||||
# LIBNGTCP2_CRYPTO_OPENSSL_FOUND - System has libngtcp2_crypto_openssl
|
||||
# LIBNGTCP2_CRYPTO_OPENSSL_INCLUDE_DIRS - The libngtcp2_crypto_openssl include directories
|
||||
# LIBNGTCP2_CRYPTO_OPENSSL_LIBRARIES - The libraries needed to use libngtcp2_crypto_openssl
|
||||
|
||||
find_package(PkgConfig QUIET)
|
||||
pkg_check_modules(PC_LIBNGTCP2_CRYPTO_OPENSSL QUIET libngtcp2_crypto_openssl)
|
||||
|
||||
find_path(LIBNGTCP2_CRYPTO_OPENSSL_INCLUDE_DIR
|
||||
NAMES ngtcp2/ngtcp2_crypto_openssl.h
|
||||
HINTS ${PC_LIBNGTCP2_CRYPTO_OPENSSL_INCLUDE_DIRS}
|
||||
)
|
||||
find_library(LIBNGTCP2_CRYPTO_OPENSSL_LIBRARY
|
||||
NAMES ngtcp2_crypto_openssl
|
||||
HINTS ${PC_LIBNGTCP2_CRYPTO_OPENSSL_LIBRARY_DIRS}
|
||||
)
|
||||
|
||||
if(LIBNGTCP2_CRYPTO_OPENSSL_INCLUDE_DIR)
|
||||
set(_version_regex "^#define[ \t]+NGTCP2_VERSION[ \t]+\"([^\"]+)\".*")
|
||||
file(STRINGS "${LIBNGTCP2_CRYPTO_OPENSSL_INCLUDE_DIR}/ngtcp2/version.h"
|
||||
LIBNGTCP2_CRYPTO_OPENSSL_VERSION REGEX "${_version_regex}")
|
||||
string(REGEX REPLACE "${_version_regex}" "\\1"
|
||||
LIBNGTCP2_CRYPTO_OPENSSL_VERSION "${LIBNGTCP2_CRYPTO_OPENSSL_VERSION}")
|
||||
unset(_version_regex)
|
||||
endif()
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
# handle the QUIETLY and REQUIRED arguments and set
|
||||
# LIBNGTCP2_CRYPTO_OPENSSL_FOUND to TRUE if all listed variables are
|
||||
# TRUE and the requested version matches.
|
||||
find_package_handle_standard_args(Libngtcp2_crypto_openssl REQUIRED_VARS
|
||||
LIBNGTCP2_CRYPTO_OPENSSL_LIBRARY
|
||||
LIBNGTCP2_CRYPTO_OPENSSL_INCLUDE_DIR
|
||||
VERSION_VAR LIBNGTCP2_CRYPTO_OPENSSL_VERSION)
|
||||
|
||||
if(LIBNGTCP2_CRYPTO_OPENSSL_FOUND)
|
||||
set(LIBNGTCP2_CRYPTO_OPENSSL_LIBRARIES ${LIBNGTCP2_CRYPTO_OPENSSL_LIBRARY})
|
||||
set(LIBNGTCP2_CRYPTO_OPENSSL_INCLUDE_DIRS ${LIBNGTCP2_CRYPTO_OPENSSL_INCLUDE_DIR})
|
||||
endif()
|
||||
|
||||
mark_as_advanced(LIBNGTCP2_CRYPTO_OPENSSL_INCLUDE_DIR
|
||||
LIBNGTCP2_CRYPTO_OPENSSL_LIBRARY)
|
||||
43
cmake/FindLibngtcp2_crypto_quictls.cmake
Normal file
43
cmake/FindLibngtcp2_crypto_quictls.cmake
Normal file
@@ -0,0 +1,43 @@
|
||||
# - Try to find libngtcp2_crypto_quictls
|
||||
# Once done this will define
|
||||
# LIBNGTCP2_CRYPTO_QUICTLS_FOUND - System has libngtcp2_crypto_quictls
|
||||
# LIBNGTCP2_CRYPTO_QUICTLS_INCLUDE_DIRS - The libngtcp2_crypto_quictls include directories
|
||||
# LIBNGTCP2_CRYPTO_QUICTLS_LIBRARIES - The libraries needed to use libngtcp2_crypto_quictls
|
||||
|
||||
find_package(PkgConfig QUIET)
|
||||
pkg_check_modules(PC_LIBNGTCP2_CRYPTO_QUICTLS QUIET libngtcp2_crypto_quictls)
|
||||
|
||||
find_path(LIBNGTCP2_CRYPTO_QUICTLS_INCLUDE_DIR
|
||||
NAMES ngtcp2/ngtcp2_crypto_quictls.h
|
||||
HINTS ${PC_LIBNGTCP2_CRYPTO_QUICTLS_INCLUDE_DIRS}
|
||||
)
|
||||
find_library(LIBNGTCP2_CRYPTO_QUICTLS_LIBRARY
|
||||
NAMES ngtcp2_crypto_quictls
|
||||
HINTS ${PC_LIBNGTCP2_CRYPTO_QUICTLS_LIBRARY_DIRS}
|
||||
)
|
||||
|
||||
if(LIBNGTCP2_CRYPTO_QUICTLS_INCLUDE_DIR)
|
||||
set(_version_regex "^#define[ \t]+NGTCP2_VERSION[ \t]+\"([^\"]+)\".*")
|
||||
file(STRINGS "${LIBNGTCP2_CRYPTO_QUICTLS_INCLUDE_DIR}/ngtcp2/version.h"
|
||||
LIBNGTCP2_CRYPTO_QUICTLS_VERSION REGEX "${_version_regex}")
|
||||
string(REGEX REPLACE "${_version_regex}" "\\1"
|
||||
LIBNGTCP2_CRYPTO_QUICTLS_VERSION "${LIBNGTCP2_CRYPTO_QUICTLS_VERSION}")
|
||||
unset(_version_regex)
|
||||
endif()
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
# handle the QUIETLY and REQUIRED arguments and set
|
||||
# LIBNGTCP2_CRYPTO_QUICTLS_FOUND to TRUE if all listed variables are
|
||||
# TRUE and the requested version matches.
|
||||
find_package_handle_standard_args(Libngtcp2_crypto_quictls REQUIRED_VARS
|
||||
LIBNGTCP2_CRYPTO_QUICTLS_LIBRARY
|
||||
LIBNGTCP2_CRYPTO_QUICTLS_INCLUDE_DIR
|
||||
VERSION_VAR LIBNGTCP2_CRYPTO_QUICTLS_VERSION)
|
||||
|
||||
if(LIBNGTCP2_CRYPTO_QUICTLS_FOUND)
|
||||
set(LIBNGTCP2_CRYPTO_QUICTLS_LIBRARIES ${LIBNGTCP2_CRYPTO_QUICTLS_LIBRARY})
|
||||
set(LIBNGTCP2_CRYPTO_QUICTLS_INCLUDE_DIRS ${LIBNGTCP2_CRYPTO_QUICTLS_INCLUDE_DIR})
|
||||
endif()
|
||||
|
||||
mark_as_advanced(LIBNGTCP2_CRYPTO_QUICTLS_INCLUDE_DIR
|
||||
LIBNGTCP2_CRYPTO_QUICTLS_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,24 +19,27 @@
|
||||
/* Define to 1 if you have `neverbleed` library. */
|
||||
#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. */
|
||||
#cmakedefine HAVE__EXIT 1
|
||||
|
||||
/* Define to 1 if you have the `accept4` function. */
|
||||
#cmakedefine HAVE_ACCEPT4 1
|
||||
|
||||
/* Define to 1 if you have the `clock_gettime` function. */
|
||||
#cmakedefine HAVE_CLOCK_GETTIME 1
|
||||
|
||||
/* Define to 1 if you have the `mkostemp` function. */
|
||||
#cmakedefine HAVE_MKOSTEMP 1
|
||||
|
||||
/* Define to 1 if you have the `GetTickCount64` function. */
|
||||
#cmakedefine HAVE_GETTICKCOUNT64 1
|
||||
|
||||
/* Define to 1 if you have the `initgroups` function. */
|
||||
#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. */
|
||||
#cmakedefine DEBUGBUILD 1
|
||||
|
||||
@@ -61,6 +64,9 @@
|
||||
/* Define to 1 if you have the <netinet/in.h> header file. */
|
||||
#cmakedefine HAVE_NETINET_IN_H 1
|
||||
|
||||
/* Define to 1 if you have the <netinet/ip.h> header file. */
|
||||
#cmakedefine HAVE_NETINET_IP_H 1
|
||||
|
||||
/* Define to 1 if you have the <pwd.h> header file. */
|
||||
#cmakedefine HAVE_PWD_H 1
|
||||
|
||||
@@ -73,12 +79,12 @@
|
||||
/* Define to 1 if you have the <syslog.h> header file. */
|
||||
#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. */
|
||||
#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. */
|
||||
#cmakedefine ENABLE_HTTP3 1
|
||||
|
||||
@@ -88,5 +94,11 @@
|
||||
/* Define to 1 if you have enum bpf_stats_type in linux/bpf.h. */
|
||||
#cmakedefine HAVE_BPF_STATS_TYPE 1
|
||||
|
||||
/* Define to 1 if you have `libngtcp2_crypto_openssl` library. */
|
||||
#cmakedefine HAVE_LIBNGTCP2_CRYPTO_OPENSSL
|
||||
/* Define to 1 if you have `libngtcp2_crypto_quictls` library. */
|
||||
#cmakedefine HAVE_LIBNGTCP2_CRYPTO_QUICTLS
|
||||
|
||||
/* Define to 1 if you have `libev` library. */
|
||||
#cmakedefine HAVE_LIBEV 1
|
||||
|
||||
/* Define to 1 if you have `libbrotlienc` and `libbrotlidec` libraries. */
|
||||
#cmakedefine HAVE_LIBBROTLI 1
|
||||
|
||||
227
configure.ac
227
configure.ac
@@ -25,7 +25,7 @@ dnl Do not change user variables!
|
||||
dnl https://www.gnu.org/software/automake/manual/html_node/Flag-Variables-Ordering.html
|
||||
|
||||
AC_PREREQ(2.61)
|
||||
AC_INIT([nghttp2], [1.54.0], [t-tujikawa@users.sourceforge.net])
|
||||
AC_INIT([nghttp2], [1.62.1], [t-tujikawa@users.sourceforge.net])
|
||||
AC_CONFIG_AUX_DIR([.])
|
||||
AC_CONFIG_MACRO_DIR([m4])
|
||||
AC_CONFIG_HEADERS([config.h])
|
||||
@@ -38,15 +38,15 @@ AC_CANONICAL_BUILD
|
||||
AC_CANONICAL_HOST
|
||||
AC_CANONICAL_TARGET
|
||||
|
||||
AM_INIT_AUTOMAKE([subdir-objects])
|
||||
AM_INIT_AUTOMAKE([subdir-objects tar-pax])
|
||||
|
||||
m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
|
||||
|
||||
dnl See versioning rule:
|
||||
dnl https://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html
|
||||
AC_SUBST(LT_CURRENT, 38)
|
||||
AC_SUBST(LT_REVISION, 2)
|
||||
AC_SUBST(LT_AGE, 24)
|
||||
AC_SUBST(LT_CURRENT, 42)
|
||||
AC_SUBST(LT_REVISION, 1)
|
||||
AC_SUBST(LT_AGE, 28)
|
||||
|
||||
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"`
|
||||
@@ -137,11 +137,6 @@ AC_ARG_WITH([libev],
|
||||
[Use libev [default=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],
|
||||
[AS_HELP_STRING([--with-jemalloc],
|
||||
[Use jemalloc [default=check]])],
|
||||
@@ -177,6 +172,16 @@ AC_ARG_WITH([libbpf],
|
||||
[Use libbpf [default=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
|
||||
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])
|
||||
@@ -233,7 +238,7 @@ fi
|
||||
save_CXXFLAGS="$CXXFLAGS"
|
||||
CXXFLAGS=
|
||||
|
||||
AX_CXX_COMPILE_STDCXX([14], [noext], [optional])
|
||||
AX_CXX_COMPILE_STDCXX([20], [], [optional])
|
||||
|
||||
CXX1XCXXFLAGS="$CXXFLAGS"
|
||||
CXXFLAGS="$save_CXXFLAGS"
|
||||
@@ -278,21 +283,20 @@ std::map<int, int>().emplace(1, 2);
|
||||
[have_std_map_emplace=no
|
||||
AC_MSG_RESULT([no])])
|
||||
|
||||
# Check that std::atomic_* overloads for std::shared_ptr are
|
||||
# available.
|
||||
AC_MSG_CHECKING([whether std::atomic_* overloads for std::shared_ptr are available])
|
||||
# Check that std::atomic<std::shared_ptr<T>> is supported.
|
||||
AC_MSG_CHECKING([whether std::atomic<std::shared_ptr<T>> is supported])
|
||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM(
|
||||
[[
|
||||
#include <memory>
|
||||
]],
|
||||
[[
|
||||
auto a = std::make_shared<int>(1000000007);
|
||||
auto p = std::atomic_load(&a);
|
||||
auto a = std::atomic<std::shared_ptr<int>>(std::make_shared<int>(1000000007));
|
||||
auto p = a.load();
|
||||
++*p;
|
||||
std::atomic_store(&a, p);
|
||||
a.store(p);
|
||||
]])],
|
||||
[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
|
||||
AC_MSG_RESULT([yes])],
|
||||
[have_atomic_std_shared_ptr=no
|
||||
@@ -377,43 +381,6 @@ case "${host_os}" in
|
||||
;;
|
||||
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)
|
||||
have_libev=no
|
||||
if test "x${request_libev}" != "xno"; then
|
||||
@@ -433,6 +400,10 @@ if test "x${request_libev}" != "xno"; then
|
||||
else
|
||||
have_libev=yes
|
||||
fi
|
||||
|
||||
if test "x${have_libev}" = "xyes"; then
|
||||
AC_DEFINE([HAVE_LIBEV], [1], [Define to 1 if you have `libev` library.])
|
||||
fi
|
||||
fi
|
||||
|
||||
if test "x${request_libev}" = "xyes" &&
|
||||
@@ -443,27 +414,30 @@ fi
|
||||
# openssl (for src)
|
||||
have_openssl=no
|
||||
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])
|
||||
if test "x${have_openssl}" = "xno"; then
|
||||
AC_MSG_NOTICE($OPENSSL_PKG_ERRORS)
|
||||
else
|
||||
save_CFLAGS="$CFLAGS"
|
||||
# Use C++ compiler because boringssl needs C++ runtime.
|
||||
AC_LANG_PUSH(C++)
|
||||
|
||||
save_CXXFLAGS="$CXXFLAGS"
|
||||
save_LIBS="$LIBS"
|
||||
CFLAGS="$OPENSSL_CFLAGS $CFLAGS"
|
||||
CXXFLAGS="$OPENSSL_CFLAGS $CXXFLAGS"
|
||||
LIBS="$OPENSSL_LIBS $LIBS"
|
||||
|
||||
# quictls/openssl has SSL_is_quic.
|
||||
have_ssl_is_quic=no
|
||||
AC_MSG_CHECKING([for SSL_is_quic])
|
||||
# quictls/openssl has SSL_provide_quic_data. boringssl also has
|
||||
# it. We will deal with it later.
|
||||
have_ssl_provide_quic_data=no
|
||||
AC_MSG_CHECKING([for SSL_provide_quic_data])
|
||||
AC_LINK_IFELSE([AC_LANG_PROGRAM([[
|
||||
#include <openssl/ssl.h>
|
||||
]], [[
|
||||
SSL *ssl = NULL;
|
||||
SSL_is_quic(ssl);
|
||||
SSL_provide_quic_data(NULL, (ssl_encryption_level_t)0, NULL, 0);
|
||||
]])],
|
||||
[AC_MSG_RESULT([yes]); have_ssl_is_quic=yes],
|
||||
[AC_MSG_RESULT([no]); have_ssl_is_quic=no])
|
||||
[AC_MSG_RESULT([yes]); have_ssl_provide_quic_data=yes],
|
||||
[AC_MSG_RESULT([no]); have_ssl_provide_quic_data=no])
|
||||
|
||||
# boringssl has SSL_set_quic_early_data_context.
|
||||
AC_MSG_CHECKING([for SSL_set_quic_early_data_context])
|
||||
@@ -476,8 +450,10 @@ if test "x${request_openssl}" != "xno"; then
|
||||
[AC_MSG_RESULT([yes]); have_boringssl_quic=yes],
|
||||
[AC_MSG_RESULT([no]); have_boringssl_quic=no])
|
||||
|
||||
CFLAGS="$save_CFLAGS"
|
||||
CXXFLAGS="$save_CXXFLAGS"
|
||||
LIBS="$save_LIBS"
|
||||
|
||||
AC_LANG_POP()
|
||||
fi
|
||||
fi
|
||||
|
||||
@@ -489,7 +465,7 @@ fi
|
||||
# c-ares (for src)
|
||||
have_libcares=no
|
||||
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])
|
||||
if test "x${have_libcares}" = "xno"; then
|
||||
AC_MSG_NOTICE($LIBCARES_PKG_ERRORS)
|
||||
@@ -504,7 +480,7 @@ fi
|
||||
# ngtcp2 (for src)
|
||||
have_libngtcp2=no
|
||||
if test "x${request_libngtcp2}" != "xno"; then
|
||||
PKG_CHECK_MODULES([LIBNGTCP2], [libngtcp2 >= 0.16.0], [have_libngtcp2=yes],
|
||||
PKG_CHECK_MODULES([LIBNGTCP2], [libngtcp2 >= 1.4.0], [have_libngtcp2=yes],
|
||||
[have_libngtcp2=no])
|
||||
if test "x${have_libngtcp2}" = "xno"; then
|
||||
AC_MSG_NOTICE($LIBNGTCP2_PKG_ERRORS)
|
||||
@@ -516,26 +492,28 @@ if test "x${request_libngtcp2}" = "xyes" &&
|
||||
AC_MSG_ERROR([libngtcp2 was requested (--with-libngtcp2) but not found])
|
||||
fi
|
||||
|
||||
# ngtcp2_crypto_openssl (for src)
|
||||
have_libngtcp2_crypto_openssl=no
|
||||
if test "x${have_ssl_is_quic}" = "xyes" &&
|
||||
# ngtcp2_crypto_quictls (for src)
|
||||
have_libngtcp2_crypto_quictls=no
|
||||
if test "x${have_ssl_provide_quic_data}" = "xyes" &&
|
||||
test "x${have_boringssl_quic}" != "xyes" &&
|
||||
test "x${request_libngtcp2}" != "xno"; then
|
||||
PKG_CHECK_MODULES([LIBNGTCP2_CRYPTO_OPENSSL],
|
||||
[libngtcp2_crypto_openssl >= 0.16.0],
|
||||
[have_libngtcp2_crypto_openssl=yes],
|
||||
[have_libngtcp2_crypto_openssl=no])
|
||||
if test "x${have_libngtcp2_crypto_openssl}" = "xno"; then
|
||||
AC_MSG_NOTICE($LIBNGTCP2_CRYPTO_OPENSSL_PKG_ERRORS)
|
||||
PKG_CHECK_MODULES([LIBNGTCP2_CRYPTO_QUICTLS],
|
||||
[libngtcp2_crypto_quictls >= 1.0.0],
|
||||
[have_libngtcp2_crypto_quictls=yes],
|
||||
[have_libngtcp2_crypto_quictls=no])
|
||||
if test "x${have_libngtcp2_crypto_quictls}" = "xno"; then
|
||||
AC_MSG_NOTICE($LIBNGTCP2_CRYPTO_QUICTLS_PKG_ERRORS)
|
||||
else
|
||||
AC_DEFINE([HAVE_LIBNGTCP2_CRYPTO_OPENSSL], [1],
|
||||
[Define to 1 if you have `libngtcp2_crypto_openssl` library.])
|
||||
AC_DEFINE([HAVE_LIBNGTCP2_CRYPTO_QUICTLS], [1],
|
||||
[Define to 1 if you have `libngtcp2_crypto_quictls` library.])
|
||||
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${have_libngtcp2_crypto_openssl}" != "xyes"; then
|
||||
AC_MSG_ERROR([libngtcp2_crypto_openssl was requested (--with-libngtcp2) but not found])
|
||||
test "x${have_libngtcp2_crypto_quictls}" != "xyes"; then
|
||||
AC_MSG_ERROR([libngtcp2_crypto_quictls was requested (--with-libngtcp2) but not found])
|
||||
fi
|
||||
|
||||
# ngtcp2_crypto_boringssl (for src)
|
||||
@@ -563,7 +541,7 @@ fi
|
||||
# nghttp3 (for src)
|
||||
have_libnghttp3=no
|
||||
if test "x${request_libnghttp3}" != "xno"; then
|
||||
PKG_CHECK_MODULES([LIBNGHTTP3], [libnghttp3 >= 0.12.0], [have_libnghttp3=yes],
|
||||
PKG_CHECK_MODULES([LIBNGHTTP3], [libnghttp3 >= 1.1.0], [have_libnghttp3=yes],
|
||||
[have_libnghttp3=no])
|
||||
if test "x${have_libnghttp3}" = "xno"; then
|
||||
AC_MSG_NOTICE($LIBNGHTTP3_PKG_ERRORS)
|
||||
@@ -620,6 +598,47 @@ fi
|
||||
|
||||
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)
|
||||
# 2.0.8 is required because we use evconnlistener_set_error_cb()
|
||||
have_libevent_openssl=no
|
||||
@@ -748,10 +767,8 @@ AM_CONDITIONAL([ENABLE_APP], [ test "x${enable_app}" = "xyes" ])
|
||||
# Check HTTP/3 support
|
||||
enable_http3=no
|
||||
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_crypto_openssl}" = "xyes" ||
|
||||
(test "x${have_libngtcp2_crypto_quictls}" = "xyes" ||
|
||||
test "x${have_libngtcp2_crypto_boringssl}" = "xyes") &&
|
||||
test "x${have_libnghttp3}" = "xyes"; then
|
||||
enable_http3=yes
|
||||
@@ -843,6 +860,7 @@ AC_CHECK_HEADERS([ \
|
||||
limits.h \
|
||||
netdb.h \
|
||||
netinet/in.h \
|
||||
netinet/ip.h \
|
||||
pwd.h \
|
||||
stddef.h \
|
||||
stdint.h \
|
||||
@@ -851,8 +869,8 @@ AC_CHECK_HEADERS([ \
|
||||
sys/socket.h \
|
||||
sys/time.h \
|
||||
syslog.h \
|
||||
time.h \
|
||||
unistd.h \
|
||||
windows.h \
|
||||
])
|
||||
|
||||
# Checks for typedefs, structures, and compiler characteristics.
|
||||
@@ -902,12 +920,6 @@ if test "x$have_struct_tm_tm_gmtoff" = "xyes"; then
|
||||
[Define to 1 if you have `struct tm.tm_gmtoff` member.])
|
||||
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.
|
||||
|
||||
# Don't check malloc, since it does not play nicely with C++ stdlib
|
||||
@@ -924,6 +936,7 @@ AC_FUNC_STRNLEN
|
||||
AC_CHECK_FUNCS([ \
|
||||
_Exit \
|
||||
accept4 \
|
||||
clock_gettime \
|
||||
dup2 \
|
||||
getcwd \
|
||||
getpwnam \
|
||||
@@ -949,6 +962,25 @@ AC_CHECK_FUNCS([ \
|
||||
AC_CHECK_FUNC([timerfd_create],
|
||||
[have_timerfd_create=yes], [have_timerfd_create=no])
|
||||
|
||||
AC_MSG_CHECKING([checking for GetTickCount64])
|
||||
AC_LINK_IFELSE([AC_LANG_PROGRAM(
|
||||
[[
|
||||
#include <windows.h>
|
||||
]],
|
||||
[[
|
||||
GetTickCount64();
|
||||
]])],
|
||||
[have_gettickcount64=yes],
|
||||
[have_gettickcount64=no])
|
||||
|
||||
if test "x${have_gettickcount64}" = "xyes"; then
|
||||
AC_MSG_RESULT([yes])
|
||||
AC_DEFINE([HAVE_GETTICKCOUNT64], [1],
|
||||
[Define to 1 if you have `GetTickCount64` function.])
|
||||
else
|
||||
AC_MSG_RESULT([no])
|
||||
fi
|
||||
|
||||
# For cygwin: we can link initgroups, so AC_CHECK_FUNCS succeeds, but
|
||||
# cygwin disables initgroups due to feature test macro magic with our
|
||||
# configuration. FreeBSD declares initgroups() in unistd.h.
|
||||
@@ -959,6 +991,10 @@ AC_CHECK_DECLS([initgroups], [], [], [[
|
||||
#include <grp.h>
|
||||
]])
|
||||
|
||||
AC_CHECK_DECLS([CLOCK_MONOTONIC], [], [], [[
|
||||
#include <time.h>
|
||||
]])
|
||||
|
||||
save_CFLAGS=$CFLAGS
|
||||
save_CXXFLAGS=$CXXFLAGS
|
||||
|
||||
@@ -1132,7 +1168,6 @@ AC_MSG_NOTICE([summary of build options:
|
||||
Python: ${PYTHON}
|
||||
PYTHON_VERSION: ${PYTHON_VERSION}
|
||||
Test:
|
||||
CUnit: ${have_cunit} (CFLAGS='${CUNIT_CFLAGS}' LIBS='${CUNIT_LIBS}')
|
||||
Failmalloc: ${enable_failmalloc}
|
||||
Libs:
|
||||
OpenSSL: ${have_openssl} (CFLAGS='${OPENSSL_CFLAGS}' LIBS='${OPENSSL_LIBS}')
|
||||
@@ -1140,7 +1175,7 @@ AC_MSG_NOTICE([summary of build options:
|
||||
Libev: ${have_libev} (CFLAGS='${LIBEV_CFLAGS}' LIBS='${LIBEV_LIBS}')
|
||||
Libc-ares: ${have_libcares} (CFLAGS='${LIBCARES_CFLAGS}' LIBS='${LIBCARES_LIBS}')
|
||||
libngtcp2: ${have_libngtcp2} (CFLAGS='${LIBNGTCP2_CFLAGS}' LIBS='${LIBNGTCP2_LIBS}')
|
||||
libngtcp2_crypto_openssl: ${have_libngtcp2_crypto_openssl} (CFLAGS='${LIBNGTCP2_CRYPTO_OPENSSL_CFLAGS}' LIBS='${LIBNGTCP2_CRYPTO_OPENSSL_LIBS}')
|
||||
libngtcp2_crypto_quictls: ${have_libngtcp2_crypto_quictls} (CFLAGS='${LIBNGTCP2_CRYPTO_QUICTLS_CFLAGS}' LIBS='${LIBNGTCP2_CRYPTO_QUICTLS_LIBS}')
|
||||
libngtcp2_crypto_boringssl: ${have_libngtcp2_crypto_boringssl} (CFLAGS='${LIBNGTCP2_CRYPTO_BORINGSSL_CFLAGS}' LIBS='${LIBNGTCP2_CRYPTO_BORINGSSL_LIBS}')
|
||||
libnghttp3: ${have_libnghttp3} (CFLAGS='${LIBNGHTTP3_CFLAGS}' LIBS='${LIBNGHTTP3_LIBS}')
|
||||
libbpf: ${have_libbpf} (CFLAGS='${LIBBPF_CFLAGS}' LIBS='${LIBBPF_LIBS}')
|
||||
@@ -1149,6 +1184,8 @@ AC_MSG_NOTICE([summary of build options:
|
||||
Jemalloc: ${have_jemalloc} (CFLAGS='${JEMALLOC_CFLAGS}' LIBS='${JEMALLOC_LIBS}')
|
||||
Zlib: ${have_zlib} (CFLAGS='${ZLIB_CFLAGS}' LIBS='${ZLIB_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:
|
||||
http-parser: ${enable_third_party}
|
||||
MRuby: ${have_mruby} (CFLAGS='${LIBMRUBY_CFLAGS}' LIBS='${LIBMRUBY_LIBS}')
|
||||
|
||||
@@ -33,6 +33,7 @@ APIDOCS= \
|
||||
nghttp2_check_header_value_rfc9113.rst \
|
||||
nghttp2_check_method.rst \
|
||||
nghttp2_check_path.rst \
|
||||
nghttp2_extpri_parse_priority.rst \
|
||||
nghttp2_hd_deflate_bound.rst \
|
||||
nghttp2_hd_deflate_change_table_size.rst \
|
||||
nghttp2_hd_deflate_del.rst \
|
||||
@@ -41,7 +42,9 @@ APIDOCS= \
|
||||
nghttp2_hd_deflate_get_num_table_entries.rst \
|
||||
nghttp2_hd_deflate_get_table_entry.rst \
|
||||
nghttp2_hd_deflate_hd.rst \
|
||||
nghttp2_hd_deflate_hd2.rst \
|
||||
nghttp2_hd_deflate_hd_vec.rst \
|
||||
nghttp2_hd_deflate_hd_vec2.rst \
|
||||
nghttp2_hd_deflate_new.rst \
|
||||
nghttp2_hd_deflate_new2.rst \
|
||||
nghttp2_hd_inflate_change_table_size.rst \
|
||||
@@ -53,6 +56,7 @@ APIDOCS= \
|
||||
nghttp2_hd_inflate_get_table_entry.rst \
|
||||
nghttp2_hd_inflate_hd.rst \
|
||||
nghttp2_hd_inflate_hd2.rst \
|
||||
nghttp2_hd_inflate_hd3.rst \
|
||||
nghttp2_hd_inflate_new.rst \
|
||||
nghttp2_hd_inflate_new2.rst \
|
||||
nghttp2_http2_strerror.rst \
|
||||
@@ -73,9 +77,12 @@ APIDOCS= \
|
||||
nghttp2_option_set_peer_max_concurrent_streams.rst \
|
||||
nghttp2_option_set_server_fallback_rfc7540_priorities.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_settings.rst \
|
||||
nghttp2_option_set_stream_reset_rate_limit.rst \
|
||||
nghttp2_pack_settings_payload.rst \
|
||||
nghttp2_pack_settings_payload2.rst \
|
||||
nghttp2_priority_spec_check_default.rst \
|
||||
nghttp2_priority_spec_default_init.rst \
|
||||
nghttp2_priority_spec_init.rst \
|
||||
@@ -84,10 +91,12 @@ APIDOCS= \
|
||||
nghttp2_rcbuf_incref.rst \
|
||||
nghttp2_rcbuf_is_static.rst \
|
||||
nghttp2_select_next_protocol.rst \
|
||||
nghttp2_select_alpn.rst \
|
||||
nghttp2_session_callbacks_del.rst \
|
||||
nghttp2_session_callbacks_new.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_callback2.rst \
|
||||
nghttp2_session_callbacks_set_error_callback.rst \
|
||||
nghttp2_session_callbacks_set_error_callback2.rst \
|
||||
nghttp2_session_callbacks_set_on_begin_frame_callback.rst \
|
||||
@@ -104,9 +113,13 @@ APIDOCS= \
|
||||
nghttp2_session_callbacks_set_on_invalid_header_callback2.rst \
|
||||
nghttp2_session_callbacks_set_on_stream_close_callback.rst \
|
||||
nghttp2_session_callbacks_set_pack_extension_callback.rst \
|
||||
nghttp2_session_callbacks_set_pack_extension_callback2.rst \
|
||||
nghttp2_session_callbacks_set_recv_callback.rst \
|
||||
nghttp2_session_callbacks_set_recv_callback2.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_callback2.rst \
|
||||
nghttp2_session_callbacks_set_send_data_callback.rst \
|
||||
nghttp2_session_callbacks_set_unpack_extension_callback.rst \
|
||||
nghttp2_session_change_extpri_stream_priority.rst \
|
||||
@@ -124,6 +137,7 @@ APIDOCS= \
|
||||
nghttp2_session_find_stream.rst \
|
||||
nghttp2_session_get_effective_local_window_size.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_inflate_dynamic_table_size.rst \
|
||||
nghttp2_session_get_last_proc_stream_id.rst \
|
||||
@@ -142,7 +156,9 @@ APIDOCS= \
|
||||
nghttp2_session_get_stream_remote_window_size.rst \
|
||||
nghttp2_session_get_stream_user_data.rst \
|
||||
nghttp2_session_mem_recv.rst \
|
||||
nghttp2_session_mem_recv2.rst \
|
||||
nghttp2_session_mem_send.rst \
|
||||
nghttp2_session_mem_send2.rst \
|
||||
nghttp2_session_recv.rst \
|
||||
nghttp2_session_resume_data.rst \
|
||||
nghttp2_session_send.rst \
|
||||
@@ -170,6 +186,7 @@ APIDOCS= \
|
||||
nghttp2_strerror.rst \
|
||||
nghttp2_submit_altsvc.rst \
|
||||
nghttp2_submit_data.rst \
|
||||
nghttp2_submit_data2.rst \
|
||||
nghttp2_submit_extension.rst \
|
||||
nghttp2_submit_goaway.rst \
|
||||
nghttp2_submit_headers.rst \
|
||||
@@ -179,7 +196,9 @@ APIDOCS= \
|
||||
nghttp2_submit_priority_update.rst \
|
||||
nghttp2_submit_push_promise.rst \
|
||||
nghttp2_submit_request.rst \
|
||||
nghttp2_submit_request2.rst \
|
||||
nghttp2_submit_response.rst \
|
||||
nghttp2_submit_response2.rst \
|
||||
nghttp2_submit_rst_stream.rst \
|
||||
nghttp2_submit_settings.rst \
|
||||
nghttp2_submit_shutdown_notice.rst \
|
||||
@@ -208,7 +227,6 @@ EXTRA_DIST = \
|
||||
sources/h2load-howto.rst \
|
||||
sources/building-android-binary.rst \
|
||||
sources/contribute.rst \
|
||||
sources/security.rst \
|
||||
_exts/rubydomain/LICENSE.rubydomain \
|
||||
_exts/rubydomain/__init__.py \
|
||||
_exts/rubydomain/rubydomain.py \
|
||||
|
||||
@@ -68,7 +68,7 @@ The example follows::
|
||||
* Callback function invoked when |session| wants to send data to
|
||||
* remote peer.
|
||||
*/
|
||||
typedef ssize_t (*nghttp2_send_callback)
|
||||
typedef nghttp2_ssize (*nghttp2_send_callback2)
|
||||
(nghttp2_session *session,
|
||||
const uint8_t *data, size_t length, int flags, void *user_data);
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ _h2load()
|
||||
_get_comp_words_by_ref cur prev
|
||||
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
|
||||
|
||||
@@ -8,7 +8,7 @@ _nghttpx()
|
||||
_get_comp_words_by_ref cur prev
|
||||
case $cur in
|
||||
-*)
|
||||
COMPREPLY=( $( compgen -W '--backend --frontend --backlog --backend-address-family --backend-http-proxy-uri --workers --single-thread --read-rate --read-burst --write-rate --write-burst --worker-read-rate --worker-read-burst --worker-write-rate --worker-write-burst --worker-frontend-connections --backend-connections-per-host --backend-connections-per-frontend --rlimit-nofile --rlimit-memlock --backend-request-buffer --backend-response-buffer --fastopen --no-kqueue --frontend-http2-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
|
||||
|
||||
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]]
|
||||
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
|
||||
..
|
||||
.TH "H2LOAD" "1" "Jun 07, 2023" "1.54.0" "nghttp2"
|
||||
.TH "H2LOAD" "1" "May 19, 2024" "1.62.1" "nghttp2"
|
||||
.SH NAME
|
||||
h2load \- HTTP/2 benchmarking tool
|
||||
.SH SYNOPSIS
|
||||
@@ -255,20 +255,19 @@ input files as usual.
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \-\-npn\-list=<LIST>
|
||||
.B \-\-alpn\-list=<LIST>
|
||||
Comma delimited list of ALPN protocol identifier sorted
|
||||
in the order of preference. That means most desirable
|
||||
protocol comes first. This is used in both ALPN and
|
||||
NPN. The parameter must be delimited by a single comma
|
||||
only and any white spaces are treated as a part of
|
||||
protocol string.
|
||||
protocol comes first. The parameter must be delimited
|
||||
by a single comma only and any white spaces are treated
|
||||
as a part of protocol string.
|
||||
.sp
|
||||
Default: \fBh2,h2\-16,h2\-14,http/1.1\fP
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.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
|
||||
http/1.1 for both http and https URI.
|
||||
.UNINDENT
|
||||
@@ -345,6 +344,12 @@ Enable ktls.
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \-\-sni=<DNSNAME>
|
||||
Send <DNSNAME> in TLS SNI, overriding the host name
|
||||
specified in URI.
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \-v, \-\-verbose
|
||||
Output debug information.
|
||||
.UNINDENT
|
||||
|
||||
@@ -213,20 +213,19 @@ OPTIONS
|
||||
the first URI appeared in the command line or inside
|
||||
input files as usual.
|
||||
|
||||
.. option:: --npn-list=<LIST>
|
||||
.. option:: --alpn-list=<LIST>
|
||||
|
||||
Comma delimited list of ALPN protocol identifier sorted
|
||||
in the order of preference. That means most desirable
|
||||
protocol comes first. This is used in both ALPN and
|
||||
NPN. The parameter must be delimited by a single comma
|
||||
only and any white spaces are treated as a part of
|
||||
protocol string.
|
||||
protocol comes first. The parameter must be delimited
|
||||
by a single comma only and any white spaces are treated
|
||||
as a part of protocol string.
|
||||
|
||||
Default: ``h2,h2-16,h2-14,http/1.1``
|
||||
|
||||
.. 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
|
||||
http/1.1 for both http and https URI.
|
||||
|
||||
@@ -291,6 +290,11 @@ OPTIONS
|
||||
|
||||
Enable ktls.
|
||||
|
||||
.. option:: --sni=<DNSNAME>
|
||||
|
||||
Send <DNSNAME> in TLS SNI, overriding the host name
|
||||
specified in URI.
|
||||
|
||||
.. option:: -v, --verbose
|
||||
|
||||
Output debug information.
|
||||
|
||||
@@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
||||
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
||||
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
|
||||
..
|
||||
.TH "NGHTTP" "1" "Jun 07, 2023" "1.54.0" "nghttp2"
|
||||
.TH "NGHTTP" "1" "May 19, 2024" "1.62.1" "nghttp2"
|
||||
.SH NAME
|
||||
nghttp \- HTTP/2 client
|
||||
.SH SYNOPSIS
|
||||
|
||||
@@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
||||
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
||||
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
|
||||
..
|
||||
.TH "NGHTTPD" "1" "Jun 07, 2023" "1.54.0" "nghttp2"
|
||||
.TH "NGHTTPD" "1" "May 19, 2024" "1.62.1" "nghttp2"
|
||||
.SH NAME
|
||||
nghttpd \- HTTP/2 server
|
||||
.SH SYNOPSIS
|
||||
|
||||
@@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
||||
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
||||
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
|
||||
..
|
||||
.TH "NGHTTPX" "1" "Jun 07, 2023" "1.54.0" "nghttp2"
|
||||
.TH "NGHTTPX" "1" "May 19, 2024" "1.62.1" "nghttp2"
|
||||
.SH NAME
|
||||
nghttpx \- HTTP/2 proxy
|
||||
.SH SYNOPSIS
|
||||
@@ -371,7 +371,7 @@ Default: \fBauto\fP
|
||||
.TP
|
||||
.B \-\-backend\-http\-proxy\-uri=<URI>
|
||||
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>.
|
||||
Note that they must be properly percent\-encoded. This
|
||||
proxy is used when the backend connection is HTTP/2.
|
||||
@@ -555,27 +555,24 @@ this option will be simply ignored.
|
||||
.SS Timeout
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \-\-frontend\-http2\-read\-timeout=<DURATION>
|
||||
Specify read timeout for HTTP/2 frontend connection.
|
||||
.B \-\-frontend\-http2\-idle\-timeout=<DURATION>
|
||||
Specify idle timeout for HTTP/2 frontend connection. If
|
||||
no active streams exist for this duration, connection is
|
||||
closed.
|
||||
.sp
|
||||
Default: \fB3m\fP
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \-\-frontend\-http3\-read\-timeout=<DURATION>
|
||||
Specify read timeout for HTTP/3 frontend connection.
|
||||
.B \-\-frontend\-http3\-idle\-timeout=<DURATION>
|
||||
Specify idle timeout for HTTP/3 frontend connection. If
|
||||
no active streams exist for this duration, connection is
|
||||
closed.
|
||||
.sp
|
||||
Default: \fB3m\fP
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.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>
|
||||
Specify write timeout for all frontend connections.
|
||||
.sp
|
||||
@@ -591,6 +588,17 @@ Default: \fB1m\fP
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.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>
|
||||
Specify read timeout for HTTP/2 streams. 0 means no
|
||||
timeout.
|
||||
@@ -783,13 +791,12 @@ available.
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \-\-npn\-list=<LIST>
|
||||
.B \-\-alpn\-list=<LIST>
|
||||
Comma delimited list of ALPN protocol identifier sorted
|
||||
in the order of preference. That means most desirable
|
||||
protocol comes first. This is used in both ALPN and
|
||||
NPN. The parameter must be delimited by a single comma
|
||||
only and any white spaces are treated as a part of
|
||||
protocol string.
|
||||
protocol comes first. The parameter must be delimited
|
||||
by a single comma only and any white spaces are treated
|
||||
as a part of protocol string.
|
||||
.sp
|
||||
Default: \fBh2,h2\-16,h2\-14,http/1.1\fP
|
||||
.UNINDENT
|
||||
@@ -1050,7 +1057,7 @@ Default: \fB1s\fP
|
||||
.B \-\-no\-http2\-cipher\-block\-list
|
||||
Allow block listed cipher suite on frontend HTTP/2
|
||||
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.
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
@@ -1058,7 +1065,7 @@ complete HTTP/2 cipher suites block list.
|
||||
.B \-\-client\-no\-http2\-cipher\-block\-list
|
||||
Allow block listed cipher suite on backend HTTP/2
|
||||
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.
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
@@ -1546,18 +1553,20 @@ in HTTP/2 frontend.
|
||||
.TP
|
||||
.B \-\-add\-request\-header=<HEADER>
|
||||
Specify additional header field to add to request header
|
||||
set. This option just appends header field and won\(aqt
|
||||
replace anything already set. This option can be used
|
||||
several times to specify multiple header fields.
|
||||
set. The field name must be lowercase. This option
|
||||
just appends header field and won\(aqt replace anything
|
||||
already set. This option can be used several times to
|
||||
specify multiple header fields.
|
||||
Example: \fI\%\-\-add\-request\-header\fP=\(dqfoo: bar\(dq
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \-\-add\-response\-header=<HEADER>
|
||||
Specify additional header field to add to response
|
||||
header set. This option just appends header field and
|
||||
won\(aqt replace anything already set. This option can be
|
||||
used several times to specify multiple header fields.
|
||||
header set. The field name must be lowercase. This
|
||||
option just appends header field and won\(aqt replace
|
||||
anything already set. This option can be used several
|
||||
times to specify multiple header fields.
|
||||
Example: \fI\%\-\-add\-response\-header\fP=\(dqfoo: bar\(dq
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
@@ -1832,8 +1841,8 @@ NEW_TOKEN frame in the previous connection.
|
||||
.TP
|
||||
.B \-\-frontend\-quic\-congestion\-controller=<CC>
|
||||
Specify a congestion controller algorithm for a frontend
|
||||
QUIC connection. <CC> should be one of \(dqcubic\(dq, \(dqbbr\(dq,
|
||||
and \(dqbbr2\(dq.
|
||||
QUIC connection. <CC> should be either \(dqcubic\(dq or
|
||||
\(dqbbr\(dq.
|
||||
.sp
|
||||
Default: \fBcubic\fP
|
||||
.UNINDENT
|
||||
@@ -1845,12 +1854,12 @@ as QUIC keying materials. It is used to derive keys for
|
||||
encrypting tokens and Connection IDs. It is not used to
|
||||
encrypt QUIC packets. Each line of this file must
|
||||
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
|
||||
keying material. An empty line or a line which starts
|
||||
\(aq#\(aq is ignored. The file can contain more than one
|
||||
keying materials. Because the identifier is 2 bits, at
|
||||
most 4 keying materials are read and the remaining data
|
||||
keying materials. Because the identifier is 3 bits, at
|
||||
most 8 keying materials are read and the remaining data
|
||||
is discarded. The first keying material in the file is
|
||||
primarily used for encryption and decryption for new
|
||||
connection. The other ones are used to decrypt data for
|
||||
@@ -2107,9 +2116,9 @@ than main process.
|
||||
.SH SERVER PUSH
|
||||
.sp
|
||||
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
|
||||
\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
|
||||
header field to initiate server push:
|
||||
.INDENT 0.0
|
||||
@@ -2155,7 +2164,7 @@ delete the socket and continues to use it.
|
||||
.sp
|
||||
OCSP query is done using external Python script
|
||||
\fBfetch\-ocsp\-response\fP, which has been originally developed in Perl
|
||||
as part of h2o project (\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.
|
||||
.sp
|
||||
The script file is usually installed under
|
||||
@@ -2251,15 +2260,15 @@ automatically. To rotate key, one has to restart nghttpx (see
|
||||
SIGNALS).
|
||||
.SH CERTIFICATE TRANSPARENCY
|
||||
.sp
|
||||
nghttpx supports TLS \fBsigned_certificate_timestamp\fP extension (\fI\%RFC
|
||||
6962\fP). The relevant options
|
||||
nghttpx supports TLS \fBsigned_certificate_timestamp\fP extension (\X'tty: link https://tools.ietf.org/html/rfc6962'\fI\%RFC
|
||||
6962\fP\X'tty: link'). The relevant options
|
||||
are \fI\%\-\-tls\-sct\-dir\fP and \fBsct\-dir\fP parameter in
|
||||
\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 are encoded as \fBSignedCertificateTimestamp\fP struct described
|
||||
in \fI\%section 3.2 of RFC 69662\fP\&. This format is
|
||||
the same one used by \fI\%nginx\-ct\fP and \fI\%mod_ssl_ct\fP\&.
|
||||
\fI\%ct\-submit\fP can be
|
||||
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 \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'\&.
|
||||
\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
|
||||
\fBSignedCertificateTimestamp\fP struct which can be used with nghttpx.
|
||||
.SH MRUBY SCRIPTING
|
||||
@@ -2503,7 +2512,7 @@ On assignment, copy of given value is assigned. The path does
|
||||
not include authority component of URI. This may include
|
||||
query component. nghttpx makes certain normalization for
|
||||
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
|
||||
should be percent\-encoded as is. So be careful when comparing
|
||||
path against desired string.
|
||||
|
||||
@@ -522,24 +522,22 @@ Performance
|
||||
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``
|
||||
|
||||
.. 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``
|
||||
|
||||
.. option:: --frontend-read-timeout=<DURATION>
|
||||
|
||||
Specify read timeout for HTTP/1.1 frontend connection.
|
||||
|
||||
Default: ``1m``
|
||||
|
||||
.. option:: --frontend-write-timeout=<DURATION>
|
||||
|
||||
Specify write timeout for all frontend connections.
|
||||
@@ -553,6 +551,16 @@ Timeout
|
||||
|
||||
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>
|
||||
|
||||
Specify read timeout for HTTP/2 streams. 0 means no
|
||||
@@ -728,14 +736,13 @@ SSL/TLS
|
||||
Without this option, DHE cipher suites are not
|
||||
available.
|
||||
|
||||
.. option:: --npn-list=<LIST>
|
||||
.. option:: --alpn-list=<LIST>
|
||||
|
||||
Comma delimited list of ALPN protocol identifier sorted
|
||||
in the order of preference. That means most desirable
|
||||
protocol comes first. This is used in both ALPN and
|
||||
NPN. The parameter must be delimited by a single comma
|
||||
only and any white spaces are treated as a part of
|
||||
protocol string.
|
||||
protocol comes first. The parameter must be delimited
|
||||
by a single comma only and any white spaces are treated
|
||||
as a part of protocol string.
|
||||
|
||||
Default: ``h2,h2-16,h2-14,http/1.1``
|
||||
|
||||
@@ -1402,17 +1409,19 @@ HTTP
|
||||
.. option:: --add-request-header=<HEADER>
|
||||
|
||||
Specify additional header field to add to request header
|
||||
set. This option just appends header field and won't
|
||||
replace anything already set. This option can be used
|
||||
several times to specify multiple header fields.
|
||||
set. The field name must be lowercase. This option
|
||||
just appends header field and won't replace anything
|
||||
already set. This option can be used several times to
|
||||
specify multiple header fields.
|
||||
Example: :option:`--add-request-header`\="foo: bar"
|
||||
|
||||
.. option:: --add-response-header=<HEADER>
|
||||
|
||||
Specify additional header field to add to response
|
||||
header set. This option just appends header field and
|
||||
won't replace anything already set. This option can be
|
||||
used several times to specify multiple header fields.
|
||||
header set. The field name must be lowercase. This
|
||||
option just appends header field and won't replace
|
||||
anything already set. This option can be used several
|
||||
times to specify multiple header fields.
|
||||
Example: :option:`--add-response-header`\="foo: bar"
|
||||
|
||||
.. option:: --request-header-field-buffer=<SIZE>
|
||||
@@ -1673,8 +1682,8 @@ HTTP/3 and QUIC
|
||||
.. option:: --frontend-quic-congestion-controller=<CC>
|
||||
|
||||
Specify a congestion controller algorithm for a frontend
|
||||
QUIC connection. <CC> should be one of "cubic", "bbr",
|
||||
and "bbr2".
|
||||
QUIC connection. <CC> should be either "cubic" or
|
||||
"bbr".
|
||||
|
||||
Default: ``cubic``
|
||||
|
||||
@@ -1685,12 +1694,12 @@ HTTP/3 and QUIC
|
||||
encrypting tokens and Connection IDs. It is not used to
|
||||
encrypt QUIC packets. Each line of this file must
|
||||
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
|
||||
keying material. An empty line or a line which starts
|
||||
'#' is ignored. The file can contain more than one
|
||||
keying materials. Because the identifier is 2 bits, at
|
||||
most 4 keying materials are read and the remaining data
|
||||
keying materials. Because the identifier is 3 bits, at
|
||||
most 8 keying materials are read and the remaining data
|
||||
is discarded. The first keying material in the file is
|
||||
primarily used for encryption and decryption for new
|
||||
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.
|
||||
|
||||
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
|
||||
`nghttp2_session_recv()` will use :type:`nghttp2_read_callback` to get
|
||||
input. On the other hand, `nghttp2_session_mem_recv()` will take
|
||||
input as its parameter. If in doubt, use `nghttp2_session_mem_recv()`
|
||||
since it is simpler, and could be faster since it avoids calling
|
||||
callback function.
|
||||
input. On the other hand, `nghttp2_session_mem_recv2()` will take
|
||||
input as its parameter. If in doubt, use
|
||||
`nghttp2_session_mem_recv2()` since it is simpler, and could be faster
|
||||
since it avoids calling callback function.
|
||||
|
||||
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
|
||||
:type:`nghttp2_send_callback` to pass output to an application. On
|
||||
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
|
||||
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
|
||||
chance to get something pushed into transmission queue while the call
|
||||
of `nghttp2_session_mem_send()`, it is recommended to call
|
||||
`nghttp2_session_mem_recv()` after `nghttp2_session_mem_send()`.
|
||||
of `nghttp2_session_mem_send2()`, it is recommended to call
|
||||
`nghttp2_session_mem_recv2()` after `nghttp2_session_mem_send2()`.
|
||||
|
||||
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
|
||||
@@ -70,7 +70,7 @@ calls for this: `nghttp2_session_want_read()` and
|
||||
can destroy :type:`nghttp2_session`, and then close the underlying
|
||||
connection. But make sure that the buffered output has been
|
||||
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
|
||||
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
|
||||
-------
|
||||
|
||||
Do not call `nghttp2_session_send()`, `nghttp2_session_mem_send()`,
|
||||
`nghttp2_session_recv()` or `nghttp2_session_mem_recv()` from the
|
||||
Do not call `nghttp2_session_send()`, `nghttp2_session_mem_send2()`,
|
||||
`nghttp2_session_recv()` or `nghttp2_session_mem_recv2()` from the
|
||||
nghttp2 callback functions directly or indirectly. It will lead to the
|
||||
crash. You can submit requests or frames in the callbacks then call
|
||||
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)
|
||||
(:macro:`NGHTTP2_CLIENT_MAGIC`) on client configuration. The
|
||||
applications are responsible to send SETTINGS frame as part of
|
||||
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
|
||||
`nghttp2_option_set_no_recv_client_magic()` is used with nonzero
|
||||
option value.
|
||||
@@ -222,7 +222,7 @@ above, the following code does not work:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
nghttp2_submit_response(...)
|
||||
nghttp2_submit_response2(...)
|
||||
nghttp2_submit_rst_stream(...)
|
||||
|
||||
RST_STREAM cancels HEADERS (and DATA), and just RST_STREAM is sent.
|
||||
@@ -258,9 +258,9 @@ For example, we will illustrate how to send `ALTSVC
|
||||
const char *field;
|
||||
} alt_svc;
|
||||
|
||||
ssize_t pack_extension_callback(nghttp2_session *session, uint8_t *buf,
|
||||
size_t len, const nghttp2_frame *frame,
|
||||
void *user_data) {
|
||||
nghttp2_ssize pack_extension_callback(nghttp2_session *session, uint8_t *buf,
|
||||
size_t len, const nghttp2_frame *frame,
|
||||
void *user_data) {
|
||||
const alt_svc *altsvc = (const alt_svc *)frame->ext.payload;
|
||||
size_t originlen = strlen(altsvc->origin);
|
||||
size_t fieldlen = strlen(altsvc->field);
|
||||
@@ -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
|
||||
option to `nghttp2_session_server_new2()` or
|
||||
`nghttp2_session_server_new3()` to create a server session. Client
|
||||
can send Priority header field via `nghttp2_submit_request()`. It can
|
||||
also send PRIORITY_UPDATE frame via
|
||||
can send Priority header field via `nghttp2_submit_request2()`. It
|
||||
can also send PRIORITY_UPDATE frame via
|
||||
`nghttp2_submit_priority_update()`. Server processes Priority header
|
||||
field in a request header field and updates the stream priority unless
|
||||
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
|
||||
clang-format configuration file .clang-format is located at the root
|
||||
directory. Since clang-format produces slightly different results
|
||||
between versions, we currently use clang-format-14.
|
||||
between versions, we currently use clang-format-15.
|
||||
|
||||
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.
|
||||
|
||||
@@ -30,8 +30,8 @@ In order to set benchmark settings, specify following 3 options.
|
||||
:option:`-m`
|
||||
The max concurrent streams to issue per client. Default: 1
|
||||
|
||||
For SSL/TLS connection, the protocol will be negotiated via ALPN/NPN.
|
||||
You can set specific protocols in :option:`--npn-list` option. For
|
||||
For SSL/TLS connection, the protocol will be negotiated via ALPN. You
|
||||
can set specific protocols in :option:`--alpn-list` option. For
|
||||
cleartext connection, the default protocol is HTTP/2. To change the
|
||||
protocol in cleartext connection, use :option:`--no-tls-proto` option.
|
||||
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.
|
||||
|
||||
In order to send HTTP/3 request, specify ``h3`` to
|
||||
:option:`--npn-list`.
|
||||
:option:`--alpn-list`.
|
||||
|
||||
@@ -18,7 +18,6 @@ Contents:
|
||||
|
||||
package_README
|
||||
contribute
|
||||
security
|
||||
building-android-binary
|
||||
tutorial-client
|
||||
tutorial-server
|
||||
|
||||
@@ -20,7 +20,7 @@ known as "HTTP/2 router".
|
||||
By default, frontend connection is encrypted using SSL/TLS. So
|
||||
server's private key and certificate must be supplied to the command
|
||||
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
|
||||
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
|
||||
Algorithm described in `QUIC-LB draft
|
||||
<https://datatracker.ietf.org/doc/html/draft-ietf-quic-load-balancers>`_.
|
||||
A Connection ID that nghttpx generates is always 20 bytes long. It
|
||||
uses first 2 bits as a configuration ID. The remaining bits in the
|
||||
A Connection ID that nghttpx generates is always 17 bytes long. It
|
||||
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.
|
||||
The next 4 bytes are used to route UDP datagram to a correct
|
||||
``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
|
||||
``main()`` and ``run()`` functions. This setup isn't specific to
|
||||
nghttp2, but one thing you should look at is setup of the NPN
|
||||
callback. The NPN callback is used by the client to select the next
|
||||
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()``::
|
||||
nghttp2, but one thing you should look at is setup of ALPN. Client
|
||||
tells application protocols that it supports to server via ALPN::
|
||||
|
||||
static SSL_CTX *create_ssl_ctx(void) {
|
||||
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_NO_COMPRESSION |
|
||||
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);
|
||||
#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L
|
||||
|
||||
return ssl_ctx;
|
||||
}
|
||||
@@ -155,12 +126,7 @@ underlying network socket::
|
||||
|
||||
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);
|
||||
}
|
||||
#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L
|
||||
SSL_get0_alpn_selected(ssl, &alpn, &alpnlen);
|
||||
|
||||
if (alpn == NULL || alpnlen != 2 || memcmp("h2", alpn, 2) != 0) {
|
||||
fprintf(stderr, "h2 is not negotiated\n");
|
||||
@@ -205,7 +171,7 @@ session object and several 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,
|
||||
on_frame_recv_callback);
|
||||
@@ -280,8 +246,8 @@ HTTP request in the ``submit_request()`` function::
|
||||
MAKE_NV(":path", stream_data->path, stream_data->pathlen)};
|
||||
fprintf(stderr, "Request headers:\n");
|
||||
print_headers(stderr, hdrs, ARRLEN(hdrs));
|
||||
stream_id = nghttp2_submit_request(session_data->session, NULL, hdrs,
|
||||
ARRLEN(hdrs), NULL, stream_data);
|
||||
stream_id = nghttp2_submit_request2(session_data->session, NULL, hdrs,
|
||||
ARRLEN(hdrs), NULL, stream_data);
|
||||
if (stream_id < 0) {
|
||||
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
|
||||
of :type:`nghttp2_nv`. There are four header fields to be sent:
|
||||
``: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
|
||||
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 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) {
|
||||
http2_session_data *session_data = (http2_session_data *)ptr;
|
||||
ssize_t readlen;
|
||||
nghttp2_ssize readlen;
|
||||
struct evbuffer *input = bufferevent_get_input(bev);
|
||||
size_t datalen = evbuffer_get_length(input);
|
||||
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) {
|
||||
warnx("Fatal error: %s", nghttp2_strerror((int)readlen));
|
||||
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
|
||||
session object using the `nghttp2_session_mem_recv()` function.
|
||||
`nghttp2_session_mem_recv()` processes the received data and may
|
||||
session object using the `nghttp2_session_mem_recv2()` function.
|
||||
`nghttp2_session_mem_recv2()` processes the received data and may
|
||||
invoke nghttp2 callbacks and queue frames for transmission. Since
|
||||
there may be pending frames for transmission, we call immediately
|
||||
``session_send()`` to send them. ``session_send()`` is defined as
|
||||
@@ -347,15 +313,16 @@ follows::
|
||||
|
||||
The `nghttp2_session_send()` function serializes pending frames into
|
||||
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::
|
||||
|
||||
static ssize_t send_callback(nghttp2_session *session _U_, const uint8_t *data,
|
||||
size_t length, int flags _U_, void *user_data) {
|
||||
static nghttp2_ssize send_callback(nghttp2_session *session _U_,
|
||||
const uint8_t *data, size_t length,
|
||||
int flags _U_, void *user_data) {
|
||||
http2_session_data *session_data = (http2_session_data *)user_data;
|
||||
struct bufferevent *bev = session_data->bev;
|
||||
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
|
||||
|
||||
@@ -24,11 +24,11 @@ deflater object for the dynamic header table. If in doubt, just
|
||||
specify 4096 here, which is the default upper bound of dynamic header
|
||||
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,
|
||||
uint8_t *buf, size_t buflen,
|
||||
const nghttp2_nv *nva, size_t nvlen);
|
||||
nghttp2_ssize nghttp2_hd_deflate_hd2(nghttp2_hd_deflater *deflater,
|
||||
uint8_t *buf, size_t buflen,
|
||||
const nghttp2_nv *nva, size_t nvlen);
|
||||
|
||||
The *deflater* is the deflater object initialized by
|
||||
`nghttp2_hd_deflate_new()` described above. The encoded byte string is
|
||||
@@ -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
|
||||
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
|
||||
one HEADERS (or optionally following (multiple) CONTINUATION
|
||||
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);
|
||||
|
||||
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
|
||||
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
|
||||
important to use `nghttp2_hd_deflate_bound()` to determine the
|
||||
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);
|
||||
|
||||
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_nv *nv_out, int *inflate_flags,
|
||||
const uint8_t *in, size_t inlen,
|
||||
int 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_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
|
||||
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
|
||||
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`_.
|
||||
|
||||
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
|
||||
``main()`` and ``run()`` functions. This setup isn't specific to
|
||||
nghttp2, but one thing you should look at is setup of the NPN
|
||||
callback. The NPN callback is used by the server to advertise which
|
||||
application protocols the server supports to a client. In this
|
||||
example program, when creating the ``SSL_CTX`` object, we store the
|
||||
application protocol name in the wire format of NPN in a statically
|
||||
allocated buffer. This is safe because we only create one ``SSL_CTX``
|
||||
object in the program's entire lifetime.
|
||||
nghttp2, but one thing you should look at is setup of ALPN callback.
|
||||
The ALPN callback is used by the server to select application
|
||||
protocols offered by client. In ALPN, client sends the list of
|
||||
supported application protocols, and server selects one of them. We
|
||||
provide the callback for it::
|
||||
|
||||
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,
|
||||
unsigned char *outlen, const unsigned char *in,
|
||||
unsigned int inlen, void *arg _U_) {
|
||||
int rv;
|
||||
|
||||
rv = nghttp2_select_next_protocol((unsigned char **)out, outlen, in, inlen);
|
||||
rv = nghttp2_select_alpn(out, outlen, in, inlen);
|
||||
|
||||
if (rv != 1) {
|
||||
return SSL_TLSEXT_ERR_NOACK;
|
||||
@@ -63,7 +40,6 @@ them. We provide the callback for it::
|
||||
|
||||
return SSL_TLSEXT_ERR_OK;
|
||||
}
|
||||
#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L
|
||||
|
||||
static SSL_CTX *create_ssl_ctx(const char *key_file, const char *cert_file) {
|
||||
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);
|
||||
#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L
|
||||
|
||||
return ssl_ctx;
|
||||
}
|
||||
|
||||
The wire format of NPN is a sequence of length prefixed strings, with
|
||||
exactly one byte used to specify the length of each protocol
|
||||
identifier. In this tutorial, we advertise the specific HTTP/2
|
||||
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
|
||||
In ``alpn_select_proto_cb()``, we use `nghttp2_select_alpn()` to
|
||||
select application protocol. The `nghttp2_select_alpn()` returns 1
|
||||
only if it selected h2 (ALPN identifier for HTTP/2), and out
|
||||
parameters were assigned accordingly.
|
||||
|
||||
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_get0_next_proto_negotiated(ssl, &alpn, &alpnlen);
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x10002000L
|
||||
if (alpn == NULL) {
|
||||
SSL_get0_alpn_selected(ssl, &alpn, &alpnlen);
|
||||
}
|
||||
#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L
|
||||
SSL_get0_alpn_selected(ssl, &alpn, &alpnlen);
|
||||
|
||||
if (alpn == NULL || alpnlen != 2 || memcmp("h2", alpn, 2) != 0) {
|
||||
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_set_send_callback(callbacks, send_callback);
|
||||
nghttp2_session_callbacks_set_send_callback2(callbacks, send_callback);
|
||||
|
||||
nghttp2_session_callbacks_set_on_frame_recv_callback(callbacks,
|
||||
on_frame_recv_callback);
|
||||
@@ -323,12 +275,12 @@ this pending data. To process the received data, we call the
|
||||
``session_recv()`` function::
|
||||
|
||||
static int session_recv(http2_session_data *session_data) {
|
||||
ssize_t readlen;
|
||||
nghttp2_ssize readlen;
|
||||
struct evbuffer *input = bufferevent_get_input(session_data->bev);
|
||||
size_t datalen = evbuffer_get_length(input);
|
||||
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) {
|
||||
warnx("Fatal error: %s", nghttp2_strerror((int)readlen));
|
||||
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
|
||||
the nghttp2 session object using the `nghttp2_session_mem_recv()`
|
||||
function. The `nghttp2_session_mem_recv()` function processes the data
|
||||
and may both invoke the previously setup callbacks and also queue
|
||||
the nghttp2 session object using the `nghttp2_session_mem_recv2()`
|
||||
function. The `nghttp2_session_mem_recv2()` function processes the
|
||||
data and may both invoke the previously setup callbacks and also queue
|
||||
outgoing frames. To send any pending outgoing frames, we immediately
|
||||
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
|
||||
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::
|
||||
|
||||
static ssize_t send_callback(nghttp2_session *session _U_, const uint8_t *data,
|
||||
size_t length, int flags _U_, void *user_data) {
|
||||
static nghttp2_ssize send_callback(nghttp2_session *session _U_,
|
||||
const uint8_t *data, size_t length,
|
||||
int flags _U_, void *user_data) {
|
||||
http2_session_data *session_data = (http2_session_data *)user_data;
|
||||
struct bufferevent *bev = session_data->bev;
|
||||
/* Avoid excessive buffering in server side. */
|
||||
@@ -377,7 +330,7 @@ follows::
|
||||
return NGHTTP2_ERR_WOULDBLOCK;
|
||||
}
|
||||
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
|
||||
@@ -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,
|
||||
nghttp2_nv *nva, size_t nvlen, int fd) {
|
||||
int rv;
|
||||
nghttp2_data_provider data_prd;
|
||||
nghttp2_data_provider2 data_prd;
|
||||
data_prd.source.fd = fd;
|
||||
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) {
|
||||
warnx("Fatal error: %s", nghttp2_strerror(rv));
|
||||
return -1;
|
||||
@@ -569,7 +522,7 @@ Sending the file content is performed by the ``send_response()`` function::
|
||||
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
|
||||
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
|
||||
@@ -577,11 +530,11 @@ server, we use it as a file descriptor. We also set the
|
||||
``file_read_callback()`` callback function to read the contents of the
|
||||
file::
|
||||
|
||||
static ssize_t file_read_callback(nghttp2_session *session _U_,
|
||||
int32_t stream_id _U_, uint8_t *buf,
|
||||
size_t length, uint32_t *data_flags,
|
||||
nghttp2_data_source *source,
|
||||
void *user_data _U_) {
|
||||
static nghttp2_ssize file_read_callback(nghttp2_session *session _U_,
|
||||
int32_t stream_id _U_, uint8_t *buf,
|
||||
size_t length, uint32_t *data_flags,
|
||||
nghttp2_data_source *source,
|
||||
void *user_data _U_) {
|
||||
int fd = source->fd;
|
||||
ssize_t r;
|
||||
while ((r = read(fd, buf, length)) == -1 && errno == EINTR)
|
||||
@@ -592,7 +545,7 @@ file::
|
||||
if (r == 0) {
|
||||
*data_flags |= NGHTTP2_DATA_FLAG_EOF;
|
||||
}
|
||||
return r;
|
||||
return (nghttp2_ssize)r;
|
||||
}
|
||||
|
||||
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
|
||||
that we have finished reading the file.
|
||||
|
||||
The `nghttp2_submit_response()` function is used to send the response to the
|
||||
remote peer.
|
||||
The `nghttp2_submit_response2()` function is used to send the response
|
||||
to the remote peer.
|
||||
|
||||
The ``on_stream_close_callback()`` function is invoked when the stream
|
||||
is about to close::
|
||||
|
||||
@@ -1,21 +1,23 @@
|
||||
FROM debian:11 as build
|
||||
FROM debian:12 as build
|
||||
|
||||
ARG NGHTTP2_BRANCH=master
|
||||
|
||||
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 \
|
||||
pkg-config \
|
||||
pkg-config cmake cmake-data \
|
||||
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_1u+quic https://github.com/quictls/openssl && \
|
||||
cd openssl && \
|
||||
./config --openssldir=/etc/ssl && \
|
||||
make -j$(nproc) && \
|
||||
make install_sw && \
|
||||
RUN git clone --recursive --depth 1 -b v1.26.0 https://github.com/aws/aws-lc && \
|
||||
cd aws-lc && \
|
||||
cmake -B build -DDISABLE_GO=ON && \
|
||||
make -j$(nproc) -C build && \
|
||||
cmake --install build && \
|
||||
cd .. && \
|
||||
rm -rf openssl
|
||||
rm -rf aws-lc
|
||||
|
||||
RUN git clone --depth 1 -b v0.12.0 https://github.com/ngtcp2/nghttp3 && \
|
||||
RUN git clone --recursive --depth 1 -b v1.3.0 https://github.com/ngtcp2/nghttp3 && \
|
||||
cd nghttp3 && \
|
||||
autoreconf -i && \
|
||||
./configure --enable-lib-only && \
|
||||
@@ -24,55 +26,57 @@ RUN git clone --depth 1 -b v0.12.0 https://github.com/ngtcp2/nghttp3 && \
|
||||
cd .. && \
|
||||
rm -rf nghttp3
|
||||
|
||||
RUN git clone --depth 1 -b v0.16.0 https://github.com/ngtcp2/ngtcp2 && \
|
||||
RUN git clone --recursive --depth 1 -b v1.5.0 https://github.com/ngtcp2/ngtcp2 && \
|
||||
cd ngtcp2 && \
|
||||
autoreconf -i && \
|
||||
./configure --enable-lib-only \
|
||||
./configure --enable-lib-only --with-boringssl \
|
||||
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" && \
|
||||
make -j$(nproc) && \
|
||||
make install-strip && \
|
||||
cd .. && \
|
||||
rm -rf ngtcp2
|
||||
|
||||
RUN git clone --depth 1 -b v1.2.0 https://github.com/libbpf/libbpf && \
|
||||
RUN git clone --depth 1 -b v1.3.0 https://github.com/libbpf/libbpf && \
|
||||
cd libbpf && \
|
||||
PREFIX=/usr/local make -C src install && \
|
||||
cd .. && \
|
||||
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 && \
|
||||
git submodule update --init && \
|
||||
autoreconf -i && \
|
||||
./configure --disable-examples --disable-hpack-tools \
|
||||
--with-mruby --with-neverbleed \
|
||||
--with-mruby \
|
||||
--enable-http3 --with-libbpf \
|
||||
--with-libbrotlienc --with-libbrotlidec \
|
||||
CC=clang CXX=clang++ \
|
||||
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" \
|
||||
JEMALLOC_LIBS="-l:libjemalloc.a" \
|
||||
LIBCARES_LIBS="-l:libcares.a" \
|
||||
ZLIB_LIBS="-l:libz.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++" \
|
||||
PKG_CONFIG_PATH="/usr/local/lib64/pkgconfig" && \
|
||||
make -j$(nproc) install-strip && \
|
||||
cd .. && \
|
||||
rm -rf nghttp2
|
||||
|
||||
FROM gcr.io/distroless/base-debian11
|
||||
FROM gcr.io/distroless/base-nossl-debian12
|
||||
|
||||
COPY --from=build \
|
||||
COPY --from=build --link \
|
||||
/usr/local/share/nghttp2/ \
|
||||
/usr/local/share/nghttp2/
|
||||
COPY --from=build \
|
||||
COPY --from=build --link \
|
||||
/usr/local/bin/h2load \
|
||||
/usr/local/bin/nghttpx \
|
||||
/usr/local/bin/nghttp \
|
||||
/usr/local/bin/nghttpd \
|
||||
/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/
|
||||
|
||||
@@ -56,6 +56,7 @@
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#define NGHTTP2_NO_SSIZE_T
|
||||
#include <nghttp2/nghttp2.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
|
||||
* bytes actually written. See the documentation of
|
||||
* nghttp2_send_callback for the details.
|
||||
*/
|
||||
static ssize_t send_callback(nghttp2_session *session, const uint8_t *data,
|
||||
size_t length, int flags, void *user_data) {
|
||||
static nghttp2_ssize send_callback(nghttp2_session *session,
|
||||
const uint8_t *data, size_t length,
|
||||
int flags, void *user_data) {
|
||||
struct Connection *connection;
|
||||
int rv;
|
||||
(void)session;
|
||||
@@ -184,13 +186,14 @@ static ssize_t send_callback(nghttp2_session *session, const uint8_t *data,
|
||||
}
|
||||
|
||||
/*
|
||||
* The implementation of nghttp2_recv_callback type. Here we read data
|
||||
* from the network and write them in |buf|. The capacity of |buf| is
|
||||
* |length| bytes. Returns the number of bytes stored in |buf|. See
|
||||
* the documentation of nghttp2_recv_callback for the details.
|
||||
* The implementation of nghttp2_recv_callback2 type. Here we read
|
||||
* data from the network and write them in |buf|. The capacity of
|
||||
* |buf| is |length| bytes. Returns the number of bytes stored in
|
||||
* |buf|. See the documentation of nghttp2_recv_callback for the
|
||||
* details.
|
||||
*/
|
||||
static ssize_t recv_callback(nghttp2_session *session, uint8_t *buf,
|
||||
size_t length, int flags, void *user_data) {
|
||||
static nghttp2_ssize recv_callback(nghttp2_session *session, uint8_t *buf,
|
||||
size_t length, int flags, void *user_data) {
|
||||
struct Connection *connection;
|
||||
int rv;
|
||||
(void)session;
|
||||
@@ -328,9 +331,9 @@ static int on_data_chunk_recv_callback(nghttp2_session *session, uint8_t flags,
|
||||
* recv_callback is also required.
|
||||
*/
|
||||
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,
|
||||
on_frame_send_callback);
|
||||
@@ -345,29 +348,6 @@ static void setup_nghttp2_callbacks(nghttp2_session_callbacks *callbacks) {
|
||||
callbacks, on_data_chunk_recv_callback);
|
||||
}
|
||||
|
||||
#ifndef OPENSSL_NO_NEXTPROTONEG
|
||||
/*
|
||||
* Callback function for TLS NPN. Since this program only supports
|
||||
* HTTP/2 protocol, if server does not offer HTTP/2 the nghttp2
|
||||
* 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.
|
||||
*/
|
||||
@@ -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_mode(ssl_ctx, SSL_MODE_AUTO_RETRY);
|
||||
SSL_CTX_set_mode(ssl_ctx, SSL_MODE_RELEASE_BUFFERS);
|
||||
/* Set NPN callback */
|
||||
#ifndef OPENSSL_NO_NEXTPROTONEG
|
||||
SSL_CTX_set_next_proto_select_cb(ssl_ctx, select_next_proto_cb, NULL);
|
||||
#endif /* !OPENSSL_NO_NEXTPROTONEG */
|
||||
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x10002000L
|
||||
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) {
|
||||
@@ -487,8 +461,8 @@ static void submit_request(struct Connection *connection, struct Request *req) {
|
||||
MAKE_NV("accept", "*/*"),
|
||||
MAKE_NV("user-agent", "nghttp2/" NGHTTP2_VERSION)};
|
||||
|
||||
stream_id = nghttp2_submit_request(connection->session, NULL, nva,
|
||||
sizeof(nva) / sizeof(nva[0]), NULL, req);
|
||||
stream_id = nghttp2_submit_request2(connection->session, NULL, nva,
|
||||
sizeof(nva) / sizeof(nva[0]), NULL, req);
|
||||
|
||||
if (stream_id < 0) {
|
||||
diec("nghttp2_submit_request", stream_id);
|
||||
@@ -719,19 +693,6 @@ int main(int argc, char **argv) {
|
||||
act.sa_handler = SIG_IGN;
|
||||
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]);
|
||||
if (rv != 0) {
|
||||
die("parse_uri failed");
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#define NGHTTP2_NO_SSIZE_T
|
||||
#include <nghttp2/nghttp2.h>
|
||||
|
||||
#define MAKE_NV(K, V) \
|
||||
@@ -93,7 +94,7 @@ int main(void) {
|
||||
static void deflate(nghttp2_hd_deflater *deflater,
|
||||
nghttp2_hd_inflater *inflater, const nghttp2_nv *const nva,
|
||||
size_t nvlen) {
|
||||
ssize_t rv;
|
||||
nghttp2_ssize rv;
|
||||
uint8_t *buf;
|
||||
size_t buflen;
|
||||
size_t outlen;
|
||||
@@ -118,10 +119,10 @@ static void deflate(nghttp2_hd_deflater *deflater,
|
||||
buflen = nghttp2_hd_deflate_bound(deflater, nva, nvlen);
|
||||
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) {
|
||||
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));
|
||||
|
||||
free(buf);
|
||||
@@ -166,17 +167,18 @@ static void deflate(nghttp2_hd_deflater *deflater,
|
||||
|
||||
int inflate_header_block(nghttp2_hd_inflater *inflater, uint8_t *in,
|
||||
size_t inlen, int final) {
|
||||
ssize_t rv;
|
||||
nghttp2_ssize rv;
|
||||
|
||||
for (;;) {
|
||||
nghttp2_nv nv;
|
||||
int inflate_flags = 0;
|
||||
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) {
|
||||
fprintf(stderr, "inflate failed with error code %zd", rv);
|
||||
fprintf(stderr, "inflate failed with error code %td", rv);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
@@ -63,6 +63,7 @@ char *strndup(const char *s, size_t size);
|
||||
#include <event2/bufferevent_ssl.h>
|
||||
#include <event2/dns.h>
|
||||
|
||||
#define NGHTTP2_NO_SSIZE_T
|
||||
#include <nghttp2/nghttp2.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");
|
||||
}
|
||||
|
||||
/* nghttp2_send_callback. Here we transmit the |data|, |length| bytes,
|
||||
to the network. Because we are using libevent bufferevent, we just
|
||||
write those bytes into bufferevent buffer. */
|
||||
static ssize_t send_callback(nghttp2_session *session, const uint8_t *data,
|
||||
size_t length, int flags, void *user_data) {
|
||||
/* nghttp2_send_callback2. Here we transmit the |data|, |length|
|
||||
bytes, to the network. Because we are using libevent bufferevent,
|
||||
we just write those bytes into bufferevent buffer. */
|
||||
static nghttp2_ssize send_callback(nghttp2_session *session,
|
||||
const uint8_t *data, size_t length,
|
||||
int flags, void *user_data) {
|
||||
http2_session_data *session_data = (http2_session_data *)user_data;
|
||||
struct bufferevent *bev = session_data->bev;
|
||||
(void)session;
|
||||
(void)flags;
|
||||
|
||||
bufferevent_write(bev, data, length);
|
||||
return (ssize_t)length;
|
||||
return (nghttp2_ssize)length;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
#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. */
|
||||
static SSL_CTX *create_ssl_ctx(void) {
|
||||
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_NO_COMPRESSION |
|
||||
SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION);
|
||||
#ifndef OPENSSL_NO_NEXTPROTONEG
|
||||
SSL_CTX_set_next_proto_select_cb(ssl_ctx, select_next_proto_cb, NULL);
|
||||
#endif /* !OPENSSL_NO_NEXTPROTONEG */
|
||||
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x10002000L
|
||||
SSL_CTX_set_alpn_protos(ssl_ctx, (const unsigned char *)"\x02h2", 3);
|
||||
#endif /* OPENSSL_VERSION_NUMBER >= 0x10002000L */
|
||||
|
||||
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_set_send_callback(callbacks, send_callback);
|
||||
nghttp2_session_callbacks_set_send_callback2(callbacks, send_callback);
|
||||
|
||||
nghttp2_session_callbacks_set_on_frame_recv_callback(callbacks,
|
||||
on_frame_recv_callback);
|
||||
@@ -425,8 +405,8 @@ static void submit_request(http2_session_data *session_data) {
|
||||
MAKE_NV(":path", stream_data->path, stream_data->pathlen)};
|
||||
fprintf(stderr, "Request headers:\n");
|
||||
print_headers(stderr, hdrs, ARRLEN(hdrs));
|
||||
stream_id = nghttp2_submit_request(session_data->session, NULL, hdrs,
|
||||
ARRLEN(hdrs), NULL, stream_data);
|
||||
stream_id = nghttp2_submit_request2(session_data->session, NULL, hdrs,
|
||||
ARRLEN(hdrs), NULL, stream_data);
|
||||
if (stream_id < 0) {
|
||||
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. */
|
||||
static void readcb(struct bufferevent *bev, void *ptr) {
|
||||
http2_session_data *session_data = (http2_session_data *)ptr;
|
||||
ssize_t readlen;
|
||||
nghttp2_ssize readlen;
|
||||
struct evbuffer *input = bufferevent_get_input(bev);
|
||||
size_t datalen = evbuffer_get_length(input);
|
||||
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) {
|
||||
warnx("Fatal error: %s", nghttp2_strerror((int)readlen));
|
||||
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);
|
||||
|
||||
#ifndef OPENSSL_NO_NEXTPROTONEG
|
||||
SSL_get0_next_proto_negotiated(ssl, &alpn, &alpnlen);
|
||||
#endif /* !OPENSSL_NO_NEXTPROTONEG */
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x10002000L
|
||||
if (alpn == NULL) {
|
||||
SSL_get0_alpn_selected(ssl, &alpn, &alpnlen);
|
||||
}
|
||||
#endif /* OPENSSL_VERSION_NUMBER >= 0x10002000L */
|
||||
|
||||
if (alpn == NULL || alpnlen != 2 || memcmp("h2", alpn, 2) != 0) {
|
||||
fprintf(stderr, "h2 is not negotiated\n");
|
||||
@@ -617,19 +592,6 @@ int main(int argc, char **argv) {
|
||||
act.sa_handler = SIG_IGN;
|
||||
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]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -71,6 +71,7 @@
|
||||
#include <event2/bufferevent_ssl.h>
|
||||
#include <event2/listener.h>
|
||||
|
||||
#define NGHTTP2_NO_SSIZE_T
|
||||
#include <nghttp2/nghttp2.h>
|
||||
|
||||
#define OUTPUT_WOULDBLOCK_THRESHOLD (1 << 16)
|
||||
@@ -106,22 +107,6 @@ struct app_context {
|
||||
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,
|
||||
unsigned char *outlen, const unsigned char *in,
|
||||
unsigned int inlen, void *arg) {
|
||||
@@ -129,7 +114,7 @@ static int alpn_select_proto_cb(SSL *ssl, const unsigned char **out,
|
||||
(void)ssl;
|
||||
(void)arg;
|
||||
|
||||
rv = nghttp2_select_next_protocol((unsigned char **)out, outlen, in, inlen);
|
||||
rv = nghttp2_select_alpn(out, outlen, in, inlen);
|
||||
|
||||
if (rv != 1) {
|
||||
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;
|
||||
}
|
||||
#endif /* OPENSSL_VERSION_NUMBER >= 0x10002000L */
|
||||
|
||||
/* Create SSL_CTX. */
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
#endif /* OPENSSL_VERSION_NUMBER >= 0x10002000L */
|
||||
|
||||
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
|
||||
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
|
||||
function. */
|
||||
static int session_recv(http2_session_data *session_data) {
|
||||
ssize_t readlen;
|
||||
nghttp2_ssize readlen;
|
||||
struct evbuffer *input = bufferevent_get_input(session_data->bev);
|
||||
size_t datalen = evbuffer_get_length(input);
|
||||
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) {
|
||||
warnx("Fatal error: %s", nghttp2_strerror((int)readlen));
|
||||
return -1;
|
||||
@@ -329,8 +302,9 @@ static int session_recv(http2_session_data *session_data) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t send_callback(nghttp2_session *session, const uint8_t *data,
|
||||
size_t length, int flags, void *user_data) {
|
||||
static nghttp2_ssize send_callback(nghttp2_session *session,
|
||||
const uint8_t *data, size_t length,
|
||||
int flags, void *user_data) {
|
||||
http2_session_data *session_data = (http2_session_data *)user_data;
|
||||
struct bufferevent *bev = session_data->bev;
|
||||
(void)session;
|
||||
@@ -342,7 +316,7 @@ static ssize_t send_callback(nghttp2_session *session, const uint8_t *data,
|
||||
return NGHTTP2_ERR_WOULDBLOCK;
|
||||
}
|
||||
bufferevent_write(bev, data, length);
|
||||
return (ssize_t)length;
|
||||
return (nghttp2_ssize)length;
|
||||
}
|
||||
|
||||
/* Returns nonzero if the string |s| ends with the substring |sub| */
|
||||
@@ -398,11 +372,11 @@ static char *percent_decode(const uint8_t *value, size_t valuelen) {
|
||||
return res;
|
||||
}
|
||||
|
||||
static ssize_t file_read_callback(nghttp2_session *session, int32_t stream_id,
|
||||
uint8_t *buf, size_t length,
|
||||
uint32_t *data_flags,
|
||||
nghttp2_data_source *source,
|
||||
void *user_data) {
|
||||
static nghttp2_ssize file_read_callback(nghttp2_session *session,
|
||||
int32_t stream_id, uint8_t *buf,
|
||||
size_t length, uint32_t *data_flags,
|
||||
nghttp2_data_source *source,
|
||||
void *user_data) {
|
||||
int fd = source->fd;
|
||||
ssize_t r;
|
||||
(void)session;
|
||||
@@ -417,17 +391,17 @@ static ssize_t file_read_callback(nghttp2_session *session, int32_t stream_id,
|
||||
if (r == 0) {
|
||||
*data_flags |= NGHTTP2_DATA_FLAG_EOF;
|
||||
}
|
||||
return r;
|
||||
return (nghttp2_ssize)r;
|
||||
}
|
||||
|
||||
static int send_response(nghttp2_session *session, int32_t stream_id,
|
||||
nghttp2_nv *nva, size_t nvlen, int fd) {
|
||||
int rv;
|
||||
nghttp2_data_provider data_prd;
|
||||
nghttp2_data_provider2 data_prd;
|
||||
data_prd.source.fd = fd;
|
||||
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) {
|
||||
warnx("Fatal error: %s", nghttp2_strerror(rv));
|
||||
return -1;
|
||||
@@ -618,7 +592,7 @@ static void initialize_nghttp2_session(http2_session_data *session_data) {
|
||||
|
||||
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,
|
||||
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);
|
||||
|
||||
#ifndef OPENSSL_NO_NEXTPROTONEG
|
||||
SSL_get0_next_proto_negotiated(ssl, &alpn, &alpnlen);
|
||||
#endif /* !OPENSSL_NO_NEXTPROTONEG */
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x10002000L
|
||||
if (alpn == NULL) {
|
||||
SSL_get0_alpn_selected(ssl, &alpn, &alpnlen);
|
||||
}
|
||||
#endif /* OPENSSL_VERSION_NUMBER >= 0x10002000L */
|
||||
SSL_get0_alpn_selected(ssl, &alpn, &alpnlen);
|
||||
|
||||
if (alpn == NULL || alpnlen != 2 || memcmp("h2", alpn, 2) != 0) {
|
||||
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;
|
||||
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]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@ namespace {
|
||||
void send_pending(nghttp2_session *session) {
|
||||
for (;;) {
|
||||
const uint8_t *data;
|
||||
auto n = nghttp2_session_mem_send(session, &data);
|
||||
auto n = nghttp2_session_mem_send2(session, &data);
|
||||
if (n == 0) {
|
||||
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_submit_settings(session, NGHTTP2_FLAG_NONE, &iv, 1);
|
||||
send_pending(session);
|
||||
nghttp2_session_mem_recv(session, data, size);
|
||||
nghttp2_session_mem_recv2(session, data, size);
|
||||
send_pending(session);
|
||||
|
||||
nghttp2_session_del(session);
|
||||
|
||||
@@ -44,7 +44,7 @@ namespace {
|
||||
void send_pending(nghttp2_session *session) {
|
||||
for (;;) {
|
||||
const uint8_t *data;
|
||||
auto n = nghttp2_session_mem_send(session, &data);
|
||||
auto n = nghttp2_session_mem_send2(session, &data);
|
||||
if (n == 0) {
|
||||
return;
|
||||
}
|
||||
@@ -87,7 +87,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
|
||||
send_pending(session);
|
||||
|
||||
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);
|
||||
|
||||
|
||||
@@ -35,6 +35,7 @@ HEADERS = [
|
||||
"early-data",
|
||||
"sec-websocket-accept",
|
||||
"sec-websocket-key",
|
||||
"priority",
|
||||
# disallowed h1 headers
|
||||
'connection',
|
||||
'keep-alive',
|
||||
|
||||
@@ -200,6 +200,10 @@ OPTIONS = [
|
||||
"frontend-quic-initial-rtt",
|
||||
"require-http-scheme",
|
||||
"tls-ktls",
|
||||
"alpn-list",
|
||||
"frontend-header-timeout",
|
||||
"frontend-http2-idle-timeout",
|
||||
"frontend-http3-idle-timeout",
|
||||
]
|
||||
|
||||
LOGVARS = [
|
||||
@@ -237,5 +241,5 @@ LOGVARS = [
|
||||
]
|
||||
|
||||
if __name__ == '__main__':
|
||||
gentokenlookup(OPTIONS, 'SHRPX_OPTID_', value_type='char', comp_fun='util::strieq_l')
|
||||
gentokenlookup(LOGVARS, 'LogFragmentType::', value_type='char', comp_fun='util::strieq_l', return_type='LogFragmentType', fail_value='LogFragmentType::NONE')
|
||||
gentokenlookup(OPTIONS, 'SHRPX_OPTID_', comp_fun='util::strieq')
|
||||
gentokenlookup(LOGVARS, 'LogFragmentType::', comp_fun='util::strieq', return_type='LogFragmentType', fail_value='LogFragmentType::NONE')
|
||||
|
||||
@@ -33,10 +33,10 @@ enum {''')
|
||||
{}MAXIDX,
|
||||
}};'''.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('''\
|
||||
{} lookup_token(const {} *name, size_t namelen) {{
|
||||
switch (namelen) {{'''.format(return_type, value_type))
|
||||
{} lookup_token(const StringRef &name) {{
|
||||
switch (name.size()) {{'''.format(return_type))
|
||||
b = build_header(tokens)
|
||||
for size in sorted(b.keys()):
|
||||
ents = b[size]
|
||||
@@ -50,7 +50,7 @@ def gen_index_header(tokens, prefix, value_type, comp_fun, return_type, fail_val
|
||||
case '{}':'''.format(c))
|
||||
for k in headers:
|
||||
print('''\
|
||||
if ({}("{}", name, {})) {{
|
||||
if ({}("{}"_sr, name, {})) {{
|
||||
return {};
|
||||
}}'''.format(comp_fun, k[:-1], size - 1, to_enum_hd(k, prefix)))
|
||||
print('''\
|
||||
@@ -63,7 +63,7 @@ def gen_index_header(tokens, prefix, value_type, comp_fun, return_type, fail_val
|
||||
return {};
|
||||
}}'''.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)
|
||||
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
|
||||
|
||||
go 1.19
|
||||
go 1.21.1
|
||||
|
||||
require (
|
||||
github.com/bradfitz/gomemcache v0.0.0-20230124162541-5f7a7d875746
|
||||
github.com/quic-go/quic-go v0.33.0
|
||||
github.com/tatsuhiro-t/go-nghttp2 v0.0.0-20150408091349-4742878d9c90
|
||||
golang.org/x/net v0.7.0
|
||||
github.com/bradfitz/gomemcache v0.0.0-20230905024940-24af94b03874
|
||||
github.com/quic-go/quic-go v0.43.1
|
||||
github.com/tatsuhiro-t/go-nghttp2 v0.0.0-20240121064059-46ccb0a462a8
|
||||
golang.org/x/net v0.24.0
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 // indirect
|
||||
github.com/golang/mock v1.6.0 // indirect
|
||||
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect
|
||||
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 // indirect
|
||||
github.com/onsi/ginkgo/v2 v2.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/qtls-go1-19 v0.2.1 // indirect
|
||||
github.com/quic-go/qtls-go1-20 v0.1.1 // indirect
|
||||
golang.org/x/crypto v0.4.0 // indirect
|
||||
go.uber.org/mock v0.4.0 // indirect
|
||||
golang.org/x/crypto v0.22.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20221205204356-47842c84f3db // indirect
|
||||
golang.org/x/mod v0.6.0 // indirect
|
||||
golang.org/x/sys v0.5.0 // indirect
|
||||
golang.org/x/text v0.7.0 // indirect
|
||||
golang.org/x/tools v0.2.0 // indirect
|
||||
golang.org/x/mod v0.11.0 // indirect
|
||||
golang.org/x/sys v0.19.0 // indirect
|
||||
golang.org/x/text v0.14.0 // indirect
|
||||
golang.org/x/tools v0.9.1 // indirect
|
||||
)
|
||||
|
||||
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-20230124162541-5f7a7d875746/go.mod h1:H0wQNHz2YrLsuXOZozoeDmnHXkNCRmMW0gwFWDfEZDA=
|
||||
github.com/bradfitz/gomemcache v0.0.0-20230905024940-24af94b03874 h1:N7oVaKyGp8bttX0bfZGmcGkjz7DLQXhAn3DNd3T0ous=
|
||||
github.com/bradfitz/gomemcache v0.0.0-20230905024940-24af94b03874/go.mod h1:r5xuitiExdLAJ09PR7vBVENGvp4ZuTBeWTGtxuX3K+c=
|
||||
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
||||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
|
||||
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 h1:p104kn46Q8WdvHunIJ9dAyjPVtrBPhSr3KT2yUst43I=
|
||||
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
|
||||
github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc=
|
||||
github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs=
|
||||
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
|
||||
github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg=
|
||||
github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ=
|
||||
github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI=
|
||||
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls=
|
||||
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
|
||||
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
||||
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 h1:yAJXTCF9TqKcTiHJAE8dj7HMvPfh66eeA2JYW7eFpSE=
|
||||
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||
github.com/onsi/ginkgo/v2 v2.2.0 h1:3ZNA3L1c5FYDFTTxbFeVGGD8jYvjYauHD30YgLxVsNI=
|
||||
github.com/onsi/ginkgo/v2 v2.2.0/go.mod h1:MEH45j8TBi6u9BMogfbp0stKC5cdGjumZj5Y7AG4VIk=
|
||||
github.com/onsi/gomega v1.20.1 h1:PA/3qinGoukvymdIDV8pii6tiZgC8kbmJO6Z5+b002Q=
|
||||
github.com/onsi/ginkgo/v2 v2.9.5 h1:+6Hr4uxzP4XIUyAkg61dWBw8lb/gc4/X5luuxN/EC+Q=
|
||||
github.com/onsi/ginkgo/v2 v2.9.5/go.mod h1:tvAoo1QUJwNEU2ITftXTpR7R1RbCzoZUOs3RonqW57k=
|
||||
github.com/onsi/gomega v1.27.6 h1:ENqfyGeS5AX/rlXDd/ETokDz93u0YufY1Pgxuy/PvWE=
|
||||
github.com/onsi/gomega v1.27.6/go.mod h1:PIQNjfQwkP3aQAH7lf7j87O/5FiNr+ZR8+ipb+qQlhg=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/quic-go/qpack v0.4.0 h1:Cr9BXA1sQS2SmDUWjSofMPNKmvF6IiIfDRmgU0w1ZCo=
|
||||
github.com/quic-go/qpack v0.4.0/go.mod h1:UZVnYIfi5GRk+zI9UMaCPsmZ2xKJP7XBUvVyT1Knj9A=
|
||||
github.com/quic-go/qtls-go1-19 v0.2.1 h1:aJcKNMkH5ASEJB9FXNeZCyTEIHU1J7MmHyz1Q1TSG1A=
|
||||
github.com/quic-go/qtls-go1-19 v0.2.1/go.mod h1:ySOI96ew8lnoKPtSqx2BlI5wCpUVPT05RMAlajtnyOI=
|
||||
github.com/quic-go/qtls-go1-20 v0.1.1 h1:KbChDlg82d3IHqaj2bn6GfKRj84Per2VGf5XV3wSwQk=
|
||||
github.com/quic-go/qtls-go1-20 v0.1.1/go.mod h1:JKtK6mjbAVcUTN/9jZpvLbGxvdWIKS8uT7EiStoU1SM=
|
||||
github.com/quic-go/quic-go v0.33.0 h1:ItNoTDN/Fm/zBlq769lLJc8ECe9gYaW40veHCCco7y0=
|
||||
github.com/quic-go/quic-go v0.33.0/go.mod h1:YMuhaAV9/jIu0XclDXwZPAsP/2Kgr5yMYhe9oxhhOFA=
|
||||
github.com/quic-go/quic-go v0.43.1 h1:fLiMNfQVe9q2JvSsiXo4fXOEguXHGGl9+6gLp4RPeZQ=
|
||||
github.com/quic-go/quic-go v0.43.1/go.mod h1:132kz4kL3F9vxhW3CtQJLDVwcFe5wdWeJXXijhsO57M=
|
||||
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.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||
github.com/tatsuhiro-t/go-nghttp2 v0.0.0-20150408091349-4742878d9c90 h1:ccVm9C6f5YMcVv6t9MXahIDkqVvzD6vklkJTIE4D2nY=
|
||||
github.com/tatsuhiro-t/go-nghttp2 v0.0.0-20150408091349-4742878d9c90/go.mod h1:YZhsh86DfZgAShPKeg1eBLVrmuQxWcR9H4TdpgNvSnw=
|
||||
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.4.0 h1:UVQgzMY87xqpKNgb+kDsll2Igd33HszWHFLmpaRMq/8=
|
||||
golang.org/x/crypto v0.4.0/go.mod h1:3quD/ATkf6oY+rnes5c3ExXTbLc8mueNue5/DoinL80=
|
||||
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
|
||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/tatsuhiro-t/go-nghttp2 v0.0.0-20240121064059-46ccb0a462a8 h1:zKJxuRe+a0O34V81GAZWOrotuU6mveT30QLjJ7OPMMg=
|
||||
github.com/tatsuhiro-t/go-nghttp2 v0.0.0-20240121064059-46ccb0a462a8/go.mod h1:gTqc3Q4boc+cKRlSFywTYdX9t6VGRcsThlNIWwaL3Dc=
|
||||
go.uber.org/mock v0.4.0 h1:VcM4ZOtdbR4f6VXfiOpwpVJDL6lCReaZ6mw31wqh7KU=
|
||||
go.uber.org/mock v0.4.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc=
|
||||
golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30=
|
||||
golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M=
|
||||
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/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.6.0 h1:b9gGHsz9/HhJ3HF5DHQytPpuwocVTChQJK3AvoLRD5I=
|
||||
golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
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.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g=
|
||||
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
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/mod v0.11.0 h1:bUO06HqtnRcc/7l71XBe4WcqTZ+3AH1J59zWDDwLKgU=
|
||||
golang.org/x/mod v0.11.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w=
|
||||
golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8=
|
||||
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.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU=
|
||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo=
|
||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
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.2.0 h1:G6AHpWxTMGY1KyEYoAQ5WTtIekUUvDNjan3ugu60JvE=
|
||||
golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA=
|
||||
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=
|
||||
golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o=
|
||||
golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
|
||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
|
||||
golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
||||
golang.org/x/tools v0.9.1 h1:8WMNJAz3zrtPmnYC7ISf5dEn3MT0gY7jBJfw27yrrLo=
|
||||
golang.org/x/tools v0.9.1/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc=
|
||||
google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw=
|
||||
google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
|
||||
@@ -2,6 +2,7 @@ set(GO_FILES
|
||||
nghttpx_http1_test.go
|
||||
nghttpx_http2_test.go
|
||||
server_tester.go
|
||||
server_tester_http3.go
|
||||
)
|
||||
|
||||
# XXX unused
|
||||
@@ -18,12 +19,6 @@ set(EXTRA_DIST
|
||||
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.
|
||||
# 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.
|
||||
@@ -40,7 +35,11 @@ if(NOT CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_CURRENT_BINARY_DIR)
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
if(ENABLE_HTTP3)
|
||||
set(GO_TEST_TAGS quic)
|
||||
endif()
|
||||
|
||||
add_custom_target(it
|
||||
COMMAND sh setenv go test -v
|
||||
COMMAND sh setenv go test -v --tags=${GO_TEST_TAGS}
|
||||
DEPENDS ${GO_BUILD_FILES}
|
||||
)
|
||||
|
||||
@@ -25,7 +25,8 @@ GO_FILES = \
|
||||
nghttpx_http1_test.go \
|
||||
nghttpx_http2_test.go \
|
||||
nghttpx_http3_test.go \
|
||||
server_tester.go
|
||||
server_tester.go \
|
||||
server_tester_http3.go
|
||||
|
||||
EXTRA_DIST = \
|
||||
CMakeLists.txt \
|
||||
|
||||
@@ -58,7 +58,7 @@ func TestH1H1PlainGETClose(t *testing.T) {
|
||||
// 501 status code
|
||||
func TestH1H1InvalidMethod(t *testing.T) {
|
||||
opts := options{
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
handler: func(http.ResponseWriter, *http.Request) {
|
||||
t.Errorf("server should not forward this request")
|
||||
},
|
||||
}
|
||||
@@ -82,7 +82,7 @@ func TestH1H1InvalidMethod(t *testing.T) {
|
||||
// contains multiple Content-Length header fields.
|
||||
func TestH1H1MultipleRequestCL(t *testing.T) {
|
||||
opts := options{
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
handler: func(http.ResponseWriter, *http.Request) {
|
||||
t.Errorf("server should not forward bad request")
|
||||
},
|
||||
}
|
||||
@@ -255,7 +255,7 @@ func TestH1H1HostRewrite(t *testing.T) {
|
||||
// characters in host header field.
|
||||
func TestH1H1BadHost(t *testing.T) {
|
||||
opts := options{
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
handler: func(http.ResponseWriter, *http.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.
|
||||
func TestH1H1BadAuthority(t *testing.T) {
|
||||
opts := options{
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
handler: func(http.ResponseWriter, *http.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.
|
||||
func TestH1H1BadScheme(t *testing.T) {
|
||||
opts := options{
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
handler: func(http.ResponseWriter, *http.Request) {
|
||||
t.Errorf("server should not forward this request")
|
||||
},
|
||||
}
|
||||
@@ -394,7 +394,7 @@ func TestH1H1HTTP10NoHostRewrite(t *testing.T) {
|
||||
// backend.
|
||||
func TestH1H1RequestTrailer(t *testing.T) {
|
||||
opts := options{
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
handler: func(_ http.ResponseWriter, r *http.Request) {
|
||||
buf := make([]byte, 4096)
|
||||
for {
|
||||
_, err := r.Body.Read(buf)
|
||||
@@ -436,7 +436,7 @@ func TestH1H1HeaderFieldBufferPath(t *testing.T) {
|
||||
// limit.
|
||||
opts := options{
|
||||
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")
|
||||
},
|
||||
}
|
||||
@@ -460,7 +460,7 @@ func TestH1H1HeaderFieldBufferPath(t *testing.T) {
|
||||
func TestH1H1HeaderFieldBuffer(t *testing.T) {
|
||||
opts := options{
|
||||
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")
|
||||
},
|
||||
}
|
||||
@@ -483,7 +483,7 @@ func TestH1H1HeaderFieldBuffer(t *testing.T) {
|
||||
func TestH1H1HeaderFields(t *testing.T) {
|
||||
opts := options{
|
||||
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")
|
||||
},
|
||||
}
|
||||
@@ -533,7 +533,7 @@ func TestH1H1Websocket(t *testing.T) {
|
||||
func TestH1H1ReqPhaseSetHeader(t *testing.T) {
|
||||
opts := options{
|
||||
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 {
|
||||
t.Errorf("User-Agent = %v; want %v", got, want)
|
||||
}
|
||||
@@ -559,7 +559,7 @@ func TestH1H1ReqPhaseSetHeader(t *testing.T) {
|
||||
func TestH1H1ReqPhaseReturn(t *testing.T) {
|
||||
opts := options{
|
||||
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")
|
||||
},
|
||||
}
|
||||
@@ -599,7 +599,7 @@ func TestH1H1ReqPhaseReturn(t *testing.T) {
|
||||
func TestH1H1ReqPhaseReturnCONNECTMethod(t *testing.T) {
|
||||
opts := options{
|
||||
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")
|
||||
},
|
||||
}
|
||||
@@ -884,7 +884,7 @@ func TestH1H1CONNECTMethodFailure(t *testing.T) {
|
||||
func TestH1H2NoHost(t *testing.T) {
|
||||
opts := options{
|
||||
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")
|
||||
},
|
||||
}
|
||||
@@ -978,7 +978,7 @@ func TestH1H2HTTP10NoHostRewrite(t *testing.T) {
|
||||
func TestH1H2CrumbleCookie(t *testing.T) {
|
||||
opts := options{
|
||||
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 {
|
||||
t.Errorf("Cookie: %v; want %v", got, want)
|
||||
}
|
||||
@@ -1006,7 +1006,7 @@ func TestH1H2CrumbleCookie(t *testing.T) {
|
||||
func TestH1H2GenerateVia(t *testing.T) {
|
||||
opts := options{
|
||||
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 {
|
||||
t.Errorf("Via: %v; want %v", got, want)
|
||||
}
|
||||
@@ -1092,7 +1092,7 @@ func TestH1H2ReqPhaseReturn(t *testing.T) {
|
||||
"--http2-bridge",
|
||||
"--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")
|
||||
},
|
||||
}
|
||||
@@ -1172,7 +1172,7 @@ func TestH1H2RespPhaseReturn(t *testing.T) {
|
||||
func TestH1H2TE(t *testing.T) {
|
||||
opts := options{
|
||||
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 {
|
||||
t.Errorf("te: %v; want %v", got, want)
|
||||
}
|
||||
@@ -1200,7 +1200,7 @@ func TestH1H2TE(t *testing.T) {
|
||||
func TestH1APIBackendconfig(t *testing.T) {
|
||||
opts := options{
|
||||
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")
|
||||
},
|
||||
connectPort: 3010,
|
||||
@@ -1242,7 +1242,7 @@ backend=127.0.0.1,3011
|
||||
func TestH1APIBackendconfigQuery(t *testing.T) {
|
||||
opts := options{
|
||||
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")
|
||||
},
|
||||
connectPort: 3010,
|
||||
@@ -1284,7 +1284,7 @@ backend=127.0.0.1,3011
|
||||
func TestH1APIBackendconfigBadMethod(t *testing.T) {
|
||||
opts := options{
|
||||
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")
|
||||
},
|
||||
connectPort: 3010,
|
||||
@@ -1325,7 +1325,7 @@ backend=127.0.0.1,3011
|
||||
func TestH1APIConfigrevision(t *testing.T) {
|
||||
opts := options{
|
||||
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")
|
||||
},
|
||||
connectPort: 3010,
|
||||
@@ -1368,7 +1368,7 @@ func TestH1APIConfigrevision(t *testing.T) {
|
||||
func TestH1APINotFound(t *testing.T) {
|
||||
opts := options{
|
||||
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")
|
||||
},
|
||||
connectPort: 3010,
|
||||
@@ -1409,7 +1409,7 @@ backend=127.0.0.1,3011
|
||||
func TestH1Healthmon(t *testing.T) {
|
||||
opts := options{
|
||||
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")
|
||||
},
|
||||
connectPort: 3011,
|
||||
@@ -1434,7 +1434,7 @@ func TestH1Healthmon(t *testing.T) {
|
||||
func TestH1ResponseBeforeRequestEnd(t *testing.T) {
|
||||
opts := options{
|
||||
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")
|
||||
},
|
||||
}
|
||||
@@ -1462,7 +1462,7 @@ func TestH1ResponseBeforeRequestEnd(t *testing.T) {
|
||||
// if the backend chunked encoded response ends prematurely.
|
||||
func TestH1H1ChunkedEndsPrematurely(t *testing.T) {
|
||||
opts := options{
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
handler: func(w http.ResponseWriter, _ *http.Request) {
|
||||
hj, ok := w.(http.Hijacker)
|
||||
if !ok {
|
||||
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")
|
||||
}
|
||||
}
|
||||
|
||||
// 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) {
|
||||
opts := options{
|
||||
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")
|
||||
if got, want := xfp, "foo, http"; 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-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")
|
||||
if got, want := xfp, "foo"; 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.
|
||||
func TestH2H1StripXfp(t *testing.T) {
|
||||
opts := options{
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
handler: func(_ http.ResponseWriter, r *http.Request) {
|
||||
xfp := r.Header.Get("X-Forwarded-Proto")
|
||||
if got, want := xfp, "http"; 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) {
|
||||
opts := options{
|
||||
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 {
|
||||
t.Errorf("X-Forwarded-Proto = %q; want nothing", got)
|
||||
}
|
||||
@@ -157,7 +157,7 @@ func TestH2H1StripNoAddXfp(t *testing.T) {
|
||||
func TestH2H1AddXff(t *testing.T) {
|
||||
opts := options{
|
||||
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")
|
||||
want := "127.0.0.1"
|
||||
if xff != want {
|
||||
@@ -184,7 +184,7 @@ func TestH2H1AddXff(t *testing.T) {
|
||||
func TestH2H1AddXff2(t *testing.T) {
|
||||
opts := options{
|
||||
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")
|
||||
want := "host, 127.0.0.1"
|
||||
if xff != want {
|
||||
@@ -214,7 +214,7 @@ func TestH2H1AddXff2(t *testing.T) {
|
||||
func TestH2H1StripXff(t *testing.T) {
|
||||
opts := options{
|
||||
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 {
|
||||
t.Errorf("X-Forwarded-For = %v; want nothing", xff)
|
||||
}
|
||||
@@ -245,7 +245,7 @@ func TestH2H1StripAddXff(t *testing.T) {
|
||||
"--strip-incoming-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")
|
||||
want := "127.0.0.1"
|
||||
if xff != want {
|
||||
@@ -275,7 +275,7 @@ func TestH2H1StripAddXff(t *testing.T) {
|
||||
func TestH2H1AddForwardedObfuscated(t *testing.T) {
|
||||
opts := options{
|
||||
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)
|
||||
validFwd := regexp.MustCompile(pattern)
|
||||
got := r.Header.Get("Forwarded")
|
||||
@@ -304,7 +304,7 @@ func TestH2H1AddForwardedObfuscated(t *testing.T) {
|
||||
func TestH2H1AddForwardedByIP(t *testing.T) {
|
||||
opts := options{
|
||||
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)
|
||||
validFwd := regexp.MustCompile(pattern)
|
||||
if got := r.Header.Get("Forwarded"); !validFwd.MatchString(got) {
|
||||
@@ -335,7 +335,7 @@ func TestH2H1AddForwardedForIP(t *testing.T) {
|
||||
"--forwarded-by=_alpha",
|
||||
"--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)
|
||||
if got := r.Header.Get("Forwarded"); got != want {
|
||||
t.Errorf("Forwarded = %v; want %v", got, want)
|
||||
@@ -362,7 +362,7 @@ func TestH2H1AddForwardedForIP(t *testing.T) {
|
||||
func TestH2H1AddForwardedMerge(t *testing.T) {
|
||||
opts := options{
|
||||
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 {
|
||||
t.Errorf("Forwarded = %v; want %v", got, want)
|
||||
}
|
||||
@@ -394,7 +394,7 @@ func TestH2H1AddForwardedStrip(t *testing.T) {
|
||||
"--strip-incoming-forwarded",
|
||||
"--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 {
|
||||
t.Errorf("Forwarded = %v; want %v", got, want)
|
||||
}
|
||||
@@ -422,7 +422,7 @@ func TestH2H1AddForwardedStrip(t *testing.T) {
|
||||
func TestH2H1StripForwarded(t *testing.T) {
|
||||
opts := options{
|
||||
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 {
|
||||
t.Errorf("Forwarded = %v; want nothing", got)
|
||||
}
|
||||
@@ -454,7 +454,7 @@ func TestH2H1AddForwardedStatic(t *testing.T) {
|
||||
"--add-forwarded=by,for",
|
||||
"--forwarded-by=_alpha",
|
||||
},
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
handler: func(_ http.ResponseWriter, r *http.Request) {
|
||||
pattern := `by=_alpha;for=_[^;]+`
|
||||
validFwd := regexp.MustCompile(pattern)
|
||||
if got := r.Header.Get("Forwarded"); !validFwd.MatchString(got) {
|
||||
@@ -480,7 +480,7 @@ func TestH2H1AddForwardedStatic(t *testing.T) {
|
||||
// from backend server.
|
||||
func TestH2H1GenerateVia(t *testing.T) {
|
||||
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 {
|
||||
t.Errorf("Via: %v; want %v", got, want)
|
||||
}
|
||||
@@ -639,7 +639,7 @@ func TestH2H1BadRequestCL(t *testing.T) {
|
||||
// response body size.
|
||||
func TestH2H1BadResponseCL(t *testing.T) {
|
||||
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.
|
||||
w.Header().Add("Content-Length", "1024")
|
||||
if _, err := w.Write([]byte("foo")); err != nil {
|
||||
@@ -667,7 +667,7 @@ func TestH2H1BadResponseCL(t *testing.T) {
|
||||
// works.
|
||||
func TestH2H1LocationRewrite(t *testing.T) {
|
||||
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
|
||||
// here.. 8443 is just a place holder. We
|
||||
// ignore it on rewrite.
|
||||
@@ -693,7 +693,7 @@ func TestH2H1LocationRewrite(t *testing.T) {
|
||||
// TestH2H1ChunkedRequestBody tests that chunked request body works.
|
||||
func TestH2H1ChunkedRequestBody(t *testing.T) {
|
||||
opts := options{
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
handler: func(_ http.ResponseWriter, r *http.Request) {
|
||||
want := "[chunked]"
|
||||
if got := fmt.Sprint(r.TransferEncoding); 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.
|
||||
func TestH2H1MultipleRequestCL(t *testing.T) {
|
||||
opts := options{
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
handler: func(http.ResponseWriter, *http.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.
|
||||
func TestH2H1InvalidRequestCL(t *testing.T) {
|
||||
opts := options{
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
handler: func(http.ResponseWriter, *http.Request) {
|
||||
t.Errorf("server should not forward bad request")
|
||||
},
|
||||
}
|
||||
@@ -800,7 +800,7 @@ func TestH2H1InvalidRequestCL(t *testing.T) {
|
||||
// 501.
|
||||
func TestH2H1InvalidMethod(t *testing.T) {
|
||||
opts := options{
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
handler: func(http.ResponseWriter, *http.Request) {
|
||||
t.Errorf("server should not forward this request")
|
||||
},
|
||||
}
|
||||
@@ -823,7 +823,7 @@ func TestH2H1InvalidMethod(t *testing.T) {
|
||||
// bad characters in :authority header field.
|
||||
func TestH2H1BadAuthority(t *testing.T) {
|
||||
opts := options{
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
handler: func(http.ResponseWriter, *http.Request) {
|
||||
t.Errorf("server should not forward this request")
|
||||
},
|
||||
}
|
||||
@@ -846,7 +846,7 @@ func TestH2H1BadAuthority(t *testing.T) {
|
||||
// bad characters in :scheme header field.
|
||||
func TestH2H1BadScheme(t *testing.T) {
|
||||
opts := options{
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
handler: func(http.ResponseWriter, *http.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.
|
||||
func TestH2H1AssembleCookies(t *testing.T) {
|
||||
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 {
|
||||
t.Errorf("Cookie: %v; want %v", got, want)
|
||||
}
|
||||
@@ -918,7 +918,7 @@ func TestH2H1TETrailers(t *testing.T) {
|
||||
// field contains gzip.
|
||||
func TestH2H1TEGzip(t *testing.T) {
|
||||
opts := options{
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
handler: func(http.ResponseWriter, *http.Request) {
|
||||
t.Error("server should not forward bad request")
|
||||
},
|
||||
}
|
||||
@@ -967,7 +967,7 @@ func TestH2H1SNI(t *testing.T) {
|
||||
// connection is encrypted.
|
||||
func TestH2H1TLSXfp(t *testing.T) {
|
||||
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 {
|
||||
t.Errorf("x-forwarded-proto: want %v; got %v", want, got)
|
||||
}
|
||||
@@ -1028,7 +1028,7 @@ func TestH2H1ServerPush(t *testing.T) {
|
||||
// backend.
|
||||
func TestH2H1RequestTrailer(t *testing.T) {
|
||||
opts := options{
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
handler: func(_ http.ResponseWriter, r *http.Request) {
|
||||
buf := make([]byte, 4096)
|
||||
for {
|
||||
_, err := r.Body.Read(buf)
|
||||
@@ -1067,7 +1067,7 @@ func TestH2H1RequestTrailer(t *testing.T) {
|
||||
func TestH2H1HeaderFieldBuffer(t *testing.T) {
|
||||
opts := options{
|
||||
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")
|
||||
},
|
||||
}
|
||||
@@ -1090,7 +1090,7 @@ func TestH2H1HeaderFieldBuffer(t *testing.T) {
|
||||
func TestH2H1HeaderFields(t *testing.T) {
|
||||
opts := options{
|
||||
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")
|
||||
},
|
||||
}
|
||||
@@ -1115,7 +1115,7 @@ func TestH2H1HeaderFields(t *testing.T) {
|
||||
func TestH2H1ReqPhaseSetHeader(t *testing.T) {
|
||||
opts := options{
|
||||
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 {
|
||||
t.Errorf("User-Agent = %v; want %v", got, want)
|
||||
}
|
||||
@@ -1141,7 +1141,7 @@ func TestH2H1ReqPhaseSetHeader(t *testing.T) {
|
||||
func TestH2H1ReqPhaseReturn(t *testing.T) {
|
||||
opts := options{
|
||||
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")
|
||||
},
|
||||
}
|
||||
@@ -1284,7 +1284,7 @@ func TestH2H1ProxyProtocolV1ForwardedForObfuscated(t *testing.T) {
|
||||
"--add-forwarded=for",
|
||||
"--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) {
|
||||
t.Errorf("Forwarded: %v; want pattern %v", got, pattern)
|
||||
}
|
||||
@@ -1321,7 +1321,7 @@ func TestH2H1ProxyProtocolV1TCP4(t *testing.T) {
|
||||
"--add-forwarded=for",
|
||||
"--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 {
|
||||
t.Errorf("X-Forwarded-For: %v; want %v", got, want)
|
||||
}
|
||||
@@ -1361,7 +1361,7 @@ func TestH2H1ProxyProtocolV1TCP6(t *testing.T) {
|
||||
"--add-forwarded=for",
|
||||
"--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 {
|
||||
t.Errorf("X-Forwarded-For: %v; want %v", got, want)
|
||||
}
|
||||
@@ -1401,7 +1401,7 @@ func TestH2H1ProxyProtocolV1TCP4TLS(t *testing.T) {
|
||||
"--add-forwarded=for",
|
||||
"--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 {
|
||||
t.Errorf("X-Forwarded-For: %v; want %v", got, want)
|
||||
}
|
||||
@@ -1439,7 +1439,7 @@ func TestH2H1ProxyProtocolV1TCP6TLS(t *testing.T) {
|
||||
"--add-forwarded=for",
|
||||
"--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 {
|
||||
t.Errorf("X-Forwarded-For: %v; want %v", got, want)
|
||||
}
|
||||
@@ -1476,7 +1476,7 @@ func TestH2H1ProxyProtocolV1Unknown(t *testing.T) {
|
||||
"--add-forwarded=for",
|
||||
"--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 {
|
||||
t.Errorf("X-Forwarded-For: %v; want something else", got)
|
||||
}
|
||||
@@ -1881,7 +1881,7 @@ func TestH2H1ProxyProtocolV2TCP4(t *testing.T) {
|
||||
"--add-forwarded=for",
|
||||
"--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 {
|
||||
t.Errorf("X-Forwarded-For: %v; want %v", got, want)
|
||||
}
|
||||
@@ -1937,7 +1937,7 @@ func TestH2H1ProxyProtocolV2TCP6(t *testing.T) {
|
||||
"--add-forwarded=for",
|
||||
"--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 {
|
||||
t.Errorf("X-Forwarded-For: %v; want %v", got, want)
|
||||
}
|
||||
@@ -2009,7 +2009,7 @@ func TestH2H1ProxyProtocolV2TCP4TLS(t *testing.T) {
|
||||
"--add-forwarded=for",
|
||||
"--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 {
|
||||
t.Errorf("X-Forwarded-For: %v; want %v", got, want)
|
||||
}
|
||||
@@ -2063,7 +2063,7 @@ func TestH2H1ProxyProtocolV2TCP6TLS(t *testing.T) {
|
||||
"--add-forwarded=for",
|
||||
"--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 {
|
||||
t.Errorf("X-Forwarded-For: %v; want %v", got, want)
|
||||
}
|
||||
@@ -2100,7 +2100,7 @@ func TestH2H1ProxyProtocolV2Local(t *testing.T) {
|
||||
"--add-forwarded=for",
|
||||
"--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 {
|
||||
t.Errorf("X-Forwarded-For: %v; want %v", got, want)
|
||||
}
|
||||
@@ -2193,7 +2193,7 @@ func TestH2H1ProxyProtocolV2Unix(t *testing.T) {
|
||||
"--add-forwarded=for",
|
||||
"--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 {
|
||||
t.Errorf("X-Forwarded-For: %v; want %v", got, want)
|
||||
}
|
||||
@@ -2248,7 +2248,7 @@ func TestH2H1ProxyProtocolV2Unspec(t *testing.T) {
|
||||
"--add-forwarded=for",
|
||||
"--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 {
|
||||
t.Errorf("X-Forwarded-For: %v; want %v", got, want)
|
||||
}
|
||||
@@ -2383,7 +2383,7 @@ func TestH2H1HTTPSRedirectPort(t *testing.T) {
|
||||
// transfer-encoding is valid.
|
||||
func TestH2H1Code204(t *testing.T) {
|
||||
opts := options{
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
handler: func(w http.ResponseWriter, _ *http.Request) {
|
||||
w.WriteHeader(http.StatusNoContent)
|
||||
},
|
||||
}
|
||||
@@ -2406,7 +2406,7 @@ func TestH2H1Code204(t *testing.T) {
|
||||
// is allowed.
|
||||
func TestH2H1Code204CL0(t *testing.T) {
|
||||
opts := options{
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
handler: func(w http.ResponseWriter, _ *http.Request) {
|
||||
hj, ok := w.(http.Hijacker)
|
||||
if !ok {
|
||||
http.Error(w, "Could not hijack the connection", http.StatusInternalServerError)
|
||||
@@ -2447,7 +2447,7 @@ func TestH2H1Code204CL0(t *testing.T) {
|
||||
// content-length is not allowed.
|
||||
func TestH2H1Code204CLNonzero(t *testing.T) {
|
||||
opts := options{
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
handler: func(w http.ResponseWriter, _ *http.Request) {
|
||||
hj, ok := w.(http.Hijacker)
|
||||
if !ok {
|
||||
http.Error(w, "Could not hijack the connection", http.StatusInternalServerError)
|
||||
@@ -2484,7 +2484,7 @@ func TestH2H1Code204CLNonzero(t *testing.T) {
|
||||
// not allowed.
|
||||
func TestH2H1Code204TE(t *testing.T) {
|
||||
opts := options{
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
handler: func(w http.ResponseWriter, _ *http.Request) {
|
||||
hj, ok := w.(http.Hijacker)
|
||||
if !ok {
|
||||
http.Error(w, "Could not hijack the connection", http.StatusInternalServerError)
|
||||
@@ -2659,7 +2659,7 @@ func TestH2H1GracefulShutdown(t *testing.T) {
|
||||
func TestH2H2MultipleResponseCL(t *testing.T) {
|
||||
opts := options{
|
||||
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")
|
||||
},
|
||||
@@ -2684,7 +2684,7 @@ func TestH2H2MultipleResponseCL(t *testing.T) {
|
||||
func TestH2H2InvalidResponseCL(t *testing.T) {
|
||||
opts := options{
|
||||
args: []string{"--http2-bridge"},
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
handler: func(w http.ResponseWriter, _ *http.Request) {
|
||||
w.Header().Add("content-length", "")
|
||||
},
|
||||
}
|
||||
@@ -2783,7 +2783,7 @@ func TestH2H2NoHostRewrite(t *testing.T) {
|
||||
func TestH2H2TLSXfp(t *testing.T) {
|
||||
opts := options{
|
||||
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 {
|
||||
t.Errorf("x-forwarded-proto: want %v; got %v", want, got)
|
||||
}
|
||||
@@ -2812,7 +2812,7 @@ func TestH2H2AddXfp(t *testing.T) {
|
||||
"--http2-bridge",
|
||||
"--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")
|
||||
if got, want := xfp, "foo, http"; 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-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")
|
||||
if got, want := xfp, "foo"; 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) {
|
||||
opts := options{
|
||||
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")
|
||||
if got, want := xfp, "http"; 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) {
|
||||
opts := options{
|
||||
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 {
|
||||
t.Errorf("X-Forwarded-Proto = %q; want nothing", got)
|
||||
}
|
||||
@@ -2935,7 +2935,7 @@ func TestH2H2StripNoAddXfp(t *testing.T) {
|
||||
func TestH2H2AddXff(t *testing.T) {
|
||||
opts := options{
|
||||
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")
|
||||
want := "127.0.0.1"
|
||||
if xff != want {
|
||||
@@ -2963,7 +2963,7 @@ func TestH2H2AddXff(t *testing.T) {
|
||||
func TestH2H2AddXff2(t *testing.T) {
|
||||
opts := options{
|
||||
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")
|
||||
want := "host, 127.0.0.1"
|
||||
if xff != want {
|
||||
@@ -2997,7 +2997,7 @@ func TestH2H2StripXff(t *testing.T) {
|
||||
"--http2-bridge",
|
||||
"--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 {
|
||||
t.Errorf("X-Forwarded-For = %v; want nothing", xff)
|
||||
}
|
||||
@@ -3030,7 +3030,7 @@ func TestH2H2StripAddXff(t *testing.T) {
|
||||
"--strip-incoming-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")
|
||||
want := "127.0.0.1"
|
||||
if xff != want {
|
||||
@@ -3065,7 +3065,7 @@ func TestH2H2AddForwarded(t *testing.T) {
|
||||
"--add-forwarded=by,for,host,proto",
|
||||
"--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)
|
||||
validFwd := regexp.MustCompile(pattern)
|
||||
if got := r.Header.Get("Forwarded"); !validFwd.MatchString(got) {
|
||||
@@ -3099,7 +3099,7 @@ func TestH2H2AddForwardedMerge(t *testing.T) {
|
||||
"--add-forwarded=by,host,proto",
|
||||
"--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)
|
||||
if got := r.Header.Get("Forwarded"); got != want {
|
||||
t.Errorf("Forwarded = %v; want %v", got, want)
|
||||
@@ -3136,7 +3136,7 @@ func TestH2H2AddForwardedStrip(t *testing.T) {
|
||||
"--add-forwarded=by,host,proto",
|
||||
"--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)
|
||||
if got := r.Header.Get("Forwarded"); got != want {
|
||||
t.Errorf("Forwarded = %v; want %v", got, want)
|
||||
@@ -3167,7 +3167,7 @@ func TestH2H2AddForwardedStrip(t *testing.T) {
|
||||
func TestH2H2StripForwarded(t *testing.T) {
|
||||
opts := options{
|
||||
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 {
|
||||
t.Errorf("Forwarded = %v; want nothing", got)
|
||||
}
|
||||
@@ -3200,7 +3200,7 @@ func TestH2H2ReqPhaseReturn(t *testing.T) {
|
||||
"--http2-bridge",
|
||||
"--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")
|
||||
},
|
||||
}
|
||||
@@ -3322,7 +3322,7 @@ func TestH2H2DNS(t *testing.T) {
|
||||
func TestH2H2Code204(t *testing.T) {
|
||||
opts := options{
|
||||
args: []string{"--http2-bridge"},
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
handler: func(w http.ResponseWriter, _ *http.Request) {
|
||||
w.WriteHeader(http.StatusNoContent)
|
||||
},
|
||||
}
|
||||
@@ -3346,7 +3346,7 @@ func TestH2H2Code204(t *testing.T) {
|
||||
func TestH2APIBackendconfig(t *testing.T) {
|
||||
opts := options{
|
||||
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")
|
||||
},
|
||||
connectPort: 3010,
|
||||
@@ -3388,7 +3388,7 @@ backend=127.0.0.1,3011
|
||||
func TestH2APIBackendconfigQuery(t *testing.T) {
|
||||
opts := options{
|
||||
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")
|
||||
},
|
||||
connectPort: 3010,
|
||||
@@ -3430,7 +3430,7 @@ backend=127.0.0.1,3011
|
||||
func TestH2APIBackendconfigBadMethod(t *testing.T) {
|
||||
opts := options{
|
||||
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")
|
||||
},
|
||||
connectPort: 3010,
|
||||
@@ -3471,7 +3471,7 @@ backend=127.0.0.1,3011
|
||||
func TestH2APIConfigrevision(t *testing.T) {
|
||||
opts := options{
|
||||
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")
|
||||
},
|
||||
connectPort: 3010,
|
||||
@@ -3514,7 +3514,7 @@ func TestH2APIConfigrevision(t *testing.T) {
|
||||
func TestH2APINotFound(t *testing.T) {
|
||||
opts := options{
|
||||
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")
|
||||
},
|
||||
connectPort: 3010,
|
||||
@@ -3555,7 +3555,7 @@ backend=127.0.0.1,3011
|
||||
func TestH2Healthmon(t *testing.T) {
|
||||
opts := options{
|
||||
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")
|
||||
},
|
||||
connectPort: 3011,
|
||||
@@ -3580,7 +3580,7 @@ func TestH2Healthmon(t *testing.T) {
|
||||
func TestH2ResponseBeforeRequestEnd(t *testing.T) {
|
||||
opts := options{
|
||||
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")
|
||||
},
|
||||
}
|
||||
@@ -3603,7 +3603,7 @@ func TestH2ResponseBeforeRequestEnd(t *testing.T) {
|
||||
// backend chunked encoded response ends prematurely.
|
||||
func TestH2H1ChunkedEndsPrematurely(t *testing.T) {
|
||||
opts := options{
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
handler: func(w http.ResponseWriter, _ *http.Request) {
|
||||
hj, ok := w.(http.Hijacker)
|
||||
if !ok {
|
||||
http.Error(w, "Could not hijack the connection", http.StatusInternalServerError)
|
||||
@@ -3641,7 +3641,7 @@ func TestH2H1ChunkedEndsPrematurely(t *testing.T) {
|
||||
func TestH2H1RequireHTTPSchemeHTTPSWithoutEncryption(t *testing.T) {
|
||||
opts := options{
|
||||
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")
|
||||
},
|
||||
}
|
||||
@@ -3666,7 +3666,7 @@ func TestH2H1RequireHTTPSchemeHTTPSWithoutEncryption(t *testing.T) {
|
||||
func TestH2H1RequireHTTPSchemeHTTPWithEncryption(t *testing.T) {
|
||||
opts := options{
|
||||
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")
|
||||
},
|
||||
tls: true,
|
||||
@@ -3693,7 +3693,7 @@ func TestH2H1RequireHTTPSchemeHTTPWithEncryption(t *testing.T) {
|
||||
func TestH2H1RequireHTTPSchemeUnknownSchemeWithoutEncryption(t *testing.T) {
|
||||
opts := options{
|
||||
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")
|
||||
},
|
||||
}
|
||||
@@ -3718,7 +3718,7 @@ func TestH2H1RequireHTTPSchemeUnknownSchemeWithoutEncryption(t *testing.T) {
|
||||
func TestH2H1RequireHTTPSchemeUnknownSchemeWithEncryption(t *testing.T) {
|
||||
opts := options{
|
||||
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")
|
||||
},
|
||||
tls: true,
|
||||
|
||||
@@ -41,7 +41,7 @@ func TestH3H1RequestBody(t *testing.T) {
|
||||
}
|
||||
|
||||
opts := options{
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
handler: func(_ http.ResponseWriter, r *http.Request) {
|
||||
buf := make([]byte, 4096)
|
||||
buflen := 0
|
||||
p := buf
|
||||
@@ -92,7 +92,7 @@ func TestH3H1RequestBody(t *testing.T) {
|
||||
// and from backend server.
|
||||
func TestH3H1GenerateVia(t *testing.T) {
|
||||
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 {
|
||||
t.Errorf("Via: %v; want %v", got, want)
|
||||
}
|
||||
@@ -177,7 +177,7 @@ func TestH3H1NoVia(t *testing.T) {
|
||||
// response body size.
|
||||
func TestH3H1BadResponseCL(t *testing.T) {
|
||||
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.
|
||||
w.Header().Add("Content-Length", "1024")
|
||||
if _, err := w.Write([]byte("foo")); err != nil {
|
||||
@@ -256,7 +256,7 @@ func TestH3H2ReqPhaseReturn(t *testing.T) {
|
||||
"--http2-bridge",
|
||||
"--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")
|
||||
},
|
||||
quic: true,
|
||||
@@ -338,7 +338,7 @@ func TestH3H2RespPhaseReturn(t *testing.T) {
|
||||
func TestH3ResponseBeforeRequestEnd(t *testing.T) {
|
||||
opts := options{
|
||||
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")
|
||||
},
|
||||
quic: true,
|
||||
@@ -362,7 +362,7 @@ func TestH3ResponseBeforeRequestEnd(t *testing.T) {
|
||||
// backend chunked encoded response ends prematurely.
|
||||
func TestH3H1ChunkedEndsPrematurely(t *testing.T) {
|
||||
opts := options{
|
||||
handler: func(w http.ResponseWriter, r *http.Request) {
|
||||
handler: func(w http.ResponseWriter, _ *http.Request) {
|
||||
hj, ok := w.(http.Hijacker)
|
||||
if !ok {
|
||||
http.Error(w, "Could not hijack the connection", http.StatusInternalServerError)
|
||||
|
||||
@@ -22,7 +22,6 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/quic-go/quic-go/http3"
|
||||
"github.com/tatsuhiro-t/go-nghttp2"
|
||||
"golang.org/x/net/http2"
|
||||
"golang.org/x/net/http2/hpack"
|
||||
@@ -390,81 +389,6 @@ func (st *serverTester) websocket(rp requestParam) *serverResponse {
|
||||
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) {
|
||||
method := "GET"
|
||||
if rp.method != "" {
|
||||
@@ -728,7 +652,7 @@ type serverResponse struct {
|
||||
errCode http2.ErrCode // error code received in HTTP/2 RST_STREAM or GOAWAY
|
||||
connErr bool // true if HTTP/2 connection error
|
||||
connClose bool // Connection: close is included in response header in HTTP/1 test
|
||||
reqHeader http.Header // http request header, currently only sotres pushed request header
|
||||
reqHeader http.Header // http request header, currently only stores pushed request header
|
||||
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_LDFLAGS="-L$libdir @LDFLAGS@"
|
||||
export LD_LIBRARY_PATH="$libdir"
|
||||
export DYLD_LIBRARY_PATH="$libdir"
|
||||
export GODEBUG=cgocheck=0
|
||||
"$@"
|
||||
|
||||
@@ -14,7 +14,7 @@ set(NGHTTP2_SOURCES
|
||||
nghttp2_stream.c nghttp2_outbound_item.c
|
||||
nghttp2_session.c nghttp2_submit.c
|
||||
nghttp2_helper.c
|
||||
nghttp2_npn.c
|
||||
nghttp2_alpn.c
|
||||
nghttp2_hd.c nghttp2_hd_huffman.c nghttp2_hd_huffman_data.c
|
||||
nghttp2_version.c
|
||||
nghttp2_priority_spec.c
|
||||
@@ -24,11 +24,19 @@ set(NGHTTP2_SOURCES
|
||||
nghttp2_http.c
|
||||
nghttp2_rcbuf.c
|
||||
nghttp2_extpri.c
|
||||
nghttp2_ratelim.c
|
||||
nghttp2_time.c
|
||||
nghttp2_debug.c
|
||||
sfparse.c
|
||||
)
|
||||
|
||||
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)
|
||||
configure_file(
|
||||
@@ -39,40 +47,61 @@ if(WIN32)
|
||||
set(NGHTTP2_RES ${CMAKE_CURRENT_BINARY_DIR}/version.rc)
|
||||
endif()
|
||||
|
||||
set(EXPORT_SET "${PROJECT_NAME}-targets")
|
||||
|
||||
# Public shared library
|
||||
if(ENABLE_SHARED_LIB)
|
||||
add_library(nghttp2 SHARED ${NGHTTP2_SOURCES} ${NGHTTP2_RES})
|
||||
set_target_properties(nghttp2 PROPERTIES
|
||||
if(BUILD_SHARED_LIBS)
|
||||
add_library(${SHARED_LIB} SHARED ${NGHTTP2_SOURCES} ${NGHTTP2_RES})
|
||||
|
||||
set_target_properties(${SHARED_LIB} PROPERTIES
|
||||
COMPILE_FLAGS "${WARNCFLAGS}"
|
||||
VERSION ${LT_VERSION} SOVERSION ${LT_SOVERSION}
|
||||
C_VISIBILITY_PRESET hidden
|
||||
)
|
||||
target_include_directories(nghttp2 INTERFACE
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/includes"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/includes"
|
||||
|
||||
target_include_directories(${SHARED_LIB} INTERFACE
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/includes>
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}/includes>
|
||||
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
|
||||
)
|
||||
|
||||
install(TARGETS nghttp2
|
||||
ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}"
|
||||
LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}"
|
||||
RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}")
|
||||
install(TARGETS ${SHARED_LIB} EXPORT ${EXPORT_SET})
|
||||
list(APPEND nghttp2_exports ${SHARED_LIB})
|
||||
endif()
|
||||
|
||||
if(HAVE_CUNIT OR ENABLE_STATIC_LIB)
|
||||
# Static library (for unittests because of symbol visibility)
|
||||
add_library(nghttp2_static STATIC ${NGHTTP2_SOURCES})
|
||||
set_target_properties(nghttp2_static PROPERTIES
|
||||
# Static library (for unittests because of symbol visibility)
|
||||
if(BUILD_STATIC_LIBS)
|
||||
add_library(${STATIC_LIB} STATIC ${NGHTTP2_SOURCES})
|
||||
|
||||
set_target_properties(${STATIC_LIB} PROPERTIES
|
||||
COMPILE_FLAGS "${WARNCFLAGS}"
|
||||
VERSION ${LT_VERSION} SOVERSION ${LT_SOVERSION}
|
||||
ARCHIVE_OUTPUT_NAME nghttp2${STATIC_LIB_SUFFIX}
|
||||
)
|
||||
target_compile_definitions(nghttp2_static PUBLIC "-DNGHTTP2_STATICLIB")
|
||||
if(ENABLE_STATIC_LIB)
|
||||
install(TARGETS nghttp2_static
|
||||
DESTINATION "${CMAKE_INSTALL_LIBDIR}")
|
||||
endif()
|
||||
|
||||
target_include_directories(${STATIC_LIB} INTERFACE
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/includes>
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}/includes>
|
||||
$<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()
|
||||
|
||||
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"
|
||||
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_session.c nghttp2_submit.c \
|
||||
nghttp2_helper.c \
|
||||
nghttp2_npn.c \
|
||||
nghttp2_alpn.c \
|
||||
nghttp2_hd.c nghttp2_hd_huffman.c nghttp2_hd_huffman_data.c \
|
||||
nghttp2_version.c \
|
||||
nghttp2_priority_spec.c \
|
||||
@@ -51,6 +51,8 @@ OBJECTS = nghttp2_pq.c nghttp2_map.c nghttp2_queue.c \
|
||||
nghttp2_http.c \
|
||||
nghttp2_rcbuf.c \
|
||||
nghttp2_extpri.c \
|
||||
nghttp2_ratelim.c \
|
||||
nghttp2_time.c \
|
||||
nghttp2_debug.c \
|
||||
sfparse.c
|
||||
|
||||
@@ -58,7 +60,7 @@ HFILES = nghttp2_pq.h nghttp2_int.h nghttp2_map.h nghttp2_queue.h \
|
||||
nghttp2_frame.h \
|
||||
nghttp2_buf.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_net.h \
|
||||
nghttp2_hd.h nghttp2_hd_huffman.h \
|
||||
@@ -69,6 +71,8 @@ HFILES = nghttp2_pq.h nghttp2_int.h nghttp2_map.h nghttp2_queue.h \
|
||||
nghttp2_http.h \
|
||||
nghttp2_rcbuf.h \
|
||||
nghttp2_extpri.h \
|
||||
nghttp2_ratelim.h \
|
||||
nghttp2_time.h \
|
||||
nghttp2_debug.h \
|
||||
sfparse.h
|
||||
|
||||
|
||||
@@ -74,7 +74,7 @@ NGHTTP2_SRC := nghttp2_pq.c \
|
||||
nghttp2_session.c \
|
||||
nghttp2_submit.c \
|
||||
nghttp2_helper.c \
|
||||
nghttp2_npn.c \
|
||||
nghttp2_alpn.c \
|
||||
nghttp2_hd.c \
|
||||
nghttp2_hd_huffman.c \
|
||||
nghttp2_hd_huffman_data.c \
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -22,13 +22,13 @@
|
||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#include "nghttp2_npn.h"
|
||||
#include "nghttp2_alpn.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
static int select_next_protocol(unsigned char **out, unsigned char *outlen,
|
||||
const unsigned char *in, unsigned int inlen,
|
||||
const char *key, unsigned int keylen) {
|
||||
static int select_alpn(const unsigned char **out, unsigned char *outlen,
|
||||
const unsigned char *in, unsigned int inlen,
|
||||
const char *key, unsigned int keylen) {
|
||||
unsigned int i;
|
||||
for (i = 0; i + keylen <= inlen; i += (unsigned int)(in[i] + 1)) {
|
||||
if (memcmp(&in[i], key, keylen) == 0) {
|
||||
@@ -45,12 +45,25 @@ static int 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) {
|
||||
if (select_next_protocol(out, outlen, in, inlen, NGHTTP2_PROTO_ALPN,
|
||||
NGHTTP2_PROTO_ALPN_LEN) == 0) {
|
||||
if (select_alpn((const unsigned char **)out, outlen, in, inlen,
|
||||
NGHTTP2_PROTO_ALPN, NGHTTP2_PROTO_ALPN_LEN) == 0) {
|
||||
return 1;
|
||||
}
|
||||
if (select_next_protocol(out, outlen, in, inlen, NGHTTP2_HTTP_1_1_ALPN,
|
||||
NGHTTP2_HTTP_1_1_ALPN_LEN) == 0) {
|
||||
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) {
|
||||
return 1;
|
||||
}
|
||||
if (select_alpn(out, outlen, in, inlen, NGHTTP2_HTTP_1_1_ALPN,
|
||||
NGHTTP2_HTTP_1_1_ALPN_LEN) == 0) {
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
@@ -22,8 +22,8 @@
|
||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#ifndef NGHTTP2_NPN_H
|
||||
#define NGHTTP2_NPN_H
|
||||
#ifndef NGHTTP2_ALPN_H
|
||||
#define NGHTTP2_ALPN_H
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
@@ -31,4 +31,4 @@
|
||||
|
||||
#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;
|
||||
}
|
||||
|
||||
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);
|
||||
if (ptr == NULL) {
|
||||
@@ -343,7 +343,7 @@ int nghttp2_bufs_add(nghttp2_bufs *bufs, const void *data, size_t len) {
|
||||
while (len) {
|
||||
buf = &bufs->cur->buf;
|
||||
|
||||
nwrite = nghttp2_min(nghttp2_buf_avail(buf), len);
|
||||
nwrite = nghttp2_min_size(nghttp2_buf_avail(buf), len);
|
||||
if (nwrite == 0) {
|
||||
rv = bufs_alloc_chain(bufs);
|
||||
if (rv != 0) {
|
||||
@@ -430,7 +430,7 @@ int nghttp2_bufs_orb_hold(nghttp2_bufs *bufs, uint8_t b) {
|
||||
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;
|
||||
nghttp2_buf_chain *chain;
|
||||
nghttp2_buf *buf;
|
||||
@@ -462,7 +462,7 @@ ssize_t nghttp2_bufs_remove(nghttp2_bufs *bufs, uint8_t **out) {
|
||||
|
||||
*out = res;
|
||||
|
||||
return (ssize_t)len;
|
||||
return (nghttp2_ssize)len;
|
||||
}
|
||||
|
||||
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
|
||||
* 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
|
||||
|
||||
@@ -45,11 +45,21 @@ void nghttp2_session_callbacks_set_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(
|
||||
nghttp2_session_callbacks *cbs, nghttp2_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(
|
||||
nghttp2_session_callbacks *cbs,
|
||||
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;
|
||||
}
|
||||
|
||||
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(
|
||||
nghttp2_session_callbacks *cbs,
|
||||
nghttp2_data_source_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(
|
||||
nghttp2_session_callbacks *cbs,
|
||||
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;
|
||||
}
|
||||
|
||||
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(
|
||||
nghttp2_session_callbacks *cbs,
|
||||
nghttp2_unpack_extension_callback unpack_extension_callback) {
|
||||
|
||||
@@ -36,19 +36,33 @@
|
||||
*/
|
||||
struct nghttp2_session_callbacks {
|
||||
/**
|
||||
* Callback function invoked when the session wants to send data to
|
||||
* the remote peer. This callback is not necessary if the
|
||||
* application uses solely `nghttp2_session_mem_send()` to serialize
|
||||
* data to transmit.
|
||||
* Deprecated. Use send_callback2 instead. Callback function
|
||||
* invoked when the session wants to send data to the remote peer.
|
||||
* This callback is not necessary if the application uses solely
|
||||
* `nghttp2_session_mem_send()` to serialize data to transmit.
|
||||
*/
|
||||
nghttp2_send_callback send_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_recv()` to process
|
||||
* received data.
|
||||
* Callback function invoked when the session wants to send data to
|
||||
* the remote peer. This callback is not necessary if the
|
||||
* application uses solely `nghttp2_session_mem_send2()` to
|
||||
* 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;
|
||||
/**
|
||||
* 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
|
||||
* frame is received.
|
||||
@@ -100,22 +114,39 @@ struct nghttp2_session_callbacks {
|
||||
nghttp2_on_invalid_header_callback on_invalid_header_callback;
|
||||
nghttp2_on_invalid_header_callback2 on_invalid_header_callback2;
|
||||
/**
|
||||
* Callback function invoked when the library asks application how
|
||||
* many padding bytes are required for the transmission of the given
|
||||
* Deprecated. Use select_padding_callback2 instead. Callback
|
||||
* function invoked when the library asks application how many
|
||||
* padding bytes are required for the transmission of the given
|
||||
* frame.
|
||||
*/
|
||||
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_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.
|
||||
*/
|
||||
nghttp2_on_begin_frame_callback on_begin_frame_callback;
|
||||
nghttp2_send_data_callback send_data_callback;
|
||||
/**
|
||||
* Deprecated. Use pack_extension_callback2 instead.
|
||||
*/
|
||||
nghttp2_pack_extension_callback pack_extension_callback;
|
||||
nghttp2_pack_extension_callback2 pack_extension_callback2;
|
||||
nghttp2_unpack_extension_callback unpack_extension_callback;
|
||||
nghttp2_on_extension_chunk_recv_callback on_extension_chunk_recv_callback;
|
||||
nghttp2_error_callback error_callback;
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#include "nghttp2_extpri.h"
|
||||
#include "nghttp2_http.h"
|
||||
|
||||
uint8_t nghttp2_extpri_to_uint8(const nghttp2_extpri *extpri) {
|
||||
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->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);
|
||||
}
|
||||
|
||||
@@ -418,8 +418,8 @@ void nghttp2_frame_unpack_priority_spec(nghttp2_priority_spec *pri_spec,
|
||||
nghttp2_priority_spec_init(pri_spec, dep_stream_id, weight, exclusive);
|
||||
}
|
||||
|
||||
int nghttp2_frame_unpack_headers_payload(nghttp2_headers *frame,
|
||||
const uint8_t *payload) {
|
||||
void nghttp2_frame_unpack_headers_payload(nghttp2_headers *frame,
|
||||
const uint8_t *payload) {
|
||||
if (frame->hd.flags & NGHTTP2_FLAG_PRIORITY) {
|
||||
nghttp2_frame_unpack_priority_spec(&frame->pri_spec, payload);
|
||||
} else {
|
||||
@@ -428,11 +428,9 @@ int nghttp2_frame_unpack_headers_payload(nghttp2_headers *frame,
|
||||
|
||||
frame->nva = NULL;
|
||||
frame->nvlen = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int nghttp2_frame_pack_priority(nghttp2_bufs *bufs, nghttp2_priority *frame) {
|
||||
void nghttp2_frame_pack_priority(nghttp2_bufs *bufs, nghttp2_priority *frame) {
|
||||
nghttp2_buf *buf;
|
||||
|
||||
assert(bufs->head == bufs->cur);
|
||||
@@ -448,8 +446,6 @@ int nghttp2_frame_pack_priority(nghttp2_bufs *bufs, nghttp2_priority *frame) {
|
||||
nghttp2_frame_pack_priority_spec(buf->last, &frame->pri_spec);
|
||||
|
||||
buf->last += NGHTTP2_PRIORITY_SPECLEN;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void nghttp2_frame_unpack_priority_payload(nghttp2_priority *frame,
|
||||
@@ -457,8 +453,8 @@ void nghttp2_frame_unpack_priority_payload(nghttp2_priority *frame,
|
||||
nghttp2_frame_unpack_priority_spec(&frame->pri_spec, payload);
|
||||
}
|
||||
|
||||
int nghttp2_frame_pack_rst_stream(nghttp2_bufs *bufs,
|
||||
nghttp2_rst_stream *frame) {
|
||||
void nghttp2_frame_pack_rst_stream(nghttp2_bufs *bufs,
|
||||
nghttp2_rst_stream *frame) {
|
||||
nghttp2_buf *buf;
|
||||
|
||||
assert(bufs->head == bufs->cur);
|
||||
@@ -473,8 +469,6 @@ int nghttp2_frame_pack_rst_stream(nghttp2_bufs *bufs,
|
||||
|
||||
nghttp2_put_uint32be(buf->last, frame->error_code);
|
||||
buf->last += 4;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void nghttp2_frame_unpack_rst_stream_payload(nghttp2_rst_stream *frame,
|
||||
@@ -592,16 +586,15 @@ int nghttp2_frame_pack_push_promise(nghttp2_bufs *bufs,
|
||||
return frame_pack_headers_shared(bufs, &frame->hd);
|
||||
}
|
||||
|
||||
int nghttp2_frame_unpack_push_promise_payload(nghttp2_push_promise *frame,
|
||||
const uint8_t *payload) {
|
||||
void nghttp2_frame_unpack_push_promise_payload(nghttp2_push_promise *frame,
|
||||
const uint8_t *payload) {
|
||||
frame->promised_stream_id =
|
||||
nghttp2_get_uint32(payload) & NGHTTP2_STREAM_ID_MASK;
|
||||
frame->nva = NULL;
|
||||
frame->nvlen = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int nghttp2_frame_pack_ping(nghttp2_bufs *bufs, nghttp2_ping *frame) {
|
||||
void nghttp2_frame_pack_ping(nghttp2_bufs *bufs, nghttp2_ping *frame) {
|
||||
nghttp2_buf *buf;
|
||||
|
||||
assert(bufs->head == bufs->cur);
|
||||
@@ -616,8 +609,6 @@ int nghttp2_frame_pack_ping(nghttp2_bufs *bufs, nghttp2_ping *frame) {
|
||||
|
||||
buf->last =
|
||||
nghttp2_cpymem(buf->last, frame->opaque_data, sizeof(frame->opaque_data));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void nghttp2_frame_unpack_ping_payload(nghttp2_ping *frame,
|
||||
@@ -697,8 +688,8 @@ int nghttp2_frame_unpack_goaway_payload2(nghttp2_goaway *frame,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int nghttp2_frame_pack_window_update(nghttp2_bufs *bufs,
|
||||
nghttp2_window_update *frame) {
|
||||
void nghttp2_frame_pack_window_update(nghttp2_bufs *bufs,
|
||||
nghttp2_window_update *frame) {
|
||||
nghttp2_buf *buf;
|
||||
|
||||
assert(bufs->head == bufs->cur);
|
||||
@@ -713,8 +704,6 @@ int nghttp2_frame_pack_window_update(nghttp2_bufs *bufs,
|
||||
|
||||
nghttp2_put_uint32be(buf->last, (uint32_t)frame->window_size_increment);
|
||||
buf->last += 4;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void nghttp2_frame_unpack_window_update_payload(nghttp2_window_update *frame,
|
||||
@@ -723,7 +712,7 @@ void nghttp2_frame_unpack_window_update_payload(nghttp2_window_update *frame,
|
||||
nghttp2_get_uint32(payload) & NGHTTP2_WINDOW_SIZE_INCREMENT_MASK;
|
||||
}
|
||||
|
||||
int nghttp2_frame_pack_altsvc(nghttp2_bufs *bufs, nghttp2_extension *frame) {
|
||||
void nghttp2_frame_pack_altsvc(nghttp2_bufs *bufs, nghttp2_extension *frame) {
|
||||
int rv;
|
||||
nghttp2_buf *buf;
|
||||
nghttp2_ext_altsvc *altsvc;
|
||||
@@ -752,8 +741,6 @@ int nghttp2_frame_pack_altsvc(nghttp2_bufs *bufs, nghttp2_extension *frame) {
|
||||
rv = nghttp2_bufs_add(bufs, altsvc->field_value, altsvc->field_value_len);
|
||||
|
||||
assert(rv == 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void nghttp2_frame_unpack_altsvc_payload(nghttp2_extension *frame,
|
||||
@@ -901,8 +888,8 @@ int nghttp2_frame_unpack_origin_payload(nghttp2_extension *frame,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int nghttp2_frame_pack_priority_update(nghttp2_bufs *bufs,
|
||||
nghttp2_extension *frame) {
|
||||
void nghttp2_frame_pack_priority_update(nghttp2_bufs *bufs,
|
||||
nghttp2_extension *frame) {
|
||||
int rv;
|
||||
nghttp2_buf *buf;
|
||||
nghttp2_ext_priority_update *priority_update;
|
||||
@@ -927,8 +914,6 @@ int nghttp2_frame_pack_priority_update(nghttp2_bufs *bufs,
|
||||
priority_update->field_value_len);
|
||||
|
||||
assert(rv == 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void nghttp2_frame_unpack_priority_update_payload(nghttp2_extension *frame,
|
||||
@@ -1186,14 +1171,14 @@ static void frame_set_pad(nghttp2_buf *buf, size_t padlen, int framehd_only) {
|
||||
buf->last += trail_padlen;
|
||||
}
|
||||
|
||||
int nghttp2_frame_add_pad(nghttp2_bufs *bufs, nghttp2_frame_hd *hd,
|
||||
size_t padlen, int framehd_only) {
|
||||
void nghttp2_frame_add_pad(nghttp2_bufs *bufs, nghttp2_frame_hd *hd,
|
||||
size_t padlen, int framehd_only) {
|
||||
nghttp2_buf *buf;
|
||||
|
||||
if (padlen == 0) {
|
||||
DEBUGF("send: padlen = 0, nothing to do\n");
|
||||
|
||||
return 0;
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1226,6 +1211,4 @@ int nghttp2_frame_add_pad(nghttp2_bufs *bufs, nghttp2_frame_hd *hd,
|
||||
hd->flags |= NGHTTP2_FLAG_PADDED;
|
||||
|
||||
DEBUGF("send: final payloadlen=%zu, padlen=%zu\n", hd->length, padlen);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -143,11 +143,9 @@ int nghttp2_frame_pack_headers(nghttp2_bufs *bufs, nghttp2_headers *frame,
|
||||
* Unpacks HEADERS frame byte sequence into |frame|. This function
|
||||
* only unapcks bytes that come before name/value header block and
|
||||
* after possible Pad Length field.
|
||||
*
|
||||
* This function always succeeds and returns 0.
|
||||
*/
|
||||
int nghttp2_frame_unpack_headers_payload(nghttp2_headers *frame,
|
||||
const uint8_t *payload);
|
||||
void nghttp2_frame_unpack_headers_payload(nghttp2_headers *frame,
|
||||
const uint8_t *payload);
|
||||
|
||||
/*
|
||||
* Packs PRIORITY frame |frame| in wire format and store it in
|
||||
@@ -155,10 +153,8 @@ int nghttp2_frame_unpack_headers_payload(nghttp2_headers *frame,
|
||||
*
|
||||
* The caller must make sure that nghttp2_bufs_reset(bufs) is called
|
||||
* before calling this function.
|
||||
*
|
||||
* This function always succeeds and returns 0.
|
||||
*/
|
||||
int nghttp2_frame_pack_priority(nghttp2_bufs *bufs, nghttp2_priority *frame);
|
||||
void nghttp2_frame_pack_priority(nghttp2_bufs *bufs, nghttp2_priority *frame);
|
||||
|
||||
/*
|
||||
* Unpacks PRIORITY wire format into |frame|.
|
||||
@@ -172,11 +168,9 @@ void nghttp2_frame_unpack_priority_payload(nghttp2_priority *frame,
|
||||
*
|
||||
* The caller must make sure that nghttp2_bufs_reset(bufs) is called
|
||||
* before calling this function.
|
||||
*
|
||||
* This function always succeeds and returns 0.
|
||||
*/
|
||||
int nghttp2_frame_pack_rst_stream(nghttp2_bufs *bufs,
|
||||
nghttp2_rst_stream *frame);
|
||||
void nghttp2_frame_pack_rst_stream(nghttp2_bufs *bufs,
|
||||
nghttp2_rst_stream *frame);
|
||||
|
||||
/*
|
||||
* Unpacks RST_STREAM frame byte sequence into |frame|.
|
||||
@@ -265,15 +259,9 @@ int nghttp2_frame_pack_push_promise(nghttp2_bufs *bufs,
|
||||
* Unpacks PUSH_PROMISE frame byte sequence into |frame|. This
|
||||
* function only unapcks bytes that come before name/value header
|
||||
* block and after possible Pad Length field.
|
||||
*
|
||||
* This function returns 0 if it succeeds or one of the following
|
||||
* negative error codes:
|
||||
*
|
||||
* NGHTTP2_ERR_PROTO
|
||||
* TODO END_HEADERS flag is not set
|
||||
*/
|
||||
int nghttp2_frame_unpack_push_promise_payload(nghttp2_push_promise *frame,
|
||||
const uint8_t *payload);
|
||||
void nghttp2_frame_unpack_push_promise_payload(nghttp2_push_promise *frame,
|
||||
const uint8_t *payload);
|
||||
|
||||
/*
|
||||
* Packs PING frame |frame| in wire format and store it in
|
||||
@@ -281,10 +269,8 @@ int nghttp2_frame_unpack_push_promise_payload(nghttp2_push_promise *frame,
|
||||
*
|
||||
* The caller must make sure that nghttp2_bufs_reset(bufs) is called
|
||||
* before calling this function.
|
||||
*
|
||||
* This function always succeeds and returns 0.
|
||||
*/
|
||||
int nghttp2_frame_pack_ping(nghttp2_bufs *bufs, nghttp2_ping *frame);
|
||||
void nghttp2_frame_pack_ping(nghttp2_bufs *bufs, nghttp2_ping *frame);
|
||||
|
||||
/*
|
||||
* Unpacks PING wire format into |frame|.
|
||||
@@ -343,11 +329,9 @@ int nghttp2_frame_unpack_goaway_payload2(nghttp2_goaway *frame,
|
||||
*
|
||||
* The caller must make sure that nghttp2_bufs_reset(bufs) is called
|
||||
* before calling this function.
|
||||
*
|
||||
* This function always succeeds and returns 0.
|
||||
*/
|
||||
int nghttp2_frame_pack_window_update(nghttp2_bufs *bufs,
|
||||
nghttp2_window_update *frame);
|
||||
void nghttp2_frame_pack_window_update(nghttp2_bufs *bufs,
|
||||
nghttp2_window_update *frame);
|
||||
|
||||
/*
|
||||
* Unpacks WINDOW_UPDATE frame byte sequence into |frame|.
|
||||
@@ -361,17 +345,13 @@ void nghttp2_frame_unpack_window_update_payload(nghttp2_window_update *frame,
|
||||
*
|
||||
* The caller must make sure that nghttp2_bufs_reset(bufs) is called
|
||||
* before calling this function.
|
||||
*
|
||||
* This function always succeeds and returns 0.
|
||||
*/
|
||||
int nghttp2_frame_pack_altsvc(nghttp2_bufs *bufs, nghttp2_extension *ext);
|
||||
void nghttp2_frame_pack_altsvc(nghttp2_bufs *bufs, nghttp2_extension *ext);
|
||||
|
||||
/*
|
||||
* Unpacks ALTSVC wire format into |frame|. The |payload| of
|
||||
* |payloadlen| bytes contains frame payload. This function assumes
|
||||
* that frame->payload points to the nghttp2_ext_altsvc object.
|
||||
*
|
||||
* This function always succeeds and returns 0.
|
||||
*/
|
||||
void nghttp2_frame_unpack_altsvc_payload(nghttp2_extension *frame,
|
||||
size_t origin_len, uint8_t *payload,
|
||||
@@ -431,19 +411,15 @@ int nghttp2_frame_unpack_origin_payload(nghttp2_extension *frame,
|
||||
*
|
||||
* The caller must make sure that nghttp2_bufs_reset(bufs) is called
|
||||
* before calling this function.
|
||||
*
|
||||
* This function always succeeds and returns 0.
|
||||
*/
|
||||
int nghttp2_frame_pack_priority_update(nghttp2_bufs *bufs,
|
||||
nghttp2_extension *ext);
|
||||
void nghttp2_frame_pack_priority_update(nghttp2_bufs *bufs,
|
||||
nghttp2_extension *ext);
|
||||
|
||||
/*
|
||||
* Unpacks PRIORITY_UPDATE wire format into |frame|. The |payload| of
|
||||
* |payloadlen| bytes contains frame payload. This function assumes
|
||||
* that frame->payload points to the nghttp2_ext_priority_update
|
||||
* object.
|
||||
*
|
||||
* This function always succeeds and returns 0.
|
||||
*/
|
||||
void nghttp2_frame_unpack_priority_update_payload(nghttp2_extension *frame,
|
||||
uint8_t *payload,
|
||||
@@ -654,16 +630,8 @@ int nghttp2_iv_check(const nghttp2_settings_entry *iv, size_t niv);
|
||||
* |padlen| including Pad Length field. The |hd| is the frame header
|
||||
* for the serialized data. This function fills zeros padding region
|
||||
* unless framehd_only is nonzero.
|
||||
*
|
||||
* This function returns 0 if it succeeds, or one of the following
|
||||
* negative error codes:
|
||||
*
|
||||
* NGHTTP2_ERR_NOMEM
|
||||
* Out of memory.
|
||||
* NGHTTP2_ERR_FRAME_SIZE_ERROR
|
||||
* The length of the resulting frame is too large.
|
||||
*/
|
||||
int nghttp2_frame_add_pad(nghttp2_bufs *bufs, nghttp2_frame_hd *hd,
|
||||
size_t padlen, int framehd_only);
|
||||
void nghttp2_frame_add_pad(nghttp2_bufs *bufs, nghttp2_frame_hd *hd,
|
||||
size_t padlen, int framehd_only);
|
||||
|
||||
#endif /* NGHTTP2_FRAME_H */
|
||||
|
||||
126
lib/nghttp2_hd.c
126
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
|
||||
* of bytes processed, or returns -1, indicating decoding error.
|
||||
*/
|
||||
static ssize_t decode_length(uint32_t *res, size_t *shift_ptr, int *fin,
|
||||
uint32_t initial, size_t shift, const uint8_t *in,
|
||||
const uint8_t *last, size_t prefix) {
|
||||
static nghttp2_ssize decode_length(uint32_t *res, size_t *shift_ptr, int *fin,
|
||||
uint32_t initial, size_t shift,
|
||||
const uint8_t *in, const uint8_t *last,
|
||||
size_t prefix) {
|
||||
uint32_t k = (uint8_t)((1 << prefix) - 1);
|
||||
uint32_t n = initial;
|
||||
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) {
|
||||
*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) {
|
||||
*res = n;
|
||||
return (ssize_t)(in - start);
|
||||
return (nghttp2_ssize)(in - start);
|
||||
}
|
||||
|
||||
*res = n;
|
||||
*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) {
|
||||
@@ -1164,7 +1165,7 @@ static int add_hd_table_incremental(nghttp2_hd_context *context,
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
ssize_t index;
|
||||
nghttp2_ssize index;
|
||||
/* Nonzero if both name and value are matched. */
|
||||
int name_value_match;
|
||||
} search_result;
|
||||
@@ -1213,8 +1214,8 @@ static search_result search_hd_table(nghttp2_hd_context *context,
|
||||
return res;
|
||||
}
|
||||
|
||||
res.index =
|
||||
(ssize_t)(context->next_seq - 1 - ent->seq + NGHTTP2_STATIC_TABLE_LENGTH);
|
||||
res.index = (nghttp2_ssize)(context->next_seq - 1 - ent->seq +
|
||||
NGHTTP2_STATIC_TABLE_LENGTH);
|
||||
res.name_value_match = exact_match;
|
||||
|
||||
return res;
|
||||
@@ -1244,13 +1245,13 @@ static void hd_context_shrink_table_size(nghttp2_hd_context *context,
|
||||
|
||||
int nghttp2_hd_deflate_change_table_size(
|
||||
nghttp2_hd_deflater *deflater, size_t settings_max_dynamic_table_size) {
|
||||
size_t next_bufsize = nghttp2_min(settings_max_dynamic_table_size,
|
||||
deflater->deflate_hd_table_bufsize_max);
|
||||
size_t next_bufsize = nghttp2_min_size(
|
||||
settings_max_dynamic_table_size, deflater->deflate_hd_table_bufsize_max);
|
||||
|
||||
deflater->ctx.hd_table_bufsize_max = next_bufsize;
|
||||
|
||||
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;
|
||||
|
||||
@@ -1343,7 +1344,7 @@ static int deflate_nv(nghttp2_hd_deflater *deflater, nghttp2_bufs *bufs,
|
||||
const nghttp2_nv *nv) {
|
||||
int rv;
|
||||
search_result res;
|
||||
ssize_t idx;
|
||||
nghttp2_ssize idx;
|
||||
int indexing_mode;
|
||||
int32_t token;
|
||||
nghttp2_mem *mem;
|
||||
@@ -1379,7 +1380,7 @@ static int deflate_nv(nghttp2_hd_deflater *deflater, nghttp2_bufs *bufs,
|
||||
|
||||
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);
|
||||
if (rv != 0) {
|
||||
@@ -1390,7 +1391,7 @@ static int deflate_nv(nghttp2_hd_deflater *deflater, nghttp2_bufs *bufs,
|
||||
}
|
||||
|
||||
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) {
|
||||
@@ -1491,6 +1492,12 @@ fail:
|
||||
ssize_t nghttp2_hd_deflate_hd(nghttp2_hd_deflater *deflater, uint8_t *buf,
|
||||
size_t buflen, const nghttp2_nv *nv,
|
||||
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;
|
||||
int rv;
|
||||
nghttp2_mem *mem;
|
||||
@@ -1517,12 +1524,18 @@ ssize_t nghttp2_hd_deflate_hd(nghttp2_hd_deflater *deflater, uint8_t *buf,
|
||||
return rv;
|
||||
}
|
||||
|
||||
return (ssize_t)buflen;
|
||||
return (nghttp2_ssize)buflen;
|
||||
}
|
||||
|
||||
ssize_t nghttp2_hd_deflate_hd_vec(nghttp2_hd_deflater *deflater,
|
||||
const nghttp2_vec *vec, size_t veclen,
|
||||
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;
|
||||
int rv;
|
||||
nghttp2_mem *mem;
|
||||
@@ -1550,7 +1563,7 @@ ssize_t nghttp2_hd_deflate_hd_vec(nghttp2_hd_deflater *deflater,
|
||||
return rv;
|
||||
}
|
||||
|
||||
return (ssize_t)buflen;
|
||||
return (nghttp2_ssize)buflen;
|
||||
}
|
||||
|
||||
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
|
||||
* Integer decoding failed
|
||||
*/
|
||||
static ssize_t hd_inflate_read_len(nghttp2_hd_inflater *inflater, int *rfin,
|
||||
const uint8_t *in, const uint8_t *last,
|
||||
size_t prefix, size_t maxlen) {
|
||||
ssize_t rv;
|
||||
static nghttp2_ssize hd_inflate_read_len(nghttp2_hd_inflater *inflater,
|
||||
int *rfin, const uint8_t *in,
|
||||
const uint8_t *last, size_t prefix,
|
||||
size_t maxlen) {
|
||||
nghttp2_ssize rv;
|
||||
uint32_t out;
|
||||
|
||||
*rfin = 0;
|
||||
@@ -1684,10 +1698,10 @@ static ssize_t hd_inflate_read_len(nghttp2_hd_inflater *inflater, int *rfin,
|
||||
* NGHTTP2_ERR_HEADER_COMP
|
||||
* Huffman decoding failed
|
||||
*/
|
||||
static ssize_t hd_inflate_read_huff(nghttp2_hd_inflater *inflater,
|
||||
nghttp2_buf *buf, const uint8_t *in,
|
||||
const uint8_t *last) {
|
||||
ssize_t readlen;
|
||||
static nghttp2_ssize hd_inflate_read_huff(nghttp2_hd_inflater *inflater,
|
||||
nghttp2_buf *buf, const uint8_t *in,
|
||||
const uint8_t *last) {
|
||||
nghttp2_ssize readlen;
|
||||
int fin = 0;
|
||||
if ((size_t)(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
|
||||
* Header decompression failed
|
||||
*/
|
||||
static ssize_t hd_inflate_read(nghttp2_hd_inflater *inflater, nghttp2_buf *buf,
|
||||
const uint8_t *in, const uint8_t *last) {
|
||||
size_t len = nghttp2_min((size_t)(last - in), inflater->left);
|
||||
static nghttp2_ssize hd_inflate_read(nghttp2_hd_inflater *inflater,
|
||||
nghttp2_buf *buf, const uint8_t *in,
|
||||
const uint8_t *last) {
|
||||
size_t len = nghttp2_min_size((size_t)(last - in), inflater->left);
|
||||
|
||||
buf->last = nghttp2_cpymem(buf->last, in, 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,
|
||||
nghttp2_nv *nv_out, int *inflate_flags,
|
||||
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;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
ssize_t nghttp2_hd_inflate_hd_nv(nghttp2_hd_inflater *inflater,
|
||||
nghttp2_hd_nv *nv_out, int *inflate_flags,
|
||||
const uint8_t *in, size_t inlen,
|
||||
int in_final) {
|
||||
ssize_t rv = 0;
|
||||
nghttp2_ssize nghttp2_hd_inflate_hd_nv(nghttp2_hd_inflater *inflater,
|
||||
nghttp2_hd_nv *nv_out,
|
||||
int *inflate_flags, const uint8_t *in,
|
||||
size_t inlen, int in_final) {
|
||||
nghttp2_ssize rv = 0;
|
||||
const uint8_t *first = in;
|
||||
const uint8_t *last = in + inlen;
|
||||
int rfin = 0;
|
||||
@@ -1939,8 +1962,8 @@ ssize_t nghttp2_hd_inflate_hd_nv(nghttp2_hd_inflater *inflater,
|
||||
rfin = 0;
|
||||
rv = hd_inflate_read_len(
|
||||
inflater, &rfin, in, last, 5,
|
||||
nghttp2_min(inflater->min_hd_table_bufsize_max,
|
||||
inflater->settings_hd_table_bufsize_max));
|
||||
nghttp2_min_size(inflater->min_hd_table_bufsize_max,
|
||||
inflater->settings_hd_table_bufsize_max));
|
||||
if (rv < 0) {
|
||||
goto fail;
|
||||
}
|
||||
@@ -1992,7 +2015,7 @@ ssize_t nghttp2_hd_inflate_hd_nv(nghttp2_hd_inflater *inflater,
|
||||
|
||||
inflater->state = NGHTTP2_HD_STATE_OPCODE;
|
||||
*inflate_flags |= NGHTTP2_HD_INFLATE_EMIT;
|
||||
return (ssize_t)(in - first);
|
||||
return (nghttp2_ssize)(in - first);
|
||||
} else {
|
||||
inflater->index = inflater->left;
|
||||
--inflater->index;
|
||||
@@ -2050,7 +2073,7 @@ ssize_t nghttp2_hd_inflate_hd_nv(nghttp2_hd_inflater *inflater,
|
||||
|
||||
in += rv;
|
||||
|
||||
DEBUGF("inflatehd: %zd bytes read\n", rv);
|
||||
DEBUGF("inflatehd: %td bytes read\n", rv);
|
||||
|
||||
if (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;
|
||||
|
||||
DEBUGF("inflatehd: %zd bytes read\n", rv);
|
||||
DEBUGF("inflatehd: %td bytes read\n", rv);
|
||||
if (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;
|
||||
|
||||
DEBUGF("inflatehd: %zd bytes read\n", rv);
|
||||
DEBUGF("inflatehd: %td bytes read\n", rv);
|
||||
|
||||
if (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;
|
||||
*inflate_flags |= NGHTTP2_HD_INFLATE_EMIT;
|
||||
|
||||
return (ssize_t)(in - first);
|
||||
return (nghttp2_ssize)(in - first);
|
||||
case NGHTTP2_HD_STATE_READ_VALUE:
|
||||
rv = hd_inflate_read(inflater, &inflater->valuebuf, in, last);
|
||||
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));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
in += rv;
|
||||
|
||||
DEBUGF("inflatehd: %zd bytes read\n", rv);
|
||||
DEBUGF("inflatehd: %td bytes read\n", rv);
|
||||
|
||||
if (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;
|
||||
*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;
|
||||
}
|
||||
return (ssize_t)(in - first);
|
||||
return (nghttp2_ssize)(in - first);
|
||||
|
||||
almost_ok:
|
||||
if (in_final) {
|
||||
@@ -2226,10 +2249,10 @@ almost_ok:
|
||||
|
||||
goto fail;
|
||||
}
|
||||
return (ssize_t)(in - first);
|
||||
return (nghttp2_ssize)(in - first);
|
||||
|
||||
fail:
|
||||
DEBUGF("inflatehd: error return %zd\n", rv);
|
||||
DEBUGF("inflatehd: error return %td\n", rv);
|
||||
|
||||
inflater->ctx.bad = 1;
|
||||
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);
|
||||
}
|
||||
|
||||
ssize_t nghttp2_hd_decode_length(uint32_t *res, size_t *shift_ptr, int *fin,
|
||||
uint32_t initial, size_t shift, uint8_t *in,
|
||||
uint8_t *last, size_t prefix) {
|
||||
nghttp2_ssize nghttp2_hd_decode_length(uint32_t *res, size_t *shift_ptr,
|
||||
int *fin, uint32_t initial, size_t shift,
|
||||
uint8_t *in, uint8_t *last,
|
||||
size_t 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
|
||||
* nghttp2_hd_inflate_hd().
|
||||
*/
|
||||
ssize_t nghttp2_hd_inflate_hd_nv(nghttp2_hd_inflater *inflater,
|
||||
nghttp2_hd_nv *nv_out, int *inflate_flags,
|
||||
const uint8_t *in, size_t inlen, int in_final);
|
||||
nghttp2_ssize nghttp2_hd_inflate_hd_nv(nghttp2_hd_inflater *inflater,
|
||||
nghttp2_hd_nv *nv_out,
|
||||
int *inflate_flags, const uint8_t *in,
|
||||
size_t inlen, int in_final);
|
||||
|
||||
/* For unittesting purpose */
|
||||
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);
|
||||
|
||||
/* For unittesting purpose */
|
||||
ssize_t nghttp2_hd_decode_length(uint32_t *res, size_t *shift_ptr, int *fin,
|
||||
uint32_t initial, size_t shift, uint8_t *in,
|
||||
uint8_t *last, size_t prefix);
|
||||
nghttp2_ssize nghttp2_hd_decode_length(uint32_t *res, size_t *shift_ptr,
|
||||
int *fin, uint32_t initial, size_t shift,
|
||||
uint8_t *in, uint8_t *last,
|
||||
size_t prefix);
|
||||
|
||||
/* Huffman encoding/decoding functions */
|
||||
|
||||
@@ -427,9 +429,9 @@ void nghttp2_hd_huff_decode_context_init(nghttp2_hd_huff_decode_context *ctx);
|
||||
* NGHTTP2_ERR_HEADER_COMP
|
||||
* Decoding process has failed.
|
||||
*/
|
||||
ssize_t nghttp2_hd_huff_decode(nghttp2_hd_huff_decode_context *ctx,
|
||||
nghttp2_buf *buf, const uint8_t *src,
|
||||
size_t srclen, int fin);
|
||||
nghttp2_ssize nghttp2_hd_huff_decode(nghttp2_hd_huff_decode_context *ctx,
|
||||
nghttp2_buf *buf, const uint8_t *src,
|
||||
size_t srclen, int fin);
|
||||
|
||||
/*
|
||||
* nghttp2_hd_huff_decode_failure_state returns nonzero if |ctx|
|
||||
|
||||
@@ -107,16 +107,18 @@ void nghttp2_hd_huff_decode_context_init(nghttp2_hd_huff_decode_context *ctx) {
|
||||
ctx->fstate = NGHTTP2_HUFF_ACCEPTED;
|
||||
}
|
||||
|
||||
ssize_t nghttp2_hd_huff_decode(nghttp2_hd_huff_decode_context *ctx,
|
||||
nghttp2_buf *buf, const uint8_t *src,
|
||||
size_t srclen, int final) {
|
||||
nghttp2_ssize nghttp2_hd_huff_decode(nghttp2_hd_huff_decode_context *ctx,
|
||||
nghttp2_buf *buf, const uint8_t *src,
|
||||
size_t srclen, int final) {
|
||||
const uint8_t *end = src + srclen;
|
||||
nghttp2_huff_decode node = {ctx->fstate, 0};
|
||||
const nghttp2_huff_decode *t = &node;
|
||||
uint8_t c;
|
||||
|
||||
/* 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;) {
|
||||
c = *src++;
|
||||
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 (ssize_t)srclen;
|
||||
return (nghttp2_ssize)srclen;
|
||||
}
|
||||
|
||||
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 delta;
|
||||
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) {
|
||||
*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;
|
||||
/* If there is recv_reduction due to earlier window_size
|
||||
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;
|
||||
if (*recv_window_size_ptr < 0) {
|
||||
*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;
|
||||
/* If there is recv_reduction due to earlier window_size
|
||||
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_window_size_ptr += recv_reduction_delta;
|
||||
@@ -336,6 +336,8 @@ const char *nghttp2_strerror(int error_code) {
|
||||
"closed";
|
||||
case NGHTTP2_ERR_TOO_MANY_SETTINGS:
|
||||
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:
|
||||
return "Unknown error code";
|
||||
}
|
||||
|
||||
@@ -35,8 +35,31 @@
|
||||
#include <nghttp2/nghttp2.h>
|
||||
#include "nghttp2_mem.h"
|
||||
|
||||
#define nghttp2_min(A, B) ((A) < (B) ? (A) : (B))
|
||||
#define nghttp2_max(A, B) ((A) > (B) ? (A) : (B))
|
||||
#define nghttp2_max_def(SUFFIX, T) \
|
||||
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)
|
||||
|
||||
|
||||
@@ -126,6 +126,7 @@ static void map_bucket_set_data(nghttp2_map_bucket *bkt, uint32_t hash,
|
||||
bkt->data = data;
|
||||
}
|
||||
|
||||
#ifndef WIN32
|
||||
void nghttp2_map_print_distance(nghttp2_map *map) {
|
||||
uint32_t i;
|
||||
size_t idx;
|
||||
@@ -145,6 +146,7 @@ void nghttp2_map_print_distance(nghttp2_map *map) {
|
||||
distance(map->tablelen, map->tablelenbits, bkt, idx));
|
||||
}
|
||||
}
|
||||
#endif /* !WIN32 */
|
||||
|
||||
static int insert(nghttp2_map_bucket *table, uint32_t tablelen,
|
||||
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),
|
||||
void *ptr);
|
||||
|
||||
#ifndef WIN32
|
||||
void nghttp2_map_print_distance(nghttp2_map *map);
|
||||
#endif /* !WIN32 */
|
||||
|
||||
#endif /* NGHTTP2_MAP_H */
|
||||
|
||||
@@ -143,3 +143,15 @@ void nghttp2_option_set_no_rfc9113_leading_and_trailing_ws_validation(
|
||||
NGHTTP2_OPT_NO_RFC9113_LEADING_AND_TRAILING_WS_VALIDATION;
|
||||
option->no_rfc9113_leading_and_trailing_ws_validation = val;
|
||||
}
|
||||
|
||||
void nghttp2_option_set_stream_reset_rate_limit(nghttp2_option *option,
|
||||
uint64_t burst, uint64_t rate) {
|
||||
option->opt_set_mask |= NGHTTP2_OPT_STREAM_RESET_RATE_LIMIT;
|
||||
option->stream_reset_burst = burst;
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -70,12 +70,19 @@ typedef enum {
|
||||
NGHTTP2_OPT_MAX_SETTINGS = 1 << 12,
|
||||
NGHTTP2_OPT_SERVER_FALLBACK_RFC7540_PRIORITIES = 1 << 13,
|
||||
NGHTTP2_OPT_NO_RFC9113_LEADING_AND_TRAILING_WS_VALIDATION = 1 << 14,
|
||||
NGHTTP2_OPT_STREAM_RESET_RATE_LIMIT = 1 << 15,
|
||||
NGHTTP2_OPT_MAX_CONTINUATIONS = 1 << 16,
|
||||
} nghttp2_option_flag;
|
||||
|
||||
/**
|
||||
* Struct to store option values for nghttp2_session.
|
||||
*/
|
||||
struct nghttp2_option {
|
||||
/**
|
||||
* NGHTTP2_OPT_STREAM_RESET_RATE_LIMIT
|
||||
*/
|
||||
uint64_t stream_reset_burst;
|
||||
uint64_t stream_reset_rate;
|
||||
/**
|
||||
* NGHTTP2_OPT_MAX_SEND_HEADER_BLOCK_LENGTH
|
||||
*/
|
||||
@@ -92,6 +99,10 @@ struct nghttp2_option {
|
||||
* NGHTTP2_OPT_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
|
||||
* are specified.
|
||||
|
||||
@@ -27,6 +27,32 @@
|
||||
#include <assert.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) {
|
||||
item->cycle = 0;
|
||||
item->qnext = NULL;
|
||||
|
||||
@@ -33,9 +33,32 @@
|
||||
#include "nghttp2_frame.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 */
|
||||
typedef struct {
|
||||
nghttp2_data_provider data_prd;
|
||||
nghttp2_data_provider_wrap dpw;
|
||||
void *stream_user_data;
|
||||
/* error code when request HEADERS is canceled by RST_STREAM while
|
||||
it is in queue. */
|
||||
@@ -50,7 +73,7 @@ typedef struct {
|
||||
/**
|
||||
* 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
|
||||
* 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;
|
||||
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,
|
||||
ncapacity * sizeof(nghttp2_pq_entry *));
|
||||
|
||||
75
lib/nghttp2_ratelim.c
Normal file
75
lib/nghttp2_ratelim.c
Normal file
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* nghttp2 - HTTP/2 C Library
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
#include "nghttp2_ratelim.h"
|
||||
#include "nghttp2_helper.h"
|
||||
|
||||
void nghttp2_ratelim_init(nghttp2_ratelim *rl, uint64_t burst, uint64_t rate) {
|
||||
rl->val = rl->burst = burst;
|
||||
rl->rate = rate;
|
||||
rl->tstamp = 0;
|
||||
}
|
||||
|
||||
void nghttp2_ratelim_update(nghttp2_ratelim *rl, uint64_t tstamp) {
|
||||
uint64_t d, gain;
|
||||
|
||||
if (tstamp == rl->tstamp) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (tstamp > rl->tstamp) {
|
||||
d = tstamp - rl->tstamp;
|
||||
} else {
|
||||
d = 1;
|
||||
}
|
||||
|
||||
rl->tstamp = tstamp;
|
||||
|
||||
if (UINT64_MAX / d < rl->rate) {
|
||||
rl->val = rl->burst;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
gain = rl->rate * d;
|
||||
|
||||
if (UINT64_MAX - gain < rl->val) {
|
||||
rl->val = rl->burst;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
rl->val += gain;
|
||||
rl->val = nghttp2_min_uint64(rl->val, rl->burst);
|
||||
}
|
||||
|
||||
int nghttp2_ratelim_drain(nghttp2_ratelim *rl, uint64_t n) {
|
||||
if (rl->val < n) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
rl->val -= n;
|
||||
|
||||
return 0;
|
||||
}
|
||||
57
lib/nghttp2_ratelim.h
Normal file
57
lib/nghttp2_ratelim.h
Normal file
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* nghttp2 - HTTP/2 C Library
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
#ifndef NGHTTP2_RATELIM_H
|
||||
#define NGHTTP2_RATELIM_H
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif /* HAVE_CONFIG_H */
|
||||
|
||||
#include <nghttp2/nghttp2.h>
|
||||
|
||||
typedef struct nghttp2_ratelim {
|
||||
/* burst is the maximum value of val. */
|
||||
uint64_t burst;
|
||||
/* rate is the amount of value that is regenerated per 1 tstamp. */
|
||||
uint64_t rate;
|
||||
/* val is the amount of value available to drain. */
|
||||
uint64_t val;
|
||||
/* tstamp is the last timestamp in second resolution that is known
|
||||
to this object. */
|
||||
uint64_t tstamp;
|
||||
} nghttp2_ratelim;
|
||||
|
||||
/* nghttp2_ratelim_init initializes |rl| with the given parameters. */
|
||||
void nghttp2_ratelim_init(nghttp2_ratelim *rl, uint64_t burst, uint64_t rate);
|
||||
|
||||
/* nghttp2_ratelim_update updates rl->val with the current |tstamp|
|
||||
given in second resolution. */
|
||||
void nghttp2_ratelim_update(nghttp2_ratelim *rl, uint64_t tstamp);
|
||||
|
||||
/* nghttp2_ratelim_drain drains |n| from rl->val. It returns 0 if it
|
||||
succeeds, or -1. */
|
||||
int nghttp2_ratelim_drain(nghttp2_ratelim *rl, uint64_t n);
|
||||
|
||||
#endif /* NGHTTP2_RATELIM_H */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -39,6 +39,7 @@
|
||||
#include "nghttp2_buf.h"
|
||||
#include "nghttp2_callbacks.h"
|
||||
#include "nghttp2_mem.h"
|
||||
#include "nghttp2_ratelim.h"
|
||||
|
||||
/* The global variable for tests where we want to disable strict
|
||||
preface handling. */
|
||||
@@ -105,6 +106,14 @@ typedef struct {
|
||||
/* The default value of maximum number of concurrent streams. */
|
||||
#define NGHTTP2_DEFAULT_MAX_CONCURRENT_STREAMS 0xffffffffu
|
||||
|
||||
/* The default values for stream reset rate limiter. */
|
||||
#define NGHTTP2_DEFAULT_STREAM_RESET_BURST 1000
|
||||
#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 */
|
||||
typedef enum {
|
||||
/* Receiving frame header */
|
||||
@@ -178,7 +187,9 @@ typedef enum {
|
||||
/* Flag means GOAWAY was sent */
|
||||
NGHTTP2_GOAWAY_SENT = 0x4,
|
||||
/* Flag means GOAWAY was received */
|
||||
NGHTTP2_GOAWAY_RECV = 0x8
|
||||
NGHTTP2_GOAWAY_RECV = 0x8,
|
||||
/* Flag means GOAWAY has been submitted at least once */
|
||||
NGHTTP2_GOAWAY_SUBMITTED = 0x10
|
||||
} nghttp2_goaway_flag;
|
||||
|
||||
/* nghttp2_inflight_settings stores the SETTINGS entries which local
|
||||
@@ -235,6 +246,9 @@ struct nghttp2_session {
|
||||
/* Queue of In-flight SETTINGS values. SETTINGS bearing ACK is not
|
||||
considered as in-flight. */
|
||||
nghttp2_inflight_settings *inflight_settings_head;
|
||||
/* Stream reset rate limiter. If receiving excessive amount of
|
||||
stream resets, GOAWAY will be sent. */
|
||||
nghttp2_ratelim stream_reset_ratelim;
|
||||
/* Sequential number across all streams to process streams in
|
||||
FIFO. */
|
||||
uint64_t stream_seq;
|
||||
@@ -280,6 +294,12 @@ struct nghttp2_session {
|
||||
size_t max_send_header_block_length;
|
||||
/* The maximum number of settings accepted per SETTINGS frame. */
|
||||
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). */
|
||||
uint32_t next_stream_id;
|
||||
/* 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) {
|
||||
weight = stream->weight * weight / stream->sum_dep_weight;
|
||||
|
||||
return nghttp2_max(1, weight);
|
||||
return nghttp2_max_int32(1, weight);
|
||||
}
|
||||
|
||||
#ifdef STREAM_DEP_DEBUG
|
||||
@@ -465,14 +465,12 @@ static int stream_update_dep_on_attach_item(nghttp2_stream *stream) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int stream_update_dep_on_detach_item(nghttp2_stream *stream) {
|
||||
static void stream_update_dep_on_detach_item(nghttp2_stream *stream) {
|
||||
if (nghttp2_pq_empty(&stream->obq)) {
|
||||
stream_obq_remove(stream);
|
||||
}
|
||||
|
||||
validate_tree(stream);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int nghttp2_stream_attach_item(nghttp2_stream *stream,
|
||||
@@ -503,20 +501,20 @@ int nghttp2_stream_attach_item(nghttp2_stream *stream,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int nghttp2_stream_detach_item(nghttp2_stream *stream) {
|
||||
void nghttp2_stream_detach_item(nghttp2_stream *stream) {
|
||||
DEBUGF("stream: stream=%d detach item=%p\n", stream->stream_id, stream->item);
|
||||
|
||||
stream->item = NULL;
|
||||
stream->flags = (uint8_t)(stream->flags & ~NGHTTP2_STREAM_FLAG_DEFERRED_ALL);
|
||||
|
||||
if (stream->flags & NGHTTP2_STREAM_FLAG_NO_RFC7540_PRIORITIES) {
|
||||
return 0;
|
||||
return;
|
||||
}
|
||||
|
||||
return stream_update_dep_on_detach_item(stream);
|
||||
stream_update_dep_on_detach_item(stream);
|
||||
}
|
||||
|
||||
int nghttp2_stream_defer_item(nghttp2_stream *stream, uint8_t flags) {
|
||||
void nghttp2_stream_defer_item(nghttp2_stream *stream, uint8_t flags) {
|
||||
assert(stream->item);
|
||||
|
||||
DEBUGF("stream: stream=%d defer item=%p cause=%02x\n", stream->stream_id,
|
||||
@@ -525,10 +523,10 @@ int nghttp2_stream_defer_item(nghttp2_stream *stream, uint8_t flags) {
|
||||
stream->flags |= flags;
|
||||
|
||||
if (stream->flags & NGHTTP2_STREAM_FLAG_NO_RFC7540_PRIORITIES) {
|
||||
return 0;
|
||||
return;
|
||||
}
|
||||
|
||||
return stream_update_dep_on_detach_item(stream);
|
||||
stream_update_dep_on_detach_item(stream);
|
||||
}
|
||||
|
||||
int nghttp2_stream_resume_deferred_item(nghttp2_stream *stream, uint8_t flags) {
|
||||
|
||||
@@ -258,14 +258,8 @@ void nghttp2_stream_shutdown(nghttp2_stream *stream, nghttp2_shut_flag flag);
|
||||
* more of NGHTTP2_STREAM_FLAG_DEFERRED_USER and
|
||||
* NGHTTP2_STREAM_FLAG_DEFERRED_FLOW_CONTROL. The |flags| indicates
|
||||
* the reason of this action.
|
||||
*
|
||||
* This function returns 0 if it succeeds, or one of the following
|
||||
* negative error codes:
|
||||
*
|
||||
* NGHTTP2_ERR_NOMEM
|
||||
* Out of memory
|
||||
*/
|
||||
int nghttp2_stream_defer_item(nghttp2_stream *stream, uint8_t flags);
|
||||
void nghttp2_stream_defer_item(nghttp2_stream *stream, uint8_t flags);
|
||||
|
||||
/*
|
||||
* Put back deferred data in this stream to active state. The |flags|
|
||||
@@ -379,14 +373,8 @@ int nghttp2_stream_attach_item(nghttp2_stream *stream,
|
||||
/*
|
||||
* Detaches |stream->item|. This function does not free
|
||||
* |stream->item|. The caller must free it.
|
||||
*
|
||||
* This function returns 0 if it succeeds, or one of the following
|
||||
* negative error codes:
|
||||
*
|
||||
* NGHTTP2_ERR_NOMEM
|
||||
* Out of memory
|
||||
*/
|
||||
int nghttp2_stream_detach_item(nghttp2_stream *stream);
|
||||
void nghttp2_stream_detach_item(nghttp2_stream *stream);
|
||||
|
||||
/*
|
||||
* Makes the |stream| depend on the |dep_stream|. This dependency is
|
||||
|
||||
@@ -68,7 +68,7 @@ static int32_t submit_headers_shared(nghttp2_session *session, uint8_t flags,
|
||||
int32_t stream_id,
|
||||
const nghttp2_priority_spec *pri_spec,
|
||||
nghttp2_nv *nva_copy, size_t nvlen,
|
||||
const nghttp2_data_provider *data_prd,
|
||||
const nghttp2_data_provider_wrap *dpw,
|
||||
void *stream_user_data) {
|
||||
int rv;
|
||||
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);
|
||||
|
||||
if (data_prd != NULL && data_prd->read_callback != NULL) {
|
||||
item->aux_data.headers.data_prd = *data_prd;
|
||||
if (dpw != NULL && dpw->data_prd.read_callback != NULL) {
|
||||
item->aux_data.headers.dpw = *dpw;
|
||||
}
|
||||
|
||||
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,
|
||||
const nghttp2_priority_spec *pri_spec,
|
||||
const nghttp2_nv *nva, size_t nvlen,
|
||||
const nghttp2_data_provider *data_prd,
|
||||
const nghttp2_data_provider_wrap *dpw,
|
||||
void *stream_user_data) {
|
||||
int rv;
|
||||
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,
|
||||
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,
|
||||
@@ -411,10 +411,10 @@ int nghttp2_submit_window_update(nghttp2_session *session, uint8_t flags,
|
||||
if (window_size_increment > 0) {
|
||||
if (stream_id == 0) {
|
||||
session->consumed_size =
|
||||
nghttp2_max(0, session->consumed_size - window_size_increment);
|
||||
nghttp2_max_int32(0, session->consumed_size - window_size_increment);
|
||||
} else {
|
||||
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,
|
||||
@@ -740,9 +740,9 @@ fail_item_malloc:
|
||||
}
|
||||
|
||||
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;
|
||||
if (data_prd == NULL || data_prd->read_callback == NULL) {
|
||||
if (dpw == NULL || dpw->data_prd.read_callback == NULL) {
|
||||
flags |= NGHTTP2_FLAG_END_STREAM;
|
||||
}
|
||||
|
||||
@@ -753,11 +753,11 @@ static uint8_t set_request_flags(const nghttp2_priority_spec *pri_spec,
|
||||
return flags;
|
||||
}
|
||||
|
||||
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) {
|
||||
static int32_t submit_request_shared(nghttp2_session *session,
|
||||
const nghttp2_priority_spec *pri_spec,
|
||||
const nghttp2_nv *nva, size_t nvlen,
|
||||
const nghttp2_data_provider_wrap *dpw,
|
||||
void *stream_user_data) {
|
||||
uint8_t flags;
|
||||
int rv;
|
||||
|
||||
@@ -775,23 +775,47 @@ int32_t nghttp2_submit_request(nghttp2_session *session,
|
||||
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,
|
||||
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;
|
||||
if (data_prd == NULL || data_prd->read_callback == NULL) {
|
||||
if (dpw == NULL || dpw->data_prd.read_callback == NULL) {
|
||||
flags |= NGHTTP2_FLAG_END_STREAM;
|
||||
}
|
||||
return flags;
|
||||
}
|
||||
|
||||
int nghttp2_submit_response(nghttp2_session *session, int32_t stream_id,
|
||||
const nghttp2_nv *nva, size_t nvlen,
|
||||
const nghttp2_data_provider *data_prd) {
|
||||
static int submit_response_shared(nghttp2_session *session, int32_t stream_id,
|
||||
const nghttp2_nv *nva, size_t nvlen,
|
||||
const nghttp2_data_provider_wrap *dpw) {
|
||||
uint8_t flags;
|
||||
|
||||
if (stream_id <= 0) {
|
||||
@@ -802,14 +826,32 @@ int nghttp2_submit_response(nghttp2_session *session, int32_t stream_id,
|
||||
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,
|
||||
data_prd, NULL);
|
||||
dpw, NULL);
|
||||
}
|
||||
|
||||
int nghttp2_submit_data(nghttp2_session *session, uint8_t flags,
|
||||
int32_t stream_id,
|
||||
const nghttp2_data_provider *data_prd) {
|
||||
int nghttp2_submit_response(nghttp2_session *session, int32_t stream_id,
|
||||
const nghttp2_nv *nva, size_t nvlen,
|
||||
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;
|
||||
nghttp2_outbound_item *item;
|
||||
nghttp2_frame *frame;
|
||||
@@ -832,7 +874,7 @@ int nghttp2_submit_data(nghttp2_session *session, uint8_t flags,
|
||||
|
||||
frame = &item->frame;
|
||||
aux_data = &item->aux_data.data;
|
||||
aux_data->data_prd = *data_prd;
|
||||
aux_data->dpw = *dpw;
|
||||
aux_data->eof = 0;
|
||||
aux_data->flags = nflags;
|
||||
|
||||
@@ -848,9 +890,37 @@ int nghttp2_submit_data(nghttp2_session *session, uint8_t flags,
|
||||
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,
|
||||
const nghttp2_settings_entry *iv,
|
||||
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)) {
|
||||
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 (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,
|
||||
@@ -875,7 +945,8 @@ int nghttp2_submit_extension(nghttp2_session *session, uint8_t type,
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
@@ -31,4 +31,10 @@
|
||||
|
||||
#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 */
|
||||
|
||||
63
lib/nghttp2_time.c
Normal file
63
lib/nghttp2_time.c
Normal file
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* nghttp2 - HTTP/2 C Library
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
#include "nghttp2_time.h"
|
||||
|
||||
#ifdef HAVE_WINDOWS_H
|
||||
# include <windows.h>
|
||||
#endif /* HAVE_WINDOWS_H */
|
||||
|
||||
#include <time.h>
|
||||
|
||||
#if !defined(HAVE_GETTICKCOUNT64) || defined(__CYGWIN__)
|
||||
static uint64_t time_now_sec(void) {
|
||||
time_t t = time(NULL);
|
||||
|
||||
if (t == -1) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (uint64_t)t;
|
||||
}
|
||||
#endif /* !HAVE_GETTICKCOUNT64 || __CYGWIN__ */
|
||||
|
||||
#if defined(HAVE_GETTICKCOUNT64) && !defined(__CYGWIN__)
|
||||
uint64_t nghttp2_time_now_sec(void) { return GetTickCount64() / 1000; }
|
||||
#elif defined(HAVE_CLOCK_GETTIME) && defined(HAVE_DECL_CLOCK_MONOTONIC) && \
|
||||
HAVE_DECL_CLOCK_MONOTONIC
|
||||
uint64_t nghttp2_time_now_sec(void) {
|
||||
struct timespec tp;
|
||||
int rv = clock_gettime(CLOCK_MONOTONIC, &tp);
|
||||
|
||||
if (rv == -1) {
|
||||
return time_now_sec();
|
||||
}
|
||||
|
||||
return (uint64_t)tp.tv_sec;
|
||||
}
|
||||
#else /* (!HAVE_CLOCK_GETTIME || !HAVE_DECL_CLOCK_MONOTONIC) && \
|
||||
(!HAVE_GETTICKCOUNT64 || __CYGWIN__)) */
|
||||
uint64_t nghttp2_time_now_sec(void) { return time_now_sec(); }
|
||||
#endif /* (!HAVE_CLOCK_GETTIME || !HAVE_DECL_CLOCK_MONOTONIC) && \
|
||||
(!HAVE_GETTICKCOUNT64 || __CYGWIN__)) */
|
||||
38
lib/nghttp2_time.h
Normal file
38
lib/nghttp2_time.h
Normal file
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* nghttp2 - HTTP/2 C Library
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
#ifndef NGHTTP2_TIME_H
|
||||
#define NGHTTP2_TIME_H
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif /* HAVE_CONFIG_H */
|
||||
|
||||
#include <nghttp2/nghttp2.h>
|
||||
|
||||
/* nghttp2_time_now_sec returns seconds from implementation-specific
|
||||
timepoint. If it is unable to get seconds, it returns 0. */
|
||||
uint64_t nghttp2_time_now_sec(void);
|
||||
|
||||
#endif /* NGHTTP2_TIME_H */
|
||||
@@ -10,13 +10,13 @@
|
||||
#
|
||||
# Check for baseline language coverage in the compiler for the specified
|
||||
# version of the C++ standard. If necessary, add switches to CXX and
|
||||
# CXXCPP to enable support. VERSION may be '11' (for the C++11 standard)
|
||||
# or '14' (for the C++14 standard).
|
||||
# CXXCPP to enable support. VERSION may be '11', '14', '17', or '20' for
|
||||
# the respective C++ standard version.
|
||||
#
|
||||
# The second argument, if specified, indicates whether you insist on an
|
||||
# extended mode (e.g. -std=gnu++11) or a strict conformance mode (e.g.
|
||||
# -std=c++11). If neither is specified, you get whatever works, with
|
||||
# preference for an extended mode.
|
||||
# preference for no added switch, and then for an extended mode.
|
||||
#
|
||||
# The third argument, if specified 'mandatory' or if left unspecified,
|
||||
# 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 Moritz Klammler <moritz@klammler.eu>
|
||||
# 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
|
||||
# permitted in any medium without royalty provided the copyright notice
|
||||
# and this notice are preserved. This file is offered as-is, without any
|
||||
# warranty.
|
||||
|
||||
#serial 10
|
||||
#serial 18
|
||||
|
||||
dnl This macro is based on the code from the AX_CXX_COMPILE_STDCXX_11 macro
|
||||
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"],
|
||||
[$1], [14], [ax_cxx_compile_alternatives="14 1y"],
|
||||
[$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_if([$2], [], [],
|
||||
[$2], [ext], [],
|
||||
@@ -61,6 +65,16 @@ AC_DEFUN([AX_CXX_COMPILE_STDCXX], [dnl
|
||||
AC_LANG_PUSH([C++])dnl
|
||||
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
|
||||
if test x$ac_success = xno; then
|
||||
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 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 MSVC needs -std:c++NN for C++17 and later (default is C++14)
|
||||
for alternative in ${ax_cxx_compile_alternatives}; do
|
||||
for switch in -std=c++${alternative} +std=c++${alternative} "-h std=c++${alternative}"; do
|
||||
cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch])
|
||||
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])
|
||||
fi
|
||||
AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch,
|
||||
$cachevar,
|
||||
[ac_save_CXX="$CXX"
|
||||
@@ -139,7 +162,6 @@ m4_define([_AX_CXX_COMPILE_STDCXX_testbody_11],
|
||||
_AX_CXX_COMPILE_STDCXX_testbody_new_in_11
|
||||
)
|
||||
|
||||
|
||||
dnl Test body for checking C++14 support
|
||||
|
||||
m4_define([_AX_CXX_COMPILE_STDCXX_testbody_14],
|
||||
@@ -147,12 +169,24 @@ m4_define([_AX_CXX_COMPILE_STDCXX_testbody_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],
|
||||
_AX_CXX_COMPILE_STDCXX_testbody_new_in_11
|
||||
_AX_CXX_COMPILE_STDCXX_testbody_new_in_14
|
||||
_AX_CXX_COMPILE_STDCXX_testbody_new_in_17
|
||||
)
|
||||
|
||||
dnl 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
|
||||
|
||||
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"
|
||||
|
||||
#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"
|
||||
|
||||
@@ -189,11 +227,13 @@ namespace cxx11
|
||||
|
||||
struct Base
|
||||
{
|
||||
virtual ~Base() {}
|
||||
virtual void f() {}
|
||||
};
|
||||
|
||||
struct Derived : public Base
|
||||
{
|
||||
virtual ~Derived() 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"
|
||||
|
||||
#elif __cplusplus < 201402L
|
||||
#elif __cplusplus < 201402L && !defined _MSC_VER
|
||||
|
||||
#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"
|
||||
|
||||
#elif __cplusplus < 201703L
|
||||
#elif __cplusplus < 201703L && !defined _MSC_VER
|
||||
|
||||
#error "This is not a C++17 compiler"
|
||||
|
||||
@@ -943,6 +983,36 @@ 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
|
||||
|
||||
]])
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user