Compare commits

...

395 Commits

Author SHA1 Message Date
Tatsuhiro Tsujikawa
5a8d5e5dd9 Update man pages 2015-06-23 23:22:35 +09:00
Tatsuhiro Tsujikawa
9bcb0ffdef Bump up version number to 1.0.4, LT revision to 14:4:0 2015-06-23 23:20:13 +09:00
Tatsuhiro Tsujikawa
1945d0f02a Fix assertion failure in nghttp2_stream.c
This is regression introduced in
46b70c1db8.
2015-06-23 23:04:53 +09:00
Tatsuhiro Tsujikawa
4870edb33d Bump up version number to 1.0.4-DEV 2015-06-23 01:02:48 +09:00
Tatsuhiro Tsujikawa
3abb162969 Update man pages 2015-06-23 00:54:09 +09:00
Tatsuhiro Tsujikawa
4242478f39 Update nghttpx man page template 2015-06-23 00:53:51 +09:00
Tatsuhiro Tsujikawa
4fa2ffe292 Dump up version number to 1.0.3, LT revision to 14:3:0 2015-06-23 00:48:23 +09:00
Tatsuhiro Tsujikawa
301df2a856 src: Disable SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS 2015-06-22 23:26:45 +09:00
Tatsuhiro Tsujikawa
f3b7f4140b nghttpx: Clarify origin host for --backend-http1-connection-per-host 2015-06-22 21:09:39 +09:00
Tatsuhiro Tsujikawa
878b873c69 src: Use using instead of typedef 2015-06-21 19:37:50 +09:00
Tatsuhiro Tsujikawa
2ca8cf36b7 util: Use constexpr for ALPN id 2015-06-21 19:34:43 +09:00
Tatsuhiro Tsujikawa
2224b98c9c Remove duplicated dependency validation in nghttp2_session_reprioritize_stream 2015-06-21 16:31:30 +09:00
Tatsuhiro Tsujikawa
a7031da364 Fix bug that idle self-depending PRIORITY is not handled gracefully
Previously, we did not handle PRIORITY frame which depends on itself
and for idle stream.  As a result, nghttp2_session_mem_recv (or
nghttp2_session_recv) returne NGHTTP2_ERR_NOMEM.  The error code was
still misleading.  It was not out of memory, and we failed to insert
hash map because of duplicated key, which was treated as out of
memory.  This commit fixes this issue, by explicitly checking
dependency for incoming PRIORITY for all cases.
2015-06-21 16:02:32 +09:00
Tatsuhiro Tsujikawa
cebfdacc5a src: Use user-defined literals for time (hours and minutes) 2015-06-21 14:51:32 +09:00
Tatsuhiro Tsujikawa
39f89f4a60 src: Use user-defined literals for k, m, and g. 2015-06-21 14:32:47 +09:00
Tatsuhiro Tsujikawa
46b70c1db8 Optimize dependency based priority code to Firefox style tree
While this commit optimizes dependency routine to Firefox style tree,
the other use cases (e.g., linear chain) are also improved
dramatically as well.
2015-06-20 22:11:24 +09:00
Tatsuhiro Tsujikawa
5537503172 Merge branch 'jfcalcerrada-patch-1' 2015-06-20 19:42:09 +09:00
José F. Calcerrada
81cc550eb9 Update README.rst
Typo
2015-06-20 11:02:33 +01:00
Tatsuhiro Tsujikawa
0a6de0d378 nghttp: Perform special handling of IPv6 literal with zone ID as per RFC 6874
This commit adds special handling of IPv6 literal with zone ID as per
RFC 6874.  Still IPv6 link local address does not work, since URI
parser from http-parser does not allow this syntax.
2015-06-18 20:00:02 +09:00
Tatsuhiro Tsujikawa
25d1de0278 nghttp: Print error if all connect() syscall faild 2015-06-18 18:03:25 +09:00
Tatsuhiro Tsujikawa
39eb8b8a6b nghttp: Print error when parsing URI failed 2015-06-18 18:00:24 +09:00
Tatsuhiro Tsujikawa
c050fca177 Merge branch 'vapier-master' 2015-06-18 17:55:50 +09:00
Mike Frysinger
19309823aa enable third-party for asio_lib too
Since this library uses the third-party subdir, make sure we auto-enable
it when that lib is turned on.
2015-06-17 13:29:37 -04:00
Tatsuhiro Tsujikawa
90bcdb0dda Merge branch 'libressl' 2015-06-17 18:27:54 +09:00
Tatsuhiro Tsujikawa
17ec30e45c Mention LibreSSL in README.rst 2015-06-17 18:27:27 +09:00
Tatsuhiro Tsujikawa
07f763be49 fetch-ocsp-response: Support LibreSSL, and include port in ocsp_host 2015-06-17 18:24:57 +09:00
Tatsuhiro Tsujikawa
69119f47c4 src: Support compile with LibreSSL 2015-06-17 18:24:51 +09:00
Tatsuhiro Tsujikawa
b0b792e735 integration: Add tests for x-forwarded-proto header field 2015-06-16 21:31:47 +09:00
Tatsuhiro Tsujikawa
8aab74ad36 nghttpx: Refactor a bit 2015-06-16 21:31:33 +09:00
Tatsuhiro Tsujikawa
f418d1239f nghttpx: Fix bug that XFP header always http on HTTP/2 backend
This commit fixes the bug that x-forwarded-proto header field sent on
HTTP/2 backend always "http", regardless of frontend scheme.
2015-06-16 21:29:47 +09:00
Tatsuhiro Tsujikawa
5b51320dc5 nghttpx: Validate :path on SPDY frontend
Unless method is CONNECT, we require that :path starts with "/",
except for OPTIONS method, which can take "*" as :path (server-wide
OPTIONS request).
2015-06-16 00:09:22 +09:00
Tatsuhiro Tsujikawa
d2e81da9e2 Bump up version number to 1.0.3-DEV 2015-06-12 22:58:14 +09:00
Tatsuhiro Tsujikawa
a61054e1f7 Update bash_completion 2015-06-12 22:38:32 +09:00
Tatsuhiro Tsujikawa
749f5d6a32 Update man pages 2015-06-12 22:38:19 +09:00
Tatsuhiro Tsujikawa
f09bd821ac Bump up version number to 1.0.2, LT revision to 14:2:0 2015-06-12 22:35:29 +09:00
Tatsuhiro Tsujikawa
6d5c00b8eb nghttpx: Use vector for WorkerEvent queue 2015-06-12 21:28:24 +09:00
Tatsuhiro Tsujikawa
532bffdb01 nghttpx: Minimize critical section for shared ocsp response 2015-06-12 21:27:12 +09:00
Tatsuhiro Tsujikawa
c6c7145167 Fix compile warning with android NDK 2015-06-12 19:19:53 +09:00
Tatsuhiro Tsujikawa
b5717cd288 Fix bug that data are not consumed for connection in race condition
When we know that stream is closed at time we read DATA frame header,
we use NGHTTP2_IB_IGN_DATA, and consume data for connection if
nghttp2_option_set_no_auto_window_update() is used.  However, if
stream is closed while we are in NGHTTP2_IB_READ_DATA, those bytes are
not consumed for connection, nor notified to application via callback,
so it eventually fills up connection window and connection will
freeze.  This commit fixes this issue by consuming these data for
connection when stream is closed or does not exist.
2015-06-11 23:34:30 +09:00
Tatsuhiro Tsujikawa
d4d7597efb nghttpx: Delete SSL_CTX on quit 2015-06-10 21:31:58 +09:00
Tatsuhiro Tsujikawa
2952706b53 Fix scan-build error 2015-06-10 00:29:03 +09:00
Tatsuhiro Tsujikawa
9b0ccdef34 h2load: Code cleanup 2015-06-10 00:28:27 +09:00
Tatsuhiro Tsujikawa
41dd5f6897 nghttpx: Tokenize request method
We share the same method value with http-parser.  This commit also
returns 501 for unknown request method on HTTP/2 and SPDY frontend.
2015-06-09 23:33:14 +09:00
Tatsuhiro Tsujikawa
f9c60d5e9d nghttpx: Return 501 if invalid method is received on h1 frontend 2015-06-09 22:08:49 +09:00
Tatsuhiro Tsujikawa
c2ca04c1db python: Call on_close callback when connection is lost for server session 2015-06-07 16:17:48 +09:00
Tatsuhiro Tsujikawa
5fbb99e3d0 Check python without python bindings to get PYTHON variable
We use PYTHON variable to execute Python script, mainly to generate
documents.  Therefore it is better to always check python interpreter
even if we don't request python bindings
2015-06-07 13:14:31 +09:00
Tatsuhiro Tsujikawa
ba34313f9f mkapiref.py: Ensure better 2 and 3 support 2015-06-07 13:13:51 +09:00
Tatsuhiro Tsujikawa
aa6699435a make_bash_completion.py: Support Python 3.4 2015-06-07 13:01:02 +09:00
Tatsuhiro Tsujikawa
e857e99df8 help2rst.py: Support Python 3.4 2015-06-07 12:55:22 +09:00
Tatsuhiro Tsujikawa
6d537c419e nghttpx: Document failure case on bind() 2015-06-07 00:05:33 +09:00
Tatsuhiro Tsujikawa
4894e24dc8 nghttpx: Add error logging for listener socket creation failure 2015-06-07 00:02:30 +09:00
Tatsuhiro Tsujikawa
bbbddedb8f Fix compiler warning 2015-06-06 23:37:46 +09:00
Tatsuhiro Tsujikawa
163dfb3150 Fix make distcheck failure 2015-06-06 23:37:31 +09:00
Tatsuhiro Tsujikawa
4f3d20e024 Include script/README.rst in dist 2015-06-06 23:32:32 +09:00
Tatsuhiro Tsujikawa
b7ba1baf48 Translate fetch-ocsp-response into Python 2015-06-06 23:18:32 +09:00
Tatsuhiro Tsujikawa
00efa86fb6 nghttpx: Add --add-request-header option 2015-06-05 23:04:20 +09:00
Tatsuhiro Tsujikawa
43b3640836 Slight code cleanup 2015-06-05 22:06:49 +09:00
Tatsuhiro Tsujikawa
708eb2a217 Increase maximum number of streams in one dep tree including idle nodes 2015-06-05 22:06:14 +09:00
Tatsuhiro Tsujikawa
590a5c3ff3 Fix typo 2015-06-05 00:18:29 +09:00
Tatsuhiro Tsujikawa
28b528dc9e Merge branch 'vapier-master' 2015-06-04 23:45:49 +09:00
Mike Frysinger
a50f6e5d50 configure: fix bashism
The == operator is not in POSIX; use = like normal.

Reported-by: Mikael Magnusson <mikachu@gmail.com>
2015-06-04 00:10:00 -04:00
Tatsuhiro Tsujikawa
1534edd3f3 Update building android doc to include zlib build instruction 2015-06-01 23:14:38 +09:00
Tatsuhiro Tsujikawa
892c159d8f Remove unused clock_gettime and dlsym detection 2015-06-01 23:05:42 +09:00
Tatsuhiro Tsujikawa
0cb4750e3c libevent-client: Fix bug that path is broken if URI does not contain path part 2015-06-01 00:22:35 +09:00
Tatsuhiro Tsujikawa
ee4d53a9e4 More constexpr 2015-05-31 18:44:37 +09:00
Tatsuhiro Tsujikawa
ad150c3ab1 Merge branch 'fwiesel-client_certificate' 2015-05-31 18:28:16 +09:00
Fabian Wiesel
7eafebfeb9 Expose client certificate, if available
Client certificates can use used for authentication/authorization in the server,
so expose them similar to the remote address.
2015-05-31 10:55:10 +02:00
Tatsuhiro Tsujikawa
3d59c6c0b7 nghttpx: Use defined string iteral when defining long_options 2015-05-29 22:48:46 +09:00
Tatsuhiro Tsujikawa
34efc6b7a4 More constexpr 2015-05-29 22:36:05 +09:00
Tatsuhiro Tsujikawa
7582640fd5 nghttpx: Remove unused 2015-05-29 22:20:46 +09:00
Tatsuhiro Tsujikawa
ad265aa9d0 Build third-party if either examples or apps is enabled 2015-05-28 22:55:47 +09:00
Tatsuhiro Tsujikawa
1f7e6ea3fe Define NGHTTP2_EXTERN to __declspec(dllimport) when using nghttp2
The private global variable nghttp2_enable_strict_preface is also
marked as NGHTTP2_EXTERN, but it is test purpose only (test with
.dll), and not part of public API.  It could be removed in the future
release.
2015-05-28 22:36:43 +09:00
Tatsuhiro Tsujikawa
a0a5f4f93e tests: Break if all compressed header input processed in nghttp2_buf 2015-05-27 00:33:24 +09:00
Tatsuhiro Tsujikawa
59e6272ba4 integration: Add WebSocket upgrade test 2015-05-26 23:28:45 +09:00
Tatsuhiro Tsujikawa
323fc8c552 nghttpx: Make WebSocket upgrade work
This commit makes sure that WebSocket upgrade works for HTTP/1.1
frontend and backend pair.  Actually, this implementation probably
supports other upgrade as well, other than HTTP/2 Upgrade, which is
handled specially in other place.
2015-05-26 22:26:17 +09:00
Tatsuhiro Tsujikawa
cbb10aa80f Merge branch 'fwiesel-python3.4-on-macos' 2015-05-26 00:48:42 +09:00
Fabian Wiesel
abe4c7c92a Catch and log failure to set TCP_NODELAY
Setting TCP_NODELAY may fail. Instead of failing the routine, log it and continue.
It seems, that setting TCP_NODELAY in python on Mac OS X is not necessarily supported.
2015-05-25 17:39:54 +02:00
Tatsuhiro Tsujikawa
326b4c467b nghttpx: Fix bug that END_STREAM is not set in backend for POST with Upgrade 2015-05-26 00:00:11 +09:00
Tatsuhiro Tsujikawa
7e51a87111 nghttpx: Don't upgrade to HTTP/2 if we have non-final HTTP/1 response pending 2015-05-25 23:59:44 +09:00
Tatsuhiro Tsujikawa
5fdb36239a nghttpx: Don't send Expect header field twice 2015-05-25 23:59:18 +09:00
Tatsuhiro Tsujikawa
9f99cad9ab Bump up version number to 1.0.2-DEV 2015-05-24 19:50:35 +09:00
Tatsuhiro Tsujikawa
7c7d4700f1 Update README.rst about go spdy package 2015-05-24 19:26:53 +09:00
Tatsuhiro Tsujikawa
8e5c8430f1 Update man pages 2015-05-24 19:21:24 +09:00
Tatsuhiro Tsujikawa
92ecd3c0fb Bump up version number to 1.0.1, LT revision to 14:1:0 2015-05-24 19:11:18 +09:00
Tatsuhiro Tsujikawa
90eac0709d src: Make sure that empty param is error when parsing Link header field 2015-05-24 15:40:16 +09:00
Tatsuhiro Tsujikawa
791660ef8d Fix up OpenSSL initialization
Use the example presented at
http://en.wikibooks.org/wiki/OpenSSL/Initialization
2015-05-23 00:23:38 +09:00
Tatsuhiro Tsujikawa
1c06cfd29f integration: Use our own copy of golang spdy package
Official golang spdy package is done.  We made a copy of it until we
drop spdy support.
2015-05-23 00:01:45 +09:00
Tatsuhiro Tsujikawa
f0379aa428 Fix invalid memory free 2015-05-22 23:36:34 +09:00
Tatsuhiro Tsujikawa
9a0b9428da nghttpx: Fill request scheme in upstream
We may log before filling scheme in Downstream, so we leave
construct_absolute_request_uri as is.
2015-05-22 02:22:59 +09:00
Tatsuhiro Tsujikawa
b20abfc11a nghttpx: Allow HTTP Upgrade from POST request if response header was not sent 2015-05-22 01:59:40 +09:00
Tatsuhiro Tsujikawa
d983dd81ec Update http-parser to 39ff0975c220ef76a2d98c8ac61b0d36f4dce80f 2015-05-22 01:55:47 +09:00
Tatsuhiro Tsujikawa
bcf9e66dbc Update README.rst 2015-05-22 01:40:23 +09:00
Tatsuhiro Tsujikawa
890a10b216 nghttpx: Fix bug that PUSH_PROMISE is sent after associated response HEADERS 2015-05-22 00:53:02 +09:00
Tatsuhiro Tsujikawa
28adb2dad3 h2load: Fix bug that NPN fails if ALPN is enabled 2015-05-22 00:48:32 +09:00
Tatsuhiro Tsujikawa
c795018f29 Dockerfile.android: Update NDK ver, and ubuntu; build and link zlib 2015-05-21 00:45:01 +09:00
Tatsuhiro Tsujikawa
c1a663b577 Don't link zlib bundled with android NDK 2015-05-21 00:15:04 +09:00
Tatsuhiro Tsujikawa
2b450f26ba Comment out uninstall-local for python
This uninstall-local rule is too strong; it could delete unexpected
files, although they are likely nghttp2 related.
2015-05-20 22:50:58 +09:00
Tatsuhiro Tsujikawa
1ddff5bbf9 Include stdint.h instead of inttypes.h when compiled with MSVC < 2013 2015-05-20 22:33:57 +09:00
Tatsuhiro Tsujikawa
3a4c8bc8f1 Document about small write 2015-05-19 22:56:23 +09:00
Tatsuhiro Tsujikawa
fe752174a9 nghttpd: Close connection after settings timeout and GOAWAY was sent 2015-05-18 21:38:12 +09:00
Tatsuhiro Tsujikawa
494ed221b6 Merge branch 'alagoutte-scan-build' 2015-05-16 02:17:28 +09:00
Tatsuhiro Tsujikawa
14f971d71f Merge branch 'scan-build' of https://github.com/alagoutte/nghttp2 into alagoutte-scan-build 2015-05-16 02:15:38 +09:00
Alexis La Goutte
ddee5d3896 fix Value stored to 'rv' is never read found by Clang Analyzer 2015-05-15 18:11:59 +02:00
Tatsuhiro Tsujikawa
447e346b1e Bump up version number to 1.0.1-DEV 2015-05-16 00:25:34 +09:00
Tatsuhiro Tsujikawa
553d741f03 Fix migration version number 2015-05-16 00:15:00 +09:00
Tatsuhiro Tsujikawa
6bd728b3c2 Update man pages 2015-05-16 00:10:41 +09:00
Tatsuhiro Tsujikawa
a99085891a Bump up version number to 1.0.0, LT revision to 14:0:0 2015-05-16 00:03:08 +09:00
Tatsuhiro Tsujikawa
68d3724fad Update README.rst 2015-05-15 23:55:30 +09:00
Tatsuhiro Tsujikawa
fe39ec8697 doc: Update Resources 2015-05-15 23:36:51 +09:00
Tatsuhiro Tsujikawa
c896118747 Fix required spdylay version 2015-05-15 23:32:15 +09:00
Tatsuhiro Tsujikawa
b89140c311 Merge branch 'v1.0.0' 2015-05-15 23:30:59 +09:00
Tatsuhiro Tsujikawa
a869c39a2c Bump up version number to 1.0.0-DEV 2015-05-15 23:30:24 +09:00
Tatsuhiro Tsujikawa
0b27f005e0 Merge branch 'master' into v1.0.0
Conflicts:
	src/HttpServer.cc
2015-05-15 23:24:19 +09:00
Tatsuhiro Tsujikawa
92a20c76e6 Update bash_completion 2015-05-15 23:01:33 +09:00
Tatsuhiro Tsujikawa
42ccea806c Update man pages 2015-05-15 23:01:19 +09:00
Tatsuhiro Tsujikawa
805f36d134 Bump up version number to 0.7.15, LT revision to 13:4:8 2015-05-15 22:59:00 +09:00
Tatsuhiro Tsujikawa
e2c0a3e43b Retry finding jemalloc lib by je_malloc_stats_print
Fixes GH-233
2015-05-15 22:40:49 +09:00
Tatsuhiro Tsujikawa
3572e7c634 inflatehd: Fix crash if 'wire' value is not string
Fixes GH-235
2015-05-15 22:29:57 +09:00
Tatsuhiro Tsujikawa
0479f833fc Revert "nghttpx: Remove last write/read fields for TLS"
This reverts commit 585af93828.
2015-05-15 22:20:15 +09:00
Tatsuhiro Tsujikawa
252aeb43e1 Add test for GH-232 2015-05-15 01:00:09 +09:00
Tatsuhiro Tsujikawa
24fe24b37d Merge branch 'etcimon-patch-1' 2015-05-15 00:57:07 +09:00
Etienne Cimon
32603d7eff Access violation in buffers
When adding a large amount of data that spans to multiple chunks, the pointer is incremented by the wrong value.
2015-05-14 10:45:17 -04:00
Tatsuhiro Tsujikawa
53bfc70c9e Include inttypes.h (or cintypes for C++) instead of stdint.h
From autoconf manual, section 5.6.1 Portability of Headers, says:

"""
The C99 standard says that inttypes.h includes stdint.h, so there's no
need to include stdint.h separately in a standard environment. Some
implementations have inttypes.h but not stdint.h (e.g., Solaris 7),
but we don't know of any implementation that has stdint.h but not
inttypes.h.
"""
2015-05-14 00:17:45 +09:00
Tatsuhiro Tsujikawa
c4068cd404 Fix travis build error
Remove AC_PROG_RANLIB because it is rendered obsolete by LT_INIT.
Remove AC_CHECK_HEADER_STDBOOl, because travis does not have one.
2015-05-13 23:48:31 +09:00
Tatsuhiro Tsujikawa
0aa17f64c1 doc: Remove 'NGHTTP2_EXTERN' from api doc 2015-05-13 23:39:48 +09:00
Tatsuhiro Tsujikawa
38cfc5c47c Check more headers and funcs 2015-05-13 23:29:20 +09:00
Tatsuhiro Tsujikawa
91c8f085ef Update man pages 2015-05-13 00:44:37 +09:00
Tatsuhiro Tsujikawa
5da49989f8 nghttpd: Add --echo-upload option to send back request body 2015-05-13 00:38:28 +09:00
Tatsuhiro Tsujikawa
260131966d help2rst.py: Add comment to tell that this is a generated file 2015-05-12 23:30:17 +09:00
Tatsuhiro Tsujikawa
6862f66c23 Merge branch 'syohex-misspelling' 2015-05-12 23:25:33 +09:00
Tatsuhiro Tsujikawa
2f2a7ace81 Fix corresponding upstream source reported in previous commits accordingly 2015-05-12 23:24:18 +09:00
Syohei YOSHIDA
132719f752 Correct misspellings in document 2015-05-12 10:49:42 +09:00
Tatsuhiro Tsujikawa
64b1aae567 integration: Fix TestH2H1Upgrade test failure 2015-05-08 19:35:09 +09:00
Tatsuhiro Tsujikawa
a8625e15f0 clang-format 2015-05-08 19:24:17 +09:00
Tatsuhiro Tsujikawa
e63d6e490a Merge branch 'master' into v1.0.0
Conflicts:
	lib/nghttp2_option.h
	lib/nghttp2_session.h
	src/HttpServer.cc
2015-05-08 19:21:51 +09:00
Tatsuhiro Tsujikawa
7f60de0c51 Bump up version number to 0.7.15-DEV 2015-05-08 18:36:58 +09:00
Tatsuhiro Tsujikawa
3a46a2c0a4 Update man pages 2015-05-08 17:55:15 +09:00
Tatsuhiro Tsujikawa
fbff101165 Update bash_completion 2015-05-08 17:54:51 +09:00
Tatsuhiro Tsujikawa
526d2c727d Bump up version number to 0.7.14, LT revision to 13:3:8 2015-05-08 17:51:54 +09:00
Tatsuhiro Tsujikawa
6c232da679 Merge branch 'alagoutte-misc' 2015-05-07 23:40:22 +09:00
Alexis La Goutte
1241c951d6 rv is only used in an assert.
The assert only evaluates to code if NDEBUG is undefined. Protect rv and its use accordingly

Issue reported by Joerg Mayer
https://code.wireshark.org/review/8260
2015-05-07 15:20:24 +02:00
Tatsuhiro Tsujikawa
73e79130d1 Update doc 2015-05-07 21:14:21 +09:00
Tatsuhiro Tsujikawa
1a1902350b Update sphinx_rtd_theme 2015-05-07 21:09:57 +09:00
Tatsuhiro Tsujikawa
eec65826cf Update man pages 2015-05-07 20:55:10 +09:00
Tatsuhiro Tsujikawa
fc17c0a618 Fix global-buffer-overflow 2015-05-07 19:37:43 +09:00
Tatsuhiro Tsujikawa
2620992003 Document about time for connect and time for 1st byte in h2load man page 2015-05-07 18:58:32 +09:00
Tatsuhiro Tsujikawa
5a2069b55c Merge branch 'wzyboy-patch-upstart' 2015-05-06 15:56:57 +09:00
Tatsuhiro Tsujikawa
14adcb2d81 Substitute bindir in nghttpx-upstart.conf 2015-05-06 15:56:18 +09:00
Tatsuhiro Tsujikawa
13660edef2 Merge branch 'patch-upstart' of https://github.com/wzyboy/nghttp2 into wzyboy-patch-upstart 2015-05-06 15:54:42 +09:00
Tatsuhiro Tsujikawa
98034286ac Substitute bindir in nghttpx.service 2015-05-06 15:53:12 +09:00
Tatsuhiro Tsujikawa
2a37a28d72 Revert "Substitute bindir for nghttpx.service"
This reverts commit 7bb154f768.
2015-05-06 15:37:56 +09:00
Tatsuhiro Tsujikawa
7bb154f768 Substitute bindir for nghttpx.service
Use static pattern rules to use same recipe for nghttpx-init and
nghttpx.service.

Also rewrite how to produce nghttpx
2015-05-06 12:02:12 +09:00
Zhuoyun Wei
eb96aa261f Add Upstart configuration file 2015-05-06 10:38:24 +08:00
Tatsuhiro Tsujikawa
232d359cbb Add nghttpx.service to distribution 2015-05-06 11:02:51 +09:00
Tatsuhiro Tsujikawa
2d5d9d5d04 nghttpd: Add -m, --max-concurrent-streams option 2015-05-06 10:42:43 +09:00
Tatsuhiro Tsujikawa
7ecca39025 nghttpx: Fix heap-use-after-free bug in http/1 frontend
This is a regression introduced in
4be4d875f3
2015-05-05 23:45:39 +09:00
Tatsuhiro Tsujikawa
bc0190c19f Merge branch 'wzyboy-patch-systemd-service' 2015-05-05 22:37:40 +09:00
Tatsuhiro Tsujikawa
9a162b81f0 Merge branch 'patch-systemd-service' of https://github.com/wzyboy/nghttp2 into wzyboy-patch-systemd-service 2015-05-05 22:37:21 +09:00
Tatsuhiro Tsujikawa
a67a8fabff Merge branch 'wzyboy-patch-logrotate' 2015-05-05 22:36:06 +09:00
Zhuoyun Wei
989d381aab Add systemd service file 2015-05-04 23:56:09 +08:00
Zhuoyun Wei
1d65d82cb5 Improve logrotate configuration file
- Avoid changing file permissions
- Make sure all log files are reopened
- Remove non-sense prerotate script
- Send SIGUSR1 to all nghttpx processes
2015-05-04 23:17:27 +08:00
Tatsuhiro Tsujikawa
4be4d875f3 nghttpx: Log absolute URI for HTTP/2 or client proxy request 2015-05-04 23:24:33 +09:00
Tatsuhiro Tsujikawa
1ab707713f nghttpx: Accept reference instead of pointer by upstream_accesslog 2015-05-04 22:45:34 +09:00
Tatsuhiro Tsujikawa
cc46d363c5 h2load: Refactor statistics hanlding to scale more upcoming new metrics 2015-05-04 22:36:21 +09:00
Tatsuhiro Tsujikawa
fa082cbdd0 Merge branch 'alex-nalivko-include_pull_request' 2015-05-03 16:52:27 +09:00
Tatsuhiro Tsujikawa
016d40ea0f Merge branch 'include_pull_request' of https://github.com/alex-nalivko/nghttp2 into alex-nalivko-include_pull_request 2015-05-03 16:50:52 +09:00
Tatsuhiro Tsujikawa
fe6d065bb4 Merge branch 'ericcarlschwartz-finer_stats' 2015-05-03 16:47:52 +09:00
Tatsuhiro Tsujikawa
b4e8bea4b5 clang-format 2015-05-03 16:47:32 +09:00
Tatsuhiro Tsujikawa
555d5abac9 Merge branch 'finer_stats' of https://github.com/ericcarlschwartz/nghttp2 into ericcarlschwartz-finer_stats 2015-05-03 16:37:02 +09:00
Alex Nalivko
3137dc4a70 h2load_spdy_session errno include 2015-05-02 19:33:04 +00:00
es
4bba4bf66c update h2load to give connect time and ttfb stats
finer statistics for h2load: update per comments from tatsuhiro-t

finer stats for h2load: fixed formatting
2015-05-01 10:30:09 -07:00
Tatsuhiro Tsujikawa
7b3a33a313 README.rst: Fix formatting and remove trailing spaces 2015-05-01 13:29:43 +09:00
Tatsuhiro Tsujikawa
ee52290de7 Merge branch 'brk0v-typo' 2015-05-01 00:41:48 +09:00
Viacheslav Biriukov
8f0899a190 mages to images typo 2015-04-30 18:22:51 +03:00
Tatsuhiro Tsujikawa
f6cfd082c7 Merge branch 'alagoutte-misc' 2015-04-30 18:43:41 +09:00
Tatsuhiro Tsujikawa
9d81be4b35 Merge branch 'misc' of https://github.com/alagoutte/nghttp2 into alagoutte-misc 2015-04-30 18:42:17 +09:00
Alexis La Goutte
a62778d6b0 fix comma at end of enumerator list [-Wpedantic] 2015-04-30 07:49:55 +02:00
Tatsuhiro Tsujikawa
ea612a2dce Merge branch 'nghttpx-headers-size-option' 2015-04-29 22:55:30 +09:00
Tatsuhiro Tsujikawa
026521b097 integration: Add tests for --header-field-buffer and --max-header-fields 2015-04-29 22:54:25 +09:00
Tatsuhiro Tsujikawa
9dc5259593 nghttpx: Take into account request URI in header size in https frontend 2015-04-29 22:23:25 +09:00
Tatsuhiro Tsujikawa
ea8a566d98 nghttpx: Send 431 if header field size exceeded the configuration limit 2015-04-29 21:39:46 +09:00
Tatsuhiro Tsujikawa
8c6f9e899f nghttpx: Enforce header field buffer limit for SPDY frontend 2015-04-29 21:27:36 +09:00
Tatsuhiro Tsujikawa
552f675466 nghttpx: Add --header-field-buffer and --max-header-fields options 2015-04-29 21:10:59 +09:00
Tatsuhiro Tsujikawa
f9a50333d2 Fix doc for nghttp2_select_next_protocol
We have to return this error code to notify OpenSSL that we have not
filled any values in |*out| and |*outlen|.
2015-04-28 23:12:27 +09:00
Tatsuhiro Tsujikawa
de4735092a Fix doc formatting 2015-04-28 23:06:48 +09:00
Tatsuhiro Tsujikawa
1c4df1832b Update doc, mainly for RFC numbers 2015-04-28 23:05:00 +09:00
Tatsuhiro Tsujikawa
1ad1fe6005 Merge branch 'master' into v1.0.0 2015-04-28 22:48:34 +09:00
Tatsuhiro Tsujikawa
f05a4830c5 nghttp: Fix assertion error if very large value is given to -t 2015-04-28 21:51:28 +09:00
Tatsuhiro Tsujikawa
9e1b068a4b Fix bug that promised stream was not reset on decompression error 2015-04-28 21:38:52 +09:00
Tatsuhiro Tsujikawa
54bff91762 Bump up version number to 0.7.14-DEV 2015-04-28 00:01:09 +09:00
Tatsuhiro Tsujikawa
63630690a8 Fix make -j3 distcheck error 2015-04-27 23:52:36 +09:00
Tatsuhiro Tsujikawa
dbc613e0d0 Update man pages 2015-04-27 23:09:00 +09:00
Tatsuhiro Tsujikawa
ee354ee6c8 Bump up version number to 0.7.13, LT revision to 13:2:8 2015-04-27 23:06:14 +09:00
Tatsuhiro Tsujikawa
df707df21b Update man pages 2015-04-27 22:36:34 +09:00
Tatsuhiro Tsujikawa
2436acbd23 Update doc about h2load flow control 2015-04-27 22:36:03 +09:00
Tatsuhiro Tsujikawa
b41835f19b h2load: Effectively disable flow control by setting large window size
Previously h2load used default flow control window as described in
HTTP/2 and SPDY specification.  The window size is 64KiB, which is a
bit small, and cannot utilize full server performance when response
size is not too small.  Basically, we do this kind of benchmarking
test to measure server's throughput, and optimal performance.  Smaller
window certainly degrades performance even in local testing because
server is so fast that it has to wait for WINDOW_UPDATE from h2load.
To make default behaviour suitable for peak performance test, we
decided to disable flow control in h2load by setting large enough
window size.

Most users used h2load without -w or -W options, so they were
implicitly throttled by flow control and the result was affected by
that negatively.  Now flow control is disabled by default, the result
may improve depending on the implementations.
2015-04-27 21:23:01 +09:00
Tatsuhiro Tsujikawa
42b2430fe1 Remove unnecessary assignment to item->cycle 2015-04-26 22:32:54 +09:00
Tatsuhiro Tsujikawa
c8f67788e0 Remove unused local variable 2015-04-26 19:47:14 +09:00
Tatsuhiro Tsujikawa
bbdff112a3 Make huffman decoding slightly faster using evil looking macro 2015-04-26 19:39:33 +09:00
Tatsuhiro Tsujikawa
02468b1ca1 Allocate field name and value in the same buffer if indname to dynamic table 2015-04-26 18:43:24 +09:00
Tatsuhiro Tsujikawa
c41f413978 Fix compile error with --enable-werror 2015-04-25 02:23:01 +09:00
Tatsuhiro Tsujikawa
e38dd37667 Update doc 2015-04-25 01:00:02 +09:00
Tatsuhiro Tsujikawa
f2cf2b625c Replace priority queue with linear queue where possible
After reviewing codebase, only queue for DATA frames requires
priorities.  Other frames can be replaced multiple linear queues.
Replacing priority queue with linear queue allows us to simplify
codebase a bit; for example, now nghttp2_session.next_seq is gone.
2015-04-25 00:56:46 +09:00
Tatsuhiro Tsujikawa
eb05777d88 clang-format 2015-04-24 00:17:13 +09:00
Tatsuhiro Tsujikawa
db4a68454a Merge branch 'master' into v1.0.0
Conflicts:
	lib/includes/nghttp2/nghttp2.h
2015-04-24 00:13:15 +09:00
Tatsuhiro Tsujikawa
6b0b8ea7d5 Update doc 2015-04-24 00:05:10 +09:00
Tatsuhiro Tsujikawa
c925c32233 Fix bug that promised stream is not reset on temporal failure from on_header_callback 2015-04-23 23:57:39 +09:00
Tatsuhiro Tsujikawa
514558afc0 Allow NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE from nghttp2_on_begin_headers_callback
Since application most likely allocates the stream object in
nghttp2_on_begin_headers_callback, it is desirable to handle its
failure as stream error.  But previously it only signals success or
fatal error.  Submitting RST_STREAM does not prevent
nghttp2_on_header_callback from being invoked.  This commit improves
this situation by allowing NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE from
nghttp2_on_begin_headers_callback.  If that value is returned, library
submits RST_STREAM with error code INTERNAL_ERROR, and
nghttp2_on_header_callback and nghttp2_on_frame_recv_callback for that
frame are not invoked.  Note that for PUSH_PROMISE frame, the stream
to be reset is promised stream.
2015-04-23 23:43:30 +09:00
Tatsuhiro Tsujikawa
b9f602b9a2 Update doc 2015-04-23 21:14:09 +09:00
Tatsuhiro Tsujikawa
1a99bcc860 Merge branch 'travis-container' 2015-04-23 00:00:06 +09:00
Tatsuhiro Tsujikawa
6b8aa36c98 travis: Use gcc-4.9 instead of gcc-4.8 2015-04-22 23:59:23 +09:00
Tatsuhiro Tsujikawa
86ddda5c0e tiny-nghttpd: Fix compile error with travis gcc-4.8 2015-04-22 23:59:23 +09:00
Tatsuhiro Tsujikawa
58b7f4a096 Fix inline error with travis gcc-4.8 2015-04-22 23:59:23 +09:00
Tatsuhiro Tsujikawa
4069aab4f7 travis: Attempt to enable gcc 2015-04-22 23:59:23 +09:00
Tatsuhiro Tsujikawa
5595ba643e travis: Use container-based infrastructure 2015-04-22 23:59:23 +09:00
Tatsuhiro Tsujikawa
77c556901c nghttpx: Increase maximum header field set size 2015-04-22 22:27:48 +09:00
Tatsuhiro Tsujikawa
4928959213 asio: Document asynchronous parameter for listen_and_serve 2015-04-22 22:25:16 +09:00
Tatsuhiro Tsujikawa
a200bb1084 Merge branch 'sunxiaoguang-asio_graceful_shutdown' 2015-04-22 21:43:52 +09:00
Xiaoguang Sun
92a1ca5917 Graceful shutdown and joinable server 2015-04-22 17:51:28 +08:00
Tatsuhiro Tsujikawa
97648d257f mkhufftbl.py: Refactor 2015-04-21 23:48:45 +09:00
Tatsuhiro Tsujikawa
5937b4b6f7 Merge branch 'master' into v1.0.0 2015-04-19 23:13:38 +09:00
Tatsuhiro Tsujikawa
787d40129b Bump up version number to 0.7.13-DEV 2015-04-19 18:32:58 +09:00
Tatsuhiro Tsujikawa
91ad7e150e Never indexing still can use header field name in dynamic table 2015-04-19 18:21:26 +09:00
Tatsuhiro Tsujikawa
28bde2cef0 Update bash_completion 2015-04-19 18:11:11 +09:00
Tatsuhiro Tsujikawa
a9b54a1bfa Update man pages 2015-04-19 18:10:54 +09:00
Tatsuhiro Tsujikawa
80f0e99f00 Bump up version number to 0.7.12, LT revision to 13:1:8 2015-04-19 18:07:57 +09:00
Tatsuhiro Tsujikawa
102ea7c0bb nghttpd: Cache fd
Implement fd caching for static files.  The response body for such as
404 was dynamically generated previously, but now it is written in
temporally file and its fd is cached.  Currently, cache is reference
counted and expired when count becomes 0.  This makes caching is not
effective other than "busy" period, but we don't need this feature if
we are not busy.
2015-04-19 17:38:06 +09:00
Tatsuhiro Tsujikawa
85671a69bf Update doc 2015-04-18 16:49:34 +09:00
Tatsuhiro Tsujikawa
a3fa257473 Fix compile error with Android NDK r10d + --enable-werror 2015-04-17 23:46:19 +09:00
Tatsuhiro Tsujikawa
c4e994c97d nghttp: Add --no-push option to disable server push 2015-04-17 23:35:16 +09:00
Tatsuhiro Tsujikawa
0b41e20d54 nghttp: Show stream ID in statistics output 2015-04-17 23:35:16 +09:00
Tatsuhiro Tsujikawa
cfabce6e70 Update man pages 2015-04-17 23:14:23 +09:00
Tatsuhiro Tsujikawa
b948c5457d Specify program directive 2015-04-17 23:13:42 +09:00
Tatsuhiro Tsujikawa
3bdf78e8af Document nghttp's dependency based priority 2015-04-17 23:06:07 +09:00
Tatsuhiro Tsujikawa
436595df98 nghttp: Remove --dep-idle option
In this commit, we made --dep-idle behaviour by default.  This is
because the previous default behaviour is not reflect current usage of
dependency priority and never will be because of fragility of tree due
to stream closure.
2015-04-17 22:24:06 +09:00
Tatsuhiro Tsujikawa
d3561a63b1 nghttp: Depend on "leader" anchor if js is linked inside head element 2015-04-17 21:25:31 +09:00
Tatsuhiro Tsujikawa
1a12a9b397 Penalize cycle according to effective weight 2015-04-17 21:17:22 +09:00
Tatsuhiro Tsujikawa
57644e0256 Effectively revert 03c4092862
This is not mandated by spec.  Also it may work badly with Firefox
style dependency tree usage.
2015-04-17 21:04:17 +09:00
Tatsuhiro Tsujikawa
7323d4c639 Fix bug that nghttp2_session_set_next_stream_id accepts invalid stream_id 2015-04-17 00:12:47 +09:00
Tatsuhiro Tsujikawa
e23225689f nghttp: Use same priority anchor nodes as Firefox does 2015-04-16 23:56:37 +09:00
Tatsuhiro Tsujikawa
e6ad2eb14f We can assert this 2015-04-16 22:58:25 +09:00
Tatsuhiro Tsujikawa
d4a22edeb3 Don't do fancy stuff yet 2015-04-16 22:58:25 +09:00
Tatsuhiro Tsujikawa
8f4e2d941f Revert accidental change in nghttp.cc 2015-04-16 22:58:25 +09:00
Tatsuhiro Tsujikawa
1a8da6caec Update doc 2015-04-16 21:40:39 +09:00
Tatsuhiro Tsujikawa
dc335b9025 Improve weight handling a bit 2015-04-16 21:38:13 +09:00
Tatsuhiro Tsujikawa
93afbc7d2f Rewrite static header table handling
We rewrite static header table handling in nghttp2_hd.c.  We expand
nghttp2_token to include all static header table entries, and fully
use them in header compression and decompression.  The lookup function
is now located in nghttp2_hd.c.  We add new nghttp2_hd_inflate_hd2()
function to export token value for header name, then we pass it to
nghttp2_http_on_header function, so that we don't have to look up
token there.  We carefully set enum value of token to static table
index, so looking up static table is now O(1), assuming we have token.
2015-04-15 23:58:56 +09:00
Tatsuhiro Tsujikawa
82e2c5bd22 Never index authorization and small cookie header field
nghttp2 library now use Literal Header Field never Indexed for
"authorization" header field and small "cookie" header field,
regardless of nghttp2_nv.flags.
2015-04-15 23:58:56 +09:00
Tatsuhiro Tsujikawa
53bcafb39f Merge branch 'cubicdaiya-alloc-error-handling' 2015-04-15 22:45:10 +09:00
Tatsuhiko Kubo
59f8397659 Use nullptr instead of NULL in C++. 2015-04-15 21:18:39 +09:00
Tatsuhiko Kubo
061732adf0 improved malloc error handlings. 2015-04-15 09:20:45 +09:00
Tatsuhiro Tsujikawa
5c2ca28706 asio: client: Call error_cb on error occurred in do_read and do_write
Fixes GH-207
2015-04-13 21:33:43 +09:00
Tatsuhiro Tsujikawa
a8ea86cfe5 src: constexpr 2015-04-12 17:51:23 +09:00
Tatsuhiro Tsujikawa
7451a73def nghttpx: Don't push resource if link header has non empty loadpolicy 2015-04-12 17:42:25 +09:00
Tatsuhiro Tsujikawa
889e705f35 nghttpx: Add logging for somewhat important events (logs, tickets, and ocsp) 2015-04-11 00:08:28 +09:00
Tatsuhiro Tsujikawa
14d4979c54 Don't install libnghttp2_asio headers if they are disabled 2015-04-10 23:11:40 +09:00
Tatsuhiro Tsujikawa
095bc178f3 nghttpx: Robust HTTP/1 backend CL and TE handling
We should ignore Content-Length and Transfer-Encoding for upgraded
response, and reset content-length if this is a non-final response.
2015-04-10 22:30:20 +09:00
Tatsuhiro Tsujikawa
308738025c nghttpx: Don't set response content-length if HTTP/2 response upgraded 2015-04-10 22:24:17 +09:00
Tatsuhiro Tsujikawa
97366bf55c nghttpx: Set content-length after complete request/response headers 2015-04-10 22:10:51 +09:00
Tatsuhiro Tsujikawa
87cadca3d8 integration: Add HTTP Upgrade test 2015-04-10 21:28:12 +09:00
Tatsuhiro Tsujikawa
9803f92e9c nghttpx: Set Downstream to stream user data on HTTP Upgrade to h2 2015-04-10 02:40:09 +09:00
Tatsuhiro Tsujikawa
cbfa021095 Bump up version number to 0.7.12-DEV 2015-04-10 00:38:17 +09:00
Tatsuhiro Tsujikawa
03746884a4 Update man pages 2015-04-10 00:35:00 +09:00
Tatsuhiro Tsujikawa
6ed710adbd Bump up version number to 0.7.11 2015-04-10 00:31:46 +09:00
Tatsuhiro Tsujikawa
44b4cda200 src: Check return value from nghttp2_session_get_stream_user_data 2015-04-10 00:21:31 +09:00
Tatsuhiro Tsujikawa
69a4f3bf42 nghttp: Consider :authority custom header field for SNI 2015-04-10 00:15:01 +09:00
Tatsuhiro Tsujikawa
5334cb5acc Enable PIE in Dockerfile.android too 2015-04-09 23:34:42 +09:00
Tatsuhiro Tsujikawa
6ca24264e4 Enable PIE for Android build 2015-04-09 23:30:12 +09:00
Tatsuhiro Tsujikawa
37a631278f Merge branch 'alagoutte-misc' 2015-04-09 23:27:15 +09:00
Alexis La Goutte
5c42687759 fix comma at end of enumerator list [-Wpedantic] 2015-04-09 15:44:36 +02:00
Tatsuhiro Tsujikawa
b636e9744f Merge branch 'nghttpx-rewrite-ocsp' 2015-04-09 01:06:13 +09:00
Tatsuhiro Tsujikawa
b873930802 nghttpx: Now ocsp works without threads 2015-04-09 01:03:28 +09:00
Tatsuhiro Tsujikawa
bc53c81616 nghttpx: Replace posix_spawn functions with fork + dup2 + execve
Although posx_spawn is very convenient and useful, we have platform
which don't have these functions (e.g., Android NDK r10d).
2015-04-09 01:03:28 +09:00
Tatsuhiro Tsujikawa
09c485e712 nghttpx: Eliminate 1 second refresh timer 2015-04-09 01:03:28 +09:00
Tatsuhiro Tsujikawa
d247470da2 nghttpx: Rewrite ocsp without thread
Since libev handles SIGCHLD, using waitpid in separate thread to wait
for the completion of fetch-ocsp-response script process is undefined.
This commit rewrite ocsp handling code so that it utilizes libev
ev_child watcher and perform ocsp update without thread.
2015-04-09 01:03:28 +09:00
Tatsuhiro Tsujikawa
90bfea77e0 doc: Remove nghttp2_submit_altsvc.rst 2015-04-08 18:12:54 +09:00
Tatsuhiro Tsujikawa
cf0576253f Merge branch 'master' into v1.0.0 2015-04-08 18:10:04 +09:00
Tatsuhiro Tsujikawa
4aca2f0b59 Bump up version number to 0.7.11-DEV 2015-04-08 18:07:38 +09:00
Tatsuhiro Tsujikawa
9d711f65f7 Fix make distcheck 2015-04-08 17:55:23 +09:00
Tatsuhiro Tsujikawa
0eab08a7cf Update bash_completion files 2015-04-08 17:38:55 +09:00
Tatsuhiro Tsujikawa
b9c4757d21 Update man pages 2015-04-08 17:36:12 +09:00
Tatsuhiro Tsujikawa
1fcd881395 nghttpx: Document that stderr is redirected to error log file 2015-04-08 17:33:18 +09:00
Tatsuhiro Tsujikawa
cd0564ddfa Bump up version number to 0.7.10, LT revision to 13:0:8 2015-04-08 17:21:40 +09:00
Tatsuhiro Tsujikawa
dd435b51ab nghttpx: Redirect stderr to errorlog file 2015-04-08 16:59:58 +09:00
Tatsuhiro Tsujikawa
ff60cc6b71 integration: Don't send Link header field for resource under /css/ 2015-04-08 16:09:02 +09:00
Tatsuhiro Tsujikawa
80743ddc7b nghttpx: Set promised Downstream as nghttp2 stream user data 2015-04-08 16:07:53 +09:00
Tatsuhiro Tsujikawa
36a8f24559 nghttpx: Finish incomplete incoming request with END_STREAM flag
Previously we send RST_STREAM when we send DATA with END_STREAM flag
set.  With this commit, we also do this when we send HEADERS with
END_STREAM flag set.
2015-04-08 16:07:13 +09:00
Tatsuhiro Tsujikawa
b25e19e876 nghttpx: HTTP backend: Check parser error first so that we can get error msg 2015-04-08 14:39:27 +09:00
Tatsuhiro Tsujikawa
e9660c3558 nghttpx: Fix heap-use-after-free
The bug was introduced by 8c3b379b66.
2015-04-08 13:43:57 +09:00
Tatsuhiro Tsujikawa
8c3b379b66 Pool Memchunk per worker 2015-04-08 00:10:48 +09:00
Tatsuhiro Tsujikawa
b2bb6f1db1 Fix android NDK build error 2015-04-07 21:25:05 +09:00
Tatsuhiro Tsujikawa
59e3783f3f Update manual entry 2015-04-07 00:19:57 +09:00
Tatsuhiro Tsujikawa
d56ecd7414 Add nghttp2_session_consume_{connection,stream} to consume bytes independently
The existing nghttp2_session_consume() affects both connection and
stream level flow control windows.  The new functions only affects
either connection or stream.  There is some interesting use cases.
For example, we may want to pause a stream by not sending
WINDOW_UPDATE, meanwhile we want to continue to process other streams.
In this case, we use nghttp2_session_consume_connection() to tell
library that only connection level window is recovered.  The relevant
discussion: https://code.google.com/p/chromium/issues/detail?id=473259
2015-04-07 00:14:18 +09:00
Tatsuhiro Tsujikawa
ef4e39be55 Update doc 2015-04-06 23:57:48 +09:00
Tatsuhiro Tsujikawa
d42f31ca78 nghttpx: Fix bug that data buffered in SSL object are not read
This is same issue described in https://github.com/h2o/h2o/issues/268.
That is if SSL object has decrypted data buffered inside it, and
application does not read it for some reason (e.g., rate limit), we
have to check the existence of data using SSL_pending.  This is
because buffered data inside SSL is not notified by io watcher.  It is
obvious, but we totally missed it.

nghttpx code normally reads everything until SSL_read returns error
(want-read).  But if rate limit is involved, we stop reading early.
Also in HTTP/1 code, while processing one request, we just read until
buffer is filled up.  In these cases, we may suffer from this problem.

This commit fixes this problem, by performing SSL_pending() and if it
has buffered data and read io watcher is enabled, we feed event using
ev_feed_event().
2015-04-06 22:31:36 +09:00
Tatsuhiro Tsujikawa
084e4487ed Add migration section 2015-04-05 23:53:19 +09:00
Tatsuhiro Tsujikawa
24897aa50d Update README.rst 2015-04-05 23:15:20 +09:00
Tatsuhiro Tsujikawa
3e50ef439d Announce h2, final HTTP/2 ALPN identifier 2015-04-05 23:15:20 +09:00
Tatsuhiro Tsujikawa
87602e5d72 Use NGHTTP2_PROTOCOL_ERROR for NGHTTP2_ERR_HTTP_{HEADER,MESSAGING} 2015-04-05 23:15:20 +09:00
Tatsuhiro Tsujikawa
d0c27d5229 Send 24 bytes client magic byte string by library
Previously nghttp2_session_send() and nghttp2_session_mem_send() did
not send 24 bytes client magic byte string (MAGIC).  We made
nghttp2_session_recv() and nghttp2_session_mem_recv() process MAGIC by
default, so it is natural to make library send MAGIC as well.  This
commit makes nghttp2_session_send() and nghttp2_session_mem_send()
send MAGIC.  This commit also replace "connection preface" with
"client magic", since we call MAGIC as "connection preface" but it is
just a part of connection preface.  NGHTTP2_CLIENT_CONNECTION_PREFACE
macro was replaced with NGHTTP2_CLIENT_MAGIC.  The already deprecated
NGHTTP2_CLIENT_CONNECTION_HEADER macro was removed permanently.
nghttp2_option_set_no_recv_client_preface() was renamed as
nghttp2_option_set_no_recv_client_magic().  NGHTTP2_ERR_BAD_PREFACE
was renamed as NGHTTP2_ERR_BAD_CLIENT_MAGIC.
2015-04-05 23:15:20 +09:00
Tatsuhiro Tsujikawa
ebf214c8fc nghttp2_on_invalid_frame_recv_callback should have lib_error_code as param
nghttp2_error_code is HTTP/2 standard error code and is too coarse to
know what's going on.
2015-04-05 23:15:20 +09:00
Tatsuhiro Tsujikawa
250ea53e4b Deal with 24 bytes client connection preface by default
Since HTTP/2 spec requires for client to send connection preface, it
is reasonable to make this option enabled by default.  It is still a
use case to disable this, so replace this option with
nghttp2_option_set_no_recv_client_preface().
2015-04-05 23:15:20 +09:00
Tatsuhiro Tsujikawa
01af6ea70c Remove ALTSVC related code
HTTP/2 and HPACK are going to be published as RFC, but ALTSVC is still
in draft state.  To make our API stable, it would be better to remove
ALTSVC API for 1.0.0 release.
2015-04-05 23:15:20 +09:00
Tatsuhiro Tsujikawa
7522d50d1a nghttpd, tiny-nghttpd: No need to check existence of stream
The stream existence is guaranteed by library as of
cc03a12b75.
2015-04-05 23:13:29 +09:00
Tatsuhiro Tsujikawa
cc03a12b75 Don't call nghttp2_send_data_callback if stream has already closed
This is more inline with other callback function invocations where if
stream was closed, they are not invoked.
2015-04-05 12:40:21 +09:00
Tatsuhiro Tsujikawa
9eff511c5e Add nghttp2_send_data_callback to send DATA payload without copying
To avoid buffer copy in nghttp2_data_source_read_callback, this commit
introduces NGHTTP2_DATA_FLAG_NO_COPY and nghttp2_send_data_callback.
By using NGHTTP2_DATA_FLAG_NO_COPY in
nghttp2_data_source_read_callback, application can avoid to copy
application data to given buffer.  Instead, application has to
implement nghttp2_send_data_callback to send complete DATA frame by
itself.  We see noticeable performance increase in nghttpd and
tiny-nghttpd using this new feature.  On the other hand, nghttpx does
not show such difference, probably because buffer copy is not
bottleneck.  Using nghttp2_send_data_callback adds complexity, so it
is recommended to measure the performance to see whether this extra
complexity worth it.
2015-04-04 21:23:50 +09:00
Tatsuhiro Tsujikawa
a96ac6f0a0 Merge branch 'remoe-patch-2' 2015-04-04 01:05:02 +09:00
Tatsuhiro Tsujikawa
213a63d97d Merge branch 'patch-2' of https://github.com/remoe/nghttp2 into remoe-patch-2 2015-04-04 01:04:28 +09:00
Tatsuhiro Tsujikawa
8d4548b9c1 Merge branch 'remoe-patch-1' 2015-04-04 01:03:33 +09:00
Tatsuhiro Tsujikawa
44f2e6ae1d Merge branch 'patch-1' of https://github.com/remoe/nghttp2 into remoe-patch-1 2015-04-04 01:02:52 +09:00
Tatsuhiro Tsujikawa
0cd7d268f3 python: Update url 2015-04-03 21:10:11 +09:00
Remo E
f3a9041851 MSVC: remove of winsock dependency 2015-04-03 12:00:06 +02:00
Remo E
776a8c64f6 "static inline" fix for build with VS2013
"static inline" doesn't build on VS2013:

https://msdn.microsoft.com/en-us/library/z8y1yy88.aspx
2015-04-03 11:55:57 +02:00
Tatsuhiro Tsujikawa
524a1f9498 Update sphinx_rtd_theme 2015-04-01 23:11:07 +09:00
Tatsuhiro Tsujikawa
28cfae162a Update doc 2015-04-01 23:10:01 +09:00
Tatsuhiro Tsujikawa
b0123448a4 python: Add async body generation support 2015-04-01 22:54:31 +09:00
Tatsuhiro Tsujikawa
2d15dca096 Merge branch 'alagoutte-scan-build' 2015-04-01 22:53:56 +09:00
Alexis La Goutte
5f05135d1b Fix some "Value stored to 'stream' is never read" found by Clang Analyzer 2015-04-01 13:03:22 +02:00
Alexis La Goutte
3b6b4ff066 Fix Value stored to 'rv' is never read found by Clang Analyzer 2015-04-01 13:03:22 +02:00
Tatsuhiro Tsujikawa
0c8ec7bfa6 Make sure that nghttp2 license is MIT license 2015-04-01 19:41:32 +09:00
Tatsuhiro Tsujikawa
2c05b8d6f0 Update doc 2015-04-01 01:26:21 +09:00
Tatsuhiro Tsujikawa
45c4187d8f doc: Update .gitignore 2015-04-01 01:19:08 +09:00
Tatsuhiro Tsujikawa
87029e05af doc: Split API reference into smaller fine grained files
Previously API reference is gigantic one rst file and it is a bit hard
to use, especially when browsing similar functions.  This commit
splits API reference into smaller fine grained files.  The macros,
enums, types are now in its own file.  Each API function has its own
file now.  API reference doc is now index to above documentation
files.  The apiref-header.rst is renamed as programmers-guide.rst and
becomes standalone document.
2015-04-01 01:13:10 +09:00
Tatsuhiro Tsujikawa
363914c3f7 Mention OCSP stapling in doc 2015-03-31 23:31:24 +09:00
Tatsuhiro Tsujikawa
1316065c14 python: Fix pseudo-header field ordering bug 2015-03-31 21:53:13 +09:00
Tatsuhiro Tsujikawa
2b6a181bef Dockerfile.android: Update openssl to 1.0.2a 2015-03-31 21:36:53 +09:00
Tatsuhiro Tsujikawa
bf68df9ef4 Merge branch 'wzyboy-patch-dockerfile' 2015-03-31 21:35:32 +09:00
Tatsuhiro Tsujikawa
e7f6089b0e Merge branch 'patch-dockerfile' of https://github.com/wzyboy/nghttp2 into wzyboy-patch-dockerfile 2015-03-31 21:35:10 +09:00
Tatsuhiro Tsujikawa
a1500b0ee3 rst document specific corrections 2015-03-31 21:32:25 +09:00
Tatsuhiro Tsujikawa
14001052f8 Merge branch 'fangdingjun-master' 2015-03-31 21:27:18 +09:00
Tatsuhiro Tsujikawa
95ab54c79d Merge branch 'master' of https://github.com/fangdingjun/nghttp2 into fangdingjun-master 2015-03-31 21:26:46 +09:00
Zhuoyun Wei
5e84f767f0 Improve Dockerfile
- Tell Vim this is a Dockerfile to enable syntax highlight;
- Explicity use Ubuntu "Trusty";
- Remove downloaded file to save space;
- Chain up some RUN commands to generate fewer layers.
2015-03-31 14:21:56 +08:00
Dingjun
c47855085b Update README.rst
fix the typo and add the missing command in sample command
2015-03-31 10:02:22 +08:00
Tatsuhiro Tsujikawa
1442b1bd0a nghttpx: Remove --tls-ctx-per-worker option
--tls-ctx-per-worker option does not work well of OCSP stapling.  Also
it makes session ID useless.
2015-03-31 00:42:21 +09:00
Tatsuhiro Tsujikawa
763293a050 Update man pages 2015-03-31 00:23:12 +09:00
Tatsuhiro Tsujikawa
cc94632b29 src: Use separator "--" to mark start of the footer without ambiguity 2015-03-31 00:21:52 +09:00
Tatsuhiro Tsujikawa
5df770b9c1 h2load: Fix compile error with Android NDK 2015-03-30 23:59:03 +09:00
Tatsuhiro Tsujikawa
4bc9afe20a nghttpx: Add OCSP stapling feature 2015-03-30 23:58:28 +09:00
Dingjun
522faeb24f Update README.rst 2015-03-30 18:39:07 +08:00
fangdingjun
362ff09183 add build notes for windows user under Mingw and Cygwin 2015-03-30 18:29:10 +08:00
Tatsuhiro Tsujikawa
ccea4d42b5 Refactor .gitignore files 2015-03-29 18:40:37 +09:00
Tatsuhiro Tsujikawa
ebbe065716 Update .gitignore 2015-03-29 18:23:55 +09:00
Tatsuhiro Tsujikawa
3a97f21383 Reorder fields 2015-03-29 18:10:38 +09:00
Tatsuhiro Tsujikawa
12ced1cddc nghttpx: Add flag to track connection state in HTTP/1 backend 2015-03-29 01:47:22 +09:00
Tatsuhiro Tsujikawa
3576f20e5a nghttpx: Revert part of 6f58434d89
The reverted part of the change may use not connected socket in HTTP/1
backend.
2015-03-29 01:32:27 +09:00
Tatsuhiro Tsujikawa
7ae6e6b4c5 Exclude num_idle_streams when counting active stream 2015-03-29 00:59:15 +09:00
Tatsuhiro Tsujikawa
a2486daee1 nghttpd: Rename Http2Handler::on_connect as connection_made 2015-03-28 20:21:12 +09:00
Tatsuhiro Tsujikawa
8bf440b89c nghttpx: Rename Http2Session::on_connect as connection_made 2015-03-28 20:19:17 +09:00
Tatsuhiro Tsujikawa
e9cdb9c896 h2load: Remove unused fields in Client class 2015-03-28 20:17:30 +09:00
Tatsuhiro Tsujikawa
c4804ee50b h2load: Remove Client::noop 2015-03-28 20:14:12 +09:00
Tatsuhiro Tsujikawa
95cb284e27 h2load: Rename Client::on_connect as connection_made 2015-03-28 20:13:37 +09:00
Tatsuhiro Tsujikawa
c4ccc376df nghttp: Refactor function names
on_SOMETHING should be used only for I/O callback functions
2015-03-28 20:07:12 +09:00
Tatsuhiro Tsujikawa
6133110386 Remove dependency on libws2_32 on Windows build 2015-03-28 19:58:44 +09:00
Tatsuhiro Tsujikawa
6f58434d89 nghttpx, h2load: Perform write whenever read succeeds 2015-03-28 19:13:14 +09:00
Tatsuhiro Tsujikawa
3fd5d0af79 Don't consider num_active_streams in nghttp2_session_want_write() 2015-03-28 19:00:24 +09:00
Tatsuhiro Tsujikawa
1a6855ea7d Merge branch 'remoe-fix/win_build' 2015-03-28 18:41:03 +09:00
remoe
0312521ac9 - source file list updated
- zlib removed
- build of .def files removed
2015-03-27 21:54:44 +01:00
Tatsuhiro Tsujikawa
67b0e0c2d6 Fix "redefine WIN32" bug 2015-03-28 02:16:37 +09:00
Tatsuhiro Tsujikawa
966e3a1308 Define NGHTTP2_EXTERN macro to export function for Windows build 2015-03-28 01:58:59 +09:00
Tatsuhiro Tsujikawa
fd8f8e2708 Bump up version number to 0.7.10-DEV 2015-03-27 01:06:42 +09:00
Tatsuhiro Tsujikawa
d7fdcbb3d6 Update man pages 2015-03-27 00:37:12 +09:00
Tatsuhiro Tsujikawa
de2c2ad65c src: Update hexdump usage output so that help2rst.py can produce good output 2015-03-27 00:36:19 +09:00
Tatsuhiro Tsujikawa
862a0ee66b Bump up version number to 0.7.9, LT revision to 12:2:7 2015-03-27 00:27:49 +09:00
Tatsuhiro Tsujikawa
c2510a01a5 examples: Place AM_CPPFLAGS first to use in-package header files first
Fixes GH-192
2015-03-26 23:09:39 +09:00
Tatsuhiro Tsujikawa
dc85623060 nghttpx: Fix PUSH_PROMISE header field corruption
Fixes GH-194
2015-03-26 22:52:51 +09:00
Tatsuhiro Tsujikawa
8afbb6ca26 h2load: Fix crash if -t > -c 2015-03-26 19:57:37 +09:00
Tatsuhiro Tsujikawa
ed79637737 h2load: Add -d option to upload data to server 2015-03-26 19:53:42 +09:00
Tatsuhiro Tsujikawa
faa2c4467a Merge branch 'wzyboy-patch-1' 2015-03-25 23:26:20 +09:00
Zhuoyun Wei
c87fae463e Fix comments, too 2015-03-25 21:04:49 +08:00
Zhuoyun Wei
29b4b11e78 Change --spdy-proxy to --http2-proxy 2015-03-25 20:42:12 +08:00
Tatsuhiro Tsujikawa
3b24be3bcd src: Fix compile error with clang-3.6 2015-03-25 01:27:18 +09:00
Tatsuhiro Tsujikawa
ece8289aaf nghttpx: Forward only "trailers" keyword in te when forwarding HTTP/2 backend 2015-03-25 01:20:41 +09:00
Tatsuhiro Tsujikawa
4042ff0fc4 nghttpx: Fix te header field is duplicated when forwarding HTTP/2 backend 2015-03-25 01:17:06 +09:00
Tatsuhiro Tsujikawa
d3d6c5e314 Fix bug that inflater->nvbufs is not reset 2015-03-24 21:54:05 +09:00
Tatsuhiro Tsujikawa
125e32eb56 src: Refactor a bit 2015-03-24 21:45:59 +09:00
Tatsuhiro Tsujikawa
94bf8dcd4e src: Refactor util::hexdump 2015-03-24 21:43:28 +09:00
Tatsuhiro Tsujikawa
89b8039466 nghttp, nghttpd: Add --hexdump option to hexdump incoming traffic
The output format is similar to `hexdump -C`
2015-03-24 02:30:51 +09:00
Tatsuhiro Tsujikawa
72843b33d0 Bump up version number to 0.7.9-DEV 2015-03-24 00:14:56 +09:00
Tatsuhiro Tsujikawa
03e699e013 Update man pages 2015-03-24 00:04:07 +09:00
Tatsuhiro Tsujikawa
fcf99fa8fc Bump up version number to 0.7.8, LT revision to 12:1:7 2015-03-24 00:00:22 +09:00
Tatsuhiro Tsujikawa
661fb2eb0e NULL-terminate name and value in nghttp2_nv
Guaranteeing NULL-termination is very useful when name or value are
used with C functions which requires NULL-terminated string.
2015-03-23 23:25:57 +09:00
Tatsuhiro Tsujikawa
42496d638b Merge branch 'Lekensteyn-documentation' 2015-03-22 17:03:31 +09:00
Peter Wu
c0a6a0a6d1 README.rst: OpenSSL 1.0.2 has already been released
OpenSSL 1.0.2 is already released. Avoid the confusing wording that
seems to suggest that a development version of OpenSSL 1.0.2 provides
ALPN support.
2015-03-21 23:16:56 +01:00
Tatsuhiro Tsujikawa
b7bda783c5 Update doc 2015-03-21 23:09:17 +09:00
Tatsuhiro Tsujikawa
6893608ae2 Use literal instead of computed value in token lookup 2015-03-21 23:03:37 +09:00
Tatsuhiro Tsujikawa
ef913bc929 Validate :path header field
For "http" or "https" URIs, :path header field must start with "/".
The only exception is OPTIONS method, which can contain "*" to
represent system-wide OPTIONS request.
2015-03-21 23:03:37 +09:00
Tatsuhiro Tsujikawa
a5ed70bcfe Merge branch 'rasa-patch-1' 2015-03-21 19:47:27 +09:00
Tatsuhiro Tsujikawa
9bf2ca6916 Merge branch 'patch-1' of https://github.com/rasa/nghttp2 into rasa-patch-1 2015-03-21 19:46:22 +09:00
Ross Smith II
57729d0a23 Removed errant markdown 2015-03-20 08:37:06 -07:00
Tatsuhiro Tsujikawa
e86b81ec10 Merge branch 'icing-h2load-reserver-fix' 2015-03-20 23:32:43 +09:00
mod-h2-dev
076eefbed6 fix for segfault by reserving correct worker count 2015-03-16 17:42:22 +02:00
Ross Smith II
58a735dc68 Update README.rst 2015-03-15 23:42:19 -07:00
Tatsuhiro Tsujikawa
948d4d43d5 Bump up version number to 0.7.8-DEV 2015-03-14 18:53:43 +09:00
Tatsuhiro Tsujikawa
ef581e94bb Update man pages 2015-03-14 18:52:50 +09:00
Tatsuhiro Tsujikawa
ad84af2b2b Bump up version number to 0.7.7 2015-03-14 18:50:12 +09:00
Tatsuhiro Tsujikawa
0e65e1254d Bump up version number to 0.7.7-DEV 2015-03-14 18:36:18 +09:00
223 changed files with 10526 additions and 4724 deletions

50
.gitignore vendored
View File

@@ -1,14 +1,18 @@
# emacs backup file
*~ *~
*.o
*.lo # autotools
*.la *.la
depcomp *.lo
*.m4 *.m4
*.o
.deps/
.libs/
INSTALL
Makefile Makefile
Makefile.in Makefile.in
libtool
missing
autom4te.cache/ autom4te.cache/
compile
config.guess config.guess
config.h config.h
config.h.in config.h.in
@@ -16,36 +20,14 @@ config.log
config.status config.status
config.sub config.sub
configure configure
depcomp
install-sh install-sh
.deps/ libtool
.libs
lib/includes/nghttp2/nghttp2ver.h
lib/libnghttp2.pc
src/libnghttp2_asio.pc
ltmain.sh ltmain.sh
missing
stamp-h1 stamp-h1
.deps/
INSTALL
.DS_STORE
compile
test-driver test-driver
.dirstamp
doc/index.rst # test logs generated by `make check`
doc/nghttp2.h.rst *.log
doc/nghttp2ver.h.rst *.trs
doc/package_README.rst
doc/tutorial-client.rst
doc/tutorial-server.rst
doc/nghttpx-howto.rst
doc/h2load-howto.rst
doc/tutorial-hpack.rst
doc/python-apiref.rst
doc/building-android-binary.rst
doc/asio_http2.h.rst
doc/asio_http2_server.h.rst
doc/asio_http2_client.h.rst
doc/libnghttp2_asio.rst
doc/contribute.rst
python/setup.py
python/dist
python/MANIFEST

View File

@@ -1,31 +1,31 @@
language: cpp language: cpp
compiler: compiler:
- clang - clang
#Disable gcc build for the moment... - gcc
# - gcc sudo: false
addons:
apt:
sources:
- ubuntu-toolchain-r-test
packages:
- g++-4.9
- libstdc++-4.9-dev
- autoconf
- automake
- autotools-dev
- libtool
- pkg-config
- zlib1g-dev
- libcunit1-dev
- libssl-dev
- libxml2-dev
- libev-dev
- libevent-dev
- libjansson-dev
- libjemalloc-dev
before_install: before_install:
- $CC --version - $CC --version
- sudo add-apt-repository --yes ppa:ubuntu-toolchain-r/test - if [ "$CXX" = "g++" ]; then export CXX="g++-4.9" CC="gcc-4.9"; fi
- sudo apt-get update -qq
#Install and use gcc-4.8 (don't build with gcc-4.6)
#libstdc++-4.8 is needed by Clang to build too
- sudo apt-get -qq install g++-4.8 libstdc++-4.8-dev
- >
sudo apt-get install --no-install-recommends -qq
autoconf
automake
autotools-dev
libtool
pkg-config
zlib1g-dev
libcunit1-dev
libssl-dev
libxml2-dev
libev-dev
libevent-dev
libjansson-dev
libjemalloc-dev
- if [ "$CXX" = "g++" ]; then export CXX="g++-4.8" CC="gcc-4.8"; fi
- $CC --version - $CC --version
before_script: before_script:
- autoreconf -i - autoreconf -i

18
CONTRIBUTION Normal file
View File

@@ -0,0 +1,18 @@
[The text below was composed based on 1.2. License section of
curl/libcurl project.]
When contributing with code, you agree to put your changes and new
code under the same license nghttp2 is already using unless stated and
agreed otherwise.
When changing existing source code, you do not alter the copyright of
the original file(s). The copyright will still be owned by the
original creator(s) or those who have been assigned copyright by the
original author(s).
By submitting a patch to the nghttp2 project, you are assumed to have
the right to the code and to be allowed by your employer or whatever
to hand over that patch/code to us. We will credit you for your
changes as far as possible, to give credit but also to keep a trace
back to who made what changes. Please always provide us with your
full real name when contributing!

19
COPYING
View File

@@ -20,22 +20,3 @@ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
[The text below was composed based on 1.2. License section of
curl/libcurl project.]
When contributing with code, you agree to put your changes and new
code under the same license nghttp2 is already using unless stated and
agreed otherwise.
When changing existing source code, you do not alter the copyright of
the original file(s). The copyright will still be owned by the
original creator(s) or those who have been assigned copyright by the
original author(s).
By submitting a patch to the nghttp2 project, you are assumed to have
the right to the code and to be allowed by your employer or whatever
to hand over that patch/code to us. We will credit you for your
changes as far as possible, to give credit but also to keep a trace
back to who made what changes. Please always provide us with your
full real name when contributing!

View File

@@ -1,3 +1,4 @@
# vim: ft=dockerfile:
# Dockerfile to build nghttp2 android binary # Dockerfile to build nghttp2 android binary
# #
# $ sudo docker build -t nghttp2-android - < Dockerfile.android # $ sudo docker build -t nghttp2-android - < Dockerfile.android
@@ -9,7 +10,7 @@
# #
# $ sudo docker run -v /path/to/dest:/out nghttp2-android cp /root/build/nghttp2/src/nghttpx /out # $ sudo docker run -v /path/to/dest:/out nghttp2-android cp /root/build/nghttp2/src/nghttpx /out
FROM ubuntu FROM ubuntu:vivid
MAINTAINER Tatsuhiro Tsujikawa MAINTAINER Tatsuhiro Tsujikawa
@@ -29,11 +30,12 @@ RUN apt-get install -y make binutils autoconf automake autotools-dev libtool \
genisoimage libc6-i386 lib32stdc++6 genisoimage libc6-i386 lib32stdc++6
WORKDIR /root/build WORKDIR /root/build
RUN curl -L -O http://dl.google.com/android/ndk/android-ndk-r10c-linux-x86_64.bin RUN curl -L -O http://dl.google.com/android/ndk/android-ndk-r10d-linux-x86_64.bin && \
RUN chmod a+x android-ndk-r10c-linux-x86_64.bin chmod a+x android-ndk-r10d-linux-x86_64.bin && \
RUN ./android-ndk-r10c-linux-x86_64.bin ./android-ndk-r10d-linux-x86_64.bin && \
rm android-ndk-r10d-linux-x86_64.bin
WORKDIR /root/build/android-ndk-r10c WORKDIR /root/build/android-ndk-r10d
RUN /bin/bash build/tools/make-standalone-toolchain.sh \ RUN /bin/bash build/tools/make-standalone-toolchain.sh \
--install-dir=$ANDROID_HOME/toolchain \ --install-dir=$ANDROID_HOME/toolchain \
--toolchain=arm-linux-androideabi-4.9 --llvm-version=3.5 \ --toolchain=arm-linux-androideabi-4.9 --llvm-version=3.5 \
@@ -57,20 +59,24 @@ RUN autoreconf -i && \
make install make install
WORKDIR /root/build WORKDIR /root/build
RUN curl -L -O https://www.openssl.org/source/openssl-1.0.1j.tar.gz RUN curl -L -O https://www.openssl.org/source/openssl-1.0.2a.tar.gz && \
RUN tar xf openssl-1.0.1j.tar.gz tar xf openssl-1.0.2a.tar.gz && \
WORKDIR /root/build/openssl-1.0.1j rm openssl-1.0.2a.tar.gz
WORKDIR /root/build/openssl-1.0.2a
RUN export CROSS_COMPILE=$TOOLCHAIN/bin/arm-linux-androideabi- && \ RUN export CROSS_COMPILE=$TOOLCHAIN/bin/arm-linux-androideabi- && \
./Configure --prefix=$PREFIX android && \ ./Configure --prefix=$PREFIX android && \
make && make install_sw make && make install_sw
WORKDIR /root/build 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/libev-4.19.tar.gz && \
RUN curl -L -O https://gist.github.com/tatsuhiro-t/48c45f08950f587180ed/raw/80a8f003b5d1091eae497c5995bbaa68096e739b/libev-4.19-android.patch curl -L -O https://gist.github.com/tatsuhiro-t/48c45f08950f587180ed/raw/80a8f003b5d1091eae497c5995bbaa68096e739b/libev-4.19-android.patch && \
RUN tar xf libev-4.19.tar.gz tar xf libev-4.19.tar.gz && \
rm libev-4.19.tar.gz
WORKDIR /root/build/libev-4.19 WORKDIR /root/build/libev-4.19
RUN patch -p1 < ../libev-4.19-android.patch RUN patch -p1 < ../libev-4.19-android.patch && \
RUN ./configure \ ./configure \
--host=arm-linux-androideabi \ --host=arm-linux-androideabi \
--build=`dpkg-architecture -qDEB_BUILD_GNU_TYPE` \ --build=`dpkg-architecture -qDEB_BUILD_GNU_TYPE` \
--prefix=$PREFIX \ --prefix=$PREFIX \
@@ -80,6 +86,25 @@ RUN ./configure \
LDFLAGS=-L$PREFIX/lib && \ LDFLAGS=-L$PREFIX/lib && \
make install 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
WORKDIR /root/build/zlib-1.2.8
RUN HOST=arm-linux-androideabi \
CC=$HOST-gcc \
AR=$HOST-ar \
LD=$HOST-ld \
RANLIB=$HOST-ranlib \
STRIP=$HOST-strip \
./configure \
--prefix=$PREFIX \
--libdir=$PREFIX/lib \
--includedir=$PREFIX/include \
--static && \
make install
WORKDIR /root/build WORKDIR /root/build
RUN git clone https://github.com/tatsuhiro-t/nghttp2 RUN git clone https://github.com/tatsuhiro-t/nghttp2
WORKDIR /root/build/nghttp2 WORKDIR /root/build/nghttp2
@@ -95,9 +120,9 @@ RUN autoreconf -i && \
--disable-threads \ --disable-threads \
LIBSPDYLAY_CFLAGS=-I$PREFIX/usr/local/include \ LIBSPDYLAY_CFLAGS=-I$PREFIX/usr/local/include \
LIBSPDYLAY_LIBS="-L$PREFIX/usr/local/lib -lspdylay" \ LIBSPDYLAY_LIBS="-L$PREFIX/usr/local/lib -lspdylay" \
CPPFLAGS="-I$PREFIX/include" \ CPPFLAGS="-fPIE -I$PREFIX/include" \
CXXFLAGS="-fno-strict-aliasing" \ CXXFLAGS="-fno-strict-aliasing" \
PKG_CONFIG_LIBDIR="$PREFIX/lib/pkgconfig" \ PKG_CONFIG_LIBDIR="$PREFIX/lib/pkgconfig" \
LDFLAGS="-L$PREFIX/lib" && \ LDFLAGS="-fPIE -pie -L$PREFIX/lib" && \
make && \ make && \
arm-linux-androideabi-strip src/nghttpx src/nghttpd src/nghttp arm-linux-androideabi-strip src/nghttpx src/nghttpd src/nghttp

View File

@@ -21,7 +21,7 @@
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
SUBDIRS = lib third-party src examples python tests integration-tests \ SUBDIRS = lib third-party src examples python tests integration-tests \
doc contrib doc contrib script
ACLOCAL_AMFLAGS = -I m4 ACLOCAL_AMFLAGS = -I m4

File diff suppressed because it is too large Load Diff

View File

@@ -42,6 +42,6 @@ PATH=$TOOLCHAIN/bin:$PATH
--enable-werror \ --enable-werror \
CC=clang \ CC=clang \
CXX=clang++ \ CXX=clang++ \
CPPFLAGS="-I$PREFIX/include" \ CPPFLAGS="-fPIE -I$PREFIX/include" \
PKG_CONFIG_LIBDIR="$PREFIX/lib/pkgconfig" \ PKG_CONFIG_LIBDIR="$PREFIX/lib/pkgconfig" \
LDFLAGS="-L$PREFIX/lib" LDFLAGS="-fPIE -pie -L$PREFIX/lib"

View File

@@ -25,29 +25,16 @@ dnl Do not change user variables!
dnl http://www.gnu.org/software/automake/manual/html_node/Flag-Variables-Ordering.html dnl http://www.gnu.org/software/automake/manual/html_node/Flag-Variables-Ordering.html
AC_PREREQ(2.61) AC_PREREQ(2.61)
AC_INIT([nghttp2], [0.7.6], [t-tujikawa@users.sourceforge.net]) AC_INIT([nghttp2], [1.0.4], [t-tujikawa@users.sourceforge.net])
AC_USE_SYSTEM_EXTENSIONS
LT_PREREQ([2.2.6]) LT_PREREQ([2.2.6])
LT_INIT() LT_INIT()
dnl See versioning rule:
dnl http://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html
AC_SUBST(LT_CURRENT, 12)
AC_SUBST(LT_REVISION, 0)
AC_SUBST(LT_AGE, 7)
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"`
patch=`echo $PACKAGE_VERSION |cut -d. -f3 | cut -d- -f1 | sed -e "s/[^0-9]//g"`
PACKAGE_VERSION_NUM=`printf "0x%02x%02x%02x" "$major" "$minor" "$patch"`
AC_SUBST(PACKAGE_VERSION_NUM)
AC_CANONICAL_BUILD AC_CANONICAL_BUILD
AC_CANONICAL_HOST AC_CANONICAL_HOST
AC_CANONICAL_TARGET AC_CANONICAL_TARGET
AC_CONFIG_MACRO_DIR([m4])
AM_INIT_AUTOMAKE([subdir-objects]) AM_INIT_AUTOMAKE([subdir-objects])
# comment out for now since this requires automake 1.13 or higher and # comment out for now since this requires automake 1.13 or higher and
# travis has older one. # travis has older one.
@@ -55,8 +42,23 @@ AM_INIT_AUTOMAKE([subdir-objects])
m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
AC_CONFIG_MACRO_DIR([m4])
AC_CONFIG_HEADERS([config.h]) AC_CONFIG_HEADERS([config.h])
dnl See versioning rule:
dnl http://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html
AC_SUBST(LT_CURRENT, 14)
AC_SUBST(LT_REVISION, 4)
AC_SUBST(LT_AGE, 0)
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"`
patch=`echo $PACKAGE_VERSION |cut -d. -f3 | cut -d- -f1 | sed -e "s/[^0-9]//g"`
PACKAGE_VERSION_NUM=`printf "0x%02x%02x%02x" "$major" "$minor" "$patch"`
AC_SUBST(PACKAGE_VERSION_NUM)
dnl Checks for command-line options dnl Checks for command-line options
AC_ARG_ENABLE([werror], AC_ARG_ENABLE([werror],
[AS_HELP_STRING([--enable-werror], [AS_HELP_STRING([--enable-werror],
@@ -129,14 +131,17 @@ AC_ARG_VAR([CYTHON], [the Cython executable])
dnl Checks for programs dnl Checks for programs
AC_PROG_CC AC_PROG_CC
AC_PROG_CXX AC_PROG_CXX
AC_PROG_CPP
AC_PROG_INSTALL AC_PROG_INSTALL
AC_PROG_LN_S AC_PROG_LN_S
AC_PROG_MAKE_SET AC_PROG_MAKE_SET
AM_PROG_CC_C_O AC_PROG_MKDIR_P
PKG_PROG_PKG_CONFIG([0.20]) PKG_PROG_PKG_CONFIG([0.20])
AM_PATH_PYTHON([2.7],, [:])
if [test "x$request_python_bindings" != "xno"]; then if [test "x$request_python_bindings" != "xno"]; then
AM_PATH_PYTHON([2.7],, [:])
AX_PYTHON_DEVEL([>= '2.7']) AX_PYTHON_DEVEL([>= '2.7'])
fi fi
@@ -226,20 +231,6 @@ TESTLDADD=
# Additional libraries required for programs under src directory. # Additional libraries required for programs under src directory.
APPLDFLAGS= APPLDFLAGS=
LIBS_OLD=$LIBS
# Search for dlsym function, which is used in tests. Linux needs -ldl,
# but netbsd does not need it.
AC_SEARCH_LIBS([dlsym], [dl])
TESTLDADD="$LIBS $TESTLDADD"
LIBS=$LIBS_OLD
LIBS_OLD=$LIBS
AC_SEARCH_LIBS([clock_gettime], [rt],
[AC_DEFINE([HAVE_CLOCK_GETTIME], [1],
[Define to 1 if you have the `clock_gettime`.])])
APPLDFLAGS="$LIBS $APPLDFLAGS"
LIBS=$LIBS_OLD
case "$host" in case "$host" in
*android*) *android*)
android_build=yes android_build=yes
@@ -253,16 +244,10 @@ case "$host" in
esac esac
# zlib # zlib
if test "x$android_build" = "xyes"; then PKG_CHECK_MODULES([ZLIB], [zlib >= 1.2.3], [have_zlib=yes], [have_zlib=no])
# Use zlib provided by NDK
APPLDFLAGS="-lz $APPLDFLAGS"
have_zlib=yes
else
PKG_CHECK_MODULES([ZLIB], [zlib >= 1.2.3], [have_zlib=yes], [have_zlib=no])
if test "x${have_zlib}" = "xno"; then if test "x${have_zlib}" = "xno"; then
AC_MSG_NOTICE($ZLIB_PKG_ERRORS) AC_MSG_NOTICE($ZLIB_PKG_ERRORS)
fi
fi fi
# cunit # cunit
@@ -328,7 +313,7 @@ fi
# jansson (for src/nghttp, src/deflatehd and src/inflatehd) # jansson (for src/nghttp, src/deflatehd and src/inflatehd)
PKG_CHECK_MODULES([JANSSON], [jansson >= 2.5], PKG_CHECK_MODULES([JANSSON], [jansson >= 2.5],
[have_jansson=yes], [have_jansson=no]) [have_jansson=yes], [have_jansson=no])
if test "x${have_jansson}" == "xyes"; then if test "x${have_jansson}" = "xyes"; then
AC_DEFINE([HAVE_JANSSON], [1], AC_DEFINE([HAVE_JANSSON], [1],
[Define to 1 if you have `libjansson` library.]) [Define to 1 if you have `libjansson` library.])
else else
@@ -358,9 +343,23 @@ if test "x${request_jemalloc}" != "xno"; then
AC_SEARCH_LIBS([malloc_stats_print], [jemalloc], [have_jemalloc=yes], [], AC_SEARCH_LIBS([malloc_stats_print], [jemalloc], [have_jemalloc=yes], [],
[$PTHREAD_LDFLAGS]) [$PTHREAD_LDFLAGS])
LIBS=$LIBS_OLD LIBS=$LIBS_OLD
if test "x${have_jemalloc}" = "xyes"; then
jemalloc_libs=${ac_cv_search_malloc_stats_print}
else
# On Darwin, malloc_stats_print is je_malloc_stats_print
AC_SEARCH_LIBS([je_malloc_stats_print], [jemalloc], [have_jemalloc=yes], [],
[$PTHREAD_LDFLAGS])
LIBS=$LIBS_OLD
if test "x${have_jemalloc}" = "xyes"; then
jemalloc_libs=${ac_cv_search_je_malloc_stats_print}
fi
fi
if test "x${have_jemalloc}" = "xyes" && if test "x${have_jemalloc}" = "xyes" &&
test "x${ac_cv_search_malloc_stats_print}" != "xnone required"; then test "x${jemalloc_libs}" != "xnone required"; then
JEMALLOC_LIBS=${ac_cv_search_malloc_stats_print} JEMALLOC_LIBS=${jemalloc_libs}
AC_SUBST([JEMALLOC_LIBS]) AC_SUBST([JEMALLOC_LIBS])
fi fi
fi fi
@@ -465,6 +464,17 @@ fi
AM_CONDITIONAL([ENABLE_EXAMPLES], [ test "x${enable_examples}" = "xyes" ]) AM_CONDITIONAL([ENABLE_EXAMPLES], [ test "x${enable_examples}" = "xyes" ])
# third-party only be built when needed
enable_third_party=no
if test "x${enable_examples}" = "xyes" ||
test "x${enable_app}" = "xyes" ||
test "x${enable_asio_lib}" = "xyes"; then
enable_third_party=yes
fi
AM_CONDITIONAL([ENABLE_THIRD_PARTY], [ test "x${enable_third_party}" = "xyes" ])
# Python bindings # Python bindings
enable_python_bindings=no enable_python_bindings=no
if test "x${request_python_bindings}" != "xno" && if test "x${request_python_bindings}" != "xno" &&
@@ -498,23 +508,23 @@ AM_CONDITIONAL([ENABLE_FAILMALLOC], [ test "x${enable_failmalloc}" = "xyes" ])
AC_HEADER_ASSERT AC_HEADER_ASSERT
AC_CHECK_HEADERS([ \ AC_CHECK_HEADERS([ \
arpa/inet.h \ arpa/inet.h \
fcntl.h \
inttypes.h \
limits.h \
netdb.h \
netinet/in.h \ netinet/in.h \
pwd.h \ pwd.h \
stddef.h \ stddef.h \
stdint.h \ stdint.h \
stdlib.h \ stdlib.h \
string.h \ string.h \
sys/socket.h \
sys/time.h \
syslog.h \
time.h \ time.h \
unistd.h \ unistd.h \
]) ])
case "${host}" in
*mingw*)
# For ntohl, ntohs in Windows
AC_CHECK_HEADERS([winsock2.h])
;;
esac
# Checks for typedefs, structures, and compiler characteristics. # Checks for typedefs, structures, and compiler characteristics.
AC_TYPE_SIZE_T AC_TYPE_SIZE_T
AC_TYPE_SSIZE_T AC_TYPE_SSIZE_T
@@ -522,8 +532,16 @@ AC_TYPE_UINT8_T
AC_TYPE_UINT16_T AC_TYPE_UINT16_T
AC_TYPE_UINT32_T AC_TYPE_UINT32_T
AC_TYPE_UINT64_T AC_TYPE_UINT64_T
AC_TYPE_INT8_T
AC_TYPE_INT16_T
AC_TYPE_INT32_T
AC_TYPE_INT64_T
AC_TYPE_OFF_T
AC_TYPE_PID_T
AC_TYPE_UID_T
AC_CHECK_TYPES([ptrdiff_t]) AC_CHECK_TYPES([ptrdiff_t])
AC_C_BIGENDIAN AC_C_BIGENDIAN
AC_C_INLINE
AC_SYS_LARGEFILE AC_SYS_LARGEFILE
AC_CHECK_MEMBER([struct tm.tm_gmtoff], [have_struct_tm_tm_gmtoff=yes], AC_CHECK_MEMBER([struct tm.tm_gmtoff], [have_struct_tm_tm_gmtoff=yes],
@@ -542,12 +560,34 @@ AC_CHECK_SIZEOF([int *])
if test "x$cross_compiling" != "xyes"; then if test "x$cross_compiling" != "xyes"; then
AC_FUNC_MALLOC AC_FUNC_MALLOC
fi fi
AC_FUNC_CHOWN
AC_FUNC_ERROR_AT_LINE
AC_FUNC_FORK
# Don't check realloc, since LeakSanitizer detects memory leak during check
# AC_FUNC_REALLOC
AC_FUNC_STRERROR_R
AC_FUNC_STRNLEN
AC_CHECK_FUNCS([ \ AC_CHECK_FUNCS([ \
_Exit \ _Exit \
accept4 \ accept4 \
dup2 \
getcwd \
getpwnam \ getpwnam \
localtime_r \
memchr \
memmove \ memmove \
memset \ memset \
socket \
sqrt \
strchr \
strdup \
strerror \
strndup \
strstr \
strtol \
strtoul \
timegm \ timegm \
]) ])
@@ -564,13 +604,6 @@ AM_CONDITIONAL([ENABLE_TINY_NGHTTPD],
[ test "x${have_epoll}" = "xyes" && [ test "x${have_epoll}" = "xyes" &&
test "x${have_timerfd_create}" = "xyes"]) test "x${have_timerfd_create}" = "xyes"])
dnl Windows library for winsock2
case "${host}" in
*mingw*)
LIBS="$LIBS -lws2_32"
;;
esac
ac_save_CFLAGS=$CFLAGS ac_save_CFLAGS=$CFLAGS
CFLAGS= CFLAGS=
@@ -664,6 +697,7 @@ AC_CONFIG_FILES([
doc/asio_http2_client.h.rst doc/asio_http2_client.h.rst
doc/contribute.rst doc/contribute.rst
contrib/Makefile contrib/Makefile
script/Makefile
]) ])
AC_OUTPUT AC_OUTPUT
@@ -702,6 +736,7 @@ AC_MSG_NOTICE([summary of build options:
Spdylay: ${have_spdylay} Spdylay: ${have_spdylay}
Jansson: ${have_jansson} Jansson: ${have_jansson}
Jemalloc: ${have_jemalloc} Jemalloc: ${have_jemalloc}
Zlib: ${have_zlib}
Boost CPPFLAGS: ${BOOST_CPPFLAGS} Boost CPPFLAGS: ${BOOST_CPPFLAGS}
Boost LDFLAGS: ${BOOST_LDFLAGS} Boost LDFLAGS: ${BOOST_LDFLAGS}
Boost::ASIO: ${BOOST_ASIO_LIB} Boost::ASIO: ${BOOST_ASIO_LIB}
@@ -714,4 +749,5 @@ AC_MSG_NOTICE([summary of build options:
Examples: ${enable_examples} Examples: ${enable_examples}
Python bindings:${enable_python_bindings} Python bindings:${enable_python_bindings}
Threading: ${enable_threads} Threading: ${enable_threads}
Third-party: ${enable_third_party}
]) ])

2
contrib/.gitignore vendored
View File

@@ -1 +1,3 @@
nghttpx-init nghttpx-init
nghttpx.service
nghttpx-upstart.conf

View File

@@ -21,19 +21,24 @@
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
EXTRA_DIST = nghttpx-init.in nghttpx-logrotate configfiles = nghttpx-init nghttpx.service nghttpx-upstart.conf
EXTRA_DIST = $(configfiles:%=%.in) nghttpx-logrotate
edit = sed -e 's|@bindir[@]|$(bindir)|g' edit = sed -e 's|@bindir[@]|$(bindir)|g'
nghttpx-init: Makefile nghttpx-init: %: $(srcdir)/%.in
rm -f $@ $@.tmp rm -f $@ $@.tmp
$(edit) $(srcdir)/$@.in > $@.tmp $(edit) $< > $@.tmp
chmod +x $@.tmp chmod +x $@.tmp
mv $@.tmp $@ mv $@.tmp $@
nghttpx-init: $(srcdir)/nghttpx-init.in nghttpx.service nghttpx-upstart.conf: %: $(srcdir)/%.in
$(edit) $< > $@
all-local: nghttpx-init $(configfiles): Makefile
all-local: $(configfiles)
clean-local: clean-local:
-rm -f nghttpx-init nghttpx-init.tmp -rm -f nghttpx-init.tmp $(configfiles)

View File

@@ -1,18 +1,11 @@
/var/log/nghttpx/*.log { /var/log/nghttpx/*.log {
weekly weekly
missingok rotate 52
rotate 52 missingok
compress compress
delaycompress delaycompress
notifempty notifempty
create 0640 www-data adm postrotate
sharedscripts killall -USR1 nghttpx 2> /dev/null || true
prerotate endscript
if [ -d /etc/logrotate.d/httpd-prerotate ]; then \
run-parts /etc/logrotate.d/httpd-prerotate; \
fi \
endscript
postrotate
[ -s /run/nghttpx.pid ] && kill -USR1 `cat /run/nghttpx.pid`
endscript
} }

View File

@@ -0,0 +1,8 @@
# vim: ft=upstart:
description "HTTP/2 reverse proxy"
start on runlevel [2]
stop on runlevel [016]
exec @bindir@/nghttpx

View File

@@ -0,0 +1,10 @@
[Unit]
Description=HTTP/2 experimental proxy
After=network.target
[Service]
Type=simple
ExecStart=@bindir@/nghttpx --errorlog-syslog
[Install]
WantedBy=multi-user.target

23
doc/.gitignore vendored
View File

@@ -1,3 +1,24 @@
# generated files
apiref.rst apiref.rst
asio_http2.h.rst
asio_http2_client.h.rst
asio_http2_server.h.rst
building-android-binary.rst
conf.py conf.py
manual contribute.rst
enums.rst
h2load-howto.rst
index.rst
libnghttp2_asio.rst
macros.rst
manual/
nghttp2.h.rst
nghttp2_*.rst
nghttp2ver.h.rst
nghttpx-howto.rst
package_README.rst
python-apiref.rst
tutorial-client.rst
tutorial-hpack.rst
tutorial-server.rst
types.rst

View File

@@ -23,10 +23,111 @@
man_MANS = nghttp.1 nghttpd.1 nghttpx.1 h2load.1 man_MANS = nghttp.1 nghttpd.1 nghttpx.1 h2load.1
APIDOCS= \
apiref.rst \
macros.rst \
enums.rst \
types.rst \
nghttp2_check_header_name.rst \
nghttp2_check_header_value.rst \
nghttp2_hd_deflate_bound.rst \
nghttp2_hd_deflate_change_table_size.rst \
nghttp2_hd_deflate_del.rst \
nghttp2_hd_deflate_hd.rst \
nghttp2_hd_deflate_new.rst \
nghttp2_hd_deflate_new2.rst \
nghttp2_hd_inflate_change_table_size.rst \
nghttp2_hd_inflate_del.rst \
nghttp2_hd_inflate_end_headers.rst \
nghttp2_hd_inflate_hd.rst \
nghttp2_hd_inflate_new.rst \
nghttp2_hd_inflate_new2.rst \
nghttp2_is_fatal.rst \
nghttp2_nv_compare_name.rst \
nghttp2_option_del.rst \
nghttp2_option_new.rst \
nghttp2_option_set_no_auto_window_update.rst \
nghttp2_option_set_no_http_messaging.rst \
nghttp2_option_set_peer_max_concurrent_streams.rst \
nghttp2_option_set_no_recv_client_magic.rst \
nghttp2_pack_settings_payload.rst \
nghttp2_priority_spec_check_default.rst \
nghttp2_priority_spec_default_init.rst \
nghttp2_priority_spec_init.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_on_begin_frame_callback.rst \
nghttp2_session_callbacks_set_on_begin_headers_callback.rst \
nghttp2_session_callbacks_set_on_data_chunk_recv_callback.rst \
nghttp2_session_callbacks_set_on_frame_not_send_callback.rst \
nghttp2_session_callbacks_set_on_frame_recv_callback.rst \
nghttp2_session_callbacks_set_on_frame_send_callback.rst \
nghttp2_session_callbacks_set_on_header_callback.rst \
nghttp2_session_callbacks_set_on_invalid_frame_recv_callback.rst \
nghttp2_session_callbacks_set_on_stream_close_callback.rst \
nghttp2_session_callbacks_set_recv_callback.rst \
nghttp2_session_callbacks_set_select_padding_callback.rst \
nghttp2_session_callbacks_set_send_callback.rst \
nghttp2_session_callbacks_set_send_data_callback.rst \
nghttp2_session_client_new.rst \
nghttp2_session_client_new2.rst \
nghttp2_session_client_new3.rst \
nghttp2_session_consume.rst \
nghttp2_session_consume_connection.rst \
nghttp2_session_consume_stream.rst \
nghttp2_session_del.rst \
nghttp2_session_get_effective_local_window_size.rst \
nghttp2_session_get_effective_recv_data_length.rst \
nghttp2_session_get_last_proc_stream_id.rst \
nghttp2_session_get_next_stream_id.rst \
nghttp2_session_get_outbound_queue_size.rst \
nghttp2_session_get_remote_settings.rst \
nghttp2_session_get_remote_window_size.rst \
nghttp2_session_get_stream_effective_local_window_size.rst \
nghttp2_session_get_stream_effective_recv_data_length.rst \
nghttp2_session_get_stream_local_close.rst \
nghttp2_session_get_stream_remote_close.rst \
nghttp2_session_get_stream_remote_window_size.rst \
nghttp2_session_get_stream_user_data.rst \
nghttp2_session_mem_recv.rst \
nghttp2_session_mem_send.rst \
nghttp2_session_recv.rst \
nghttp2_session_resume_data.rst \
nghttp2_session_send.rst \
nghttp2_session_server_new.rst \
nghttp2_session_server_new2.rst \
nghttp2_session_server_new3.rst \
nghttp2_session_set_next_stream_id.rst \
nghttp2_session_set_stream_user_data.rst \
nghttp2_session_terminate_session.rst \
nghttp2_session_terminate_session2.rst \
nghttp2_session_upgrade.rst \
nghttp2_session_want_read.rst \
nghttp2_session_want_write.rst \
nghttp2_strerror.rst \
nghttp2_submit_data.rst \
nghttp2_submit_goaway.rst \
nghttp2_submit_headers.rst \
nghttp2_submit_ping.rst \
nghttp2_submit_priority.rst \
nghttp2_submit_push_promise.rst \
nghttp2_submit_request.rst \
nghttp2_submit_response.rst \
nghttp2_submit_rst_stream.rst \
nghttp2_submit_settings.rst \
nghttp2_submit_shutdown_notice.rst \
nghttp2_submit_trailer.rst \
nghttp2_submit_window_update.rst \
nghttp2_version.rst
EXTRA_DIST = \ EXTRA_DIST = \
mkapiref.py \ mkapiref.py \
README.rst \ README.rst \
apiref-header.rst \ programmers-guide.rst \
$(APIDOCS) \
nghttp.1.rst \ nghttp.1.rst \
nghttpd.1.rst \ nghttpd.1.rst \
nghttpx.1.rst \ nghttpx.1.rst \
@@ -99,13 +200,30 @@ help:
@echo " linkcheck to check all external links for integrity" @echo " linkcheck to check all external links for integrity"
@echo " doctest to run all doctests embedded in the documentation (if enabled)" @echo " doctest to run all doctests embedded in the documentation (if enabled)"
apiref.rst: $(top_builddir)/lib/includes/nghttp2/nghttp2ver.h \ apiref.rst macros.rst enums.rst types.rst: \
$(top_builddir)/lib/includes/nghttp2/nghttp2ver.h \
$(top_builddir)/lib/includes/nghttp2/nghttp2.h $(top_builddir)/lib/includes/nghttp2/nghttp2.h
$(PYTHON) $(top_srcdir)/doc/mkapiref.py \ $(PYTHON) $(top_srcdir)/doc/mkapiref.py \
--header $(top_srcdir)/doc/apiref-header.rst $^ > $@ $@ macros.rst enums.rst types.rst . $^
# Inspired by
# http://www.gnu.org/savannah-checkouts/gnu/automake/manual/html_node/Multiple-Outputs.html
apidoc.stamp: $(top_builddir)/lib/includes/nghttp2/nghttp2ver.h \
$(top_builddir)/lib/includes/nghttp2/nghttp2.h
@rm -f apidoc.tmp
@touch apidoc.tmp
$(PYTHON) $(top_srcdir)/doc/mkapiref.py \
$@ macros.rst enums.rst types.rst . $^
@mv -f apidoc.tmp $@
$(APIDOC): apidoc.stamp
## Recover from the removal of $@
@if test -f $@; then :; else \
rm -f apidoc.stamp; \
$(MAKE) $(AM_MAKEFLAGS) apidoc.stamp; \
fi
clean-local: clean-local:
-rm apiref.rst -rm $(APIDOCS)
-rm -rf $(BUILDDIR)/* -rm -rf $(BUILDDIR)/*
html-local: apiref.rst html-local: apiref.rst

View File

@@ -5,7 +5,7 @@ From https://github.com/ryan-roemer/sphinx-bootstrap-theme.
""" """
import os import os
VERSION = (0, 1, 5) VERSION = (0, 1, 8)
__version__ = ".".join(str(v) for v in VERSION) __version__ = ".".join(str(v) for v in VERSION)
__version_full__ = __version__ __version_full__ = __version__

View File

@@ -6,12 +6,16 @@
{% endfor %} {% endfor %}
<li>{{ title }}</li> <li>{{ title }}</li>
<li class="wy-breadcrumbs-aside"> <li class="wy-breadcrumbs-aside">
{% if display_github %} {% if pagename != "search" %}
<a href="https://github.com/{{ github_user }}/{{ github_repo }}/blob/{{ github_version }}{{ conf_py_path }}{{ pagename }}{{ source_suffix }}" class="fa fa-github"> Edit on GitHub</a> {% if display_github %}
{% elif display_bitbucket %} <a href="https://{{ github_host|default("github.com") }}/{{ github_user }}/{{ github_repo }}/blob/{{ github_version }}{{ conf_py_path }}{{ pagename }}{{ source_suffix }}" class="fa fa-github"> Edit on GitHub</a>
<a href="https://bitbucket.org/{{ bitbucket_user }}/{{ bitbucket_repo }}/src/{{ bitbucket_version}}{{ conf_py_path }}{{ pagename }}{{ source_suffix }}" class="fa fa-bitbucket"> Edit on Bitbucket</a> {% elif display_bitbucket %}
{% elif show_source and has_source and sourcename %} <a href="https://bitbucket.org/{{ bitbucket_user }}/{{ bitbucket_repo }}/src/{{ bitbucket_version}}{{ conf_py_path }}{{ pagename }}{{ source_suffix }}" class="fa fa-bitbucket"> Edit on Bitbucket</a>
<a href="{{ pathto('_sources/' + sourcename, true)|e }}" rel="nofollow"> View page source</a> {% elif show_source and source_url_prefix %}
<a href="{{ source_url_prefix }}{{ pagename }}{{ source_suffix }}">View page source</a>
{% elif show_source and has_source and sourcename %}
<a href="{{ pathto('_sources/' + sourcename, true)|e }}" rel="nofollow"> View page source</a>
{% endif %}
{% endif %} {% endif %}
</li> </li>
</ul> </ul>

View File

@@ -2,10 +2,10 @@
{% if next or prev %} {% if next or prev %}
<div class="rst-footer-buttons" role="navigation" aria-label="footer navigation"> <div class="rst-footer-buttons" role="navigation" aria-label="footer navigation">
{% if next %} {% if next %}
<a href="{{ next.link|e }}" class="btn btn-neutral float-right" title="{{ next.title|striptags|e }}">Next <span class="fa fa-arrow-circle-right"></span></a> <a href="{{ next.link|e }}" class="btn btn-neutral float-right" title="{{ next.title|striptags|e }}" accesskey="n">Next <span class="fa fa-arrow-circle-right"></span></a>
{% endif %} {% endif %}
{% if prev %} {% if prev %}
<a href="{{ prev.link|e }}" class="btn btn-neutral" title="{{ prev.title|striptags|e }}"><span class="fa fa-arrow-circle-left"></span> Previous</a> <a href="{{ prev.link|e }}" class="btn btn-neutral" title="{{ prev.title|striptags|e }}" accesskey="p"><span class="fa fa-arrow-circle-left"></span> Previous</a>
{% endif %} {% endif %}
</div> </div>
{% endif %} {% endif %}
@@ -28,6 +28,9 @@
</p> </p>
</div> </div>
{%- if show_sphinx %}
{% trans %}Built with <a href="http://sphinx-doc.org/">Sphinx</a> using a <a href="https://github.com/snide/sphinx_rtd_theme">theme</a> provided by <a href="https://readthedocs.org">Read the Docs</a>{% endtrans %}. {% trans %}Built with <a href="http://sphinx-doc.org/">Sphinx</a> using a <a href="https://github.com/snide/sphinx_rtd_theme">theme</a> provided by <a href="https://readthedocs.org">Read the Docs</a>{% endtrans %}.
{%- endif %}
</footer> </footer>

View File

@@ -12,6 +12,7 @@
<!--[if gt IE 8]><!--> <html class="no-js" lang="en" > <!--<![endif]--> <!--[if gt IE 8]><!--> <html class="no-js" lang="en" > <!--<![endif]-->
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
{{ metatags }}
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
{% block htmltitle %} {% block htmltitle %}
<title>{{ title|striptags|e }}{{ titlesuffix }}</title> <title>{{ title|striptags|e }}{{ titlesuffix }}</title>
@@ -23,7 +24,6 @@
{% endif %} {% endif %}
{# CSS #} {# CSS #}
<link href='https://fonts.googleapis.com/css?family=Lato:400,700,400italic,700italic|Roboto+Slab:400,700|Inconsolata:400,700&subset=latin,cyrillic' rel='stylesheet' type='text/css'>
{# OPENSEARCH #} {# OPENSEARCH #}
{% if not embedded %} {% if not embedded %}
@@ -42,6 +42,10 @@
<link rel="stylesheet" href="{{ pathto(cssfile, 1) }}" type="text/css" /> <link rel="stylesheet" href="{{ pathto(cssfile, 1) }}" type="text/css" />
{% endfor %} {% endfor %}
{% for cssfile in extra_css_files %}
<link rel="stylesheet" href="{{ pathto(cssfile, 1) }}" type="text/css" />
{% endfor %}
{%- block linktags %} {%- block linktags %}
{%- if hasdoc('about') %} {%- if hasdoc('about') %}
<link rel="author" title="{{ _('About these documents') }}" <link rel="author" title="{{ _('About these documents') }}"
@@ -71,7 +75,7 @@
{%- block extrahead %} {% endblock %} {%- block extrahead %} {% endblock %}
{# Keep modernizr in head - http://modernizr.com/docs/#installing #} {# Keep modernizr in head - http://modernizr.com/docs/#installing #}
<script src="https://cdnjs.cloudflare.com/ajax/libs/modernizr/2.6.2/modernizr.min.js"></script> <script src="_static/js/modernizr.min.js"></script>
</head> </head>
@@ -83,14 +87,27 @@
<nav data-toggle="wy-nav-shift" class="wy-nav-side"> <nav data-toggle="wy-nav-shift" class="wy-nav-side">
<div class="wy-side-nav-search"> <div class="wy-side-nav-search">
{% block sidebartitle %} {% block sidebartitle %}
<a href="{{ pathto(master_doc) }}" class="fa fa-home"> {{ project }}</a>
{% endblock %} {% if logo and theme_logo_only %}
<a href="{{ pathto(master_doc) }}">
{% else %}
<a href="{{ pathto(master_doc) }}" class="icon icon-home"> {{ project }}
{% endif %}
{% if logo %}
{# Not strictly valid HTML, but it's the only way to display/scale it properly, without weird scripting or heaps of work #}
<img src="{{ pathto('_static/' + logo, 1) }}" class="logo" />
{% endif %}
</a>
{% include "searchbox.html" %} {% include "searchbox.html" %}
{% endblock %}
</div> </div>
<div class="wy-menu wy-menu-vertical" data-spy="affix" role="navigation" aria-label="main navigation"> <div class="wy-menu wy-menu-vertical" data-spy="affix" role="navigation" aria-label="main navigation">
{% block menu %} {% block menu %}
{% set toctree = toctree(maxdepth=2, collapse=False, includehidden=True) %} {% set toctree = toctree(maxdepth=4, collapse=False, includehidden=True) %}
{% if toctree %} {% if toctree %}
{{ toctree }} {{ toctree }}
{% else %} {% else %}

View File

@@ -0,0 +1,7 @@
{
"version": 3,
"mappings": "CAyDA,SAAY,EACV,qBAAsB,EAAE,UAAW,EAqDrC,QAAS,EARP,IAAK,EAAE,AAAC,EACR,+BAAS,EAEP,MAAO,EAAE,IAAK,EACd,MAAO,EAAE,CAAE,EACb,cAAO,EACL,IAAK,EAAE,GAAI,EC1Gb,SAkBC,EAjBC,UAAW,ECFJ,UAAW,EDGlB,UAAW,EAHqC,KAAM,EAItD,SAAU,EAJsD,KAAM,EAapE,EAAG,EAAE,qCAAwB,EAC7B,EAAG,EAAE,0PAAyE,ECZpF,SAAU,EACR,MAAO,EAAE,WAAY,EACrB,UAAW,EAAE,UAAW,EACxB,SAAU,EAAE,KAAM,EAClB,UAAW,EAAE,KAAM,EACnB,UAAW,EAAE,AAAC,EACd,cAAe,EAAE,MAAO,EAG1B,IAAK,EACH,MAAO,EAAE,WAAY,EACrB,cAAe,EAAE,MAAO,EAIxB,KAAG,EACD,MAAO,EAAE,WAAY,EACvB,sCAAiB,EAGf,IAAK,EAAE,MAAY,EAEvB,KAAM,EACJ,cAAe,EAAE,GAAI,EACrB,UAAW,EAAE,EAAG,EAChB,UAAW,EAAE,KAAM,EAEjB,YAAG,EACD,IAAK,EAAE,IAAI,EACb,oDAAiB,EAGf,aAAc,EAAE,OAAQ,EAG9B,cAAe,EACb,MAAO,EAAE,EAAO,EAElB,gBAAiB,EACf,MAAO,EAAE,EAAO,EAElB,oBAAqB,EACnB,MAAO,EAAE,EAAO,EAElB,sBAAuB,EACrB,MAAO,EAAE,EAAO,EAElB,kBAAmB,EACjB,MAAO,EAAE,EAAO,EAElB,oBAAqB,EACnB,MAAO,EAAE,EAAO,EAElB,oBAAqB,EACnB,MAAO,EAAE,EAAO,EAElB,sBAAuB,EACrB,MAAO,EAAE,EAAO,EAElB,qBAAsB,EACpB,MAAO,EAAE,EAAO,EAElB,uBAAwB,EACtB,MAAO,EAAE,EAAO,ECnElB,YAAa,EACX,OAAQ,EAAE,IAAK,EACf,KAAM,EAAE,AAAC,EACT,GAAI,EAAE,AAAC,EACP,IAAK,EC6E+B,IAAK,ED5EzC,IAAK,ECE+B,MAAyB,EDD7D,SAAU,EAAE,MAAkC,EAC9C,SAAU,EAAE,iBAAiC,EAC7C,UAAW,EEAyB,sDAAM,EFC1C,MAAO,EC+E6B,EAAG,ED9EvC,cAAC,EACC,IAAK,ECqE6B,MAAW,EDpE7C,cAAe,EAAE,GAAI,EACvB,6BAAgB,EACd,MAAO,EAAE,GAAI,EACf,iCAAoB,EAClB,MAAO,EAAE,GAAqB,EAC9B,eAAgB,EAAE,MAAkC,EACpD,MAAO,EAAE,IAAK,EACd,SAAU,EAAE,IAAK,EACjB,QAAS,EAAE,EAAG,EACd,KAAM,EAAE,MAAO,EACf,IAAK,ECiD6B,MAAM,EJgC1C,IAAK,EAAE,AAAC,EACR,iFAAS,EAEP,MAAO,EAAE,IAAK,EACd,MAAO,EAAE,CAAE,EACb,uCAAO,EACL,IAAK,EAAE,GAAI,EGrFX,qCAAG,EACD,IAAK,EClB2B,MAAyB,EDmB3D,0CAAQ,EACN,IAAK,EAAE,GAAI,EACb,4CAAU,EACR,IAAK,EAAE,GAAI,EACb,iDAAiB,EACf,eAAgB,ECQgB,MAAI,EDPpC,IAAK,EC0B2B,GAAM,EDzBxC,wDAAwB,EACtB,eAAgB,ECXgB,MAAO,EDYvC,IAAK,ECzB2B,GAAI,ED0BxC,yCAA8B,EAC5B,MAAO,EAAE,IAAK,EAChB,gCAAmB,EACjB,QAAS,EAAE,EAAG,EACd,MAAO,EAAE,GAAqB,EAC9B,IAAK,ECE6B,GAAwB,EDD1D,MAAO,EAAE,GAAI,EACb,mCAAE,EACA,MAAO,EAAE,IAAK,EACd,KAAM,EAAE,EAAG,EACX,KAAM,EAAE,AAAC,EACT,KAAM,EAAE,KAAM,EACd,MAAO,EAAE,AAAC,EACV,SAAU,EAAE,gBAA6C,EAC3D,mCAAE,EACA,MAAO,EAAE,WAAY,EACrB,KAAM,EAAE,AAAC,EACT,qCAAC,EACC,MAAO,EAAE,WAAY,EACrB,MAAO,EAAE,EAAqB,EAC9B,IAAK,ECjDyB,MAAyB,EDkD7D,sBAAW,EACT,IAAK,EAAE,GAAI,EACX,KAAM,EAAE,GAAI,EACZ,IAAK,EAAE,GAAI,EACX,GAAI,EAAE,GAAI,EACV,KAAM,EAAE,GAAI,EACZ,QAAS,ECkByB,IAAK,EDjBvC,iCAAU,EACR,IAAK,EAAE,GAAI,EACb,+BAAQ,EACN,IAAK,EAAE,GAAI,EACb,oDAA+B,EAC7B,SAAU,EAAE,IAAK,EACjB,6DAAQ,EACN,IAAK,EAAE,GAAI,EACb,+DAAU,EACR,IAAK,EAAE,GAAI,EACf,2CAAoB,EAClB,IAAK,EAAE,GAAI,EACX,KAAM,EAAE,GAAI,EACZ,UAAW,EAAE,GAAI,EACjB,MAAO,EAAE,IAAuB,EAChC,MAAO,EAAE,IAAK,EACd,SAAU,EAAE,KAAM,EGhDpB,mCAAsB,EHmDxB,YAAa,EACX,IAAK,EAAE,EAAG,EACV,MAAO,EAAE,GAAI,EACb,kBAAO,EACL,MAAO,EAAE,IAAK,EAClB,EAAG,EACD,IAAK,EAAE,GAAI,EACX,KAAM,EAAE,GAAI",
"sources": ["../../../bower_components/wyrm/sass/wyrm_core/_mixin.sass","../../../bower_components/bourbon/dist/css3/_font-face.scss","../../../sass/_theme_badge_fa.sass","../../../sass/_theme_badge.sass","../../../bower_components/wyrm/sass/wyrm_core/_wy_variables.sass","../../../sass/_theme_variables.sass","../../../bower_components/neat/app/assets/stylesheets/grid/_media.scss"],
"names": [],
"file": "badge_only.css"
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

File diff suppressed because one or more lines are too long

View File

@@ -1,47 +1,113 @@
$( document ).ready(function() { function toggleCurrent (elem) {
var parent_li = elem.closest('li');
parent_li.siblings('li.current').removeClass('current');
parent_li.siblings().find('li.current').removeClass('current');
parent_li.find('> ul li.current').removeClass('current');
parent_li.toggleClass('current');
}
$(document).ready(function() {
// Shift nav in mobile when clicking the menu. // Shift nav in mobile when clicking the menu.
$(document).on('click', "[data-toggle='wy-nav-top']", function() { $(document).on('click', "[data-toggle='wy-nav-top']", function() {
$("[data-toggle='wy-nav-shift']").toggleClass("shift"); $("[data-toggle='wy-nav-shift']").toggleClass("shift");
$("[data-toggle='rst-versions']").toggleClass("shift"); $("[data-toggle='rst-versions']").toggleClass("shift");
}); });
// Close menu when you click a link. // Nav menu link click operations
$(document).on('click', ".wy-menu-vertical .current ul li a", function() { $(document).on('click', ".wy-menu-vertical .current ul li a", function() {
$("[data-toggle='wy-nav-shift']").removeClass("shift"); var target = $(this);
$("[data-toggle='rst-versions']").toggleClass("shift"); // Close menu when you click a link.
$("[data-toggle='wy-nav-shift']").removeClass("shift");
$("[data-toggle='rst-versions']").toggleClass("shift");
// Handle dynamic display of l3 and l4 nav lists
toggleCurrent(target);
if (typeof(window.SphinxRtdTheme) != 'undefined') {
window.SphinxRtdTheme.StickyNav.hashChange();
}
}); });
$(document).on('click', "[data-toggle='rst-current-version']", function() { $(document).on('click', "[data-toggle='rst-current-version']", function() {
$("[data-toggle='rst-versions']").toggleClass("shift-up"); $("[data-toggle='rst-versions']").toggleClass("shift-up");
}); });
// Make tables responsive // Make tables responsive
$("table.docutils:not(.field-list)").wrap("<div class='wy-table-responsive'></div>"); $("table.docutils:not(.field-list)").wrap("<div class='wy-table-responsive'></div>");
// Add expand links to all parents of nested ul
$('.wy-menu-vertical ul').siblings('a').each(function () {
var link = $(this);
expand = $('<span class="toctree-expand"></span>');
expand.on('click', function (ev) {
toggleCurrent(link);
ev.stopPropagation();
return false;
});
link.prepend(expand);
});
}); });
// Sphinx theme state
window.SphinxRtdTheme = (function (jquery) { window.SphinxRtdTheme = (function (jquery) {
var stickyNav = (function () { var stickyNav = (function () {
var navBar, var navBar,
win, win,
stickyNavCssClass = 'stickynav', winScroll = false,
applyStickNav = function () { linkScroll = false,
if (navBar.height() <= win.height()) { winPosition = 0,
navBar.addClass(stickyNavCssClass);
} else {
navBar.removeClass(stickyNavCssClass);
}
},
enable = function () { enable = function () {
applyStickNav(); init();
win.on('resize', applyStickNav); reset();
win.on('hashchange', reset);
// Set scrolling
win.on('scroll', function () {
if (!linkScroll) {
winScroll = true;
}
});
setInterval(function () {
if (winScroll) {
winScroll = false;
var newWinPosition = win.scrollTop(),
navPosition = navBar.scrollTop(),
newNavPosition = navPosition + (newWinPosition - winPosition);
navBar.scrollTop(newNavPosition);
winPosition = newWinPosition;
}
}, 25);
}, },
init = function () { init = function () {
navBar = jquery('nav.wy-nav-side:first'); navBar = jquery('nav.wy-nav-side:first');
win = jquery(window); win = jquery(window);
},
reset = function () {
// Get anchor from URL and open up nested nav
var anchor = encodeURI(window.location.hash);
if (anchor) {
try {
var link = $('.wy-menu-vertical')
.find('[href="' + anchor + '"]');
$('.wy-menu-vertical li.toctree-l1 li.current')
.removeClass('current');
link.closest('li.toctree-l2').addClass('current');
link.closest('li.toctree-l3').addClass('current');
link.closest('li.toctree-l4').addClass('current');
}
catch (err) {
console.log("Error expanding nav for anchor", err);
}
}
},
hashChange = function () {
linkScroll = true;
win.one('hashchange', function () {
linkScroll = false;
});
}; };
jquery(init); jquery(init);
return { return {
enable : enable enable: enable,
hashChange: hashChange
}; };
}()); }());
return { return {
StickyNav : stickyNav StickyNav: stickyNav
}; };
}($)); }($));

View File

@@ -6,3 +6,4 @@ stylesheet = css/theme.css
typekit_id = hiw1hhg typekit_id = hiw1hhg
analytics_id = analytics_id =
sticky_navigation = False sticky_navigation = False
logo_only =

View File

@@ -8,7 +8,7 @@ _h2load()
_get_comp_words_by_ref cur prev _get_comp_words_by_ref cur prev
case $cur in case $cur in
-*) -*)
COMPREPLY=( $( compgen -W '--threads --connection-window-bits --input-file --help --requests --verbose --version --window-bits --clients --no-tls-proto --header --max-concurrent-streams ' -- "$cur" ) ) COMPREPLY=( $( compgen -W '--threads --connection-window-bits --input-file --help --requests --data --verbose --version --window-bits --clients --no-tls-proto --header --max-concurrent-streams ' -- "$cur" ) )
;; ;;
*) *)
_filedir _filedir

View File

@@ -1,7 +1,10 @@
#!/usr/bin/env python #!/usr/bin/env python
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from __future__ import print_function
import subprocess import subprocess
from StringIO import StringIO import io
import re import re
import sys import sys
import os.path import os.path
@@ -14,10 +17,10 @@ class Option:
def get_all_options(cmd): def get_all_options(cmd):
opt_pattern = re.compile(r' (?:(-.), )?(--[^\s\[=]+)(\[)?') opt_pattern = re.compile(r' (?:(-.), )?(--[^\s\[=]+)(\[)?')
proc = subprocess.Popen([cmd, "--help"], stdout=subprocess.PIPE) proc = subprocess.Popen([cmd, "--help"], stdout=subprocess.PIPE)
stdoutdata, stderrdata = proc.communicate() stdoutdata, _ = proc.communicate()
cur_option = None cur_option = None
opts = {} opts = {}
for line in StringIO(stdoutdata): for line in io.StringIO(stdoutdata.decode('utf-8')):
match = opt_pattern.match(line) match = opt_pattern.match(line)
if not match: if not match:
continue continue
@@ -45,7 +48,7 @@ _{name}()
-*) -*)
COMPREPLY=( $( compgen -W '\ COMPREPLY=( $( compgen -W '\
''') ''')
for opt in opts.itervalues(): for opt in opts.values():
out.write(opt.long_opt) out.write(opt.long_opt)
out.write(' ') out.write(' ')
@@ -66,8 +69,8 @@ complete -F _{name} {name}
if __name__ == '__main__': if __name__ == '__main__':
if len(sys.argv) < 2: if len(sys.argv) < 2:
print "Generates bash_completion using `/path/to/cmd --help'" print("Generates bash_completion using `/path/to/cmd --help'")
print "Usage: make_bash_completion.py /path/to/cmd" print("Usage: make_bash_completion.py /path/to/cmd")
exit(1) exit(1)
name = os.path.basename(sys.argv[1]) name = os.path.basename(sys.argv[1])
opts = get_all_options(sys.argv[1]) opts = get_all_options(sys.argv[1])

View File

@@ -8,7 +8,7 @@ _nghttp()
_get_comp_words_by_ref cur prev _get_comp_words_by_ref cur prev
case $cur in case $cur in
-*) -*)
COMPREPLY=( $( compgen -W '--verbose --no-dep --get-assets --har --header-table-size --multiply --padding --dep-idle --continuation --connection-window-bits --peer-max-concurrent-streams --timeout --data --no-content-length --version --color --cert --upgrade --remote-name --weight --help --key --null-out --window-bits --stat --header ' -- "$cur" ) ) COMPREPLY=( $( compgen -W '--no-push --verbose --no-dep --get-assets --har --header-table-size --multiply --padding --hexdump --continuation --connection-window-bits --peer-max-concurrent-streams --timeout --data --no-content-length --version --color --cert --upgrade --remote-name --trailer --weight --help --key --null-out --window-bits --stat --header ' -- "$cur" ) )
;; ;;
*) *)
_filedir _filedir

View File

@@ -8,7 +8,7 @@ _nghttpd()
_get_comp_words_by_ref cur prev _get_comp_words_by_ref cur prev
case $cur in case $cur in
-*) -*)
COMPREPLY=( $( compgen -W '--error-gzip --push --header-table-size --htdocs --padding --verbose --version --help --daemon --verify-client --workers --no-tls --color --early-response --dh-param-file ' -- "$cur" ) ) COMPREPLY=( $( compgen -W '--error-gzip --push --header-table-size --trailer --htdocs --address --padding --verbose --version --help --hexdump --dh-param-file --daemon --verify-client --echo-upload --workers --no-tls --color --early-response --max-concurrent-streams ' -- "$cur" ) )
;; ;;
*) *)
_filedir _filedir

View File

@@ -8,7 +8,7 @@ _nghttpx()
_get_comp_words_by_ref cur prev _get_comp_words_by_ref cur prev
case $cur in case $cur in
-*) -*)
COMPREPLY=( $( compgen -W '--frontend-http2-connection-window-bits --worker-read-rate --frontend-no-tls --frontend-http2-dump-request-header --daemon --write-rate --altsvc --frontend-http2-dump-response-header --backend-http1-connections-per-frontend --tls-ticket-key-file --ciphers --verify-client-cacert --backend-keep-alive-timeout --strip-incoming-x-forwarded-for --errorlog-file --private-key-passwd-file --version --backlog --backend-http-proxy-uri --add-response-header --backend-write-timeout --backend-request-buffer --add-x-forwarded-for --write-burst --backend-http2-connection-window-bits --insecure --rlimit-nofile --backend-http2-window-bits --tls-proto-list --no-location-rewrite --padding --accesslog-syslog --conf --http2-max-concurrent-streams --client-proxy --worker-frontend-connections --cacert --frontend-read-timeout --worker-write-burst --npn-list --syslog-facility --backend-http1-connections-per-host --no-server-push --client --http2-bridge --no-via --user --stream-write-timeout --backend-response-buffer --http2-no-cookie-crumbling --backend-read-timeout --stream-read-timeout --workers --worker-read-burst --tls-ctx-per-worker --dh-param-file --errorlog-syslog --frontend --accesslog-file --http2-proxy --read-burst --accesslog-format --frontend-http2-window-bits --backend-no-tls --client-private-key-file --pid-file --client-cert-file --no-host-rewrite --log-level --worker-write-rate --help --backend-tls-sni-field --subcert --frontend-frame-debug --frontend-write-timeout --verify-client --read-rate --frontend-http2-read-timeout --backend-ipv4 --listener-disable-timeout --backend-ipv6 --backend ' -- "$cur" ) ) COMPREPLY=( $( compgen -W '--worker-read-rate --frontend-no-tls --frontend-http2-dump-response-header --backend-http1-connections-per-frontend --tls-ticket-key-file --verify-client-cacert --backend-request-buffer --backend-http2-connection-window-bits --conf --worker-write-burst --npn-list --fetch-ocsp-response-file --stream-read-timeout --accesslog-syslog --frontend-http2-read-timeout --listener-disable-timeout --frontend-http2-connection-window-bits --ciphers --strip-incoming-x-forwarded-for --daemon --backend-keep-alive-timeout --backend-http-proxy-uri --backend-http1-connections-per-host --rlimit-nofile --no-via --ocsp-update-interval --backend-write-timeout --client --http2-no-cookie-crumbling --worker-read-burst --client-proxy --http2-bridge --accesslog-format --errorlog-syslog --errorlog-file --http2-max-concurrent-streams --frontend-write-timeout --read-burst --backend-ipv4 --backend-ipv6 --backend --insecure --log-level --tls-proto-list --backend-http2-connections-per-worker --dh-param-file --worker-frontend-connections --header-field-buffer --no-server-push --no-location-rewrite --no-ocsp --backend-response-buffer --workers --frontend-http2-window-bits --no-host-rewrite --worker-write-rate --add-request-header --backend-tls-sni-field --subcert --help --frontend-frame-debug --pid-file --frontend-http2-dump-request-header --private-key-passwd-file --write-rate --altsvc --user --add-x-forwarded-for --syslog-facility --frontend-read-timeout --backlog --write-burst --backend-http2-window-bits --padding --stream-write-timeout --cacert --version --verify-client --backend-read-timeout --frontend --accesslog-file --http2-proxy --max-header-fields --backend-no-tls --client-private-key-file --client-cert-file --add-response-header --read-rate ' -- "$cur" ) )
;; ;;
*) *)
_filedir _filedir

View File

@@ -1,6 +1,6 @@
.\" Man page generated from reStructuredText. .\" Man page generated from reStructuredText.
. .
.TH "H2LOAD" "1" "February 27, 2015" "0.7.5" "nghttp2" .TH "H2LOAD" "1" "June 23, 2015" "1.0.4" "nghttp2"
.SH NAME .SH NAME
h2load \- HTTP/2 benchmarking tool h2load \- HTTP/2 benchmarking tool
. .
@@ -71,7 +71,7 @@ Default: \fB1\fP
.INDENT 0.0 .INDENT 0.0
.TP .TP
.B \-i, \-\-input\-file=<FILE> .B \-i, \-\-input\-file=<FILE>
Path of a file with multiple URIs are seperated by EOLs. Path of a file with multiple URIs are separated by EOLs.
This option will disable URIs getting from command\-line. This option will disable URIs getting from command\-line.
If \(aq\-\(aq is given as <FILE>, URIs will be read from stdin. If \(aq\-\(aq is given as <FILE>, URIs will be read from stdin.
URIs are used in this order for each client. All URIs URIs are used in this order for each client. All URIs
@@ -93,6 +93,8 @@ Default: \fBauto\fP
.B \-w, \-\-window\-bits=<N> .B \-w, \-\-window\-bits=<N>
Sets the stream level initial window size to (2**<N>)\-1. Sets the stream level initial window size to (2**<N>)\-1.
For SPDY, 2**<N> is used instead. For SPDY, 2**<N> is used instead.
.sp
Default: \fB30\fP
.UNINDENT .UNINDENT
.INDENT 0.0 .INDENT 0.0
.TP .TP
@@ -101,6 +103,8 @@ Sets the connection level initial window size to
(2**<N>)\-1. For SPDY, if <N> is strictly less than 16, (2**<N>)\-1. For SPDY, if <N> is strictly less than 16,
this option is ignored. Otherwise 2**<N> is used for this option is ignored. Otherwise 2**<N> is used for
SPDY. SPDY.
.sp
Default: \fB30\fP
.UNINDENT .UNINDENT
.INDENT 0.0 .INDENT 0.0
.TP .TP
@@ -112,9 +116,15 @@ Add/Override a header to the requests.
.B \-p, \-\-no\-tls\-proto=<PROTOID> .B \-p, \-\-no\-tls\-proto=<PROTOID>
Specify ALPN identifier of the protocol to be used when Specify ALPN identifier of the protocol to be used when
accessing http URI without SSL/TLS. accessing http URI without SSL/TLS.
Available protocols: spdy/2, spdy/3, spdy/3.1 and h2c\-14 Available protocols: spdy/2, spdy/3, spdy/3.1 and h2c
.sp .sp
Default: \fBh2c\-14\fP Default: \fBh2c\fP
.UNINDENT
.INDENT 0.0
.TP
.B \-d, \-\-data=<FILE>
Post FILE to server. The request method is changed to
POST.
.UNINDENT .UNINDENT
.INDENT 0.0 .INDENT 0.0
.TP .TP
@@ -195,13 +205,63 @@ The maximum time taken for request and response.
The mean time taken for request and response. The mean time taken for request and response.
.TP .TP
.B sd .B sd
The standard deviation of the time for request and response. The standard deviation of the time taken for request and response.
.TP .TP
.B +/\- sd .B +/\- sd
The fraction of the number of requests within standard deviation The fraction of the number of requests within standard deviation
range (mean +/\- sd) against total number of successful requests. range (mean +/\- sd) against total number of successful requests.
.UNINDENT .UNINDENT
.TP
.B time for connect
.INDENT 7.0
.TP
.B min
The minimum time taken to connect to a server.
.TP
.B max
The maximum time taken to connect to a server.
.TP
.B mean
The mean time taken to connect to a server.
.TP
.B sd
The standard deviation of the time taken to connect to a server.
.TP
.B +/\- sd
The fraction of the number of connections within standard
deviation range (mean +/\- sd) against total number of successful
connections.
.UNINDENT .UNINDENT
.TP
.B time for 1st byte (of (decrypted in case of TLS) application data)
.INDENT 7.0
.TP
.B min
The minimum time taken to get 1st byte from a server.
.TP
.B max
The maximum time taken to get 1st byte from a server.
.TP
.B mean
The mean time taken to get 1st byte from a server.
.TP
.B sd
The standard deviation of the time taken to get 1st byte from a
server.
.TP
.B +/\- sd
The fraction of the number of connections within standard
deviation range (mean +/\- sd) against total number of successful
connections.
.UNINDENT
.UNINDENT
.SH FLOW CONTROL
.sp
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.
.SH SEE ALSO .SH SEE ALSO
.sp .sp
\fInghttp(1)\fP, \fInghttpd(1)\fP, \fInghttpx(1)\fP \fInghttp(1)\fP, \fInghttpd(1)\fP, \fInghttpx(1)\fP

View File

@@ -1,4 +1,8 @@
.. GENERATED by help2rst.py. DO NOT EDIT DIRECTLY.
.. program:: h2load
h2load(1) h2load(1)
========= =========
@@ -44,7 +48,7 @@ OPTIONS
.. option:: -i, --input-file=<FILE> .. option:: -i, --input-file=<FILE>
Path of a file with multiple URIs are seperated by EOLs. Path of a file with multiple URIs are separated by EOLs.
This option will disable URIs getting from command-line. This option will disable URIs getting from command-line.
If '-' is given as <FILE>, URIs will be read from stdin. If '-' is given as <FILE>, URIs will be read from stdin.
URIs are used in this order for each client. All URIs URIs are used in this order for each client. All URIs
@@ -65,6 +69,8 @@ OPTIONS
Sets the stream level initial window size to (2\*\*<N>)-1. Sets the stream level initial window size to (2\*\*<N>)-1.
For SPDY, 2**<N> is used instead. For SPDY, 2**<N> is used instead.
Default: ``30``
.. option:: -W, --connection-window-bits=<N> .. option:: -W, --connection-window-bits=<N>
Sets the connection level initial window size to Sets the connection level initial window size to
@@ -72,6 +78,8 @@ OPTIONS
this option is ignored. Otherwise 2\*\*<N> is used for this option is ignored. Otherwise 2\*\*<N> is used for
SPDY. SPDY.
Default: ``30``
.. option:: -H, --header=<HEADER> .. option:: -H, --header=<HEADER>
Add/Override a header to the requests. Add/Override a header to the requests.
@@ -80,9 +88,14 @@ OPTIONS
Specify ALPN identifier of the protocol to be used when Specify ALPN identifier of the protocol to be used when
accessing http URI without SSL/TLS. accessing http URI without SSL/TLS.
Available protocols: spdy/2, spdy/3, spdy/3.1 and h2c-14 Available protocols: spdy/2, spdy/3, spdy/3.1 and h2c
Default: ``h2c-14`` Default: ``h2c``
.. option:: -d, --data=<FILE>
Post FILE to server. The request method is changed to
POST.
.. option:: -v, --verbose .. option:: -v, --verbose
@@ -142,11 +155,49 @@ time for request
mean mean
The mean time taken for request and response. The mean time taken for request and response.
sd sd
The standard deviation of the time for request and response. The standard deviation of the time taken for request and response.
+/- sd +/- sd
The fraction of the number of requests within standard deviation The fraction of the number of requests within standard deviation
range (mean +/- sd) against total number of successful requests. range (mean +/- sd) against total number of successful requests.
time for connect
min
The minimum time taken to connect to a server.
max
The maximum time taken to connect to a server.
mean
The mean time taken to connect to a server.
sd
The standard deviation of the time taken to connect to a server.
+/- sd
The fraction of the number of connections within standard
deviation range (mean +/- sd) against total number of successful
connections.
time for 1st byte (of (decrypted in case of TLS) application data)
min
The minimum time taken to get 1st byte from a server.
max
The maximum time taken to get 1st byte from a server.
mean
The mean time taken to get 1st byte from a server.
sd
The standard deviation of the time taken to get 1st byte from a
server.
+/- sd
The fraction of the number of connections within standard
deviation range (mean +/- sd) against total number of successful
connections.
FLOW CONTROL
------------
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.
SEE ALSO SEE ALSO
-------- --------

View File

@@ -44,11 +44,49 @@ time for request
mean mean
The mean time taken for request and response. The mean time taken for request and response.
sd sd
The standard deviation of the time for request and response. The standard deviation of the time taken for request and response.
+/- sd +/- sd
The fraction of the number of requests within standard deviation The fraction of the number of requests within standard deviation
range (mean +/- sd) against total number of successful requests. range (mean +/- sd) against total number of successful requests.
time for connect
min
The minimum time taken to connect to a server.
max
The maximum time taken to connect to a server.
mean
The mean time taken to connect to a server.
sd
The standard deviation of the time taken to connect to a server.
+/- sd
The fraction of the number of connections within standard
deviation range (mean +/- sd) against total number of successful
connections.
time for 1st byte (of (decrypted in case of TLS) application data)
min
The minimum time taken to get 1st byte from a server.
max
The maximum time taken to get 1st byte from a server.
mean
The mean time taken to get 1st byte from a server.
sd
The standard deviation of the time taken to get 1st byte from a
server.
+/- sd
The fraction of the number of connections within standard
deviation range (mean +/- sd) against total number of successful
connections.
FLOW CONTROL
------------
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.
SEE ALSO SEE ALSO
-------- --------

View File

@@ -1,4 +1,5 @@
#!/usr/bin/env python #!/usr/bin/env python
# -*- coding: utf-8 -*-
# nghttp2 - HTTP/2 C Library # nghttp2 - HTTP/2 C Library
# Copyright (c) 2012 Tatsuhiro Tsujikawa # Copyright (c) 2012 Tatsuhiro Tsujikawa
@@ -23,20 +24,24 @@
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
# Generates API reference from C source code. # Generates API reference from C source code.
from __future__ import unicode_literals
from __future__ import print_function # At least python 2.6 is required from __future__ import print_function # At least python 2.6 is required
import re, sys, argparse import re, sys, argparse, os.path
class FunctionDoc: class FunctionDoc:
def __init__(self, name, content, domain): def __init__(self, name, content, domain):
self.name = name self.name = name
self.content = content self.content = content
self.domain = domain self.domain = domain
if self.domain == 'function':
self.funcname = re.search(r'(nghttp2_[^ )]+)\(', self.name).group(1)
def write(self, out): def write(self, out):
print('''.. {}:: {}'''.format(self.domain, self.name)) out.write('.. {}:: {}\n'.format(self.domain, self.name))
print('') out.write('\n')
for line in self.content: for line in self.content:
print(' {}'.format(line)) out.write(' {}\n'.format(line))
class StructDoc: class StructDoc:
def __init__(self, name, content, members, member_domain): def __init__(self, name, content, members, member_domain):
@@ -47,17 +52,17 @@ class StructDoc:
def write(self, out): def write(self, out):
if self.name: if self.name:
print('''.. type:: {}'''.format(self.name)) out.write('.. type:: {}\n'.format(self.name))
print('') out.write('\n')
for line in self.content: for line in self.content:
print(' {}'.format(line)) out.write(' {}\n'.format(line))
print('') out.write('\n')
for name, content in self.members: for name, content in self.members:
print(''' .. {}:: {}'''.format(self.member_domain, name)) out.write(' .. {}:: {}\n'.format(self.member_domain, name))
print('') out.write('\n')
for line in content: for line in content:
print(''' {}'''.format(line)) out.write(' {}\n'.format(line))
print('') out.write('\n')
class MacroDoc: class MacroDoc:
def __init__(self, name, content): def __init__(self, name, content):
@@ -65,10 +70,10 @@ class MacroDoc:
self.content = content self.content = content
def write(self, out): def write(self, out):
print('''.. macro:: {}'''.format(self.name)) out.write('''.. macro:: {}\n'''.format(self.name))
print('') out.write('\n')
for line in self.content: for line in self.content:
print(' {}'.format(line)) out.write(' {}\n'.format(line))
def make_api_ref(infiles): def make_api_ref(infiles):
macros = [] macros = []
@@ -93,19 +98,65 @@ def make_api_ref(infiles):
enums.append(process_enum(infile)) enums.append(process_enum(infile))
elif doctype == '@macro': elif doctype == '@macro':
macros.append(process_macro(infile)) macros.append(process_macro(infile))
return macros, enums, types, functions
alldocs = [('Macros', macros), alldocs = [('Macros', macros),
('Enums', enums), ('Enums', enums),
('Types (structs, unions and typedefs)', types), ('Types (structs, unions and typedefs)', types),
('Functions', functions)] ('Functions', functions)]
for title, docs in alldocs:
if not docs: def output(
continue indexfile, macrosfile, enumsfile, typesfile, funcsdir,
print(title) macros, enums, types, functions):
print('-'*len(title)) indexfile.write('''
for doc in docs: API Reference
doc.write(sys.stdout) =============
print('')
print('') .. toctree::
:maxdepth: 1
macros
enums
types
''')
for doc in functions:
indexfile.write(' {}\n'.format(doc.funcname))
macrosfile.write('''
Macros
======
''')
for doc in macros:
doc.write(macrosfile)
enumsfile.write('''
Enums
=====
''')
for doc in enums:
doc.write(enumsfile)
typesfile.write('''
Types (structs, unions and typedefs)
====================================
''')
for doc in types:
doc.write(typesfile)
for doc in functions:
with open(os.path.join(funcsdir, doc.funcname + '.rst'), 'w') as f:
f.write('''
{funcname}
{secul}
Synopsis
--------
*#include <nghttp2/nghttp2.h>*
'''.format(funcname=doc.funcname, secul='='*len(doc.funcname)))
doc.write(f)
def process_macro(infile): def process_macro(infile):
content = read_content(infile) content = read_content(infile)
@@ -174,6 +225,7 @@ def process_function(domain, infile):
func_proto = ''.join(func_proto) func_proto = ''.join(func_proto)
func_proto = re.sub(r';\n$', '', func_proto) func_proto = re.sub(r';\n$', '', func_proto)
func_proto = re.sub(r'\s+', ' ', func_proto) func_proto = re.sub(r'\s+', ' ', func_proto)
func_proto = re.sub(r'NGHTTP2_EXTERN ', '', func_proto)
return FunctionDoc(func_proto, content, domain) return FunctionDoc(func_proto, content, domain)
def read_content(infile): def read_content(infile):
@@ -199,12 +251,30 @@ def transform_content(content):
if __name__ == '__main__': if __name__ == '__main__':
parser = argparse.ArgumentParser(description="Generate API reference") parser = argparse.ArgumentParser(description="Generate API reference")
parser.add_argument('--header', type=argparse.FileType('r'), parser.add_argument('index', type=argparse.FileType('w'),
help='header inserted at the top of the page') help='index output file')
parser.add_argument('macros', type=argparse.FileType('w'),
help='macros section output file. The filename should be macros.rst')
parser.add_argument('enums', type=argparse.FileType('w'),
help='enums section output file. The filename should be enums.rst')
parser.add_argument('types', type=argparse.FileType('w'),
help='types section output file. The filename should be types.rst')
parser.add_argument('funcsdir',
help='functions doc output dir')
parser.add_argument('files', nargs='+', type=argparse.FileType('r'), parser.add_argument('files', nargs='+', type=argparse.FileType('r'),
help='source file') help='source file')
args = parser.parse_args() args = parser.parse_args()
if args.header: macros = []
print(args.header.read()) enums = []
types = []
funcs = []
for infile in args.files: for infile in args.files:
make_api_ref(args.files) m, e, t, f = make_api_ref(args.files)
macros.extend(m)
enums.extend(e)
types.extend(t)
funcs.extend(f)
funcs.sort(key=lambda x: x.funcname)
output(
args.index, args.macros, args.enums, args.types, args.funcsdir,
macros, enums, types, funcs)

View File

@@ -1,6 +1,6 @@
.\" Man page generated from reStructuredText. .\" Man page generated from reStructuredText.
. .
.TH "NGHTTP" "1" "February 27, 2015" "0.7.5" "nghttp2" .TH "NGHTTP" "1" "June 23, 2015" "1.0.4" "nghttp2"
.SH NAME .SH NAME
nghttp \- HTTP/2 experimental client nghttp \- HTTP/2 experimental client
. .
@@ -64,8 +64,9 @@ yet.
.UNINDENT .UNINDENT
.INDENT 0.0 .INDENT 0.0
.TP .TP
.B \-t, \-\-timeout=<SEC> .B \-t, \-\-timeout=<DURATION>
Timeout each request after <SEC> seconds. Timeout each request after <DURATION>. Set 0 to disable
timeout.
.UNINDENT .UNINDENT
.INDENT 0.0 .INDENT 0.0
.TP .TP
@@ -101,6 +102,14 @@ Add a header to the requests. Example: \fI\%\-H\fP\(aq:method: PUT\(aq
.UNINDENT .UNINDENT
.INDENT 0.0 .INDENT 0.0
.TP .TP
.B \-\-trailer=<HEADER>
Add a trailer header to the requests. <HEADER> must not
include pseudo header field (header field name starting
with \(aq:\(aq). To send trailer, one must use \fI\%\-d\fP option to
send request body. Example: \fI\%\-\-trailer\fP \(aqfoo: bar\(aq.
.UNINDENT
.INDENT 0.0
.TP
.B \-\-cert=<CERT> .B \-\-cert=<CERT>
Use the specified client certificate file. The file Use the specified client certificate file. The file
must be in PEM format. must be in PEM format.
@@ -127,7 +136,7 @@ requested twice. This option disables it too.
.TP .TP
.B \-u, \-\-upgrade .B \-u, \-\-upgrade
Perform HTTP Upgrade for HTTP/2. This option is ignored Perform HTTP Upgrade for HTTP/2. This option is ignored
if the request URI has https scheme. If \fI\-d\fP is used, the if the request URI has https scheme. If \fI\%\-d\fP is used, the
HTTP upgrade request is performed with OPTIONS method. HTTP upgrade request is performed with OPTIONS method.
.UNINDENT .UNINDENT
.INDENT 0.0 .INDENT 0.0
@@ -184,8 +193,15 @@ Don\(aqt send dependency based priority hint to server.
.UNINDENT .UNINDENT
.INDENT 0.0 .INDENT 0.0
.TP .TP
.B \-\-dep\-idle .B \-\-hexdump
Use idle streams as anchor nodes to express priority. Display the incoming traffic in hexadecimal (Canonical
hex+ASCII display). If SSL/TLS is used, decrypted data
are used.
.UNINDENT
.INDENT 0.0
.TP
.B \-\-no\-push
Disable server push.
.UNINDENT .UNINDENT
.INDENT 0.0 .INDENT 0.0
.TP .TP
@@ -200,6 +216,68 @@ Display this help and exit.
.sp .sp
The <SIZE> argument is an integer and an optional unit (e.g., 10K is The <SIZE> argument is an integer and an optional unit (e.g., 10K is
10 * 1024). Units are K, M and G (powers of 1024). 10 * 1024). Units are K, M and G (powers of 1024).
.sp
The <DURATION> argument is an integer and an optional unit (e.g., 1s
is 1 second and 500ms is 500 milliseconds). Units are h, m, s or ms
(hours, minutes, seconds and milliseconds, respectively). If a unit
is omitted, a second is used as unit.
.SH DEPENDENCY BASED PRIORITY
.sp
nghttp sends priority hints to server by default unless
\fI\%\-\-no\-dep\fP is used. nghttp mimics the way Firefox employs to
manages dependency using idle streams. We follows the behaviour of
Firefox Nightly as of April, 2015, and nghttp\(aqs behaviour is very
static and could be different from Firefox in detail. But reproducing
the same behaviour of Firefox is not our goal. The goal is provide
the easy way to test out the dependency priority in server
implementation.
.sp
When connection is established, nghttp sends 5 PRIORITY frames to idle
streams 3, 5, 7, 9 and 11 to create "anchor" nodes in dependency
tree:
.INDENT 0.0
.INDENT 3.5
.sp
.nf
.ft C
+\-\-\-\-\-+
|id=0 |
+\-\-\-\-\-+
^ ^ ^
w=201 / | \e w=1
/ | \e
/ w=101| \e
+\-\-\-\-\-+ +\-\-\-\-\-+ +\-\-\-\-\-+
|id=3 | |id=5 | |id=7 |
+\-\-\-\-\-+ +\-\-\-\-\-+ +\-\-\-\-\-+
^ ^
w=1 | w=1 |
| |
+\-\-\-\-\-+ +\-\-\-\-\-+
|id=11| |id=9 |
+\-\-\-\-\-+ +\-\-\-\-\-+
.ft P
.fi
.UNINDENT
.UNINDENT
.sp
In the above figure, \fBid\fP means stream ID, and \fBw\fP means weight.
The stream 0 is non\-existence stream, and forms the root of the tree.
The stream 7 and 9 are not used for now.
.sp
The URIs given in the command\-line depend on stream 11 with the weight
given in \fI\%\-p\fP option, which defaults to 16.
.sp
If \fI\%\-a\fP option is used, nghttp parses the resource pointed by
URI given in command\-line as html, and extracts resource links from
it. When requesting those resources, nghttp uses dependency according
to its resource type.
.sp
For CSS, and Javascript files inside "head" element, they depend on
stream 3 with the weight 2. The Javascript files outside "head"
element depend on stream 5 with the weight 2. The mages depend on
stream 11 with the weight 12. The other resources (e.g., icon) depend
on stream 11 with the weight 2.
.SH SEE ALSO .SH SEE ALSO
.sp .sp
\fInghttpd(1)\fP, \fInghttpx(1)\fP, \fIh2load(1)\fP \fInghttpd(1)\fP, \fInghttpx(1)\fP, \fIh2load(1)\fP

View File

@@ -1,4 +1,8 @@
.. GENERATED by help2rst.py. DO NOT EDIT DIRECTLY.
.. program:: nghttp
nghttp(1) nghttp(1)
========= =========
@@ -36,9 +40,10 @@ OPTIONS
'index.html' is used as a filename. Not implemented 'index.html' is used as a filename. Not implemented
yet. yet.
.. option:: -t, --timeout=<SEC> .. option:: -t, --timeout=<DURATION>
Timeout each request after <SEC> seconds. Timeout each request after <DURATION>. Set 0 to disable
timeout.
.. option:: -w, --window-bits=<N> .. option:: -w, --window-bits=<N>
@@ -67,6 +72,13 @@ OPTIONS
Add a header to the requests. Example: :option:`-H`\':method: PUT' Add a header to the requests. Example: :option:`-H`\':method: PUT'
.. option:: --trailer=<HEADER>
Add a trailer header to the requests. <HEADER> must not
include pseudo header field (header field name starting
with ':'). To send trailer, one must use :option:`-d` option to
send request body. Example: :option:`--trailer` 'foo: bar'.
.. option:: --cert=<CERT> .. option:: --cert=<CERT>
Use the specified client certificate file. The file Use the specified client certificate file. The file
@@ -136,9 +148,15 @@ OPTIONS
Don't send dependency based priority hint to server. Don't send dependency based priority hint to server.
.. option:: --dep-idle .. option:: --hexdump
Use idle streams as anchor nodes to express priority. Display the incoming traffic in hexadecimal (Canonical
hex+ASCII display). If SSL/TLS is used, decrypted data
are used.
.. option:: --no-push
Disable server push.
.. option:: --version .. option:: --version
@@ -149,9 +167,66 @@ OPTIONS
Display this help and exit. Display this help and exit.
The <SIZE> argument is an integer and an optional unit (e.g., 10K is The <SIZE> argument is an integer and an optional unit (e.g., 10K is
10 * 1024). Units are K, M and G (powers of 1024). 10 * 1024). Units are K, M and G (powers of 1024).
The <DURATION> argument is an integer and an optional unit (e.g., 1s
is 1 second and 500ms is 500 milliseconds). Units are h, m, s or ms
(hours, minutes, seconds and milliseconds, respectively). If a unit
is omitted, a second is used as unit.
DEPENDENCY BASED PRIORITY
-------------------------
nghttp sends priority hints to server by default unless
:option:`--no-dep` is used. nghttp mimics the way Firefox employs to
manages dependency using idle streams. We follows the behaviour of
Firefox Nightly as of April, 2015, and nghttp's behaviour is very
static and could be different from Firefox in detail. But reproducing
the same behaviour of Firefox is not our goal. The goal is provide
the easy way to test out the dependency priority in server
implementation.
When connection is established, nghttp sends 5 PRIORITY frames to idle
streams 3, 5, 7, 9 and 11 to create "anchor" nodes in dependency
tree::
+-----+
|id=0 |
+-----+
^ ^ ^
w=201 / | \ w=1
/ | \
/ w=101| \
+-----+ +-----+ +-----+
|id=3 | |id=5 | |id=7 |
+-----+ +-----+ +-----+
^ ^
w=1 | w=1 |
| |
+-----+ +-----+
|id=11| |id=9 |
+-----+ +-----+
In the above figure, ``id`` means stream ID, and ``w`` means weight.
The stream 0 is non-existence stream, and forms the root of the tree.
The stream 7 and 9 are not used for now.
The URIs given in the command-line depend on stream 11 with the weight
given in :option:`-p` option, which defaults to 16.
If :option:`-a` option is used, nghttp parses the resource pointed by
URI given in command-line as html, and extracts resource links from
it. When requesting those resources, nghttp uses dependency according
to its resource type.
For CSS, and Javascript files inside "head" element, they depend on
stream 3 with the weight 2. The Javascript files outside "head"
element depend on stream 5 with the weight 2. The mages depend on
stream 11 with the weight 12. The other resources (e.g., icon) depend
on stream 11 with the weight 2.
SEE ALSO SEE ALSO
-------- --------

View File

@@ -1,3 +1,54 @@
DEPENDENCY BASED PRIORITY
-------------------------
nghttp sends priority hints to server by default unless
:option:`--no-dep` is used. nghttp mimics the way Firefox employs to
manages dependency using idle streams. We follows the behaviour of
Firefox Nightly as of April, 2015, and nghttp's behaviour is very
static and could be different from Firefox in detail. But reproducing
the same behaviour of Firefox is not our goal. The goal is provide
the easy way to test out the dependency priority in server
implementation.
When connection is established, nghttp sends 5 PRIORITY frames to idle
streams 3, 5, 7, 9 and 11 to create "anchor" nodes in dependency
tree::
+-----+
|id=0 |
+-----+
^ ^ ^
w=201 / | \ w=1
/ | \
/ w=101| \
+-----+ +-----+ +-----+
|id=3 | |id=5 | |id=7 |
+-----+ +-----+ +-----+
^ ^
w=1 | w=1 |
| |
+-----+ +-----+
|id=11| |id=9 |
+-----+ +-----+
In the above figure, ``id`` means stream ID, and ``w`` means weight.
The stream 0 is non-existence stream, and forms the root of the tree.
The stream 7 and 9 are not used for now.
The URIs given in the command-line depend on stream 11 with the weight
given in :option:`-p` option, which defaults to 16.
If :option:`-a` option is used, nghttp parses the resource pointed by
URI given in command-line as html, and extracts resource links from
it. When requesting those resources, nghttp uses dependency according
to its resource type.
For CSS, and Javascript files inside "head" element, they depend on
stream 3 with the weight 2. The Javascript files outside "head"
element depend on stream 5 with the weight 2. The mages depend on
stream 11 with the weight 12. The other resources (e.g., icon) depend
on stream 11 with the weight 2.
SEE ALSO SEE ALSO
-------- --------

View File

@@ -1,6 +1,6 @@
.\" Man page generated from reStructuredText. .\" Man page generated from reStructuredText.
. .
.TH "NGHTTPD" "1" "February 27, 2015" "0.7.5" "nghttp2" .TH "NGHTTPD" "1" "June 23, 2015" "1.0.4" "nghttp2"
.SH NAME .SH NAME
nghttpd \- HTTP/2 experimental server nghttpd \- HTTP/2 experimental server
. .
@@ -63,7 +63,7 @@ address determined by getaddrinfo is used.
.INDENT 0.0 .INDENT 0.0
.TP .TP
.B \-D, \-\-daemon .B \-D, \-\-daemon
Run in a background. If \fI\-D\fP is used, the current working Run in a background. If \fI\%\-D\fP is used, the current working
directory is changed to \(aq\fI/\fP\(aq. Therefore if this option directory is changed to \(aq\fI/\fP\(aq. Therefore if this option
is used, \fI\%\-d\fP option must be specified. is used, \fI\%\-d\fP option must be specified.
.UNINDENT .UNINDENT
@@ -109,7 +109,7 @@ Push resources <PUSH_PATH>s when <PATH> is requested.
This option can be used repeatedly to specify multiple This option can be used repeatedly to specify multiple
push configurations. <PATH> and <PUSH_PATH>s are push configurations. <PATH> and <PUSH_PATH>s are
relative to document root. See \fI\%\-\-htdocs\fP option. relative to document root. See \fI\%\-\-htdocs\fP option.
Example: \fI\-p\fP/=/foo.png \fI\-p\fP/doc=/bar.css Example: \fI\%\-p\fP/=/foo.png \fI\%\-p\fP/doc=/bar.css
.UNINDENT .UNINDENT
.INDENT 0.0 .INDENT 0.0
.TP .TP
@@ -119,6 +119,14 @@ Specify 0 to disable padding.
.UNINDENT .UNINDENT
.INDENT 0.0 .INDENT 0.0
.TP .TP
.B \-m, \-\-max\-concurrent\-streams=<N>
Set the maximum number of the concurrent streams in one
HTTP/2 session.
.sp
Default: \fB100\fP
.UNINDENT
.INDENT 0.0
.TP
.B \-n, \-\-workers=<N> .B \-n, \-\-workers=<N>
Set the number of worker threads. Set the number of worker threads.
.sp .sp
@@ -144,6 +152,26 @@ rather than complete request is received.
.UNINDENT .UNINDENT
.INDENT 0.0 .INDENT 0.0
.TP .TP
.B \-\-trailer=<HEADER>
Add a trailer header to a response. <HEADER> must not
include pseudo header field (header field name starting
with \(aq:\(aq). The trailer is sent only if a response has
body part. Example: \fI\%\-\-trailer\fP \(aqfoo: bar\(aq.
.UNINDENT
.INDENT 0.0
.TP
.B \-\-hexdump
Display the incoming traffic in hexadecimal (Canonical
hex+ASCII display). If SSL/TLS is used, decrypted data
are used.
.UNINDENT
.INDENT 0.0
.TP
.B \-\-echo\-upload
Send back uploaded content if method is POST or PUT.
.UNINDENT
.INDENT 0.0
.TP
.B \-\-version .B \-\-version
Display version information and exit. Display version information and exit.
.UNINDENT .UNINDENT

View File

@@ -1,4 +1,8 @@
.. GENERATED by help2rst.py. DO NOT EDIT DIRECTLY.
.. program:: nghttpd
nghttpd(1) nghttpd(1)
========== ==========
@@ -83,6 +87,13 @@ OPTIONS
Add at most <N> bytes to a frame payload as padding. Add at most <N> bytes to a frame payload as padding.
Specify 0 to disable padding. Specify 0 to disable padding.
.. option:: -m, --max-concurrent-streams=<N>
Set the maximum number of the concurrent streams in one
HTTP/2 session.
Default: ``100``
.. option:: -n, --workers=<N> .. option:: -n, --workers=<N>
Set the number of worker threads. Set the number of worker threads.
@@ -104,6 +115,23 @@ OPTIONS
Start sending response when request HEADERS is received, Start sending response when request HEADERS is received,
rather than complete request is received. rather than complete request is received.
.. option:: --trailer=<HEADER>
Add a trailer header to a response. <HEADER> must not
include pseudo header field (header field name starting
with ':'). The trailer is sent only if a response has
body part. Example: :option:`--trailer` 'foo: bar'.
.. option:: --hexdump
Display the incoming traffic in hexadecimal (Canonical
hex+ASCII display). If SSL/TLS is used, decrypted data
are used.
.. option:: --echo-upload
Send back uploaded content if method is POST or PUT.
.. option:: --version .. option:: --version
Display version information and exit. Display version information and exit.
@@ -113,6 +141,7 @@ OPTIONS
Display this help and exit. Display this help and exit.
The <SIZE> argument is an integer and an optional unit (e.g., 10K is The <SIZE> argument is an integer and an optional unit (e.g., 10K is
10 * 1024). Units are K, M and G (powers of 1024). 10 * 1024). Units are K, M and G (powers of 1024).

View File

@@ -1,6 +1,6 @@
.\" Man page generated from reStructuredText. .\" Man page generated from reStructuredText.
. .
.TH "NGHTTPX" "1" "February 27, 2015" "0.7.5" "nghttp2" .TH "NGHTTPX" "1" "June 23, 2015" "1.0.4" "nghttp2"
.SH NAME .SH NAME
nghttpx \- HTTP/2 experimental proxy nghttpx \- HTTP/2 experimental proxy
. .
@@ -46,7 +46,8 @@ Set path to server\(aqs private key. Required unless \fI\%\-p\fP,
.TP .TP
.B <CERT> .B <CERT>
Set path to server\(aqs certificate. Required unless \fI\%\-p\fP, Set path to server\(aqs certificate. Required unless \fI\%\-p\fP,
\fI\%\-\-client\fP or \fI\%\-\-frontend\-no\-tls\fP are given. \fI\%\-\-client\fP or \fI\%\-\-frontend\-no\-tls\fP are given. To make OCSP
stapling work, this must be absolute path.
.UNINDENT .UNINDENT
.SH OPTIONS .SH OPTIONS
.sp .sp
@@ -55,13 +56,10 @@ The options are categorized into several groups.
.INDENT 0.0 .INDENT 0.0
.TP .TP
.B \-b, \-\-backend=<HOST,PORT> .B \-b, \-\-backend=<HOST,PORT>
Set backend host and port. For HTTP/1 backend, multiple Set backend host and port. The multiple backend
backend addresses are accepted by repeating this option. addresses are accepted by repeating this option. UNIX
HTTP/2 backend does not support multiple backend domain socket can be specified by prefixing path name
addresses and the first occurrence of this option is with "unix:" (e.g., unix:/var/run/backend.sock)
used. UNIX domain socket can be specified by prefixing
path name with "unix:" (e.g.,
unix:/var/run/backend.sock)
.sp .sp
Default: \fB127.0.0.1,80\fP Default: \fB127.0.0.1,80\fP
.UNINDENT .UNINDENT
@@ -196,11 +194,20 @@ Default: \fB0\fP
.UNINDENT .UNINDENT
.INDENT 0.0 .INDENT 0.0
.TP .TP
.B \-\-backend\-http2\-connections\-per\-worker=<N>
Set maximum number of HTTP/2 connections per worker.
The default value is 0, which means the number of
backend addresses specified by \fI\%\-b\fP option.
.UNINDENT
.INDENT 0.0
.TP
.B \-\-backend\-http1\-connections\-per\-host=<N> .B \-\-backend\-http1\-connections\-per\-host=<N>
Set maximum number of backend concurrent HTTP/1 Set maximum number of backend concurrent HTTP/1
connections per host. This option is meaningful when \fI\%\-s\fP connections per origin host. This option is meaningful
option is used. To limit the number of connections per when \fI\%\-s\fP option is used. The origin host is determined
frontend for default mode, use by authority portion of requset URI (or :authority
header field for HTTP/2). To limit the number of
connections per frontend for default mode, use
\fI\%\-\-backend\-http1\-connections\-per\-frontend\fP\&. \fI\%\-\-backend\-http1\-connections\-per\-frontend\fP\&.
.sp .sp
Default: \fB8\fP Default: \fB8\fP
@@ -245,14 +252,14 @@ Default: \fB16K\fP
Specify read timeout for HTTP/2 and SPDY frontend Specify read timeout for HTTP/2 and SPDY frontend
connection. connection.
.sp .sp
Default: \fB180s\fP Default: \fB3m\fP
.UNINDENT .UNINDENT
.INDENT 0.0 .INDENT 0.0
.TP .TP
.B \-\-frontend\-read\-timeout=<DURATION> .B \-\-frontend\-read\-timeout=<DURATION>
Specify read timeout for HTTP/1.1 frontend connection. Specify read timeout for HTTP/1.1 frontend connection.
.sp .sp
Default: \fB180s\fP Default: \fB3m\fP
.UNINDENT .UNINDENT
.INDENT 0.0 .INDENT 0.0
.TP .TP
@@ -282,7 +289,7 @@ Default: \fB0\fP
.B \-\-backend\-read\-timeout=<DURATION> .B \-\-backend\-read\-timeout=<DURATION>
Specify read timeout for backend connection. Specify read timeout for backend connection.
.sp .sp
Default: \fB180s\fP Default: \fB3m\fP
.UNINDENT .UNINDENT
.INDENT 0.0 .INDENT 0.0
.TP .TP
@@ -344,7 +351,8 @@ password protected it\(aqll be requested interactively.
Specify additional certificate and private key file. Specify additional certificate and private key file.
nghttpx will choose certificates based on the hostname nghttpx will choose certificates based on the hostname
indicated by client using TLS SNI extension. This indicated by client using TLS SNI extension. This
option can be used multiple times. option can be used multiple times. To make OCSP
stapling work, <CERTPATH> must be absolute path.
.UNINDENT .UNINDENT
.INDENT 0.0 .INDENT 0.0
.TP .TP
@@ -429,14 +437,23 @@ are stored in memory.
.UNINDENT .UNINDENT
.INDENT 0.0 .INDENT 0.0
.TP .TP
.B \-\-tls\-ctx\-per\-worker .B \-\-fetch\-ocsp\-response\-file=<PATH>
Create OpenSSL\(aqs SSL_CTX per worker, so that no internal Path to fetch\-ocsp\-response script file. It should be
locking is required. This may improve scalability with absolute path.
multi threaded configuration. If this option is .sp
enabled, session ID is no longer shared accross SSL_CTX Default: \fB/usr/local/share/nghttp2/fetch\-ocsp\-response\fP
objects, which means session ID generated by one worker .UNINDENT
is not acceptable by another worker. On the other hand, .INDENT 0.0
session ticket key is shared across all worker threads. .TP
.B \-\-ocsp\-update\-interval=<DURATION>
Set interval to update OCSP response cache.
.sp
Default: \fB4h\fP
.UNINDENT
.INDENT 0.0
.TP
.B \-\-no\-ocsp
Disable OCSP stapling.
.UNINDENT .UNINDENT
.SS HTTP/2 and SPDY .SS HTTP/2 and SPDY
.INDENT 0.0 .INDENT 0.0
@@ -617,7 +634,8 @@ Default: \fB$remote_addr \- \- [$time_local] "$request" $status $body_bytes_sent
.TP .TP
.B \-\-errorlog\-file=<PATH> .B \-\-errorlog\-file=<PATH>
Set path to write error log. To reopen file, send USR1 Set path to write error log. To reopen file, send USR1
signal to nghttpx. signal to nghttpx. stderr will be redirected to the
error log file unless \fI\%\-\-errorlog\-syslog\fP is used.
.sp .sp
Default: \fB/dev/stderr\fP Default: \fB/dev/stderr\fP
.UNINDENT .UNINDENT
@@ -674,10 +692,19 @@ will not be altered regardless of this option.
.B \-\-altsvc=<PROTOID,PORT[,HOST,[ORIGIN]]> .B \-\-altsvc=<PROTOID,PORT[,HOST,[ORIGIN]]>
Specify protocol ID, port, host and origin of Specify protocol ID, port, host and origin of
alternative service. <HOST> and <ORIGIN> are optional. alternative service. <HOST> and <ORIGIN> are optional.
They are advertised in alt\-svc header field or HTTP/2 They are advertised in alt\-svc header field only in
ALTSVC frame. This option can be used multiple times to HTTP/1.1 frontend. This option can be used multiple
specify multiple alternative services. Example: times to specify multiple alternative services.
\fI\%\-\-altsvc\fP=h2,443 Example: \fI\%\-\-altsvc\fP=h2,443
.UNINDENT
.INDENT 0.0
.TP
.B \-\-add\-request\-header=<HEADER>
Specify additional header field to add to request header
set. This option just appends header field and won\(aqt
replace anything already set. This option can be used
several times to specify multiple header fields.
Example: \fI\%\-\-add\-request\-header\fP="foo: bar"
.UNINDENT .UNINDENT
.INDENT 0.0 .INDENT 0.0
.TP .TP
@@ -688,6 +715,23 @@ won\(aqt replace anything already set. This option can be
used several times to specify multiple header fields. used several times to specify multiple header fields.
Example: \fI\%\-\-add\-response\-header\fP="foo: bar" Example: \fI\%\-\-add\-response\-header\fP="foo: bar"
.UNINDENT .UNINDENT
.INDENT 0.0
.TP
.B \-\-header\-field\-buffer=<SIZE>
Set maximum buffer size for incoming HTTP header field
list. This is the sum of header name and value in
bytes.
.sp
Default: \fB64K\fP
.UNINDENT
.INDENT 0.0
.TP
.B \-\-max\-header\-fields=<N>
Set maximum number of incoming HTTP header fields, which
appear in one request or response header field list.
.sp
Default: \fB100\fP
.UNINDENT
.SS Debug .SS Debug
.INDENT 0.0 .INDENT 0.0
.TP .TP
@@ -755,8 +799,9 @@ The <SIZE> argument is an integer and an optional unit (e.g., 10K is
10 * 1024). Units are K, M and G (powers of 1024). 10 * 1024). Units are K, M and G (powers of 1024).
.sp .sp
The <DURATION> argument is an integer and an optional unit (e.g., 1s The <DURATION> argument is an integer and an optional unit (e.g., 1s
is 1 second and 500ms is 500 milliseconds). Units are s or ms. If is 1 second and 500ms is 500 milliseconds). Units are h, m, s or ms
a unit is omitted, a second is used as unit. (hours, minutes, seconds and milliseconds, respectively). If a unit
is omitted, a second is used as unit.
.SH FILES .SH FILES
.INDENT 0.0 .INDENT 0.0
.TP .TP
@@ -778,7 +823,7 @@ argument in the configuration file. Specify \fByes\fP as an argument
ignored. ignored.
.sp .sp
To specify private key and certificate file which are given as To specify private key and certificate file which are given as
positional arguments in commnad\-line, use \fBprivate\-key\-file\fP and positional arguments in command\-line, use \fBprivate\-key\-file\fP and
\fBcertificate\-file\fP\&. \fBcertificate\-file\fP\&.
.sp .sp
\fI\%\-\-conf\fP option cannot be used in the configuration file and \fI\%\-\-conf\fP option cannot be used in the configuration file and
@@ -845,6 +890,16 @@ specified socket already exists in the file system, nghttpx first
deletes it. However, if SIGUSR2 is used to execute new binary and deletes it. However, if SIGUSR2 is used to execute new binary and
both old and new configurations use same filename, new binary does not both old and new configurations use same filename, new binary does not
delete the socket and continues to use it. delete the socket and continues to use it.
.SH OCSP STAPLING
.sp
OCSP query is done using external Python script
\fBfetch\-ocsp\-response\fP, which has been originally developed in Perl
as part of h2o project (\fI\%https://github.com/h2o/h2o\fP), and was
translated into Python.
.sp
The script file is usually installed under
\fB$(prefix)/share/nghttp2/\fP directory. The actual path to script can
be customized using \fI\%\-\-fetch\-ocsp\-response\-file\fP option.
.SH SEE ALSO .SH SEE ALSO
.sp .sp
\fInghttp(1)\fP, \fInghttpd(1)\fP, \fIh2load(1)\fP \fInghttp(1)\fP, \fInghttpd(1)\fP, \fIh2load(1)\fP

View File

@@ -1,4 +1,8 @@
.. GENERATED by help2rst.py. DO NOT EDIT DIRECTLY.
.. program:: nghttpx
nghttpx(1) nghttpx(1)
========== ==========
@@ -21,7 +25,8 @@ A reverse proxy for HTTP/2, HTTP/1 and SPDY.
.. describe:: <CERT> .. describe:: <CERT>
Set path to server's certificate. Required unless :option:`-p`\, Set path to server's certificate. Required unless :option:`-p`\,
:option:`--client` or :option:`\--frontend-no-tls` are given. :option:`--client` or :option:`\--frontend-no-tls` are given. To make OCSP
stapling work, this must be absolute path.
OPTIONS OPTIONS
@@ -34,13 +39,10 @@ Connections
.. option:: -b, --backend=<HOST,PORT> .. option:: -b, --backend=<HOST,PORT>
Set backend host and port. For HTTP/1 backend, multiple Set backend host and port. The multiple backend
backend addresses are accepted by repeating this option. addresses are accepted by repeating this option. UNIX
HTTP/2 backend does not support multiple backend domain socket can be specified by prefixing path name
addresses and the first occurrence of this option is with "unix:" (e.g., unix:/var/run/backend.sock)
used. UNIX domain socket can be specified by prefixing
path name with "unix:" (e.g.,
unix:/var/run/backend.sock)
Default: ``127.0.0.1,80`` Default: ``127.0.0.1,80``
@@ -161,12 +163,20 @@ Performance
Default: ``0`` Default: ``0``
.. option:: --backend-http2-connections-per-worker=<N>
Set maximum number of HTTP/2 connections per worker.
The default value is 0, which means the number of
backend addresses specified by :option:`-b` option.
.. option:: --backend-http1-connections-per-host=<N> .. option:: --backend-http1-connections-per-host=<N>
Set maximum number of backend concurrent HTTP/1 Set maximum number of backend concurrent HTTP/1
connections per host. This option is meaningful when :option:`-s` connections per origin host. This option is meaningful
option is used. To limit the number of connections per when :option:`-s` option is used. The origin host is determined
frontend for default mode, use by authority portion of requset URI (or :authority
header field for HTTP/2). To limit the number of
connections per frontend for default mode, use
:option:`--backend-http1-connections-per-frontend`\. :option:`--backend-http1-connections-per-frontend`\.
Default: ``8`` Default: ``8``
@@ -209,13 +219,13 @@ Timeout
Specify read timeout for HTTP/2 and SPDY frontend Specify read timeout for HTTP/2 and SPDY frontend
connection. connection.
Default: ``180s`` Default: ``3m``
.. option:: --frontend-read-timeout=<DURATION> .. option:: --frontend-read-timeout=<DURATION>
Specify read timeout for HTTP/1.1 frontend connection. Specify read timeout for HTTP/1.1 frontend connection.
Default: ``180s`` Default: ``3m``
.. option:: --frontend-write-timeout=<DURATION> .. option:: --frontend-write-timeout=<DURATION>
@@ -241,7 +251,7 @@ Timeout
Specify read timeout for backend connection. Specify read timeout for backend connection.
Default: ``180s`` Default: ``3m``
.. option:: --backend-write-timeout=<DURATION> .. option:: --backend-write-timeout=<DURATION>
@@ -298,7 +308,8 @@ SSL/TLS
Specify additional certificate and private key file. Specify additional certificate and private key file.
nghttpx will choose certificates based on the hostname nghttpx will choose certificates based on the hostname
indicated by client using TLS SNI extension. This indicated by client using TLS SNI extension. This
option can be used multiple times. option can be used multiple times. To make OCSP
stapling work, <CERTPATH> must be absolute path.
.. option:: --backend-tls-sni-field=<HOST> .. option:: --backend-tls-sni-field=<HOST>
@@ -372,15 +383,22 @@ SSL/TLS
automatically and renewed every 12hrs. At most 2 keys automatically and renewed every 12hrs. At most 2 keys
are stored in memory. are stored in memory.
.. option:: --tls-ctx-per-worker .. option:: --fetch-ocsp-response-file=<PATH>
Create OpenSSL's SSL_CTX per worker, so that no internal Path to fetch-ocsp-response script file. It should be
locking is required. This may improve scalability with absolute path.
multi threaded configuration. If this option is
enabled, session ID is no longer shared accross SSL_CTX Default: ``/usr/local/share/nghttp2/fetch-ocsp-response``
objects, which means session ID generated by one worker
is not acceptable by another worker. On the other hand, .. option:: --ocsp-update-interval=<DURATION>
session ticket key is shared across all worker threads.
Set interval to update OCSP response cache.
Default: ``4h``
.. option:: --no-ocsp
Disable OCSP stapling.
HTTP/2 and SPDY HTTP/2 and SPDY
@@ -539,7 +557,8 @@ Logging
.. option:: --errorlog-file=<PATH> .. option:: --errorlog-file=<PATH>
Set path to write error log. To reopen file, send USR1 Set path to write error log. To reopen file, send USR1
signal to nghttpx. signal to nghttpx. stderr will be redirected to the
error log file unless :option:`--errorlog-syslog` is used.
Default: ``/dev/stderr`` Default: ``/dev/stderr``
@@ -591,10 +610,18 @@ HTTP
Specify protocol ID, port, host and origin of Specify protocol ID, port, host and origin of
alternative service. <HOST> and <ORIGIN> are optional. alternative service. <HOST> and <ORIGIN> are optional.
They are advertised in alt-svc header field or HTTP/2 They are advertised in alt-svc header field only in
ALTSVC frame. This option can be used multiple times to HTTP/1.1 frontend. This option can be used multiple
specify multiple alternative services. Example: times to specify multiple alternative services.
:option:`--altsvc`\=h2,443 Example: :option:`--altsvc`\=h2,443
.. option:: --add-request-header=<HEADER>
Specify additional header field to add to request header
set. This option just appends header field and won't
replace anything already set. This option can be used
several times to specify multiple header fields.
Example: :option:`--add-request-header`\="foo: bar"
.. option:: --add-response-header=<HEADER> .. option:: --add-response-header=<HEADER>
@@ -604,6 +631,21 @@ HTTP
used several times to specify multiple header fields. used several times to specify multiple header fields.
Example: :option:`--add-response-header`\="foo: bar" Example: :option:`--add-response-header`\="foo: bar"
.. option:: --header-field-buffer=<SIZE>
Set maximum buffer size for incoming HTTP header field
list. This is the sum of header name and value in
bytes.
Default: ``64K``
.. option:: --max-header-fields=<N>
Set maximum number of incoming HTTP header fields, which
appear in one request or response header field list.
Default: ``100``
Debug Debug
~~~~~ ~~~~~
@@ -667,12 +709,14 @@ Misc
Print this help and exit. Print this help and exit.
The <SIZE> argument is an integer and an optional unit (e.g., 10K is The <SIZE> argument is an integer and an optional unit (e.g., 10K is
10 * 1024). Units are K, M and G (powers of 1024). 10 * 1024). Units are K, M and G (powers of 1024).
The <DURATION> argument is an integer and an optional unit (e.g., 1s The <DURATION> argument is an integer and an optional unit (e.g., 1s
is 1 second and 500ms is 500 milliseconds). Units are s or ms. If is 1 second and 500ms is 500 milliseconds). Units are h, m, s or ms
a unit is omitted, a second is used as unit. (hours, minutes, seconds and milliseconds, respectively). If a unit
is omitted, a second is used as unit.
FILES FILES
----- -----
@@ -695,7 +739,7 @@ FILES
ignored. ignored.
To specify private key and certificate file which are given as To specify private key and certificate file which are given as
positional arguments in commnad-line, use ``private-key-file`` and positional arguments in command-line, use ``private-key-file`` and
``certificate-file``. ``certificate-file``.
:option:`--conf` option cannot be used in the configuration file and :option:`--conf` option cannot be used in the configuration file and
@@ -760,6 +804,18 @@ deletes it. However, if SIGUSR2 is used to execute new binary and
both old and new configurations use same filename, new binary does not both old and new configurations use same filename, new binary does not
delete the socket and continues to use it. delete the socket and continues to use it.
OCSP STAPLING
-------------
OCSP query is done using external Python script
``fetch-ocsp-response``, which has been originally developed in Perl
as part of h2o project (https://github.com/h2o/h2o), and was
translated into Python.
The script file is usually installed under
``$(prefix)/share/nghttp2/`` directory. The actual path to script can
be customized using :option:`--fetch-ocsp-response-file` option.
SEE ALSO SEE ALSO
-------- --------

View File

@@ -19,7 +19,7 @@ FILES
ignored. ignored.
To specify private key and certificate file which are given as To specify private key and certificate file which are given as
positional arguments in commnad-line, use ``private-key-file`` and positional arguments in command-line, use ``private-key-file`` and
``certificate-file``. ``certificate-file``.
:option:`--conf` option cannot be used in the configuration file and :option:`--conf` option cannot be used in the configuration file and
@@ -84,6 +84,18 @@ deletes it. However, if SIGUSR2 is used to execute new binary and
both old and new configurations use same filename, new binary does not both old and new configurations use same filename, new binary does not
delete the socket and continues to use it. delete the socket and continues to use it.
OCSP STAPLING
-------------
OCSP query is done using external Python script
``fetch-ocsp-response``, which has been originally developed in Perl
as part of h2o project (https://github.com/h2o/h2o), and was
translated into Python.
The script file is usually installed under
``$(prefix)/share/nghttp2/`` directory. The actual path to script can
be customized using :option:`--fetch-ocsp-response-file` option.
SEE ALSO SEE ALSO
-------- --------

View File

@@ -1,5 +1,5 @@
API Reference Programmers' Guide
============= ==================
Includes Includes
-------- --------
@@ -20,17 +20,17 @@ nghttp2 callback functions directly or indirectly. It will lead to the
crash. You can submit requests or frames in the callbacks then call crash. You can submit requests or frames in the callbacks then call
these functions outside the callbacks. these functions outside the callbacks.
Currently, `nghttp2_session_send()` and `nghttp2_session_mem_send()` `nghttp2_session_send()` and `nghttp2_session_mem_send()` send first
do not send client connection preface 24 bytes of client magic string (MAGIC)
(:macro:`NGHTTP2_CLIENT_CONNECTION_PREFACE`). The applications are (:macro:`NGHTTP2_CLIENT_MAGIC`) on client configuration. The
responsible to send it before sending any HTTP/2 frames using these applications are responsible to send SETTINGS frame as part of
functions if :type:`nghttp2_session` is configured as client. connection preface using `nghttp2_submit_settings()`. Similarly,
Similarly, `nghttp2_session_recv()` and `nghttp2_session_mem_recv()` `nghttp2_session_recv()` and `nghttp2_session_mem_recv()` consume
do not consume client connection preface unless MAGIC on server configuration unless
`nghttp2_option_set_recv_client_preface()` is used with nonzero option `nghttp2_option_set_no_recv_client_magic()` is used with nonzero
value. The applications are responsible to receive it before calling option value.
these functions if :type:`nghttp2_session` is configured as server and
`nghttp2_option_set_recv_client_preface()` is not used. .. _http-messaging:
HTTP Messaging HTTP Messaging
-------------- --------------
@@ -84,6 +84,11 @@ are floating around in existing internet and resetting stream just
because of this may break many web sites. This is especially true if because of this may break many web sites. This is especially true if
we forward to or translate from HTTP/1 traffic. we forward to or translate from HTTP/1 traffic.
For "http" or "https" URIs, ":path" pseudo header fields must start
with "/". The only exception is OPTIONS request, in that case, "*" is
allowed in ":path" pseudo header field to represent system-wide
OPTIONS request.
With the above validations, nghttp2 library guarantees that header With the above validations, nghttp2 library guarantees that header
field name passed to `nghttp2_on_header_callback()` is not empty. field name passed to `nghttp2_on_header_callback()` is not empty.
Also required pseudo headers are all present and not empty. Also required pseudo headers are all present and not empty.

View File

@@ -36,8 +36,9 @@ with the toolchain and installed under ``$ANDROID_HOME/usr/local``.
We recommend to build these libraries as static library to make the We recommend to build these libraries as static library to make the
deployment easier. libxml2 support is currently disabled. deployment easier. libxml2 support is currently disabled.
We use zlib which comes with Android NDK, so we don't have to build it Although zlib comes with Android NDK, it seems not to be a part of
by ourselves. public API, so we have to built it for our own. That also provides us
proper .pc file as a bonus.
If SPDY support is required for nghttpx and h2load, build and install If SPDY support is required for nghttpx and h2load, build and install
spdylay as well. spdylay as well.
@@ -95,10 +96,41 @@ patch, to configure libev, use the following script:
And run ``make install`` to build and install. And run ``make install`` to build and install.
To configure zlib, use the following script:
.. code-block:: sh
#!/bin/sh -e
if [ -z "$ANDROID_HOME" ]; then
echo 'No $ANDROID_HOME specified.'
exit 1
fi
PREFIX=$ANDROID_HOME/usr/local
TOOLCHAIN=$ANDROID_HOME/toolchain
PATH=$TOOLCHAIN/bin:$PATH
HOST=arm-linux-androideabi
CC=$HOST-gcc \
AR=$HOST-ar \
LD=$HOST-ld \
RANLIB=$HOST-ranlib \
STRIP=$HOST-strip \
./configure \
--prefix=$PREFIX \
--libdir=$PREFIX/lib \
--includedir=$PREFIX/include \
--static
And run ``make install`` to build and install.
To configure spdylay, use the following script: To configure spdylay, use the following script:
.. code-block:: sh .. code-block:: sh
#!/bin/sh -e
if [ -z "$ANDROID_HOME" ]; then if [ -z "$ANDROID_HOME" ]; then
echo 'No $ANDROID_HOME specified.' echo 'No $ANDROID_HOME specified.'
exit 1 exit 1
@@ -119,11 +151,7 @@ To configure spdylay, use the following script:
PKG_CONFIG_LIBDIR="$PREFIX/lib/pkgconfig" \ PKG_CONFIG_LIBDIR="$PREFIX/lib/pkgconfig" \
LDFLAGS="-L$PREFIX/lib" LDFLAGS="-L$PREFIX/lib"
And run ``make install`` to build and install. After spdylay And run ``make install`` to build and install.
installation, edit $ANDROID_HOME/usr/local/lib/pkgconfig/libspdylay.pc
and remove the following line::
Requires.private: zlib
After prerequisite libraries are prepared, run ``android-config`` and After prerequisite libraries are prepared, run ``android-config`` and
then ``android-make`` to compile nghttp2 source files. then ``android-make`` to compile nghttp2 source files.

View File

@@ -50,8 +50,9 @@ Flow Control
------------ ------------
HTTP/2 and SPDY/3 or later employ flow control and it may affect HTTP/2 and SPDY/3 or later employ flow control and it may affect
benchmarking results. To adjust receiver flow control window size, benchmarking results. By default, h2load uses large enough flow
there is following options: control window, which effectively disables flow control. To adjust
receiver flow control window size, there are following options:
``-w`` ``-w``
Sets the stream level initial window size to Sets the stream level initial window size to
@@ -86,5 +87,5 @@ If multiple URIs are specified, they are used in round robin manner.
.. note:: .. note::
Please note that h2load uses sheme, host and port in the first URI Please note that h2load uses scheme, host and port in the first URI
and ignores those parts in the rest of the URIs. and ignores those parts in the rest of the URIs.

View File

@@ -28,6 +28,7 @@ Contents:
h2load.1 h2load.1
nghttpx-howto nghttpx-howto
h2load-howto h2load-howto
programmers-guide
apiref apiref
libnghttp2_asio libnghttp2_asio
python-apiref python-apiref
@@ -48,5 +49,5 @@ https://github.com/tatsuhiro-t/nghttp2/releases
Resources Resources
--------- ---------
* http://tools.ietf.org/html/draft-ietf-httpbis-http2-14 * HTTP/2 https://tools.ietf.org/html/rfc7540
* http://tools.ietf.org/html/draft-ietf-httpbis-header-compression-09 * HPACK https://tools.ietf.org/html/rfc7541

View File

@@ -80,7 +80,7 @@ status code, in the above example, which is 200. The second argument,
which is omitted in the above example, is additional header fields to which is omitted in the above example, is additional header fields to
send. send.
``nghttp2::asio_http2::server::response::end`` sends responde body. ``nghttp2::asio_http2::server::response::end`` sends response body.
In the above example, we send string "hello, world". In the above example, we send string "hello, world".
The life time of req and res object ends after the callback set by The life time of req and res object ends after the callback set by
@@ -277,7 +277,7 @@ response header fields and response body to the console screen:
``boost::asio::io_service`` object and remote server address. When ``boost::asio::io_service`` object and remote server address. When
connection is made, the callback function passed to connection is made, the callback function passed to
``nghttp2::asio_http2::client::on_connect`` is invoked with connected ``nghttp2::asio_http2::client::on_connect`` is invoked with connected
address as its paramter. After this callback call, use address as its parameter. After this callback call, use
``nghttp2::asio_http2::session::submit`` to send request to the ``nghttp2::asio_http2::session::submit`` to send request to the
server. You can submit multiple requests at once without waiting for server. You can submit multiple requests at once without waiting for
the completion of previous request. the completion of previous request.

View File

@@ -21,7 +21,7 @@ SSL/TLS, the frontend also supports SPDY protocol.
By default, this mode's frontend connection is encrypted using By default, this mode's frontend connection is encrypted using
SSL/TLS. So server's private key and certificate must be supplied to SSL/TLS. So server's private key and certificate must be supplied to
the command line (or through configuration file). In this case, the the command line (or through configuration file). In this case, the
fontend protocol selection will is done via ALPN or NPN. frontend protocol selection will is done via ALPN or NPN.
With ``--frontend-no-tls`` option, user can turn off SSL/TLS in With ``--frontend-no-tls`` option, user can turn off SSL/TLS in
frontend connection. In this case, SPDY protocol is not available frontend connection. In this case, SPDY protocol is not available
@@ -243,7 +243,7 @@ Read/write rate limit
--------------------- ---------------------
nghttpx supports transfer rate limiting on frontend connections. You nghttpx supports transfer rate limiting on frontend connections. You
can do rate limit per frontend connection for reading and writeing can do rate limit per frontend connection for reading and writing
individually. individually.
To perform rate limit for reading, use ``--read-rate`` and To perform rate limit for reading, use ``--read-rate`` and

View File

@@ -220,6 +220,10 @@ HTTP/2 servers
This is a value of ``:path`` header field. This is a value of ``:path`` header field.
.. py:attribute:: headers
Request header fields.
A :py:class:`BaseRequestHandler` has the following methods: A :py:class:`BaseRequestHandler` has the following methods:
.. py:method:: on_headers() .. py:method:: on_headers()
@@ -249,10 +253,28 @@ HTTP/2 servers
Send response. The *status* is HTTP status code. The *headers* Send response. The *status* is HTTP status code. The *headers*
is additional response headers. The *:status* header field will is additional response headers. The *:status* header field will
be appended by the library. The *body* is the response body. be appended by the library. The *body* is the response body.
It could be ``None`` if response body is empty. Or it must be It could be ``None`` if response body is empty. Or it must be
instance of either ``str``, ``bytes`` or :py:class:`io.IOBase`. instance of either ``str``, ``bytes``, :py:class:`io.IOBase` or
If instance of ``str`` is specified, it will be encoded using callable, called body generator, which takes one parameter,
UTF-8. size. The body generator generates response body. It can pause
generation of response so that it can wait for slow backend data
generation. When invoked, it should return tuple, byte string
at most size length and flag. The flag is either
:py:data:`DATA_OK`, :py:data:`DATA_EOF` or
:py:data:`DATA_DEFERRED`. For non-empty byte string and it is
not the last chunk of response, :py:data:`DATA_OK` must be
returned as flag. If this is the last chunk of the response
(byte string could be ``None``), :py:data:`DATA_EOF` must be
returned as flag. If there is no data available right now, but
additional data are anticipated, return tuple (``None``,
:py:data:`DATA_DEFERRED`). When data arrived, call
:py:meth:`resume()` and restart response body transmission.
Only the body generator can pause response body generation;
instance of :py:class:`io.IOBase` must not block.
If instance of ``str`` is specified as *body*, it will be
encoded using UTF-8.
The *headers* is a list of tuple of the form ``(name, The *headers* is a list of tuple of the form ``(name,
value)``. The ``name`` and ``value`` can be either byte string value)``. The ``name`` and ``value`` can be either byte string
@@ -273,10 +295,8 @@ HTTP/2 servers
The *status* is HTTP status code. The *headers* is additional The *status* is HTTP status code. The *headers* is additional
response headers. The ``:status`` header field is appended by response headers. The ``:status`` header field is appended by
the library. The *body* is the response body. It could be the library. The *body* is the response body. It has the same
``None`` if response body is empty. Or it must be instance of semantics of *body* parameter of :py:meth:`send_response()`.
either ``str``, ``bytes`` or ``io.IOBase``. If instance of
``str`` is specified, it is encoded using UTF-8.
The headers and request_headers are a list of tuple of the form The headers and request_headers are a list of tuple of the form
``(name, value)``. The ``name`` and ``value`` can be either byte ``(name, value)``. The ``name`` and ``value`` can be either byte
@@ -288,6 +308,27 @@ HTTP/2 servers
Raises the exception if any error occurs. Raises the exception if any error occurs.
.. py:method:: resume()
Signals the restarting of response body transmission paused by
``DATA_DEFERRED`` from the body generator (see
:py:meth:`send_response()` about the body generator). It is not
an error calling this method while response body transmission is
not paused.
.. py:data:: DATA_OK
``DATA_OK`` indicates non empty data is generated from body generator.
.. py:data:: DATA_EOF
``DATA_EOF`` indicates the end of response body.
.. py:data:: DATA_DEFERRED
``DATA_DEFERRED`` indicates that data are not available right now
and response should be paused.
The following example illustrates :py:class:`HTTP2Server` and The following example illustrates :py:class:`HTTP2Server` and
:py:class:`BaseRequestHandler` usage: :py:class:`BaseRequestHandler` usage:
@@ -296,6 +337,7 @@ The following example illustrates :py:class:`HTTP2Server` and
#!/usr/bin/env python #!/usr/bin/env python
import io, ssl import io, ssl
import nghttp2 import nghttp2
class Handler(nghttp2.BaseRequestHandler): class Handler(nghttp2.BaseRequestHandler):
@@ -311,9 +353,85 @@ The following example illustrates :py:class:`HTTP2Server` and
body=io.BytesIO(b'nghttp2-python FTW')) body=io.BytesIO(b'nghttp2-python FTW'))
ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23) ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
ctx.options = ssl.OP_ALL | ssl.OP_NO_SSLv2 ctx.options = ssl.OP_ALL | ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3
ctx.load_cert_chain('server.crt', 'server.key') ctx.load_cert_chain('server.crt', 'server.key')
# give None to ssl to make the server non-SSL/TLS # give None to ssl to make the server non-SSL/TLS
server = nghttp2.HTTP2Server(('127.0.0.1', 8443), Handler, ssl=ctx) server = nghttp2.HTTP2Server(('127.0.0.1', 8443), Handler, ssl=ctx)
server.serve_forever() server.serve_forever()
The following example illustrates HTTP/2 server using asynchronous
response body generation. This is simplified reverse proxy:
.. code-block:: python
#!/usr/bin/env python
import ssl
import os
import urllib
import asyncio
import io
import nghttp2
@asyncio.coroutine
def get_http_header(handler, url):
url = urllib.parse.urlsplit(url)
ssl = url.scheme == 'https'
if url.port == None:
if url.scheme == 'https':
port = 443
else:
port = 80
else:
port = url.port
connect = asyncio.open_connection(url.hostname, port, ssl=ssl)
reader, writer = yield from connect
req = 'GET {path} HTTP/1.0\r\n\r\n'.format(path=url.path or '/')
writer.write(req.encode('utf-8'))
# skip response header fields
while True:
line = yield from reader.readline()
line = line.rstrip()
if not line:
break
# read body
while True:
b = yield from reader.read(4096)
if not b:
break
handler.buf.write(b)
writer.close()
handler.buf.seek(0)
handler.eof = True
handler.resume()
class Body:
def __init__(self, handler):
self.handler = handler
self.handler.eof = False
self.handler.buf = io.BytesIO()
def generate(self, n):
buf = self.handler.buf
data = buf.read1(n)
if not data and not self.handler.eof:
return None, nghttp2.DATA_DEFERRED
return data, nghttp2.DATA_EOF if self.handler.eof else nghttp2.DATA_OK
class Handler(nghttp2.BaseRequestHandler):
def on_headers(self):
body = Body(self)
asyncio.async(get_http_header(
self, 'http://localhost' + self.path.decode('utf-8')))
self.send_response(status=200, body=body.generate)
ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
ctx.options = ssl.OP_ALL | ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3
ctx.load_cert_chain('server.crt', 'server.key')
server = nghttp2.HTTP2Server(('127.0.0.1', 8443), Handler, ssl=ctx)
server.serve_forever()

View File

@@ -65,11 +65,11 @@ its stream specific data in ``http2_stream_data`` structure and the
defined as follows:: defined as follows::
typedef struct { typedef struct {
/* The NULL-terminated URI string to retreive. */ /* The NULL-terminated URI string to retrieve. */
const char *uri; const char *uri;
/* Parsed result of the |uri| */ /* Parsed result of the |uri| */
struct http_parser_url *u; struct http_parser_url *u;
/* The authroity portion of the |uri|, not NULL-terminated */ /* The authority portion of the |uri|, not NULL-terminated */
char *authority; char *authority;
/* The path portion of the |uri|, including query, not /* The path portion of the |uri|, including query, not
NULL-terminated */ NULL-terminated */
@@ -184,9 +184,9 @@ its bufferevent, so it closes underlying connection as well. It also
calls `nghttp2_session_del()` to delete nghttp2 session object. calls `nghttp2_session_del()` to delete nghttp2 session object.
We begin HTTP/2 communication by sending client connection preface, We begin HTTP/2 communication by sending client connection preface,
which is 24 bytes magic byte sequence which is 24 bytes magic byte string (:macro:`NGHTTP2_CLIENT_MAGIC`)
(:macro:`NGHTTP2_CLIENT_CONNECTION_PREFACE`) and SETTINGS frame. The followed by SETTINGS frame. First 24 bytes magic string is
transmission of client connection header is done in automatically sent by nghttp2 library. We send SETTINGS frame in
``send_client_connection_header()``:: ``send_client_connection_header()``::
static void send_client_connection_header(http2_session_data *session_data) { static void send_client_connection_header(http2_session_data *session_data) {
@@ -194,8 +194,7 @@ transmission of client connection header is done in
{NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS, 100}}; {NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS, 100}};
int rv; int rv;
bufferevent_write(session_data->bev, NGHTTP2_CLIENT_CONNECTION_PREFACE, /* client 24 bytes magic string will be sent by nghttp2 library */
NGHTTP2_CLIENT_CONNECTION_PREFACE_LEN);
rv = nghttp2_submit_settings(session_data->session, NGHTTP2_FLAG_NONE, iv, rv = nghttp2_submit_settings(session_data->session, NGHTTP2_FLAG_NONE, iv,
ARRLEN(iv)); ARRLEN(iv));
if (rv != 0) { if (rv != 0) {
@@ -204,7 +203,7 @@ transmission of client connection header is done in
} }
Here we specify SETTINGS_MAX_CONCURRENT_STREAMS to 100, which is Here we specify SETTINGS_MAX_CONCURRENT_STREAMS to 100, which is
really not needed for this tiny example progoram, but we are really not needed for this tiny example program, but we are
demonstrating the use of SETTINGS frame. To queue the SETTINGS frame demonstrating the use of SETTINGS frame. To queue the SETTINGS frame
for the transmission, we use `nghttp2_submit_settings()`. Note that for the transmission, we use `nghttp2_submit_settings()`. Note that
`nghttp2_submit_settings()` function only queues the frame and not `nghttp2_submit_settings()` function only queues the frame and not
@@ -388,7 +387,7 @@ After all name/value pairs are emitted for a frame,
} }
In this tutorial, we are just interested in the HTTP response In this tutorial, we are just interested in the HTTP response
HEADERS. We check te frame type and its category (it should be HEADERS. We check the frame type and its category (it should be
:macro:`NGHTTP2_HCAT_RESPONSE` for HTTP response HEADERS). Also check :macro:`NGHTTP2_HCAT_RESPONSE` for HTTP response HEADERS). Also check
its stream ID. its stream ID.
@@ -407,7 +406,7 @@ of data is received from the remote peer::
} }
In our case, a chunk of data is response body. After checking stream In our case, a chunk of data is response body. After checking stream
ID, we just write the recieved data to the stdout. Note that the ID, we just write the received data to the stdout. Note that the
output in the terminal may be corrupted if the response body contains output in the terminal may be corrupted if the response body contains
some binary data. some binary data.

View File

@@ -51,7 +51,7 @@ bound of encoded result, use `nghttp2_hd_deflate_bound()` function::
size_t nghttp2_hd_deflate_bound(nghttp2_hd_deflater *deflater, size_t nghttp2_hd_deflate_bound(nghttp2_hd_deflater *deflater,
const nghttp2_nv *nva, size_t nvlen); const nghttp2_nv *nva, size_t nvlen);
Pass this function with the same paramters *deflater*, *nva* and Pass this function with the same parameters *deflater*, *nva* and
*nvlen* which will be passed to `nghttp2_hd_deflate_hd()`. *nvlen* which will be passed to `nghttp2_hd_deflate_hd()`.
The subsequent call of `nghttp2_hd_deflate_hd()` will use current The subsequent call of `nghttp2_hd_deflate_hd()` will use current

View File

@@ -194,15 +194,8 @@ We initialize a nghttp2 session object which is done in
``initialize_nghttp2_session()``:: ``initialize_nghttp2_session()``::
static void initialize_nghttp2_session(http2_session_data *session_data) { static void initialize_nghttp2_session(http2_session_data *session_data) {
nghttp2_option *option;
nghttp2_session_callbacks *callbacks; nghttp2_session_callbacks *callbacks;
nghttp2_option_new(&option);
/* Tells nghttp2_session object that it handles client connection
preface */
nghttp2_option_set_recv_client_preface(option, 1);
nghttp2_session_callbacks_new(&callbacks); nghttp2_session_callbacks_new(&callbacks);
nghttp2_session_callbacks_set_send_callback(callbacks, send_callback); nghttp2_session_callbacks_set_send_callback(callbacks, send_callback);
@@ -219,20 +212,15 @@ We initialize a nghttp2 session object which is done in
nghttp2_session_callbacks_set_on_begin_headers_callback( nghttp2_session_callbacks_set_on_begin_headers_callback(
callbacks, on_begin_headers_callback); callbacks, on_begin_headers_callback);
nghttp2_session_server_new2(&session_data->session, callbacks, session_data, nghttp2_session_server_new(&session_data->session, callbacks, session_data);
option);
nghttp2_session_callbacks_del(callbacks); nghttp2_session_callbacks_del(callbacks);
nghttp2_option_del(option);
} }
Since we are creating a server and uses options, the nghttp2 session Since we are creating a server and uses options, the nghttp2 session
object is created using `nghttp2_session_server_new2()` function. We object is created using `nghttp2_session_server_new2()` function. We
registers five callbacks for nghttp2 session object. We'll talk about registers five callbacks for nghttp2 session object. We'll talk about
these callbacks later. Our server only speaks HTTP/2. In this case, these callbacks later.
we use `nghttp2_option_set_recv_client_preface()` to make
:type:`nghttp2_session` object handle client connection preface, which
saves some lines of application code.
After initialization of the nghttp2 session object, we are going to send After initialization of the nghttp2 session object, we are going to send
a server connection header in ``send_server_connection_header()``:: a server connection header in ``send_server_connection_header()``::

View File

@@ -60,7 +60,10 @@ if ENABLE_ASIO_LIB
noinst_PROGRAMS += asio-sv asio-sv2 asio-cl asio-cl2 noinst_PROGRAMS += asio-sv asio-sv2 asio-cl asio-cl2
ASIOCPPFLAGS = ${BOOST_CPPFLAGS} ${AM_CPPFLAGS} # AM_CPPFLAGS must be placed first, so that header file (e.g.,
# nghttp2/nghttp2.h) in this package is used rather than installed
# one.
ASIOCPPFLAGS = ${AM_CPPFLAGS} ${BOOST_CPPFLAGS}
ASIOLDADD = $(top_builddir)/lib/libnghttp2.la \ ASIOLDADD = $(top_builddir)/lib/libnghttp2.la \
$(top_builddir)/src/libnghttp2_asio.la @JEMALLOC_LIBS@ \ $(top_builddir)/src/libnghttp2_asio.la @JEMALLOC_LIBS@ \
$(top_builddir)/third-party/libhttp-parser.la \ $(top_builddir)/third-party/libhttp-parser.la \

View File

@@ -35,8 +35,12 @@
// //
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h> #include <unistd.h>
#endif // HAVE_UNISTD_H
#ifdef HAVE_FCNTL_H
#include <fcntl.h> #include <fcntl.h>
#endif // HAVE_FCNTL_H
#include <iostream> #include <iostream>
#include <string> #include <string>

View File

@@ -28,16 +28,26 @@
*/ */
#ifdef HAVE_CONFIG_H #ifdef HAVE_CONFIG_H
#include <config.h> #include <config.h>
#endif /* !HAVE_CONFIG_H */ #endif /* HAVE_CONFIG_H */
#include <stdint.h> #include <inttypes.h>
#include <stdlib.h> #include <stdlib.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h> #include <unistd.h>
#endif /* HAVE_UNISTD_H */
#ifdef HAVE_FCNTL_H
#include <fcntl.h> #include <fcntl.h>
#endif /* HAVE_FCNTL_H */
#include <sys/types.h> #include <sys/types.h>
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h> #include <sys/socket.h>
#endif /* HAVE_SYS_SOCKET_H */
#ifdef HAVE_NETDB_H
#include <netdb.h> #include <netdb.h>
#endif /* HAVE_NETDB_H */
#ifdef HAVE_NETINET_IN_H
#include <netinet/in.h> #include <netinet/in.h>
#endif /* HAVE_NETINET_IN_H */
#include <netinet/tcp.h> #include <netinet/tcp.h>
#include <poll.h> #include <poll.h>
#include <signal.h> #include <signal.h>
@@ -528,14 +538,6 @@ static void fetch_uri(const struct URI *uri) {
connection.ssl = ssl; connection.ssl = ssl;
connection.want_io = IO_NONE; connection.want_io = IO_NONE;
/* Send connection header in blocking I/O mode */
rv = SSL_write(ssl, NGHTTP2_CLIENT_CONNECTION_PREFACE,
NGHTTP2_CLIENT_CONNECTION_PREFACE_LEN);
if (rv <= 0) {
dief("SSL_write failed: could not send connection preface",
ERR_error_string(ERR_get_error(), NULL));
}
/* Here make file descriptor non-block */ /* Here make file descriptor non-block */
make_non_block(fd); make_non_block(fd);
set_tcp_nodelay(fd); set_tcp_nodelay(fd);
@@ -687,10 +689,10 @@ int main(int argc, char **argv) {
act.sa_handler = SIG_IGN; act.sa_handler = SIG_IGN;
sigaction(SIGPIPE, &act, 0); sigaction(SIGPIPE, &act, 0);
OPENSSL_config(NULL);
OpenSSL_add_all_algorithms();
SSL_load_error_strings(); SSL_load_error_strings();
SSL_library_init(); SSL_library_init();
OpenSSL_add_all_algorithms();
OPENSSL_config(NULL);
rv = parse_uri(&uri, argv[1]); rv = parse_uri(&uri, argv[1]);
if (rv != 0) { if (rv != 0) {

View File

@@ -24,12 +24,18 @@
*/ */
#ifdef HAVE_CONFIG_H #ifdef HAVE_CONFIG_H
#include <config.h> #include <config.h>
#endif /* !HAVE_CONFIG_H */ #endif /* HAVE_CONFIG_H */
#include <sys/types.h> #include <sys/types.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h> #include <unistd.h>
#endif /* HAVE_UNISTD_H */
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h> #include <sys/socket.h>
#endif /* HAVE_SYS_SOCKET_H */
#ifdef HAVE_NETINET_IN_H
#include <netinet/in.h> #include <netinet/in.h>
#endif /* HAVE_NETINET_IN_H */
#include <netinet/tcp.h> #include <netinet/tcp.h>
#include <err.h> #include <err.h>
#include <signal.h> #include <signal.h>
@@ -50,11 +56,11 @@
#define ARRLEN(x) (sizeof(x) / sizeof(x[0])) #define ARRLEN(x) (sizeof(x) / sizeof(x[0]))
typedef struct { typedef struct {
/* The NULL-terminated URI string to retreive. */ /* The NULL-terminated URI string to retrieve. */
const char *uri; const char *uri;
/* Parsed result of the |uri| */ /* Parsed result of the |uri| */
struct http_parser_url *u; struct http_parser_url *u;
/* The authroity portion of the |uri|, not NULL-terminated */ /* The authority portion of the |uri|, not NULL-terminated */
char *authority; char *authority;
/* The path portion of the |uri|, including query, not /* The path portion of the |uri|, including query, not
NULL-terminated */ NULL-terminated */
@@ -94,7 +100,8 @@ static http2_stream_data *create_http2_stream_data(const char *uri,
":%u", u->port); ":%u", u->port);
} }
stream_data->pathlen = 0; /* If we don't have path in URI, we use "/" as path. */
stream_data->pathlen = 1;
if (u->field_set & (1 << UF_PATH)) { if (u->field_set & (1 << UF_PATH)) {
stream_data->pathlen = u->field_data[UF_PATH].len; stream_data->pathlen = u->field_data[UF_PATH].len;
} }
@@ -102,19 +109,22 @@ static http2_stream_data *create_http2_stream_data(const char *uri,
/* +1 for '?' character */ /* +1 for '?' character */
stream_data->pathlen += u->field_data[UF_QUERY].len + 1; stream_data->pathlen += u->field_data[UF_QUERY].len + 1;
} }
if (stream_data->pathlen > 0) {
stream_data->path = malloc(stream_data->pathlen); stream_data->path = malloc(stream_data->pathlen);
if (u->field_set & (1 << UF_PATH)) { if (u->field_set & (1 << UF_PATH)) {
memcpy(stream_data->path, &uri[u->field_data[UF_PATH].off], memcpy(stream_data->path, &uri[u->field_data[UF_PATH].off],
u->field_data[UF_PATH].len); u->field_data[UF_PATH].len);
}
if (u->field_set & (1 << UF_QUERY)) {
memcpy(stream_data->path + u->field_data[UF_PATH].len + 1,
&uri[u->field_data[UF_QUERY].off], u->field_data[UF_QUERY].len);
}
} else { } else {
stream_data->path = NULL; stream_data->path[0] = '/';
} }
if (u->field_set & (1 << UF_QUERY)) {
stream_data->path[stream_data->pathlen - u->field_data[UF_QUERY].len - 1] =
'?';
memcpy(stream_data->path + stream_data->pathlen -
u->field_data[UF_QUERY].len,
&uri[u->field_data[UF_QUERY].off], u->field_data[UF_QUERY].len);
}
return stream_data; return stream_data;
} }
@@ -258,8 +268,7 @@ static int on_data_chunk_recv_callback(nghttp2_session *session _U_,
stream), if it is closed, we send GOAWAY and tear down the stream), if it is closed, we send GOAWAY and tear down the
session */ session */
static int on_stream_close_callback(nghttp2_session *session, int32_t stream_id, static int on_stream_close_callback(nghttp2_session *session, int32_t stream_id,
uint32_t error_code, uint32_t error_code, void *user_data) {
void *user_data) {
http2_session_data *session_data = (http2_session_data *)user_data; http2_session_data *session_data = (http2_session_data *)user_data;
int rv; int rv;
@@ -345,8 +354,7 @@ static void send_client_connection_header(http2_session_data *session_data) {
{NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS, 100}}; {NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS, 100}};
int rv; int rv;
bufferevent_write(session_data->bev, NGHTTP2_CLIENT_CONNECTION_PREFACE, /* client 24 bytes magic string will be sent by nghttp2 library */
NGHTTP2_CLIENT_CONNECTION_PREFACE_LEN);
rv = nghttp2_submit_settings(session_data->session, NGHTTP2_FLAG_NONE, iv, rv = nghttp2_submit_settings(session_data->session, NGHTTP2_FLAG_NONE, iv,
ARRLEN(iv)); ARRLEN(iv));
if (rv != 0) { if (rv != 0) {
@@ -547,10 +555,10 @@ int main(int argc, char **argv) {
act.sa_handler = SIG_IGN; act.sa_handler = SIG_IGN;
sigaction(SIGPIPE, &act, NULL); sigaction(SIGPIPE, &act, NULL);
OPENSSL_config(NULL);
OpenSSL_add_all_algorithms();
SSL_load_error_strings(); SSL_load_error_strings();
SSL_library_init(); SSL_library_init();
OpenSSL_add_all_algorithms();
OPENSSL_config(NULL);
run(argv[1]); run(argv[1]);
return 0; return 0;

View File

@@ -24,17 +24,27 @@
*/ */
#ifdef HAVE_CONFIG_H #ifdef HAVE_CONFIG_H
#include <config.h> #include <config.h>
#endif /* !HAVE_CONFIG_H */ #endif /* HAVE_CONFIG_H */
#include <sys/types.h> #include <sys/types.h>
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h> #include <sys/socket.h>
#endif /* HAVE_SYS_SOCKET_H */
#ifdef HAVE_NETDB_H
#include <netdb.h> #include <netdb.h>
#endif /* HAVE_NETDB_H */
#include <signal.h> #include <signal.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h> #include <unistd.h>
#endif /* HAVE_UNISTD_H */
#include <sys/stat.h> #include <sys/stat.h>
#ifdef HAVE_FCNTL_H
#include <fcntl.h> #include <fcntl.h>
#endif /* HAVE_FCNTL_H */
#include <ctype.h> #include <ctype.h>
#ifdef HAVE_NETINET_IN_H
#include <netinet/in.h> #include <netinet/in.h>
#endif /* HAVE_NETINET_IN_H */
#include <netinet/tcp.h> #include <netinet/tcp.h>
#include <err.h> #include <err.h>
@@ -537,15 +547,8 @@ static int on_stream_close_callback(nghttp2_session *session, int32_t stream_id,
} }
static void initialize_nghttp2_session(http2_session_data *session_data) { static void initialize_nghttp2_session(http2_session_data *session_data) {
nghttp2_option *option;
nghttp2_session_callbacks *callbacks; nghttp2_session_callbacks *callbacks;
nghttp2_option_new(&option);
/* Tells nghttp2_session object that it handles client connection
preface */
nghttp2_option_set_recv_client_preface(option, 1);
nghttp2_session_callbacks_new(&callbacks); nghttp2_session_callbacks_new(&callbacks);
nghttp2_session_callbacks_set_send_callback(callbacks, send_callback); nghttp2_session_callbacks_set_send_callback(callbacks, send_callback);
@@ -562,11 +565,9 @@ static void initialize_nghttp2_session(http2_session_data *session_data) {
nghttp2_session_callbacks_set_on_begin_headers_callback( nghttp2_session_callbacks_set_on_begin_headers_callback(
callbacks, on_begin_headers_callback); callbacks, on_begin_headers_callback);
nghttp2_session_server_new2(&session_data->session, callbacks, session_data, nghttp2_session_server_new(&session_data->session, callbacks, session_data);
option);
nghttp2_session_callbacks_del(callbacks); nghttp2_session_callbacks_del(callbacks);
nghttp2_option_del(option);
} }
/* Send HTTP/2 client connection header, which includes 24 bytes /* Send HTTP/2 client connection header, which includes 24 bytes
@@ -723,10 +724,10 @@ int main(int argc, char **argv) {
act.sa_handler = SIG_IGN; act.sa_handler = SIG_IGN;
sigaction(SIGPIPE, &act, NULL); sigaction(SIGPIPE, &act, NULL);
OPENSSL_config(NULL);
OpenSSL_add_all_algorithms();
SSL_load_error_strings(); SSL_load_error_strings();
SSL_library_init(); SSL_library_init();
OpenSSL_add_all_algorithms();
OPENSSL_config(NULL);
run(argv[1], argv[2], argv[3]); run(argv[1], argv[2], argv[3]);
return 0; return 0;

View File

@@ -30,18 +30,30 @@
#ifdef HAVE_CONFIG_H #ifdef HAVE_CONFIG_H
#include <config.h> #include <config.h>
#endif /* !HAVE_CONFIG_H */ #endif /* HAVE_CONFIG_H */
#include <sys/types.h> #include <sys/types.h>
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h> #include <sys/socket.h>
#endif /* HAVE_SYS_SOCKET_H */
#include <sys/stat.h> #include <sys/stat.h>
#ifdef HAVE_FCNTL_H
#include <fcntl.h> #include <fcntl.h>
#endif /* HAVE_FCNTL_H */
#ifdef HAVE_NETDB_H
#include <netdb.h> #include <netdb.h>
#endif /* HAVE_NETDB_H */
#ifdef HAVE_NETINET_IN_H
#include <netinet/in.h> #include <netinet/in.h>
#endif /* HAVE_NETINET_IN_H */
#include <netinet/tcp.h> #include <netinet/tcp.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h> #include <unistd.h>
#endif /* HAVE_UNISTD_H */
#include <stdlib.h> #include <stdlib.h>
#ifdef HAVE_TIME_H
#include <time.h> #include <time.h>
#endif /* HAVE_TIME_H */
#include <string.h> #include <string.h>
#include <stdio.h> #include <stdio.h>
#include <errno.h> #include <errno.h>
@@ -153,7 +165,6 @@ const char *docroot;
size_t docrootlen; size_t docrootlen;
nghttp2_session_callbacks *shared_callbacks; nghttp2_session_callbacks *shared_callbacks;
nghttp2_option *shared_option;
static int handle_accept(io_loop *loop, uint32_t events, void *ptr); static int handle_accept(io_loop *loop, uint32_t events, void *ptr);
static int handle_connection(io_loop *loop, uint32_t events, void *ptr); static int handle_connection(io_loop *loop, uint32_t events, void *ptr);
@@ -190,7 +201,7 @@ typedef enum {
NGHTTP2_TOKEN__METHOD, NGHTTP2_TOKEN__METHOD,
NGHTTP2_TOKEN__PATH, NGHTTP2_TOKEN__PATH,
NGHTTP2_TOKEN__SCHEME, NGHTTP2_TOKEN__SCHEME,
NGHTTP2_TOKEN_HOST, NGHTTP2_TOKEN_HOST
} nghttp2_token; } nghttp2_token;
/* Inspired by h2o header lookup. https://github.com/h2o/h2o */ /* Inspired by h2o header lookup. https://github.com/h2o/h2o */
@@ -388,8 +399,7 @@ static connection *connection_new(int fd) {
conn = malloc(sizeof(connection)); conn = malloc(sizeof(connection));
rv = nghttp2_session_server_new2(&conn->session, shared_callbacks, conn, rv = nghttp2_session_server_new(&conn->session, shared_callbacks, conn);
shared_option);
if (rv != 0) { if (rv != 0) {
goto cleanup; goto cleanup;
@@ -658,19 +668,52 @@ static void stream_error(connection *conn, int32_t stream_id,
error_code); error_code);
} }
static int send_data_callback(nghttp2_session *session _U_,
nghttp2_frame *frame, const uint8_t *framehd,
size_t length, nghttp2_data_source *source,
void *user_data) {
connection *conn = user_data;
uint8_t *p = conn->buf.last;
stream *strm = source->ptr;
/* We never use padding in this program */
assert(frame->data.padlen == 0);
if ((size_t)io_buf_left(&conn->buf) < 9 + frame->hd.length) {
return NGHTTP2_ERR_WOULDBLOCK;
}
memcpy(p, framehd, 9);
p += 9;
while (length) {
ssize_t nread;
while ((nread = read(strm->filefd, p, length)) == -1 && errno == EINTR)
;
if (nread == -1) {
return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
}
length -= nread;
p += nread;
}
conn->buf.last = p;
return 0;
}
static ssize_t fd_read_callback(nghttp2_session *session _U_, static ssize_t fd_read_callback(nghttp2_session *session _U_,
int32_t stream_id _U_, uint8_t *buf, int32_t stream_id _U_, uint8_t *buf _U_,
size_t length, uint32_t *data_flags, size_t length, uint32_t *data_flags,
nghttp2_data_source *source, nghttp2_data_source *source,
void *user_data _U_) { void *user_data _U_) {
stream *strm = source->ptr; stream *strm = source->ptr;
ssize_t nread; ssize_t nread =
(int64_t)length < strm->fileleft ? (int64_t)length : strm->fileleft;
*data_flags |= NGHTTP2_DATA_FLAG_NO_COPY;
while ((nread = read(strm->filefd, buf, length)) == -1 && errno == EINTR)
;
if (nread == -1) {
return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
}
strm->fileleft -= nread; strm->fileleft -= nread;
if (nread == 0 || strm->fileleft == 0) { if (nread == 0 || strm->fileleft == 0) {
if (strm->fileleft != 0) { if (strm->fileleft != 0) {
@@ -1274,14 +1317,8 @@ int main(int argc, char **argv) {
shared_callbacks, on_stream_close_callback); shared_callbacks, on_stream_close_callback);
nghttp2_session_callbacks_set_on_frame_not_send_callback( nghttp2_session_callbacks_set_on_frame_not_send_callback(
shared_callbacks, on_frame_not_send_callback); shared_callbacks, on_frame_not_send_callback);
nghttp2_session_callbacks_set_send_data_callback(shared_callbacks,
rv = nghttp2_option_new(&shared_option); send_data_callback);
if (rv != 0) {
fprintf(stderr, "nghttp2_option_new: %s", nghttp2_strerror(rv));
exit(EXIT_FAILURE);
}
nghttp2_option_set_recv_client_preface(shared_option, 1);
rv = io_loop_add(&loop, serv.fd, EPOLLIN, &serv); rv = io_loop_add(&loop, serv.fd, EPOLLIN, &serv);
@@ -1299,7 +1336,6 @@ int main(int argc, char **argv) {
io_loop_run(&loop, &serv); io_loop_run(&loop, &serv);
nghttp2_option_del(shared_option);
nghttp2_session_callbacks_del(shared_callbacks); nghttp2_session_callbacks_del(shared_callbacks);
return 0; return 0;

View File

@@ -1,5 +1,7 @@
#!/usr/bin/env python #!/usr/bin/env python
from gentokenlookup import gentokenlookup
HEADERS = [ HEADERS = [
':authority', ':authority',
':method', ':method',
@@ -34,70 +36,5 @@ HEADERS = [
'upgrade' 'upgrade'
] ]
def to_enum_hd(k):
res = 'HD_'
for c in k.upper():
if c == ':' or c == '-':
res += '_'
continue
res += c
return res
def build_header(headers):
res = {}
for k in headers:
size = len(k)
if size not in res:
res[size] = {}
ent = res[size]
c = k[-1]
if c not in ent:
ent[c] = []
ent[c].append(k)
return res
def gen_enum():
print '''\
enum {'''
for k in sorted(HEADERS):
print '''\
{},'''.format(to_enum_hd(k))
print '''\
HD_MAXIDX,
};'''
def gen_index_header():
print '''\
int lookup_token(const uint8_t *name, size_t namelen) {
switch (namelen) {'''
b = build_header(HEADERS)
for size in sorted(b.keys()):
ents = b[size]
print '''\
case {}:'''.format(size)
print '''\
switch (name[namelen - 1]) {'''
for c in sorted(ents.keys()):
headers = sorted(ents[c])
print '''\
case '{}':'''.format(c)
for k in headers:
print '''\
if (util::streq_l("{}", name, {})) {{
return {};
}}'''.format(k[:-1], size - 1, to_enum_hd(k))
print '''\
break;'''
print '''\
}
break;'''
print '''\
}
return -1;
}'''
if __name__ == '__main__': if __name__ == '__main__':
gen_enum() gentokenlookup(HEADERS, 'HD')
print ''
gen_index_header()

View File

@@ -1,19 +1,72 @@
#!/usr/bin/env python #!/usr/bin/env python
HEADERS = [ HEADERS = [
':authority', (':authority', 0),
':method', (':method', 1),
':path', (':method', 2),
':scheme', (':path', 3),
':status', (':path', 4),
"content-length", (':scheme', 5),
"host", (':scheme', 6),
"te", (':status', 7),
'connection', (':status', 8),
'keep-alive', (':status', 9),
'proxy-connection', (':status', 10),
'transfer-encoding', (':status', 11),
'upgrade' (':status', 12),
(':status', 13),
('accept-charset', 14),
('accept-encoding', 15),
('accept-language', 16),
('accept-ranges', 17),
('accept', 18),
('access-control-allow-origin', 19),
('age', 20),
('allow', 21),
('authorization', 22),
('cache-control', 23),
('content-disposition', 24),
('content-encoding', 25),
('content-language', 26),
('content-length', 27),
('content-location', 28),
('content-range', 29),
('content-type', 30),
('cookie', 31),
('date', 32),
('etag', 33),
('expect', 34),
('expires', 35),
('from', 36),
('host', 37),
('if-match', 38),
('if-modified-since', 39),
('if-none-match', 40),
('if-range', 41),
('if-unmodified-since', 42),
('last-modified', 43),
('link', 44),
('location', 45),
('max-forwards', 46),
('proxy-authenticate', 47),
('proxy-authorization', 48),
('range', 49),
('referer', 50),
('refresh', 51),
('retry-after', 52),
('server', 53),
('set-cookie', 54),
('strict-transport-security', 55),
('transfer-encoding', 56),
('user-agent', 57),
('vary', 58),
('via', 59),
('www-authenticate', 60),
('te', None),
('connection', None),
('keep-alive',None),
('proxy-connection', None),
('upgrade', None),
] ]
def to_enum_hd(k): def to_enum_hd(k):
@@ -27,7 +80,7 @@ def to_enum_hd(k):
def build_header(headers): def build_header(headers):
res = {} res = {}
for k in headers: for k, _ in headers:
size = len(k) size = len(k)
if size not in res: if size not in res:
res[size] = {} res[size] = {}
@@ -40,18 +93,20 @@ def build_header(headers):
return res return res
def gen_enum(): def gen_enum():
print '''\ name = ''
typedef enum {''' print 'typedef enum {'
for k in sorted(HEADERS): for k, token in HEADERS:
print '''\ if token is None:
{},'''.format(to_enum_hd(k)) print ' {},'.format(to_enum_hd(k))
print '''\ else:
NGHTTP2_TOKEN_MAXIDX, if name != k:
} nghttp2_token;''' name = k
print ' {} = {},'.format(to_enum_hd(k), token)
print '} nghttp2_token;'
def gen_index_header(): def gen_index_header():
print '''\ print '''\
static int lookup_token(const uint8_t *name, size_t namelen) { static inline int lookup_token(const uint8_t *name, size_t namelen) {
switch (namelen) {''' switch (namelen) {'''
b = build_header(HEADERS) b = build_header(HEADERS)
for size in sorted(b.keys()): for size in sorted(b.keys()):
@@ -59,14 +114,14 @@ static int lookup_token(const uint8_t *name, size_t namelen) {
print '''\ print '''\
case {}:'''.format(size) case {}:'''.format(size)
print '''\ print '''\
switch (name[namelen - 1]) {''' switch (name[{}]) {{'''.format(size - 1)
for c in sorted(ents.keys()): for c in sorted(ents.keys()):
headers = sorted(ents[c]) headers = sorted(ents[c])
print '''\ print '''\
case '{}':'''.format(c) case '{}':'''.format(c)
for k in headers: for k in headers:
print '''\ print '''\
if (streq("{}", name, {})) {{ if (lstreq("{}", name, {})) {{
return {}; return {};
}}'''.format(k[:-1], size - 1, to_enum_hd(k)) }}'''.format(k[:-1], size - 1, to_enum_hd(k))
print '''\ print '''\

53
genmethodfunc.py Executable file
View File

@@ -0,0 +1,53 @@
#!/usr/bin/env python
from __future__ import unicode_literals
from io import StringIO
from gentokenlookup import gentokenlookup
# copied from http-parser/http_parser.h, and stripped trailing spaces
# and backslashes.
SRC = '''
XX(0, DELETE, DELETE)
XX(1, GET, GET)
XX(2, HEAD, HEAD)
XX(3, POST, POST)
XX(4, PUT, PUT)
/* pathological */
XX(5, CONNECT, CONNECT)
XX(6, OPTIONS, OPTIONS)
XX(7, TRACE, TRACE)
/* webdav */
XX(8, COPY, COPY)
XX(9, LOCK, LOCK)
XX(10, MKCOL, MKCOL)
XX(11, MOVE, MOVE)
XX(12, PROPFIND, PROPFIND)
XX(13, PROPPATCH, PROPPATCH)
XX(14, SEARCH, SEARCH)
XX(15, UNLOCK, UNLOCK)
/* subversion */
XX(16, REPORT, REPORT)
XX(17, MKACTIVITY, MKACTIVITY)
XX(18, CHECKOUT, CHECKOUT)
XX(19, MERGE, MERGE)
/* upnp */
XX(20, MSEARCH, M-SEARCH)
XX(21, NOTIFY, NOTIFY)
XX(22, SUBSCRIBE, SUBSCRIBE)
XX(23, UNSUBSCRIBE, UNSUBSCRIBE)
/* RFC-5789 */
XX(24, PATCH, PATCH)
XX(25, PURGE, PURGE)
/* CalDAV */
XX(26, MKCALENDAR, MKCALENDAR)
'''
if __name__ == '__main__':
methods = []
for line in StringIO(SRC):
line = line.strip()
if not line.startswith('XX'):
continue
_, m, _ = line.split(',', 2)
methods.append(m.strip())
gentokenlookup(methods, 'HTTP')

69
gentokenlookup.py Normal file
View File

@@ -0,0 +1,69 @@
#!/usr/bin/env python
def to_enum_hd(k, prefix):
res = prefix + '_'
for c in k.upper():
if c == ':' or c == '-':
res += '_'
continue
res += c
return res
def build_header(headers):
res = {}
for k in headers:
size = len(k)
if size not in res:
res[size] = {}
ent = res[size]
c = k[-1]
if c not in ent:
ent[c] = []
ent[c].append(k)
return res
def gen_enum(tokens, prefix):
print '''\
enum {'''
for k in sorted(tokens):
print '''\
{},'''.format(to_enum_hd(k, prefix))
print '''\
{}_MAXIDX,
}};'''.format(prefix)
def gen_index_header(tokens, prefix):
print '''\
int lookup_token(const uint8_t *name, size_t namelen) {
switch (namelen) {'''
b = build_header(tokens)
for size in sorted(b.keys()):
ents = b[size]
print '''\
case {}:'''.format(size)
print '''\
switch (name[{}]) {{'''.format(size - 1)
for c in sorted(ents.keys()):
headers = sorted(ents[c])
print '''\
case '{}':'''.format(c)
for k in headers:
print '''\
if (util::streq_l("{}", name, {})) {{
return {};
}}'''.format(k[:-1], size - 1, to_enum_hd(k, prefix))
print '''\
break;'''
print '''\
}
break;'''
print '''\
}
return -1;
}'''
def gentokenlookup(tokens, prefix):
gen_enum(tokens, prefix)
print ''
gen_index_header(tokens, prefix)

View File

@@ -4,6 +4,7 @@
# script to produce rst file from program's help output. # script to produce rst file from program's help output.
from __future__ import unicode_literals from __future__ import unicode_literals
from __future__ import print_function
import sys import sys
import re import re
import argparse import argparse
@@ -44,8 +45,8 @@ def help2man(infile):
line = infile.readline().strip() line = infile.readline().strip()
m = re.match(r'^Usage: (.*)', line) m = re.match(r'^Usage: (.*)', line)
if not m: if not m:
print 'usage line is invalid. Expected following lines:' print('usage line is invalid. Expected following lines:')
print 'Usage: cmdname ...' print('Usage: cmdname ...')
sys.exit(1) sys.exit(1)
synopsis = m.group(1).split(' ', 1) synopsis = m.group(1).split(' ', 1)
if len(synopsis) == 2: if len(synopsis) == 2:
@@ -60,7 +61,11 @@ def help2man(infile):
break break
description.append(line) description.append(line)
print ''' print('''
.. GENERATED by help2rst.py. DO NOT EDIT DIRECTLY.
.. program:: {cmdname}
{cmdname}(1) {cmdname}(1)
{cmdnameunderline} {cmdnameunderline}
@@ -75,39 +80,48 @@ DESCRIPTION
{description} {description}
'''.format(cmdname=cmdname, args=args, '''.format(cmdname=cmdname, args=args,
cmdnameunderline='=' * (len(cmdname) + 3), cmdnameunderline='=' * (len(cmdname) + 3),
synopsis=synopsis, description=format_text('\n'.join(description))) synopsis=synopsis, description=format_text('\n'.join(description))))
in_arg = False in_arg = False
in_footer = False
for line in infile: for line in infile:
line = line.rstrip() line = line.rstrip()
if not line.strip() and in_arg: if not line.strip() and in_arg:
print '' print()
continue continue
if line.startswith(' ') and in_arg: if line.startswith(' ') and in_arg:
if not line.startswith(arg_indent): if not line.startswith(arg_indent):
sys.stderr.write('warning: argument description is not indented correctly. We need {} spaces as indentation.\n'.format(len(arg_indent))) sys.stderr.write('warning: argument description is not indented correctly. We need {} spaces as indentation.\n'.format(len(arg_indent)))
print '{}'.format(format_arg_text(line[len(arg_indent):])) print('{}'.format(format_arg_text(line[len(arg_indent):])))
continue continue
if in_arg: if in_arg:
print '' print()
in_arg = False in_arg = False
if line == '--':
in_footer = True
continue
if in_footer:
print(line.strip())
continue
if line == 'Options:': if line == 'Options:':
print 'OPTIONS' print('OPTIONS')
print '-------' print('-------')
print '' print()
continue continue
if line.startswith(' <'): if line.startswith(' <'):
# positional argument # positional argument
m = re.match(r'^(?:\s+)([a-zA-Z0-9-_<>]+)(.*)', line) m = re.match(r'^(?:\s+)([a-zA-Z0-9-_<>]+)(.*)', line)
argname, rest = m.group(1), m.group(2) argname, rest = m.group(1), m.group(2)
print '.. describe:: {}'.format(argname) print('.. describe:: {}'.format(argname))
print '' print()
print '{}'.format(format_arg_text(rest.strip())) print('{}'.format(format_arg_text(rest.strip())))
in_arg = True in_arg = True
continue continue
@@ -115,9 +129,9 @@ DESCRIPTION
# positional argument # positional argument
m = re.match(r'^(?:\s+)(\([a-zA-Z0-9-_<> ]+\))(.*)', line) m = re.match(r'^(?:\s+)(\([a-zA-Z0-9-_<> ]+\))(.*)', line)
argname, rest = m.group(1), m.group(2) argname, rest = m.group(1), m.group(2)
print '.. describe:: {}'.format(argname) print('.. describe:: {}'.format(argname))
print '' print()
print '{}'.format(format_arg_text(rest.strip())) print('{}'.format(format_arg_text(rest.strip())))
in_arg = True in_arg = True
continue continue
@@ -127,23 +141,23 @@ DESCRIPTION
r'^(?:\s+)(-\S+?(?:, -\S+?)*)($| .*)', r'^(?:\s+)(-\S+?(?:, -\S+?)*)($| .*)',
line) line)
argname, rest = m.group(1), m.group(2) argname, rest = m.group(1), m.group(2)
print '.. option:: {}'.format(argname) print('.. option:: {}'.format(argname))
print '' print()
rest = rest.strip() rest = rest.strip()
if len(rest): if len(rest):
print '{}'.format(format_arg_text(rest)) print('{}'.format(format_arg_text(rest)))
in_arg = True in_arg = True
continue continue
if not line.startswith(' ') and line.endswith(':'): if not line.startswith(' ') and line.endswith(':'):
# subsection # subsection
subsec = line.strip()[:-1] subsec = line.strip()[:-1]
print '{}'.format(subsec) print('{}'.format(subsec))
print '{}'.format('~' * len(subsec)) print('{}'.format('~' * len(subsec)))
print '' print()
continue continue
print line.strip() print(line.strip())
def format_text(text): def format_text(text):
# escape * # escape *
@@ -173,6 +187,6 @@ if __name__ == '__main__':
args = parser.parse_args() args = parser.parse_args()
help2man(sys.stdin) help2man(sys.stdin)
if args.include: if args.include:
print '' print()
with open(args.include) as f: with open(args.include) as f:
sys.stdout.write(f.read()) sys.stdout.write(f.read())

2
integration-tests/.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
# generated files
config.go

View File

@@ -37,7 +37,8 @@ EXTRA_DIST = \
itprep: itprep:
go get -d -v github.com/bradfitz/http2 go get -d -v github.com/bradfitz/http2
go get -d -v github.com/tatsuhiro-t/go-nghttp2 go get -d -v github.com/tatsuhiro-t/go-nghttp2
go get -d -v golang.org/x/net/spdy go get -d -v github.com/tatsuhiro-t/spdy
go get -d -v golang.org/x/net/websocket
it: it:
sh setenv go test -v sh setenv go test -v

View File

@@ -2,8 +2,10 @@ package nghttp2
import ( import (
"bufio" "bufio"
"bytes"
"fmt" "fmt"
"github.com/bradfitz/http2/hpack" "github.com/bradfitz/http2/hpack"
"golang.org/x/net/websocket"
"io" "io"
"net/http" "net/http"
"syscall" "syscall"
@@ -50,6 +52,27 @@ func TestH1H1PlainGETClose(t *testing.T) {
} }
} }
// TestH1H1InvalidMethod tests that server rejects invalid method with
// 501 status code
func TestH1H1InvalidMethod(t *testing.T) {
st := newServerTester(nil, t, func(w http.ResponseWriter, r *http.Request) {
t.Errorf("server should not forward this request")
})
defer st.Close()
res, err := st.http1(requestParam{
name: "TestH1H1InvalidMethod",
method: "get",
})
if err != nil {
t.Fatalf("Error st.http1() = %v", err)
}
if got, want := res.status, 501; got != want {
t.Errorf("status = %v; want %v", got, want)
}
}
// TestH1H1MultipleRequestCL tests that server rejects request which // TestH1H1MultipleRequestCL tests that server rejects request which
// contains multiple Content-Length header fields. // contains multiple Content-Length header fields.
func TestH1H1MultipleRequestCL(t *testing.T) { func TestH1H1MultipleRequestCL(t *testing.T) {
@@ -246,6 +269,92 @@ func TestH1H1RequestTrailer(t *testing.T) {
} }
} }
// TestH1H1HeaderFieldBufferPath tests that request with request path
// larger than configured buffer size is rejected.
func TestH1H1HeaderFieldBufferPath(t *testing.T) {
// The value 100 is chosen so that sum of header fields bytes
// does not exceed it. We use > 100 bytes URI to exceed this
// limit.
st := newServerTester([]string{"--header-field-buffer=100"}, t, func(w http.ResponseWriter, r *http.Request) {
t.Fatal("execution path should not be here")
})
defer st.Close()
res, err := st.http1(requestParam{
name: "TestH1H1HeaderFieldBufferPath",
path: "/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
})
if err != nil {
t.Fatalf("Error st.http1() = %v", err)
}
if got, want := res.status, 431; got != want {
t.Errorf("status: %v; want %v", got, want)
}
}
// TestH1H1HeaderFieldBuffer tests that request with header fields
// larger than configured buffer size is rejected.
func TestH1H1HeaderFieldBuffer(t *testing.T) {
st := newServerTester([]string{"--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.http1(requestParam{
name: "TestH1H1HeaderFieldBuffer",
})
if err != nil {
t.Fatalf("Error st.http1() = %v", err)
}
if got, want := res.status, 431; got != want {
t.Errorf("status: %v; want %v", got, want)
}
}
// TestH1H1HeaderFields tests that request with header fields more
// than configured number is rejected.
func TestH1H1HeaderFields(t *testing.T) {
st := newServerTester([]string{"--max-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.http1(requestParam{
name: "TestH1H1HeaderFields",
header: []hpack.HeaderField{
// Add extra header field to ensure that
// header field limit exceeds
pair("Connection", "close"),
},
})
if err != nil {
t.Fatalf("Error st.http1() = %v", err)
}
if got, want := res.status, 431; got != want {
t.Errorf("status: %v; want %v", got, want)
}
}
// TestH1H1Websocket tests that HTTP Upgrade to WebSocket works.
func TestH1H1Websocket(t *testing.T) {
st := newServerTesterHandler(nil, t, websocket.Handler(func(ws *websocket.Conn) {
io.Copy(ws, ws)
}))
defer st.Close()
content := []byte("hello world")
res, err := st.websocket(requestParam{
name: "TestH1H1Websocket",
body: content,
})
if err != nil {
t.Fatalf("Error st.websocket() = %v", err)
}
if got, want := res.body, content; !bytes.Equal(got, want) {
t.Errorf("echo: %q; want %q", got, want)
}
}
// TestH1H2ConnectFailure tests that server handles the situation that // TestH1H2ConnectFailure tests that server handles the situation that
// connection attempt to HTTP/2 backend failed. // connection attempt to HTTP/2 backend failed.
func TestH1H2ConnectFailure(t *testing.T) { func TestH1H2ConnectFailure(t *testing.T) {

View File

@@ -8,6 +8,7 @@ import (
"io" "io"
"io/ioutil" "io/ioutil"
"net/http" "net/http"
"strings"
"syscall" "syscall"
"testing" "testing"
) )
@@ -403,6 +404,26 @@ func TestH2H1ConnectFailure(t *testing.T) {
} }
} }
// TestH2H1InvalidMethod tests that server rejects invalid method with
// 501.
func TestH2H1InvalidMethod(t *testing.T) {
st := newServerTester(nil, t, func(w http.ResponseWriter, r *http.Request) {
t.Errorf("server should not forward this request")
})
defer st.Close()
res, err := st.http2(requestParam{
name: "TestH2H1InvalidMethod",
method: "get",
})
if err != nil {
t.Fatalf("Error st.http2() = %v", err)
}
if got, want := res.status, 501; got != want {
t.Errorf("status: %v; want %v", got, want)
}
}
// TestH2H1AssembleCookies tests that crumbled cookies in HTTP/2 // TestH2H1AssembleCookies tests that crumbled cookies in HTTP/2
// request is assembled into 1 when forwarding to HTTP/1 backend link. // request is assembled into 1 when forwarding to HTTP/1 backend link.
func TestH2H1AssembleCookies(t *testing.T) { func TestH2H1AssembleCookies(t *testing.T) {
@@ -489,12 +510,36 @@ func TestH2H1SNI(t *testing.T) {
} }
} }
// TestH2H1TLSXfp tests nghttpx sends x-forwarded-proto header field
// with http value since :scheme is http, even if the frontend
// connection is encrypted.
func TestH2H1TLSXfp(t *testing.T) {
st := newServerTesterTLS(nil, t, func(w http.ResponseWriter, r *http.Request) {
if got, want := r.Header.Get("x-forwarded-proto"), "http"; got != want {
t.Errorf("x-forwarded-proto: want %v; got %v", want, got)
}
})
defer st.Close()
res, err := st.http2(requestParam{
name: "TestH2H1TLSXfp",
})
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)
}
}
// TestH2H1ServerPush tests server push using Link header field from // TestH2H1ServerPush tests server push using Link header field from
// backend server. // backend server.
func TestH2H1ServerPush(t *testing.T) { func TestH2H1ServerPush(t *testing.T) {
st := newServerTester(nil, t, func(w http.ResponseWriter, r *http.Request) { st := newServerTester(nil, t, func(w http.ResponseWriter, r *http.Request) {
// only resources marked as rel=preload are pushed // only resources marked as rel=preload are pushed
w.Header().Add("Link", "</css/main.css>; rel=preload, </foo>, </css/theme.css>; rel=preload") if !strings.HasPrefix(r.URL.Path, "/css/") {
w.Header().Add("Link", "</css/main.css>; rel=preload, </foo>, </css/theme.css>; rel=preload")
}
}) })
defer st.Close() defer st.Close()
@@ -555,6 +600,79 @@ func TestH2H1RequestTrailer(t *testing.T) {
} }
} }
// TestH2H1HeaderFieldBuffer tests that request with header fields
// larger than configured buffer size is rejected.
func TestH2H1HeaderFieldBuffer(t *testing.T) {
st := newServerTester([]string{"--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.http2(requestParam{
name: "TestH2H1HeaderFieldBuffer",
})
if err != nil {
t.Fatalf("Error st.http2() = %v", err)
}
if got, want := res.status, 431; got != want {
t.Errorf("status: %v; want %v", got, want)
}
}
// TestH2H1HeaderFields tests that request with header fields more
// than configured number is rejected.
func TestH2H1HeaderFields(t *testing.T) {
st := newServerTester([]string{"--max-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.http2(requestParam{
name: "TestH2H1HeaderFields",
// we have at least 4 pseudo-header fields sent, and
// that ensures that buffer limit exceeds.
})
if err != nil {
t.Fatalf("Error st.http2() = %v", err)
}
if got, want := res.status, 431; got != want {
t.Errorf("status: %v; want %v", got, want)
}
}
// TestH2H1Upgrade tests HTTP Upgrade to HTTP/2
func TestH2H1Upgrade(t *testing.T) {
st := newServerTester(nil, t, func(w http.ResponseWriter, r *http.Request) {})
defer st.Close()
res, err := st.http1(requestParam{
name: "TestH2H1Upgrade",
header: []hpack.HeaderField{
pair("Connection", "Upgrade, HTTP2-Settings"),
pair("Upgrade", "h2c"),
pair("HTTP2-Settings", "AAMAAABkAAQAAP__"),
},
})
if err != nil {
t.Fatalf("Error st.http1() = %v", err)
}
if got, want := res.status, 101; got != want {
t.Errorf("res.status: %v; want %v", got, want)
}
res, err = st.http2(requestParam{
httpUpgrade: true,
})
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)
}
}
// TestH2H1GracefulShutdown tests graceful shutdown. // TestH2H1GracefulShutdown tests graceful shutdown.
func TestH2H1GracefulShutdown(t *testing.T) { func TestH2H1GracefulShutdown(t *testing.T) {
st := newServerTester(nil, t, noopHandler) st := newServerTester(nil, t, noopHandler)
@@ -735,3 +853,25 @@ func TestH2H2NoHostRewrite(t *testing.T) {
t.Errorf("request-host: %v; want %v", got, want) t.Errorf("request-host: %v; want %v", got, want)
} }
} }
// TestH2H2TLSXfp tests nghttpx sends x-forwarded-proto header field
// with http value since :scheme is http, even if the frontend
// connection is encrypted.
func TestH2H2TLSXfp(t *testing.T) {
st := newServerTesterTLS([]string{"--http2-bridge"}, t, func(w http.ResponseWriter, r *http.Request) {
if got, want := r.Header.Get("x-forwarded-proto"), "http"; got != want {
t.Errorf("x-forwarded-proto: want %v; got %v", want, got)
}
})
defer st.Close()
res, err := st.http2(requestParam{
name: "TestH2H2TLSXfp",
})
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)
}
}

View File

@@ -2,7 +2,7 @@ package nghttp2
import ( import (
"github.com/bradfitz/http2/hpack" "github.com/bradfitz/http2/hpack"
"golang.org/x/net/spdy" "github.com/tatsuhiro-t/spdy"
"net/http" "net/http"
"testing" "testing"
) )
@@ -170,6 +170,66 @@ func TestS3H1NoVia(t *testing.T) {
} }
} }
// 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", "--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-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)
}
}
// TestS3H2ConnectFailure tests that server handles the situation that // TestS3H2ConnectFailure tests that server handles the situation that
// connection attempt to HTTP/2 backend failed. // connection attempt to HTTP/2 backend failed.
func TestS3H2ConnectFailure(t *testing.T) { func TestS3H2ConnectFailure(t *testing.T) {

View File

@@ -9,7 +9,8 @@ import (
"github.com/bradfitz/http2" "github.com/bradfitz/http2"
"github.com/bradfitz/http2/hpack" "github.com/bradfitz/http2/hpack"
"github.com/tatsuhiro-t/go-nghttp2" "github.com/tatsuhiro-t/go-nghttp2"
"golang.org/x/net/spdy" "github.com/tatsuhiro-t/spdy"
"golang.org/x/net/websocket"
"io" "io"
"io/ioutil" "io/ioutil"
"net" "net"
@@ -66,6 +67,10 @@ func newServerTester(args []string, t *testing.T, handler http.HandlerFunc) *ser
return newServerTesterInternal(args, t, handler, false, nil) return newServerTesterInternal(args, t, handler, false, nil)
} }
func newServerTesterHandler(args []string, t *testing.T, handler http.Handler) *serverTester {
return newServerTesterInternal(args, t, handler, false, nil)
}
// newServerTester creates test context for TLS frontend connection. // newServerTester creates test context for TLS frontend connection.
func newServerTesterTLS(args []string, t *testing.T, handler http.HandlerFunc) *serverTester { func newServerTesterTLS(args []string, t *testing.T, handler http.HandlerFunc) *serverTester {
return newServerTesterInternal(args, t, handler, true, nil) return newServerTesterInternal(args, t, handler, true, nil)
@@ -79,7 +84,7 @@ func newServerTesterTLSConfig(args []string, t *testing.T, handler http.HandlerF
// newServerTesterInternal creates test context. If frontendTLS is // newServerTesterInternal creates test context. If frontendTLS is
// true, set up TLS frontend connection. // true, set up TLS frontend connection.
func newServerTesterInternal(args []string, t *testing.T, handler http.HandlerFunc, frontendTLS bool, clientConfig *tls.Config) *serverTester { func newServerTesterInternal(args []string, t *testing.T, handler http.Handler, frontendTLS bool, clientConfig *tls.Config) *serverTester {
ts := httptest.NewUnstartedServer(handler) ts := httptest.NewUnstartedServer(handler)
backendTLS := false backendTLS := false
@@ -247,15 +252,16 @@ func (st *serverTester) readSpdyFrame() (spdy.Frame, error) {
} }
type requestParam struct { type requestParam struct {
name string // name for this request to identify the request in log easily name string // name for this request to identify the request in log easily
streamID uint32 // stream ID, automatically assigned if 0 streamID uint32 // stream ID, automatically assigned if 0
method string // method, defaults to GET method string // method, defaults to GET
scheme string // scheme, defaults to http scheme string // scheme, defaults to http
authority string // authority, defaults to backend server address authority string // authority, defaults to backend server address
path string // path, defaults to / path string // path, defaults to /
header []hpack.HeaderField // additional request header fields header []hpack.HeaderField // additional request header fields
body []byte // request body body []byte // request body
trailer []hpack.HeaderField // trailer part trailer []hpack.HeaderField // trailer part
httpUpgrade bool // true if upgraded to HTTP/2 through HTTP Upgrade
} }
// wrapper for request body to set trailer part // wrapper for request body to set trailer part
@@ -278,6 +284,41 @@ func (cbr *chunkedBodyReader) Read(p []byte) (n int, err error) {
return cbr.body.Read(p) return cbr.body.Read(p)
} }
func (st *serverTester) websocket(rp requestParam) (*serverResponse, error) {
urlstring := st.url + "/echo"
config, err := websocket.NewConfig(urlstring, st.url)
if err != nil {
st.t.Fatalf("websocket.NewConfig(%q, %q) returned error: %v", urlstring, st.url, err)
}
config.Header.Add("Test-Case", rp.name)
for _, h := range rp.header {
config.Header.Add(h.Name, h.Value)
}
ws, err := websocket.NewClient(config, st.conn)
if err != nil {
st.t.Fatalf("Error creating websocket client: %v", err)
}
if _, err := ws.Write(rp.body); err != nil {
st.t.Fatalf("ws.Write() returned error: %v", err)
}
msg := make([]byte, 1024)
var n int
if n, err = ws.Read(msg); err != nil {
st.t.Fatalf("ws.Read() returned error: %v", err)
}
res := &serverResponse{
body: msg[:n],
}
return res, nil
}
func (st *serverTester) http1(rp requestParam) (*serverResponse, error) { func (st *serverTester) http1(rp requestParam) (*serverResponse, error) {
method := "GET" method := "GET"
if rp.method != "" { if rp.method != "" {
@@ -296,7 +337,19 @@ func (st *serverTester) http1(rp requestParam) (*serverResponse, error) {
body = cbr body = cbr
} }
} }
req, err := http.NewRequest(method, st.url, body)
reqURL := st.url
if rp.path != "" {
u, err := url.Parse(st.url)
if err != nil {
st.t.Fatalf("Error parsing URL from st.url %v: %v", st.url, err)
}
u.Path = rp.path
reqURL = u.String()
}
req, err := http.NewRequest(method, reqURL, body)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -478,69 +531,70 @@ func (st *serverTester) http2(rp requestParam) (*serverResponse, error) {
streams := make(map[uint32]*serverResponse) streams := make(map[uint32]*serverResponse)
streams[id] = res streams[id] = res
method := "GET" if !rp.httpUpgrade {
if rp.method != "" { method := "GET"
method = rp.method if rp.method != "" {
} method = rp.method
_ = st.enc.WriteField(pair(":method", method))
scheme := "http"
if rp.scheme != "" {
scheme = rp.scheme
}
_ = st.enc.WriteField(pair(":scheme", scheme))
authority := st.authority
if rp.authority != "" {
authority = rp.authority
}
_ = st.enc.WriteField(pair(":authority", authority))
path := "/"
if rp.path != "" {
path = rp.path
}
_ = st.enc.WriteField(pair(":path", path))
_ = st.enc.WriteField(pair("test-case", rp.name))
for _, h := range rp.header {
_ = st.enc.WriteField(h)
}
err := st.fr.WriteHeaders(http2.HeadersFrameParam{
StreamID: id,
EndStream: len(rp.body) == 0 && len(rp.trailer) == 0,
EndHeaders: true,
BlockFragment: st.headerBlkBuf.Bytes(),
})
if err != nil {
return nil, err
}
if len(rp.body) != 0 {
// TODO we assume rp.body fits in 1 frame
if err := st.fr.WriteData(id, len(rp.trailer) == 0, rp.body); err != nil {
return nil, err
} }
} _ = st.enc.WriteField(pair(":method", method))
if len(rp.trailer) != 0 { scheme := "http"
st.headerBlkBuf.Reset() if rp.scheme != "" {
for _, h := range rp.trailer { scheme = rp.scheme
}
_ = st.enc.WriteField(pair(":scheme", scheme))
authority := st.authority
if rp.authority != "" {
authority = rp.authority
}
_ = st.enc.WriteField(pair(":authority", authority))
path := "/"
if rp.path != "" {
path = rp.path
}
_ = st.enc.WriteField(pair(":path", path))
_ = st.enc.WriteField(pair("test-case", rp.name))
for _, h := range rp.header {
_ = st.enc.WriteField(h) _ = st.enc.WriteField(h)
} }
err := st.fr.WriteHeaders(http2.HeadersFrameParam{ err := st.fr.WriteHeaders(http2.HeadersFrameParam{
StreamID: id, StreamID: id,
EndStream: true, EndStream: len(rp.body) == 0 && len(rp.trailer) == 0,
EndHeaders: true, EndHeaders: true,
BlockFragment: st.headerBlkBuf.Bytes(), BlockFragment: st.headerBlkBuf.Bytes(),
}) })
if err != nil { if err != nil {
return nil, err return nil, err
} }
}
if len(rp.body) != 0 {
// TODO we assume rp.body fits in 1 frame
if err := st.fr.WriteData(id, len(rp.trailer) == 0, rp.body); err != nil {
return nil, err
}
}
if len(rp.trailer) != 0 {
st.headerBlkBuf.Reset()
for _, h := range rp.trailer {
_ = st.enc.WriteField(h)
}
err := st.fr.WriteHeaders(http2.HeadersFrameParam{
StreamID: id,
EndStream: true,
EndHeaders: true,
BlockFragment: st.headerBlkBuf.Bytes(),
})
if err != nil {
return nil, err
}
}
}
loop: loop:
for { for {
fr, err := st.readFrame() fr, err := st.readFrame()

3
lib/.gitignore vendored Normal file
View File

@@ -0,0 +1,3 @@
# generated files
includes/nghttp2/nghttp2ver.h
libnghttp2.pc

View File

@@ -25,7 +25,8 @@ SUBDIRS = includes
EXTRA_DIST = Makefile.msvc EXTRA_DIST = Makefile.msvc
AM_CFLAGS = $(WARNCFLAGS) AM_CFLAGS = $(WARNCFLAGS)
AM_CPPFLAGS = -I$(srcdir)/includes -I$(builddir)/includes @DEFS@ AM_CPPFLAGS = -I$(srcdir)/includes -I$(builddir)/includes -DBUILDING_NGHTTP2 \
@DEFS@
pkgconfigdir = $(libdir)/pkgconfig pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = libnghttp2.pc pkgconfig_DATA = libnghttp2.pc

View File

@@ -2,15 +2,14 @@
# GNU Makefile for nghttp2 / MSVC. # GNU Makefile for nghttp2 / MSVC.
# #
# By G. Vanem <gvanem@yahoo.no> 2013 # By G. Vanem <gvanem@yahoo.no> 2013
# Updated 3/2015 by Remo Eichenberger @remoe
# The MIT License apply. # The MIT License apply.
# #
# #
# Choose your weapons: # Choose your weapons:
# Set 'ZLIB_ROOT' to the root of zlib.
# Set 'USE_CYTHON=1' to build and install the 'nghttp2.pyd' Python extension. # Set 'USE_CYTHON=1' to build and install the 'nghttp2.pyd' Python extension.
# #
ZLIB_ROOT = g:/MingW32/src/Compression/zlib-1.2.8
USE_CYTHON = 1 USE_CYTHON = 1
_VERSION := $(shell grep AC_INIT ../configure.ac | cut -d'[' -f3 | sed -e 's/-DEV], //g') _VERSION := $(shell grep AC_INIT ../configure.ac | cut -d'[' -f3 | sed -e 's/-DEV], //g')
@@ -38,7 +37,7 @@ INSTALL_HDR = $(VC_ROOT)/include
TARGETS = nghttp2.lib nghttp2.dll nghttp2_imp.lib \ TARGETS = nghttp2.lib nghttp2.dll nghttp2_imp.lib \
nghttp2d.lib nghttp2d.dll nghttp2d_imp.lib nghttp2d.lib nghttp2d.dll nghttp2d_imp.lib
EXT_LIBS = $(ZLIB_ROOT)/zlib.lib ws2_32.lib EXT_LIBS =
OBJ_DIR = MSVC_obj OBJ_DIR = MSVC_obj
@@ -46,32 +45,34 @@ NGHTTP2_PDB_R = $(OBJ_DIR)/nghttp2.pdb
NGHTTP2_PDB_D = $(OBJ_DIR)/nghttp2d.pdb NGHTTP2_PDB_D = $(OBJ_DIR)/nghttp2d.pdb
CC = cl CC = cl
CFLAGS = -I./includes -I$(ZLIB_ROOT) -DHAVE_WINSOCK2_H -Dssize_t=long CFLAGS = -I./includes -Dssize_t=long -D_U_=""
CFLAGS_R = -nologo -MD -W3 -Zi -Fd./$(NGHTTP2_PDB_R) CFLAGS_R = -nologo -MD -W3 -Zi -Fd./$(NGHTTP2_PDB_R)
CFLAGS_D = -nologo -MDd -W3 -Zi -Fd./$(NGHTTP2_PDB_D) \ CFLAGS_D = -nologo -MDd -W3 -Zi -Fd./$(NGHTTP2_PDB_D) \
-Ot -D_DEBUG -GF -RTCs -RTCu # -RTCc -GS -Ot -D_DEBUG -GF -RTCs -RTCu # -RTCc -GS
LDFLAGS = -nologo -machine:i386 -map -debug -incremental:no # -verbose LDFLAGS = -nologo -machine:x64 -map -debug -incremental:no # -verbose
NGHTTP2_SRC = nghttp2_buf.c \ NGHTTP2_SRC = nghttp2_pq.c \
nghttp2_callbacks.c \ nghttp2_map.c \
nghttp2_frame.c \ nghttp2_queue.c \
nghttp2_helper.c \ nghttp2_frame.c \
nghttp2_hd.c \ nghttp2_buf.c \
nghttp2_hd_huffman.c \ nghttp2_stream.c \
nghttp2_hd_huffman_data.c \ nghttp2_outbound_item.c \
nghttp2_map.c \ nghttp2_session.c \
nghttp2_npn.c \ nghttp2_submit.c \
nghttp2_option.c \ nghttp2_helper.c \
nghttp2_outbound_item.c \ nghttp2_npn.c \
nghttp2_priority_spec.c \ nghttp2_hd.c \
nghttp2_pq.c \ nghttp2_hd_huffman.c \
nghttp2_queue.c \ nghttp2_hd_huffman_data.c \
nghttp2_session.c \ nghttp2_version.c \
nghttp2_stream.c \ nghttp2_priority_spec.c \
nghttp2_submit.c \ nghttp2_option.c \
nghttp2_version.c nghttp2_callbacks.c \
nghttp2_mem.c \
nghttp2_http.c
NGHTTP2_OBJ_R = $(addprefix $(OBJ_DIR)/r_, $(notdir $(NGHTTP2_SRC:.c=.obj))) NGHTTP2_OBJ_R = $(addprefix $(OBJ_DIR)/r_, $(notdir $(NGHTTP2_SRC:.c=.obj)))
NGHTTP2_OBJ_D = $(addprefix $(OBJ_DIR)/d_, $(notdir $(NGHTTP2_SRC:.c=.obj))) NGHTTP2_OBJ_D = $(addprefix $(OBJ_DIR)/d_, $(notdir $(NGHTTP2_SRC:.c=.obj)))
@@ -116,13 +117,13 @@ nghttp2d.lib: $(NGHTTP2_OBJ_D)
lib -nologo -out:$@ $^ lib -nologo -out:$@ $^
@echo @echo
nghttp2.dll nghttp2_imp.lib: $(NGHTTP2_OBJ_R) $(OBJ_DIR)/r_nghttp2.res $(OBJ_DIR)/r_nghttp2.def nghttp2.dll nghttp2_imp.lib: $(NGHTTP2_OBJ_R) $(OBJ_DIR)/r_nghttp2.res
link $(LDFLAGS) -dll -out:nghttp2.dll -implib:nghttp2_imp.lib -def:$(OBJ_DIR)/r_nghttp2.def \ link $(LDFLAGS) -dll -out:nghttp2.dll -implib:nghttp2_imp.lib \
$(NGHTTP2_OBJ_R) $(OBJ_DIR)/r_nghttp2.res $(EXT_LIBS) $(NGHTTP2_OBJ_R) $(OBJ_DIR)/r_nghttp2.res $(EXT_LIBS)
@echo @echo
nghttp2d.dll nghttp2d_imp.lib: $(NGHTTP2_OBJ_D) $(OBJ_DIR)/d_nghttp2.res $(OBJ_DIR)/d_nghttp2.def nghttp2d.dll nghttp2d_imp.lib: $(NGHTTP2_OBJ_D) $(OBJ_DIR)/d_nghttp2.res
link $(LDFLAGS) -dll -out:nghttp2d.dll -implib:nghttp2d_imp.lib -def:$(OBJ_DIR)/d_nghttp2.def \ link $(LDFLAGS) -dll -out:nghttp2d.dll -implib:nghttp2d_imp.lib \
$(NGHTTP2_OBJ_D) $(OBJ_DIR)/d_nghttp2.res $(EXT_LIBS) $(NGHTTP2_OBJ_D) $(OBJ_DIR)/d_nghttp2.res $(EXT_LIBS)
@echo @echo
@@ -219,24 +220,6 @@ nghttp2.rc: Makefile.MSVC
@echo ' */' >> $@ @echo ' */' >> $@
@echo "$$RES_FILE" >> $@ @echo "$$RES_FILE" >> $@
$(OBJ_DIR)/r_nghttp2.def: Makefile.MSVC
@echo 'Generating $@...'
@echo '; $(GENERATED). DO NOT EDIT.' > $@
@echo ';' >> $@
@echo 'LIBRARY nghttp2.dll' >> $@
@echo 'EXPORTS' >> $@
nm $(NGHTTP2_OBJ_R) | grep ' T .*_nghttp2' | sed 's/^.* _/ /' >> $@
@echo 'NGHTTP2_STATIC_TABLE_LENGTH DATA' >> $@
$(OBJ_DIR)/d_nghttp2.def: Makefile.MSVC
@echo 'Generating $@...'
@echo '; $(GENERATED). DO NOT EDIT.' > $@
@echo ';' >> $@
@echo 'LIBRARY nghttp2d.dll' >> $@
@echo 'EXPORTS' >> $@
nm $(NGHTTP2_OBJ_D) | grep ' T .*_nghttp2' | sed 's/^.* _/ /' >> $@
@echo 'NGHTTP2_STATIC_TABLE_LENGTH DATA' >> $@
clean: clean:
rm -f $(OBJ_DIR)/* nghttp2_imp.exp nghttp2_imp.exp \ rm -f $(OBJ_DIR)/* nghttp2_imp.exp nghttp2_imp.exp \
nghttp2.map nghttp2d.map nghttp2.rc includes/nghttp2/nghttp2ver.h nghttp2.map nghttp2d.map nghttp2.rc includes/nghttp2/nghttp2ver.h
@@ -263,4 +246,4 @@ depend: includes/nghttp2/nghttp2ver.h
sed -e $(REPLACE_D) .depend.tmp >> .depend.MSVC sed -e $(REPLACE_D) .depend.tmp >> .depend.MSVC
rm -f .depend.tmp rm -f .depend.tmp
-include .depend.MSVC -include .depend.MSVC

File diff suppressed because it is too large Load Diff

View File

@@ -320,7 +320,7 @@ int nghttp2_bufs_add(nghttp2_bufs *bufs, const void *data, size_t len) {
} }
buf->last = nghttp2_cpymem(buf->last, p, nwrite); buf->last = nghttp2_cpymem(buf->last, p, nwrite);
p += len; p += nwrite;
len -= nwrite; len -= nwrite;
} }
@@ -410,36 +410,46 @@ ssize_t nghttp2_bufs_remove(nghttp2_bufs *bufs, uint8_t **out) {
len += nghttp2_buf_len(&chain->buf); len += nghttp2_buf_len(&chain->buf);
} }
if (!len) { if (len == 0) {
res = NULL; res = NULL;
} else { return 0;
res = nghttp2_mem_malloc(bufs->mem, len); }
if (res == NULL) { res = nghttp2_mem_malloc(bufs->mem, len);
return NGHTTP2_ERR_NOMEM; if (res == NULL) {
} return NGHTTP2_ERR_NOMEM;
} }
nghttp2_buf_wrap_init(&resbuf, res, len); nghttp2_buf_wrap_init(&resbuf, res, len);
for (chain = bufs->head; chain; chain = chain->next) { for (chain = bufs->head; chain; chain = chain->next) {
buf = &chain->buf; buf = &chain->buf;
resbuf.last = nghttp2_cpymem(resbuf.last, buf->pos, nghttp2_buf_len(buf));
if (resbuf.last) {
resbuf.last = nghttp2_cpymem(resbuf.last, buf->pos, nghttp2_buf_len(buf));
}
nghttp2_buf_reset(buf);
nghttp2_buf_shift_right(&chain->buf, bufs->offset);
} }
bufs->cur = bufs->head;
*out = res; *out = res;
return (ssize_t)len; return (ssize_t)len;
} }
size_t nghttp2_bufs_remove_copy(nghttp2_bufs *bufs, uint8_t *out) {
size_t len;
nghttp2_buf_chain *chain;
nghttp2_buf *buf;
nghttp2_buf resbuf;
len = nghttp2_bufs_len(bufs);
nghttp2_buf_wrap_init(&resbuf, out, len);
for (chain = bufs->head; chain; chain = chain->next) {
buf = &chain->buf;
resbuf.last = nghttp2_cpymem(resbuf.last, buf->pos, nghttp2_buf_len(buf));
}
return len;
}
void nghttp2_bufs_reset(nghttp2_bufs *bufs) { void nghttp2_bufs_reset(nghttp2_bufs *bufs) {
nghttp2_buf_chain *chain, *ci; nghttp2_buf_chain *chain, *ci;
size_t k; size_t k;

View File

@@ -313,9 +313,8 @@ int nghttp2_bufs_orb_hold(nghttp2_bufs *bufs, uint8_t b);
* function allocates the contagious memory to store all data in * function allocates the contagious memory to store all data in
* |bufs| and assigns it to |*out|. * |bufs| and assigns it to |*out|.
* *
* On successful return, nghttp2_bufs_len(bufs) returns 0, just like * The contents of |bufs| is left unchanged.
* after calling nghttp2_bufs_reset(). *
* This function returns the length of copied data and assigns the * This function returns the length of copied data and assigns the
* pointer to copied data to |*out| if it succeeds, or one of the * pointer to copied data to |*out| if it succeeds, or one of the
* following negative error codes: * following negative error codes:
@@ -325,6 +324,17 @@ int nghttp2_bufs_orb_hold(nghttp2_bufs *bufs, uint8_t b);
*/ */
ssize_t nghttp2_bufs_remove(nghttp2_bufs *bufs, uint8_t **out); ssize_t nghttp2_bufs_remove(nghttp2_bufs *bufs, uint8_t **out);
/*
* Copies all data stored in |bufs| to |out|. This function assumes
* that the buffer space pointed by |out| has at least
* nghttp2_bufs(bufs) bytes.
*
* The contents of |bufs| is left unchanged.
*
* This function returns the length of copied data.
*/
size_t nghttp2_bufs_remove_copy(nghttp2_bufs *bufs, uint8_t *out);
/* /*
* Resets |bufs| and makes the buffers empty. * Resets |bufs| and makes the buffers empty.
*/ */

View File

@@ -121,3 +121,9 @@ void nghttp2_session_callbacks_set_on_begin_frame_callback(
nghttp2_on_begin_frame_callback on_begin_frame_callback) { nghttp2_on_begin_frame_callback on_begin_frame_callback) {
cbs->on_begin_frame_callback = on_begin_frame_callback; cbs->on_begin_frame_callback = on_begin_frame_callback;
} }
void nghttp2_session_callbacks_set_send_data_callback(
nghttp2_session_callbacks *cbs,
nghttp2_send_data_callback send_data_callback) {
cbs->send_data_callback = send_data_callback;
}

View File

@@ -106,6 +106,7 @@ struct nghttp2_session_callbacks {
* Sets callback function invoked when a frame header is received. * Sets callback function invoked when a frame header is received.
*/ */
nghttp2_on_begin_frame_callback on_begin_frame_callback; nghttp2_on_begin_frame_callback on_begin_frame_callback;
nghttp2_send_data_callback send_data_callback;
}; };
#endif /* NGHTTP2_CALLBACKS_H */ #endif /* NGHTTP2_CALLBACKS_H */

View File

@@ -739,7 +739,8 @@ int nghttp2_nv_array_copy(nghttp2_nv **nva_ptr, const nghttp2_nv *nva,
nghttp2_nv *p; nghttp2_nv *p;
for (i = 0; i < nvlen; ++i) { for (i = 0; i < nvlen; ++i) {
buflen += nva[i].namelen + nva[i].valuelen; /* + 2 for null-termination */
buflen += nva[i].namelen + nva[i].valuelen + 2;
} }
if (nvlen == 0) { if (nvlen == 0) {
@@ -765,12 +766,14 @@ int nghttp2_nv_array_copy(nghttp2_nv **nva_ptr, const nghttp2_nv *nva,
memcpy(data, nva[i].name, nva[i].namelen); memcpy(data, nva[i].name, nva[i].namelen);
p->name = data; p->name = data;
p->namelen = nva[i].namelen; p->namelen = nva[i].namelen;
data[p->namelen] = '\0';
nghttp2_downcase(p->name, p->namelen); nghttp2_downcase(p->name, p->namelen);
data += nva[i].namelen; data += nva[i].namelen + 1;
memcpy(data, nva[i].value, nva[i].valuelen); memcpy(data, nva[i].value, nva[i].valuelen);
p->value = data; p->value = data;
p->valuelen = nva[i].valuelen; p->valuelen = nva[i].valuelen;
data += nva[i].valuelen; data[p->valuelen] = '\0';
data += nva[i].valuelen + 1;
++p; ++p;
} }
return 0; return 0;
@@ -810,7 +813,7 @@ int nghttp2_iv_check(const nghttp2_settings_entry *iv, size_t niv) {
return 1; return 1;
} }
static void frame_set_pad(nghttp2_buf *buf, size_t padlen) { static void frame_set_pad(nghttp2_buf *buf, size_t padlen, int framehd_only) {
size_t trail_padlen; size_t trail_padlen;
size_t newlen; size_t newlen;
@@ -825,6 +828,10 @@ static void frame_set_pad(nghttp2_buf *buf, size_t padlen) {
newlen = (nghttp2_get_uint32(buf->pos) >> 8) + padlen; newlen = (nghttp2_get_uint32(buf->pos) >> 8) + padlen;
nghttp2_put_uint32be(buf->pos, (uint32_t)((newlen << 8) + buf->pos[3])); nghttp2_put_uint32be(buf->pos, (uint32_t)((newlen << 8) + buf->pos[3]));
if (framehd_only) {
return;
}
trail_padlen = padlen - 1; trail_padlen = padlen - 1;
buf->pos[NGHTTP2_FRAME_HDLEN] = trail_padlen; buf->pos[NGHTTP2_FRAME_HDLEN] = trail_padlen;
@@ -833,12 +840,10 @@ static void frame_set_pad(nghttp2_buf *buf, size_t padlen) {
/* extend buffers trail_padlen bytes, since we ate previous padlen - /* extend buffers trail_padlen bytes, since we ate previous padlen -
trail_padlen byte(s) */ trail_padlen byte(s) */
buf->last += trail_padlen; buf->last += trail_padlen;
return;
} }
int nghttp2_frame_add_pad(nghttp2_bufs *bufs, nghttp2_frame_hd *hd, int nghttp2_frame_add_pad(nghttp2_bufs *bufs, nghttp2_frame_hd *hd,
size_t padlen) { size_t padlen, int framehd_only) {
nghttp2_buf *buf; nghttp2_buf *buf;
if (padlen == 0) { if (padlen == 0) {
@@ -871,7 +876,7 @@ int nghttp2_frame_add_pad(nghttp2_bufs *bufs, nghttp2_frame_hd *hd,
assert(nghttp2_buf_avail(buf) >= (ssize_t)padlen - 1); assert(nghttp2_buf_avail(buf) >= (ssize_t)padlen - 1);
frame_set_pad(buf, padlen); frame_set_pad(buf, padlen, framehd_only);
hd->length += padlen; hd->length += padlen;
hd->flags |= NGHTTP2_FLAG_PADDED; hd->flags |= NGHTTP2_FLAG_PADDED;

View File

@@ -75,7 +75,7 @@
#define NGHTTP2_MAX_PADLEN 256 #define NGHTTP2_MAX_PADLEN 256
/* Union of extension frame payload */ /* Union of extension frame payload */
typedef union { nghttp2_ext_altsvc altsvc; } nghttp2_ext_frame_payload; typedef union { int dummy; } nghttp2_ext_frame_payload;
void nghttp2_frame_pack_frame_hd(uint8_t *buf, const nghttp2_frame_hd *hd); void nghttp2_frame_pack_frame_hd(uint8_t *buf, const nghttp2_frame_hd *hd);
@@ -471,7 +471,9 @@ void nghttp2_nv_array_sort(nghttp2_nv *nva, size_t nvlen);
/* /*
* Copies name/value pairs from |nva|, which contains |nvlen| pairs, * Copies name/value pairs from |nva|, which contains |nvlen| pairs,
* to |*nva_ptr|, which is dynamically allocated so that all items can * to |*nva_ptr|, which is dynamically allocated so that all items can
* be stored. * be stored. The resultant name and value in nghttp2_nv are
* guaranteed to be NULL-terminated even if the input is not
* null-terminated.
* *
* The |*nva_ptr| must be freed using nghttp2_nv_array_del(). * The |*nva_ptr| must be freed using nghttp2_nv_array_del().
* *
@@ -508,7 +510,8 @@ int nghttp2_iv_check(const nghttp2_settings_entry *iv, size_t niv);
* Sets Pad Length field and flags and adjusts frame header position * Sets Pad Length field and flags and adjusts frame header position
* of each buffers in |bufs|. The number of padding is given in the * of each buffers in |bufs|. The number of padding is given in the
* |padlen| including Pad Length field. The |hd| is the frame header * |padlen| including Pad Length field. The |hd| is the frame header
* for the serialized data. * for the serialized data. This function fills zeros padding region
* unless framehd_only is nonzero.
* *
* This function returns 0 if it succeeds, or one of the following * This function returns 0 if it succeeds, or one of the following
* negative error codes: * negative error codes:
@@ -519,6 +522,6 @@ int nghttp2_iv_check(const nghttp2_settings_entry *iv, size_t niv);
* The length of the resulting frame is too large. * The length of the resulting frame is too large.
*/ */
int nghttp2_frame_add_pad(nghttp2_bufs *bufs, nghttp2_frame_hd *hd, int nghttp2_frame_add_pad(nghttp2_bufs *bufs, nghttp2_frame_hd *hd,
size_t padlen); size_t padlen, int framehd_only);
#endif /* NGHTTP2_FRAME_H */ #endif /* NGHTTP2_FRAME_H */

File diff suppressed because it is too large Load Diff

View File

@@ -49,7 +49,68 @@
#define NGHTTP2_HD_DEFAULT_MAX_DEFLATE_BUFFER_SIZE (1 << 12) #define NGHTTP2_HD_DEFAULT_MAX_DEFLATE_BUFFER_SIZE (1 << 12)
/* Exported for unit test */ /* Exported for unit test */
extern const size_t NGHTTP2_STATIC_TABLE_LENGTH; #define NGHTTP2_STATIC_TABLE_LENGTH 61
/* Generated by genlibtokenlookup.py */
typedef enum {
NGHTTP2_TOKEN__AUTHORITY = 0,
NGHTTP2_TOKEN__METHOD = 1,
NGHTTP2_TOKEN__PATH = 3,
NGHTTP2_TOKEN__SCHEME = 5,
NGHTTP2_TOKEN__STATUS = 7,
NGHTTP2_TOKEN_ACCEPT_CHARSET = 14,
NGHTTP2_TOKEN_ACCEPT_ENCODING = 15,
NGHTTP2_TOKEN_ACCEPT_LANGUAGE = 16,
NGHTTP2_TOKEN_ACCEPT_RANGES = 17,
NGHTTP2_TOKEN_ACCEPT = 18,
NGHTTP2_TOKEN_ACCESS_CONTROL_ALLOW_ORIGIN = 19,
NGHTTP2_TOKEN_AGE = 20,
NGHTTP2_TOKEN_ALLOW = 21,
NGHTTP2_TOKEN_AUTHORIZATION = 22,
NGHTTP2_TOKEN_CACHE_CONTROL = 23,
NGHTTP2_TOKEN_CONTENT_DISPOSITION = 24,
NGHTTP2_TOKEN_CONTENT_ENCODING = 25,
NGHTTP2_TOKEN_CONTENT_LANGUAGE = 26,
NGHTTP2_TOKEN_CONTENT_LENGTH = 27,
NGHTTP2_TOKEN_CONTENT_LOCATION = 28,
NGHTTP2_TOKEN_CONTENT_RANGE = 29,
NGHTTP2_TOKEN_CONTENT_TYPE = 30,
NGHTTP2_TOKEN_COOKIE = 31,
NGHTTP2_TOKEN_DATE = 32,
NGHTTP2_TOKEN_ETAG = 33,
NGHTTP2_TOKEN_EXPECT = 34,
NGHTTP2_TOKEN_EXPIRES = 35,
NGHTTP2_TOKEN_FROM = 36,
NGHTTP2_TOKEN_HOST = 37,
NGHTTP2_TOKEN_IF_MATCH = 38,
NGHTTP2_TOKEN_IF_MODIFIED_SINCE = 39,
NGHTTP2_TOKEN_IF_NONE_MATCH = 40,
NGHTTP2_TOKEN_IF_RANGE = 41,
NGHTTP2_TOKEN_IF_UNMODIFIED_SINCE = 42,
NGHTTP2_TOKEN_LAST_MODIFIED = 43,
NGHTTP2_TOKEN_LINK = 44,
NGHTTP2_TOKEN_LOCATION = 45,
NGHTTP2_TOKEN_MAX_FORWARDS = 46,
NGHTTP2_TOKEN_PROXY_AUTHENTICATE = 47,
NGHTTP2_TOKEN_PROXY_AUTHORIZATION = 48,
NGHTTP2_TOKEN_RANGE = 49,
NGHTTP2_TOKEN_REFERER = 50,
NGHTTP2_TOKEN_REFRESH = 51,
NGHTTP2_TOKEN_RETRY_AFTER = 52,
NGHTTP2_TOKEN_SERVER = 53,
NGHTTP2_TOKEN_SET_COOKIE = 54,
NGHTTP2_TOKEN_STRICT_TRANSPORT_SECURITY = 55,
NGHTTP2_TOKEN_TRANSFER_ENCODING = 56,
NGHTTP2_TOKEN_USER_AGENT = 57,
NGHTTP2_TOKEN_VARY = 58,
NGHTTP2_TOKEN_VIA = 59,
NGHTTP2_TOKEN_WWW_AUTHENTICATE = 60,
NGHTTP2_TOKEN_TE,
NGHTTP2_TOKEN_CONNECTION,
NGHTTP2_TOKEN_KEEP_ALIVE,
NGHTTP2_TOKEN_PROXY_CONNECTION,
NGHTTP2_TOKEN_UPGRADE
} nghttp2_token;
typedef enum { typedef enum {
NGHTTP2_HD_FLAG_NONE = 0, NGHTTP2_HD_FLAG_NONE = 0,
@@ -67,18 +128,14 @@ typedef enum {
typedef struct { typedef struct {
nghttp2_nv nv; nghttp2_nv nv;
uint32_t name_hash; /* nghttp2_token value for nv.name. It could be -1 if we have no
uint32_t value_hash; token for that header field name. */
int token;
/* Reference count */ /* Reference count */
uint8_t ref; uint8_t ref;
uint8_t flags; uint8_t flags;
} nghttp2_hd_entry; } nghttp2_hd_entry;
typedef struct {
nghttp2_hd_entry ent;
size_t index;
} nghttp2_hd_static_entry;
typedef struct { typedef struct {
nghttp2_hd_entry **buffer; nghttp2_hd_entry **buffer;
size_t mask; size_t mask;
@@ -107,6 +164,12 @@ typedef enum {
NGHTTP2_HD_STATE_READ_VALUE NGHTTP2_HD_STATE_READ_VALUE
} nghttp2_hd_inflate_state; } nghttp2_hd_inflate_state;
typedef enum {
NGHTTP2_HD_WITH_INDEXING,
NGHTTP2_HD_WITHOUT_INDEXING,
NGHTTP2_HD_NEVER_INDEXING
} nghttp2_hd_indexing_mode;
typedef struct { typedef struct {
/* dynamic header table */ /* dynamic header table */
nghttp2_hd_ringbuf hd_table; nghttp2_hd_ringbuf hd_table;
@@ -176,9 +239,8 @@ struct nghttp2_hd_inflater {
* set in the |flags|, the content pointed by the |name| with length * set in the |flags|, the content pointed by the |name| with length
* |namelen| is copied. Likewise, if NGHTTP2_HD_FLAG_VALUE_ALLOC bit * |namelen| is copied. Likewise, if NGHTTP2_HD_FLAG_VALUE_ALLOC bit
* set in the |flags|, the content pointed by the |value| with length * set in the |flags|, the content pointed by the |value| with length
* |valuelen| is copied. The |name_hash| and |value_hash| are hash * |valuelen| is copied. The |token| is enum number looked up by
* value for |name| and |value| respectively. The hash function is * |name|. It could be -1 if we don't have that enum value.
* defined in nghttp2_hd.c.
* *
* This function returns 0 if it succeeds, or one of the following * This function returns 0 if it succeeds, or one of the following
* negative error codes: * negative error codes:
@@ -188,8 +250,7 @@ struct nghttp2_hd_inflater {
*/ */
int nghttp2_hd_entry_init(nghttp2_hd_entry *ent, uint8_t flags, uint8_t *name, int nghttp2_hd_entry_init(nghttp2_hd_entry *ent, uint8_t flags, uint8_t *name,
size_t namelen, uint8_t *value, size_t valuelen, size_t namelen, uint8_t *value, size_t valuelen,
uint32_t name_hash, uint32_t value_hash, int token, nghttp2_mem *mem);
nghttp2_mem *mem);
void nghttp2_hd_entry_free(nghttp2_hd_entry *ent, nghttp2_mem *mem); void nghttp2_hd_entry_free(nghttp2_hd_entry *ent, nghttp2_mem *mem);
@@ -271,13 +332,25 @@ int nghttp2_hd_inflate_init(nghttp2_hd_inflater *inflater, nghttp2_mem *mem);
*/ */
void nghttp2_hd_inflate_free(nghttp2_hd_inflater *inflater); void nghttp2_hd_inflate_free(nghttp2_hd_inflater *inflater);
/*
* Similar to nghttp2_hd_inflate_hd(), but this takes additional
* output parameter |token|. On successful header emission, it
* contains nghttp2_token value for nv_out->name. It could be -1 if
* we don't have enum value for the name. Other than that return
* values and semantics are the same as nghttp2_hd_inflate_hd().
*/
ssize_t nghttp2_hd_inflate_hd2(nghttp2_hd_inflater *inflater,
nghttp2_nv *nv_out, int *inflate_flags,
int *token, uint8_t *in, size_t inlen,
int in_final);
/* For unittesting purpose */ /* For unittesting purpose */
int nghttp2_hd_emit_indname_block(nghttp2_bufs *bufs, size_t index, int nghttp2_hd_emit_indname_block(nghttp2_bufs *bufs, size_t index,
nghttp2_nv *nv, int inc_indexing); nghttp2_nv *nv, int indexing_mode);
/* For unittesting purpose */ /* For unittesting purpose */
int nghttp2_hd_emit_newname_block(nghttp2_bufs *bufs, nghttp2_nv *nv, int nghttp2_hd_emit_newname_block(nghttp2_bufs *bufs, nghttp2_nv *nv,
int inc_indexing); int indexing_mode);
/* For unittesting purpose */ /* For unittesting purpose */
int nghttp2_hd_emit_table_size(nghttp2_bufs *bufs, size_t table_size); int nghttp2_hd_emit_table_size(nghttp2_bufs *bufs, size_t table_size);
@@ -324,8 +397,7 @@ void nghttp2_hd_huff_decode_context_init(nghttp2_hd_huff_decode_context *ctx);
* be initialized by nghttp2_hd_huff_decode_context_init(). The result * be initialized by nghttp2_hd_huff_decode_context_init(). The result
* will be added to |dest|. This function may expand |dest| as * will be added to |dest|. This function may expand |dest| as
* needed. The caller is responsible to release the memory of |dest| * needed. The caller is responsible to release the memory of |dest|
* by calling nghttp2_bufs_free() or export its content using * by calling nghttp2_bufs_free().
* nghttp2_bufs_remove().
* *
* The caller must set the |final| to nonzero if the given input is * The caller must set the |final| to nonzero if the given input is
* the final block. * the final block.

View File

@@ -168,10 +168,27 @@ void nghttp2_hd_huff_decode_context_init(nghttp2_hd_huff_decode_context *ctx) {
ctx->accept = 1; ctx->accept = 1;
} }
/* Use macro to make the code simpler..., but error case is tricky.
We spent most of the CPU in decoding, so we are doing this
thing. */
#define hd_huff_decode_sym_emit(bufs, sym, avail) \
do { \
if ((avail)) { \
nghttp2_bufs_fast_addb((bufs), (sym)); \
--(avail); \
} else { \
rv = nghttp2_bufs_addb((bufs), (sym)); \
if (rv != 0) { \
return rv; \
} \
(avail) = nghttp2_bufs_cur_avail((bufs)); \
} \
} while (0)
ssize_t nghttp2_hd_huff_decode(nghttp2_hd_huff_decode_context *ctx, ssize_t nghttp2_hd_huff_decode(nghttp2_hd_huff_decode_context *ctx,
nghttp2_bufs *bufs, const uint8_t *src, nghttp2_bufs *bufs, const uint8_t *src,
size_t srclen, int final) { size_t srclen, int final) {
size_t i, j; size_t i;
int rv; int rv;
size_t avail; size_t avail;
@@ -180,30 +197,28 @@ ssize_t nghttp2_hd_huff_decode(nghttp2_hd_huff_decode_context *ctx,
/* We use the decoding algorithm described in /* We use the decoding algorithm described in
http://graphics.ics.uci.edu/pub/Prefix.pdf */ http://graphics.ics.uci.edu/pub/Prefix.pdf */
for (i = 0; i < srclen; ++i) { for (i = 0; i < srclen; ++i) {
uint8_t in = src[i] >> 4; const nghttp2_huff_decode *t;
for (j = 0; j < 2; ++j) {
const nghttp2_huff_decode *t;
t = &huff_decode_table[ctx->state][in]; t = &huff_decode_table[ctx->state][src[i] >> 4];
if (t->flags & NGHTTP2_HUFF_FAIL) { if (t->flags & NGHTTP2_HUFF_FAIL) {
return NGHTTP2_ERR_HEADER_COMP; return NGHTTP2_ERR_HEADER_COMP;
}
if (t->flags & NGHTTP2_HUFF_SYM) {
if (avail) {
nghttp2_bufs_fast_addb(bufs, t->sym);
--avail;
} else {
rv = nghttp2_bufs_addb(bufs, t->sym);
if (rv != 0) {
return rv;
}
avail = nghttp2_bufs_cur_avail(bufs);
}
}
ctx->state = t->state;
ctx->accept = (t->flags & NGHTTP2_HUFF_ACCEPTED) != 0;
in = src[i] & 0xf;
} }
if (t->flags & NGHTTP2_HUFF_SYM) {
/* this is macro, and may return from this function on error */
hd_huff_decode_sym_emit(bufs, t->sym, avail);
}
t = &huff_decode_table[t->state][src[i] & 0xf];
if (t->flags & NGHTTP2_HUFF_FAIL) {
return NGHTTP2_ERR_HEADER_COMP;
}
if (t->flags & NGHTTP2_HUFF_SYM) {
/* this is macro, and may return from this function on error */
hd_huff_decode_sym_emit(bufs, t->sym, avail);
}
ctx->state = t->state;
ctx->accept = (t->flags & NGHTTP2_HUFF_ACCEPTED) != 0;
} }
if (final && !ctx->accept) { if (final && !ctx->accept) {
return NGHTTP2_ERR_HEADER_COMP; return NGHTTP2_ERR_HEADER_COMP;

View File

@@ -297,12 +297,18 @@ const char *nghttp2_strerror(int error_code) {
return "The current session is closing"; return "The current session is closing";
case NGHTTP2_ERR_HTTP_HEADER: case NGHTTP2_ERR_HTTP_HEADER:
return "Invalid HTTP header field was received"; return "Invalid HTTP header field was received";
case NGHTTP2_ERR_HTTP_MESSAGING:
return "Violation in HTTP messaging rule";
case NGHTTP2_ERR_REFUSED_STREAM:
return "Stream was refused";
case NGHTTP2_ERR_INTERNAL:
return "Internal error";
case NGHTTP2_ERR_NOMEM: case NGHTTP2_ERR_NOMEM:
return "Out of memory"; return "Out of memory";
case NGHTTP2_ERR_CALLBACK_FAILURE: case NGHTTP2_ERR_CALLBACK_FAILURE:
return "The user callback function failed"; return "The user callback function failed";
case NGHTTP2_ERR_BAD_PREFACE: case NGHTTP2_ERR_BAD_CLIENT_MAGIC:
return "Received bad connection preface"; return "Received bad clinet magic byte string";
default: default:
return "Unknown error code"; return "Unknown error code";
} }

View File

@@ -29,12 +29,16 @@
#include <config.h> #include <config.h>
#endif /* HAVE_CONFIG_H */ #endif /* HAVE_CONFIG_H */
#include <string.h>
#include <nghttp2/nghttp2.h> #include <nghttp2/nghttp2.h>
#include "nghttp2_mem.h" #include "nghttp2_mem.h"
#define nghttp2_min(A, B) ((A) < (B) ? (A) : (B)) #define nghttp2_min(A, B) ((A) < (B) ? (A) : (B))
#define nghttp2_max(A, B) ((A) > (B) ? (A) : (B)) #define nghttp2_max(A, B) ((A) > (B) ? (A) : (B))
#define lstreq(A, B, N) ((sizeof((A)) - 1) == (N) && memcmp((A), (B), (N)) == 0)
/* /*
* Copies 2 byte unsigned integer |n| in host byte order to |buf| in * Copies 2 byte unsigned integer |n| in host byte order to |buf| in
* network byte order. * network byte order.

View File

@@ -28,11 +28,8 @@
#include <assert.h> #include <assert.h>
#include <stdio.h> #include <stdio.h>
static int memeq(const void *a, const void *b, size_t n) { #include "nghttp2_hd.h"
return memcmp(a, b, n) == 0; #include "nghttp2_helper.h"
}
#define streq(A, B, N) ((sizeof((A)) - 1) == (N) && memeq((A), (B), (N)))
static char downcase(char c) { static char downcase(char c) {
return 'A' <= c && c <= 'Z' ? (c - 'A' + 'a') : c; return 'A' <= c && c <= 'Z' ? (c - 'A' + 'a') : c;
@@ -50,129 +47,7 @@ static int memieq(const void *a, const void *b, size_t n) {
return 1; return 1;
} }
#define strieq(A, B, N) ((sizeof((A)) - 1) == (N) && memieq((A), (B), (N))) #define lstrieq(A, B, N) ((sizeof((A)) - 1) == (N) && memieq((A), (B), (N)))
typedef enum {
NGHTTP2_TOKEN__AUTHORITY,
NGHTTP2_TOKEN__METHOD,
NGHTTP2_TOKEN__PATH,
NGHTTP2_TOKEN__SCHEME,
NGHTTP2_TOKEN__STATUS,
NGHTTP2_TOKEN_CONNECTION,
NGHTTP2_TOKEN_CONTENT_LENGTH,
NGHTTP2_TOKEN_HOST,
NGHTTP2_TOKEN_KEEP_ALIVE,
NGHTTP2_TOKEN_PROXY_CONNECTION,
NGHTTP2_TOKEN_TE,
NGHTTP2_TOKEN_TRANSFER_ENCODING,
NGHTTP2_TOKEN_UPGRADE,
NGHTTP2_TOKEN_MAXIDX,
} nghttp2_token;
/*
* This function was generated by genlibtokenlookup.py. Inspired by
* h2o header lookup. https://github.com/h2o/h2o
*/
static int lookup_token(const uint8_t *name, size_t namelen) {
switch (namelen) {
case 2:
switch (name[namelen - 1]) {
case 'e':
if (streq("t", name, 1)) {
return NGHTTP2_TOKEN_TE;
}
break;
}
break;
case 4:
switch (name[namelen - 1]) {
case 't':
if (streq("hos", name, 3)) {
return NGHTTP2_TOKEN_HOST;
}
break;
}
break;
case 5:
switch (name[namelen - 1]) {
case 'h':
if (streq(":pat", name, 4)) {
return NGHTTP2_TOKEN__PATH;
}
break;
}
break;
case 7:
switch (name[namelen - 1]) {
case 'd':
if (streq(":metho", name, 6)) {
return NGHTTP2_TOKEN__METHOD;
}
break;
case 'e':
if (streq(":schem", name, 6)) {
return NGHTTP2_TOKEN__SCHEME;
}
if (streq("upgrad", name, 6)) {
return NGHTTP2_TOKEN_UPGRADE;
}
break;
case 's':
if (streq(":statu", name, 6)) {
return NGHTTP2_TOKEN__STATUS;
}
break;
}
break;
case 10:
switch (name[namelen - 1]) {
case 'e':
if (streq("keep-aliv", name, 9)) {
return NGHTTP2_TOKEN_KEEP_ALIVE;
}
break;
case 'n':
if (streq("connectio", name, 9)) {
return NGHTTP2_TOKEN_CONNECTION;
}
break;
case 'y':
if (streq(":authorit", name, 9)) {
return NGHTTP2_TOKEN__AUTHORITY;
}
break;
}
break;
case 14:
switch (name[namelen - 1]) {
case 'h':
if (streq("content-lengt", name, 13)) {
return NGHTTP2_TOKEN_CONTENT_LENGTH;
}
break;
}
break;
case 16:
switch (name[namelen - 1]) {
case 'n':
if (streq("proxy-connectio", name, 15)) {
return NGHTTP2_TOKEN_PROXY_CONNECTION;
}
break;
}
break;
case 17:
switch (name[namelen - 1]) {
case 'g':
if (streq("transfer-encodin", name, 16)) {
return NGHTTP2_TOKEN_TRANSFER_ENCODING;
}
break;
}
break;
}
return -1;
}
static int64_t parse_uint(const uint8_t *s, size_t len) { static int64_t parse_uint(const uint8_t *s, size_t len) {
int64_t n = 0; int64_t n = 0;
@@ -225,10 +100,20 @@ static int expect_response_body(nghttp2_stream *stream) {
stream->status_code != 204; stream->status_code != 204;
} }
static int http_request_on_header(nghttp2_stream *stream, nghttp2_nv *nv, /* For "http" or "https" URIs, OPTIONS request may have "*" in :path
int trailer) { header field to represent system-wide OPTIONS request. Otherwise,
int token; :path header field value must start with "/". This function must
be called after ":method" header field was received. This function
returns nonzero if path is valid.*/
static int check_path(nghttp2_stream *stream) {
return (stream->http_flags & NGHTTP2_HTTP_FLAG_SCHEME_HTTP) == 0 ||
((stream->http_flags & NGHTTP2_HTTP_FLAG_PATH_REGULAR) ||
((stream->http_flags & NGHTTP2_HTTP_FLAG_METH_OPTIONS) &&
(stream->http_flags & NGHTTP2_HTTP_FLAG_PATH_ASTERISK)));
}
static int http_request_on_header(nghttp2_stream *stream, nghttp2_nv *nv,
int token, int trailer) {
if (nv->name[0] == ':') { if (nv->name[0] == ':') {
if (trailer || if (trailer ||
(stream->http_flags & NGHTTP2_HTTP_FLAG_PSEUDO_HEADER_DISALLOWED)) { (stream->http_flags & NGHTTP2_HTTP_FLAG_PSEUDO_HEADER_DISALLOWED)) {
@@ -236,8 +121,6 @@ static int http_request_on_header(nghttp2_stream *stream, nghttp2_nv *nv,
} }
} }
token = lookup_token(nv->name, nv->namelen);
switch (token) { switch (token) {
case NGHTTP2_TOKEN__AUTHORITY: case NGHTTP2_TOKEN__AUTHORITY:
if (!check_pseudo_header(stream, nv, NGHTTP2_HTTP_FLAG__AUTHORITY)) { if (!check_pseudo_header(stream, nv, NGHTTP2_HTTP_FLAG__AUTHORITY)) {
@@ -248,18 +131,34 @@ static int http_request_on_header(nghttp2_stream *stream, nghttp2_nv *nv,
if (!check_pseudo_header(stream, nv, NGHTTP2_HTTP_FLAG__METHOD)) { if (!check_pseudo_header(stream, nv, NGHTTP2_HTTP_FLAG__METHOD)) {
return NGHTTP2_ERR_HTTP_HEADER; return NGHTTP2_ERR_HTTP_HEADER;
} }
if (streq("HEAD", nv->value, nv->valuelen)) { switch (nv->valuelen) {
stream->http_flags |= NGHTTP2_HTTP_FLAG_METH_HEAD; case 4:
} else if (streq("CONNECT", nv->value, nv->valuelen)) { if (lstreq("HEAD", nv->value, nv->valuelen)) {
if (stream->stream_id % 2 == 0) { stream->http_flags |= NGHTTP2_HTTP_FLAG_METH_HEAD;
/* we won't allow CONNECT for push */
return NGHTTP2_ERR_HTTP_HEADER;
} }
stream->http_flags |= NGHTTP2_HTTP_FLAG_METH_CONNECT; break;
if (stream->http_flags & case 7:
(NGHTTP2_HTTP_FLAG__PATH | NGHTTP2_HTTP_FLAG__SCHEME)) { switch (nv->value[6]) {
return NGHTTP2_ERR_HTTP_HEADER; case 'T':
if (lstreq("CONNECT", nv->value, nv->valuelen)) {
if (stream->stream_id % 2 == 0) {
/* we won't allow CONNECT for push */
return NGHTTP2_ERR_HTTP_HEADER;
}
stream->http_flags |= NGHTTP2_HTTP_FLAG_METH_CONNECT;
if (stream->http_flags &
(NGHTTP2_HTTP_FLAG__PATH | NGHTTP2_HTTP_FLAG__SCHEME)) {
return NGHTTP2_ERR_HTTP_HEADER;
}
}
break;
case 'S':
if (lstreq("OPTIONS", nv->value, nv->valuelen)) {
stream->http_flags |= NGHTTP2_HTTP_FLAG_METH_OPTIONS;
}
break;
} }
break;
} }
break; break;
case NGHTTP2_TOKEN__PATH: case NGHTTP2_TOKEN__PATH:
@@ -269,6 +168,11 @@ static int http_request_on_header(nghttp2_stream *stream, nghttp2_nv *nv,
if (!check_pseudo_header(stream, nv, NGHTTP2_HTTP_FLAG__PATH)) { if (!check_pseudo_header(stream, nv, NGHTTP2_HTTP_FLAG__PATH)) {
return NGHTTP2_ERR_HTTP_HEADER; return NGHTTP2_ERR_HTTP_HEADER;
} }
if (nv->value[0] == '/') {
stream->http_flags |= NGHTTP2_HTTP_FLAG_PATH_REGULAR;
} else if (nv->valuelen == 1 && nv->value[0] == '*') {
stream->http_flags |= NGHTTP2_HTTP_FLAG_PATH_ASTERISK;
}
break; break;
case NGHTTP2_TOKEN__SCHEME: case NGHTTP2_TOKEN__SCHEME:
if (stream->http_flags & NGHTTP2_HTTP_FLAG_METH_CONNECT) { if (stream->http_flags & NGHTTP2_HTTP_FLAG_METH_CONNECT) {
@@ -277,6 +181,10 @@ static int http_request_on_header(nghttp2_stream *stream, nghttp2_nv *nv,
if (!check_pseudo_header(stream, nv, NGHTTP2_HTTP_FLAG__SCHEME)) { if (!check_pseudo_header(stream, nv, NGHTTP2_HTTP_FLAG__SCHEME)) {
return NGHTTP2_ERR_HTTP_HEADER; return NGHTTP2_ERR_HTTP_HEADER;
} }
if ((nv->valuelen == 4 && memieq("http", nv->value, 4)) ||
(nv->valuelen == 5 && memieq("https", nv->value, 5))) {
stream->http_flags |= NGHTTP2_HTTP_FLAG_SCHEME_HTTP;
}
break; break;
case NGHTTP2_TOKEN_HOST: case NGHTTP2_TOKEN_HOST:
if (!check_pseudo_header(stream, nv, NGHTTP2_HTTP_FLAG_HOST)) { if (!check_pseudo_header(stream, nv, NGHTTP2_HTTP_FLAG_HOST)) {
@@ -301,7 +209,7 @@ static int http_request_on_header(nghttp2_stream *stream, nghttp2_nv *nv,
case NGHTTP2_TOKEN_UPGRADE: case NGHTTP2_TOKEN_UPGRADE:
return NGHTTP2_ERR_HTTP_HEADER; return NGHTTP2_ERR_HTTP_HEADER;
case NGHTTP2_TOKEN_TE: case NGHTTP2_TOKEN_TE:
if (!strieq("trailers", nv->value, nv->valuelen)) { if (!lstrieq("trailers", nv->value, nv->valuelen)) {
return NGHTTP2_ERR_HTTP_HEADER; return NGHTTP2_ERR_HTTP_HEADER;
} }
break; break;
@@ -319,9 +227,7 @@ static int http_request_on_header(nghttp2_stream *stream, nghttp2_nv *nv,
} }
static int http_response_on_header(nghttp2_stream *stream, nghttp2_nv *nv, static int http_response_on_header(nghttp2_stream *stream, nghttp2_nv *nv,
int trailer) { int token, int trailer) {
int token;
if (nv->name[0] == ':') { if (nv->name[0] == ':') {
if (trailer || if (trailer ||
(stream->http_flags & NGHTTP2_HTTP_FLAG_PSEUDO_HEADER_DISALLOWED)) { (stream->http_flags & NGHTTP2_HTTP_FLAG_PSEUDO_HEADER_DISALLOWED)) {
@@ -329,8 +235,6 @@ static int http_response_on_header(nghttp2_stream *stream, nghttp2_nv *nv,
} }
} }
token = lookup_token(nv->name, nv->namelen);
switch (token) { switch (token) {
case NGHTTP2_TOKEN__STATUS: { case NGHTTP2_TOKEN__STATUS: {
if (!check_pseudo_header(stream, nv, NGHTTP2_HTTP_FLAG__STATUS)) { if (!check_pseudo_header(stream, nv, NGHTTP2_HTTP_FLAG__STATUS)) {
@@ -363,7 +267,7 @@ static int http_response_on_header(nghttp2_stream *stream, nghttp2_nv *nv,
case NGHTTP2_TOKEN_UPGRADE: case NGHTTP2_TOKEN_UPGRADE:
return NGHTTP2_ERR_HTTP_HEADER; return NGHTTP2_ERR_HTTP_HEADER;
case NGHTTP2_TOKEN_TE: case NGHTTP2_TOKEN_TE:
if (!strieq("trailers", nv->value, nv->valuelen)) { if (!lstrieq("trailers", nv->value, nv->valuelen)) {
return NGHTTP2_ERR_HTTP_HEADER; return NGHTTP2_ERR_HTTP_HEADER;
} }
break; break;
@@ -381,7 +285,8 @@ static int http_response_on_header(nghttp2_stream *stream, nghttp2_nv *nv,
} }
int nghttp2_http_on_header(nghttp2_session *session, nghttp2_stream *stream, int nghttp2_http_on_header(nghttp2_session *session, nghttp2_stream *stream,
nghttp2_frame *frame, nghttp2_nv *nv, int trailer) { nghttp2_frame *frame, nghttp2_nv *nv, int token,
int trailer) {
/* We are strict for pseudo header field. One bad character should /* We are strict for pseudo header field. One bad character should
lead to fail. OTOH, we should be a bit forgiving for regular lead to fail. OTOH, we should be a bit forgiving for regular
headers, since existing public internet has so much illegal headers, since existing public internet has so much illegal
@@ -421,10 +326,10 @@ int nghttp2_http_on_header(nghttp2_session *session, nghttp2_stream *stream,
} }
if (session->server || frame->hd.type == NGHTTP2_PUSH_PROMISE) { if (session->server || frame->hd.type == NGHTTP2_PUSH_PROMISE) {
return http_request_on_header(stream, nv, trailer); return http_request_on_header(stream, nv, token, trailer);
} }
return http_response_on_header(stream, nv, trailer); return http_response_on_header(stream, nv, token, trailer);
} }
int nghttp2_http_on_request_headers(nghttp2_stream *stream, int nghttp2_http_on_request_headers(nghttp2_stream *stream,
@@ -434,11 +339,16 @@ int nghttp2_http_on_request_headers(nghttp2_stream *stream,
return -1; return -1;
} }
stream->content_length = -1; stream->content_length = -1;
} else if ((stream->http_flags & NGHTTP2_HTTP_FLAG_REQ_HEADERS) != } else {
NGHTTP2_HTTP_FLAG_REQ_HEADERS || if ((stream->http_flags & NGHTTP2_HTTP_FLAG_REQ_HEADERS) !=
(stream->http_flags & NGHTTP2_HTTP_FLAG_REQ_HEADERS ||
(NGHTTP2_HTTP_FLAG__AUTHORITY | NGHTTP2_HTTP_FLAG_HOST)) == 0) { (stream->http_flags &
return -1; (NGHTTP2_HTTP_FLAG__AUTHORITY | NGHTTP2_HTTP_FLAG_HOST)) == 0) {
return -1;
}
if (!check_path(stream)) {
return -1;
}
} }
if (frame->hd.type == NGHTTP2_PUSH_PROMISE) { if (frame->hd.type == NGHTTP2_PUSH_PROMISE) {
@@ -532,14 +442,15 @@ void nghttp2_http_record_request_method(nghttp2_stream *stream,
/* TODO we should do this strictly. */ /* TODO we should do this strictly. */
for (i = 0; i < nvlen; ++i) { for (i = 0; i < nvlen; ++i) {
const nghttp2_nv *nv = &nva[i]; const nghttp2_nv *nv = &nva[i];
if (lookup_token(nv->name, nv->namelen) != NGHTTP2_TOKEN__METHOD) { if (!(nv->namelen == 7 && nv->name[6] == 'd' &&
memcmp(":metho", nv->name, nv->namelen - 1) == 0)) {
continue; continue;
} }
if (streq("CONNECT", nv->value, nv->valuelen)) { if (lstreq("CONNECT", nv->value, nv->valuelen)) {
stream->http_flags |= NGHTTP2_HTTP_FLAG_METH_CONNECT; stream->http_flags |= NGHTTP2_HTTP_FLAG_METH_CONNECT;
return; return;
} }
if (streq("HEAD", nv->value, nv->valuelen)) { if (lstreq("HEAD", nv->value, nv->valuelen)) {
stream->http_flags |= NGHTTP2_HTTP_FLAG_METH_HEAD; stream->http_flags |= NGHTTP2_HTTP_FLAG_METH_HEAD;
return; return;
} }

View File

@@ -36,7 +36,8 @@
/* /*
* This function is called when HTTP header field |nv| in |frame| is * This function is called when HTTP header field |nv| in |frame| is
* received for |stream|. This function will validate |nv| against * received for |stream|. This function will validate |nv| against
* the current state of stream. * the current state of stream. The |token| is nghttp2_token value
* for nv->name, or -1 if we don't have enum value for the name.
* *
* This function returns 0 if it succeeds, or one of the following * This function returns 0 if it succeeds, or one of the following
* negative error codes: * negative error codes:
@@ -48,7 +49,8 @@
* if it was not received because of compatibility reasons. * if it was not received because of compatibility reasons.
*/ */
int nghttp2_http_on_header(nghttp2_session *session, nghttp2_stream *stream, int nghttp2_http_on_header(nghttp2_session *session, nghttp2_stream *stream,
nghttp2_frame *frame, nghttp2_nv *nv, int trailer); nghttp2_frame *frame, nghttp2_nv *nv, int token,
int trailer);
/* /*
* This function is called when request header is received. This * This function is called when request header is received. This

View File

@@ -39,7 +39,8 @@
} while (0) } while (0)
#endif #endif
typedef int (*nghttp2_compar)(const void *lhs, const void *rhs); /* "less" function, return nonzero if |lhs| is less than |rhs|. */
typedef int (*nghttp2_less)(const void *lhs, const void *rhs);
/* Internal error code. They must be in the range [-499, -100], /* Internal error code. They must be in the range [-499, -100],
inclusive. */ inclusive. */
@@ -51,7 +52,7 @@ typedef enum {
* Invalid HTTP header field was received but it can be treated as * Invalid HTTP header field was received but it can be treated as
* if it was not received because of compatibility reasons. * if it was not received because of compatibility reasons.
*/ */
NGHTTP2_ERR_IGN_HTTP_HEADER = -105, NGHTTP2_ERR_IGN_HTTP_HEADER = -105
} nghttp2_internal_error; } nghttp2_internal_error;
#endif /* NGHTTP2_INT_H */ #endif /* NGHTTP2_INT_H */

View File

@@ -37,8 +37,55 @@
#include <netinet/in.h> #include <netinet/in.h>
#endif /* HAVE_NETINET_IN_H */ #endif /* HAVE_NETINET_IN_H */
#ifdef HAVE_WINSOCK2_H #include <nghttp2/nghttp2.h>
#include <winsock2.h>
#endif /* HAVE_WINSOCK2_H */ #if defined(WIN32)
/* Windows requires ws2_32 library for ntonl family functions. We
define inline functions for those function so that we don't have
dependeny on that lib. */
#ifdef _MSC_VER
#define STIN static __inline
#else
#define STIN static inline
#endif
STIN uint32_t htonl(uint32_t hostlong) {
uint32_t res;
unsigned char *p = (unsigned char *)&res;
*p++ = hostlong >> 24;
*p++ = (hostlong >> 16) & 0xffu;
*p++ = (hostlong >> 8) & 0xffu;
*p = hostlong & 0xffu;
return res;
}
STIN uint16_t htons(uint16_t hostshort) {
uint16_t res;
unsigned char *p = (unsigned char *)&res;
*p++ = hostshort >> 8;
*p = hostshort & 0xffu;
return res;
}
STIN uint32_t ntohl(uint32_t netlong) {
uint32_t res;
unsigned char *p = (unsigned char *)&netlong;
res = *p++ << 24;
res += *p++ << 16;
res += *p++ << 8;
res += *p;
return res;
}
STIN uint16_t ntohs(uint16_t netshort) {
uint16_t res;
unsigned char *p = (unsigned char *)&netshort;
res = *p++ << 8;
res += *p;
return res;
}
#endif /* WIN32 */
#endif /* NGHTTP2_NET_H */ #endif /* NGHTTP2_NET_H */

View File

@@ -47,9 +47,9 @@ void nghttp2_option_set_peer_max_concurrent_streams(nghttp2_option *option,
option->peer_max_concurrent_streams = val; option->peer_max_concurrent_streams = val;
} }
void nghttp2_option_set_recv_client_preface(nghttp2_option *option, int val) { void nghttp2_option_set_no_recv_client_magic(nghttp2_option *option, int val) {
option->opt_set_mask |= NGHTTP2_OPT_RECV_CLIENT_PREFACE; option->opt_set_mask |= NGHTTP2_OPT_NO_RECV_CLIENT_MAGIC;
option->recv_client_preface = val; option->no_recv_client_magic = val;
} }
void nghttp2_option_set_no_http_messaging(nghttp2_option *option, int val) { void nghttp2_option_set_no_http_messaging(nghttp2_option *option, int val) {

View File

@@ -57,8 +57,8 @@ typedef enum {
* SETTINGS_MAX_CONCURRENT_STREAMS from the remote endpoint. * SETTINGS_MAX_CONCURRENT_STREAMS from the remote endpoint.
*/ */
NGHTTP2_OPT_PEER_MAX_CONCURRENT_STREAMS = 1 << 1, NGHTTP2_OPT_PEER_MAX_CONCURRENT_STREAMS = 1 << 1,
NGHTTP2_OPT_RECV_CLIENT_PREFACE = 1 << 2, NGHTTP2_OPT_NO_RECV_CLIENT_MAGIC = 1 << 2,
NGHTTP2_OPT_NO_HTTP_MESSAGING = 1 << 3, NGHTTP2_OPT_NO_HTTP_MESSAGING = 1 << 3
} nghttp2_option_flag; } nghttp2_option_flag;
/** /**
@@ -79,9 +79,9 @@ struct nghttp2_option {
*/ */
uint8_t no_auto_window_update; uint8_t no_auto_window_update;
/** /**
* NGHTTP2_OPT_RECV_CLIENT_PREFACE * NGHTTP2_OPT_NO_RECV_CLIENT_MAGIC
*/ */
uint8_t recv_client_preface; uint8_t no_recv_client_magic;
/** /**
* NGHTTP2_OPT_NO_HTTP_MESSAGING * NGHTTP2_OPT_NO_HTTP_MESSAGING
*/ */

View File

@@ -25,6 +25,15 @@
#include "nghttp2_outbound_item.h" #include "nghttp2_outbound_item.h"
#include <assert.h> #include <assert.h>
#include <string.h>
void nghttp2_outbound_item_init(nghttp2_outbound_item *item) {
item->cycle = 0;
item->qnext = NULL;
item->queued = 0;
memset(&item->aux_data, 0, sizeof(nghttp2_aux_data));
}
void nghttp2_outbound_item_free(nghttp2_outbound_item *item, nghttp2_mem *mem) { void nghttp2_outbound_item_free(nghttp2_outbound_item *item, nghttp2_mem *mem) {
nghttp2_frame *frame; nghttp2_frame *frame;
@@ -65,3 +74,32 @@ void nghttp2_outbound_item_free(nghttp2_outbound_item *item, nghttp2_mem *mem) {
break; break;
} }
} }
void nghttp2_outbound_queue_init(nghttp2_outbound_queue *q) {
q->head = q->tail = NULL;
q->n = 0;
}
void nghttp2_outbound_queue_push(nghttp2_outbound_queue *q,
nghttp2_outbound_item *item) {
if (q->tail) {
q->tail = q->tail->qnext = item;
} else {
q->head = q->tail = item;
}
++q->n;
}
void nghttp2_outbound_queue_pop(nghttp2_outbound_queue *q) {
nghttp2_outbound_item *item;
if (!q->head) {
return;
}
item = q->head;
q->head = q->head->qnext;
item->qnext = NULL;
if (!q->head) {
q->tail = NULL;
}
--q->n;
}

View File

@@ -33,13 +33,6 @@
#include "nghttp2_frame.h" #include "nghttp2_frame.h"
#include "nghttp2_mem.h" #include "nghttp2_mem.h"
/* A bit higher weight for non-DATA frames */
#define NGHTTP2_OB_EX_WEIGHT 300
/* Higher weight for SETTINGS */
#define NGHTTP2_OB_SETTINGS_WEIGHT 301
/* Highest weight for PING */
#define NGHTTP2_OB_PING_WEIGHT 302
/* struct used for HEADERS and PUSH_PROMISE frame */ /* struct used for HEADERS and PUSH_PROMISE frame */
typedef struct { typedef struct {
nghttp2_data_provider data_prd; nghttp2_data_provider data_prd;
@@ -74,6 +67,10 @@ typedef struct {
* |eof| is 0. It becomes 1 after all data were read. * |eof| is 0. It becomes 1 after all data were read.
*/ */
uint8_t eof; uint8_t eof;
/**
* The flag to indicate that NGHTTP2_DATA_FLAG_NO_COPY is used.
*/
uint8_t no_copy;
} nghttp2_data_aux_data; } nghttp2_data_aux_data;
typedef enum { typedef enum {
@@ -84,7 +81,7 @@ typedef enum {
/* indicates that this GOAWAY is just a notification for graceful /* indicates that this GOAWAY is just a notification for graceful
shutdown. No nghttp2_session.goaway_flags should be updated on shutdown. No nghttp2_session.goaway_flags should be updated on
the reaction to this frame. */ the reaction to this frame. */
NGHTTP2_GOAWAY_AUX_SHUTDOWN_NOTICE = 0x2, NGHTTP2_GOAWAY_AUX_SHUTDOWN_NOTICE = 0x2
} nghttp2_goaway_aux_flag; } nghttp2_goaway_aux_flag;
/* struct used for GOAWAY frame */ /* struct used for GOAWAY frame */
@@ -100,19 +97,31 @@ typedef union {
nghttp2_goaway_aux_data goaway; nghttp2_goaway_aux_data goaway;
} nghttp2_aux_data; } nghttp2_aux_data;
typedef struct { struct nghttp2_outbound_item;
typedef struct nghttp2_outbound_item nghttp2_outbound_item;
struct nghttp2_outbound_item {
nghttp2_frame frame; nghttp2_frame frame;
nghttp2_aux_data aux_data; nghttp2_aux_data aux_data;
int64_t seq; /* The priority used in priority comparion. Smaller is served
/* Reset count of weight. See comment for last_cycle in ealier. For PING, SETTINGS and non-DATA frames (excluding
nghttp2_session.h */ 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
that the amount of transmission is distributed across streams
proportional to effective weight (inside a tree). */
uint64_t cycle; uint64_t cycle;
/* The priority used in priority comparion. Larger is served nghttp2_outbound_item *qnext;
ealier. */
int32_t weight;
/* nonzero if this object is queued. */ /* nonzero if this object is queued. */
uint8_t queued; uint8_t queued;
} nghttp2_outbound_item; };
/*
* Initializes |item|. No memory allocation is done in this function.
* Don't call nghttp2_outbound_item_free() until frame member is
* initialized.
*/
void nghttp2_outbound_item_init(nghttp2_outbound_item *item);
/* /*
* Deallocates resource for |item|. If |item| is NULL, this function * Deallocates resource for |item|. If |item| is NULL, this function
@@ -120,4 +129,29 @@ typedef struct {
*/ */
void nghttp2_outbound_item_free(nghttp2_outbound_item *item, nghttp2_mem *mem); void nghttp2_outbound_item_free(nghttp2_outbound_item *item, nghttp2_mem *mem);
/*
* queue for nghttp2_outbound_item.
*/
typedef struct {
nghttp2_outbound_item *head, *tail;
/* number of items in this queue. */
size_t n;
} nghttp2_outbound_queue;
void nghttp2_outbound_queue_init(nghttp2_outbound_queue *q);
/* Pushes |item| into |q| */
void nghttp2_outbound_queue_push(nghttp2_outbound_queue *q,
nghttp2_outbound_item *item);
/* Pops |item| at the top from |q|. If |q| is empty, nothing
happens. */
void nghttp2_outbound_queue_pop(nghttp2_outbound_queue *q);
/* Returns the top item. */
#define nghttp2_outbound_queue_top(Q) ((Q)->head)
/* Returns the size of the queue */
#define nghttp2_outbound_queue_size(Q) ((Q)->n)
#endif /* NGHTTP2_OUTBOUND_ITEM_H */ #endif /* NGHTTP2_OUTBOUND_ITEM_H */

View File

@@ -24,7 +24,7 @@
*/ */
#include "nghttp2_pq.h" #include "nghttp2_pq.h"
int nghttp2_pq_init(nghttp2_pq *pq, nghttp2_compar compar, nghttp2_mem *mem) { int nghttp2_pq_init(nghttp2_pq *pq, nghttp2_less less, nghttp2_mem *mem) {
pq->mem = mem; pq->mem = mem;
pq->capacity = 128; pq->capacity = 128;
pq->q = nghttp2_mem_malloc(mem, pq->capacity * sizeof(void *)); pq->q = nghttp2_mem_malloc(mem, pq->capacity * sizeof(void *));
@@ -32,7 +32,7 @@ int nghttp2_pq_init(nghttp2_pq *pq, nghttp2_compar compar, nghttp2_mem *mem) {
return NGHTTP2_ERR_NOMEM; return NGHTTP2_ERR_NOMEM;
} }
pq->length = 0; pq->length = 0;
pq->compar = compar; pq->less = less;
return 0; return 0;
} }
@@ -52,7 +52,7 @@ static void bubble_up(nghttp2_pq *pq, size_t index) {
return; return;
} else { } else {
size_t parent = (index - 1) / 2; size_t parent = (index - 1) / 2;
if (pq->compar(pq->q[parent], pq->q[index]) > 0) { if (pq->less(pq->q[index], pq->q[parent])) {
swap(pq, parent, index); swap(pq, parent, index);
bubble_up(pq, parent); bubble_up(pq, parent);
} }
@@ -93,7 +93,7 @@ static void bubble_down(nghttp2_pq *pq, size_t index) {
if (j >= pq->length) { if (j >= pq->length) {
break; break;
} }
if (pq->compar(pq->q[minindex], pq->q[j]) > 0) { if (pq->less(pq->q[j], pq->q[minindex])) {
minindex = j; minindex = j;
} }
} }

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