Compare commits

..

381 Commits

Author SHA1 Message Date
Tatsuhiro Tsujikawa
6e74466231 Update bash_completion 2018-02-27 21:18:50 +09:00
Tatsuhiro Tsujikawa
478eac099f Update manual pages 2018-02-27 21:18:05 +09:00
Tatsuhiro Tsujikawa
88e2029e37 Bump up version number to 1.31.0, LT revision to 30:0:16 2018-02-27 21:15:26 +09:00
Tatsuhiro Tsujikawa
45d76cf501 nghttpx: Close listening socket on graceful shutdown 2018-02-26 22:40:24 +09:00
Tatsuhiro Tsujikawa
54573f28a8 Merge pull request #1137 from nghttp2/session-set-user-data
Add nghttp2_session_set_user_data() public API function
2018-02-25 18:26:43 +09:00
Tatsuhiro Tsujikawa
17793e99dc Add nghttp2_session_set_user_data() public API function 2018-02-22 21:02:16 +09:00
Tatsuhiro Tsujikawa
5eac3c9025 Update manual pages 2018-02-22 16:14:34 +09:00
Tatsuhiro Tsujikawa
e70195ae91 nghttpx: Update doc 2018-02-22 16:12:38 +09:00
Tatsuhiro Tsujikawa
fe51e7fa1a Merge pull request #1130 from nghttp2/avoid-inet_pton-macro
src: Define nghttp2_inet_pton wrapper to avoid inet_pton macro
2018-02-17 22:58:37 +09:00
Tatsuhiro Tsujikawa
eb951c2ce4 src: Define nghttp2_inet_pton wrapper to avoid inet_pton macro 2018-02-12 16:22:47 +09:00
Tatsuhiro Tsujikawa
39f0ce7c25 Merge pull request #1126 from nghttp2/nghttpx-expired-client-cert
nghttpx: Add an option to accept expired client certificate
2018-02-10 16:00:43 +09:00
Tatsuhiro Tsujikawa
65157811d4 Merge pull request #1123 from nghttp2/mruby-client-cert-not-before-after
nghttpx: Add mruby tls_client_not_before, and tls_client_not_after
2018-02-10 16:00:29 +09:00
Tatsuhiro Tsujikawa
e8af7afc65 nghttpx: Add an option to accept expired client certificate 2018-02-08 16:51:23 +09:00
Tatsuhiro Tsujikawa
38abfd1863 nghttpx: Add mruby tls_client_not_before, and tls_client_not_after 2018-02-08 16:25:31 +09:00
Tatsuhiro Tsujikawa
ff3edc09ed nghttpx: Fix potential memory leak 2018-02-03 18:21:42 +09:00
Tatsuhiro Tsujikawa
0bb1540682 Bump up version number to 1.31.0-DEV 2018-02-02 22:17:47 +09:00
Tatsuhiro Tsujikawa
f0836c7e39 Update manual pages 2018-02-02 21:19:16 +09:00
Tatsuhiro Tsujikawa
25db178b7d Bump up version number to 1.30.0, LT revision to 29:2:15 2018-02-02 21:15:03 +09:00
Tatsuhiro Tsujikawa
1b6713e6ec Update AUTHORS 2018-02-02 21:12:40 +09:00
Tatsuhiro Tsujikawa
c1a496cf4e nghttpx: Fix bug that h1 backend idle timeout expires sooner 2018-02-02 21:09:04 +09:00
Tatsuhiro Tsujikawa
e098a21132 mruby: Fix bug that response header is unexpectedly overwritten
The bug is the same bug fixed by
6deee2037d, but in response handler.
2018-01-28 19:41:45 +09:00
Tatsuhiro Tsujikawa
0ba4bf51e4 Merge pull request #1120 from dylanplecki/issue-1119-mruby-header-overwrite
Fix #1119: Overwrite of first header on mruby call to env.req.set_header(..)
2018-01-28 19:35:20 +09:00
Dylan Plecki
6deee2037d Fix #1119: Stop overwrite of first header on mruby call to env.req.set_header(..) 2018-01-26 18:49:08 -08:00
Tatsuhiro Tsujikawa
6761a933fe Merge pull request #1105 from nghttp2/nghttpx-upgrade-scheme
nghttpx: Add upgrade-scheme parameter to backend option
2018-01-14 23:44:00 +09:00
Tatsuhiro Tsujikawa
5cc3d159e1 nghttpx: Add upgrade-scheme parameter to backend option
If "upgrade-scheme" parameter is present in backend option along with
"tls" paramter, HTTP/2 :scheme pseudo header field is changed to
"https" from "http" when forwarding a request to this particular
backend.  This is a workaround for a server which requests "https"
scheme on HTTP/2 connection encrypted by TLS.
2018-01-08 18:08:01 +09:00
Tatsuhiro Tsujikawa
652f57e79d Merge pull request #1104 from nghttp2/allow-ping-after-goaway
Allow PING frame to be sent after GOAWAY
2018-01-08 17:26:47 +09:00
Tatsuhiro Tsujikawa
acd6b40e4c Allow PING frame to be sent after GOAWAY 2018-01-08 17:03:48 +09:00
Tatsuhiro Tsujikawa
0fbb46edd6 Merge pull request #1101 from nghttp2/remember-pushed-links
nghttpx: Remember which resource is pushed
2018-01-04 23:15:35 +09:00
Tatsuhiro Tsujikawa
6ad629de47 Merge pull request #1102 from nghttp2/fix-missing-alpn-validation
nghttpx: Fix missing ALPN validation (--npn-list)
2018-01-04 23:15:10 +09:00
Tatsuhiro Tsujikawa
74754982f1 nghttpx: Fix missing ALPN validation (--npn-list)
This commit fixes the bug that ALPN validation does not occur when
ALPN list is not sent from client.
2018-01-04 22:43:47 +09:00
Tatsuhiro Tsujikawa
a31a2e3b2c nghttpx: Remember which resource is pushed
Remember which resource is pushed in order to conform to the semantics
described in RFC 8297.
2018-01-04 22:35:22 +09:00
Tatsuhiro Tsujikawa
a776b0dbcc Merge pull request #1092 from nghttp2/define-103
src: Define 103 status code
2017-12-20 20:39:22 +09:00
Tatsuhiro Tsujikawa
cfd926f09b src: Define 103 status code 2017-12-20 19:30:55 +09:00
Tatsuhiro Tsujikawa
72f52716ae Bump up version number to 1.30.0-DEV 2017-12-19 23:37:09 +09:00
Tatsuhiro Tsujikawa
439b9b6c6a Update manual pages 2017-12-19 23:18:56 +09:00
Tatsuhiro Tsujikawa
4849845292 Bump up version number to v1.29.0, LT revision to 29:1:15 2017-12-19 23:16:34 +09:00
Tatsuhiro Tsujikawa
d30f38163c Update manual pages 2017-12-17 14:16:53 +09:00
Tatsuhiro Tsujikawa
cff9ebe1dd Merge pull request #1091 from nghttp2/remove-spdy
Remove SPDY
2017-12-17 14:14:14 +09:00
Tatsuhiro Tsujikawa
4d1139f653 Remove SPDY 2017-12-17 13:28:44 +09:00
Tatsuhiro Tsujikawa
48f574076c nghttpx: Update doc 2017-12-16 00:13:27 +09:00
Tatsuhiro Tsujikawa
c1f14d73c7 Update manual pages 2017-12-14 22:25:07 +09:00
Tatsuhiro Tsujikawa
216f4dad83 nghttpx: Remove redundant check 2017-12-14 21:39:22 +09:00
Tatsuhiro Tsujikawa
a4e27d766b Revert "nghttpx: Use an existing h2 backend connection as much as possible"
This reverts commit f507b5eee4.

Balancing load is more important at the moment.
2017-12-14 21:34:04 +09:00
Tatsuhiro Tsujikawa
96df14d2ec Merge pull request #1084 from dvetutnev/cmake_module_path
Fix CMAKE_MODULE_PATH
2017-12-14 21:19:34 +09:00
Dmitriy Vetutnev
2365f12e39 Fix CMAKE_MODULE_PATH 2017-12-06 20:48:52 +03:00
Tatsuhiro Tsujikawa
96ea9cdaf7 Merge pull request #1083 from nghttp2/nghttpx-api-tmp-file
nghttpx: Write API request body in temporary file
2017-12-03 16:43:54 +09:00
Tatsuhiro Tsujikawa
03f7ec0f60 nghttpx: Write API request body in temporary file 2017-12-03 16:19:57 +09:00
Tatsuhiro Tsujikawa
a941699962 Merge pull request #1082 from nghttp2/nghttpx-increase-api-max-request-body
nghttpx: Increase api-max-request-body
2017-12-02 14:55:45 +09:00
Tatsuhiro Tsujikawa
2056e812bd nghttpx: Increase api-max-request-body 2017-12-02 13:49:42 +09:00
Tatsuhiro Tsujikawa
04348ff20e Merge pull request #1081 from nghttp2/nghttpx-faster-parse-config
nghttpx: Faster configuration loading with lots of backends
2017-12-01 23:47:34 +09:00
Tatsuhiro Tsujikawa
d8e378fea9 Merge pull request #1080 from nghttp2/nghttpx-fix-crash-with-backend-http-proxy-uri
nghttpx: Fix crash with --backend-http-proxy-uri option
2017-12-01 23:07:38 +09:00
Tatsuhiro Tsujikawa
1ebb6810a1 nghttpx: Faster configuration loading with lots of backends 2017-12-01 23:06:06 +09:00
Tatsuhiro Tsujikawa
2a694b270a Merge pull request #1077 from nghttp2/refused-stream
Use NGHTTP2_REFUSED_STREAM for streams which are closed by GOAWAY
2017-12-01 22:36:09 +09:00
Tatsuhiro Tsujikawa
a3ebeeafba nghttpx: Fix crash with --backend-http-proxy-uri option 2017-12-01 22:28:16 +09:00
Tatsuhiro Tsujikawa
422ad1be32 Use NGHTTP2_REFUSED_STREAM for streams which are closed by GOAWAY
The error code NGHTTP2_REFUSED_STREAM is passed to
nghttp2_on_stream_close callback when a stream is closed because its
stream ID is strictly larger than incoming or outgoing GOAWAY.
2017-11-30 23:10:57 +09:00
Tatsuhiro Tsujikawa
97f1735cf5 Bump up version number to 1.29.0 2017-11-25 23:04:03 +09:00
Tatsuhiro Tsujikawa
939ad5ddbe Update manual pages 2017-11-25 22:19:11 +09:00
Tatsuhiro Tsujikawa
24d92b979d Add deprecation warning when spdylay support is enabled 2017-11-25 22:16:23 +09:00
Tatsuhiro Tsujikawa
4c92ff1843 Bump up version number to 1.28.0, LT revision to 29:0:15 2017-11-25 22:10:02 +09:00
Tatsuhiro Tsujikawa
280db5c6ba Update neverbleed 2017-11-25 21:27:14 +09:00
Tatsuhiro Tsujikawa
7fbcb2d005 Merge pull request #1074 from nghttp2/fix-doc
Fix doc
2017-11-24 22:59:04 +09:00
Tatsuhiro Tsujikawa
53aeb2c3d7 Fix doc 2017-11-24 22:26:29 +09:00
Tatsuhiro Tsujikawa
ff200bfcf3 clang-format-5.0 2017-11-23 14:19:12 +09:00
Tatsuhiro Tsujikawa
fee3151fd2 Switch to clang-format-5.0 2017-11-23 14:16:42 +09:00
Tatsuhiro Tsujikawa
99a85159ae Update manual pages 2017-11-21 23:27:02 +09:00
Tatsuhiro Tsujikawa
2a981a3f56 Merge pull request #1066 from nghttp2/nghttpx-add-affinity-cookie-secure
nghttpx: Add affinity-cookie-secure parameter to backend option
2017-11-21 23:24:40 +09:00
Tatsuhiro Tsujikawa
0028275d7b nghttpx: Add affinity-cookie-secure parameter to backend option 2017-11-21 22:29:22 +09:00
Tatsuhiro Tsujikawa
ee8bfddfc9 Merge pull request #1063 from nghttp2/error_callback2
Error callback2
2017-11-21 21:25:53 +09:00
Tatsuhiro Tsujikawa
194acb1f2c src: Use nghttp2_error_callback2 2017-11-19 16:51:52 +09:00
Tatsuhiro Tsujikawa
43a2a70ae7 Add nghttp2_error_callback2
nghttp2_error_callback2 is an extended version of the existing
nghttp2_error_callback by adding error code parameter.  This
deprecates nghttp2_error_callback.
2017-11-19 16:51:52 +09:00
Tatsuhiro Tsujikawa
73344ae9aa nghttpx: Use plain hex string format for client serial 2017-11-17 00:04:23 +09:00
Tatsuhiro Tsujikawa
c479f6122f Merge pull request #1060 from nghttp2/nghttpx-add-client-serial
Nghttpx add client serial
2017-11-16 23:26:35 +09:00
Tatsuhiro Tsujikawa
eca0a3025b nghttpx: Add $tls_client_serial log variable 2017-11-16 22:53:54 +09:00
Tatsuhiro Tsujikawa
4720c5cb3d nghttpx: Make client serial available in mruby script 2017-11-16 22:53:54 +09:00
Tatsuhiro Tsujikawa
cd55ab28ab nghttpx: Add function to get serial number from certificate 2017-11-16 22:53:54 +09:00
Tatsuhiro Tsujikawa
d402cfdf16 Merge pull request #1057 from nghttp2/nghttpx-add-tls-client-issuer-name
Add tls_client_issuer_name log variable and expose it to mruby
2017-11-16 01:16:11 +09:00
Tatsuhiro Tsujikawa
22502182d0 Add tls_client_issuer_name log variable and expose it to mruby 2017-11-15 23:41:47 +09:00
Tatsuhiro Tsujikawa
05e1fd5e77 Update manual pages 2017-11-04 17:53:51 +09:00
Tatsuhiro Tsujikawa
943d7923f9 Add Session Affinity section to nghttpx howto 2017-11-04 17:49:09 +09:00
Tatsuhiro Tsujikawa
568ecbfb28 doc: Add missing port 2017-11-04 17:48:46 +09:00
Tatsuhiro Tsujikawa
f5ddd7f43b nghttpx: Make initial_addr_idx_ unsigned 2017-11-04 17:30:56 +09:00
Tatsuhiro Tsujikawa
88abbce7e7 nghttpx: Fix compile error with gcc 2017-11-04 17:30:27 +09:00
Tatsuhiro Tsujikawa
16e9036568 nghttpx: Fix affinity retry 2017-11-04 17:13:45 +09:00
Tatsuhiro Tsujikawa
fa7945c627 nghttpx: Refactor 2017-11-04 15:55:25 +09:00
Tatsuhiro Tsujikawa
daca43f0dd nghttpx: Fix stalled backend connection on retry 2017-11-04 15:46:08 +09:00
Tatsuhiro Tsujikawa
16bc11e670 nghttpx: Remove duplicated util::make_socket_nodelay 2017-11-04 13:00:17 +09:00
Tatsuhiro Tsujikawa
6f7e94cdba Merge pull request #1047 from PiotrSikora/go_vet
integration: Fix issues reported by the `go vet` tool.
2017-11-03 23:02:37 +09:00
Piotr Sikora
61efa15a14 integration: Fix issues reported by the go vet tool.
Signed-off-by: Piotr Sikora <piotrsikora@google.com>
2017-11-02 21:13:25 -07:00
Tatsuhiro Tsujikawa
8c0ea56bb8 Merge pull request #1036 from nghttp2/nghttpx-affinity-cookie
nghttpx: Cookie based session affinity
2017-11-01 22:45:38 +09:00
Tatsuhiro Tsujikawa
549053710b nghttpx: Refactor 2017-11-01 22:33:49 +09:00
Tatsuhiro Tsujikawa
6010d39325 integration: Add tests 2017-11-01 22:18:03 +09:00
Tatsuhiro Tsujikawa
be5c39a1cf src: Add tests 2017-11-01 22:18:03 +09:00
Tatsuhiro Tsujikawa
b8fda6808b nghttpx: Cookie based session affinity 2017-11-01 22:18:03 +09:00
Tatsuhiro Tsujikawa
e29b9c1261 Merge pull request #1045 from nghttp2/nghttpx-sha1-fingerprint
Nghttpx sha1 fingerprint
2017-10-31 23:07:39 +09:00
Tatsuhiro Tsujikawa
539e27812b nghttpx: Add tls_client_fingerprint_sha1 to mruby and accesslog
Also tls_client_fingerprint is renamed to
tls_client_fingerprint_sha256.
2017-10-31 21:41:40 +09:00
Tatsuhiro Tsujikawa
7008afd40e nghttpx: Refactor get_x509_fingerprint to accept hash function 2017-10-31 21:28:16 +09:00
Tatsuhiro Tsujikawa
77a41756db Merge pull request #1041 from nghttp2/fix-examples-client-server
examples: Make client and server work with libevent-2.1.8
2017-10-30 17:30:20 +09:00
Tatsuhiro Tsujikawa
b15045d60e Merge pull request #1040 from nghttp2/nghttpx-mruby-add-more-tls-vars
nghttpx: Add more TLS related attributes to mruby Env object
2017-10-29 23:14:16 +09:00
Tatsuhiro Tsujikawa
03084f7517 examples: Make client and server work with libevent-2.1.8 2017-10-29 23:09:23 +09:00
Tatsuhiro Tsujikawa
60baca27e4 nghttpx: Add more TLS related attributes to mruby Env object
The added attributes are:

* tls_cipher
* tls_protocol
* tls_session_id
* tls_session_reused
* alpn
2017-10-29 22:42:30 +09:00
Tatsuhiro Tsujikawa
86990db236 Merge pull request #1038 from nghttp2/nghttpx-add-more-logging-vars
nghttpx: Add client fingerprint and subject name to accesslog
2017-10-29 22:21:10 +09:00
Tatsuhiro Tsujikawa
cb376bcd80 nghttpx: Add client fingerprint and subject name to accesslog 2017-10-29 21:47:00 +09:00
Tatsuhiro Tsujikawa
f2b8edd1e2 nghttpx: Fix memory leak 2017-10-29 21:46:12 +09:00
Tatsuhiro Tsujikawa
c4f8afcfde nghttpx: Get TLS info only when it is necessary when writing accesslog 2017-10-29 21:22:33 +09:00
Tatsuhiro Tsujikawa
1a1a216d5a Merge pull request #1037 from nghttp2/nghttpx-mruby-tls-client-vars
nghttpx: Add client fingerprint and subject name to mruby env
2017-10-29 21:13:20 +09:00
Tatsuhiro Tsujikawa
9f80a82c1a nghttpx: Add client fingerprint and subject name to mruby env 2017-10-29 19:54:42 +09:00
Tatsuhiro Tsujikawa
c573c80bd3 nghttpx: Pass a pointer to SSL instead of TLSSessionInfo to LogSpec 2017-10-29 19:47:39 +09:00
Tatsuhiro Tsujikawa
3cd6817e21 Fix typos 2017-10-29 16:54:21 +09:00
Tatsuhiro Tsujikawa
d4a69658a1 Add another warning about mruby 2017-10-29 16:18:20 +09:00
Tatsuhiro Tsujikawa
8e06fe4971 Fix typo 2017-10-29 16:14:30 +09:00
Tatsuhiro Tsujikawa
aaeeec8f1c Fix typos 2017-10-28 22:25:42 +09:00
Tatsuhiro Tsujikawa
66d5e24606 Bump up version number to 1.28.0-DEV 2017-10-25 21:20:16 +09:00
Tatsuhiro Tsujikawa
e8907a073f Update manual pages 2017-10-24 23:10:37 +09:00
Tatsuhiro Tsujikawa
9656ac0254 Fix sphinx warnings 2017-10-24 23:10:23 +09:00
Tatsuhiro Tsujikawa
75624617ce Bump up version number to 1.27.0 2017-10-24 22:51:17 +09:00
Tatsuhiro Tsujikawa
1a8f6578b3 Update AUTHORS 2017-10-24 22:49:51 +09:00
Tatsuhiro Tsujikawa
4f0548b018 travis: Compile mruby and neverbleed in make distcheck
gcc is upgraded to gcc-7.
2017-10-24 21:41:10 +09:00
Tatsuhiro Tsujikawa
5119e82b93 src: Fix memory leak in unit test 2017-10-24 21:40:30 +09:00
Tatsuhiro Tsujikawa
3be5856c82 nghttpx: Fix unused function warnings 2017-10-24 21:40:30 +09:00
Tatsuhiro Tsujikawa
a319143901 nghttpx: Fix bug that header fields are missing in HTTP/1.0 response 2017-10-22 01:11:32 +09:00
Tatsuhiro Tsujikawa
17c88d60c7 Compile with g++ 7.2.1 2017-10-19 23:04:12 +09:00
Tatsuhiro Tsujikawa
7601511fdf Merge pull request #1029 from lazyhamster/master
Fixed accidental compiler flags concatenation for MSVC.
2017-10-19 21:21:46 +09:00
Tatsuhiro Tsujikawa
f507b5eee4 nghttpx: Use an existing h2 backend connection as much as possible
h2load measurement reveals that this strategy is 3 times faster than
the previous implementations.
2017-10-19 21:15:08 +09:00
LazyHamster
93821165be Fixed accidental compiler flags concatenation for MSVC. 2017-10-18 15:25:17 +03:00
Tatsuhiro Tsujikawa
aaa0b858e4 Amend some macro comments 2017-10-14 11:50:16 +09:00
Tatsuhiro Tsujikawa
5fa1938691 clang-format 2017-10-14 11:45:41 +09:00
Tatsuhiro Tsujikawa
56ee3d4820 Merge pull request #1027 from dermojo/mingw
Support for Windows / MinGW
2017-10-14 11:44:57 +09:00
Daniel Evers
c2d9a1ed6f Support for Windows / MinGW 2017-10-12 18:15:12 +02:00
Tatsuhiro Tsujikawa
fcf9ab2798 Merge pull request #1023 from nckx/fix-fuzz-typo
fuzz: Fix typo (‘-fsanitize=adres’) in README.rst
2017-10-12 21:00:18 +09:00
Tobias Geerinckx-Rice
35e445bd04 fuzz: Fix typo (‘-fsanitize=adres’) in README.rst 2017-10-10 22:14:25 +02:00
Tatsuhiro Tsujikawa
88ce3c31b7 Merge pull request #1020 from FireBurn/master
Reduce libxml2 version requirement to 2.6.26
2017-10-07 21:17:33 +09:00
Mike Lothian
16320a0f81 Reduce libxml2 version requirement to 2.6.26
It's currently set at 2.7.7 but reducing this down to 2.6.26 allows
nghttp2 to be built on RHEL5
2017-10-04 14:25:12 +01:00
Tatsuhiro Tsujikawa
8c72fb3539 Merge pull request #1018 from nghttp2/h2load-verbose-h2-headers
h2load: Print out h2 header fields with --verbose option
2017-10-01 12:49:13 +09:00
Tatsuhiro Tsujikawa
8ffe389daa h2load: Print out h2 header fields with --verbose option 2017-09-22 18:12:20 +09:00
Tatsuhiro Tsujikawa
189a4516a1 Merge pull request #1016 from nghttp2/nghttpx-non-final-response
nghttpx: Send non-final response to HTTP/1.1 or HTTP/2 client only
2017-09-21 22:28:51 +09:00
Tatsuhiro Tsujikawa
2576855ded nghttpx: Send non-final response to HTTP/1.1 or HTTP/2 client only 2017-09-21 21:42:56 +09:00
Tatsuhiro Tsujikawa
7d4d48a35e Add timing-based load-testing section to h2load howto 2017-09-21 17:57:32 +09:00
Tatsuhiro Tsujikawa
cc6f759190 src: Add static to constexpr char[] 2017-09-20 23:54:10 +09:00
Tatsuhiro Tsujikawa
c23fc86a23 Bump up version number to 1.27.0-DEV 2017-09-20 22:52:43 +09:00
Tatsuhiro Tsujikawa
d2324bdda1 Update bash_completion 2017-09-20 22:42:14 +09:00
Tatsuhiro Tsujikawa
6f0ae9d49a Update manual pages 2017-09-20 22:41:56 +09:00
Tatsuhiro Tsujikawa
0389af5724 Bump up version number to 1.26.0 2017-09-20 22:29:38 +09:00
Tatsuhiro Tsujikawa
1766e25f45 Update AUTHORS 2017-09-20 22:28:43 +09:00
Tatsuhiro Tsujikawa
323001238a clang-format 2017-09-20 22:08:22 +09:00
Tatsuhiro Tsujikawa
91f062f873 src: Fix compile error 2017-09-20 22:08:08 +09:00
Tatsuhiro Tsujikawa
650a0cfbff Merge pull request #1013 from marcbachmann/patch-1
Fix some typos in the nghttpx how-to doc
2017-09-13 23:59:07 +09:00
Marc Bachmann
e6b8b3d1d3 docs: Fix some typos in the nghttpx how-to 2017-09-11 22:10:03 +02:00
Tatsuhiro Tsujikawa
a170023f23 nghttpx: Verify OCSP response using trusted CA certificates 2017-09-01 21:35:38 +09:00
Tatsuhiro Tsujikawa
4be4c0cddc Revert "nghttpx: Verify OCSP response using trusted CA certificates"
This reverts commit 59c78d5809.
2017-08-30 22:27:02 +09:00
Tatsuhiro Tsujikawa
0de9d374df Merge pull request #1002 from GitaiQAQ/master
Just fix unreachable links and remove ndk...
2017-08-26 22:39:24 +09:00
Tatsuhiro Tsujikawa
0df199198a Merge pull request #1001 from rlei/master
Fix OCSP related error when building with BoringSSL
2017-08-26 22:00:56 +09:00
Gitai
7646e376e0 Fix unreachable 2017-08-26 12:54:03 +08:00
Rick Lei
5996798a34 Fix OCSP related error when building with BoringSSL
BoringSSL has no "openssl/ocsp.h" nor most OCSP related APIs used in
shrpx_tls.cc. This commit add ifdefs to disable related code to allow
building nghttp2 with BoringSSL (again).

It's possible to use !defined(OPENSSL_IS_BORINGSSL), but since BoringSSL
defines OPENSSL_NO_OCSP which is more specific, I chose to go with the
latter one.
2017-08-24 11:56:46 -04:00
Tatsuhiro Tsujikawa
6fec532012 Merge pull request #998 from nghttp2/h2load-fix-timing-script-stall
Fix bug that timing script stalls with -m1
2017-08-24 21:17:43 +09:00
Tatsuhiro Tsujikawa
15713e0b7c h2load: Ignore -n for timing-based mode instead of requiring -n=0 2017-08-23 20:35:01 +09:00
Tatsuhiro Tsujikawa
a6a561af47 Fix bug that timing script stalls with -m1 2017-08-23 20:10:23 +09:00
Tatsuhiro Tsujikawa
09c468a4b4 Merge branch 'sohamm17-master' 2017-08-23 19:22:44 +09:00
Tatsuhiro Tsujikawa
bcda1c2409 Fix assertion failure 2017-08-23 19:22:23 +09:00
Tatsuhiro Tsujikawa
afcd8d9ab1 clang-format 2017-08-23 19:19:00 +09:00
Tatsuhiro Tsujikawa
c9b1c91944 Fix compile error 2017-08-23 19:18:27 +09:00
Tatsuhiro Tsujikawa
5d9434eb09 Merge branch 'master' of https://github.com/sohamm17/nghttp2 into sohamm17-master 2017-08-23 19:16:40 +09:00
Tatsuhiro Tsujikawa
1a44b5d52a Merge pull request #984 from nghttp2/h2load-reservoir-sampling
h2load: Reservoir sampling
2017-08-23 19:00:28 +09:00
Tatsuhiro Tsujikawa
6635ca5e26 Merge pull request #988 from dvetutnev/refactoring_include_directories
Refactoring include directories
2017-08-23 18:59:28 +09:00
Tatsuhiro Tsujikawa
9c6c78833b Bump up version number to 1.26.0-DEV 2017-08-18 23:19:36 +09:00
Tatsuhiro Tsujikawa
9a9ab0813c Update manual pages 2017-08-18 23:00:58 +09:00
Tatsuhiro Tsujikawa
0ccaaa48ce Bump up version number to 1.25.0, LT revision to 28:0:14 2017-08-18 22:38:10 +09:00
Tatsuhiro Tsujikawa
3f2fe98dd1 Update AUTHORS 2017-08-18 22:11:11 +09:00
Tatsuhiro Tsujikawa
0d91e9c255 Update doc 2017-08-18 22:06:43 +09:00
Dmitriy Vetutnev
af926fbe1f Refactoring include directories for build as CMake subdirectory (add_subdirectory(nghttp2)) 2017-08-16 21:28:12 +03:00
Tatsuhiro Tsujikawa
83039ae2d4 h2load: Reservoir sampling 2017-08-14 20:25:02 +09:00
Tatsuhiro Tsujikawa
4c53da6961 Merge pull request #983 from addaleax/static-rcbuf
lib: add nghttp2_rcbuf_is_static()
2017-08-13 09:10:41 +09:00
Anna Henningsen
eb306f463e lib: add nghttp2_rcbuf_is_static()
Add a `nghttp2_rcbuf_is_static()` method to tell whether a rcbuf
is statically allocated.

This can be useful for language bindings that wish to avoid
creating duplicate strings for these buffers; concretely, I am
planning to use this in the Node HTTP/2 module that is being
introduced.
2017-08-12 17:48:14 +02:00
Tatsuhiro Tsujikawa
788835c5fd Merge pull request #980 from nghttp2/fix-forwarded-for-with-proxyprotocol
Fix bug that forwarded for is not affected by proxy protocol
2017-08-09 23:34:43 +09:00
Tatsuhiro Tsujikawa
4d76606fa2 Fix bug that forwarded for is not affected by proxy protocol 2017-08-09 22:44:14 +09:00
Soham Sinha
1baf7d34b3 Duration watcher and warmup watcher is initialised in Worker constructor. Statistic calculation is removed from duration watcher call_back, it's done in free_client. 2017-08-08 17:26:37 -04:00
Soham Sinha
c78159469a Added a function to free a client from Worker's list of client, if the client is destroyed 2017-08-07 18:58:12 -04:00
Soham Sinha
b72ca0289c formatting issue 2017-08-04 14:20:00 -04:00
Soham Sinha
46f670f8a2 concurrent connections are created in timing-based mode. Some safety asserts added. 2017-08-03 16:15:14 -04:00
Soham Sinha
4b44362b9f minor style changes 2017-08-01 20:22:20 -04:00
Soham Sinha
d068a29798 removed unnecessary code 2017-08-01 19:51:47 -04:00
Soham Sinha
0836a51408 Handling requests starting in warm-up phase and ending in MAIN_DURATION 2017-08-01 18:29:00 -04:00
Soham Sinha
566cee8fe7 MAIN_DURATION is initiliazed in Worker constructor, MAIN_DURATION check is removed from two functions because those functions are needed in warm-up phase as well. 2017-08-01 17:45:52 -04:00
Soham Sinha
e85698e131 MAIN_DURATION is initiliazed in Worker constructor, MAIN_DURATION check is removed from two functions because those functions are needed in warm-up phase as well. 2017-08-01 17:45:18 -04:00
Soham Sinha
5f3c541c4c enabled --duration option. 2017-07-28 17:31:13 -04:00
Soham Sinha
3c43e00d8a Timing (#1)
* Adding timing-sensitive load test option in h2load.

* more checks added for parameters

* A worker thread can control its clients' warmup and main duration.

* Changed warmup to an enum variable.

* removed unnecessary call to ev_timer_stop

* assertion is done before starting main measurement phase

* phase variable is implemented only inside the Worker class

* enum to enum class

* else indentation corrected

* check added for timing-based test when duration CB is called explicitly

* New argument is introduced for timing-based benchmarking.

* styling corrections

* duration watcher initialization is pushed back into warmup timeout

* Warmup and Duration timer is moved to Worker instead of clients. Now both timers and phase belongs to the Workers.

* some client functions are modified to return if it's not main_duration phase. client is not destructed but sessions are terminated

* outputs are adjusted for thread.

* Needed to check if a session exist before terminating

* formatting

* more formatting

* formatting
2017-07-28 17:08:20 -04:00
Tatsuhiro Tsujikawa
92d686d356 Merge branch 'mruby-1.3.0' 2017-07-28 00:51:48 +09:00
Tatsuhiro Tsujikawa
0f69e9c825 Fix typo 2017-07-28 00:51:34 +09:00
Tatsuhiro Tsujikawa
217d979458 Update mruby to 1.3.0
Fix compile error with mruby 1.3.0
2017-07-28 00:23:25 +09:00
Tatsuhiro Tsujikawa
cc289972fc Merge pull request #958 from sebdeckers/patch-1
fix: typo
2017-07-15 11:44:14 +09:00
Sebastiaan Deckers
c601e603c2 fix: typo
Came up in downstream code review by @lucaslago https://github.com/nodejs/node/pull/14239#discussion_r127539852
2017-07-15 07:46:26 +08:00
Tatsuhiro Tsujikawa
1002c6da1c src: Use llround instead of round 2017-07-12 23:23:47 +09:00
Tatsuhiro Tsujikawa
0911337689 Bump up version number to 1.25.0-DEV 2017-07-02 17:51:24 +09:00
Tatsuhiro Tsujikawa
3bcc416e13 Update manual pages 2017-07-02 13:40:21 +09:00
Tatsuhiro Tsujikawa
65837806f5 Bump up version number to 1.24.0 2017-07-02 13:37:53 +09:00
Tatsuhiro Tsujikawa
b0772dcc66 Update AUTHORS 2017-07-02 13:31:47 +09:00
Tatsuhiro Tsujikawa
c6d65aad3b Merge branch 'nghttp-not-upgrade-without-reason-phrase' 2017-06-28 21:36:13 +09:00
Tatsuhiro Tsujikawa
18dd20ce55 nghttp: Fix bug that upgrade fails if reason-phrase is missing 2017-06-28 01:01:39 +09:00
Tatsuhiro Tsujikawa
0f6d76a501 Merge pull request #947 from bassosimone/patch-1
README.rst: fix typo
2017-06-23 00:33:00 +09:00
Simone Basso
0f1320109f README.rst: fix typo 2017-06-22 17:03:05 +02:00
Tatsuhiro Tsujikawa
defa28c618 Merge pull request #945 from benjaminp/trailer-grammar
fix up grammar in submit_trailer docs
2017-06-20 00:35:46 +09:00
Benjamin Peterson
b7c95be47c fix up grammar in submit_trailer docs 2017-06-18 23:55:53 -07:00
Tatsuhiro Tsujikawa
a18d154e0e Merge pull request #943 from nghttp2/nghttpx-verify-ocsp-resp-with-cacerts
nghttpx: Verify OCSP response using trusted CA certificates
2017-06-15 20:56:44 +09:00
Tatsuhiro Tsujikawa
52195a12ee Merge pull request #941 from nghttp2/nghttpx-tls-min-proto
nghttpx: Set default minimum TLS version to TLSv1.2
2017-06-13 23:01:54 +09:00
Tatsuhiro Tsujikawa
59c78d5809 nghttpx: Verify OCSP response using trusted CA certificates 2017-06-13 23:00:26 +09:00
Tatsuhiro Tsujikawa
be164fc8f9 nghttpx: Set default minimum TLS version to TLSv1.2
Previously, the default minimum TLS version was TLSv1.1, but the
default cipher list didn't include any compatible ciphers with it.
This made handshake fail if TLSv1.1 was negotiated because there was
no shared ciphers.  To make the default settings consistent, the
default minimum TLS version is now TLSv1.2.
2017-06-12 23:54:12 +09:00
Tatsuhiro Tsujikawa
5833ef1efc Merge pull request #938 from benjaminp/fix-clean
fix cleaning in out-of-tree builds
2017-06-12 00:21:10 +09:00
Benjamin Peterson
28f88d46f3 fix cleaning in out-of-tree builds
The altered previously failed if the rst sources hadn't been copied over.
2017-06-11 00:03:36 -07:00
Tatsuhiro Tsujikawa
6ec7683991 nghttpx: Use nocopy version to send trailer headers to backend
It looks like we can use nocopy version here.  We use nocopy version
in frontend in day 1.
2017-06-02 22:38:39 +09:00
Tatsuhiro Tsujikawa
fb2d8f79d6 Update doc 2017-06-02 22:22:44 +09:00
Tatsuhiro Tsujikawa
8f7fa1b1bf nghttpx: Fix crash in OCSP response verification 2017-05-30 23:52:38 +09:00
Tatsuhiro Tsujikawa
e5889ce622 Bump up version number to 1.24.0-DEV 2017-05-26 23:07:50 +09:00
Tatsuhiro Tsujikawa
3a6f83394c Update bash_completion 2017-05-26 22:17:10 +09:00
Tatsuhiro Tsujikawa
acf36f3d1a Update manual pages 2017-05-26 22:16:51 +09:00
Tatsuhiro Tsujikawa
63e6a8bab2 Bump up version number to 1.23.0, LT revision to 27:3:13 2017-05-26 21:37:28 +09:00
Tatsuhiro Tsujikawa
5361cc6bd1 Update authors 2017-05-26 21:34:43 +09:00
Tatsuhiro Tsujikawa
cabac55394 Merge pull request #925 from sohamm17/patch-1
spelling mistake in arguments to build nghttp apps
2017-05-25 23:38:54 +09:00
Tatsuhiro Tsujikawa
db7483ef10 Merge branch 'nghttpx-verify-ocsp' 2017-05-25 23:37:34 +09:00
Tatsuhiro Tsujikawa
4b51ccbefe examples: Attempt to fix OpenSSL link error 2017-05-25 23:24:44 +09:00
Tatsuhiro Tsujikawa
74c2f1257a nghttpx: Add --no-verify-ocsp to disable OCSP response verification 2017-05-25 23:14:58 +09:00
Tatsuhiro Tsujikawa
1428a5e3ae nghttpx: Verify OCSP response
At least we should make sure that the OCSP response is targeted to the
expected certificate.  This is important because we pass the file path
to the external script, and if the file is replaced because of
renewal, and nghttpx has not reloaded its configuration, the
certificate nghttpx has loaded and the one included in the file
differ.  Verifying the OCSP response detects this, and avoids to send
wrong OCSP response.
2017-05-25 23:14:57 +09:00
Tatsuhiro Tsujikawa
fe021c1524 Merge branch 'memchunk-no-unique-ptr' 2017-05-25 00:53:13 +09:00
Tatsuhiro Tsujikawa
c57bf21306 src: memchunks: Don't use std::unique_ptr to avoid potential SO 2017-05-25 00:23:51 +09:00
Soham Sinha
1743b7d92d spelling mistake in arguments to build nghttp apps 2017-05-22 17:20:30 -04:00
Tatsuhiro Tsujikawa
7f31278c4c Update doc 2017-05-22 22:53:49 +09:00
Tatsuhiro Tsujikawa
8401e16a15 nghttpx: Fix compile error with gcc 2017-05-22 22:10:55 +09:00
Tatsuhiro Tsujikawa
07fb5854f3 nghttpx: Compile with openssl 1.0.2 2017-05-22 22:09:34 +09:00
Tatsuhiro Tsujikawa
b56a99bfba Update bash_completion 2017-05-21 11:43:00 +09:00
Tatsuhiro Tsujikawa
b91e4e4df1 Update manual pages 2017-05-21 11:42:46 +09:00
Tatsuhiro Tsujikawa
52a4d6ac31 Merge branch 'nghttpx-fix-cert-selection' 2017-05-21 11:26:12 +09:00
Tatsuhiro Tsujikawa
796ab87b14 nghttpx: Fix certificate selection based on pub key algorithm 2017-05-21 11:12:47 +09:00
Tatsuhiro Tsujikawa
ed1fad3bd4 nghttpx: Call ERR_clear_error()
Call ERR_clear_error() before the OpenSSL function if we use
SSL_get_error() to examine error stack.
2017-05-21 10:32:12 +09:00
Tatsuhiro Tsujikawa
9c1876f542 nghttpx: Fix certificate indexing bug 2017-05-21 00:19:33 +09:00
Tatsuhiro Tsujikawa
7d111d9963 Merge pull request #923 from nghttp2/compile-with-disable-assert
Compile with --disable-assert
2017-05-18 23:49:41 +09:00
Tatsuhiro Tsujikawa
8c2ce0cf3f Merge pull request #922 from nghttp2/nghttpx-ocsp-startup
nghttpx: Run OCSP at startup
2017-05-18 23:49:23 +09:00
Tatsuhiro Tsujikawa
1b442cb16f Compile with --disable-assert 2017-05-18 23:10:44 +09:00
Tatsuhiro Tsujikawa
2bf3680d87 Merge pull request #919 from projectgus/fix_ndebug_compile
nghttp2_session: Allow for compiling library with -DNDEBUG set
2017-05-18 22:37:51 +09:00
Tatsuhiro Tsujikawa
0d4f0f0db5 nghttpx: Run OCSP at startup
With --ocsp-startup option, nghttpx starts accepting connections after
initial attempts to get OCSP responses finish.  It does not matter
some of the attempts fail.  This feature is useful if OCSP responses
must be available before accepting connections.
2017-05-18 22:33:49 +09:00
Angus Gratton
e17ff8fd32 nghttp2_session: Allow for compiling library with -DNDEBUG set 2017-05-17 14:43:06 +10:00
Tatsuhiro Tsujikawa
14edd12304 nghttpx: Refactor the code for the anti-replay 2017-05-14 17:45:35 +09:00
Tatsuhiro Tsujikawa
e6ffdb23a4 nghttpx: Share session_cache_ssl_ctx across threads 2017-05-14 17:43:11 +09:00
Tatsuhiro Tsujikawa
98fdedac06 Merge pull request #917 from Tapanito/patch-1
Update docs
2017-05-13 10:27:22 +09:00
Tapanito
255037264a updated docs 2017-05-12 16:35:44 +01:00
Tatsuhiro Tsujikawa
d3fcbe9a02 Merge branch 'invalid-header-field-error' 2017-05-12 21:37:20 +09:00
Tatsuhiro Tsujikawa
bcdd588c6e Merge branch 'nghttpx-wildcard-path-match' 2017-05-11 23:50:56 +09:00
Tatsuhiro Tsujikawa
b5007d45f7 nghttpx: Wildcard path matching
This commit adds wildcard path matching.  If path pattern given in
backend option ends with "*", it is considered as wildcard path.  "*"
must match at least one character.  All paths which include wildcard
path without last "*" as prefix, and are strictly longer than wildcard
path without last "*" are matched.
2017-05-11 22:15:28 +09:00
Tatsuhiro Tsujikawa
a584cf5a4f Use clang-format-4.0 2017-04-30 15:45:53 +09:00
Tatsuhiro Tsujikawa
77f7a2fa7f Update doc 2017-04-29 22:21:21 +09:00
Tatsuhiro Tsujikawa
f2c539dc70 Clarify the effect of nghttp2_option_set_no_http_messaging 2017-04-29 21:00:20 +09:00
Tatsuhiro Tsujikawa
78d7160a99 Treat incoming invalid regular header field as stream error
Previously, the incoming invalid regular header field was ignored by
default.  With this commit, they are now treated as stream error, and
the stream is reset by default.  The error code used is now
PROTOCOL_ERROR, instead of INTERNAL_ERROR.
2017-04-28 23:46:06 +09:00
Tatsuhiro Tsujikawa
196673bbce nghttp: Remove unused short option 'g' 2017-04-28 22:39:12 +09:00
Tatsuhiro Tsujikawa
794d13082c Merge branch 'nghttp-no-verify-peer' 2017-04-28 22:36:23 +09:00
Tatsuhiro Tsujikawa
5f5cf4107e nghttpx: Reseve rcbufs_ 2017-04-28 22:31:09 +09:00
Tatsuhiro Tsujikawa
6f3ec54b9f nghttp: Add -y, --no-verify-peer option to suppress peer verify warn 2017-04-28 09:53:37 +09:00
Tatsuhiro Tsujikawa
58043a6b04 nghttpx: Guard the presence of TLS1_3_VERSION 2017-04-27 23:13:15 +09:00
Tatsuhiro Tsujikawa
a885315ef5 Merge branch 'nghttpx-unrecognized-sni' 2017-04-27 22:57:54 +09:00
Tatsuhiro Tsujikawa
d7581525ac nghttpx: Update TLSv1.3 TLS record overhead 2017-04-27 22:57:06 +09:00
Tatsuhiro Tsujikawa
385068eb91 Merge branch 'altsvc-invalid-callback' 2017-04-27 22:35:25 +09:00
Tatsuhiro Tsujikawa
1085f68018 nghttpx: Return SSL_TLSEXT_ERR_NOACK if server name is not recognized
With this commit, SSL_TLSEXT_ERR_NOACK is returned from
servername_callback, which removes server_name extension from
ServerHello.  CertLookupTree is now used even if the number of server
certificate is one.  It is better to exercise it regularly.
2017-04-27 22:25:58 +09:00
Tatsuhiro Tsujikawa
21af775ce0 Call nghttp2_on_invalid_frame_callback if altsvc validation fails 2017-04-27 18:53:43 +09:00
Tatsuhiro Tsujikawa
bf16fee6e9 Merge pull request #903 from nghttp2/nghttpx-forward-multiple-header-fields
nghttpx: Forward multiple via, xff, and xfp header fields
2017-04-26 22:32:33 +09:00
Tatsuhiro Tsujikawa
2358a2137a Refactor predicate functions 2017-04-26 22:31:43 +09:00
Tatsuhiro Tsujikawa
66baa7dc25 Estimate header block size after predicate function succeeds 2017-04-26 22:15:53 +09:00
Tatsuhiro Tsujikawa
d63b4c1034 nghttpx: Forward multiple via, xff, and xfp header fields
Previously, for Via, X-Forwarded-For, and X-Forwarded-Proto header
field, nghttpx only forwarded the last header field of each.  With
this commit, nghttpx forwards all of them if it is configured to do
so.
2017-04-26 21:23:13 +09:00
Tatsuhiro Tsujikawa
963e220a1c Bump up version number to 1.23.0-DEV 2017-04-24 22:34:13 +09:00
Tatsuhiro Tsujikawa
2f146e4d4c Update manual pages 2017-04-24 21:41:15 +09:00
Tatsuhiro Tsujikawa
f796eede5a Bump up version number to 1.22.0, LT revision to 27:2:13 2017-04-24 21:32:18 +09:00
Tatsuhiro Tsujikawa
c89453be95 Update AUTHORS 2017-04-24 21:29:12 +09:00
Tatsuhiro Tsujikawa
c3f5f5ca36 nghttpx: Clarify --conf option behaviour 2017-04-20 22:25:38 +09:00
Tatsuhiro Tsujikawa
911d12f7c4 nghttpx: Add log when loading configuration file 2017-04-20 22:22:29 +09:00
Tatsuhiro Tsujikawa
34d3c45d35 Update manual pages 2017-04-19 23:03:08 +09:00
Tatsuhiro Tsujikawa
17614312e0 Merge pull request #892 from nghttp2/nghttpx-sni-fwd
nghttpx: SNI based backend server selection
2017-04-19 21:22:15 +09:00
Tatsuhiro Tsujikawa
977779ae8d Merge pull request #896 from nghttp2/nghttpx-add-tls-sni-log-var
nghttpx: Add $tls_sni access log variable
2017-04-19 21:21:01 +09:00
Tatsuhiro Tsujikawa
a2e35a0757 nghttpx: Add $tls_sni access log variable 2017-04-18 22:44:26 +09:00
Tatsuhiro Tsujikawa
a4a2b6403b nghttpx: Use SHRPX_LOGF_TLS_* instead of SHRPX_LOGF_SSL_* 2017-04-18 22:34:08 +09:00
Tatsuhiro Tsujikawa
8ce8e289c9 Merge pull request #895 from nghttp2/nghttpx-rename-ssl-log-vars
nghttpx: Rename ssl_* log variables as tls_*
2017-04-18 22:31:44 +09:00
Tatsuhiro Tsujikawa
03be97e437 nghttpx: Rename ssl_* log variables as tls_*
The exiting ssl_* log variables still work for backward compatibility.
2017-04-18 22:11:05 +09:00
Tatsuhiro Tsujikawa
2c5cf5a82a Merge pull request #894 from nghttp2/nghttpx-fix-path-match
nghttpx: Fix path matching bug
2017-04-18 21:28:21 +09:00
Tatsuhiro Tsujikawa
0a2d1965df nghttpx: Fix path matching bug
Previously, if path is empty or path does not start with "/", nghttpx
did not try to match with wildcard pattern.  This commit fixes it.
2017-04-18 21:03:50 +09:00
Tatsuhiro Tsujikawa
c8a5f1e335 nghttpx: SNI based backend server selection 2017-04-16 23:47:10 +09:00
Tatsuhiro Tsujikawa
5e00cf9620 Update doc 2017-04-14 00:55:31 +09:00
Tatsuhiro Tsujikawa
ce6370e25c Merge pull request #886 from lstefani/patch-1
Update nghttp2_session.c
2017-04-14 00:16:06 +09:00
Tatsuhiro Tsujikawa
3f8c1e4b34 tests: Fix failmalloc tests 2017-04-14 00:00:36 +09:00
lstefani
25cda200be Update nghttp2_session.c
Add missing free call on error in inflight_settings_new().
2017-04-13 10:00:15 -04:00
Tatsuhiro Tsujikawa
a1bc83a2ba Merge pull request #881 from mway/dev/request-priority
Support specifying stream priority via session::submit()
2017-04-12 23:36:40 +09:00
Matt Way
bc3949db9e Support specifying stream priority via session::submit() 2017-04-12 10:07:16 -04:00
Tatsuhiro Tsujikawa
6cfa885207 nghttpx: Remove unused lambda capture 2017-04-12 22:09:44 +09:00
Tatsuhiro Tsujikawa
899588e0b5 Update bash_completion 2017-04-09 16:10:07 +09:00
Tatsuhiro Tsujikawa
49af52a68d Update manual pages 2017-04-09 16:09:44 +09:00
Tatsuhiro Tsujikawa
ec908af19c integration: Use nip.io instead of xip.io 2017-04-09 16:06:37 +09:00
Tatsuhiro Tsujikawa
e61ac4682e Merge branch 'nghttpx-xfp-take2' 2017-04-09 16:02:53 +09:00
Tatsuhiro Tsujikawa
4d10dce61d nghttpx: Only send SCT for leaf certificate 2017-04-09 14:38:18 +09:00
Tatsuhiro Tsujikawa
c569830dfc Merge branch 'nghttpx-tls13-sct' 2017-04-09 14:24:00 +09:00
Tatsuhiro Tsujikawa
2d9fd87029 nghttpx: Enable signed_certificate_timestamp extension for TLSv1.3 2017-04-09 14:11:49 +09:00
Tatsuhiro Tsujikawa
2670bfb8ba integration: Add tests for X-Forwarded-Proto handling 2017-04-08 18:46:37 +09:00
Tatsuhiro Tsujikawa
cc9190ab37 nghttpx: Add options for X-Forwarded-Proto header field
This commit adds 2 new options to handle X-Forwarded-Proto header
field.  The --no-add-x-forwarded-proto option makes nghttpx not to
append X-Forwarded-Proto value.  The
--no-strip-incoming-x-forwarded-proto option prevents nghttpx from
stripping the header field from client.

Previously, nghttpx always strips incoming header field, and set its
own header field.  This commit preserves this behaviour, and adds
additional knobs.
2017-04-08 18:46:36 +09:00
Tatsuhiro Tsujikawa
980570de71 Revert "nghttpx: Add options for X-Forwarded-Proto header field"
This reverts commit 8c0b2c684a.
2017-04-08 18:37:54 +09:00
Tatsuhiro Tsujikawa
ef92b54db3 Revert "integration: Add tests for X-Forwarded-Proto handling"
This reverts commit 6aa581d2f0.
2017-04-08 18:34:10 +09:00
Tatsuhiro Tsujikawa
0130124cea Revert "doc: Add migration doc for nghttpx"
This reverts commit 82b326e684.
2017-04-08 18:34:07 +09:00
Tatsuhiro Tsujikawa
e2a7e867f9 integration: Add more tests for 204 status code 2017-04-07 22:36:46 +09:00
Tatsuhiro Tsujikawa
32ce0ce5d9 Merge branch 'nghttpx-fix-204-handling' 2017-04-07 22:11:39 +09:00
Tatsuhiro Tsujikawa
28082ff5f5 integration: Add tests for 204 status code 2017-04-07 21:46:33 +09:00
Tatsuhiro Tsujikawa
46ccc4332c nghttpx: Fix bug that 204 from h1 backend is always treated as error 2017-04-07 21:45:13 +09:00
Tatsuhiro Tsujikawa
3a1217e667 Update bash_completion 2017-04-06 20:26:32 +09:00
Tatsuhiro Tsujikawa
39fd0c1278 Update manual pages 2017-04-06 20:26:08 +09:00
Tatsuhiro Tsujikawa
4e6bd54dd1 Merge branch 'nghttpx-single-process' 2017-04-06 20:18:33 +09:00
Tatsuhiro Tsujikawa
5c9f46a6b0 Merge branch 'nghttp-verify-server-certificate' 2017-04-06 20:17:29 +09:00
Tatsuhiro Tsujikawa
7d53866157 Update doc 2017-04-06 20:14:49 +09:00
Tatsuhiro Tsujikawa
9a2e948c42 Update doc
Add section to promote the build from tar archives.
2017-04-06 20:13:00 +09:00
Tatsuhiro Tsujikawa
223e971c7e nghttpx: Add --single-process option
With --single-process option, nghttpx will run in a single process
mode where master and worker are unified into one process.  nghttpx
still spawns additional process for neverbleed.  In the single process
mode, signal handling is disabled.
2017-04-06 20:02:57 +09:00
Tatsuhiro Tsujikawa
df814223ff Merge branch 'nghttpx-xfp' 2017-04-06 19:36:27 +09:00
Tatsuhiro Tsujikawa
82b326e684 doc: Add migration doc for nghttpx 2017-04-06 19:24:02 +09:00
Tatsuhiro Tsujikawa
6aa581d2f0 integration: Add tests for X-Forwarded-Proto handling 2017-04-06 19:20:08 +09:00
Tatsuhiro Tsujikawa
8c0b2c684a nghttpx: Add options for X-Forwarded-Proto header field
This commit adds 2 new options to handle X-Forwarded-Proto header
field.  The --add-x-forwarded-proto option makes nghttpx append
X-Forwarded-Proto value.  The --strip-incoming-x-forwarded-proto
option makes nghttpx to strip the header field from client.

Previously, nghttpx always strips incoming header field, and set its
own header field.  This commit changes this behaviour.  Now nghttpx
does not strip, and append X-Forwarded-Proto header field by default.
The X-Forwarded-For, and Forwarded header fields are also handled in
the same way.  To recover the old behaviour, use
--add-x-forwarded-proto and --strip-incoming-x-forwarded-proto
options.
2017-04-06 19:17:36 +09:00
Tatsuhiro Tsujikawa
62324781bd integration: Close channel instead of writing struct 2017-04-05 23:57:33 +09:00
Tatsuhiro Tsujikawa
7ae0b2dc09 nghttp: Verify server certificate and show warning if it fails 2017-04-01 17:49:57 +09:00
Tatsuhiro Tsujikawa
058122b804 nghttpx: Rename shrpx_ssl.{h,cc} as shrpx_tls.{h,cc}
The namespace shrpx::ssl was also renamed as shrpx::tls.
2017-04-01 15:12:28 +09:00
Tatsuhiro Tsujikawa
69f63c529d src: Rename ssl.{h,cc} as tls.{h,cc}
nghttp2::ssl namespace was also renamed as nghttp2::tls.
2017-04-01 15:12:28 +09:00
Tatsuhiro Tsujikawa
e17a6b29b6 nghttpx: Use 502 as server error code 2017-04-01 14:04:55 +09:00
Tatsuhiro Tsujikawa
b12c2a13c0 nghttpx: Fail handshake if server certificate verification fails
Previously, we drop connection if server certificate verification
fails after handshake.  With this commit, we fail handshake if that
happens.
2017-04-01 13:41:41 +09:00
Tatsuhiro Tsujikawa
236c835abc nghttpx: Don't enable SSL_MODE_AUTO_RETRY since we do non-blocking I/O 2017-04-01 12:05:07 +09:00
Tatsuhiro Tsujikawa
b41a5afe04 Merge branch 'fix-asio-client-ping' 2017-03-31 22:20:07 +09:00
Tatsuhiro Tsujikawa
ad338bfa44 asio: Fix crash if connect takes longer time than ping interval 2017-03-31 21:17:57 +09:00
Tatsuhiro Tsujikawa
a899522679 asio: Fix compile error 2017-03-31 21:14:08 +09:00
Tatsuhiro Tsujikawa
b9b58c781e nghttpx: Avoid extra TLS handshake calls 2017-03-30 22:23:55 +09:00
Tatsuhiro Tsujikawa
aa1eec4642 nghttpx: Cache client side session inside openssl callback 2017-03-30 21:07:58 +09:00
Tatsuhiro Tsujikawa
0c8d9469ea nghttpx: Use SSL_CTX_set_early_data_enabled with boringssl 2017-03-27 23:58:49 +09:00
Tatsuhiro Tsujikawa
079e1bdffc Revert "nghttpx: Use SSL_CTX_set_early_data_enabled with boringssl"
This reverts commit b4337d1b54.
2017-03-27 23:47:24 +09:00
Tatsuhiro Tsujikawa
b4337d1b54 nghttpx: Use SSL_CTX_set_early_data_enabled with boringssl 2017-03-27 23:29:28 +09:00
Tatsuhiro Tsujikawa
e6a11c5e12 Bump up version number to 1.22.0-DEV 2017-03-27 23:13:56 +09:00
Tatsuhiro Tsujikawa
dbe287ff5e nghttpx: Print version number with -v option 2017-03-27 22:49:53 +09:00
Tatsuhiro Tsujikawa
61dc1a7c62 Update man pages 2017-03-27 22:48:00 +09:00
Tatsuhiro Tsujikawa
dc1e0c0195 Bump up version number to 1.21.0, LT revision to 27:1:13 2017-03-27 22:45:23 +09:00
Tatsuhiro Tsujikawa
041531458b Merge pull request #858 from nghttp2/nghttpx-ai-addrconfig
nghttpx: Retry getaddrinfo without AI_ADDRCONFIG
2017-03-27 22:37:07 +09:00
Tatsuhiro Tsujikawa
1374bb81fd nghttpx: Enable X25519 with boringssl 2017-03-27 21:18:44 +09:00
Tatsuhiro Tsujikawa
f41ac103d3 nghttpx: Retry getaddrinfo without AI_ADDRCONFIG 2017-03-27 00:20:42 +09:00
Tatsuhiro Tsujikawa
f6301714db nghttpx: Avoid copy of std::mt19937 which is huge 2017-03-26 21:14:34 +09:00
Tatsuhiro Tsujikawa
7dc39b1ee9 nghttpx: Failing to listen on server socket is fatal error 2017-03-26 11:04:45 +09:00
Tatsuhiro Tsujikawa
696a7ce407 Merge pull request #856 from nghttp2/escape-access-log
Escape access log
2017-03-25 23:36:02 +09:00
Tatsuhiro Tsujikawa
d28d788623 Merge pull request #853 from PiotrSikora/ssl_ctx_set_proto_versions
src: BoringSSL supports SSL_CTX_set_{min,max}_proto_version.
2017-03-25 19:45:12 +09:00
Tatsuhiro Tsujikawa
99122ee7bb nghttpx: Find illegal character in path for SPDY CONNECT method 2017-03-25 19:18:35 +09:00
Tatsuhiro Tsujikawa
19ee7ec794 nghttpx: Escape certain characters in access log
The certain characters coming from client are now escaped with "\xNN"
where NN is the ascii code of the character in hex notation.
2017-03-25 19:17:24 +09:00
Piotr Sikora
cd9ec0d20f src: BoringSSL supports SSL_CTX_set_{min,max}_proto_version.
Signed-off-by: Piotr Sikora <piotrsikora@google.com>
2017-03-23 19:26:49 -07:00
Tatsuhiro Tsujikawa
e77883e980 nghttpx: Fix typo 2017-03-22 22:53:46 +09:00
Tatsuhiro Tsujikawa
0994c92550 nghttpx: Don't cache session server side if TLS version is 1.3 2017-03-22 21:34:13 +09:00
Tatsuhiro Tsujikawa
465c7208cc nghttpx: Don't look up session ID if length is 0 2017-03-22 21:33:31 +09:00
Tatsuhiro Tsujikawa
4f9f181f07 Merge pull request #848 from nghttp2/asio-client-ping
asio: client: Send PING after 30 seconds idle
2017-03-22 21:20:23 +09:00
Tatsuhiro Tsujikawa
b7e7a4bf26 asio: client: Send PING after 30 seconds idle 2017-03-20 18:37:56 +09:00
Tatsuhiro Tsujikawa
c7df65309b nghttpx: Ignore further input if connection is going to close 2017-03-19 13:24:12 +09:00
Tatsuhiro Tsujikawa
26900262f3 Revert "nghttpx: Attempt to avoid TCP RST on socket closure on Linux"
This reverts commit f69b52b1aa.
2017-03-18 22:43:30 +09:00
Tatsuhiro Tsujikawa
9b5ce36368 nghttpx: Reset write timer on write 2017-03-18 21:33:00 +09:00
Tatsuhiro Tsujikawa
f69b52b1aa nghttpx: Attempt to avoid TCP RST on socket closure on Linux 2017-03-18 00:59:26 +09:00
Tatsuhiro Tsujikawa
1e1d908c12 nghttpx: Eliminate global std::random_device 2017-03-17 22:25:10 +09:00
Tatsuhiro Tsujikawa
6c69d675da nghttpx: Should take reference 2017-03-17 22:24:32 +09:00
Tatsuhiro Tsujikawa
feabd6f739 nghttpx: Delete unused delete_bio_method 2017-03-15 23:37:39 +09:00
Tatsuhiro Tsujikawa
1ea590c364 nghttpx: Return new BIO_METHOD object with OpenSSL < 1.1.0 2017-03-15 23:36:38 +09:00
Tatsuhiro Tsujikawa
b21779e685 nghttpx: Use raw pointer for apis 2017-03-15 23:33:07 +09:00
Tatsuhiro Tsujikawa
12a4e7c3a2 src: Use raw pointer for ssl_global_locks 2017-03-15 23:24:28 +09:00
Tatsuhiro Tsujikawa
799a76de74 nghttpx: Lesser usage of DIE 2017-03-15 23:14:07 +09:00
Tatsuhiro Tsujikawa
b1fee8ff63 nghttpx: Use raw pointer for config 2017-03-15 23:13:14 +09:00
Tatsuhiro Tsujikawa
9cc223d419 nghttpx: Use constexpr 2017-03-15 23:12:50 +09:00
Tatsuhiro Tsujikawa
20edd64301 nghttpx: Handle return value of write(2) 2017-03-15 21:28:53 +09:00
Tatsuhiro Tsujikawa
9aee518352 nghttpx: Effectively revert ff64f64e1d 2017-03-15 00:07:57 +09:00
Tatsuhiro Tsujikawa
6ca515ea70 Fix sphinx warning about README markup 2017-03-12 23:46:21 +09:00
Tatsuhiro Tsujikawa
51b933c5f0 src: Use "Modern compatibility" ciphers by default 2017-03-11 23:58:52 +09:00
Tatsuhiro Tsujikawa
3f13d33543 Merge branch 'eliminate-u-macro' 2017-03-11 18:56:23 +09:00
Tatsuhiro Tsujikawa
85a12429ee Eliminate _U_ macro
Instead use (void)VAR for better compiler compatibility.
2017-03-11 18:45:49 +09:00
Tatsuhiro Tsujikawa
3e0e3f5459 src: Fix typo 2017-03-10 23:10:13 +09:00
Tatsuhiro Tsujikawa
801869a5d5 Merge branch 'fix-nghttp2_session_want_write' 2017-03-07 23:33:58 +09:00
Tatsuhiro Tsujikawa
54f4b85beb Fix nghttp2_session_want_write
This commit fixes the bug in nghttp2_session_want_write.  Previously,
it may return 0 if there is pending frames after GOAWAY frame is
submitted.

To avoid the situation that nghttp2_session_want_write keeps returning
nonzero after GOAWAY and the number of active streams is 0 (e.g., keep
receiving SETTINGS or PING), nghttp2_session_mem_recv now just
swallows the input data without parsing in this case.
2017-03-07 22:55:39 +09:00
Tatsuhiro Tsujikawa
fa074145a4 Merge pull request #788 from nghttp2/nghttpx-h2-proxy-pattern-match
nghttpx: Enable backend pattern matching with http2-proxy
2017-03-06 21:22:34 +09:00
Tatsuhiro Tsujikawa
b2d6550179 src: BoringSSL only requires CRYPTO_library_init 2017-03-05 21:36:52 +09:00
Tatsuhiro Tsujikawa
62dd1f5177 src: OpenSSL 1.1.0 does not require explicit initialization 2017-03-05 19:57:06 +09:00
Tatsuhiro Tsujikawa
dc7c12d474 Document pkg-config path usage 2017-03-02 23:09:56 +09:00
Tatsuhiro Tsujikawa
a6dda5f91c nghttpx: Log rstatus in hex 2017-03-01 23:21:11 +09:00
Tatsuhiro Tsujikawa
c1f7795dd6 nghttpx: Set close-on-exec flag on listener in worker process 2017-03-01 23:20:36 +09:00
Tatsuhiro Tsujikawa
4989e6e419 nghttpx: Don't call functions which are not async-signal-safe
.. after fork but before execv in multithreaded process.
2017-03-01 22:42:30 +09:00
Tatsuhiro Tsujikawa
d4963bcd32 Merge pull request #823 from alagoutte/gcc7
nghtt2_gzip: fix this statement may fall through [-Werror=implicit-fa…
2017-02-28 23:21:29 +09:00
Alexis La Goutte
d725255784 nghttp2_gzip: fix this statement may fall through [-Werror=implicit-fallthrough=] found by gcc7 2017-02-27 21:38:55 +01:00
Tatsuhiro Tsujikawa
5f4159a0d7 tests: Fix uninitialized bug 2017-02-27 21:26:12 +09:00
Tatsuhiro Tsujikawa
0a2a5e6604 Bump up version number to 1.21.0-DEV 2017-02-26 19:16:33 +09:00
Tatsuhiro Tsujikawa
3ddc446ba2 nghttpx: Enable backend pattern matching with http2-proxy 2017-01-26 01:04:27 +09:00
176 changed files with 6338 additions and 4934 deletions

View File

@@ -4,7 +4,7 @@ AccessModifierOffset: -2
AlignAfterOpenBracket: Align
AlignConsecutiveAssignments: false
AlignConsecutiveDeclarations: false
AlignEscapedNewlinesLeft: false
AlignEscapedNewlines: Right
AlignOperands: true
AlignTrailingComments: true
AllowAllParametersOfDeclarationOnNextLine: true
@@ -31,14 +31,20 @@ BraceWrapping:
BeforeCatch: false
BeforeElse: false
IndentBraces: false
SplitEmptyFunction: true
SplitEmptyRecord: true
SplitEmptyNamespace: true
BreakBeforeBinaryOperators: None
BreakBeforeBraces: Attach
BreakBeforeInheritanceComma: false
BreakBeforeTernaryOperators: true
BreakConstructorInitializersBeforeComma: false
BreakConstructorInitializers: BeforeColon
BreakAfterJavaFieldAnnotations: false
BreakStringLiterals: true
ColumnLimit: 80
CommentPragmas: '^ IWYU pragma:'
CompactNamespaces: false
ConstructorInitializerAllOnOneLineOrOnePerLine: true
ConstructorInitializerIndentWidth: 4
ContinuationIndentWidth: 4
@@ -46,7 +52,11 @@ Cpp11BracedListStyle: true
DerivePointerAlignment: false
DisableFormat: false
ExperimentalAutoDetectBinPacking: false
ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ]
FixNamespaceComments: true
ForEachMacros:
- foreach
- Q_FOREACH
- BOOST_FOREACH
IncludeCategories:
- Regex: '^"(llvm|llvm-c|clang|clang-c)/'
Priority: 2
@@ -68,6 +78,7 @@ NamespaceIndentation: None
ObjCBlockIndentWidth: 2
ObjCSpaceAfterProperty: false
ObjCSpaceBeforeProtocolList: true
PenaltyBreakAssignment: 2
PenaltyBreakBeforeFirstCallParameter: 19
PenaltyBreakComment: 300
PenaltyBreakFirstLessLess: 120
@@ -77,7 +88,9 @@ PenaltyReturnTypeOnItsOwnLine: 60
PointerAlignment: Right
ReflowComments: true
SortIncludes: false
SortUsingDeclarations: true
SpaceAfterCStyleCast: false
SpaceAfterTemplateKeyword: true
SpaceBeforeAssignmentOperators: true
SpaceBeforeParens: ControlStatements
SpaceInEmptyParentheses: false

View File

@@ -1,3 +1,4 @@
dist: trusty
env:
matrix:
- CI_BUILD=cmake
@@ -6,15 +7,13 @@ language: cpp
compiler:
- clang
- gcc
sudo: false
sudo: required
addons:
apt:
sources:
- ubuntu-toolchain-r-test
- george-edison55-precise-backports
packages:
- g++-4.9
- libstdc++-4.9-dev
- g++-7
- autoconf
- automake
- autotools-dev
@@ -33,29 +32,18 @@ addons:
- cmake-data
before_install:
- $CC --version
- if [ "$CXX" = "g++" ]; then export CXX="g++-4.9" CC="gcc-4.9"; fi
- if [ "$CXX" = "g++" ]; then export CXX="g++-7" CC="gcc-7"; 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
- cd third-party
- 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
- if [ "$CI_BUILD" = "autotools" ]; then autoreconf -i; fi
- git submodule update --init
- 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
- if [ "$CI_BUILD" = "autotools" ]; then ./configure --with-mruby; fi
- if [ "$CI_BUILD" = "cmake" ]; then cmake -DENABLE_WERROR=1 -DWITH_MRUBY=1 -DWITH_NEVERBLEED=1; fi
script:
- if [ "$CI_BUILD" = "autotools" ]; then make distcheck; fi
- if [ "$CI_BUILD" = "autotools" ]; then make distcheck DISTCHECK_CONFIGURE_FLAGS="--with-mruby --with-neverbleed --enable-werror CPPFLAGS=-fsanitize=address LDFLAGS=\"-fsanitize=address -fuse-ld=gold\""; fi
- if [ "$CI_BUILD" = "cmake" ]; then make check; fi
# As of April, 23, 2016, golang http2 build fails, probably because
# the default go version is too old.

20
AUTHORS
View File

@@ -21,21 +21,26 @@ Amir Pakdel
Anders Bakken
Andreas Pohl
Andy Davies
Angus Gratton
Anna Henningsen
Ant Bryan
Benedikt Christoph Wolters
Benedikt Christoph Wolters
Bernard Spil
Benjamin Peterson
Bernard Spil
Brian Card
Brian Suh
Daniel Evers
Daniel Stenberg
Dave Reisner
David Beitey
David Weekly
Dmitriy Vetutnev
Dylan Plecki
Etienne Cimon
Fabian Möller
Fabian Wiesel
Gabi Davar
Gitai
Google Inc.
Jacob Champion
Jan-E
@@ -50,11 +55,15 @@ Kenny (kang-yen) Peng
Kenny Peng
Kit Chan
Kyle Schomp
LazyHamster
Lucas Pardue
MATSUMOTO Ryosuke
Marc Bachmann
Matt Rudary
Matt Way
Mike Conlen
Mike Frysinger
Mike Lothian
Nicholas Hurley
Nora Shoemaker
Peeyush Aggarwal
@@ -63,15 +72,21 @@ Piotr Sikora
Raul Gutierrez Segales
Remo E
Reza Tavakoli
Rick Lei
Ross Smith II
Scott Mitchell
Sebastiaan Deckers
Simone Basso
Soham Sinha
Stefan Eissing
Stephen Ludin
Sunpoet Po-Chuan Hsieh
Svante Signell
Syohei YOSHIDA
Tapanito
Tatsuhiko Kubo
Tatsuhiro Tsujikawa
Tobias Geerinckx-Rice
Tom Harwood
Tomasz Buchert
Tomasz Torcz
@@ -89,6 +104,7 @@ dalf
es
fangdingjun
kumagi
lstefani
makovich
mod-h2-dev
moparisthebest

View File

@@ -24,15 +24,15 @@
cmake_minimum_required(VERSION 3.0)
# XXX using 1.8.90 instead of 1.9.0-DEV
project(nghttp2 VERSION 1.20.0)
project(nghttp2 VERSION 1.31.0)
# See versioning rule:
# http://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html
set(LT_CURRENT 27)
set(LT_CURRENT 30)
set(LT_REVISION 0)
set(LT_AGE 13)
set(LT_AGE 16)
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH})
include(Version)
math(EXPR LT_SOVERSION "${LT_CURRENT} - ${LT_AGE}")
@@ -79,7 +79,7 @@ else()
set(ENABLE_PYTHON_BINDINGS_DEFAULT OFF)
endif()
find_package(LibXml2 2.7.7)
find_package(LibXml2 2.6.26)
set(WITH_LIBXML2_DEFAULT ${LIBXML2_FOUND})
find_package(Jemalloc)
set(WITH_JEMALLOC_DEFAULT ${JEMALLOC_FOUND})
@@ -106,23 +106,13 @@ endif()
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}}")
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()
@@ -312,6 +302,7 @@ check_type_size("time_t" SIZEOF_TIME_T)
include(CheckFunctionExists)
check_function_exists(_Exit HAVE__EXIT)
check_function_exists(accept4 HAVE_ACCEPT4)
check_function_exists(mkostemp HAVE_MKOSTEMP)
include(CheckSymbolExists)
# XXX does this correctly detect initgroups (un)availability on cygwin?

View File

@@ -10,39 +10,47 @@
#
# $ sudo docker run -v /path/to/dest:/out nghttp2-android cp /root/build/nghttp2/src/nghttpx /out
FROM ubuntu:vivid
# Only use standalone-toolchain for reduce size
FROM ubuntu:xenial
MAINTAINER Tatsuhiro Tsujikawa
ENV ANDROID_HOME /root/android
ENV PREFIX $ANDROID_HOME/usr/local
ENV ANDROID_HOME /root
ENV TOOLCHAIN $ANDROID_HOME/toolchain
ENV PATH $TOOLCHAIN/bin:$PATH
# It would be better to use nearest ubuntu archive mirror for faster
# downloads.
# RUN sed -ie 's/archive\.ubuntu/jp.archive.ubuntu/g' /etc/apt/sources.list
ENV NDK_VERSION r14b
RUN apt-get update
# genisoimage, libc6-i386 and lib32stdc++6 are required to decompress ndk.
RUN apt-get install -y make binutils autoconf automake autotools-dev libtool \
pkg-config git curl dpkg-dev libxml2-dev \
genisoimage libc6-i386 lib32stdc++6
WORKDIR /root
RUN apt-get update && \
apt-get install -y unzip make binutils autoconf \
automake autotools-dev libtool pkg-config git \
curl dpkg-dev libxml2-dev genisoimage libc6-i386 \
lib32stdc++6 python&& \
rm -rf /var/cache/apk/*
# Install toolchain
RUN curl -L -O https://dl.google.com/android/repository/android-ndk-$NDK_VERSION-linux-x86_64.zip && \
unzip -q android-ndk-$NDK_VERSION-linux-x86_64.zip && \
rm android-ndk-$NDK_VERSION-linux-x86_64.zip && \
mkdir -p $ANDROID_HOME/toolchain && \
$ANDROID_HOME/android-ndk-$NDK_VERSION/build/tools/make-standalone-toolchain.sh \
--install-dir=$ANDROID_HOME/toolchain \
--toolchain=arm-linux-androideabi-4.9 \
--force && \
rm -r android-ndk-$NDK_VERSION
ENV PREFIX /root/usr/local
# Setup version of libraries
ENV OPENSSL_VERSION 1.0.2d
ENV SPDYLAY_VERSION v1.4.0
ENV LIBEV_VERSION 4.19
ENV ZLIB_VERSION 1.2.8
ENV CARES_VERSION 1.13.0
ENV NGHTTP2_VERSION v1.24.0
WORKDIR /root/build
RUN curl -L -O http://dl.google.com/android/ndk/android-ndk-r10d-linux-x86_64.bin && \
chmod a+x android-ndk-r10d-linux-x86_64.bin && \
./android-ndk-r10d-linux-x86_64.bin && \
rm android-ndk-r10d-linux-x86_64.bin
WORKDIR /root/build/android-ndk-r10d
RUN /bin/bash build/tools/make-standalone-toolchain.sh \
--install-dir=$ANDROID_HOME/toolchain \
--toolchain=arm-linux-androideabi-4.9 --llvm-version=3.5 \
--system=linux-x86_64
WORKDIR /root/build
RUN git clone https://github.com/tatsuhiro-t/spdylay
RUN git clone https://github.com/tatsuhiro-t/spdylay -b $SPDYLAY_VERSION --depth 1
WORKDIR /root/build/spdylay
RUN autoreconf -i && \
./configure \
@@ -59,22 +67,22 @@ RUN autoreconf -i && \
make install
WORKDIR /root/build
RUN curl -L -O https://www.openssl.org/source/openssl-1.0.2d.tar.gz && \
tar xf openssl-1.0.2d.tar.gz && \
rm openssl-1.0.2d.tar.gz
RUN curl -L -O https://www.openssl.org/source/openssl-$OPENSSL_VERSION.tar.gz && \
tar xf openssl-$OPENSSL_VERSION.tar.gz && \
rm openssl-$OPENSSL_VERSION.tar.gz
WORKDIR /root/build/openssl-1.0.2d
WORKDIR /root/build/openssl-$OPENSSL_VERSION
RUN export CROSS_COMPILE=$TOOLCHAIN/bin/arm-linux-androideabi- && \
./Configure --prefix=$PREFIX android && \
make && make install_sw
WORKDIR /root/build
RUN curl -L -O http://dist.schmorp.de/libev/libev-4.19.tar.gz && \
RUN curl -L -O http://dist.schmorp.de/libev/Attic/libev-$LIBEV_VERSION.tar.gz && \
curl -L -O https://gist.github.com/tatsuhiro-t/48c45f08950f587180ed/raw/80a8f003b5d1091eae497c5995bbaa68096e739b/libev-4.19-android.patch && \
tar xf libev-4.19.tar.gz && \
rm libev-4.19.tar.gz
tar xf libev-$LIBEV_VERSION.tar.gz && \
rm libev-$LIBEV_VERSION.tar.gz
WORKDIR /root/build/libev-4.19
WORKDIR /root/build/libev-$LIBEV_VERSION
RUN patch -p1 < ../libev-4.19-android.patch && \
./configure \
--host=arm-linux-androideabi \
@@ -87,11 +95,11 @@ RUN patch -p1 < ../libev-4.19-android.patch && \
make install
WORKDIR /root/build
RUN curl -L -O http://zlib.net/zlib-1.2.8.tar.gz && \
tar xf zlib-1.2.8.tar.gz && \
rm zlib-1.2.8.tar.gz
RUN curl -L -O https://downloads.sourceforge.net/project/libpng/zlib/$ZLIB_VERSION/zlib-$ZLIB_VERSION.tar.gz && \
tar xf zlib-$ZLIB_VERSION.tar.gz && \
rm zlib-$ZLIB_VERSION.tar.gz
WORKDIR /root/build/zlib-1.2.8
WORKDIR /root/build/zlib-$ZLIB_VERSION
RUN HOST=arm-linux-androideabi \
CC=$HOST-gcc \
AR=$HOST-ar \
@@ -105,11 +113,26 @@ RUN HOST=arm-linux-androideabi \
--static && \
make install
WORKDIR /root/build
RUN git clone https://github.com/nghttp2/nghttp2
RUN curl -L -O https://c-ares.haxx.se/download/c-ares-$CARES_VERSION.tar.gz && \
tar xf c-ares-$CARES_VERSION.tar.gz && \
rm c-ares-$CARES_VERSION.tar.gz
WORKDIR /root/build/c-ares-$CARES_VERSION
RUN ./configure \
--host=arm-linux-androideabi \
--build=`dpkg-architecture -qDEB_BUILD_GNU_TYPE` \
--prefix=$PREFIX \
--disable-shared && \
make install
WORKDIR /root/build
RUN git clone https://github.com/nghttp2/nghttp2 -b $NGHTTP2_VERSION --depth 1
WORKDIR /root/build/nghttp2
RUN autoreconf -i && \
./configure \
--enable-app \
--disable-shared \
--host=arm-linux-androideabi \
--build=`dpkg-architecture -qDEB_BUILD_GNU_TYPE` \
@@ -118,11 +141,10 @@ RUN autoreconf -i && \
--disable-python-bindings \
--disable-examples \
--disable-threads \
LIBSPDYLAY_CFLAGS=-I$PREFIX/usr/local/include \
LIBSPDYLAY_LIBS="-L$PREFIX/usr/local/lib -lspdylay" \
CPPFLAGS="-fPIE -I$PREFIX/include" \
CXXFLAGS="-fno-strict-aliasing" \
PKG_CONFIG_LIBDIR="$PREFIX/lib/pkgconfig" \
LDFLAGS="-fPIE -pie -L$PREFIX/lib" && \
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" && \
make && \
arm-linux-androideabi-strip src/nghttpx src/nghttpd src/nghttp

View File

@@ -4,10 +4,10 @@ nghttp2 - HTTP/2 C Library
This is an implementation of the Hypertext Transfer Protocol version 2
in C.
The framing layer of HTTP/2 is implemented as a reusable C
library. On top of that, we have implemented an HTTP/2 client, server
and proxy. We have also developed load test and benchmarking tools for
HTTP/2 and SPDY.
The framing layer of HTTP/2 is implemented as a reusable C library.
On top of that, we have implemented an HTTP/2 client, server and
proxy. We have also developed load test and benchmarking tools for
HTTP/2.
An HPACK encoder and decoder are available as a public API.
@@ -34,8 +34,8 @@ implementation.
* https://nghttp2.org/ (TLS + ALPN/NPN)
This endpoint supports ``h2``, ``h2-16``, ``h2-14``, ``spdy/3.1``
and ``http/1.1`` via ALPN/NPN and requires TLSv1.2 for HTTP/2
This endpoint supports ``h2``, ``h2-16``, ``h2-14``, and
``http/1.1`` via ALPN/NPN and requires TLSv1.2 for HTTP/2
connection.
* http://nghttp2.org/ (HTTP Upgrade and HTTP/2 Direct)
@@ -76,18 +76,10 @@ ALPN support requires OpenSSL >= 1.0.2 (released 22 January 2015).
LibreSSL >= 2.2.0 can be used instead of OpenSSL, but OpenSSL has more
features than LibreSSL at the time of this writing.
To enable the SPDY protocol in the application program ``nghttpx`` and
``h2load``, the following package is required:
* spdylay >= 1.3.2
We no longer recommend to build nghttp2 with SPDY protocol support
enabled. SPDY support will be removed soon.
To enable ``-a`` option (getting linked assets from the downloaded
resource) in ``nghttp``, the following package is required:
* libxml2 >= 2.7.7
* libxml2 >= 2.6.26
To enable systemd support in nghttpx, the following package is
required:
@@ -130,13 +122,9 @@ and above, run the following to install the required packages:
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 \
libc-ares-dev libjemalloc-dev libsystemd-dev libspdylay-dev \
libc-ares-dev libjemalloc-dev libsystemd-dev \
cython python3-dev python-setuptools
Since 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
mruby with C++ ABI explicitly turned on, and probably need other
@@ -157,22 +145,8 @@ minimizes the risk of private key leakage when serious bug like
Heartbleed is exploited. The neverbleed is disabled by default. To
enable it, use ``--with-neverbleed`` configure option.
Building from git
-----------------
Building from git is easy, but please be sure that at least autoconf 2.68 is
used:
.. code-block:: text
$ git submodule update --init
$ autoreconf -i
$ automake
$ autoconf
$ ./configure
$ make
To compile the source code, gcc >= 4.8.3 or clang >= 3.4 is required.
In order to compile the source code, gcc >= 4.8.3 or clang >= 3.4 is
required.
.. note::
@@ -197,6 +171,62 @@ To compile the source code, gcc >= 4.8.3 or clang >= 3.4 is required.
applications were not built, then using ``--enable-app`` may find
that cause, such as the missing dependency.
.. note::
In order to detect third party libraries, pkg-config is used
(however we don't use pkg-config for some libraries (e.g., libev)).
By default, pkg-config searches ``*.pc`` file in the standard
locations (e.g., /usr/lib/pkgconfig). If it is necessary to use
``*.pc`` file in the custom location, specify paths to
``PKG_CONFIG_PATH`` environment variable, and pass it to configure
script, like so:
.. code-block:: text
$ ./configure PKG_CONFIG_PATH=/path/to/pkgconfig
For pkg-config managed libraries, ``*_CFLAG`` and ``*_LIBS``
environment variables are defined (e.g., ``OPENSSL_CFLAGS``,
``OPENSSL_LIBS``). Specifying non-empty string to these variables
completely overrides pkg-config. In other words, if they are
specified, pkg-config is not used for detection, and user is
responsible to specify the correct values to these variables. For
complete list of these variables, run ``./configure -h``.
Building nghttp2 from release tar archive
-----------------------------------------
The nghttp2 project regularly releases tar archives which includes
nghttp2 source code, and generated build files. They can be
downloaded from `Releases
<https://github.com/nghttp2/nghttp2/releases>`_ page.
Building nghttp2 from git requires autotools development packages.
Building from tar archives does not require them, and thus it is much
easier. The usual build step is as follows:
.. code-block:: text
$ tar xf nghttp2-X.Y.Z.tar.bz2
$ cd nghttp2-X.Y.Z
$ ./configure
$ make
Building from git
-----------------
Building from git is easy, but please be sure that at least autoconf 2.68 is
used:
.. code-block:: text
$ git submodule update --init
$ autoreconf -i
$ automake
$ autoconf
$ ./configure
$ make
Notes for building on Windows (MSVC)
------------------------------------
@@ -243,6 +273,18 @@ If you want to compile the applications under ``examples/``, you need
to remove or rename the ``event.h`` from libev's installation, because
it conflicts with libevent's installation.
Notes for installation on Linux systems
--------------------------------------------
After installing nghttp2 tool suite with ``make install`` one might experience a similar error:
.. code-block:: text
nghttpx: error while loading shared libraries: libnghttp2.so.14: cannot open shared object file: No such file or directory
This means that the tool is unable to locate the ``libnghttp2.so`` shared library.
To update the shared library cache run ``sudo ldconfig``.
Building the documentation
--------------------------
@@ -278,7 +320,6 @@ its testing framework. We depend on the following libraries:
* golang.org/x/net/http2
* golang.org/x/net/websocket
* https://github.com/tatsuhiro-t/go-nghttp2
* https://github.com/tatsuhiro-t/spdy
To download the above packages, after settings ``GOPATH``, run the
following command under ``integration-tests`` directory:
@@ -296,11 +337,6 @@ To run the tests, run the following command under
Inside the tests, we use port 3009 to run the test subject server.
.. note::
github.com/tatsuhiro-t/spdy is a copy used to be available at
golang.org/x/net/spdy, but it is now gone.
Migration from v0.7.15 or earlier
---------------------------------
@@ -701,7 +737,7 @@ information. Here is sample output from ``nghttpd``:
nghttpx - proxy
+++++++++++++++
``nghttpx`` is a multi-threaded reverse proxy for HTTP/2, SPDY and
``nghttpx`` is a multi-threaded reverse proxy for HTTP/2, and
HTTP/1.1, and powers http://nghttp2.org and supports HTTP/2 server
push.
@@ -716,31 +752,30 @@ 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. ``nghttpx`` also offers the functionality to share session
cache and ticket keys among multiple ``nghttpx`` instances via
memcached.
stapling, dynamic record sizing, ALPN/NPN, forward secrecy and HTTP/2.
``nghttpx`` also offers the functionality to share session cache and
ticket keys among multiple ``nghttpx`` instances via memcached.
``nghttpx`` has 2 operation modes:
================== ====================== ================ =============
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
================== ====================== ================ =============
================== ================ ================ =============
Mode option Frontend Backend Note
================== ================ ================ =============
default mode HTTP/2, HTTP/1.1 HTTP/1.1, HTTP/2 Reverse proxy
``--http2-proxy`` HTTP/2, 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
a reverse proxy and listens for HTTP/2, and HTTP/1.1 and can be
deployed as a SSL/TLS terminator for existing web server.
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.
``--frontend`` option. If encryption is disabled, 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``.
@@ -750,16 +785,16 @@ server:
.. code-block:: text
Client <-- (HTTP/2, SPDY, HTTP/1.1) --> nghttpx <-- (HTTP/1.1, HTTP/2) --> Web Server
[reverse proxy]
Client <-- (HTTP/2, HTTP/1.1) --> nghttpx <-- (HTTP/1.1, HTTP/2) --> Web Server
[reverse proxy]
With the ``--http2-proxy`` option, it works as forward proxy, and it
is so called secure HTTP/2 proxy (aka SPDY proxy):
is so called secure HTTP/2 proxy:
.. code-block:: text
Client <-- (HTTP/2, SPDY, HTTP/1.1) --> nghttpx <-- (HTTP/1.1) --> Proxy
[secure proxy] (e.g., Squid, ATS)
Client <-- (HTTP/2, HTTP/1.1) --> nghttpx <-- (HTTP/1.1) --> Proxy
[secure proxy] (e.g., Squid, ATS)
The ``Client`` in the above example needs to be configured to use
``nghttpx`` as secure proxy.
@@ -791,7 +826,7 @@ proxy through an HTTP proxy:
.. code-block:: text
Client <-- (HTTP/2, SPDY, HTTP/1.1) --> nghttpx <-- (HTTP/2) --
Client <-- (HTTP/2, HTTP/1.1) --> nghttpx <-- (HTTP/2) --
--===================---> HTTP/2 Proxy
(HTTP proxy tunnel) (e.g., nghttpx -s)
@@ -799,9 +834,8 @@ proxy through an HTTP proxy:
Benchmarking tool
-----------------
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``
The ``h2load`` program is a benchmarking tool for HTTP/2. The UI of
``h2load`` is heavily inspired by ``weighttp``
(https://github.com/lighttpd/weighttp). The typical usage is as
follows:

View File

@@ -1,7 +1,3 @@
/* 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@
@@ -38,6 +34,9 @@
/* Define to 1 if you have the `accept4` function. */
#cmakedefine HAVE_ACCEPT4 1
/* Define to 1 if you have the `mkostemp` function. */
#cmakedefine HAVE_MKOSTEMP 1
/* Define to 1 if you have the `initgroups` function. */
#cmakedefine01 HAVE_DECL_INITGROUPS

View File

@@ -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.20.0], [t-tujikawa@users.sourceforge.net])
AC_INIT([nghttp2], [1.31.0], [t-tujikawa@users.sourceforge.net])
AC_CONFIG_AUX_DIR([.])
AC_CONFIG_MACRO_DIR([m4])
AC_CONFIG_HEADERS([config.h])
@@ -44,9 +44,9 @@ m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
dnl See versioning rule:
dnl http://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html
AC_SUBST(LT_CURRENT, 27)
AC_SUBST(LT_CURRENT, 30)
AC_SUBST(LT_REVISION, 0)
AC_SUBST(LT_AGE, 13)
AC_SUBST(LT_AGE, 16)
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"`
@@ -117,11 +117,6 @@ AC_ARG_WITH([jemalloc],
[Use jemalloc [default=check]])],
[request_jemalloc=$withval], [request_jemalloc=check])
AC_ARG_WITH([spdylay],
[AS_HELP_STRING([--with-spdylay],
[Use spdylay [default=no]])],
[request_spdylay=$withval], [request_spdylay=no])
AC_ARG_WITH([systemd],
[AS_HELP_STRING([--with-systemd],
[Enable systemd support in nghttpx [default=check]])],
@@ -176,19 +171,9 @@ else
AC_SUBST([CYTHON])
fi
#
# 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 test "x$GCC" = "xyes" -o "x$CC" = "xclang" ; then
AC_DEFINE([_U_], [__attribute__((unused))], [Hint to the compiler that a function parameters is not used])
AC_DEFINE([NGHTTP2_NORETURN], [__attribute__((noreturn))], [Hint to the compiler that a function never return])
else
AC_DEFINE([_U_], , [Hint to the compiler that a function parameter is not used])
AC_DEFINE([NGHTTP2_NORETURN], , [Hint to the compiler that a function never return])
fi
@@ -420,7 +405,7 @@ if test "x${request_systemd}" = "xyes" &&
fi
# libxml2 (for src/nghttp)
PKG_CHECK_MODULES([LIBXML2], [libxml-2.0 >= 2.7.7],
PKG_CHECK_MODULES([LIBXML2], [libxml-2.0 >= 2.6.26],
[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.])
@@ -468,26 +453,6 @@ if test "x${request_jemalloc}" = "xyes" &&
AC_MSG_ERROR([jemalloc was requested (--with-jemalloc) but not found])
fi
# spdylay (for src/nghttpx and src/h2load)
have_spdylay=no
if test "x${request_spdylay}" != "xno"; then
PKG_CHECK_MODULES([LIBSPDYLAY], [libspdylay >= 1.3.2],
[have_spdylay=yes], [have_spdylay=no])
if test "x${have_spdylay}" = "xyes"; then
AC_DEFINE([HAVE_SPDYLAY], [1], [Define to 1 if you have `spdylay` library.])
else
AC_MSG_NOTICE($LIBSPDYLAY_PKG_ERRORS)
AC_MSG_NOTICE([The SPDY support in nghttpx and h2load will be disabled.])
fi
fi
if test "x${request_spdylay}" = "xyes" &&
test "x${have_spdylay}" != "xyes"; then
AC_MSG_ERROR([spdylay was requested (--with-spdylay) but not found])
fi
AM_CONDITIONAL([HAVE_SPDYLAY], [ test "x${have_spdylay}" = "xyes" ])
# Check Boost Asio library
have_asio_lib=no
@@ -723,6 +688,7 @@ AC_CHECK_FUNCS([ \
memchr \
memmove \
memset \
mkostemp \
socket \
sqrt \
strchr \
@@ -814,6 +780,9 @@ if test "x$werror" != "xno"; then
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"])
# Disable noexcept-type warning of g++-7. This is not harmful as
# long as all source files are compiled with the same compiler.
AX_CHECK_COMPILE_FLAG([-Wno-noexcept-type], [CXXFLAGS="$CXXFLAGS -Wno-noexcept-type"])
AC_LANG_POP()
fi
@@ -934,7 +903,6 @@ AC_MSG_NOTICE([summary of build options:
Libev: ${have_libev} (CFLAGS='${LIBEV_CFLAGS}' LIBS='${LIBEV_LIBS}')
Libc-ares ${have_libcares} (CFLAGS='${LIBCARES_CFLAGS}' LIBS='${LIBCARES_LIBS}')
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}')
Jemalloc: ${have_jemalloc} (LIBS='${JEMALLOC_LIBS}')
Zlib: ${have_zlib} (CFLAGS='${ZLIB_CFLAGS}' LIBS='${ZLIB_LIBS}')

View File

@@ -49,6 +49,7 @@ set(APIDOCS
nghttp2_rcbuf_decref.rst
nghttp2_rcbuf_get_buf.rst
nghttp2_rcbuf_incref.rst
nghttp2_rcbuf_is_static.rst
nghttp2_select_next_protocol.rst
nghttp2_session_callbacks_del.rst
nghttp2_session_callbacks_new.rst

View File

@@ -74,12 +74,14 @@ APIDOCS= \
nghttp2_rcbuf_decref.rst \
nghttp2_rcbuf_get_buf.rst \
nghttp2_rcbuf_incref.rst \
nghttp2_rcbuf_is_static.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_error_callback2.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 \
@@ -141,6 +143,7 @@ APIDOCS= \
nghttp2_session_set_local_window_size.rst \
nghttp2_session_set_next_stream_id.rst \
nghttp2_session_set_stream_user_data.rst \
nghttp2_session_set_user_data.rst \
nghttp2_session_terminate_session.rst \
nghttp2_session_terminate_session2.rst \
nghttp2_session_upgrade.rst \
@@ -267,7 +270,7 @@ apiref.rst: \
$(APIDOCS): apiref.rst
clean-local:
[ $(srcdir) = $(builddir) ] || for i in $(RST_FILES); do [ -e $(builddir)/$$i ] && rm -f $(builddir)/$$i; done
if [ $(srcdir) != $(builddir) ]; then for i in $(RST_FILES); do rm -f $(builddir)/$$i; done fi
-rm -f apiref.rst
-rm -f $(APIDOCS)
-rm -rf $(BUILDDIR)/*

View File

@@ -13,6 +13,7 @@ import re
from docutils import nodes
from docutils.parsers.rst import directives
from docutils.parsers.rst import Directive
from sphinx import addnodes
from sphinx import version_info
@@ -21,10 +22,8 @@ from sphinx.locale import l_, _
from sphinx.domains import Domain, ObjType, Index
from sphinx.directives import ObjectDescription
from sphinx.util.nodes import make_refnode
from sphinx.util.compat import Directive
from sphinx.util.docfields import Field, GroupedField, TypedField
# REs for Ruby signatures
rb_sig_re = re.compile(
r'''^ ([\w.]*\.)? # class name(s)

View File

@@ -8,7 +8,7 @@ _h2load()
_get_comp_words_by_ref cur prev
case $cur in
-*)
COMPREPLY=( $( compgen -W '--connection-window-bits --clients --verbose --ciphers --rate --no-tls-proto --header-table-size --requests --base-uri --h1 --threads --npn-list --rate-period --data --version --connection-inactivity-timeout --timing-script-file --encoder-header-table-size --max-concurrent-streams --connection-active-timeout --input-file --help --window-bits --header ' -- "$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 --warm-up-time --duration --header ' -- "$cur" ) )
;;
*)
_filedir

View File

@@ -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 --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" ) )
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 --no-verify-peer --header ' -- "$cur" ) )
;;
*)
_filedir

View File

@@ -8,7 +8,7 @@ _nghttpx()
_get_comp_words_by_ref cur prev
case $cur in
-*)
COMPREPLY=( $( compgen -W '--worker-read-rate --include --frontend-http2-dump-response-header --tls-ticket-key-file --verify-client-cacert --max-response-header-fields --backend-http2-window-size --frontend-keep-alive-timeout --backend-request-buffer --max-request-header-fields --fastopen --backend-connect-timeout --tls-max-proto-version --conf --dns-lookup-timeout --backend-http2-max-concurrent-streams --worker-write-burst --npn-list --dns-max-try --fetch-ocsp-response-file --no-via --tls-session-cache-memcached-cert-file --no-http2-cipher-black-list --mruby-file --client-no-http2-cipher-black-list --stream-read-timeout --client-ciphers --forwarded-for --accesslog-syslog --dns-cache-timeout --frontend-http2-read-timeout --listener-disable-timeout --ciphers --client-psk-secrets --strip-incoming-x-forwarded-for --no-server-rewrite --private-key-passwd-file --backend-keep-alive-timeout --backend-http-proxy-uri --frontend-max-requests --rlimit-nofile --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 --redirect-https-port --request-header-field-buffer --api-max-request-body --frontend-http2-decoder-dynamic-table-size --errorlog-file --frontend-http2-max-concurrent-streams --psk-secrets --frontend-write-timeout --tls-ticket-key-cipher --read-burst --backend --server-name --insecure --backend-max-backoff --log-level --host-rewrite --tls-ticket-key-memcached-interval --frontend-http2-setting-timeout --frontend-http2-connection-window-size --worker-frontend-connections --syslog-facility --no-server-push --no-location-rewrite --single-thread --tls-session-cache-memcached --no-ocsp --backend-response-buffer --tls-min-proto-version --workers --add-forwarded --worker-write-rate --add-request-header --backend-http2-settings-timeout --subcert --ecdh-curves --no-kqueue --help --frontend-frame-debug --tls-sct-dir --pid-file --frontend-http2-dump-request-header --daemon --write-rate --altsvc --backend-http2-decoder-dynamic-table-size --user --add-x-forwarded-for --frontend-read-timeout --tls-ticket-key-memcached-max-fail --backlog --write-burst --backend-connections-per-host --response-header-field-buffer --tls-ticket-key-memcached-address-family --padding --tls-session-cache-memcached-address-family --stream-write-timeout --cacert --tls-ticket-key-memcached-private-key-file --accesslog-write-early --backend-address-family --backend-http2-connection-window-size --version --add-response-header --backend-read-timeout --frontend-http2-optimize-window-size --frontend --accesslog-file --http2-proxy --backend-http2-encoder-dynamic-table-size --client-private-key-file --client-cert-file --tls-ticket-key-memcached --tls-dyn-rec-idle-timeout --frontend-http2-optimize-write-buffer-size --verify-client --frontend-http2-encoder-dynamic-table-size --read-rate --backend-connections-per-frontend --strip-incoming-forwarded ' -- "$cur" ) )
COMPREPLY=( $( compgen -W '--worker-read-rate --include --frontend-http2-dump-response-header --tls-ticket-key-file --verify-client-cacert --max-response-header-fields --backend-http2-window-size --frontend-keep-alive-timeout --backend-request-buffer --max-request-header-fields --backend-connect-timeout --tls-max-proto-version --conf --dns-lookup-timeout --backend-http2-max-concurrent-streams --worker-write-burst --npn-list --dns-max-try --fetch-ocsp-response-file --no-via --tls-session-cache-memcached-cert-file --no-http2-cipher-black-list --mruby-file --add-forwarded --client-no-http2-cipher-black-list --stream-read-timeout --client-ciphers --ocsp-update-interval --forwarded-for --accesslog-syslog --dns-cache-timeout --frontend-http2-read-timeout --listener-disable-timeout --ciphers --client-psk-secrets --strip-incoming-x-forwarded-for --no-server-rewrite --private-key-passwd-file --backend-keep-alive-timeout --backend-http-proxy-uri --frontend-max-requests --rlimit-nofile --no-strip-incoming-x-forwarded-proto --tls-ticket-key-memcached-cert-file --no-verify-ocsp --forwarded-by --tls-session-cache-memcached-private-key-file --error-page --ocsp-startup --backend-write-timeout --tls-dyn-rec-warmup-threshold --tls-ticket-key-memcached-max-retry --frontend-http2-window-size --http2-no-cookie-crumbling --worker-read-burst --dh-param-file --accesslog-format --errorlog-syslog --redirect-https-port --request-header-field-buffer --api-max-request-body --frontend-http2-decoder-dynamic-table-size --errorlog-file --frontend-http2-max-concurrent-streams --psk-secrets --frontend-write-timeout --tls-ticket-key-cipher --read-burst --no-add-x-forwarded-proto --backend --server-name --insecure --backend-max-backoff --log-level --host-rewrite --tls-ticket-key-memcached-interval --frontend-http2-setting-timeout --frontend-http2-connection-window-size --worker-frontend-connections --syslog-facility --fastopen --no-location-rewrite --single-thread --tls-session-cache-memcached --no-ocsp --backend-response-buffer --tls-min-proto-version --workers --add-x-forwarded-for --no-server-push --worker-write-rate --add-request-header --backend-http2-settings-timeout --subcert --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 --verify-client-tolerate-expired --frontend-read-timeout --tls-ticket-key-memcached-max-fail --backlog --write-burst --backend-connections-per-host --response-header-field-buffer --tls-ticket-key-memcached-address-family --padding --tls-session-cache-memcached-address-family --stream-write-timeout --cacert --tls-ticket-key-memcached-private-key-file --accesslog-write-early --backend-address-family --backend-http2-connection-window-size --version --add-response-header --backend-read-timeout --frontend-http2-optimize-window-size --frontend --accesslog-file --http2-proxy --backend-http2-encoder-dynamic-table-size --client-private-key-file --single-process --client-cert-file --tls-ticket-key-memcached --tls-dyn-rec-idle-timeout --frontend-http2-optimize-write-buffer-size --verify-client --frontend-http2-encoder-dynamic-table-size --read-rate --backend-connections-per-frontend --strip-incoming-forwarded ' -- "$cur" ) )
;;
*)
_filedir

View File

@@ -157,7 +157,7 @@ html_theme_path = ['@top_srcdir@/doc/_themes']
# If true, SmartyPants will be used to convert quotes and dashes to
# typographically correct entities.
html_use_smartypants = False
#html_use_smartypants = False
# Custom sidebar templates, maps document names to template names.
html_sidebars = {

2
doc/docutils.conf Normal file
View File

@@ -0,0 +1,2 @@
[parsers]
smart_quotes=no

View File

@@ -1,6 +1,6 @@
.\" Man page generated from reStructuredText.
.
.TH "H2LOAD" "1" "Feb 26, 2017" "1.20.0" "nghttp2"
.TH "H2LOAD" "1" "Feb 27, 2018" "1.31.0" "nghttp2"
.SH NAME
h2load \- HTTP/2 benchmarking tool
.
@@ -35,7 +35,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
\fBh2load\fP [OPTIONS]... [URI]...
.SH DESCRIPTION
.sp
benchmarking tool for HTTP/2 and SPDY server
benchmarking tool for HTTP/2 server
.INDENT 0.0
.TP
.B <URI>
@@ -54,7 +54,9 @@ scheme, host or port values.
Number of requests across all clients. If it is used
with \fI\%\-\-timing\-script\-file\fP option, this option specifies
the number of requests each client performs rather than
the number of requests across all clients.
the number of requests across all clients. This option
is ignored if timing\-based benchmarking is enabled (see
\fI\%\-\-duration\fP option).
.sp
Default: \fB1\fP
.UNINDENT
@@ -99,7 +101,6 @@ Default: \fB1\fP
.TP
.B \-w, \-\-window\-bits=<N>
Sets the stream level initial window size to (2**<N>)\-1.
For SPDY, 2**<N> is used instead.
.sp
Default: \fB30\fP
.UNINDENT
@@ -107,9 +108,7 @@ Default: \fB30\fP
.TP
.B \-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,
this option is ignored. Otherwise 2**<N> is used for
SPDY.
(2**<N>)\-1.
.sp
Default: \fB30\fP
.UNINDENT
@@ -124,15 +123,14 @@ Add/Override a header to the requests.
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
Default: \fBECDHE\-ECDSA\-AES256\-GCM\-SHA384:ECDHE\-RSA\-AES256\-GCM\-SHA384:ECDHE\-ECDSA\-CHACHA20\-POLY1305:ECDHE\-RSA\-CHACHA20\-POLY1305:ECDHE\-ECDSA\-AES128\-GCM\-SHA256:ECDHE\-RSA\-AES128\-GCM\-SHA256:ECDHE\-ECDSA\-AES256\-SHA384:ECDHE\-RSA\-AES256\-SHA384:ECDHE\-ECDSA\-AES128\-SHA256:ECDHE\-RSA\-AES128\-SHA256\fP
.UNINDENT
.INDENT 0.0
.TP
.B \-p, \-\-no\-tls\-proto=<PROTOID>
Specify ALPN identifier of the protocol to be used when
accessing http URI without SSL/TLS.
Available protocols: h2c and
http/1.1
Available protocols: h2c and http/1.1
.sp
Default: \fBh2c\fP
.UNINDENT
@@ -170,6 +168,19 @@ option is 1s.
.UNINDENT
.INDENT 0.0
.TP
.B \-D, \-\-duration=<N>
Specifies the main duration for the measurements in case
of timing\-based benchmarking.
.UNINDENT
.INDENT 0.0
.TP
.B \-\-warm\-up\-time=<DURATION>
Specifies the time period before starting the actual
measurements, in case of timing\-based benchmarking.
Needs to provided along with \fI\%\-D\fP option.
.UNINDENT
.INDENT 0.0
.TP
.B \-T, \-\-connection\-active\-timeout=<DURATION>
Specifies the maximum time that h2load is willing to
keep a connection open, regardless of the activity on
@@ -335,8 +346,7 @@ compression. Let \fBdecompressed(headers)\fP to the number of bytes
used for header fields after decompression. The \fBspace savings\fP
is calculated by (1 \- \fBheaders\fP / \fBdecompressed(headers)\fP) *
100. For HTTP/1.1, this is usually 0.00%, since it does not have
header compression. For HTTP/2 and SPDY, it shows some insightful
numbers.
header compression. For HTTP/2, it shows some insightful numbers.
.TP
.B data
The number of response body bytes received from the server.
@@ -433,7 +443,7 @@ h2load sets large flow control window by default, and effectively
disables flow control to avoid under utilization of server
performance. To set smaller flow control window, use \fI\%\-w\fP and
\fI\%\-W\fP options. For example, use \fB\-w16 \-W16\fP to set default
window size described in HTTP/2 and SPDY protocol specification.
window size described in HTTP/2 protocol specification.
.SH SEE ALSO
.sp
\fBnghttp(1)\fP, \fBnghttpd(1)\fP, \fBnghttpx(1)\fP

View File

@@ -14,7 +14,7 @@ SYNOPSIS
DESCRIPTION
-----------
benchmarking tool for HTTP/2 and SPDY server
benchmarking tool for HTTP/2 server
.. describe:: <URI>
@@ -34,7 +34,9 @@ OPTIONS
Number of requests across all clients. If it is used
with :option:`--timing-script-file` option, this option specifies
the number of requests each client performs rather than
the number of requests across all clients.
the number of requests across all clients. This option
is ignored if timing-based benchmarking is enabled (see
:option:`--duration` option).
Default: ``1``
@@ -74,16 +76,13 @@ OPTIONS
.. option:: -w, --window-bits=<N>
Sets the stream level initial window size to (2\*\*<N>)-1.
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,
this option is ignored. Otherwise 2\*\*<N> is used for
SPDY.
(2\*\*<N>)-1.
Default: ``30``
@@ -96,14 +95,13 @@ 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``
Default: ``ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256``
.. option:: -p, --no-tls-proto=<PROTOID>
Specify ALPN identifier of the protocol to be used when
accessing http URI without SSL/TLS.
Available protocols: h2c and
http/1.1
Available protocols: h2c and http/1.1
Default: ``h2c``
@@ -136,6 +134,17 @@ OPTIONS
the rate option is not used. The default value for this
option is 1s.
.. option:: -D, --duration=<N>
Specifies the main duration for the measurements in case
of timing-based benchmarking.
.. option:: --warm-up-time=<DURATION>
Specifies the time period before starting the actual
measurements, in case of timing-based benchmarking.
Needs to provided along with :option:`-D` option.
.. option:: -T, --connection-active-timeout=<DURATION>
Specifies the maximum time that h2load is willing to
@@ -284,8 +293,7 @@ traffic
used for header fields after decompression. The ``space savings``
is calculated by (1 - ``headers`` / ``decompressed(headers)``) *
100. For HTTP/1.1, this is usually 0.00%, since it does not have
header compression. For HTTP/2 and SPDY, it shows some insightful
numbers.
header compression. For HTTP/2, it shows some insightful numbers.
data
The number of response body bytes received from the server.
@@ -353,7 +361,7 @@ h2load sets large flow control window by default, and effectively
disables flow control to avoid under utilization of server
performance. To set smaller flow control window, use :option:`-w` and
:option:`-W` options. For example, use ``-w16 -W16`` to set default
window size described in HTTP/2 and SPDY protocol specification.
window size described in HTTP/2 protocol specification.
SEE ALSO
--------

View File

@@ -41,8 +41,7 @@ traffic
used for header fields after decompression. The ``space savings``
is calculated by (1 - ``headers`` / ``decompressed(headers)``) *
100. For HTTP/1.1, this is usually 0.00%, since it does not have
header compression. For HTTP/2 and SPDY, it shows some insightful
numbers.
header compression. For HTTP/2, it shows some insightful numbers.
data
The number of response body bytes received from the server.
@@ -110,7 +109,7 @@ h2load sets large flow control window by default, and effectively
disables flow control to avoid under utilization of server
performance. To set smaller flow control window, use :option:`-w` and
:option:`-W` options. For example, use ``-w16 -W16`` to set default
window size described in HTTP/2 and SPDY protocol specification.
window size described in HTTP/2 protocol specification.
SEE ALSO
--------

View File

@@ -1,6 +1,6 @@
.\" Man page generated from reStructuredText.
.
.TH "NGHTTP" "1" "Feb 26, 2017" "1.20.0" "nghttp2"
.TH "NGHTTP" "1" "Feb 27, 2018" "1.31.0" "nghttp2"
.SH NAME
nghttp \- HTTP/2 client
.
@@ -236,6 +236,12 @@ combined with the \fI\%\-d\fP option.
.UNINDENT
.INDENT 0.0
.TP
.B \-y, \-\-no\-verify\-peer
Suppress warning on server certificate verification
failure.
.UNINDENT
.INDENT 0.0
.TP
.B \-\-version
Display version information and exit.
.UNINDENT

View File

@@ -186,6 +186,11 @@ OPTIONS
Continue interim response. This option is ignored unless
combined with the :option:`-d` option.
.. option:: -y, --no-verify-peer
Suppress warning on server certificate verification
failure.
.. option:: --version
Display version information and exit.

View File

@@ -1,6 +1,6 @@
.\" Man page generated from reStructuredText.
.
.TH "NGHTTPD" "1" "Feb 26, 2017" "1.20.0" "nghttp2"
.TH "NGHTTPD" "1" "Feb 27, 2018" "1.31.0" "nghttp2"
.SH NAME
nghttpd \- HTTP/2 server
.

View File

@@ -1,6 +1,6 @@
.\" Man page generated from reStructuredText.
.
.TH "NGHTTPX" "1" "Feb 26, 2017" "1.20.0" "nghttp2"
.TH "NGHTTPX" "1" "Feb 27, 2018" "1.31.0" "nghttp2"
.SH NAME
nghttpx \- HTTP/2 proxy
.
@@ -35,7 +35,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
\fBnghttpx\fP [OPTIONS]... [<PRIVATE_KEY> <CERT>]
.SH DESCRIPTION
.sp
A reverse proxy for HTTP/2, HTTP/1 and SPDY.
A reverse proxy for HTTP/2, and HTTP/1.
.INDENT 0.0
.TP
.B <PRIVATE_KEY>
@@ -62,8 +62,7 @@ domain socket can be specified by prefixing path name
with "unix:" (e.g., unix:/var/run/backend.sock).
.sp
Optionally, if <PATTERN>s are given, the backend address
is only used if request matches the pattern. If
\fI\%\-\-http2\-proxy\fP is used, <PATTERN>s are ignored. The
is only used if request matches the pattern. The
pattern matching is closely designed to ServeMux in
net/http package of Go programming language. <PATTERN>
consists of path, host + path or just host. The path
@@ -74,11 +73,16 @@ path which ends with "\fI/\fP" also matches the request path
which only lacks trailing \(aq\fI/\fP\(aq (e.g., path "\fI/foo/\fP"
matches request path "\fI/foo\fP"). If it does not end with
"\fI/\fP", it performs exact match against the request path.
If host is given, it performs exact match against the
request host. If host alone is given, "\fI/\fP" is appended
to it, so that it matches all request paths under the
host (e.g., specifying "nghttp2.org" equals to
"nghttp2.org/").
If host is given, it performs a match against the
request host. For a request received on the frontend
listener with "sni\-fwd" parameter enabled, SNI host is
used instead of a request host. If host alone is given,
"\fI/\fP" is appended to it, so that it matches all request
paths under the host (e.g., specifying "nghttp2.org"
equals to "nghttp2.org/"). CONNECT method is treated
specially. It does not have path, and we don\(aqt allow
empty path. To workaround this, we assume that CONNECT
method has "\fI/\fP" as path.
.sp
Patterns with host take precedence over patterns with
just path. Then, longer patterns take precedence over
@@ -92,6 +96,18 @@ host pattern "*.nghttp2.org" matches against
match against "nghttp2.org". The exact hosts match
takes precedence over the wildcard hosts match.
.sp
If path part ends with "*", it is treated as wildcard
path. The wildcard path behaves differently from the
normal path. For normal path, match is made around the
boundary of path component separator,"\fI/\fP". On the other
hand, the wildcard path does not take into account the
path component separator. All paths which include the
wildcard path without last "*" as prefix, and are
strictly longer than wildcard path without last "*" are
matched. "*" must match at least one character. For
example, the pattern "\fI/foo*\fP" matches "\fI/foo/\fP" and
"\fI/foobar\fP". But it does not match "\fI/foo\fP", or "\fI/fo\fP".
.sp
If <PATTERN> is omitted or empty string, "\fI/\fP" is used as
pattern, which matches all request paths (catch\-all
pattern). The catch\-all backend must be given.
@@ -164,16 +180,32 @@ state, and this is the default behaviour.
The session affinity is enabled using
"affinity=<METHOD>" parameter. If "ip" is given in
<METHOD>, client IP based session affinity is enabled.
If "none" is given in <METHOD>, session affinity is
disabled, and this is the default. The session affinity
is enabled per <PATTERN>. If at least one backend has
"affinity" parameter, and its <METHOD> is not "none",
session affinity is enabled for all backend servers
sharing the same <PATTERN>. It is advised to set
"affinity" parameter to all backend explicitly if
session affinity is desired. The session affinity may
break if one of the backend gets unreachable, or backend
settings are reloaded or replaced by API.
If "cookie" is given in <METHOD>, cookie based session
affinity is enabled. If "none" is given in <METHOD>,
session affinity is disabled, and this is the default.
The session affinity is enabled per <PATTERN>. If at
least one backend has "affinity" parameter, and its
<METHOD> is not "none", session affinity is enabled for
all backend servers sharing the same <PATTERN>. It is
advised to set "affinity" parameter to all backend
explicitly if session affinity is desired. The session
affinity may break if one of the backend gets
unreachable, or backend settings are reloaded or
replaced by API.
.sp
If "affinity=cookie" is used, the additional
configuration is required.
"affinity\-cookie\-name=<NAME>" must be used to specify a
name of cookie to use. Optionally,
"affinity\-cookie\-path=<PATH>" can be used to specify a
path which cookie is applied. The optional
"affinity\-cookie\-secure=<SECURE>" controls the Secure
attribute of a cookie. The default value is "auto", and
the Secure attribute is determined by a request scheme.
If a request scheme is "https", then Secure attribute is
set. Otherwise, it is not set. If <SECURE> is "yes",
the Secure attribute is always set. If <SECURE> is
"no", the Secure attribute is always omitted.
.sp
By default, name resolution of backend host name is done
at start up, or reloading configuration. If "dns"
@@ -196,6 +228,13 @@ the same <PATTERN>. It is advised to set
"redirect\-if\-no\-tls" parameter to all backends
explicitly if this feature is desired.
.sp
If "upgrade\-scheme" parameter is used along with "tls"
parameter, HTTP/2 :scheme pseudo header field is changed
to "https" from "http" when forwarding a request to this
particular backend. This is a workaround for a backend
server which requires "https" :scheme pseudo header
field on TLS encrypted connection.
.sp
Since ";" and ":" are used as delimiter, <PATTERN> must
not contain these characters. Since ";" has special
meaning in shell, the option value must be quoted.
@@ -219,6 +258,11 @@ parameters are mutually exclusive.
Optionally, TLS can be disabled by specifying "no\-tls"
parameter. TLS is enabled by default.
.sp
If "sni\-fwd" parameter is used, when performing a match
to select a backend server, SNI host name received from
the client is used instead of the request host. See
\fI\%\-\-backend\fP option about the pattern match.
.sp
To make this frontend as API endpoint, specify "api"
parameter. This is disabled by default. It is
important to limit the access to the API frontend.
@@ -434,8 +478,7 @@ this option will be simply ignored.
.INDENT 0.0
.TP
.B \-\-frontend\-http2\-read\-timeout=<DURATION>
Specify read timeout for HTTP/2 and SPDY frontend
connection.
Specify read timeout for HTTP/2 frontend connection.
.sp
Default: \fB3m\fP
.UNINDENT
@@ -464,16 +507,16 @@ Default: \fB1m\fP
.INDENT 0.0
.TP
.B \-\-stream\-read\-timeout=<DURATION>
Specify read timeout for HTTP/2 and SPDY streams. 0
means no timeout.
Specify read timeout for HTTP/2 streams. 0 means no
timeout.
.sp
Default: \fB0\fP
.UNINDENT
.INDENT 0.0
.TP
.B \-\-stream\-write\-timeout=<DURATION>
Specify write timeout for HTTP/2 and SPDY streams. 0
means no timeout.
Specify write timeout for HTTP/2 streams. 0 means no
timeout.
.sp
Default: \fB1m\fP
.UNINDENT
@@ -553,7 +596,7 @@ Default: \fB2m\fP
Set allowed cipher list for frontend connection. 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
Default: \fBECDHE\-ECDSA\-AES256\-GCM\-SHA384:ECDHE\-RSA\-AES256\-GCM\-SHA384:ECDHE\-ECDSA\-CHACHA20\-POLY1305:ECDHE\-RSA\-CHACHA20\-POLY1305:ECDHE\-ECDSA\-AES128\-GCM\-SHA256:ECDHE\-RSA\-AES128\-GCM\-SHA256:ECDHE\-ECDSA\-AES256\-SHA384:ECDHE\-RSA\-AES256\-SHA384:ECDHE\-ECDSA\-AES128\-SHA256:ECDHE\-RSA\-AES128\-SHA256\fP
.UNINDENT
.INDENT 0.0
.TP
@@ -561,7 +604,7 @@ Default: \fBECDHE\-ECDSA\-CHACHA20\-POLY1305:ECDHE\-RSA\-CHACHA20\-POLY1305:ECDH
Set allowed cipher list for backend connection. 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
Default: \fBECDHE\-ECDSA\-AES256\-GCM\-SHA384:ECDHE\-RSA\-AES256\-GCM\-SHA384:ECDHE\-ECDSA\-CHACHA20\-POLY1305:ECDHE\-RSA\-CHACHA20\-POLY1305:ECDHE\-ECDSA\-AES128\-GCM\-SHA256:ECDHE\-RSA\-AES128\-GCM\-SHA256:ECDHE\-ECDSA\-AES256\-SHA384:ECDHE\-RSA\-AES256\-SHA384:ECDHE\-ECDSA\-AES128\-SHA256:ECDHE\-RSA\-AES128\-SHA256\fP
.UNINDENT
.INDENT 0.0
.TP
@@ -583,11 +626,14 @@ enabled for backend connections.
.INDENT 0.0
.TP
.B \-\-cacert=<PATH>
Set path to trusted CA certificate file used in backend
TLS connections. The file must be in PEM format. It
can contain multiple certificates. If the linked
OpenSSL is configured to load system wide certificates,
they are loaded at startup regardless of this option.
Set path to trusted CA certificate file. It is used in
backend TLS connections to verify peer\(aqs certificate.
It is also used to verify OCSP response from the script
set by \fI\%\-\-fetch\-ocsp\-response\-file\fP\&. The file must be in
PEM format. It can contain multiple certificates. If
the linked OpenSSL is configured to load system wide
certificates, they are loaded at startup regardless of
this option.
.UNINDENT
.INDENT 0.0
.TP
@@ -602,12 +648,12 @@ password protected it\(aqll be requested interactively.
Specify additional certificate and private key file.
nghttpx will choose certificates based on the hostname
indicated by client using TLS SNI extension. If nghttpx
is built with OpenSSL >= 1.0.2, signature algorithms
(e.g., ECDSA+SHA256, RSA+SHA256) presented by client are
also taken into consideration. This allows nghttpx to
send ECDSA certificate to modern clients, while sending
RSA based certificate to older clients. This option can
be used multiple times. To make OCSP stapling work,
is built with OpenSSL >= 1.0.2, the shared elliptic
curves (e.g., P\-256) between client and server are also
taken into consideration. This allows nghttpx to send
ECDSA certificate to modern clients, while sending RSA
based certificate to older clients. This option can be
used multiple times. To make OCSP stapling work,
<CERTPATH> must be absolute path.
.sp
Additional parameter can be specified in <PARAM>. The
@@ -652,6 +698,14 @@ can contain multiple certificates.
.UNINDENT
.INDENT 0.0
.TP
.B \-\-verify\-client\-tolerate\-expired
Accept expired client certificate. Operator should
handle the expired client certificate by some means
(e.g., mruby script). Otherwise, this option might
cause a security risk.
.UNINDENT
.INDENT 0.0
.TP
.B \-\-client\-private\-key\-file=<PATH>
Path to file that contains client private key used in
backend client authentication.
@@ -670,10 +724,14 @@ done in case\-insensitive manner. The versions between
\fI\%\-\-tls\-min\-proto\-version\fP and \fI\%\-\-tls\-max\-proto\-version\fP are
enabled. If the protocol list advertised by client does
not overlap this range, you will receive the error
message "unknown protocol". The available versions are:
message "unknown protocol". If a protocol version lower
than TLSv1.2 is specified, make sure that the compatible
ciphers are included in \fI\%\-\-ciphers\fP option. The default
cipher list only includes ciphers compatible with
TLSv1.2 or above. The available versions are:
TLSv1.2, TLSv1.1, and TLSv1.0
.sp
Default: \fBTLSv1.1\fP
Default: \fBTLSv1.2\fP
.UNINDENT
.INDENT 0.0
.TP
@@ -803,6 +861,20 @@ Default: \fB4h\fP
.UNINDENT
.INDENT 0.0
.TP
.B \-\-ocsp\-startup
Start accepting connections after initial attempts to
get OCSP responses finish. It does not matter some of
the attempts fail. This feature is useful if OCSP
responses must be available before accepting
connections.
.UNINDENT
.INDENT 0.0
.TP
.B \-\-no\-verify\-ocsp
nghttpx does not verify OCSP response.
.UNINDENT
.INDENT 0.0
.TP
.B \-\-no\-ocsp
Disable OCSP stapling.
.UNINDENT
@@ -925,14 +997,14 @@ HTTP/2. To use those cipher suites with HTTP/2,
consider to use \fI\%\-\-client\-no\-http2\-cipher\-black\-list\fP
option. But be aware its implications.
.UNINDENT
.SS HTTP/2 and SPDY
.SS HTTP/2
.INDENT 0.0
.TP
.B \-c, \-\-frontend\-http2\-max\-concurrent\-streams=<N>
Set the maximum number of the concurrent streams in one
frontend HTTP/2 and SPDY session.
frontend HTTP/2 session.
.sp
Default: \(ga\(ga 100\(ga\(ga
Default: \fB100\fP
.UNINDENT
.INDENT 0.0
.TP
@@ -947,17 +1019,16 @@ Default: \fB100\fP
.INDENT 0.0
.TP
.B \-\-frontend\-http2\-window\-size=<SIZE>
Sets the per\-stream initial window size of HTTP/2 and
SPDY frontend connection.
Sets the per\-stream initial window size of HTTP/2
frontend connection.
.sp
Default: \fB65535\fP
.UNINDENT
.INDENT 0.0
.TP
.B \-\-frontend\-http2\-connection\-window\-size=<SIZE>
Sets the per\-connection window size of HTTP/2 and SPDY
frontend connection. For SPDY connection, the value
less than 64KiB is rounded up to 64KiB.
Sets the per\-connection window size of HTTP/2 frontend
connection.
.sp
Default: \fB65535\fP
.UNINDENT
@@ -998,8 +1069,7 @@ default mode and HTTP/2 frontend via Link header field.
It is also supported if both frontend and backend are
HTTP/2 in default mode. In this case, server push from
backend session is relayed to frontend, and server push
via Link header field is also supported. SPDY frontend
does not support server push.
via Link header field is also supported.
.UNINDENT
.INDENT 0.0
.TP
@@ -1070,7 +1140,7 @@ Default: \fB4K\fP
.INDENT 0.0
.TP
.B (default mode)
Accept HTTP/2, SPDY and HTTP/1.1 over SSL/TLS. "no\-tls"
Accept HTTP/2, and HTTP/1.1 over SSL/TLS. "no\-tls"
parameter is used in \fI\%\-\-frontend\fP option, accept HTTP/2
and HTTP/1.1 over cleartext TCP. The incoming HTTP/1.1
connection can be upgraded to HTTP/2 through HTTP
@@ -1140,15 +1210,32 @@ $alpn: ALPN identifier of the protocol which generates
the response. For HTTP/1, ALPN is always http/1.1,
regardless of minor version.
.IP \(bu 2
$ssl_cipher: cipher used for SSL/TLS connection.
$tls_cipher: cipher used for SSL/TLS connection.
.IP \(bu 2
$ssl_protocol: protocol for SSL/TLS connection.
$tls_client_fingerprint_sha256: SHA\-256 fingerprint of
client certificate.
.IP \(bu 2
$ssl_session_id: session ID for SSL/TLS connection.
$tls_client_fingerprint_sha1: SHA\-1 fingerprint of
client certificate.
.IP \(bu 2
$ssl_session_reused: "r" if SSL/TLS session was
$tls_client_subject_name: subject name in client
certificate.
.IP \(bu 2
$tls_client_issuer_name: issuer name in client
certificate.
.IP \(bu 2
$tls_client_serial: serial number in client
certificate.
.IP \(bu 2
$tls_protocol: protocol for SSL/TLS connection.
.IP \(bu 2
$tls_session_id: session ID for SSL/TLS connection.
.IP \(bu 2
$tls_session_reused: "r" if SSL/TLS session was
reused. Otherwise, "."
.IP \(bu 2
$tls_sni: SNI server name for SSL/TLS connection.
.IP \(bu 2
$backend_host: backend host used to fulfill the
request. "\-" if backend host is not available.
.IP \(bu 2
@@ -1205,6 +1292,21 @@ requests.
.UNINDENT
.INDENT 0.0
.TP
.B \-\-no\-add\-x\-forwarded\-proto
Don\(aqt append additional X\-Forwarded\-Proto header field
to the backend request. If inbound client sets
X\-Forwarded\-Proto, and
\fI\%\-\-no\-strip\-incoming\-x\-forwarded\-proto\fP option is used,
they are passed to the backend.
.UNINDENT
.INDENT 0.0
.TP
.B \-\-no\-strip\-incoming\-x\-forwarded\-proto
Don\(aqt strip X\-Forwarded\-Proto header field from inbound
client requests.
.UNINDENT
.INDENT 0.0
.TP
.B \-\-add\-forwarded=<LIST>
Append RFC 7239 Forwarded header field with parameters
specified in comma delimited list <LIST>. The supported
@@ -1375,7 +1477,7 @@ Default: \fB443\fP
.B \-\-api\-max\-request\-body=<SIZE>
Set the maximum size of request body for API request.
.sp
Default: \fB16K\fP
Default: \fB32M\fP
.UNINDENT
.SS DNS
.INDENT 0.0
@@ -1458,6 +1560,17 @@ Set path to save PID of this program.
Run this program as <USER>. This option is intended to
be used to drop root privileges.
.UNINDENT
.INDENT 0.0
.TP
.B \-\-single\-process
Run this program in a single process mode for debugging
purpose. Without this option, nghttpx creates at least
2 processes: master and worker processes. If this
option is used, master and worker are unified into a
single process. nghttpx still spawns additional process
if neverbleed is used. In the single process mode, the
signal handling feature is disabled.
.UNINDENT
.SS Scripting
.INDENT 0.0
.TP
@@ -1468,7 +1581,9 @@ Set mruby script file
.INDENT 0.0
.TP
.B \-\-conf=<PATH>
Load configuration from <PATH>.
Load configuration from <PATH>. Please note that
nghttpx always tries to read the default configuration
file if \fI\%\-\-conf\fP is not given.
.sp
Default: \fB/etc/nghttpx/nghttpx.conf\fP
.UNINDENT
@@ -1562,7 +1677,7 @@ follows:
.INDENT 7.0
.TP
.B <datetime>
It is a conbination of date and time when the log is written. It
It is a combination of date and time when the log is written. It
is in ISO 8601 format.
.TP
.B <master\-pid>
@@ -1691,6 +1806,22 @@ be customized using \fI\%\-\-fetch\-ocsp\-response\-file\fP option.
.sp
If OCSP query is failed, previous OCSP response, if any, is continued
to be used.
.sp
\fI\%\-\-fetch\-ocsp\-response\-file\fP option provides wide range of
possibility to manage OCSP response. It can take an arbitrary script
or executable. The requirement is that it supports the command\-line
interface of \fBfetch\-ocsp\-response\fP script, and it must return a
valid DER encoded OCSP response on success. It must return exit code
0 on success, and 75 for temporary error, and the other error code for
generic failure. For large cluster of servers, it is not efficient
for each server to perform OCSP query using \fBfetch\-ocsp\-response\fP\&.
Instead, you can retrieve OCSP response in some way, and store it in a
disk or a shared database. Then specify a program in
\fI\%\-\-fetch\-ocsp\-response\-file\fP to fetch it from those stores.
This could provide a way to share the OCSP response between fleet of
servers, and also any OCSP query strategy can be applied which may be
beyond the ability of nghttpx itself or \fBfetch\-ocsp\-response\fP
script.
.SH TLS SESSION RESUMPTION
.sp
nghttpx supports TLS session resumption through both session ID and
@@ -1701,7 +1832,7 @@ By default, session ID is shared by all worker threads.
.sp
If \fI\%\-\-tls\-session\-cache\-memcached\fP is given, nghttpx will
insert serialized session data to memcached with
\fBnghttpx:tls\-session\-cache:\fP + lowercased hex string of session ID
\fBnghttpx:tls\-session\-cache:\fP + lowercase hex string of session ID
as a memcached entry key, with expiry time 12 hours. Session timeout
is set to 12 hours.
.sp
@@ -1783,6 +1914,17 @@ API is subject to change in the future release.
.UNINDENT
.UNINDENT
.sp
\fBWARNING:\fP
.INDENT 0.0
.INDENT 3.5
Almost all string value returned from method, or attribute is a
fresh new mruby string, which involves memory allocation, and
copies. Therefore, it is strongly recommended to store a return
value in a local variable, and use it, instead of calling method or
accessing attribute repeatedly.
.UNINDENT
.UNINDENT
.sp
nghttpx allows users to extend its capability using mruby scripts.
nghttpx has 2 hook points to execute mruby script: request phase and
response phase. The request phase hook is invoked after all request
@@ -1831,7 +1973,7 @@ Return \fI\%Response\fP object.
.TP
.B attribute [R] ctx
Return Ruby hash object. It persists until request finishes.
So values set in request phase hoo can be retrieved in
So values set in request phase hook can be retrieved in
response phase hook.
.UNINDENT
.INDENT 7.0
@@ -1869,6 +2011,68 @@ Return true if TLS is used on the connection.
.B attribute [R] tls_sni
Return the TLS SNI value which client sent in this connection.
.UNINDENT
.INDENT 7.0
.TP
.B attribute [R] tls_client_fingerprint_sha256
Return the SHA\-256 fingerprint of a client certificate.
.UNINDENT
.INDENT 7.0
.TP
.B attribute [R] tls_client_fingerprint_sha1
Return the SHA\-1 fingerprint of a client certificate.
.UNINDENT
.INDENT 7.0
.TP
.B attribute [R] tls_client_issuer_name
Return the issuer name of a client certificate.
.UNINDENT
.INDENT 7.0
.TP
.B attribute [R] tls_client_subject_name
Return the subject name of a client certificate.
.UNINDENT
.INDENT 7.0
.TP
.B attribute [R] tls_client_serial
Return the serial number of a client certificate.
.UNINDENT
.INDENT 7.0
.TP
.B attribute [R] tls_client_not_before
Return the start date of a client certificate in seconds since
the epoch.
.UNINDENT
.INDENT 7.0
.TP
.B attribute [R] tls_client_not_after
Return the end date of a client certificate in seconds since
the epoch.
.UNINDENT
.INDENT 7.0
.TP
.B attribute [R] tls_cipher
Return a TLS cipher negotiated in this connection.
.UNINDENT
.INDENT 7.0
.TP
.B attribute [R] tls_protocol
Return a TLS protocol version negotiated in this connection.
.UNINDENT
.INDENT 7.0
.TP
.B attribute [R] tls_session_id
Return a session ID for this connection in hex string.
.UNINDENT
.INDENT 7.0
.TP
.B attribute [R] tls_session_reused
Return true if, and only if a SSL/TLS session is reused.
.UNINDENT
.INDENT 7.0
.TP
.B attribute [R] alpn
Return ALPN identifier negotiated in this connection.
.UNINDENT
.UNINDENT
.INDENT 0.0
.TP
@@ -2146,7 +2350,7 @@ 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.
.sp
The one limitation is that only numeric IP address is allowd in
The one limitation is that only numeric IP address is allowed in
\fI\%backend\fP in request body unless "dns" parameter
is used while non numeric hostname is allowed in command\-line or
configuration file is read using \fI\%\-\-conf\fP\&.

View File

@@ -14,7 +14,7 @@ SYNOPSIS
DESCRIPTION
-----------
A reverse proxy for HTTP/2, HTTP/1 and SPDY.
A reverse proxy for HTTP/2, and HTTP/1.
.. describe:: <PRIVATE_KEY>
@@ -46,8 +46,7 @@ Connections
with "unix:" (e.g., unix:/var/run/backend.sock).
Optionally, if <PATTERN>s are given, the backend address
is only used if request matches the pattern. If
:option:`--http2-proxy` is used, <PATTERN>s are ignored. The
is only used if request matches the pattern. The
pattern matching is closely designed to ServeMux in
net/http package of Go programming language. <PATTERN>
consists of path, host + path or just host. The path
@@ -58,11 +57,16 @@ Connections
which only lacks trailing '*/*' (e.g., path "*/foo/*"
matches request path "*/foo*"). If it does not end with
"*/*", it performs exact match against the request path.
If host is given, it performs exact match against the
request host. If host alone is given, "*/*" is appended
to it, so that it matches all request paths under the
host (e.g., specifying "nghttp2.org" equals to
"nghttp2.org/").
If host is given, it performs a match against the
request host. For a request received on the frontend
listener with "sni-fwd" parameter enabled, SNI host is
used instead of a request host. If host alone is given,
"*/*" is appended to it, so that it matches all request
paths under the host (e.g., specifying "nghttp2.org"
equals to "nghttp2.org/"). CONNECT method is treated
specially. It does not have path, and we don't allow
empty path. To workaround this, we assume that CONNECT
method has "*/*" as path.
Patterns with host take precedence over patterns with
just path. Then, longer patterns take precedence over
@@ -76,6 +80,18 @@ Connections
match against "nghttp2.org". The exact hosts match
takes precedence over the wildcard hosts match.
If path part ends with "\*", it is treated as wildcard
path. The wildcard path behaves differently from the
normal path. For normal path, match is made around the
boundary of path component separator,"*/*". On the other
hand, the wildcard path does not take into account the
path component separator. All paths which include the
wildcard path without last "\*" as prefix, and are
strictly longer than wildcard path without last "\*" are
matched. "\*" must match at least one character. For
example, the pattern "*/foo\**" matches "*/foo/*" and
"*/foobar*". But it does not match "*/foo*", or "*/fo*".
If <PATTERN> is omitted or empty string, "*/*" is used as
pattern, which matches all request paths (catch-all
pattern). The catch-all backend must be given.
@@ -148,16 +164,32 @@ Connections
The session affinity is enabled using
"affinity=<METHOD>" parameter. If "ip" is given in
<METHOD>, client IP based session affinity is enabled.
If "none" is given in <METHOD>, session affinity is
disabled, and this is the default. The session affinity
is enabled per <PATTERN>. If at least one backend has
"affinity" parameter, and its <METHOD> is not "none",
session affinity is enabled for all backend servers
sharing the same <PATTERN>. It is advised to set
"affinity" parameter to all backend explicitly if
session affinity is desired. The session affinity may
break if one of the backend gets unreachable, or backend
settings are reloaded or replaced by API.
If "cookie" is given in <METHOD>, cookie based session
affinity is enabled. If "none" is given in <METHOD>,
session affinity is disabled, and this is the default.
The session affinity is enabled per <PATTERN>. If at
least one backend has "affinity" parameter, and its
<METHOD> is not "none", session affinity is enabled for
all backend servers sharing the same <PATTERN>. It is
advised to set "affinity" parameter to all backend
explicitly if session affinity is desired. The session
affinity may break if one of the backend gets
unreachable, or backend settings are reloaded or
replaced by API.
If "affinity=cookie" is used, the additional
configuration is required.
"affinity-cookie-name=<NAME>" must be used to specify a
name of cookie to use. Optionally,
"affinity-cookie-path=<PATH>" can be used to specify a
path which cookie is applied. The optional
"affinity-cookie-secure=<SECURE>" controls the Secure
attribute of a cookie. The default value is "auto", and
the Secure attribute is determined by a request scheme.
If a request scheme is "https", then Secure attribute is
set. Otherwise, it is not set. If <SECURE> is "yes",
the Secure attribute is always set. If <SECURE> is
"no", the Secure attribute is always omitted.
By default, name resolution of backend host name is done
at start up, or reloading configuration. If "dns"
@@ -180,6 +212,13 @@ Connections
"redirect-if-no-tls" parameter to all backends
explicitly if this feature is desired.
If "upgrade-scheme" parameter is used along with "tls"
parameter, HTTP/2 :scheme pseudo header field is changed
to "https" from "http" when forwarding a request to this
particular backend. This is a workaround for a backend
server which requires "https" :scheme pseudo header
field on TLS encrypted connection.
Since ";" and ":" are used as delimiter, <PATTERN> must
not contain these characters. Since ";" has special
meaning in shell, the option value must be quoted.
@@ -203,6 +242,11 @@ Connections
Optionally, TLS can be disabled by specifying "no-tls"
parameter. TLS is enabled by default.
If "sni-fwd" parameter is used, when performing a match
to select a backend server, SNI host name received from
the client is used instead of the request host. See
:option:`--backend` option about the pattern match.
To make this frontend as API endpoint, specify "api"
parameter. This is disabled by default. It is
important to limit the access to the API frontend.
@@ -403,8 +447,7 @@ Timeout
.. option:: --frontend-http2-read-timeout=<DURATION>
Specify read timeout for HTTP/2 and SPDY frontend
connection.
Specify read timeout for HTTP/2 frontend connection.
Default: ``3m``
@@ -429,15 +472,15 @@ Timeout
.. option:: --stream-read-timeout=<DURATION>
Specify read timeout for HTTP/2 and SPDY streams. 0
means no timeout.
Specify read timeout for HTTP/2 streams. 0 means no
timeout.
Default: ``0``
.. option:: --stream-write-timeout=<DURATION>
Specify write timeout for HTTP/2 and SPDY streams. 0
means no timeout.
Specify write timeout for HTTP/2 streams. 0 means no
timeout.
Default: ``1m``
@@ -511,14 +554,14 @@ SSL/TLS
Set allowed cipher list for frontend connection. 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``
Default: ``ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256``
.. option:: --client-ciphers=<SUITE>
Set allowed cipher list for backend connection. 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``
Default: ``ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256``
.. option:: --ecdh-curves=<LIST>
@@ -537,11 +580,14 @@ SSL/TLS
.. option:: --cacert=<PATH>
Set path to trusted CA certificate file used in backend
TLS connections. The file must be in PEM format. It
can contain multiple certificates. If the linked
OpenSSL is configured to load system wide certificates,
they are loaded at startup regardless of this option.
Set path to trusted CA certificate file. It is used in
backend TLS connections to verify peer's certificate.
It is also used to verify OCSP response from the script
set by :option:`--fetch-ocsp-response-file`\. The file must be in
PEM format. It can contain multiple certificates. If
the linked OpenSSL is configured to load system wide
certificates, they are loaded at startup regardless of
this option.
.. option:: --private-key-passwd-file=<PATH>
@@ -554,12 +600,12 @@ SSL/TLS
Specify additional certificate and private key file.
nghttpx will choose certificates based on the hostname
indicated by client using TLS SNI extension. If nghttpx
is built with OpenSSL >= 1.0.2, signature algorithms
(e.g., ECDSA+SHA256, RSA+SHA256) presented by client are
also taken into consideration. This allows nghttpx to
send ECDSA certificate to modern clients, while sending
RSA based certificate to older clients. This option can
be used multiple times. To make OCSP stapling work,
is built with OpenSSL >= 1.0.2, the shared elliptic
curves (e.g., P-256) between client and server are also
taken into consideration. This allows nghttpx to send
ECDSA certificate to modern clients, while sending RSA
based certificate to older clients. This option can be
used multiple times. To make OCSP stapling work,
<CERTPATH> must be absolute path.
Additional parameter can be specified in <PARAM>. The
@@ -598,6 +644,13 @@ SSL/TLS
client certificate. The file must be in PEM format. It
can contain multiple certificates.
.. option:: --verify-client-tolerate-expired
Accept expired client certificate. Operator should
handle the expired client certificate by some means
(e.g., mruby script). Otherwise, this option might
cause a security risk.
.. option:: --client-private-key-file=<PATH>
Path to file that contains client private key used in
@@ -615,10 +668,14 @@ SSL/TLS
:option:`--tls-min-proto-version` and :option:`\--tls-max-proto-version` are
enabled. If the protocol list advertised by client does
not overlap this range, you will receive the error
message "unknown protocol". The available versions are:
message "unknown protocol". If a protocol version lower
than TLSv1.2 is specified, make sure that the compatible
ciphers are included in :option:`--ciphers` option. The default
cipher list only includes ciphers compatible with
TLSv1.2 or above. The available versions are:
TLSv1.2, TLSv1.1, and TLSv1.0
Default: ``TLSv1.1``
Default: ``TLSv1.2``
.. option:: --tls-max-proto-version=<VER>
@@ -734,6 +791,18 @@ SSL/TLS
Default: ``4h``
.. option:: --ocsp-startup
Start accepting connections after initial attempts to
get OCSP responses finish. It does not matter some of
the attempts fail. This feature is useful if OCSP
responses must be available before accepting
connections.
.. option:: --no-verify-ocsp
nghttpx does not verify OCSP response.
.. option:: --no-ocsp
Disable OCSP stapling.
@@ -847,15 +916,15 @@ SSL/TLS
option. But be aware its implications.
HTTP/2 and SPDY
~~~~~~~~~~~~~~~
HTTP/2
~~~~~~
.. option:: -c, --frontend-http2-max-concurrent-streams=<N>
Set the maximum number of the concurrent streams in one
frontend HTTP/2 and SPDY session.
frontend HTTP/2 session.
Default: `` 100``
Default: ``100``
.. option:: --backend-http2-max-concurrent-streams=<N>
@@ -868,16 +937,15 @@ HTTP/2 and SPDY
.. option:: --frontend-http2-window-size=<SIZE>
Sets the per-stream initial window size of HTTP/2 and
SPDY frontend connection.
Sets the per-stream initial window size of HTTP/2
frontend connection.
Default: ``65535``
.. option:: --frontend-http2-connection-window-size=<SIZE>
Sets the per-connection window size of HTTP/2 and SPDY
frontend connection. For SPDY connection, the value
less than 64KiB is rounded up to 64KiB.
Sets the per-connection window size of HTTP/2 frontend
connection.
Default: ``65535``
@@ -913,8 +981,7 @@ HTTP/2 and SPDY
It is also supported if both frontend and backend are
HTTP/2 in default mode. In this case, server push from
backend session is relayed to frontend, and server push
via Link header field is also supported. SPDY frontend
does not support server push.
via Link header field is also supported.
.. option:: --frontend-http2-optimize-write-buffer-size
@@ -982,7 +1049,7 @@ Mode
.. describe:: (default mode)
Accept HTTP/2, SPDY and HTTP/1.1 over SSL/TLS. "no-tls"
Accept HTTP/2, and HTTP/1.1 over SSL/TLS. "no-tls"
parameter is used in :option:`--frontend` option, accept HTTP/2
and HTTP/1.1 over cleartext TCP. The incoming HTTP/1.1
connection can be upgraded to HTTP/2 through HTTP
@@ -1037,11 +1104,22 @@ Logging
* $alpn: ALPN identifier of the protocol which generates
the response. For HTTP/1, ALPN is always http/1.1,
regardless of minor version.
* $ssl_cipher: cipher used for SSL/TLS connection.
* $ssl_protocol: protocol for SSL/TLS connection.
* $ssl_session_id: session ID for SSL/TLS connection.
* $ssl_session_reused: "r" if SSL/TLS session was
* $tls_cipher: cipher used for SSL/TLS connection.
* $tls_client_fingerprint_sha256: SHA-256 fingerprint of
client certificate.
* $tls_client_fingerprint_sha1: SHA-1 fingerprint of
client certificate.
* $tls_client_subject_name: subject name in client
certificate.
* $tls_client_issuer_name: issuer name in client
certificate.
* $tls_client_serial: serial number in client
certificate.
* $tls_protocol: protocol for SSL/TLS connection.
* $tls_session_id: session ID for SSL/TLS connection.
* $tls_session_reused: "r" if SSL/TLS session was
reused. Otherwise, "."
* $tls_sni: SNI server name for SSL/TLS connection.
* $backend_host: backend host used to fulfill the
request. "-" if backend host is not available.
* $backend_port: backend port used to fulfill the
@@ -1092,6 +1170,19 @@ HTTP
Strip X-Forwarded-For header field from inbound client
requests.
.. option:: --no-add-x-forwarded-proto
Don't append additional X-Forwarded-Proto header field
to the backend request. If inbound client sets
X-Forwarded-Proto, and
:option:`--no-strip-incoming-x-forwarded-proto` option is used,
they are passed to the backend.
.. option:: --no-strip-incoming-x-forwarded-proto
Don't strip X-Forwarded-Proto header field from inbound
client requests.
.. option:: --add-forwarded=<LIST>
Append RFC 7239 Forwarded header field with parameters
@@ -1248,7 +1339,7 @@ API
Set the maximum size of request body for API request.
Default: ``16K``
Default: ``32M``
DNS
@@ -1330,6 +1421,16 @@ Process
Run this program as <USER>. This option is intended to
be used to drop root privileges.
.. option:: --single-process
Run this program in a single process mode for debugging
purpose. Without this option, nghttpx creates at least
2 processes: master and worker processes. If this
option is used, master and worker are unified into a
single process. nghttpx still spawns additional process
if neverbleed is used. In the single process mode, the
signal handling feature is disabled.
Scripting
~~~~~~~~~
@@ -1344,7 +1445,9 @@ Misc
.. option:: --conf=<PATH>
Load configuration from <PATH>.
Load configuration from <PATH>. Please note that
nghttpx always tries to read the default configuration
file if :option:`--conf` is not given.
Default: ``/etc/nghttpx/nghttpx.conf``
@@ -1424,7 +1527,7 @@ Error log
<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
It is a combination of date and time when the log is written. It
is in ISO 8601 format.
<master-pid>
@@ -1546,6 +1649,22 @@ be customized using :option:`--fetch-ocsp-response-file` option.
If OCSP query is failed, previous OCSP response, if any, is continued
to be used.
:option:`--fetch-ocsp-response-file` option provides wide range of
possibility to manage OCSP response. It can take an arbitrary script
or executable. The requirement is that it supports the command-line
interface of ``fetch-ocsp-response`` script, and it must return a
valid DER encoded OCSP response on success. It must return exit code
0 on success, and 75 for temporary error, and the other error code for
generic failure. For large cluster of servers, it is not efficient
for each server to perform OCSP query using ``fetch-ocsp-response``.
Instead, you can retrieve OCSP response in some way, and store it in a
disk or a shared database. Then specify a program in
:option:`--fetch-ocsp-response-file` to fetch it from those stores.
This could provide a way to share the OCSP response between fleet of
servers, and also any OCSP query strategy can be applied which may be
beyond the ability of nghttpx itself or ``fetch-ocsp-response``
script.
TLS SESSION RESUMPTION
----------------------
@@ -1559,7 +1678,7 @@ By default, session ID is shared by all worker threads.
If :option:`--tls-session-cache-memcached` is given, nghttpx will
insert serialized session data to memcached with
``nghttpx:tls-session-cache:`` + lowercased hex string of session ID
``nghttpx:tls-session-cache:`` + lowercase hex string of session ID
as a memcached entry key, with expiry time 12 hours. Session timeout
is set to 12 hours.
@@ -1641,6 +1760,14 @@ MRUBY SCRIPTING
The current mruby extension API is experimental and not frozen. The
API is subject to change in the future release.
.. warning::
Almost all string value returned from method, or attribute is a
fresh new mruby string, which involves memory allocation, and
copies. Therefore, it is strongly recommended to store a return
value in a local variable, and use it, instead of calling method or
accessing attribute repeatedly.
nghttpx allows users to extend its capability using mruby scripts.
nghttpx has 2 hook points to execute mruby script: request phase and
response phase. The request phase hook is invoked after all request
@@ -1687,7 +1814,7 @@ respectively.
.. rb:attr_reader:: ctx
Return Ruby hash object. It persists until request finishes.
So values set in request phase hoo can be retrieved in
So values set in request phase hook can be retrieved in
response phase hook.
.. rb:attr_reader:: phase
@@ -1719,6 +1846,56 @@ respectively.
Return the TLS SNI value which client sent in this connection.
.. rb:attr_reader:: tls_client_fingerprint_sha256
Return the SHA-256 fingerprint of a client certificate.
.. rb:attr_reader:: tls_client_fingerprint_sha1
Return the SHA-1 fingerprint of a client certificate.
.. rb:attr_reader:: tls_client_issuer_name
Return the issuer name of a client certificate.
.. rb:attr_reader:: tls_client_subject_name
Return the subject name of a client certificate.
.. rb:attr_reader:: tls_client_serial
Return the serial number of a client certificate.
.. rb:attr_reader:: tls_client_not_before
Return the start date of a client certificate in seconds since
the epoch.
.. rb:attr_reader:: tls_client_not_after
Return the end date of a client certificate in seconds since
the epoch.
.. rb:attr_reader:: tls_cipher
Return a TLS cipher negotiated in this connection.
.. rb:attr_reader:: tls_protocol
Return a TLS protocol version negotiated in this connection.
.. rb:attr_reader:: tls_session_id
Return a session ID for this connection in hex string.
.. rb:attr_reader:: tls_session_reused
Return true if, and only if a SSL/TLS session is reused.
.. rb:attr_reader:: alpn
Return ALPN identifier negotiated in this connection.
.. rb:class:: Request
Object to represent request from client. The modification to
@@ -1963,7 +2140,7 @@ 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
The one limitation is that only numeric IP address is allowed 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`.

View File

@@ -49,7 +49,7 @@ Error log
<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
It is a combination of date and time when the log is written. It
is in ISO 8601 format.
<master-pid>
@@ -171,6 +171,22 @@ be customized using :option:`--fetch-ocsp-response-file` option.
If OCSP query is failed, previous OCSP response, if any, is continued
to be used.
:option:`--fetch-ocsp-response-file` option provides wide range of
possibility to manage OCSP response. It can take an arbitrary script
or executable. The requirement is that it supports the command-line
interface of ``fetch-ocsp-response`` script, and it must return a
valid DER encoded OCSP response on success. It must return exit code
0 on success, and 75 for temporary error, and the other error code for
generic failure. For large cluster of servers, it is not efficient
for each server to perform OCSP query using ``fetch-ocsp-response``.
Instead, you can retrieve OCSP response in some way, and store it in a
disk or a shared database. Then specify a program in
:option:`--fetch-ocsp-response-file` to fetch it from those stores.
This could provide a way to share the OCSP response between fleet of
servers, and also any OCSP query strategy can be applied which may be
beyond the ability of nghttpx itself or ``fetch-ocsp-response``
script.
TLS SESSION RESUMPTION
----------------------
@@ -184,7 +200,7 @@ By default, session ID is shared by all worker threads.
If :option:`--tls-session-cache-memcached` is given, nghttpx will
insert serialized session data to memcached with
``nghttpx:tls-session-cache:`` + lowercased hex string of session ID
``nghttpx:tls-session-cache:`` + lowercase hex string of session ID
as a memcached entry key, with expiry time 12 hours. Session timeout
is set to 12 hours.
@@ -266,6 +282,14 @@ MRUBY SCRIPTING
The current mruby extension API is experimental and not frozen. The
API is subject to change in the future release.
.. warning::
Almost all string value returned from method, or attribute is a
fresh new mruby string, which involves memory allocation, and
copies. Therefore, it is strongly recommended to store a return
value in a local variable, and use it, instead of calling method or
accessing attribute repeatedly.
nghttpx allows users to extend its capability using mruby scripts.
nghttpx has 2 hook points to execute mruby script: request phase and
response phase. The request phase hook is invoked after all request
@@ -312,7 +336,7 @@ respectively.
.. rb:attr_reader:: ctx
Return Ruby hash object. It persists until request finishes.
So values set in request phase hoo can be retrieved in
So values set in request phase hook can be retrieved in
response phase hook.
.. rb:attr_reader:: phase
@@ -344,6 +368,56 @@ respectively.
Return the TLS SNI value which client sent in this connection.
.. rb:attr_reader:: tls_client_fingerprint_sha256
Return the SHA-256 fingerprint of a client certificate.
.. rb:attr_reader:: tls_client_fingerprint_sha1
Return the SHA-1 fingerprint of a client certificate.
.. rb:attr_reader:: tls_client_issuer_name
Return the issuer name of a client certificate.
.. rb:attr_reader:: tls_client_subject_name
Return the subject name of a client certificate.
.. rb:attr_reader:: tls_client_serial
Return the serial number of a client certificate.
.. rb:attr_reader:: tls_client_not_before
Return the start date of a client certificate in seconds since
the epoch.
.. rb:attr_reader:: tls_client_not_after
Return the end date of a client certificate in seconds since
the epoch.
.. rb:attr_reader:: tls_cipher
Return a TLS cipher negotiated in this connection.
.. rb:attr_reader:: tls_protocol
Return a TLS protocol version negotiated in this connection.
.. rb:attr_reader:: tls_session_id
Return a session ID for this connection in hex string.
.. rb:attr_reader:: tls_session_reused
Return true if, and only if a SSL/TLS session is reused.
.. rb:attr_reader:: alpn
Return ALPN identifier negotiated in this connection.
.. rb:class:: Request
Object to represent request from client. The modification to
@@ -588,7 +662,7 @@ 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
The one limitation is that only numeric IP address is allowed 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`.

View File

@@ -116,7 +116,10 @@ briefly describe what the library does in this area. In the following
description, without loss of generality we omit CONTINUATION frame
since they must follow HEADERS frame and are processed atomically. In
other words, they are just one big HEADERS frame. To disable these
validations, use `nghttp2_option_set_no_http_messaging()`.
validations, use `nghttp2_option_set_no_http_messaging()`. Please
note that disabling this feature does not change the fundamental
client and server model of HTTP. That is, even if the validation is
disabled, only client can send requests.
For HTTP request, including those carried by PUSH_PROMISE, HTTP
message starts with one HEADERS frame containing request headers. It
@@ -149,13 +152,11 @@ header fields must not appear: "Connection", "Keep-Alive",
Each header field name and value must obey the field-name and
field-value production rules described in `RFC 7230, section
3.2. <https://tools.ietf.org/html/rfc7230#section-3.2>`_.
Additionally, all field name must be lower cased. While the pseudo
header fields must satisfy these rules, we just ignore illegal regular
headers (this means that these header fields are not passed to
application callback). This is because these illegal header fields
are floating around in existing internet and resetting stream just
because of this may break many web sites. This is especially true if
we forward to or translate from HTTP/1 traffic.
Additionally, all field name must be lower cased. The invalid header
fields are treated as stream error, and that stream is reset. If
application wants to treat these headers in their own way, use
`nghttp2_on_invalid_header_callback
<https://nghttp2.org/documentation/types.html#c.nghttp2_on_invalid_header_callback>`_.
For "http" or "https" URIs, ":path" pseudo header fields must start
with "/". The only exception is OPTIONS request, in that case, "*" is

View File

@@ -2,7 +2,7 @@ Building Android binary
=======================
In this article, we briefly describe how to build Android binary using
`Android NDK <http://developer.android.com/tools/sdk/ndk/index.html>`_
`Android NDK <https://developer.android.com/ndk/index.html>`_
cross-compiler on Debian Linux.
The easiest way to build android binary is use Dockerfile.android.

View File

@@ -26,8 +26,7 @@ Coding style
We use clang-format to format source code consistently. The
clang-format configuration file .clang-format is located at the root
directory. Since clang-format produces slightly different results
between versions, we currently use clang-format which comes with
clang-3.9.
between versions, we currently use clang-format-5.0.
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 +34,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.9 in debian), either add it to PATH variable or
clang-format-diff-5.0 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.

View File

@@ -3,16 +3,14 @@
h2load - HTTP/2 benchmarking tool - HOW-TO
==========================================
: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.
:doc:`h2load.1` is benchmarking tool for HTTP/2 and HTTP/1.1. 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
``--enable-app`` 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
@@ -64,23 +62,40 @@ The benchmarking result looks like this:
See the h2load manual page :ref:`h2load-1-output` section for the
explanation of the above numbers.
Timing-based load-testing
-------------------------
As of v1.26.0, h2load supports timing-based load-testing. This method
performs load-testing in terms of a given duration instead of a
pre-defined number of requests. The new option :option:`--duration`
specifies how long the load-testing takes. For example,
``--duration=10`` makes h2load perform load-testing against a server
for 10 seconds. You can also specify a “warming-up” period with
:option:`--warm-up-time`. If :option:`--duration` is used,
:option:`-n` option is ignored.
The following command performs load-testing for 10 seconds after 5
seconds warming up period:
.. code-block:: text
$ h2load -c100 -m100 --duration=10 --warm-up-time=5 https://localhost
Flow Control
------------
HTTP/2 and SPDY/3 or later employ flow control and it may affect
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:
HTTP/2 has flow control and it may affect 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:
:option:`-w`
Sets the stream level initial window size to
(2**<N>)-1. For SPDY, 2**<N> is used instead.
(2**<N>)-1.
: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
2**<N> is used for SPDY.
(2**<N>)-1.
Multi-Threading
---------------

View File

@@ -290,7 +290,7 @@ Normally, client does not stop even after all requests are done unless
connection is lost. To stop client, call
``nghttp2::asio_http2::server::session::shutdown()``.
Recieve server push and enable SSL/TLS
Receive server push and enable SSL/TLS
++++++++++++++++++++++++++++++++++++++
.. code-block:: cpp

View File

@@ -4,10 +4,10 @@ nghttpx - HTTP/2 proxy - HOW-TO
===============================
: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.
other protocols (e.g., HTTP/1). 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
------------
@@ -15,9 +15,7 @@ Default mode
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.
as "HTTP/2 router".
By default, frontend connection is encrypted using SSL/TLS. So
server's private key and certificate must be supplied to the command
@@ -25,11 +23,10 @@ line (or through configuration file). In this case, the frontend
protocol selection will be done via ALPN or NPN.
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.
in :option:`--frontend` option. 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.
nghttpx can listen on multiple frontend addresses. This is achieved
by using multiple :option:`--frontend` options. For each frontend
@@ -45,17 +42,17 @@ 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
The backend is supposed to be a Web server. For example, to make
nghttpx listen to encrypted HTTP/2 requests at port 8443, and a
backend Web server is configured to listen to HTTP request at port
8080 in the same host, run nghttpx command-line like this:
backend Web server is configured to listen to HTTP requests at port
8080 on 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:
Then an HTTP/2 enabled client can access the nghttpx server using HTTP/2. For
example, you can send a GET request using nghttp:
.. code-block:: text
@@ -66,19 +63,18 @@ HTTP/2 proxy mode
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.
protocols in frontend and backend connections are the same as in `default
mode`_. The difference is that this mode acts like a forward proxy and
assumes the backend is an HTTP proxy server (e.g., Squid, Apache Traffic
Server). HTTP/1 requests must include an 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.
By default, the frontend connection is encrypted. So this mode is
also called secure proxy.
To turn off encryption on frontend connection, use ``no-tls`` keyword
To turn off encryption on the frontend connection, use ``no-tls`` keyword
in :option:`--frontend` option.
The backend must be HTTP proxy server. nghttpx supports multiple
The backend must be an 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
@@ -92,7 +88,7 @@ connection, use :option:`--backend` option, and specify ``h2`` in
For example, to make nghttpx listen to encrypted HTTP/2 requests at
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
HTTP/1 requests at port 8080 on the same host, run nghttpx command-line
like this:
.. code-block:: text
@@ -102,8 +98,8 @@ like this:
At the time of this writing, Firefox 41 and Chromium v46 can use
nghttpx as HTTP/2 proxy.
To make Firefox or Chromium use nghttpx as HTTP/2 or SPDY proxy, user
has to create proxy.pac script file like this:
To make Firefox or Chromium use nghttpx as HTTP/2 proxy, user has to
create proxy.pac script file like this:
.. code-block:: javascript
@@ -297,13 +293,31 @@ 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:
To route, request to request path ``/foo`` to backend server
``[::1]:8080``, you can write like so:
.. code-block:: text
backend=::1,8080;/foo
If the last character of path pattern is ``/``, all request paths
which start with that pattern match:
.. code-block:: text
backend=::1,8080;/bar/
The request path ``/bar/buzz`` matches the ``/bar/``.
You can use ``*`` at the end of the path pattern to make it wildcard
pattern. ``*`` must match at least one character:
.. code-block:: text
backend=::1,8080;/sample*
The request path ``/sample1/foo`` matches the ``/sample*`` pattern.
Of course, you can specify both host and request path at the same
time:
@@ -371,7 +385,7 @@ parameter in :option:`--backend` option, like so:
.. code-block:: text
backend=foo.example.com;;dns
backend=foo.example.com,80;;dns
nghttpx will cache resolved addresses for certain period of time. To
change this cache period, use :option:`--dns-cache-timeout`.
@@ -387,6 +401,28 @@ like so:
frontend=*,443;proxyproto
Session affinity
----------------
Two kinds of session affinity are available: client IP, and HTTP
Cookie.
To enable client IP based affinity, specify ``affinity=ip`` parameter
in :option:`--backend` option. If PROXY protocol is enabled, then an
address obtained from PROXY protocol is taken into consideration.
To enable HTTP Cookie based affinity, specify ``affinity=cookie``
parameter, and specify a name of cookie in ``affinity-cookie-name``
parameter. Optionally, a Path attribute can be specified in
``affinity-cookie-path`` parameter:
.. code-block:: text
backend=127.0.0.1,3000;;affinity=cookie;affinity-cookie-name=nghttpxlb;affinity-cookie-path=/
Secure attribute of cookie is set if client connection is protected by
TLS.
PSK cipher suites
-----------------

View File

@@ -124,6 +124,7 @@ remote server. It's defined as::
bev = bufferevent_openssl_socket_new(
evbase, -1, ssl, BUFFEREVENT_SSL_CONNECTING,
BEV_OPT_DEFER_CALLBACKS | BEV_OPT_CLOSE_ON_FREE);
bufferevent_enable(bev, EV_READ | EV_WRITE);
bufferevent_setcb(bev, readcb, writecb, eventcb, session_data);
rv = bufferevent_socket_connect_hostname(bev, session_data->dnsbase,
AF_UNSPEC, host, port);

View File

@@ -7,11 +7,8 @@ if(ENABLE_EXAMPLES)
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
${CMAKE_CURRENT_SOURCE_DIR}
"${CMAKE_CURRENT_SOURCE_DIR}/../third-party"
${LIBEVENT_INCLUDE_DIRS}
${OPENSSL_INCLUDE_DIRS}

View File

@@ -62,11 +62,11 @@ ASIOCPPFLAGS = ${AM_CPPFLAGS} ${BOOST_CPPFLAGS}
ASIOLDADD = $(top_builddir)/lib/libnghttp2.la \
$(top_builddir)/src/libnghttp2_asio.la @JEMALLOC_LIBS@ \
$(top_builddir)/third-party/libhttp-parser.la \
@OPENSSL_LIBS@ \
${BOOST_LDFLAGS} \
${BOOST_ASIO_LIB} \
${BOOST_THREAD_LIB} \
${BOOST_SYSTEM_LIB} \
@OPENSSL_LIBS@ \
@APPLDFLAGS@
asio_sv_SOURCES = asio-sv.cc

View File

@@ -159,10 +159,13 @@ static void diec(const char *func, int error_code) {
* bytes actually written. See the documentation of
* nghttp2_send_callback for the details.
*/
static ssize_t send_callback(nghttp2_session *session _U_, const uint8_t *data,
size_t length, int flags _U_, void *user_data) {
static ssize_t send_callback(nghttp2_session *session, const uint8_t *data,
size_t length, int flags, void *user_data) {
struct Connection *connection;
int rv;
(void)session;
(void)flags;
connection = (struct Connection *)user_data;
connection->want_io = IO_NONE;
ERR_clear_error();
@@ -186,10 +189,13 @@ static ssize_t send_callback(nghttp2_session *session _U_, const uint8_t *data,
* |length| bytes. Returns the number of bytes stored in |buf|. See
* the documentation of nghttp2_recv_callback for the details.
*/
static ssize_t recv_callback(nghttp2_session *session _U_, uint8_t *buf,
size_t length, int flags _U_, void *user_data) {
static ssize_t recv_callback(nghttp2_session *session, uint8_t *buf,
size_t length, int flags, void *user_data) {
struct Connection *connection;
int rv;
(void)session;
(void)flags;
connection = (struct Connection *)user_data;
connection->want_io = IO_NONE;
ERR_clear_error();
@@ -210,9 +216,10 @@ static ssize_t recv_callback(nghttp2_session *session _U_, uint8_t *buf,
}
static int on_frame_send_callback(nghttp2_session *session,
const nghttp2_frame *frame,
void *user_data _U_) {
const nghttp2_frame *frame, void *user_data) {
size_t i;
(void)user_data;
switch (frame->hd.type) {
case NGHTTP2_HEADERS:
if (nghttp2_session_get_stream_user_data(session, frame->hd.stream_id)) {
@@ -237,9 +244,10 @@ static int on_frame_send_callback(nghttp2_session *session,
}
static int on_frame_recv_callback(nghttp2_session *session,
const nghttp2_frame *frame,
void *user_data _U_) {
const nghttp2_frame *frame, void *user_data) {
size_t i;
(void)user_data;
switch (frame->hd.type) {
case NGHTTP2_HEADERS:
if (frame->headers.cat == NGHTTP2_HCAT_RESPONSE) {
@@ -274,9 +282,11 @@ static int on_frame_recv_callback(nghttp2_session *session,
* we submit GOAWAY and close the session.
*/
static int on_stream_close_callback(nghttp2_session *session, int32_t stream_id,
uint32_t error_code _U_,
void *user_data _U_) {
uint32_t error_code, void *user_data) {
struct Request *req;
(void)error_code;
(void)user_data;
req = nghttp2_session_get_stream_user_data(session, stream_id);
if (req) {
int rv;
@@ -293,11 +303,13 @@ static int on_stream_close_callback(nghttp2_session *session, int32_t stream_id,
* The implementation of nghttp2_on_data_chunk_recv_callback type. We
* use this function to print the received response body.
*/
static int on_data_chunk_recv_callback(nghttp2_session *session,
uint8_t flags _U_, int32_t stream_id,
const uint8_t *data, size_t len,
void *user_data _U_) {
static int on_data_chunk_recv_callback(nghttp2_session *session, uint8_t flags,
int32_t stream_id, const uint8_t *data,
size_t len, void *user_data) {
struct Request *req;
(void)flags;
(void)user_data;
req = nghttp2_session_get_stream_user_data(session, stream_id);
if (req) {
printf("[INFO] C <---------------------------- S (DATA chunk)\n"
@@ -338,10 +350,13 @@ static void setup_nghttp2_callbacks(nghttp2_session_callbacks *callbacks) {
* HTTP/2 protocol, if server does not offer HTTP/2 the nghttp2
* library supports, we terminate program.
*/
static int select_next_proto_cb(SSL *ssl _U_, unsigned char **out,
static int select_next_proto_cb(SSL *ssl, unsigned char **out,
unsigned char *outlen, const unsigned char *in,
unsigned int inlen, void *arg _U_) {
unsigned int inlen, void *arg) {
int rv;
(void)ssl;
(void)arg;
/* nghttp2_select_next_protocol() selects HTTP/2 protocol the
nghttp2 library supports. */
rv = nghttp2_select_next_protocol(out, outlen, in, inlen);

View File

@@ -44,7 +44,7 @@ static void deflate(nghttp2_hd_deflater *deflater,
static int inflate_header_block(nghttp2_hd_inflater *inflater, uint8_t *in,
size_t inlen, int final);
int main(int argc _U_, char **argv _U_) {
int main() {
int rv;
nghttp2_hd_deflater *deflater;
nghttp2_hd_inflater *inflater;

View File

@@ -199,22 +199,27 @@ static void print_headers(FILE *f, nghttp2_nv *nva, size_t nvlen) {
/* nghttp2_send_callback. Here we transmit the |data|, |length| bytes,
to the network. Because we are using libevent bufferevent, we just
write those bytes into bufferevent buffer. */
static ssize_t send_callback(nghttp2_session *session _U_, const uint8_t *data,
size_t length, int flags _U_, void *user_data) {
static ssize_t send_callback(nghttp2_session *session, const uint8_t *data,
size_t length, int flags, void *user_data) {
http2_session_data *session_data = (http2_session_data *)user_data;
struct bufferevent *bev = session_data->bev;
(void)session;
(void)flags;
bufferevent_write(bev, data, length);
return (ssize_t)length;
}
/* nghttp2_on_header_callback: Called when nghttp2 library emits
single header name/value pair. */
static int on_header_callback(nghttp2_session *session _U_,
static int on_header_callback(nghttp2_session *session,
const nghttp2_frame *frame, const uint8_t *name,
size_t namelen, const uint8_t *value,
size_t valuelen, uint8_t flags _U_,
void *user_data) {
size_t valuelen, uint8_t flags, void *user_data) {
http2_session_data *session_data = (http2_session_data *)user_data;
(void)session;
(void)flags;
switch (frame->hd.type) {
case NGHTTP2_HEADERS:
if (frame->headers.cat == NGHTTP2_HCAT_RESPONSE &&
@@ -229,10 +234,12 @@ static int on_header_callback(nghttp2_session *session _U_,
/* nghttp2_on_begin_headers_callback: Called when nghttp2 library gets
started to receive header block. */
static int on_begin_headers_callback(nghttp2_session *session _U_,
static int on_begin_headers_callback(nghttp2_session *session,
const nghttp2_frame *frame,
void *user_data) {
http2_session_data *session_data = (http2_session_data *)user_data;
(void)session;
switch (frame->hd.type) {
case NGHTTP2_HEADERS:
if (frame->headers.cat == NGHTTP2_HCAT_RESPONSE &&
@@ -247,9 +254,11 @@ static int on_begin_headers_callback(nghttp2_session *session _U_,
/* nghttp2_on_frame_recv_callback: Called when nghttp2 library
received a complete frame from the remote peer. */
static int on_frame_recv_callback(nghttp2_session *session _U_,
static int on_frame_recv_callback(nghttp2_session *session,
const nghttp2_frame *frame, void *user_data) {
http2_session_data *session_data = (http2_session_data *)user_data;
(void)session;
switch (frame->hd.type) {
case NGHTTP2_HEADERS:
if (frame->headers.cat == NGHTTP2_HCAT_RESPONSE &&
@@ -266,11 +275,13 @@ static int on_frame_recv_callback(nghttp2_session *session _U_,
is meant to the stream we initiated, print the received data in
stdout, so that the user can redirect its output to the file
easily. */
static int on_data_chunk_recv_callback(nghttp2_session *session _U_,
uint8_t flags _U_, int32_t stream_id,
const uint8_t *data, size_t len,
void *user_data) {
static int on_data_chunk_recv_callback(nghttp2_session *session, uint8_t flags,
int32_t stream_id, const uint8_t *data,
size_t len, void *user_data) {
http2_session_data *session_data = (http2_session_data *)user_data;
(void)session;
(void)flags;
if (session_data->stream_data->stream_id == stream_id) {
fwrite(data, 1, len, stdout);
}
@@ -300,9 +311,12 @@ static int on_stream_close_callback(nghttp2_session *session, int32_t stream_id,
/* NPN TLS extension client callback. We check that server advertised
the HTTP/2 protocol the nghttp2 library supports. If not, exit
the program. */
static int select_next_proto_cb(SSL *ssl _U_, unsigned char **out,
static int select_next_proto_cb(SSL *ssl, unsigned char **out,
unsigned char *outlen, const unsigned char *in,
unsigned int inlen, void *arg _U_) {
unsigned int inlen, void *arg) {
(void)ssl;
(void)arg;
if (nghttp2_select_next_protocol(out, outlen, in, inlen) <= 0) {
errx(1, "Server did not advertise " NGHTTP2_PROTO_VERSION_ID);
}
@@ -461,8 +475,10 @@ static void readcb(struct bufferevent *bev, void *ptr) {
receiving GOAWAY, we check the some conditions on the nghttp2
library and output buffer of bufferevent. If it indicates we have
no business to this session, tear down the connection. */
static void writecb(struct bufferevent *bev _U_, void *ptr) {
static void writecb(struct bufferevent *bev, void *ptr) {
http2_session_data *session_data = (http2_session_data *)ptr;
(void)bev;
if (nghttp2_session_want_read(session_data->session) == 0 &&
nghttp2_session_want_write(session_data->session) == 0 &&
evbuffer_get_length(bufferevent_get_output(session_data->bev)) == 0) {
@@ -532,6 +548,7 @@ static void initiate_connection(struct event_base *evbase, SSL_CTX *ssl_ctx,
bev = bufferevent_openssl_socket_new(
evbase, -1, ssl, BUFFEREVENT_SSL_CONNECTING,
BEV_OPT_DEFER_CALLBACKS | BEV_OPT_CLOSE_ON_FREE);
bufferevent_enable(bev, EV_READ | EV_WRITE);
bufferevent_setcb(bev, readcb, writecb, eventcb, session_data);
rv = bufferevent_socket_connect_hostname(bev, session_data->dnsbase,
AF_UNSPEC, host, port);

View File

@@ -109,18 +109,23 @@ struct app_context {
static unsigned char next_proto_list[256];
static size_t next_proto_list_len;
static int next_proto_cb(SSL *s _U_, const unsigned char **data,
unsigned int *len, void *arg _U_) {
static int next_proto_cb(SSL *ssl, const unsigned char **data,
unsigned int *len, void *arg) {
(void)ssl;
(void)arg;
*data = next_proto_list;
*len = (unsigned int)next_proto_list_len;
return SSL_TLSEXT_ERR_OK;
}
#if OPENSSL_VERSION_NUMBER >= 0x10002000L
static int alpn_select_proto_cb(SSL *ssl _U_, const unsigned char **out,
static int alpn_select_proto_cb(SSL *ssl, const unsigned char **out,
unsigned char *outlen, const unsigned char *in,
unsigned int inlen, void *arg _U_) {
unsigned int inlen, void *arg) {
int rv;
(void)ssl;
(void)arg;
rv = nghttp2_select_next_protocol((unsigned char **)out, outlen, in, inlen);
@@ -197,8 +202,10 @@ static void add_stream(http2_session_data *session_data,
}
}
static void remove_stream(http2_session_data *session_data _U_,
static void remove_stream(http2_session_data *session_data,
http2_stream_data *stream_data) {
(void)session_data;
stream_data->prev->next = stream_data->next;
if (stream_data->next) {
stream_data->next->prev = stream_data->prev;
@@ -243,6 +250,7 @@ static http2_session_data *create_http2_session_data(app_context *app_ctx,
session_data->bev = bufferevent_openssl_socket_new(
app_ctx->evbase, fd, ssl, BUFFEREVENT_SSL_ACCEPTING,
BEV_OPT_CLOSE_ON_FREE | BEV_OPT_DEFER_CALLBACKS);
bufferevent_enable(session_data->bev, EV_READ | EV_WRITE);
rv = getnameinfo(addr, (socklen_t)addrlen, host, sizeof(host), NULL, 0,
NI_NUMERICHOST);
if (rv != 0) {
@@ -309,10 +317,13 @@ static int session_recv(http2_session_data *session_data) {
return 0;
}
static ssize_t send_callback(nghttp2_session *session _U_, const uint8_t *data,
size_t length, int flags _U_, void *user_data) {
static ssize_t send_callback(nghttp2_session *session, const uint8_t *data,
size_t length, int flags, void *user_data) {
http2_session_data *session_data = (http2_session_data *)user_data;
struct bufferevent *bev = session_data->bev;
(void)session;
(void)flags;
/* Avoid excessive buffering in server side. */
if (evbuffer_get_length(bufferevent_get_output(session_data->bev)) >=
OUTPUT_WOULDBLOCK_THRESHOLD) {
@@ -375,13 +386,17 @@ static char *percent_decode(const uint8_t *value, size_t valuelen) {
return res;
}
static ssize_t file_read_callback(nghttp2_session *session _U_,
int32_t stream_id _U_, uint8_t *buf,
size_t length, uint32_t *data_flags,
static ssize_t file_read_callback(nghttp2_session *session, int32_t stream_id,
uint8_t *buf, size_t length,
uint32_t *data_flags,
nghttp2_data_source *source,
void *user_data _U_) {
void *user_data) {
int fd = source->fd;
ssize_t r;
(void)session;
(void)stream_id;
(void)user_data;
while ((r = read(fd, buf, length)) == -1 && errno == EINTR)
;
if (r == -1) {
@@ -454,10 +469,12 @@ static int error_reply(nghttp2_session *session,
static int on_header_callback(nghttp2_session *session,
const nghttp2_frame *frame, const uint8_t *name,
size_t namelen, const uint8_t *value,
size_t valuelen, uint8_t flags _U_,
void *user_data _U_) {
size_t valuelen, uint8_t flags, void *user_data) {
http2_stream_data *stream_data;
const char PATH[] = ":path";
(void)flags;
(void)user_data;
switch (frame->hd.type) {
case NGHTTP2_HEADERS:
if (frame->headers.cat != NGHTTP2_HCAT_REQUEST) {
@@ -570,9 +587,10 @@ static int on_frame_recv_callback(nghttp2_session *session,
}
static int on_stream_close_callback(nghttp2_session *session, int32_t stream_id,
uint32_t error_code _U_, void *user_data) {
uint32_t error_code, void *user_data) {
http2_session_data *session_data = (http2_session_data *)user_data;
http2_stream_data *stream_data;
(void)error_code;
stream_data = nghttp2_session_get_stream_user_data(session, stream_id);
if (!stream_data) {
@@ -625,8 +643,10 @@ static int send_server_connection_header(http2_session_data *session_data) {
/* readcb for bufferevent after client connection header was
checked. */
static void readcb(struct bufferevent *bev _U_, void *ptr) {
static void readcb(struct bufferevent *bev, void *ptr) {
http2_session_data *session_data = (http2_session_data *)ptr;
(void)bev;
if (session_recv(session_data) != 0) {
delete_http2_session_data(session_data);
return;
@@ -658,12 +678,13 @@ static void writecb(struct bufferevent *bev, void *ptr) {
}
/* eventcb for bufferevent */
static void eventcb(struct bufferevent *bev _U_, short events, void *ptr) {
static void eventcb(struct bufferevent *bev, 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;
(void)bev;
fprintf(stderr, "%s connected\n", session_data->client_addr);
@@ -703,10 +724,11 @@ static void eventcb(struct bufferevent *bev _U_, short events, void *ptr) {
}
/* callback for evconnlistener */
static void acceptcb(struct evconnlistener *listener _U_, int fd,
static void acceptcb(struct evconnlistener *listener, int fd,
struct sockaddr *addr, int addrlen, void *arg) {
app_context *app_ctx = (app_context *)arg;
http2_session_data *session_data;
(void)listener;
session_data = create_http2_session_data(app_ctx, fd, addr, addrlen);

View File

@@ -23,8 +23,8 @@ following compiler/linker flags:
.. code-block:: text
CPPFLAGS="-fsanitize-coverage=edge -fsanitize=addres"
LDFLAGS="-fsanitize-coverage=edge -fsanitize=addres"
CPPFLAGS="-fsanitize-coverage=edge -fsanitize=address"
LDFLAGS="-fsanitize-coverage=edge -fsanitize=address"
Then, fuzz_target.cc can be built using the following command:

View File

@@ -163,6 +163,12 @@ OPTIONS = [
"redirect-https-port",
"frontend-max-requests",
"single-thread",
"single-process",
"no-add-x-forwarded-proto",
"no-strip-incoming-x-forwarded-proto",
"ocsp-startup",
"no-verify-ocsp",
"verify-client-tolerate-expired",
]
LOGVARS = [
@@ -181,6 +187,16 @@ LOGVARS = [
"ssl_protocol",
"ssl_session_id",
"ssl_session_reused",
"tls_cipher",
"tls_protocol",
"tls_session_id",
"tls_session_reused",
"tls_sni",
"tls_client_fingerprint_sha256",
"tls_client_fingerprint_sha1",
"tls_client_subject_name",
"tls_client_issuer_name",
"tls_client_serial",
"backend_host",
"backend_port",
]

View File

@@ -24,7 +24,6 @@
GO_FILES = \
nghttpx_http1_test.go \
nghttpx_http2_test.go \
nghttpx_spdy_test.go \
server_tester.go
EXTRA_DIST = \
@@ -43,7 +42,6 @@ EXTRA_DIST = \
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:

View File

@@ -9,6 +9,7 @@ import (
"golang.org/x/net/websocket"
"io"
"net/http"
"regexp"
"syscall"
"testing"
"time"
@@ -125,6 +126,54 @@ Content-Length: 0
// }
// }
// TestH1H1AffinityCookie tests that affinity cookie is sent back in
// cleartext http.
func TestH1H1AffinityCookie(t *testing.T) {
st := newServerTester([]string{"--affinity-cookie"}, t, noopHandler)
defer st.Close()
res, err := st.http1(requestParam{
name: "TestH1H1AffinityCookie",
})
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)
}
const pattern = `affinity=[0-9a-f]{8}; Path=/foo/bar`
validCookie := regexp.MustCompile(pattern)
if got := res.header.Get("Set-Cookie"); !validCookie.MatchString(got) {
t.Errorf("Set-Cookie: %v; want pattern %v", got, pattern)
}
}
// TestH1H1AffinityCookieTLS tests that affinity cookie is sent back
// in https.
func TestH1H1AffinityCookieTLS(t *testing.T) {
st := newServerTesterTLS([]string{"--alpn-h1", "--affinity-cookie"}, t, noopHandler)
defer st.Close()
res, err := st.http1(requestParam{
name: "TestH1H1AffinityCookieTLS",
})
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)
}
const pattern = `affinity=[0-9a-f]{8}; Path=/foo/bar; Secure`
validCookie := regexp.MustCompile(pattern)
if got := res.header.Get("Set-Cookie"); !validCookie.MatchString(got) {
t.Errorf("Set-Cookie: %v; want pattern %v", got, pattern)
}
}
// TestH1H1GracefulShutdown tests graceful shutdown.
func TestH1H1GracefulShutdown(t *testing.T) {
st := newServerTester(nil, t, noopHandler)
@@ -162,7 +211,7 @@ func TestH1H1GracefulShutdown(t *testing.T) {
want := io.EOF
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)
t.Errorf("st.conn.Read(): %v; want %v", err, want)
}
}

View File

@@ -35,6 +35,105 @@ func TestH2H1PlainGET(t *testing.T) {
}
}
// TestH2H1AddXfp tests that server appends :scheme to the existing
// x-forwarded-proto header field.
func TestH2H1AddXfp(t *testing.T) {
st := newServerTester([]string{"--no-strip-incoming-x-forwarded-proto"}, t, func(w http.ResponseWriter, r *http.Request) {
xfp := r.Header.Get("X-Forwarded-Proto")
if got, want := xfp, "foo, http"; got != want {
t.Errorf("X-Forwarded-Proto = %q; want %q", got, want)
}
})
defer st.Close()
res, err := st.http2(requestParam{
name: "TestH2H1AddXfp",
header: []hpack.HeaderField{
pair("x-forwarded-proto", "foo"),
},
})
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)
}
}
// TestH2H1NoAddXfp tests that server does not append :scheme to the
// existing x-forwarded-proto header field.
func TestH2H1NoAddXfp(t *testing.T) {
st := newServerTester([]string{"--no-add-x-forwarded-proto", "--no-strip-incoming-x-forwarded-proto"}, t, func(w http.ResponseWriter, r *http.Request) {
xfp := r.Header.Get("X-Forwarded-Proto")
if got, want := xfp, "foo"; got != want {
t.Errorf("X-Forwarded-Proto = %q; want %q", got, want)
}
})
defer st.Close()
res, err := st.http2(requestParam{
name: "TestH2H1NoAddXfp",
header: []hpack.HeaderField{
pair("x-forwarded-proto", "foo"),
},
})
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)
}
}
// TestH2H1StripXfp tests that server strips incoming
// x-forwarded-proto header field.
func TestH2H1StripXfp(t *testing.T) {
st := newServerTester(nil, t, func(w http.ResponseWriter, r *http.Request) {
xfp := r.Header.Get("X-Forwarded-Proto")
if got, want := xfp, "http"; got != want {
t.Errorf("X-Forwarded-Proto = %q; want %q", got, want)
}
})
defer st.Close()
res, err := st.http2(requestParam{
name: "TestH2H1StripXfp",
header: []hpack.HeaderField{
pair("x-forwarded-proto", "foo"),
},
})
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)
}
}
// TestH2H1StripNoAddXfp tests that server strips incoming
// x-forwarded-proto header field, and does not add another.
func TestH2H1StripNoAddXfp(t *testing.T) {
st := newServerTester([]string{"--no-add-x-forwarded-proto"}, t, func(w http.ResponseWriter, r *http.Request) {
if got, found := r.Header["X-Forwarded-Proto"]; found {
t.Errorf("X-Forwarded-Proto = %q; want nothing", got)
}
})
defer st.Close()
res, err := st.http2(requestParam{
name: "TestH2H1StripNoAddXfp",
header: []hpack.HeaderField{
pair("x-forwarded-proto", "foo"),
},
})
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)
}
}
// TestH2H1AddXff tests that server generates X-Forwarded-For header
// field when forwarding request to backend.
func TestH2H1AddXff(t *testing.T) {
@@ -1014,14 +1113,45 @@ func TestH2H1Upgrade(t *testing.T) {
}
}
// TestH2H1ProxyProtocolV1ForwardedForObfuscated tests that Forwarded
// header field includes obfuscated address even if PROXY protocol
// version 1 containing TCP4 entry is accepted.
func TestH2H1ProxyProtocolV1ForwardedForObfuscated(t *testing.T) {
pattern := fmt.Sprintf(`^for=_[^;]+$`)
validFwd := regexp.MustCompile(pattern)
st := newServerTester([]string{"--accept-proxy-protocol", "--add-x-forwarded-for", "--add-forwarded=for", "--forwarded-for=obfuscated"}, t, func(w http.ResponseWriter, r *http.Request) {
if got := r.Header.Get("Forwarded"); !validFwd.MatchString(got) {
t.Errorf("Forwarded: %v; want pattern %v", got, pattern)
}
})
defer st.Close()
st.conn.Write([]byte("PROXY TCP4 192.168.0.2 192.168.0.100 12345 8080\r\n"))
res, err := st.http2(requestParam{
name: "TestH2H1ProxyProtocolV1ForwardedForObfuscated",
})
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)
}
}
// TestH2H1ProxyProtocolV1TCP4 tests PROXY protocol version 1
// containing TCP4 entry is accepted and X-Forwarded-For contains
// advertised src address.
func TestH2H1ProxyProtocolV1TCP4(t *testing.T) {
st := newServerTester([]string{"--accept-proxy-protocol", "--add-x-forwarded-for"}, t, func(w http.ResponseWriter, r *http.Request) {
st := newServerTester([]string{"--accept-proxy-protocol", "--add-x-forwarded-for", "--add-forwarded=for", "--forwarded-for=ip"}, t, func(w http.ResponseWriter, r *http.Request) {
if got, want := r.Header.Get("X-Forwarded-For"), "192.168.0.2"; got != want {
t.Errorf("X-Forwarded-For: %v; want %v", got, want)
}
if got, want := r.Header.Get("Forwarded"), "for=192.168.0.2"; got != want {
t.Errorf("Forwarded: %v; want %v", got, want)
}
})
defer st.Close()
@@ -1044,10 +1174,13 @@ func TestH2H1ProxyProtocolV1TCP4(t *testing.T) {
// containing TCP6 entry is accepted and X-Forwarded-For contains
// advertised src address.
func TestH2H1ProxyProtocolV1TCP6(t *testing.T) {
st := newServerTester([]string{"--accept-proxy-protocol", "--add-x-forwarded-for"}, t, func(w http.ResponseWriter, r *http.Request) {
st := newServerTester([]string{"--accept-proxy-protocol", "--add-x-forwarded-for", "--add-forwarded=for", "--forwarded-for=ip"}, t, func(w http.ResponseWriter, r *http.Request) {
if got, want := r.Header.Get("X-Forwarded-For"), "2001:0db8:85a3:0000:0000:8a2e:0370:7334"; got != want {
t.Errorf("X-Forwarded-For: %v; want %v", got, want)
}
if got, want := r.Header.Get("Forwarded"), `for="[2001:0db8:85a3:0000:0000:8a2e:0370:7334]"`; got != want {
t.Errorf("Forwarded: %v; want %v", got, want)
}
})
defer st.Close()
@@ -1069,9 +1202,12 @@ func TestH2H1ProxyProtocolV1TCP6(t *testing.T) {
// TestH2H1ProxyProtocolV1Unknown tests PROXY protocol version 1
// containing UNKNOWN entry is accepted.
func TestH2H1ProxyProtocolV1Unknown(t *testing.T) {
st := newServerTester([]string{"--accept-proxy-protocol", "--add-x-forwarded-for"}, t, func(w http.ResponseWriter, r *http.Request) {
st := newServerTester([]string{"--accept-proxy-protocol", "--add-x-forwarded-for", "--add-forwarded=for", "--forwarded-for=ip"}, t, func(w http.ResponseWriter, r *http.Request) {
if got, notWant := r.Header.Get("X-Forwarded-For"), "192.168.0.2"; got == notWant {
t.Errorf("X-Forwarded-For: %v")
t.Errorf("X-Forwarded-For: %v; want something else", got)
}
if got, notWant := r.Header.Get("Forwarded"), "for=192.168.0.2"; got == notWant {
t.Errorf("Forwarded: %v; want something else", got)
}
})
defer st.Close()
@@ -1449,6 +1585,175 @@ func TestH2H1HTTPSRedirectPort(t *testing.T) {
}
}
// TestH2H1Code204 tests that 204 response without content-length, and
// transfer-encoding is valid.
func TestH2H1Code204(t *testing.T) {
st := newServerTester(nil, t, func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusNoContent)
})
defer st.Close()
res, err := st.http2(requestParam{
name: "TestH2H1Code204",
})
if err != nil {
t.Fatalf("Error st.http2() = %v", err)
}
if got, want := res.status, 204; got != want {
t.Errorf("status = %v; want %v", got, want)
}
}
// TestH2H1Code204CL0 tests that 204 response with content-length: 0
// is allowed.
func TestH2H1Code204CL0(t *testing.T) {
st := newServerTester(nil, t, func(w http.ResponseWriter, r *http.Request) {
hj, ok := w.(http.Hijacker)
if !ok {
http.Error(w, "Could not hijack the connection", http.StatusInternalServerError)
return
}
conn, bufrw, err := hj.Hijack()
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
defer conn.Close()
bufrw.WriteString("HTTP/1.1 204\r\nContent-Length: 0\r\n\r\n")
bufrw.Flush()
})
defer st.Close()
res, err := st.http2(requestParam{
name: "TestH2H1Code204CL0",
})
if err != nil {
t.Fatalf("Error st.http2() = %v", err)
}
if got, want := res.status, 204; got != want {
t.Errorf("status = %v; want %v", got, want)
}
if got, found := res.header["Content-Length"]; found {
t.Errorf("Content-Length = %v, want nothing", got)
}
}
// TestH2H1Code204CLNonzero tests that 204 response with nonzero
// content-length is not allowed.
func TestH2H1Code204CLNonzero(t *testing.T) {
st := newServerTester(nil, t, func(w http.ResponseWriter, r *http.Request) {
hj, ok := w.(http.Hijacker)
if !ok {
http.Error(w, "Could not hijack the connection", http.StatusInternalServerError)
return
}
conn, bufrw, err := hj.Hijack()
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
defer conn.Close()
bufrw.WriteString("HTTP/1.1 204\r\nContent-Length: 1\r\n\r\n")
bufrw.Flush()
})
defer st.Close()
res, err := st.http2(requestParam{
name: "TestH2H1Code204CLNonzero",
})
if err != nil {
t.Fatalf("Error st.http2() = %v", err)
}
if got, want := res.status, 502; got != want {
t.Errorf("status = %v; want %v", got, want)
}
}
// TestH2H1Code204TE tests that 204 response with transfer-encoding is
// not allowed.
func TestH2H1Code204TE(t *testing.T) {
st := newServerTester(nil, t, func(w http.ResponseWriter, r *http.Request) {
hj, ok := w.(http.Hijacker)
if !ok {
http.Error(w, "Could not hijack the connection", http.StatusInternalServerError)
return
}
conn, bufrw, err := hj.Hijack()
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
defer conn.Close()
bufrw.WriteString("HTTP/1.1 204\r\nTransfer-Encoding: chunked\r\n\r\n")
bufrw.Flush()
})
defer st.Close()
res, err := st.http2(requestParam{
name: "TestH2H1Code204TE",
})
if err != nil {
t.Fatalf("Error st.http2() = %v", err)
}
if got, want := res.status, 502; got != want {
t.Errorf("status = %v; want %v", got, want)
}
}
// TestH2H1AffinityCookie tests that affinity cookie is sent back in
// cleartext http.
func TestH2H1AffinityCookie(t *testing.T) {
st := newServerTester([]string{"--affinity-cookie"}, t, noopHandler)
defer st.Close()
res, err := st.http2(requestParam{
name: "TestH2H1AffinityCookie",
})
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)
}
const pattern = `affinity=[0-9a-f]{8}; Path=/foo/bar`
validCookie := regexp.MustCompile(pattern)
if got := res.header.Get("Set-Cookie"); !validCookie.MatchString(got) {
t.Errorf("Set-Cookie: %v; want pattern %v", got, pattern)
}
}
// TestH2H1AffinityCookieTLS tests that affinity cookie is sent back
// in https.
func TestH2H1AffinityCookieTLS(t *testing.T) {
st := newServerTesterTLS([]string{"--affinity-cookie"}, t, noopHandler)
defer st.Close()
res, err := st.http2(requestParam{
name: "TestH2H1AffinityCookieTLS",
scheme: "https",
})
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)
}
const pattern = `affinity=[0-9a-f]{8}; Path=/foo/bar; Secure`
validCookie := regexp.MustCompile(pattern)
if got := res.header.Get("Set-Cookie"); !validCookie.MatchString(got) {
t.Errorf("Set-Cookie: %v; want pattern %v", got, pattern)
}
}
// TestH2H1GracefulShutdown tests graceful shutdown.
func TestH2H1GracefulShutdown(t *testing.T) {
st := newServerTester(nil, t, noopHandler)
@@ -1653,6 +1958,105 @@ func TestH2H2TLSXfp(t *testing.T) {
}
}
// TestH2H2AddXfp tests that server appends :scheme to the existing
// x-forwarded-proto header field.
func TestH2H2AddXfp(t *testing.T) {
st := newServerTesterTLS([]string{"--http2-bridge", "--no-strip-incoming-x-forwarded-proto"}, t, func(w http.ResponseWriter, r *http.Request) {
xfp := r.Header.Get("X-Forwarded-Proto")
if got, want := xfp, "foo, http"; got != want {
t.Errorf("X-Forwarded-Proto = %q; want %q", got, want)
}
})
defer st.Close()
res, err := st.http2(requestParam{
name: "TestH2H2AddXfp",
header: []hpack.HeaderField{
pair("x-forwarded-proto", "foo"),
},
})
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)
}
}
// TestH2H2NoAddXfp tests that server does not append :scheme to the
// existing x-forwarded-proto header field.
func TestH2H2NoAddXfp(t *testing.T) {
st := newServerTesterTLS([]string{"--http2-bridge", "--no-add-x-forwarded-proto", "--no-strip-incoming-x-forwarded-proto"}, t, func(w http.ResponseWriter, r *http.Request) {
xfp := r.Header.Get("X-Forwarded-Proto")
if got, want := xfp, "foo"; got != want {
t.Errorf("X-Forwarded-Proto = %q; want %q", got, want)
}
})
defer st.Close()
res, err := st.http2(requestParam{
name: "TestH2H2NoAddXfp",
header: []hpack.HeaderField{
pair("x-forwarded-proto", "foo"),
},
})
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)
}
}
// TestH2H2StripXfp tests that server strips incoming
// x-forwarded-proto header field.
func TestH2H2StripXfp(t *testing.T) {
st := newServerTesterTLS([]string{"--http2-bridge"}, t, func(w http.ResponseWriter, r *http.Request) {
xfp := r.Header.Get("X-Forwarded-Proto")
if got, want := xfp, "http"; got != want {
t.Errorf("X-Forwarded-Proto = %q; want %q", got, want)
}
})
defer st.Close()
res, err := st.http2(requestParam{
name: "TestH2H2StripXfp",
header: []hpack.HeaderField{
pair("x-forwarded-proto", "foo"),
},
})
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)
}
}
// TestH2H2StripNoAddXfp tests that server strips incoming
// x-forwarded-proto header field, and does not add another.
func TestH2H2StripNoAddXfp(t *testing.T) {
st := newServerTesterTLS([]string{"--http2-bridge", "--no-add-x-forwarded-proto"}, t, func(w http.ResponseWriter, r *http.Request) {
if got, found := r.Header["X-Forwarded-Proto"]; found {
t.Errorf("X-Forwarded-Proto = %q; want nothing", got)
}
})
defer st.Close()
res, err := st.http2(requestParam{
name: "TestH2H2StripNoAddXfp",
header: []hpack.HeaderField{
pair("x-forwarded-proto", "foo"),
},
})
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)
}
}
// TestH2H2AddXff tests that server generates X-Forwarded-For header
// field when forwarding request to backend.
func TestH2H2AddXff(t *testing.T) {
@@ -1961,6 +2365,26 @@ func TestH2H2DNS(t *testing.T) {
}
}
// TestH2H2Code204 tests that 204 response without content-length, and
// transfer-encoding is valid.
func TestH2H2Code204(t *testing.T) {
st := newServerTester([]string{"--http2-bridge"}, t, func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusNoContent)
})
defer st.Close()
res, err := st.http2(requestParam{
name: "TestH2H2Code204",
})
if err != nil {
t.Fatalf("Error st.http2() = %v", err)
}
if got, want := res.status, 204; got != want {
t.Errorf("status = %v; want %v", got, want)
}
}
// TestH2APIBackendconfig exercise backendconfig API endpoint routine
// for successful case.
func TestH2APIBackendconfig(t *testing.T) {

View File

@@ -1,664 +0,0 @@
package nghttp2
import (
"encoding/json"
"github.com/tatsuhiro-t/spdy"
"golang.org/x/net/http2/hpack"
"net/http"
"testing"
)
// TestS3H1PlainGET tests whether simple SPDY GET request works.
func TestS3H1PlainGET(t *testing.T) {
st := newServerTesterTLS([]string{"--npn-list=spdy/3.1"}, t, noopHandler)
defer st.Close()
res, err := st.spdy(requestParam{
name: "TestS3H1PlainGET",
})
if err != nil {
t.Fatalf("Error st.spdy() = %v", err)
}
want := 200
if got := res.status; got != want {
t.Errorf("status = %v; want %v", got, want)
}
}
// TestS3H1BadRequestCL tests that server rejects request whose
// content-length header field value does not match its request body
// size.
func TestS3H1BadRequestCL(t *testing.T) {
st := newServerTesterTLS([]string{"--npn-list=spdy/3.1"}, t, noopHandler)
defer st.Close()
// we set content-length: 1024, but the actual request body is
// 3 bytes.
res, err := st.spdy(requestParam{
name: "TestS3H1BadRequestCL",
method: "POST",
header: []hpack.HeaderField{
pair("content-length", "1024"),
},
body: []byte("foo"),
})
if err != nil {
t.Fatalf("Error st.spdy() = %v", err)
}
want := spdy.ProtocolError
if got := res.spdyRstErrCode; got != want {
t.Errorf("res.spdyRstErrCode = %v; want %v", got, want)
}
}
// TestS3H1MultipleRequestCL tests that server rejects request with
// multiple Content-Length request header fields.
func TestS3H1MultipleRequestCL(t *testing.T) {
st := newServerTesterTLS([]string{"--npn-list=spdy/3.1"}, t, func(w http.ResponseWriter, r *http.Request) {
t.Errorf("server should not forward bad request")
})
defer st.Close()
res, err := st.spdy(requestParam{
name: "TestS3H1MultipleRequestCL",
header: []hpack.HeaderField{
pair("content-length", "1"),
pair("content-length", "1"),
},
})
if err != nil {
t.Fatalf("Error st.spdy() = %v", err)
}
want := 400
if got := res.status; got != want {
t.Errorf("status: %v; want %v", got, want)
}
}
// TestS3H1InvalidRequestCL tests that server rejects request with
// Content-Length which cannot be parsed as a number.
func TestS3H1InvalidRequestCL(t *testing.T) {
st := newServerTesterTLS([]string{"--npn-list=spdy/3.1"}, t, func(w http.ResponseWriter, r *http.Request) {
t.Errorf("server should not forward bad request")
})
defer st.Close()
res, err := st.spdy(requestParam{
name: "TestS3H1InvalidRequestCL",
header: []hpack.HeaderField{
pair("content-length", ""),
},
})
if err != nil {
t.Fatalf("Error st.spdy() = %v", err)
}
want := 400
if got := res.status; got != want {
t.Errorf("status: %v; want %v", got, want)
}
}
// TestS3H1GenerateVia tests that server generates Via header field to and
// from backend server.
func TestS3H1GenerateVia(t *testing.T) {
st := newServerTesterTLS([]string{"--npn-list=spdy/3.1"}, t, func(w http.ResponseWriter, r *http.Request) {
if got, want := r.Header.Get("Via"), "1.1 nghttpx"; got != want {
t.Errorf("Via: %v; want %v", got, want)
}
})
defer st.Close()
res, err := st.spdy(requestParam{
name: "TestS3H1GenerateVia",
})
if err != nil {
t.Fatalf("Error st.spdy() = %v", err)
}
if got, want := res.header.Get("Via"), "1.1 nghttpx"; got != want {
t.Errorf("Via: %v; want %v", got, want)
}
}
// TestS3H1AppendVia tests that server adds value to existing Via
// header field to and from backend server.
func TestS3H1AppendVia(t *testing.T) {
st := newServerTesterTLS([]string{"--npn-list=spdy/3.1"}, t, func(w http.ResponseWriter, r *http.Request) {
if got, want := r.Header.Get("Via"), "foo, 1.1 nghttpx"; got != want {
t.Errorf("Via: %v; want %v", got, want)
}
w.Header().Add("Via", "bar")
})
defer st.Close()
res, err := st.spdy(requestParam{
name: "TestS3H1AppendVia",
header: []hpack.HeaderField{
pair("via", "foo"),
},
})
if err != nil {
t.Fatalf("Error st.spdy() = %v", err)
}
if got, want := res.header.Get("Via"), "bar, 1.1 nghttpx"; got != want {
t.Errorf("Via: %v; want %v", got, want)
}
}
// TestS3H1NoVia tests that server does not add value to existing Via
// header field to and from backend server.
func TestS3H1NoVia(t *testing.T) {
st := newServerTesterTLS([]string{"--npn-list=spdy/3.1", "--no-via"}, t, func(w http.ResponseWriter, r *http.Request) {
if got, want := r.Header.Get("Via"), "foo"; got != want {
t.Errorf("Via: %v; want %v", got, want)
}
w.Header().Add("Via", "bar")
})
defer st.Close()
res, err := st.spdy(requestParam{
name: "TestS3H1NoVia",
header: []hpack.HeaderField{
pair("via", "foo"),
},
})
if err != nil {
t.Fatalf("Error st.spdy() = %v", err)
}
if got, want := res.header.Get("Via"), "bar"; got != want {
t.Errorf("Via: %v; want %v", got, want)
}
}
// TestS3H1HeaderFieldBuffer tests that request with header fields
// larger than configured buffer size is rejected.
func TestS3H1HeaderFieldBuffer(t *testing.T) {
st := newServerTesterTLS([]string{"--npn-list=spdy/3.1", "--request-header-field-buffer=10"}, t, func(w http.ResponseWriter, r *http.Request) {
t.Fatal("execution path should not be here")
})
defer st.Close()
res, err := st.spdy(requestParam{
name: "TestS3H1HeaderFieldBuffer",
})
if err != nil {
t.Fatalf("Error st.spdy() = %v", err)
}
if got, want := res.spdyRstErrCode, spdy.InternalError; got != want {
t.Errorf("res.spdyRstErrCode: %v; want %v", got, want)
}
}
// TestS3H1HeaderFields tests that request with header fields more
// than configured number is rejected.
func TestS3H1HeaderFields(t *testing.T) {
st := newServerTesterTLS([]string{"--npn-list=spdy/3.1", "--max-request-header-fields=1"}, t, func(w http.ResponseWriter, r *http.Request) {
t.Fatal("execution path should not be here")
})
defer st.Close()
res, err := st.spdy(requestParam{
name: "TestS3H1HeaderFields",
// we have at least 5 pseudo-header fields sent, and
// that ensures that buffer limit exceeds.
})
if err != nil {
t.Fatalf("Error st.spdy() = %v", err)
}
if got, want := res.spdyRstErrCode, spdy.InternalError; got != want {
t.Errorf("res.spdyRstErrCode: %v; want %v", got, want)
}
}
// TestS3H1InvalidMethod tests that server rejects invalid method with
// 501.
func TestS3H1InvalidMethod(t *testing.T) {
st := newServerTesterTLS([]string{"--npn-list=spdy/3.1"}, t, func(w http.ResponseWriter, r *http.Request) {
t.Errorf("server should not forward this request")
})
defer st.Close()
res, err := st.spdy(requestParam{
name: "TestS3H1InvalidMethod",
method: "get",
})
if err != nil {
t.Fatalf("Error st.spdy() = %v", err)
}
if got, want := res.status, 501; got != want {
t.Errorf("status: %v; want %v", got, want)
}
}
// TestS3H1BadHost tests that server rejects request including bad
// character in :host header field.
func TestS3H1BadHost(t *testing.T) {
st := newServerTesterTLS([]string{"--npn-list=spdy/3.1"}, t, func(w http.ResponseWriter, r *http.Request) {
t.Errorf("server should not forward this request")
})
defer st.Close()
res, err := st.spdy(requestParam{
name: "TestS3H1BadHost",
authority: `foo\bar`,
})
if err != nil {
t.Fatalf("Error st.spdy() = %v", err)
}
if got, want := res.status, 400; got != want {
t.Errorf("status: %v; want %v", got, want)
}
}
// TestS3H1BadScheme tests that server rejects request including bad
// character in :scheme header field.
func TestS3H1BadScheme(t *testing.T) {
st := newServerTesterTLS([]string{"--npn-list=spdy/3.1"}, t, func(w http.ResponseWriter, r *http.Request) {
t.Errorf("server should not forward this request")
})
defer st.Close()
res, err := st.spdy(requestParam{
name: "TestS3H1BadScheme",
scheme: `http*`,
})
if err != nil {
t.Fatalf("Error st.spdy() = %v", err)
}
if got, want := res.status, 400; got != want {
t.Errorf("status: %v; want %v", got, want)
}
}
// TestS3H1ReqPhaseSetHeader tests mruby request phase hook
// modifies request header fields.
func TestS3H1ReqPhaseSetHeader(t *testing.T) {
st := newServerTesterTLS([]string{"--npn-list=spdy/3.1", "--mruby-file=" + testDir + "/req-set-header.rb"}, t, func(w http.ResponseWriter, r *http.Request) {
if got, want := r.Header.Get("User-Agent"), "mruby"; got != want {
t.Errorf("User-Agent = %v; want %v", got, want)
}
})
defer st.Close()
res, err := st.spdy(requestParam{
name: "TestS3H1ReqPhaseSetHeader",
})
if err != nil {
t.Fatalf("Error st.spdy() = %v", err)
}
if got, want := res.status, 200; got != want {
t.Errorf("status = %v; want %v", got, want)
}
}
// TestS3H1ReqPhaseReturn tests mruby request phase hook returns
// custom response.
func TestS3H1ReqPhaseReturn(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.Fatalf("request should not be forwarded")
})
defer st.Close()
res, err := st.spdy(requestParam{
name: "TestS3H1ReqPhaseReturn",
})
if err != nil {
t.Fatalf("Error st.spdy() = %v", err)
}
if got, want := res.status, 404; got != want {
t.Errorf("status = %v; want %v", got, want)
}
hdtests := []struct {
k, v string
}{
{"content-length", "20"},
{"from", "mruby"},
}
for _, tt := range hdtests {
if got, want := res.header.Get(tt.k), tt.v; got != want {
t.Errorf("%v = %v; want %v", tt.k, got, want)
}
}
if got, want := string(res.body), "Hello World from req"; got != want {
t.Errorf("body = %v; want %v", got, want)
}
}
// TestS3H1RespPhaseSetHeader tests mruby response phase hook modifies
// response header fields.
func TestS3H1RespPhaseSetHeader(t *testing.T) {
st := newServerTesterTLS([]string{"--npn-list=spdy/3.1", "--mruby-file=" + testDir + "/resp-set-header.rb"}, t, noopHandler)
defer st.Close()
res, err := st.spdy(requestParam{
name: "TestS3H1RespPhaseSetHeader",
})
if err != nil {
t.Fatalf("Error st.spdy() = %v", err)
}
if got, want := res.status, 200; got != want {
t.Errorf("status = %v; want %v", got, want)
}
if got, want := res.header.Get("alpha"), "bravo"; got != want {
t.Errorf("alpha = %v; want %v", got, want)
}
}
// TestS3H1RespPhaseReturn tests mruby response phase hook returns
// custom response.
func TestS3H1RespPhaseReturn(t *testing.T) {
st := newServerTesterTLS([]string{"--npn-list=spdy/3.1", "--mruby-file=" + testDir + "/resp-return.rb"}, t, noopHandler)
defer st.Close()
res, err := st.spdy(requestParam{
name: "TestS3H1RespPhaseReturn",
})
if err != nil {
t.Fatalf("Error st.spdy() = %v", err)
}
if got, want := res.status, 404; got != want {
t.Errorf("status = %v; want %v", got, want)
}
hdtests := []struct {
k, v string
}{
{"content-length", "21"},
{"from", "mruby"},
}
for _, tt := range hdtests {
if got, want := res.header.Get(tt.k), tt.v; got != want {
t.Errorf("%v = %v; want %v", tt.k, got, want)
}
}
if got, want := string(res.body), "Hello World from resp"; got != want {
t.Errorf("body = %v; want %v", got, want)
}
}
// // 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()
// 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.
func TestS3H2ReqPhaseReturn(t *testing.T) {
st := newServerTesterTLS([]string{"--npn-list=spdy/3.1", "--http2-bridge", "--mruby-file=" + testDir + "/req-return.rb"}, t, func(w http.ResponseWriter, r *http.Request) {
t.Fatalf("request should not be forwarded")
})
defer st.Close()
res, err := st.spdy(requestParam{
name: "TestS3H2ReqPhaseReturn",
})
if err != nil {
t.Fatalf("Error st.spdy() = %v", err)
}
if got, want := res.status, 404; got != want {
t.Errorf("status = %v; want %v", got, want)
}
hdtests := []struct {
k, v string
}{
{"content-length", "20"},
{"from", "mruby"},
}
for _, tt := range hdtests {
if got, want := res.header.Get(tt.k), tt.v; got != want {
t.Errorf("%v = %v; want %v", tt.k, got, want)
}
}
if got, want := string(res.body), "Hello World from req"; got != want {
t.Errorf("body = %v; want %v", got, want)
}
}
// TestS3H2RespPhaseReturn tests mruby response phase hook returns
// custom response.
func TestS3H2RespPhaseReturn(t *testing.T) {
st := newServerTesterTLS([]string{"--npn-list=spdy/3.1", "--http2-bridge", "--mruby-file=" + testDir + "/resp-return.rb"}, t, noopHandler)
defer st.Close()
res, err := st.spdy(requestParam{
name: "TestS3H2RespPhaseReturn",
})
if err != nil {
t.Fatalf("Error st.spdy() = %v", err)
}
if got, want := res.status, 404; got != want {
t.Errorf("status = %v; want %v", got, want)
}
hdtests := []struct {
k, v string
}{
{"content-length", "21"},
{"from", "mruby"},
}
for _, tt := range hdtests {
if got, want := res.header.Get(tt.k), tt.v; got != want {
t.Errorf("%v = %v; want %v", tt.k, got, want)
}
}
if got, want := string(res.body), "Hello World from resp"; got != want {
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)
}
}

View File

@@ -101,7 +101,7 @@ func newServerTesterInternal(src_args []string, t *testing.T, handler http.Handl
args := []string{}
var backendTLS, dns, externalDNS, acceptProxyProtocol, redirectIfNotTLS bool
var backendTLS, dns, externalDNS, acceptProxyProtocol, redirectIfNotTLS, affinityCookie, alpnH1 bool
for _, k := range src_args {
switch k {
@@ -116,6 +116,10 @@ func newServerTesterInternal(src_args []string, t *testing.T, handler http.Handl
acceptProxyProtocol = true
case "--redirect-if-not-tls":
redirectIfNotTLS = true
case "--affinity-cookie":
affinityCookie = true
case "--alpn-h1":
alpnH1 = true
default:
args = append(args, k)
}
@@ -153,8 +157,8 @@ func newServerTesterInternal(src_args []string, t *testing.T, handler http.Handl
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:])
// We use awesome service nip.io.
b += fmt.Sprintf("%v.nip.io,%v;", backendURL.Host[:sep], backendURL.Host[sep+1:])
}
if backendTLS {
@@ -168,6 +172,10 @@ func newServerTesterInternal(src_args []string, t *testing.T, handler http.Handl
b += ";redirect-if-not-tls"
}
if affinityCookie {
b += ";affinity=cookie;affinity-cookie-name=affinity;affinity-cookie-path=/foo/bar"
}
noTLS := ";no-tls"
if frontendTLS {
noTLS = ""
@@ -218,7 +226,11 @@ func newServerTesterInternal(src_args []string, t *testing.T, handler http.Handl
tlsConfig = clientConfig
}
tlsConfig.InsecureSkipVerify = true
tlsConfig.NextProtos = []string{"h2", "spdy/3.1"}
if alpnH1 {
tlsConfig.NextProtos = []string{"http/1.1"}
} else {
tlsConfig.NextProtos = []string{"h2", "spdy/3.1"}
}
conn, err = tls.Dial("tcp", authority, tlsConfig)
} else {
conn, err = net.Dial("tcp", authority)
@@ -266,7 +278,7 @@ func (st *serverTester) Close() {
done := make(chan struct{})
go func() {
st.cmd.Wait()
done <- struct{}{}
close(done)
}()
st.cmd.Process.Signal(syscall.SIGQUIT)
@@ -769,7 +781,7 @@ type serverResponse struct {
connErr bool // true if HTTP/2 connection error
spdyGoAwayErrCode spdy.GoAwayStatus // status code received in SPDY RST_STREAM
spdyRstErrCode spdy.RstStreamStatus // status code received in SPDY GOAWAY
connClose bool // Conection: close is included in response header in HTTP/1 test
connClose bool // Connection: close is included in response header in HTTP/1 test
reqHeader http.Header // http request header, currently only sotres pushed request header
pushResponse []*serverResponse // pushed response
}

View File

@@ -44,6 +44,10 @@ set_target_properties(nghttp2 PROPERTIES
VERSION ${LT_VERSION} SOVERSION ${LT_SOVERSION}
C_VISIBILITY_PRESET hidden
)
target_include_directories(nghttp2 INTERFACE
"${CMAKE_CURRENT_BINARY_DIR}/includes"
"${CMAKE_CURRENT_SOURCE_DIR}/includes"
)
if(HAVE_CUNIT)
# Static library (for unittests because of symbol visibility)

View File

@@ -62,7 +62,7 @@ AR := lib
#LD := xilink
#AR := xilib
RC := rc
CFLAGS := -I./includes -Dssize_t=long -D_U_=""
CFLAGS := -I./includes -Dssize_t=long
CFLAGS_R := -nologo -MD -W3 -Z7 -DBUILDING_NGHTTP2
CFLAGS_D := -nologo -MDd -W3 -Z7 -DBUILDING_NGHTTP2 \

View File

@@ -387,6 +387,11 @@ typedef enum {
* Indicates that a processing was canceled.
*/
NGHTTP2_ERR_CANCEL = -535,
/**
* When a local endpoint expects to receive SETTINGS frame, it
* receives an other type of frame.
*/
NGHTTP2_ERR_SETTINGS_EXPECTED = -536,
/**
* The errors < :enum:`NGHTTP2_ERR_FATAL` mean that the library is
* under unexpected condition and processing was terminated (e.g.,
@@ -469,6 +474,15 @@ NGHTTP2_EXTERN void nghttp2_rcbuf_decref(nghttp2_rcbuf *rcbuf);
*/
NGHTTP2_EXTERN nghttp2_vec nghttp2_rcbuf_get_buf(nghttp2_rcbuf *rcbuf);
/**
* @function
*
* Returns nonzero if the underlying buffer is statically allocated,
* and 0 otherwise. This can be useful for language bindings that wish
* to avoid creating duplicate strings for these buffers.
*/
NGHTTP2_EXTERN int nghttp2_rcbuf_is_static(const nghttp2_rcbuf *rcbuf);
/**
* @enum
*
@@ -1741,11 +1755,12 @@ typedef int (*nghttp2_on_header_callback2)(nghttp2_session *session,
* The parameter and behaviour are similar to
* :type:`nghttp2_on_header_callback`. The difference is that this
* callback is only invoked when a invalid header name/value pair is
* received which is silently ignored if this callback is not set.
* Only invalid regular header field are passed to this callback. In
* other words, invalid pseudo header field is not passed to this
* callback. Also header fields which includes upper cased latter are
* also treated as error without passing them to this callback.
* received which is treated as stream error if this callback is not
* set. Only invalid regular header field are passed to this
* callback. In other words, invalid pseudo header field is not
* passed to this callback. Also header fields which includes upper
* cased latter are also treated as error without passing them to this
* callback.
*
* This callback is only considered if HTTP messaging validation is
* turned on (which is on by default, see
@@ -1754,10 +1769,13 @@ typedef int (*nghttp2_on_header_callback2)(nghttp2_session *session,
* With this callback, application inspects the incoming invalid
* field, and it also can reset stream from this callback by returning
* :enum:`NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE`. By default, the
* error code is :enum:`NGHTTP2_INTERNAL_ERROR`. To change the error
* error code is :enum:`NGHTTP2_PROTOCOL_ERROR`. To change the error
* code, call `nghttp2_submit_rst_stream()` with the error code of
* choice in addition to returning
* :enum:`NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE`.
*
* If 0 is returned, the header field is ignored, and the stream is
* not reset.
*/
typedef int (*nghttp2_on_invalid_header_callback)(
nghttp2_session *session, const nghttp2_frame *frame, const uint8_t *name,
@@ -1974,6 +1992,9 @@ typedef ssize_t (*nghttp2_pack_extension_callback)(nghttp2_session *session,
* of length |len|. |len| does not include the sentinel NULL
* character.
*
* This function is deprecated. The new application should use
* :type:`nghttp2_error_callback2`.
*
* The format of error message may change between nghttp2 library
* versions. The application should not depend on the particular
* format.
@@ -1990,6 +2011,33 @@ typedef ssize_t (*nghttp2_pack_extension_callback)(nghttp2_session *session,
typedef int (*nghttp2_error_callback)(nghttp2_session *session, const char *msg,
size_t len, void *user_data);
/**
* @functypedef
*
* Callback function invoked when library provides the error code, and
* message. This callback is solely for debugging purpose.
* |lib_error_code| is one of error code defined in
* :enum:`nghttp2_error`. The |msg| is typically NULL-terminated
* string of length |len|, and intended for human consumption. |len|
* does not include the sentinel NULL character.
*
* The format of error message may change between nghttp2 library
* versions. The application should not depend on the particular
* format.
*
* Normally, application should return 0 from this callback. If fatal
* error occurred while doing something in this callback, application
* should return :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`. In this case,
* library will return immediately with return value
* :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`. Currently, if nonzero value
* is returned from this callback, they are treated as
* :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`, but application should not
* rely on this details.
*/
typedef int (*nghttp2_error_callback2)(nghttp2_session *session,
int lib_error_code, const char *msg,
size_t len, void *user_data);
struct nghttp2_session_callbacks;
/**
@@ -2254,10 +2302,30 @@ nghttp2_session_callbacks_set_on_extension_chunk_recv_callback(
*
* Sets callback function invoked when library tells error message to
* the application.
*
* This function is deprecated. The new application should use
* `nghttp2_session_callbacks_set_error_callback2()`.
*
* If both :type:`nghttp2_error_callback` and
* :type:`nghttp2_error_callback2` are set, the latter takes
* precedence.
*/
NGHTTP2_EXTERN void nghttp2_session_callbacks_set_error_callback(
nghttp2_session_callbacks *cbs, nghttp2_error_callback error_callback);
/**
* @function
*
* Sets callback function invoked when library tells error code, and
* message to the application.
*
* If both :type:`nghttp2_error_callback` and
* :type:`nghttp2_error_callback2` are set, the latter takes
* precedence.
*/
NGHTTP2_EXTERN void nghttp2_session_callbacks_set_error_callback2(
nghttp2_session_callbacks *cbs, nghttp2_error_callback2 error_callback2);
/**
* @functypedef
*
@@ -2448,7 +2516,10 @@ nghttp2_option_set_no_recv_client_magic(nghttp2_option *option, int val);
* <https://tools.ietf.org/html/rfc7540#section-8>`_. See
* :ref:`http-messaging` section for details. For those applications
* who use nghttp2 library as non-HTTP use, give nonzero to |val| to
* disable this enforcement.
* disable this enforcement. Please note that disabling this feature
* does not change the fundamental client and server model of HTTP.
* That is, even if the validation is disabled, only client can send
* requests.
*/
NGHTTP2_EXTERN void nghttp2_option_set_no_http_messaging(nghttp2_option *option,
int val);
@@ -3010,6 +3081,16 @@ NGHTTP2_EXTERN int
nghttp2_session_set_stream_user_data(nghttp2_session *session,
int32_t stream_id, void *stream_user_data);
/**
* @function
*
* Sets |user_data| to |session|, overwriting the existing user data
* specified in `nghttp2_session_client_new()`, or
* `nghttp2_session_server_new()`.
*/
NGHTTP2_EXTERN void nghttp2_session_set_user_data(nghttp2_session *session,
void *user_data);
/**
* @function
*
@@ -3802,9 +3883,8 @@ nghttp2_submit_response(nghttp2_session *session, int32_t stream_id,
* Submits trailer fields HEADERS against the stream |stream_id|.
*
* The |nva| is an array of name/value pair :type:`nghttp2_nv` with
* |nvlen| elements. The application is responsible not to include
* pseudo-header fields (header field whose name starts with ":") in
* |nva|.
* |nvlen| elements. The application must not include pseudo-header
* fields (headers whose names starts with ":") in |nva|.
*
* This function creates copies of all name/value pairs in |nva|. It
* also lower-cases all names in |nva|. The order of elements in
@@ -4687,8 +4767,8 @@ nghttp2_hd_deflate_change_table_size(nghttp2_hd_deflater *deflater,
*
* After this function returns, it is safe to delete the |nva|.
*
* This function returns 0 if it succeeds, or one of the following
* negative error codes:
* This function returns the number of bytes written to |buf| if it
* succeeds, or one of the following negative error codes:
*
* :enum:`NGHTTP2_ERR_NOMEM`
* Out of memory.
@@ -4719,8 +4799,8 @@ NGHTTP2_EXTERN ssize_t nghttp2_hd_deflate_hd(nghttp2_hd_deflater *deflater,
*
* After this function returns, it is safe to delete the |nva|.
*
* This function returns 0 if it succeeds, or one of the following
* negative error codes:
* This function returns the number of bytes written to |vec| if it
* succeeds, or one of the following negative error codes:
*
* :enum:`NGHTTP2_ERR_NOMEM`
* Out of memory.

View File

@@ -398,7 +398,7 @@ int nghttp2_bufs_advance(nghttp2_bufs *bufs);
void nghttp2_bufs_seek_last_present(nghttp2_bufs *bufs);
/*
* Returns nonzero if bufs->cur->next is not emtpy.
* Returns nonzero if bufs->cur->next is not empty.
*/
int nghttp2_bufs_next_present(nghttp2_bufs *bufs);

View File

@@ -168,3 +168,8 @@ void nghttp2_session_callbacks_set_error_callback(
nghttp2_session_callbacks *cbs, nghttp2_error_callback error_callback) {
cbs->error_callback = error_callback;
}
void nghttp2_session_callbacks_set_error_callback2(
nghttp2_session_callbacks *cbs, nghttp2_error_callback2 error_callback2) {
cbs->error_callback2 = error_callback2;
}

View File

@@ -119,6 +119,7 @@ struct nghttp2_session_callbacks {
nghttp2_unpack_extension_callback unpack_extension_callback;
nghttp2_on_extension_chunk_recv_callback on_extension_chunk_recv_callback;
nghttp2_error_callback error_callback;
nghttp2_error_callback2 error_callback2;
};
#endif /* NGHTTP2_CALLBACKS_H */

View File

@@ -53,6 +53,8 @@ void nghttp2_set_debug_vprintf_callback(
#else /* !DEBUGBUILD */
void nghttp2_set_debug_vprintf_callback(
nghttp2_debug_vprintf_callback debug_vprintf_callback _U_) {}
nghttp2_debug_vprintf_callback debug_vprintf_callback) {
(void)debug_vprintf_callback;
}
#endif /* !DEBUGBUILD */

View File

@@ -87,7 +87,7 @@ void nghttp2_frame_priority_init(nghttp2_priority *frame, int32_t stream_id,
frame->pri_spec = *pri_spec;
}
void nghttp2_frame_priority_free(nghttp2_priority *frame _U_) {}
void nghttp2_frame_priority_free(nghttp2_priority *frame) { (void)frame; }
void nghttp2_frame_rst_stream_init(nghttp2_rst_stream *frame, int32_t stream_id,
uint32_t error_code) {
@@ -96,7 +96,7 @@ void nghttp2_frame_rst_stream_init(nghttp2_rst_stream *frame, int32_t stream_id,
frame->error_code = error_code;
}
void nghttp2_frame_rst_stream_free(nghttp2_rst_stream *frame _U_) {}
void nghttp2_frame_rst_stream_free(nghttp2_rst_stream *frame) { (void)frame; }
void nghttp2_frame_settings_init(nghttp2_settings *frame, uint8_t flags,
nghttp2_settings_entry *iv, size_t niv) {
@@ -137,7 +137,7 @@ void nghttp2_frame_ping_init(nghttp2_ping *frame, uint8_t flags,
}
}
void nghttp2_frame_ping_free(nghttp2_ping *frame _U_) {}
void nghttp2_frame_ping_free(nghttp2_ping *frame) { (void)frame; }
void nghttp2_frame_goaway_init(nghttp2_goaway *frame, int32_t last_stream_id,
uint32_t error_code, uint8_t *opaque_data,
@@ -163,7 +163,9 @@ void nghttp2_frame_window_update_init(nghttp2_window_update *frame,
frame->reserved = 0;
}
void nghttp2_frame_window_update_free(nghttp2_window_update *frame _U_) {}
void nghttp2_frame_window_update_free(nghttp2_window_update *frame) {
(void)frame;
}
size_t nghttp2_frame_trail_padlen(nghttp2_frame *frame, size_t padlen) {
/* We have iframe->padlen == 0, but iframe->frame.hd.flags may have
@@ -183,7 +185,7 @@ void nghttp2_frame_data_init(nghttp2_data *frame, uint8_t flags,
frame->padlen = 0;
}
void nghttp2_frame_data_free(nghttp2_data *frame _U_) {}
void nghttp2_frame_data_free(nghttp2_data *frame) { (void)frame; }
void nghttp2_frame_extension_init(nghttp2_extension *frame, uint8_t type,
uint8_t flags, int32_t stream_id,
@@ -192,7 +194,7 @@ void nghttp2_frame_extension_init(nghttp2_extension *frame, uint8_t type,
frame->payload = payload;
}
void nghttp2_frame_extension_free(nghttp2_extension *frame _U_) {}
void nghttp2_frame_extension_free(nghttp2_extension *frame) { (void)frame; }
void nghttp2_frame_altsvc_init(nghttp2_extension *frame, int32_t stream_id,
uint8_t *origin, size_t origin_len,
@@ -346,9 +348,7 @@ void nghttp2_frame_pack_priority_spec(uint8_t *buf,
}
void nghttp2_frame_unpack_priority_spec(nghttp2_priority_spec *pri_spec,
uint8_t flags _U_,
const uint8_t *payload,
size_t payloadlen _U_) {
const uint8_t *payload) {
int32_t dep_stream_id;
uint8_t exclusive;
int32_t weight;
@@ -361,11 +361,9 @@ void nghttp2_frame_unpack_priority_spec(nghttp2_priority_spec *pri_spec,
}
int nghttp2_frame_unpack_headers_payload(nghttp2_headers *frame,
const uint8_t *payload,
size_t payloadlen) {
const uint8_t *payload) {
if (frame->hd.flags & NGHTTP2_FLAG_PRIORITY) {
nghttp2_frame_unpack_priority_spec(&frame->pri_spec, frame->hd.flags,
payload, payloadlen);
nghttp2_frame_unpack_priority_spec(&frame->pri_spec, payload);
} else {
nghttp2_priority_spec_default_init(&frame->pri_spec);
}
@@ -397,10 +395,8 @@ int nghttp2_frame_pack_priority(nghttp2_bufs *bufs, nghttp2_priority *frame) {
}
void nghttp2_frame_unpack_priority_payload(nghttp2_priority *frame,
const uint8_t *payload,
size_t payloadlen) {
nghttp2_frame_unpack_priority_spec(&frame->pri_spec, frame->hd.flags, payload,
payloadlen);
const uint8_t *payload) {
nghttp2_frame_unpack_priority_spec(&frame->pri_spec, payload);
}
int nghttp2_frame_pack_rst_stream(nghttp2_bufs *bufs,
@@ -424,8 +420,7 @@ int nghttp2_frame_pack_rst_stream(nghttp2_bufs *bufs,
}
void nghttp2_frame_unpack_rst_stream_payload(nghttp2_rst_stream *frame,
const uint8_t *payload,
size_t payloadlen _U_) {
const uint8_t *payload) {
frame->error_code = nghttp2_get_uint32(payload);
}
@@ -540,8 +535,7 @@ int nghttp2_frame_pack_push_promise(nghttp2_bufs *bufs,
}
int nghttp2_frame_unpack_push_promise_payload(nghttp2_push_promise *frame,
const uint8_t *payload,
size_t payloadlen _U_) {
const uint8_t *payload) {
frame->promised_stream_id =
nghttp2_get_uint32(payload) & NGHTTP2_STREAM_ID_MASK;
frame->nva = NULL;
@@ -569,8 +563,7 @@ int nghttp2_frame_pack_ping(nghttp2_bufs *bufs, nghttp2_ping *frame) {
}
void nghttp2_frame_unpack_ping_payload(nghttp2_ping *frame,
const uint8_t *payload,
size_t payloadlen _U_) {
const uint8_t *payload) {
memcpy(frame->opaque_data, payload, sizeof(frame->opaque_data));
}
@@ -607,7 +600,6 @@ int nghttp2_frame_pack_goaway(nghttp2_bufs *bufs, nghttp2_goaway *frame) {
void nghttp2_frame_unpack_goaway_payload(nghttp2_goaway *frame,
const uint8_t *payload,
size_t payloadlen _U_,
uint8_t *var_gift_payload,
size_t var_gift_payloadlen) {
frame->last_stream_id = nghttp2_get_uint32(payload) & NGHTTP2_STREAM_ID_MASK;
@@ -643,8 +635,8 @@ int nghttp2_frame_unpack_goaway_payload2(nghttp2_goaway *frame,
memcpy(var_gift_payload, payload + 8, var_gift_payloadlen);
}
nghttp2_frame_unpack_goaway_payload(frame, payload, payloadlen,
var_gift_payload, var_gift_payloadlen);
nghttp2_frame_unpack_goaway_payload(frame, payload, var_gift_payload,
var_gift_payloadlen);
return 0;
}
@@ -670,8 +662,7 @@ int nghttp2_frame_pack_window_update(nghttp2_bufs *bufs,
}
void nghttp2_frame_unpack_window_update_payload(nghttp2_window_update *frame,
const uint8_t *payload,
size_t payloadlen _U_) {
const uint8_t *payload) {
frame->window_size_increment =
nghttp2_get_uint32(payload) & NGHTTP2_WINDOW_SIZE_INCREMENT_MASK;
}
@@ -681,6 +672,9 @@ int nghttp2_frame_pack_altsvc(nghttp2_bufs *bufs, nghttp2_extension *frame) {
nghttp2_buf *buf;
nghttp2_ext_altsvc *altsvc;
/* This is required with --disable-assert. */
(void)rv;
altsvc = frame->payload;
buf = &bufs->head->buf;

View File

@@ -70,7 +70,9 @@
#define NGHTTP2_MAX_PADLEN 256
/* Union of extension frame payload */
typedef union { nghttp2_ext_altsvc altsvc; } 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);
@@ -104,8 +106,7 @@ void nghttp2_frame_pack_priority_spec(uint8_t *buf,
* assumes the |payload| contains whole priority specification.
*/
void nghttp2_frame_unpack_priority_spec(nghttp2_priority_spec *pri_spec,
uint8_t flags, const uint8_t *payload,
size_t payloadlen);
const uint8_t *payload);
/*
* Returns the offset from the HEADERS frame payload where the
@@ -144,8 +145,7 @@ int nghttp2_frame_pack_headers(nghttp2_bufs *bufs, nghttp2_headers *frame,
* This function always succeeds and returns 0.
*/
int nghttp2_frame_unpack_headers_payload(nghttp2_headers *frame,
const uint8_t *payload,
size_t payloadlen);
const uint8_t *payload);
/*
* Packs PRIORITY frame |frame| in wire format and store it in
@@ -162,8 +162,7 @@ int nghttp2_frame_pack_priority(nghttp2_bufs *bufs, nghttp2_priority *frame);
* Unpacks PRIORITY wire format into |frame|.
*/
void nghttp2_frame_unpack_priority_payload(nghttp2_priority *frame,
const uint8_t *payload,
size_t payloadlen);
const uint8_t *payload);
/*
* Packs RST_STREAM frame |frame| in wire frame format and store it in
@@ -181,8 +180,7 @@ int nghttp2_frame_pack_rst_stream(nghttp2_bufs *bufs,
* Unpacks RST_STREAM frame byte sequence into |frame|.
*/
void nghttp2_frame_unpack_rst_stream_payload(nghttp2_rst_stream *frame,
const uint8_t *payload,
size_t payloadlen);
const uint8_t *payload);
/*
* Packs SETTINGS frame |frame| in wire format and store it in
@@ -273,8 +271,7 @@ int nghttp2_frame_pack_push_promise(nghttp2_bufs *bufs,
* TODO END_HEADERS flag is not set
*/
int nghttp2_frame_unpack_push_promise_payload(nghttp2_push_promise *frame,
const uint8_t *payload,
size_t payloadlen);
const uint8_t *payload);
/*
* Packs PING frame |frame| in wire format and store it in
@@ -291,8 +288,7 @@ int nghttp2_frame_pack_ping(nghttp2_bufs *bufs, nghttp2_ping *frame);
* Unpacks PING wire format into |frame|.
*/
void nghttp2_frame_unpack_ping_payload(nghttp2_ping *frame,
const uint8_t *payload,
size_t payloadlen);
const uint8_t *payload);
/*
* Packs GOAWAY frame |frame| in wire format and store it in |bufs|.
@@ -321,7 +317,6 @@ int nghttp2_frame_pack_goaway(nghttp2_bufs *bufs, nghttp2_goaway *frame);
*/
void nghttp2_frame_unpack_goaway_payload(nghttp2_goaway *frame,
const uint8_t *payload,
size_t payloadlen,
uint8_t *var_gift_payload,
size_t var_gift_payloadlen);
@@ -356,8 +351,7 @@ int nghttp2_frame_pack_window_update(nghttp2_bufs *bufs,
* Unpacks WINDOW_UPDATE frame byte sequence into |frame|.
*/
void nghttp2_frame_unpack_window_update_payload(nghttp2_window_update *frame,
const uint8_t *payload,
size_t payloadlen);
const uint8_t *payload);
/*
* Packs ALTSVC frame |frame| in wire frame format and store it in

View File

@@ -662,9 +662,9 @@ static int hd_context_init(nghttp2_hd_context *context, nghttp2_mem *mem) {
context->mem = mem;
context->bad = 0;
context->hd_table_bufsize_max = NGHTTP2_HD_DEFAULT_MAX_BUFFER_SIZE;
rv = hd_ringbuf_init(&context->hd_table, context->hd_table_bufsize_max /
NGHTTP2_HD_ENTRY_OVERHEAD,
mem);
rv = hd_ringbuf_init(
&context->hd_table,
context->hd_table_bufsize_max / NGHTTP2_HD_ENTRY_OVERHEAD, mem);
if (rv != 0) {
return rv;
}
@@ -1537,10 +1537,11 @@ ssize_t nghttp2_hd_deflate_hd_vec(nghttp2_hd_deflater *deflater,
return (ssize_t)buflen;
}
size_t nghttp2_hd_deflate_bound(nghttp2_hd_deflater *deflater _U_,
size_t nghttp2_hd_deflate_bound(nghttp2_hd_deflater *deflater,
const nghttp2_nv *nva, size_t nvlen) {
size_t n = 0;
size_t i;
(void)deflater;
/* Possible Maximum Header Table Size Change. Encoding (1u << 31) -
1 using 4 bit prefix requires 6 bytes. We may emit this at most

View File

@@ -211,7 +211,9 @@ typedef struct {
#define HD_MAP_SIZE 128
typedef struct { nghttp2_hd_entry *table[HD_MAP_SIZE]; } nghttp2_hd_map;
typedef struct {
nghttp2_hd_entry *table[HD_MAP_SIZE];
} nghttp2_hd_map;
struct nghttp2_hd_deflater {
nghttp2_hd_context ctx;
@@ -313,7 +315,7 @@ void nghttp2_hd_deflate_free(nghttp2_hd_deflater *deflater);
*
* This function expands |bufs| as necessary to store the result. If
* buffers is full and the process still requires more space, this
* funtion fails and returns NGHTTP2_ERR_HEADER_COMP.
* function fails and returns NGHTTP2_ERR_HEADER_COMP.
*
* After this function returns, it is safe to delete the |nva|.
*

View File

@@ -322,6 +322,9 @@ const char *nghttp2_strerror(int error_code) {
return "Internal error";
case NGHTTP2_ERR_CANCEL:
return "Cancel";
case NGHTTP2_ERR_SETTINGS_EXPECTED:
return "When a local endpoint expects to receive SETTINGS frame, it "
"receives an other type of frame";
case NGHTTP2_ERR_NOMEM:
return "Out of memory";
case NGHTTP2_ERR_CALLBACK_FAILURE:

View File

@@ -521,8 +521,10 @@ int nghttp2_http_on_response_headers(nghttp2_stream *stream) {
return 0;
}
int nghttp2_http_on_trailer_headers(nghttp2_stream *stream _U_,
int nghttp2_http_on_trailer_headers(nghttp2_stream *stream,
nghttp2_frame *frame) {
(void)stream;
if ((frame->hd.flags & NGHTTP2_FLAG_END_STREAM) == 0) {
return -1;
}

View File

@@ -24,18 +24,27 @@
*/
#include "nghttp2_mem.h"
static void *default_malloc(size_t size, void *mem_user_data _U_) {
static void *default_malloc(size_t size, void *mem_user_data) {
(void)mem_user_data;
return malloc(size);
}
static void default_free(void *ptr, void *mem_user_data _U_) { free(ptr); }
static void default_free(void *ptr, void *mem_user_data) {
(void)mem_user_data;
free(ptr);
}
static void *default_calloc(size_t nmemb, size_t size, void *mem_user_data) {
(void)mem_user_data;
static void *default_calloc(size_t nmemb, size_t size,
void *mem_user_data _U_) {
return calloc(nmemb, size);
}
static void *default_realloc(void *ptr, size_t size, void *mem_user_data _U_) {
static void *default_realloc(void *ptr, size_t size, void *mem_user_data) {
(void)mem_user_data;
return realloc(ptr, size);
}

View File

@@ -112,7 +112,7 @@ struct nghttp2_outbound_item {
nghttp2_ext_frame_payload ext_frame_payload;
nghttp2_aux_data aux_data;
/* The priority used in priority comparion. Smaller is served
ealier. For PING, SETTINGS and non-DATA frames (excluding
earlier. For PING, SETTINGS and non-DATA frames (excluding
response HEADERS frame) have dedicated cycle value defined above.
For DATA frame, cycle is computed by taking into account of
effective weight and frame payload length previously sent, so

View File

@@ -35,14 +35,16 @@
/* Implementation of priority queue */
typedef struct { size_t index; } nghttp2_pq_entry;
typedef struct {
size_t index;
} nghttp2_pq_entry;
typedef struct {
/* The pointer to the pointer to the item stored */
nghttp2_pq_entry **q;
/* Memory allocator */
nghttp2_mem *mem;
/* The number of items sotred */
/* The number of items stored */
size_t length;
/* The maximum number of items this pq can store. This is
automatically extended when length is reached to this value. */
@@ -71,7 +73,7 @@ void nghttp2_pq_free(nghttp2_pq *pq);
/*
* Adds |item| to the priority queue |pq|.
*
* This function returns 0 if it succeds, or one of the following
* This function returns 0 if it succeeds, or one of the following
* negative error codes:
*
* NGHTTP2_ERR_NOMEM

View File

@@ -36,7 +36,9 @@ typedef struct nghttp2_queue_cell {
struct nghttp2_queue_cell *next;
} nghttp2_queue_cell;
typedef struct { nghttp2_queue_cell *front, *back; } nghttp2_queue;
typedef struct {
nghttp2_queue_cell *front, *back;
} nghttp2_queue;
void nghttp2_queue_init(nghttp2_queue *queue);
void nghttp2_queue_free(nghttp2_queue *queue);

View File

@@ -96,3 +96,7 @@ nghttp2_vec nghttp2_rcbuf_get_buf(nghttp2_rcbuf *rcbuf) {
nghttp2_vec res = {rcbuf->base, rcbuf->len};
return res;
}
int nghttp2_rcbuf_is_static(const nghttp2_rcbuf *rcbuf) {
return rcbuf->ref == -1;
}

View File

@@ -148,14 +148,16 @@ static int check_ext_type_set(const uint8_t *ext_types, uint8_t type) {
}
static int session_call_error_callback(nghttp2_session *session,
const char *fmt, ...) {
int lib_error_code, const char *fmt,
...) {
size_t bufsize;
va_list ap;
char *buf;
int rv;
nghttp2_mem *mem;
if (!session->callbacks.error_callback) {
if (!session->callbacks.error_callback &&
!session->callbacks.error_callback2) {
return 0;
}
@@ -189,8 +191,13 @@ static int session_call_error_callback(nghttp2_session *session,
return 0;
}
rv = session->callbacks.error_callback(session, buf, (size_t)rv,
session->user_data);
if (session->callbacks.error_callback2) {
rv = session->callbacks.error_callback2(session, lib_error_code, buf,
(size_t)rv, session->user_data);
} else {
rv = session->callbacks.error_callback(session, buf, (size_t)rv,
session->user_data);
}
nghttp2_mem_free(mem, buf);
@@ -541,9 +548,8 @@ static int session_new(nghttp2_session **session_ptr,
if (nghttp2_enable_strict_preface) {
nghttp2_inbound_frame *iframe = &(*session_ptr)->iframe;
if (server &&
((*session_ptr)->opt_flags & NGHTTP2_OPTMASK_NO_RECV_CLIENT_MAGIC) ==
0) {
if (server && ((*session_ptr)->opt_flags &
NGHTTP2_OPTMASK_NO_RECV_CLIENT_MAGIC) == 0) {
iframe->state = NGHTTP2_IB_READ_CLIENT_MAGIC;
iframe->payloadleft = NGHTTP2_CLIENT_MAGIC_LEN;
} else {
@@ -682,6 +688,7 @@ static int inflight_settings_new(nghttp2_inflight_settings **settings_ptr,
if (niv > 0) {
(*settings_ptr)->iv = nghttp2_frame_iv_copy(iv, niv, mem);
if (!(*settings_ptr)->iv) {
nghttp2_mem_free(mem, *settings_ptr);
return NGHTTP2_ERR_NOMEM;
}
} else {
@@ -1523,13 +1530,14 @@ static int session_predicate_response_headers_send(nghttp2_session *session,
if (nghttp2_session_is_my_stream_id(session, stream->stream_id)) {
return NGHTTP2_ERR_INVALID_STREAM_ID;
}
if (stream->state == NGHTTP2_STREAM_OPENING) {
switch (stream->state) {
case NGHTTP2_STREAM_OPENING:
return 0;
}
if (stream->state == NGHTTP2_STREAM_CLOSING) {
case NGHTTP2_STREAM_CLOSING:
return NGHTTP2_ERR_STREAM_CLOSING;
default:
return NGHTTP2_ERR_INVALID_STREAM_STATE;
}
return NGHTTP2_ERR_INVALID_STREAM_STATE;
}
/*
@@ -1572,9 +1580,6 @@ session_predicate_push_response_headers_send(nghttp2_session *session,
if (stream->state != NGHTTP2_STREAM_RESERVED) {
return NGHTTP2_ERR_PROTO;
}
if (stream->state == NGHTTP2_STREAM_CLOSING) {
return NGHTTP2_ERR_STREAM_CLOSING;
}
if (session->goaway_flags & NGHTTP2_GOAWAY_RECV) {
return NGHTTP2_ERR_START_STREAM_NOT_ALLOWED;
}
@@ -1609,19 +1614,18 @@ static int session_predicate_headers_send(nghttp2_session *session,
return rv;
}
assert(stream);
if (nghttp2_session_is_my_stream_id(session, stream->stream_id)) {
if (stream->state == NGHTTP2_STREAM_CLOSING) {
return NGHTTP2_ERR_STREAM_CLOSING;
}
switch (stream->state) {
case NGHTTP2_STREAM_OPENED:
return 0;
}
if (stream->state == NGHTTP2_STREAM_OPENED) {
return 0;
}
if (stream->state == NGHTTP2_STREAM_CLOSING) {
case NGHTTP2_STREAM_CLOSING:
return NGHTTP2_ERR_STREAM_CLOSING;
default:
if (nghttp2_session_is_my_stream_id(session, stream->stream_id)) {
return 0;
}
return NGHTTP2_ERR_INVALID_STREAM_STATE;
}
return NGHTTP2_ERR_INVALID_STREAM_STATE;
}
/*
@@ -2067,14 +2071,6 @@ static int session_prep_frame(nghttp2_session *session,
/* We don't call nghttp2_session_adjust_closed_stream() here,
since we don't keep closed stream in client side */
estimated_payloadlen = session_estimate_headers_payload(
session, frame->headers.nva, frame->headers.nvlen,
NGHTTP2_PRIORITY_SPECLEN);
if (estimated_payloadlen > session->max_send_header_block_length) {
return NGHTTP2_ERR_FRAME_SIZE_ERROR;
}
rv = session_predicate_request_headers_send(session, item);
if (rv != 0) {
return rv;
@@ -2086,14 +2082,6 @@ static int session_prep_frame(nghttp2_session *session,
} else {
nghttp2_stream *stream;
estimated_payloadlen = session_estimate_headers_payload(
session, frame->headers.nva, frame->headers.nvlen,
NGHTTP2_PRIORITY_SPECLEN);
if (estimated_payloadlen > session->max_send_header_block_length) {
return NGHTTP2_ERR_FRAME_SIZE_ERROR;
}
stream = nghttp2_session_get_stream(session, frame->hd.stream_id);
if (stream && stream->state == NGHTTP2_STREAM_RESERVED) {
@@ -2120,6 +2108,14 @@ static int session_prep_frame(nghttp2_session *session,
}
}
estimated_payloadlen = session_estimate_headers_payload(
session, frame->headers.nva, frame->headers.nvlen,
NGHTTP2_PRIORITY_SPECLEN);
if (estimated_payloadlen > session->max_send_header_block_length) {
return NGHTTP2_ERR_FRAME_SIZE_ERROR;
}
rv = nghttp2_frame_pack_headers(&session->aob.framebufs, &frame->headers,
&session->hd_deflater);
@@ -2189,18 +2185,11 @@ static int session_prep_frame(nghttp2_session *session,
nghttp2_stream *stream;
size_t estimated_payloadlen;
estimated_payloadlen = session_estimate_headers_payload(
session, frame->push_promise.nva, frame->push_promise.nvlen, 0);
if (estimated_payloadlen > session->max_send_header_block_length) {
return NGHTTP2_ERR_FRAME_SIZE_ERROR;
}
/* stream could be NULL if associated stream was already
closed. */
stream = nghttp2_session_get_stream(session, frame->hd.stream_id);
/* predicte should fail if stream is NULL. */
/* predicate should fail if stream is NULL. */
rv = session_predicate_push_promise_send(session, stream);
if (rv != 0) {
return rv;
@@ -2208,6 +2197,13 @@ static int session_prep_frame(nghttp2_session *session,
assert(stream);
estimated_payloadlen = session_estimate_headers_payload(
session, frame->push_promise.nva, frame->push_promise.nvlen, 0);
if (estimated_payloadlen > session->max_send_header_block_length) {
return NGHTTP2_ERR_FRAME_SIZE_ERROR;
}
rv = nghttp2_frame_pack_push_promise(
&session->aob.framebufs, &frame->push_promise, &session->hd_deflater);
if (rv != 0) {
@@ -2229,8 +2225,9 @@ static int session_prep_frame(nghttp2_session *session,
assert(session->obq_flood_counter_ > 0);
--session->obq_flood_counter_;
}
if (session_is_closing(session)) {
/* PING frame is allowed to be sent unless termination GOAWAY is
sent */
if (session->goaway_flags & NGHTTP2_GOAWAY_TERM_ON_SEND) {
return NGHTTP2_ERR_SESSION_CLOSING;
}
nghttp2_frame_pack_ping(&session->aob.framebufs, &frame->ping);
@@ -2421,19 +2418,16 @@ static int session_close_stream_on_goaway(nghttp2_session *session,
nghttp2_stream *stream, *next_stream;
nghttp2_close_stream_on_goaway_arg arg = {session, NULL, last_stream_id,
incoming};
uint32_t error_code;
rv = nghttp2_map_each(&session->streams, find_stream_on_goaway_func, &arg);
assert(rv == 0);
error_code =
session->server && incoming ? NGHTTP2_REFUSED_STREAM : NGHTTP2_CANCEL;
stream = arg.head;
while (stream) {
next_stream = stream->closed_next;
stream->closed_next = NULL;
rv = nghttp2_session_close_stream(session, stream->stream_id, error_code);
rv = nghttp2_session_close_stream(session, stream->stream_id,
NGHTTP2_REFUSED_STREAM);
/* stream may be deleted here */
@@ -3331,7 +3325,7 @@ static int session_call_on_invalid_header(nghttp2_session *session,
session, frame, nv->name->base, nv->name->len, nv->value->base,
nv->value->len, nv->flags, session->user_data);
} else {
return 0;
return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
}
if (rv == NGHTTP2_ERR_PAUSE || rv == NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE) {
@@ -3394,8 +3388,7 @@ static int session_call_unpack_extension_callback(nghttp2_session *session) {
* NGHTTP2_ERR_NOMEM
* Out of memory.
*/
static int session_handle_frame_size_error(nghttp2_session *session,
nghttp2_frame *frame _U_) {
static int session_handle_frame_size_error(nghttp2_session *session) {
/* TODO Currently no callback is called for this error, because we
call this callback before reading any payload */
return nghttp2_session_terminate_session(session, NGHTTP2_FRAME_SIZE_ERROR);
@@ -3422,6 +3415,27 @@ static uint32_t get_error_code_from_lib_error_code(int lib_error_code) {
}
}
/*
* Calls on_invalid_frame_recv_callback if it is set to |session|.
*
* This function returns 0 if it succeeds, or one of the following
* negative error codes:
*
* NGHTTP2_ERR_CALLBACK_FAILURE
* User defined callback function fails.
*/
static int session_call_on_invalid_frame_recv_callback(nghttp2_session *session,
nghttp2_frame *frame,
int lib_error_code) {
if (session->callbacks.on_invalid_frame_recv_callback) {
if (session->callbacks.on_invalid_frame_recv_callback(
session, frame, lib_error_code, session->user_data) != 0) {
return NGHTTP2_ERR_CALLBACK_FAILURE;
}
}
return 0;
}
static int session_handle_invalid_stream2(nghttp2_session *session,
int32_t stream_id,
nghttp2_frame *frame,
@@ -3579,14 +3593,46 @@ static int inflate_header_block(nghttp2_session *session, nghttp2_frame *frame,
if (subject_stream && session_enforce_http_messaging(session)) {
rv = nghttp2_http_on_header(session, subject_stream, frame, &nv,
trailer);
if (rv == NGHTTP2_ERR_IGN_HTTP_HEADER) {
/* Don't overwrite rv here */
int rv2;
rv2 = session_call_on_invalid_header(session, frame, &nv);
if (rv2 == NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE) {
rv = NGHTTP2_ERR_HTTP_HEADER;
} else {
if (rv2 != 0) {
return rv2;
}
/* header is ignored */
DEBUGF("recv: HTTP ignored: type=%u, id=%d, header %.*s: %.*s\n",
frame->hd.type, frame->hd.stream_id, (int)nv.name->len,
nv.name->base, (int)nv.value->len, nv.value->base);
rv2 = session_call_error_callback(
session, NGHTTP2_ERR_HTTP_HEADER,
"Ignoring received invalid HTTP header field: frame type: "
"%u, stream: %d, name: [%.*s], value: [%.*s]",
frame->hd.type, frame->hd.stream_id, (int)nv.name->len,
nv.name->base, (int)nv.value->len, nv.value->base);
if (nghttp2_is_fatal(rv2)) {
return rv2;
}
}
}
if (rv == NGHTTP2_ERR_HTTP_HEADER) {
DEBUGF("recv: HTTP error: type=%u, id=%d, header %.*s: %.*s\n",
frame->hd.type, frame->hd.stream_id, (int)nv.name->len,
nv.name->base, (int)nv.value->len, nv.value->base);
rv = session_call_error_callback(
session, "Invalid HTTP header field was received: frame type: "
"%u, stream: %d, name: [%.*s], value: [%.*s]",
session, NGHTTP2_ERR_HTTP_HEADER,
"Invalid HTTP header field was received: frame type: "
"%u, stream: %d, name: [%.*s], value: [%.*s]",
frame->hd.type, frame->hd.stream_id, (int)nv.name->len,
nv.name->base, (int)nv.value->len, nv.value->base);
@@ -3602,34 +3648,6 @@ static int inflate_header_block(nghttp2_session *session, nghttp2_frame *frame,
}
return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
}
if (rv == NGHTTP2_ERR_IGN_HTTP_HEADER) {
/* Don't overwrite rv here */
int rv2;
rv2 = session_call_on_invalid_header(session, frame, &nv);
/* This handles NGHTTP2_ERR_PAUSE and
NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE as well */
if (rv2 != 0) {
return rv2;
}
/* header is ignored */
DEBUGF("recv: HTTP ignored: type=%u, id=%d, header %.*s: %.*s\n",
frame->hd.type, frame->hd.stream_id, (int)nv.name->len,
nv.name->base, (int)nv.value->len, nv.value->base);
rv2 = session_call_error_callback(
session,
"Ignoring received invalid HTTP header field: frame type: "
"%u, stream: %d, name: [%.*s], value: [%.*s]",
frame->hd.type, frame->hd.stream_id, (int)nv.name->len,
nv.name->base, (int)nv.value->len, nv.value->base);
if (nghttp2_is_fatal(rv2)) {
return rv2;
}
}
}
if (rv == 0) {
rv = session_call_on_header(session, frame, &nv);
@@ -3768,7 +3786,7 @@ int nghttp2_session_on_request_headers_received(nghttp2_session *session,
session, frame, NGHTTP2_ERR_PROTO, "request HEADERS: stream_id == 0");
}
/* If client recieves idle stream from server, it is invalid
/* If client receives idle stream from server, it is invalid
regardless stream ID is even or odd. This is because client is
not expected to receive request from server. */
if (!session->server) {
@@ -3991,8 +4009,7 @@ static int session_process_headers_frame(nghttp2_session *session) {
nghttp2_frame *frame = &iframe->frame;
nghttp2_stream *stream;
rv = nghttp2_frame_unpack_headers_payload(&frame->headers, iframe->sbuf.pos,
nghttp2_buf_len(&iframe->sbuf));
rv = nghttp2_frame_unpack_headers_payload(&frame->headers, iframe->sbuf.pos);
if (rv != 0) {
return nghttp2_session_terminate_session_with_reason(
@@ -4082,8 +4099,7 @@ static int session_process_priority_frame(nghttp2_session *session) {
nghttp2_inbound_frame *iframe = &session->iframe;
nghttp2_frame *frame = &iframe->frame;
nghttp2_frame_unpack_priority_payload(&frame->priority, iframe->sbuf.pos,
nghttp2_buf_len(&iframe->sbuf));
nghttp2_frame_unpack_priority_payload(&frame->priority, iframe->sbuf.pos);
return nghttp2_session_on_priority_received(session, frame);
}
@@ -4124,8 +4140,7 @@ static int session_process_rst_stream_frame(nghttp2_session *session) {
nghttp2_inbound_frame *iframe = &session->iframe;
nghttp2_frame *frame = &iframe->frame;
nghttp2_frame_unpack_rst_stream_payload(&frame->rst_stream, iframe->sbuf.pos,
nghttp2_buf_len(&iframe->sbuf));
nghttp2_frame_unpack_rst_stream_payload(&frame->rst_stream, iframe->sbuf.pos);
return nghttp2_session_on_rst_stream_received(session, frame);
}
@@ -4597,8 +4612,8 @@ static int session_process_push_promise_frame(nghttp2_session *session) {
nghttp2_inbound_frame *iframe = &session->iframe;
nghttp2_frame *frame = &iframe->frame;
rv = nghttp2_frame_unpack_push_promise_payload(
&frame->push_promise, iframe->sbuf.pos, nghttp2_buf_len(&iframe->sbuf));
rv = nghttp2_frame_unpack_push_promise_payload(&frame->push_promise,
iframe->sbuf.pos);
if (rv != 0) {
return nghttp2_session_terminate_session_with_reason(
@@ -4632,8 +4647,7 @@ static int session_process_ping_frame(nghttp2_session *session) {
nghttp2_inbound_frame *iframe = &session->iframe;
nghttp2_frame *frame = &iframe->frame;
nghttp2_frame_unpack_ping_payload(&frame->ping, iframe->sbuf.pos,
nghttp2_buf_len(&iframe->sbuf));
nghttp2_frame_unpack_ping_payload(&frame->ping, iframe->sbuf.pos);
return nghttp2_session_on_ping_received(session, frame);
}
@@ -4674,9 +4688,9 @@ static int session_process_goaway_frame(nghttp2_session *session) {
nghttp2_inbound_frame *iframe = &session->iframe;
nghttp2_frame *frame = &iframe->frame;
nghttp2_frame_unpack_goaway_payload(
&frame->goaway, iframe->sbuf.pos, nghttp2_buf_len(&iframe->sbuf),
iframe->lbuf.pos, nghttp2_buf_len(&iframe->lbuf));
nghttp2_frame_unpack_goaway_payload(&frame->goaway, iframe->sbuf.pos,
iframe->lbuf.pos,
nghttp2_buf_len(&iframe->lbuf));
nghttp2_buf_wrap_init(&iframe->lbuf, NULL, 0);
@@ -4759,8 +4773,8 @@ static int session_process_window_update_frame(nghttp2_session *session) {
nghttp2_inbound_frame *iframe = &session->iframe;
nghttp2_frame *frame = &iframe->frame;
nghttp2_frame_unpack_window_update_payload(
&frame->window_update, iframe->sbuf.pos, nghttp2_buf_len(&iframe->sbuf));
nghttp2_frame_unpack_window_update_payload(&frame->window_update,
iframe->sbuf.pos);
return nghttp2_session_on_window_update_received(session, frame);
}
@@ -4776,11 +4790,13 @@ int nghttp2_session_on_altsvc_received(nghttp2_session *session,
if (frame->hd.stream_id == 0) {
if (altsvc->origin_len == 0) {
return 0;
return session_call_on_invalid_frame_recv_callback(session, frame,
NGHTTP2_ERR_PROTO);
}
} else {
if (altsvc->origin_len > 0) {
return 0;
return session_call_on_invalid_frame_recv_callback(session, frame,
NGHTTP2_ERR_PROTO);
}
stream = nghttp2_session_get_stream(session, frame->hd.stream_id);
@@ -4793,6 +4809,11 @@ int nghttp2_session_on_altsvc_received(nghttp2_session *session,
}
}
if (altsvc->field_value_len == 0) {
return session_call_on_invalid_frame_recv_callback(session, frame,
NGHTTP2_ERR_PROTO);
}
return session_call_on_frame_received(session, frame);
}
@@ -5289,6 +5310,10 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
return rv;
}
if (!nghttp2_session_want_read(session)) {
return (ssize_t)inlen;
}
for (;;) {
switch (iframe->state) {
case NGHTTP2_IB_READ_CLIENT_MAGIC:
@@ -5325,9 +5350,10 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
iframe->state = NGHTTP2_IB_IGN_ALL;
rv = session_call_error_callback(
session, "Remote peer returned unexpected data while we expected "
"SETTINGS frame. Perhaps, peer does not support HTTP/2 "
"properly.");
session, NGHTTP2_ERR_SETTINGS_EXPECTED,
"Remote peer returned unexpected data while we expected "
"SETTINGS frame. Perhaps, peer does not support HTTP/2 "
"properly.");
if (nghttp2_is_fatal(rv)) {
return rv;
@@ -5568,7 +5594,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
if (iframe->payloadleft) {
nghttp2_settings_entry *min_header_table_size_entry;
/* We allocate iv with addtional one entry, to store the
/* We allocate iv with additional one entry, to store the
minimum header table size. */
iframe->max_niv =
iframe->frame.hd.length / NGHTTP2_FRAME_SETTINGS_ENTRY_LENGTH + 1;
@@ -5951,7 +5977,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
DEBUGF("recv: origin_len=%zu\n", origin_len);
if (2 + origin_len > iframe->payloadleft) {
if (origin_len > iframe->payloadleft) {
busy = 1;
iframe->state = NGHTTP2_IB_FRAME_SIZE_ERROR;
break;
@@ -6037,9 +6063,10 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
/* Use promised stream ID for PUSH_PROMISE */
rv = nghttp2_session_add_rst_stream(
session, iframe->frame.hd.type == NGHTTP2_PUSH_PROMISE
? iframe->frame.push_promise.promised_stream_id
: iframe->frame.hd.stream_id,
session,
iframe->frame.hd.type == NGHTTP2_PUSH_PROMISE
? iframe->frame.push_promise.promised_stream_id
: iframe->frame.hd.stream_id,
NGHTTP2_INTERNAL_ERROR);
if (nghttp2_is_fatal(rv)) {
return rv;
@@ -6124,7 +6151,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
case NGHTTP2_IB_FRAME_SIZE_ERROR:
DEBUGF("recv: [IB_FRAME_SIZE_ERROR]\n");
rv = session_handle_frame_size_error(session, &iframe->frame);
rv = session_handle_frame_size_error(session);
if (nghttp2_is_fatal(rv)) {
return rv;
}
@@ -6609,21 +6636,12 @@ int nghttp2_session_want_write(nghttp2_session *session) {
* response HEADERS and concurrent stream limit is reached, we don't
* want to write them.
*/
if (session->aob.item == NULL &&
nghttp2_outbound_queue_top(&session->ob_urgent) == NULL &&
nghttp2_outbound_queue_top(&session->ob_reg) == NULL &&
(nghttp2_pq_empty(&session->root.obq) ||
session->remote_window_size == 0) &&
(nghttp2_outbound_queue_top(&session->ob_syn) == NULL ||
session_is_outgoing_concurrent_streams_max(session))) {
return 0;
}
/* If there is no active streams and GOAWAY has been sent or
received, we are done with this session. */
return (session->goaway_flags &
(NGHTTP2_GOAWAY_SENT | NGHTTP2_GOAWAY_RECV)) == 0;
return session->aob.item || nghttp2_outbound_queue_top(&session->ob_urgent) ||
nghttp2_outbound_queue_top(&session->ob_reg) ||
(!nghttp2_pq_empty(&session->root.obq) &&
session->remote_window_size > 0) ||
(nghttp2_outbound_queue_top(&session->ob_syn) &&
!session_is_outgoing_concurrent_streams_max(session));
}
int nghttp2_session_add_ping(nghttp2_session *session, uint8_t flags,
@@ -7138,6 +7156,7 @@ uint32_t nghttp2_session_get_remote_settings(nghttp2_session *session,
}
assert(0);
abort(); /* if NDEBUG is set */
}
uint32_t nghttp2_session_get_local_settings(nghttp2_session *session,
@@ -7158,6 +7177,7 @@ uint32_t nghttp2_session_get_local_settings(nghttp2_session *session,
}
assert(0);
abort(); /* if NDEBUG is set */
}
static int nghttp2_session_upgrade_internal(nghttp2_session *session,
@@ -7501,3 +7521,7 @@ size_t
nghttp2_session_get_hd_deflate_dynamic_table_size(nghttp2_session *session) {
return nghttp2_hd_deflate_get_dynamic_table_size(&session->hd_deflater);
}
void nghttp2_session_set_user_data(nghttp2_session *session, void *user_data) {
session->user_data = user_data;
}

View File

@@ -311,7 +311,7 @@ struct nghttp2_session {
/* Unacked local SETTINGS_MAX_CONCURRENT_STREAMS value. We use this
to refuse the incoming stream if it exceeds this value. */
uint32_t pending_local_max_concurrent_stream;
/* The bitwose OR of zero or more of nghttp2_typemask to indicate
/* The bitwise OR of zero or more of nghttp2_typemask to indicate
that the default handling of extension frame is enabled. */
uint32_t builtin_recv_ext_types;
/* Unacked local ENABLE_PUSH value. We use this to refuse
@@ -319,7 +319,7 @@ struct nghttp2_session {
uint8_t pending_enable_push;
/* Nonzero if the session is server side. */
uint8_t server;
/* Flags indicating GOAWAY is sent and/or recieved. The flags are
/* Flags indicating GOAWAY is sent and/or received. The flags are
composed by bitwise OR-ing nghttp2_goaway_flag. */
uint8_t goaway_flags;
/* This flag is used to reduce excessive queuing of WINDOW_UPDATE to
@@ -722,7 +722,7 @@ int nghttp2_session_on_goaway_received(nghttp2_session *session,
nghttp2_frame *frame);
/*
* Called when WINDOW_UPDATE is recieved, assuming |frame| is properly
* Called when WINDOW_UPDATE is received, assuming |frame| is properly
* initialized.
*
* This function returns 0 if it succeeds, or one of the following
@@ -737,7 +737,7 @@ int nghttp2_session_on_window_update_received(nghttp2_session *session,
nghttp2_frame *frame);
/*
* Called when ALTSVC is recieved, assuming |frame| is properly
* Called when ALTSVC is received, assuming |frame| is properly
* initialized.
*
* This function returns 0 if it succeeds, or one of the following

View File

@@ -366,8 +366,9 @@ static void check_queued(nghttp2_stream *stream) {
}
}
if (queued == 0) {
fprintf(stderr, "stream(%p)=%d, stream->queued == 1, and "
"!stream_active(), but no descendants is queued\n",
fprintf(stderr,
"stream(%p)=%d, stream->queued == 1, and "
"!stream_active(), but no descendants is queued\n",
stream, stream->stream_id);
assert(0);
}
@@ -378,9 +379,10 @@ static void check_queued(nghttp2_stream *stream) {
}
} else {
if (stream_active(stream) || !nghttp2_pq_empty(&stream->obq)) {
fprintf(stderr, "stream(%p) = %d, stream->queued == 0, but "
"stream_active(stream) == %d and "
"nghttp2_pq_size(&stream->obq) = %zu\n",
fprintf(stderr,
"stream(%p) = %d, stream->queued == 0, but "
"stream_active(stream) == %d and "
"nghttp2_pq_size(&stream->obq) = %zu\n",
stream, stream->stream_id, stream_active(stream),
nghttp2_pq_size(&stream->obq));
assert(0);
@@ -449,8 +451,8 @@ static void validate_tree(nghttp2_stream *stream) {
check_sum_dep(stream);
check_dep_prev(stream);
}
#else /* !STREAM_DEP_DEBUG */
static void validate_tree(nghttp2_stream *stream _U_) {}
#else /* !STREAM_DEP_DEBUG */
static void validate_tree(nghttp2_stream *stream) { (void)stream; }
#endif /* !STREAM_DEP_DEBUG*/
static int stream_update_dep_on_attach_item(nghttp2_stream *stream) {

View File

@@ -217,7 +217,7 @@ int nghttp2_submit_ping(nghttp2_session *session, uint8_t flags,
return nghttp2_session_add_ping(session, flags, opaque_data);
}
int nghttp2_submit_priority(nghttp2_session *session, uint8_t flags _U_,
int nghttp2_submit_priority(nghttp2_session *session, uint8_t flags,
int32_t stream_id,
const nghttp2_priority_spec *pri_spec) {
int rv;
@@ -225,6 +225,7 @@ int nghttp2_submit_priority(nghttp2_session *session, uint8_t flags _U_,
nghttp2_frame *frame;
nghttp2_priority_spec copy_pri_spec;
nghttp2_mem *mem;
(void)flags;
mem = &session->mem;
@@ -264,8 +265,10 @@ int nghttp2_submit_priority(nghttp2_session *session, uint8_t flags _U_,
return 0;
}
int nghttp2_submit_rst_stream(nghttp2_session *session, uint8_t flags _U_,
int nghttp2_submit_rst_stream(nghttp2_session *session, uint8_t flags,
int32_t stream_id, uint32_t error_code) {
(void)flags;
if (stream_id == 0) {
return NGHTTP2_ERR_INVALID_ARGUMENT;
}
@@ -273,9 +276,11 @@ int nghttp2_submit_rst_stream(nghttp2_session *session, uint8_t flags _U_,
return nghttp2_session_add_rst_stream(session, stream_id, error_code);
}
int nghttp2_submit_goaway(nghttp2_session *session, uint8_t flags _U_,
int nghttp2_submit_goaway(nghttp2_session *session, uint8_t flags,
int32_t last_stream_id, uint32_t error_code,
const uint8_t *opaque_data, size_t opaque_data_len) {
(void)flags;
if (session->goaway_flags & NGHTTP2_GOAWAY_TERM_ON_SEND) {
return 0;
}
@@ -296,12 +301,13 @@ int nghttp2_submit_shutdown_notice(nghttp2_session *session) {
NGHTTP2_GOAWAY_AUX_SHUTDOWN_NOTICE);
}
int nghttp2_submit_settings(nghttp2_session *session, uint8_t flags _U_,
int nghttp2_submit_settings(nghttp2_session *session, uint8_t flags,
const nghttp2_settings_entry *iv, size_t niv) {
(void)flags;
return nghttp2_session_add_settings(session, NGHTTP2_FLAG_NONE, iv, niv);
}
int32_t nghttp2_submit_push_promise(nghttp2_session *session, uint8_t flags _U_,
int32_t nghttp2_submit_push_promise(nghttp2_session *session, uint8_t flags,
int32_t stream_id, const nghttp2_nv *nva,
size_t nvlen,
void *promised_stream_user_data) {
@@ -312,6 +318,7 @@ int32_t nghttp2_submit_push_promise(nghttp2_session *session, uint8_t flags _U_,
int32_t promised_stream_id;
int rv;
nghttp2_mem *mem;
(void)flags;
mem = &session->mem;
@@ -365,11 +372,13 @@ int32_t nghttp2_submit_push_promise(nghttp2_session *session, uint8_t flags _U_,
return promised_stream_id;
}
int nghttp2_submit_window_update(nghttp2_session *session, uint8_t flags _U_,
int nghttp2_submit_window_update(nghttp2_session *session, uint8_t flags,
int32_t stream_id,
int32_t window_size_increment) {
int rv;
nghttp2_stream *stream = 0;
(void)flags;
if (window_size_increment == 0) {
return 0;
}
@@ -410,11 +419,12 @@ int nghttp2_submit_window_update(nghttp2_session *session, uint8_t flags _U_,
}
int nghttp2_session_set_local_window_size(nghttp2_session *session,
uint8_t flags _U_, int32_t stream_id,
uint8_t flags, int32_t stream_id,
int32_t window_size) {
int32_t window_size_increment;
nghttp2_stream *stream;
int rv;
(void)flags;
if (window_size < 0) {
return NGHTTP2_ERR_INVALID_ARGUMENT;
@@ -476,7 +486,7 @@ int nghttp2_session_set_local_window_size(nghttp2_session *session,
return 0;
}
int nghttp2_submit_altsvc(nghttp2_session *session, uint8_t flags _U_,
int nghttp2_submit_altsvc(nghttp2_session *session, uint8_t flags,
int32_t stream_id, const uint8_t *origin,
size_t origin_len, const uint8_t *field_value,
size_t field_value_len) {
@@ -488,6 +498,7 @@ int nghttp2_submit_altsvc(nghttp2_session *session, uint8_t flags _U_,
nghttp2_frame *frame;
nghttp2_ext_altsvc *altsvc;
int rv;
(void)flags;
mem = &session->mem;

View File

@@ -8,11 +8,8 @@ set_source_files_properties(${cxx_sources} PROPERTIES
COMPILE_FLAGS "${WARNCXXFLAGS} ${CXX1XCXXFLAGS}")
include_directories(
"${CMAKE_SOURCE_DIR}/lib/includes"
"${CMAKE_BINARY_DIR}/lib/includes"
"${CMAKE_SOURCE_DIR}/lib"
"${CMAKE_SOURCE_DIR}/src/includes"
"${CMAKE_SOURCE_DIR}/third-party"
"${CMAKE_CURRENT_SOURCE_DIR}/includes"
"${CMAKE_CURRENT_SOURCE_DIR}/../third-party"
${JEMALLOC_INCLUDE_DIRS}
${SPDYLAY_INCLUDE_DIRS}
@@ -48,7 +45,7 @@ if(ENABLE_APP)
set(NGHTTP_SOURCES
${HELPER_OBJECTS}
nghttp.cc
ssl.cc
tls.cc
)
if(HAVE_LIBXML2)
list(APPEND NGHTTP_SOURCES HtmlParser.cc)
@@ -58,7 +55,7 @@ if(ENABLE_APP)
set(NGHTTPD_SOURCES
${HELPER_OBJECTS}
nghttpd.cc
ssl.cc
tls.cc
HttpServer.cc
)
@@ -67,7 +64,7 @@ if(ENABLE_APP)
util.cc
http2.cc h2load.cc
timegm.c
ssl.cc
tls.cc
h2load_http2_session.cc
h2load_http1_session.cc
)
@@ -82,7 +79,7 @@ if(ENABLE_APP)
set(NGHTTPX_SRCS
util.cc http2.cc timegm.c
app_helper.cc
ssl.cc
tls.cc
shrpx_config.cc
shrpx_accept_handler.cc
shrpx_connection_handler.cc
@@ -98,7 +95,7 @@ if(ENABLE_APP)
shrpx_log.cc
shrpx_http.cc
shrpx_io_control.cc
shrpx_ssl.cc
shrpx_tls.cc
shrpx_worker.cc
shrpx_log_config.cc
shrpx_connect_blocker.cc
@@ -152,7 +149,7 @@ if(ENABLE_APP)
if(HAVE_CUNIT)
set(NGHTTPX_UNITTEST_SOURCES
shrpx-unittest.cc
shrpx_ssl_test.cc
shrpx_tls_test.cc
shrpx_downstream_test.cc
shrpx_config_test.cc
shrpx_worker_test.cc
@@ -216,7 +213,7 @@ endif()
if(ENABLE_ASIO_LIB)
set(NGHTTP2_ASIO_SOURCES
util.cc http2.cc
ssl.cc
tls.cc
timegm.c
asio_common.cc
asio_io_service_pool.cc
@@ -252,6 +249,11 @@ if(ENABLE_ASIO_LIB)
${OPENSSL_INCLUDE_DIRS}
${Boost_INCLUDE_DIRS}
)
target_include_directories(nghttp2_asio INTERFACE
"${CMAKE_CURRENT_BINARY_DIR}/../lib/includes"
"${CMAKE_CURRENT_SOURCE_DIR}/../lib/includes"
"${CMAKE_CURRENT_SOURCE_DIR}/includes"
)
target_link_libraries(nghttp2_asio
nghttp2
${OPENSSL_LIBRARIES}

View File

@@ -60,7 +60,7 @@
#include "app_helper.h"
#include "http2.h"
#include "util.h"
#include "ssl.h"
#include "tls.h"
#include "template.h"
#ifndef O_BINARY
@@ -877,7 +877,7 @@ int Http2Handler::connection_made() {
}
}
if (ssl_ && !nghttp2::ssl::check_http2_requirement(ssl_)) {
if (ssl_ && !nghttp2::tls::check_http2_requirement(ssl_)) {
terminate_session(NGHTTP2_INADEQUATE_SECURITY);
}
@@ -1749,8 +1749,8 @@ void fill_callback(nghttp2_session_callbacks *callbacks, const Config *config) {
nghttp2_session_callbacks_set_on_invalid_frame_recv_callback(
callbacks, verbose_on_invalid_frame_recv_callback);
nghttp2_session_callbacks_set_error_callback(callbacks,
verbose_error_callback);
nghttp2_session_callbacks_set_error_callback2(callbacks,
verbose_error_callback);
}
nghttp2_session_callbacks_set_on_data_chunk_recv_callback(
@@ -1779,7 +1779,7 @@ struct ClientInfo {
struct Worker {
std::unique_ptr<Sessions> sessions;
ev_async w;
// protectes q
// protects q
std::mutex m;
std::deque<ClientInfo> q;
};
@@ -2122,14 +2122,14 @@ int HttpServer::run() {
SSL_CTX_set_mode(ssl_ctx, SSL_MODE_AUTO_RETRY);
SSL_CTX_set_mode(ssl_ctx, SSL_MODE_RELEASE_BUFFERS);
if (nghttp2::ssl::ssl_ctx_set_proto_versions(
ssl_ctx, nghttp2::ssl::NGHTTP2_TLS_MIN_VERSION,
nghttp2::ssl::NGHTTP2_TLS_MAX_VERSION) != 0) {
if (nghttp2::tls::ssl_ctx_set_proto_versions(
ssl_ctx, nghttp2::tls::NGHTTP2_TLS_MIN_VERSION,
nghttp2::tls::NGHTTP2_TLS_MAX_VERSION) != 0) {
std::cerr << "Could not set TLS versions" << std::endl;
return -1;
}
if (SSL_CTX_set_cipher_list(ssl_ctx, ssl::DEFAULT_CIPHER_LIST) == 0) {
if (SSL_CTX_set_cipher_list(ssl_ctx, tls::DEFAULT_CIPHER_LIST) == 0) {
std::cerr << ERR_error_string(ERR_get_error(), nullptr) << std::endl;
return -1;
}
@@ -2156,7 +2156,7 @@ int HttpServer::run() {
}
SSL_CTX_set_tmp_ecdh(ssl_ctx, ecdh);
EC_KEY_free(ecdh);
// #endif // OPENSSL_VERSION_NUBMER < 0x10002000L
// #endif // OPENSSL_VERSION_NUBMER < 0x10002000L
#endif // OPENSSL_NO_EC
@@ -2197,8 +2197,9 @@ int HttpServer::run() {
return -1;
}
if (config_->verify_client) {
SSL_CTX_set_verify(ssl_ctx, SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE |
SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
SSL_CTX_set_verify(ssl_ctx,
SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE |
SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
verify_callback);
}

View File

@@ -40,7 +40,6 @@ AM_CPPFLAGS = \
-I$(top_srcdir)/lib \
-I$(top_srcdir)/src/includes \
-I$(top_srcdir)/third-party \
@LIBSPDYLAY_CFLAGS@ \
@LIBXML2_CFLAGS@ \
@LIBEV_CFLAGS@ \
@OPENSSL_CFLAGS@ \
@@ -52,7 +51,6 @@ AM_CPPFLAGS = \
LDADD = $(top_builddir)/lib/libnghttp2.la \
$(top_builddir)/third-party/libhttp-parser.la \
@JEMALLOC_LIBS@ \
@LIBSPDYLAY_LIBS@ \
@LIBXML2_LIBS@ \
@LIBEV_LIBS@ \
@OPENSSL_LIBS@ \
@@ -81,10 +79,10 @@ endif # HAVE_LIBXML2
nghttp_SOURCES = ${HELPER_OBJECTS} ${HELPER_HFILES} nghttp.cc nghttp.h \
${HTML_PARSER_OBJECTS} ${HTML_PARSER_HFILES} \
ssl.cc ssl.h
tls.cc tls.h
nghttpd_SOURCES = ${HELPER_OBJECTS} ${HELPER_HFILES} nghttpd.cc \
ssl.cc ssl.h \
tls.cc tls.h \
HttpServer.cc HttpServer.h
bin_PROGRAMS += h2load
@@ -92,19 +90,15 @@ bin_PROGRAMS += h2load
h2load_SOURCES = util.cc util.h \
http2.cc http2.h h2load.cc h2load.h \
timegm.c timegm.h \
ssl.cc ssl.h \
tls.cc tls.h \
h2load_session.h \
h2load_http2_session.cc h2load_http2_session.h \
h2load_http1_session.cc h2load_http1_session.h
if HAVE_SPDYLAY
h2load_SOURCES += h2load_spdy_session.cc h2load_spdy_session.h
endif # HAVE_SPDYLAY
NGHTTPX_SRCS = \
util.cc util.h http2.cc http2.h timegm.c timegm.h base64.h \
app_helper.cc app_helper.h \
ssl.cc ssl.h \
tls.cc tls.h \
shrpx_config.cc shrpx_config.h \
shrpx_error.h \
shrpx_accept_handler.cc shrpx_accept_handler.h \
@@ -122,7 +116,7 @@ NGHTTPX_SRCS = \
shrpx_log.cc shrpx_log.h \
shrpx_http.cc shrpx_http.h \
shrpx_io_control.cc shrpx_io_control.h \
shrpx_ssl.cc shrpx_ssl.h \
shrpx_tls.cc shrpx_tls.h \
shrpx_worker.cc shrpx_worker.h \
shrpx_log_config.cc shrpx_log_config.h \
shrpx_connect_blocker.cc shrpx_connect_blocker.h \
@@ -148,10 +142,6 @@ NGHTTPX_SRCS = \
buffer.h memchunk.h template.h allocator.h \
xsi_strerror.c xsi_strerror.h
if HAVE_SPDYLAY
NGHTTPX_SRCS += shrpx_spdy_upstream.cc shrpx_spdy_upstream.h
endif # HAVE_SPDYLAY
if HAVE_MRUBY
NGHTTPX_SRCS += \
shrpx_mruby.cc shrpx_mruby.h \
@@ -183,7 +173,7 @@ endif # HAVE_NEVERBLEED
if HAVE_CUNIT
check_PROGRAMS += nghttpx-unittest
nghttpx_unittest_SOURCES = shrpx-unittest.cc \
shrpx_ssl_test.cc shrpx_ssl_test.h \
shrpx_tls_test.cc shrpx_tls_test.h \
shrpx_downstream_test.cc shrpx_downstream_test.h \
shrpx_config_test.cc shrpx_config_test.h \
shrpx_worker_test.cc shrpx_worker_test.h \
@@ -240,7 +230,7 @@ lib_LTLIBRARIES = libnghttp2_asio.la
libnghttp2_asio_la_SOURCES = \
util.cc util.h http2.cc http2.h \
ssl.cc ssl.h \
tls.cc tls.h \
ssl_compat.h \
timegm.c timegm.h \
asio_common.cc asio_common.h \

View File

@@ -27,7 +27,9 @@
#include "nghttp2_config.h"
#ifndef _WIN32
#include <sys/uio.h>
#endif // !_WIN32
#include <cassert>
@@ -271,6 +273,6 @@ ByteRef make_byte_ref(BlockAllocator &alloc, size_t size) {
return {dst, size};
}
} // namespace aria2
} // namespace nghttp2
#endif // ALLOCATOR_H

View File

@@ -155,7 +155,7 @@ void print_nv(nghttp2_nv *nva, size_t nvlen) {
print_nv(nva);
}
}
} // namelen
} // namespace
void print_timer() {
auto millis = get_timer();
@@ -327,8 +327,9 @@ void print_frame(print_type ptype, const nghttp2_frame *frame) {
break;
case NGHTTP2_GOAWAY:
print_frame_attr_indent();
fprintf(outfile, "(last_stream_id=%d, error_code=%s(0x%02x), "
"opaque_data(%u)=[%s])\n",
fprintf(outfile,
"(last_stream_id=%d, error_code=%s(0x%02x), "
"opaque_data(%u)=[%s])\n",
frame->goaway.last_stream_id,
nghttp2_http2_strerror(frame->goaway.error_code),
frame->goaway.error_code,
@@ -425,8 +426,8 @@ int verbose_on_data_chunk_recv_callback(nghttp2_session *session, uint8_t flags,
return 0;
}
int verbose_error_callback(nghttp2_session *session, const char *msg,
size_t len, void *user_data) {
int verbose_error_callback(nghttp2_session *session, int lib_error_code,
const char *msg, size_t len, void *user_data) {
print_timer();
fprintf(outfile, " [ERROR] %.*s\n", (int)len, msg);
fflush(outfile);

View File

@@ -60,8 +60,8 @@ int verbose_on_data_chunk_recv_callback(nghttp2_session *session, uint8_t flags,
int32_t stream_id, const uint8_t *data,
size_t len, void *user_data);
int verbose_error_callback(nghttp2_session *session, const char *msg,
size_t len, void *user_data);
int verbose_error_callback(nghttp2_session *session, int lib_error_code,
const char *msg, size_t len, void *user_data);
// Returns difference between |a| and |b| in milliseconds, assuming
// |a| is more recent than |b|.

View File

@@ -96,29 +96,48 @@ boost::asio::io_service &session::io_service() const {
const request *session::submit(boost::system::error_code &ec,
const std::string &method,
const std::string &uri, header_map h) const {
return impl_->submit(ec, method, uri, generator_cb(), std::move(h));
const std::string &uri, header_map h,
priority_spec prio) const {
return impl_->submit(ec, method, uri, generator_cb(), std::move(h),
std::move(prio));
}
const request *session::submit(boost::system::error_code &ec,
const std::string &method,
const std::string &uri, std::string data,
header_map h) const {
header_map h, priority_spec prio) const {
return impl_->submit(ec, method, uri, string_generator(std::move(data)),
std::move(h));
std::move(h), std::move(prio));
}
const request *session::submit(boost::system::error_code &ec,
const std::string &method,
const std::string &uri, generator_cb cb,
header_map h) const {
return impl_->submit(ec, method, uri, std::move(cb), std::move(h));
header_map h, priority_spec prio) const {
return impl_->submit(ec, method, uri, std::move(cb), std::move(h),
std::move(prio));
}
void session::read_timeout(const boost::posix_time::time_duration &t) {
impl_->read_timeout(t);
}
priority_spec::priority_spec(const int32_t stream_id, const int32_t weight,
const bool exclusive)
: valid_(true) {
nghttp2_priority_spec_init(&spec_, stream_id, weight, exclusive);
}
const nghttp2_priority_spec *priority_spec::get() const {
if (!valid_) {
return nullptr;
}
return &spec_;
}
const bool priority_spec::valid() const { return valid_; }
} // namespace client
} // namespace asio_http2
} // nghttp2
} // namespace nghttp2

View File

@@ -47,6 +47,7 @@ session_impl::session_impl(
deadline_(io_service),
connect_timeout_(connect_timeout),
read_timeout_(boost::posix_time::seconds(60)),
ping_(io_service),
session_(nullptr),
data_pending_(nullptr),
data_pendinglen_(0),
@@ -102,6 +103,27 @@ void session_impl::handle_deadline() {
std::bind(&session_impl::handle_deadline, this->shared_from_this()));
}
void handle_ping2(const boost::system::error_code &ec, int) {}
void session_impl::start_ping() {
ping_.expires_from_now(boost::posix_time::seconds(30));
ping_.async_wait(std::bind(&session_impl::handle_ping, shared_from_this(),
std::placeholders::_1));
}
void session_impl::handle_ping(const boost::system::error_code &ec) {
if (stopped_ || ec == boost::asio::error::operation_aborted ||
!streams_.empty()) {
return;
}
nghttp2_submit_ping(session_, NGHTTP2_FLAG_NONE, nullptr);
signal_write();
start_ping();
}
void session_impl::connected(tcp::resolver::iterator endpoint_it) {
if (!setup_session()) {
return;
@@ -112,6 +134,8 @@ void session_impl::connected(tcp::resolver::iterator endpoint_it) {
do_write();
do_read();
start_ping();
auto &connect_cb = on_connect();
if (connect_cb) {
connect_cb(endpoint_it);
@@ -433,6 +457,9 @@ std::unique_ptr<stream> session_impl::pop_stream(int32_t stream_id) {
}
auto strm = std::move((*it).second);
streams_.erase(it);
if (streams_.empty()) {
start_ping();
}
return strm;
}
@@ -441,6 +468,7 @@ stream *session_impl::create_push_stream(int32_t stream_id) {
strm->stream_id(stream_id);
auto p = streams_.emplace(stream_id, std::move(strm));
assert(p.second);
ping_.cancel();
return (*p.first).second.get();
}
@@ -451,7 +479,7 @@ std::unique_ptr<stream> session_impl::create_stream() {
const request *session_impl::submit(boost::system::error_code &ec,
const std::string &method,
const std::string &uri, generator_cb cb,
header_map h) {
header_map h, priority_spec prio) {
ec.clear();
if (stopped_) {
@@ -531,7 +559,7 @@ const request *session_impl::submit(boost::system::error_code &ec,
prdptr = &prd;
}
auto stream_id = nghttp2_submit_request(session_, nullptr, nva.data(),
auto stream_id = nghttp2_submit_request(session_, prio.get(), nva.data(),
nva.size(), prdptr, strm.get());
if (stream_id < 0) {
ec = make_error_code(static_cast<nghttp2_error>(stream_id));
@@ -544,6 +572,7 @@ const request *session_impl::submit(boost::system::error_code &ec,
auto p = streams_.emplace(stream_id, std::move(strm));
assert(p.second);
ping_.cancel();
return &(*p.first).second->request();
}
@@ -715,6 +744,7 @@ void session_impl::stop() {
shutdown_socket();
deadline_.cancel();
ping_.cancel();
stopped_ = true;
}
@@ -726,4 +756,4 @@ void session_impl::read_timeout(const boost::posix_time::time_duration &t) {
} // namespace client
} // namespace asio_http2
} // nghttp2
} // namespace nghttp2

View File

@@ -70,7 +70,7 @@ public:
const request *submit(boost::system::error_code &ec,
const std::string &method, const std::string &uri,
generator_cb cb, header_map h);
generator_cb cb, header_map h, priority_spec spec);
virtual void start_connect(tcp::resolver::iterator endpoint_it) = 0;
virtual tcp::socket &socket() = 0;
@@ -109,6 +109,8 @@ private:
bool setup_session();
void call_error_cb(const boost::system::error_code &ec);
void handle_deadline();
void start_ping();
void handle_ping(const boost::system::error_code &ec);
boost::asio::io_service &io_service_;
tcp::resolver resolver_;
@@ -122,6 +124,8 @@ private:
boost::posix_time::time_duration connect_timeout_;
boost::posix_time::time_duration read_timeout_;
boost::asio::deadline_timer ping_;
nghttp2_session *session_;
const uint8_t *data_pending_;

View File

@@ -45,8 +45,9 @@ session_tls_impl::~session_tls_impl() {}
void session_tls_impl::start_connect(tcp::resolver::iterator endpoint_it) {
auto self = std::static_pointer_cast<session_tls_impl>(shared_from_this());
boost::asio::async_connect(
socket(), endpoint_it, [self](const boost::system::error_code &ec,
tcp::resolver::iterator endpoint_it) {
socket(), endpoint_it,
[self](const boost::system::error_code &ec,
tcp::resolver::iterator endpoint_it) {
if (self->stopped()) {
return;
}

View File

@@ -28,7 +28,7 @@
#include <boost/asio/ssl.hpp>
#include "ssl.h"
#include "tls.h"
#include "util.h"
namespace nghttp2 {

View File

@@ -24,6 +24,7 @@
*/
#include "asio_common.h"
#include <fcntl.h>
#include <memory>
#include "util.h"

View File

@@ -169,6 +169,6 @@ private:
} // namespace server
} // namespace asio_http2
} // namespace nghttp
} // namespace nghttp2
#endif // ASIO_SERVER_HTTP2_HANDLER_H

View File

@@ -28,7 +28,7 @@
#include "asio_server.h"
#include "util.h"
#include "ssl.h"
#include "tls.h"
#include "template.h"
namespace nghttp2 {

View File

@@ -28,7 +28,7 @@
#include <boost/asio/ssl.hpp>
#include "ssl.h"
#include "tls.h"
#include "util.h"
namespace nghttp2 {
@@ -72,7 +72,7 @@ configure_tls_context_easy(boost::system::error_code &ec,
SSL_CTX_set_mode(ctx, SSL_MODE_AUTO_RETRY);
SSL_CTX_set_mode(ctx, SSL_MODE_RELEASE_BUFFERS);
SSL_CTX_set_cipher_list(ctx, ssl::DEFAULT_CIPHER_LIST);
SSL_CTX_set_cipher_list(ctx, tls::DEFAULT_CIPHER_LIST);
#ifndef OPENSSL_NO_EC
auto ecdh = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);

File diff suppressed because it is too large Load Diff

View File

@@ -64,7 +64,6 @@ struct Worker;
struct Config {
std::vector<std::vector<nghttp2_nv>> nva;
std::vector<std::vector<const char *>> nv;
std::vector<std::string> h1reqs;
std::vector<ev_tstamp> timings;
nghttp2::Headers custom_headers;
@@ -85,17 +84,15 @@ struct Config {
// rate at which connections should be made
size_t rate;
ev_tstamp rate_period;
// amount of time for main measurements in timing-based test
ev_tstamp duration;
// amount of time to wait before starting measurements in timing-based test
ev_tstamp warm_up_time;
// amount of time to wait for activity on a given connection
ev_tstamp conn_active_timeout;
// amount of time to wait after the last request is made on a connection
ev_tstamp conn_inactivity_timeout;
enum {
PROTO_HTTP2,
PROTO_SPDY2,
PROTO_SPDY3,
PROTO_SPDY3_1,
PROTO_HTTP1_1
} no_tls_proto;
enum { PROTO_HTTP2, PROTO_HTTP1_1 } no_tls_proto;
uint32_t header_table_size;
uint32_t encoder_header_table_size;
// file descriptor for upload data
@@ -118,6 +115,7 @@ struct Config {
~Config();
bool is_rate_mode() const;
bool is_timing_based_mode() const;
bool has_base_uri() const;
};
@@ -139,7 +137,7 @@ struct ClientStat {
// time client end (i.e., client somehow processed all requests it
// is responsible for, and disconnected)
std::chrono::steady_clock::time_point client_end_time;
// The number of requests completed successfull, but not necessarily
// The number of requests completed successful, but not necessarily
// means successful HTTP status code.
size_t req_success;
@@ -180,7 +178,7 @@ struct Stats {
size_t req_started;
// The number of requests finished
size_t req_done;
// The number of requests completed successfull, but not necessarily
// The number of requests completed successful, but not necessarily
// means successful HTTP status code.
size_t req_success;
// The number of requests marked as success. HTTP status code is
@@ -215,15 +213,21 @@ struct Stats {
enum ClientState { CLIENT_IDLE, CLIENT_CONNECTED };
// This type tells whether the client is in warmup phase or not or is over
enum class Phase {
INITIAL_IDLE, // Initial idle state before warm-up phase
WARM_UP, // Warm up phase when no measurements are done
MAIN_DURATION, // Main measurement phase; if timing-based
// test is not run, this is the default phase
DURATION_OVER // This phase occurs after the measurements are over
};
struct Client;
// We use systematic sampling method
// We use reservoir sampling method
struct Sampling {
// sampling interval
double interval;
// cumulative value of interval, and the next point is the integer
// rounded up from this value.
double point;
// maximum number of samples
size_t max_samples;
// number of samples seen, including discarded samples.
size_t n;
};
@@ -253,6 +257,15 @@ struct Worker {
ev_timer timeout_watcher;
// The next client ID this worker assigns
uint32_t next_client_id;
// Keeps track of the current phase (for timing-based experiment) for the
// worker
Phase current_phase;
// We need to keep track of the clients in order to stop them when needed
std::vector<Client *> clients;
// This is only active when there is not a bounded number of requests
// specified
ev_timer duration_watcher;
ev_timer warmup_watcher;
Worker(uint32_t id, SSL_CTX *ssl_ctx, size_t nreq_todo, size_t nclients,
size_t rate, size_t max_samples, Config *config);
@@ -263,6 +276,10 @@ struct Worker {
void sample_client_stat(ClientStat *cstat);
void report_progress();
void report_rate_progress();
// This function calls the destructors of all the clients.
void stop_all_clients();
// This function frees a client from the list of clients for this Worker.
void free_client(Client *);
};
struct Stream {

View File

@@ -26,6 +26,7 @@
#include <cassert>
#include <cerrno>
#include <iostream>
#include "h2load.h"
#include "util.h"
@@ -52,6 +53,15 @@ int on_header_callback(nghttp2_session *session, const nghttp2_frame *frame,
}
client->on_header(frame->hd.stream_id, name, namelen, value, valuelen);
client->worker->stats.bytes_head_decomp += namelen + valuelen;
if (client->worker->config->verbose) {
std::cout << "[stream_id=" << frame->hd.stream_id << "] ";
std::cout.write(reinterpret_cast<const char *>(name), namelen);
std::cout << ": ";
std::cout.write(reinterpret_cast<const char *>(value), valuelen);
std::cout << "\n";
}
return 0;
}
} // namespace
@@ -180,6 +190,9 @@ ssize_t send_callback(nghttp2_session *session, const uint8_t *data,
void Http2Session::on_connect() {
int rv;
// This is required with --disable-assert.
(void)rv;
nghttp2_session_callbacks *callbacks;
nghttp2_session_callbacks_new(&callbacks);

View File

@@ -1,289 +0,0 @@
/*
* nghttp2 - HTTP/2 C Library
*
* Copyright (c) 2014 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 "h2load_spdy_session.h"
#include <cassert>
#include <cerrno>
#include "h2load.h"
#include "util.h"
using namespace nghttp2;
namespace h2load {
SpdySession::SpdySession(Client *client, uint16_t spdy_version)
: client_(client), session_(nullptr), spdy_version_(spdy_version) {}
SpdySession::~SpdySession() { spdylay_session_del(session_); }
namespace {
void before_ctrl_send_callback(spdylay_session *session,
spdylay_frame_type type, spdylay_frame *frame,
void *user_data) {
auto client = static_cast<Client *>(user_data);
if (type != SPDYLAY_SYN_STREAM) {
return;
}
client->on_request(frame->syn_stream.stream_id);
auto req_stat = client->get_req_stat(frame->syn_stream.stream_id);
client->record_request_time(req_stat);
}
} // namespace
namespace {
void on_ctrl_recv_callback(spdylay_session *session, spdylay_frame_type type,
spdylay_frame *frame, void *user_data) {
auto client = static_cast<Client *>(user_data);
if (type != SPDYLAY_SYN_REPLY) {
return;
}
for (auto p = frame->syn_reply.nv; *p; p += 2) {
auto name = *p;
auto value = *(p + 1);
auto namelen = strlen(name);
auto valuelen = strlen(value);
client->on_header(frame->syn_reply.stream_id,
reinterpret_cast<const uint8_t *>(name), namelen,
reinterpret_cast<const uint8_t *>(value), valuelen);
client->worker->stats.bytes_head_decomp += namelen + valuelen;
}
// Strictly speaking, we have to subtract 2 (unused field) if SPDY
// version is 2. But it is already deprecated, and we don't do
// extra work for it.
client->worker->stats.bytes_head += frame->syn_reply.hd.length - 4;
if (frame->syn_stream.hd.flags & SPDYLAY_CTRL_FLAG_FIN) {
client->record_ttfb();
}
}
} // namespace
namespace {
void on_data_chunk_recv_callback(spdylay_session *session, uint8_t flags,
int32_t stream_id, const uint8_t *data,
size_t len, void *user_data) {
auto client = static_cast<Client *>(user_data);
client->record_ttfb();
client->worker->stats.bytes_body += len;
auto spdy_session = static_cast<SpdySession *>(client->session.get());
spdy_session->handle_window_update(stream_id, len);
}
} // namespace
namespace {
void on_stream_close_callback(spdylay_session *session, int32_t stream_id,
spdylay_status_code status_code,
void *user_data) {
auto client = static_cast<Client *>(user_data);
client->on_stream_close(stream_id, status_code == SPDYLAY_OK);
}
} // namespace
namespace {
ssize_t send_callback(spdylay_session *session, const uint8_t *data,
size_t length, int flags, void *user_data) {
auto client = static_cast<Client *>(user_data);
auto &wb = client->wb;
if (wb.rleft() >= BACKOFF_WRITE_BUFFER_THRES) {
return SPDYLAY_ERR_WOULDBLOCK;
}
return wb.append(data, length);
}
} // namespace
namespace {
ssize_t file_read_callback(spdylay_session *session, int32_t stream_id,
uint8_t *buf, size_t length, int *eof,
spdylay_data_source *source, void *user_data) {
auto client = static_cast<Client *>(user_data);
auto config = client->worker->config;
auto req_stat = client->get_req_stat(stream_id);
ssize_t nread;
while ((nread = pread(config->data_fd, buf, length, req_stat->data_offset)) ==
-1 &&
errno == EINTR)
;
if (nread == -1) {
return SPDYLAY_ERR_TEMPORAL_CALLBACK_FAILURE;
}
req_stat->data_offset += nread;
if (nread == 0 || req_stat->data_offset == config->data_length) {
*eof = 1;
}
return nread;
}
} // namespace
void SpdySession::on_connect() {
spdylay_session_callbacks callbacks = {0};
callbacks.send_callback = send_callback;
callbacks.before_ctrl_send_callback = before_ctrl_send_callback;
callbacks.on_data_chunk_recv_callback = on_data_chunk_recv_callback;
callbacks.on_stream_close_callback = on_stream_close_callback;
callbacks.on_ctrl_recv_callback = on_ctrl_recv_callback;
spdylay_session_client_new(&session_, spdy_version_, &callbacks, client_);
int val = 1;
spdylay_session_set_option(session_, SPDYLAY_OPT_NO_AUTO_WINDOW_UPDATE, &val,
sizeof(val));
spdylay_settings_entry iv;
iv.settings_id = SPDYLAY_SETTINGS_INITIAL_WINDOW_SIZE;
iv.flags = SPDYLAY_ID_FLAG_SETTINGS_NONE;
iv.value = (1 << client_->worker->config->window_bits);
spdylay_submit_settings(session_, SPDYLAY_FLAG_SETTINGS_NONE, &iv, 1);
auto config = client_->worker->config;
if (spdy_version_ >= SPDYLAY_PROTO_SPDY3_1 &&
config->connection_window_bits > 16) {
auto delta =
(1 << config->connection_window_bits) - SPDYLAY_INITIAL_WINDOW_SIZE;
spdylay_submit_window_update(session_, 0, delta);
}
client_->signal_write();
}
int SpdySession::submit_request() {
int rv;
auto config = client_->worker->config;
auto &nv = config->nv[client_->reqidx++];
if (client_->reqidx == config->nv.size()) {
client_->reqidx = 0;
}
spdylay_data_provider prd{{0}, file_read_callback};
rv = spdylay_submit_request(session_, 0, nv.data(),
config->data_fd == -1 ? nullptr : &prd, nullptr);
if (rv != 0) {
return -1;
}
return 0;
}
int SpdySession::on_read(const uint8_t *data, size_t len) {
auto rv = spdylay_session_mem_recv(session_, data, len);
if (rv < 0) {
return -1;
}
assert(static_cast<size_t>(rv) == len);
if (spdylay_session_want_read(session_) == 0 &&
spdylay_session_want_write(session_) == 0 && client_->wb.rleft() == 0) {
return -1;
}
client_->signal_write();
return 0;
}
int SpdySession::on_write() {
auto rv = spdylay_session_send(session_);
if (rv != 0) {
return -1;
}
if (spdylay_session_want_read(session_) == 0 &&
spdylay_session_want_write(session_) == 0 && client_->wb.rleft() == 0) {
return -1;
}
return 0;
}
void SpdySession::terminate() {
spdylay_session_fail_session(session_, SPDYLAY_OK);
}
namespace {
int32_t determine_window_update_transmission(spdylay_session *session,
int32_t stream_id,
size_t window_bits) {
int32_t recv_length;
if (stream_id == 0) {
recv_length = spdylay_session_get_recv_data_length(session);
} else {
recv_length =
spdylay_session_get_stream_recv_data_length(session, stream_id);
}
auto window_size = 1 << window_bits;
if (recv_length != -1 && recv_length >= window_size / 2) {
return recv_length;
}
return -1;
}
} // namespace
void SpdySession::handle_window_update(int32_t stream_id, size_t recvlen) {
auto config = client_->worker->config;
size_t connection_window_bits;
if (config->connection_window_bits > 16) {
connection_window_bits = config->connection_window_bits;
} else {
connection_window_bits = 16;
}
auto delta =
determine_window_update_transmission(session_, 0, connection_window_bits);
if (delta > 0) {
spdylay_submit_window_update(session_, 0, delta);
}
delta = determine_window_update_transmission(session_, stream_id,
config->window_bits);
if (delta > 0) {
spdylay_submit_window_update(session_, stream_id, delta);
}
}
size_t SpdySession::max_concurrent_streams() {
return (size_t)client_->worker->config->max_concurrent_streams;
}
} // namespace h2load

View File

@@ -1,58 +0,0 @@
/*
* nghttp2 - HTTP/2 C Library
*
* Copyright (c) 2014 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 H2LOAD_SPDY_SESSION_H
#define H2LOAD_SPDY_SESSION_H
#include "h2load_session.h"
#include <spdylay/spdylay.h>
#include "util.h"
namespace h2load {
struct Client;
class SpdySession : public Session {
public:
SpdySession(Client *client, uint16_t spdy_version);
virtual ~SpdySession();
virtual void on_connect();
virtual int submit_request();
virtual int on_read(const uint8_t *data, size_t len);
virtual int on_write();
virtual void terminate();
virtual size_t max_concurrent_streams();
void handle_window_update(int32_t stream_id, size_t recvlen);
private:
Client *client_;
spdylay_session *session_;
uint16_t spdy_version_;
};
} // namespace h2load
#endif // H2LOAD_SPDY_SESSION_H

View File

@@ -36,6 +36,8 @@ StringRef get_reason_phrase(unsigned int status_code) {
return StringRef::from_lit("Continue");
case 101:
return StringRef::from_lit("Switching Protocols");
case 103:
return StringRef::from_lit("Early Hints");
case 200:
return StringRef::from_lit("OK");
case 201:
@@ -140,6 +142,8 @@ StringRef stringify_status(BlockAllocator &balloc, unsigned int status_code) {
return StringRef::from_lit("100");
case 101:
return StringRef::from_lit("101");
case 103:
return StringRef::from_lit("103");
case 200:
return StringRef::from_lit("200");
case 201:
@@ -358,15 +362,21 @@ nghttp2_nv make_nv_nocopy(const StringRef &name, const StringRef &value,
namespace {
void copy_headers_to_nva_internal(std::vector<nghttp2_nv> &nva,
const HeaderRefs &headers, uint8_t nv_flags) {
for (auto &kv : headers) {
if (kv.name.empty() || kv.name[0] == ':') {
const HeaderRefs &headers, uint8_t nv_flags,
uint32_t flags) {
auto it_forwarded = std::end(headers);
auto it_xff = std::end(headers);
auto it_xfp = std::end(headers);
auto it_via = std::end(headers);
for (auto it = std::begin(headers); it != std::end(headers); ++it) {
auto kv = &(*it);
if (kv->name.empty() || kv->name[0] == ':') {
continue;
}
switch (kv.token) {
switch (kv->token) {
case HD_COOKIE:
case HD_CONNECTION:
case HD_FORWARDED:
case HD_HOST:
case HD_HTTP2_SETTINGS:
case HD_KEEP_ALIVE:
@@ -375,51 +385,157 @@ void copy_headers_to_nva_internal(std::vector<nghttp2_nv> &nva,
case HD_TE:
case HD_TRANSFER_ENCODING:
case HD_UPGRADE:
case HD_VIA:
case HD_X_FORWARDED_FOR:
case HD_X_FORWARDED_PROTO:
continue;
case HD_FORWARDED:
if (flags & HDOP_STRIP_FORWARDED) {
continue;
}
if (it_forwarded == std::end(headers)) {
it_forwarded = it;
continue;
}
kv = &(*it_forwarded);
it_forwarded = it;
break;
case HD_X_FORWARDED_FOR:
if (flags & HDOP_STRIP_X_FORWARDED_FOR) {
continue;
}
if (it_xff == std::end(headers)) {
it_xff = it;
continue;
}
kv = &(*it_xff);
it_xff = it;
break;
case HD_X_FORWARDED_PROTO:
if (flags & HDOP_STRIP_X_FORWARDED_PROTO) {
continue;
}
if (it_xfp == std::end(headers)) {
it_xfp = it;
continue;
}
kv = &(*it_xfp);
it_xfp = it;
break;
case HD_VIA:
if (flags & HDOP_STRIP_VIA) {
continue;
}
if (it_via == std::end(headers)) {
it_via = it;
continue;
}
kv = &(*it_via);
it_via = it;
break;
}
nva.push_back(make_nv_internal(kv.name, kv.value, kv.no_index, nv_flags));
nva.push_back(
make_nv_internal(kv->name, kv->value, kv->no_index, nv_flags));
}
}
} // namespace
void copy_headers_to_nva(std::vector<nghttp2_nv> &nva,
const HeaderRefs &headers) {
copy_headers_to_nva_internal(nva, headers, NGHTTP2_NV_FLAG_NONE);
const HeaderRefs &headers, uint32_t flags) {
copy_headers_to_nva_internal(nva, headers, NGHTTP2_NV_FLAG_NONE, flags);
}
void copy_headers_to_nva_nocopy(std::vector<nghttp2_nv> &nva,
const HeaderRefs &headers) {
copy_headers_to_nva_internal(nva, headers, NGHTTP2_NV_FLAG_NO_COPY_NAME |
NGHTTP2_NV_FLAG_NO_COPY_VALUE);
const HeaderRefs &headers, uint32_t flags) {
copy_headers_to_nva_internal(
nva, headers,
NGHTTP2_NV_FLAG_NO_COPY_NAME | NGHTTP2_NV_FLAG_NO_COPY_VALUE, flags);
}
void build_http1_headers_from_headers(DefaultMemchunks *buf,
const HeaderRefs &headers) {
for (auto &kv : headers) {
if (kv.name.empty() || kv.name[0] == ':') {
const HeaderRefs &headers,
uint32_t flags) {
auto it_forwarded = std::end(headers);
auto it_xff = std::end(headers);
auto it_xfp = std::end(headers);
auto it_via = std::end(headers);
for (auto it = std::begin(headers); it != std::end(headers); ++it) {
auto kv = &(*it);
if (kv->name.empty() || kv->name[0] == ':') {
continue;
}
switch (kv.token) {
switch (kv->token) {
case HD_CONNECTION:
case HD_COOKIE:
case HD_FORWARDED:
case HD_HOST:
case HD_HTTP2_SETTINGS:
case HD_KEEP_ALIVE:
case HD_PROXY_CONNECTION:
case HD_SERVER:
case HD_UPGRADE:
case HD_VIA:
case HD_X_FORWARDED_FOR:
case HD_X_FORWARDED_PROTO:
continue;
case HD_FORWARDED:
if (flags & HDOP_STRIP_FORWARDED) {
continue;
}
if (it_forwarded == std::end(headers)) {
it_forwarded = it;
continue;
}
kv = &(*it_forwarded);
it_forwarded = it;
break;
case HD_X_FORWARDED_FOR:
if (flags & HDOP_STRIP_X_FORWARDED_FOR) {
continue;
}
if (it_xff == std::end(headers)) {
it_xff = it;
continue;
}
kv = &(*it_xff);
it_xff = it;
break;
case HD_X_FORWARDED_PROTO:
if (flags & HDOP_STRIP_X_FORWARDED_PROTO) {
continue;
}
if (it_xfp == std::end(headers)) {
it_xfp = it;
continue;
}
kv = &(*it_xfp);
it_xfp = it;
break;
case HD_VIA:
if (flags & HDOP_STRIP_VIA) {
continue;
}
if (it_via == std::end(headers)) {
it_via = it;
continue;
}
kv = &(*it_via);
it_via = it;
break;
}
capitalize(buf, kv.name);
capitalize(buf, kv->name);
buf->append(": ");
buf->append(kv.value);
buf->append(kv->value);
buf->append("\r\n");
}
}
@@ -1486,7 +1602,7 @@ template <typename InputIt> InputIt eat_file(InputIt first, InputIt last) {
for (; p != first && *(p - 1) != '/'; --p)
;
if (p == first) {
// this should not happend in normal case, where we expect path
// this should not happened in normal case, where we expect path
// starts with '/'
*first++ = '/';
return first;

View File

@@ -187,24 +187,50 @@ nghttp2_nv make_nv_ls_nocopy(const char (&name)[N], const StringRef &value) {
NGHTTP2_NV_FLAG_NO_COPY_NAME | NGHTTP2_NV_FLAG_NO_COPY_VALUE};
}
enum HeaderBuildOp {
HDOP_NONE,
// Forwarded header fields must be stripped. If this flag is not
// set, all Forwarded header fields other than last one are added.
HDOP_STRIP_FORWARDED = 1,
// X-Forwarded-For header fields must be stripped. If this flag is
// not set, all X-Forwarded-For header fields other than last one
// are added.
HDOP_STRIP_X_FORWARDED_FOR = 1 << 1,
// X-Forwarded-Proto header fields must be stripped. If this flag
// is not set, all X-Forwarded-Proto header fields other than last
// one are added.
HDOP_STRIP_X_FORWARDED_PROTO = 1 << 2,
// Via header fields must be stripped. If this flag is not set, all
// Via header fields other than last one are added.
HDOP_STRIP_VIA = 1 << 3,
// Strip above all header fields.
HDOP_STRIP_ALL = HDOP_STRIP_FORWARDED | HDOP_STRIP_X_FORWARDED_FOR |
HDOP_STRIP_X_FORWARDED_PROTO | HDOP_STRIP_VIA,
};
// Appends headers in |headers| to |nv|. |headers| must be indexed
// before this call (its element's token field is assigned). Certain
// headers, including disallowed headers in HTTP/2 spec and headers
// which require special handling (i.e. via), are not copied.
// which require special handling (i.e. via), are not copied. |flags|
// is one or more of HeaderBuildOp flags. They tell function that
// certain header fields should not be added.
void copy_headers_to_nva(std::vector<nghttp2_nv> &nva,
const HeaderRefs &headers);
const HeaderRefs &headers, uint32_t flags);
// Just like copy_headers_to_nva(), but this adds
// NGHTTP2_NV_FLAG_NO_COPY_NAME and NGHTTP2_NV_FLAG_NO_COPY_VALUE.
void copy_headers_to_nva_nocopy(std::vector<nghttp2_nv> &nva,
const HeaderRefs &headers);
const HeaderRefs &headers, uint32_t flags);
// Appends HTTP/1.1 style header lines to |buf| from headers in
// |headers|. |headers| must be indexed before this call (its
// element's token field is assigned). Certain headers, which
// requires special handling (i.e. via and cookie), are not appended.
// |flags| is one or more of HeaderBuildOp flags. They tell function
// that certain header fields should not be added.
void build_http1_headers_from_headers(DefaultMemchunks *buf,
const HeaderRefs &headers);
const HeaderRefs &headers,
uint32_t flags);
// Return positive window_size_increment if WINDOW_UPDATE should be
// sent for the stream |stream_id|. If |stream_id| == 0, this function
@@ -242,7 +268,7 @@ void erase_header(HeaderRef *hd);
//
// This function returns the new rewritten URI on success. If the
// location URI is not subject to the rewrite, this function returns
// emtpy string.
// empty string.
StringRef rewrite_location_uri(BlockAllocator &balloc, const StringRef &uri,
const http_parser_url &u,
const StringRef &match_host,

View File

@@ -150,11 +150,33 @@ auto headers = HeaderRefs{
{StringRef::from_lit("zulu"), StringRef::from_lit("12")}};
} // namespace
namespace {
auto headers2 = HeaderRefs{
{StringRef::from_lit("x-forwarded-for"), StringRef::from_lit("xff1"), false,
http2::HD_X_FORWARDED_FOR},
{StringRef::from_lit("x-forwarded-for"), StringRef::from_lit("xff2"), false,
http2::HD_X_FORWARDED_FOR},
{StringRef::from_lit("x-forwarded-proto"), StringRef::from_lit("xfp1"),
false, http2::HD_X_FORWARDED_PROTO},
{StringRef::from_lit("x-forwarded-proto"), StringRef::from_lit("xfp2"),
false, http2::HD_X_FORWARDED_PROTO},
{StringRef::from_lit("forwarded"), StringRef::from_lit("fwd1"), false,
http2::HD_FORWARDED},
{StringRef::from_lit("forwarded"), StringRef::from_lit("fwd2"), false,
http2::HD_FORWARDED},
{StringRef::from_lit("via"), StringRef::from_lit("via1"), false,
http2::HD_VIA},
{StringRef::from_lit("via"), StringRef::from_lit("via2"), false,
http2::HD_VIA},
};
} // namespace
void test_http2_copy_headers_to_nva(void) {
auto ans = std::vector<int>{0, 1, 4, 5, 6, 7, 12};
std::vector<nghttp2_nv> nva;
http2::copy_headers_to_nva_nocopy(nva, headers);
http2::copy_headers_to_nva_nocopy(nva, headers,
http2::HDOP_STRIP_X_FORWARDED_FOR);
CU_ASSERT(7 == nva.size());
for (size_t i = 0; i < ans.size(); ++i) {
check_nv(headers[ans[i]], &nva[i]);
@@ -169,7 +191,7 @@ void test_http2_copy_headers_to_nva(void) {
}
nva.clear();
http2::copy_headers_to_nva(nva, headers);
http2::copy_headers_to_nva(nva, headers, http2::HDOP_STRIP_X_FORWARDED_FOR);
CU_ASSERT(7 == nva.size());
for (size_t i = 0; i < ans.size(); ++i) {
check_nv(headers[ans[i]], &nva[i]);
@@ -180,12 +202,27 @@ void test_http2_copy_headers_to_nva(void) {
CU_ASSERT(NGHTTP2_NV_FLAG_NONE == nva[i].flags);
}
}
nva.clear();
auto ans2 = std::vector<int>{0, 2, 4, 6};
http2::copy_headers_to_nva(nva, headers2, http2::HDOP_NONE);
CU_ASSERT(ans2.size() == nva.size());
for (size_t i = 0; i < ans2.size(); ++i) {
check_nv(headers2[ans2[i]], &nva[i]);
}
nva.clear();
http2::copy_headers_to_nva(nva, headers2, http2::HDOP_STRIP_ALL);
CU_ASSERT(nva.empty());
}
void test_http2_build_http1_headers_from_headers(void) {
MemchunkPool pool;
DefaultMemchunks buf(&pool);
http2::build_http1_headers_from_headers(&buf, headers);
http2::build_http1_headers_from_headers(&buf, headers,
http2::HDOP_STRIP_X_FORWARDED_FOR);
auto hdrs = std::string(buf.head->pos, buf.head->last);
CU_ASSERT("Alpha: 0\r\n"
"Bravo: 1\r\n"
@@ -196,6 +233,21 @@ void test_http2_build_http1_headers_from_headers(void) {
"Te: 8\r\n"
"Te: 9\r\n"
"Zulu: 12\r\n" == hdrs);
buf.reset();
http2::build_http1_headers_from_headers(&buf, headers2, http2::HDOP_NONE);
hdrs = std::string(buf.head->pos, buf.head->last);
CU_ASSERT("X-Forwarded-For: xff1\r\n"
"X-Forwarded-Proto: xfp1\r\n"
"Forwarded: fwd1\r\n"
"Via: via1\r\n" == hdrs);
buf.reset();
http2::build_http1_headers_from_headers(&buf, headers2,
http2::HDOP_STRIP_ALL);
CU_ASSERT(0 == buf.rleft());
}
void test_http2_lws(void) {

View File

@@ -118,6 +118,28 @@ private:
std::unique_ptr<request_impl> impl_;
};
// Wrapper around an nghttp2_priority_spec.
class priority_spec {
public:
// The default ctor is used only by sentinel values.
priority_spec() = default;
// Create a priority spec with the given priority settings.
explicit priority_spec(const int32_t stream_id, const int32_t weight,
const bool exclusive = false);
// Return a pointer to a valid nghttp2 priority spec, or null.
const nghttp2_priority_spec *get() const;
// Indicates whether or not this spec is valid (i.e. was constructed with
// values).
const bool valid() const;
private:
nghttp2_priority_spec spec_;
bool valid_ = false;
};
class session_impl;
class session {
@@ -177,7 +199,8 @@ public:
// succeeds, or nullptr and |ec| contains error message.
const request *submit(boost::system::error_code &ec,
const std::string &method, const std::string &uri,
header_map h = header_map{}) const;
header_map h = header_map{},
priority_spec prio = priority_spec()) const;
// Submits request to server using |method| (e.g., "GET"), |uri|
// (e.g., "http://localhost/") and optionally additional header
@@ -186,7 +209,8 @@ public:
// contains error message.
const request *submit(boost::system::error_code &ec,
const std::string &method, const std::string &uri,
std::string data, header_map h = header_map{}) const;
std::string data, header_map h = header_map{},
priority_spec prio = priority_spec()) const;
// Submits request to server using |method| (e.g., "GET"), |uri|
// (e.g., "http://localhost/") and optionally additional header
@@ -195,7 +219,8 @@ public:
// nullptr and |ec| contains error message.
const request *submit(boost::system::error_code &ec,
const std::string &method, const std::string &uri,
generator_cb cb, header_map h = header_map{}) const;
generator_cb cb, header_map h = header_map{},
priority_spec prio = priority_spec()) const;
private:
std::shared_ptr<session_impl> impl_;

View File

@@ -48,7 +48,9 @@
namespace nghttp2 {
typedef struct { int dump_header_table; } inflate_config;
typedef struct {
int dump_header_table;
} inflate_config;
static inflate_config config;

View File

@@ -28,7 +28,15 @@
#include "nghttp2_config.h"
#include <limits.h>
#ifdef _WIN32
/* Structure for scatter/gather I/O. */
struct iovec {
void *iov_base; /* Pointer to data. */
size_t iov_len; /* Length of data. */
};
#else // !_WIN32
#include <sys/uio.h>
#endif // !_WIN32
#include <cassert>
#include <cstring>
@@ -50,23 +58,21 @@ namespace nghttp2 {
#endif // !defined(IOV_MAX) || IOV_MAX >= DEFAULT_WR_IOVCNT
template <size_t N> struct Memchunk {
Memchunk(std::unique_ptr<Memchunk> next_chunk)
: pos(std::begin(buf)),
last(pos),
knext(std::move(next_chunk)),
next(nullptr) {}
Memchunk(Memchunk *next_chunk)
: pos(std::begin(buf)), last(pos), knext(next_chunk), next(nullptr) {}
size_t len() const { return last - pos; }
size_t left() const { return std::end(buf) - last; }
void reset() { pos = last = std::begin(buf); }
std::array<uint8_t, N> buf;
uint8_t *pos, *last;
std::unique_ptr<Memchunk> knext;
Memchunk *knext;
Memchunk *next;
static const size_t size = N;
};
template <typename T> struct Pool {
Pool() : pool(nullptr), freelist(nullptr), poolsize(0) {}
~Pool() { clear(); }
T *get() {
if (freelist) {
auto m = freelist;
@@ -76,9 +82,9 @@ template <typename T> struct Pool {
return m;
}
pool = make_unique<T>(std::move(pool));
pool = new T{pool};
poolsize += T::size;
return pool.get();
return pool;
}
void recycle(T *m) {
m->next = freelist;
@@ -86,11 +92,16 @@ template <typename T> struct Pool {
}
void clear() {
freelist = nullptr;
for (auto p = pool; p;) {
auto knext = p->knext;
delete p;
p = knext;
}
pool = nullptr;
poolsize = 0;
}
using value_type = T;
std::unique_ptr<T> pool;
T *pool;
T *freelist;
size_t poolsize;
};

View File

@@ -42,34 +42,34 @@ void test_pool_recycle(void) {
auto m1 = pool.get();
CU_ASSERT(m1 == pool.pool.get());
CU_ASSERT(m1 == pool.pool);
CU_ASSERT(MemchunkPool::value_type::size == pool.poolsize);
CU_ASSERT(nullptr == pool.freelist);
auto m2 = pool.get();
CU_ASSERT(m2 == pool.pool.get());
CU_ASSERT(m2 == pool.pool);
CU_ASSERT(2 * MemchunkPool::value_type::size == pool.poolsize);
CU_ASSERT(nullptr == pool.freelist);
CU_ASSERT(m1 == m2->knext.get());
CU_ASSERT(nullptr == m1->knext.get());
CU_ASSERT(m1 == m2->knext);
CU_ASSERT(nullptr == m1->knext);
auto m3 = pool.get();
CU_ASSERT(m3 == pool.pool.get());
CU_ASSERT(m3 == pool.pool);
CU_ASSERT(3 * MemchunkPool::value_type::size == pool.poolsize);
CU_ASSERT(nullptr == pool.freelist);
pool.recycle(m3);
CU_ASSERT(m3 == pool.pool.get());
CU_ASSERT(m3 == pool.pool);
CU_ASSERT(3 * MemchunkPool::value_type::size == pool.poolsize);
CU_ASSERT(m3 == pool.freelist);
auto m4 = pool.get();
CU_ASSERT(m3 == m4);
CU_ASSERT(m4 == pool.pool.get());
CU_ASSERT(m4 == pool.pool);
CU_ASSERT(3 * MemchunkPool::value_type::size == pool.poolsize);
CU_ASSERT(nullptr == pool.freelist);

View File

@@ -33,7 +33,11 @@
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif // HAVE_SYS_SOCKET_H
#ifdef _WIN32
#include <ws2tcpip.h>
#else // !_WIN32
#include <sys/un.h>
#endif // !_WIN32
#ifdef HAVE_NETINET_IN_H
#include <netinet/in.h>
#endif // HAVE_NETINET_IN_H
@@ -48,7 +52,9 @@ union sockaddr_union {
sockaddr sa;
sockaddr_in6 in6;
sockaddr_in in;
#ifndef _WIN32
sockaddr_un un;
#endif // !_WIN32
};
struct Address {

View File

@@ -57,7 +57,7 @@
#include "HtmlParser.h"
#include "util.h"
#include "base64.h"
#include "ssl.h"
#include "tls.h"
#include "template.h"
#ifndef O_BINARY
@@ -89,7 +89,11 @@ enum {
namespace {
constexpr auto anchors = std::array<Anchor, 5>{{
{3, 0, 201}, {5, 0, 101}, {7, 0, 1}, {9, 7, 1}, {11, 3, 1},
{3, 0, 201},
{5, 0, 101},
{7, 0, 1},
{9, 7, 1},
{11, 3, 1},
}};
} // namespace
@@ -116,7 +120,8 @@ Config::Config()
no_dep(false),
hexdump(false),
no_push(false),
expect_continue(false) {
expect_continue(false),
verify_peer(true) {
nghttp2_option_new(&http2_option);
nghttp2_option_set_peer_max_concurrent_streams(http2_option,
peer_max_concurrent_streams);
@@ -171,6 +176,8 @@ Request::~Request() { nghttp2_gzip_inflate_del(inflater); }
void Request::init_inflater() {
int rv;
// This is required with --disable-assert.
(void)rv;
rv = nghttp2_gzip_inflate_new(&inflater);
assert(rv == 0);
}
@@ -401,17 +408,10 @@ int htp_msg_begincb(http_parser *htp) {
}
} // namespace
namespace {
int htp_statuscb(http_parser *htp, const char *at, size_t length) {
auto client = static_cast<HttpClient *>(htp->data);
client->upgrade_response_status_code = htp->status_code;
return 0;
}
} // namespace
namespace {
int htp_msg_completecb(http_parser *htp) {
auto client = static_cast<HttpClient *>(htp->data);
client->upgrade_response_status_code = htp->status_code;
client->upgrade_response_complete = true;
return 0;
}
@@ -421,7 +421,7 @@ namespace {
constexpr http_parser_settings htp_hooks = {
htp_msg_begincb, // http_cb on_message_begin;
nullptr, // http_data_cb on_url;
htp_statuscb, // http_data_cb on_status;
nullptr, // http_data_cb on_status;
nullptr, // http_data_cb on_header_field;
nullptr, // http_data_cb on_header_value;
nullptr, // http_cb on_headers_complete;
@@ -646,6 +646,11 @@ int HttpClient::resolve_host(const std::string &host, uint16_t port) {
return 0;
}
namespace {
// Just returns 1 to continue handshake.
int verify_cb(int preverify_ok, X509_STORE_CTX *ctx) { return 1; }
} // namespace
int HttpClient::initiate_connection() {
int rv;
@@ -675,6 +680,17 @@ int HttpClient::initiate_connection() {
const auto &host_string =
config.host_override.empty() ? host : config.host_override;
#if (!defined(LIBRESSL_VERSION_NUMBER) && \
OPENSSL_VERSION_NUMBER >= 0x10002000L) || \
defined(OPENSSL_IS_BORINGSSL)
auto param = SSL_get0_param(ssl);
X509_VERIFY_PARAM_set_hostflags(param, 0);
X509_VERIFY_PARAM_set1_host(param, host_string.c_str(),
host_string.size());
#endif // (!defined(LIBRESSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >=
// 0x10002000L) || defined(OPENSSL_IS_BORINGSSL)
SSL_set_verify(ssl, SSL_VERIFY_PEER, verify_cb);
if (!util::numeric_host(host_string.c_str())) {
SSL_set_tlsext_host_name(ssl, host_string.c_str());
}
@@ -1295,6 +1311,14 @@ int HttpClient::tls_handshake() {
readfn = &HttpClient::read_tls;
writefn = &HttpClient::write_tls;
if (config.verify_peer) {
auto verify_res = SSL_get_verify_result(ssl);
if (verify_res != X509_V_OK) {
std::cerr << "[WARNING] Certificate verification failed: "
<< X509_verify_cert_error_string(verify_res) << std::endl;
}
}
if (connection_made() != 0) {
return -1;
}
@@ -2247,15 +2271,20 @@ int communicate(
SSL_CTX_set_mode(ssl_ctx, SSL_MODE_AUTO_RETRY);
SSL_CTX_set_mode(ssl_ctx, SSL_MODE_RELEASE_BUFFERS);
if (nghttp2::ssl::ssl_ctx_set_proto_versions(
ssl_ctx, nghttp2::ssl::NGHTTP2_TLS_MIN_VERSION,
nghttp2::ssl::NGHTTP2_TLS_MAX_VERSION) != 0) {
if (SSL_CTX_set_default_verify_paths(ssl_ctx) != 1) {
std::cerr << "[WARNING] Could not load system trusted CA certificates: "
<< ERR_error_string(ERR_get_error(), nullptr) << std::endl;
}
if (nghttp2::tls::ssl_ctx_set_proto_versions(
ssl_ctx, nghttp2::tls::NGHTTP2_TLS_MIN_VERSION,
nghttp2::tls::NGHTTP2_TLS_MAX_VERSION) != 0) {
std::cerr << "[ERROR] Could not set TLS versions" << std::endl;
result = -1;
goto fin;
}
if (SSL_CTX_set_cipher_list(ssl_ctx, ssl::DEFAULT_CIPHER_LIST) == 0) {
if (SSL_CTX_set_cipher_list(ssl_ctx, tls::DEFAULT_CIPHER_LIST) == 0) {
std::cerr << "[ERROR] " << ERR_error_string(ERR_get_error(), nullptr)
<< std::endl;
result = -1;
@@ -2433,8 +2462,8 @@ int run(char **uris, int n) {
nghttp2_session_callbacks_set_on_invalid_frame_recv_callback(
callbacks, verbose_on_invalid_frame_recv_callback);
nghttp2_session_callbacks_set_error_callback(callbacks,
verbose_error_callback);
nghttp2_session_callbacks_set_error_callback2(callbacks,
verbose_error_callback);
}
nghttp2_session_callbacks_set_on_data_chunk_recv_callback(
@@ -2701,6 +2730,9 @@ Options:
(up to a short timeout) until the server sends a 100
Continue interim response. This option is ignored unless
combined with the -d option.
-y, --no-verify-peer
Suppress warning on server certificate verification
failure.
--version Display version information and exit.
-h, --help Display this help and exit.
@@ -2718,7 +2750,7 @@ Options:
} // namespace
int main(int argc, char **argv) {
ssl::libssl_init();
tls::libssl_init();
bool color = false;
while (1) {
@@ -2742,6 +2774,7 @@ int main(int argc, char **argv) {
{"header-table-size", required_argument, nullptr, 'c'},
{"padding", required_argument, nullptr, 'b'},
{"har", required_argument, nullptr, 'r'},
{"no-verify-peer", no_argument, nullptr, 'y'},
{"cert", required_argument, &flag, 1},
{"key", required_argument, &flag, 2},
{"color", no_argument, &flag, 3},
@@ -2757,8 +2790,9 @@ int main(int argc, char **argv) {
{"encoder-header-table-size", required_argument, &flag, 14},
{nullptr, 0, nullptr, 0}};
int option_index = 0;
int c = getopt_long(argc, argv, "M:Oab:c:d:gm:np:r:hH:vst:uw:W:",
long_options, &option_index);
int c =
getopt_long(argc, argv, "M:Oab:c:d:m:np:r:hH:vst:uw:yW:", long_options,
&option_index);
if (c == -1) {
break;
}
@@ -2888,6 +2922,9 @@ int main(int argc, char **argv) {
config.min_header_table_size = std::min(config.min_header_table_size, n);
break;
}
case 'y':
config.verify_peer = false;
break;
case '?':
util::show_candidates(argv[optind - 1], long_options);
exit(EXIT_FAILURE);

View File

@@ -96,6 +96,7 @@ struct Config {
bool hexdump;
bool no_push;
bool expect_continue;
bool verify_peer;
};
enum class RequestState { INITIAL, ON_REQUEST, ON_RESPONSE, ON_COMPLETE };

View File

@@ -72,6 +72,7 @@ int nghttp2_gzip_inflate(nghttp2_gzip *inflater, uint8_t *out,
switch (rv) {
case Z_STREAM_END:
inflater->finished = 1;
/* FALL THROUGH */
case Z_OK:
case Z_BUF_ERROR:
return 0;

View File

@@ -43,14 +43,14 @@ static size_t deflate_data(uint8_t *out, size_t outlen, const uint8_t *in,
zst.opaque = Z_NULL;
rv = deflateInit(&zst, Z_DEFAULT_COMPRESSION);
assert(rv == Z_OK);
CU_ASSERT(rv == Z_OK);
zst.avail_in = (unsigned int)inlen;
zst.next_in = (uint8_t *)in;
zst.avail_out = (unsigned int)outlen;
zst.next_out = out;
rv = deflate(&zst, Z_SYNC_FLUSH);
assert(rv == Z_OK);
CU_ASSERT(rv == Z_OK);
deflateEnd(&zst);

View File

@@ -48,7 +48,7 @@
#include "app_helper.h"
#include "HttpServer.h"
#include "util.h"
#include "ssl.h"
#include "tls.h"
namespace nghttp2 {
@@ -174,8 +174,7 @@ Options:
--mime-types-file=<PATH>
Path to file that contains MIME media types and the
extensions that represent them.
Default: )"
<< config.mime_types_file << R"(
Default: )" << config.mime_types_file << R"(
--no-content-length
Don't send content-length header field.
--version Display version information and exit.
@@ -190,10 +189,10 @@ Options:
} // namespace
int main(int argc, char **argv) {
ssl::libssl_init();
tls::libssl_init();
#ifndef NOTHREADS
ssl::LibsslGlobalLock lock;
tls::LibsslGlobalLock lock;
#endif // NOTHREADS
Config config;

Some files were not shown because too many files have changed in this diff Show More