mirror of
https://github.com/nghttp2/nghttp2.git
synced 2025-12-06 18:18:52 +08:00
Compare commits
1105 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fbf156d22d | ||
|
|
965a0e87e5 | ||
|
|
2b55ca1ce6 | ||
|
|
534c01896c | ||
|
|
c25197ac40 | ||
|
|
becae65257 | ||
|
|
ba9f2c3ae2 | ||
|
|
0387525b77 | ||
|
|
5311185333 | ||
|
|
2fc2a27ac1 | ||
|
|
db938afd66 | ||
|
|
89ddc47616 | ||
|
|
90b7849af1 | ||
|
|
3176e872b3 | ||
|
|
16206d5f67 | ||
|
|
0f33749790 | ||
|
|
5e7e4c0cc0 | ||
|
|
25503ad763 | ||
|
|
8f513fceca | ||
|
|
91af4ed70d | ||
|
|
685e926494 | ||
|
|
a2afd393ed | ||
|
|
4e9098bccf | ||
|
|
33aa327ef5 | ||
|
|
9067ff5eee | ||
|
|
efeede4192 | ||
|
|
6a8749873f | ||
|
|
b1b8308555 | ||
|
|
9b574a5a76 | ||
|
|
0567f1f038 | ||
|
|
4be5de1163 | ||
|
|
9db1c9467c | ||
|
|
3444b42d44 | ||
|
|
6595ae26ea | ||
|
|
41d8a3ac09 | ||
|
|
175001a8d9 | ||
|
|
7cf9e00283 | ||
|
|
8a3eb3f066 | ||
|
|
7e1a0d204b | ||
|
|
cbca2e35b5 | ||
|
|
fc9bdf024f | ||
|
|
3f97e6cd3a | ||
|
|
4fa150c494 | ||
|
|
e8b2508036 | ||
|
|
ac399e41ac | ||
|
|
95dd908834 | ||
|
|
9c7e54d9b5 | ||
|
|
3c03024881 | ||
|
|
36dfc0a56a | ||
|
|
55bf6cdb15 | ||
|
|
0abc220013 | ||
|
|
c28900990a | ||
|
|
5108193d7b | ||
|
|
79a24f5dd9 | ||
|
|
83c759572c | ||
|
|
1a07fb000b | ||
|
|
4aab15999d | ||
|
|
441982674f | ||
|
|
8256c6e070 | ||
|
|
ae87a44b94 | ||
|
|
87d1692e27 | ||
|
|
1d2f008656 | ||
|
|
b064d8a9ff | ||
|
|
528af200b6 | ||
|
|
c6827a7dac | ||
|
|
55ecb082ee | ||
|
|
5f2cf461e6 | ||
|
|
b313386988 | ||
|
|
3933280d29 | ||
|
|
2b6073900f | ||
|
|
d1ba43a69f | ||
|
|
a0779edec4 | ||
|
|
d70fefe72f | ||
|
|
b52db072f1 | ||
|
|
ab0b98db61 | ||
|
|
4245d98653 | ||
|
|
93b4866f5b | ||
|
|
25df164219 | ||
|
|
ba03c082e9 | ||
|
|
bcfa333322 | ||
|
|
c4aeadd57d | ||
|
|
e6b4454e48 | ||
|
|
3226d21609 | ||
|
|
3d20c2dce6 | ||
|
|
cd83d70e7b | ||
|
|
a0ce5ea9ab | ||
|
|
3c600c103f | ||
|
|
841ac75c3e | ||
|
|
80a96817aa | ||
|
|
ecc05e0a1a | ||
|
|
359730af54 | ||
|
|
e9cb19c80e | ||
|
|
049e064e28 | ||
|
|
0463928a1e | ||
|
|
02d34c8c4c | ||
|
|
46acf32c41 | ||
|
|
cab0a76795 | ||
|
|
0c76cebbfc | ||
|
|
5029b85b25 | ||
|
|
0b71d9b828 | ||
|
|
464d7c4ec6 | ||
|
|
ed21b631ae | ||
|
|
950e2d9954 | ||
|
|
71c054a789 | ||
|
|
d2f456e5b1 | ||
|
|
30a44b26d3 | ||
|
|
7dff758f8b | ||
|
|
bd3ececdd8 | ||
|
|
77416b0ac2 | ||
|
|
fce9efd341 | ||
|
|
928fda1d70 | ||
|
|
2d9d654507 | ||
|
|
7398e57174 | ||
|
|
503ec82f4d | ||
|
|
22bd9fb530 | ||
|
|
e007b6b031 | ||
|
|
c487cd888f | ||
|
|
fd403a85c8 | ||
|
|
a06a8c36a4 | ||
|
|
0967ee9cb9 | ||
|
|
d66d34f9b9 | ||
|
|
264a98d106 | ||
|
|
7c11d2d9bb | ||
|
|
b58d7b406f | ||
|
|
5ed9e4c83b | ||
|
|
e7da2a669e | ||
|
|
d66377d4b6 | ||
|
|
77a324fa46 | ||
|
|
38b5cad4e3 | ||
|
|
29014643a9 | ||
|
|
0872f6babe | ||
|
|
b6a9cf9ffa | ||
|
|
5645cad577 | ||
|
|
85ba33c08f | ||
|
|
ff64f64e1d | ||
|
|
bdd3425028 | ||
|
|
70e02cddd3 | ||
|
|
d1c0a17cc2 | ||
|
|
35c5cbbc21 | ||
|
|
2ff31bdd2b | ||
|
|
2fa3d34af1 | ||
|
|
fa3452ec68 | ||
|
|
7451f2f212 | ||
|
|
e9ab75a386 | ||
|
|
d83949bc88 | ||
|
|
50f42a80c9 | ||
|
|
00bd76fc3d | ||
|
|
93ea6b581e | ||
|
|
8e52a5c7f3 | ||
|
|
0aa35e574a | ||
|
|
5a81f2441f | ||
|
|
2b75aff32e | ||
|
|
f4474d57ec | ||
|
|
d0310c8aee | ||
|
|
8471c9e92e | ||
|
|
f5a4c9d971 | ||
|
|
a0dd8918eb | ||
|
|
baa9b1cac0 | ||
|
|
38443d2195 | ||
|
|
208d71561a | ||
|
|
25fbc7b435 | ||
|
|
6bd95d885d | ||
|
|
c171097dea | ||
|
|
6bcdb178a5 | ||
|
|
5e10cc4cad | ||
|
|
95e6c875f0 | ||
|
|
6eb2829ee8 | ||
|
|
6ad9ddcdea | ||
|
|
e082b7be72 | ||
|
|
da01d8dedb | ||
|
|
ca6f6511f2 | ||
|
|
ee8440408c | ||
|
|
9cd695a1db | ||
|
|
4b45906f46 | ||
|
|
d448eb54f9 | ||
|
|
65739fe754 | ||
|
|
0344c962f8 | ||
|
|
46d1e6bb55 | ||
|
|
04606b9339 | ||
|
|
7bb083e69e | ||
|
|
3a831fa95c | ||
|
|
5b9cacc2d7 | ||
|
|
10a84f3e3d | ||
|
|
c42715ed6a | ||
|
|
177d51ddab | ||
|
|
6c882e1ece | ||
|
|
f09c5c4bf9 | ||
|
|
08a9a2eca9 | ||
|
|
19f1785cde | ||
|
|
109de15c1f | ||
|
|
8b64e7b4e1 | ||
|
|
a5d66e71d0 | ||
|
|
3de2654223 | ||
|
|
d49bd50908 | ||
|
|
4130c68db1 | ||
|
|
ad3dac81a2 | ||
|
|
0cf6848646 | ||
|
|
e9d562f987 | ||
|
|
bc0f501dd3 | ||
|
|
a591001e7b | ||
|
|
eaa9229d72 | ||
|
|
1d5cde1c6b | ||
|
|
de03c41111 | ||
|
|
19340da8d4 | ||
|
|
5e99531b4d | ||
|
|
bef3d47c16 | ||
|
|
b8f7b474b4 | ||
|
|
1fb291d0e1 | ||
|
|
bc3dc6b765 | ||
|
|
ee7c36c022 | ||
|
|
857791dbb9 | ||
|
|
3c3267ea7d | ||
|
|
d654664fb2 | ||
|
|
1a37044d3c | ||
|
|
00a8c378d4 | ||
|
|
7549341081 | ||
|
|
5db8473f12 | ||
|
|
00b89f10bd | ||
|
|
281df33f40 | ||
|
|
e6ae681f07 | ||
|
|
7e681dc98f | ||
|
|
412c8f9e67 | ||
|
|
2795da840c | ||
|
|
175c7886ea | ||
|
|
4a4b2cf538 | ||
|
|
2c2188c09d | ||
|
|
1f07c24a2e | ||
|
|
e038625881 | ||
|
|
cdb1d6b462 | ||
|
|
1b4ccd0d51 | ||
|
|
8babaac8c3 | ||
|
|
d1624d6929 | ||
|
|
e4472b5aec | ||
|
|
9439ba75d3 | ||
|
|
9254c563ca | ||
|
|
35594e09df | ||
|
|
96ff3be5e6 | ||
|
|
3d5d76ba74 | ||
|
|
8c1e155f44 | ||
|
|
dba0d2791c | ||
|
|
f310e82fc8 | ||
|
|
1240e55bb6 | ||
|
|
75039c573c | ||
|
|
4b5179a544 | ||
|
|
8efccddcf4 | ||
|
|
97843e3874 | ||
|
|
5dd2704051 | ||
|
|
de7b7fd440 | ||
|
|
1037d3ad26 | ||
|
|
c4368a9416 | ||
|
|
fdc1eb526b | ||
|
|
99a91e3172 | ||
|
|
272cfa320e | ||
|
|
f5285d1f5a | ||
|
|
ede6104900 | ||
|
|
5aec60fbeb | ||
|
|
e1a865c406 | ||
|
|
5e03b6a0db | ||
|
|
b85924bf70 | ||
|
|
19707aac55 | ||
|
|
9ad873fc06 | ||
|
|
8a9810ed32 | ||
|
|
68a6d8c50b | ||
|
|
600605400c | ||
|
|
97aa4dabc8 | ||
|
|
a6f487240d | ||
|
|
da135416bb | ||
|
|
13eb881e5e | ||
|
|
82c84d163b | ||
|
|
a526183928 | ||
|
|
60222ae7c3 | ||
|
|
2052a1a4bd | ||
|
|
183be9cac9 | ||
|
|
69b53b9aaa | ||
|
|
02b9fcd332 | ||
|
|
231d739b10 | ||
|
|
e1dfff8929 | ||
|
|
db1716ae93 | ||
|
|
4cdc74c957 | ||
|
|
2c17ec3df8 | ||
|
|
e464b10fc3 | ||
|
|
03ba399176 | ||
|
|
751d66a397 | ||
|
|
3ec71bf5a2 | ||
|
|
f19b0724a3 | ||
|
|
a7e0a69f97 | ||
|
|
e532e20491 | ||
|
|
3e1cfa8e99 | ||
|
|
a100df9cae | ||
|
|
56284b1e15 | ||
|
|
f267e400fa | ||
|
|
8bac5899cc | ||
|
|
f4016644a9 | ||
|
|
d9bc6d04f7 | ||
|
|
743fc4a3c3 | ||
|
|
392256e542 | ||
|
|
905e16cb99 | ||
|
|
9d4e8eeb12 | ||
|
|
8099dd9558 | ||
|
|
a3a6b91c5f | ||
|
|
d9bb3448bf | ||
|
|
d508a0c72c | ||
|
|
bc31146c1f | ||
|
|
1ad7d5e366 | ||
|
|
456038e3de | ||
|
|
9aa26970be | ||
|
|
20c39fa843 | ||
|
|
f5a2f1da25 | ||
|
|
27b250ac8e | ||
|
|
b14375ec63 | ||
|
|
6858cda366 | ||
|
|
8a703d21ae | ||
|
|
1dabe43ff4 | ||
|
|
900aef10da | ||
|
|
ded576f423 | ||
|
|
136aae725f | ||
|
|
a60c3f8939 | ||
|
|
99dc31ff1a | ||
|
|
7673848325 | ||
|
|
0f8a5ffc23 | ||
|
|
fddb019baf | ||
|
|
72bf7d4af0 | ||
|
|
581e0938a9 | ||
|
|
1064e017c6 | ||
|
|
79b07f0ce2 | ||
|
|
cd471a989a | ||
|
|
0ea44072a3 | ||
|
|
6ba1abac6c | ||
|
|
0110d2f9f8 | ||
|
|
baa0f60dc8 | ||
|
|
69aa70086a | ||
|
|
13d3f785bd | ||
|
|
39c068974d | ||
|
|
0d4d1a63d4 | ||
|
|
833cd962a1 | ||
|
|
8103f43b65 | ||
|
|
1c8a672a8d | ||
|
|
4749e66c67 | ||
|
|
25ea41972a | ||
|
|
7d66188910 | ||
|
|
979c99eaea | ||
|
|
cf7f87c2ad | ||
|
|
bd0c1edaa6 | ||
|
|
c7ef021b4b | ||
|
|
00c80a15c0 | ||
|
|
8f47b68a95 | ||
|
|
d9139fc286 | ||
|
|
e693f75670 | ||
|
|
759f6c0b39 | ||
|
|
3e0d73c01d | ||
|
|
5cf21ec187 | ||
|
|
62e1d1c952 | ||
|
|
6ae58cc22e | ||
|
|
874ef1ac54 | ||
|
|
5f65460944 | ||
|
|
41b2745dad | ||
|
|
30f9f9ef87 | ||
|
|
4807e71b7d | ||
|
|
09c647fd1b | ||
|
|
d0fea96e69 | ||
|
|
b8883101d3 | ||
|
|
508c88f659 | ||
|
|
40d217beb1 | ||
|
|
e36caef006 | ||
|
|
9b864380a5 | ||
|
|
0e1d0400d8 | ||
|
|
afdd51ff15 | ||
|
|
488c3588d9 | ||
|
|
4f02b191d1 | ||
|
|
8acef2711b | ||
|
|
c6111b3792 | ||
|
|
c4d36aeff7 | ||
|
|
f50596e355 | ||
|
|
abf81b5bb7 | ||
|
|
8579b8a968 | ||
|
|
8df2c357d9 | ||
|
|
4c381611a1 | ||
|
|
7dfd6ab1ad | ||
|
|
0c7d48dede | ||
|
|
4639a66e53 | ||
|
|
65cc2f0515 | ||
|
|
4eb7f98449 | ||
|
|
2d8059a9a5 | ||
|
|
a3d22b6db9 | ||
|
|
3f31424ee2 | ||
|
|
e0119452a3 | ||
|
|
60cae325bc | ||
|
|
16c46114dc | ||
|
|
862175b21c | ||
|
|
e7e3d77c53 | ||
|
|
af9aeee752 | ||
|
|
ad3d43b8be | ||
|
|
210a5c4f01 | ||
|
|
d8822f2a8e | ||
|
|
b7a72b1e5a | ||
|
|
2f106dc96b | ||
|
|
f619286ca3 | ||
|
|
271f7fbbb6 | ||
|
|
318235db33 | ||
|
|
8ab079ccc2 | ||
|
|
a4d2104c3c | ||
|
|
44672e437a | ||
|
|
fb3d6f68a8 | ||
|
|
d7c9015d8b | ||
|
|
54f640f3e1 | ||
|
|
e2906025c8 | ||
|
|
9a8e9815c9 | ||
|
|
8c3e864989 | ||
|
|
22570b7260 | ||
|
|
fb49182c29 | ||
|
|
b9b648e0ed | ||
|
|
494775a25d | ||
|
|
1214f9e23b | ||
|
|
a54cda22ab | ||
|
|
f4a4abd180 | ||
|
|
c9559b5c0d | ||
|
|
af5b354685 | ||
|
|
3c1c2c4aad | ||
|
|
767ed255ca | ||
|
|
aa0023b3c1 | ||
|
|
3bdc143474 | ||
|
|
8b50cc0ece | ||
|
|
a24c94e92a | ||
|
|
a00442bee6 | ||
|
|
f857b63986 | ||
|
|
cbd72da9a1 | ||
|
|
7506a93179 | ||
|
|
53e1623ab3 | ||
|
|
0cb0bdabec | ||
|
|
ed8d5f04bb | ||
|
|
33153010c5 | ||
|
|
2c500b62fd | ||
|
|
30f26a2b9d | ||
|
|
ca39c71ac3 | ||
|
|
2bbe4422d2 | ||
|
|
5d3535126e | ||
|
|
d2addbc1ed | ||
|
|
110ca3131a | ||
|
|
fd7d3c57d7 | ||
|
|
179561e4be | ||
|
|
903e0077aa | ||
|
|
3fadad1bf3 | ||
|
|
acb5d45a88 | ||
|
|
6fd4dd99da | ||
|
|
1bcf13b28b | ||
|
|
c7210908df | ||
|
|
ad7cded2f4 | ||
|
|
7d847d8796 | ||
|
|
ab9cc37ca0 | ||
|
|
65095c448d | ||
|
|
76e188e368 | ||
|
|
0613a16c11 | ||
|
|
aced5b3b6c | ||
|
|
97d8bb16e6 | ||
|
|
3e14f0d8a5 | ||
|
|
f7c0d48152 | ||
|
|
2a4733857f | ||
|
|
3c1efeff55 | ||
|
|
532f801fbd | ||
|
|
cbced219ec | ||
|
|
66ca8272ca | ||
|
|
f945653ba9 | ||
|
|
fdc27c9f0e | ||
|
|
3aa0ebbbd6 | ||
|
|
aa16412850 | ||
|
|
e2bdf1d734 | ||
|
|
4aa79763be | ||
|
|
057db65657 | ||
|
|
c42296acf1 | ||
|
|
d6def22ad5 | ||
|
|
cdd72bad77 | ||
|
|
123752a032 | ||
|
|
ec5e438a7c | ||
|
|
c0b6b9a282 | ||
|
|
1fb3d71f77 | ||
|
|
43d595b7f3 | ||
|
|
fa8bccbae2 | ||
|
|
56e7cd4be2 | ||
|
|
af9662f971 | ||
|
|
af4e262d47 | ||
|
|
96218a1078 | ||
|
|
50c9c3358a | ||
|
|
6f025619de | ||
|
|
7e31340045 | ||
|
|
cddb411495 | ||
|
|
92572203e7 | ||
|
|
57259481c8 | ||
|
|
c7b0e04498 | ||
|
|
47fa56fd0a | ||
|
|
fd09d8b861 | ||
|
|
d48d399fb3 | ||
|
|
34468eccc4 | ||
|
|
81bfb84b32 | ||
|
|
11bca9a98a | ||
|
|
2868370f9e | ||
|
|
9f6c947a87 | ||
|
|
1a2dc1e822 | ||
|
|
9bdf214f48 | ||
|
|
7469139dda | ||
|
|
51c7a13cee | ||
|
|
c06e8c89ff | ||
|
|
a809da68a3 | ||
|
|
084206bace | ||
|
|
288449b9bc | ||
|
|
11e66510e4 | ||
|
|
38f4f50e93 | ||
|
|
d36afb7cdb | ||
|
|
f9897f8ccd | ||
|
|
143d0b69b7 | ||
|
|
ac97c122d4 | ||
|
|
7751f4fb3b | ||
|
|
3cd0b87685 | ||
|
|
2867f03861 | ||
|
|
8248598601 | ||
|
|
4ef3f9d11c | ||
|
|
c3817913ee | ||
|
|
6214c1b4b6 | ||
|
|
2499b36801 | ||
|
|
d196639aed | ||
|
|
2c33da36cc | ||
|
|
708c99c052 | ||
|
|
fbdfecc143 | ||
|
|
d3495405d9 | ||
|
|
aad2a24a22 | ||
|
|
27fa9c3c12 | ||
|
|
92db6820d8 | ||
|
|
851cbd49f4 | ||
|
|
8288f5713b | ||
|
|
951ef0c6d5 | ||
|
|
9653ae98a6 | ||
|
|
d837887af6 | ||
|
|
2a504224de | ||
|
|
d0bf247419 | ||
|
|
9237d30e34 | ||
|
|
ef3fa23b2e | ||
|
|
cb7269f334 | ||
|
|
0ca7c4cb38 | ||
|
|
43913838b4 | ||
|
|
845aa7a710 | ||
|
|
fe58614b23 | ||
|
|
2fd095d036 | ||
|
|
09150a7927 | ||
|
|
667c8b0e27 | ||
|
|
2a0d0e798b | ||
|
|
8b6947eda5 | ||
|
|
88e635e0b9 | ||
|
|
3753b47475 | ||
|
|
be06f1d428 | ||
|
|
e4dc6cf432 | ||
|
|
204f9a3ec7 | ||
|
|
f68dc02d6b | ||
|
|
2ca3bf7a7e | ||
|
|
43b045e84c | ||
|
|
852a320586 | ||
|
|
631f977236 | ||
|
|
046ec307c3 | ||
|
|
50083f0d22 | ||
|
|
c4fba5139c | ||
|
|
81b3e3811b | ||
|
|
26eb983cf0 | ||
|
|
e0491c2ee8 | ||
|
|
fce7908fe6 | ||
|
|
2a4bf9f615 | ||
|
|
45f7c17932 | ||
|
|
f2a1fadda9 | ||
|
|
98396f00ff | ||
|
|
e7d5cfff30 | ||
|
|
c308be39de | ||
|
|
65135bc319 | ||
|
|
944297df28 | ||
|
|
f725e419e8 | ||
|
|
0fca352114 | ||
|
|
9a3461e2b6 | ||
|
|
0b9ee38db6 | ||
|
|
a224aba577 | ||
|
|
9f770fec36 | ||
|
|
c39a669671 | ||
|
|
e6dfd4ff27 | ||
|
|
e99f3c58f7 | ||
|
|
2a3b6c11eb | ||
|
|
e26d6a2b27 | ||
|
|
dce7288658 | ||
|
|
d1968c4465 | ||
|
|
863fbffda4 | ||
|
|
629f1e6f0f | ||
|
|
7a3c656adf | ||
|
|
2a96d433ec | ||
|
|
796160cb77 | ||
|
|
5c82a36072 | ||
|
|
b011012d8f | ||
|
|
8026bdd45a | ||
|
|
5ff6da11b1 | ||
|
|
de3f2951b3 | ||
|
|
d00788ceeb | ||
|
|
e0df95a1d8 | ||
|
|
6d22898936 | ||
|
|
15a9dfbaea | ||
|
|
c6facaf662 | ||
|
|
60e443b90b | ||
|
|
d39335829d | ||
|
|
5d4f3f36e3 | ||
|
|
752b5b3d44 | ||
|
|
70e8dc3761 | ||
|
|
0ee80be995 | ||
|
|
3712c89a66 | ||
|
|
8e33f0a535 | ||
|
|
fd801864e3 | ||
|
|
99f7e7e2a5 | ||
|
|
6c999e6fb5 | ||
|
|
4aa4fe56e1 | ||
|
|
09b97a3313 | ||
|
|
d2f4e4e325 | ||
|
|
dba0f35ee1 | ||
|
|
2d2b72d4eb | ||
|
|
b39ad3135d | ||
|
|
13f97ccf45 | ||
|
|
43bbcd35aa | ||
|
|
220f49b157 | ||
|
|
918ca4ca7c | ||
|
|
7d7dc830ef | ||
|
|
f939000ad9 | ||
|
|
4b34bc583d | ||
|
|
91fce2f0e6 | ||
|
|
5487b64fa6 | ||
|
|
b27107385e | ||
|
|
3d00dd6537 | ||
|
|
e85bc70bef | ||
|
|
b0e98718f5 | ||
|
|
3d4a4cb617 | ||
|
|
86777defa8 | ||
|
|
52b455cfeb | ||
|
|
add182b495 | ||
|
|
3d948fd3d7 | ||
|
|
e04e24c1c2 | ||
|
|
68059ccda9 | ||
|
|
bc2b941866 | ||
|
|
9b81eec944 | ||
|
|
00bf701600 | ||
|
|
5339c1774c | ||
|
|
e41d8c2f62 | ||
|
|
73740477fb | ||
|
|
f86a9d654d | ||
|
|
6f52da834b | ||
|
|
4041d1eb26 | ||
|
|
81f81e6b70 | ||
|
|
a16daf109b | ||
|
|
b6708a4b87 | ||
|
|
bda352bf73 | ||
|
|
ca261a7971 | ||
|
|
0819716332 | ||
|
|
a14cea6363 | ||
|
|
2cac7bb838 | ||
|
|
65378f80ea | ||
|
|
40f3779eb1 | ||
|
|
d88f962565 | ||
|
|
9c0bd8c60a | ||
|
|
9e64d10223 | ||
|
|
94c8a8fbde | ||
|
|
16647622f5 | ||
|
|
9028512a5f | ||
|
|
3086d65657 | ||
|
|
d4144a7475 | ||
|
|
6638ca9333 | ||
|
|
b924ef5fff | ||
|
|
df56f55f84 | ||
|
|
31595c2416 | ||
|
|
795ee8c20f | ||
|
|
efbd48b122 | ||
|
|
9b4089c244 | ||
|
|
8b5a85ae1d | ||
|
|
ecabef2dc7 | ||
|
|
4a6fc6cede | ||
|
|
287d4e35f3 | ||
|
|
a803be9171 | ||
|
|
ece3654139 | ||
|
|
bf5392dafe | ||
|
|
7bc35044c7 | ||
|
|
f9b872ab78 | ||
|
|
ffddefc177 | ||
|
|
2a59c832c1 | ||
|
|
ea5f424dec | ||
|
|
46514074a4 | ||
|
|
1816af4fb2 | ||
|
|
b1662a31f4 | ||
|
|
5974abad75 | ||
|
|
344541dd89 | ||
|
|
c17b3b8517 | ||
|
|
b26503f51c | ||
|
|
2b22ec42c7 | ||
|
|
dfdeeb3815 | ||
|
|
4bed7854b5 | ||
|
|
aa64e7ad3c | ||
|
|
8667bbb823 | ||
|
|
1fef49aaa4 | ||
|
|
e30edb096a | ||
|
|
cdb466956d | ||
|
|
199600af73 | ||
|
|
edb874e659 | ||
|
|
fe0843be88 | ||
|
|
ff07018720 | ||
|
|
402eccf06d | ||
|
|
0641d314a6 | ||
|
|
2928afa51f | ||
|
|
757bcf1310 | ||
|
|
c9aba4ea0c | ||
|
|
2cee80acf0 | ||
|
|
d9a2ff278c | ||
|
|
8a539420c2 | ||
|
|
371497968b | ||
|
|
388d7a944a | ||
|
|
afe724ecda | ||
|
|
0d636893f1 | ||
|
|
4ac9417d8d | ||
|
|
75110320ab | ||
|
|
8691ec4899 | ||
|
|
b6e2214903 | ||
|
|
7ec50e55c9 | ||
|
|
ad8be7d474 | ||
|
|
07926cffca | ||
|
|
00b2d7d513 | ||
|
|
f74d7ea119 | ||
|
|
2bca6360b6 | ||
|
|
841b3c87db | ||
|
|
2ab79f4938 | ||
|
|
2182a85875 | ||
|
|
72d8d78d36 | ||
|
|
dad61d032e | ||
|
|
1bbb241baa | ||
|
|
3e6c38e3be | ||
|
|
9272e80fa6 | ||
|
|
333dd73a18 | ||
|
|
8e84bbd781 | ||
|
|
44af3dab50 | ||
|
|
22128767e6 | ||
|
|
f6b78a027c | ||
|
|
a46c815e4e | ||
|
|
186d440168 | ||
|
|
a9e365ad7d | ||
|
|
a104d8a80b | ||
|
|
a5029d1eed | ||
|
|
848e45e333 | ||
|
|
7972593586 | ||
|
|
79968c6374 | ||
|
|
1699aef609 | ||
|
|
2d2d6c3cc0 | ||
|
|
bfccab9b9f | ||
|
|
17ccbae084 | ||
|
|
0875e66aab | ||
|
|
4dfae3484f | ||
|
|
372123c178 | ||
|
|
13596bde90 | ||
|
|
3b7b6a660e | ||
|
|
daa1ae3a45 | ||
|
|
44ee67ff71 | ||
|
|
144ae3af9d | ||
|
|
eec0b04a33 | ||
|
|
58b06f32a2 | ||
|
|
5b58db39ff | ||
|
|
1bc5cf5ee4 | ||
|
|
f4c7ebcbca | ||
|
|
feb3d1b478 | ||
|
|
7c954c1ea7 | ||
|
|
e9f4d0eec2 | ||
|
|
4f9c78799c | ||
|
|
0f9ed40bd9 | ||
|
|
4bb88b35ec | ||
|
|
04145e22a2 | ||
|
|
cca7e398fd | ||
|
|
3d04fe2a87 | ||
|
|
c459034ae9 | ||
|
|
442bd47535 | ||
|
|
5cea3e227c | ||
|
|
db0a22e991 | ||
|
|
dc3119303a | ||
|
|
d2b55ad1a2 | ||
|
|
d7051f5207 | ||
|
|
db1ee3aa88 | ||
|
|
a1e0bd134e | ||
|
|
7a1e0eb618 | ||
|
|
65b59bd78a | ||
|
|
dcae6efaa2 | ||
|
|
71cc7a96c2 | ||
|
|
8da0d649e4 | ||
|
|
08c7656e47 | ||
|
|
bd253e1bdd | ||
|
|
d10f149161 | ||
|
|
3a2a943fe9 | ||
|
|
f34971774b | ||
|
|
f8a9a21428 | ||
|
|
0c49e5d56e | ||
|
|
e84755eb35 | ||
|
|
b348a02b85 | ||
|
|
439636c579 | ||
|
|
162b1c5e03 | ||
|
|
dc56b951df | ||
|
|
4d801cd696 | ||
|
|
7c55c335cc | ||
|
|
2ddb83206b | ||
|
|
ab734f09b6 | ||
|
|
dd2bdf3e31 | ||
|
|
a909bb3eca | ||
|
|
aaebeceded | ||
|
|
3de435d7b8 | ||
|
|
01408209d8 | ||
|
|
e8b62c620d | ||
|
|
2eb7137e04 | ||
|
|
caa12ec587 | ||
|
|
0f71fbce8d | ||
|
|
4e2972a5dc | ||
|
|
78e5417ff2 | ||
|
|
77852cf572 | ||
|
|
fa36537f82 | ||
|
|
4cde76c9c3 | ||
|
|
e02512032b | ||
|
|
b092166bc6 | ||
|
|
e58db4f8b0 | ||
|
|
dad222b8f4 | ||
|
|
e80977c812 | ||
|
|
2b3bc710fc | ||
|
|
a45540fd79 | ||
|
|
7f8110601e | ||
|
|
37b09f6785 | ||
|
|
2a606bae4c | ||
|
|
3b2811bfc4 | ||
|
|
27275a02ac | ||
|
|
34d209b30b | ||
|
|
94f52d49dc | ||
|
|
0720671e0a | ||
|
|
0ee09320e0 | ||
|
|
78fcb2143f | ||
|
|
755b14de5d | ||
|
|
3455cb35e4 | ||
|
|
c1571a3209 | ||
|
|
67569486d1 | ||
|
|
d64051fedc | ||
|
|
c897d5b294 | ||
|
|
863a944179 | ||
|
|
3db9c2c796 | ||
|
|
12dad32890 | ||
|
|
689d2a1afb | ||
|
|
ff0d137fb3 | ||
|
|
8da20975f9 | ||
|
|
eb393985b7 | ||
|
|
7a412df9a5 | ||
|
|
b1b57cc740 | ||
|
|
bdb6581990 | ||
|
|
618073e2b4 | ||
|
|
fa601e5ba3 | ||
|
|
bae37e3e4a | ||
|
|
907eeeda8a | ||
|
|
fe6ccd16da | ||
|
|
10ec00126c | ||
|
|
2d6211c455 | ||
|
|
e302cc9c16 | ||
|
|
3f2b54cfc4 | ||
|
|
acbf38fd3c | ||
|
|
1e8bea15e5 | ||
|
|
aaf0177318 | ||
|
|
9afc017532 | ||
|
|
5da38b22c0 | ||
|
|
ce61f62644 | ||
|
|
2c525f2471 | ||
|
|
5bbcb7148c | ||
|
|
8bca2d1048 | ||
|
|
d6c3b6e84c | ||
|
|
e453759637 | ||
|
|
a21c87d11c | ||
|
|
478fde5fef | ||
|
|
bffc0ec87a | ||
|
|
1b9b03b68f | ||
|
|
a59445ccff | ||
|
|
c2ec73302d | ||
|
|
284691253f | ||
|
|
124d4c9fad | ||
|
|
5fbe4cc225 | ||
|
|
df6466cfbd | ||
|
|
2326337d32 | ||
|
|
06921f35f3 | ||
|
|
44d3801760 | ||
|
|
1832f78684 | ||
|
|
e7601cde8a | ||
|
|
36f6a009b8 | ||
|
|
1e1752266f | ||
|
|
aafcc55006 | ||
|
|
c731d1fea5 | ||
|
|
aa892e4d37 | ||
|
|
8ca3e5f6ba | ||
|
|
21007da392 | ||
|
|
9eeac27966 | ||
|
|
e6ff7e1e4a | ||
|
|
d1f9f9a3aa | ||
|
|
2415a22757 | ||
|
|
887d4d2a41 | ||
|
|
1c8e625045 | ||
|
|
36e931e0d7 | ||
|
|
31d4077638 | ||
|
|
c098b4ac70 | ||
|
|
32446a5197 | ||
|
|
40c1b29f36 | ||
|
|
bc933e9981 | ||
|
|
ba34e911e1 | ||
|
|
8aac5d6af2 | ||
|
|
56bdfd1df2 | ||
|
|
dbffb8995b | ||
|
|
ebfae904ab | ||
|
|
827abb57e9 | ||
|
|
9aee43f7d8 | ||
|
|
34bf153653 | ||
|
|
2782ef67de | ||
|
|
9d15f9b00d | ||
|
|
3e72711e23 | ||
|
|
f4bb8776d0 | ||
|
|
95ffb4565f | ||
|
|
f3a415f623 | ||
|
|
936d4aca1a | ||
|
|
216ae0a328 | ||
|
|
9672bc322f | ||
|
|
b68be1e1fb | ||
|
|
f2a7275700 | ||
|
|
177d0a513f | ||
|
|
dfc02843b6 | ||
|
|
11c8803b92 | ||
|
|
c9a4f293a1 | ||
|
|
61579ad20f | ||
|
|
9678daa46a | ||
|
|
23ecfd412d | ||
|
|
3ff148811b | ||
|
|
6f1347fc8b | ||
|
|
1703201084 | ||
|
|
7921029e33 | ||
|
|
b7159f80b2 | ||
|
|
9c874bf9b5 | ||
|
|
9ab5ef3b5b | ||
|
|
f0b5a8db8c | ||
|
|
4814d14db5 | ||
|
|
77e8190b6c | ||
|
|
f4b2a4ab00 | ||
|
|
a909eb6b23 | ||
|
|
3dd57e1f59 | ||
|
|
1b67b2d33e | ||
|
|
9bc6dc7113 | ||
|
|
f407f7f406 | ||
|
|
094168a58f | ||
|
|
474ecc4b47 | ||
|
|
0afc21c9d8 | ||
|
|
63e43bff99 | ||
|
|
8c46d9181f | ||
|
|
cc92ebf471 | ||
|
|
02b7116d42 | ||
|
|
aa3373a107 | ||
|
|
7aabc6b125 | ||
|
|
466e4b7a1e | ||
|
|
76a425226f | ||
|
|
2b707bff27 | ||
|
|
9055323b67 | ||
|
|
67804cfc8c | ||
|
|
2344932b45 | ||
|
|
35ebdd35bc | ||
|
|
ac81003669 | ||
|
|
c999987baf | ||
|
|
529a59d309 | ||
|
|
52f6417813 | ||
|
|
c96cf1b303 | ||
|
|
660bc389e6 | ||
|
|
bfc26e8299 | ||
|
|
47106c0756 | ||
|
|
49fa914db5 | ||
|
|
93eabc642b | ||
|
|
2d273f8237 | ||
|
|
a53f0f0a17 | ||
|
|
1bd98dcf4f | ||
|
|
eebed206c9 | ||
|
|
fe74600a5f | ||
|
|
08e2d7cdb3 | ||
|
|
503f0a29a7 | ||
|
|
ee285fa5da | ||
|
|
8c562bd38d | ||
|
|
15adc23277 | ||
|
|
a2ec695ec9 | ||
|
|
55b270587b | ||
|
|
5297136bc0 | ||
|
|
61bb6428fd | ||
|
|
ccd2d34160 | ||
|
|
ea6eed10c7 | ||
|
|
7a86758edb | ||
|
|
90d66ea4a9 | ||
|
|
5b21c39bb2 | ||
|
|
744e80d579 | ||
|
|
3842fe175c | ||
|
|
900667a998 | ||
|
|
147e098827 | ||
|
|
5819d03c68 | ||
|
|
90f5bf796d | ||
|
|
2b63980758 | ||
|
|
65d33c553c | ||
|
|
2593036053 | ||
|
|
a6effb4d23 | ||
|
|
17215002a1 | ||
|
|
0e469ed221 | ||
|
|
093eb51f8c | ||
|
|
5f1866fd6b | ||
|
|
d8c8a4631d | ||
|
|
6b12f17f44 | ||
|
|
eb0c82d91f | ||
|
|
7adfa5dea7 | ||
|
|
17758126fa | ||
|
|
b440f585bc | ||
|
|
63a13ccb18 | ||
|
|
72877379ec | ||
|
|
8449958425 | ||
|
|
9037641592 | ||
|
|
c0078ab45a | ||
|
|
3a41e4dd1a | ||
|
|
3297a303bf | ||
|
|
f1580f95d4 | ||
|
|
1e150bcf61 | ||
|
|
ca371e3ba9 | ||
|
|
61dda40b44 | ||
|
|
5ad753b90c | ||
|
|
0a1beea13a | ||
|
|
00e722f02c | ||
|
|
ff22862b9d | ||
|
|
b2264ad57e | ||
|
|
b0227d4051 | ||
|
|
28b643e531 | ||
|
|
82f942c3a3 | ||
|
|
e4a727f86c | ||
|
|
b624ca6dcd | ||
|
|
ba4c268172 | ||
|
|
00175eac33 | ||
|
|
396dde1347 | ||
|
|
042a59117d | ||
|
|
b8717208c7 | ||
|
|
c3a5fe7185 | ||
|
|
c8b6a79225 | ||
|
|
92e66fc167 | ||
|
|
64ffc1fc73 | ||
|
|
304ff6a6f9 | ||
|
|
fc39f2d9d2 | ||
|
|
0d806978e6 | ||
|
|
62c43ce2be | ||
|
|
88eaeb5d1c | ||
|
|
60c0c2dd56 | ||
|
|
6c147aa1c5 | ||
|
|
2a9b23bfab | ||
|
|
4fb4617d20 | ||
|
|
ede0f6aa32 | ||
|
|
4e7271a88f | ||
|
|
6d49110a33 | ||
|
|
b540aa34d0 | ||
|
|
15fa38c72f | ||
|
|
e7de5e9f6c | ||
|
|
5c10534b88 | ||
|
|
b3e5d49a3e | ||
|
|
6806196404 | ||
|
|
2e38208d74 | ||
|
|
cde79052dd | ||
|
|
e763770f3e | ||
|
|
26d49c1dc3 | ||
|
|
bb4e2f6a24 | ||
|
|
344cc1b5c3 | ||
|
|
21f9b6d8bb | ||
|
|
024d0d09ee | ||
|
|
e4b2847d31 | ||
|
|
ee07694783 | ||
|
|
8741503db1 | ||
|
|
eec409dba7 | ||
|
|
95ca4f55d5 | ||
|
|
231665d67b | ||
|
|
4c05558273 | ||
|
|
35c3b36549 | ||
|
|
03872bfacd | ||
|
|
5e9bcbec9a | ||
|
|
aa07fe7fa6 | ||
|
|
1d99b425ca | ||
|
|
7a6a59178a | ||
|
|
4e44fccdcf | ||
|
|
703c77ec89 | ||
|
|
a06af3fa85 | ||
|
|
686a303cb5 | ||
|
|
b95df43384 | ||
|
|
5659e295b3 | ||
|
|
5b195092e1 | ||
|
|
85bb37ab7c | ||
|
|
c5f3eee3be | ||
|
|
1cfdf386ff | ||
|
|
6d8fe72174 | ||
|
|
98253b1d0d | ||
|
|
ad93cea544 | ||
|
|
1739b5a0e6 | ||
|
|
9ef8e24049 | ||
|
|
7fbbaf01a9 | ||
|
|
5a6f312182 | ||
|
|
2b441ef9af | ||
|
|
e14da859b6 | ||
|
|
0248d979fe | ||
|
|
0caefe20ef | ||
|
|
9c84f60ba0 | ||
|
|
83cc2511e3 | ||
|
|
eb4e402aae | ||
|
|
5d611d2e24 | ||
|
|
837e716306 | ||
|
|
061a557839 | ||
|
|
d9893d014c | ||
|
|
3785cf07ba |
@@ -1,57 +1,94 @@
|
||||
---
|
||||
Language: Cpp
|
||||
# BasedOnStyle: LLVM
|
||||
AccessModifierOffset: -2
|
||||
ConstructorInitializerIndentWidth: 4
|
||||
AlignAfterOpenBracket: Align
|
||||
AlignConsecutiveAssignments: false
|
||||
AlignConsecutiveDeclarations: false
|
||||
AlignEscapedNewlinesLeft: false
|
||||
AlignOperands: true
|
||||
AlignTrailingComments: true
|
||||
AllowAllParametersOfDeclarationOnNextLine: true
|
||||
AllowShortBlocksOnASingleLine: false
|
||||
AllowShortCaseLabelsOnASingleLine: false
|
||||
AllowShortFunctionsOnASingleLine: All
|
||||
AllowShortIfStatementsOnASingleLine: false
|
||||
AllowShortLoopsOnASingleLine: false
|
||||
AllowShortFunctionsOnASingleLine: All
|
||||
AlwaysBreakTemplateDeclarations: false
|
||||
AlwaysBreakAfterDefinitionReturnType: None
|
||||
AlwaysBreakAfterReturnType: None
|
||||
AlwaysBreakBeforeMultilineStrings: false
|
||||
BreakBeforeBinaryOperators: false
|
||||
AlwaysBreakTemplateDeclarations: false
|
||||
BinPackArguments: true
|
||||
BinPackParameters: true
|
||||
BraceWrapping:
|
||||
AfterClass: false
|
||||
AfterControlStatement: false
|
||||
AfterEnum: false
|
||||
AfterFunction: false
|
||||
AfterNamespace: false
|
||||
AfterObjCDeclaration: false
|
||||
AfterStruct: false
|
||||
AfterUnion: false
|
||||
BeforeCatch: false
|
||||
BeforeElse: false
|
||||
IndentBraces: false
|
||||
BreakBeforeBinaryOperators: None
|
||||
BreakBeforeBraces: Attach
|
||||
BreakBeforeTernaryOperators: true
|
||||
BreakConstructorInitializersBeforeComma: false
|
||||
BinPackParameters: true
|
||||
BreakAfterJavaFieldAnnotations: false
|
||||
BreakStringLiterals: true
|
||||
ColumnLimit: 80
|
||||
ConstructorInitializerAllOnOneLineOrOnePerLine: false
|
||||
CommentPragmas: '^ IWYU pragma:'
|
||||
ConstructorInitializerAllOnOneLineOrOnePerLine: true
|
||||
ConstructorInitializerIndentWidth: 4
|
||||
ContinuationIndentWidth: 4
|
||||
Cpp11BracedListStyle: true
|
||||
DerivePointerAlignment: false
|
||||
DisableFormat: false
|
||||
ExperimentalAutoDetectBinPacking: false
|
||||
ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ]
|
||||
IncludeCategories:
|
||||
- Regex: '^"(llvm|llvm-c|clang|clang-c)/'
|
||||
Priority: 2
|
||||
- Regex: '^(<|"(gtest|isl|json)/)'
|
||||
Priority: 3
|
||||
- Regex: '.*'
|
||||
Priority: 1
|
||||
IncludeIsMainRegex: '$'
|
||||
IndentCaseLabels: false
|
||||
IndentWidth: 2
|
||||
IndentWrappedFunctionNames: false
|
||||
IndentFunctionDeclarationAfterType: false
|
||||
MaxEmptyLinesToKeep: 1
|
||||
JavaScriptQuotes: Leave
|
||||
JavaScriptWrapImports: true
|
||||
KeepEmptyLinesAtTheStartOfBlocks: true
|
||||
MacroBlockBegin: ''
|
||||
MacroBlockEnd: ''
|
||||
MaxEmptyLinesToKeep: 1
|
||||
NamespaceIndentation: None
|
||||
ObjCBlockIndentWidth: 2
|
||||
ObjCSpaceAfterProperty: false
|
||||
ObjCSpaceBeforeProtocolList: true
|
||||
PenaltyBreakBeforeFirstCallParameter: 19
|
||||
PenaltyBreakComment: 300
|
||||
PenaltyBreakString: 1000
|
||||
PenaltyBreakFirstLessLess: 120
|
||||
PenaltyBreakString: 1000
|
||||
PenaltyExcessCharacter: 1000000
|
||||
PenaltyReturnTypeOnItsOwnLine: 60
|
||||
PointerAlignment: Right
|
||||
ReflowComments: true
|
||||
SortIncludes: false
|
||||
SpaceAfterCStyleCast: false
|
||||
SpaceBeforeAssignmentOperators: true
|
||||
SpaceBeforeParens: ControlStatements
|
||||
SpaceInEmptyParentheses: false
|
||||
SpacesBeforeTrailingComments: 1
|
||||
Cpp11BracedListStyle: true
|
||||
SpacesInAngles: false
|
||||
SpacesInContainerLiterals: true
|
||||
SpacesInCStyleCastParentheses: false
|
||||
SpacesInParentheses: false
|
||||
SpacesInSquareBrackets: false
|
||||
Standard: Cpp11
|
||||
IndentWidth: 2
|
||||
TabWidth: 8
|
||||
UseTab: Never
|
||||
BreakBeforeBraces: Attach
|
||||
SpacesInParentheses: false
|
||||
SpacesInAngles: false
|
||||
SpaceInEmptyParentheses: false
|
||||
SpacesInCStyleCastParentheses: false
|
||||
SpacesInContainerLiterals: true
|
||||
SpaceBeforeAssignmentOperators: true
|
||||
ContinuationIndentWidth: 4
|
||||
CommentPragmas: '^ IWYU pragma:'
|
||||
ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ]
|
||||
SpaceBeforeParens: ControlStatements
|
||||
DisableFormat: false
|
||||
...
|
||||
|
||||
|
||||
16
.gitignore
vendored
16
.gitignore
vendored
@@ -29,6 +29,22 @@ missing
|
||||
stamp-h1
|
||||
test-driver
|
||||
|
||||
# cmake
|
||||
CMakeCache.txt
|
||||
CMakeFiles/
|
||||
cmake_install.cmake
|
||||
install_manifest.txt
|
||||
CTestTestfile.cmake
|
||||
build.ninja
|
||||
rules.ninja
|
||||
.ninja_deps
|
||||
.ninja_log
|
||||
lib*.so
|
||||
lib*.so.*
|
||||
lib*.a
|
||||
# generated by "make test" with cmake
|
||||
Testing/
|
||||
|
||||
# test logs generated by `make check`
|
||||
*.log
|
||||
*.trs
|
||||
|
||||
29
.travis.yml
29
.travis.yml
@@ -1,3 +1,7 @@
|
||||
env:
|
||||
matrix:
|
||||
- CI_BUILD=cmake
|
||||
- CI_BUILD=autotools
|
||||
language: cpp
|
||||
compiler:
|
||||
- clang
|
||||
@@ -7,6 +11,7 @@ addons:
|
||||
apt:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
- george-edison55-precise-backports
|
||||
packages:
|
||||
- g++-4.9
|
||||
- libstdc++-4.9-dev
|
||||
@@ -23,11 +28,15 @@ addons:
|
||||
- libevent-dev
|
||||
- libjansson-dev
|
||||
- libjemalloc-dev
|
||||
- libc-ares-dev
|
||||
- cmake
|
||||
- cmake-data
|
||||
before_install:
|
||||
- $CC --version
|
||||
- if [ "$CXX" = "g++" ]; then export CXX="g++-4.9" CC="gcc-4.9"; fi
|
||||
- $CC --version
|
||||
- go version
|
||||
- cmake --version
|
||||
before_script:
|
||||
# First build spdylay, since integration tests require it.
|
||||
# spdylay is going to be built under third-party/spdylay
|
||||
@@ -35,18 +44,22 @@ before_script:
|
||||
- git clone https://github.com/tatsuhiro-t/spdylay.git
|
||||
- cd spdylay
|
||||
- autoreconf -i
|
||||
# Don't use ASAN for spdylay since failmalloc does not work with it.
|
||||
- ./configure --disable-src --disable-examples
|
||||
- make check
|
||||
- export SPDYLAY_HOME=$PWD
|
||||
- cd ../..
|
||||
# Now build nghttp2
|
||||
- autoreconf -i
|
||||
- if [ "$CI_BUILD" = "autotools" ]; then autoreconf -i; fi
|
||||
- git submodule update --init
|
||||
- ./configure --enable-werror --with-mruby --with-neverbleed LIBSPDYLAY_CFLAGS="-I$SPDYLAY_HOME/lib/includes" LIBSPDYLAY_LIBS="-L$SPDYLAY_HOME/lib/.libs -lspdylay"
|
||||
- if [ "$CI_BUILD" = "autotools" ]; then ./configure --enable-werror --with-mruby --with-neverbleed LIBSPDYLAY_CFLAGS="-I$SPDYLAY_HOME/lib/includes" LIBSPDYLAY_LIBS="-L$SPDYLAY_HOME/lib/.libs -lspdylay" CPPFLAGS=-fsanitize=address LDFLAGS=-fsanitize=address; fi
|
||||
- if [ "$CI_BUILD" = "cmake" ]; then cmake -DENABLE_WERROR=1 -DWITH_MRUBY=1 -DWITH_NEVERBLEED=1 -DSPDYLAY_INCLUDE_DIR="$SPDYLAY_HOME/lib/includes" -DSPDYLAY_LIBRARY="$SPDYLAY_HOME/lib/.libs/libspdylay.so"; fi
|
||||
script:
|
||||
- make
|
||||
- make check
|
||||
- cd integration-tests
|
||||
- export GOPATH="$PWD/integration-tests/golang"
|
||||
- make itprep-local
|
||||
- make it-local
|
||||
- if [ "$CI_BUILD" = "autotools" ]; then make distcheck; fi
|
||||
- if [ "$CI_BUILD" = "cmake" ]; then make check; fi
|
||||
# As of April, 23, 2016, golang http2 build fails, probably because
|
||||
# the default go version is too old.
|
||||
# - cd integration-tests
|
||||
# - export GOPATH="$PWD/integration-tests/golang"
|
||||
# - make itprep
|
||||
# - make it
|
||||
|
||||
92
AUTHORS
92
AUTHORS
@@ -1 +1,91 @@
|
||||
Tatsuhiro Tsujikawa <t-tujikawa at users dot sourceforge dot net>
|
||||
nghttp2 project was started as a fork of spdylay project [1]. Both
|
||||
projects were started by Tatsuhiro Tsujikawa, who is still the main
|
||||
author of these projects. Meanwhile, we have many contributions, and
|
||||
we are not here without them. We sincerely thank you to all who made
|
||||
a contribution. Here is the all individuals/organizations who
|
||||
contributed to nghttp2 and spdylay project at which we forked. These
|
||||
names are retrieved from git commit log. If you have made a
|
||||
contribution, but you are missing in the list, please let us know via
|
||||
github issues [2].
|
||||
|
||||
[1] https://github.com/tatsuhiro-t/spdylay
|
||||
[2] https://github.com/nghttp2/nghttp2/issues
|
||||
|
||||
--------
|
||||
|
||||
187j3x1
|
||||
Alek Storm
|
||||
Alex Nalivko
|
||||
Alexis La Goutte
|
||||
Anders Bakken
|
||||
Andreas Pohl
|
||||
Andy Davies
|
||||
Ant Bryan
|
||||
Benedikt Christoph Wolters
|
||||
Bernard Spil
|
||||
Brian Card
|
||||
Brian Suh
|
||||
Daniel Stenberg
|
||||
Dave Reisner
|
||||
David Beitey
|
||||
David Weekly
|
||||
Etienne Cimon
|
||||
Fabian Möller
|
||||
Fabian Wiesel
|
||||
Gabi Davar
|
||||
Google Inc.
|
||||
Jacob Champion
|
||||
Jan-E
|
||||
Janusz Dziemidowicz
|
||||
Jay Satiro
|
||||
Jianqing Wang
|
||||
Jim Morrison
|
||||
José F. Calcerrada
|
||||
Kamil Dudka
|
||||
Kazuho Oku
|
||||
Kenny (kang-yen) Peng
|
||||
Kenny Peng
|
||||
Kit Chan
|
||||
Kyle Schomp
|
||||
Lucas Pardue
|
||||
MATSUMOTO Ryosuke
|
||||
Matt Rudary
|
||||
Mike Conlen
|
||||
Mike Frysinger
|
||||
Nicholas Hurley
|
||||
Nora Shoemaker
|
||||
Peeyush Aggarwal
|
||||
Peter Wu
|
||||
Piotr Sikora
|
||||
Raul Gutierrez Segales
|
||||
Remo E
|
||||
Reza Tavakoli
|
||||
Ross Smith II
|
||||
Scott Mitchell
|
||||
Stefan Eissing
|
||||
Stephen Ludin
|
||||
Sunpoet Po-Chuan Hsieh
|
||||
Svante Signell
|
||||
Syohei YOSHIDA
|
||||
Tatsuhiko Kubo
|
||||
Tatsuhiro Tsujikawa
|
||||
Tom Harwood
|
||||
Tomasz Buchert
|
||||
Vernon Tang
|
||||
Viacheslav Biriukov
|
||||
Viktor Szépe
|
||||
Wenfeng Liu
|
||||
Xiaoguang Sun
|
||||
Zhuoyun Wei
|
||||
acesso
|
||||
ayanamist
|
||||
bxshi
|
||||
dalf
|
||||
es
|
||||
fangdingjun
|
||||
kumagi
|
||||
makovich
|
||||
mod-h2-dev
|
||||
moparisthebest
|
||||
snnn
|
||||
yuuki-kodama
|
||||
|
||||
526
CMakeLists.txt
Normal file
526
CMakeLists.txt
Normal file
@@ -0,0 +1,526 @@
|
||||
# nghttp2 - HTTP/2 C Library
|
||||
#
|
||||
# Copyright (c) 2012, 2013, 2014, 2015 Tatsuhiro Tsujikawa
|
||||
# Copyright (c) 2016 Peter Wu <peter@lekensteyn.nl>
|
||||
#
|
||||
# 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.
|
||||
|
||||
cmake_minimum_required(VERSION 3.0)
|
||||
# XXX using 1.8.90 instead of 1.9.0-DEV
|
||||
project(nghttp2 VERSION 1.19.0)
|
||||
|
||||
# See versioning rule:
|
||||
# http://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html
|
||||
set(LT_CURRENT 26)
|
||||
set(LT_REVISION 4)
|
||||
set(LT_AGE 12)
|
||||
|
||||
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
|
||||
include(Version)
|
||||
|
||||
math(EXPR LT_SOVERSION "${LT_CURRENT} - ${LT_AGE}")
|
||||
set(LT_VERSION "${LT_SOVERSION}.${LT_AGE}.${LT_REVISION}")
|
||||
set(PACKAGE_VERSION "${PROJECT_VERSION}")
|
||||
HexVersion(PACKAGE_VERSION_NUM ${PROJECT_VERSION_MAJOR} ${PROJECT_VERSION_MINOR} ${PROJECT_VERSION_PATCH})
|
||||
|
||||
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
|
||||
set(CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING "Choose the build type" FORCE)
|
||||
|
||||
# Include "None" as option to disable any additional (optimization) flags,
|
||||
# relying on just CMAKE_C_FLAGS and CMAKE_CXX_FLAGS (which are empty by
|
||||
# default). These strings are presented in cmake-gui.
|
||||
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS
|
||||
"None" "Debug" "Release" "MinSizeRel" "RelWithDebInfo")
|
||||
endif()
|
||||
|
||||
include(GNUInstallDirs)
|
||||
|
||||
# For Python bindings and documentation
|
||||
# (Must be called before PythonLibs for matching versions.)
|
||||
find_package(PythonInterp)
|
||||
|
||||
# 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)
|
||||
if(OPENSSL_FOUND AND LIBEV_FOUND AND ZLIB_FOUND)
|
||||
set(ENABLE_APP_DEFAULT ON)
|
||||
else()
|
||||
set(ENABLE_APP_DEFAULT OFF)
|
||||
endif()
|
||||
find_package(Jansson 2.5)
|
||||
set(ENABLE_HPACK_TOOLS_DEFAULT ${JANSSON_FOUND})
|
||||
# 2.0.8 is required because we use evconnlistener_set_error_cb()
|
||||
find_package(Libevent 2.0.8 COMPONENTS libevent openssl)
|
||||
set(ENABLE_EXAMPLES_DEFAULT ${LIBEVENT_OPENSSL_FOUND})
|
||||
find_package(Cython)
|
||||
find_package(PythonLibs)
|
||||
if(CYTHON_FOUND AND PYTHONLIBS_FOUND)
|
||||
set(ENABLE_PYTHON_BINDINGS_DEFAULT ON)
|
||||
else()
|
||||
set(ENABLE_PYTHON_BINDINGS_DEFAULT OFF)
|
||||
endif()
|
||||
|
||||
find_package(LibXml2 2.7.7)
|
||||
set(WITH_LIBXML2_DEFAULT ${LIBXML2_FOUND})
|
||||
find_package(Jemalloc)
|
||||
set(WITH_JEMALLOC_DEFAULT ${JEMALLOC_FOUND})
|
||||
find_package(Spdylay 1.3.2)
|
||||
set(WITH_SPDYLAY_DEFAULT ${SPDYLAY_FOUND})
|
||||
|
||||
include(CMakeOptions.txt)
|
||||
|
||||
if(ENABLE_LIB_ONLY AND (ENABLE_APP OR ENABLE_HPACK_TOOLS OR ENABLE_EXAMPLES OR
|
||||
ENABLE_PYTHON_BINDINGS))
|
||||
# Remember when disabled options are disabled for later diagnostics.
|
||||
set(ENABLE_LIB_ONLY_DISABLED_OTHERS 1)
|
||||
else()
|
||||
set(ENABLE_LIB_ONLY_DISABLED_OTHERS 0)
|
||||
endif()
|
||||
if(ENABLE_LIB_ONLY)
|
||||
set(ENABLE_APP OFF)
|
||||
set(ENABLE_HPACK_TOOLS OFF)
|
||||
set(ENABLE_EXAMPLES OFF)
|
||||
set(ENABLE_PYTHON_BINDINGS OFF)
|
||||
endif()
|
||||
|
||||
# Do not disable assertions based on CMAKE_BUILD_TYPE.
|
||||
foreach(_build_type "Release" "MinSizeRel" "RelWithDebInfo")
|
||||
foreach(_lang C CXX)
|
||||
string(TOUPPER "CMAKE_${_lang}_FLAGS_${_build_type}" _var)
|
||||
string(REGEX REPLACE "(^| )[/-]D *NDEBUG($| )" "" ${_var} "${${_var}}")
|
||||
endforeach()
|
||||
endforeach()
|
||||
|
||||
#
|
||||
# If we're running GCC or clang define _U_ to be "__attribute__((unused))"
|
||||
# so we can use _U_ to flag unused function parameters and not get warnings
|
||||
# about them. Otherwise, define _U_ to be an empty string so that _U_ used
|
||||
# to flag an unused function parameters will compile with other compilers.
|
||||
#
|
||||
# XXX - similar hints for other compilers?
|
||||
#
|
||||
if(CMAKE_C_COMPILER_ID MATCHES "GNU" OR CMAKE_C_COMPILER_ID MATCHES "Clang")
|
||||
set(HINT_UNUSED_PARAM "__attribute__((unused))")
|
||||
set(HINT_NORETURN "__attribute__((noreturn))")
|
||||
else()
|
||||
set(HINT_UNUSED_PARAM)
|
||||
set(HINT_NORETURN)
|
||||
endif()
|
||||
|
||||
include(ExtractValidFlags)
|
||||
foreach(_cxx1x_flag -std=c++11 -std=c++0x)
|
||||
extract_valid_cxx_flags(_cxx1x_flag_supported ${_cxx1x_flag})
|
||||
if(_cxx1x_flag_supported)
|
||||
set(CXX1XCXXFLAGS ${_cxx1x_flag})
|
||||
break()
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
include(CMakePushCheckState)
|
||||
include(CheckCXXSourceCompiles)
|
||||
cmake_push_check_state()
|
||||
set(CMAKE_REQUIRED_DEFINITIONS "${CXX1XCXXFLAGS}")
|
||||
# Check that std::future is available.
|
||||
check_cxx_source_compiles("
|
||||
#include <vector>
|
||||
#include <future>
|
||||
int main() { std::vector<std::future<int>> v; }" HAVE_STD_FUTURE)
|
||||
# Check that std::map::emplace is available for g++-4.7.
|
||||
check_cxx_source_compiles("
|
||||
#include <map>
|
||||
int main() { std::map<int, int>().emplace(1, 2); }" HAVE_STD_MAP_EMPLACE)
|
||||
cmake_pop_check_state()
|
||||
|
||||
|
||||
# Checks for libraries.
|
||||
# Additional libraries required for programs under src directory.
|
||||
set(APP_LIBRARIES)
|
||||
|
||||
if(ENABLE_PYTHON_BINDINGS)
|
||||
if(NOT (CYTHON_FOUND AND PYTHONLIBS_FOUND))
|
||||
message(FATAL_ERROR "python bindings were requested "
|
||||
"(ENABLE_PYTHON_BINDINGS=1) but dependencies are not met.")
|
||||
endif()
|
||||
if(NOT PYTHON_VERSION_STRING STREQUAL PYTHONLIBS_VERSION_STRING)
|
||||
message(FATAL_ERROR
|
||||
"Python executable and library must have the same version!"
|
||||
" Found Python ${PYTHON_VERSION_STRING} and"
|
||||
" PythonLibs ${PYTHONLIBS_VERSION_STRING}"
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(CMAKE_THREAD_PREFER_PTHREAD 1)
|
||||
find_package(Threads)
|
||||
if(CMAKE_USE_PTHREADS_INIT)
|
||||
list(APPEND APP_LIBRARIES ${CMAKE_THREAD_LIBS_INIT})
|
||||
endif()
|
||||
# XXX android and C++, is this still needed in cmake?
|
||||
# case "$host" in
|
||||
# *android*)
|
||||
# android_build=yes
|
||||
# # android does not need -pthread, but needs followng 3 libs for C++
|
||||
# APPLDFLAGS="$APPLDFLAGS -lstdc++ -latomic -lsupc++"
|
||||
|
||||
# dl: openssl requires libdl when it is statically linked.
|
||||
# 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()
|
||||
|
||||
# openssl (for src)
|
||||
set(HAVE_OPENSSL ${OPENSSL_FOUND})
|
||||
if(OPENSSL_FOUND)
|
||||
set(OPENSSL_INCLUDE_DIRS ${OPENSSL_INCLUDE_DIR})
|
||||
else()
|
||||
set(OPENSSL_INCLUDE_DIRS "")
|
||||
set(OPENSSL_LIBRARIES "")
|
||||
endif()
|
||||
# libev (for src)
|
||||
set(HAVE_LIBEV ${LIBEV_FOUND})
|
||||
set(HAVE_ZLIB ${ZLIB_FOUND})
|
||||
set(HAVE_LIBEVENT_OPENSSL ${LIBEVENT_FOUND})
|
||||
if(LIBEVENT_FOUND)
|
||||
# Must both link the core and openssl libraries.
|
||||
set(LIBEVENT_OPENSSL_LIBRARIES ${LIBEVENT_LIBRARIES})
|
||||
endif()
|
||||
# libc-ares (for src)
|
||||
set(HAVE_LIBCARES ${LIBCARES_FOUND})
|
||||
if(LIBCARES_FOUND)
|
||||
set(LIBCARES_INCLUDE_DIRS ${LIBCARES_INCLUDE_DIR})
|
||||
else()
|
||||
set(LIBCARES_INCLUDE_DIRS "")
|
||||
set(LIBCARES_LIBRARIES "")
|
||||
endif()
|
||||
# jansson (for src/nghttp, src/deflatehd and src/inflatehd)
|
||||
set(HAVE_JANSSON ${JANSSON_FOUND})
|
||||
# libxml2 (for src/nghttp)
|
||||
set(HAVE_LIBXML2 ${LIBXML2_FOUND})
|
||||
if(LIBXML2_FOUND)
|
||||
set(LIBXML2_INCLUDE_DIRS ${LIBXML2_INCLUDE_DIR})
|
||||
else()
|
||||
set(LIBXML2_INCLUDE_DIRS "")
|
||||
set(LIBXML2_LIBRARIES "")
|
||||
endif()
|
||||
# jemalloc
|
||||
set(HAVE_JEMALLOC ${JEMALLOC_FOUND})
|
||||
# spdylay (for src/nghttpx and src/h2load)
|
||||
set(HAVE_SPDYLAY ${SPDYLAY_FOUND})
|
||||
|
||||
if(ENABLE_ASIO_LIB)
|
||||
find_package(Boost 1.54.0 REQUIRED system thread)
|
||||
endif()
|
||||
|
||||
# The nghttp, nghttpd and nghttpx under src depend on zlib, OpenSSL and libev
|
||||
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()
|
||||
|
||||
# HPACK tools requires jansson
|
||||
if(ENABLE_HPACK_TOOLS AND NOT HAVE_JANSSON)
|
||||
message(FATAL_ERROR "HPACK tools were requested (ENABLE_HPACK_TOOLS=1) but dependencies are not met.")
|
||||
endif()
|
||||
|
||||
# C++ library libnghttp2_asio
|
||||
if(ENABLE_EXAMPLES AND NOT (OPENSSL_FOUND AND LIBEVENT_OPENSSL_FOUND))
|
||||
message(FATAL_ERROR "examples were requested (ENABLE_EXAMPLES=1) but dependencies are not met.")
|
||||
endif()
|
||||
|
||||
# third-party http-parser only be built when needed
|
||||
if(ENABLE_EXAMPLES OR ENABLE_APP OR ENABLE_HPACK_TOOLS OR ENABLE_ASIO_LIB)
|
||||
set(ENABLE_THIRD_PARTY 1)
|
||||
# mruby (for src/nghttpx)
|
||||
set(HAVE_MRUBY ${WITH_MRUBY})
|
||||
set(HAVE_NEVERBLEED ${WITH_NEVERBLEED})
|
||||
else()
|
||||
set(HAVE_MRUBY 0)
|
||||
set(HAVE_NEVERBLEED 0)
|
||||
endif()
|
||||
|
||||
# Checks for header files.
|
||||
include(CheckIncludeFile)
|
||||
check_include_file("arpa/inet.h" HAVE_ARPA_INET_H)
|
||||
check_include_file("fcntl.h" HAVE_FCNTL_H)
|
||||
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("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)
|
||||
|
||||
include(CheckTypeSize)
|
||||
# Checks for typedefs, structures, and compiler characteristics.
|
||||
# AC_TYPE_SIZE_T
|
||||
check_type_size("ssize_t" SIZEOF_SSIZE_T)
|
||||
if(SIZEOF_SSIZE_T STREQUAL "")
|
||||
# ssize_t is a signed type in POSIX storing at least -1.
|
||||
# Set it to "int" to match the behavior of AC_TYPE_SSIZE_T (autotools).
|
||||
set(ssize_t int)
|
||||
endif()
|
||||
# AC_TYPE_UINT8_T
|
||||
# AC_TYPE_UINT16_T
|
||||
# AC_TYPE_UINT32_T
|
||||
# AC_TYPE_UINT64_T
|
||||
# AC_TYPE_INT8_T
|
||||
# AC_TYPE_INT16_T
|
||||
# AC_TYPE_INT32_T
|
||||
# AC_TYPE_INT64_T
|
||||
# AC_TYPE_OFF_T
|
||||
# AC_TYPE_PID_T
|
||||
# AC_TYPE_UID_T
|
||||
# XXX To support inline for crappy compilers, see https://cmake.org/Wiki/CMakeTestInline
|
||||
# AC_C_INLINE
|
||||
# XXX is AC_SYS_LARGEFILE still needed for modern systems?
|
||||
# add_definitions(-D_FILE_OFFSET_BITS=64)
|
||||
|
||||
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)
|
||||
|
||||
include(CheckSymbolExists)
|
||||
# XXX does this correctly detect initgroups (un)availability on cygwin?
|
||||
check_symbol_exists(initgroups grp.h HAVE_DECL_INITGROUPS)
|
||||
if(NOT HAVE_DECL_INITGROUPS AND HAVE_UNISTD_H)
|
||||
# FreeBSD declares initgroups() in unistd.h
|
||||
check_symbol_exists(initgroups unistd.h HAVE_DECL_INITGROUPS2)
|
||||
if(HAVE_DECL_INITGROUPS2)
|
||||
set(HAVE_DECL_INITGROUPS 1)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(WARNCFLAGS)
|
||||
set(WARNCXXFLAGS)
|
||||
if(CMAKE_C_COMPILER_ID MATCHES "MSVC")
|
||||
if(ENABLE_WERROR)
|
||||
set(WARNCFLAGS /WX)
|
||||
set(WARNCXXFLAGS /WX)
|
||||
endif()
|
||||
else()
|
||||
if(ENABLE_WERROR)
|
||||
extract_valid_c_flags(WARNCFLAGS -Werror)
|
||||
extract_valid_c_flags(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
|
||||
)
|
||||
endif()
|
||||
|
||||
if(ENABLE_DEBUG)
|
||||
set(DEBUGBUILD 1)
|
||||
endif()
|
||||
|
||||
# Some platform does not have working std::future. We disable
|
||||
# threading for those platforms.
|
||||
if(NOT ENABLE_THREADS OR NOT HAVE_STD_FUTURE)
|
||||
set(NOTHREADS 1)
|
||||
endif()
|
||||
|
||||
add_definitions(-DHAVE_CONFIG_H)
|
||||
configure_file(cmakeconfig.h.in config.h)
|
||||
# autotools-compatible names
|
||||
# Sphinx expects relative paths in the .rst files. Use the fact that the files
|
||||
# below are all one directory level deep.
|
||||
file(RELATIVE_PATH top_srcdir "${CMAKE_CURRENT_BINARY_DIR}/dir" "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||
file(RELATIVE_PATH top_builddir "${CMAKE_CURRENT_BINARY_DIR}/dir" "${CMAKE_CURRENT_BINARY_DIR}")
|
||||
set(abs_top_srcdir "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||
set(abs_top_builddir "${CMAKE_CURRENT_BINARY_DIR}")
|
||||
# libnghttp2.pc (pkg-config file)
|
||||
set(prefix "${CMAKE_INSTALL_PREFIX}")
|
||||
set(exec_prefix "${CMAKE_INSTALL_PREFIX}")
|
||||
set(libdir "${CMAKE_INSTALL_FULL_LIBDIR}")
|
||||
set(includedir "${CMAKE_INSTALL_FULL_INCLUDEDIR}")
|
||||
set(VERSION "${PACKAGE_VERSION}")
|
||||
# For init scripts and systemd service file (in contrib/)
|
||||
set(bindir "${CMAKE_INSTALL_FULL_BINDIR}")
|
||||
set(sbindir "${CMAKE_INSTALL_FULL_SBINDIR}")
|
||||
foreach(name
|
||||
lib/libnghttp2.pc
|
||||
lib/includes/nghttp2/nghttp2ver.h
|
||||
src/libnghttp2_asio.pc
|
||||
python/setup.py
|
||||
integration-tests/config.go
|
||||
integration-tests/setenv
|
||||
doc/conf.py
|
||||
doc/index.rst
|
||||
doc/package_README.rst
|
||||
doc/tutorial-client.rst
|
||||
doc/tutorial-server.rst
|
||||
doc/tutorial-hpack.rst
|
||||
doc/nghttpx-howto.rst
|
||||
doc/h2load-howto.rst
|
||||
doc/libnghttp2_asio.rst
|
||||
doc/python-apiref.rst
|
||||
doc/building-android-binary.rst
|
||||
doc/nghttp2.h.rst
|
||||
doc/nghttp2ver.h.rst
|
||||
doc/asio_http2.h.rst
|
||||
doc/asio_http2_server.h.rst
|
||||
doc/asio_http2_client.h.rst
|
||||
doc/contribute.rst
|
||||
)
|
||||
configure_file("${name}.in" "${name}" @ONLY)
|
||||
endforeach()
|
||||
|
||||
include_directories(
|
||||
"${CMAKE_CURRENT_BINARY_DIR}" # for config.h
|
||||
)
|
||||
# For use in src/CMakeLists.txt
|
||||
set(PKGDATADIR "${CMAKE_INSTALL_FULL_DATADIR}/${CMAKE_PROJECT_NAME}")
|
||||
|
||||
install(FILES README.rst DESTINATION "${CMAKE_INSTALL_DOCDIR}")
|
||||
|
||||
add_subdirectory(lib)
|
||||
#add_subdirectory(lib/includes)
|
||||
add_subdirectory(third-party)
|
||||
add_subdirectory(src)
|
||||
#add_subdirectory(src/includes)
|
||||
add_subdirectory(examples)
|
||||
add_subdirectory(python)
|
||||
add_subdirectory(tests)
|
||||
#add_subdirectory(tests/testdata)
|
||||
add_subdirectory(integration-tests)
|
||||
add_subdirectory(doc)
|
||||
add_subdirectory(contrib)
|
||||
add_subdirectory(script)
|
||||
|
||||
|
||||
string(TOUPPER "${CMAKE_BUILD_TYPE}" _build_type)
|
||||
message(STATUS "summary of build options:
|
||||
|
||||
Package version: ${VERSION}
|
||||
Library version: ${LT_CURRENT}:${LT_REVISION}:${LT_AGE}
|
||||
Install prefix: ${CMAKE_INSTALL_PREFIX}
|
||||
Target system: ${CMAKE_SYSTEM_NAME}
|
||||
Compiler:
|
||||
Build type: ${CMAKE_BUILD_TYPE}
|
||||
C compiler: ${CMAKE_C_COMPILER}
|
||||
CFLAGS: ${CMAKE_C_FLAGS_${_build_type}} ${CMAKE_C_FLAGS}
|
||||
C++ compiler: ${CMAKE_CXX_COMPILER}
|
||||
CXXFLAGS: ${CMAKE_CXX_FLAGS_${_build_type}} ${CMAKE_CXX_FLAGS}
|
||||
WARNCFLAGS: ${WARNCFLAGS}
|
||||
CXX1XCXXFLAGS: ${CXX1XCXXFLAGS}
|
||||
Python:
|
||||
Python: ${PYTHON_EXECUTABLE}
|
||||
PYTHON_VERSION: ${PYTHON_VERSION_STRING}
|
||||
Library version:${PYTHONLIBS_VERSION_STRING}
|
||||
Cython: ${CYTHON_EXECUTABLE}
|
||||
Test:
|
||||
CUnit: ${HAVE_CUNIT} (LIBS='${CUNIT_LIBRARIES}')
|
||||
Failmalloc: ${ENABLE_FAILMALLOC}
|
||||
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}')
|
||||
Libevent(SSL): ${HAVE_LIBEVENT_OPENSSL} (LIBS='${LIBEVENT_OPENSSL_LIBRARIES}')
|
||||
Spdylay: ${HAVE_SPDYLAY} (LIBS='${SPDYLAY_LIBRARIES}')
|
||||
Jansson: ${HAVE_JANSSON} (LIBS='${JANSSON_LIBRARIES}')
|
||||
Jemalloc: ${HAVE_JEMALLOC} (LIBS='${JEMALLOC_LIBRARIES}')
|
||||
Zlib: ${HAVE_ZLIB} (LIBS='${ZLIB_LIBRARIES}')
|
||||
Boost::System: ${Boost_SYSTEM_LIBRARY}
|
||||
Boost::Thread: ${Boost_THREAD_LIBRARY}
|
||||
Third-party:
|
||||
http-parser: ${ENABLE_THIRD_PARTY}
|
||||
MRuby: ${HAVE_MRUBY}
|
||||
Neverbleed: ${HAVE_NEVERBLEED}
|
||||
Features:
|
||||
Applications: ${ENABLE_APP}
|
||||
HPACK tools: ${ENABLE_HPACK_TOOLS}
|
||||
Libnghttp2_asio:${ENABLE_ASIO_LIB}
|
||||
Examples: ${ENABLE_EXAMPLES}
|
||||
Python bindings:${ENABLE_PYTHON_BINDINGS}
|
||||
Threading: ${ENABLE_THREADS}
|
||||
")
|
||||
if(ENABLE_LIB_ONLY_DISABLED_OTHERS)
|
||||
message("Only the library will be built. To build other components "
|
||||
"(such as applications and examples), set ENABLE_LIB_ONLY=OFF.")
|
||||
endif()
|
||||
27
CMakeOptions.txt
Normal file
27
CMakeOptions.txt
Normal file
@@ -0,0 +1,27 @@
|
||||
# Features that can be enabled for cmake (see CMakeLists.txt)
|
||||
|
||||
option(ENABLE_WERROR "Turn on compile time warnings")
|
||||
option(ENABLE_DEBUG "Turn on debug output")
|
||||
option(ENABLE_THREADS "Turn on threading in apps" ON)
|
||||
option(ENABLE_APP "Build applications (nghttp, nghttpd, nghttpx and h2load)"
|
||||
${ENABLE_APP_DEFAULT})
|
||||
option(ENABLE_HPACK_TOOLS "Build HPACK tools"
|
||||
${ENABLE_HPACK_TOOLS_DEFAULT})
|
||||
option(ENABLE_ASIO_LIB "Build C++ libnghttp2_asio library")
|
||||
option(ENABLE_EXAMPLES "Build examples"
|
||||
${ENABLE_EXAMPLES_DEFAULT})
|
||||
option(ENABLE_PYTHON_BINDINGS "Build Python bindings"
|
||||
${ENABLE_PYTHON_BINDINGS_DEFAULT})
|
||||
option(ENABLE_FAILMALLOC "Build failmalloc test program" ON)
|
||||
option(ENABLE_LIB_ONLY "Build libnghttp2 only. This is a short hand for -DENABLE_APP=0 -DENABLE_EXAMPLES=0 -DENABLE_HPACK_TOOLS=0 -DENABLE_PYTHON_BINDINGS=0")
|
||||
|
||||
option(WITH_LIBXML2 "Use libxml2"
|
||||
${WITH_LIBXML2_DEFAULT})
|
||||
option(WITH_JEMALLOC "Use jemalloc"
|
||||
${WITH_JEMALLOC_DEFAULT})
|
||||
option(WITH_SPDYLAY "Use spdylay"
|
||||
${WITH_SPDYLAY_DEFAULT})
|
||||
option(WITH_MRUBY "Use mruby")
|
||||
option(WITH_NEVERBLEED "Use neverbleed")
|
||||
|
||||
# vim: ft=cmake:
|
||||
1
COPYING
1
COPYING
@@ -1,6 +1,7 @@
|
||||
The MIT License
|
||||
|
||||
Copyright (c) 2012, 2014, 2015, 2016 Tatsuhiro Tsujikawa
|
||||
Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
|
||||
@@ -106,7 +106,7 @@ RUN HOST=arm-linux-androideabi \
|
||||
make install
|
||||
|
||||
WORKDIR /root/build
|
||||
RUN git clone https://github.com/tatsuhiro-t/nghttp2
|
||||
RUN git clone https://github.com/nghttp2/nghttp2
|
||||
WORKDIR /root/build/nghttp2
|
||||
RUN autoreconf -i && \
|
||||
./configure \
|
||||
|
||||
15
Makefile.am
15
Makefile.am
@@ -33,7 +33,20 @@ ACLOCAL_AMFLAGS = -I m4
|
||||
dist_doc_DATA = README.rst
|
||||
|
||||
EXTRA_DIST = nghttpx.conf.sample proxy.pac.sample android-config android-make \
|
||||
Dockerfile.android
|
||||
Dockerfile.android \
|
||||
cmakeconfig.h.in \
|
||||
CMakeLists.txt \
|
||||
CMakeOptions.txt \
|
||||
cmake/FindSpdylay.cmake \
|
||||
cmake/ExtractValidFlags.cmake \
|
||||
cmake/FindJemalloc.cmake \
|
||||
cmake/FindLibev.cmake \
|
||||
cmake/FindCUnit.cmake \
|
||||
cmake/Version.cmake \
|
||||
cmake/FindCython.cmake \
|
||||
cmake/FindLibevent.cmake \
|
||||
cmake/FindJansson.cmake \
|
||||
cmake/FindLibcares.cmake
|
||||
|
||||
.PHONY: clang-format
|
||||
|
||||
|
||||
243
README.rst
243
README.rst
@@ -58,13 +58,19 @@ To build the documentation, you need to install:
|
||||
|
||||
* sphinx (http://sphinx-doc.org/)
|
||||
|
||||
To build and run the application programs (``nghttp``, ``nghttpd`` and
|
||||
``nghttpx``) in the ``src`` directory, the following packages are
|
||||
required:
|
||||
If you need libnghttp2 (C library) only, then the above packages are
|
||||
all you need. Use ``--enable-lib-only`` to ensure that only
|
||||
libnghttp2 is built. This avoids potential build error related to
|
||||
building bundled applications.
|
||||
|
||||
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
|
||||
* libev >= 4.15
|
||||
* 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
|
||||
@@ -93,6 +99,11 @@ To mitigate heap fragmentation in long running server programs
|
||||
|
||||
* jemalloc
|
||||
|
||||
.. note::
|
||||
|
||||
Alpine Linux currently does not support malloc replacement
|
||||
due to musl limitations. See details in issue `#762 <https://github.com/nghttp2/nghttp2/issues/762>`_.
|
||||
|
||||
libnghttp2_asio C++ library requires the following packages:
|
||||
|
||||
* libboost-dev >= 1.54.0
|
||||
@@ -104,14 +115,17 @@ The Python bindings require the following packages:
|
||||
* python >= 2.7
|
||||
* python-setuptools
|
||||
|
||||
If you are using Ubuntu 14.04 LTS (trusty) or Debian 7.0 (wheezy) and above run the following to install the needed packages::
|
||||
If you are using Ubuntu 14.04 LTS (trusty) or Debian 7.0 (wheezy) and above run the following to install the needed packages:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
sudo apt-get install g++ make binutils autoconf automake autotools-dev libtool pkg-config \
|
||||
zlib1g-dev libcunit1-dev libssl-dev libxml2-dev libev-dev libevent-dev libjansson-dev \
|
||||
libjemalloc-dev cython python3-dev python-setuptools
|
||||
libc-ares-dev libjemalloc-dev cython python3-dev python-setuptools
|
||||
|
||||
spdylay is not packaged in Ubuntu, so you need to build it yourself:
|
||||
http://tatsuhiro-t.github.io/spdylay/
|
||||
From Ubuntu 15.10, spdylay has been available as a package named
|
||||
`libspdylay-dev`. For the earlier Ubuntu release, you need to build
|
||||
it yourself: http://tatsuhiro-t.github.io/spdylay/
|
||||
|
||||
To enable mruby support for nghttpx, `mruby
|
||||
<https://github.com/mruby/mruby>`_ is required. We need to build
|
||||
@@ -137,8 +151,11 @@ Building from git
|
||||
-----------------
|
||||
|
||||
Building from git is easy, but please be sure that at least autoconf 2.68 is
|
||||
used::
|
||||
used:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
$ git submodule update --init
|
||||
$ autoreconf -i
|
||||
$ automake
|
||||
$ autoconf
|
||||
@@ -149,8 +166,7 @@ To compile the source code, gcc >= 4.8.3 or clang >= 3.4 is required.
|
||||
|
||||
.. note::
|
||||
|
||||
To enable mruby support in nghttpx, run ``git submodule update
|
||||
--init`` before running configure script, and use ``--with-mruby``
|
||||
To enable mruby support in nghttpx, and use ``--with-mruby``
|
||||
configure option.
|
||||
|
||||
.. note::
|
||||
@@ -160,6 +176,34 @@ To compile the source code, gcc >= 4.8.3 or clang >= 3.4 is required.
|
||||
them from crashing. A patch is welcome to make multi threading work
|
||||
on Mac OS X platform.
|
||||
|
||||
.. note::
|
||||
|
||||
To compile the associated applications (nghttp, nghttpd, nghttpx
|
||||
and h2load), you must use the ``--enable-app`` configure option and
|
||||
ensure that the specified requirements above are met. Normally,
|
||||
configure script checks required dependencies to build these
|
||||
applications, and enable ``--enable-app`` automatically, so you
|
||||
don't have to use it explicitly. But if you found that
|
||||
applications were not built, then using ``--enable-app`` may find
|
||||
that cause, such as the missing dependency.
|
||||
|
||||
Notes for building on Windows (MSVC)
|
||||
------------------------------------
|
||||
|
||||
The easiest way to build native Windows nghttp2 dll is use `cmake
|
||||
<https://cmake.org/>`_. The free version of `Visual C++ Build Tools
|
||||
<http://landinghub.visualstudio.com/visual-cpp-build-tools>`_ works
|
||||
fine.
|
||||
|
||||
1. Install cmake for windows
|
||||
2. Open "Visual C++ ... Native Build Tool Command Prompt", and inside
|
||||
nghttp2 directly, run ``cmake``.
|
||||
3. Then run ``cmake --build`` to build library.
|
||||
4. nghttp2.dll, nghttp2.lib, nghttp2.exp are placed under lib directory.
|
||||
|
||||
Note that the above steps most likely produce nghttp2 library only.
|
||||
No bundled applications are compiled.
|
||||
|
||||
Notes for building on Windows (Mingw/Cygwin)
|
||||
--------------------------------------------
|
||||
|
||||
@@ -176,7 +220,9 @@ Secondly, you need to undefine the macro ``__STRICT_ANSI__``, if you
|
||||
not, the functions ``fdopen``, ``fileno`` and ``strptime`` will not
|
||||
available.
|
||||
|
||||
the sample command like this::
|
||||
the sample command like this:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
$ export CFLAGS="-U__STRICT_ANSI__ -I$libev_PREFIX/include -L$libev_PREFIX/lib"
|
||||
$ export CXXFLAGS=$CFLAGS
|
||||
@@ -194,7 +240,9 @@ Building the documentation
|
||||
|
||||
Documentation is still incomplete.
|
||||
|
||||
To build the documentation, run::
|
||||
To build the documentation, run:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
$ make html
|
||||
|
||||
@@ -223,12 +271,16 @@ its testing framework. We depend on the following libraries:
|
||||
* https://github.com/tatsuhiro-t/spdy
|
||||
|
||||
To download the above packages, after settings ``GOPATH``, run the
|
||||
following command under ``integration-tests`` directory::
|
||||
following command under ``integration-tests`` directory:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
$ make itprep
|
||||
|
||||
To run the tests, run the following command under
|
||||
``integration-tests`` directory::
|
||||
``integration-tests`` directory:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
$ make it
|
||||
|
||||
@@ -349,7 +401,9 @@ nghttp - client
|
||||
with prior knowledge, HTTP Upgrade and NPN/ALPN TLS extension.
|
||||
|
||||
It has verbose output mode for framing information. Here is sample
|
||||
output from ``nghttp`` client::
|
||||
output from ``nghttp`` client:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
$ nghttp -nv https://nghttp2.org
|
||||
[ 0.190] Connected
|
||||
@@ -432,7 +486,9 @@ output from ``nghttp`` client::
|
||||
[ 0.228] send GOAWAY frame <length=8, flags=0x00, stream_id=0>
|
||||
(last_stream_id=2, error_code=NO_ERROR(0x00), opaque_data(0)=[])
|
||||
|
||||
The HTTP Upgrade is performed like so::
|
||||
The HTTP Upgrade is performed like so:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
$ nghttp -nvu http://nghttp2.org
|
||||
[ 0.011] Connected
|
||||
@@ -528,7 +584,9 @@ The HTTP Upgrade is performed like so::
|
||||
(last_stream_id=2, error_code=NO_ERROR(0x00), opaque_data(0)=[])
|
||||
|
||||
Using the ``-s`` option, ``nghttp`` prints out some timing information for
|
||||
requests, sorted by completion time::
|
||||
requests, sorted by completion time:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
$ nghttp -nas https://nghttp2.org/
|
||||
***** Statistics *****
|
||||
@@ -572,7 +630,9 @@ HTTP/2 connections. No HTTP Upgrade is supported.
|
||||
The ``-p`` option allows users to configure server push.
|
||||
|
||||
Just like ``nghttp``, it has a verbose output mode for framing
|
||||
information. Here is sample output from ``nghttpd``::
|
||||
information. Here is sample output from ``nghttpd``:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
$ nghttpd --no-tls -v 8080
|
||||
IPv4: listen 0.0.0.0:8080
|
||||
@@ -635,50 +695,58 @@ nghttpx - proxy
|
||||
HTTP/1.1, and powers http://nghttp2.org and supports HTTP/2 server
|
||||
push.
|
||||
|
||||
We reworked ``nghttpx`` command-line interface, and as a result, there
|
||||
are several incompatibles from 1.8.0 or earlier. This is necessary to
|
||||
extend its capability, and secure the further feature enhancements in
|
||||
the future release. Please read `Migration from nghttpx v1.8.0 or
|
||||
earlier
|
||||
<https://nghttp2.org/documentation/nghttpx-howto.html#migration-from-nghttpx-v1-8-0-or-earlier>`_
|
||||
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 SPDY &
|
||||
HTTP/2.
|
||||
HTTP/2. ``nghttpx`` also offers the functionality to share session
|
||||
cache and ticket keys among multiple ``nghttpx`` instances via
|
||||
memcached.
|
||||
|
||||
``nghttpx`` has several operational modes:
|
||||
``nghttpx`` has 2 operation modes:
|
||||
|
||||
================== ============================ ============== =============
|
||||
Mode option Frontend Backend Note
|
||||
================== ============================ ============== =============
|
||||
default mode HTTP/2, SPDY, HTTP/1.1 (TLS) HTTP/1.1 Reverse proxy
|
||||
``--http2-proxy`` HTTP/2, SPDY, HTTP/1.1 (TLS) HTTP/1.1 SPDY proxy
|
||||
``--http2-bridge`` HTTP/2, SPDY, HTTP/1.1 (TLS) HTTP/2 (TLS)
|
||||
``--client`` HTTP/2, HTTP/1.1 HTTP/2 (TLS)
|
||||
``--client-proxy`` HTTP/2, HTTP/1.1 HTTP/2 (TLS) Forward proxy
|
||||
================== ============================ ============== =============
|
||||
================== ====================== ================ =============
|
||||
Mode option Frontend Backend Note
|
||||
================== ====================== ================ =============
|
||||
default mode HTTP/2, SPDY, HTTP/1.1 HTTP/1.1, HTTP/2 Reverse proxy
|
||||
``--http2-proxy`` HTTP/2, SPDY, HTTP/1.1 HTTP/1.1, HTTP/2 Forward proxy
|
||||
================== ====================== ================ =============
|
||||
|
||||
The interesting mode at the moment is the default mode. It works like
|
||||
a reverse proxy and listens for HTTP/2, SPDY and HTTP/1.1 and can be
|
||||
deployed as a SSL/TLS terminator for existing web server.
|
||||
|
||||
The default mode, ``--http2-proxy`` and ``--http2-bridge`` modes use
|
||||
SSL/TLS in the frontend connection by default. To disable SSL/TLS,
|
||||
use the ``--frontend-no-tls`` option. If that option is used, SPDY is
|
||||
disabled in the frontend and incoming HTTP/1.1 connections can be
|
||||
upgraded to HTTP/2 through HTTP Upgrade.
|
||||
|
||||
The ``--http2-bridge``, ``--client`` and ``--client-proxy`` modes use
|
||||
SSL/TLS in the backend connection by default. To disable SSL/TLS, use
|
||||
the ``--backend-no-tls`` option.
|
||||
In all modes, the frontend connections are encrypted by SSL/TLS by
|
||||
default. To disable encryption, use the ``no-tls`` keyword in
|
||||
``--frontend`` option. If encryption is disabled, SPDY is disabled in
|
||||
the frontend and incoming HTTP/1.1 connections can be upgraded to
|
||||
HTTP/2 through HTTP Upgrade. On the other hard, backend connections
|
||||
are not encrypted by default. To encrypt backend connections, use
|
||||
``tls`` keyword in ``--backend`` option.
|
||||
|
||||
``nghttpx`` supports a configuration file. See the ``--conf`` option and
|
||||
sample configuration file ``nghttpx.conf.sample``.
|
||||
|
||||
In the default mode, (without any of ``--http2-proxy``,
|
||||
``--http2-bridge``, ``--client-proxy`` and ``--client`` options),
|
||||
``nghttpx`` works as reverse proxy to the backend server::
|
||||
In the default mode, ``nghttpx`` works as reverse proxy to the backend
|
||||
server:
|
||||
|
||||
Client <-- (HTTP/2, SPDY, HTTP/1.1) --> nghttpx <-- (HTTP/1.1) --> Web Server
|
||||
.. code-block:: text
|
||||
|
||||
Client <-- (HTTP/2, SPDY, HTTP/1.1) --> nghttpx <-- (HTTP/1.1, HTTP/2) --> Web Server
|
||||
[reverse proxy]
|
||||
|
||||
With the ``--http2-proxy`` option, it works as a so called secure proxy (aka
|
||||
SPDY proxy)::
|
||||
With the ``--http2-proxy`` option, it works as forward proxy, and it
|
||||
is so called secure HTTP/2 proxy (aka SPDY proxy):
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
Client <-- (HTTP/2, SPDY, HTTP/1.1) --> nghttpx <-- (HTTP/1.1) --> Proxy
|
||||
[secure proxy] (e.g., Squid, ATS)
|
||||
@@ -686,9 +754,9 @@ SPDY proxy)::
|
||||
The ``Client`` in the above example needs to be configured to use
|
||||
``nghttpx`` as secure proxy.
|
||||
|
||||
At the time of this writing, Chrome is the only browser which supports
|
||||
secure proxy. One way to configure Chrome to use a secure proxy is
|
||||
to create a proxy.pac script like this:
|
||||
At the time of this writing, both Chrome and Firefox support secure
|
||||
HTTP/2 proxy. One way to configure Chrome to use a secure proxy is to
|
||||
create a proxy.pac script like this:
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
@@ -700,42 +768,18 @@ to create a proxy.pac script like this:
|
||||
machine nghttpx is running on. Please note that Chrome requires a valid
|
||||
certificate for secure proxy.
|
||||
|
||||
Then run Chrome with the following arguments::
|
||||
Then run Chrome with the following arguments:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
$ google-chrome --proxy-pac-url=file:///path/to/proxy.pac --use-npn
|
||||
|
||||
With ``--http2-bridge``, it accepts HTTP/2, SPDY and HTTP/1.1
|
||||
connections and communicates with the backend in HTTP/2::
|
||||
|
||||
Client <-- (HTTP/2, SPDY, HTTP/1.1) --> nghttpx <-- (HTTP/2) --> Web or HTTP/2 Proxy etc
|
||||
(e.g., nghttpx -s)
|
||||
|
||||
With ``--client-proxy``, it works as a forward proxy and expects
|
||||
that the backend is an HTTP/2 proxy::
|
||||
|
||||
Client <-- (HTTP/2, HTTP/1.1) --> nghttpx <-- (HTTP/2) --> HTTP/2 Proxy
|
||||
[forward proxy] (e.g., nghttpx -s)
|
||||
|
||||
The ``Client`` needs to be configured to use nghttpx as a forward
|
||||
proxy. The frontend HTTP/1.1 connection can be upgraded to HTTP/2
|
||||
through HTTP Upgrade. With the above configuration, one can use
|
||||
HTTP/1.1 client to access and test their HTTP/2 servers.
|
||||
|
||||
With ``--client``, it works as a reverse proxy and expects that
|
||||
the backend is an HTTP/2 Web server::
|
||||
|
||||
Client <-- (HTTP/2, HTTP/1.1) --> nghttpx <-- (HTTP/2) --> Web Server
|
||||
[reverse proxy]
|
||||
|
||||
The frontend HTTP/1.1 connection can be upgraded to HTTP/2
|
||||
through HTTP Upgrade.
|
||||
|
||||
For the operation modes which talk to the backend in HTTP/2 over
|
||||
SSL/TLS, the backend connections can be tunneled through an HTTP proxy.
|
||||
The backend HTTP/2 connections can be tunneled through an HTTP proxy.
|
||||
The proxy is specified using ``--backend-http-proxy-uri``. The
|
||||
following figure illustrates the example of the ``--http2-bridge`` and
|
||||
``--backend-http-proxy-uri`` options to talk to the outside HTTP/2
|
||||
proxy through an HTTP proxy::
|
||||
following figure illustrates how nghttpx talks to the outside HTTP/2
|
||||
proxy through an HTTP proxy:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
Client <-- (HTTP/2, SPDY, HTTP/1.1) --> nghttpx <-- (HTTP/2) --
|
||||
|
||||
@@ -749,7 +793,9 @@ The ``h2load`` program is a benchmarking tool for HTTP/2 and SPDY.
|
||||
The SPDY support is enabled if the program was built with the spdylay
|
||||
library. The UI of ``h2load`` is heavily inspired by ``weighttp``
|
||||
(https://github.com/lighttpd/weighttp). The typical usage is as
|
||||
follows::
|
||||
follows:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
$ h2load -n100000 -c100 -m100 https://localhost:8443/
|
||||
starting benchmark...
|
||||
@@ -837,7 +883,9 @@ Example:
|
||||
With the ``-t`` option, the program can accept more familiar HTTP/1 style
|
||||
header field blocks. Each header set is delimited by an empty line:
|
||||
|
||||
Example::
|
||||
Example:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
:method: GET
|
||||
:scheme: https
|
||||
@@ -1333,7 +1381,7 @@ The extension module is called ``nghttp2``.
|
||||
determined by the ``configure`` script. If the detected Python version is not
|
||||
what you expect, specify a path to Python executable in a ``PYTHON``
|
||||
variable as an argument to configure script (e.g., ``./configure
|
||||
PYTHON=/usr/bin/python3.4``).
|
||||
PYTHON=/usr/bin/python3.5``).
|
||||
|
||||
The following example code illustrates basic usage of the HPACK compressor
|
||||
and decompressor in Python:
|
||||
@@ -1462,3 +1510,32 @@ full real name when contributing!
|
||||
See `Contribution Guidelines
|
||||
<https://nghttp2.org/documentation/contribute.html>`_ for more
|
||||
details.
|
||||
|
||||
Reporting vulnerability
|
||||
-----------------------
|
||||
|
||||
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.
|
||||
|
||||
We may release PATCH releases between the regular releases, mainly for
|
||||
severe security bug fixes.
|
||||
|
||||
We have no plan to break API compatibility changes involving soname
|
||||
bump, so MAJOR version will stay 1 for the foreseeable future.
|
||||
|
||||
License
|
||||
-------
|
||||
|
||||
The MIT License
|
||||
|
||||
@@ -39,9 +39,9 @@ PATH="$TOOLCHAIN"/bin:"$PATH"
|
||||
--without-libxml2 \
|
||||
--disable-python-bindings \
|
||||
--disable-examples \
|
||||
--enable-werror \
|
||||
CC="$TOOLCHAIN"/bin/clang \
|
||||
CXX="$TOOLCHAIN"/bin/clang++ \
|
||||
--disable-threads \
|
||||
CC="$TOOLCHAIN"/bin/arm-linux-androideabi-clang \
|
||||
CXX="$TOOLCHAIN"/bin/arm-linux-androideabi-clang++ \
|
||||
CPPFLAGS="-fPIE -I$PREFIX/include" \
|
||||
PKG_CONFIG_LIBDIR="$PREFIX/lib/pkgconfig" \
|
||||
LDFLAGS="-fPIE -pie -L$PREFIX/lib"
|
||||
|
||||
53
appveyor.yml
Normal file
53
appveyor.yml
Normal file
@@ -0,0 +1,53 @@
|
||||
# Notes:
|
||||
# - Minimal appveyor.yml file is an empty file. All sections are optional.
|
||||
# - Indent each level of configuration with 2 spaces. Do not use tabs!
|
||||
# - All section names are case-sensitive.
|
||||
# - Section names should be unique on each level.
|
||||
|
||||
#---------------------------------#
|
||||
# general configuration #
|
||||
#---------------------------------#
|
||||
|
||||
# version format
|
||||
#version: 0.10.{build}
|
||||
|
||||
# branches to build
|
||||
branches:
|
||||
# blacklist
|
||||
except:
|
||||
- gh-pages
|
||||
|
||||
# Do not build on tags (GitHub only)
|
||||
skip_tags: true
|
||||
|
||||
#---------------------------------#
|
||||
# environment configuration #
|
||||
#---------------------------------#
|
||||
|
||||
os: Windows Server 2012
|
||||
|
||||
# scripts that run after cloning repository
|
||||
install:
|
||||
# install Win-Flex-Bison
|
||||
#- cmd: cinst winflexbison -y
|
||||
|
||||
#---------------------------------#
|
||||
# build configuration #
|
||||
#---------------------------------#
|
||||
|
||||
# scripts to run before build
|
||||
before_build:
|
||||
- cmd: cmake .
|
||||
|
||||
# scripts to run *after* solution is built and *before* automatic packaging occurs (web apps, NuGet packages, Azure Cloud Services)
|
||||
# before_package:
|
||||
|
||||
# scripts to run after build
|
||||
# after_build:
|
||||
|
||||
# to run your custom scripts instead of automatic MSBuild
|
||||
build_script:
|
||||
- cmd: cmake --build .
|
||||
|
||||
# to disable automatic builds
|
||||
# build: off
|
||||
52
author.py
Executable file
52
author.py
Executable file
@@ -0,0 +1,52 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
# script to extract commit author's name from standard input. The
|
||||
# input should be <AUTHOR>:<EMAIL>, one per line.
|
||||
# This script expects the input is created by git-log command:
|
||||
#
|
||||
# git log --format=%aN:%aE
|
||||
#
|
||||
# This script removes duplicates based on email address, breaking a
|
||||
# tie with longer author name. Among the all author names extract the
|
||||
# previous step, we remove duplicate by case-insensitive match.
|
||||
#
|
||||
# So we can do this in one line:
|
||||
#
|
||||
# git log --format=%aN:%aE | sort | uniq | ./author.py > authors
|
||||
|
||||
import sys
|
||||
|
||||
edict = {}
|
||||
|
||||
for line in sys.stdin:
|
||||
author, email = line.strip().split(':', 1)
|
||||
if email in edict:
|
||||
an = edict[email]
|
||||
if len(an) < len(author) or an > author:
|
||||
sys.stderr.write(
|
||||
'eliminated {} in favor of {}\n'.format(an, author))
|
||||
edict[email] = author
|
||||
else:
|
||||
sys.stderr.write(
|
||||
'eliminated {} in favor of {}\n'.format(author, an))
|
||||
else:
|
||||
edict[email] = author
|
||||
|
||||
names = list(sorted(edict.values()))
|
||||
|
||||
ndict = {}
|
||||
|
||||
for name in names:
|
||||
lowname = name.lower()
|
||||
if lowname in ndict:
|
||||
an = ndict[lowname]
|
||||
if an > name:
|
||||
sys.stderr.write('eliminated {} in favor of {}\n'.format(an, name))
|
||||
ndict[lowname] = name
|
||||
else:
|
||||
sys.stderr.write('eliminated {} in favor of {}\n'.format(name, an))
|
||||
else:
|
||||
ndict[lowname] = name
|
||||
|
||||
for name in sorted(ndict.values()):
|
||||
print name
|
||||
31
cmake/ExtractValidFlags.cmake
Normal file
31
cmake/ExtractValidFlags.cmake
Normal file
@@ -0,0 +1,31 @@
|
||||
# Convenience function that checks the availability of certain
|
||||
# C or C++ compiler flags and returns valid ones as a string.
|
||||
|
||||
include(CheckCCompilerFlag)
|
||||
include(CheckCXXCompilerFlag)
|
||||
|
||||
function(extract_valid_c_flags varname)
|
||||
set(valid_flags)
|
||||
foreach(flag IN LISTS ARGN)
|
||||
string(REGEX REPLACE "[^a-zA-Z0-9_]+" "_" flag_var ${flag})
|
||||
set(flag_var "C_FLAG_${flag_var}")
|
||||
check_c_compiler_flag("${flag}" "${flag_var}")
|
||||
if(${flag_var})
|
||||
set(valid_flags "${valid_flags} ${flag}")
|
||||
endif()
|
||||
endforeach()
|
||||
set(${varname} "${valid_flags}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
function(extract_valid_cxx_flags varname)
|
||||
set(valid_flags)
|
||||
foreach(flag IN LISTS ARGN)
|
||||
string(REGEX REPLACE "[^a-zA-Z0-9_]+" "_" flag_var ${flag})
|
||||
set(flag_var "CXX_FLAG_${flag_var}")
|
||||
check_cxx_compiler_flag("${flag}" "${flag_var}")
|
||||
if(${flag_var})
|
||||
set(valid_flags "${valid_flags} ${flag}")
|
||||
endif()
|
||||
endforeach()
|
||||
set(${varname} "${valid_flags}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
40
cmake/FindCUnit.cmake
Normal file
40
cmake/FindCUnit.cmake
Normal file
@@ -0,0 +1,40 @@
|
||||
# - 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)
|
||||
44
cmake/FindCython.cmake
Normal file
44
cmake/FindCython.cmake
Normal file
@@ -0,0 +1,44 @@
|
||||
# Find the Cython compiler.
|
||||
#
|
||||
# This code sets the following variables:
|
||||
#
|
||||
# CYTHON_EXECUTABLE
|
||||
#
|
||||
# See also UseCython.cmake
|
||||
|
||||
#=============================================================================
|
||||
# Copyright 2011 Kitware, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#=============================================================================
|
||||
|
||||
# Use the Cython executable that lives next to the Python executable
|
||||
# if it is a local installation.
|
||||
find_package( PythonInterp )
|
||||
if( PYTHONINTERP_FOUND )
|
||||
get_filename_component( _python_path ${PYTHON_EXECUTABLE} PATH )
|
||||
find_program( CYTHON_EXECUTABLE
|
||||
NAMES cython cython.bat cython3
|
||||
HINTS ${_python_path}
|
||||
)
|
||||
else()
|
||||
find_program( CYTHON_EXECUTABLE
|
||||
NAMES cython cython.bat cython3
|
||||
)
|
||||
endif()
|
||||
|
||||
|
||||
include( FindPackageHandleStandardArgs )
|
||||
FIND_PACKAGE_HANDLE_STANDARD_ARGS( Cython REQUIRED_VARS CYTHON_EXECUTABLE )
|
||||
|
||||
mark_as_advanced( CYTHON_EXECUTABLE )
|
||||
40
cmake/FindJansson.cmake
Normal file
40
cmake/FindJansson.cmake
Normal file
@@ -0,0 +1,40 @@
|
||||
# - Try to find jansson
|
||||
# Once done this will define
|
||||
# JANSSON_FOUND - System has jansson
|
||||
# JANSSON_INCLUDE_DIRS - The jansson include directories
|
||||
# JANSSON_LIBRARIES - The libraries needed to use jansson
|
||||
|
||||
find_package(PkgConfig QUIET)
|
||||
pkg_check_modules(PC_JANSSON QUIET jansson)
|
||||
|
||||
find_path(JANSSON_INCLUDE_DIR
|
||||
NAMES jansson.h
|
||||
HINTS ${PC_JANSSON_INCLUDE_DIRS}
|
||||
)
|
||||
find_library(JANSSON_LIBRARY
|
||||
NAMES jansson
|
||||
HINTS ${PC_JANSSON_LIBRARY_DIRS}
|
||||
)
|
||||
|
||||
if(JANSSON_INCLUDE_DIR)
|
||||
set(_version_regex "^#define[ \t]+JANSSON_VERSION[ \t]+\"([^\"]+)\".*")
|
||||
file(STRINGS "${JANSSON_INCLUDE_DIR}/jansson.h"
|
||||
JANSSON_VERSION REGEX "${_version_regex}")
|
||||
string(REGEX REPLACE "${_version_regex}" "\\1"
|
||||
JANSSON_VERSION "${JANSSON_VERSION}")
|
||||
unset(_version_regex)
|
||||
endif()
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
# handle the QUIETLY and REQUIRED arguments and set JANSSON_FOUND to TRUE
|
||||
# if all listed variables are TRUE and the requested version matches.
|
||||
find_package_handle_standard_args(Jansson REQUIRED_VARS
|
||||
JANSSON_LIBRARY JANSSON_INCLUDE_DIR
|
||||
VERSION_VAR JANSSON_VERSION)
|
||||
|
||||
if(JANSSON_FOUND)
|
||||
set(JANSSON_LIBRARIES ${JANSSON_LIBRARY})
|
||||
set(JANSSON_INCLUDE_DIRS ${JANSSON_INCLUDE_DIR})
|
||||
endif()
|
||||
|
||||
mark_as_advanced(JANSSON_INCLUDE_DIR JANSSON_LIBRARY)
|
||||
40
cmake/FindJemalloc.cmake
Normal file
40
cmake/FindJemalloc.cmake
Normal file
@@ -0,0 +1,40 @@
|
||||
# - Try to find jemalloc
|
||||
# Once done this will define
|
||||
# JEMALLOC_FOUND - System has jemalloc
|
||||
# JEMALLOC_INCLUDE_DIRS - The jemalloc include directories
|
||||
# JEMALLOC_LIBRARIES - The libraries needed to use jemalloc
|
||||
|
||||
find_package(PkgConfig QUIET)
|
||||
pkg_check_modules(PC_JEMALLOC QUIET jemalloc)
|
||||
|
||||
find_path(JEMALLOC_INCLUDE_DIR
|
||||
NAMES jemalloc/jemalloc.h
|
||||
HINTS ${PC_JEMALLOC_INCLUDE_DIRS}
|
||||
)
|
||||
find_library(JEMALLOC_LIBRARY
|
||||
NAMES jemalloc
|
||||
HINTS ${PC_JEMALLOC_LIBRARY_DIRS}
|
||||
)
|
||||
|
||||
if(JEMALLOC_INCLUDE_DIR)
|
||||
set(_version_regex "^#define[ \t]+JEMALLOC_VERSION[ \t]+\"([^\"]+)\".*")
|
||||
file(STRINGS "${JEMALLOC_INCLUDE_DIR}/jemalloc/jemalloc.h"
|
||||
JEMALLOC_VERSION REGEX "${_version_regex}")
|
||||
string(REGEX REPLACE "${_version_regex}" "\\1"
|
||||
JEMALLOC_VERSION "${JEMALLOC_VERSION}")
|
||||
unset(_version_regex)
|
||||
endif()
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
# handle the QUIETLY and REQUIRED arguments and set JEMALLOC_FOUND to TRUE
|
||||
# if all listed variables are TRUE and the requested version matches.
|
||||
find_package_handle_standard_args(Jemalloc REQUIRED_VARS
|
||||
JEMALLOC_LIBRARY JEMALLOC_INCLUDE_DIR
|
||||
VERSION_VAR JEMALLOC_VERSION)
|
||||
|
||||
if(JEMALLOC_FOUND)
|
||||
set(JEMALLOC_LIBRARIES ${JEMALLOC_LIBRARY})
|
||||
set(JEMALLOC_INCLUDE_DIRS ${JEMALLOC_INCLUDE_DIR})
|
||||
endif()
|
||||
|
||||
mark_as_advanced(JEMALLOC_INCLUDE_DIR JEMALLOC_LIBRARY)
|
||||
40
cmake/FindLibcares.cmake
Normal file
40
cmake/FindLibcares.cmake
Normal file
@@ -0,0 +1,40 @@
|
||||
# - Try to find libcares
|
||||
# Once done this will define
|
||||
# LIBCARES_FOUND - System has libcares
|
||||
# LIBCARES_INCLUDE_DIRS - The libcares include directories
|
||||
# LIBCARES_LIBRARIES - The libraries needed to use libcares
|
||||
|
||||
find_package(PkgConfig QUIET)
|
||||
pkg_check_modules(PC_LIBCARES QUIET libcares)
|
||||
|
||||
find_path(LIBCARES_INCLUDE_DIR
|
||||
NAMES ares.h
|
||||
HINTS ${PC_LIBCARES_INCLUDE_DIRS}
|
||||
)
|
||||
find_library(LIBCARES_LIBRARY
|
||||
NAMES cares
|
||||
HINTS ${PC_LIBCARES_LIBRARY_DIRS}
|
||||
)
|
||||
|
||||
if(LIBCARES_INCLUDE_DIR)
|
||||
set(_version_regex "^#define[ \t]+ARES_VERSION_STR[ \t]+\"([^\"]+)\".*")
|
||||
file(STRINGS "${LIBCARES_INCLUDE_DIR}/ares_version.h"
|
||||
LIBCARES_VERSION REGEX "${_version_regex}")
|
||||
string(REGEX REPLACE "${_version_regex}" "\\1"
|
||||
LIBCARES_VERSION "${LIBCARES_VERSION}")
|
||||
unset(_version_regex)
|
||||
endif()
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
# handle the QUIETLY and REQUIRED arguments and set LIBCARES_FOUND to TRUE
|
||||
# if all listed variables are TRUE and the requested version matches.
|
||||
find_package_handle_standard_args(Libcares REQUIRED_VARS
|
||||
LIBCARES_LIBRARY LIBCARES_INCLUDE_DIR
|
||||
VERSION_VAR LIBCARES_VERSION)
|
||||
|
||||
if(LIBCARES_FOUND)
|
||||
set(LIBCARES_LIBRARIES ${LIBCARES_LIBRARY})
|
||||
set(LIBCARES_INCLUDE_DIRS ${LIBCARES_INCLUDE_DIR})
|
||||
endif()
|
||||
|
||||
mark_as_advanced(LIBCARES_INCLUDE_DIR LIBCARES_LIBRARY)
|
||||
38
cmake/FindLibev.cmake
Normal file
38
cmake/FindLibev.cmake
Normal file
@@ -0,0 +1,38 @@
|
||||
# - Try to find libev
|
||||
# Once done this will define
|
||||
# LIBEV_FOUND - System has libev
|
||||
# LIBEV_INCLUDE_DIRS - The libev include directories
|
||||
# LIBEV_LIBRARIES - The libraries needed to use libev
|
||||
|
||||
find_path(LIBEV_INCLUDE_DIR
|
||||
NAMES ev.h
|
||||
)
|
||||
find_library(LIBEV_LIBRARY
|
||||
NAMES ev
|
||||
)
|
||||
|
||||
if(LIBEV_INCLUDE_DIR)
|
||||
file(STRINGS "${LIBEV_INCLUDE_DIR}/ev.h"
|
||||
LIBEV_VERSION_MAJOR REGEX "^#define[ \t]+EV_VERSION_MAJOR[ \t]+[0-9]+")
|
||||
file(STRINGS "${LIBEV_INCLUDE_DIR}/ev.h"
|
||||
LIBEV_VERSION_MINOR REGEX "^#define[ \t]+EV_VERSION_MINOR[ \t]+[0-9]+")
|
||||
string(REGEX REPLACE "[^0-9]+" "" LIBEV_VERSION_MAJOR "${LIBEV_VERSION_MAJOR}")
|
||||
string(REGEX REPLACE "[^0-9]+" "" LIBEV_VERSION_MINOR "${LIBEV_VERSION_MINOR}")
|
||||
set(LIBEV_VERSION "${LIBEV_VERSION_MAJOR}.${LIBEV_VERSION_MINOR}")
|
||||
unset(LIBEV_VERSION_MINOR)
|
||||
unset(LIBEV_VERSION_MAJOR)
|
||||
endif()
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
# handle the QUIETLY and REQUIRED arguments and set LIBEV_FOUND to TRUE
|
||||
# if all listed variables are TRUE and the requested version matches.
|
||||
find_package_handle_standard_args(Libev REQUIRED_VARS
|
||||
LIBEV_LIBRARY LIBEV_INCLUDE_DIR
|
||||
VERSION_VAR LIBEV_VERSION)
|
||||
|
||||
if(LIBEV_FOUND)
|
||||
set(LIBEV_LIBRARIES ${LIBEV_LIBRARY})
|
||||
set(LIBEV_INCLUDE_DIRS ${LIBEV_INCLUDE_DIR})
|
||||
endif()
|
||||
|
||||
mark_as_advanced(LIBEV_INCLUDE_DIR LIBEV_LIBRARY)
|
||||
94
cmake/FindLibevent.cmake
Normal file
94
cmake/FindLibevent.cmake
Normal file
@@ -0,0 +1,94 @@
|
||||
# - Try to find libevent
|
||||
#.rst
|
||||
# FindLibevent
|
||||
# ------------
|
||||
#
|
||||
# Find Libevent include directories and libraries. Invoke as::
|
||||
#
|
||||
# find_package(Libevent
|
||||
# [version] [EXACT] # Minimum or exact version
|
||||
# [REQUIRED] # Fail if Libevent is not found
|
||||
# [COMPONENT <C>...]) # Libraries to look for
|
||||
#
|
||||
# Valid components are one or more of:: libevent core extra pthreads openssl.
|
||||
# Note that 'libevent' contains both core and extra. You must specify one of
|
||||
# them for the other components.
|
||||
#
|
||||
# This module will define the following variables::
|
||||
#
|
||||
# LIBEVENT_FOUND - True if headers and requested libraries were found
|
||||
# LIBEVENT_INCLUDE_DIRS - Libevent include directories
|
||||
# LIBEVENT_LIBRARIES - Libevent libraries to be linked
|
||||
# LIBEVENT_<C>_FOUND - Component <C> was found (<C> is uppercase)
|
||||
# LIBEVENT_<C>_LIBRARY - Library to be linked for Libevent component <C>.
|
||||
|
||||
find_package(PkgConfig QUIET)
|
||||
pkg_check_modules(PC_LIBEVENT QUIET libevent)
|
||||
|
||||
# Look for the Libevent 2.0 or 1.4 headers
|
||||
find_path(LIBEVENT_INCLUDE_DIR
|
||||
NAMES
|
||||
event2/event-config.h
|
||||
event-config.h
|
||||
HINTS
|
||||
${PC_LIBEVENT_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
if(LIBEVENT_INCLUDE_DIR)
|
||||
set(_version_regex "^#define[ \t]+_EVENT_VERSION[ \t]+\"([^\"]+)\".*")
|
||||
if(EXISTS "${LIBEVENT_INCLUDE_DIR}/event2/event-config.h")
|
||||
# Libevent 2.0
|
||||
file(STRINGS "${LIBEVENT_INCLUDE_DIR}/event2/event-config.h"
|
||||
LIBEVENT_VERSION REGEX "${_version_regex}")
|
||||
else()
|
||||
# Libevent 1.4
|
||||
file(STRINGS "${LIBEVENT_INCLUDE_DIR}/event-config.h"
|
||||
LIBEVENT_VERSION REGEX "${_version_regex}")
|
||||
endif()
|
||||
string(REGEX REPLACE "${_version_regex}" "\\1"
|
||||
LIBEVENT_VERSION "${LIBEVENT_VERSION}")
|
||||
unset(_version_regex)
|
||||
endif()
|
||||
|
||||
set(_LIBEVENT_REQUIRED_VARS)
|
||||
foreach(COMPONENT ${Libevent_FIND_COMPONENTS})
|
||||
set(_LIBEVENT_LIBNAME libevent)
|
||||
# Note: compare two variables to avoid a CMP0054 policy warning
|
||||
if(COMPONENT STREQUAL _LIBEVENT_LIBNAME)
|
||||
set(_LIBEVENT_LIBNAME event)
|
||||
else()
|
||||
set(_LIBEVENT_LIBNAME "event_${COMPONENT}")
|
||||
endif()
|
||||
string(TOUPPER "${COMPONENT}" COMPONENT_UPPER)
|
||||
find_library(LIBEVENT_${COMPONENT_UPPER}_LIBRARY
|
||||
NAMES ${_LIBEVENT_LIBNAME}
|
||||
HINTS ${PC_LIBEVENT_LIBRARY_DIRS}
|
||||
)
|
||||
if(LIBEVENT_${COMPONENT_UPPER}_LIBRARY)
|
||||
set(Libevent_${COMPONENT}_FOUND 1)
|
||||
endif()
|
||||
list(APPEND _LIBEVENT_REQUIRED_VARS LIBEVENT_${COMPONENT_UPPER}_LIBRARY)
|
||||
endforeach()
|
||||
unset(_LIBEVENT_LIBNAME)
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
# handle the QUIETLY and REQUIRED arguments and set LIBEVENT_FOUND to TRUE
|
||||
# if all listed variables are TRUE and the requested version matches.
|
||||
find_package_handle_standard_args(Libevent REQUIRED_VARS
|
||||
${_LIBEVENT_REQUIRED_VARS}
|
||||
LIBEVENT_INCLUDE_DIR
|
||||
VERSION_VAR LIBEVENT_VERSION
|
||||
HANDLE_COMPONENTS)
|
||||
|
||||
if(LIBEVENT_FOUND)
|
||||
set(LIBEVENT_INCLUDE_DIRS ${LIBEVENT_INCLUDE_DIR})
|
||||
set(LIBEVENT_LIBRARIES)
|
||||
foreach(COMPONENT ${Libevent_FIND_COMPONENTS})
|
||||
string(TOUPPER "${COMPONENT}" COMPONENT_UPPER)
|
||||
list(APPEND LIBEVENT_LIBRARIES ${LIBEVENT_${COMPONENT_UPPER}_LIBRARY})
|
||||
set(LIBEVENT_${COMPONENT_UPPER}_FOUND ${Libevent_${COMPONENT}_FOUND})
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
mark_as_advanced(LIBEVENT_INCLUDE_DIR ${_LIBEVENT_REQUIRED_VARS})
|
||||
unset(_LIBEVENT_REQUIRED_VARS)
|
||||
40
cmake/FindSpdylay.cmake
Normal file
40
cmake/FindSpdylay.cmake
Normal file
@@ -0,0 +1,40 @@
|
||||
# - Try to find spdylay
|
||||
# Once done this will define
|
||||
# SPDYLAY_FOUND - System has spdylay
|
||||
# SPDYLAY_INCLUDE_DIRS - The spdylay include directories
|
||||
# SPDYLAY_LIBRARIES - The libraries needed to use spdylay
|
||||
|
||||
find_package(PkgConfig QUIET)
|
||||
pkg_check_modules(PC_SPDYLAY QUIET libspdylay)
|
||||
|
||||
find_path(SPDYLAY_INCLUDE_DIR
|
||||
NAMES spdylay/spdylay.h
|
||||
HINTS ${PC_SPDYLAY_INCLUDE_DIRS}
|
||||
)
|
||||
find_library(SPDYLAY_LIBRARY
|
||||
NAMES spdylay
|
||||
HINTS ${PC_SPDYLAY_LIBRARY_DIRS}
|
||||
)
|
||||
|
||||
if(SPDYLAY_INCLUDE_DIR)
|
||||
set(_version_regex "^#define[ \t]+SPDYLAY_VERSION[ \t]+\"([^\"]+)\".*")
|
||||
file(STRINGS "${SPDYLAY_INCLUDE_DIR}/spdylay/spdylayver.h"
|
||||
SPDYLAY_VERSION REGEX "${_version_regex}")
|
||||
string(REGEX REPLACE "${_version_regex}" "\\1"
|
||||
SPDYLAY_VERSION "${SPDYLAY_VERSION}")
|
||||
unset(_version_regex)
|
||||
endif()
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
# handle the QUIETLY and REQUIRED arguments and set SPDYLAY_FOUND to TRUE
|
||||
# if all listed variables are TRUE and the requested version matches.
|
||||
find_package_handle_standard_args(Spdylay REQUIRED_VARS
|
||||
SPDYLAY_LIBRARY SPDYLAY_INCLUDE_DIR
|
||||
VERSION_VAR SPDYLAY_VERSION)
|
||||
|
||||
if(SPDYLAY_FOUND)
|
||||
set(SPDYLAY_LIBRARIES ${SPDYLAY_LIBRARY})
|
||||
set(SPDYLAY_INCLUDE_DIRS ${SPDYLAY_INCLUDE_DIR})
|
||||
endif()
|
||||
|
||||
mark_as_advanced(SPDYLAY_INCLUDE_DIR SPDYLAY_LIBRARY)
|
||||
11
cmake/Version.cmake
Normal file
11
cmake/Version.cmake
Normal file
@@ -0,0 +1,11 @@
|
||||
# Converts a version such as 1.2.255 to 0x0102ff
|
||||
function(HexVersion version_hex_var major minor patch)
|
||||
math(EXPR version_dec "${major} * 256 * 256 + ${minor} * 256 + ${patch}")
|
||||
set(version_hex "0x")
|
||||
foreach(i RANGE 5 0 -1)
|
||||
math(EXPR num "(${version_dec} >> (4 * ${i})) & 15")
|
||||
string(SUBSTRING "0123456789abcdef" ${num} 1 num_hex)
|
||||
set(version_hex "${version_hex}${num_hex}")
|
||||
endforeach()
|
||||
set(${version_hex_var} "${version_hex}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
84
cmakeconfig.h.in
Normal file
84
cmakeconfig.h.in
Normal file
@@ -0,0 +1,84 @@
|
||||
|
||||
/* Hint to the compiler that a function parameter is not used */
|
||||
#define _U_ @HINT_UNUSED_PARAM@
|
||||
|
||||
/* Hint to the compiler that a function never returns */
|
||||
#define NGHTTP2_NORETURN @HINT_NORETURN@
|
||||
|
||||
/* Define to `int' if <sys/types.h> does not define. */
|
||||
#cmakedefine ssize_t @ssize_t@
|
||||
|
||||
/* Define to 1 if you have the `std::map::emplace`. */
|
||||
#cmakedefine HAVE_STD_MAP_EMPLACE 1
|
||||
|
||||
/* Define to 1 if you have `libjansson` library. */
|
||||
#cmakedefine HAVE_JANSSON 1
|
||||
|
||||
/* Define to 1 if you have `libxml2` library. */
|
||||
#cmakedefine HAVE_LIBXML2 1
|
||||
|
||||
/* Define to 1 if you have `spdylay` library. */
|
||||
#cmakedefine HAVE_SPDYLAY 1
|
||||
|
||||
/* Define to 1 if you have `mruby` library. */
|
||||
#cmakedefine HAVE_MRUBY 1
|
||||
|
||||
/* 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 `initgroups` function. */
|
||||
#cmakedefine01 HAVE_DECL_INITGROUPS
|
||||
|
||||
/* Define to 1 to enable debug output. */
|
||||
#cmakedefine DEBUGBUILD 1
|
||||
|
||||
/* Define to 1 if you want to disable threads. */
|
||||
#cmakedefine NOTHREADS 1
|
||||
|
||||
/* Define to 1 if you have the <arpa/inet.h> header file. */
|
||||
#cmakedefine HAVE_ARPA_INET_H 1
|
||||
|
||||
/* Define to 1 if you have the <fcntl.h> header file. */
|
||||
#cmakedefine HAVE_FCNTL_H 1
|
||||
|
||||
/* Define to 1 if you have the <inttypes.h> header file. */
|
||||
#cmakedefine HAVE_INTTYPES_H 1
|
||||
|
||||
/* Define to 1 if you have the <limits.h> header file. */
|
||||
#cmakedefine HAVE_LIMITS_H 1
|
||||
|
||||
/* Define to 1 if you have the <netdb.h> header file. */
|
||||
#cmakedefine HAVE_NETDB_H 1
|
||||
|
||||
/* 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 <pwd.h> header file. */
|
||||
#cmakedefine HAVE_PWD_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/socket.h> header file. */
|
||||
#cmakedefine HAVE_SYS_SOCKET_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/time.h> header file. */
|
||||
#cmakedefine HAVE_SYS_TIME_H 1
|
||||
|
||||
/* 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
|
||||
168
configure.ac
168
configure.ac
@@ -25,7 +25,7 @@ dnl Do not change user variables!
|
||||
dnl http://www.gnu.org/software/automake/manual/html_node/Flag-Variables-Ordering.html
|
||||
|
||||
AC_PREREQ(2.61)
|
||||
AC_INIT([nghttp2], [1.7.1], [t-tujikawa@users.sourceforge.net])
|
||||
AC_INIT([nghttp2], [1.19.0], [t-tujikawa@users.sourceforge.net])
|
||||
AC_CONFIG_AUX_DIR([.])
|
||||
AC_CONFIG_MACRO_DIR([m4])
|
||||
AC_CONFIG_HEADERS([config.h])
|
||||
@@ -40,15 +40,13 @@ AC_CANONICAL_TARGET
|
||||
|
||||
AM_INIT_AUTOMAKE([subdir-objects])
|
||||
|
||||
# AM_EXTRA_RECURSIVE_TARGETS requires automake 1.13 or higher
|
||||
m4_ifdef([AM_EXTRA_RECURSIVE_TARGETS], [AM_EXTRA_RECURSIVE_TARGETS([it itprep])])
|
||||
m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
|
||||
|
||||
dnl See versioning rule:
|
||||
dnl http://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html
|
||||
AC_SUBST(LT_CURRENT, 18)
|
||||
AC_SUBST(LT_REVISION, 1)
|
||||
AC_SUBST(LT_AGE, 4)
|
||||
AC_SUBST(LT_CURRENT, 26)
|
||||
AC_SUBST(LT_REVISION, 4)
|
||||
AC_SUBST(LT_AGE, 12)
|
||||
|
||||
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"`
|
||||
@@ -76,7 +74,7 @@ AC_ARG_ENABLE([threads],
|
||||
|
||||
AC_ARG_ENABLE([app],
|
||||
[AS_HELP_STRING([--enable-app],
|
||||
[Build applications (nghttp, nghttpd and nghttpx) [default=check]])],
|
||||
[Build applications (nghttp, nghttpd, nghttpx and h2load) [default=check]])],
|
||||
[request_app=$enableval], [request_app=check])
|
||||
|
||||
AC_ARG_ENABLE([hpack-tools],
|
||||
@@ -189,10 +187,20 @@ else
|
||||
AC_DEFINE([NGHTTP2_NORETURN], , [Hint to the compiler that a function never return])
|
||||
fi
|
||||
|
||||
save_CXXFLAGS="$CXXFLAGS"
|
||||
CXXFLAGS=
|
||||
|
||||
AX_CXX_COMPILE_STDCXX_11([noext], [optional])
|
||||
|
||||
CXX1XCXXFLAGS="$CXXFLAGS"
|
||||
CXXFLAGS="$save_CXXFLAGS"
|
||||
AC_SUBST([CXX1XCXXFLAGS])
|
||||
|
||||
AC_LANG_PUSH(C++)
|
||||
|
||||
save_CXXFLAGS="$CXXFLAGS"
|
||||
CXXFLAGS="$CXXFLAGS $CXX1XCXXFLAGS"
|
||||
|
||||
# Check that std::future is available.
|
||||
AC_MSG_CHECKING([whether std::future is available])
|
||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM(
|
||||
@@ -226,6 +234,43 @@ 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])
|
||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM(
|
||||
[[
|
||||
#include <memory>
|
||||
]],
|
||||
[[
|
||||
auto a = std::make_shared<int>(1000000007);
|
||||
auto p = std::atomic_load(&a);
|
||||
++*p;
|
||||
std::atomic_store(&a, p);
|
||||
]])],
|
||||
[AC_DEFINE([HAVE_ATOMIC_STD_SHARED_PTR], [1],
|
||||
[Define to 1 if you have the std::atomic_* overloads for std::shared_ptr.])
|
||||
have_atomic_std_shared_ptr=yes
|
||||
AC_MSG_RESULT([yes])],
|
||||
[have_atomic_std_shared_ptr=no
|
||||
AC_MSG_RESULT([no])])
|
||||
|
||||
# Check that thread_local storage specifier is available
|
||||
AC_MSG_CHECKING([whether thread_local storage class specifier is available.])
|
||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM(
|
||||
,
|
||||
[[
|
||||
thread_local int a = 0;
|
||||
(void)a;
|
||||
]])],
|
||||
[AC_DEFINE([HAVE_THREAD_LOCAL], [1],
|
||||
[Define to 1 if you have thread_local storage specifier.])
|
||||
have_thread_local=yes
|
||||
AC_MSG_RESULT([yes])],
|
||||
[have_Thread_local=no
|
||||
AC_MSG_RESULT([no])])
|
||||
|
||||
CXXFLAGS=$save_CXXFLAGS
|
||||
|
||||
AC_LANG_POP()
|
||||
|
||||
# Checks for libraries.
|
||||
@@ -236,7 +281,7 @@ TESTLDADD=
|
||||
# Additional libraries required for programs under src directory.
|
||||
APPLDFLAGS=
|
||||
|
||||
case "$host" in
|
||||
case "$host_os" in
|
||||
*android*)
|
||||
android_build=yes
|
||||
# android does not need -pthread, but needs followng 3 libs for C++
|
||||
@@ -248,6 +293,12 @@ case "$host" in
|
||||
;;
|
||||
esac
|
||||
|
||||
case "$host_os" in
|
||||
*solaris*)
|
||||
APPLDFLAGS="$APPLDFLAGS -lsocket -lnsl"
|
||||
;;
|
||||
esac
|
||||
|
||||
# zlib
|
||||
PKG_CHECK_MODULES([ZLIB], [zlib >= 1.2.3], [have_zlib=yes], [have_zlib=no])
|
||||
|
||||
@@ -256,9 +307,16 @@ if test "x${have_zlib}" = "xno"; then
|
||||
fi
|
||||
|
||||
# dl: openssl requires libdl when it is statically linked.
|
||||
LIBS_OLD=$LIBS
|
||||
AC_SEARCH_LIBS([dlopen], [dl], [APPLDFLAGS="-ldl $APPLDFLAGS"], [], [])
|
||||
LIBS=$LIBS_OLD
|
||||
case "${host_os}" in
|
||||
*bsd*)
|
||||
# dlopen is in libc on *BSD
|
||||
;;
|
||||
*)
|
||||
save_LIBS=$LIBS
|
||||
AC_SEARCH_LIBS([dlopen], [dl], [APPLDFLAGS="-ldl $APPLDFLAGS"], [], [])
|
||||
LIBS=$save_LIBS
|
||||
;;
|
||||
esac
|
||||
|
||||
# cunit
|
||||
PKG_CHECK_MODULES([CUNIT], [cunit >= 2.1], [have_cunit=yes], [have_cunit=no])
|
||||
@@ -291,7 +349,7 @@ AM_CONDITIONAL([HAVE_CUNIT], [ test "x${have_cunit}" = "xyes" ])
|
||||
|
||||
# libev (for src)
|
||||
# libev does not have pkg-config file. Check it in an old way.
|
||||
LIBS_OLD=$LIBS
|
||||
save_LIBS=$LIBS
|
||||
# android requires -lm for floor
|
||||
AC_CHECK_LIB([ev], [ev_time], [have_libev=yes], [have_libev=no], [-lm])
|
||||
if test "x${have_libev}" = "xyes"; then
|
||||
@@ -303,7 +361,7 @@ if test "x${have_libev}" = "xyes"; then
|
||||
AC_SUBST([LIBEV_CFLAGS])
|
||||
fi
|
||||
fi
|
||||
LIBS=$LIBS_OLD
|
||||
LIBS=$save_LIBS
|
||||
|
||||
# openssl (for src)
|
||||
PKG_CHECK_MODULES([OPENSSL], [openssl >= 1.0.1],
|
||||
@@ -312,6 +370,13 @@ if test "x${have_openssl}" = "xno"; then
|
||||
AC_MSG_NOTICE($OPENSSL_PKG_ERRORS)
|
||||
fi
|
||||
|
||||
# c-ares (for src)
|
||||
PKG_CHECK_MODULES([LIBCARES], [libcares >= 1.7.5], [have_libcares=yes],
|
||||
[have_libcares=no])
|
||||
if test "x${have_libcares}" = "xno"; then
|
||||
AC_MSG_NOTICE($LIBCARES_PKG_ERRORS)
|
||||
fi
|
||||
|
||||
# libevent_openssl (for examples)
|
||||
# 2.0.8 is required because we use evconnlistener_set_error_cb()
|
||||
PKG_CHECK_MODULES([LIBEVENT_OPENSSL], [libevent_openssl >= 2.0.8],
|
||||
@@ -331,12 +396,12 @@ else
|
||||
fi
|
||||
|
||||
# libxml2 (for src/nghttp)
|
||||
have_libxml2=no
|
||||
if test "x${request_libxml2}" != "xno"; then
|
||||
AM_PATH_XML2(2.7.7, [have_libxml2=yes], [have_libxml2=no])
|
||||
if test "x${have_libxml2}" = "xyes"; then
|
||||
AC_DEFINE([HAVE_LIBXML2], [1], [Define to 1 if you have `libxml2` library.])
|
||||
fi
|
||||
PKG_CHECK_MODULES([LIBXML2], [libxml-2.0 >= 2.7.7],
|
||||
[have_libxml2=yes], [have_libxml2=no])
|
||||
if test "x${have_libxml2}" = "xyes"; then
|
||||
AC_DEFINE([HAVE_LIBXML2], [1], [Define to 1 if you have `libxml2` library.])
|
||||
else
|
||||
AC_MSG_NOTICE($LIBXML2_PKG_ERRORS)
|
||||
fi
|
||||
|
||||
if test "x${request_libxml2}" = "xyes" &&
|
||||
@@ -349,7 +414,7 @@ AM_CONDITIONAL([HAVE_LIBXML2], [ test "x${have_libxml2}" = "xyes" ])
|
||||
# jemalloc
|
||||
have_jemalloc=no
|
||||
if test "x${request_jemalloc}" != "xno"; then
|
||||
LIBS_OLD=$LIBS
|
||||
save_LIBS=$LIBS
|
||||
AC_SEARCH_LIBS([malloc_stats_print], [jemalloc], [have_jemalloc=yes], [],
|
||||
[$PTHREAD_LDFLAGS])
|
||||
|
||||
@@ -365,7 +430,7 @@ if test "x${request_jemalloc}" != "xno"; then
|
||||
fi
|
||||
fi
|
||||
|
||||
LIBS=$LIBS_OLD
|
||||
LIBS=$save_LIBS
|
||||
|
||||
if test "x${have_jemalloc}" = "xyes" &&
|
||||
test "x${jemalloc_libs}" != "xnone required"; then
|
||||
@@ -418,13 +483,14 @@ if test "x${request_asio_lib}" = "xyes"; then
|
||||
fi
|
||||
fi
|
||||
|
||||
# The nghttp, nghttpd and nghttpx under src depend on zlib, OpenSSL
|
||||
# and libev
|
||||
# The nghttp, nghttpd and nghttpx under src depend on zlib, OpenSSL,
|
||||
# libev, and libc-ares.
|
||||
enable_app=no
|
||||
if test "x${request_app}" != "xno" &&
|
||||
test "x${have_zlib}" = "xyes" &&
|
||||
test "x${have_openssl}" = "xyes" &&
|
||||
test "x${have_libev}" = "xyes"; then
|
||||
test "x${have_libev}" = "xyes" &&
|
||||
test "x${have_libcares}" = "xyes"; then
|
||||
enable_app=yes
|
||||
fi
|
||||
|
||||
@@ -579,6 +645,26 @@ AC_SYS_LARGEFILE
|
||||
AC_CHECK_MEMBER([struct tm.tm_gmtoff], [have_struct_tm_tm_gmtoff=yes],
|
||||
[have_struct_tm_tm_gmtoff=no], [[#include <time.h>]])
|
||||
|
||||
AC_CHECK_MEMBER([struct sockaddr_in.sin_len],
|
||||
[AC_DEFINE([HAVE_SOCKADDR_IN_SIN_LEN],[1],
|
||||
[Define to 1 if struct sockaddr_in has sin_len member.])],
|
||||
[],
|
||||
[[
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
]])
|
||||
|
||||
AC_CHECK_MEMBER([struct sockaddr_in6.sin6_len],
|
||||
[AC_DEFINE([HAVE_SOCKADDR_IN6_SIN6_LEN],[1],
|
||||
[Define to 1 if struct sockaddr_in6 has sin6_len member.])],
|
||||
[],
|
||||
[[
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
]])
|
||||
|
||||
if test "x$have_struct_tm_tm_gmtoff" = "xyes"; then
|
||||
AC_DEFINE([HAVE_STRUCT_TM_TM_GMTOFF], [1],
|
||||
[Define to 1 if you have `struct tm.tm_gmtoff` member.])
|
||||
@@ -632,18 +718,16 @@ AC_CHECK_FUNC([timerfd_create],
|
||||
|
||||
# For cygwin: we can link initgroups, so AC_CHECK_FUNCS succeeds, but
|
||||
# cygwin disables initgroups due to feature test macro magic with our
|
||||
# configuration.
|
||||
AC_CHECK_DECLS([initgroups], [], [], [[#include <grp.h>]])
|
||||
# configuration. FreeBSD declares initgroups() in unistd.h.
|
||||
AC_CHECK_DECLS([initgroups], [], [], [[
|
||||
#ifdef HAVE_UNISTD_H
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
#include <grp.h>
|
||||
]])
|
||||
|
||||
# Checks for epoll availability, primarily for examples/tiny-nghttpd
|
||||
AX_HAVE_EPOLL([have_epoll=yes], [have_epoll=no])
|
||||
|
||||
AM_CONDITIONAL([ENABLE_TINY_NGHTTPD],
|
||||
[ test "x${have_epoll}" = "xyes" &&
|
||||
test "x${have_timerfd_create}" = "xyes"])
|
||||
|
||||
ac_save_CFLAGS=$CFLAGS
|
||||
ac_save_CXXFLAGS=$CXXFLAGS
|
||||
save_CFLAGS=$CFLAGS
|
||||
save_CXXFLAGS=$CXXFLAGS
|
||||
|
||||
CFLAGS=
|
||||
CXXFLAGS=
|
||||
@@ -695,20 +779,25 @@ if test "x$werror" != "xno"; then
|
||||
AX_CHECK_COMPILE_FLAG([-Wredundant-decls], [CFLAGS="$CFLAGS -Wredundant-decls"])
|
||||
# Only work with Clang for the moment
|
||||
AX_CHECK_COMPILE_FLAG([-Wheader-guard], [CFLAGS="$CFLAGS -Wheader-guard"])
|
||||
AX_CHECK_COMPILE_FLAG([-Wsometimes-uninitialized], [CFLAGS="$CFLAGS -Wsometimes-uninitialized"])
|
||||
|
||||
# This is required because we pass format string as "const char*.
|
||||
AX_CHECK_COMPILE_FLAG([-Wno-format-nonliteral], [CFLAGS="$CFLAGS -Wno-format-nonliteral"])
|
||||
|
||||
# For C++ compiler
|
||||
AC_LANG_PUSH(C++)
|
||||
AX_CHECK_COMPILE_FLAG([-Wall], [CXXFLAGS="$CXXFLAGS -Wall"])
|
||||
AX_CHECK_COMPILE_FLAG([-Werror], [CXXFLAGS="$CXXFLAGS -Werror"])
|
||||
AX_CHECK_COMPILE_FLAG([-Wformat-security], [CXXFLAGS="$CXXFLAGS -Wformat-security"])
|
||||
AX_CHECK_COMPILE_FLAG([-Wsometimes-uninitialized], [CXXFLAGS="$CXXFLAGS -Wsometimes-uninitialized"])
|
||||
AC_LANG_POP()
|
||||
fi
|
||||
|
||||
WARNCFLAGS=$CFLAGS
|
||||
WARNCXXFLAGS=$CXXFLAGS
|
||||
|
||||
CFLAGS=$ac_save_CFLAGS
|
||||
CXXFLAGS=$ac_save_CXXFLAGS
|
||||
CFLAGS=$save_CFLAGS
|
||||
CXXFLAGS=$save_CXXFLAGS
|
||||
|
||||
AC_SUBST([WARNCFLAGS])
|
||||
AC_SUBST([WARNCXXFLAGS])
|
||||
@@ -797,6 +886,8 @@ AC_MSG_NOTICE([summary of build options:
|
||||
C preprocessor: ${CPP}
|
||||
CPPFLAGS: ${CPPFLAGS}
|
||||
WARNCFLAGS: ${WARNCFLAGS}
|
||||
WARNCXXFLAGS: ${WARNCXXFLAGS}
|
||||
CXX1XCXXFLAGS: ${CXX1XCXXFLAGS}
|
||||
EXTRACFLAG: ${EXTRACFLAG}
|
||||
LIBS: ${LIBS}
|
||||
Library:
|
||||
@@ -815,8 +906,9 @@ AC_MSG_NOTICE([summary of build options:
|
||||
Failmalloc: ${enable_failmalloc}
|
||||
Libs:
|
||||
OpenSSL: ${have_openssl} (CFLAGS='${OPENSSL_CFLAGS}' LIBS='${OPENSSL_LIBS}')
|
||||
Libxml2: ${have_libxml2} (CFLAGS='${XML_CPPFLAGS}' LIBS='${XML_LIBS}')
|
||||
Libxml2: ${have_libxml2} (CFLAGS='${LIBXML2_CPPFLAGS}' LIBS='${LIBXML2_LIBS}')
|
||||
Libev: ${have_libev} (CFLAGS='${LIBEV_CFLAGS}' LIBS='${LIBEV_LIBS}')
|
||||
Libc-ares ${have_libcares} (CFLAGS='${LIBCARES_CFLAGS}' LIBS='${LIBCARES_LIBS}')
|
||||
Libevent(SSL): ${have_libevent_openssl} (CFLAGS='${LIBEVENT_OPENSSL_CFLAGS}' LIBS='${LIBEVENT_OPENSSL_LIBS}')
|
||||
Spdylay: ${have_spdylay} (CFLAGS='${LIBSPDYLAY_CFLAGS}' LIBS='${LIBSPDYLAY_LIBS}')
|
||||
Jansson: ${have_jansson} (CFLAGS='${JANSSON_CFLAGS}' LIBS='${JANSSON_LIBS}')
|
||||
|
||||
12
contrib/CMakeLists.txt
Normal file
12
contrib/CMakeLists.txt
Normal file
@@ -0,0 +1,12 @@
|
||||
set(CONFIGFILES
|
||||
nghttpx-init
|
||||
nghttpx.service
|
||||
nghttpx-upstart.conf
|
||||
)
|
||||
|
||||
# Note that the execute permissions of nghttpx-init is preserved
|
||||
foreach(name IN LISTS CONFIGFILES)
|
||||
configure_file("${name}.in" "${name}" @ONLY)
|
||||
endforeach()
|
||||
|
||||
# set(EXTRA_DIST ${CONFIGFILES} nghttpx-logrotate tlsticketupdate.go)
|
||||
@@ -23,17 +23,24 @@
|
||||
|
||||
configfiles = nghttpx-init nghttpx.service nghttpx-upstart.conf
|
||||
|
||||
EXTRA_DIST = $(configfiles:%=%.in) nghttpx-logrotate tlsticketupdate.go
|
||||
EXTRA_DIST = \
|
||||
CMakeLists.txt \
|
||||
$(configfiles:%=%.in) \
|
||||
nghttpx-logrotate \
|
||||
tlsticketupdate.go
|
||||
|
||||
edit = sed -e 's|@bindir[@]|$(bindir)|g'
|
||||
|
||||
nghttpx-init: %: $(srcdir)/%.in
|
||||
nghttpx-init: $(srcdir)/nghttpx-init.in
|
||||
rm -f $@ $@.tmp
|
||||
$(edit) $< > $@.tmp
|
||||
chmod +x $@.tmp
|
||||
mv $@.tmp $@
|
||||
|
||||
nghttpx.service nghttpx-upstart.conf: %: $(srcdir)/%.in
|
||||
nghttpx.service: $(srcdir)/nghttpx.service.in
|
||||
$(edit) $< > $@
|
||||
|
||||
nghttpx-upstart.conf: $(srcdir)/nghttpx-upstart.conf.in
|
||||
$(edit) $< > $@
|
||||
|
||||
$(configfiles): Makefile
|
||||
|
||||
352
doc/CMakeLists.txt
Normal file
352
doc/CMakeLists.txt
Normal file
@@ -0,0 +1,352 @@
|
||||
# Generated documents
|
||||
set(APIDOCS
|
||||
macros.rst
|
||||
enums.rst
|
||||
types.rst
|
||||
nghttp2_check_header_name.rst
|
||||
nghttp2_check_header_value.rst
|
||||
nghttp2_hd_deflate_bound.rst
|
||||
nghttp2_hd_deflate_change_table_size.rst
|
||||
nghttp2_hd_deflate_del.rst
|
||||
nghttp2_hd_deflate_get_dynamic_table_size.rst
|
||||
nghttp2_hd_deflate_get_max_dynamic_table_size.rst
|
||||
nghttp2_hd_deflate_get_num_table_entries.rst
|
||||
nghttp2_hd_deflate_get_table_entry.rst
|
||||
nghttp2_hd_deflate_hd.rst
|
||||
nghttp2_hd_deflate_hd_vec.rst
|
||||
nghttp2_hd_deflate_new.rst
|
||||
nghttp2_hd_deflate_new2.rst
|
||||
nghttp2_hd_inflate_change_table_size.rst
|
||||
nghttp2_hd_inflate_del.rst
|
||||
nghttp2_hd_inflate_end_headers.rst
|
||||
nghttp2_hd_inflate_get_dynamic_table_size.rst
|
||||
nghttp2_hd_inflate_get_max_dynamic_table_size.rst
|
||||
nghttp2_hd_inflate_get_num_table_entries.rst
|
||||
nghttp2_hd_inflate_get_table_entry.rst
|
||||
nghttp2_hd_inflate_hd.rst
|
||||
nghttp2_hd_inflate_hd2.rst
|
||||
nghttp2_hd_inflate_new.rst
|
||||
nghttp2_hd_inflate_new2.rst
|
||||
nghttp2_http2_strerror.rst
|
||||
nghttp2_is_fatal.rst
|
||||
nghttp2_nv_compare_name.rst
|
||||
nghttp2_option_del.rst
|
||||
nghttp2_option_new.rst
|
||||
nghttp2_option_set_builtin_recv_extension_type.rst
|
||||
nghttp2_option_set_max_deflate_dynamic_table_size.rst
|
||||
nghttp2_option_set_max_reserved_remote_streams.rst
|
||||
nghttp2_option_set_max_send_header_block_length.rst
|
||||
nghttp2_option_set_no_auto_ping_ack.rst
|
||||
nghttp2_option_set_no_auto_window_update.rst
|
||||
nghttp2_option_set_no_http_messaging.rst
|
||||
nghttp2_option_set_no_recv_client_magic.rst
|
||||
nghttp2_option_set_peer_max_concurrent_streams.rst
|
||||
nghttp2_option_set_user_recv_extension_type.rst
|
||||
nghttp2_pack_settings_payload.rst
|
||||
nghttp2_priority_spec_check_default.rst
|
||||
nghttp2_priority_spec_default_init.rst
|
||||
nghttp2_priority_spec_init.rst
|
||||
nghttp2_rcbuf_decref.rst
|
||||
nghttp2_rcbuf_get_buf.rst
|
||||
nghttp2_rcbuf_incref.rst
|
||||
nghttp2_select_next_protocol.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_error_callback.rst
|
||||
nghttp2_session_callbacks_set_on_begin_frame_callback.rst
|
||||
nghttp2_session_callbacks_set_on_begin_headers_callback.rst
|
||||
nghttp2_session_callbacks_set_on_data_chunk_recv_callback.rst
|
||||
nghttp2_session_callbacks_set_on_extension_chunk_recv_callback.rst
|
||||
nghttp2_session_callbacks_set_on_frame_not_send_callback.rst
|
||||
nghttp2_session_callbacks_set_on_frame_recv_callback.rst
|
||||
nghttp2_session_callbacks_set_on_frame_send_callback.rst
|
||||
nghttp2_session_callbacks_set_on_header_callback.rst
|
||||
nghttp2_session_callbacks_set_on_header_callback2.rst
|
||||
nghttp2_session_callbacks_set_on_invalid_frame_recv_callback.rst
|
||||
nghttp2_session_callbacks_set_on_invalid_header_callback.rst
|
||||
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_recv_callback.rst
|
||||
nghttp2_session_callbacks_set_select_padding_callback.rst
|
||||
nghttp2_session_callbacks_set_send_callback.rst
|
||||
nghttp2_session_callbacks_set_send_data_callback.rst
|
||||
nghttp2_session_callbacks_set_unpack_extension_callback.rst
|
||||
nghttp2_session_change_stream_priority.rst
|
||||
nghttp2_session_check_request_allowed.rst
|
||||
nghttp2_session_check_server_session.rst
|
||||
nghttp2_session_client_new.rst
|
||||
nghttp2_session_client_new2.rst
|
||||
nghttp2_session_client_new3.rst
|
||||
nghttp2_session_consume.rst
|
||||
nghttp2_session_consume_connection.rst
|
||||
nghttp2_session_consume_stream.rst
|
||||
nghttp2_session_create_idle_stream.rst
|
||||
nghttp2_session_del.rst
|
||||
nghttp2_session_find_stream.rst
|
||||
nghttp2_session_get_effective_local_window_size.rst
|
||||
nghttp2_session_get_effective_recv_data_length.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
|
||||
nghttp2_session_get_local_settings.rst
|
||||
nghttp2_session_get_local_window_size.rst
|
||||
nghttp2_session_get_next_stream_id.rst
|
||||
nghttp2_session_get_outbound_queue_size.rst
|
||||
nghttp2_session_get_remote_settings.rst
|
||||
nghttp2_session_get_remote_window_size.rst
|
||||
nghttp2_session_get_root_stream.rst
|
||||
nghttp2_session_get_stream_effective_local_window_size.rst
|
||||
nghttp2_session_get_stream_effective_recv_data_length.rst
|
||||
nghttp2_session_get_stream_local_close.rst
|
||||
nghttp2_session_get_stream_local_window_size.rst
|
||||
nghttp2_session_get_stream_remote_close.rst
|
||||
nghttp2_session_get_stream_remote_window_size.rst
|
||||
nghttp2_session_get_stream_user_data.rst
|
||||
nghttp2_session_mem_recv.rst
|
||||
nghttp2_session_mem_send.rst
|
||||
nghttp2_session_recv.rst
|
||||
nghttp2_session_resume_data.rst
|
||||
nghttp2_session_send.rst
|
||||
nghttp2_session_server_new.rst
|
||||
nghttp2_session_server_new2.rst
|
||||
nghttp2_session_server_new3.rst
|
||||
nghttp2_session_set_local_window_size.rst
|
||||
nghttp2_session_set_next_stream_id.rst
|
||||
nghttp2_session_set_stream_user_data.rst
|
||||
nghttp2_session_terminate_session.rst
|
||||
nghttp2_session_terminate_session2.rst
|
||||
nghttp2_session_upgrade.rst
|
||||
nghttp2_session_upgrade2.rst
|
||||
nghttp2_session_want_read.rst
|
||||
nghttp2_session_want_write.rst
|
||||
nghttp2_set_debug_vprintf_callback.rst
|
||||
nghttp2_stream_get_first_child.rst
|
||||
nghttp2_stream_get_next_sibling.rst
|
||||
nghttp2_stream_get_parent.rst
|
||||
nghttp2_stream_get_previous_sibling.rst
|
||||
nghttp2_stream_get_state.rst
|
||||
nghttp2_stream_get_sum_dependency_weight.rst
|
||||
nghttp2_stream_get_weight.rst
|
||||
nghttp2_strerror.rst
|
||||
nghttp2_submit_altsvc.rst
|
||||
nghttp2_submit_data.rst
|
||||
nghttp2_submit_extension.rst
|
||||
nghttp2_submit_goaway.rst
|
||||
nghttp2_submit_headers.rst
|
||||
nghttp2_submit_ping.rst
|
||||
nghttp2_submit_priority.rst
|
||||
nghttp2_submit_push_promise.rst
|
||||
nghttp2_submit_request.rst
|
||||
nghttp2_submit_response.rst
|
||||
nghttp2_submit_rst_stream.rst
|
||||
nghttp2_submit_settings.rst
|
||||
nghttp2_submit_shutdown_notice.rst
|
||||
nghttp2_submit_trailer.rst
|
||||
nghttp2_submit_window_update.rst
|
||||
nghttp2_version.rst
|
||||
)
|
||||
|
||||
set(MAN_PAGES
|
||||
nghttp.1
|
||||
nghttpd.1
|
||||
nghttpx.1
|
||||
h2load.1
|
||||
)
|
||||
|
||||
# Other .rst files from the source tree that need to be copied
|
||||
# XXX move them to sources/ and create .in files?
|
||||
set(RST_FILES
|
||||
README.rst
|
||||
programmers-guide.rst
|
||||
nghttp.1.rst
|
||||
nghttpd.1.rst
|
||||
nghttpx.1.rst
|
||||
h2load.1.rst
|
||||
)
|
||||
|
||||
# XXX unused for now
|
||||
set(EXTRA_DIST
|
||||
mkapiref.py
|
||||
${RST_FILES}
|
||||
${APIDOCS}
|
||||
sources/index.rst
|
||||
sources/tutorial-client.rst
|
||||
sources/tutorial-server.rst
|
||||
sources/tutorial-hpack.rst
|
||||
sources/nghttpx-howto.rst
|
||||
sources/h2load-howto.rst
|
||||
sources/libnghttp2_asio.rst
|
||||
sources/python-apiref.rst
|
||||
sources/building-android-binary.rst
|
||||
sources/contribute.rst
|
||||
_exts/sphinxcontrib/LICENSE.rubydomain
|
||||
_exts/sphinxcontrib/__init__.py
|
||||
_exts/sphinxcontrib/rubydomain.py
|
||||
_themes/sphinx_rtd_theme/__init__.py
|
||||
_themes/sphinx_rtd_theme/breadcrumbs.html
|
||||
_themes/sphinx_rtd_theme/footer.html
|
||||
_themes/sphinx_rtd_theme/layout.html
|
||||
_themes/sphinx_rtd_theme/layout_old.html
|
||||
_themes/sphinx_rtd_theme/search.html
|
||||
_themes/sphinx_rtd_theme/searchbox.html
|
||||
_themes/sphinx_rtd_theme/static/css/badge_only.css
|
||||
_themes/sphinx_rtd_theme/static/css/theme.css
|
||||
_themes/sphinx_rtd_theme/static/fonts/FontAwesome.otf
|
||||
_themes/sphinx_rtd_theme/static/fonts/fontawesome-webfont.eot
|
||||
_themes/sphinx_rtd_theme/static/fonts/fontawesome-webfont.svg
|
||||
_themes/sphinx_rtd_theme/static/fonts/fontawesome-webfont.ttf
|
||||
_themes/sphinx_rtd_theme/static/fonts/fontawesome-webfont.woff
|
||||
_themes/sphinx_rtd_theme/static/js/theme.js
|
||||
_themes/sphinx_rtd_theme/theme.conf
|
||||
_themes/sphinx_rtd_theme/versions.html
|
||||
${MAN_PAGES}
|
||||
bash_completion/nghttp
|
||||
bash_completion/nghttpd
|
||||
bash_completion/nghttpx
|
||||
bash_completion/h2load
|
||||
)
|
||||
|
||||
# Based on Makefile for Sphinx documentation
|
||||
|
||||
# You can set these variables from the command line.
|
||||
set(SPHINXOPTS)
|
||||
set(SPHINXBUILD sphinx-build)
|
||||
set(PAPER)
|
||||
set(BUILDDIR manual)
|
||||
|
||||
# Internal variables.
|
||||
set(PAPEROPT_a4 -D latex_paper_size=a4)
|
||||
set(PAPEROPT_letter -D latex_paper_size=letter)
|
||||
set(ALLSPHINXOPTS -d ${BUILDDIR}/doctrees ${PAPEROPT_${PAPER}} ${SPHINXOPTS} .)
|
||||
|
||||
# "Please use `make <target>' where <target> is one of"
|
||||
# " html to make standalone HTML files"
|
||||
# " dirhtml to make HTML files named index.html in directories"
|
||||
# " singlehtml to make a single large HTML file"
|
||||
# " pickle to make pickle files"
|
||||
# " json to make JSON files"
|
||||
# " htmlhelp to make HTML files and a HTML help project"
|
||||
# " qthelp to make HTML files and a qthelp project"
|
||||
# " devhelp to make HTML files and a Devhelp project"
|
||||
# " epub to make an epub"
|
||||
# " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
|
||||
# " latexpdf to make LaTeX files and run them through pdflatex"
|
||||
# " text to make text files"
|
||||
# " man to make manual pages"
|
||||
# " changes to make an overview of all changed/added/deprecated items"
|
||||
# " linkcheck to check all external links for integrity"
|
||||
# " doctest to run all doctests embedded in the documentation (if enabled)"
|
||||
|
||||
|
||||
# Copy files for out-of-tree builds
|
||||
if(NOT CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_CURRENT_BINARY_DIR)
|
||||
set(RST_BUILD_FILES)
|
||||
foreach(rstfile IN LISTS RST_FILES)
|
||||
set(outfile "${CMAKE_CURRENT_BINARY_DIR}/${rstfile}")
|
||||
add_custom_command(OUTPUT "${outfile}"
|
||||
COMMAND ${CMAKE_COMMAND} -E copy
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/${rstfile}" "${outfile}"
|
||||
DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/${rstfile}"
|
||||
)
|
||||
list(APPEND RST_BUILD_FILES "${outfile}")
|
||||
endforeach()
|
||||
else()
|
||||
set(RST_BUILD_FILES "${RST_FILES}")
|
||||
endif()
|
||||
|
||||
set(apiref_SOURCES
|
||||
${CMAKE_BINARY_DIR}/lib/includes/nghttp2/nghttp2ver.h
|
||||
${CMAKE_SOURCE_DIR}/lib/includes/nghttp2/nghttp2.h
|
||||
)
|
||||
# Generates apiref.rst and other files
|
||||
add_custom_command(
|
||||
OUTPUT
|
||||
apiref.rst
|
||||
${APIDOCS}
|
||||
COMMAND
|
||||
"${PYTHON_EXECUTABLE}" "${CMAKE_CURRENT_SOURCE_DIR}/mkapiref.py"
|
||||
apiref.rst macros.rst enums.rst types.rst .
|
||||
${apiref_SOURCES}
|
||||
DEPENDS
|
||||
${RST_BUILD_FILES}
|
||||
${apiref_SOURCES}
|
||||
)
|
||||
|
||||
|
||||
|
||||
set_directory_properties(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES "${BUILDDIR}")
|
||||
|
||||
# Invokes sphinx-build and prints the given messages when completed
|
||||
function(sphinxbuild builder)
|
||||
set(echo_commands)
|
||||
foreach(message IN LISTS ARGN)
|
||||
list(APPEND echo_commands COMMAND ${CMAKE_COMMAND} -E echo "${message}")
|
||||
endforeach()
|
||||
add_custom_target(${builder}
|
||||
COMMAND "${SPHINXBUILD}" -b ${builder} ${ALLSPHINXOPTS} "${BUILDDIR}/${builder}"
|
||||
COMMAND ${CMAKE_COMMAND} -E echo
|
||||
${echo_commands}
|
||||
VERBATIM
|
||||
DEPENDS apiref.rst
|
||||
)
|
||||
endfunction()
|
||||
|
||||
foreach(builder html dirhtml singlehtml)
|
||||
sphinxbuild(${builder}
|
||||
"Build finished. The HTML pages are in ${BUILDDIR}/${builder}.")
|
||||
endforeach()
|
||||
sphinxbuild(pickle "Build finished; now you can process the pickle files.")
|
||||
sphinxbuild(json "Build finished; now you can process the JSON files.")
|
||||
sphinxbuild(htmlhelp
|
||||
"Build finished; now you can run HTML Help Workshop with the"
|
||||
".hhp project file in ${BUILDDIR}/htmlhelp."
|
||||
)
|
||||
sphinxbuild(qthelp
|
||||
"Build finished; now you can run \"qcollectiongenerator\" with the"
|
||||
".qhcp project file in ${BUILDDIR}/qthelp, like this:"
|
||||
"# qcollectiongenerator ${BUILDDIR}/qthelp/nghttp2.qhcp"
|
||||
"To view the help file:"
|
||||
"# assistant -collectionFile ${BUILDDIR}/qthelp/nghttp2.qhc"
|
||||
)
|
||||
sphinxbuild(devhelp
|
||||
"Build finished."
|
||||
"To view the help file:"
|
||||
"# mkdir -p ~/.local/share/devhelp/nghttp2"
|
||||
"# ln -s ${BUILDDIR}/devhelp ~/.local/share/devhelp/nghttp2"
|
||||
"# devhelp"
|
||||
)
|
||||
sphinxbuild(epub "Build finished. The epub file is in ${BUILDDIR}/epub.")
|
||||
sphinxbuild(latex
|
||||
"Build finished; the LaTeX files are in ${BUILDDIR}/latex."
|
||||
"Run `make' in that directory to run these through (pdf)latex"
|
||||
"(use `make latexpdf' here to do that automatically)."
|
||||
)
|
||||
|
||||
# Invoke the Makefile generated by sphinx
|
||||
add_custom_target(latexpdf
|
||||
COMMAND ${CMAKE_COMMAND} -E echo "Running LaTeX files through pdflatex..."
|
||||
COMMAND make -C "${BUILDDIR}/latex" all-pdf
|
||||
COMMAND ${CMAKE_COMMAND} -E echo "pdflatex finished; the PDF files are in ${BUILDDIR}/latex."
|
||||
DEPENDS latex
|
||||
)
|
||||
|
||||
sphinxbuild(text "Build finished. The text files are in ${BUILDDIR}/text.")
|
||||
sphinxbuild(man "Build finished. The manual pages are in ${BUILDDIR}/man.")
|
||||
sphinxbuild(changes "The overview file is in ${BUILDDIR}/changes.")
|
||||
sphinxbuild(linkcheck
|
||||
"Link check complete; look for any errors in the above output"
|
||||
"or in ${BUILDDIR}/linkcheck/output.txt."
|
||||
)
|
||||
sphinxbuild(doctest
|
||||
"Testing of doctests in the sources finished, look at the"
|
||||
"results in ${BUILDDIR}/doctest/output.txt."
|
||||
)
|
||||
|
||||
foreach(_man_page IN LISTS MAN_PAGES)
|
||||
install(FILES ${_man_page}
|
||||
DESTINATION "${CMAKE_INSTALL_MANDIR}/man1"
|
||||
)
|
||||
endforeach()
|
||||
@@ -37,6 +37,7 @@ APIDOCS= \
|
||||
nghttp2_hd_deflate_get_num_table_entries.rst \
|
||||
nghttp2_hd_deflate_get_table_entry.rst \
|
||||
nghttp2_hd_deflate_hd.rst \
|
||||
nghttp2_hd_deflate_hd_vec.rst \
|
||||
nghttp2_hd_deflate_new.rst \
|
||||
nghttp2_hd_deflate_new2.rst \
|
||||
nghttp2_hd_inflate_change_table_size.rst \
|
||||
@@ -47,39 +48,59 @@ APIDOCS= \
|
||||
nghttp2_hd_inflate_get_num_table_entries.rst \
|
||||
nghttp2_hd_inflate_get_table_entry.rst \
|
||||
nghttp2_hd_inflate_hd.rst \
|
||||
nghttp2_hd_inflate_hd2.rst \
|
||||
nghttp2_hd_inflate_new.rst \
|
||||
nghttp2_hd_inflate_new2.rst \
|
||||
nghttp2_http2_strerror.rst \
|
||||
nghttp2_is_fatal.rst \
|
||||
nghttp2_nv_compare_name.rst \
|
||||
nghttp2_option_del.rst \
|
||||
nghttp2_option_new.rst \
|
||||
nghttp2_option_set_builtin_recv_extension_type.rst \
|
||||
nghttp2_option_set_max_deflate_dynamic_table_size.rst \
|
||||
nghttp2_option_set_max_reserved_remote_streams.rst \
|
||||
nghttp2_option_set_max_send_header_block_length.rst \
|
||||
nghttp2_option_set_no_auto_ping_ack.rst \
|
||||
nghttp2_option_set_no_auto_window_update.rst \
|
||||
nghttp2_option_set_no_http_messaging.rst \
|
||||
nghttp2_option_set_no_recv_client_magic.rst \
|
||||
nghttp2_option_set_peer_max_concurrent_streams.rst \
|
||||
nghttp2_option_set_user_recv_extension_type.rst \
|
||||
nghttp2_pack_settings_payload.rst \
|
||||
nghttp2_priority_spec_check_default.rst \
|
||||
nghttp2_priority_spec_default_init.rst \
|
||||
nghttp2_priority_spec_init.rst \
|
||||
nghttp2_rcbuf_decref.rst \
|
||||
nghttp2_rcbuf_get_buf.rst \
|
||||
nghttp2_rcbuf_incref.rst \
|
||||
nghttp2_select_next_protocol.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_error_callback.rst \
|
||||
nghttp2_session_callbacks_set_on_begin_frame_callback.rst \
|
||||
nghttp2_session_callbacks_set_on_begin_headers_callback.rst \
|
||||
nghttp2_session_callbacks_set_on_data_chunk_recv_callback.rst \
|
||||
nghttp2_session_callbacks_set_on_extension_chunk_recv_callback.rst \
|
||||
nghttp2_session_callbacks_set_on_frame_not_send_callback.rst \
|
||||
nghttp2_session_callbacks_set_on_frame_recv_callback.rst \
|
||||
nghttp2_session_callbacks_set_on_frame_send_callback.rst \
|
||||
nghttp2_session_callbacks_set_on_header_callback.rst \
|
||||
nghttp2_session_callbacks_set_on_header_callback2.rst \
|
||||
nghttp2_session_callbacks_set_on_invalid_frame_recv_callback.rst \
|
||||
nghttp2_session_callbacks_set_on_invalid_header_callback.rst \
|
||||
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_recv_callback.rst \
|
||||
nghttp2_session_callbacks_set_select_padding_callback.rst \
|
||||
nghttp2_session_callbacks_set_send_callback.rst \
|
||||
nghttp2_session_callbacks_set_send_data_callback.rst \
|
||||
nghttp2_session_callbacks_set_unpack_extension_callback.rst \
|
||||
nghttp2_session_change_stream_priority.rst \
|
||||
nghttp2_session_check_request_allowed.rst \
|
||||
nghttp2_session_check_server_session.rst \
|
||||
nghttp2_session_client_new.rst \
|
||||
nghttp2_session_client_new2.rst \
|
||||
nghttp2_session_client_new3.rst \
|
||||
@@ -91,7 +112,11 @@ 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_hd_deflate_dynamic_table_size.rst \
|
||||
nghttp2_session_get_hd_inflate_dynamic_table_size.rst \
|
||||
nghttp2_session_get_last_proc_stream_id.rst \
|
||||
nghttp2_session_get_local_settings.rst \
|
||||
nghttp2_session_get_local_window_size.rst \
|
||||
nghttp2_session_get_next_stream_id.rst \
|
||||
nghttp2_session_get_outbound_queue_size.rst \
|
||||
nghttp2_session_get_remote_settings.rst \
|
||||
@@ -100,20 +125,19 @@ APIDOCS= \
|
||||
nghttp2_session_get_stream_effective_local_window_size.rst \
|
||||
nghttp2_session_get_stream_effective_recv_data_length.rst \
|
||||
nghttp2_session_get_stream_local_close.rst \
|
||||
nghttp2_session_get_stream_local_window_size.rst \
|
||||
nghttp2_session_get_stream_remote_close.rst \
|
||||
nghttp2_session_get_stream_remote_window_size.rst \
|
||||
nghttp2_session_get_stream_user_data.rst \
|
||||
nghttp2_session_mem_recv.rst \
|
||||
nghttp2_session_mem_send.rst \
|
||||
nghttp2_session_recv.rst \
|
||||
nghttp2_session_change_stream_priority.rst \
|
||||
nghttp2_session_check_request_allowed.rst \
|
||||
nghttp2_session_check_server_session.rst \
|
||||
nghttp2_session_resume_data.rst \
|
||||
nghttp2_session_send.rst \
|
||||
nghttp2_session_server_new.rst \
|
||||
nghttp2_session_server_new2.rst \
|
||||
nghttp2_session_server_new3.rst \
|
||||
nghttp2_session_set_local_window_size.rst \
|
||||
nghttp2_session_set_next_stream_id.rst \
|
||||
nghttp2_session_set_stream_user_data.rst \
|
||||
nghttp2_session_terminate_session.rst \
|
||||
@@ -122,6 +146,7 @@ APIDOCS= \
|
||||
nghttp2_session_upgrade2.rst \
|
||||
nghttp2_session_want_read.rst \
|
||||
nghttp2_session_want_write.rst \
|
||||
nghttp2_set_debug_vprintf_callback.rst \
|
||||
nghttp2_stream_get_first_child.rst \
|
||||
nghttp2_stream_get_next_sibling.rst \
|
||||
nghttp2_stream_get_parent.rst \
|
||||
@@ -130,7 +155,9 @@ APIDOCS= \
|
||||
nghttp2_stream_get_sum_dependency_weight.rst \
|
||||
nghttp2_stream_get_weight.rst \
|
||||
nghttp2_strerror.rst \
|
||||
nghttp2_submit_altsvc.rst \
|
||||
nghttp2_submit_data.rst \
|
||||
nghttp2_submit_extension.rst \
|
||||
nghttp2_submit_goaway.rst \
|
||||
nghttp2_submit_headers.rst \
|
||||
nghttp2_submit_ping.rst \
|
||||
@@ -145,15 +172,19 @@ APIDOCS= \
|
||||
nghttp2_submit_window_update.rst \
|
||||
nghttp2_version.rst
|
||||
|
||||
EXTRA_DIST = \
|
||||
mkapiref.py \
|
||||
RST_FILES = \
|
||||
README.rst \
|
||||
programmers-guide.rst \
|
||||
$(APIDOCS) \
|
||||
nghttp.1.rst \
|
||||
nghttpd.1.rst \
|
||||
nghttpx.1.rst \
|
||||
h2load.1.rst \
|
||||
h2load.1.rst
|
||||
|
||||
EXTRA_DIST = \
|
||||
CMakeLists.txt \
|
||||
mkapiref.py \
|
||||
$(RST_FILES) \
|
||||
$(APIDOCS) \
|
||||
sources/index.rst \
|
||||
sources/tutorial-client.rst \
|
||||
sources/tutorial-server.rst \
|
||||
@@ -227,13 +258,15 @@ help:
|
||||
|
||||
apiref.rst: \
|
||||
$(top_builddir)/lib/includes/nghttp2/nghttp2ver.h \
|
||||
$(top_builddir)/lib/includes/nghttp2/nghttp2.h
|
||||
$(top_srcdir)/lib/includes/nghttp2/nghttp2.h
|
||||
for i in $(RST_FILES); do [ -e $(builddir)/$$i ] || cp $(srcdir)/$$i $(builddir); done
|
||||
$(PYTHON) $(top_srcdir)/doc/mkapiref.py \
|
||||
apiref.rst macros.rst enums.rst types.rst . $^
|
||||
|
||||
$(APIDOCS): apiref.rst
|
||||
|
||||
clean-local:
|
||||
[ $(srcdir) = $(builddir) ] || for i in $(RST_FILES); do [ -e $(builddir)/$$i ] && rm -f $(builddir)/$$i; done
|
||||
-rm -f apiref.rst
|
||||
-rm -f $(APIDOCS)
|
||||
-rm -rf $(BUILDDIR)/*
|
||||
|
||||
@@ -15,6 +15,7 @@ from docutils import nodes
|
||||
from docutils.parsers.rst import directives
|
||||
|
||||
from sphinx import addnodes
|
||||
from sphinx import version_info
|
||||
from sphinx.roles import XRefRole
|
||||
from sphinx.locale import l_, _
|
||||
from sphinx.domains import Domain, ObjType, Index
|
||||
@@ -231,8 +232,8 @@ class RubyObject(ObjectDescription):
|
||||
|
||||
indextext = self.get_index_text(modname, name_cls)
|
||||
if indextext:
|
||||
self.indexnode['entries'].append(('single', indextext,
|
||||
fullname, fullname))
|
||||
self.indexnode['entries'].append(
|
||||
_make_index('single', indextext, fullname, fullname))
|
||||
|
||||
def before_content(self):
|
||||
# needed for automatic qualification of members (reset in subclasses)
|
||||
@@ -415,11 +416,19 @@ class RubyModule(Directive):
|
||||
# modindex currently
|
||||
if not noindex:
|
||||
indextext = _('%s (module)') % modname
|
||||
inode = addnodes.index(entries=[('single', indextext,
|
||||
'module-' + modname, modname)])
|
||||
inode = addnodes.index(entries=[_make_index(
|
||||
'single', indextext, 'module-' + modname, modname)])
|
||||
ret.append(inode)
|
||||
return ret
|
||||
|
||||
def _make_index(entrytype, entryname, target, ignored, key=None):
|
||||
# Sphinx 1.4 introduced backward incompatible changes, it now
|
||||
# requires 5 tuples. Last one is categorization key. See
|
||||
# http://www.sphinx-doc.org/en/stable/extdev/nodes.html#sphinx.addnodes.index
|
||||
if version_info >= (1, 4, 0, '', 0):
|
||||
return (entrytype, entryname, target, ignored, key)
|
||||
else:
|
||||
return (entrytype, entryname, target, ignored)
|
||||
|
||||
class RubyCurrentModule(Directive):
|
||||
"""
|
||||
|
||||
1
doc/_themes/sphinx_rtd_theme/layout.html
vendored
1
doc/_themes/sphinx_rtd_theme/layout.html
vendored
@@ -81,6 +81,7 @@
|
||||
|
||||
<body class="wy-body-for-nav" role="document">
|
||||
|
||||
{% block extrabody %} {% endblock %}
|
||||
<div class="wy-grid-for-nav">
|
||||
|
||||
{# SIDE NAV, TOGGLES ON MOBILE #}
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -8,7 +8,7 @@ _h2load()
|
||||
_get_comp_words_by_ref cur prev
|
||||
case $cur in
|
||||
-*)
|
||||
COMPREPLY=( $( compgen -W '--connection-window-bits --clients --verbose --ciphers --rate --no-tls-proto --requests --base-uri --h1 --threads --npn-list --rate-period --data --version --connection-inactivity-timeout --timing-script-file --max-concurrent-streams --connection-active-timeout --input-file --header --window-bits --help ' -- "$cur" ) )
|
||||
COMPREPLY=( $( compgen -W '--connection-window-bits --clients --verbose --ciphers --rate --no-tls-proto --header-table-size --requests --base-uri --h1 --threads --npn-list --rate-period --data --version --connection-inactivity-timeout --timing-script-file --encoder-header-table-size --max-concurrent-streams --connection-active-timeout --input-file --help --window-bits --header ' -- "$cur" ) )
|
||||
;;
|
||||
*)
|
||||
_filedir
|
||||
|
||||
@@ -8,7 +8,7 @@ _nghttp()
|
||||
_get_comp_words_by_ref cur prev
|
||||
case $cur in
|
||||
-*)
|
||||
COMPREPLY=( $( compgen -W '--no-push --verbose --no-dep --get-assets --har --header-table-size --multiply --padding --hexdump --max-concurrent-streams --continuation --connection-window-bits --peer-max-concurrent-streams --timeout --data --no-content-length --version --color --cert --upgrade --remote-name --trailer --weight --help --key --null-out --window-bits --stat --header ' -- "$cur" ) )
|
||||
COMPREPLY=( $( compgen -W '--no-push --verbose --no-dep --get-assets --har --header-table-size --multiply --encoder-header-table-size --padding --hexdump --max-concurrent-streams --continuation --connection-window-bits --peer-max-concurrent-streams --timeout --data --no-content-length --version --color --cert --upgrade --remote-name --trailer --weight --help --key --null-out --window-bits --expect-continue --stat --header ' -- "$cur" ) )
|
||||
;;
|
||||
*)
|
||||
_filedir
|
||||
|
||||
@@ -8,7 +8,7 @@ _nghttpd()
|
||||
_get_comp_words_by_ref cur prev
|
||||
case $cur in
|
||||
-*)
|
||||
COMPREPLY=( $( compgen -W '--htdocs --verbose --daemon --echo-upload --error-gzip --push --header-table-size --padding --hexdump --max-concurrent-streams --no-tls --mime-types-file --no-content-length --workers --version --color --early-response --dh-param-file --trailer --address --verify-client --help ' -- "$cur" ) )
|
||||
COMPREPLY=( $( compgen -W '--htdocs --verbose --daemon --echo-upload --error-gzip --push --header-table-size --encoder-header-table-size --padding --hexdump --max-concurrent-streams --no-tls --connection-window-bits --mime-types-file --no-content-length --workers --version --color --early-response --dh-param-file --trailer --address --window-bits --verify-client --help ' -- "$cur" ) )
|
||||
;;
|
||||
*)
|
||||
_filedir
|
||||
|
||||
@@ -8,7 +8,7 @@ _nghttpx()
|
||||
_get_comp_words_by_ref cur prev
|
||||
case $cur in
|
||||
-*)
|
||||
COMPREPLY=( $( compgen -W '--worker-read-rate --frontend-no-tls --frontend-http2-dump-response-header --backend-http1-connections-per-frontend --tls-ticket-key-file --verify-client-cacert --include --backend-request-buffer --backend-http2-connection-window-bits --conf --worker-write-burst --npn-list --fetch-ocsp-response-file --mruby-file --stream-read-timeout --tls-ticket-key-memcached --forwarded-for --accesslog-syslog --frontend-http2-read-timeout --listener-disable-timeout --frontend-http2-connection-window-bits --ciphers --strip-incoming-x-forwarded-for --private-key-passwd-file --backend-keep-alive-timeout --backend-http-proxy-uri --backend-http1-connections-per-host --rlimit-nofile --tls-dyn-rec-warmup-threshold --no-via --ocsp-update-interval --backend-write-timeout --client --tls-ticket-key-memcached-max-retry --http2-no-cookie-crumbling --worker-read-burst --client-proxy --http2-bridge --accesslog-format --errorlog-syslog --errorlog-file --http2-max-concurrent-streams --frontend-write-timeout --tls-ticket-key-cipher --read-burst --backend-ipv4 --backend-ipv6 --backend --insecure --log-level --host-rewrite --tls-proto-list --backend-http2-connections-per-worker --tls-ticket-key-memcached-interval --dh-param-file --worker-frontend-connections --syslog-facility --fastopen --no-location-rewrite --tls-session-cache-memcached --no-ocsp --backend-response-buffer --workers --add-forwarded --frontend-http2-window-bits --worker-write-rate --add-request-header --backend-tls-sni-field --subcert --help --frontend-frame-debug --pid-file --frontend-http2-dump-request-header --daemon --write-rate --altsvc --user --add-x-forwarded-for --header-field-buffer --frontend-read-timeout --tls-ticket-key-memcached-max-fail --backlog --write-burst --no-server-push --backend-http2-window-bits --padding --stream-write-timeout --cacert --forwarded-by --version --add-response-header --backend-read-timeout --frontend --accesslog-file --http2-proxy --max-header-fields --backend-no-tls --client-private-key-file --client-cert-file --accept-proxy-protocol --tls-dyn-rec-idle-timeout --verify-client --read-rate --strip-incoming-forwarded ' -- "$cur" ) )
|
||||
COMPREPLY=( $( compgen -W '--worker-read-rate --include --frontend-http2-dump-response-header --tls-ticket-key-file --verify-client-cacert --max-response-header-fields --backend-http2-window-size --frontend-keep-alive-timeout --backend-request-buffer --max-request-header-fields --fastopen --backend-connect-timeout --conf --dns-lookup-timeout --backend-http2-max-concurrent-streams --worker-write-burst --npn-list --dns-max-try --fetch-ocsp-response-file --no-via --tls-session-cache-memcached-cert-file --no-http2-cipher-black-list --mruby-file --client-no-http2-cipher-black-list --stream-read-timeout --client-ciphers --forwarded-for --accesslog-syslog --dns-cache-timeout --frontend-http2-read-timeout --listener-disable-timeout --ciphers --client-psk-secrets --strip-incoming-x-forwarded-for --no-server-rewrite --private-key-passwd-file --backend-keep-alive-timeout --backend-http-proxy-uri --rlimit-nofile --tls-ticket-key-memcached-cert-file --ocsp-update-interval --forwarded-by --tls-session-cache-memcached-private-key-file --error-page --backend-write-timeout --tls-dyn-rec-warmup-threshold --tls-ticket-key-memcached-max-retry --frontend-http2-window-size --http2-no-cookie-crumbling --worker-read-burst --dh-param-file --accesslog-format --errorlog-syslog --request-header-field-buffer --api-max-request-body --frontend-http2-decoder-dynamic-table-size --errorlog-file --frontend-http2-max-concurrent-streams --psk-secrets --frontend-write-timeout --tls-ticket-key-cipher --read-burst --backend --server-name --insecure --backend-max-backoff --log-level --host-rewrite --tls-proto-list --tls-ticket-key-memcached-interval --frontend-http2-setting-timeout --frontend-http2-connection-window-size --worker-frontend-connections --syslog-facility --no-server-push --no-location-rewrite --tls-session-cache-memcached --no-ocsp --frontend-http2-encoder-dynamic-table-size --workers --add-forwarded --worker-write-rate --add-request-header --backend-http2-settings-timeout --subcert --ecdh-curves --no-kqueue --help --frontend-frame-debug --tls-sct-dir --pid-file --frontend-http2-dump-request-header --daemon --write-rate --altsvc --backend-http2-decoder-dynamic-table-size --user --add-x-forwarded-for --frontend-read-timeout --tls-ticket-key-memcached-max-fail --backlog --write-burst --backend-connections-per-host --response-header-field-buffer --tls-ticket-key-memcached-address-family --padding --tls-session-cache-memcached-address-family --stream-write-timeout --cacert --tls-ticket-key-memcached-private-key-file --accesslog-write-early --backend-address-family --backend-http2-connection-window-size --version --add-response-header --backend-read-timeout --frontend-http2-optimize-window-size --frontend --accesslog-file --http2-proxy --backend-http2-encoder-dynamic-table-size --client-private-key-file --client-cert-file --tls-ticket-key-memcached --tls-dyn-rec-idle-timeout --frontend-http2-optimize-write-buffer-size --verify-client --backend-response-buffer --read-rate --backend-connections-per-frontend --strip-incoming-forwarded ' -- "$cur" ) )
|
||||
;;
|
||||
*)
|
||||
_filedir
|
||||
|
||||
@@ -41,7 +41,7 @@ import sys, os
|
||||
# documentation root, use os.path.abspath to make it absolute, like shown here.
|
||||
#sys.path.insert(0, os.path.abspath('.'))
|
||||
|
||||
sys.path.append(os.path.abspath('_exts'))
|
||||
sys.path.append(os.path.abspath('@top_srcdir@/doc/_exts'))
|
||||
|
||||
# -- General configuration -----------------------------------------------------
|
||||
|
||||
|
||||
32
doc/h2load.1
32
doc/h2load.1
@@ -1,6 +1,6 @@
|
||||
.\" Man page generated from reStructuredText.
|
||||
.
|
||||
.TH "H2LOAD" "1" "February 11, 2016" "1.7.1" "nghttp2"
|
||||
.TH "H2LOAD" "1" "Jan 25, 2017" "1.19.0" "nghttp2"
|
||||
.SH NAME
|
||||
h2load \- HTTP/2 benchmarking tool
|
||||
.
|
||||
@@ -123,6 +123,8 @@ Add/Override a header to the requests.
|
||||
.B \-\-ciphers=<SUITE>
|
||||
Set allowed cipher list. The format of the string is
|
||||
described in OpenSSL ciphers(1).
|
||||
.sp
|
||||
Default: \fBECDHE\-ECDSA\-CHACHA20\-POLY1305:ECDHE\-RSA\-CHACHA20\-POLY1305:ECDHE\-ECDSA\-AES128\-GCM\-SHA256:ECDHE\-RSA\-AES128\-GCM\-SHA256:ECDHE\-ECDSA\-AES256\-GCM\-SHA384:ECDHE\-RSA\-AES256\-GCM\-SHA384:DHE\-RSA\-AES128\-GCM\-SHA256:DHE\-RSA\-AES256\-GCM\-SHA384:ECDHE\-ECDSA\-AES128\-SHA256:ECDHE\-RSA\-AES128\-SHA256:ECDHE\-ECDSA\-AES128\-SHA:ECDHE\-RSA\-AES256\-SHA384:ECDHE\-RSA\-AES128\-SHA:ECDHE\-ECDSA\-AES256\-SHA384:ECDHE\-ECDSA\-AES256\-SHA:ECDHE\-RSA\-AES256\-SHA:DHE\-RSA\-AES128\-SHA256:DHE\-RSA\-AES128\-SHA:DHE\-RSA\-AES256\-SHA256:DHE\-RSA\-AES256\-SHA:ECDHE\-ECDSA\-DES\-CBC3\-SHA:ECDHE\-RSA\-DES\-CBC3\-SHA:EDH\-RSA\-DES\-CBC3\-SHA:AES128\-GCM\-SHA256:AES256\-GCM\-SHA384:AES128\-SHA256:AES256\-SHA256:AES128\-SHA:AES256\-SHA:DES\-CBC3\-SHA:!DSS\fP
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
@@ -138,7 +140,9 @@ Default: \fBh2c\fP
|
||||
.TP
|
||||
.B \-d, \-\-data=<PATH>
|
||||
Post FILE to server. The request method is changed to
|
||||
POST.
|
||||
POST. For http/1.1 connection, if \fI\%\-d\fP is used, the
|
||||
maximum number of in\-flight pipelined requests is set to
|
||||
1.
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
@@ -149,7 +153,7 @@ representing the number of connections to be made per
|
||||
rate period. The maximum number of connections to be
|
||||
made is given in \fI\%\-c\fP option. This rate will be
|
||||
distributed among threads as evenly as possible. For
|
||||
example, with \fB\-t2\fP and \fB\-r4\fP, each thread gets 2
|
||||
example, with \fI\%\-t\fP2 and \fI\%\-r\fP4, each thread gets 2
|
||||
connections per period. When the rate is 0, the program
|
||||
will run as it normally does, creating connections at
|
||||
whatever variable rate it wants. The default value for
|
||||
@@ -240,6 +244,23 @@ http/1.1 for both http and https URI.
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \-\-header\-table\-size=<SIZE>
|
||||
Specify decoder header table size.
|
||||
.sp
|
||||
Default: \fB4K\fP
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \-\-encoder\-header\-table\-size=<SIZE>
|
||||
Specify encoder header table size. The decoder (server)
|
||||
specifies the maximum dynamic table size it accepts.
|
||||
Then the negotiated dynamic table size is the minimum of
|
||||
this option value and the value which server specified.
|
||||
.sp
|
||||
Default: \fB4K\fP
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \-v, \-\-verbose
|
||||
Output debug information.
|
||||
.UNINDENT
|
||||
@@ -254,6 +275,9 @@ Display version information and exit.
|
||||
Display this help and exit.
|
||||
.UNINDENT
|
||||
.sp
|
||||
The <SIZE> argument is an integer and an optional unit (e.g., 10K is
|
||||
10 * 1024). Units are K, M and G (powers of 1024).
|
||||
.sp
|
||||
The <DURATION> argument is an integer and an optional unit (e.g., 1s
|
||||
is 1 second and 500ms is 500 milliseconds). Units are h, m, s or ms
|
||||
(hours, minutes, seconds and milliseconds, respectively). If a unit
|
||||
@@ -412,7 +436,7 @@ performance. To set smaller flow control window, use \fI\%\-w\fP and
|
||||
window size described in HTTP/2 and SPDY protocol specification.
|
||||
.SH SEE ALSO
|
||||
.sp
|
||||
\fInghttp(1)\fP, \fInghttpd(1)\fP, \fInghttpx(1)\fP
|
||||
\fBnghttp(1)\fP, \fBnghttpd(1)\fP, \fBnghttpx(1)\fP
|
||||
.SH AUTHOR
|
||||
Tatsuhiro Tsujikawa
|
||||
.SH COPYRIGHT
|
||||
|
||||
@@ -74,14 +74,14 @@ OPTIONS
|
||||
.. option:: -w, --window-bits=<N>
|
||||
|
||||
Sets the stream level initial window size to (2\*\*<N>)-1.
|
||||
For SPDY, 2**<N> is used instead.
|
||||
For SPDY, 2\*\*<N> is used instead.
|
||||
|
||||
Default: ``30``
|
||||
|
||||
.. option:: -W, --connection-window-bits=<N>
|
||||
|
||||
Sets the connection level initial window size to
|
||||
(2**<N>)-1. For SPDY, if <N> is strictly less than 16,
|
||||
(2\*\*<N>)-1. For SPDY, if <N> is strictly less than 16,
|
||||
this option is ignored. Otherwise 2\*\*<N> is used for
|
||||
SPDY.
|
||||
|
||||
@@ -96,6 +96,8 @@ OPTIONS
|
||||
Set allowed cipher list. The format of the string is
|
||||
described in OpenSSL ciphers(1).
|
||||
|
||||
Default: ``ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS``
|
||||
|
||||
.. option:: -p, --no-tls-proto=<PROTOID>
|
||||
|
||||
Specify ALPN identifier of the protocol to be used when
|
||||
@@ -108,7 +110,9 @@ OPTIONS
|
||||
.. option:: -d, --data=<PATH>
|
||||
|
||||
Post FILE to server. The request method is changed to
|
||||
POST.
|
||||
POST. For http/1.1 connection, if :option:`-d` is used, the
|
||||
maximum number of in-flight pipelined requests is set to
|
||||
1.
|
||||
|
||||
.. option:: -r, --rate=<N>
|
||||
|
||||
@@ -118,7 +122,7 @@ OPTIONS
|
||||
rate period. The maximum number of connections to be
|
||||
made is given in :option:`-c` option. This rate will be
|
||||
distributed among threads as evenly as possible. For
|
||||
example, with :option:`-t2` and :option:`\-r4`, each thread gets 2
|
||||
example, with :option:`-t`\2 and :option:`-r`\4, each thread gets 2
|
||||
connections per period. When the rate is 0, the program
|
||||
will run as it normally does, creating connections at
|
||||
whatever variable rate it wants. The default value for
|
||||
@@ -200,6 +204,21 @@ OPTIONS
|
||||
:option:`--no-tls-proto`\=http/1.1, which effectively force
|
||||
http/1.1 for both http and https URI.
|
||||
|
||||
.. option:: --header-table-size=<SIZE>
|
||||
|
||||
Specify decoder header table size.
|
||||
|
||||
Default: ``4K``
|
||||
|
||||
.. option:: --encoder-header-table-size=<SIZE>
|
||||
|
||||
Specify encoder header table size. The decoder (server)
|
||||
specifies the maximum dynamic table size it accepts.
|
||||
Then the negotiated dynamic table size is the minimum of
|
||||
this option value and the value which server specified.
|
||||
|
||||
Default: ``4K``
|
||||
|
||||
.. option:: -v, --verbose
|
||||
|
||||
Output debug information.
|
||||
@@ -214,6 +233,9 @@ OPTIONS
|
||||
|
||||
|
||||
|
||||
The <SIZE> argument is an integer and an optional unit (e.g., 10K is
|
||||
10 * 1024). Units are K, M and G (powers of 1024).
|
||||
|
||||
The <DURATION> argument is an integer and an optional unit (e.g., 1s
|
||||
is 1 second and 500ms is 500 milliseconds). Units are h, m, s or ms
|
||||
(hours, minutes, seconds and milliseconds, respectively). If a unit
|
||||
|
||||
29
doc/nghttp.1
29
doc/nghttp.1
@@ -1,6 +1,6 @@
|
||||
.\" Man page generated from reStructuredText.
|
||||
.
|
||||
.TH "NGHTTP" "1" "February 11, 2016" "1.7.1" "nghttp2"
|
||||
.TH "NGHTTP" "1" "Jan 25, 2017" "1.19.0" "nghttp2"
|
||||
.SH NAME
|
||||
nghttp \- HTTP/2 client
|
||||
.
|
||||
@@ -142,10 +142,13 @@ HTTP upgrade request is performed with OPTIONS method.
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \-p, \-\-weight=<WEIGHT>
|
||||
Sets priority group weight. The valid value range is
|
||||
Sets weight of given URI. This option can be used
|
||||
multiple times, and N\-th \fI\%\-p\fP option sets weight of N\-th
|
||||
URI in the command line. If the number of \fI\%\-p\fP option is
|
||||
less than the number of URI, the last \fI\%\-p\fP option value is
|
||||
repeated. If there is no \fI\%\-p\fP option, default weight, 16,
|
||||
is assumed. The valid value range is
|
||||
[1, 256], inclusive.
|
||||
.sp
|
||||
Default: \fB16\fP
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
@@ -167,6 +170,14 @@ multiple header table size change.
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \-\-encoder\-header\-table\-size=<SIZE>
|
||||
Specify encoder header table size. The decoder (server)
|
||||
specifies the maximum dynamic table size it accepts.
|
||||
Then the negotiated dynamic table size is the minimum of
|
||||
this option value and the value which server specified.
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \-b, \-\-padding=<N>
|
||||
Add at most <N> bytes to a frame payload as padding.
|
||||
Specify 0 to disable padding.
|
||||
@@ -217,6 +228,14 @@ accepts.
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \-\-expect\-continue
|
||||
Perform an Expect/Continue handshake: wait to send DATA
|
||||
(up to a short timeout) until the server sends a 100
|
||||
Continue interim response. This option is ignored unless
|
||||
combined with the \fI\%\-d\fP option.
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \-\-version
|
||||
Display version information and exit.
|
||||
.UNINDENT
|
||||
@@ -292,7 +311,7 @@ stream 11 with the weight 12. The other resources (e.g., icon) depend
|
||||
on stream 11 with the weight 2.
|
||||
.SH SEE ALSO
|
||||
.sp
|
||||
\fInghttpd(1)\fP, \fInghttpx(1)\fP, \fIh2load(1)\fP
|
||||
\fBnghttpd(1)\fP, \fBnghttpx(1)\fP, \fBh2load(1)\fP
|
||||
.SH AUTHOR
|
||||
Tatsuhiro Tsujikawa
|
||||
.SH COPYRIGHT
|
||||
|
||||
@@ -107,11 +107,14 @@ OPTIONS
|
||||
|
||||
.. option:: -p, --weight=<WEIGHT>
|
||||
|
||||
Sets priority group weight. The valid value range is
|
||||
Sets weight of given URI. This option can be used
|
||||
multiple times, and N-th :option:`-p` option sets weight of N-th
|
||||
URI in the command line. If the number of :option:`-p` option is
|
||||
less than the number of URI, the last :option:`-p` option value is
|
||||
repeated. If there is no :option:`-p` option, default weight, 16,
|
||||
is assumed. The valid value range is
|
||||
[1, 256], inclusive.
|
||||
|
||||
Default: ``16``
|
||||
|
||||
.. option:: -M, --peer-max-concurrent-streams=<N>
|
||||
|
||||
Use <N> as SETTINGS_MAX_CONCURRENT_STREAMS value of
|
||||
@@ -128,6 +131,13 @@ OPTIONS
|
||||
frame payload before the last value, to simulate
|
||||
multiple header table size change.
|
||||
|
||||
.. option:: --encoder-header-table-size=<SIZE>
|
||||
|
||||
Specify encoder header table size. The decoder (server)
|
||||
specifies the maximum dynamic table size it accepts.
|
||||
Then the negotiated dynamic table size is the minimum of
|
||||
this option value and the value which server specified.
|
||||
|
||||
.. option:: -b, --padding=<N>
|
||||
|
||||
Add at most <N> bytes to a frame payload as padding.
|
||||
@@ -169,6 +179,13 @@ OPTIONS
|
||||
The number of concurrent pushed streams this client
|
||||
accepts.
|
||||
|
||||
.. option:: --expect-continue
|
||||
|
||||
Perform an Expect/Continue handshake: wait to send DATA
|
||||
(up to a short timeout) until the server sends a 100
|
||||
Continue interim response. This option is ignored unless
|
||||
combined with the :option:`-d` option.
|
||||
|
||||
.. option:: --version
|
||||
|
||||
Display version information and exit.
|
||||
@@ -201,7 +218,9 @@ implementation.
|
||||
|
||||
When connection is established, nghttp sends 5 PRIORITY frames to idle
|
||||
streams 3, 5, 7, 9 and 11 to create "anchor" nodes in dependency
|
||||
tree::
|
||||
tree:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
+-----+
|
||||
|id=0 |
|
||||
|
||||
@@ -12,7 +12,9 @@ implementation.
|
||||
|
||||
When connection is established, nghttp sends 5 PRIORITY frames to idle
|
||||
streams 3, 5, 7, 9 and 11 to create "anchor" nodes in dependency
|
||||
tree::
|
||||
tree:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
+-----+
|
||||
|id=0 |
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
.\" Man page generated from reStructuredText.
|
||||
.
|
||||
.TH "NGHTTPD" "1" "February 11, 2016" "1.7.1" "nghttp2"
|
||||
.TH "NGHTTPD" "1" "Jan 25, 2017" "1.19.0" "nghttp2"
|
||||
.SH NAME
|
||||
nghttpd \- HTTP/2 server
|
||||
.
|
||||
@@ -99,6 +99,14 @@ Specify decoder header table size.
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \-\-encoder\-header\-table\-size=<SIZE>
|
||||
Specify encoder header table size. The decoder (client)
|
||||
specifies the maximum dynamic table size it accepts.
|
||||
Then the negotiated dynamic table size is the minimum of
|
||||
this option value and the value which client specified.
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \-\-color
|
||||
Force colored log output.
|
||||
.UNINDENT
|
||||
@@ -139,6 +147,17 @@ Make error response gzipped.
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \-w, \-\-window\-bits=<N>
|
||||
Sets the stream level initial window size to 2**<N>\-1.
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \-W, \-\-connection\-window\-bits=<N>
|
||||
Sets the connection level initial window size to
|
||||
2**<N>\-1.
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B \-\-dh\-param\-file=<PATH>
|
||||
Path to file that contains DH parameters in PEM format.
|
||||
Without this option, DHE cipher suites are not
|
||||
@@ -198,7 +217,7 @@ The <SIZE> argument is an integer and an optional unit (e.g., 10K is
|
||||
10 * 1024). Units are K, M and G (powers of 1024).
|
||||
.SH SEE ALSO
|
||||
.sp
|
||||
\fInghttp(1)\fP, \fInghttpx(1)\fP, \fIh2load(1)\fP
|
||||
\fBnghttp(1)\fP, \fBnghttpx(1)\fP, \fBh2load(1)\fP
|
||||
.SH AUTHOR
|
||||
Tatsuhiro Tsujikawa
|
||||
.SH COPYRIGHT
|
||||
|
||||
@@ -70,6 +70,13 @@ OPTIONS
|
||||
|
||||
Specify decoder header table size.
|
||||
|
||||
.. option:: --encoder-header-table-size=<SIZE>
|
||||
|
||||
Specify encoder header table size. The decoder (client)
|
||||
specifies the maximum dynamic table size it accepts.
|
||||
Then the negotiated dynamic table size is the minimum of
|
||||
this option value and the value which client specified.
|
||||
|
||||
.. option:: --color
|
||||
|
||||
Force colored log output.
|
||||
@@ -104,6 +111,15 @@ OPTIONS
|
||||
|
||||
Make error response gzipped.
|
||||
|
||||
.. option:: -w, --window-bits=<N>
|
||||
|
||||
Sets the stream level initial window size to 2\*\*<N>-1.
|
||||
|
||||
.. option:: -W, --connection-window-bits=<N>
|
||||
|
||||
Sets the connection level initial window size to
|
||||
2\*\*<N>-1.
|
||||
|
||||
.. option:: --dh-param-file=<PATH>
|
||||
|
||||
Path to file that contains DH parameters in PEM format.
|
||||
|
||||
932
doc/nghttpx.1
932
doc/nghttpx.1
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
163
doc/nghttpx.h2r
163
doc/nghttpx.h2r
@@ -41,6 +41,33 @@ FILES
|
||||
:option:`--conf` option cannot be used in the configuration file and
|
||||
will be ignored if specified.
|
||||
|
||||
Error log
|
||||
Error log is written to stderr by default. It can be configured
|
||||
using :option:`--errorlog-file`. The format of log message is as
|
||||
follows:
|
||||
|
||||
<datetime> <master-pid> <current-pid> <thread-id> <level> (<filename>:<line>) <msg>
|
||||
|
||||
<datetime>
|
||||
It is a conbination of date and time when the log is written. It
|
||||
is in ISO 8601 format.
|
||||
|
||||
<master-pid>
|
||||
It is a master process ID.
|
||||
|
||||
<current-pid>
|
||||
It is a process ID which writes this log.
|
||||
|
||||
<thread-id>
|
||||
It is a thread ID which writes this log. It would be unique
|
||||
within <current-pid>.
|
||||
|
||||
<filename> and <line>
|
||||
They are source file name, and line number which produce this log.
|
||||
|
||||
<msg>
|
||||
It is a log message body.
|
||||
|
||||
SIGNALS
|
||||
-------
|
||||
|
||||
@@ -49,6 +76,9 @@ SIGQUIT
|
||||
accepting connection. After all connections are handled, nghttpx
|
||||
exits.
|
||||
|
||||
SIGHUP
|
||||
Reload configuration file given in :option:`--conf`.
|
||||
|
||||
SIGUSR1
|
||||
Reopen log files.
|
||||
|
||||
@@ -56,7 +86,11 @@ SIGUSR2
|
||||
Fork and execute nghttpx. It will execute the binary in the same
|
||||
path with same command-line arguments and environment variables.
|
||||
After new process comes up, sending SIGQUIT to the original process
|
||||
to perform hot swapping.
|
||||
to perform hot swapping. The difference between SIGUSR2 + SIGQUIT
|
||||
and SIGHUP is that former is usually used to execute new binary, and
|
||||
the master process is newly spawned. On the other hand, the latter
|
||||
just reloads configuration file, and the same master process
|
||||
continues to exist.
|
||||
|
||||
.. note::
|
||||
|
||||
@@ -85,7 +119,7 @@ backend server and extracts URI-reference with parameter
|
||||
and pushes those URIs to the frontend client. Here is a sample Link
|
||||
header field to initiate server push:
|
||||
|
||||
.. code-block:: http
|
||||
.. code-block:: text
|
||||
|
||||
Link: </fonts/font.woff>; rel=preload
|
||||
Link: </css/theme.css>; rel=preload
|
||||
@@ -98,12 +132,12 @@ Currently, the following restriction is applied for server push:
|
||||
This limitation may be loosened in the future release.
|
||||
|
||||
nghttpx also supports server push if both frontend and backend are
|
||||
HTTP/2 (which implies :option:`--http2-bridge` or :option:`--client`).
|
||||
In this case, in addition to server push via Link header field, server
|
||||
push from backend is relayed to frontend HTTP/2 session.
|
||||
HTTP/2 in default mode. In this case, in addition to server push via
|
||||
Link header field, server push from backend is forwarded to frontend
|
||||
HTTP/2 session.
|
||||
|
||||
HTTP/2 server push will be disabled if :option:`--http2-proxy` or
|
||||
:option:`--client-proxy` is used.
|
||||
HTTP/2 server push will be disabled if :option:`--http2-proxy` is
|
||||
used.
|
||||
|
||||
UNIX DOMAIN SOCKET
|
||||
------------------
|
||||
@@ -150,6 +184,10 @@ insert serialized session data to memcached with
|
||||
as a memcached entry key, with expiry time 12 hours. Session timeout
|
||||
is set to 12 hours.
|
||||
|
||||
By default, connections to memcached server are not encrypted. To
|
||||
enable encryption, use ``tls`` keyword in
|
||||
:option:`--tls-session-cache-memcached` option.
|
||||
|
||||
TLS SESSION TICKET RESUMPTION
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
@@ -189,11 +227,33 @@ used, LEN must be 48. If
|
||||
keys. The key appeared first is used as encryption key. All the
|
||||
remaining keys are used as decryption only.
|
||||
|
||||
By default, connections to memcached server are not encrypted. To
|
||||
enable encryption, use ``tls`` keyword in
|
||||
:option:`--tls-ticket-key-memcached` option.
|
||||
|
||||
If :option:`--tls-ticket-key-file` is given, encryption key is read
|
||||
from the given file. In this case, nghttpx does not rotate key
|
||||
automatically. To rotate key, one has to restart nghttpx (see
|
||||
SIGNALS).
|
||||
|
||||
CERTIFICATE TRANSPARENCY
|
||||
------------------------
|
||||
|
||||
nghttpx supports TLS ``signed_certificate_timestamp`` extension (`RFC
|
||||
6962 <https://tools.ietf.org/html/rfc6962>`_). The relevant options
|
||||
are :option:`--tls-sct-dir` and ``sct-dir`` parameter in
|
||||
:option:`--subcert`. They takes a directory, and nghttpx reads all
|
||||
files whose extension is ``.sct`` under the directory. The ``*.sct``
|
||||
files are encoded as ``SignedCertificateTimestamp`` struct described
|
||||
in `section 3.2 of RFC 69662
|
||||
<https://tools.ietf.org/html/rfc6962#section-3.2>`_. This format is
|
||||
the same one used by `nginx-ct
|
||||
<https://github.com/grahamedgecombe/nginx-ct>`_ and `mod_ssl_ct
|
||||
<https://httpd.apache.org/docs/trunk/mod/mod_ssl_ct.html>`_.
|
||||
`ct-submit <https://github.com/grahamedgecombe/ct-submit>`_ can be
|
||||
used to submit certificates to log servers, and obtain the
|
||||
``SignedCertificateTimestamp`` struct which can be used with nghttpx.
|
||||
|
||||
MRUBY SCRIPTING
|
||||
---------------
|
||||
|
||||
@@ -257,7 +317,28 @@ respectively.
|
||||
|
||||
.. rb:attr_reader:: remote_addr
|
||||
|
||||
Return IP address of a remote client.
|
||||
Return IP address of a remote client. If connection is made
|
||||
via UNIX domain socket, this returns the string "localhost".
|
||||
|
||||
.. rb:attr_reader:: server_addr
|
||||
|
||||
Return address of server that accepted the connection. This
|
||||
is a string which specified in :option:`--frontend` option,
|
||||
excluding port number, and not a resolved IP address. For
|
||||
UNIX domain socket, this is a path to UNIX domain socket.
|
||||
|
||||
.. rb:attr_reader:: server_port
|
||||
|
||||
Return port number of the server frontend which accepted the
|
||||
connection from client.
|
||||
|
||||
.. rb:attr_reader:: tls_used
|
||||
|
||||
Return true if TLS is used on the connection.
|
||||
|
||||
.. rb:attr_reader:: tls_sni
|
||||
|
||||
Return the TLS SNI value which client sent in this connection.
|
||||
|
||||
.. rb:class:: Request
|
||||
|
||||
@@ -293,7 +374,13 @@ respectively.
|
||||
|
||||
Request path, including query component (i.e., /index.html).
|
||||
On assignment, copy of given value is assigned. The path does
|
||||
not include authority component of URI.
|
||||
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 https://tools.ietf.org/html/rfc3986#section-2.3), and
|
||||
resolves ".." and ".". But it may leave characters which
|
||||
should be percent-encoded as is. So be careful when comparing
|
||||
path against desired string.
|
||||
|
||||
.. rb:attr_reader:: headers
|
||||
|
||||
@@ -320,7 +407,7 @@ respectively.
|
||||
|
||||
Clear all existing request header fields.
|
||||
|
||||
.. rb:method:: push uri
|
||||
.. rb:method:: push(uri)
|
||||
|
||||
Initiate to push resource identified by *uri*. Only HTTP/2
|
||||
protocol supports this feature. For the other protocols, this
|
||||
@@ -431,6 +518,62 @@ addresses:
|
||||
|
||||
App.new
|
||||
|
||||
API ENDPOINTS
|
||||
-------------
|
||||
|
||||
nghttpx exposes API endpoints to manipulate it via HTTP based API. By
|
||||
default, API endpoint is disabled. To enable it, add a dedicated
|
||||
frontend for API using :option:`--frontend` option with "api"
|
||||
parameter. All requests which come from this frontend address, will
|
||||
be treated as API request.
|
||||
|
||||
The response is normally JSON dictionary, and at least includes the
|
||||
following keys:
|
||||
|
||||
status
|
||||
The status of the request processing. The following values are
|
||||
defined:
|
||||
|
||||
Success
|
||||
The request was successful.
|
||||
|
||||
Failure
|
||||
The request was failed. No change has been made.
|
||||
|
||||
code
|
||||
HTTP status code
|
||||
|
||||
We wrote "normally", since nghttpx may return ordinal HTML response in
|
||||
some cases where the error has occurred before reaching API endpoint
|
||||
(e.g., header field is too large).
|
||||
|
||||
The following section describes available API endpoints.
|
||||
|
||||
PUT /api/v1beta1/backendconfig
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
This API replaces the current backend server settings with the
|
||||
requested ones. The request method should be PUT, but POST is also
|
||||
acceptable. The request body must be nghttpx configuration file
|
||||
format. For configuration file format, see `FILES`_ section. The
|
||||
line separator inside the request body must be single LF (0x0A).
|
||||
Currently, only :option:`backend <--backend>` option is parsed, the
|
||||
others are simply ignored. The semantics of this API is replace the
|
||||
current backend with the backend options in request body. Describe
|
||||
the desired set of backend severs, and nghttpx makes it happen. If
|
||||
there is no :option:`backend <--backend>` option is found in request
|
||||
body, the current set of backend is replaced with the :option:`backend
|
||||
<--backend>` option's default value, which is ``127.0.0.1,80``.
|
||||
|
||||
The replacement is done instantly without breaking existing
|
||||
connections or requests. It also avoids any process creation as is
|
||||
the case with hot swapping with signals.
|
||||
|
||||
The one limitation is that only numeric IP address is allowd in
|
||||
:option:`backend <--backend>` in request body unless "dns" parameter
|
||||
is used while non numeric hostname is allowed in command-line or
|
||||
configuration file is read using :option:`--conf`.
|
||||
|
||||
SEE ALSO
|
||||
--------
|
||||
|
||||
|
||||
@@ -1,6 +1,79 @@
|
||||
Programmers' Guide
|
||||
==================
|
||||
|
||||
Architecture
|
||||
------------
|
||||
|
||||
The most notable point in nghttp2 library architecture is it does not
|
||||
perform any I/O. nghttp2 only performs HTTP/2 protocol stuff based on
|
||||
input byte strings. It will calls callback functions set by
|
||||
applications while processing input. The output of nghttp2 is just
|
||||
byte string. An application is responsible to send these output to
|
||||
the remote peer. The callback functions may be called while producing
|
||||
output.
|
||||
|
||||
Not doing I/O makes embedding nghttp2 library in the existing code
|
||||
base very easy. Usually, the existing applications have its own I/O
|
||||
event loops. It is very hard to use nghttp2 in that situation if
|
||||
nghttp2 does its own I/O. It also makes light weight language wrapper
|
||||
for nghttp2 easy with the same reason. The down side is that an
|
||||
application author has to write more code to write complete
|
||||
application using nghttp2. This is especially true for simple "toy"
|
||||
application. For the real applications, however, this is not the
|
||||
case. This is because you probably want to support HTTP/1 which
|
||||
nghttp2 does not provide, and to do that, you will need to write your
|
||||
own HTTP/1 stack or use existing third-party library, and bind them
|
||||
together with nghttp2 and I/O event loop. In this point, not
|
||||
performing I/O in nghttp2 has more point than doing it.
|
||||
|
||||
The primary object that an application uses is :type:`nghttp2_session`
|
||||
object, which is opaque struct and its details are hidden in order to
|
||||
ensure the upgrading its internal architecture without breaking the
|
||||
backward compatibility. An application can set callbacks to
|
||||
:type:`nghttp2_session` object through the dedicated object and
|
||||
functions, and it also interacts with it via many API function calls.
|
||||
|
||||
An application can create as many :type:`nghttp2_session` object as it
|
||||
wants. But single :type:`nghttp2_session` object must be used by a
|
||||
single thread at the same time. This is not so hard to enforce since
|
||||
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.
|
||||
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.
|
||||
|
||||
To get output from :type:`nghttp2_session` object, one can use
|
||||
`nghttp2_session_send()` or `nghttp2_session_mem_send()`. 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
|
||||
`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()`
|
||||
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()`.
|
||||
|
||||
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
|
||||
calls for this: `nghttp2_session_want_read()` and
|
||||
`nghttp2_session_want_write()`. If they both return 0, application
|
||||
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_want_write()` does not take into account the
|
||||
transmission of the buffered data outside of :type:`nghttp2_session`.
|
||||
|
||||
Includes
|
||||
--------
|
||||
|
||||
@@ -100,6 +173,308 @@ parsed as 64 bit signed integer. The sum of data length in the
|
||||
following DATA frames must match with the number in "Content-Length"
|
||||
header field if it is present (this does not include padding bytes).
|
||||
|
||||
RFC 7230 says that server must not send "Content-Length" in any
|
||||
response with 1xx, and 204 status code. It also says that
|
||||
"Content-Length" is not allowed in any response with 200 status code
|
||||
to a CONNECT request. nghttp2 enforces them as well.
|
||||
|
||||
Any deviation results in stream error of type PROTOCOL_ERROR. If
|
||||
error is found in PUSH_PROMISE frame, stream error is raised against
|
||||
promised stream.
|
||||
|
||||
The order of transmission of the HTTP/2 frames
|
||||
----------------------------------------------
|
||||
|
||||
This section describes the internals of libnghttp2 about the
|
||||
scheduling of transmission of HTTP/2 frames. This is pretty much
|
||||
internal stuff, so the details could change in the future versions of
|
||||
the library.
|
||||
|
||||
libnghttp2 categorizes HTTP/2 frames into 4 categories: urgent,
|
||||
regular, syn_stream, and data in the order of higher priority.
|
||||
|
||||
The urgent category includes PING and SETTINGS. They are sent with
|
||||
highest priority. The order inside the category is FIFO.
|
||||
|
||||
The regular category includes frames other than PING, SETTINGS, DATA,
|
||||
and HEADERS which does not create stream (which counts toward
|
||||
concurrent stream limit). The order inside the category is FIFO.
|
||||
|
||||
The syn_stream category includes HEADERS frame which creates stream,
|
||||
that counts toward the concurrent stream limit.
|
||||
|
||||
The data category includes DATA frame, and the scheduling among DATA
|
||||
frames are determined by HTTP/2 dependency tree.
|
||||
|
||||
If the application wants to send frames in the specific order, and the
|
||||
default transmission order does not fit, it has to schedule frames by
|
||||
itself using the callbacks (e.g.,
|
||||
:type:`nghttp2_on_frame_send_callback`).
|
||||
|
||||
RST_STREAM has special side effect when it is submitted by
|
||||
`nghttp2_submit_rst_stream()`. It cancels all pending HEADERS and
|
||||
DATA frames whose stream ID matches the one in the RST_STREAM frame.
|
||||
This may cause unexpected behaviour for the application in some cases.
|
||||
For example, suppose that application wants to send RST_STREAM after
|
||||
sending response HEADERS and DATA. Because of the reason we mentioned
|
||||
above, the following code does not work:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
nghttp2_submit_response(...)
|
||||
nghttp2_submit_rst_stream(...)
|
||||
|
||||
RST_STREAM cancels HEADERS (and DATA), and just RST_STREAM is sent.
|
||||
The correct way is use :type:`nghttp2_on_frame_send_callback`, and
|
||||
after HEADERS and DATA frames are sent, issue
|
||||
`nghttp2_submit_rst_stream()`. FYI,
|
||||
:type:`nghttp2_on_frame_not_send_callback` tells you why frames are
|
||||
not sent.
|
||||
|
||||
Implement user defined HTTP/2 non-critical extensions
|
||||
-----------------------------------------------------
|
||||
|
||||
As of nghttp2 v1.8.0, we have added HTTP/2 non-critical extension
|
||||
framework, which lets application send and receive user defined custom
|
||||
HTTP/2 non-critical extension frames. nghttp2 also offers built-in
|
||||
functionality to send and receive official HTTP/2 extension frames
|
||||
(e.g., ALTSVC frame). For these built-in handler, refer to the next
|
||||
section.
|
||||
|
||||
To send extension frame, use `nghttp2_submit_extension()`, and
|
||||
implement :type:`nghttp2_pack_extension_callback`. The callback
|
||||
implements how to encode data into wire format. The callback must be
|
||||
set to :type:`nghttp2_session_callbacks` using
|
||||
`nghttp2_session_callbacks_set_pack_extension_callback()`.
|
||||
|
||||
For example, we will illustrate how to send `ALTSVC
|
||||
<https://tools.ietf.org/html/draft-ietf-httpbis-alt-svc-14>`_ frame.
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
typedef struct {
|
||||
const char *origin;
|
||||
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) {
|
||||
const alt_svc *altsvc = (const alt_svc *)frame->ext.payload;
|
||||
size_t originlen = strlen(altsvc->origin);
|
||||
size_t fieldlen = strlen(altsvc->field);
|
||||
|
||||
uint8_t *p;
|
||||
|
||||
if (len < 2 + originlen + fieldlen || originlen > 0xffff) {
|
||||
return NGHTTP2_ERR_CANCEL;
|
||||
}
|
||||
|
||||
p = buf;
|
||||
*p++ = originlen >> 8;
|
||||
*p++ = originlen & 0xff;
|
||||
memcpy(p, altsvc->origin, originlen);
|
||||
p += originlen;
|
||||
memcpy(p, altsvc->field, fieldlen);
|
||||
p += fieldlen;
|
||||
|
||||
return p - buf;
|
||||
}
|
||||
|
||||
This implements :type:`nghttp2_pack_extension_callback`. We have to
|
||||
set this callback to :type:`nghttp2_session_callbacks`:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
nghttp2_session_callbacks_set_pack_extension_callback(
|
||||
callbacks, pack_extension_callback);
|
||||
|
||||
To send ALTSVC frame, call `nghttp2_submit_extension()`:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
static const alt_svc altsvc = {"example.com", "h2=\":8000\""};
|
||||
|
||||
nghttp2_submit_extension(session, 0xa, NGHTTP2_FLAG_NONE, 0,
|
||||
(void *)&altsvc);
|
||||
|
||||
Notice that ALTSVC is use frame type ``0xa``.
|
||||
|
||||
To receive extension frames, implement 2 callbacks:
|
||||
:type:`nghttp2_unpack_extension_callback` and
|
||||
:type:`nghttp2_on_extension_chunk_recv_callback`.
|
||||
:type:`nghttp2_unpack_extension_callback` implements the way how to
|
||||
decode wire format. :type:`nghttp2_on_extension_chunk_recv_callback`
|
||||
implements how to buffer the incoming extension payload. These
|
||||
callbacks must be set using
|
||||
`nghttp2_session_callbacks_set_unpack_extension_callback()` and
|
||||
`nghttp2_session_callbacks_set_on_extension_chunk_recv_callback()`
|
||||
respectively. The application also must tell the library which
|
||||
extension frame type it is willing to receive using
|
||||
`nghttp2_option_set_user_recv_extension_type()`. Note that the
|
||||
application has to create :type:`nghttp2_option` object for that
|
||||
purpose, and initialize session with it.
|
||||
|
||||
We use ALTSVC again to illustrate how to receive extension frames. We
|
||||
use different ``alt_svc`` struct than the previous one.
|
||||
|
||||
First implement 2 callbacks. We store incoming ALTSVC payload to
|
||||
global variable ``altsvc_buffer``. Don't do this in production code
|
||||
since this is not thread safe:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
typedef struct {
|
||||
const uint8_t *origin;
|
||||
size_t originlen;
|
||||
const uint8_t *field;
|
||||
size_t fieldlen;
|
||||
} alt_svc;
|
||||
|
||||
/* buffers incoming ALTSVC payload */
|
||||
uint8_t altsvc_buffer[4096];
|
||||
/* The length of byte written to altsvc_buffer */
|
||||
size_t altsvc_bufferlen = 0;
|
||||
|
||||
int on_extension_chunk_recv_callback(nghttp2_session *session,
|
||||
const nghttp2_frame_hd *hd,
|
||||
const uint8_t *data, size_t len,
|
||||
void *user_data) {
|
||||
if (sizeof(altsvc_buffer) < altsvc_bufferlen + len) {
|
||||
altsvc_bufferlen = 0;
|
||||
return NGHTTP2_ERR_CANCEL;
|
||||
}
|
||||
|
||||
memcpy(altsvc_buffer + altsvc_bufferlen, data, len);
|
||||
altsvc_bufferlen += len;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int unpack_extension_callback(nghttp2_session *session, void **payload,
|
||||
const nghttp2_frame_hd *hd, void *user_data) {
|
||||
uint8_t *origin, *field;
|
||||
size_t originlen, fieldlen;
|
||||
uint8_t *p, *end;
|
||||
alt_svc *altsvc;
|
||||
|
||||
if (altsvc_bufferlen < 2) {
|
||||
altsvc_bufferlen = 0;
|
||||
return NGHTTP2_ERR_CANCEL;
|
||||
}
|
||||
|
||||
p = altsvc_buffer;
|
||||
end = altsvc_buffer + altsvc_bufferlen;
|
||||
|
||||
originlen = ((*p) << 8) + *(p + 1);
|
||||
p += 2;
|
||||
|
||||
if (p + originlen > end) {
|
||||
altsvc_bufferlen = 0;
|
||||
return NGHTTP2_ERR_CANCEL;
|
||||
}
|
||||
|
||||
origin = p;
|
||||
field = p + originlen;
|
||||
fieldlen = end - field;
|
||||
|
||||
altsvc = (alt_svc *)malloc(sizeof(alt_svc));
|
||||
altsvc->origin = origin;
|
||||
altsvc->originlen = originlen;
|
||||
altsvc->field = field;
|
||||
altsvc->fieldlen = fieldlen;
|
||||
|
||||
*payload = altsvc;
|
||||
|
||||
altsvc_bufferlen = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Set these callbacks to :type:`nghttp2_session_callbacks`:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
nghttp2_session_callbacks_set_on_extension_chunk_recv_callback(
|
||||
callbacks, on_extension_chunk_recv_callback);
|
||||
|
||||
nghttp2_session_callbacks_set_unpack_extension_callback(
|
||||
callbacks, unpack_extension_callback);
|
||||
|
||||
|
||||
In ``unpack_extension_callback`` above, we set unpacked ``alt_svc``
|
||||
object to ``*payload``. nghttp2 library then, calls
|
||||
:type:`nghttp2_on_frame_recv_callback`, and ``*payload`` will be
|
||||
available as ``frame->ext.payload``:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
int on_frame_recv_callback(nghttp2_session *session,
|
||||
const nghttp2_frame *frame, void *user_data) {
|
||||
|
||||
switch (frame->hd.type) {
|
||||
...
|
||||
case 0xa: {
|
||||
alt_svc *altsvc = (alt_svc *)frame->ext.payload;
|
||||
fprintf(stderr, "ALTSVC frame received\n");
|
||||
fprintf(stderr, " origin: %.*s\n", (int)altsvc->originlen, altsvc->origin);
|
||||
fprintf(stderr, " field : %.*s\n", (int)altsvc->fieldlen, altsvc->field);
|
||||
free(altsvc);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Finally, application should set the extension frame types it is
|
||||
willing to receive:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
nghttp2_option_set_user_recv_extension_type(option, 0xa);
|
||||
|
||||
The :type:`nghttp2_option` must be set to :type:`nghttp2_session` on
|
||||
its creation:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
nghttp2_session_client_new2(&session, callbacks, user_data, option);
|
||||
|
||||
How to use built-in HTTP/2 extension frame handlers
|
||||
---------------------------------------------------
|
||||
|
||||
In the previous section, we talked about the user defined HTTP/2
|
||||
extension frames. In this section, we talk about HTTP/2 extension
|
||||
frame support built into nghttp2 library.
|
||||
|
||||
As of this writing, nghttp2 supports ALTSVC extension frame. To send
|
||||
ALTSVC frame, use `nghttp2_submit_altsvc()` function.
|
||||
|
||||
To receive ALTSVC frame through built-in functionality, application
|
||||
has to use `nghttp2_option_set_builtin_recv_extension_type()` to
|
||||
indicate the willingness of receiving ALTSVC frame:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
nghttp2_option_set_builtin_recv_extension_type(option, NGHTTP2_ALTSVC);
|
||||
|
||||
This is very similar to the case when we used to receive user defined
|
||||
frames.
|
||||
|
||||
If the same frame type is set using
|
||||
`nghttp2_option_set_builtin_recv_extension_type()` and
|
||||
`nghttp2_option_set_user_recv_extension_type()`, the latter takes
|
||||
precedence. Application can implement its own frame handler rather
|
||||
than using built-in handler.
|
||||
|
||||
The :type:`nghttp2_option` must be set to :type:`nghttp2_session` on
|
||||
its creation, like so:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
nghttp2_session_client_new2(&session, callbacks, user_data, option);
|
||||
|
||||
When ALTSVC is received, :type:`nghttp2_on_frame_recv_callback` will
|
||||
be called as usual.
|
||||
|
||||
|
||||
@@ -17,24 +17,22 @@ installed in the following way. First, let us introduce
|
||||
under ``$ANDROID_HOME/toolchain``. An user can freely choose the path
|
||||
for ``ANDROID_HOME``. For example, to install toolchain under
|
||||
``$ANDROID_HOME/toolchain``, do this in the the directory where NDK is
|
||||
unpacked::
|
||||
unpacked:
|
||||
|
||||
$ build/tools/make-standalone-toolchain.sh \
|
||||
--install-dir=$ANDROID_HOME/toolchain \
|
||||
--toolchain=arm-linux-androideabi-4.9 \
|
||||
--llvm-version=3.5 \
|
||||
--platform=android-16
|
||||
.. code-block:: text
|
||||
|
||||
The additional flag ``--system=linux-x86_64`` may be required if you
|
||||
are using x86_64 system.
|
||||
$ build/tools/make_standalone_toolchain.py \
|
||||
--arch arm --api 16 --stl gnustl \
|
||||
--install-dir $ANDROID_HOME/toolchain
|
||||
|
||||
The platform level is not important here because we don't use Android
|
||||
specific C/C++ API.
|
||||
The API level (``--api``) is not important here because we don't use
|
||||
Android specific C/C++ API.
|
||||
|
||||
The dependent libraries, such as OpenSSL and libev should be built
|
||||
with the toolchain and installed under ``$ANDROID_HOME/usr/local``.
|
||||
We recommend to build these libraries as static library to make the
|
||||
deployment easier. libxml2 support is currently disabled.
|
||||
The dependent libraries, such as OpenSSL, libev, and c-ares should be
|
||||
built with the toolchain and installed under
|
||||
``$ANDROID_HOME/usr/local``. We recommend to build these libraries as
|
||||
static library to make the deployment easier. libxml2 support is
|
||||
currently disabled.
|
||||
|
||||
Although zlib comes with Android NDK, it seems not to be a part of
|
||||
public API, so we have to built it for our own. That also provides us
|
||||
@@ -45,7 +43,9 @@ spdylay as well.
|
||||
|
||||
Before running ``android-config`` and ``android-make``,
|
||||
``ANDROID_HOME`` environment variable must be set to point to the
|
||||
correct path. Also add ``$ANDROID_HOME/toolchain/bin`` to ``PATH``::
|
||||
correct path. Also add ``$ANDROID_HOME/toolchain/bin`` to ``PATH``:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
$ export PATH=$PATH:$ANDROID_HOME/toolchain/bin
|
||||
|
||||
@@ -97,6 +97,26 @@ patch, to configure libev, use the following script:
|
||||
|
||||
And run ``make install`` to build and install.
|
||||
|
||||
To configure c-ares, use the following script:
|
||||
|
||||
.. code-block:: sh
|
||||
|
||||
#!/bin/sh -e
|
||||
|
||||
if [ -z "$ANDROID_HOME" ]; then
|
||||
echo 'No $ANDROID_HOME specified.'
|
||||
exit 1
|
||||
fi
|
||||
PREFIX=$ANDROID_HOME/usr/local
|
||||
TOOLCHAIN=$ANDROID_HOME/toolchain
|
||||
PATH=$TOOLCHAIN/bin:$PATH
|
||||
|
||||
./configure \
|
||||
--host=arm-linux-androideabi \
|
||||
--build=`dpkg-architecture -qDEB_BUILD_GNU_TYPE` \
|
||||
--prefix=$PREFIX \
|
||||
--disable-shared
|
||||
|
||||
To configure zlib, use the following script:
|
||||
|
||||
.. code-block:: sh
|
||||
@@ -133,24 +153,24 @@ To configure spdylay, use the following script:
|
||||
#!/bin/sh -e
|
||||
|
||||
if [ -z "$ANDROID_HOME" ]; then
|
||||
echo 'No $ANDROID_HOME specified.'
|
||||
exit 1
|
||||
echo 'No $ANDROID_HOME specified.'
|
||||
exit 1
|
||||
fi
|
||||
PREFIX=$ANDROID_HOME/usr/local
|
||||
TOOLCHAIN=$ANDROID_HOME/toolchain
|
||||
PATH=$TOOLCHAIN/bin:$PATH
|
||||
|
||||
./configure \
|
||||
--disable-shared \
|
||||
--host=arm-linux-androideabi \
|
||||
--build=`dpkg-architecture -qDEB_BUILD_GNU_TYPE` \
|
||||
--prefix=$PREFIX \
|
||||
--without-libxml2 \
|
||||
--disable-src \
|
||||
--disable-examples \
|
||||
CPPFLAGS="-I$PREFIX/include" \
|
||||
PKG_CONFIG_LIBDIR="$PREFIX/lib/pkgconfig" \
|
||||
LDFLAGS="-L$PREFIX/lib"
|
||||
--disable-shared \
|
||||
--host=arm-linux-androideabi \
|
||||
--build=`dpkg-architecture -qDEB_BUILD_GNU_TYPE` \
|
||||
--prefix=$PREFIX \
|
||||
--without-libxml2 \
|
||||
--disable-src \
|
||||
--disable-examples \
|
||||
CPPFLAGS="-I$PREFIX/include" \
|
||||
PKG_CONFIG_LIBDIR="$PREFIX/lib/pkgconfig" \
|
||||
LDFLAGS="-L$PREFIX/lib"
|
||||
|
||||
And run ``make install`` to build and install.
|
||||
|
||||
@@ -159,6 +179,8 @@ then ``android-make`` to compile nghttp2 source files.
|
||||
|
||||
If all went well, application binaries, such as nghttpx, are created
|
||||
under src directory. Strip debugging information from the binary
|
||||
using the following command::
|
||||
using the following command:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
$ arm-linux-androideabi-strip src/nghttpx
|
||||
|
||||
@@ -27,7 +27,7 @@ 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 which comes with
|
||||
clang-3.6.
|
||||
clang-3.9.
|
||||
|
||||
To detect any violation to the coding style, we recommend to setup git
|
||||
pre-commit hook to check coding style of the changes you introduced.
|
||||
@@ -35,7 +35,7 @@ The pre-commit file is located at the root directory. Copy it under
|
||||
.git/hooks and make sure that it is executable. The pre-commit script
|
||||
uses clang-format-diff.py to detect any style errors. If it is not in
|
||||
your PATH or it exists under different name (e.g.,
|
||||
clang-format-diff-3.6 in debian), either add it to PATH variable or
|
||||
clang-format-diff-3.9 in debian), either add it to PATH variable or
|
||||
add git option ``clangformatdiff.binary`` to point to the script.
|
||||
|
||||
For emacs users, integrating clang-format to emacs is very easy.
|
||||
|
||||
@@ -1,33 +1,43 @@
|
||||
.. program:: h2load
|
||||
|
||||
h2load - HTTP/2 benchmarking tool - HOW-TO
|
||||
==========================================
|
||||
|
||||
h2load is benchmarking tool for HTTP/2 and HTTP/1.1. If built with
|
||||
spdylay (http://tatsuhiro-t.github.io/spdylay/) library, it also
|
||||
supports SPDY protocol. It supports SSL/TLS and clear text for all
|
||||
supported protocols.
|
||||
:doc:`h2load.1` is benchmarking tool for HTTP/2 and HTTP/1.1. If
|
||||
built with spdylay (http://tatsuhiro-t.github.io/spdylay/) library, it
|
||||
also supports SPDY protocol. It supports SSL/TLS and clear text for
|
||||
all supported protocols.
|
||||
|
||||
Compiling from source
|
||||
---------------------
|
||||
|
||||
h2load is compiled alongside nghttp2 and requires that the
|
||||
``--enable-apps`` flag is passed to ``./configure`` and `required
|
||||
dependencies <https://github.com/nghttp2/nghttp2#requirements>`_ are
|
||||
available during compilation. For details on compiling, see `nghttp2:
|
||||
Building from Git
|
||||
<https://github.com/nghttp2/nghttp2#building-from-git>`_.
|
||||
|
||||
Basic Usage
|
||||
-----------
|
||||
|
||||
In order to set benchmark settings, specify following 3 options.
|
||||
|
||||
``-n``
|
||||
:option:`-n`
|
||||
The number of total requests. Default: 1
|
||||
|
||||
``-c``
|
||||
:option:`-c`
|
||||
The number of concurrent clients. Default: 1
|
||||
|
||||
``-m``
|
||||
The max concurrent streams to issue per client.
|
||||
If ``auto`` is given, the number of given URIs is used.
|
||||
Default: ``auto``
|
||||
: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 ``--npn-list`` option. For
|
||||
You can set specific protocols in :option:`--npn-list` option. For
|
||||
cleartext connection, the default protocol is HTTP/2. To change the
|
||||
protocol in cleartext connection, use ``--no-tls-proto`` option. For
|
||||
convenience, ``--h1`` option forces HTTP/1.1 for both cleartext and
|
||||
SSL/TLS connections.
|
||||
protocol in cleartext connection, use :option:`--no-tls-proto` option.
|
||||
For convenience, :option:`--h1` option forces HTTP/1.1 for both
|
||||
cleartext and SSL/TLS connections.
|
||||
|
||||
Here is a command-line to perform benchmark to URI \https://localhost
|
||||
using total 100000 requests, 100 concurrent clients and 10 max
|
||||
@@ -62,11 +72,11 @@ benchmarking results. By default, h2load uses large enough flow
|
||||
control window, which effectively disables flow control. To adjust
|
||||
receiver flow control window size, there are following options:
|
||||
|
||||
``-w``
|
||||
:option:`-w`
|
||||
Sets the stream level initial window size to
|
||||
(2**<N>)-1. For SPDY, 2**<N> is used instead.
|
||||
|
||||
``-W``
|
||||
:option:`-W`
|
||||
Sets the connection level initial window size to
|
||||
(2**<N>)-1. For SPDY, if <N> is strictly less
|
||||
than 16, this option is ignored. Otherwise
|
||||
@@ -76,17 +86,17 @@ Multi-Threading
|
||||
---------------
|
||||
|
||||
Sometimes benchmarking client itself becomes a bottleneck. To remedy
|
||||
this situation, use ``-t`` option to specify the number of native
|
||||
this situation, use :option:`-t` option to specify the number of native
|
||||
thread to use.
|
||||
|
||||
``-t``
|
||||
:option:`-t`
|
||||
The number of native threads. Default: 1
|
||||
|
||||
Selecting protocol for clear text
|
||||
---------------------------------
|
||||
|
||||
By default, if \http:// URI is given, HTTP/2 protocol is used. To
|
||||
change the protocol to use for clear text, use ``-p`` option.
|
||||
change the protocol to use for clear text, use :option:`-p` option.
|
||||
|
||||
Multiple URIs
|
||||
-------------
|
||||
@@ -97,3 +107,12 @@ If multiple URIs are specified, they are used in round robin manner.
|
||||
|
||||
Please note that h2load uses scheme, host and port in the first URI
|
||||
and ignores those parts in the rest of the URIs.
|
||||
|
||||
UNIX domain socket
|
||||
------------------
|
||||
|
||||
To request against UNIX domain socket, use :option:`--base-uri`, and
|
||||
specify ``unix:`` followed by the path to UNIX domain socket. For
|
||||
example, if UNIX domain socket is ``/tmp/nghttpx.sock``, use
|
||||
``--base-uri=unix:/tmp/nghttpx.sock``. h2load uses scheme, host and
|
||||
port in the first URI in command-line or input file.
|
||||
|
||||
@@ -8,7 +8,8 @@ nghttp2 - HTTP/2 C Library
|
||||
|
||||
This is an implementation of Hypertext Transfer Protocol version 2.
|
||||
|
||||
The project is hosted at `github.com/tatsuhiro-t/nghttp2 <https://github.com/tatsuhiro-t/nghttp2>`_.
|
||||
The project is hosted at `github.com/nghttp2/nghttp2
|
||||
<https://github.com/nghttp2/nghttp2>`_.
|
||||
|
||||
Contents:
|
||||
|
||||
@@ -36,17 +37,18 @@ Contents:
|
||||
asio_http2_server.h
|
||||
asio_http2_client.h
|
||||
asio_http2.h
|
||||
Source <https://github.com/tatsuhiro-t/nghttp2>
|
||||
Issues <https://github.com/tatsuhiro-t/nghttp2/issues>
|
||||
Source <https://github.com/nghttp2/nghttp2>
|
||||
Issues <https://github.com/nghttp2/nghttp2/issues>
|
||||
nghttp2.org <https://nghttp2.org/>
|
||||
|
||||
Released Versions
|
||||
=================
|
||||
|
||||
https://github.com/tatsuhiro-t/nghttp2/releases
|
||||
https://github.com/nghttp2/nghttp2/releases
|
||||
|
||||
Resources
|
||||
---------
|
||||
|
||||
* HTTP/2 https://tools.ietf.org/html/rfc7540
|
||||
* HPACK https://tools.ietf.org/html/rfc7541
|
||||
* HTTP Alternative Services https://tools.ietf.org/html/rfc7838
|
||||
|
||||
@@ -1,74 +1,101 @@
|
||||
.. program:: nghttpx
|
||||
|
||||
nghttpx - HTTP/2 proxy - HOW-TO
|
||||
===============================
|
||||
|
||||
nghttpx is a proxy translating protocols between HTTP/2 and other
|
||||
protocols (e.g., HTTP/1, SPDY). It operates in several modes and each
|
||||
mode may require additional programs to work with. This article
|
||||
describes each operation mode and explains the intended use-cases. It
|
||||
also covers some useful options later.
|
||||
:doc:`nghttpx.1` is a proxy translating protocols between HTTP/2 and
|
||||
other protocols (e.g., HTTP/1, SPDY). It operates in several modes
|
||||
and each mode may require additional programs to work with. This
|
||||
article describes each operation mode and explains the intended
|
||||
use-cases. It also covers some useful options later.
|
||||
|
||||
Default mode
|
||||
------------
|
||||
|
||||
If nghttpx is invoked without any ``-s``, ``-p`` and ``--client``, it
|
||||
operates in default mode. In this mode, nghttpx frontend listens for
|
||||
HTTP/2 requests and translates them to HTTP/1 requests. Thus it works
|
||||
as reverse proxy (gateway) for HTTP/2 clients to HTTP/1 web server.
|
||||
HTTP/1 requests are also supported in frontend as a fallback. If
|
||||
nghttpx is linked with spdylay library and frontend connection is
|
||||
SSL/TLS, the frontend also supports SPDY protocol.
|
||||
If nghttpx is invoked without :option:`--http2-proxy`, it operates in
|
||||
default mode. In this mode, it works as reverse proxy (gateway) for
|
||||
both HTTP/2 and HTTP/1 clients to backend servers. This is also known
|
||||
as "HTTP/2 router". If nghttpx is linked with spdylay library and
|
||||
frontend connection is SSL/TLS, the frontend also supports SPDY
|
||||
protocol.
|
||||
|
||||
By default, this mode's 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.
|
||||
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.
|
||||
|
||||
With ``--frontend-no-tls`` option, user can turn off SSL/TLS in
|
||||
frontend connection. In this case, SPDY protocol is not available
|
||||
even if spdylay library is liked to nghttpx. HTTP/2 and HTTP/1 are
|
||||
available on the frontend and a HTTP/1 connection can be upgraded to
|
||||
HTTP/2 using HTTP Upgrade. Starting HTTP/2 connection by sending
|
||||
HTTP/2 connection preface is also supported.
|
||||
To turn off encryption on frontend connection, use ``no-tls`` keyword
|
||||
in :option:`--frontend` option. In this case, SPDY protocol is not
|
||||
available even if spdylay library is liked to nghttpx. HTTP/2 and
|
||||
HTTP/1 are available on the frontend, and an HTTP/1 connection can be
|
||||
upgraded to HTTP/2 using HTTP Upgrade. Starting HTTP/2 connection by
|
||||
sending HTTP/2 connection preface is also supported.
|
||||
|
||||
The backend is supposed to be HTTP/1 Web server. For example, to make
|
||||
nghttpx can listen on multiple frontend addresses. This is achieved
|
||||
by using multiple :option:`--frontend` options. For each frontend
|
||||
address, TLS can be enabled or disabled.
|
||||
|
||||
By default, backend connections are not encrypted. To enable TLS
|
||||
encryption on backend connections, use ``tls`` keyword in
|
||||
:option:`--backend` option. Using patterns and ``proto`` keyword in
|
||||
:option:`--backend` option, backend application protocol can be
|
||||
specified per host/request path pattern. It means that you can use
|
||||
both HTTP/2 and HTTP/1 in backend connections at the same time. Note
|
||||
that default backend protocol is HTTP/1.1. To use HTTP/2 in backend,
|
||||
you have to specify ``h2`` in ``proto`` keyword in :option:`--backend`
|
||||
explicitly.
|
||||
|
||||
The backend is supposed to be Web server. For example, to make
|
||||
nghttpx listen to encrypted HTTP/2 requests at port 8443, and a
|
||||
backend HTTP/1 web server is configured to listen to HTTP/1 request at
|
||||
port 8080 in the same host, run nghttpx command-line like this::
|
||||
backend Web server is configured to listen to HTTP request at port
|
||||
8080 in the same host, run nghttpx command-line like this:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
$ nghttpx -f0.0.0.0,8443 -b127.0.0.1,8080 /path/to/server.key /path/to/server.crt
|
||||
|
||||
Then HTTP/2 enabled client can access to the nghttpx in HTTP/2. For
|
||||
example, you can send GET request to the server using nghttp::
|
||||
example, you can send GET request to the server using nghttp:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
$ nghttp -nv https://localhost:8443/
|
||||
|
||||
HTTP/2 proxy mode
|
||||
-----------------
|
||||
|
||||
If nghttpx is invoked with ``-s`` option, it operates in HTTP/2 proxy
|
||||
mode. The supported protocols in frontend and backend connections are
|
||||
the same in `default mode`_. The difference is that this mode acts
|
||||
like forward proxy and assumes the backend is HTTP/1 proxy server
|
||||
(e.g., squid, traffic server). So HTTP/1 request must include
|
||||
absolute URI in request line.
|
||||
If nghttpx is invoked with :option:`--http2-proxy` (or its shorthand
|
||||
:option:`-s`) option, it operates in HTTP/2 proxy mode. The supported
|
||||
protocols in frontend and backend connections are the same in `default
|
||||
mode`_. The difference is that this mode acts like forward proxy and
|
||||
assumes the backend is HTTP proxy server (e.g., Squid, Apache Traffic
|
||||
Server). HTTP/1 request must include absolute URI in request line.
|
||||
|
||||
By default, frontend connection is encrypted. So this mode is also
|
||||
called secure proxy. If nghttpx is linked with spdylay, it supports
|
||||
SPDY protocols and it works as so called SPDY proxy.
|
||||
|
||||
With ``--frontend-no-tls`` option, SSL/TLS is turned off in frontend
|
||||
connection, so the connection gets insecure.
|
||||
To turn off encryption on frontend connection, use ``no-tls`` keyword
|
||||
in :option:`--frontend` option.
|
||||
|
||||
The backend must be HTTP/1 proxy server. nghttpx supports multiple
|
||||
backend server addresses. It translates incoming requests to HTTP/1
|
||||
The backend must be HTTP proxy server. nghttpx supports multiple
|
||||
backend server addresses. It translates incoming requests to HTTP
|
||||
request to backend server. The backend server performs real proxy
|
||||
work for each request, for example, dispatching requests to the origin
|
||||
server and caching contents.
|
||||
|
||||
The backend connection is not encrypted by default. To enable
|
||||
encryption, use ``tls`` keyword in :option:`--backend` option. The
|
||||
default backend protocol is HTTP/1.1. To use HTTP/2 in backend
|
||||
connection, use :option:`--backend` option, and specify ``h2`` in
|
||||
``proto`` keyword explicitly.
|
||||
|
||||
For example, to make nghttpx listen to encrypted HTTP/2 requests at
|
||||
port 8443, and a backend HTTP/1 proxy server is configured to listen
|
||||
to HTTP/1 request at port 8080 in the same host, run nghttpx
|
||||
command-line like this::
|
||||
port 8443, and a backend HTTP proxy server is configured to listen to
|
||||
HTTP/1 request at port 8080 in the same host, run nghttpx command-line
|
||||
like this:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
$ nghttpx -s -f'*,8443' -b127.0.0.1,8080 /path/to/server.key /path/to/server.crt
|
||||
|
||||
@@ -91,152 +118,78 @@ Chromium require valid certificate for secure proxy.
|
||||
For Firefox, open Preference window and select Advanced then click
|
||||
Network tab. Clicking Connection Settings button will show the
|
||||
dialog. Select "Automatic proxy configuration URL" and enter the path
|
||||
to proxy.pac file, something like this::
|
||||
to proxy.pac file, something like this:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
file:///path/to/proxy.pac
|
||||
|
||||
For Chromium, use following command-line::
|
||||
For Chromium, use following command-line:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
$ google-chrome --proxy-pac-url=file:///path/to/proxy.pac --use-npn
|
||||
|
||||
As HTTP/1 proxy server, Squid may work as out-of-box. Traffic server
|
||||
requires to be configured as forward proxy. Here is the minimum
|
||||
configuration items to edit::
|
||||
configuration items to edit:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
CONFIG proxy.config.reverse_proxy.enabled INT 0
|
||||
CONFIG proxy.config.url_remap.remap_required INT 0
|
||||
|
||||
Consult Traffic server `documentation
|
||||
<https://docs.trafficserver.apache.org/en/latest/admin/forward-proxy.en.html>`_
|
||||
<http://trafficserver.readthedocs.org/en/latest/admin-guide/configuration/transparent-forward-proxying.en.html>`_
|
||||
to know how to configure traffic server as forward proxy and its
|
||||
security implications.
|
||||
|
||||
Client mode
|
||||
-----------
|
||||
ALPN support
|
||||
------------
|
||||
|
||||
If nghttpx is invoked with ``--client`` option, it operates in client
|
||||
mode. In this mode, nghttpx listens for plain, unencrypted HTTP/2 and
|
||||
HTTP/1 requests and translates them to encrypted HTTP/2 requests to
|
||||
the backend. User cannot enable SSL/TLS in frontend connection.
|
||||
ALPN support requires OpenSSL >= 1.0.2.
|
||||
|
||||
HTTP/1 frontend connection can be upgraded to HTTP/2 using HTTP
|
||||
Upgrade. To disable SSL/TLS in backend connection, use
|
||||
``--backend-no-tls`` option.
|
||||
Disable frontend SSL/TLS
|
||||
------------------------
|
||||
|
||||
By default, the number of backend HTTP/2 connections per worker
|
||||
(thread) is determined by number of ``-b`` option. To adjust this
|
||||
value, use ``--backend-http2-connections-per-worker`` option.
|
||||
The frontend connections are encrypted with SSL/TLS by default. To
|
||||
turn off SSL/TLS, use ``no-tls`` keyword in :option:`--frontend`
|
||||
option. If this option is used, the private key and certificate are
|
||||
not required to run nghttpx.
|
||||
|
||||
The backend server is supporsed to be a HTTP/2 web server (e.g.,
|
||||
nghttpd). The one use-case of this mode is utilize existing HTTP/1
|
||||
clients to test HTTP/2 deployment. Suppose that HTTP/2 web server
|
||||
listens to port 80 without encryption. Then run nghttpx as client
|
||||
mode to access to that web server::
|
||||
Enable backend SSL/TLS
|
||||
----------------------
|
||||
|
||||
$ nghttpx --client -f127.0.0.1,8080 -b127.0.0.1,80 --backend-no-tls
|
||||
The backend connections are not encrypted by default. To enable
|
||||
SSL/TLS encryption, use ``tls`` keyword in :option:`--backend` option.
|
||||
|
||||
.. note::
|
||||
Enable SSL/TLS on memcached connection
|
||||
--------------------------------------
|
||||
|
||||
You may need ``-k`` option if HTTP/2 server enables SSL/TLS and
|
||||
its certificate is self-signed. But please note that it is
|
||||
insecure.
|
||||
By default, memcached connection is not encrypted. To enable
|
||||
encryption, use ``tls`` keyword in
|
||||
:option:`--tls-ticket-key-memcached` for TLS ticket key, and
|
||||
:option:`--tls-session-cache-memcached` for TLS session cache.
|
||||
|
||||
Then you can use curl to access HTTP/2 server via nghttpx::
|
||||
Specifying additional server certificates
|
||||
-----------------------------------------
|
||||
|
||||
$ curl http://localhost:8080/
|
||||
|
||||
Client proxy mode
|
||||
-----------------
|
||||
|
||||
If nghttpx is invoked with ``-p`` option, it operates in client proxy
|
||||
mode. This mode behaves like `client mode`_, but it works like
|
||||
forward proxy. So HTTP/1 request must include absolute URI in request
|
||||
line.
|
||||
|
||||
HTTP/1 frontend connection can be upgraded to HTTP/2 using HTTP
|
||||
Upgrade. To disable SSL/TLS in backend connection, use
|
||||
``--backend-no-tls`` option.
|
||||
|
||||
By default, the number of backend HTTP/2 connections per worker
|
||||
(thread) is determined by number of ``-b`` option. To adjust this
|
||||
value, use ``--backend-http2-connections-per-worker`` option.
|
||||
|
||||
The backend server must be a HTTP/2 proxy. You can use nghttpx in
|
||||
`HTTP/2 proxy mode`_ as backend server. The one use-case of this mode
|
||||
is utilize existing HTTP/1 clients to test HTTP/2 connections between
|
||||
2 proxies. The another use-case is use this mode to aggregate local
|
||||
HTTP/1 connections to one HTTP/2 backend encrypted connection. This
|
||||
makes HTTP/1 clients which does not support secure proxy can use
|
||||
secure HTTP/2 proxy via nghttpx client mode.
|
||||
|
||||
Suppose that HTTP/2 proxy listens to port 8443, just like we saw in
|
||||
`HTTP/2 proxy mode`_. To run nghttpx in client proxy mode to access
|
||||
that server, invoke nghttpx like this::
|
||||
|
||||
$ nghttpx -p -f127.0.0.1,8080 -b127.0.0.1,8443
|
||||
|
||||
.. note::
|
||||
|
||||
You may need ``-k`` option if HTTP/2 server's certificate is
|
||||
self-signed. But please note that it is insecure.
|
||||
|
||||
Then you can use curl to issue HTTP request via HTTP/2 proxy::
|
||||
|
||||
$ curl --http-proxy=http://localhost:8080 http://www.google.com/
|
||||
|
||||
You can configure web browser to use localhost:8080 as forward
|
||||
proxy.
|
||||
|
||||
HTTP/2 bridge mode
|
||||
------------------
|
||||
|
||||
If nghttpx is invoked with ``--http2-bridge`` option, it operates in
|
||||
HTTP/2 bridge mode. The supported protocols in frontend connections
|
||||
are the same in `default mode`_. The protocol in backend is HTTP/2
|
||||
only.
|
||||
|
||||
With ``--frontend-no-tls`` option, SSL/TLS is turned off in frontend
|
||||
connection, so the connection gets insecure. To disable SSL/TLS in
|
||||
backend connection, use ``--backend-no-tls`` option.
|
||||
|
||||
By default, the number of backend HTTP/2 connections per worker
|
||||
(thread) is determined by number of ``-b`` option. To adjust this
|
||||
value, use ``--backend-http2-connections-per-worker`` option.
|
||||
|
||||
The backend server is supporsed to be a HTTP/2 web server or HTTP/2
|
||||
proxy. If backend server is HTTP/2 proxy, use
|
||||
``--no-location-rewrite`` and ``--no-host-rewrite`` options to disable
|
||||
rewriting location, host and :authority header field.
|
||||
|
||||
The use-case of this mode is aggregate the incoming connections to one
|
||||
HTTP/2 connection. One backend HTTP/2 connection is created per
|
||||
worker (thread).
|
||||
|
||||
Disable SSL/TLS
|
||||
---------------
|
||||
|
||||
In `default mode`_, `HTTP/2 proxy mode`_ and `HTTP/2 bridge mode`_,
|
||||
frontend connections are encrypted with SSL/TLS by default. To turn
|
||||
off SSL/TLS, use ``--frontend-no-tls`` option. If this option is
|
||||
used, the private key and certificate are not required to run nghttpx.
|
||||
|
||||
In `client mode`_, `client proxy mode`_ and `HTTP/2 bridge mode`_,
|
||||
backend connections are encrypted with SSL/TLS by default. To turn
|
||||
off SSL/TLS, use ``--backend-no-tls`` option.
|
||||
nghttpx accepts additional server private key and certificate pairs
|
||||
using :option:`--subcert` option. It can be used multiple times.
|
||||
|
||||
Specifying additional CA certificate
|
||||
------------------------------------
|
||||
|
||||
By default, nghttpx tries to read CA certificate from system. But
|
||||
depending on the system you use, this may fail or is not supported.
|
||||
To specify CA certificate manually, use ``--cacert`` option. The
|
||||
specified file must be PEM format and can contain multiple
|
||||
To specify CA certificate manually, use :option:`--cacert` option.
|
||||
The specified file must be PEM format and can contain multiple
|
||||
certificates.
|
||||
|
||||
By default, nghttpx validates server's certificate. If you want to
|
||||
turn off this validation, knowing this is really insecure and what you
|
||||
are doing, you can use ``-k`` option to disable certificate
|
||||
validation.
|
||||
are doing, you can use :option:`--insecure` option to disable
|
||||
certificate validation.
|
||||
|
||||
Read/write rate limit
|
||||
---------------------
|
||||
@@ -245,9 +198,9 @@ nghttpx supports transfer rate limiting on frontend connections. You
|
||||
can do rate limit per frontend connection for reading and writing
|
||||
individually.
|
||||
|
||||
To perform rate limit for reading, use ``--read-rate`` and
|
||||
``--read-burst`` options. For writing, use ``--write-rate`` and
|
||||
``--write-burst``.
|
||||
To perform rate limit for reading, use :option:`--read-rate` and
|
||||
:option:`--read-burst` options. For writing, use
|
||||
:option:`--write-rate` and :option:`--write-burst`.
|
||||
|
||||
Please note that rate limit is performed on top of TCP and nothing to
|
||||
do with HTTP/2 flow control.
|
||||
@@ -258,17 +211,17 @@ Rewriting location header field
|
||||
nghttpx automatically rewrites location response header field if the
|
||||
following all conditions satisfy:
|
||||
|
||||
* URI in location header field is not absolute URI or is not https URI.
|
||||
* In the default mode (:option:`--http2-proxy` is not used)
|
||||
* :option:`--no-location-rewrite` is not used
|
||||
* URI in location header field is an absolute URI
|
||||
* URI in location header field includes non empty host component.
|
||||
* host (without port) in URI in location header field must match the
|
||||
host appearing in :authority or host header field.
|
||||
host appearing in ``:authority`` or ``host`` header field.
|
||||
|
||||
When rewrite happens, URI scheme and port are replaced with the ones
|
||||
used in frontend, and host is replaced with which appears in
|
||||
:authority or host request header field. :authority header field has
|
||||
precedence. If the above conditions are not met with the host value
|
||||
in :authority header field, rewrite is retried with the value in host
|
||||
header field.
|
||||
When rewrite happens, URI scheme is replaced with the ones used in
|
||||
frontend, and authority is replaced with which appears in
|
||||
``:authority``, or ``host`` request header field. ``:authority``
|
||||
header field has precedence over ``host``.
|
||||
|
||||
Hot swapping
|
||||
------------
|
||||
@@ -283,20 +236,266 @@ all existing frontend connections are done, the current process will
|
||||
exit. At this point, only new nghttpx process exists and serves
|
||||
incoming requests.
|
||||
|
||||
If you want to just reload configuration file without executing new
|
||||
binary, send SIGHUP to nghttpx master process.
|
||||
|
||||
Re-opening log files
|
||||
--------------------
|
||||
|
||||
When rotating log files, it is desirable to re-open log files after
|
||||
log rotation daemon renamed existing log files. To tell nghttpx to
|
||||
re-open log files, send USR1 signal to nghttpx process. It will
|
||||
re-open files specified by ``--accesslog-file`` and
|
||||
``--errorlog-file`` options.
|
||||
re-open files specified by :option:`--accesslog-file` and
|
||||
:option:`--errorlog-file` options.
|
||||
|
||||
Multiple frontend addresses
|
||||
---------------------------
|
||||
|
||||
nghttpx can listen on multiple frontend addresses. To specify them,
|
||||
just use :option:`--frontend` (or its shorthand :option:`-f`) option
|
||||
repeatedly. TLS can be enabled or disabled per frontend address
|
||||
basis. For example, to listen on port 443 with TLS enabled, and on
|
||||
port 80 without TLS:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
frontend=*,443
|
||||
frontend=*,80;no-tls
|
||||
|
||||
|
||||
Multiple backend addresses
|
||||
--------------------------
|
||||
|
||||
nghttpx supports multiple backend addresses. To specify them, just
|
||||
use ``-b`` option repeatedly. For example, to use backend1:8080 and
|
||||
backend2:8080, use command-line like this: ``-bbackend1,8080
|
||||
-bbackend2,8080``. For HTTP/2 backend, see also
|
||||
``--backend-http2-connections-per-worker`` option.
|
||||
use :option:`--backend` (or its shorthand :option:`-b`) option
|
||||
repeatedly. For example, to use ``192.168.0.10:8080`` and
|
||||
``192.168.0.11:8080``, use command-line like this:
|
||||
``-b192.168.0.10,8080 -b192.168.0.11,8080``. In configuration file,
|
||||
this looks like:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
backend=192.168.0.10,8080
|
||||
backend=192.168.0.11,8008
|
||||
|
||||
nghttpx can route request to different backend according to request
|
||||
host and path. For example, to route request destined to host
|
||||
``doc.example.com`` to backend server ``docserv:3000``, you can write
|
||||
like so:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
backend=docserv,3000;doc.example.com/
|
||||
|
||||
When you write this option in command-line, you should enclose
|
||||
argument with single or double quotes, since the character ``;`` has a
|
||||
special meaning in shell.
|
||||
|
||||
To route, request to request path whose prefix is ``/foo`` to backend
|
||||
server ``[::1]:8080``, you can write like so:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
backend=::1,8080;/foo
|
||||
|
||||
Of course, you can specify both host and request path at the same
|
||||
time:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
backend=192.168.0.10,8080;example.com/foo
|
||||
|
||||
We can use ``*`` in the left most position of host to achieve wildcard
|
||||
suffix match. If ``*`` is the left most character, then the remaining
|
||||
string should match the request host suffix. ``*`` must match at
|
||||
least one character. For example, ``*.example.com`` matches
|
||||
``www.example.com`` and ``dev.example.com``, and does not match
|
||||
``example.com`` and ``nghttp2.org``. The exact match (without ``*``)
|
||||
always takes precedence over wildcard match.
|
||||
|
||||
One important thing you have to remember is that we have to specify
|
||||
default routing pattern for so called "catch all" pattern. To write
|
||||
"catch all" pattern, just specify backend server address, without
|
||||
pattern.
|
||||
|
||||
Usually, host is the value of ``Host`` header field. In HTTP/2, the
|
||||
value of ``:authority`` pseudo header field is used.
|
||||
|
||||
When you write multiple backend addresses sharing the same routing
|
||||
pattern, they are used as load balancing. For example, to use 2
|
||||
servers ``serv1:3000`` and ``serv2:3000`` for request host
|
||||
``example.com`` and path ``/myservice``, you can write like so:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
backend=serv1,3000;example.com/myservice
|
||||
backend=serv2,3000;example.com/myservice
|
||||
|
||||
You can also specify backend application protocol in
|
||||
:option:`--backend` option using ``proto`` keyword after pattern.
|
||||
Utilizing this allows ngttpx to route certain request to HTTP/2, other
|
||||
requests to HTTP/1. For example, to route requests to ``/ws/`` in
|
||||
backend HTTP/1.1 connection, and use backend HTTP/2 for other
|
||||
requests, do this:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
backend=serv1,3000;/;proto=h2
|
||||
backend=serv1,3000;/ws/;proto=http/1.1
|
||||
|
||||
The default backend protocol is HTTP/1.1.
|
||||
|
||||
TLS can be enabled per pattern basis:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
backend=serv1,8443;/;proto=h2;tls
|
||||
backend=serv2,8080;/ws/;proto=http/1.1
|
||||
|
||||
In the above case, connection to serv1 will be encrypted by TLS. On
|
||||
the other hand, connection to serv2 will not be encrypted by TLS.
|
||||
|
||||
Dynamic hostname lookup
|
||||
-----------------------
|
||||
|
||||
By default, nghttpx performs backend hostname lookup at start up, or
|
||||
configuration reload, and keeps using them in its entire session. To
|
||||
make nghttpx perform hostname lookup dynamically, use ``dns``
|
||||
parameter in :option:`--backend` option, like so:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
backend=foo.example.com;;dns
|
||||
|
||||
nghttpx will cache resolved addresses for certain period of time. To
|
||||
change this cache period, use :option:`--dns-cache-timeout`.
|
||||
|
||||
Enable PROXY protocol
|
||||
---------------------
|
||||
|
||||
PROXY protocol can be enabled per frontend. In order to enable PROXY
|
||||
protocol, use ``proxyproto`` parameter in :option:`--frontend` option,
|
||||
like so:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
frontend=*,443;proxyproto
|
||||
|
||||
PSK cipher suites
|
||||
-----------------
|
||||
|
||||
nghttpx supports pre-shared key (PSK) cipher suites for both frontend
|
||||
and backend TLS connections. For frontend connection, use
|
||||
:option:`--psk-secrets` option to specify a file which contains PSK
|
||||
identity and secrets. The format of the file is
|
||||
``<identity>:<hex-secret>``, where ``<identity>`` is PSK identity, and
|
||||
``<hex-secret>`` is PSK secret in hex, like so:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
client1:9567800e065e078085c241d54a01c6c3f24b3bab71a606600f4c6ad2c134f3b9
|
||||
client2:b1376c3f8f6dcf7c886c5bdcceecd1e6f1d708622b6ddd21bda26ebd0c0bca99
|
||||
|
||||
nghttpx server accepts any of the identity and secret pairs in the
|
||||
file. The default cipher suite list does not contain PSK cipher
|
||||
suites. In order to use PSK, PSK cipher suite must be enabled by
|
||||
using :option:`--ciphers` option. The desired PSK cipher suite may be
|
||||
listed in `HTTP/2 cipher black list
|
||||
<https://tools.ietf.org/html/rfc7540#appendix-A>`_. In order to use
|
||||
such PSK cipher suite with HTTP/2, disable HTTP/2 cipher black list by
|
||||
using :option:`--no-http2-cipher-black-list` option. But you should
|
||||
understand its implications.
|
||||
|
||||
At the time of writing, even if only PSK cipher suites are specified
|
||||
in :option:`--ciphers` option, certificate and private key are still
|
||||
required.
|
||||
|
||||
For backend connection, use :option:`--client-psk-secrets` option to
|
||||
specify a file which contains single PSK identity and secret. The
|
||||
format is the same as the file used by :option:`--psk-secrets`
|
||||
described above, but only first identity and secret pair is solely
|
||||
used, like so:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
client2:b1376c3f8f6dcf7c886c5bdcceecd1e6f1d708622b6ddd21bda26ebd0c0bca99
|
||||
|
||||
The default cipher suite list does not contain PSK cipher suites. In
|
||||
order to use PSK, PSK cipher suite must be enabled by using
|
||||
:option:`--client-ciphers` option. The desired PSK cipher suite may
|
||||
be listed in `HTTP/2 cipher black list
|
||||
<https://tools.ietf.org/html/rfc7540#appendix-A>`_. In order to use
|
||||
such PSK cipher suite with HTTP/2, disable HTTP/2 cipher black list by
|
||||
using :option:`--client-no-http2-cipher-black-list` option. But you
|
||||
should understand its implications.
|
||||
|
||||
Migration from nghttpx v1.18.x or earlier
|
||||
-----------------------------------------
|
||||
|
||||
As of nghttpx v1.19.0, :option:`--ciphers` option only changes cipher
|
||||
list for frontend TLS connection. In order to change cipher list for
|
||||
backend connection, use :option:`--client-ciphers` option.
|
||||
|
||||
Similarly, :option:`--no-http2-cipher-black-list` option only disables
|
||||
HTTP/2 cipher black list for frontend connection. In order to disable
|
||||
HTTP/2 cipher black list for backend connection, use
|
||||
:option:`--client-no-http2-cipher-black-list` option.
|
||||
|
||||
``--accept-proxy-protocol`` option was deprecated. Instead, use
|
||||
``proxyproto`` parameter in :option:`--frontend` option to enable
|
||||
PROXY protocol support per frontend.
|
||||
|
||||
Migration from nghttpx v1.8.0 or earlier
|
||||
----------------------------------------
|
||||
|
||||
As of nghttpx 1.9.0, ``--frontend-no-tls`` and ``--backend-no-tls``
|
||||
have been removed.
|
||||
|
||||
To disable encryption on frontend connection, use ``no-tls`` keyword
|
||||
in :option:`--frontend` potion:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
frontend=*,3000;no-tls
|
||||
|
||||
The TLS encryption is now disabled on backend connection in all modes
|
||||
by default. To enable encryption on backend connection, use ``tls``
|
||||
keyword in :option:`--backend` option:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
backend=127.0.0.1,8080;tls
|
||||
|
||||
As of nghttpx 1.9.0, ``--http2-bridge``, ``--client`` and
|
||||
``--client-proxy`` options have been removed. These functionality can
|
||||
be used using combinations of options.
|
||||
|
||||
Use following option instead of ``--http2-bridge``:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
backend=<ADDR>,<PORT>;;proto=h2;tls
|
||||
|
||||
Use following options instead of ``--client``:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
frontend=<ADDR>,<PORT>;no-tls
|
||||
backend=<ADDR>,<PORT>;;proto=h2;tls
|
||||
|
||||
Use following options instead of ``--client-proxy``:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
http2-proxy=yes
|
||||
frontend=<ADDR>,<PORT>;no-tls
|
||||
backend=<ADDR>,<PORT>;;proto=h2;tls
|
||||
|
||||
We also removed ``--backend-http2-connections-per-worker`` option. It
|
||||
was present because previously the number of backend h2 connection was
|
||||
statically configured, and defaulted to 1. Now the number of backend
|
||||
h2 connection is increased on demand. We know the maximum number of
|
||||
concurrent streams per connection. When we push as many request as
|
||||
the maximum concurrency to the one connection, we create another new
|
||||
connection so that we can distribute load and avoid delay the request
|
||||
processing. This is done automatically without any configuration.
|
||||
|
||||
@@ -13,7 +13,7 @@ The extension module is called ``nghttp2``.
|
||||
determined by configure script. If the detected Python version is not
|
||||
what you expect, specify a path to Python executable in ``PYTHON``
|
||||
variable as an argument to configure script (e.g., ``./configure
|
||||
PYTHON=/usr/bin/python3.4``).
|
||||
PYTHON=/usr/bin/python3.5``).
|
||||
|
||||
HPACK API
|
||||
---------
|
||||
@@ -136,13 +136,15 @@ HTTP/2 servers
|
||||
|
||||
.. note::
|
||||
|
||||
We use :py:mod:`asyncio` for HTTP/2 server classes. Therefore,
|
||||
Python 3.4 or later is required to use these objects. To
|
||||
explicitly configure nghttp2 build to use Python 3.4, specify the
|
||||
``PYTHON`` variable to the path to Python 3.4 executable when
|
||||
invoking configure script like this::
|
||||
We use :py:mod:`asyncio` for HTTP/2 server classes, and ALPN.
|
||||
Therefore, Python 3.5 or later is required to use these objects.
|
||||
To explicitly configure nghttp2 build to use Python 3.5, specify
|
||||
the ``PYTHON`` variable to the path to Python 3.5 executable when
|
||||
invoking configure script like this:
|
||||
|
||||
$ ./configure PYTHON=/usr/bin/python3.4
|
||||
.. code-block:: text
|
||||
|
||||
$ ./configure PYTHON=/usr/bin/python3.5
|
||||
|
||||
.. py:class:: HTTP2Server(address, RequestHandlerClass, ssl=None)
|
||||
|
||||
|
||||
@@ -7,7 +7,9 @@ the end of this page. It also resides in the examples directory in
|
||||
the archive or repository.
|
||||
|
||||
This simple client takes a single HTTPS URI and retrieves the resource
|
||||
at the URI. The synopsis is::
|
||||
at the URI. The synopsis is:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
$ libevent-client HTTPS_URI
|
||||
|
||||
@@ -31,6 +33,17 @@ protocol the library supports::
|
||||
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()``::
|
||||
|
||||
@@ -46,9 +59,18 @@ The callback is added to the SSL_CTX object using
|
||||
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;
|
||||
}
|
||||
|
||||
Here we see ``SSL_CTX_get_alpn_protos()`` function call. We instructs
|
||||
OpenSSL to notify the server that we support h2, ALPN identifier for
|
||||
HTTP/2.
|
||||
|
||||
The example client defines a couple of structs:
|
||||
|
||||
We define and use a ``http2_session_data`` structure to store data
|
||||
@@ -124,7 +146,27 @@ underlying network socket::
|
||||
if (events & BEV_EVENT_CONNECTED) {
|
||||
int fd = bufferevent_getfd(bev);
|
||||
int val = 1;
|
||||
const unsigned char *alpn = NULL;
|
||||
unsigned int alpnlen = 0;
|
||||
SSL *ssl;
|
||||
|
||||
fprintf(stderr, "Connected\n");
|
||||
|
||||
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
|
||||
|
||||
if (alpn == NULL || alpnlen != 2 || memcmp("h2", alpn, 2) != 0) {
|
||||
fprintf(stderr, "h2 is not negotiated\n");
|
||||
delete_http2_session_data(session_data);
|
||||
return;
|
||||
}
|
||||
|
||||
setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char *)&val, sizeof(val));
|
||||
initialize_nghttp2_session(session_data);
|
||||
send_client_connection_header(session_data);
|
||||
@@ -144,6 +186,9 @@ underlying network socket::
|
||||
delete_http2_session_data(session_data);
|
||||
}
|
||||
|
||||
Here we validate that HTTP/2 is negotiated, and if not, drop
|
||||
connection.
|
||||
|
||||
For ``BEV_EVENT_EOF``, ``BEV_EVENT_ERROR``, and ``BEV_EVENT_TIMEOUT``
|
||||
events, we just simply tear down the connection.
|
||||
|
||||
|
||||
@@ -78,15 +78,16 @@ 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_hd()`::
|
||||
To inflate header data, use `nghttp2_hd_inflate_hd2()`::
|
||||
|
||||
ssize_t nghttp2_hd_inflate_hd(nghttp2_hd_inflater *inflater,
|
||||
nghttp2_nv *nv_out, int *inflate_flags,
|
||||
uint8_t *in, size_t inlen, int in_final);
|
||||
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_hd_inflate_hd()` 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.
|
||||
`nghttp2_hd_inflate_hd2()` 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.
|
||||
|
||||
The *inflater* is the inflater object initialized above. The *nv_out*
|
||||
is a pointer to a :type:`nghttp2_nv` into which one header field may
|
||||
@@ -118,11 +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.
|
||||
|
||||
It is important to note that the function may produce one or more
|
||||
header fields even if *inlen* is 0 when *in_final* is nonzero, due to
|
||||
differential encoding.
|
||||
|
||||
Example usage of `nghttp2_hd_inflate_hd()` is shown in the
|
||||
Example usage of `nghttp2_hd_inflate_hd2()` is shown in the
|
||||
`inflate_header_block()` function in `deflate.c`_.
|
||||
|
||||
Finally, to delete a :type:`nghttp2_hd_inflater` object, use
|
||||
|
||||
@@ -10,7 +10,9 @@ archive or repository.
|
||||
|
||||
This simple server takes 3 arguments: The port number to listen on,
|
||||
the path to your SSL/TLS private key file, and the path to your
|
||||
certificate file. The synopsis is::
|
||||
certificate file. The synopsis is:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
$ libevent-server PORT /path/to/server.key /path/to/server.crt
|
||||
|
||||
@@ -25,7 +27,17 @@ 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::
|
||||
object in the program's entire lifetime.
|
||||
|
||||
If you are following TLS related RFC, you know that NPN is not the
|
||||
standardized way to negotiate HTTP/2. NPN itself is not even
|
||||
published as RFC. The standard way to negotiate HTTP/2 is ALPN,
|
||||
Application-Layer Protocol Negotiation Extension, defined in `RFC 7301
|
||||
<https://tools.ietf.org/html/rfc7301>`_. The one caveat of ALPN is
|
||||
that OpenSSL >= 1.0.2 is required. We use macro to enable/disable
|
||||
ALPN support depending on OpenSSL version. In ALPN, client sends the
|
||||
list of supported application protocols, and server selects one of
|
||||
them. We provide the callback for it::
|
||||
|
||||
static unsigned char next_proto_list[256];
|
||||
static size_t next_proto_list_len;
|
||||
@@ -37,6 +49,22 @@ object in the program's entire lifetime::
|
||||
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);
|
||||
|
||||
if (rv != 1) {
|
||||
return SSL_TLSEXT_ERR_NOACK;
|
||||
}
|
||||
|
||||
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;
|
||||
EC_KEY *ecdh;
|
||||
@@ -51,6 +79,11 @@ object in the program's entire lifetime::
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -64,6 +97,11 @@ OpenSSL implementation, we just assign the pointer to the NPN buffers
|
||||
we filled in earlier. The NPN callback function is set to the
|
||||
``SSL_CTX`` object using ``SSL_CTX_set_next_protos_advertised_cb()``.
|
||||
|
||||
In ``alpn_select_proto_cb()``, we use `nghttp2_select_next_protocol()`
|
||||
to select application protocol. The `nghttp2_select_next_protocol()`
|
||||
returns 1 only if it selected h2 (ALPN identifier for HTTP/2), and out
|
||||
parameters were assigned accordingly.
|
||||
|
||||
Next, let's take a look at the main structures used by the example
|
||||
application:
|
||||
|
||||
@@ -167,11 +205,31 @@ underlying network socket::
|
||||
static void eventcb(struct bufferevent *bev _U_, short events, void *ptr) {
|
||||
http2_session_data *session_data = (http2_session_data *)ptr;
|
||||
if (events & BEV_EVENT_CONNECTED) {
|
||||
const unsigned char *alpn = NULL;
|
||||
unsigned int alpnlen = 0;
|
||||
SSL *ssl;
|
||||
|
||||
fprintf(stderr, "%s connected\n", session_data->client_addr);
|
||||
|
||||
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
|
||||
|
||||
if (alpn == NULL || alpnlen != 2 || memcmp("h2", alpn, 2) != 0) {
|
||||
fprintf(stderr, "%s h2 is not negotiated\n", session_data->client_addr);
|
||||
delete_http2_session_data(session_data);
|
||||
return;
|
||||
}
|
||||
|
||||
initialize_nghttp2_session(session_data);
|
||||
|
||||
if (send_server_connection_header(session_data) != 0) {
|
||||
if (send_server_connection_header(session_data) != 0 ||
|
||||
session_send(session_data) != 0) {
|
||||
delete_http2_session_data(session_data);
|
||||
return;
|
||||
}
|
||||
@@ -188,6 +246,9 @@ underlying network socket::
|
||||
delete_http2_session_data(session_data);
|
||||
}
|
||||
|
||||
Here we validate that HTTP/2 is negotiated, and if not, drop
|
||||
connection.
|
||||
|
||||
For the ``BEV_EVENT_EOF``, ``BEV_EVENT_ERROR``, and
|
||||
``BEV_EVENT_TIMEOUT`` events, we just simply tear down the connection.
|
||||
The ``delete_http2_session_data()`` function destroys the
|
||||
|
||||
49
examples/CMakeLists.txt
Normal file
49
examples/CMakeLists.txt
Normal file
@@ -0,0 +1,49 @@
|
||||
if(ENABLE_EXAMPLES)
|
||||
file(GLOB c_sources *.c)
|
||||
set_source_files_properties(${c_sources} PROPERTIES
|
||||
COMPILE_FLAGS "${WARNCFLAGS}")
|
||||
file(GLOB cxx_sources *.cc)
|
||||
set_source_files_properties(${cxx_sources} PROPERTIES
|
||||
COMPILE_FLAGS "${WARNCXXFLAGS} ${CXX1XCXXFLAGS}")
|
||||
|
||||
include_directories(
|
||||
${CMAKE_SOURCE_DIR}
|
||||
${CMAKE_SOURCE_DIR}/lib/includes
|
||||
${CMAKE_BINARY_DIR}/lib/includes
|
||||
${CMAKE_SOURCE_DIR}/src/includes
|
||||
${CMAKE_SOURCE_DIR}/third-party
|
||||
|
||||
${LIBEVENT_INCLUDE_DIRS}
|
||||
${OPENSSL_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
link_libraries(
|
||||
nghttp2
|
||||
${LIBEVENT_OPENSSL_LIBRARIES}
|
||||
${OPENSSL_LIBRARIES}
|
||||
${APP_LIBRARIES}
|
||||
)
|
||||
|
||||
add_executable(client client.c $<TARGET_OBJECTS:http-parser>)
|
||||
add_executable(libevent-client libevent-client.c $<TARGET_OBJECTS:http-parser>)
|
||||
add_executable(libevent-server libevent-server.c $<TARGET_OBJECTS:http-parser>)
|
||||
add_executable(deflate deflate.c $<TARGET_OBJECTS:http-parser>)
|
||||
|
||||
if(ENABLE_ASIO_LIB)
|
||||
foreach(name asio-sv asio-sv2 asio-cl asio-cl2)
|
||||
add_executable(${name} ${name}.cc $<TARGET_OBJECTS:http-parser>)
|
||||
target_include_directories(${name} PRIVATE
|
||||
${OPENSSL_INCLUDE_DIRS}
|
||||
${Boost_INCLUDE_DIRS}
|
||||
)
|
||||
target_link_libraries(${name}
|
||||
nghttp2
|
||||
nghttp2_asio
|
||||
${JEMALLOC_LIBRARIES}
|
||||
${OPENSSL_LIBRARIES}
|
||||
${Boost_LIBRARIES}
|
||||
${APP_LIBRARIES}
|
||||
)
|
||||
endforeach()
|
||||
endif()
|
||||
endif()
|
||||
@@ -21,10 +21,12 @@
|
||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
EXTRA_DIST = CMakeLists.txt
|
||||
|
||||
if ENABLE_EXAMPLES
|
||||
|
||||
AM_CFLAGS = $(WARNCFLAGS)
|
||||
AM_CXXFLAGS = $(WARNCXXFLAGS)
|
||||
AM_CXXFLAGS = $(WARNCXXFLAGS) $(CXX1XCXXFLAGS)
|
||||
AM_CPPFLAGS = \
|
||||
-I$(top_srcdir)/lib/includes \
|
||||
-I$(top_builddir)/lib/includes \
|
||||
@@ -49,14 +51,6 @@ libevent_server_SOURCES = libevent-server.c
|
||||
|
||||
deflate_SOURCES = deflate.c
|
||||
|
||||
if ENABLE_TINY_NGHTTPD
|
||||
|
||||
noinst_PROGRAMS += tiny-nghttpd
|
||||
|
||||
tiny_nghttpd_SOURCES = tiny-nghttpd.c
|
||||
|
||||
endif # ENABLE_TINY_NGHTTPD
|
||||
|
||||
if ENABLE_ASIO_LIB
|
||||
|
||||
noinst_PROGRAMS += asio-sv asio-sv2 asio-cl asio-cl2
|
||||
|
||||
@@ -66,13 +66,13 @@ enum { IO_NONE, WANT_READ, WANT_WRITE };
|
||||
|
||||
#define MAKE_NV(NAME, VALUE) \
|
||||
{ \
|
||||
(uint8_t *) NAME, (uint8_t *)VALUE, sizeof(NAME) - 1, sizeof(VALUE) - 1, \
|
||||
(uint8_t *)NAME, (uint8_t *)VALUE, sizeof(NAME) - 1, sizeof(VALUE) - 1, \
|
||||
NGHTTP2_NV_FLAG_NONE \
|
||||
}
|
||||
|
||||
#define MAKE_NV_CS(NAME, VALUE) \
|
||||
{ \
|
||||
(uint8_t *) NAME, (uint8_t *)VALUE, sizeof(NAME) - 1, strlen(VALUE), \
|
||||
(uint8_t *)NAME, (uint8_t *)VALUE, sizeof(NAME) - 1, strlen(VALUE), \
|
||||
NGHTTP2_NV_FLAG_NONE \
|
||||
}
|
||||
|
||||
@@ -219,9 +219,9 @@ static int on_frame_send_callback(nghttp2_session *session,
|
||||
const nghttp2_nv *nva = frame->headers.nva;
|
||||
printf("[INFO] C ----------------------------> S (HEADERS)\n");
|
||||
for (i = 0; i < frame->headers.nvlen; ++i) {
|
||||
fwrite(nva[i].name, nva[i].namelen, 1, stdout);
|
||||
fwrite(nva[i].name, 1, nva[i].namelen, stdout);
|
||||
printf(": ");
|
||||
fwrite(nva[i].value, nva[i].valuelen, 1, stdout);
|
||||
fwrite(nva[i].value, 1, nva[i].valuelen, stdout);
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
@@ -249,9 +249,9 @@ static int on_frame_recv_callback(nghttp2_session *session,
|
||||
if (req) {
|
||||
printf("[INFO] C <---------------------------- S (HEADERS)\n");
|
||||
for (i = 0; i < frame->headers.nvlen; ++i) {
|
||||
fwrite(nva[i].name, nva[i].namelen, 1, stdout);
|
||||
fwrite(nva[i].name, 1, nva[i].namelen, stdout);
|
||||
printf(": ");
|
||||
fwrite(nva[i].value, nva[i].valuelen, 1, stdout);
|
||||
fwrite(nva[i].value, 1, nva[i].valuelen, stdout);
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
@@ -289,8 +289,6 @@ static int on_stream_close_callback(nghttp2_session *session, int32_t stream_id,
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define MAX_OUTLEN 4096
|
||||
|
||||
/*
|
||||
* The implementation of nghttp2_on_data_chunk_recv_callback type. We
|
||||
* use this function to print the received response body.
|
||||
@@ -459,11 +457,12 @@ static void ctl_poll(struct pollfd *pollfd, struct Connection *connection) {
|
||||
static void submit_request(struct Connection *connection, struct Request *req) {
|
||||
int32_t stream_id;
|
||||
/* Make sure that the last item is NULL */
|
||||
const nghttp2_nv nva[] = {
|
||||
MAKE_NV(":method", "GET"), MAKE_NV_CS(":path", req->path),
|
||||
MAKE_NV(":scheme", "https"), MAKE_NV_CS(":authority", req->hostport),
|
||||
MAKE_NV("accept", "*/*"),
|
||||
MAKE_NV("user-agent", "nghttp2/" NGHTTP2_VERSION)};
|
||||
const nghttp2_nv nva[] = {MAKE_NV(":method", "GET"),
|
||||
MAKE_NV_CS(":path", req->path),
|
||||
MAKE_NV(":scheme", "https"),
|
||||
MAKE_NV_CS(":authority", req->hostport),
|
||||
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);
|
||||
@@ -564,7 +563,11 @@ static void fetch_uri(const struct URI *uri) {
|
||||
diec("nghttp2_session_client_new", rv);
|
||||
}
|
||||
|
||||
nghttp2_submit_settings(connection.session, NGHTTP2_FLAG_NONE, NULL, 0);
|
||||
rv = nghttp2_submit_settings(connection.session, NGHTTP2_FLAG_NONE, NULL, 0);
|
||||
|
||||
if (rv != 0) {
|
||||
diec("nghttp2_submit_settings", rv);
|
||||
}
|
||||
|
||||
/* Submit the HTTP request to the outbound queue. */
|
||||
submit_request(&connection, &req);
|
||||
@@ -693,9 +696,6 @@ int main(int argc, char **argv) {
|
||||
act.sa_handler = SIG_IGN;
|
||||
sigaction(SIGPIPE, &act, 0);
|
||||
|
||||
#ifndef OPENSSL_IS_BORINGSSL
|
||||
OPENSSL_config(NULL);
|
||||
#endif /* OPENSSL_IS_BORINGSSL */
|
||||
SSL_load_error_strings();
|
||||
SSL_library_init();
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
|
||||
#define MAKE_NV(K, V) \
|
||||
{ \
|
||||
(uint8_t *) K, (uint8_t *)V, sizeof(K) - 1, sizeof(V) - 1, \
|
||||
(uint8_t *)K, (uint8_t *)V, sizeof(K) - 1, sizeof(V) - 1, \
|
||||
NGHTTP2_NV_FLAG_NONE \
|
||||
}
|
||||
|
||||
@@ -109,9 +109,9 @@ static void deflate(nghttp2_hd_deflater *deflater,
|
||||
printf("Input (%zu byte(s)):\n\n", sum);
|
||||
|
||||
for (i = 0; i < nvlen; ++i) {
|
||||
fwrite(nva[i].name, nva[i].namelen, 1, stdout);
|
||||
fwrite(nva[i].name, 1, nva[i].namelen, stdout);
|
||||
printf(": ");
|
||||
fwrite(nva[i].value, nva[i].valuelen, 1, stdout);
|
||||
fwrite(nva[i].value, 1, nva[i].valuelen, stdout);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
@@ -186,9 +186,9 @@ int inflate_header_block(nghttp2_hd_inflater *inflater, uint8_t *in,
|
||||
inlen -= proclen;
|
||||
|
||||
if (inflate_flags & NGHTTP2_HD_INFLATE_EMIT) {
|
||||
fwrite(nv.name, nv.namelen, 1, stderr);
|
||||
fwrite(nv.name, 1, nv.namelen, stderr);
|
||||
fprintf(stderr, ": ");
|
||||
fwrite(nv.value, nv.valuelen, 1, stderr);
|
||||
fwrite(nv.value, 1, nv.valuelen, stderr);
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
|
||||
|
||||
@@ -179,9 +179,9 @@ static void delete_http2_session_data(http2_session_data *session_data) {
|
||||
|
||||
static void print_header(FILE *f, const uint8_t *name, size_t namelen,
|
||||
const uint8_t *value, size_t valuelen) {
|
||||
fwrite(name, namelen, 1, f);
|
||||
fwrite(name, 1, namelen, f);
|
||||
fprintf(f, ": ");
|
||||
fwrite(value, valuelen, 1, f);
|
||||
fwrite(value, 1, valuelen, f);
|
||||
fprintf(f, "\n");
|
||||
}
|
||||
|
||||
@@ -272,7 +272,7 @@ static int on_data_chunk_recv_callback(nghttp2_session *session _U_,
|
||||
void *user_data) {
|
||||
http2_session_data *session_data = (http2_session_data *)user_data;
|
||||
if (session_data->stream_data->stream_id == stream_id) {
|
||||
fwrite(data, len, 1, stdout);
|
||||
fwrite(data, 1, len, stdout);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -287,7 +287,7 @@ static int on_stream_close_callback(nghttp2_session *session, int32_t stream_id,
|
||||
int rv;
|
||||
|
||||
if (session_data->stream_data->stream_id == stream_id) {
|
||||
fprintf(stderr, "Stream %d closed with error_code=%d\n", stream_id,
|
||||
fprintf(stderr, "Stream %d closed with error_code=%u\n", stream_id,
|
||||
error_code);
|
||||
rv = nghttp2_session_terminate_session(session, NGHTTP2_NO_ERROR);
|
||||
if (rv != 0) {
|
||||
@@ -322,6 +322,11 @@ static SSL_CTX *create_ssl_ctx(void) {
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -378,13 +383,13 @@ static void send_client_connection_header(http2_session_data *session_data) {
|
||||
|
||||
#define MAKE_NV(NAME, VALUE, VALUELEN) \
|
||||
{ \
|
||||
(uint8_t *) NAME, (uint8_t *)VALUE, sizeof(NAME) - 1, VALUELEN, \
|
||||
(uint8_t *)NAME, (uint8_t *)VALUE, sizeof(NAME) - 1, VALUELEN, \
|
||||
NGHTTP2_NV_FLAG_NONE \
|
||||
}
|
||||
|
||||
#define MAKE_NV2(NAME, VALUE) \
|
||||
{ \
|
||||
(uint8_t *) NAME, (uint8_t *)VALUE, sizeof(NAME) - 1, sizeof(VALUE) - 1, \
|
||||
(uint8_t *)NAME, (uint8_t *)VALUE, sizeof(NAME) - 1, sizeof(VALUE) - 1, \
|
||||
NGHTTP2_NV_FLAG_NONE \
|
||||
}
|
||||
|
||||
@@ -475,7 +480,27 @@ static void eventcb(struct bufferevent *bev, short events, void *ptr) {
|
||||
if (events & BEV_EVENT_CONNECTED) {
|
||||
int fd = bufferevent_getfd(bev);
|
||||
int val = 1;
|
||||
const unsigned char *alpn = NULL;
|
||||
unsigned int alpnlen = 0;
|
||||
SSL *ssl;
|
||||
|
||||
fprintf(stderr, "Connected\n");
|
||||
|
||||
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
|
||||
|
||||
if (alpn == NULL || alpnlen != 2 || memcmp("h2", alpn, 2) != 0) {
|
||||
fprintf(stderr, "h2 is not negotiated\n");
|
||||
delete_http2_session_data(session_data);
|
||||
return;
|
||||
}
|
||||
|
||||
setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char *)&val, sizeof(val));
|
||||
initialize_nghttp2_session(session_data);
|
||||
send_client_connection_header(session_data);
|
||||
@@ -569,9 +594,6 @@ int main(int argc, char **argv) {
|
||||
act.sa_handler = SIG_IGN;
|
||||
sigaction(SIGPIPE, &act, NULL);
|
||||
|
||||
#ifndef OPENSSL_IS_BORINGSSL
|
||||
OPENSSL_config(NULL);
|
||||
#endif /* OPENSSL_IS_BORINGSSL */
|
||||
SSL_load_error_strings();
|
||||
SSL_library_init();
|
||||
|
||||
|
||||
@@ -79,7 +79,7 @@
|
||||
|
||||
#define MAKE_NV(NAME, VALUE) \
|
||||
{ \
|
||||
(uint8_t *) NAME, (uint8_t *)VALUE, sizeof(NAME) - 1, sizeof(VALUE) - 1, \
|
||||
(uint8_t *)NAME, (uint8_t *)VALUE, sizeof(NAME) - 1, sizeof(VALUE) - 1, \
|
||||
NGHTTP2_NV_FLAG_NONE \
|
||||
}
|
||||
|
||||
@@ -116,6 +116,22 @@ static int next_proto_cb(SSL *s _U_, const unsigned char **data,
|
||||
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);
|
||||
|
||||
if (rv != 1) {
|
||||
return SSL_TLSEXT_ERR_NOACK;
|
||||
}
|
||||
|
||||
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) {
|
||||
SSL_CTX *ssl_ctx;
|
||||
@@ -152,6 +168,11 @@ static SSL_CTX *create_ssl_ctx(const char *key_file, const char *cert_file) {
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -640,11 +661,31 @@ static void writecb(struct bufferevent *bev, void *ptr) {
|
||||
static void eventcb(struct bufferevent *bev _U_, short events, void *ptr) {
|
||||
http2_session_data *session_data = (http2_session_data *)ptr;
|
||||
if (events & BEV_EVENT_CONNECTED) {
|
||||
const unsigned char *alpn = NULL;
|
||||
unsigned int alpnlen = 0;
|
||||
SSL *ssl;
|
||||
|
||||
fprintf(stderr, "%s connected\n", session_data->client_addr);
|
||||
|
||||
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
|
||||
|
||||
if (alpn == NULL || alpnlen != 2 || memcmp("h2", alpn, 2) != 0) {
|
||||
fprintf(stderr, "%s h2 is not negotiated\n", session_data->client_addr);
|
||||
delete_http2_session_data(session_data);
|
||||
return;
|
||||
}
|
||||
|
||||
initialize_nghttp2_session(session_data);
|
||||
|
||||
if (send_server_connection_header(session_data) != 0) {
|
||||
if (send_server_connection_header(session_data) != 0 ||
|
||||
session_send(session_data) != 0) {
|
||||
delete_http2_session_data(session_data);
|
||||
return;
|
||||
}
|
||||
@@ -740,9 +781,6 @@ int main(int argc, char **argv) {
|
||||
act.sa_handler = SIG_IGN;
|
||||
sigaction(SIGPIPE, &act, NULL);
|
||||
|
||||
#ifndef OPENSSL_IS_BORINGSSL
|
||||
OPENSSL_config(NULL);
|
||||
#endif /* OPENSSL_IS_BORINGSSL */
|
||||
SSL_load_error_strings();
|
||||
SSL_library_init();
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
32
genauthoritychartbl.py
Executable file
32
genauthoritychartbl.py
Executable file
@@ -0,0 +1,32 @@
|
||||
#!/usr/bin/env python
|
||||
import sys
|
||||
|
||||
def name(i):
|
||||
if i < 0x21:
|
||||
return \
|
||||
['NUL ', 'SOH ', 'STX ', 'ETX ', 'EOT ', 'ENQ ', 'ACK ', 'BEL ',
|
||||
'BS ', 'HT ', 'LF ', 'VT ', 'FF ', 'CR ', 'SO ', 'SI ',
|
||||
'DLE ', 'DC1 ', 'DC2 ', 'DC3 ', 'DC4 ', 'NAK ', 'SYN ', 'ETB ',
|
||||
'CAN ', 'EM ', 'SUB ', 'ESC ', 'FS ', 'GS ', 'RS ', 'US ',
|
||||
'SPC '][i]
|
||||
elif i == 0x7f:
|
||||
return 'DEL '
|
||||
|
||||
for i in range(256):
|
||||
if chr(i) in [
|
||||
"-", ".", "_", "~",
|
||||
"!", "$", "&", "'", "(", ")",
|
||||
"*", "+", ",", ";", "=",
|
||||
"%", "@", ":", "[", "]"] or\
|
||||
('0' <= chr(i) and chr(i) <= '9') or \
|
||||
('A' <= chr(i) and chr(i) <= 'Z') or \
|
||||
('a' <= chr(i) and chr(i) <= 'z'):
|
||||
sys.stdout.write('1 /* {} */, '.format(chr(i)))
|
||||
elif (0x21 <= i and i < 0x7f):
|
||||
sys.stdout.write('0 /* {} */, '.format(chr(i)))
|
||||
elif 0x80 <= i:
|
||||
sys.stdout.write('0 /* {} */, '.format(hex(i)))
|
||||
else:
|
||||
sys.stdout.write('0 /* {} */, '.format(name(i)))
|
||||
if (i + 1)%4 == 0:
|
||||
sys.stdout.write('\n')
|
||||
@@ -88,7 +88,8 @@ def build_header(headers):
|
||||
c = k[-1]
|
||||
if c not in ent:
|
||||
ent[c] = []
|
||||
ent[c].append(k)
|
||||
if k not in ent[c]:
|
||||
ent[c].append(k)
|
||||
|
||||
return res
|
||||
|
||||
@@ -106,7 +107,7 @@ def gen_enum():
|
||||
|
||||
def gen_index_header():
|
||||
print '''\
|
||||
static inline int lookup_token(const uint8_t *name, size_t namelen) {
|
||||
static int32_t lookup_token(const uint8_t *name, size_t namelen) {
|
||||
switch (namelen) {'''
|
||||
b = build_header(HEADERS)
|
||||
for size in sorted(b.keys()):
|
||||
@@ -121,7 +122,7 @@ static inline int lookup_token(const uint8_t *name, size_t namelen) {
|
||||
case '{}':'''.format(c)
|
||||
for k in headers:
|
||||
print '''\
|
||||
if (lstreq("{}", name, {})) {{
|
||||
if (memeq("{}", name, {})) {{
|
||||
return {};
|
||||
}}'''.format(k[:-1], size - 1, to_enum_hd(k))
|
||||
print '''\
|
||||
|
||||
@@ -88,12 +88,11 @@ OPTIONS = [
|
||||
"fetch-ocsp-response-file",
|
||||
"ocsp-update-interval",
|
||||
"no-ocsp",
|
||||
"header-field-buffer",
|
||||
"max-header-fields",
|
||||
"include",
|
||||
"tls-ticket-key-cipher",
|
||||
"host-rewrite",
|
||||
"tls-session-cache-memcached",
|
||||
"tls-session-cache-memcached-tls",
|
||||
"tls-ticket-key-memcached",
|
||||
"tls-ticket-key-memcached-interval",
|
||||
"tls-ticket-key-memcached-max-retry",
|
||||
@@ -107,7 +106,58 @@ OPTIONS = [
|
||||
"add-forwarded",
|
||||
"strip-incoming-forwarded",
|
||||
"forwarded-by",
|
||||
"forwarded-for"
|
||||
"forwarded-for",
|
||||
"response-header-field-buffer",
|
||||
"max-response-header-fields",
|
||||
"request-header-field-buffer",
|
||||
"max-request-header-fields",
|
||||
"header-field-buffer",
|
||||
"max-header-fields",
|
||||
"no-http2-cipher-black-list",
|
||||
"backend-http1-tls",
|
||||
"tls-session-cache-memcached-cert-file",
|
||||
"tls-session-cache-memcached-private-key-file",
|
||||
"tls-session-cache-memcached-address-family",
|
||||
"tls-ticket-key-memcached-tls",
|
||||
"tls-ticket-key-memcached-cert-file",
|
||||
"tls-ticket-key-memcached-private-key-file",
|
||||
"tls-ticket-key-memcached-address-family",
|
||||
"backend-address-family",
|
||||
"frontend-http2-max-concurrent-streams",
|
||||
"backend-http2-max-concurrent-streams",
|
||||
"backend-connections-per-frontend",
|
||||
"backend-tls",
|
||||
"backend-connections-per-host",
|
||||
"error-page",
|
||||
"no-kqueue",
|
||||
"frontend-http2-settings-timeout",
|
||||
"backend-http2-settings-timeout",
|
||||
"api-max-request-body",
|
||||
"backend-max-backoff",
|
||||
"server-name",
|
||||
"no-server-rewrite",
|
||||
"frontend-http2-optimize-write-buffer-size",
|
||||
"frontend-http2-optimize-window-size",
|
||||
"frontend-http2-window-size",
|
||||
"frontend-http2-connection-window-size",
|
||||
"backend-http2-window-size",
|
||||
"backend-http2-connection-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",
|
||||
"ecdh-curves",
|
||||
"tls-sct-dir",
|
||||
"backend-connect-timeout",
|
||||
"dns-cache-timeout",
|
||||
"dns-lookup-timeout",
|
||||
"dns-max-try",
|
||||
"frontend-keep-alive-timeout",
|
||||
"psk-secrets",
|
||||
"client-psk-secrets",
|
||||
"client-no-http2-cipher-black-list",
|
||||
"client-ciphers",
|
||||
"accesslog-write-early",
|
||||
]
|
||||
|
||||
LOGVARS = [
|
||||
@@ -126,6 +176,8 @@ LOGVARS = [
|
||||
"ssl_protocol",
|
||||
"ssl_session_id",
|
||||
"ssl_session_reused",
|
||||
"backend_host",
|
||||
"backend_port",
|
||||
]
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
10
help2rst.py
10
help2rst.py
@@ -160,13 +160,15 @@ DESCRIPTION
|
||||
print(line.strip())
|
||||
|
||||
def format_text(text):
|
||||
# escape *
|
||||
if len(text) > len(arg_indent):
|
||||
text = text[:len(arg_indent) + 1] + re.sub(r'\*', r'\*', text[len(arg_indent) + 1:])
|
||||
# escape *, but don't escape * if it is used as bullet list.
|
||||
m = re.match(r'^\s*\*\s+', text)
|
||||
if m:
|
||||
text = text[:len(m.group(0))] + re.sub(r'\*', r'\*', text[len(m.group(0)):])
|
||||
else:
|
||||
text = re.sub(r'\*', r'\*', text)
|
||||
# markup option reference
|
||||
text = re.sub(r'(^|\s)(-[a-zA-Z0-9-]+)', r'\1:option:`\2`', text)
|
||||
text = re.sub(r'(^|\s)(-[a-zA-Z0-9]|--[a-zA-Z0-9-]+)',
|
||||
r'\1:option:`\2`', text)
|
||||
# sphinx does not like markup like ':option:`-f`='. We need
|
||||
# backslash between ` and =.
|
||||
text = re.sub(r'(:option:`.*?`)(\S)', r'\1\\\2', text)
|
||||
|
||||
1
integration-tests/.gitignore
vendored
1
integration-tests/.gitignore
vendored
@@ -1,2 +1,3 @@
|
||||
# generated files
|
||||
config.go
|
||||
setenv
|
||||
|
||||
48
integration-tests/CMakeLists.txt
Normal file
48
integration-tests/CMakeLists.txt
Normal file
@@ -0,0 +1,48 @@
|
||||
set(GO_FILES
|
||||
nghttpx_http1_test.go
|
||||
nghttpx_http2_test.go
|
||||
nghttpx_spdy_test.go
|
||||
server_tester.go
|
||||
)
|
||||
|
||||
# XXX unused
|
||||
set(EXTRA_DIST
|
||||
${GO_FILES}
|
||||
server.key
|
||||
server.crt
|
||||
alt-server.key
|
||||
alt-server.crt
|
||||
setenv
|
||||
req-set-header.rb
|
||||
resp-set-header.rb
|
||||
req-return.rb
|
||||
resp-return.rb
|
||||
)
|
||||
|
||||
add_custom_target(itprep
|
||||
COMMAND go get -d -v golang.org/x/net/http2
|
||||
COMMAND go get -d -v github.com/tatsuhiro-t/go-nghttp2
|
||||
COMMAND go get -d -v github.com/tatsuhiro-t/spdy
|
||||
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.
|
||||
set(GO_BUILD_FILES)
|
||||
if(NOT CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_CURRENT_BINARY_DIR)
|
||||
foreach(gofile IN LISTS GO_FILES)
|
||||
set(outfile "${CMAKE_CURRENT_BINARY_DIR}/${gofile}")
|
||||
add_custom_command(OUTPUT "${outfile}"
|
||||
COMMAND ${CMAKE_COMMAND} -E copy
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/${gofile}" "${outfile}"
|
||||
DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/${gofile}"
|
||||
)
|
||||
list(APPEND GO_BUILD_FILES "${outfile}")
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
add_custom_target(it
|
||||
COMMAND sh setenv go test -v
|
||||
DEPENDS ${GO_BUILD_FILES}
|
||||
)
|
||||
@@ -21,11 +21,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.
|
||||
|
||||
EXTRA_DIST = \
|
||||
GO_FILES = \
|
||||
nghttpx_http1_test.go \
|
||||
nghttpx_http2_test.go \
|
||||
nghttpx_spdy_test.go \
|
||||
server_tester.go \
|
||||
server_tester.go
|
||||
|
||||
EXTRA_DIST = \
|
||||
CMakeLists.txt \
|
||||
$(GO_FILES) \
|
||||
server.key \
|
||||
server.crt \
|
||||
alt-server.key \
|
||||
@@ -36,11 +40,12 @@ EXTRA_DIST = \
|
||||
req-return.rb \
|
||||
resp-return.rb
|
||||
|
||||
itprep-local:
|
||||
itprep:
|
||||
go get -d -v golang.org/x/net/http2
|
||||
go get -d -v github.com/tatsuhiro-t/go-nghttp2
|
||||
go get -d -v github.com/tatsuhiro-t/spdy
|
||||
go get -d -v golang.org/x/net/websocket
|
||||
|
||||
it-local:
|
||||
it:
|
||||
for i in $(GO_FILES); do [ -e $(builddir)/$$i ] || cp $(srcdir)/$$i $(builddir); done
|
||||
sh setenv go test -v
|
||||
|
||||
@@ -2,4 +2,5 @@ package nghttp2
|
||||
|
||||
const (
|
||||
buildDir = "@top_builddir@"
|
||||
sourceDir = "@top_srcdir@"
|
||||
)
|
||||
|
||||
@@ -3,6 +3,7 @@ package nghttp2
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"golang.org/x/net/http2/hpack"
|
||||
"golang.org/x/net/websocket"
|
||||
@@ -103,26 +104,26 @@ Content-Length: 0
|
||||
}
|
||||
}
|
||||
|
||||
// TestH1H1ConnectFailure tests that server handles the situation that
|
||||
// connection attempt to HTTP/1 backend failed.
|
||||
func TestH1H1ConnectFailure(t *testing.T) {
|
||||
st := newServerTester(nil, t, noopHandler)
|
||||
defer st.Close()
|
||||
// // TestH1H1ConnectFailure tests that server handles the situation that
|
||||
// // connection attempt to HTTP/1 backend failed.
|
||||
// func TestH1H1ConnectFailure(t *testing.T) {
|
||||
// st := newServerTester(nil, t, noopHandler)
|
||||
// defer st.Close()
|
||||
|
||||
// shutdown backend server to simulate backend connect failure
|
||||
st.ts.Close()
|
||||
// // shutdown backend server to simulate backend connect failure
|
||||
// st.ts.Close()
|
||||
|
||||
res, err := st.http1(requestParam{
|
||||
name: "TestH1H1ConnectFailure",
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("Error st.http1() = %v", err)
|
||||
}
|
||||
want := 503
|
||||
if got := res.status; got != want {
|
||||
t.Errorf("status: %v; want %v", got, want)
|
||||
}
|
||||
}
|
||||
// res, err := st.http1(requestParam{
|
||||
// name: "TestH1H1ConnectFailure",
|
||||
// })
|
||||
// if err != nil {
|
||||
// t.Fatalf("Error st.http1() = %v", err)
|
||||
// }
|
||||
// want := 503
|
||||
// if got := res.status; got != want {
|
||||
// t.Errorf("status: %v; want %v", got, want)
|
||||
// }
|
||||
// }
|
||||
|
||||
// TestH1H1GracefulShutdown tests graceful shutdown.
|
||||
func TestH1H1GracefulShutdown(t *testing.T) {
|
||||
@@ -159,8 +160,9 @@ func TestH1H1GracefulShutdown(t *testing.T) {
|
||||
}
|
||||
|
||||
want := io.EOF
|
||||
if _, err := st.conn.Read(nil); err == nil || err != want {
|
||||
t.Errorf("st.conn.Read(): %v; want %v", err, want)
|
||||
b := make([]byte, 256)
|
||||
if _, err := st.conn.Read(b); err == nil || err != want {
|
||||
t.Errorf("st.conn.Read(): %v; want %v, %v", err, want)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -531,26 +533,26 @@ func TestH1H1RespPhaseReturn(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TestH1H2ConnectFailure tests that server handles the situation that
|
||||
// connection attempt to HTTP/2 backend failed.
|
||||
func TestH1H2ConnectFailure(t *testing.T) {
|
||||
st := newServerTester([]string{"--http2-bridge"}, t, noopHandler)
|
||||
defer st.Close()
|
||||
// // TestH1H2ConnectFailure tests that server handles the situation that
|
||||
// // connection attempt to HTTP/2 backend failed.
|
||||
// func TestH1H2ConnectFailure(t *testing.T) {
|
||||
// st := newServerTester([]string{"--http2-bridge"}, t, noopHandler)
|
||||
// defer st.Close()
|
||||
|
||||
// simulate backend connect attempt failure
|
||||
st.ts.Close()
|
||||
// // simulate backend connect attempt failure
|
||||
// st.ts.Close()
|
||||
|
||||
res, err := st.http1(requestParam{
|
||||
name: "TestH1H2ConnectFailure",
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("Error st.http1() = %v", err)
|
||||
}
|
||||
want := 503
|
||||
if got := res.status; got != want {
|
||||
t.Errorf("status: %v; want %v", got, want)
|
||||
}
|
||||
}
|
||||
// res, err := st.http1(requestParam{
|
||||
// name: "TestH1H2ConnectFailure",
|
||||
// })
|
||||
// if err != nil {
|
||||
// t.Fatalf("Error st.http1() = %v", err)
|
||||
// }
|
||||
// want := 503
|
||||
// if got := res.status; got != want {
|
||||
// t.Errorf("status: %v; want %v", got, want)
|
||||
// }
|
||||
// }
|
||||
|
||||
// TestH1H2NoHost tests that server rejects request without Host
|
||||
// header field for HTTP/2 backend.
|
||||
@@ -793,3 +795,221 @@ func TestH1H2RespPhaseReturn(t *testing.T) {
|
||||
t.Errorf("body = %v; want %v", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
// TestH1H2TE tests that "te: trailers" header is forwarded to HTTP/2
|
||||
// backend server by stripping other encodings.
|
||||
func TestH1H2TE(t *testing.T) {
|
||||
st := newServerTester([]string{"--http2-bridge"}, t, func(w http.ResponseWriter, r *http.Request) {
|
||||
if got, want := r.Header.Get("te"), "trailers"; got != want {
|
||||
t.Errorf("te: %v; want %v", got, want)
|
||||
}
|
||||
})
|
||||
defer st.Close()
|
||||
|
||||
res, err := st.http1(requestParam{
|
||||
name: "TestH1H2TE",
|
||||
header: []hpack.HeaderField{
|
||||
pair("te", "foo,trailers,bar"),
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("Error st.http1() = %v", err)
|
||||
}
|
||||
if got, want := res.status, 200; got != want {
|
||||
t.Errorf("status: %v; want %v", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
// TestH1APIBackendconfig exercise backendconfig API endpoint routine
|
||||
// for successful case.
|
||||
func TestH1APIBackendconfig(t *testing.T) {
|
||||
st := newServerTesterConnectPort([]string{"-f127.0.0.1,3010;api;no-tls"}, t, func(w http.ResponseWriter, r *http.Request) {
|
||||
t.Fatalf("request should not be forwarded")
|
||||
}, 3010)
|
||||
defer st.Close()
|
||||
|
||||
res, err := st.http1(requestParam{
|
||||
name: "TestH1APIBackendconfig",
|
||||
path: "/api/v1beta1/backendconfig",
|
||||
method: "PUT",
|
||||
body: []byte(`# comment
|
||||
backend=127.0.0.1,3011
|
||||
|
||||
`),
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("Error st.http1() = %v", err)
|
||||
}
|
||||
if got, want := res.status, 200; got != want {
|
||||
t.Errorf("res.status: %v; want %v", got, want)
|
||||
}
|
||||
|
||||
var apiResp APIResponse
|
||||
err = json.Unmarshal(res.body, &apiResp)
|
||||
if err != nil {
|
||||
t.Fatalf("Error unmarshaling API response: %v", err)
|
||||
}
|
||||
if got, want := apiResp.Status, "Success"; got != want {
|
||||
t.Errorf("apiResp.Status: %v; want %v", got, want)
|
||||
}
|
||||
if got, want := apiResp.Code, 200; got != want {
|
||||
t.Errorf("apiResp.Status: %v; want %v", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
// TestH1APIBackendconfigQuery exercise backendconfig API endpoint
|
||||
// routine with query.
|
||||
func TestH1APIBackendconfigQuery(t *testing.T) {
|
||||
st := newServerTesterConnectPort([]string{"-f127.0.0.1,3010;api;no-tls"}, t, func(w http.ResponseWriter, r *http.Request) {
|
||||
t.Fatalf("request should not be forwarded")
|
||||
}, 3010)
|
||||
defer st.Close()
|
||||
|
||||
res, err := st.http1(requestParam{
|
||||
name: "TestH1APIBackendconfigQuery",
|
||||
path: "/api/v1beta1/backendconfig?foo=bar",
|
||||
method: "PUT",
|
||||
body: []byte(`# comment
|
||||
backend=127.0.0.1,3011
|
||||
|
||||
`),
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("Error st.http1() = %v", err)
|
||||
}
|
||||
if got, want := res.status, 200; got != want {
|
||||
t.Errorf("res.status: %v; want %v", got, want)
|
||||
}
|
||||
|
||||
var apiResp APIResponse
|
||||
err = json.Unmarshal(res.body, &apiResp)
|
||||
if err != nil {
|
||||
t.Fatalf("Error unmarshaling API response: %v", err)
|
||||
}
|
||||
if got, want := apiResp.Status, "Success"; got != want {
|
||||
t.Errorf("apiResp.Status: %v; want %v", got, want)
|
||||
}
|
||||
if got, want := apiResp.Code, 200; got != want {
|
||||
t.Errorf("apiResp.Status: %v; want %v", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
// TestH1APIBackendconfigBadMethod exercise backendconfig API endpoint
|
||||
// routine with bad method.
|
||||
func TestH1APIBackendconfigBadMethod(t *testing.T) {
|
||||
st := newServerTesterConnectPort([]string{"-f127.0.0.1,3010;api;no-tls"}, t, func(w http.ResponseWriter, r *http.Request) {
|
||||
t.Fatalf("request should not be forwarded")
|
||||
}, 3010)
|
||||
defer st.Close()
|
||||
|
||||
res, err := st.http1(requestParam{
|
||||
name: "TestH1APIBackendconfigBadMethod",
|
||||
path: "/api/v1beta1/backendconfig",
|
||||
method: "GET",
|
||||
body: []byte(`# comment
|
||||
backend=127.0.0.1,3011
|
||||
|
||||
`),
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("Error st.http1() = %v", err)
|
||||
}
|
||||
if got, want := res.status, 405; got != want {
|
||||
t.Errorf("res.status: %v; want %v", got, want)
|
||||
}
|
||||
|
||||
var apiResp APIResponse
|
||||
err = json.Unmarshal(res.body, &apiResp)
|
||||
if err != nil {
|
||||
t.Fatalf("Error unmarshaling API response: %v", err)
|
||||
}
|
||||
if got, want := apiResp.Status, "Failure"; got != want {
|
||||
t.Errorf("apiResp.Status: %v; want %v", got, want)
|
||||
}
|
||||
if got, want := apiResp.Code, 405; got != want {
|
||||
t.Errorf("apiResp.Status: %v; want %v", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
// TestH1APINotFound exercise backendconfig API endpoint routine when
|
||||
// API endpoint is not found.
|
||||
func TestH1APINotFound(t *testing.T) {
|
||||
st := newServerTesterConnectPort([]string{"-f127.0.0.1,3010;api;no-tls"}, t, func(w http.ResponseWriter, r *http.Request) {
|
||||
t.Fatalf("request should not be forwarded")
|
||||
}, 3010)
|
||||
defer st.Close()
|
||||
|
||||
res, err := st.http1(requestParam{
|
||||
name: "TestH1APINotFound",
|
||||
path: "/api/notfound",
|
||||
method: "GET",
|
||||
body: []byte(`# comment
|
||||
backend=127.0.0.1,3011
|
||||
|
||||
`),
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("Error st.http1() = %v", err)
|
||||
}
|
||||
if got, want := res.status, 404; got != want {
|
||||
t.Errorf("res.status: %v; want %v", got, want)
|
||||
}
|
||||
|
||||
var apiResp APIResponse
|
||||
err = json.Unmarshal(res.body, &apiResp)
|
||||
if err != nil {
|
||||
t.Fatalf("Error unmarshaling API response: %v", err)
|
||||
}
|
||||
if got, want := apiResp.Status, "Failure"; got != want {
|
||||
t.Errorf("apiResp.Status: %v; want %v", got, want)
|
||||
}
|
||||
if got, want := apiResp.Code, 404; got != want {
|
||||
t.Errorf("apiResp.Status: %v; want %v", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
// TestH1Healthmon tests health monitor endpoint.
|
||||
func TestH1Healthmon(t *testing.T) {
|
||||
st := newServerTesterConnectPort([]string{"-f127.0.0.1,3011;healthmon;no-tls"}, t, func(w http.ResponseWriter, r *http.Request) {
|
||||
t.Fatalf("request should not be forwarded")
|
||||
}, 3011)
|
||||
defer st.Close()
|
||||
|
||||
res, err := st.http1(requestParam{
|
||||
name: "TestH1Healthmon",
|
||||
path: "/alpha/bravo",
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("Error st.http1() = %v", err)
|
||||
}
|
||||
if got, want := res.status, 200; got != want {
|
||||
t.Errorf("res.status: %v; want %v", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
// TestH1ResponseBeforeRequestEnd tests the situation where response
|
||||
// ends before request body finishes.
|
||||
func TestH1ResponseBeforeRequestEnd(t *testing.T) {
|
||||
st := newServerTester([]string{"--mruby-file=" + testDir + "/req-return.rb"}, t, func(w http.ResponseWriter, r *http.Request) {
|
||||
t.Fatal("request should not be forwarded")
|
||||
})
|
||||
defer st.Close()
|
||||
|
||||
if _, err := io.WriteString(st.conn, fmt.Sprintf(`POST / HTTP/1.1
|
||||
Host: %v
|
||||
Test-Case: TestH1ResponseBeforeRequestEnd
|
||||
Content-Length: 1000000
|
||||
|
||||
`, 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)
|
||||
}
|
||||
|
||||
if got, want := resp.StatusCode, 404; got != want {
|
||||
t.Errorf("status: %v; want %v", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package nghttp2
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"golang.org/x/net/http2"
|
||||
"golang.org/x/net/http2/hpack"
|
||||
@@ -568,26 +569,26 @@ func TestH2H1InvalidRequestCL(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TestH2H1ConnectFailure tests that server handles the situation that
|
||||
// connection attempt to HTTP/1 backend failed.
|
||||
func TestH2H1ConnectFailure(t *testing.T) {
|
||||
st := newServerTester(nil, t, noopHandler)
|
||||
defer st.Close()
|
||||
// // TestH2H1ConnectFailure tests that server handles the situation that
|
||||
// // connection attempt to HTTP/1 backend failed.
|
||||
// func TestH2H1ConnectFailure(t *testing.T) {
|
||||
// st := newServerTester(nil, t, noopHandler)
|
||||
// defer st.Close()
|
||||
|
||||
// shutdown backend server to simulate backend connect failure
|
||||
st.ts.Close()
|
||||
// // shutdown backend server to simulate backend connect failure
|
||||
// st.ts.Close()
|
||||
|
||||
res, err := st.http2(requestParam{
|
||||
name: "TestH2H1ConnectFailure",
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("Error st.http2() = %v", err)
|
||||
}
|
||||
want := 503
|
||||
if got := res.status; got != want {
|
||||
t.Errorf("status: %v; want %v", got, want)
|
||||
}
|
||||
}
|
||||
// res, err := st.http2(requestParam{
|
||||
// name: "TestH2H1ConnectFailure",
|
||||
// })
|
||||
// if err != nil {
|
||||
// t.Fatalf("Error st.http2() = %v", err)
|
||||
// }
|
||||
// want := 503
|
||||
// if got := res.status; got != want {
|
||||
// t.Errorf("status: %v; want %v", got, want)
|
||||
// }
|
||||
// }
|
||||
|
||||
// TestH2H1InvalidMethod tests that server rejects invalid method with
|
||||
// 501.
|
||||
@@ -1368,6 +1369,42 @@ func TestH2H1ProxyProtocolV1InvalidID(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TestH2H1ExternalDNS tests that DNS resolution using external DNS
|
||||
// with HTTP/1 backend works.
|
||||
func TestH2H1ExternalDNS(t *testing.T) {
|
||||
st := newServerTester([]string{"--external-dns"}, t, noopHandler)
|
||||
defer st.Close()
|
||||
|
||||
res, err := st.http2(requestParam{
|
||||
name: "TestH2H1ExternalDNS",
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("Error st.http2() = %v", err)
|
||||
}
|
||||
|
||||
if got, want := res.status, 200; got != want {
|
||||
t.Errorf("status = %v; want %v", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
// TestH2H1DNS tests that DNS resolution without external DNS with
|
||||
// HTTP/1 backend works.
|
||||
func TestH2H1DNS(t *testing.T) {
|
||||
st := newServerTester([]string{"--dns"}, t, noopHandler)
|
||||
defer st.Close()
|
||||
|
||||
res, err := st.http2(requestParam{
|
||||
name: "TestH2H1DNS",
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("Error st.http2() = %v", err)
|
||||
}
|
||||
|
||||
if got, want := res.status, 200; got != want {
|
||||
t.Errorf("status = %v; want %v", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
// TestH2H1GracefulShutdown tests graceful shutdown.
|
||||
func TestH2H1GracefulShutdown(t *testing.T) {
|
||||
st := newServerTester(nil, t, noopHandler)
|
||||
@@ -1486,26 +1523,26 @@ func TestH2H2InvalidResponseCL(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TestH2H2ConnectFailure tests that server handles the situation that
|
||||
// connection attempt to HTTP/2 backend failed.
|
||||
func TestH2H2ConnectFailure(t *testing.T) {
|
||||
st := newServerTester([]string{"--http2-bridge"}, t, noopHandler)
|
||||
defer st.Close()
|
||||
// // TestH2H2ConnectFailure tests that server handles the situation that
|
||||
// // connection attempt to HTTP/2 backend failed.
|
||||
// func TestH2H2ConnectFailure(t *testing.T) {
|
||||
// st := newServerTester([]string{"--http2-bridge"}, t, noopHandler)
|
||||
// defer st.Close()
|
||||
|
||||
// simulate backend connect attempt failure
|
||||
st.ts.Close()
|
||||
// // simulate backend connect attempt failure
|
||||
// st.ts.Close()
|
||||
|
||||
res, err := st.http2(requestParam{
|
||||
name: "TestH2H2ConnectFailure",
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("Error st.http2() = %v", err)
|
||||
}
|
||||
want := 503
|
||||
if got := res.status; got != want {
|
||||
t.Errorf("status: %v; want %v", got, want)
|
||||
}
|
||||
}
|
||||
// res, err := st.http2(requestParam{
|
||||
// name: "TestH2H2ConnectFailure",
|
||||
// })
|
||||
// if err != nil {
|
||||
// t.Fatalf("Error st.http2() = %v", err)
|
||||
// }
|
||||
// want := 503
|
||||
// if got := res.status; got != want {
|
||||
// t.Errorf("status: %v; want %v", got, want)
|
||||
// }
|
||||
// }
|
||||
|
||||
// TestH2H2HostRewrite tests that server rewrites host header field
|
||||
func TestH2H2HostRewrite(t *testing.T) {
|
||||
@@ -1843,3 +1880,226 @@ func TestH2H2RespPhaseReturn(t *testing.T) {
|
||||
t.Errorf("body = %v; want %v", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
// TestH2H2ExternalDNS tests that DNS resolution using external DNS
|
||||
// with HTTP/2 backend works.
|
||||
func TestH2H2ExternalDNS(t *testing.T) {
|
||||
st := newServerTester([]string{"--http2-bridge", "--external-dns"}, t, noopHandler)
|
||||
defer st.Close()
|
||||
|
||||
res, err := st.http2(requestParam{
|
||||
name: "TestH2H2ExternalDNS",
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("Error st.http2() = %v", err)
|
||||
}
|
||||
|
||||
if got, want := res.status, 200; got != want {
|
||||
t.Errorf("status = %v; want %v", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
// TestH2H2DNS tests that DNS resolution without external DNS with
|
||||
// HTTP/2 backend works.
|
||||
func TestH2H2DNS(t *testing.T) {
|
||||
st := newServerTester([]string{"--http2-bridge", "--dns"}, t, noopHandler)
|
||||
defer st.Close()
|
||||
|
||||
res, err := st.http2(requestParam{
|
||||
name: "TestH2H2DNS",
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("Error st.http2() = %v", err)
|
||||
}
|
||||
|
||||
if got, want := res.status, 200; got != want {
|
||||
t.Errorf("status = %v; want %v", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
// TestH2APIBackendconfig exercise backendconfig API endpoint routine
|
||||
// for successful case.
|
||||
func TestH2APIBackendconfig(t *testing.T) {
|
||||
st := newServerTesterConnectPort([]string{"-f127.0.0.1,3010;api;no-tls"}, t, func(w http.ResponseWriter, r *http.Request) {
|
||||
t.Fatalf("request should not be forwarded")
|
||||
}, 3010)
|
||||
defer st.Close()
|
||||
|
||||
res, err := st.http2(requestParam{
|
||||
name: "TestH2APIBackendconfig",
|
||||
path: "/api/v1beta1/backendconfig",
|
||||
method: "PUT",
|
||||
body: []byte(`# comment
|
||||
backend=127.0.0.1,3011
|
||||
|
||||
`),
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("Error st.http2() = %v", err)
|
||||
}
|
||||
if got, want := res.status, 200; got != want {
|
||||
t.Errorf("res.status: %v; want %v", got, want)
|
||||
}
|
||||
|
||||
var apiResp APIResponse
|
||||
err = json.Unmarshal(res.body, &apiResp)
|
||||
if err != nil {
|
||||
t.Fatalf("Error unmarshaling API response: %v", err)
|
||||
}
|
||||
if got, want := apiResp.Status, "Success"; got != want {
|
||||
t.Errorf("apiResp.Status: %v; want %v", got, want)
|
||||
}
|
||||
if got, want := apiResp.Code, 200; got != want {
|
||||
t.Errorf("apiResp.Status: %v; want %v", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
// TestH2APIBackendconfigQuery exercise backendconfig API endpoint
|
||||
// routine with query.
|
||||
func TestH2APIBackendconfigQuery(t *testing.T) {
|
||||
st := newServerTesterConnectPort([]string{"-f127.0.0.1,3010;api;no-tls"}, t, func(w http.ResponseWriter, r *http.Request) {
|
||||
t.Fatalf("request should not be forwarded")
|
||||
}, 3010)
|
||||
defer st.Close()
|
||||
|
||||
res, err := st.http2(requestParam{
|
||||
name: "TestH2APIBackendconfigQuery",
|
||||
path: "/api/v1beta1/backendconfig?foo=bar",
|
||||
method: "PUT",
|
||||
body: []byte(`# comment
|
||||
backend=127.0.0.1,3011
|
||||
|
||||
`),
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("Error st.http2() = %v", err)
|
||||
}
|
||||
if got, want := res.status, 200; got != want {
|
||||
t.Errorf("res.status: %v; want %v", got, want)
|
||||
}
|
||||
|
||||
var apiResp APIResponse
|
||||
err = json.Unmarshal(res.body, &apiResp)
|
||||
if err != nil {
|
||||
t.Fatalf("Error unmarshaling API response: %v", err)
|
||||
}
|
||||
if got, want := apiResp.Status, "Success"; got != want {
|
||||
t.Errorf("apiResp.Status: %v; want %v", got, want)
|
||||
}
|
||||
if got, want := apiResp.Code, 200; got != want {
|
||||
t.Errorf("apiResp.Status: %v; want %v", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
// TestH2APIBackendconfigBadMethod exercise backendconfig API endpoint
|
||||
// routine with bad method.
|
||||
func TestH2APIBackendconfigBadMethod(t *testing.T) {
|
||||
st := newServerTesterConnectPort([]string{"-f127.0.0.1,3010;api;no-tls"}, t, func(w http.ResponseWriter, r *http.Request) {
|
||||
t.Fatalf("request should not be forwarded")
|
||||
}, 3010)
|
||||
defer st.Close()
|
||||
|
||||
res, err := st.http2(requestParam{
|
||||
name: "TestH2APIBackendconfigBadMethod",
|
||||
path: "/api/v1beta1/backendconfig",
|
||||
method: "GET",
|
||||
body: []byte(`# comment
|
||||
backend=127.0.0.1,3011
|
||||
|
||||
`),
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("Error st.http2() = %v", err)
|
||||
}
|
||||
if got, want := res.status, 405; got != want {
|
||||
t.Errorf("res.status: %v; want %v", got, want)
|
||||
}
|
||||
|
||||
var apiResp APIResponse
|
||||
err = json.Unmarshal(res.body, &apiResp)
|
||||
if err != nil {
|
||||
t.Fatalf("Error unmarshaling API response: %v", err)
|
||||
}
|
||||
if got, want := apiResp.Status, "Failure"; got != want {
|
||||
t.Errorf("apiResp.Status: %v; want %v", got, want)
|
||||
}
|
||||
if got, want := apiResp.Code, 405; got != want {
|
||||
t.Errorf("apiResp.Status: %v; want %v", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
// TestH2APINotFound exercise backendconfig API endpoint routine when
|
||||
// API endpoint is not found.
|
||||
func TestH2APINotFound(t *testing.T) {
|
||||
st := newServerTesterConnectPort([]string{"-f127.0.0.1,3010;api;no-tls"}, t, func(w http.ResponseWriter, r *http.Request) {
|
||||
t.Fatalf("request should not be forwarded")
|
||||
}, 3010)
|
||||
defer st.Close()
|
||||
|
||||
res, err := st.http2(requestParam{
|
||||
name: "TestH2APINotFound",
|
||||
path: "/api/notfound",
|
||||
method: "GET",
|
||||
body: []byte(`# comment
|
||||
backend=127.0.0.1,3011
|
||||
|
||||
`),
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("Error st.http2() = %v", err)
|
||||
}
|
||||
if got, want := res.status, 404; got != want {
|
||||
t.Errorf("res.status: %v; want %v", got, want)
|
||||
}
|
||||
|
||||
var apiResp APIResponse
|
||||
err = json.Unmarshal(res.body, &apiResp)
|
||||
if err != nil {
|
||||
t.Fatalf("Error unmarshaling API response: %v", err)
|
||||
}
|
||||
if got, want := apiResp.Status, "Failure"; got != want {
|
||||
t.Errorf("apiResp.Status: %v; want %v", got, want)
|
||||
}
|
||||
if got, want := apiResp.Code, 404; got != want {
|
||||
t.Errorf("apiResp.Status: %v; want %v", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
// TestH2Healthmon tests health monitor endpoint.
|
||||
func TestH2Healthmon(t *testing.T) {
|
||||
st := newServerTesterConnectPort([]string{"-f127.0.0.1,3011;healthmon;no-tls"}, t, func(w http.ResponseWriter, r *http.Request) {
|
||||
t.Fatalf("request should not be forwarded")
|
||||
}, 3011)
|
||||
defer st.Close()
|
||||
|
||||
res, err := st.http2(requestParam{
|
||||
name: "TestH2Healthmon",
|
||||
path: "/alpha/bravo",
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("Error st.http2() = %v", err)
|
||||
}
|
||||
if got, want := res.status, 200; got != want {
|
||||
t.Errorf("res.status: %v; want %v", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
// TestH2ResponseBeforeRequestEnd tests the situation where response
|
||||
// ends before request body finishes.
|
||||
func TestH2ResponseBeforeRequestEnd(t *testing.T) {
|
||||
st := newServerTester([]string{"--mruby-file=" + testDir + "/req-return.rb"}, t, func(w http.ResponseWriter, r *http.Request) {
|
||||
t.Fatal("request should not be forwarded")
|
||||
})
|
||||
defer st.Close()
|
||||
|
||||
res, err := st.http2(requestParam{
|
||||
name: "TestH2ResponseBeforeRequestEnd",
|
||||
noEndStream: true,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("Error st.http2() = %v", err)
|
||||
}
|
||||
if got, want := res.status, 404; got != want {
|
||||
t.Errorf("res.status: %v; want %v", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package nghttp2
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/tatsuhiro-t/spdy"
|
||||
"golang.org/x/net/http2/hpack"
|
||||
"net/http"
|
||||
@@ -384,26 +385,26 @@ func TestS3H1RespPhaseReturn(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TestS3H2ConnectFailure tests that server handles the situation that
|
||||
// connection attempt to HTTP/2 backend failed.
|
||||
func TestS3H2ConnectFailure(t *testing.T) {
|
||||
st := newServerTesterTLS([]string{"--npn-list=spdy/3.1", "--http2-bridge"}, t, noopHandler)
|
||||
defer st.Close()
|
||||
// // TestS3H2ConnectFailure tests that server handles the situation that
|
||||
// // connection attempt to HTTP/2 backend failed.
|
||||
// func TestS3H2ConnectFailure(t *testing.T) {
|
||||
// st := newServerTesterTLS([]string{"--npn-list=spdy/3.1", "--http2-bridge"}, t, noopHandler)
|
||||
// defer st.Close()
|
||||
|
||||
// simulate backend connect attempt failure
|
||||
st.ts.Close()
|
||||
// // simulate backend connect attempt failure
|
||||
// st.ts.Close()
|
||||
|
||||
res, err := st.spdy(requestParam{
|
||||
name: "TestS3H2ConnectFailure",
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("Error st.spdy() = %v", err)
|
||||
}
|
||||
want := 503
|
||||
if got := res.status; got != want {
|
||||
t.Errorf("status: %v; want %v", got, want)
|
||||
}
|
||||
}
|
||||
// res, err := st.spdy(requestParam{
|
||||
// name: "TestS3H2ConnectFailure",
|
||||
// })
|
||||
// if err != nil {
|
||||
// t.Fatalf("Error st.spdy() = %v", err)
|
||||
// }
|
||||
// want := 503
|
||||
// if got := res.status; got != want {
|
||||
// t.Errorf("status: %v; want %v", got, want)
|
||||
// }
|
||||
// }
|
||||
|
||||
// TestS3H2ReqPhaseReturn tests mruby request phase hook returns
|
||||
// custom response.
|
||||
@@ -474,3 +475,190 @@ func TestS3H2RespPhaseReturn(t *testing.T) {
|
||||
t.Errorf("body = %v; want %v", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
// TestS3APIBackendconfig exercise backendconfig API endpoint routine
|
||||
// for successful case.
|
||||
func TestS3APIBackendconfig(t *testing.T) {
|
||||
st := newServerTesterTLSConnectPort([]string{"--npn-list=spdy/3.1", "-f127.0.0.1,3010;api"}, t, func(w http.ResponseWriter, r *http.Request) {
|
||||
t.Fatalf("request should not be forwarded")
|
||||
}, 3010)
|
||||
defer st.Close()
|
||||
|
||||
res, err := st.spdy(requestParam{
|
||||
name: "TestS3APIBackendconfig",
|
||||
path: "/api/v1beta1/backendconfig",
|
||||
method: "PUT",
|
||||
body: []byte(`# comment
|
||||
backend=127.0.0.1,3011
|
||||
|
||||
`),
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("Error st.spdy() = %v", err)
|
||||
}
|
||||
if got, want := res.status, 200; got != want {
|
||||
t.Errorf("res.status: %v; want %v", got, want)
|
||||
}
|
||||
|
||||
var apiResp APIResponse
|
||||
err = json.Unmarshal(res.body, &apiResp)
|
||||
if err != nil {
|
||||
t.Fatalf("Error unmarshaling API response: %v", err)
|
||||
}
|
||||
if got, want := apiResp.Status, "Success"; got != want {
|
||||
t.Errorf("apiResp.Status: %v; want %v", got, want)
|
||||
}
|
||||
if got, want := apiResp.Code, 200; got != want {
|
||||
t.Errorf("apiResp.Status: %v; want %v", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
// TestS3APIBackendconfigQuery exercise backendconfig API endpoint
|
||||
// routine with query.
|
||||
func TestS3APIBackendconfigQuery(t *testing.T) {
|
||||
st := newServerTesterTLSConnectPort([]string{"--npn-list=spdy/3.1", "-f127.0.0.1,3010;api"}, t, func(w http.ResponseWriter, r *http.Request) {
|
||||
t.Fatalf("request should not be forwarded")
|
||||
}, 3010)
|
||||
defer st.Close()
|
||||
|
||||
res, err := st.spdy(requestParam{
|
||||
name: "TestS3APIBackendconfigQuery",
|
||||
path: "/api/v1beta1/backendconfig?foo=bar",
|
||||
method: "PUT",
|
||||
body: []byte(`# comment
|
||||
backend=127.0.0.1,3011
|
||||
|
||||
`),
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("Error st.spdy() = %v", err)
|
||||
}
|
||||
if got, want := res.status, 200; got != want {
|
||||
t.Errorf("res.status: %v; want %v", got, want)
|
||||
}
|
||||
|
||||
var apiResp APIResponse
|
||||
err = json.Unmarshal(res.body, &apiResp)
|
||||
if err != nil {
|
||||
t.Fatalf("Error unmarshaling API response: %v", err)
|
||||
}
|
||||
if got, want := apiResp.Status, "Success"; got != want {
|
||||
t.Errorf("apiResp.Status: %v; want %v", got, want)
|
||||
}
|
||||
if got, want := apiResp.Code, 200; got != want {
|
||||
t.Errorf("apiResp.Status: %v; want %v", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
// TestS3APIBackendconfigBadMethod exercise backendconfig API endpoint
|
||||
// routine with bad method.
|
||||
func TestS3APIBackendconfigBadMethod(t *testing.T) {
|
||||
st := newServerTesterTLSConnectPort([]string{"--npn-list=spdy/3.1", "-f127.0.0.1,3010;api"}, t, func(w http.ResponseWriter, r *http.Request) {
|
||||
t.Fatalf("request should not be forwarded")
|
||||
}, 3010)
|
||||
defer st.Close()
|
||||
|
||||
res, err := st.spdy(requestParam{
|
||||
name: "TestS3APIBackendconfigBadMethod",
|
||||
path: "/api/v1beta1/backendconfig",
|
||||
method: "GET",
|
||||
body: []byte(`# comment
|
||||
backend=127.0.0.1,3011
|
||||
|
||||
`),
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("Error st.spdy() = %v", err)
|
||||
}
|
||||
if got, want := res.status, 405; got != want {
|
||||
t.Errorf("res.status: %v; want %v", got, want)
|
||||
}
|
||||
|
||||
var apiResp APIResponse
|
||||
err = json.Unmarshal(res.body, &apiResp)
|
||||
if err != nil {
|
||||
t.Fatalf("Error unmarshaling API response: %v", err)
|
||||
}
|
||||
if got, want := apiResp.Status, "Failure"; got != want {
|
||||
t.Errorf("apiResp.Status: %v; want %v", got, want)
|
||||
}
|
||||
if got, want := apiResp.Code, 405; got != want {
|
||||
t.Errorf("apiResp.Status: %v; want %v", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
// TestS3APINotFound exercise backendconfig API endpoint routine when
|
||||
// API endpoint is not found.
|
||||
func TestS3APINotFound(t *testing.T) {
|
||||
st := newServerTesterTLSConnectPort([]string{"--npn-list=spdy/3.1", "-f127.0.0.1,3010;api"}, t, func(w http.ResponseWriter, r *http.Request) {
|
||||
t.Fatalf("request should not be forwarded")
|
||||
}, 3010)
|
||||
defer st.Close()
|
||||
|
||||
res, err := st.spdy(requestParam{
|
||||
name: "TestS3APINotFound",
|
||||
path: "/api/notfound",
|
||||
method: "GET",
|
||||
body: []byte(`# comment
|
||||
backend=127.0.0.1,3011
|
||||
|
||||
`),
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("Error st.spdy() = %v", err)
|
||||
}
|
||||
if got, want := res.status, 404; got != want {
|
||||
t.Errorf("res.status: %v; want %v", got, want)
|
||||
}
|
||||
|
||||
var apiResp APIResponse
|
||||
err = json.Unmarshal(res.body, &apiResp)
|
||||
if err != nil {
|
||||
t.Fatalf("Error unmarshaling API response: %v", err)
|
||||
}
|
||||
if got, want := apiResp.Status, "Failure"; got != want {
|
||||
t.Errorf("apiResp.Status: %v; want %v", got, want)
|
||||
}
|
||||
if got, want := apiResp.Code, 404; got != want {
|
||||
t.Errorf("apiResp.Status: %v; want %v", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
// TestS3Healthmon tests health monitor endpoint.
|
||||
func TestS3Healthmon(t *testing.T) {
|
||||
st := newServerTesterTLSConnectPort([]string{"--npn-list=spdy/3.1", "-f127.0.0.1,3011;healthmon"}, t, func(w http.ResponseWriter, r *http.Request) {
|
||||
t.Fatalf("request should not be forwarded")
|
||||
}, 3011)
|
||||
defer st.Close()
|
||||
|
||||
res, err := st.spdy(requestParam{
|
||||
name: "TestS3Healthmon",
|
||||
path: "/alpha/bravo",
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("Error st.spdy() = %v", err)
|
||||
}
|
||||
if got, want := res.status, 200; got != want {
|
||||
t.Errorf("res.status: %v; want %v", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
// TestS3ResponseBeforeRequestEnd tests the situation where response
|
||||
// ends before request body finishes.
|
||||
func TestS3ResponseBeforeRequestEnd(t *testing.T) {
|
||||
st := newServerTesterTLS([]string{"--npn-list=spdy/3.1", "--mruby-file=" + testDir + "/req-return.rb"}, t, func(w http.ResponseWriter, r *http.Request) {
|
||||
t.Fatal("request should not be forwarded")
|
||||
})
|
||||
defer st.Close()
|
||||
|
||||
res, err := st.spdy(requestParam{
|
||||
name: "TestS3ResponseBeforeRequestEnd",
|
||||
noEndStream: true,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("Error st.spdy() = %v", err)
|
||||
}
|
||||
if got, want := res.status, 404; got != want {
|
||||
t.Errorf("res.status: %v; want %v", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,10 +6,10 @@ import (
|
||||
"crypto/tls"
|
||||
"errors"
|
||||
"fmt"
|
||||
"golang.org/x/net/http2"
|
||||
"golang.org/x/net/http2/hpack"
|
||||
"github.com/tatsuhiro-t/go-nghttp2"
|
||||
"github.com/tatsuhiro-t/spdy"
|
||||
"golang.org/x/net/http2"
|
||||
"golang.org/x/net/http2/hpack"
|
||||
"golang.org/x/net/websocket"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
@@ -29,7 +29,8 @@ import (
|
||||
const (
|
||||
serverBin = buildDir + "/src/nghttpx"
|
||||
serverPort = 3009
|
||||
testDir = buildDir + "/integration-tests"
|
||||
testDir = sourceDir + "/integration-tests"
|
||||
logDir = buildDir + "/integration-tests"
|
||||
)
|
||||
|
||||
func pair(name, value string) hpack.HeaderField {
|
||||
@@ -65,34 +66,57 @@ type serverTester struct {
|
||||
// newServerTester creates test context for plain TCP frontend
|
||||
// connection.
|
||||
func newServerTester(args []string, t *testing.T, handler http.HandlerFunc) *serverTester {
|
||||
return newServerTesterInternal(args, t, handler, false, nil)
|
||||
return newServerTesterInternal(args, t, handler, false, serverPort, nil)
|
||||
}
|
||||
|
||||
func newServerTesterConnectPort(args []string, t *testing.T, handler http.HandlerFunc, port int) *serverTester {
|
||||
return newServerTesterInternal(args, t, handler, false, port, nil)
|
||||
}
|
||||
|
||||
func newServerTesterHandler(args []string, t *testing.T, handler http.Handler) *serverTester {
|
||||
return newServerTesterInternal(args, t, handler, false, nil)
|
||||
return newServerTesterInternal(args, t, handler, false, serverPort, nil)
|
||||
}
|
||||
|
||||
// newServerTester creates test context for TLS frontend connection.
|
||||
func newServerTesterTLS(args []string, t *testing.T, handler http.HandlerFunc) *serverTester {
|
||||
return newServerTesterInternal(args, t, handler, true, nil)
|
||||
return newServerTesterInternal(args, t, handler, true, serverPort, nil)
|
||||
}
|
||||
|
||||
func newServerTesterTLSConnectPort(args []string, t *testing.T, handler http.HandlerFunc, port int) *serverTester {
|
||||
return newServerTesterInternal(args, t, handler, true, port, nil)
|
||||
}
|
||||
|
||||
// newServerTester creates test context for TLS frontend connection
|
||||
// with given clientConfig
|
||||
func newServerTesterTLSConfig(args []string, t *testing.T, handler http.HandlerFunc, clientConfig *tls.Config) *serverTester {
|
||||
return newServerTesterInternal(args, t, handler, true, clientConfig)
|
||||
return newServerTesterInternal(args, t, handler, true, serverPort, clientConfig)
|
||||
}
|
||||
|
||||
// newServerTesterInternal creates test context. If frontendTLS is
|
||||
// true, set up TLS frontend connection.
|
||||
func newServerTesterInternal(args []string, t *testing.T, handler http.Handler, frontendTLS bool, clientConfig *tls.Config) *serverTester {
|
||||
// true, set up TLS frontend connection. connectPort is the server
|
||||
// side port where client connection is made.
|
||||
func newServerTesterInternal(src_args []string, t *testing.T, handler http.Handler, frontendTLS bool, connectPort int, clientConfig *tls.Config) *serverTester {
|
||||
ts := httptest.NewUnstartedServer(handler)
|
||||
|
||||
args := []string{}
|
||||
|
||||
backendTLS := false
|
||||
for _, k := range args {
|
||||
dns := false
|
||||
externalDNS := false
|
||||
acceptProxyProtocol := false
|
||||
for _, k := range src_args {
|
||||
switch k {
|
||||
case "--http2-bridge":
|
||||
backendTLS = true
|
||||
case "--dns":
|
||||
dns = true
|
||||
case "--external-dns":
|
||||
dns = true
|
||||
externalDNS = true
|
||||
case "--accept-proxy-protocol":
|
||||
acceptProxyProtocol = true
|
||||
default:
|
||||
args = append(args, k)
|
||||
}
|
||||
}
|
||||
if backendTLS {
|
||||
@@ -101,7 +125,7 @@ func newServerTesterInternal(args []string, t *testing.T, handler http.Handler,
|
||||
// NextProtos separately for ts.TLS. NextProtos set
|
||||
// in nghttp2.ConfigureServer is effectively ignored.
|
||||
ts.TLS = new(tls.Config)
|
||||
ts.TLS.NextProtos = append(ts.TLS.NextProtos, "h2-14")
|
||||
ts.TLS.NextProtos = append(ts.TLS.NextProtos, "h2")
|
||||
ts.StartTLS()
|
||||
args = append(args, "-k")
|
||||
} else {
|
||||
@@ -111,8 +135,6 @@ func newServerTesterInternal(args []string, t *testing.T, handler http.Handler,
|
||||
if frontendTLS {
|
||||
scheme = "https"
|
||||
args = append(args, testDir+"/server.key", testDir+"/server.crt")
|
||||
} else {
|
||||
args = append(args, "--frontend-no-tls")
|
||||
}
|
||||
|
||||
backendURL, err := url.Parse(ts.URL)
|
||||
@@ -122,11 +144,39 @@ func newServerTesterInternal(args []string, t *testing.T, handler http.Handler,
|
||||
|
||||
// URL.Host looks like "127.0.0.1:8080", but we want
|
||||
// "127.0.0.1,8080"
|
||||
b := "-b" + strings.Replace(backendURL.Host, ":", ",", -1)
|
||||
args = append(args, fmt.Sprintf("-f127.0.0.1,%v", serverPort), b,
|
||||
"--errorlog-file="+testDir+"/log.txt", "-LINFO")
|
||||
b := "-b"
|
||||
if !externalDNS {
|
||||
b += fmt.Sprintf("%v;", strings.Replace(backendURL.Host, ":", ",", -1))
|
||||
} else {
|
||||
sep := strings.LastIndex(backendURL.Host, ":")
|
||||
if sep == -1 {
|
||||
t.Fatalf("backendURL.Host %v does not contain separator ':'", backendURL.Host)
|
||||
}
|
||||
// We use awesome service xip.io.
|
||||
b += fmt.Sprintf("%v.xip.io,%v;", backendURL.Host[:sep], backendURL.Host[sep+1:])
|
||||
}
|
||||
|
||||
authority := fmt.Sprintf("127.0.0.1:%v", serverPort)
|
||||
if backendTLS {
|
||||
b += ";proto=h2;tls"
|
||||
}
|
||||
if dns {
|
||||
b += ";dns"
|
||||
}
|
||||
|
||||
noTLS := ";no-tls"
|
||||
if frontendTLS {
|
||||
noTLS = ""
|
||||
}
|
||||
|
||||
var proxyProto string
|
||||
if acceptProxyProtocol {
|
||||
proxyProto = ";proxyproto"
|
||||
}
|
||||
|
||||
args = append(args, fmt.Sprintf("-f127.0.0.1,%v%v%v", serverPort, noTLS, proxyProto), b,
|
||||
"--errorlog-file="+logDir+"/log.txt", "-LINFO")
|
||||
|
||||
authority := fmt.Sprintf("127.0.0.1:%v", connectPort)
|
||||
|
||||
st := &serverTester{
|
||||
cmd: exec.Command(serverBin, args...),
|
||||
@@ -148,6 +198,8 @@ func newServerTesterInternal(args []string, t *testing.T, handler http.Handler,
|
||||
|
||||
retry := 0
|
||||
for {
|
||||
time.Sleep(50 * time.Millisecond)
|
||||
|
||||
var conn net.Conn
|
||||
var err error
|
||||
if frontendTLS {
|
||||
@@ -158,7 +210,7 @@ func newServerTesterInternal(args []string, t *testing.T, handler http.Handler,
|
||||
tlsConfig = clientConfig
|
||||
}
|
||||
tlsConfig.InsecureSkipVerify = true
|
||||
tlsConfig.NextProtos = []string{"h2-14", "spdy/3.1"}
|
||||
tlsConfig.NextProtos = []string{"h2", "spdy/3.1"}
|
||||
conn, err = tls.Dial("tcp", authority, tlsConfig)
|
||||
} else {
|
||||
conn, err = net.Dial("tcp", authority)
|
||||
@@ -169,7 +221,6 @@ func newServerTesterInternal(args []string, t *testing.T, handler http.Handler,
|
||||
st.Close()
|
||||
st.t.Fatalf("Error server is not responding too long; server command-line arguments may be invalid")
|
||||
}
|
||||
time.Sleep(150 * time.Millisecond)
|
||||
continue
|
||||
}
|
||||
if frontendTLS {
|
||||
@@ -275,6 +326,7 @@ type requestParam struct {
|
||||
body []byte // request body
|
||||
trailer []hpack.HeaderField // trailer part
|
||||
httpUpgrade bool // true if upgraded to HTTP/2 through HTTP Upgrade
|
||||
noEndStream bool // true if END_STREAM should not be sent
|
||||
}
|
||||
|
||||
// wrapper for request body to set trailer part
|
||||
@@ -358,8 +410,9 @@ func (st *serverTester) http1(rp requestParam) (*serverResponse, error) {
|
||||
if err != nil {
|
||||
st.t.Fatalf("Error parsing URL from st.url %v: %v", st.url, err)
|
||||
}
|
||||
u.Path = rp.path
|
||||
reqURL = u.String()
|
||||
u.Path = ""
|
||||
u.RawQuery = ""
|
||||
reqURL = u.String() + rp.path
|
||||
}
|
||||
|
||||
req, err := http.NewRequest(method, reqURL, body)
|
||||
@@ -448,7 +501,7 @@ func (st *serverTester) spdy(rp requestParam) (*serverResponse, error) {
|
||||
}
|
||||
|
||||
var synStreamFlags spdy.ControlFlags
|
||||
if len(rp.body) == 0 {
|
||||
if len(rp.body) == 0 && !rp.noEndStream {
|
||||
synStreamFlags = spdy.ControlFlagFin
|
||||
}
|
||||
if err := st.spdyFr.WriteFrame(&spdy.SynStreamFrame{
|
||||
@@ -462,9 +515,13 @@ func (st *serverTester) spdy(rp requestParam) (*serverResponse, error) {
|
||||
}
|
||||
|
||||
if len(rp.body) != 0 {
|
||||
var dataFlags spdy.DataFlags
|
||||
if !rp.noEndStream {
|
||||
dataFlags = spdy.DataFlagFin
|
||||
}
|
||||
if err := st.spdyFr.WriteFrame(&spdy.DataFrame{
|
||||
StreamId: id,
|
||||
Flags: spdy.DataFlagFin,
|
||||
Flags: dataFlags,
|
||||
Data: rp.body,
|
||||
}); err != nil {
|
||||
return nil, err
|
||||
@@ -577,7 +634,7 @@ func (st *serverTester) http2(rp requestParam) (*serverResponse, error) {
|
||||
|
||||
err := st.fr.WriteHeaders(http2.HeadersFrameParam{
|
||||
StreamID: id,
|
||||
EndStream: len(rp.body) == 0 && len(rp.trailer) == 0,
|
||||
EndStream: len(rp.body) == 0 && len(rp.trailer) == 0 && !rp.noEndStream,
|
||||
EndHeaders: true,
|
||||
BlockFragment: st.headerBlkBuf.Bytes(),
|
||||
})
|
||||
@@ -587,7 +644,7 @@ func (st *serverTester) http2(rp requestParam) (*serverResponse, error) {
|
||||
|
||||
if len(rp.body) != 0 {
|
||||
// TODO we assume rp.body fits in 1 frame
|
||||
if err := st.fr.WriteData(id, len(rp.trailer) == 0, rp.body); err != nil {
|
||||
if err := st.fr.WriteData(id, len(rp.trailer) == 0 && !rp.noEndStream, rp.body); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
@@ -734,3 +791,8 @@ func cloneHeader(h http.Header) http.Header {
|
||||
}
|
||||
|
||||
func noopHandler(w http.ResponseWriter, r *http.Request) {}
|
||||
|
||||
type APIResponse struct {
|
||||
Status string `json:"status,omitempty"`
|
||||
Code int `json:"code,omitempty"`
|
||||
}
|
||||
|
||||
@@ -1,6 +1,12 @@
|
||||
#!/bin/sh -e
|
||||
|
||||
libdir="@abs_top_builddir@/lib"
|
||||
if [ -d "$libdir/.libs" ]; then
|
||||
libdir="$libdir/.libs"
|
||||
fi
|
||||
|
||||
export CGO_CFLAGS="-I@abs_top_srcdir@/lib/includes -I@abs_top_builddir@/lib/includes"
|
||||
export CGO_LDFLAGS="-L@abs_top_builddir@/lib/.libs"
|
||||
export LD_LIBRARY_PATH="@abs_top_builddir@/lib/.libs"
|
||||
export CGO_LDFLAGS="-L$libdir"
|
||||
export LD_LIBRARY_PATH="$libdir"
|
||||
export GODEBUG=cgocheck=0
|
||||
"$@"
|
||||
|
||||
63
lib/CMakeLists.txt
Normal file
63
lib/CMakeLists.txt
Normal file
@@ -0,0 +1,63 @@
|
||||
add_subdirectory(includes)
|
||||
|
||||
include_directories(
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/includes"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/includes"
|
||||
)
|
||||
|
||||
add_definitions(-DBUILDING_NGHTTP2)
|
||||
|
||||
set(NGHTTP2_SOURCES
|
||||
nghttp2_pq.c nghttp2_map.c nghttp2_queue.c
|
||||
nghttp2_frame.c
|
||||
nghttp2_buf.c
|
||||
nghttp2_stream.c nghttp2_outbound_item.c
|
||||
nghttp2_session.c nghttp2_submit.c
|
||||
nghttp2_helper.c
|
||||
nghttp2_npn.c
|
||||
nghttp2_hd.c nghttp2_hd_huffman.c nghttp2_hd_huffman_data.c
|
||||
nghttp2_version.c
|
||||
nghttp2_priority_spec.c
|
||||
nghttp2_option.c
|
||||
nghttp2_callbacks.c
|
||||
nghttp2_mem.c
|
||||
nghttp2_http.c
|
||||
nghttp2_rcbuf.c
|
||||
nghttp2_debug.c
|
||||
)
|
||||
|
||||
set(NGHTTP2_RES "")
|
||||
|
||||
if(WIN32)
|
||||
configure_file(
|
||||
version.rc.in
|
||||
${CMAKE_CURRENT_BINARY_DIR}/version.rc
|
||||
@ONLY)
|
||||
|
||||
set(NGHTTP2_RES ${CMAKE_CURRENT_BINARY_DIR}/version.rc)
|
||||
endif()
|
||||
|
||||
# Public shared library
|
||||
add_library(nghttp2 SHARED ${NGHTTP2_SOURCES} ${NGHTTP2_RES})
|
||||
set_target_properties(nghttp2 PROPERTIES
|
||||
COMPILE_FLAGS "${WARNCFLAGS}"
|
||||
VERSION ${LT_VERSION} SOVERSION ${LT_SOVERSION}
|
||||
C_VISIBILITY_PRESET hidden
|
||||
)
|
||||
|
||||
if(HAVE_CUNIT)
|
||||
# Static library (for unittests because of symbol visibility)
|
||||
add_library(nghttp2_static STATIC ${NGHTTP2_SOURCES})
|
||||
set_target_properties(nghttp2_static PROPERTIES
|
||||
COMPILE_FLAGS "${WARNCFLAGS}"
|
||||
VERSION ${LT_VERSION} SOVERSION ${LT_SOVERSION}
|
||||
ARCHIVE_OUTPUT_NAME nghttp2
|
||||
)
|
||||
target_compile_definitions(nghttp2_static PUBLIC "-DNGHTTP2_STATICLIB")
|
||||
endif()
|
||||
|
||||
install(TARGETS nghttp2
|
||||
DESTINATION "${CMAKE_INSTALL_LIBDIR}")
|
||||
|
||||
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/libnghttp2.pc"
|
||||
DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig")
|
||||
@@ -22,7 +22,7 @@
|
||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
SUBDIRS = includes
|
||||
|
||||
EXTRA_DIST = Makefile.msvc
|
||||
EXTRA_DIST = Makefile.msvc CMakeLists.txt version.rc.in
|
||||
|
||||
AM_CFLAGS = $(WARNCFLAGS) $(EXTRACFLAG)
|
||||
AM_CPPFLAGS = -I$(srcdir)/includes -I$(builddir)/includes -DBUILDING_NGHTTP2 \
|
||||
@@ -47,7 +47,9 @@ OBJECTS = nghttp2_pq.c nghttp2_map.c nghttp2_queue.c \
|
||||
nghttp2_option.c \
|
||||
nghttp2_callbacks.c \
|
||||
nghttp2_mem.c \
|
||||
nghttp2_http.c
|
||||
nghttp2_http.c \
|
||||
nghttp2_rcbuf.c \
|
||||
nghttp2_debug.c
|
||||
|
||||
HFILES = nghttp2_pq.h nghttp2_int.h nghttp2_map.h nghttp2_queue.h \
|
||||
nghttp2_frame.h \
|
||||
@@ -61,7 +63,9 @@ HFILES = nghttp2_pq.h nghttp2_int.h nghttp2_map.h nghttp2_queue.h \
|
||||
nghttp2_option.h \
|
||||
nghttp2_callbacks.h \
|
||||
nghttp2_mem.h \
|
||||
nghttp2_http.h
|
||||
nghttp2_http.h \
|
||||
nghttp2_rcbuf.h \
|
||||
nghttp2_debug.h
|
||||
|
||||
libnghttp2_la_SOURCES = $(HFILES) $(OBJECTS)
|
||||
libnghttp2_la_LDFLAGS = -no-undefined \
|
||||
|
||||
@@ -12,16 +12,16 @@
|
||||
#
|
||||
THIS_MAKEFILE := $(lastword $(MAKEFILE_LIST))
|
||||
|
||||
USE_CYTHON := 1
|
||||
#USE_CYTHON := 0
|
||||
USE_CYTHON := 0
|
||||
#USE_CYTHON := 1
|
||||
|
||||
_VERSION := $(shell grep AC_INIT ../configure.ac | cut -d'[' -f3 | sed -e 's/-DEV], //g')
|
||||
_VERSION := $(shell grep AC_INIT ../configure.ac | cut -d'[' -f3 | sed -e 's/-DEV//g' -e 's/], //g')
|
||||
_VERSION := $(subst ., ,$(_VERSION))
|
||||
VER_MAJOR := $(word 1,$(_VERSION))
|
||||
VER_MINOR := $(word 2,$(_VERSION))
|
||||
VER_MICRO := $(word 3,$(_VERSION))
|
||||
VERSION := $(VER_MAJOR).$(VER_MINOR).$(VER_MICRO)
|
||||
VERSION_NUM := ($(VER_MAJOR) << 16) + ($(VER_MINOR) << 8) + $(VER_MICRO)
|
||||
VERSION_NUM := (($(VER_MAJOR) << 16) + ($(VER_MINOR) << 8) + $(VER_MICRO))
|
||||
|
||||
GENERATED := 'Generated by $(realpath Makefile.MSVC)'
|
||||
|
||||
@@ -90,7 +90,8 @@ NGHTTP2_SRC := nghttp2_pq.c \
|
||||
nghttp2_option.c \
|
||||
nghttp2_callbacks.c \
|
||||
nghttp2_mem.c \
|
||||
nghttp2_http.c
|
||||
nghttp2_http.c \
|
||||
nghttp2_rcbuf.c
|
||||
|
||||
NGHTTP2_OBJ_R := $(addprefix $(OBJ_DIR)/r_, $(notdir $(NGHTTP2_SRC:.c=.obj)))
|
||||
NGHTTP2_OBJ_D := $(addprefix $(OBJ_DIR)/d_, $(notdir $(NGHTTP2_SRC:.c=.obj)))
|
||||
@@ -101,7 +102,7 @@ NGHTTP2_OBJ_D := $(addprefix $(OBJ_DIR)/d_, $(notdir $(NGHTTP2_SRC:.c=.obj)))
|
||||
clean_nghttp2_pyd_0 clean_nghttp2_pyd_1
|
||||
|
||||
|
||||
all: intro $(OBJ_DIR) $(TARGETS) build_nghttp2_pyd_$(USE_CYTHON)
|
||||
all: intro includes/nghttp2/nghttp2ver.h $(OBJ_DIR) $(TARGETS) build_nghttp2_pyd_$(USE_CYTHON)
|
||||
@echo 'Welcome to NgHTTP2 (release + debug).'
|
||||
@echo 'Do a "make -f Makefile.MSVC install" at own risk!'
|
||||
|
||||
@@ -193,17 +194,17 @@ $(OBJ_DIR)/d_%.obj: %.c $(THIS_MAKEFILE)
|
||||
@echo
|
||||
|
||||
$(OBJ_DIR)/r_nghttp2.res: $(OBJ_DIR)/nghttp2.rc $(THIS_MAKEFILE)
|
||||
$(RC) -nologo -D_RELEASE -Fo $@ $<
|
||||
$(RC) -D_RELEASE -Fo $@ $<
|
||||
@echo
|
||||
|
||||
$(OBJ_DIR)/d_nghttp2.res: $(OBJ_DIR)/nghttp2.rc $(THIS_MAKEFILE)
|
||||
$(RC) -nologo -D_DEBUG -Fo $@ $<
|
||||
$(RC) -D_DEBUG -Fo $@ $<
|
||||
@echo
|
||||
|
||||
includes/nghttp2/nghttp2ver.h: includes/nghttp2/nghttp2ver.h.in $(THIS_MAKEFILE)
|
||||
sed < includes/nghttp2/nghttp2ver.h.in \
|
||||
-e 's/@PACKAGE_VERSION@/$(VERSION)/g' \
|
||||
-e 's/@PACKAGE_VERSION_NUM@/($(VERSION_NUM))/g' > $@
|
||||
-e 's/@PACKAGE_VERSION_NUM@/$(VERSION_NUM)/g' > $@
|
||||
touch --reference=includes/nghttp2/nghttp2ver.h.in $@
|
||||
|
||||
|
||||
|
||||
4
lib/includes/CMakeLists.txt
Normal file
4
lib/includes/CMakeLists.txt
Normal file
@@ -0,0 +1,4 @@
|
||||
install(FILES
|
||||
nghttp2/nghttp2.h
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/nghttp2/nghttp2ver.h"
|
||||
DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/nghttp2")
|
||||
@@ -20,4 +20,7 @@
|
||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
EXTRA_DIST = CMakeLists.txt
|
||||
|
||||
nobase_include_HEADERS = nghttp2/nghttp2.h nghttp2/nghttp2ver.h
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -27,6 +27,7 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#include "nghttp2_helper.h"
|
||||
#include "nghttp2_debug.h"
|
||||
|
||||
void nghttp2_buf_init(nghttp2_buf *buf) {
|
||||
buf->begin = NULL;
|
||||
@@ -223,13 +224,54 @@ int nghttp2_bufs_wrap_init(nghttp2_bufs *bufs, uint8_t *begin, size_t len,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int nghttp2_bufs_wrap_init2(nghttp2_bufs *bufs, const nghttp2_vec *vec,
|
||||
size_t veclen, nghttp2_mem *mem) {
|
||||
size_t i = 0;
|
||||
nghttp2_buf_chain *cur_chain;
|
||||
nghttp2_buf_chain *head_chain;
|
||||
nghttp2_buf_chain **dst_chain = &head_chain;
|
||||
|
||||
if (veclen == 0) {
|
||||
return nghttp2_bufs_wrap_init(bufs, NULL, 0, mem);
|
||||
}
|
||||
|
||||
head_chain = nghttp2_mem_malloc(mem, sizeof(nghttp2_buf_chain) * veclen);
|
||||
if (head_chain == NULL) {
|
||||
return NGHTTP2_ERR_NOMEM;
|
||||
}
|
||||
|
||||
for (i = 0; i < veclen; ++i) {
|
||||
cur_chain = &head_chain[i];
|
||||
cur_chain->next = NULL;
|
||||
nghttp2_buf_wrap_init(&cur_chain->buf, vec[i].base, vec[i].len);
|
||||
|
||||
*dst_chain = cur_chain;
|
||||
dst_chain = &cur_chain->next;
|
||||
}
|
||||
|
||||
bufs->mem = mem;
|
||||
bufs->offset = 0;
|
||||
|
||||
bufs->head = head_chain;
|
||||
bufs->cur = bufs->head;
|
||||
|
||||
/* We don't use chunk_length since no allocation is expected. */
|
||||
bufs->chunk_length = 0;
|
||||
bufs->chunk_used = veclen;
|
||||
bufs->max_chunk = veclen;
|
||||
bufs->chunk_keep = veclen;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void nghttp2_bufs_wrap_free(nghttp2_bufs *bufs) {
|
||||
if (bufs == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
nghttp2_mem_free(bufs->mem, bufs->head);
|
||||
bufs->head = NULL;
|
||||
if (bufs->head) {
|
||||
nghttp2_mem_free(bufs->mem, bufs->head);
|
||||
}
|
||||
}
|
||||
|
||||
void nghttp2_bufs_seek_last_present(nghttp2_bufs *bufs) {
|
||||
@@ -256,12 +298,6 @@ size_t nghttp2_bufs_len(nghttp2_bufs *bufs) {
|
||||
return len;
|
||||
}
|
||||
|
||||
static size_t bufs_avail(nghttp2_bufs *bufs) {
|
||||
return nghttp2_buf_avail(&bufs->cur->buf) +
|
||||
(bufs->chunk_length - bufs->offset) *
|
||||
(bufs->max_chunk - bufs->chunk_used);
|
||||
}
|
||||
|
||||
static int bufs_alloc_chain(nghttp2_bufs *bufs) {
|
||||
int rv;
|
||||
nghttp2_buf_chain *chain;
|
||||
@@ -281,9 +317,8 @@ static int bufs_alloc_chain(nghttp2_bufs *bufs) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
DEBUGF(fprintf(stderr,
|
||||
"new buffer %zu bytes allocated for bufs %p, used %zu\n",
|
||||
bufs->chunk_length, bufs, bufs->chunk_used));
|
||||
DEBUGF("new buffer %zu bytes allocated for bufs %p, used %zu\n",
|
||||
bufs->chunk_length, bufs, bufs->chunk_used);
|
||||
|
||||
++bufs->chunk_used;
|
||||
|
||||
@@ -301,10 +336,6 @@ int nghttp2_bufs_add(nghttp2_bufs *bufs, const void *data, size_t len) {
|
||||
nghttp2_buf *buf;
|
||||
const uint8_t *p;
|
||||
|
||||
if (bufs_avail(bufs) < len) {
|
||||
return NGHTTP2_ERR_BUFFER_ERROR;
|
||||
}
|
||||
|
||||
p = data;
|
||||
|
||||
while (len) {
|
||||
|
||||
@@ -73,7 +73,7 @@ typedef struct {
|
||||
|
||||
/*
|
||||
* Initializes the |buf|. No memory is allocated in this function. Use
|
||||
* nghttp2_buf_reserve() or nghttp2_buf_reserve2() to allocate memory.
|
||||
* nghttp2_buf_reserve() to allocate memory.
|
||||
*/
|
||||
void nghttp2_buf_init(nghttp2_buf *buf);
|
||||
|
||||
@@ -138,7 +138,9 @@ typedef struct {
|
||||
nghttp2_buf_chain *cur;
|
||||
/* Memory allocator */
|
||||
nghttp2_mem *mem;
|
||||
/* The buffer capacity of each buf */
|
||||
/* The buffer capacity of each buf. This field may be 0 if
|
||||
nghttp2_bufs is initialized by nghttp2_bufs_wrap_init* family
|
||||
functions. */
|
||||
size_t chunk_length;
|
||||
/* The maximum number of nghttp2_buf_chain */
|
||||
size_t max_chunk;
|
||||
@@ -197,10 +199,13 @@ void nghttp2_bufs_free(nghttp2_bufs *bufs);
|
||||
/*
|
||||
* Initializes |bufs| using supplied buffer |begin| of length |len|.
|
||||
* The first buffer bufs->head uses buffer |begin|. The buffer size
|
||||
* is fixed and no allocate extra chunk buffer is allocated. In other
|
||||
* is fixed and no extra chunk buffer is allocated. In other
|
||||
* words, max_chunk = chunk_keep = 1. To free the resource allocated
|
||||
* for |bufs|, use nghttp2_bufs_wrap_free().
|
||||
*
|
||||
* Don't use the function which performs allocation, such as
|
||||
* nghttp2_bufs_realloc().
|
||||
*
|
||||
* This function returns 0 if it succeeds, or one of the following
|
||||
* negative error codes:
|
||||
*
|
||||
@@ -210,6 +215,25 @@ void nghttp2_bufs_free(nghttp2_bufs *bufs);
|
||||
int nghttp2_bufs_wrap_init(nghttp2_bufs *bufs, uint8_t *begin, size_t len,
|
||||
nghttp2_mem *mem);
|
||||
|
||||
/*
|
||||
* Initializes |bufs| using supplied |veclen| size of buf vector
|
||||
* |vec|. The number of buffers is fixed and no extra chunk buffer is
|
||||
* allocated. In other words, max_chunk = chunk_keep = |in_len|. To
|
||||
* free the resource allocated for |bufs|, use
|
||||
* nghttp2_bufs_wrap_free().
|
||||
*
|
||||
* Don't use the function which performs allocation, such as
|
||||
* nghttp2_bufs_realloc().
|
||||
*
|
||||
* This function returns 0 if it succeeds, or one of the following
|
||||
* negative error codes:
|
||||
*
|
||||
* NGHTTP2_ERR_NOMEM
|
||||
* Out of memory.
|
||||
*/
|
||||
int nghttp2_bufs_wrap_init2(nghttp2_bufs *bufs, const nghttp2_vec *vec,
|
||||
size_t veclen, nghttp2_mem *mem);
|
||||
|
||||
/*
|
||||
* Frees any related resource to the |bufs|. This function does not
|
||||
* free supplied buffer provided in nghttp2_bufs_wrap_init().
|
||||
@@ -312,8 +336,8 @@ int nghttp2_bufs_orb_hold(nghttp2_bufs *bufs, uint8_t b);
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* Copies all data stored in |bufs| to the contagious buffer. This
|
||||
* function allocates the contagious memory to store all data in
|
||||
* Copies all data stored in |bufs| to the contiguous buffer. This
|
||||
* function allocates the contiguous memory to store all data in
|
||||
* |bufs| and assigns it to |*out|.
|
||||
*
|
||||
* The contents of |bufs| is left unchanged.
|
||||
@@ -381,7 +405,7 @@ int nghttp2_bufs_next_present(nghttp2_bufs *bufs);
|
||||
#define nghttp2_bufs_cur_avail(BUFS) nghttp2_buf_avail(&(BUFS)->cur->buf)
|
||||
|
||||
/*
|
||||
* Returns the buffer length of |bufs|.
|
||||
* Returns the total buffer length of |bufs|.
|
||||
*/
|
||||
size_t nghttp2_bufs_len(nghttp2_bufs *bufs);
|
||||
|
||||
|
||||
@@ -104,6 +104,24 @@ void nghttp2_session_callbacks_set_on_header_callback(
|
||||
cbs->on_header_callback = on_header_callback;
|
||||
}
|
||||
|
||||
void nghttp2_session_callbacks_set_on_header_callback2(
|
||||
nghttp2_session_callbacks *cbs,
|
||||
nghttp2_on_header_callback2 on_header_callback2) {
|
||||
cbs->on_header_callback2 = on_header_callback2;
|
||||
}
|
||||
|
||||
void nghttp2_session_callbacks_set_on_invalid_header_callback(
|
||||
nghttp2_session_callbacks *cbs,
|
||||
nghttp2_on_invalid_header_callback on_invalid_header_callback) {
|
||||
cbs->on_invalid_header_callback = on_invalid_header_callback;
|
||||
}
|
||||
|
||||
void nghttp2_session_callbacks_set_on_invalid_header_callback2(
|
||||
nghttp2_session_callbacks *cbs,
|
||||
nghttp2_on_invalid_header_callback2 on_invalid_header_callback2) {
|
||||
cbs->on_invalid_header_callback2 = on_invalid_header_callback2;
|
||||
}
|
||||
|
||||
void nghttp2_session_callbacks_set_select_padding_callback(
|
||||
nghttp2_session_callbacks *cbs,
|
||||
nghttp2_select_padding_callback select_padding_callback) {
|
||||
@@ -127,3 +145,26 @@ void nghttp2_session_callbacks_set_send_data_callback(
|
||||
nghttp2_send_data_callback send_data_callback) {
|
||||
cbs->send_data_callback = send_data_callback;
|
||||
}
|
||||
|
||||
void nghttp2_session_callbacks_set_pack_extension_callback(
|
||||
nghttp2_session_callbacks *cbs,
|
||||
nghttp2_pack_extension_callback pack_extension_callback) {
|
||||
cbs->pack_extension_callback = pack_extension_callback;
|
||||
}
|
||||
|
||||
void nghttp2_session_callbacks_set_unpack_extension_callback(
|
||||
nghttp2_session_callbacks *cbs,
|
||||
nghttp2_unpack_extension_callback unpack_extension_callback) {
|
||||
cbs->unpack_extension_callback = unpack_extension_callback;
|
||||
}
|
||||
|
||||
void nghttp2_session_callbacks_set_on_extension_chunk_recv_callback(
|
||||
nghttp2_session_callbacks *cbs,
|
||||
nghttp2_on_extension_chunk_recv_callback on_extension_chunk_recv_callback) {
|
||||
cbs->on_extension_chunk_recv_callback = on_extension_chunk_recv_callback;
|
||||
}
|
||||
|
||||
void nghttp2_session_callbacks_set_error_callback(
|
||||
nghttp2_session_callbacks *cbs, nghttp2_error_callback error_callback) {
|
||||
cbs->error_callback = error_callback;
|
||||
}
|
||||
|
||||
@@ -91,6 +91,14 @@ struct nghttp2_session_callbacks {
|
||||
* received.
|
||||
*/
|
||||
nghttp2_on_header_callback on_header_callback;
|
||||
nghttp2_on_header_callback2 on_header_callback2;
|
||||
/**
|
||||
* Callback function invoked when a invalid header name/value pair
|
||||
* is received which is silently ignored if these callbacks are not
|
||||
* set.
|
||||
*/
|
||||
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
|
||||
@@ -107,6 +115,10 @@ struct nghttp2_session_callbacks {
|
||||
*/
|
||||
nghttp2_on_begin_frame_callback on_begin_frame_callback;
|
||||
nghttp2_send_data_callback send_data_callback;
|
||||
nghttp2_pack_extension_callback pack_extension_callback;
|
||||
nghttp2_unpack_extension_callback unpack_extension_callback;
|
||||
nghttp2_on_extension_chunk_recv_callback on_extension_chunk_recv_callback;
|
||||
nghttp2_error_callback error_callback;
|
||||
};
|
||||
|
||||
#endif /* NGHTTP2_CALLBACKS_H */
|
||||
|
||||
58
lib/nghttp2_debug.c
Normal file
58
lib/nghttp2_debug.c
Normal file
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* nghttp2 - HTTP/2 C Library
|
||||
*
|
||||
* Copyright (c) 2016 Tatsuhiro Tsujikawa
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#include "nghttp2_debug.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef DEBUGBUILD
|
||||
|
||||
static void nghttp2_default_debug_vfprintf_callback(const char *fmt,
|
||||
va_list args) {
|
||||
vfprintf(stderr, fmt, args);
|
||||
}
|
||||
|
||||
static nghttp2_debug_vprintf_callback static_debug_vprintf_callback =
|
||||
nghttp2_default_debug_vfprintf_callback;
|
||||
|
||||
void nghttp2_debug_vprintf(const char *format, ...) {
|
||||
if (static_debug_vprintf_callback) {
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
static_debug_vprintf_callback(format, args);
|
||||
va_end(args);
|
||||
}
|
||||
}
|
||||
|
||||
void nghttp2_set_debug_vprintf_callback(
|
||||
nghttp2_debug_vprintf_callback debug_vprintf_callback) {
|
||||
static_debug_vprintf_callback = debug_vprintf_callback;
|
||||
}
|
||||
|
||||
#else /* !DEBUGBUILD */
|
||||
|
||||
void nghttp2_set_debug_vprintf_callback(
|
||||
nghttp2_debug_vprintf_callback debug_vprintf_callback _U_) {}
|
||||
|
||||
#endif /* !DEBUGBUILD */
|
||||
43
lib/nghttp2_debug.h
Normal file
43
lib/nghttp2_debug.h
Normal file
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* nghttp2 - HTTP/2 C Library
|
||||
*
|
||||
* Copyright (c) 2016 Tatsuhiro Tsujikawa
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#ifndef NGHTTP2_DEBUG_H
|
||||
#define NGHTTP2_DEBUG_H
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif /* HAVE_CONFIG_H */
|
||||
|
||||
#include <nghttp2/nghttp2.h>
|
||||
|
||||
#ifdef DEBUGBUILD
|
||||
#define DEBUGF(...) nghttp2_debug_vprintf(__VA_ARGS__)
|
||||
void nghttp2_debug_vprintf(const char *format, ...);
|
||||
#else
|
||||
#define DEBUGF(...) \
|
||||
do { \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
#endif /* NGHTTP2_DEBUG_H */
|
||||
@@ -32,6 +32,7 @@
|
||||
#include "nghttp2_helper.h"
|
||||
#include "nghttp2_net.h"
|
||||
#include "nghttp2_priority_spec.h"
|
||||
#include "nghttp2_debug.h"
|
||||
|
||||
void nghttp2_frame_pack_frame_hd(uint8_t *buf, const nghttp2_frame_hd *hd) {
|
||||
nghttp2_put_uint32be(&buf[0], (uint32_t)(hd->length << 8));
|
||||
@@ -184,6 +185,39 @@ void nghttp2_frame_data_init(nghttp2_data *frame, uint8_t flags,
|
||||
|
||||
void nghttp2_frame_data_free(nghttp2_data *frame _U_) {}
|
||||
|
||||
void nghttp2_frame_extension_init(nghttp2_extension *frame, uint8_t type,
|
||||
uint8_t flags, int32_t stream_id,
|
||||
void *payload) {
|
||||
nghttp2_frame_hd_init(&frame->hd, 0, type, flags, stream_id);
|
||||
frame->payload = payload;
|
||||
}
|
||||
|
||||
void nghttp2_frame_extension_free(nghttp2_extension *frame _U_) {}
|
||||
|
||||
void nghttp2_frame_altsvc_init(nghttp2_extension *frame, int32_t stream_id,
|
||||
uint8_t *origin, size_t origin_len,
|
||||
uint8_t *field_value, size_t field_value_len) {
|
||||
nghttp2_ext_altsvc *altsvc;
|
||||
|
||||
nghttp2_frame_hd_init(&frame->hd, 2 + origin_len + field_value_len,
|
||||
NGHTTP2_ALTSVC, NGHTTP2_FLAG_NONE, stream_id);
|
||||
|
||||
altsvc = frame->payload;
|
||||
altsvc->origin = origin;
|
||||
altsvc->origin_len = origin_len;
|
||||
altsvc->field_value = field_value;
|
||||
altsvc->field_value_len = field_value_len;
|
||||
}
|
||||
|
||||
void nghttp2_frame_altsvc_free(nghttp2_extension *frame, nghttp2_mem *mem) {
|
||||
nghttp2_ext_altsvc *altsvc;
|
||||
|
||||
altsvc = frame->payload;
|
||||
/* We use the same buffer for altsvc->origin and
|
||||
altsvc->field_value. */
|
||||
nghttp2_mem_free(mem, altsvc->origin);
|
||||
}
|
||||
|
||||
size_t nghttp2_frame_priority_len(uint8_t flags) {
|
||||
if (flags & NGHTTP2_FLAG_PRIORITY) {
|
||||
return NGHTTP2_PRIORITY_SPECLEN;
|
||||
@@ -219,8 +253,7 @@ static int frame_pack_headers_shared(nghttp2_bufs *bufs,
|
||||
hd = *frame_hd;
|
||||
hd.length = nghttp2_buf_len(buf);
|
||||
|
||||
DEBUGF(fprintf(stderr, "send: HEADERS/PUSH_PROMISE, payloadlen=%zu\n",
|
||||
hd.length));
|
||||
DEBUGF("send: HEADERS/PUSH_PROMISE, payloadlen=%zu\n", hd.length);
|
||||
|
||||
/* We have multiple frame buffers, which means one or more
|
||||
CONTINUATION frame is involved. Remove END_HEADERS flag from the
|
||||
@@ -245,8 +278,7 @@ static int frame_pack_headers_shared(nghttp2_bufs *bufs,
|
||||
|
||||
hd.length = nghttp2_buf_len(buf);
|
||||
|
||||
DEBUGF(fprintf(stderr, "send: int CONTINUATION, payloadlen=%zu\n",
|
||||
hd.length));
|
||||
DEBUGF("send: int CONTINUATION, payloadlen=%zu\n", hd.length);
|
||||
|
||||
buf->pos -= NGHTTP2_FRAME_HDLEN;
|
||||
nghttp2_frame_pack_frame_hd(buf->pos, &hd);
|
||||
@@ -257,8 +289,7 @@ static int frame_pack_headers_shared(nghttp2_bufs *bufs,
|
||||
/* Set END_HEADERS flag for last CONTINUATION */
|
||||
hd.flags = NGHTTP2_FLAG_END_HEADERS;
|
||||
|
||||
DEBUGF(fprintf(stderr, "send: last CONTINUATION, payloadlen=%zu\n",
|
||||
hd.length));
|
||||
DEBUGF("send: last CONTINUATION, payloadlen=%zu\n", hd.length);
|
||||
|
||||
buf->pos -= NGHTTP2_FRAME_HDLEN;
|
||||
nghttp2_frame_pack_frame_hd(buf->pos, &hd);
|
||||
@@ -430,25 +461,11 @@ size_t nghttp2_frame_pack_settings_payload(uint8_t *buf,
|
||||
return NGHTTP2_FRAME_SETTINGS_ENTRY_LENGTH * niv;
|
||||
}
|
||||
|
||||
int nghttp2_frame_unpack_settings_payload(nghttp2_settings *frame,
|
||||
nghttp2_settings_entry *iv,
|
||||
size_t niv, nghttp2_mem *mem) {
|
||||
size_t payloadlen = niv * sizeof(nghttp2_settings_entry);
|
||||
|
||||
if (niv == 0) {
|
||||
frame->iv = NULL;
|
||||
} else {
|
||||
frame->iv = nghttp2_mem_malloc(mem, payloadlen);
|
||||
|
||||
if (frame->iv == NULL) {
|
||||
return NGHTTP2_ERR_NOMEM;
|
||||
}
|
||||
|
||||
memcpy(frame->iv, iv, payloadlen);
|
||||
}
|
||||
|
||||
void nghttp2_frame_unpack_settings_payload(nghttp2_settings *frame,
|
||||
nghttp2_settings_entry *iv,
|
||||
size_t niv) {
|
||||
frame->iv = iv;
|
||||
frame->niv = niv;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void nghttp2_frame_unpack_settings_entry(nghttp2_settings_entry *iv,
|
||||
@@ -659,6 +676,79 @@ 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) {
|
||||
int rv;
|
||||
nghttp2_buf *buf;
|
||||
nghttp2_ext_altsvc *altsvc;
|
||||
|
||||
altsvc = frame->payload;
|
||||
|
||||
buf = &bufs->head->buf;
|
||||
|
||||
assert(nghttp2_buf_avail(buf) >=
|
||||
2 + altsvc->origin_len + altsvc->field_value_len);
|
||||
|
||||
buf->pos -= NGHTTP2_FRAME_HDLEN;
|
||||
|
||||
nghttp2_frame_pack_frame_hd(buf->pos, &frame->hd);
|
||||
|
||||
nghttp2_put_uint16be(buf->last, (uint16_t)altsvc->origin_len);
|
||||
buf->last += 2;
|
||||
|
||||
rv = nghttp2_bufs_add(bufs, altsvc->origin, altsvc->origin_len);
|
||||
|
||||
assert(rv == 0);
|
||||
|
||||
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,
|
||||
size_t origin_len, uint8_t *payload,
|
||||
size_t payloadlen) {
|
||||
nghttp2_ext_altsvc *altsvc;
|
||||
uint8_t *p;
|
||||
|
||||
altsvc = frame->payload;
|
||||
p = payload;
|
||||
|
||||
altsvc->origin = p;
|
||||
|
||||
p += origin_len;
|
||||
|
||||
altsvc->origin_len = origin_len;
|
||||
|
||||
altsvc->field_value = p;
|
||||
altsvc->field_value_len = (size_t)(payload + payloadlen - p);
|
||||
}
|
||||
|
||||
int nghttp2_frame_unpack_altsvc_payload2(nghttp2_extension *frame,
|
||||
const uint8_t *payload,
|
||||
size_t payloadlen, nghttp2_mem *mem) {
|
||||
uint8_t *buf;
|
||||
size_t origin_len;
|
||||
|
||||
if (payloadlen < 2) {
|
||||
return NGHTTP2_FRAME_SIZE_ERROR;
|
||||
}
|
||||
|
||||
origin_len = nghttp2_get_uint16(payload);
|
||||
|
||||
buf = nghttp2_mem_malloc(mem, payloadlen - 2);
|
||||
if (!buf) {
|
||||
return NGHTTP2_ERR_NOMEM;
|
||||
}
|
||||
|
||||
nghttp2_cpymem(buf, payload + 2, payloadlen - 2);
|
||||
|
||||
nghttp2_frame_unpack_altsvc_payload(frame, origin_len, buf, payloadlen - 2);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
nghttp2_settings_entry *nghttp2_frame_iv_copy(const nghttp2_settings_entry *iv,
|
||||
size_t niv, nghttp2_mem *mem) {
|
||||
nghttp2_settings_entry *iv_copy;
|
||||
@@ -779,7 +869,9 @@ int nghttp2_nv_array_copy(nghttp2_nv **nva_ptr, const nghttp2_nv *nva,
|
||||
p->name = nva[i].name;
|
||||
p->namelen = nva[i].namelen;
|
||||
} else {
|
||||
memcpy(data, nva[i].name, nva[i].namelen);
|
||||
if (nva[i].namelen) {
|
||||
memcpy(data, nva[i].name, nva[i].namelen);
|
||||
}
|
||||
p->name = data;
|
||||
p->namelen = nva[i].namelen;
|
||||
data[p->namelen] = '\0';
|
||||
@@ -791,7 +883,9 @@ int nghttp2_nv_array_copy(nghttp2_nv **nva_ptr, const nghttp2_nv *nva,
|
||||
p->value = nva[i].value;
|
||||
p->valuelen = nva[i].valuelen;
|
||||
} else {
|
||||
memcpy(data, nva[i].value, nva[i].valuelen);
|
||||
if (nva[i].valuelen) {
|
||||
memcpy(data, nva[i].value, nva[i].valuelen);
|
||||
}
|
||||
p->value = data;
|
||||
p->valuelen = nva[i].valuelen;
|
||||
data[p->valuelen] = '\0';
|
||||
@@ -838,7 +932,7 @@ static void frame_set_pad(nghttp2_buf *buf, size_t padlen, int framehd_only) {
|
||||
size_t trail_padlen;
|
||||
size_t newlen;
|
||||
|
||||
DEBUGF(fprintf(stderr, "send: padlen=%zu, shift left 1 bytes\n", padlen));
|
||||
DEBUGF("send: padlen=%zu, shift left 1 bytes\n", padlen);
|
||||
|
||||
memmove(buf->pos - 1, buf->pos, NGHTTP2_FRAME_HDLEN);
|
||||
|
||||
@@ -868,7 +962,7 @@ int nghttp2_frame_add_pad(nghttp2_bufs *bufs, nghttp2_frame_hd *hd,
|
||||
nghttp2_buf *buf;
|
||||
|
||||
if (padlen == 0) {
|
||||
DEBUGF(fprintf(stderr, "send: padlen = 0, nothing to do\n"));
|
||||
DEBUGF("send: padlen = 0, nothing to do\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -902,8 +996,7 @@ int nghttp2_frame_add_pad(nghttp2_bufs *bufs, nghttp2_frame_hd *hd,
|
||||
hd->length += padlen;
|
||||
hd->flags |= NGHTTP2_FLAG_PADDED;
|
||||
|
||||
DEBUGF(fprintf(stderr, "send: final payloadlen=%zu, padlen=%zu\n", hd->length,
|
||||
padlen));
|
||||
DEBUGF("send: final payloadlen=%zu, padlen=%zu\n", hd->length, padlen);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -52,14 +52,12 @@
|
||||
#define NGHTTP2_FRAMEBUF_CHUNKLEN \
|
||||
(NGHTTP2_FRAME_HDLEN + 1 + NGHTTP2_MAX_PAYLOADLEN)
|
||||
|
||||
/* Number of inbound buffer */
|
||||
#define NGHTTP2_FRAMEBUF_MAX_NUM 5
|
||||
|
||||
/* The default length of DATA frame payload. */
|
||||
#define NGHTTP2_DATA_PAYLOADLEN NGHTTP2_MAX_FRAME_SIZE_MIN
|
||||
|
||||
/* Maximum headers payload length, calculated in compressed form.
|
||||
This applies to transmission only. */
|
||||
/* Maximum headers block size to send, calculated using
|
||||
nghttp2_hd_deflate_bound(). This is the default value, and can be
|
||||
overridden by nghttp2_option_set_max_send_header_block_size(). */
|
||||
#define NGHTTP2_MAX_HEADERSLEN 65536
|
||||
|
||||
/* The number of bytes for each SETTINGS entry */
|
||||
@@ -72,7 +70,7 @@
|
||||
#define NGHTTP2_MAX_PADLEN 256
|
||||
|
||||
/* Union of extension frame payload */
|
||||
typedef union { int dummy; } nghttp2_ext_frame_payload;
|
||||
typedef union { nghttp2_ext_altsvc altsvc; } nghttp2_ext_frame_payload;
|
||||
|
||||
void nghttp2_frame_pack_frame_hd(uint8_t *buf, const nghttp2_frame_hd *hd);
|
||||
|
||||
@@ -215,18 +213,12 @@ void nghttp2_frame_unpack_settings_entry(nghttp2_settings_entry *iv,
|
||||
const uint8_t *payload);
|
||||
|
||||
/*
|
||||
* Makes a copy of |iv| in frame->settings.iv. The |niv| is assigned
|
||||
* to frame->settings.niv.
|
||||
*
|
||||
* This function returns 0 if it succeeds or one of the following
|
||||
* negative error codes:
|
||||
*
|
||||
* NGHTTP2_ERR_NOMEM
|
||||
* Out of memory.
|
||||
* Initializes payload of frame->settings. The |frame| takes
|
||||
* ownership of |iv|.
|
||||
*/
|
||||
int nghttp2_frame_unpack_settings_payload(nghttp2_settings *frame,
|
||||
nghttp2_settings_entry *iv,
|
||||
size_t niv, nghttp2_mem *mem);
|
||||
void nghttp2_frame_unpack_settings_payload(nghttp2_settings *frame,
|
||||
nghttp2_settings_entry *iv,
|
||||
size_t niv);
|
||||
|
||||
/*
|
||||
* Unpacks SETTINGS payload into |*iv_ptr|. The number of entries are
|
||||
@@ -367,6 +359,45 @@ void nghttp2_frame_unpack_window_update_payload(nghttp2_window_update *frame,
|
||||
const uint8_t *payload,
|
||||
size_t payloadlen);
|
||||
|
||||
/*
|
||||
* Packs ALTSVC frame |frame| in wire frame format and store it in
|
||||
* |bufs|.
|
||||
*
|
||||
* The caller must make sure that nghttp2_bufs_reset(bufs) is called
|
||||
* before calling this function.
|
||||
*
|
||||
* This function always succeeds and returns 0.
|
||||
*/
|
||||
int 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,
|
||||
size_t payloadlen);
|
||||
|
||||
/*
|
||||
* Unpacks ALTSVC wire format into |frame|. This function only exists
|
||||
* for unit test. After allocating buffer for fields, this function
|
||||
* internally calls nghttp2_frame_unpack_altsvc_payload().
|
||||
*
|
||||
* This function returns 0 if it succeeds, or one of the following
|
||||
* negative error codes:
|
||||
*
|
||||
* NGHTTP2_ERR_NOMEM
|
||||
* Out of memory.
|
||||
* NGHTTP2_ERR_FRAME_SIZE_ERROR
|
||||
* The payload is too small.
|
||||
*/
|
||||
int nghttp2_frame_unpack_altsvc_payload2(nghttp2_extension *frame,
|
||||
const uint8_t *payload,
|
||||
size_t payloadlen, nghttp2_mem *mem);
|
||||
|
||||
/*
|
||||
* Initializes HEADERS frame |frame| with given values. |frame| takes
|
||||
* ownership of |nva|, so caller must not free it. If |stream_id| is
|
||||
@@ -439,6 +470,31 @@ void nghttp2_frame_window_update_init(nghttp2_window_update *frame,
|
||||
|
||||
void nghttp2_frame_window_update_free(nghttp2_window_update *frame);
|
||||
|
||||
void nghttp2_frame_extension_init(nghttp2_extension *frame, uint8_t type,
|
||||
uint8_t flags, int32_t stream_id,
|
||||
void *payload);
|
||||
|
||||
void nghttp2_frame_extension_free(nghttp2_extension *frame);
|
||||
|
||||
/*
|
||||
* Initializes ALTSVC frame |frame| with given values. This function
|
||||
* assumes that frame->payload points to nghttp2_ext_altsvc object.
|
||||
* Also |origin| and |field_value| are allocated in single buffer,
|
||||
* starting |origin|. On success, this function takes ownership of
|
||||
* |origin|, so caller must not free it.
|
||||
*/
|
||||
void nghttp2_frame_altsvc_init(nghttp2_extension *frame, int32_t stream_id,
|
||||
uint8_t *origin, size_t origin_len,
|
||||
uint8_t *field_value, size_t field_value_len);
|
||||
|
||||
/*
|
||||
* Frees up resources under |frame|. This function does not free
|
||||
* nghttp2_ext_altsvc object pointed by frame->payload. This function
|
||||
* only frees origin pointed by nghttp2_ext_altsvc.origin. Therefore,
|
||||
* other fields must be allocated in the same buffer with origin.
|
||||
*/
|
||||
void nghttp2_frame_altsvc_free(nghttp2_extension *frame, nghttp2_mem *mem);
|
||||
|
||||
/*
|
||||
* Returns the number of padding bytes after payload. The total
|
||||
* padding length is given in the |padlen|. The returned value does
|
||||
|
||||
1185
lib/nghttp2_hd.c
1185
lib/nghttp2_hd.c
File diff suppressed because it is too large
Load Diff
136
lib/nghttp2_hd.h
136
lib/nghttp2_hd.h
@@ -34,6 +34,7 @@
|
||||
#include "nghttp2_hd_huffman.h"
|
||||
#include "nghttp2_buf.h"
|
||||
#include "nghttp2_mem.h"
|
||||
#include "nghttp2_rcbuf.h"
|
||||
|
||||
#define NGHTTP2_HD_DEFAULT_MAX_BUFFER_SIZE NGHTTP2_DEFAULT_HEADER_TABLE_SIZE
|
||||
#define NGHTTP2_HD_ENTRY_OVERHEAD 32
|
||||
@@ -109,28 +110,32 @@ typedef enum {
|
||||
NGHTTP2_TOKEN_CONNECTION,
|
||||
NGHTTP2_TOKEN_KEEP_ALIVE,
|
||||
NGHTTP2_TOKEN_PROXY_CONNECTION,
|
||||
NGHTTP2_TOKEN_UPGRADE
|
||||
NGHTTP2_TOKEN_UPGRADE,
|
||||
} nghttp2_token;
|
||||
|
||||
typedef enum {
|
||||
NGHTTP2_HD_FLAG_NONE = 0,
|
||||
/* Indicates name was dynamically allocated and must be freed */
|
||||
NGHTTP2_HD_FLAG_NAME_ALLOC = 1,
|
||||
/* Indicates value was dynamically allocated and must be freed */
|
||||
NGHTTP2_HD_FLAG_VALUE_ALLOC = 1 << 1,
|
||||
/* Indicates that the name was gifted to the entry and no copying
|
||||
necessary. */
|
||||
NGHTTP2_HD_FLAG_NAME_GIFT = 1 << 2,
|
||||
/* Indicates that the value was gifted to the entry and no copying
|
||||
necessary. */
|
||||
NGHTTP2_HD_FLAG_VALUE_GIFT = 1 << 3
|
||||
} nghttp2_hd_flags;
|
||||
|
||||
struct nghttp2_hd_entry;
|
||||
typedef struct nghttp2_hd_entry nghttp2_hd_entry;
|
||||
|
||||
typedef struct {
|
||||
/* The buffer containing header field name. NULL-termination is
|
||||
guaranteed. */
|
||||
nghttp2_rcbuf *name;
|
||||
/* The buffer containing header field value. NULL-termination is
|
||||
guaranteed. */
|
||||
nghttp2_rcbuf *value;
|
||||
/* nghttp2_token value for name. It could be -1 if we have no token
|
||||
for that header field name. */
|
||||
int32_t token;
|
||||
/* Bitwise OR of one or more of nghttp2_nv_flag. */
|
||||
uint8_t flags;
|
||||
} nghttp2_hd_nv;
|
||||
|
||||
struct nghttp2_hd_entry {
|
||||
nghttp2_nv nv;
|
||||
/* The header field name/value pair */
|
||||
nghttp2_hd_nv nv;
|
||||
/* This is solely for nghttp2_hd_{deflate,inflate}_get_table_entry
|
||||
APIs to keep backward compatibility. */
|
||||
nghttp2_nv cnv;
|
||||
/* The next entry which shares same bucket in hash table. */
|
||||
nghttp2_hd_entry *next;
|
||||
/* The sequence number. We will increment it by one whenever we
|
||||
@@ -138,14 +143,17 @@ struct nghttp2_hd_entry {
|
||||
uint32_t seq;
|
||||
/* The hash value for header name (nv.name). */
|
||||
uint32_t hash;
|
||||
/* nghttp2_token value for nv.name. It could be -1 if we have no
|
||||
token for that header field name. */
|
||||
int token;
|
||||
/* Reference count */
|
||||
uint8_t ref;
|
||||
uint8_t flags;
|
||||
};
|
||||
|
||||
/* The entry used for static header table. */
|
||||
typedef struct {
|
||||
nghttp2_rcbuf name;
|
||||
nghttp2_rcbuf value;
|
||||
nghttp2_nv cnv;
|
||||
int32_t token;
|
||||
uint32_t hash;
|
||||
} nghttp2_hd_static_entry;
|
||||
|
||||
typedef struct {
|
||||
nghttp2_hd_entry **buffer;
|
||||
size_t mask;
|
||||
@@ -219,24 +227,18 @@ struct nghttp2_hd_deflater {
|
||||
|
||||
struct nghttp2_hd_inflater {
|
||||
nghttp2_hd_context ctx;
|
||||
/* header buffer */
|
||||
nghttp2_bufs nvbufs;
|
||||
/* Stores current state of huffman decoding */
|
||||
nghttp2_hd_huff_decode_context huff_decode_ctx;
|
||||
/* Pointer to the nghttp2_hd_entry which is used current header
|
||||
emission. This is required because in some cases the
|
||||
ent_keep->ref == 0 and we have to keep track of it. */
|
||||
nghttp2_hd_entry *ent_keep;
|
||||
/* Pointer to the name/value pair buffer which is used in the
|
||||
current header emission. */
|
||||
uint8_t *nv_keep;
|
||||
/* header buffer */
|
||||
nghttp2_buf namebuf, valuebuf;
|
||||
nghttp2_rcbuf *namercbuf, *valuercbuf;
|
||||
/* Pointer to the name/value pair which are used in the current
|
||||
header emission. */
|
||||
nghttp2_rcbuf *nv_name_keep, *nv_value_keep;
|
||||
/* The number of bytes to read */
|
||||
size_t left;
|
||||
/* The index in indexed repr or indexed name */
|
||||
size_t index;
|
||||
/* The length of new name encoded in literal. For huffman encoded
|
||||
string, this is the length after it is decoded. */
|
||||
size_t newnamelen;
|
||||
/* The maximum header table size the inflater supports. This is the
|
||||
same value transmitted in SETTINGS_HEADER_TABLE_SIZE */
|
||||
size_t settings_hd_table_bufsize_max;
|
||||
@@ -256,24 +258,16 @@ struct nghttp2_hd_inflater {
|
||||
};
|
||||
|
||||
/*
|
||||
* Initializes the |ent| members. If NGHTTP2_HD_FLAG_NAME_ALLOC bit
|
||||
* set in the |flags|, the content pointed by the |name| with length
|
||||
* |namelen| is copied. Likewise, if NGHTTP2_HD_FLAG_VALUE_ALLOC bit
|
||||
* set in the |flags|, the content pointed by the |value| with length
|
||||
* |valuelen| is copied. The |token| is enum number looked up by
|
||||
* |name|. It could be -1 if we don't have that enum value.
|
||||
*
|
||||
* This function returns 0 if it succeeds, or one of the following
|
||||
* negative error codes:
|
||||
*
|
||||
* NGHTTP2_ERR_NOMEM
|
||||
* Out of memory.
|
||||
* Initializes the |ent| members. The reference counts of nv->name
|
||||
* and nv->value are increased by one for each.
|
||||
*/
|
||||
int nghttp2_hd_entry_init(nghttp2_hd_entry *ent, uint8_t flags, uint8_t *name,
|
||||
size_t namelen, uint8_t *value, size_t valuelen,
|
||||
int token, nghttp2_mem *mem);
|
||||
void nghttp2_hd_entry_init(nghttp2_hd_entry *ent, nghttp2_hd_nv *nv);
|
||||
|
||||
void nghttp2_hd_entry_free(nghttp2_hd_entry *ent, nghttp2_mem *mem);
|
||||
/*
|
||||
* This function decreases the reference counts of nv->name and
|
||||
* nv->value.
|
||||
*/
|
||||
void nghttp2_hd_entry_free(nghttp2_hd_entry *ent);
|
||||
|
||||
/*
|
||||
* Initializes |deflater| for deflating name/values pairs.
|
||||
@@ -294,7 +288,7 @@ int nghttp2_hd_deflate_init(nghttp2_hd_deflater *deflater, nghttp2_mem *mem);
|
||||
/*
|
||||
* Initializes |deflater| for deflating name/values pairs.
|
||||
*
|
||||
* The encoder only uses up to |deflate_hd_table_bufsize_max| bytes
|
||||
* The encoder only uses up to |max_deflate_dynamic_table_size| bytes
|
||||
* for header table even if the larger value is specified later in
|
||||
* nghttp2_hd_change_table_size().
|
||||
*
|
||||
@@ -305,7 +299,7 @@ int nghttp2_hd_deflate_init(nghttp2_hd_deflater *deflater, nghttp2_mem *mem);
|
||||
* Out of memory.
|
||||
*/
|
||||
int nghttp2_hd_deflate_init2(nghttp2_hd_deflater *deflater,
|
||||
size_t deflate_hd_table_bufsize_max,
|
||||
size_t max_deflate_dynamic_table_size,
|
||||
nghttp2_mem *mem);
|
||||
|
||||
/*
|
||||
@@ -354,16 +348,14 @@ int nghttp2_hd_inflate_init(nghttp2_hd_inflater *inflater, nghttp2_mem *mem);
|
||||
void nghttp2_hd_inflate_free(nghttp2_hd_inflater *inflater);
|
||||
|
||||
/*
|
||||
* Similar to nghttp2_hd_inflate_hd(), but this takes additional
|
||||
* output parameter |token|. On successful header emission, it
|
||||
* contains nghttp2_token value for nv_out->name. It could be -1 if
|
||||
* we don't have enum value for the name. Other than that return
|
||||
* values and semantics are the same as nghttp2_hd_inflate_hd().
|
||||
* Similar to nghttp2_hd_inflate_hd(), but this takes nghttp2_hd_nv
|
||||
* instead of nghttp2_nv as output parameter |nv_out|. Other than
|
||||
* that return values and semantics are the same as
|
||||
* nghttp2_hd_inflate_hd().
|
||||
*/
|
||||
ssize_t nghttp2_hd_inflate_hd2(nghttp2_hd_inflater *inflater,
|
||||
nghttp2_nv *nv_out, int *inflate_flags,
|
||||
int *token, uint8_t *in, size_t inlen,
|
||||
int in_final);
|
||||
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);
|
||||
|
||||
/* For unittesting purpose */
|
||||
int nghttp2_hd_emit_indname_block(nghttp2_bufs *bufs, size_t index,
|
||||
@@ -377,11 +369,10 @@ int nghttp2_hd_emit_newname_block(nghttp2_bufs *bufs, nghttp2_nv *nv,
|
||||
int nghttp2_hd_emit_table_size(nghttp2_bufs *bufs, size_t table_size);
|
||||
|
||||
/* For unittesting purpose */
|
||||
nghttp2_hd_entry *nghttp2_hd_table_get(nghttp2_hd_context *context,
|
||||
size_t index);
|
||||
nghttp2_hd_nv nghttp2_hd_table_get(nghttp2_hd_context *context, size_t index);
|
||||
|
||||
/* For unittesting purpose */
|
||||
ssize_t nghttp2_hd_decode_length(uint32_t *res, size_t *shift_ptr, int *final,
|
||||
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);
|
||||
|
||||
@@ -414,14 +405,13 @@ int nghttp2_hd_huff_encode(nghttp2_bufs *bufs, const uint8_t *src,
|
||||
void nghttp2_hd_huff_decode_context_init(nghttp2_hd_huff_decode_context *ctx);
|
||||
|
||||
/*
|
||||
* Decodes the given data |src| with length |srclen|. The |ctx| must
|
||||
* Decodes the given data |src| with length |srclen|. The |ctx| must
|
||||
* be initialized by nghttp2_hd_huff_decode_context_init(). The result
|
||||
* will be added to |dest|. This function may expand |dest| as
|
||||
* needed. The caller is responsible to release the memory of |dest|
|
||||
* by calling nghttp2_bufs_free().
|
||||
* will be written to |buf|. This function assumes that |buf| has the
|
||||
* enough room to store the decoded byte string.
|
||||
*
|
||||
* The caller must set the |final| to nonzero if the given input is
|
||||
* the final block.
|
||||
* The caller must set the |fin| to nonzero if the given input is the
|
||||
* final block.
|
||||
*
|
||||
* This function returns the number of read bytes from the |in|.
|
||||
*
|
||||
@@ -430,13 +420,11 @@ void nghttp2_hd_huff_decode_context_init(nghttp2_hd_huff_decode_context *ctx);
|
||||
*
|
||||
* NGHTTP2_ERR_NOMEM
|
||||
* Out of memory.
|
||||
* NGHTTP2_ERR_BUFFER_ERROR
|
||||
* Maximum buffer capacity size exceeded.
|
||||
* NGHTTP2_ERR_HEADER_COMP
|
||||
* Decoding process has failed.
|
||||
*/
|
||||
ssize_t nghttp2_hd_huff_decode(nghttp2_hd_huff_decode_context *ctx,
|
||||
nghttp2_bufs *bufs, const uint8_t *src,
|
||||
size_t srclen, int final);
|
||||
nghttp2_buf *buf, const uint8_t *src,
|
||||
size_t srclen, int fin);
|
||||
|
||||
#endif /* NGHTTP2_HD_H */
|
||||
|
||||
@@ -64,15 +64,44 @@ static ssize_t huff_encode_sym(nghttp2_bufs *bufs, size_t *avail_ptr,
|
||||
code <<= 8 - (nbits & 0x7);
|
||||
}
|
||||
|
||||
/* we lose at most 3 bytes, but it is not critical in practice */
|
||||
if (*avail_ptr < (nbits + 7) / 8) {
|
||||
rv = nghttp2_bufs_advance(bufs);
|
||||
/* slow path */
|
||||
if (nbits > 24) {
|
||||
rv = nghttp2_bufs_addb(bufs, (uint8_t)(code >> 24));
|
||||
if (rv != 0) {
|
||||
return rv;
|
||||
}
|
||||
nbits -= 8;
|
||||
}
|
||||
if (nbits > 16) {
|
||||
rv = nghttp2_bufs_addb(bufs, (uint8_t)(code >> 16));
|
||||
if (rv != 0) {
|
||||
return rv;
|
||||
}
|
||||
nbits -= 8;
|
||||
}
|
||||
if (nbits > 8) {
|
||||
rv = nghttp2_bufs_addb(bufs, (uint8_t)(code >> 8));
|
||||
if (rv != 0) {
|
||||
return rv;
|
||||
}
|
||||
nbits -= 8;
|
||||
}
|
||||
if (nbits == 8) {
|
||||
rv = nghttp2_bufs_addb(bufs, (uint8_t)code);
|
||||
if (rv != 0) {
|
||||
return rv;
|
||||
}
|
||||
*avail_ptr = nghttp2_bufs_cur_avail(bufs);
|
||||
return 8;
|
||||
}
|
||||
|
||||
rv = nghttp2_bufs_addb_hold(bufs, (uint8_t)code);
|
||||
if (rv != 0) {
|
||||
return rv;
|
||||
}
|
||||
*avail_ptr = nghttp2_bufs_cur_avail(bufs);
|
||||
/* we assume that we at least 3 buffer space available */
|
||||
assert(*avail_ptr >= 3);
|
||||
return (ssize_t)(8 - nbits);
|
||||
}
|
||||
|
||||
/* fast path, since most code is less than 8 */
|
||||
@@ -166,31 +195,10 @@ void nghttp2_hd_huff_decode_context_init(nghttp2_hd_huff_decode_context *ctx) {
|
||||
ctx->accept = 1;
|
||||
}
|
||||
|
||||
/* Use macro to make the code simpler..., but error case is tricky.
|
||||
We spent most of the CPU in decoding, so we are doing this
|
||||
thing. */
|
||||
#define hd_huff_decode_sym_emit(bufs, sym, avail) \
|
||||
do { \
|
||||
if ((avail)) { \
|
||||
nghttp2_bufs_fast_addb((bufs), (sym)); \
|
||||
--(avail); \
|
||||
} else { \
|
||||
rv = nghttp2_bufs_addb((bufs), (sym)); \
|
||||
if (rv != 0) { \
|
||||
return rv; \
|
||||
} \
|
||||
(avail) = nghttp2_bufs_cur_avail((bufs)); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
ssize_t nghttp2_hd_huff_decode(nghttp2_hd_huff_decode_context *ctx,
|
||||
nghttp2_bufs *bufs, const uint8_t *src,
|
||||
nghttp2_buf *buf, const uint8_t *src,
|
||||
size_t srclen, int final) {
|
||||
size_t i;
|
||||
int rv;
|
||||
size_t avail;
|
||||
|
||||
avail = nghttp2_bufs_cur_avail(bufs);
|
||||
|
||||
/* We use the decoding algorithm described in
|
||||
http://graphics.ics.uci.edu/pub/Prefix.pdf */
|
||||
@@ -202,8 +210,7 @@ ssize_t nghttp2_hd_huff_decode(nghttp2_hd_huff_decode_context *ctx,
|
||||
return NGHTTP2_ERR_HEADER_COMP;
|
||||
}
|
||||
if (t->flags & NGHTTP2_HUFF_SYM) {
|
||||
/* this is macro, and may return from this function on error */
|
||||
hd_huff_decode_sym_emit(bufs, t->sym, avail);
|
||||
*buf->last++ = t->sym;
|
||||
}
|
||||
|
||||
t = &huff_decode_table[t->state][src[i] & 0xf];
|
||||
@@ -211,8 +218,7 @@ ssize_t nghttp2_hd_huff_decode(nghttp2_hd_huff_decode_context *ctx,
|
||||
return NGHTTP2_ERR_HEADER_COMP;
|
||||
}
|
||||
if (t->flags & NGHTTP2_HUFF_SYM) {
|
||||
/* this is macro, and may return from this function on error */
|
||||
hd_huff_decode_sym_emit(bufs, t->sym, avail);
|
||||
*buf->last++ = t->sym;
|
||||
}
|
||||
|
||||
ctx->state = t->state;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -189,8 +189,8 @@ int nghttp2_adjust_local_window_size(int32_t *local_window_size_ptr,
|
||||
account it in *delta_ptr. */
|
||||
*recv_window_size_ptr = recv_reduction_delta;
|
||||
}
|
||||
/* recv_reduction_delta must be paied from *delta_ptr, since it
|
||||
was added in window size reduction (see below). */
|
||||
/* recv_reduction_delta must be paid from *delta_ptr, since it was
|
||||
added in window size reduction (see below). */
|
||||
*delta_ptr -= recv_reduction_delta;
|
||||
|
||||
return 0;
|
||||
@@ -213,6 +213,38 @@ int nghttp2_adjust_local_window_size(int32_t *local_window_size_ptr,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int nghttp2_increase_local_window_size(int32_t *local_window_size_ptr,
|
||||
int32_t *recv_window_size_ptr,
|
||||
int32_t *recv_reduction_ptr,
|
||||
int32_t *delta_ptr) {
|
||||
int32_t recv_reduction_delta;
|
||||
int32_t delta;
|
||||
|
||||
delta = *delta_ptr;
|
||||
|
||||
assert(delta >= 0);
|
||||
|
||||
/* The delta size is strictly more than received bytes. Increase
|
||||
local_window_size by that difference |delta|. */
|
||||
if (*local_window_size_ptr > NGHTTP2_MAX_WINDOW_SIZE - delta) {
|
||||
return NGHTTP2_ERR_FLOW_CONTROL;
|
||||
}
|
||||
|
||||
*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_ptr -= recv_reduction_delta;
|
||||
|
||||
*recv_window_size_ptr += recv_reduction_delta;
|
||||
|
||||
/* recv_reduction_delta must be paid from *delta_ptr, since it was
|
||||
added in window size reduction (see below). */
|
||||
*delta_ptr -= recv_reduction_delta;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int nghttp2_should_send_window_update(int32_t local_window_size,
|
||||
int32_t recv_window_size) {
|
||||
return recv_window_size > 0 && recv_window_size >= local_window_size / 2;
|
||||
@@ -288,6 +320,8 @@ const char *nghttp2_strerror(int error_code) {
|
||||
return "Stream was refused";
|
||||
case NGHTTP2_ERR_INTERNAL:
|
||||
return "Internal error";
|
||||
case NGHTTP2_ERR_CANCEL:
|
||||
return "Cancel";
|
||||
case NGHTTP2_ERR_NOMEM:
|
||||
return "Out of memory";
|
||||
case NGHTTP2_ERR_CALLBACK_FAILURE:
|
||||
@@ -304,58 +338,70 @@ const char *nghttp2_strerror(int error_code) {
|
||||
|
||||
/* Generated by gennmchartbl.py */
|
||||
static int VALID_HD_NAME_CHARS[] = {
|
||||
0 /* NUL */, 0 /* SOH */, 0 /* STX */, 0 /* ETX */, 0 /* EOT */,
|
||||
0 /* ENQ */, 0 /* ACK */, 0 /* BEL */, 0 /* BS */, 0 /* HT */,
|
||||
0 /* LF */, 0 /* VT */, 0 /* FF */, 0 /* CR */, 0 /* SO */,
|
||||
0 /* SI */, 0 /* DLE */, 0 /* DC1 */, 0 /* DC2 */, 0 /* DC3 */,
|
||||
0 /* DC4 */, 0 /* NAK */, 0 /* SYN */, 0 /* ETB */, 0 /* CAN */,
|
||||
0 /* EM */, 0 /* SUB */, 0 /* ESC */, 0 /* FS */, 0 /* GS */,
|
||||
0 /* RS */, 0 /* US */, 0 /* SPC */, 1 /* ! */, 0 /* " */,
|
||||
1 /* # */, 1 /* $ */, 1 /* % */, 1 /* & */, 1 /* ' */,
|
||||
0 /* ( */, 0 /* ) */, 1 /* * */, 1 /* + */, 0 /* , */,
|
||||
1 /* - */, 1 /* . */, 0 /* / */, 1 /* 0 */, 1 /* 1 */,
|
||||
1 /* 2 */, 1 /* 3 */, 1 /* 4 */, 1 /* 5 */, 1 /* 6 */,
|
||||
1 /* 7 */, 1 /* 8 */, 1 /* 9 */, 0 /* : */, 0 /* ; */,
|
||||
0 /* < */, 0 /* = */, 0 /* > */, 0 /* ? */, 0 /* @ */,
|
||||
0 /* A */, 0 /* B */, 0 /* C */, 0 /* D */, 0 /* E */,
|
||||
0 /* F */, 0 /* G */, 0 /* H */, 0 /* I */, 0 /* J */,
|
||||
0 /* K */, 0 /* L */, 0 /* M */, 0 /* N */, 0 /* O */,
|
||||
0 /* P */, 0 /* Q */, 0 /* R */, 0 /* S */, 0 /* T */,
|
||||
0 /* U */, 0 /* V */, 0 /* W */, 0 /* X */, 0 /* Y */,
|
||||
0 /* Z */, 0 /* [ */, 0 /* \ */, 0 /* ] */, 1 /* ^ */,
|
||||
1 /* _ */, 1 /* ` */, 1 /* a */, 1 /* b */, 1 /* c */,
|
||||
1 /* d */, 1 /* e */, 1 /* f */, 1 /* g */, 1 /* h */,
|
||||
1 /* i */, 1 /* j */, 1 /* k */, 1 /* l */, 1 /* m */,
|
||||
1 /* n */, 1 /* o */, 1 /* p */, 1 /* q */, 1 /* r */,
|
||||
1 /* s */, 1 /* t */, 1 /* u */, 1 /* v */, 1 /* w */,
|
||||
1 /* x */, 1 /* y */, 1 /* z */, 0 /* { */, 1 /* | */,
|
||||
0 /* } */, 1 /* ~ */, 0 /* DEL */, 0 /* 0x80 */, 0 /* 0x81 */,
|
||||
0 /* 0x82 */, 0 /* 0x83 */, 0 /* 0x84 */, 0 /* 0x85 */, 0 /* 0x86 */,
|
||||
0 /* 0x87 */, 0 /* 0x88 */, 0 /* 0x89 */, 0 /* 0x8a */, 0 /* 0x8b */,
|
||||
0 /* 0x8c */, 0 /* 0x8d */, 0 /* 0x8e */, 0 /* 0x8f */, 0 /* 0x90 */,
|
||||
0 /* 0x91 */, 0 /* 0x92 */, 0 /* 0x93 */, 0 /* 0x94 */, 0 /* 0x95 */,
|
||||
0 /* 0x96 */, 0 /* 0x97 */, 0 /* 0x98 */, 0 /* 0x99 */, 0 /* 0x9a */,
|
||||
0 /* 0x9b */, 0 /* 0x9c */, 0 /* 0x9d */, 0 /* 0x9e */, 0 /* 0x9f */,
|
||||
0 /* 0xa0 */, 0 /* 0xa1 */, 0 /* 0xa2 */, 0 /* 0xa3 */, 0 /* 0xa4 */,
|
||||
0 /* 0xa5 */, 0 /* 0xa6 */, 0 /* 0xa7 */, 0 /* 0xa8 */, 0 /* 0xa9 */,
|
||||
0 /* 0xaa */, 0 /* 0xab */, 0 /* 0xac */, 0 /* 0xad */, 0 /* 0xae */,
|
||||
0 /* 0xaf */, 0 /* 0xb0 */, 0 /* 0xb1 */, 0 /* 0xb2 */, 0 /* 0xb3 */,
|
||||
0 /* 0xb4 */, 0 /* 0xb5 */, 0 /* 0xb6 */, 0 /* 0xb7 */, 0 /* 0xb8 */,
|
||||
0 /* 0xb9 */, 0 /* 0xba */, 0 /* 0xbb */, 0 /* 0xbc */, 0 /* 0xbd */,
|
||||
0 /* 0xbe */, 0 /* 0xbf */, 0 /* 0xc0 */, 0 /* 0xc1 */, 0 /* 0xc2 */,
|
||||
0 /* 0xc3 */, 0 /* 0xc4 */, 0 /* 0xc5 */, 0 /* 0xc6 */, 0 /* 0xc7 */,
|
||||
0 /* 0xc8 */, 0 /* 0xc9 */, 0 /* 0xca */, 0 /* 0xcb */, 0 /* 0xcc */,
|
||||
0 /* 0xcd */, 0 /* 0xce */, 0 /* 0xcf */, 0 /* 0xd0 */, 0 /* 0xd1 */,
|
||||
0 /* 0xd2 */, 0 /* 0xd3 */, 0 /* 0xd4 */, 0 /* 0xd5 */, 0 /* 0xd6 */,
|
||||
0 /* 0xd7 */, 0 /* 0xd8 */, 0 /* 0xd9 */, 0 /* 0xda */, 0 /* 0xdb */,
|
||||
0 /* 0xdc */, 0 /* 0xdd */, 0 /* 0xde */, 0 /* 0xdf */, 0 /* 0xe0 */,
|
||||
0 /* 0xe1 */, 0 /* 0xe2 */, 0 /* 0xe3 */, 0 /* 0xe4 */, 0 /* 0xe5 */,
|
||||
0 /* 0xe6 */, 0 /* 0xe7 */, 0 /* 0xe8 */, 0 /* 0xe9 */, 0 /* 0xea */,
|
||||
0 /* 0xeb */, 0 /* 0xec */, 0 /* 0xed */, 0 /* 0xee */, 0 /* 0xef */,
|
||||
0 /* 0xf0 */, 0 /* 0xf1 */, 0 /* 0xf2 */, 0 /* 0xf3 */, 0 /* 0xf4 */,
|
||||
0 /* 0xf5 */, 0 /* 0xf6 */, 0 /* 0xf7 */, 0 /* 0xf8 */, 0 /* 0xf9 */,
|
||||
0 /* 0xfa */, 0 /* 0xfb */, 0 /* 0xfc */, 0 /* 0xfd */, 0 /* 0xfe */,
|
||||
0 /* 0xff */
|
||||
0 /* NUL */, 0 /* SOH */, 0 /* STX */, 0 /* ETX */,
|
||||
0 /* EOT */, 0 /* ENQ */, 0 /* ACK */, 0 /* BEL */,
|
||||
0 /* BS */, 0 /* HT */, 0 /* LF */, 0 /* VT */,
|
||||
0 /* FF */, 0 /* CR */, 0 /* SO */, 0 /* SI */,
|
||||
0 /* DLE */, 0 /* DC1 */, 0 /* DC2 */, 0 /* DC3 */,
|
||||
0 /* DC4 */, 0 /* NAK */, 0 /* SYN */, 0 /* ETB */,
|
||||
0 /* CAN */, 0 /* EM */, 0 /* SUB */, 0 /* ESC */,
|
||||
0 /* FS */, 0 /* GS */, 0 /* RS */, 0 /* US */,
|
||||
0 /* SPC */, 1 /* ! */, 0 /* " */, 1 /* # */,
|
||||
1 /* $ */, 1 /* % */, 1 /* & */, 1 /* ' */,
|
||||
0 /* ( */, 0 /* ) */, 1 /* * */, 1 /* + */,
|
||||
0 /* , */, 1 /* - */, 1 /* . */, 0 /* / */,
|
||||
1 /* 0 */, 1 /* 1 */, 1 /* 2 */, 1 /* 3 */,
|
||||
1 /* 4 */, 1 /* 5 */, 1 /* 6 */, 1 /* 7 */,
|
||||
1 /* 8 */, 1 /* 9 */, 0 /* : */, 0 /* ; */,
|
||||
0 /* < */, 0 /* = */, 0 /* > */, 0 /* ? */,
|
||||
0 /* @ */, 0 /* A */, 0 /* B */, 0 /* C */,
|
||||
0 /* D */, 0 /* E */, 0 /* F */, 0 /* G */,
|
||||
0 /* H */, 0 /* I */, 0 /* J */, 0 /* K */,
|
||||
0 /* L */, 0 /* M */, 0 /* N */, 0 /* O */,
|
||||
0 /* P */, 0 /* Q */, 0 /* R */, 0 /* S */,
|
||||
0 /* T */, 0 /* U */, 0 /* V */, 0 /* W */,
|
||||
0 /* X */, 0 /* Y */, 0 /* Z */, 0 /* [ */,
|
||||
0 /* \ */, 0 /* ] */, 1 /* ^ */, 1 /* _ */,
|
||||
1 /* ` */, 1 /* a */, 1 /* b */, 1 /* c */,
|
||||
1 /* d */, 1 /* e */, 1 /* f */, 1 /* g */,
|
||||
1 /* h */, 1 /* i */, 1 /* j */, 1 /* k */,
|
||||
1 /* l */, 1 /* m */, 1 /* n */, 1 /* o */,
|
||||
1 /* p */, 1 /* q */, 1 /* r */, 1 /* s */,
|
||||
1 /* t */, 1 /* u */, 1 /* v */, 1 /* w */,
|
||||
1 /* x */, 1 /* y */, 1 /* z */, 0 /* { */,
|
||||
1 /* | */, 0 /* } */, 1 /* ~ */, 0 /* DEL */,
|
||||
0 /* 0x80 */, 0 /* 0x81 */, 0 /* 0x82 */, 0 /* 0x83 */,
|
||||
0 /* 0x84 */, 0 /* 0x85 */, 0 /* 0x86 */, 0 /* 0x87 */,
|
||||
0 /* 0x88 */, 0 /* 0x89 */, 0 /* 0x8a */, 0 /* 0x8b */,
|
||||
0 /* 0x8c */, 0 /* 0x8d */, 0 /* 0x8e */, 0 /* 0x8f */,
|
||||
0 /* 0x90 */, 0 /* 0x91 */, 0 /* 0x92 */, 0 /* 0x93 */,
|
||||
0 /* 0x94 */, 0 /* 0x95 */, 0 /* 0x96 */, 0 /* 0x97 */,
|
||||
0 /* 0x98 */, 0 /* 0x99 */, 0 /* 0x9a */, 0 /* 0x9b */,
|
||||
0 /* 0x9c */, 0 /* 0x9d */, 0 /* 0x9e */, 0 /* 0x9f */,
|
||||
0 /* 0xa0 */, 0 /* 0xa1 */, 0 /* 0xa2 */, 0 /* 0xa3 */,
|
||||
0 /* 0xa4 */, 0 /* 0xa5 */, 0 /* 0xa6 */, 0 /* 0xa7 */,
|
||||
0 /* 0xa8 */, 0 /* 0xa9 */, 0 /* 0xaa */, 0 /* 0xab */,
|
||||
0 /* 0xac */, 0 /* 0xad */, 0 /* 0xae */, 0 /* 0xaf */,
|
||||
0 /* 0xb0 */, 0 /* 0xb1 */, 0 /* 0xb2 */, 0 /* 0xb3 */,
|
||||
0 /* 0xb4 */, 0 /* 0xb5 */, 0 /* 0xb6 */, 0 /* 0xb7 */,
|
||||
0 /* 0xb8 */, 0 /* 0xb9 */, 0 /* 0xba */, 0 /* 0xbb */,
|
||||
0 /* 0xbc */, 0 /* 0xbd */, 0 /* 0xbe */, 0 /* 0xbf */,
|
||||
0 /* 0xc0 */, 0 /* 0xc1 */, 0 /* 0xc2 */, 0 /* 0xc3 */,
|
||||
0 /* 0xc4 */, 0 /* 0xc5 */, 0 /* 0xc6 */, 0 /* 0xc7 */,
|
||||
0 /* 0xc8 */, 0 /* 0xc9 */, 0 /* 0xca */, 0 /* 0xcb */,
|
||||
0 /* 0xcc */, 0 /* 0xcd */, 0 /* 0xce */, 0 /* 0xcf */,
|
||||
0 /* 0xd0 */, 0 /* 0xd1 */, 0 /* 0xd2 */, 0 /* 0xd3 */,
|
||||
0 /* 0xd4 */, 0 /* 0xd5 */, 0 /* 0xd6 */, 0 /* 0xd7 */,
|
||||
0 /* 0xd8 */, 0 /* 0xd9 */, 0 /* 0xda */, 0 /* 0xdb */,
|
||||
0 /* 0xdc */, 0 /* 0xdd */, 0 /* 0xde */, 0 /* 0xdf */,
|
||||
0 /* 0xe0 */, 0 /* 0xe1 */, 0 /* 0xe2 */, 0 /* 0xe3 */,
|
||||
0 /* 0xe4 */, 0 /* 0xe5 */, 0 /* 0xe6 */, 0 /* 0xe7 */,
|
||||
0 /* 0xe8 */, 0 /* 0xe9 */, 0 /* 0xea */, 0 /* 0xeb */,
|
||||
0 /* 0xec */, 0 /* 0xed */, 0 /* 0xee */, 0 /* 0xef */,
|
||||
0 /* 0xf0 */, 0 /* 0xf1 */, 0 /* 0xf2 */, 0 /* 0xf3 */,
|
||||
0 /* 0xf4 */, 0 /* 0xf5 */, 0 /* 0xf6 */, 0 /* 0xf7 */,
|
||||
0 /* 0xf8 */, 0 /* 0xf9 */, 0 /* 0xfa */, 0 /* 0xfb */,
|
||||
0 /* 0xfc */, 0 /* 0xfd */, 0 /* 0xfe */, 0 /* 0xff */
|
||||
};
|
||||
|
||||
int nghttp2_check_header_name(const uint8_t *name, size_t len) {
|
||||
@@ -380,58 +426,70 @@ int nghttp2_check_header_name(const uint8_t *name, size_t len) {
|
||||
|
||||
/* Generated by genvchartbl.py */
|
||||
static int VALID_HD_VALUE_CHARS[] = {
|
||||
0 /* NUL */, 0 /* SOH */, 0 /* STX */, 0 /* ETX */, 0 /* EOT */,
|
||||
0 /* ENQ */, 0 /* ACK */, 0 /* BEL */, 0 /* BS */, 1 /* HT */,
|
||||
0 /* LF */, 0 /* VT */, 0 /* FF */, 0 /* CR */, 0 /* SO */,
|
||||
0 /* SI */, 0 /* DLE */, 0 /* DC1 */, 0 /* DC2 */, 0 /* DC3 */,
|
||||
0 /* DC4 */, 0 /* NAK */, 0 /* SYN */, 0 /* ETB */, 0 /* CAN */,
|
||||
0 /* EM */, 0 /* SUB */, 0 /* ESC */, 0 /* FS */, 0 /* GS */,
|
||||
0 /* RS */, 0 /* US */, 1 /* SPC */, 1 /* ! */, 1 /* " */,
|
||||
1 /* # */, 1 /* $ */, 1 /* % */, 1 /* & */, 1 /* ' */,
|
||||
1 /* ( */, 1 /* ) */, 1 /* * */, 1 /* + */, 1 /* , */,
|
||||
1 /* - */, 1 /* . */, 1 /* / */, 1 /* 0 */, 1 /* 1 */,
|
||||
1 /* 2 */, 1 /* 3 */, 1 /* 4 */, 1 /* 5 */, 1 /* 6 */,
|
||||
1 /* 7 */, 1 /* 8 */, 1 /* 9 */, 1 /* : */, 1 /* ; */,
|
||||
1 /* < */, 1 /* = */, 1 /* > */, 1 /* ? */, 1 /* @ */,
|
||||
1 /* A */, 1 /* B */, 1 /* C */, 1 /* D */, 1 /* E */,
|
||||
1 /* F */, 1 /* G */, 1 /* H */, 1 /* I */, 1 /* J */,
|
||||
1 /* K */, 1 /* L */, 1 /* M */, 1 /* N */, 1 /* O */,
|
||||
1 /* P */, 1 /* Q */, 1 /* R */, 1 /* S */, 1 /* T */,
|
||||
1 /* U */, 1 /* V */, 1 /* W */, 1 /* X */, 1 /* Y */,
|
||||
1 /* Z */, 1 /* [ */, 1 /* \ */, 1 /* ] */, 1 /* ^ */,
|
||||
1 /* _ */, 1 /* ` */, 1 /* a */, 1 /* b */, 1 /* c */,
|
||||
1 /* d */, 1 /* e */, 1 /* f */, 1 /* g */, 1 /* h */,
|
||||
1 /* i */, 1 /* j */, 1 /* k */, 1 /* l */, 1 /* m */,
|
||||
1 /* n */, 1 /* o */, 1 /* p */, 1 /* q */, 1 /* r */,
|
||||
1 /* s */, 1 /* t */, 1 /* u */, 1 /* v */, 1 /* w */,
|
||||
1 /* x */, 1 /* y */, 1 /* z */, 1 /* { */, 1 /* | */,
|
||||
1 /* } */, 1 /* ~ */, 0 /* DEL */, 1 /* 0x80 */, 1 /* 0x81 */,
|
||||
1 /* 0x82 */, 1 /* 0x83 */, 1 /* 0x84 */, 1 /* 0x85 */, 1 /* 0x86 */,
|
||||
1 /* 0x87 */, 1 /* 0x88 */, 1 /* 0x89 */, 1 /* 0x8a */, 1 /* 0x8b */,
|
||||
1 /* 0x8c */, 1 /* 0x8d */, 1 /* 0x8e */, 1 /* 0x8f */, 1 /* 0x90 */,
|
||||
1 /* 0x91 */, 1 /* 0x92 */, 1 /* 0x93 */, 1 /* 0x94 */, 1 /* 0x95 */,
|
||||
1 /* 0x96 */, 1 /* 0x97 */, 1 /* 0x98 */, 1 /* 0x99 */, 1 /* 0x9a */,
|
||||
1 /* 0x9b */, 1 /* 0x9c */, 1 /* 0x9d */, 1 /* 0x9e */, 1 /* 0x9f */,
|
||||
1 /* 0xa0 */, 1 /* 0xa1 */, 1 /* 0xa2 */, 1 /* 0xa3 */, 1 /* 0xa4 */,
|
||||
1 /* 0xa5 */, 1 /* 0xa6 */, 1 /* 0xa7 */, 1 /* 0xa8 */, 1 /* 0xa9 */,
|
||||
1 /* 0xaa */, 1 /* 0xab */, 1 /* 0xac */, 1 /* 0xad */, 1 /* 0xae */,
|
||||
1 /* 0xaf */, 1 /* 0xb0 */, 1 /* 0xb1 */, 1 /* 0xb2 */, 1 /* 0xb3 */,
|
||||
1 /* 0xb4 */, 1 /* 0xb5 */, 1 /* 0xb6 */, 1 /* 0xb7 */, 1 /* 0xb8 */,
|
||||
1 /* 0xb9 */, 1 /* 0xba */, 1 /* 0xbb */, 1 /* 0xbc */, 1 /* 0xbd */,
|
||||
1 /* 0xbe */, 1 /* 0xbf */, 1 /* 0xc0 */, 1 /* 0xc1 */, 1 /* 0xc2 */,
|
||||
1 /* 0xc3 */, 1 /* 0xc4 */, 1 /* 0xc5 */, 1 /* 0xc6 */, 1 /* 0xc7 */,
|
||||
1 /* 0xc8 */, 1 /* 0xc9 */, 1 /* 0xca */, 1 /* 0xcb */, 1 /* 0xcc */,
|
||||
1 /* 0xcd */, 1 /* 0xce */, 1 /* 0xcf */, 1 /* 0xd0 */, 1 /* 0xd1 */,
|
||||
1 /* 0xd2 */, 1 /* 0xd3 */, 1 /* 0xd4 */, 1 /* 0xd5 */, 1 /* 0xd6 */,
|
||||
1 /* 0xd7 */, 1 /* 0xd8 */, 1 /* 0xd9 */, 1 /* 0xda */, 1 /* 0xdb */,
|
||||
1 /* 0xdc */, 1 /* 0xdd */, 1 /* 0xde */, 1 /* 0xdf */, 1 /* 0xe0 */,
|
||||
1 /* 0xe1 */, 1 /* 0xe2 */, 1 /* 0xe3 */, 1 /* 0xe4 */, 1 /* 0xe5 */,
|
||||
1 /* 0xe6 */, 1 /* 0xe7 */, 1 /* 0xe8 */, 1 /* 0xe9 */, 1 /* 0xea */,
|
||||
1 /* 0xeb */, 1 /* 0xec */, 1 /* 0xed */, 1 /* 0xee */, 1 /* 0xef */,
|
||||
1 /* 0xf0 */, 1 /* 0xf1 */, 1 /* 0xf2 */, 1 /* 0xf3 */, 1 /* 0xf4 */,
|
||||
1 /* 0xf5 */, 1 /* 0xf6 */, 1 /* 0xf7 */, 1 /* 0xf8 */, 1 /* 0xf9 */,
|
||||
1 /* 0xfa */, 1 /* 0xfb */, 1 /* 0xfc */, 1 /* 0xfd */, 1 /* 0xfe */,
|
||||
1 /* 0xff */
|
||||
0 /* NUL */, 0 /* SOH */, 0 /* STX */, 0 /* ETX */,
|
||||
0 /* EOT */, 0 /* ENQ */, 0 /* ACK */, 0 /* BEL */,
|
||||
0 /* BS */, 1 /* HT */, 0 /* LF */, 0 /* VT */,
|
||||
0 /* FF */, 0 /* CR */, 0 /* SO */, 0 /* SI */,
|
||||
0 /* DLE */, 0 /* DC1 */, 0 /* DC2 */, 0 /* DC3 */,
|
||||
0 /* DC4 */, 0 /* NAK */, 0 /* SYN */, 0 /* ETB */,
|
||||
0 /* CAN */, 0 /* EM */, 0 /* SUB */, 0 /* ESC */,
|
||||
0 /* FS */, 0 /* GS */, 0 /* RS */, 0 /* US */,
|
||||
1 /* SPC */, 1 /* ! */, 1 /* " */, 1 /* # */,
|
||||
1 /* $ */, 1 /* % */, 1 /* & */, 1 /* ' */,
|
||||
1 /* ( */, 1 /* ) */, 1 /* * */, 1 /* + */,
|
||||
1 /* , */, 1 /* - */, 1 /* . */, 1 /* / */,
|
||||
1 /* 0 */, 1 /* 1 */, 1 /* 2 */, 1 /* 3 */,
|
||||
1 /* 4 */, 1 /* 5 */, 1 /* 6 */, 1 /* 7 */,
|
||||
1 /* 8 */, 1 /* 9 */, 1 /* : */, 1 /* ; */,
|
||||
1 /* < */, 1 /* = */, 1 /* > */, 1 /* ? */,
|
||||
1 /* @ */, 1 /* A */, 1 /* B */, 1 /* C */,
|
||||
1 /* D */, 1 /* E */, 1 /* F */, 1 /* G */,
|
||||
1 /* H */, 1 /* I */, 1 /* J */, 1 /* K */,
|
||||
1 /* L */, 1 /* M */, 1 /* N */, 1 /* O */,
|
||||
1 /* P */, 1 /* Q */, 1 /* R */, 1 /* S */,
|
||||
1 /* T */, 1 /* U */, 1 /* V */, 1 /* W */,
|
||||
1 /* X */, 1 /* Y */, 1 /* Z */, 1 /* [ */,
|
||||
1 /* \ */, 1 /* ] */, 1 /* ^ */, 1 /* _ */,
|
||||
1 /* ` */, 1 /* a */, 1 /* b */, 1 /* c */,
|
||||
1 /* d */, 1 /* e */, 1 /* f */, 1 /* g */,
|
||||
1 /* h */, 1 /* i */, 1 /* j */, 1 /* k */,
|
||||
1 /* l */, 1 /* m */, 1 /* n */, 1 /* o */,
|
||||
1 /* p */, 1 /* q */, 1 /* r */, 1 /* s */,
|
||||
1 /* t */, 1 /* u */, 1 /* v */, 1 /* w */,
|
||||
1 /* x */, 1 /* y */, 1 /* z */, 1 /* { */,
|
||||
1 /* | */, 1 /* } */, 1 /* ~ */, 0 /* DEL */,
|
||||
1 /* 0x80 */, 1 /* 0x81 */, 1 /* 0x82 */, 1 /* 0x83 */,
|
||||
1 /* 0x84 */, 1 /* 0x85 */, 1 /* 0x86 */, 1 /* 0x87 */,
|
||||
1 /* 0x88 */, 1 /* 0x89 */, 1 /* 0x8a */, 1 /* 0x8b */,
|
||||
1 /* 0x8c */, 1 /* 0x8d */, 1 /* 0x8e */, 1 /* 0x8f */,
|
||||
1 /* 0x90 */, 1 /* 0x91 */, 1 /* 0x92 */, 1 /* 0x93 */,
|
||||
1 /* 0x94 */, 1 /* 0x95 */, 1 /* 0x96 */, 1 /* 0x97 */,
|
||||
1 /* 0x98 */, 1 /* 0x99 */, 1 /* 0x9a */, 1 /* 0x9b */,
|
||||
1 /* 0x9c */, 1 /* 0x9d */, 1 /* 0x9e */, 1 /* 0x9f */,
|
||||
1 /* 0xa0 */, 1 /* 0xa1 */, 1 /* 0xa2 */, 1 /* 0xa3 */,
|
||||
1 /* 0xa4 */, 1 /* 0xa5 */, 1 /* 0xa6 */, 1 /* 0xa7 */,
|
||||
1 /* 0xa8 */, 1 /* 0xa9 */, 1 /* 0xaa */, 1 /* 0xab */,
|
||||
1 /* 0xac */, 1 /* 0xad */, 1 /* 0xae */, 1 /* 0xaf */,
|
||||
1 /* 0xb0 */, 1 /* 0xb1 */, 1 /* 0xb2 */, 1 /* 0xb3 */,
|
||||
1 /* 0xb4 */, 1 /* 0xb5 */, 1 /* 0xb6 */, 1 /* 0xb7 */,
|
||||
1 /* 0xb8 */, 1 /* 0xb9 */, 1 /* 0xba */, 1 /* 0xbb */,
|
||||
1 /* 0xbc */, 1 /* 0xbd */, 1 /* 0xbe */, 1 /* 0xbf */,
|
||||
1 /* 0xc0 */, 1 /* 0xc1 */, 1 /* 0xc2 */, 1 /* 0xc3 */,
|
||||
1 /* 0xc4 */, 1 /* 0xc5 */, 1 /* 0xc6 */, 1 /* 0xc7 */,
|
||||
1 /* 0xc8 */, 1 /* 0xc9 */, 1 /* 0xca */, 1 /* 0xcb */,
|
||||
1 /* 0xcc */, 1 /* 0xcd */, 1 /* 0xce */, 1 /* 0xcf */,
|
||||
1 /* 0xd0 */, 1 /* 0xd1 */, 1 /* 0xd2 */, 1 /* 0xd3 */,
|
||||
1 /* 0xd4 */, 1 /* 0xd5 */, 1 /* 0xd6 */, 1 /* 0xd7 */,
|
||||
1 /* 0xd8 */, 1 /* 0xd9 */, 1 /* 0xda */, 1 /* 0xdb */,
|
||||
1 /* 0xdc */, 1 /* 0xdd */, 1 /* 0xde */, 1 /* 0xdf */,
|
||||
1 /* 0xe0 */, 1 /* 0xe1 */, 1 /* 0xe2 */, 1 /* 0xe3 */,
|
||||
1 /* 0xe4 */, 1 /* 0xe5 */, 1 /* 0xe6 */, 1 /* 0xe7 */,
|
||||
1 /* 0xe8 */, 1 /* 0xe9 */, 1 /* 0xea */, 1 /* 0xeb */,
|
||||
1 /* 0xec */, 1 /* 0xed */, 1 /* 0xee */, 1 /* 0xef */,
|
||||
1 /* 0xf0 */, 1 /* 0xf1 */, 1 /* 0xf2 */, 1 /* 0xf3 */,
|
||||
1 /* 0xf4 */, 1 /* 0xf5 */, 1 /* 0xf6 */, 1 /* 0xf7 */,
|
||||
1 /* 0xf8 */, 1 /* 0xf9 */, 1 /* 0xfa */, 1 /* 0xfb */,
|
||||
1 /* 0xfc */, 1 /* 0xfd */, 1 /* 0xfe */, 1 /* 0xff */
|
||||
};
|
||||
|
||||
int nghttp2_check_header_value(const uint8_t *value, size_t len) {
|
||||
@@ -445,7 +503,46 @@ int nghttp2_check_header_value(const uint8_t *value, size_t len) {
|
||||
}
|
||||
|
||||
uint8_t *nghttp2_cpymem(uint8_t *dest, const void *src, size_t len) {
|
||||
if (len == 0) {
|
||||
return dest;
|
||||
}
|
||||
|
||||
memcpy(dest, src, len);
|
||||
|
||||
return dest + len;
|
||||
}
|
||||
|
||||
const char *nghttp2_http2_strerror(uint32_t error_code) {
|
||||
switch (error_code) {
|
||||
case NGHTTP2_NO_ERROR:
|
||||
return "NO_ERROR";
|
||||
case NGHTTP2_PROTOCOL_ERROR:
|
||||
return "PROTOCOL_ERROR";
|
||||
case NGHTTP2_INTERNAL_ERROR:
|
||||
return "INTERNAL_ERROR";
|
||||
case NGHTTP2_FLOW_CONTROL_ERROR:
|
||||
return "FLOW_CONTROL_ERROR";
|
||||
case NGHTTP2_SETTINGS_TIMEOUT:
|
||||
return "SETTINGS_TIMEOUT";
|
||||
case NGHTTP2_STREAM_CLOSED:
|
||||
return "STREAM_CLOSED";
|
||||
case NGHTTP2_FRAME_SIZE_ERROR:
|
||||
return "FRAME_SIZE_ERROR";
|
||||
case NGHTTP2_REFUSED_STREAM:
|
||||
return "REFUSED_STREAM";
|
||||
case NGHTTP2_CANCEL:
|
||||
return "CANCEL";
|
||||
case NGHTTP2_COMPRESSION_ERROR:
|
||||
return "COMPRESSION_ERROR";
|
||||
case NGHTTP2_CONNECT_ERROR:
|
||||
return "CONNECT_ERROR";
|
||||
case NGHTTP2_ENHANCE_YOUR_CALM:
|
||||
return "ENHANCE_YOUR_CALM";
|
||||
case NGHTTP2_INADEQUATE_SECURITY:
|
||||
return "INADEQUATE_SECURITY";
|
||||
case NGHTTP2_HTTP_1_1_REQUIRED:
|
||||
return "HTTP_1_1_REQUIRED";
|
||||
default:
|
||||
return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -89,6 +89,22 @@ int nghttp2_adjust_local_window_size(int32_t *local_window_size_ptr,
|
||||
int32_t *recv_reduction_ptr,
|
||||
int32_t *delta_ptr);
|
||||
|
||||
/*
|
||||
* This function works like nghttp2_adjust_local_window_size(). The
|
||||
* difference is that this function assumes *delta_ptr >= 0, and
|
||||
* *recv_window_size_ptr is not decreased by *delta_ptr.
|
||||
*
|
||||
* This function returns 0 if it succeeds, or one of the following
|
||||
* negative error codes:
|
||||
*
|
||||
* NGHTTP2_ERR_FLOW_CONTROL
|
||||
* local_window_size overflow or gets negative.
|
||||
*/
|
||||
int nghttp2_increase_local_window_size(int32_t *local_window_size_ptr,
|
||||
int32_t *recv_window_size_ptr,
|
||||
int32_t *recv_reduction_ptr,
|
||||
int32_t *delta_ptr);
|
||||
|
||||
/*
|
||||
* Returns non-zero if the function decided that WINDOW_UPDATE should
|
||||
* be sent.
|
||||
|
||||
@@ -82,12 +82,12 @@ static int lws(const uint8_t *s, size_t n) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int check_pseudo_header(nghttp2_stream *stream, const nghttp2_nv *nv,
|
||||
static int check_pseudo_header(nghttp2_stream *stream, const nghttp2_hd_nv *nv,
|
||||
int flag) {
|
||||
if (stream->http_flags & flag) {
|
||||
return 0;
|
||||
}
|
||||
if (lws(nv->value, nv->valuelen)) {
|
||||
if (lws(nv->value->base, nv->value->len)) {
|
||||
return 0;
|
||||
}
|
||||
stream->http_flags = (uint16_t)(stream->http_flags | flag);
|
||||
@@ -112,16 +112,16 @@ static int check_path(nghttp2_stream *stream) {
|
||||
(stream->http_flags & NGHTTP2_HTTP_FLAG_PATH_ASTERISK)));
|
||||
}
|
||||
|
||||
static int http_request_on_header(nghttp2_stream *stream, nghttp2_nv *nv,
|
||||
int token, int trailer) {
|
||||
if (nv->name[0] == ':') {
|
||||
static int http_request_on_header(nghttp2_stream *stream, nghttp2_hd_nv *nv,
|
||||
int trailer) {
|
||||
if (nv->name->base[0] == ':') {
|
||||
if (trailer ||
|
||||
(stream->http_flags & NGHTTP2_HTTP_FLAG_PSEUDO_HEADER_DISALLOWED)) {
|
||||
return NGHTTP2_ERR_HTTP_HEADER;
|
||||
}
|
||||
}
|
||||
|
||||
switch (token) {
|
||||
switch (nv->token) {
|
||||
case NGHTTP2_TOKEN__AUTHORITY:
|
||||
if (!check_pseudo_header(stream, nv, NGHTTP2_HTTP_FLAG__AUTHORITY)) {
|
||||
return NGHTTP2_ERR_HTTP_HEADER;
|
||||
@@ -131,16 +131,16 @@ static int http_request_on_header(nghttp2_stream *stream, nghttp2_nv *nv,
|
||||
if (!check_pseudo_header(stream, nv, NGHTTP2_HTTP_FLAG__METHOD)) {
|
||||
return NGHTTP2_ERR_HTTP_HEADER;
|
||||
}
|
||||
switch (nv->valuelen) {
|
||||
switch (nv->value->len) {
|
||||
case 4:
|
||||
if (lstreq("HEAD", nv->value, nv->valuelen)) {
|
||||
if (lstreq("HEAD", nv->value->base, nv->value->len)) {
|
||||
stream->http_flags |= NGHTTP2_HTTP_FLAG_METH_HEAD;
|
||||
}
|
||||
break;
|
||||
case 7:
|
||||
switch (nv->value[6]) {
|
||||
switch (nv->value->base[6]) {
|
||||
case 'T':
|
||||
if (lstreq("CONNECT", nv->value, nv->valuelen)) {
|
||||
if (lstreq("CONNECT", nv->value->base, nv->value->len)) {
|
||||
if (stream->stream_id % 2 == 0) {
|
||||
/* we won't allow CONNECT for push */
|
||||
return NGHTTP2_ERR_HTTP_HEADER;
|
||||
@@ -153,7 +153,7 @@ static int http_request_on_header(nghttp2_stream *stream, nghttp2_nv *nv,
|
||||
}
|
||||
break;
|
||||
case 'S':
|
||||
if (lstreq("OPTIONS", nv->value, nv->valuelen)) {
|
||||
if (lstreq("OPTIONS", nv->value->base, nv->value->len)) {
|
||||
stream->http_flags |= NGHTTP2_HTTP_FLAG_METH_OPTIONS;
|
||||
}
|
||||
break;
|
||||
@@ -168,9 +168,9 @@ static int http_request_on_header(nghttp2_stream *stream, nghttp2_nv *nv,
|
||||
if (!check_pseudo_header(stream, nv, NGHTTP2_HTTP_FLAG__PATH)) {
|
||||
return NGHTTP2_ERR_HTTP_HEADER;
|
||||
}
|
||||
if (nv->value[0] == '/') {
|
||||
if (nv->value->base[0] == '/') {
|
||||
stream->http_flags |= NGHTTP2_HTTP_FLAG_PATH_REGULAR;
|
||||
} else if (nv->valuelen == 1 && nv->value[0] == '*') {
|
||||
} else if (nv->value->len == 1 && nv->value->base[0] == '*') {
|
||||
stream->http_flags |= NGHTTP2_HTTP_FLAG_PATH_ASTERISK;
|
||||
}
|
||||
break;
|
||||
@@ -181,8 +181,8 @@ static int http_request_on_header(nghttp2_stream *stream, nghttp2_nv *nv,
|
||||
if (!check_pseudo_header(stream, nv, NGHTTP2_HTTP_FLAG__SCHEME)) {
|
||||
return NGHTTP2_ERR_HTTP_HEADER;
|
||||
}
|
||||
if ((nv->valuelen == 4 && memieq("http", nv->value, 4)) ||
|
||||
(nv->valuelen == 5 && memieq("https", nv->value, 5))) {
|
||||
if ((nv->value->len == 4 && memieq("http", nv->value->base, 4)) ||
|
||||
(nv->value->len == 5 && memieq("https", nv->value->base, 5))) {
|
||||
stream->http_flags |= NGHTTP2_HTTP_FLAG_SCHEME_HTTP;
|
||||
}
|
||||
break;
|
||||
@@ -195,7 +195,7 @@ static int http_request_on_header(nghttp2_stream *stream, nghttp2_nv *nv,
|
||||
if (stream->content_length != -1) {
|
||||
return NGHTTP2_ERR_HTTP_HEADER;
|
||||
}
|
||||
stream->content_length = parse_uint(nv->value, nv->valuelen);
|
||||
stream->content_length = parse_uint(nv->value->base, nv->value->len);
|
||||
if (stream->content_length == -1) {
|
||||
return NGHTTP2_ERR_HTTP_HEADER;
|
||||
}
|
||||
@@ -209,51 +209,70 @@ static int http_request_on_header(nghttp2_stream *stream, nghttp2_nv *nv,
|
||||
case NGHTTP2_TOKEN_UPGRADE:
|
||||
return NGHTTP2_ERR_HTTP_HEADER;
|
||||
case NGHTTP2_TOKEN_TE:
|
||||
if (!lstrieq("trailers", nv->value, nv->valuelen)) {
|
||||
if (!lstrieq("trailers", nv->value->base, nv->value->len)) {
|
||||
return NGHTTP2_ERR_HTTP_HEADER;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (nv->name[0] == ':') {
|
||||
if (nv->name->base[0] == ':') {
|
||||
return NGHTTP2_ERR_HTTP_HEADER;
|
||||
}
|
||||
}
|
||||
|
||||
if (nv->name[0] != ':') {
|
||||
if (nv->name->base[0] != ':') {
|
||||
stream->http_flags |= NGHTTP2_HTTP_FLAG_PSEUDO_HEADER_DISALLOWED;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int http_response_on_header(nghttp2_stream *stream, nghttp2_nv *nv,
|
||||
int token, int trailer) {
|
||||
if (nv->name[0] == ':') {
|
||||
static int http_response_on_header(nghttp2_stream *stream, nghttp2_hd_nv *nv,
|
||||
int trailer) {
|
||||
if (nv->name->base[0] == ':') {
|
||||
if (trailer ||
|
||||
(stream->http_flags & NGHTTP2_HTTP_FLAG_PSEUDO_HEADER_DISALLOWED)) {
|
||||
return NGHTTP2_ERR_HTTP_HEADER;
|
||||
}
|
||||
}
|
||||
|
||||
switch (token) {
|
||||
switch (nv->token) {
|
||||
case NGHTTP2_TOKEN__STATUS: {
|
||||
if (!check_pseudo_header(stream, nv, NGHTTP2_HTTP_FLAG__STATUS)) {
|
||||
return NGHTTP2_ERR_HTTP_HEADER;
|
||||
}
|
||||
if (nv->valuelen != 3) {
|
||||
if (nv->value->len != 3) {
|
||||
return NGHTTP2_ERR_HTTP_HEADER;
|
||||
}
|
||||
stream->status_code = (int16_t)parse_uint(nv->value, nv->valuelen);
|
||||
stream->status_code = (int16_t)parse_uint(nv->value->base, nv->value->len);
|
||||
if (stream->status_code == -1) {
|
||||
return NGHTTP2_ERR_HTTP_HEADER;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case NGHTTP2_TOKEN_CONTENT_LENGTH: {
|
||||
if (stream->status_code == 204) {
|
||||
/* content-length header field in 204 response is prohibited by
|
||||
RFC 7230. But some widely used servers send content-length:
|
||||
0. Until they get fixed, we ignore it. */
|
||||
if (stream->content_length != -1) {
|
||||
/* Found multiple content-length field */
|
||||
return NGHTTP2_ERR_HTTP_HEADER;
|
||||
}
|
||||
if (!lstrieq("0", nv->value->base, nv->value->len)) {
|
||||
return NGHTTP2_ERR_HTTP_HEADER;
|
||||
}
|
||||
stream->content_length = 0;
|
||||
return NGHTTP2_ERR_REMOVE_HTTP_HEADER;
|
||||
}
|
||||
if (stream->status_code / 100 == 1 ||
|
||||
(stream->status_code == 200 &&
|
||||
(stream->http_flags & NGHTTP2_HTTP_FLAG_METH_CONNECT))) {
|
||||
return NGHTTP2_ERR_HTTP_HEADER;
|
||||
}
|
||||
if (stream->content_length != -1) {
|
||||
return NGHTTP2_ERR_HTTP_HEADER;
|
||||
}
|
||||
stream->content_length = parse_uint(nv->value, nv->valuelen);
|
||||
stream->content_length = parse_uint(nv->value->base, nv->value->len);
|
||||
if (stream->content_length == -1) {
|
||||
return NGHTTP2_ERR_HTTP_HEADER;
|
||||
}
|
||||
@@ -267,17 +286,17 @@ static int http_response_on_header(nghttp2_stream *stream, nghttp2_nv *nv,
|
||||
case NGHTTP2_TOKEN_UPGRADE:
|
||||
return NGHTTP2_ERR_HTTP_HEADER;
|
||||
case NGHTTP2_TOKEN_TE:
|
||||
if (!lstrieq("trailers", nv->value, nv->valuelen)) {
|
||||
if (!lstrieq("trailers", nv->value->base, nv->value->len)) {
|
||||
return NGHTTP2_ERR_HTTP_HEADER;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (nv->name[0] == ':') {
|
||||
if (nv->name->base[0] == ':') {
|
||||
return NGHTTP2_ERR_HTTP_HEADER;
|
||||
}
|
||||
}
|
||||
|
||||
if (nv->name[0] != ':') {
|
||||
if (nv->name->base[0] != ':') {
|
||||
stream->http_flags |= NGHTTP2_HTTP_FLAG_PSEUDO_HEADER_DISALLOWED;
|
||||
}
|
||||
|
||||
@@ -286,58 +305,70 @@ static int http_response_on_header(nghttp2_stream *stream, nghttp2_nv *nv,
|
||||
|
||||
/* Generated by genauthroitychartbl.py */
|
||||
static char VALID_AUTHORITY_CHARS[] = {
|
||||
0 /* NUL */, 0 /* SOH */, 0 /* STX */, 0 /* ETX */, 0 /* EOT */,
|
||||
0 /* ENQ */, 0 /* ACK */, 0 /* BEL */, 0 /* BS */, 0 /* HT */,
|
||||
0 /* LF */, 0 /* VT */, 0 /* FF */, 0 /* CR */, 0 /* SO */,
|
||||
0 /* SI */, 0 /* DLE */, 0 /* DC1 */, 0 /* DC2 */, 0 /* DC3 */,
|
||||
0 /* DC4 */, 0 /* NAK */, 0 /* SYN */, 0 /* ETB */, 0 /* CAN */,
|
||||
0 /* EM */, 0 /* SUB */, 0 /* ESC */, 0 /* FS */, 0 /* GS */,
|
||||
0 /* RS */, 0 /* US */, 0 /* SPC */, 1 /* ! */, 0 /* " */,
|
||||
0 /* # */, 1 /* $ */, 1 /* % */, 1 /* & */, 1 /* ' */,
|
||||
1 /* ( */, 1 /* ) */, 1 /* * */, 1 /* + */, 1 /* , */,
|
||||
1 /* - */, 1 /* . */, 0 /* / */, 1 /* 0 */, 1 /* 1 */,
|
||||
1 /* 2 */, 1 /* 3 */, 1 /* 4 */, 1 /* 5 */, 1 /* 6 */,
|
||||
1 /* 7 */, 1 /* 8 */, 1 /* 9 */, 1 /* : */, 1 /* ; */,
|
||||
0 /* < */, 1 /* = */, 0 /* > */, 0 /* ? */, 1 /* @ */,
|
||||
1 /* A */, 1 /* B */, 1 /* C */, 1 /* D */, 1 /* E */,
|
||||
1 /* F */, 1 /* G */, 1 /* H */, 1 /* I */, 1 /* J */,
|
||||
1 /* K */, 1 /* L */, 1 /* M */, 1 /* N */, 1 /* O */,
|
||||
1 /* P */, 1 /* Q */, 1 /* R */, 1 /* S */, 1 /* T */,
|
||||
1 /* U */, 1 /* V */, 1 /* W */, 1 /* X */, 1 /* Y */,
|
||||
1 /* Z */, 1 /* [ */, 0 /* \ */, 1 /* ] */, 0 /* ^ */,
|
||||
1 /* _ */, 0 /* ` */, 1 /* a */, 1 /* b */, 1 /* c */,
|
||||
1 /* d */, 1 /* e */, 1 /* f */, 1 /* g */, 1 /* h */,
|
||||
1 /* i */, 1 /* j */, 1 /* k */, 1 /* l */, 1 /* m */,
|
||||
1 /* n */, 1 /* o */, 1 /* p */, 1 /* q */, 1 /* r */,
|
||||
1 /* s */, 1 /* t */, 1 /* u */, 1 /* v */, 1 /* w */,
|
||||
1 /* x */, 1 /* y */, 1 /* z */, 0 /* { */, 0 /* | */,
|
||||
0 /* } */, 1 /* ~ */, 0 /* DEL */, 0 /* 0x80 */, 0 /* 0x81 */,
|
||||
0 /* 0x82 */, 0 /* 0x83 */, 0 /* 0x84 */, 0 /* 0x85 */, 0 /* 0x86 */,
|
||||
0 /* 0x87 */, 0 /* 0x88 */, 0 /* 0x89 */, 0 /* 0x8a */, 0 /* 0x8b */,
|
||||
0 /* 0x8c */, 0 /* 0x8d */, 0 /* 0x8e */, 0 /* 0x8f */, 0 /* 0x90 */,
|
||||
0 /* 0x91 */, 0 /* 0x92 */, 0 /* 0x93 */, 0 /* 0x94 */, 0 /* 0x95 */,
|
||||
0 /* 0x96 */, 0 /* 0x97 */, 0 /* 0x98 */, 0 /* 0x99 */, 0 /* 0x9a */,
|
||||
0 /* 0x9b */, 0 /* 0x9c */, 0 /* 0x9d */, 0 /* 0x9e */, 0 /* 0x9f */,
|
||||
0 /* 0xa0 */, 0 /* 0xa1 */, 0 /* 0xa2 */, 0 /* 0xa3 */, 0 /* 0xa4 */,
|
||||
0 /* 0xa5 */, 0 /* 0xa6 */, 0 /* 0xa7 */, 0 /* 0xa8 */, 0 /* 0xa9 */,
|
||||
0 /* 0xaa */, 0 /* 0xab */, 0 /* 0xac */, 0 /* 0xad */, 0 /* 0xae */,
|
||||
0 /* 0xaf */, 0 /* 0xb0 */, 0 /* 0xb1 */, 0 /* 0xb2 */, 0 /* 0xb3 */,
|
||||
0 /* 0xb4 */, 0 /* 0xb5 */, 0 /* 0xb6 */, 0 /* 0xb7 */, 0 /* 0xb8 */,
|
||||
0 /* 0xb9 */, 0 /* 0xba */, 0 /* 0xbb */, 0 /* 0xbc */, 0 /* 0xbd */,
|
||||
0 /* 0xbe */, 0 /* 0xbf */, 0 /* 0xc0 */, 0 /* 0xc1 */, 0 /* 0xc2 */,
|
||||
0 /* 0xc3 */, 0 /* 0xc4 */, 0 /* 0xc5 */, 0 /* 0xc6 */, 0 /* 0xc7 */,
|
||||
0 /* 0xc8 */, 0 /* 0xc9 */, 0 /* 0xca */, 0 /* 0xcb */, 0 /* 0xcc */,
|
||||
0 /* 0xcd */, 0 /* 0xce */, 0 /* 0xcf */, 0 /* 0xd0 */, 0 /* 0xd1 */,
|
||||
0 /* 0xd2 */, 0 /* 0xd3 */, 0 /* 0xd4 */, 0 /* 0xd5 */, 0 /* 0xd6 */,
|
||||
0 /* 0xd7 */, 0 /* 0xd8 */, 0 /* 0xd9 */, 0 /* 0xda */, 0 /* 0xdb */,
|
||||
0 /* 0xdc */, 0 /* 0xdd */, 0 /* 0xde */, 0 /* 0xdf */, 0 /* 0xe0 */,
|
||||
0 /* 0xe1 */, 0 /* 0xe2 */, 0 /* 0xe3 */, 0 /* 0xe4 */, 0 /* 0xe5 */,
|
||||
0 /* 0xe6 */, 0 /* 0xe7 */, 0 /* 0xe8 */, 0 /* 0xe9 */, 0 /* 0xea */,
|
||||
0 /* 0xeb */, 0 /* 0xec */, 0 /* 0xed */, 0 /* 0xee */, 0 /* 0xef */,
|
||||
0 /* 0xf0 */, 0 /* 0xf1 */, 0 /* 0xf2 */, 0 /* 0xf3 */, 0 /* 0xf4 */,
|
||||
0 /* 0xf5 */, 0 /* 0xf6 */, 0 /* 0xf7 */, 0 /* 0xf8 */, 0 /* 0xf9 */,
|
||||
0 /* 0xfa */, 0 /* 0xfb */, 0 /* 0xfc */, 0 /* 0xfd */, 0 /* 0xfe */,
|
||||
0 /* 0xff */
|
||||
0 /* NUL */, 0 /* SOH */, 0 /* STX */, 0 /* ETX */,
|
||||
0 /* EOT */, 0 /* ENQ */, 0 /* ACK */, 0 /* BEL */,
|
||||
0 /* BS */, 0 /* HT */, 0 /* LF */, 0 /* VT */,
|
||||
0 /* FF */, 0 /* CR */, 0 /* SO */, 0 /* SI */,
|
||||
0 /* DLE */, 0 /* DC1 */, 0 /* DC2 */, 0 /* DC3 */,
|
||||
0 /* DC4 */, 0 /* NAK */, 0 /* SYN */, 0 /* ETB */,
|
||||
0 /* CAN */, 0 /* EM */, 0 /* SUB */, 0 /* ESC */,
|
||||
0 /* FS */, 0 /* GS */, 0 /* RS */, 0 /* US */,
|
||||
0 /* SPC */, 1 /* ! */, 0 /* " */, 0 /* # */,
|
||||
1 /* $ */, 1 /* % */, 1 /* & */, 1 /* ' */,
|
||||
1 /* ( */, 1 /* ) */, 1 /* * */, 1 /* + */,
|
||||
1 /* , */, 1 /* - */, 1 /* . */, 0 /* / */,
|
||||
1 /* 0 */, 1 /* 1 */, 1 /* 2 */, 1 /* 3 */,
|
||||
1 /* 4 */, 1 /* 5 */, 1 /* 6 */, 1 /* 7 */,
|
||||
1 /* 8 */, 1 /* 9 */, 1 /* : */, 1 /* ; */,
|
||||
0 /* < */, 1 /* = */, 0 /* > */, 0 /* ? */,
|
||||
1 /* @ */, 1 /* A */, 1 /* B */, 1 /* C */,
|
||||
1 /* D */, 1 /* E */, 1 /* F */, 1 /* G */,
|
||||
1 /* H */, 1 /* I */, 1 /* J */, 1 /* K */,
|
||||
1 /* L */, 1 /* M */, 1 /* N */, 1 /* O */,
|
||||
1 /* P */, 1 /* Q */, 1 /* R */, 1 /* S */,
|
||||
1 /* T */, 1 /* U */, 1 /* V */, 1 /* W */,
|
||||
1 /* X */, 1 /* Y */, 1 /* Z */, 1 /* [ */,
|
||||
0 /* \ */, 1 /* ] */, 0 /* ^ */, 1 /* _ */,
|
||||
0 /* ` */, 1 /* a */, 1 /* b */, 1 /* c */,
|
||||
1 /* d */, 1 /* e */, 1 /* f */, 1 /* g */,
|
||||
1 /* h */, 1 /* i */, 1 /* j */, 1 /* k */,
|
||||
1 /* l */, 1 /* m */, 1 /* n */, 1 /* o */,
|
||||
1 /* p */, 1 /* q */, 1 /* r */, 1 /* s */,
|
||||
1 /* t */, 1 /* u */, 1 /* v */, 1 /* w */,
|
||||
1 /* x */, 1 /* y */, 1 /* z */, 0 /* { */,
|
||||
0 /* | */, 0 /* } */, 1 /* ~ */, 0 /* DEL */,
|
||||
0 /* 0x80 */, 0 /* 0x81 */, 0 /* 0x82 */, 0 /* 0x83 */,
|
||||
0 /* 0x84 */, 0 /* 0x85 */, 0 /* 0x86 */, 0 /* 0x87 */,
|
||||
0 /* 0x88 */, 0 /* 0x89 */, 0 /* 0x8a */, 0 /* 0x8b */,
|
||||
0 /* 0x8c */, 0 /* 0x8d */, 0 /* 0x8e */, 0 /* 0x8f */,
|
||||
0 /* 0x90 */, 0 /* 0x91 */, 0 /* 0x92 */, 0 /* 0x93 */,
|
||||
0 /* 0x94 */, 0 /* 0x95 */, 0 /* 0x96 */, 0 /* 0x97 */,
|
||||
0 /* 0x98 */, 0 /* 0x99 */, 0 /* 0x9a */, 0 /* 0x9b */,
|
||||
0 /* 0x9c */, 0 /* 0x9d */, 0 /* 0x9e */, 0 /* 0x9f */,
|
||||
0 /* 0xa0 */, 0 /* 0xa1 */, 0 /* 0xa2 */, 0 /* 0xa3 */,
|
||||
0 /* 0xa4 */, 0 /* 0xa5 */, 0 /* 0xa6 */, 0 /* 0xa7 */,
|
||||
0 /* 0xa8 */, 0 /* 0xa9 */, 0 /* 0xaa */, 0 /* 0xab */,
|
||||
0 /* 0xac */, 0 /* 0xad */, 0 /* 0xae */, 0 /* 0xaf */,
|
||||
0 /* 0xb0 */, 0 /* 0xb1 */, 0 /* 0xb2 */, 0 /* 0xb3 */,
|
||||
0 /* 0xb4 */, 0 /* 0xb5 */, 0 /* 0xb6 */, 0 /* 0xb7 */,
|
||||
0 /* 0xb8 */, 0 /* 0xb9 */, 0 /* 0xba */, 0 /* 0xbb */,
|
||||
0 /* 0xbc */, 0 /* 0xbd */, 0 /* 0xbe */, 0 /* 0xbf */,
|
||||
0 /* 0xc0 */, 0 /* 0xc1 */, 0 /* 0xc2 */, 0 /* 0xc3 */,
|
||||
0 /* 0xc4 */, 0 /* 0xc5 */, 0 /* 0xc6 */, 0 /* 0xc7 */,
|
||||
0 /* 0xc8 */, 0 /* 0xc9 */, 0 /* 0xca */, 0 /* 0xcb */,
|
||||
0 /* 0xcc */, 0 /* 0xcd */, 0 /* 0xce */, 0 /* 0xcf */,
|
||||
0 /* 0xd0 */, 0 /* 0xd1 */, 0 /* 0xd2 */, 0 /* 0xd3 */,
|
||||
0 /* 0xd4 */, 0 /* 0xd5 */, 0 /* 0xd6 */, 0 /* 0xd7 */,
|
||||
0 /* 0xd8 */, 0 /* 0xd9 */, 0 /* 0xda */, 0 /* 0xdb */,
|
||||
0 /* 0xdc */, 0 /* 0xdd */, 0 /* 0xde */, 0 /* 0xdf */,
|
||||
0 /* 0xe0 */, 0 /* 0xe1 */, 0 /* 0xe2 */, 0 /* 0xe3 */,
|
||||
0 /* 0xe4 */, 0 /* 0xe5 */, 0 /* 0xe6 */, 0 /* 0xe7 */,
|
||||
0 /* 0xe8 */, 0 /* 0xe9 */, 0 /* 0xea */, 0 /* 0xeb */,
|
||||
0 /* 0xec */, 0 /* 0xed */, 0 /* 0xee */, 0 /* 0xef */,
|
||||
0 /* 0xf0 */, 0 /* 0xf1 */, 0 /* 0xf2 */, 0 /* 0xf3 */,
|
||||
0 /* 0xf4 */, 0 /* 0xf5 */, 0 /* 0xf6 */, 0 /* 0xf7 */,
|
||||
0 /* 0xf8 */, 0 /* 0xf9 */, 0 /* 0xfa */, 0 /* 0xfb */,
|
||||
0 /* 0xfc */, 0 /* 0xfd */, 0 /* 0xfe */, 0 /* 0xff */
|
||||
};
|
||||
|
||||
static int check_authority(const uint8_t *value, size_t len) {
|
||||
@@ -375,7 +406,7 @@ static int check_scheme(const uint8_t *value, size_t len) {
|
||||
}
|
||||
|
||||
int nghttp2_http_on_header(nghttp2_session *session, nghttp2_stream *stream,
|
||||
nghttp2_frame *frame, nghttp2_nv *nv, int token,
|
||||
nghttp2_frame *frame, nghttp2_hd_nv *nv,
|
||||
int trailer) {
|
||||
int rv;
|
||||
|
||||
@@ -386,14 +417,14 @@ int nghttp2_http_on_header(nghttp2_session *session, nghttp2_stream *stream,
|
||||
this, we may disrupt many web sites and/or libraries. So we
|
||||
become conservative here, and just ignore those illegal regular
|
||||
headers. */
|
||||
if (!nghttp2_check_header_name(nv->name, nv->namelen)) {
|
||||
if (!nghttp2_check_header_name(nv->name->base, nv->name->len)) {
|
||||
size_t i;
|
||||
if (nv->namelen > 0 && nv->name[0] == ':') {
|
||||
if (nv->name->len > 0 && nv->name->base[0] == ':') {
|
||||
return NGHTTP2_ERR_HTTP_HEADER;
|
||||
}
|
||||
/* header field name must be lower-cased without exception */
|
||||
for (i = 0; i < nv->namelen; ++i) {
|
||||
uint8_t c = nv->name[i];
|
||||
for (i = 0; i < nv->name->len; ++i) {
|
||||
uint8_t c = nv->name->base[i];
|
||||
if ('A' <= c && c <= 'Z') {
|
||||
return NGHTTP2_ERR_HTTP_HEADER;
|
||||
}
|
||||
@@ -405,17 +436,18 @@ int nghttp2_http_on_header(nghttp2_session *session, nghttp2_stream *stream,
|
||||
return NGHTTP2_ERR_IGN_HTTP_HEADER;
|
||||
}
|
||||
|
||||
if (token == NGHTTP2_TOKEN__AUTHORITY || token == NGHTTP2_TOKEN_HOST) {
|
||||
rv = check_authority(nv->value, nv->valuelen);
|
||||
} else if (token == NGHTTP2_TOKEN__SCHEME) {
|
||||
rv = check_scheme(nv->value, nv->valuelen);
|
||||
if (nv->token == NGHTTP2_TOKEN__AUTHORITY ||
|
||||
nv->token == NGHTTP2_TOKEN_HOST) {
|
||||
rv = check_authority(nv->value->base, nv->value->len);
|
||||
} else if (nv->token == NGHTTP2_TOKEN__SCHEME) {
|
||||
rv = check_scheme(nv->value->base, nv->value->len);
|
||||
} else {
|
||||
rv = nghttp2_check_header_value(nv->value, nv->valuelen);
|
||||
rv = nghttp2_check_header_value(nv->value->base, nv->value->len);
|
||||
}
|
||||
|
||||
if (rv == 0) {
|
||||
assert(nv->namelen > 0);
|
||||
if (nv->name[0] == ':') {
|
||||
assert(nv->name->len > 0);
|
||||
if (nv->name->base[0] == ':') {
|
||||
return NGHTTP2_ERR_HTTP_HEADER;
|
||||
}
|
||||
/* When ignoring regular headers, we set this flag so that we
|
||||
@@ -426,10 +458,10 @@ int nghttp2_http_on_header(nghttp2_session *session, nghttp2_stream *stream,
|
||||
}
|
||||
|
||||
if (session->server || frame->hd.type == NGHTTP2_PUSH_PROMISE) {
|
||||
return http_request_on_header(stream, nv, token, trailer);
|
||||
return http_request_on_header(stream, nv, trailer);
|
||||
}
|
||||
|
||||
return http_response_on_header(stream, nv, token, trailer);
|
||||
return http_response_on_header(stream, nv, trailer);
|
||||
}
|
||||
|
||||
int nghttp2_http_on_request_headers(nghttp2_stream *stream,
|
||||
|
||||
@@ -36,8 +36,7 @@
|
||||
/*
|
||||
* This function is called when HTTP header field |nv| in |frame| is
|
||||
* received for |stream|. This function will validate |nv| against
|
||||
* the current state of stream. The |token| is nghttp2_token value
|
||||
* for nv->name, or -1 if we don't have enum value for the name.
|
||||
* the current state of stream.
|
||||
*
|
||||
* This function returns 0 if it succeeds, or one of the following
|
||||
* negative error codes:
|
||||
@@ -49,7 +48,7 @@
|
||||
* if it was not received because of compatibility reasons.
|
||||
*/
|
||||
int nghttp2_http_on_header(nghttp2_session *session, nghttp2_stream *stream,
|
||||
nghttp2_frame *frame, nghttp2_nv *nv, int token,
|
||||
nghttp2_frame *frame, nghttp2_hd_nv *nv,
|
||||
int trailer);
|
||||
|
||||
/*
|
||||
|
||||
@@ -29,15 +29,9 @@
|
||||
#include <config.h>
|
||||
#endif /* HAVE_CONFIG_H */
|
||||
|
||||
/* Macros, types and constants for internal use */
|
||||
#include <nghttp2/nghttp2.h>
|
||||
|
||||
#ifdef DEBUGBUILD
|
||||
#define DEBUGF(x) x
|
||||
#else
|
||||
#define DEBUGF(x) \
|
||||
do { \
|
||||
} while (0)
|
||||
#endif
|
||||
/* Macros, types and constants for internal use */
|
||||
|
||||
/* "less" function, return nonzero if |lhs| is less than |rhs|. */
|
||||
typedef int (*nghttp2_less)(const void *lhs, const void *rhs);
|
||||
@@ -52,7 +46,13 @@ typedef enum {
|
||||
* Invalid HTTP header field was received but it can be treated as
|
||||
* if it was not received because of compatibility reasons.
|
||||
*/
|
||||
NGHTTP2_ERR_IGN_HTTP_HEADER = -105
|
||||
NGHTTP2_ERR_IGN_HTTP_HEADER = -105,
|
||||
/*
|
||||
* Invalid HTTP header field was received, and it is ignored.
|
||||
* Unlike NGHTTP2_ERR_IGN_HTTP_HEADER, this does not invoke
|
||||
* nghttp2_on_invalid_header_callback.
|
||||
*/
|
||||
NGHTTP2_ERR_REMOVE_HTTP_HEADER = -106
|
||||
} nghttp2_internal_error;
|
||||
|
||||
#endif /* NGHTTP2_INT_H */
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user