Compare commits

...

1177 Commits

Author SHA1 Message Date
Tatsuhiro Tsujikawa
bdfb2b9a0d Update man pages 2015-01-11 19:03:45 +09:00
Tatsuhiro Tsujikawa
3fd37462bb Bump up version number to 0.7.1, LT revision to 8:1:3 2015-01-11 19:00:49 +09:00
Tatsuhiro Tsujikawa
1164e931c5 Use clang for android build
With androideabi-4.9, android build now supports threading.
2015-01-11 18:50:54 +09:00
Tatsuhiro Tsujikawa
0e8afdb050 Add extra doc to FILES section in nghttpx man pages 2015-01-11 17:34:43 +09:00
Tatsuhiro Tsujikawa
23119a6f12 Update sphinx_rtd_theme 2015-01-11 17:20:46 +09:00
Tatsuhiro Tsujikawa
8001f226b9 Update instruction and Dockerfile to build android binary 2015-01-11 17:04:50 +09:00
Tatsuhiro Tsujikawa
1c0fa46dfa nghttpx: RateLimit: Use ev_timer_again for clarity 2015-01-11 00:32:08 +09:00
Tatsuhiro Tsujikawa
f7455d48cc Compile with android NDK
This also fixes the bug that nghttpx's acceptor fd is blocking if
SOCK_NONBLOCK is undefined.
2015-01-11 00:28:00 +09:00
Tatsuhiro Tsujikawa
a86d78216c Merge branch 'alagoutte-misc' 2015-01-10 23:21:07 +09:00
Tatsuhiro Tsujikawa
47c0b0326d Merge branch 'misc' of https://github.com/alagoutte/nghttp2 into alagoutte-misc 2015-01-10 23:19:33 +09:00
Tatsuhiro Tsujikawa
0ca979b453 nghttpx: Add --rlimit-nofile option 2015-01-10 23:17:48 +09:00
Alexis La Goutte
c87631c2e6 Fix other shorten-64-to-32 casting error found by MSVC (64bits)
Thanks to Pascal
2015-01-10 15:17:31 +01:00
Tatsuhiro Tsujikawa
987aa2dd85 nghttpx: Define max iovcnt for http1 backend write operation 2015-01-10 23:04:54 +09:00
Tatsuhiro Tsujikawa
91b40d1e84 src: Add test for memchunk.h 2015-01-10 23:01:03 +09:00
Tatsuhiro Tsujikawa
bc17f95c80 src: Move ipv6_numeric_addr to util and add test 2015-01-10 21:33:53 +09:00
Tatsuhiro Tsujikawa
0069ca9ce8 nghttp: Fix compile error with libstdc++ 2015-01-10 17:57:44 +09:00
Tatsuhiro Tsujikawa
fe750240c8 Update doc about nghttpx feature 2015-01-10 17:12:24 +09:00
Tatsuhiro Tsujikawa
1795d3ea27 nghttp: Add include file to clarify used objects 2015-01-10 16:44:09 +09:00
Tatsuhiro Tsujikawa
b933ee8e78 h2load: Don't retry connection on read error
Connection failure is handled by connected() and other errors lead to
just failure, no retry is needed.
2015-01-10 16:02:15 +09:00
Tatsuhiro Tsujikawa
a3dcf1e004 Produce man pages using sphinx
Previously to create manual page for bundled programs, we use help2man
to create man page from program's help output.  Then our man2rst.py
script converts man page to rst document.  Sphinx generates html from
rst documents.

Now help2rst.py produces rst document from programs output.  We use
Sphinx solely to produce both man pages and html files.
2015-01-10 00:37:42 +09:00
Tatsuhiro Tsujikawa
b2411d949e Remove return in void function 2015-01-09 20:56:37 +09:00
Tatsuhiro Tsujikawa
19101f7f4a Revert "nghttpx: Use smaller write buffer"
This reverts commit 742d80aac4.
2015-01-09 20:55:39 +09:00
Tatsuhiro Tsujikawa
a2e4a1eb26 tests: Remove unintended debug output 2015-01-09 10:07:57 +09:00
Tatsuhiro Tsujikawa
742d80aac4 nghttpx: Use smaller write buffer 2015-01-09 09:51:46 +09:00
Tatsuhiro Tsujikawa
473f1d71ff src: Clear OpenSSL error queue before SSL_shutdown 2015-01-09 09:15:01 +09:00
Tatsuhiro Tsujikawa
8f40bd4675 nghttp, nghttpd, h2load: Clear OpenSSL error queue and handle renegotiation 2015-01-09 09:10:59 +09:00
Tatsuhiro Tsujikawa
7add262721 nghttpx: Detect TLS renegotiation after SSL_read and SSL_write 2015-01-09 00:49:27 +09:00
Tatsuhiro Tsujikawa
4a218f1b79 nghttpx: Clear OpenSSL error and handle limit change in read_tls 2015-01-09 00:08:34 +09:00
Tatsuhiro Tsujikawa
419c03daa2 nghttpx: Fix TLS write error
SSL_write requires the same arguments (buf pointer and its length) on
SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE.  get_write_limit() may
return smaller length than previously passed to SSL_write, which
violates OpenSSL assumption.  To avoid this, we keep last legnth
passed to SSL_write to tls_last_writelen_ if SSL_write indicated I/O
blocking.
2015-01-08 23:03:56 +09:00
Tatsuhiro Tsujikawa
019f1e9fc7 nghttpx: Remove useless comments 2015-01-08 22:28:30 +09:00
Tatsuhiro Tsujikawa
53604782e5 nghttpx: Clean up worker_event handling 2015-01-08 22:24:29 +09:00
Tatsuhiro Tsujikawa
689e8c0ee3 nghttpx: Don't copy ticket_keys std::shared_ptr 2015-01-08 21:49:19 +09:00
Tatsuhiro Tsujikawa
0173929538 nghttpx: Rename ListenHandler as ConnectionHandler 2015-01-08 21:48:39 +09:00
Tatsuhiro Tsujikawa
f570757701 nghttpd: Fix data race when updating cached_date 2015-01-08 21:41:26 +09:00
Tatsuhiro Tsujikawa
5473e870eb nghttpx: Use smaller buffer for reading 2015-01-08 21:28:52 +09:00
Tatsuhiro Tsujikawa
a41b7baf81 nghttpx: Handle NEW_CONNECTION event first 2015-01-08 21:20:17 +09:00
Tatsuhiro Tsujikawa
fcddb5c06c nghttpx: Distribute session ticket keys to workers without mutex 2015-01-08 21:15:45 +09:00
Tatsuhiro Tsujikawa
5d3544185c nghttpx: Fix crash in SSL_CTX_set_tlsext_ticket_key_cb
It seems that returning 0 when enc == 0 crashes OpenSSL.
2015-01-08 20:46:35 +09:00
Tatsuhiro Tsujikawa
5dce9501a6 Fix compile error with libstdc++ and/or --disable-threads 2015-01-08 01:57:59 +09:00
Tatsuhiro Tsujikawa
b313068cab Fix compile error with --enable-werror 2015-01-08 01:33:09 +09:00
Tatsuhiro Tsujikawa
08e8cc1915 nghttpx: Add --tls-ticket-key-file option
This option specifies files contains 48 random bytes to construct
session ticket key data.  This option can be used repeatedly to
specify multiple keys, but only the first one is used to encrypt
tickets.
2015-01-08 01:26:30 +09:00
Tatsuhiro Tsujikawa
52f3572d5b nghttpx: Enable TLS session tickets with session key rotation every 12hrs 2015-01-08 00:01:09 +09:00
Tatsuhiro Tsujikawa
a804117c83 Fix GOAWAY handling
On reception of GOAWAY, new stream creation is disallowed regardless
of last-stream-id in GOAWAY is larger than next stream ID.
2015-01-07 22:53:43 +09:00
Tatsuhiro Tsujikawa
2b14e4a617 Bump up version number to 0.7.1-DEV 2015-01-07 01:57:30 +09:00
Tatsuhiro Tsujikawa
ad57435953 Update man pages 2015-01-07 01:40:55 +09:00
Tatsuhiro Tsujikawa
7702d38699 Bump up version number to 0.7.0, LT revision to 8:0:3 2015-01-07 01:39:36 +09:00
Tatsuhiro Tsujikawa
90914b38f1 nghttpx: Do not limit DATA frame length 2015-01-07 01:25:43 +09:00
Tatsuhiro Tsujikawa
8bfd900be5 src, examples: Check return value 2015-01-07 00:26:17 +09:00
Tatsuhiro Tsujikawa
40e8eaf5fd nghttpx: Fix uninitialized pointer member 2015-01-07 00:25:42 +09:00
Tatsuhiro Tsujikawa
d3a606e9d9 nghttpx: open_file_for_write: Use O_CLOEXEC flag 2015-01-07 00:25:10 +09:00
Tatsuhiro Tsujikawa
2fb3d5fd1f nghttpx: Remove Http2Upstream::deferred_ for now 2015-01-06 23:32:58 +09:00
Tatsuhiro Tsujikawa
ba795d86f0 nghttpx: Don't cache time for logging
Update is done by main event loop which is stopped after graceful
shutdown is commenced, which means time is no longer update.  To avoid
this situation, we just avoid caching and get time for each logging.
2015-01-06 23:17:09 +09:00
Tatsuhiro Tsujikawa
e8107b68c8 nghttpx: Avoid std::chrono::high_resolution_clock as wall clock
This is because std::chrono::high_resolution_clock may not be wall
clock; it may be alias of std::chrono::stead_clock.
2015-01-06 23:10:11 +09:00
Tatsuhiro Tsujikawa
94e69d5e30 nghttpx: Remove commented lines 2015-01-06 22:55:01 +09:00
Tatsuhiro Tsujikawa
d1391f1db7 nghttpx: Process buffered data first without reading additional data 2015-01-06 22:48:17 +09:00
Tatsuhiro Tsujikawa
b9174b828e nghttpx: Use util::make_socket_closeonexec instead of calling fcntl 2015-01-06 22:03:44 +09:00
Tatsuhiro Tsujikawa
a6cf6c00ea nghttpx: Add SSL_read/write error logging 2015-01-06 22:02:24 +09:00
Tatsuhiro Tsujikawa
f6097ce6d0 nghttp: Fix compile error with openssl >= 1.0.2 2015-01-06 01:40:24 +09:00
Tatsuhiro Tsujikawa
1474f755cf Merge branch 'libev' 2015-01-06 01:33:55 +09:00
Tatsuhiro Tsujikawa
dcdbd5ab20 h2load: Fix wrong kbytes/s value 2015-01-06 01:24:03 +09:00
Tatsuhiro Tsujikawa
cbc02bbc4c nghttpx: Code cleanup 2015-01-06 00:51:52 +09:00
Tatsuhiro Tsujikawa
b5796c6b96 nghttp: Add missing initialization Request::res_hdidx on res_nva.clear() 2015-01-06 00:51:18 +09:00
Tatsuhiro Tsujikawa
d80952a2bc nghttpx: Implement stream level timeout using ev_timer 2015-01-06 00:30:57 +09:00
Tatsuhiro Tsujikawa
2e8544f48d Update http-parser to 167dcdfc063e16adba1af2f7ad5ad77b3994c8d3 2015-01-05 18:28:25 +09:00
Tatsuhiro Tsujikawa
f26d436ee6 src: http2::lookup_token: Don't need to make char lowcase 2015-01-05 18:17:52 +09:00
Tatsuhiro Tsujikawa
6052a86df1 python: Fix request header ordering 2015-01-05 17:00:07 +09:00
Tatsuhiro Tsujikawa
9854e3746f src: Fix compile error with libstdc++ 2015-01-05 16:20:35 +09:00
Tatsuhiro Tsujikawa
7a50299cb0 nghttpx: Handle connect error 2015-01-05 16:14:10 +09:00
Tatsuhiro Tsujikawa
7dba426db4 nghttpx: Use accept if accept4 is not available 2015-01-05 16:04:28 +09:00
Tatsuhiro Tsujikawa
fcf0ceeac6 nghttpd: Make use of accept4 2015-01-05 15:59:51 +09:00
Tatsuhiro Tsujikawa
e253d8f6db h2load: Retry next address when connection cannot be established 2015-01-05 01:56:02 +09:00
Tatsuhiro Tsujikawa
8fb544523c nghttpx: Fix HTTP/2 settings timer for HTTP/2 backend 2015-01-05 01:46:41 +09:00
Tatsuhiro Tsujikawa
3ae44ef2f3 nghttpd, nghttpx: Rework incoming header handling 2015-01-05 01:46:41 +09:00
Tatsuhiro Tsujikawa
730d47f7ad src: Add unittest for http2::index_header 2015-01-03 22:03:00 +09:00
Tatsuhiro Tsujikawa
ea0ab938c4 src: Only index header in lowercase 2015-01-03 21:56:59 +09:00
Tatsuhiro Tsujikawa
9763ea768d travis: Add libev-dev 2015-01-03 00:25:19 +09:00
Tatsuhiro Tsujikawa
8e3406ad20 nghttpd: Use faster request header handling 2015-01-03 00:19:41 +09:00
Tatsuhiro Tsujikawa
aaf0dc825d Update README.rst 2015-01-03 00:19:41 +09:00
Tatsuhiro Tsujikawa
8729d1e4c2 src: Remove libevent dependency 2015-01-03 00:19:41 +09:00
Tatsuhiro Tsujikawa
db6eec653b Fix errors reported by scan-build 2015-01-03 00:19:41 +09:00
Tatsuhiro Tsujikawa
c654549d35 nghttpx: Remove commented code 2015-01-03 00:19:41 +09:00
Tatsuhiro Tsujikawa
645897503d nghttpx: Reset buffer on empty 2015-01-03 00:19:41 +09:00
Tatsuhiro Tsujikawa
fe8f2a4603 nghttpd: Use larger write buffer 2015-01-03 00:19:41 +09:00
Tatsuhiro Tsujikawa
0a4330ee3c nghttpd: Fix handling pending data and rename rb_ as wb_ 2015-01-03 00:19:41 +09:00
Tatsuhiro Tsujikawa
d157744fb2 nghttpx: Fix handling of pending data 2015-01-03 00:19:41 +09:00
Tatsuhiro Tsujikawa
82320d6e55 nghttpd: Reset write buffer on empty 2015-01-03 00:19:41 +09:00
Tatsuhiro Tsujikawa
7db1864766 nghttpx: Add --backend-http1-connections-per-frontend option 2015-01-03 00:19:41 +09:00
Tatsuhiro Tsujikawa
a55a07940c nghttpx: Show not implemented warning for per wroker rate limit 2015-01-03 00:19:41 +09:00
Tatsuhiro Tsujikawa
37c01a0a4d nghttpx: Remove unused IOControl::set_lim 2015-01-03 00:19:41 +09:00
Tatsuhiro Tsujikawa
2003be8dc5 src: Fix unit tests failure 2015-01-03 00:19:41 +09:00
Tatsuhiro Tsujikawa
bfac015d61 src: Use libev for rest of the applications 2015-01-03 00:19:41 +09:00
Tatsuhiro Tsujikawa
cd7258a7cd Use libev for nghttpd
Benchmark shows 10% faster with libev compared to libevent.  Also
response time in high load condition is much faster.
2015-01-03 00:19:41 +09:00
Tatsuhiro Tsujikawa
c3215af5f6 Fix missing error handling for session_after_frame_sent1 2015-01-02 14:49:36 +09:00
Tatsuhiro Tsujikawa
ba0f4d77a0 Merge branch 'alagoutte-travis' 2015-01-02 13:02:41 +09:00
Tatsuhiro Tsujikawa
eb681c827d Merge branch 'travis' of https://github.com/alagoutte/nghttp2 into alagoutte-travis 2015-01-02 13:02:18 +09:00
Tatsuhiro Tsujikawa
e82c53803f Merge branch 'alagoutte-misc' 2015-01-02 13:00:54 +09:00
Alexis La Goutte
781d570ec1 Travis: Remove python (No needed)
and it is now valided by http://lint.travis-ci.org/

(Hooray, your .travis.yml seems to be solid!)
2014-12-31 11:16:24 +01:00
Alexis La Goutte
fef9530ca5 fix error: variable 'mem' set but not used [-Werror=unused-but-set-variable] 2014-12-30 16:18:52 +01:00
Tatsuhiro Tsujikawa
ab1dd11705 nghttpd: Fix typo :host, which should be host 2014-12-25 00:49:36 +09:00
Tatsuhiro Tsujikawa
7bf5be9c17 nghttpd: Reserve 10 headers for request headers 2014-12-24 01:05:12 +09:00
Tatsuhiro Tsujikawa
ac11ba32ee nghttpd: Use stack allocated array for headers in submit_file_response 2014-12-24 00:56:25 +09:00
Tatsuhiro Tsujikawa
a20ad03f7b nghttpd: Use evbuffer_pullup(input, -1) cause buffer is most likely just one 2014-12-24 00:46:04 +09:00
Tatsuhiro Tsujikawa
292f219900 nghttpd: Avoid sending last 0-sized DATA 2014-12-24 00:31:21 +09:00
Tatsuhiro Tsujikawa
55e550f08f nghttpd: Remove unused variable 2014-12-24 00:23:01 +09:00
Tatsuhiro Tsujikawa
32943a74b2 nghttpd: Just use socket send buffer and don't count our own buffer size 2014-12-24 00:19:16 +09:00
Tatsuhiro Tsujikawa
89291e4010 nghttpx: Improve priority handling in http2 upstream 2014-12-23 17:45:57 +09:00
Tatsuhiro Tsujikawa
a8a66843db Merge branch 'kazuho-kazuho/issues/133' 2014-12-22 21:30:51 +09:00
Tatsuhiro Tsujikawa
32b34c4b80 Merge branch 'kazuho/issues/133' of https://github.com/kazuho/nghttp2 into kazuho-kazuho/issues/133 2014-12-22 21:29:26 +09:00
Kazuho Oku
45d0d731eb fill-in data_stat after copying the request entity into the temporary file 2014-12-22 07:26:02 +09:00
Kazuho Oku
125f62b71e unlink the temporary file immediately after calling mkstemp 2014-12-22 07:24:36 +09:00
Kazuho Oku
eb6ba2a703 copy the request entity to temporary file if the source is stdin and if it is not a regular file 2014-12-21 14:06:44 +09:00
Tatsuhiro Tsujikawa
e559168bd7 Enable failmalloc test by default 2014-12-20 23:56:33 +09:00
Tatsuhiro Tsujikawa
959d05e6f8 failmalloc: Use nghttp2_mem instead of using dlsym 2014-12-20 23:56:33 +09:00
Tatsuhiro Tsujikawa
e60183313b Document that calling nghttp2_submit_response to same stream twice is bad idea 2014-12-20 21:53:33 +09:00
Tatsuhiro Tsujikawa
7c0a0c495d Rename nghttp2_stream.data_item to nghttp2_stream.item and related functions
Initially, we use nghttp2_stream.data_item to refer only item with
DATA frame.  But recently we use it to refer HEADERS frame as well.
So it is better to call just item rather than data_item.  This applies
to all related functions.
2014-12-20 21:48:31 +09:00
Tatsuhiro Tsujikawa
39eb1e4753 nghttp: Adjust priority upon upgrade 2014-12-19 23:33:13 +09:00
Tatsuhiro Tsujikawa
079682f313 deflatehd: Fix crash 2014-12-19 23:23:42 +09:00
Tatsuhiro Tsujikawa
e8513b3241 Make huffman encoding faster 2014-12-19 23:22:55 +09:00
Tatsuhiro Tsujikawa
8bac2087cf nghttp2_session_mem_send: Handle stream closure early
Previously session_after_frame_sent is called after we detected all
data is sent.  In nghttp2_session_mem_send, we only detect it in the
next call of the function.  It means that if a frame data bearing
END_STREAM is on flight to the peer as a result of
nghttp2_session_mem_send, peer may get that data and knows the stream
closure and issues new stream.  We may receive this new stream before
the next nghttp2_session_mem_send call, which means that we may
incorrectly assumes that peer violates maximum concurrent stream
limit.  To fix this issue, we separate session_after_frame_sent into 2
functions: session_after_frame_sent1 and session_after_frame_sent2.
session_after_frame_sent1 handles on_frame_send_callback and stream
closure and we call this early in nghttp2_session_mem_send.  This
makes number of streams are synchronized correctly with peer.
2014-12-18 21:52:17 +09:00
Tatsuhiro Tsujikawa
ce1bf11d4b Fix memory leak 2014-12-18 21:02:44 +09:00
Tatsuhiro Tsujikawa
eb8138bfbd nghttp: Advance next stream ID only when --idle-dep is used 2014-12-17 23:36:29 +09:00
Tatsuhiro Tsujikawa
5180eb93e5 Merge branch 'alagoutte-misc' 2014-12-17 23:25:22 +09:00
Alexis La Goutte
27fa4d310a Fix: error pointer target types incompatible in C++ [-Werror=c++-compat] 2014-12-16 17:54:47 +01:00
Tatsuhiro Tsujikawa
adc22ec80b nghttp: Print failed address 2014-12-17 00:26:41 +09:00
Tatsuhiro Tsujikawa
4bc9f2422b Add nghttp2_mem example 2014-12-16 23:21:50 +09:00
Tatsuhiro Tsujikawa
d695d2ccc0 nghttp, nghttpx, nghttpd, h2load: Support h2-16 in NPN/ALPN
The nghttp2 library itself is still h2-14.  To experiment with the
implementations to require h2-16 to test new features (e.g.,
prioritization), nghttp, nghttpx, nghttpd and h2load now support h2-16
as well as h2-14.  Cleartext HTTP Upgrade is still limited to h2-14
however.
2014-12-16 22:57:58 +09:00
Tatsuhiro Tsujikawa
5fa9dd7cd5 nghttpx: Remove unused variable 2014-12-16 01:10:54 +09:00
Tatsuhiro Tsujikawa
b352ae03a9 src: Fix undefined reference error 2014-12-16 01:09:19 +09:00
Tatsuhiro Tsujikawa
c93da867e0 nghttpx: Fix bug SPDY upstream requires content-length if no FIN in SYN_STREAM 2014-12-15 23:42:59 +09:00
Tatsuhiro Tsujikawa
556811ec64 nghttpx: Don't connect backend if connection is not establish up front 2014-12-15 23:34:00 +09:00
Tatsuhiro Tsujikawa
403ece66e3 nghttpd: Fail if listen failed 2014-12-15 23:17:50 +09:00
Tatsuhiro Tsujikawa
9a35dbc4ab src: Just check emptiness for value since spaces around value are stripped 2014-12-15 23:14:07 +09:00
Tatsuhiro Tsujikawa
6f70a53da6 src: http2::add_header: strip white spaces in value 2014-12-15 23:04:45 +09:00
Tatsuhiro Tsujikawa
93ee9e30d8 nghttp, h2load: Use recommended ciphers and assign sane SSL_CTX options 2014-12-13 01:37:57 +09:00
Tatsuhiro Tsujikawa
a84c319d62 src: Print stream ID in priority field as dep_stream_id 2014-12-13 01:20:58 +09:00
Tatsuhiro Tsujikawa
467b419947 nghttp: Add --dep-idle option to create anchor idle node for dependency 2014-12-13 01:19:27 +09:00
Tatsuhiro Tsujikawa
ee158fb0aa Add nghttp2_session_{set,get}_next_stream_id API function 2014-12-13 01:18:15 +09:00
Tatsuhiro Tsujikawa
280c9dfcf3 Keep idle streams in separate list
Previously we handle idle streams as closed streams.  We only keeps
sum of closed streams and active streams under max concurrent streams
limit, idle streams gets deleted earlier than client expects.

In this change, idle streams are kept in separate list and not handled
as closed streams.  To mitigate possible attack vector to make
unlimited idle streams, we cap the number of idle streams in a half of
max concurrent streams.  This is arbitrary choice.  It may be adjusted
in the future when we have interop experience.
2014-12-13 00:14:52 +09:00
Tatsuhiro Tsujikawa
e4c59dd164 nghttpd: Fix next_session_id_ is not incremented 2014-12-10 01:21:12 +09:00
Tatsuhiro Tsujikawa
f705b2aec4 Use NGHTTP2_PROTOCOL_ERROR for WINDOW_UPDATE with increments == 0 2014-12-10 01:02:30 +09:00
Tatsuhiro Tsujikawa
dce20c3e6a nghttpx: Check HTTP/2 downstream connection after certain idle time
Previously when requests are issued to HTTP/2 downstream connection,
but it turns out that connection is down, handlers of those requests
are deleted.  In some situations, we only know connection is down when
we write something to network, so we'd like to handle this kind of
situation in more robust manner.  In this change, certain seconds
passed after last network activity, we first issue PING frame to
downstream connection before issuing new HTTP request.  If writing
PING frame is failed, it means connection was lost.  In this case,
instead of deleting handler, pending requests are migrated to new
HTTP2/ downstream connection, so that it can continue without
affecting upstream connection.
2014-12-09 21:41:29 +09:00
Tatsuhiro Tsujikawa
e0a2353c56 Fix crash with custom memory allocator 2014-12-08 21:22:20 +09:00
Tatsuhiro Tsujikawa
c0ffed7788 Support custom memory allocator
nghttp2_mem structure is introduced to hold custom memory allocator
functions and user supplied pointer.  nghttp2_mem object can be passed
to nghttp2_session_client_new3(), nghttp2_session_server_new3(),
nghttp2_hd_deflate_new2() and nghttp2_hd_inflate_new2() to replace
standard malloc(), free(), calloc() and realloc().  nghttp2_mem
structure has user supplied pointer mem_user_data which can be used as
per session/object memory pool.
2014-12-08 00:55:55 +09:00
Tatsuhiro Tsujikawa
21b48d24e4 Remove altsvc 2014-12-07 23:11:54 +09:00
Tatsuhiro Tsujikawa
e13c9102b8 Update man pages 2014-12-06 23:03:50 +09:00
Tatsuhiro Tsujikawa
14d8894b40 Update doc 2014-12-06 23:00:04 +09:00
Tatsuhiro Tsujikawa
b607a22076 nghttpx: Support multiple HTTP/1 backend address
For HTTP/1 backend, -b option can be used several times to specify
multiple backend address.  HTTP/2 backend does not support multiple
addresses and only uses first address even if multiple addresses are
specified.
2014-12-06 19:30:27 +09:00
Tatsuhiro Tsujikawa
b8dafbdf5e nghttpx: Pass NI_NUMERICSERV to getnameinfo to get numeric service name 2014-12-06 01:07:05 +09:00
Tatsuhiro Tsujikawa
3b03ff626a nghttpx: Don't log access log for blocked streams 2014-12-05 21:29:31 +09:00
Tatsuhiro Tsujikawa
9614611969 nghttpx: Limit # of downstream connections per host when h2 proxy is used
This commit limits the number of concurrent HTTP/1 downstream
connections to same host.  By defualt, it is limited to 8 connections.
--backend-connections-per-frontend option was replaced with
--backend-http1-connections-per-host, which changes the maximum number
of connections per host.  This limitation only kicks in when h2 proxy
is used (-s option).
2014-12-05 01:47:03 +09:00
Tatsuhiro Tsujikawa
f178b78816 nghttpx: Longer read timeouts 2014-12-03 23:45:44 +09:00
Tatsuhiro Tsujikawa
381488a9bd doc: Add link to nghttp2.org 2014-12-03 23:14:44 +09:00
Tatsuhiro Tsujikawa
0cbc78656e building-android-binary.rst: Highlight sh code 2014-12-03 23:09:16 +09:00
Tatsuhiro Tsujikawa
e180d8e594 nghttpx: Longer downstream HTTP/1 idle connection timeout 2014-12-03 23:00:53 +09:00
Tatsuhiro Tsujikawa
cbb5da5285 nghttpx: Fix --backend-http-proxy-uri does not work 2014-12-02 03:03:14 +09:00
Tatsuhiro Tsujikawa
03877c3752 asio-lib: Put ${AM_CPPFLAGS} before ${BOOST_CPPFLAGS} 2014-12-01 23:20:53 +09:00
Tatsuhiro Tsujikawa
54a3209cf5 configure.ac: Rename some variables so that they follow automake convention 2014-12-01 23:14:28 +09:00
Tatsuhiro Tsujikawa
9eb554a843 configure.ac: Categorize configure result 2014-12-01 23:10:34 +09:00
Tatsuhiro Tsujikawa
7036859823 Do not change user variable CFLAGS in configure.ac 2014-12-01 23:06:11 +09:00
Tatsuhiro Tsujikawa
60cb3f67f2 Refactor nghttp2_adjust_local_window_size 2014-12-01 21:49:32 +09:00
Tatsuhiro Tsujikawa
6b59609f9b Fix typo: s/.PONY/.PHONY/ 2014-12-01 21:13:56 +09:00
Tatsuhiro Tsujikawa
a3c5ac4730 Bump up version number to 0.6.8-DEV 2014-11-30 23:43:24 +09:00
Tatsuhiro Tsujikawa
ed1ea91a6f Update man pages 2014-11-30 23:14:02 +09:00
Tatsuhiro Tsujikawa
209d1b0946 Bump up version number to 0.6.7, LT revision to 7:2:2 2014-11-30 23:02:40 +09:00
Tatsuhiro Tsujikawa
761cb97090 Update README.rst 2014-11-30 22:54:55 +09:00
Tatsuhiro Tsujikawa
dcc7b23980 nghttpx: Remove cipher suite requirement
This makes the library h2-16 compatible now.
2014-11-30 22:52:34 +09:00
Tatsuhiro Tsujikawa
b9667fd209 asio: Listen to all resolved addresses 2014-11-30 22:39:16 +09:00
Tatsuhiro Tsujikawa
d23105ccb7 Add note about pseudo header ordering validation in on_header_callback 2014-11-30 21:30:48 +09:00
Tatsuhiro Tsujikawa
30499005f8 Reformat source code in libnghttp2_asio.rst 2014-11-30 21:26:13 +09:00
Tatsuhiro Tsujikawa
f2cd057e89 Update tutorial 2014-11-30 21:10:59 +09:00
Tatsuhiro Tsujikawa
2b465ee65f libevent-client: Disable SSLv3 2014-11-30 21:09:23 +09:00
Tatsuhiro Tsujikawa
7e092a7658 Make sure that head_stream is not NULL 2014-11-30 19:52:05 +09:00
Tatsuhiro Tsujikawa
d39b56adaa Remove unused nghttp2_stream.blocked_sent 2014-11-30 17:41:40 +09:00
Tatsuhiro Tsujikawa
152a20a416 Influence last_stream_id to nghttp2_session_want_{read,write} 2014-11-29 23:13:42 +09:00
Tatsuhiro Tsujikawa
7ff0797535 Rewrite session_is_new_peer_stream_id() 2014-11-29 17:24:49 +09:00
Tatsuhiro Tsujikawa
ca57c2f6b6 Rename NGHTTP2_GOAWAY_FAIL_ON_SEND with NGHTTP2_GOAWAY_TERM_ON_FAIL 2014-11-29 16:28:08 +09:00
Tatsuhiro Tsujikawa
d75ba74bbd Return error if invalid stream_id is given to nghttp2_submit_push_promise 2014-11-29 16:17:02 +09:00
Tatsuhiro Tsujikawa
9ff1925538 Robust GOAWAY handling
This change will utilize last_stream_id in GOAWAY extensively.  When
GOAWAY is received with a last_stream_id, library closes all outgoing
streams whose stream_id > received last_stream_id.
nghttp2_on_stream_callback is called for each stream to be closed.

When GOAWAY is sent with a last_stream_id, library closes all incoming
streams whose stream_id > sent last_stream_id.
nghttp2_on_stream_callback is called for each stream to be closed.
2014-11-29 16:02:13 +09:00
Tatsuhiro Tsujikawa
1915408096 doc: Add language attribute in asio_http2.h.rst.in 2014-11-28 02:01:59 +09:00
Tatsuhiro Tsujikawa
45801883ba Cleanup previous commit 2014-11-28 01:35:12 +09:00
Tatsuhiro Tsujikawa
382a328ead Issue connection error if client receives HEADERS with idle stream ID
If stream ID is not idle, it might be valid HEADERS.  If stream ID is
idle, it is invalid regardless stream ID is even or odd, since client
is not expected to recieve request from server.  nghttp2 library
historically allows this, but now we forbids this.
2014-11-28 01:22:57 +09:00
Tatsuhiro Tsujikawa
babfa41424 Just ignore HEADERS with non-idle stream ID and not found in stream map 2014-11-28 01:01:33 +09:00
Tatsuhiro Tsujikawa
204ff787fa nghttpx: Submit RST_STREAM if HEADERS appears in the middle of a stream 2014-11-28 00:23:46 +09:00
Tatsuhiro Tsujikawa
2a68cc7076 Merge branch 'clang-format' 2014-11-27 23:56:53 +09:00
Tatsuhiro Tsujikawa
b1f807abd1 Reformat lines with clang-format-3.5 2014-11-27 23:56:30 +09:00
Tatsuhiro Tsujikawa
2c830a4698 Add make clang-format 2014-11-27 23:56:29 +09:00
Tatsuhiro Tsujikawa
87ce5068bb Add pre-commit script 2014-11-27 23:56:29 +09:00
Tatsuhiro Tsujikawa
7c794b8d93 Add .clang-format config file and git-clang-format from clang project 2014-11-27 23:56:29 +09:00
Tatsuhiro Tsujikawa
0a406eab94 Add contribution guidelines 2014-11-27 23:56:29 +09:00
Tatsuhiro Tsujikawa
c67ccad74d nghttpx: Use cached get_config()->pid in save_pid() 2014-11-27 22:41:14 +09:00
Tatsuhiro Tsujikawa
5d59adc52b libevent-server: Disable SSLv3 2014-11-27 21:40:34 +09:00
Tatsuhiro Tsujikawa
770cfcaae9 libevent-server: Enable ECDHE ciphers 2014-11-27 21:38:54 +09:00
Tatsuhiro Tsujikawa
04dae32509 nghttpx: Store PID to Config again after daemon() 2014-11-27 21:32:34 +09:00
Tatsuhiro Tsujikawa
3e0813d407 Merge branch 'alagoutte-scan-build' 2014-11-27 21:27:52 +09:00
Tatsuhiro Tsujikawa
c8b83d7024 Merge branch 'scan-build' of https://github.com/alagoutte/nghttp2 into alagoutte-scan-build 2014-11-27 21:25:56 +09:00
Alexis La Goutte
d1285255eb Fix last warning found by Clang Analyzer
nghttp2_session.c:636:3: warning: Branch condition evaluates to a garbage value
2014-11-26 18:20:16 +01:00
Tatsuhiro Tsujikawa
dfbc6e6a57 examples: Guard include config.h with HAVE_CONFIG_H 2014-11-27 00:12:42 +09:00
Tatsuhiro Tsujikawa
2eab5d03fd Merge branch 'alagoutte-Wunused-parameter' 2014-11-26 01:20:21 +09:00
Tatsuhiro Tsujikawa
fe634e5326 Merge branch 'Wunused-parameter' of https://github.com/alagoutte/nghttp2 into alagoutte-Wunused-parameter 2014-11-26 01:16:52 +09:00
Alexis La Goutte
bac44d7ffb Fix -Werror=unused-parameter using _U_ macro 2014-11-25 17:08:09 +01:00
Alexis La Goutte
51b59bc8f0 Remove -Wno-unused-parameter (and add _U_ macro) 2014-11-25 17:08:09 +01:00
Tatsuhiro Tsujikawa
2d10e31931 Merge branch 'andydavies-master' 2014-11-26 00:04:40 +09:00
Andy Davies
4cf7b3cebd Fixed minor typo
turotial -> tutorial
2014-11-25 10:03:10 +00:00
Tatsuhiro Tsujikawa
e11834d1c9 src: Add code in case struct tm.tm_gmtoff is not available 2014-11-24 18:39:35 +09:00
Tatsuhiro Tsujikawa
8f22ff3032 Update man pages 2014-11-24 15:27:41 +09:00
Tatsuhiro Tsujikawa
8e94551881 Handle idle stream in priority field 2014-11-24 15:25:19 +09:00
Tatsuhiro Tsujikawa
6e1470c9d3 Remove duplicated code 2014-11-24 15:25:19 +09:00
Tatsuhiro Tsujikawa
9416bf9079 Update doc 2014-11-24 15:25:19 +09:00
Tatsuhiro Tsujikawa
24f83eef7c Reduce nghttp2_session_get_stream() call before sending frame 2014-11-24 15:25:19 +09:00
Tatsuhiro Tsujikawa
b7c0576eb5 Make certain type of HEADERS subject to priority
We make following HEADERS under priority control:
* push response HEADERS
* HEADERS submitted by nghttp2_submit_response

Currently, HEADERS submitted by nghttp2_submit_headers is not attached
to stream.  This is because it may be used as non-final response
header and application may submit final response using
nghttp2_submit_response without checking non-final response header
transmission.
2014-11-24 15:25:19 +09:00
Tatsuhiro Tsujikawa
5a48750e16 Assign default weight if NGHTTP2_MAX_DEP_TREE_LENGTH is exceeded 2014-11-24 15:25:19 +09:00
Tatsuhiro Tsujikawa
ae93f6345c Allow PRIORITY frame at anytime.
Allowing PRIORITY frame at anytime so that PRIORITY frame to idle
stream can create anchor node in dependency tree.  In this change, we
open stream with new NGHTTP2_STREAM_IDLE state, which is linked in
session->closed_stream_head and is treated as if it is closed stream.
One difference is that if the stream is opened, we remove it from
linked list and change the state to the appropriate one.  To O(1)
removal from linked list, we change session->closed_stream_head to
doubly linked list.
2014-11-24 15:25:19 +09:00
Tatsuhiro Tsujikawa
9bba616426 nghttpx: Add $alpn variable to accesslog formatting
$alpn is a variable which represents ALPN identifier of the protocol
which generates the response.
2014-11-24 15:24:09 +09:00
Tatsuhiro Tsujikawa
1fe50f272b nghttpx: Add $pid to --accesslog-format variable
$pid refers to the PID of the running process.
2014-11-24 14:34:43 +09:00
Tatsuhiro Tsujikawa
93023acc6c nghttpx: Make --accesslog-format usage doc help2man friendly
This is unfortunate but help2man behaves badly when there is indented
lines in help messages in commnad-line args.  We removed indentations
to make help2man happy.
2014-11-24 14:16:48 +09:00
Tatsuhiro Tsujikawa
daf659c64e nghttpx: Note the conversion made in <VAR> 2014-11-24 14:04:37 +09:00
Tatsuhiro Tsujikawa
de2a855572 Implement faster formatting for format_iso8601 and format_common_log 2014-11-24 14:00:52 +09:00
Tatsuhiro Tsujikawa
df401f57a2 Merge branch 'LPardue-accesslog_port' 2014-11-24 13:35:47 +09:00
Lucas Pardue
6e178653a5 fixed conflict 2014-11-23 21:10:51 +00:00
Lucas Pardue
9cf1a0c77c Add features to logging, client and server port,
time_iso8601 and request_time.
2014-11-23 20:37:51 +00:00
Tatsuhiro Tsujikawa
ebdbe88bc0 Add contrib/.gitignore 2014-11-23 19:32:54 +09:00
Tatsuhiro Tsujikawa
74ec1d3377 nghttpx: Write accesslog when upstream connection is lost for HTTP/2 and SPDY 2014-11-23 17:24:23 +09:00
Tatsuhiro Tsujikawa
1e4f288a7c nghttpx: Remove misleading logging 2014-11-23 16:45:36 +09:00
Tatsuhiro Tsujikawa
6a21a6f148 Merge branch 'alagoutte-http_parser' 2014-11-22 23:16:40 +09:00
Tatsuhiro Tsujikawa
661b99ec17 Merge branch 'http_parser' of https://github.com/alagoutte/nghttp2 into alagoutte-http_parser 2014-11-22 23:14:44 +09:00
Tatsuhiro Tsujikawa
ecd143fcc2 nghttpx: Send RST_STREAM with NO_ERROR when closing upgraded connection 2014-11-22 23:13:29 +09:00
Tatsuhiro Tsujikawa
bd9389b956 nghttpx: Refactor http2_data_read_callback 2014-11-22 21:12:28 +09:00
Tatsuhiro Tsujikawa
1a09cef0ef nghttpx: Avoid 0-length DATA in HTTP/2 upstream 2014-11-22 21:12:28 +09:00
Alexis La Goutte
aa3a6d5916 Update Third Party lib (http-parser) 2014-11-21 19:45:55 +01:00
Tatsuhiro Tsujikawa
bded1d1115 h2load: Support ALPN 2014-11-22 01:13:18 +09:00
Tatsuhiro Tsujikawa
fa4f03525e nghttp: Fix compile error and warning with libc++ 2014-11-22 00:37:37 +09:00
Tatsuhiro Tsujikawa
4ee89e62fc nghttp2_hd: Refactor a bit 2014-11-21 01:59:20 +09:00
Tatsuhiro Tsujikawa
ee65dea8af nghttp: Fix compile error without libjansson 2014-11-19 21:18:31 +09:00
Tatsuhiro Tsujikawa
27609327ee nghttpx: Fix heap-after-free crash in https upstream
Add Upstream::on_handler_delete() hook to safely write log for
HttpsUpstream.
2014-11-19 01:59:09 +09:00
Tatsuhiro Tsujikawa
958cd0de64 nghttpx: Add configurable access logging format
This commit adds functionality to customize access logging format in
nghttpx.  The format variables are inspired by nginx.  The default
format is combined format.
2014-11-19 01:29:55 +09:00
Tatsuhiro Tsujikawa
1d7601edfb nghttpx: Better handling EOF from downstream connection to tunnel stream 2014-11-18 00:03:52 +09:00
Tatsuhiro Tsujikawa
8a0fdcfea9 nghttpd: Fix crash 2014-11-17 19:01:06 +09:00
Tatsuhiro Tsujikawa
75a1ad8bdb src: format_iso8601: Fix invalid millisecond formatting 2014-11-16 17:32:35 +09:00
Tatsuhiro Tsujikawa
5bac7f0ca6 python: Fix request is not sent without TLS 2014-11-16 17:31:11 +09:00
Tatsuhiro Tsujikawa
08fea5705a python: Fix bug that settings timer is started when SETTINGS with ACK is sent 2014-11-16 17:30:33 +09:00
Tatsuhiro Tsujikawa
8e5b5d00e1 Merge branch 'scoky-master' 2014-11-16 17:27:16 +09:00
Tatsuhiro Tsujikawa
97e8482348 Merge branch 'master' of https://github.com/scoky/nghttp2 into scoky-master 2014-11-16 16:48:07 +09:00
Kyle Schomp
0cc73e279e Pull of the client Python bindings 2014-11-15 16:37:41 +01:00
Tatsuhiro Tsujikawa
54232c6542 nghttp: Add --no-dep option to disable sending priority hints to server 2014-11-15 23:42:26 +09:00
Tatsuhiro Tsujikawa
ee2856f9bc nghttp: Update doc 2014-11-15 23:34:37 +09:00
Tatsuhiro Tsujikawa
737cea0b38 nghttp: Add -r, --har option to output HTTP transactions in HAR format 2014-11-15 23:34:10 +09:00
Tatsuhiro Tsujikawa
a8eeea0b18 Initialize frame header for upgrade SETTINGS frame 2014-11-15 11:30:01 +09:00
Tatsuhiro Tsujikawa
a2bc88f6db nghttpx: Check max length of ALPN field 2014-11-14 23:19:16 +09:00
Tatsuhiro Tsujikawa
5ce8ae79f0 nghttpx: Disable spdy/3 and spdy/2 by default 2014-11-14 23:16:06 +09:00
Tatsuhiro Tsujikawa
d98e9a63d0 src: Refactor code around ALPN setup 2014-11-14 23:14:39 +09:00
Tatsuhiro Tsujikawa
8e30adbca0 asio: Add http2::backlog API function 2014-11-10 23:26:01 +09:00
Tatsuhiro Tsujikawa
9adfd08848 asio_http2_handler: Use util::utos instead of std::to_string 2014-11-10 22:39:20 +09:00
Tatsuhiro Tsujikawa
2e3419ccbb nghttpd: Cache formatted date string 2014-11-10 22:35:08 +09:00
Tatsuhiro Tsujikawa
5b6b6dc1b7 src: Rewrite http_date 2014-11-10 21:53:19 +09:00
Tatsuhiro Tsujikawa
d0271a90b5 nghttpd: Use util::utos instead of slow util::to_str 2014-11-10 21:23:26 +09:00
Tatsuhiro Tsujikawa
20ffe2b2a0 tiny-nghttpd: Fix memory leak 2014-11-10 21:20:44 +09:00
Tatsuhiro Tsujikawa
94c80e2507 Bump up version number to 0.6.7-DEV 2014-11-08 23:40:23 +09:00
Tatsuhiro Tsujikawa
efa344be98 Add assert to ensure non-null dep_stream 2014-11-08 23:23:54 +09:00
Tatsuhiro Tsujikawa
2ba9a009fe nghttpd: Fix resource leak 2014-11-08 23:07:40 +09:00
Tatsuhiro Tsujikawa
c59ffa09e0 Update man pages 2014-11-08 22:55:24 +09:00
Tatsuhiro Tsujikawa
72f5e028d0 Bump up version number to 0.6.6, LT revision to 7:1:2 2014-11-08 22:52:45 +09:00
Tatsuhiro Tsujikawa
80b361dbb0 nghttpx: Use exit instead of abort for DIE macro 2014-11-08 21:38:57 +09:00
Tatsuhiro Tsujikawa
58254adb11 h2load: Print used SSL/TLS cipher name and parameters 2014-11-08 21:24:24 +09:00
Tatsuhiro Tsujikawa
7f60e8a307 Fix C++ lib sample 2014-11-08 16:52:03 +09:00
Tatsuhiro Tsujikawa
c31be5af4d Assign default priority if dep_stream in PRIORITY does not exist 2014-11-08 16:12:13 +09:00
Tatsuhiro Tsujikawa
292c01fda2 Add test to make sure that default priority is assigned 2014-11-08 11:37:53 +09:00
Tatsuhiro Tsujikawa
91f7d43e84 Assign default priority if dependency parent stream does not exist 2014-11-08 11:23:18 +09:00
Tatsuhiro Tsujikawa
ce71e65aee nghttpx: Replace WARNING with WARN for consistency 2014-11-08 10:51:56 +09:00
Tatsuhiro Tsujikawa
1119701071 nghttpx: Fix -L option help message
WARNING should be WARN.
2014-11-08 10:45:58 +09:00
Tatsuhiro Tsujikawa
42122c270a Don't reprioritize stream if it is not in dependency tree
Normally stream is in dependency tree, but sometimes it isn't.  For
example, client does not put pushed reserved stream in dependency
tree.
2014-11-08 10:31:53 +09:00
Tatsuhiro Tsujikawa
1348621d9e Fix bug that priority is ignored if dependency parent does not exist 2014-11-08 10:18:10 +09:00
Tatsuhiro Tsujikawa
8c5ea61376 Merge branch 'LPardue-log_notice' 2014-11-07 21:21:21 +09:00
Tatsuhiro Tsujikawa
c410f4055f Merge branch 'log_notice' of https://github.com/LPardue/nghttp2 into LPardue-log_notice 2014-11-07 21:15:02 +09:00
Tatsuhiro Tsujikawa
1e86635572 h2load: Make shutdown sequence simpler 2014-11-07 00:28:10 +09:00
Tatsuhiro Tsujikawa
62ede05c09 Fix heap-use-after-free due to duplicated push of DATA item 2014-11-06 23:47:41 +09:00
Lucas Pardue
a067eb02a5 Add LOG_NOTICE level logging for application lifecycle events 2014-11-06 14:32:56 +00:00
Tatsuhiro Tsujikawa
154876a17b nghttpx: Apply TLS record length limit to DATA frame payload
This is not obvious but it makes intermediaries flush and forward DATA
frame boundary without excessive buffering.  Since we have different
TCP connections frontend and backend, this may not work.  This is
still experimental.
2014-11-06 21:14:14 +09:00
Tatsuhiro Tsujikawa
f8c70993c0 nghttpx: Adjust TLS record size dynamically
Use the same behaviour the current Google server does: start with 1300
TLS record size and after transmitting 1MiB, change record size to
16384.  After 1 second idle time, reset to 1300.  Only applies to
HTTP/2 and SPDY upstream connections.
2014-11-06 02:36:53 +09:00
Tatsuhiro Tsujikawa
03a2828fcf src: Disable SSL_MODE_ENABLE_PARTIAL_WRITE for apps which use libevent 2014-11-05 01:15:38 +09:00
Tatsuhiro Tsujikawa
2fc0056ada nghttp: Allow multiple -v option to increase verbosity
Now the number of -v option specifies verbosity level.  Current all
verbose output are turned on for at lest one -v option, except for the
debug output for each data chunk which is only turned on more than one
-v options.
2014-11-05 00:42:12 +09:00
Tatsuhiro Tsujikawa
9a33116526 Fix bug in priority tree
This change fixes the bug that stream is out of dependency tree if the
number of nodes in a dependency tree which we add new node to is
already maximum (NGHTTP2_MAX_DEP_TREE_LENGTH) and the number of
maximum concurrent streams is more than more than
NGHTTP2_MAX_DEP_TREE_LENGTH.
2014-11-05 00:32:16 +09:00
Tatsuhiro Tsujikawa
29fcd7c946 nghttpd: Use http2::Headers 2014-11-02 23:33:04 +09:00
Tatsuhiro Tsujikawa
189f122dd7 nghttpd: Perform redirect if directory is requested 2014-11-02 23:27:38 +09:00
Tatsuhiro Tsujikawa
69c708be44 Bump up version number to 0.6.6-DEV 2014-11-02 23:27:16 +09:00
Tatsuhiro Tsujikawa
14e56fcd81 Update man pages 2014-10-31 00:11:38 +09:00
Tatsuhiro Tsujikawa
db67412511 Bump up version number to 0.6.5, LT revision to 7:0:2 2014-10-31 00:05:09 +09:00
Tatsuhiro Tsujikawa
76800dc8e7 Remove unused functions 2014-10-30 23:31:36 +09:00
Tatsuhiro Tsujikawa
7d282cd0bd Code cleanup 2014-10-30 23:31:28 +09:00
Tatsuhiro Tsujikawa
49b8d1d88c Rename max_header_set_size as max_header_list_size 2014-10-30 22:42:15 +09:00
Tatsuhiro Tsujikawa
4d93dd9d91 Upate to draft-15
* Add NGHTTP2_HTTP_1_1_REQUIRED error code
* Allow transmission of WINDOW_UPDATE on reserved (remote)
* Allow reception of WINDOW_UPDATE on reserved (local)
* Treat frame larger than MAX_FRAME_SIZE as FRAME_SIZE_ERROR

ALPN identifier is still h2-14 to continue interop, since draft-14 and
-15 are binary compatible.  The new error code was added in draft-15,
but HTTP/2 allows extensions can freely add new error code, so it is
not a problem.
2014-10-30 22:40:02 +09:00
Tatsuhiro Tsujikawa
be1a513c59 nghttpx: Shut up scan-build 2014-10-30 22:36:22 +09:00
Tatsuhiro Tsujikawa
20900b133e nghttpx: Fix heap-use-after-free in ClientHandler object
This bug was found by scan-build
2014-10-30 21:47:38 +09:00
Tatsuhiro Tsujikawa
279fc2ad37 Update doc 2014-10-30 00:56:19 +09:00
Tatsuhiro Tsujikawa
0ef99b90d9 asio-lib: Make request_cb take const ref and use int64_t as http_date arg 2014-10-28 01:01:48 +09:00
Tatsuhiro Tsujikawa
1bd8f6a0e2 Update doc 2014-10-28 00:51:51 +09:00
Tatsuhiro Tsujikawa
f70c142e10 doc: Remove note about legacy NULL concatenation of header field 2014-10-28 00:39:46 +09:00
Tatsuhiro Tsujikawa
b3fbf047b2 Update man pages 2014-10-28 00:35:44 +09:00
Tatsuhiro Tsujikawa
0cd8da2cd9 Update doc 2014-10-28 00:18:28 +09:00
Tatsuhiro Tsujikawa
7fa0f2763e nghttpx: Update Alt-Svc header field spec to alt-svc-04 2014-10-28 00:17:32 +09:00
Tatsuhiro Tsujikawa
f381b13c91 mod a+x to auto-gen scripts 2014-10-27 21:27:41 +09:00
Tatsuhiro Tsujikawa
6b9382d865 Add comments to the auto-generated table 2014-10-27 21:27:03 +09:00
Tatsuhiro Tsujikawa
2c335dbc7a Add more comment about local window size adjustment 2014-10-27 21:24:41 +09:00
Tatsuhiro Tsujikawa
b3463b20a3 Update doc 2014-10-27 21:24:41 +09:00
Tatsuhiro Tsujikawa
15bdf048cc mkstatictbl.py: Update doc 2014-10-27 21:24:41 +09:00
Tatsuhiro Tsujikawa
992ca93533 mkhufftbl.py: Update doc 2014-10-27 21:24:41 +09:00
Tatsuhiro Tsujikawa
b4ed3324c0 mkcipherlist.py: Update doc 2014-10-27 21:24:41 +09:00
Tatsuhiro Tsujikawa
98fd6019cf man2rst.py: Add purpose of the script 2014-10-27 21:24:41 +09:00
Tatsuhiro Tsujikawa
6ccae48f7c man2rst.py: Add "DO NOT MODIFY THIS FILE!" comment 2014-10-27 21:24:41 +09:00
Tatsuhiro Tsujikawa
6933e0ef54 h2load: Use Headers instead of std::vector<std::pair<>> to store custom headers 2014-10-27 21:23:36 +09:00
Tatsuhiro Tsujikawa
a9ecdca08a h2load: Read URIs from stdin if -i- is used 2014-10-27 21:23:36 +09:00
Tatsuhiro Tsujikawa
af5bedd45f h2load: Move code pasing URIs to separate function 2014-10-27 21:23:36 +09:00
Tatsuhiro Tsujikawa
7097a31968 h2load: Uniform handling of URIs from command-line and file 2014-10-27 21:23:36 +09:00
Tatsuhiro Tsujikawa
4122920dc6 h2load: Fix doc and remove trailing spaces 2014-10-27 21:23:36 +09:00
Tatsuhiro Tsujikawa
9aed11e3dc Merge branch 'LPardue-master' 2014-10-27 21:22:21 +09:00
Lucas Pardue
9ea4905f68 Added X-Forwarded-For header stripping option to nghttpx 2014-10-27 10:23:20 +00:00
Tatsuhiro Tsujikawa
c6cfcc3c30 src: Disable insecure SSLv3 2014-10-22 23:14:07 +09:00
Tatsuhiro Tsujikawa
4bc5e55113 Merge branch 'kennypeng-header_add_override' 2014-10-22 21:30:31 +09:00
Tatsuhiro Tsujikawa
566a252577 Merge branch 'header_add_override' of https://github.com/kennypeng/nghttp2 into kennypeng-header_add_override 2014-10-22 21:25:53 +09:00
Kenny (kang-yen) Peng
27c766cb04 fix some comments and descriptions 2014-10-21 22:38:45 +00:00
Kenny (kang-yen) Peng
41dd6d0205 use option i to accept input URI list file 2014-10-21 22:29:36 +00:00
Kenny (kang-yen) Peng
db071ca35c fix comments of header add/override 2014-10-21 21:25:38 +00:00
Tatsuhiro Tsujikawa
e3af9d8bd3 nghttp: Use Headers to store custom headers 2014-10-21 23:24:50 +09:00
Tatsuhiro Tsujikawa
73955f0519 nghttp: Take advantage the fact that custom headers are already lower cased 2014-10-21 23:17:53 +09:00
Tatsuhiro Tsujikawa
5df21e3683 nghttp: Add missing metavar to -H and add example 2014-10-21 22:47:24 +09:00
Kenny (kang-yen) Peng
a6e1a40c05 support uri list file input 2014-10-20 20:59:55 +00:00
Tatsuhiro Tsujikawa
e330520341 Fix compile error on arm 2014-10-19 22:40:39 +09:00
Tatsuhiro Tsujikawa
d13ed04b17 Add Dockerfile.android 2014-10-19 21:51:43 +09:00
Tatsuhiro Tsujikawa
75a23c6c7e Add sample nghttpx logrotate configuration 2014-10-19 18:09:01 +09:00
Tatsuhiro Tsujikawa
eaca5d83b0 Add nghttpx init file for convenience 2014-10-19 18:06:34 +09:00
Tatsuhiro Tsujikawa
9c1b5e8fb1 Update .gitignore 2014-10-18 18:55:42 +09:00
Tatsuhiro Tsujikawa
0c31dbb5d9 Add aux script 2014-10-18 18:55:07 +09:00
Tatsuhiro Tsujikawa
8a0b11e9e1 Add aux script 2014-10-18 18:54:50 +09:00
Tatsuhiro Tsujikawa
7ca2787cc8 man2rst.py: Erase \& 2014-10-18 18:29:59 +09:00
Tatsuhiro Tsujikawa
cfbf907418 doc: Disable smartypants since we use '--' prefix for cmd options 2014-10-18 18:25:37 +09:00
Kenny Peng
dd02c4cd9b support header add/override 2014-10-17 15:25:59 -07:00
Tatsuhiro Tsujikawa
93ee5bdba6 REAMDE.rst: Add make and binutils to required ubuntu packages 2014-10-17 23:55:08 +09:00
Tatsuhiro Tsujikawa
f2aa6f4e2b nghttp: Document prioritization with -a option 2014-10-16 23:17:19 +09:00
Tatsuhiro Tsujikawa
bc8a583184 Refactor stream tree code 2014-10-16 21:59:52 +09:00
Tatsuhiro Tsujikawa
502ff24568 Avoid iterate siblings when adding/removing stream tree 2014-10-16 01:12:59 +09:00
Tatsuhiro Tsujikawa
47692d113c Bump up version number to 0.6.5-DEV 2014-10-14 23:49:10 +09:00
Tatsuhiro Tsujikawa
19c2805d0d Update man pages 2014-10-14 23:30:44 +09:00
Tatsuhiro Tsujikawa
df078dc004 Bump up version number to 0.6.4
Library code has not changed at all since the last release, so LT
revision stays the same.
2014-10-14 23:27:35 +09:00
Tatsuhiro Tsujikawa
e570225e97 tiny-nghttpd: Simplify timer event handling 2014-10-14 21:52:30 +09:00
Tatsuhiro Tsujikawa
8fffa05513 src: Fix possible heap-use-after free for OpenSSL global locking
This is simply programming error, but it is interesting that using
libstdc++ does not reveal this error.  With clang++-libc++, we got
std::system_error: mutex lock faild: Invalid argument.  This is
because we did not give a name to lock object, so it is immediately
destructed.  I think this will fix the reported crash on Mac OSX.
2014-10-14 21:47:07 +09:00
Tatsuhiro Tsujikawa
0d4120ce2c nghttpx: Apply same fix from a225bb2 to spdy upstream 2014-10-13 21:13:45 +09:00
Tatsuhiro Tsujikawa
20de432725 nghttpx: Pool http downstream connection per thread 2014-10-13 21:09:00 +09:00
Tatsuhiro Tsujikawa
325bb0115e Bump up version number to 0.6.4-DEV 2014-10-11 00:22:25 +09:00
Tatsuhiro Tsujikawa
cc3b41ec96 Bump up version number to 0.6.3, LT revision to 6:1:1 2014-10-11 00:08:32 +09:00
Tatsuhiro Tsujikawa
225b90eefd Use switch-case instead of if 2014-10-10 22:52:47 +09:00
Tatsuhiro Tsujikawa
3931a0b04d Fix bugs found by coverity scan 2014-10-10 22:50:35 +09:00
Tatsuhiro Tsujikawa
70c0558443 Set payload length when expected SETTINGS is not received 2014-10-10 21:46:02 +09:00
Tatsuhiro Tsujikawa
f2bfe623fc Update doc 2014-10-09 21:40:26 +09:00
Tatsuhiro Tsujikawa
80dcb565eb Check first SETTINGS strictly 2014-10-09 21:37:18 +09:00
Tatsuhiro Tsujikawa
6d42b6697b examples: Disable tiny-nghttpd if timerfd_create is not available 2014-10-09 21:18:24 +09:00
Tatsuhiro Tsujikawa
bcbb2e8649 src: Use fcntl and FD_CLOEXEC if O_CLOEXEC is undefined
We may run into race condition if execve is called at the same time
when fcntl is called.  But we just does this for now to compile
nghttp2 applications under older kernel.
2014-10-08 23:44:38 +09:00
Tatsuhiro Tsujikawa
ba92935f64 Define NOTHREADS if std:future is not available 2014-10-08 23:36:55 +09:00
Tatsuhiro Tsujikawa
402c262de5 Push stream to queue after effective weight was calculated 2014-10-08 22:44:02 +09:00
Tatsuhiro Tsujikawa
03c4092862 Distribute closed or blocked stream's weight to its siblings
This also means that at least one stream whose dpri is
NGHTTP2_STREAM_DPRI_TOP exists, its siblings descendants have no
chance to send streams, even if their parent stream has
NGHTTP2_STREAM_DPRI_NODATA.
2014-10-07 23:52:36 +09:00
Tatsuhiro Tsujikawa
a225bb29df nghttpx: Fix request is sent to backend prematurely with http2 upstream 2014-10-07 00:31:35 +09:00
Tatsuhiro Tsujikawa
f3a76d84f1 Document that only one data is allowed for one stream at a time 2014-10-06 23:47:43 +09:00
Tatsuhiro Tsujikawa
7a09feebc3 h2load: Don't use std::future with --disable-threads
Now we don't use std::future with --disable-threads, checking
std::future in configure.ac was removed and building h2load is always
enabled.
2014-10-05 14:25:15 +09:00
Tatsuhiro Tsujikawa
32ddca532a Use 256 elements table in nghttp2_downcast 2014-10-04 00:40:51 +09:00
Svante Signell
df875db989 Avoid PATH_MAX by using getcwd(nullptr, 0) as supported by modern glibc-based OSes. 2014-10-03 21:58:15 +09:00
Tatsuhiro Tsujikawa
1d138accb9 Unify DATA and other frames in nghttp2_outbound_item and save malloc() 2014-10-03 21:31:37 +09:00
Tatsuhiro Tsujikawa
7e6019aef1 nghttp2_hd: Don't malloc if name/value is in first chunk without indexing 2014-09-30 23:01:58 +09:00
Tatsuhiro Tsujikawa
e20b417b84 Embed aux_data to nghttp2_outbound_item so that we can save some malloc() calls 2014-09-30 21:45:15 +09:00
Tatsuhiro Tsujikawa
df56b69060 nghttp2_map: Use initial size 256 so that we don't resize it until 100 streams 2014-09-29 22:46:13 +09:00
Tatsuhiro Tsujikawa
b6d0a32d0e tiny-nghttpd: Save number of read(2) calls using file size 2014-09-29 22:37:41 +09:00
Tatsuhiro Tsujikawa
a82956d1d6 nghttp2_hd: Use binary search to lookup static table (again) 2014-09-29 21:58:37 +09:00
Tatsuhiro Tsujikawa
9c0760e3c1 Bump up version number to 0.6.3-DEV 2014-09-29 00:08:21 +09:00
Tatsuhiro Tsujikawa
4e71e9e2e8 Update man pages 2014-09-28 23:34:07 +09:00
Tatsuhiro Tsujikawa
521450c7ad Bump up version number to 0.6.2, LT revision to 6:0:1 2014-09-28 23:33:10 +09:00
Tatsuhiro Tsujikawa
aa57e91e85 Fix make distcheck 2014-09-28 23:29:57 +09:00
Tatsuhiro Tsujikawa
4023c26cf1 Update doc 2014-09-28 23:24:39 +09:00
Tatsuhiro Tsujikawa
a0f558ee3c doc: Add example to use nghttp2::asio_http2::server::request::run_task 2014-09-28 16:55:32 +09:00
Tatsuhiro Tsujikawa
4f0d03b4b9 libnghttp2_asio: Move common types and functions to nghttp2::asio_http2 ns 2014-09-28 16:54:00 +09:00
Tatsuhiro Tsujikawa
88d7abcc23 libnghttp2_asio: Add request::run_task to execute task in separate thread 2014-09-28 16:25:45 +09:00
Tatsuhiro Tsujikawa
409316018d examples: Fix travis error: unreachable-code 2014-09-28 00:02:13 +09:00
Tatsuhiro Tsujikawa
d25b9da9f6 Check Boost library only when it is requested 2014-09-27 23:50:33 +09:00
Tatsuhiro Tsujikawa
b48ceac56c nghttp2_hd: Search dynamic table first
Since recently used headers are in dynamic header table, it is
advantageous to search dynamic table first, saving time to search
through static table.
2014-09-27 23:45:58 +09:00
Tatsuhiro Tsujikawa
34413d8d7c examples: Build tiny-nghttpd only when epoll is available 2014-09-27 23:45:57 +09:00
Tatsuhiro Tsujikawa
b7ccca4c47 examples: Add tiny-nghttpd
tiny-nghttpd is HTTP/2 server and its purpose is measure the
performance of nghttp2 library code.  Currently it only accepts direct
HTTP/2 connection only.
2014-09-27 23:44:33 +09:00
Tatsuhiro Tsujikawa
e887b2516f Remove boost LDFLAGS from examples 2014-09-26 21:42:31 +09:00
Tatsuhiro Tsujikawa
be0f6dcaaf Clear 2 types of stream deferred flag indenpendently
Previously when nghttp2_stream_resume_deferred_data() is called,
deferred flags in stream->flags are all cleared.  This is not ideal
because if application returned NGHTTP2_ERR_DEFERRED, and also that
stream is deferred by flow control, then all flags are cleared and
read callback will be invoked again.  This commit fixes this issue.
This changes error condition of nghttp2_session_resume_data().
Previously we return error if stream was deferred by flow control.
Now we don't return error in this case.  We just clear
NGHTTP2_FLAG_DEFERRED_USER and if still
NGHTTP2_FLAG_DEFERRED_FLOW_CONTROL is set, just return 0.
2014-09-26 21:32:17 +09:00
Tatsuhiro Tsujikawa
937bb9f768 Update doc 2014-09-26 01:25:00 +09:00
Tatsuhiro Tsujikawa
a11fbf6e2f Optimize connection level remote flow control
Previously when connection level remote flow control window gets 0, we
mark the stream having DATA frame with
NGHTTP2_STREAM_FLAG_DEFERRED_FLOW_CONTROL.  When connection level
WINDOW_UPDATE is received, we checks all existing streams, including
closed ones, and call nghttp2_stream_resume_deferred_data().  The
profiler shows this is expensive.

Now we prepare dedicated priority queue for DATA frames.  And we don't
mark stream with NGHTTP2_STREAM_FLAG_DEFERRED_FLOW_CONTROL when DATA
cannot be sent solely due to connection level flow control.  Instead,
we just queue DATA item to queue.  We won't pop DATA item from queue
when connection level remote window size is 0.  This way, we avoid the
expensive operation for all streams when WINDOW_UPDATE is arrived.
2014-09-26 00:01:51 +09:00
Tatsuhiro Tsujikawa
9aa914c756 Update README.rst 2014-09-25 02:08:09 +09:00
Tatsuhiro Tsujikawa
e20d2ba9c1 nghttpx: Don't send x-forwarded-proto if -s or -p is used 2014-09-25 00:41:38 +09:00
Tatsuhiro Tsujikawa
c1be28684a libnghttp2_asio: Add request::closed() to indicate that stream has been closed 2014-09-25 00:15:52 +09:00
Tatsuhiro Tsujikawa
fd07f5e142 src: Add utility APIs to asio_http2.h; add asio-sv2 example to serve files 2014-09-24 23:05:13 +09:00
Tatsuhiro Tsujikawa
99ca15cae0 Lower boost version requirement to 1.54.0 2014-09-24 21:07:37 +09:00
Tatsuhiro Tsujikawa
3651467c71 src: Silence compiler warning 2014-09-24 00:57:43 +09:00
Tatsuhiro Tsujikawa
c27ec6f57b doc: Add doc how to enable multi threading in libnghttp2_asio 2014-09-24 00:45:40 +09:00
Tatsuhiro Tsujikawa
485d04851c Add libnghttp2_asio.pc to .gitignore 2014-09-24 00:45:40 +09:00
Tatsuhiro Tsujikawa
83728219db Update doc 2014-09-24 00:45:40 +09:00
Tatsuhiro Tsujikawa
5d0bf4cc84 Add C++ library libnghttp2_asio on top of libnghttp2
The libnghttp2_asio library is C++ library built on top of libnghttp2.
Currently, it has server API and easily create HTTP/2 server using
node.js like API calls.  See the example server source code in
examples/asio-sv.cc.  The library depends on Boost::ASIO library.
2014-09-24 00:45:40 +09:00
Tatsuhiro Tsujikawa
446f8f13aa src: Move libevent related helper functions to libevent_util 2014-09-24 00:45:40 +09:00
Tatsuhiro Tsujikawa
96bb9c2018 Move Makefile.msvc under lib 2014-09-24 00:44:45 +09:00
Tatsuhiro Tsujikawa
a9b74261b6 nghttpd: Rewrite using bufferevent (again) for simplicity 2014-09-19 00:58:32 +09:00
Tatsuhiro Tsujikawa
89c3c08590 tests: Fix compiler warning 2014-09-19 00:20:54 +09:00
Tatsuhiro Tsujikawa
83309b6391 nghttpx: Reduce epoll_ctl call 2014-09-18 23:56:01 +09:00
Tatsuhiro Tsujikawa
23dd428d65 nghttpx: Reset timeouts when either read or write succeeds
See previous commit message why we need this.
2014-09-18 23:19:28 +09:00
Tatsuhiro Tsujikawa
b305495a75 nghttpx: Reset both timeouts when either read or write succeeds
Previously read and write timeouts work independently.  When we are
writing response to the client, read timeout still ticks (e.g., HTTP/2
or tunneled HTTPS connection).  So read timeout may occur during long
download.  This commit fixes this issue.  This commit only fixes the
upstream part.  We need similar fix for the downstream.
2014-09-18 23:03:36 +09:00
Tatsuhiro Tsujikawa
727662257c Add missing NGHTTP2_ERR_BAD_PREFACE to nghttp2_strerror 2014-09-17 23:25:47 +09:00
Tatsuhiro Tsujikawa
b2f88f8fe3 Fix memory leak around stream->data_item
Previously we missed the case where stream->data_item is not deleted
and it caused leak.  Now stream->data_item is properly deleted when
session is deleted.  We decided not to delete data_item in
nghttp2_stream_free() since we need nghttp2_session to decide whether
data_item should be deleted or not there.
2014-09-17 23:16:00 +09:00
Tatsuhiro Tsujikawa
44ac571037 nghttpx: Add more handling situation where response ends before request 2014-09-17 22:53:29 +09:00
Tatsuhiro Tsujikawa
5bff48a15a nghttpx: Call upstream resume_read after sending pending request to backend
With the combination of HTTP/1 upstream and HTTP/2 downstream,
downstream tells SHRPX_NO_BUFFER while connecting to the backend
server.  Previously, we did not call upstream resume_read and upload
was blocked.  This commit now calls upstream resume_read to unblock.
This commit also remove pending output buffer size of Http2Session
when calculating downstream connection's buffer is full.  This is
desirable since we only operate resume_read by stream basis.
2014-09-17 22:36:42 +09:00
Tatsuhiro Tsujikawa
e4751a798a Replace auto_delete* with defer 2014-09-16 23:39:38 +09:00
Tatsuhiro Tsujikawa
6fc12caa6d Just link to github releases page for released versions 2014-09-14 22:46:59 +09:00
Tatsuhiro Tsujikawa
d00d4d647d Compile with android NDK r10b 32bit target
Android does not have _Exit.  We detect this and use _exit instead.
clang-3.4 has an issue around undefined reference to
__atomic_fetch_add_4, so we stick to gcc-4.8 for now.
2014-09-14 21:32:53 +09:00
Tatsuhiro Tsujikawa
5ff73de195 libevent-server: Use nghttp2_option_set_recv_client_preface() 2014-09-13 21:24:45 +09:00
Tatsuhiro Tsujikawa
901de5fbce Add nghttp2_option_set_recv_client_preface()
By default, nghttp2 library only handles HTTP/2 frames and does not
recognize first 24 bytes of client connection preface. This design
choice is done due to the fact that server may want to detect the
application protocol based on first few bytes on clear text
communication. But for simple servers which only speak HTTP/2, it is
easier for developers if nghttp2 library takes care of client
connection preface.

If this option is used with nonzero val, nghttp2 library checks first
24 bytes client connection preface. If it is not a valid one,
nghttp2_session_recv() and nghttp2_session_mem_recv() will return
error NGHTTP2_ERR_BAD_PREFACE, which is fatal error.
2014-09-13 19:50:44 +09:00
Tatsuhiro Tsujikawa
5847a56c40 Bump up version number to 0.6.2-DEV 2014-09-11 00:36:56 +09:00
Tatsuhiro Tsujikawa
0da0140026 Update man pages 2014-09-11 00:31:02 +09:00
Tatsuhiro Tsujikawa
207b1db6af Bump up version number to 0.6.1 2014-09-11 00:28:48 +09:00
Tatsuhiro Tsujikawa
85f605f20d src: Check availability of ENONET 2014-09-02 01:00:27 +09:00
Tatsuhiro Tsujikawa
5cf07f5c21 Bump up version number to 0.6.1-DEV 2014-08-30 00:18:25 +09:00
Tatsuhiro Tsujikawa
340b52da84 Update man pages 2014-08-30 00:15:31 +09:00
Tatsuhiro Tsujikawa
3de678e164 Bump up version number to 0.6.0 and LT revision to 5:0:0 2014-08-30 00:09:37 +09:00
Tatsuhiro Tsujikawa
0af71ee6be Update sphinx_rtd_theme 2014-08-30 00:07:48 +09:00
Tatsuhiro Tsujikawa
d8c0d87c90 src: Add missing SETTINGS ID to debug output
SETTINGS_MAX_FRAME_SIZE and SETTINGS_MAX_HEADER_LIST_SIZE are 2
missing SETTINGS IDs and now they are shown correctly.
2014-08-29 00:14:10 +09:00
Tatsuhiro Tsujikawa
9b2c24ad68 tests: Remove debug output 2014-08-28 23:32:14 +09:00
Tatsuhiro Tsujikawa
b4bb6a6101 Add reserved bits to header and frames
Currently reserved bit is always set to 0.  The addition of reserved
bit is for future extension.
2014-08-28 23:30:42 +09:00
Tatsuhiro Tsujikawa
8890e593e6 src: Add util::array_size 2014-08-28 00:45:12 +09:00
Tatsuhiro Tsujikawa
ec0a2e7cca Add Makefile for MSVC
Contributed by G. Vanem
2014-08-27 23:54:29 +09:00
Tatsuhiro Tsujikawa
f8471a5f45 nghttpx: Move --backend-http-proxy-uri to Connections section 2014-08-27 23:37:54 +09:00
Tatsuhiro Tsujikawa
f34cbf9b45 tests: Include config.h 2014-08-27 23:36:57 +09:00
Tatsuhiro Tsujikawa
a23a705121 nghttpx: Strict integer config validation 2014-08-27 23:36:36 +09:00
Tatsuhiro Tsujikawa
822ec75814 nghttpx: Add --listener-disable-timeout option 2014-08-27 22:34:00 +09:00
Tatsuhiro Tsujikawa
0209b7c083 nghttpx: Fix location rewrite is failed because request headers are empty
Previously we empties request headers after they are sent to
downstream in order to free memory.  But it turns out that we use
request headers when rewriting location header response field.  Also
user reported that request headers are useful to add new features.
This commits defers the deletion of request headers to the point when
response headers are deleted (which is after response headers are sent
to upstream client).
2014-08-27 21:25:25 +09:00
Tatsuhiro Tsujikawa
70a8fd59b1 python: Add version 2014-08-26 23:52:19 +09:00
Tatsuhiro Tsujikawa
223242b512 nghttpx: Don't consume response data in downstream on_stream_close_callback
Even after on_stream_close_callback, Http2DownstreamConnection is
still alive and upstream keeps sending response to the client.  The
consumed bytes are processed normally (data_source_read_callback) and
also we have a code to consume all allocated bytes for
Http2DownstreamConnection object when it is deleted.  This means that
we don't need to and should not consume response data in downstream
on_stream_close_callback.  If we do, we may get assertion error in
Http2DownstreamConnection::resume_read().
2014-08-26 22:16:19 +09:00
Tatsuhiro Tsujikawa
42ac80d3da python: Fix build error 2014-08-26 00:13:53 +09:00
Tatsuhiro Tsujikawa
4c11cd0671 Add test to submit DATA frame twice
This commit adds test to submit DATA frame twice and fixes the bug
that 2nd DATA is not sent.
2014-08-25 23:46:17 +09:00
Tatsuhiro Tsujikawa
4c5c6749a0 Check buffer capacity explicitly 2014-08-25 23:12:17 +09:00
Tatsuhiro Tsujikawa
dd038bf753 Fix crash when buffer was reallocated after read_length_callback
Added test for this crash.
2014-08-25 23:05:39 +09:00
Tatsuhiro Tsujikawa
577512f2ca Use datamax if buffer reallocation failed 2014-08-25 22:46:55 +09:00
Tatsuhiro Tsujikawa
565c635e9b Wrap longer lines (> 80) 2014-08-25 22:41:34 +09:00
Tatsuhiro Tsujikawa
0b1ab90fb8 Move frame_type parameter in front of stream_id
This commit moves frame_type parameter of
nghttp2_data_soruce_read_length_callback in front of stream_id
parameter.  The motivation is that other callback is generally put
frame related parameters first.  To make it consistent, we move
frame_type, which is frame ralted parameter, to the left.
2014-08-25 22:31:11 +09:00
Tatsuhiro Tsujikawa
93b4d9efc3 Allow application to call nghttp2_submit_data() in on_frame_send_callback
Previously we always call on_frame_send_callback before calling
nghttp2_stream_detach_data() after sending DATA frame.  As a result,
even if DATA frame has END_STREAM, application cannot call
nghttp2_submit_data() in on_frame_send_callback because previous data
is still attached.  This commit makes a change so that
nghttp2_stream_detach_data() is called before on_frame_send_callback
so that application can issue nghttp2_submit_data() in the callback.
2014-08-25 21:53:40 +09:00
Tatsuhiro Tsujikawa
82bc7198e6 Change nghttp2_session_get_stream_remote_window_size behavior
Now it returns only stream's available remote window size, without
considering connection level window size.  For connection-level window
size, nghttp2_session_get_remote_window_size() is added by this
commit.  To get old behavior of
nghttp2_session_get_stream_remote_window_size() is use
min(nghttp2_session_get_stream_remote_window_size(),
nghttp2_session_get_remote_window_size()).  The reason of this change
is that it is desirable to know just stream level window size without
taking into connection level window size.  This is useful for
debugging purpose.
2014-08-25 21:44:22 +09:00
Tatsuhiro Tsujikawa
03ed29953e Move nghttp2_data_source_read_length_callback to session callbacks section
Also edited its documentation to make hyperlink works.
2014-08-25 21:38:08 +09:00
Tatsuhiro Tsujikawa
a36c4c6f5f Add nghttp2_on_begin_frame_callback
nghttp2_on_begin_frame_callback will be invoked when a frame header is
received.
2014-08-25 21:26:50 +09:00
Tatsuhiro Tsujikawa
3daa6f2c30 doc: Update tutorials 2014-08-25 21:24:04 +09:00
Tatsuhiro Tsujikawa
53ee21caa9 Remove nghttp2_on_unknown_frame_recv_callback
It is not used by library for a while.  It could be used to pass
unsupported extension frames to application, but its interface
requires library to buffer entire frame, which we'd like to avoid.
For unsupported extension frames, we will add new callbacks which does
not require buffering if they are required.
2014-08-25 21:24:04 +09:00
Tatsuhiro Tsujikawa
31528b6267 Use uint32_t for HTTP/2 error_code
h2-14 now allows extensions to define new error codes.  To allow
application callback to access such error codes, we uses uint32_t as
error_code type for structs and function parameters.  Previously we
treated unknown error code as INTERNAL_ERROR, but this change removes
this and unknown error code is passed to application callback as is.
2014-08-25 21:24:04 +09:00
Tatsuhiro Tsujikawa
ab5b81bee1 Hide nghttp2_session_callbacks details and provide setter like functions
To make it possible to add new callbacks without bumping so name, we
decided to hide details of nghttp2_session_callbacks.  We provide
setter like functions to set individual callback function.
2014-08-25 21:24:04 +09:00
Tatsuhiro Tsujikawa
9f6bb989e3 Merge branch 'akamai-window_size_control' 2014-08-25 21:15:38 +09:00
Tatsuhiro Tsujikawa
3655090997 Merge branch 'window_size_control' of https://github.com/akamai/nghttp2 into akamai-window_size_control 2014-08-25 21:09:26 +09:00
Scott Mitchell
3cd08251ca Send window size API extension
Motivation:

The send window size is currently fixed by a macro at compile time.
In order for users of the library to impact the send window size they
would have to change a macro at compile time. The window size may be dynamic
depending on the environment and deployment scheme. The library users
currently have no way to change this parameter.

Modifications:

Add a new optional callback method which is called before data is sent to
obtain the desired send window size. The callback return value will be
subject to a range check for the current session, stream, and settings
limits defined by flow control.

Result:
Library users have control over their send sizes.
2014-08-24 11:32:44 -04:00
Tatsuhiro Tsujikawa
1673ae2c99 src: Add 308 Permanent Redirect (RFC 7238) 2014-08-24 22:56:48 +09:00
Tatsuhiro Tsujikawa
bf48ef9bab Add test to check consumed size when no auto window update is enabled 2014-08-24 22:36:35 +09:00
Tatsuhiro Tsujikawa
1093b3eeab Check explicitly that padding field is really read 2014-08-24 22:29:05 +09:00
Tatsuhiro Tsujikawa
d5da7611fa nghttpx: Remove unused member function and variable 2014-08-24 22:27:10 +09:00
Tatsuhiro Tsujikawa
9893ae81af Add nghttp2_bufs_realloc 2014-08-24 15:34:55 +09:00
Tatsuhiro Tsujikawa
7bfa276e96 Fix bug that NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE causes session failure
Previously returning NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE from
on_header_callback moves input offset badly and it causes header
decompression error on the subsequent frames.  This commit fix this
bug.
2014-08-24 00:50:55 +09:00
Tatsuhiro Tsujikawa
02c5621c61 Refactor functions to update consumed size 2014-08-23 18:56:04 +09:00
Tatsuhiro Tsujikawa
9ad2c0887e nghttpx: Use _Exit() instead of exit() when execve is failed in child process 2014-08-23 18:15:47 +09:00
Tatsuhiro Tsujikawa
0c7e2fbec6 Use parenthesis explicitly for bit wise operation 2014-08-23 18:03:20 +09:00
Tatsuhiro Tsujikawa
cfee9cab36 Avoid possible double-free and make nghttp2_buf{s}_free(NULL) success 2014-08-23 11:16:49 +09:00
Tatsuhiro Tsujikawa
679a0a0fa1 README.rst: Require spdylay >= 1.3.0 2014-08-21 22:50:19 +09:00
Tatsuhiro Tsujikawa
d5dcbf6f3b nghttpx: Fix possible flow control issue
Previously we only update consumed flow control window when number of
bytes read in nghttp2 and spdylay callback is 0.  Now we notify
nghttp2 library the consumed bytes even if number of bytes read > 0.
This change also uses newly added spdylay_session_consume() API, so we
require spdylay >= 1.3.0.
2014-08-21 21:22:16 +09:00
Tatsuhiro Tsujikawa
69b9ce6b68 nghttpx: Fix possible deadlock due to exhaustion of send window 2014-08-20 01:39:07 +09:00
Tatsuhiro Tsujikawa
c81e87bf37 nghttpx: Fix dereference after null check 2014-08-20 00:17:50 +09:00
Tatsuhiro Tsujikawa
97533c966d nghttpx: Fix gcc compiler warning 2014-08-20 00:09:18 +09:00
Tatsuhiro Tsujikawa
d6b495f2a7 nghttpx: Returns 503 if downstream connect fail for https upstream 2014-08-19 23:41:53 +09:00
Tatsuhiro Tsujikawa
c7e9fe8154 nghttpx: Implement connection blocker for HTTP/1 backend 2014-08-19 23:36:04 +09:00
Tatsuhiro Tsujikawa
fb62a5ed4f nghttpx: Use pointer for worker_config 2014-08-19 22:29:44 +09:00
Tatsuhiro Tsujikawa
345121975a nghttpx: Handle socket creation error 2014-08-19 22:29:44 +09:00
Tatsuhiro Tsujikawa
a5dfe24e49 nghttpx: Use std::unique_ptr for DownstreamConnection 2014-08-19 00:20:57 +09:00
Tatsuhiro Tsujikawa
273d9f4f7d nghttpx: Use std::unique_ptr for Downstream object 2014-08-19 00:20:56 +09:00
Tatsuhiro Tsujikawa
500c5eea56 nghttpx: Rename Http2Upstream::add_downstream as add_pending_downstream 2014-08-18 21:38:03 +09:00
Tatsuhiro Tsujikawa
83a39f5b49 nghttpx: Fix stream handling of upgraded request 2014-08-18 21:36:55 +09:00
Tatsuhiro Tsujikawa
2fb675f13c nghttpx: Open default log files for errors occurred while parsing options 2014-08-17 22:37:30 +09:00
Tatsuhiro Tsujikawa
eebd1f5492 nghttpx: Add some more info about prohibition of --read-burst=0 2014-08-17 22:31:44 +09:00
Tatsuhiro Tsujikawa
00ead22395 Don't allow frame submission for pending new frame
This is partial revert of bbe4f5a3d1.
Only documentation is reverted.  Since we have 2 queues to handle
maximum concurrent streams, we are not ready to allow immediate frame
submission for pending new frames.
2014-08-17 21:26:56 +09:00
Tatsuhiro Tsujikawa
2b4bd57c7f doc: Add building-android-binary document 2014-08-17 19:15:19 +09:00
Tatsuhiro Tsujikawa
86dd1519b4 nghttpx: Android specific hack for special files for logging
Android lacks /dev/stderr, so directly use /proc/self/fd/2 as default
errorlog-file.  Android does not like O_APPEND for /proc/self/fd/1 and
/proc/self/fd/2, so omit the flag for these paths.
2014-08-17 19:01:51 +09:00
Tatsuhiro Tsujikawa
a507fc80b6 Isolate std::future when NOTHREADS is defined and build without SOCK_{NONBLOCK, CLOEXEC} 2014-08-17 18:50:10 +09:00
Tatsuhiro Tsujikawa
69c3920a1a android-config: Disable libxml2 for user build, use long clang names 2014-08-17 18:49:21 +09:00
Tatsuhiro Tsujikawa
bbe4f5a3d1 Allow frame submission immediately after nghttp2_submit_{request,headers,pp}
This commit makes handling of outgoing HEADERS and PUSH_PROMISE in the
same priority of other frames on the stream, so these frames are
processed in the order they are submitted.  This allows application to
submit frames to a stream returned by nghttp2_submit_{request,
headers, push_promise} immediately.  The only exception is
WINDOW_UPDATA frame, which requires nghttp2_stream object, which is
not created yet.
2014-08-17 17:31:43 +09:00
Tatsuhiro Tsujikawa
49a9ec2cb3 nghttpx: Use int for resonse_rst_stream_error_code_ 2014-08-17 16:36:02 +09:00
Tatsuhiro Tsujikawa
5d2390deba nghttpx: Bring per-connection rate limit back
--read-burst=0 still does not work.  But specifying n > 0 workarounds
this.
2014-08-17 16:17:10 +09:00
Tatsuhiro Tsujikawa
02c347fe6b Add text dealing license around contribution to COPYING 2014-08-17 15:10:57 +09:00
Tatsuhiro Tsujikawa
3c056973a1 nghttpx: Ignore SIGCHLD not to create zombie on SIGUSR2 if -D is used 2014-08-17 00:05:24 +09:00
Tatsuhiro Tsujikawa
d17f35a488 Add Contribution section to README.rst 2014-08-16 23:23:52 +09:00
Tatsuhiro Tsujikawa
1b8ad61779 doc: Add note how to re-open log files in nghttpx 2014-08-16 23:00:35 +09:00
Tatsuhiro Tsujikawa
ede801d099 doc: Update man pages 2014-08-16 22:54:15 +09:00
Tatsuhiro Tsujikawa
9649b2d346 doc: Fix typo 2014-08-16 22:53:12 +09:00
Tatsuhiro Tsujikawa
53e52194b5 Bump up version number to 0.6.0-DEV 2014-08-16 22:50:33 +09:00
Tatsuhiro Tsujikawa
0e8419ac37 nghttpx: Add backend-connections-per-frontend option
This option limits the number of backend connections per frontend.
This is meaningful for the combination of HTTP/2 and SPDY frontend and
HTTP/1 backend.
2014-08-16 22:24:17 +09:00
Tatsuhiro Tsujikawa
da08ba5d50 nghttpx: Reset upstream timer on upgrade 2014-08-15 10:29:46 +09:00
Tatsuhiro Tsujikawa
30fa6d24d0 nghttpx: Rewirte server header field if configured as reverse proxy 2014-08-14 22:45:21 +09:00
Tatsuhiro Tsujikawa
f776c50d43 nghttpx: Just record error code when RST_STREAM is received
libnghttp2 will call on_stream_close callback when RST_STREAM is
received.  So we can use on_stream_close callback to handle existing
stream, instead of on_frame_recv callback.
2014-08-14 12:48:30 +09:00
Tatsuhiro Tsujikawa
7b85f6c50d nghttpx: Store errno to a variable temporarly 2014-08-13 22:13:08 +09:00
Tatsuhiro Tsujikawa
21cbf417c8 nghttpx: Use SOCK_NONBLOCK and SOCK_CLOEXEC flag in socketpair to avoid race 2014-08-13 22:09:35 +09:00
Tatsuhiro Tsujikawa
ca680c16e3 nghttpx: Chown file to effective user 2014-08-13 01:53:44 +09:00
Tatsuhiro Tsujikawa
bf13d91264 nghttpx: Add hot deploy feature
nghttpx supports hot deploy feature using signals.  The host deploy in
nghttpx is multi step process.  First send USR2 signal to nghttpx
process.  It will do fork and execute new executable, using same
command-line arguments and environment variables.  At this point, both
current and new processes can accept requests.  To gracefully shutdown
current process, send QUIT signal to current nghttpx process.  When
all existing frontend connections are done, the current process will
exit.  At this point, only new nghttpx process exists and serves
incoming requests.
2014-08-13 00:43:54 +09:00
Tatsuhiro Tsujikawa
8aa6580d89 nghttpx: Chown log files with --user 2014-08-10 20:58:02 +09:00
Tatsuhiro Tsujikawa
11fa71ba6c Update doc 2014-08-10 18:05:24 +09:00
Tatsuhiro Tsujikawa
58afce2382 nghttp: Verbose output for received DATA chunk with current received window 2014-08-10 17:18:28 +09:00
Tatsuhiro Tsujikawa
24cfb52b5a nghttpx: Add --no-location-rewrite option
--no-location-rewrite option disallows location header rewrite on
--http2-bridge, --client and default mode.  This option is useful when
connecting nghttpx proxy with --http2-bridge to backend nghttpx with
http2-proxy mode.
2014-08-10 12:39:27 +09:00
Tatsuhiro Tsujikawa
d499803221 Fix another heap-use-after-free bug 2014-08-10 12:20:36 +09:00
Tatsuhiro Tsujikawa
894783f572 Add note how to specify error code on NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE 2014-08-10 00:18:41 +09:00
Tatsuhiro Tsujikawa
93ed89df5f nghttpx: Make stream timeout disable by default
It might be useful to clean the unused stream out to make up the room
for new streams.  On the other hand, proxy should maintain the
connection between upstream client and downstream server and they have
the timeout for their own.  Proxy just reacts to their decision.
2014-08-10 00:08:44 +09:00
Tatsuhiro Tsujikawa
1a2e50ca08 nghttpx: Lower timeouts 2014-08-09 22:59:31 +09:00
Tatsuhiro Tsujikawa
76703f79fa nghttpx: Add stream level timeout for HTTP/2 and SPDY upstream/downstream 2014-08-09 22:56:27 +09:00
Tatsuhiro Tsujikawa
4679188069 Fix crash 2014-08-09 18:41:08 +09:00
Tatsuhiro Tsujikawa
4c3aa081a0 nghttp: Improve error logging a bit 2014-08-09 00:03:33 +09:00
Tatsuhiro Tsujikawa
ab9b0538bc Add doc how to issue non-final response headers 2014-08-08 23:38:20 +09:00
Tatsuhiro Tsujikawa
24edd2972d Remove note about 0x00 concatenation rule and add note about pseudo-headers 2014-08-08 23:32:45 +09:00
Tatsuhiro Tsujikawa
a8b7fa524f Merge branch 'alagoutte-travis' 2014-08-08 23:15:42 +09:00
Tatsuhiro Tsujikawa
b827b99b2f Merge branch 'travis' of https://github.com/alagoutte/nghttp2 into alagoutte-travis 2014-08-08 23:14:58 +09:00
Tatsuhiro Tsujikawa
88add854ff nghttpx: Treat malformed request as PROTOCOL_ERROR 2014-08-08 23:11:58 +09:00
Tatsuhiro Tsujikawa
704bbbfcaa nghttpx: Fail if :status is not digits on http2 downstream 2014-08-08 23:08:24 +09:00
Tatsuhiro Tsujikawa
e217e789de nghttp: Support non-final response and check pseudo headers 2014-08-08 23:03:12 +09:00
Tatsuhiro Tsujikawa
d4d56e1846 nghttpd, nghttpx: Check that pseudo headers come before normal headers 2014-08-08 20:52:32 +09:00
Alexis La Goutte
8883df2fd6 Add make check to Travis 2014-08-08 13:20:48 +02:00
Tatsuhiro Tsujikawa
d496c42dc9 Revert "nghttpx, nghttpd: Check pseudo header fields come before normal header fields"
This reverts commit cc24b9aaf0.
2014-08-08 20:17:03 +09:00
Alexis La Goutte
8433a75a6b Travis : Disable GCC build (don't work with GCC travis release) 2014-08-08 13:14:18 +02:00
Tatsuhiro Tsujikawa
76b3ba2832 nghttp: Sort request header fields using http2::name_less 2014-08-08 00:27:04 +09:00
Tatsuhiro Tsujikawa
05f982dcfb src: Sort header fields so that pseudo headers come first 2014-08-07 23:27:13 +09:00
Tatsuhiro Tsujikawa
cc24b9aaf0 nghttpx, nghttpd: Check pseudo header fields come before normal header fields 2014-08-07 22:49:34 +09:00
Tatsuhiro Tsujikawa
e6695d9ba7 nghttp: Check HTTP header field characters 2014-08-07 22:01:00 +09:00
Tatsuhiro Tsujikawa
9fb2bc8468 src: Remove http2::sort_nva
This function is no longer necessary because 0x00 concatenation rule
is gone.
2014-08-07 21:55:30 +09:00
Tatsuhiro Tsujikawa
6ccf06c6da nghtp2_hd: Calculate hash values once 2014-08-06 22:00:12 +09:00
Tatsuhiro Tsujikawa
49e3fd6862 Add some header names which won't be indexed 2014-08-06 21:50:54 +09:00
Tatsuhiro Tsujikawa
9c1a956e47 hpackcheck.py: Remove sorting to check ordering requirements 2014-08-06 20:34:51 +09:00
Tatsuhiro Tsujikawa
86b089f957 Fix buffer overrun in raw_sbuf 2014-08-06 01:49:36 +09:00
Tatsuhiro Tsujikawa
3f212a60a5 nghttpx: Fix android build error 2014-08-06 00:23:46 +09:00
Tatsuhiro Tsujikawa
5c61917007 src: Move jemalloc front so that it is surely linked 2014-08-05 22:27:54 +09:00
Tatsuhiro Tsujikawa
8736f61fbd Detect static libjemalloc
libjemalloc as static library requires -pthread flag to link.  Without
that, the check in configure.ac fails with unresolved symbols.
2014-08-05 21:49:50 +09:00
Tatsuhiro Tsujikawa
04e94824a0 Merge branch 'alagoutte-misc' 2014-08-05 01:06:15 +09:00
Alexis La Goutte
ec93c9f55f Fix some other shorten-64-to-32 casting error found by MSVC (64bits)
Thanks to Pascal
2014-08-04 09:04:49 +02:00
Alexis La Goutte
6c71889552 Fix some other shorten-64-to-32 casting error found by MSVC (64bits) 2014-08-03 16:09:30 +02:00
Tatsuhiro Tsujikawa
4bbb4172aa Fix typo 2014-08-03 14:07:35 +09:00
Tatsuhiro Tsujikawa
9ccf4c037d Update README.rst 2014-08-03 01:08:42 +09:00
Tatsuhiro Tsujikawa
1f356391f1 Update README.rst 2014-08-03 00:52:40 +09:00
Tatsuhiro Tsujikawa
3c603ec4ae add_hd_table_incremental: Remove unused bufs parameter 2014-08-02 16:21:42 +09:00
Tatsuhiro Tsujikawa
d36bea8554 Add debug output for HPACK decoded integer 2014-08-02 10:40:25 +09:00
Tatsuhiro Tsujikawa
16101b8b3f Fix compile error with --enable-debug 2014-08-02 10:16:32 +09:00
Tatsuhiro Tsujikawa
455d911f61 src, examples: Call OPENSSL_config() 2014-08-02 10:11:45 +09:00
Tatsuhiro Tsujikawa
2fb750f2e3 nghttp2_check_header_value: Disallow 0x00 2014-08-02 00:30:09 +09:00
Tatsuhiro Tsujikawa
7c781bcd1a nghttpx: Issue RST_STREAM instead of returning NGHTTP2_ERR_TEMPORAL_CALLBACKFAILURE
NGHTTP2_ERR_TEMPORAL_CALLBACKFAILURE is not supported in
on_frame_recv_callback.
2014-08-02 00:26:43 +09:00
Tatsuhiro Tsujikawa
a234166fc4 Merge branch 'bagder-server-tutorial' 2014-08-01 20:55:45 +09:00
Tatsuhiro Tsujikawa
ecb7e7db74 Merge branch 'server-tutorial' of https://github.com/bagder/nghttp2 into bagder-server-tutorial 2014-08-01 20:52:39 +09:00
Tatsuhiro Tsujikawa
99ceb7df33 Merge branch 'alagoutte-misc' 2014-08-01 20:51:49 +09:00
Daniel Stenberg
2e0775d506 tutorial-server.rst: language
I went through and fixed the English and grammar somwhat
2014-08-01 10:50:23 +02:00
Alexis La Goutte
ac28cd7efa Fix typo 2014-08-01 09:05:37 +02:00
Tatsuhiro Tsujikawa
a5ec5c1a1d Merge branch 'h2-14' 2014-07-31 23:39:04 +09:00
Tatsuhiro Tsujikawa
7952029752 Advertise h2-14 2014-07-31 23:34:54 +09:00
Tatsuhiro Tsujikawa
2e083352d5 nghttpx: Fix crash on http2 downstream disconnect 2014-07-31 23:34:33 +09:00
Tatsuhiro Tsujikawa
d848b9815a python: Use draft-09 2014-07-31 23:19:31 +09:00
Tatsuhiro Tsujikawa
48734b6d05 Update doc 2014-07-31 23:18:39 +09:00
Tatsuhiro Tsujikawa
8838f666cb Update doc 2014-07-31 23:16:52 +09:00
Tatsuhiro Tsujikawa
d8d14a3fc9 Code cleanup 2014-07-31 23:08:51 +09:00
Tatsuhiro Tsujikawa
6e027ad830 nghttpd, nghttpx: Check allowed pseudo headers 2014-07-31 23:05:53 +09:00
Tatsuhiro Tsujikawa
9d78167297 nghttpx: Treat unexpected HEADERS as stream error 2014-07-31 23:05:53 +09:00
Tatsuhiro Tsujikawa
c13329b328 Treat delta 0 WINDOW_UPDATE as error 2014-07-31 23:05:53 +09:00
Tatsuhiro Tsujikawa
b8a2bf2675 Remove END_SEGMENT flag 2014-07-31 23:05:53 +09:00
Tatsuhiro Tsujikawa
98be65a1eb Allow submission of unknown SETTINGS 2014-07-31 23:05:53 +09:00
Tatsuhiro Tsujikawa
742b28833a Rename NGHTTP2_SETTINGS_MAX_HEADER_SET_SIZE as NGHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE 2014-07-31 23:05:53 +09:00
Tatsuhiro Tsujikawa
77374ac6e2 Implement SETTINGS_MAX_FRAME_SIZE and SETTINGS_MAX_HEADER_LIST_SIZE 2014-07-31 23:05:53 +09:00
Tatsuhiro Tsujikawa
c4be7d48a0 nghttp2_hd: Code cleanup 2014-07-31 23:05:53 +09:00
Tatsuhiro Tsujikawa
0752ce6701 nghttp2_hd_deflate_bound: Take into account possible 2nd context update 2014-07-31 23:05:53 +09:00
Tatsuhiro Tsujikawa
8d5422c9bb Remove check for incoming header block size
The application should be responsible for the size of incoming header
block size.  Framing layer just passes everything (we have size limit
for one header/field though) to application.
2014-07-31 23:05:53 +09:00
Tatsuhiro Tsujikawa
04b5d1679f nghttpx: Log non-final response headers 2014-07-31 23:05:53 +09:00
Tatsuhiro Tsujikawa
15055c11f9 nghttpx: Support server-wide OPTIONS in http/1 upstream 2014-07-31 23:05:53 +09:00
Tatsuhiro Tsujikawa
c859fb8f7c nghttpx: Don't respond DATA frame for HEAD request or 204, 304, 1xx 2014-07-31 23:05:53 +09:00
Tatsuhiro Tsujikawa
dd1850aed0 Emit minimum header table size in encoding context update 2014-07-31 23:05:53 +09:00
Tatsuhiro Tsujikawa
079db14d45 Add nghttp2_session_consume() API
Reworked no automatic WINDOW_UPDATE feature.  We added new API
nghttp2_session_consume() which tells the library how many bytes are
consumed by the application.  Instead of submitting WINDOW_UPDATE by
the application, the library is now responsible to submit
WINDOW_UPDATE based on consumed bytes.  This is more reliable method,
since it enables us to properly send WINDOW_UPDATE for stream and
connection individually.  The previous implementation of nghttpx had
broken connection window management.
2014-07-31 23:05:53 +09:00
Tatsuhiro Tsujikawa
9f17bee51d Fix unittest failure 2014-07-31 23:05:53 +09:00
Tatsuhiro Tsujikawa
e904842504 Update doc 2014-07-31 23:05:52 +09:00
Tatsuhiro Tsujikawa
4f815521ae nghttpx, nghttpd: Support non-final response 2014-07-31 23:05:52 +09:00
Tatsuhiro Tsujikawa
78df530b90 Don't ignore aux_data for HEADERS with NGHTTP2_HCAT_HEADERS tag 2014-07-31 23:05:52 +09:00
Tatsuhiro Tsujikawa
e147c14186 Remove ent_name member and use index solely 2014-07-31 23:05:52 +09:00
Tatsuhiro Tsujikawa
06453fb15e Remove unused role member in nghttp2_hd_context 2014-07-31 23:05:52 +09:00
Tatsuhiro Tsujikawa
af5fd2019d src: Remove 0x00 concatenation for headers
Now concatenating header values with 0x00 as delimiter is not
necessary because HPACK reference set is removed and the order of
header field fed into HPACK encoder is preserved when they are
decoded.
2014-07-31 23:05:52 +09:00
Tatsuhiro Tsujikawa
744ec4dba1 Don't copy static header and put static table in front of dynamic table 2014-07-31 23:05:52 +09:00
Tatsuhiro Tsujikawa
38bfbffb1b Remove HPACK reference set 2014-07-31 23:05:52 +09:00
Tatsuhiro Tsujikawa
63398f30dd Extend frame length field to 24 bits 2014-07-31 23:05:52 +09:00
Tatsuhiro Tsujikawa
961dcf614a Fix wrong detection of neverIndex bit 2014-07-26 23:27:34 +09:00
Tatsuhiro Tsujikawa
5b572d8d59 Bump up version number to 0.5.2-DEV 2014-07-23 00:51:46 +09:00
Tatsuhiro Tsujikawa
8d29710393 Update man pages 2014-07-23 00:47:33 +09:00
Tatsuhiro Tsujikawa
e839ea8596 Bump up version number to 0.5.1, LT revision to 4:1:0 2014-07-23 00:45:39 +09:00
Tatsuhiro Tsujikawa
57e9b94aaa Handle header table size up to UINT32_MAX 2014-07-22 22:38:18 +09:00
Tatsuhiro Tsujikawa
9de9b6ebd6 Remove unnecessarily code 2014-07-22 01:52:51 +09:00
Tatsuhiro Tsujikawa
44310c6de5 Fix integer decoding when it takes multiple reads 2014-07-22 01:50:29 +09:00
Tatsuhiro Tsujikawa
139c3b508a Revert "Use gcc-4.9 for travis build"
This reverts commit 8207dd33b7.
2014-07-20 22:32:46 +09:00
Tatsuhiro Tsujikawa
8207dd33b7 Use gcc-4.9 for travis build 2014-07-20 22:26:20 +09:00
Tatsuhiro Tsujikawa
d99e1135c8 Search static header table linearly 2014-07-20 19:13:56 +09:00
Tatsuhiro Tsujikawa
db3b07735b Bump up version number to 0.5.1-DEV 2014-07-18 21:32:18 +09:00
Tatsuhiro Tsujikawa
0a2149f322 Update man pages 2014-07-18 21:26:32 +09:00
Tatsuhiro Tsujikawa
da85d2eecc Bump up version number to 0.5.0, LT revision to 4:0:0 2014-07-18 21:20:11 +09:00
Tatsuhiro Tsujikawa
cc5802ec05 Update README.rst 2014-07-18 21:17:10 +09:00
Tatsuhiro Tsujikawa
67b13ad9ff Remove unused nghttp2_nva_out 2014-07-18 21:14:07 +09:00
Tatsuhiro Tsujikawa
8dc47c6750 Fix resource leaks 2014-07-18 00:31:32 +09:00
Tatsuhiro Tsujikawa
39498beffd examples: Fix possible division by zero 2014-07-18 00:09:05 +09:00
Tatsuhiro Tsujikawa
5c305acb97 Remove unused nghttp2_io_flag 2014-07-17 23:44:03 +09:00
Tatsuhiro Tsujikawa
61053653df src: Retry write(2) if errno == EINTR 2014-07-17 23:41:54 +09:00
Tatsuhiro Tsujikawa
62423f5949 Fix double free 2014-07-15 22:47:04 +09:00
Tatsuhiro Tsujikawa
55c697e9f4 Handle multiple SETTINGS_HEADER_TABLE_SIZE in incoming SETTINGS frame
Previously we just assumed that if same settings ID is found in
SETTINGS, it is enough to process last seen entry.  But it turns out
it is not enough for SETTINGS_HEADER_TABLE_SIZE.  If we have 0 and
4096 for SETTINGS_HEADER_TABLE_SIZE in one SETTINGS, we must first
shrink dynamic table to 0 and then enlarge it to 4096.  This means
that we have to remember the minimum value and last value.
2014-07-15 00:25:31 +09:00
Tatsuhiro Tsujikawa
bb47484667 nghttpx: Log transmission and reception of GOAWAY 2014-07-12 23:30:13 +09:00
Tatsuhiro Tsujikawa
c4d2639ed8 nghttpd: Don't shutdown session if pending data is left 2014-07-12 23:17:25 +09:00
Tatsuhiro Tsujikawa
8f1249ab67 Check NGHTTP2_GOAWAY_SEND and NGHTTP2_GOAWAY_RECV flags explicitly 2014-07-12 23:16:25 +09:00
Tatsuhiro Tsujikawa
35ffeb5ff4 Send additional debug info when terminating session 2014-07-12 22:57:17 +09:00
Tatsuhiro Tsujikawa
25326b40db doc: Generate HTML version manual page from manpage 2014-07-09 00:38:43 +09:00
Tatsuhiro Tsujikawa
25e18174dd src: Add additional HTTP status codes defined in RFC 6585 2014-07-08 22:41:17 +09:00
Tatsuhiro Tsujikawa
a072d719b3 nghttpx: Use 431 instead of 413 2014-07-08 22:37:48 +09:00
Tatsuhiro Tsujikawa
d0d0488301 Disable threading for android build because it lacks thread local storage 2014-07-08 21:28:45 +09:00
Tatsuhiro Tsujikawa
0d1ebd73de nghttpx: Only use thread_local if NOTHREADS is not defined 2014-07-08 21:28:11 +09:00
Tatsuhiro Tsujikawa
d3ca003346 Update android-config and fix build warning with android NDK 2014-07-06 23:32:08 +09:00
Tatsuhiro Tsujikawa
9cbedb16d0 nghttpx: Log filename and line number after severity in one line 2014-07-06 19:26:12 +09:00
Tatsuhiro Tsujikawa
9f1c819242 nghttpx: Cleanup create_evlistener 2014-07-06 19:21:18 +09:00
Tatsuhiro Tsujikawa
a02624c9ed nghttpx: Use std::shared_ptr to share cached time
To ensure that cached time buffer is not altered while referencing it,
we rely on inerlocking in std::shared_ptr to acheive this.
2014-07-06 13:27:51 +09:00
Tatsuhiro Tsujikawa
933e24d412 nghttpx: Use std::atomic for Config::cached_time 2014-07-05 23:50:32 +09:00
Tatsuhiro Tsujikawa
fe2843f9d6 nghttpx: Include pid in errorlog 2014-07-05 22:53:17 +09:00
Tatsuhiro Tsujikawa
afdc61a253 nghttpx: Remove S_IROTH when creating log file 2014-07-05 22:41:53 +09:00
Tatsuhiro Tsujikawa
367e764ca3 nghttpx: Log user-agent as "-" if it is empty 2014-07-05 19:48:14 +09:00
Tatsuhiro Tsujikawa
9841f778a9 nghttpx: Do not compile pthread_sigmask if NOTHREADS is defined 2014-07-05 19:43:39 +09:00
Tatsuhiro Tsujikawa
bf4042ce98 nghttpx: Cache time for logging 2014-07-05 19:40:30 +09:00
Tatsuhiro Tsujikawa
2e6d5e9bd0 nghttpx: Use %lld instead of PRId64 2014-07-05 18:51:55 +09:00
Tatsuhiro Tsujikawa
0ce848a611 nghttpx: Rewrite logging system
This change rewrites logging system of nghttpx.  Previously access log
and error log are written to stderr or syslog and there was no option
to change stderr to something else.  With this change, file path of
access log and error log can be configured separately and logging to
regular file is now added.  To support rotating log, if SIGUSR1 signal
is received by nghttpx, it closes the current log files and reopen it
with the same name.  The format of access log is changed and has same
look of apache's.  But not all columns are not supported yet.
2014-07-05 18:43:24 +09:00
Tatsuhiro Tsujikawa
57230b4029 nghttpx: Fix regression POST http2 downstream does not work 2014-07-04 02:03:09 +09:00
Tatsuhiro Tsujikawa
3111138ca3 nghttpx: Don't add transfer-encoding to CONNECT request 2014-07-03 23:44:20 +09:00
Tatsuhiro Tsujikawa
0f4d01c25c nghttpx: Pass through NGHTTP2_NO_ERROR from downstream to upstream 2014-07-03 23:00:19 +09:00
Tatsuhiro Tsujikawa
f8b872096e nghttpx: Use NGHTTP2_NO_ERROR to close upgraded (tunneled) stream 2014-07-03 22:59:49 +09:00
Tatsuhiro Tsujikawa
e18c439a73 nghttp: Add --no-content-length option 2014-07-03 22:48:43 +09:00
Tatsuhiro Tsujikawa
545732fed8 nghttpd: Add --early-response option
This option is testing the client behavior when it gets response
before sending all request.
2014-07-03 22:44:27 +09:00
Tatsuhiro Tsujikawa
4b6f124b7e Add API to check half-closed state for both direction of stream 2014-07-03 21:44:29 +09:00
Tatsuhiro Tsujikawa
119fb05cc2 nghttpx: Call on_response_headers for response header only in http2 downstream 2014-07-03 21:18:01 +09:00
Tatsuhiro Tsujikawa
e08df2840c nghttpx: Disallow 2nd message in http downstream 2014-07-03 20:57:07 +09:00
Tatsuhiro Tsujikawa
1ce00f455c nghttpx: Remove requirement of content-length for HTTP2 upstream POST 2014-07-03 19:59:10 +09:00
Tatsuhiro Tsujikawa
9cddb05f54 nghttpx: Use error_reply instead of RST_STREAM for http2 upstream request 2014-07-03 00:12:16 +09:00
Tatsuhiro Tsujikawa
93b3a44fb5 nghttpx: Add ability to Http2Upstream to send RST_STREAM after END_STREAM 2014-07-02 23:56:26 +09:00
Tatsuhiro Tsujikawa
acb3d4dcfc nghttpx: Handle connection flow control for DATA not sent to frontend 2014-07-02 23:24:59 +09:00
Tatsuhiro Tsujikawa
797edae4d4 nghttpx: Handle connection flow control for DATA not sent to backend 2014-07-02 23:24:58 +09:00
Tatsuhiro Tsujikawa
e5abc475f1 Don't send more than NGHTTP2_MAX_HEADERSLEN bytes header block 2014-07-02 22:45:38 +09:00
Tatsuhiro Tsujikawa
593485c652 Put a limit for total contiguous headers length currently receiving 2014-07-02 22:25:32 +09:00
Tatsuhiro Tsujikawa
6da044cbb5 Send WINDOW_UPDATE for ignored DATA bytes when manual flow control is enabled
Since we do not call on_data_chunk_recv_callback for ignored DATA
chunk, if nghttp2_option_set_no_auto_connection_window_update is used,
application may not have a chance to send connection WINDOW_UPDATE.
To fix this, we accumulate those received bytes, and if it exceeds
certain number, we automatically send connection-level WINDOW_UPDATE.
2014-07-02 21:20:40 +09:00
Tatsuhiro Tsujikawa
ed38dbf67a Add const qualifier to opaque_data parameter in nghttp2_submit_ping 2014-07-02 00:59:36 +09:00
Tatsuhiro Tsujikawa
499af94840 python: Check draft version in hpackcheck.py 2014-07-01 00:39:54 +09:00
Tatsuhiro Tsujikawa
2f91a7f603 Update doc 2014-07-01 00:26:02 +09:00
Tatsuhiro Tsujikawa
e517ff6534 python: Use public HPACK API 2014-06-30 22:45:18 +09:00
Tatsuhiro Tsujikawa
1039dc59ea Update doc 2014-06-30 00:02:40 +09:00
Tatsuhiro Tsujikawa
a7501609e8 doc: Fix python-apiref.rst is not generated in distribution 2014-06-29 23:57:18 +09:00
Tatsuhiro Tsujikawa
8235bb136b doc: Add HPACK API tutorial 2014-06-29 23:45:49 +09:00
Tatsuhiro Tsujikawa
bd06f2cec3 Add const qualifier to nva parameter in nghttp2_hd_deflate_hd() 2014-06-29 23:43:14 +09:00
Tatsuhiro Tsujikawa
48c8c89a3f Add Rewriting location header field section to nghttpx how-to 2014-06-29 00:17:06 +09:00
Tatsuhiro Tsujikawa
8167968efb Update README.rst 2014-06-28 16:12:46 +09:00
Tatsuhiro Tsujikawa
4e81a34146 nghttpd: Add --dh-param-file option to support DHE ciphers 2014-06-28 15:43:06 +09:00
Tatsuhiro Tsujikawa
9fec34968b nghttpd: Disable SSL_CTX_set_ecdh_auto for OpenSSL >= 1.0.2 2014-06-28 15:35:10 +09:00
Tatsuhiro Tsujikawa
a3334bb21c nghttpd: Use cipher suites recommended by Mozilla 2014-06-28 15:28:19 +09:00
Tatsuhiro Tsujikawa
d318e6a62e Support one header field size (name + value) up to 64KiB by default
This commits changes the upper bound of one header field size (the sum
of the length of name and value) to 64KiB by default.  We may add an
option to change this upper bound in the future.
2014-06-28 11:04:41 +09:00
Tatsuhiro Tsujikawa
ff3a4a770f Treat larger last stream ID in GOAWAY than previous value as PROTOCOL_ERROR 2014-06-28 10:46:05 +09:00
Tatsuhiro Tsujikawa
305efe4181 Update doc 2014-06-28 00:25:23 +09:00
Tatsuhiro Tsujikawa
c1be7c734f src: Update status code according to RFC 7231 2014-06-27 23:02:12 +09:00
Tatsuhiro Tsujikawa
303f0f3fcd nghttpx: Return 413 if request header is too large
For now, if request has request body, we'll issue RST_STREAM to inform
the peer to stop sending body.  RST_STREAM may be sent before error
page header or data, so peer may receive RST_STREAM only.
2014-06-27 22:54:33 +09:00
Tatsuhiro Tsujikawa
ca87b45fe4 nghttpx: Don't fail backend connection if one of backend request fails 2014-06-27 22:34:54 +09:00
Tatsuhiro Tsujikawa
31d99b3664 nghttp: Adjust header size for CONTINUATION test 2014-06-27 21:16:36 +09:00
Tatsuhiro Tsujikawa
3312df42d2 nghttpx: Use std::unique_ptr for ListenHandler::http2session_ 2014-06-27 00:39:53 +09:00
Tatsuhiro Tsujikawa
68cd12ac29 nghttpx: Use std::vector instead of raw array 2014-06-27 00:26:21 +09:00
Tatsuhiro Tsujikawa
451c7d957d doc: Add h2load-howto.rst 2014-06-27 00:05:49 +09:00
Tatsuhiro Tsujikawa
15a7b0414c Update doc 2014-06-26 23:24:08 +09:00
Tatsuhiro Tsujikawa
52ff158f34 h2load: Fix failed stream count is added multiple times
The number of failed stream is counted multiple times if several
connection attempts are made.
2014-06-26 23:20:12 +09:00
Tatsuhiro Tsujikawa
479e15469c nghttpx: Add worker-frontend-connections option 2014-06-26 22:55:22 +09:00
Tatsuhiro Tsujikawa
16fef227e8 nghttp2_hd_*_new: Leave *inflater_ptr or *deflater_ptr untouched on failure 2014-06-25 21:26:47 +09:00
Tatsuhiro Tsujikawa
55c338d7af nghttp2_session_*_new: Leave session parameter untouched on failure 2014-06-25 21:21:17 +09:00
Tatsuhiro Tsujikawa
4cbfe5d3d1 Ensure that maximum padding is 256 2014-06-25 21:17:03 +09:00
Tatsuhiro Tsujikawa
ad60a18fb9 Remove BLOCKED frame 2014-06-24 00:22:41 +09:00
Tatsuhiro Tsujikawa
5aba6e6d1b h2load: Set number of request per client explicitly
Previously we do not specify the number of requests each client has to
issue.  The each client corresponds to 1 TCP connection.  If
connection was not accepted by server or not TLS handshake is not
done, we effectively don't use that connection and the requests
supposed to be issued for those connections are done via other
established connections.  If this occurs, servers which do not accept
all connections may gain good benchmark results since they don't have
to pay extra cost to handle all connections (e.g., SSL/TLS handshake).
This change explicitly set the number of requests each client has to
issue so that servers cannot *cheat*.
2014-06-22 15:03:46 +09:00
Tatsuhiro Tsujikawa
31de732e3b Allocate header table ringbuffer lazily
Previously in inflater we reserve new ringbuffer when table size is
changed.  This may be potentially a problem if new table size is very
large number.  When inflater is not used directly by application, this
is not a problem because application can choose the buffer size.  On
the other hand, if application uses inflater directly and it does not
have control of new buffer size (e.g., protocol dissector), then we
just fail to allocate large buffer in
nghttp2_hd_inflate_change_table_size() without actually use such huge
buffer.  This change defers the actual allocation of buffer when it is
actually needed so that we will fail when it is absolutely needed.
2014-06-22 13:39:17 +09:00
Tatsuhiro Tsujikawa
1caec7cb16 h2load: Fix memory leak detected by LeakSanitizer 2014-06-20 00:00:06 +09:00
Tatsuhiro Tsujikawa
0cd26d6f3b nghttp: Remove garbage for deprecated per-stream compression which cause leak 2014-06-19 23:35:58 +09:00
Tatsuhiro Tsujikawa
2bfa772472 nghttpx: Update cipher suite list 2014-06-19 23:26:30 +09:00
Tatsuhiro Tsujikawa
133c3d66be nghttpx: Remove TLSv1.0 from default TLS proto list 2014-06-19 23:21:53 +09:00
Tatsuhiro Tsujikawa
266a15ccd3 nghttpx: Remove per-connection rate limit
It looks like setting read-rate and read-burst to 0 makes busy loop.
It seems a bug.  On the other hand, we most likely want per-thread
rate limit rather than per-connection.  So we decided to drop them.
2014-06-19 23:19:14 +09:00
Tatsuhiro Tsujikawa
4ff522764c h2load: Call session->on_write() explicitly in Client::on_connect() 2014-06-19 22:49:38 +09:00
Tatsuhiro Tsujikawa
4ab594b144 nghttpx: Fix connection preface is not read by upstream_http2_connhd_readcb
It seems that if readcb is not set before SSL/TLS handshake, the
incoming data already available when eventcb (BEV_EVENT_CONNECTED
event) is fired is not further notified after setting new readcb.  We
knew this fact and call upstream->on_read() in eventcb, but it is
wrong for HTTP/2.  We have to call upstream_http2_connhd_readcb to
check connection preface.  Otherwise, we consume it by nghttp2 session
and it is treated as unknown frame and connection preface is not
detected properly.
2014-06-19 22:43:54 +09:00
Tatsuhiro Tsujikawa
3f5e359ef4 Fix failmalloc test 2014-06-18 15:12:54 +09:00
Tatsuhiro Tsujikawa
a344a8f566 src: Don't build h2load if std::future is not working 2014-06-18 14:24:45 +09:00
Tatsuhiro Tsujikawa
8acd67b3fa Fix have_zlib is not set for android build 2014-06-18 14:12:40 +09:00
Tatsuhiro Tsujikawa
323c3b4225 doc: Update tutorial 2014-06-18 13:14:07 +09:00
Tatsuhiro Tsujikawa
ae74a18624 examples: Fix libevent-server which could not send error reply 2014-06-18 13:11:01 +09:00
Tatsuhiro Tsujikawa
85a43cfa66 examples: Check return value of evbuffer_drain 2014-06-18 13:06:05 +09:00
Tatsuhiro Tsujikawa
4fdc274a42 python: Add -c, --simulate-table-size-change option to hpackmake.py 2014-06-18 13:02:18 +09:00
Tatsuhiro Tsujikawa
2d18a07364 python: Bump up HPACK draft version to 8 2014-06-18 12:20:36 +09:00
Tatsuhiro Tsujikawa
6cb971ee7b doc: Update reference 2014-06-18 12:15:15 +09:00
Tatsuhiro Tsujikawa
cb132338df Update README.rst 2014-06-18 12:13:01 +09:00
Tatsuhiro Tsujikawa
87360b4f7d nghttpx: Require TLSv.12 for h2 2014-06-18 12:09:30 +09:00
Tatsuhiro Tsujikawa
8e0fcd3922 Add test for graceful shutdown use case 2014-06-18 12:08:12 +09:00
Tatsuhiro Tsujikawa
9294622519 Treat unknown error code as NGHTTP2_INTERNAL_ERROR 2014-06-18 11:53:32 +09:00
Tatsuhiro Tsujikawa
b78a51da0e Support graceful shutdown using multiple GOAWAY
Add last_stream_id parameter to nghttp2_submit_goaway().  To terminate
connection immediately with application chosen last stream ID,
nghttp2_session_terminate_session2() was added.
2014-06-18 11:35:08 +09:00
Tatsuhiro Tsujikawa
975524a125 Don't send GOAWAY with last stream ID larger than the value previously sent 2014-06-18 11:03:55 +09:00
Tatsuhiro Tsujikawa
817e1ce2a7 Rename last_stream_id in nghttp2_session to remote_last_stream_id
This commits also fixes last stream ID in GOAWAY uses wrong stream ID.
2014-06-18 10:56:32 +09:00
Tatsuhiro Tsujikawa
62900cd85b Allow multiple transmission of GOAWAY frame 2014-06-18 10:51:33 +09:00
Tatsuhiro Tsujikawa
174e410b93 Use hex in nghttp2_error_code and nghttp2_settings_id 2014-06-18 10:48:31 +09:00
Tatsuhiro Tsujikawa
a5af621947 Change protocol ID to h2-13 2014-06-18 09:42:51 +09:00
Tatsuhiro Tsujikawa
b53ef8de8f Merge branch 'alagoutte-h2-13-misc' into h2-13 2014-06-17 22:37:53 +09:00
Alexis La Goutte
9a3cdeb7e6 Fix some other shorten-64-to-32 casting error found by MSVC (64bits)
Thanks for Pascal
2014-06-16 19:17:49 +02:00
Alexis La Goutte
c9b6371977 When assertions is disable, there is a warning about unused check_index_range function
Make the check for a valid index range a macro, so the compiler doesn't
whine if it's not used, but it's available if it *is* used.
2014-06-16 18:52:11 +02:00
Tatsuhiro Tsujikawa
7f6ddd0f2e Update huffman code table 2014-06-16 23:03:55 +09:00
Tatsuhiro Tsujikawa
94b9c3771d nghttpx: Throw away request and response headers when they are done 2014-06-15 17:25:24 +09:00
Tatsuhiro Tsujikawa
86956db27f Update README.rst 2014-06-14 22:55:19 +09:00
Tatsuhiro Tsujikawa
5383db467e Update README.rst 2014-06-14 22:49:18 +09:00
Tatsuhiro Tsujikawa
1cbb5a3d8f Update tutorial 2014-06-14 22:47:56 +09:00
Tatsuhiro Tsujikawa
6513711943 Update README.rst 2014-06-14 22:42:18 +09:00
Tatsuhiro Tsujikawa
f85a213fb1 Update static header table 2014-06-14 22:24:47 +09:00
Tatsuhiro Tsujikawa
041cec2d97 nghttpx: Check error from SSL_set_fd 2014-06-12 23:39:58 +09:00
Tatsuhiro Tsujikawa
25b58d5e22 nghttpx: Code cleanup 2014-06-12 23:37:33 +09:00
Tatsuhiro Tsujikawa
dd006f8a79 Change protocol ID to h2-lc 2014-06-12 22:51:30 +09:00
Tatsuhiro Tsujikawa
1ee847c21a nghttp: Code cleanup 2014-06-12 22:48:40 +09:00
Tatsuhiro Tsujikawa
1af9a9cee0 nghttpx: Don't stderr log if syslog is used
This change also reverts previous commits and tty is set to false if
syslog is used.
2014-06-12 21:47:00 +09:00
Tatsuhiro Tsujikawa
6a2950aef0 nghttpx: Make tty to false when daemonized 2014-06-12 00:19:46 +09:00
Alexis La Goutte
a15d4fc306 Fix nghttp2_hd_huffman.h:41:31: warning: comma at end of enumerator list [-Wpedantic] 2014-06-11 23:43:10 +09:00
Tatsuhiro Tsujikawa
9b174bf5c9 Fix compile error with -Wshorten-64-to-32
The original patch was contributed by Alexis La Goutte
2014-06-11 23:37:16 +09:00
Alexis La Goutte
6e316e269f Add -Wshorten-64-to-32 to configure.ac 2014-06-11 21:22:29 +09:00
Tatsuhiro Tsujikawa
f0f5342cd4 Update doc 2014-06-11 01:40:20 +09:00
Tatsuhiro Tsujikawa
21c4931197 nghttpx: Get rid of openssl filter
Libevent Openssl filter is very inconvenient in various respect.  The
most annoying thing is it somehow emits data when SSL_shutdown is
called.  The reason we introduced this filter solution is drop
connection if TLS renegotiation is detected.  This commit implements
renegotiation detection and drop connection without filtering.
2014-06-11 01:16:49 +09:00
Tatsuhiro Tsujikawa
24762db8f5 nghttpx: Drop connection if HTTP/2 security level is not satisfied on backend 2014-06-11 00:19:54 +09:00
Tatsuhiro Tsujikawa
492b42e6e9 nghttpx: Drop connection if HTTP/2 security level is not satisfied on frontend 2014-06-11 00:07:51 +09:00
Tatsuhiro Tsujikawa
d6b5824c9c nghttpx: Don't check TLS requirement in ALPN cb cause cipher obj is nullptr
Also don't compare ALPN identifier with streq, since they are just
byte string.
2014-06-10 23:22:52 +09:00
Tatsuhiro Tsujikawa
c204861dec nghttpx: Create NPN prefs only once 2014-06-10 23:22:23 +09:00
Tatsuhiro Tsujikawa
7b0ed5d9bd nghttpx: Only allow DHE, ECDHE + AEAD ciphers for HTTP/2
Cipher suites are chosen by DHE and ECDHE ciphers + GCM (AEAD).  Now
default cipher list is the one recommended by Mozilla web site.  The
--honor-cipher-order option is removed and now it is always assumed.
2014-06-10 22:47:22 +09:00
Tatsuhiro Tsujikawa
5f5b5378c9 Merge branch 'master' into h2-13
Conflicts:
	lib/nghttp2_session.c
2014-06-10 21:38:26 +09:00
Tatsuhiro Tsujikawa
cfcecca751 Make return type of inbound_frame_set_settings_entry void 2014-06-10 21:32:20 +09:00
Tatsuhiro Tsujikawa
2878e1e258 Refactor storage of settings
Now local and remote settings values are stored in dedicated structure
nghttp2_settings_storage.
2014-06-10 21:29:19 +09:00
Tatsuhiro Tsujikawa
4596f73ee0 Fix unused header_cb_arg structure 2014-06-09 23:21:55 +09:00
Tatsuhiro Tsujikawa
caf3e1c035 Fix compile error with --enable-debug 2014-06-09 23:21:30 +09:00
Tatsuhiro Tsujikawa
dacc9b2f1c Separate extension frames from core frames
ALTSVC and BLOCKED frames are now extension frames.  To add new
extension frame without modifying nghttp2_frame union, which causes so
name bump, we separated extension frames from core frames.
nghttp2_frame includes generic nghttp2_extension.  The payload member
of nghttp2_extension will point to the structure of extension frame
payload.  The frame types of extension frames are defined in
nghttp2_ext_frame_type.
2014-06-09 23:16:54 +09:00
Tatsuhiro Tsujikawa
de14c02227 nghttpx: Code cleanup 2014-06-08 23:09:44 +09:00
Tatsuhiro Tsujikawa
e665123ebe nghttpx: Use nullptr instead of NULL 2014-06-08 23:09:44 +09:00
Tatsuhiro Tsujikawa
db8af31e2b nghttpx: Code cleanup 2014-06-08 23:09:44 +09:00
Tatsuhiro Tsujikawa
0fd5b2aa32 nghttpx: Use std::vector for tls_proto_list and npn_list
Now SSL/TLS option mask to disable particular SSL/TLS protocol
versions are pre-calculated and stored in Config.
2014-06-08 23:09:44 +09:00
Tatsuhiro Tsujikawa
1f58be423d nghttpx: Use nullptr instead of 0 2014-06-08 21:05:36 +09:00
Tatsuhiro Tsujikawa
14b818efc8 nghttpx: Use std::unique_ptr<char[]> instead of char* 2014-06-08 21:02:40 +09:00
Tatsuhiro Tsujikawa
19ed13c753 Fix off-by-one error when computing padding 2014-06-07 22:56:27 +09:00
Tatsuhiro Tsujikawa
317b8baa4f Set HTTP/2 protocol id to h2-13 for now 2014-06-07 19:39:14 +09:00
Tatsuhiro Tsujikawa
d4602a0991 Remove reserved field from ALTSVC frame 2014-06-07 19:10:09 +09:00
Tatsuhiro Tsujikawa
3daeadcb07 Remove bogus comments 2014-06-07 18:51:20 +09:00
Tatsuhiro Tsujikawa
19729962a3 Check stream_id is nonzero for DATA, HEADERS, PRIORITY, RST_STREAM, PUSH_PROMISE 2014-06-07 18:48:37 +09:00
Tatsuhiro Tsujikawa
bfaab30733 Allow transmission and reception of PRIORITY frame to a closed stream 2014-06-07 18:36:58 +09:00
Tatsuhiro Tsujikawa
c46d3dafc6 Remove PAD_HIGH and Pad High field
CONTINUATION now doesn't have padding.
2014-06-07 18:15:36 +09:00
Tatsuhiro Tsujikawa
70c86979e8 Ignore unknown settings ID 2014-06-07 16:41:36 +09:00
Tatsuhiro Tsujikawa
d402ba6fa2 Make settings_id 2 bytes field 2014-06-07 16:37:29 +09:00
Tatsuhiro Tsujikawa
458ccb3681 Ignore unknown frame types
Unexpected CONTINUATION frame is handled separately as connection
error.
2014-06-07 16:30:55 +09:00
Tatsuhiro Tsujikawa
3db8935e20 Remove per-frame compression 2014-06-07 16:04:43 +09:00
Tatsuhiro Tsujikawa
b8ed74c1ec nghttpx: Disable SSL_CTX_set_ecdh_auto() for now 2014-06-06 23:17:32 +09:00
Tatsuhiro Tsujikawa
fcec996925 h2load: Use 1 thread if the number of concurrent client is 1 2014-06-06 23:11:08 +09:00
Tatsuhiro Tsujikawa
7cb28e88e2 h2load: Return Stats rather than Worker from std::future 2014-06-06 23:08:32 +09:00
Tatsuhiro Tsujikawa
aea4001d73 deflatehd: Fix crash with -t option 2014-06-05 00:59:22 +09:00
Tatsuhiro Tsujikawa
eb0a894ede Merge branch 'Wshadow' of https://github.com/alagoutte/nghttp2 into alagoutte-Wshadow 2014-06-04 23:34:04 +09:00
Alexis La Goutte
6b08534ffc Fix declaration of ‘index’ shadows a global declaration [-Werror=shadow]
I have this error with some old gcc (4.6) release (Ubuntu 12.04 or Travis...)
2014-06-03 10:20:05 +02:00
Tatsuhiro Tsujikawa
1390378341 Bump up version number to 0.4.2-DEV 2014-06-02 22:49:56 +09:00
Tatsuhiro Tsujikawa
7146954de2 Update man pages 2014-06-02 22:36:22 +09:00
Tatsuhiro Tsujikawa
75b9be2d5a Bump up version number to 0.4.1, LT revision to 3:1:0 2014-06-02 22:34:18 +09:00
Tatsuhiro Tsujikawa
99aaaccf03 Update doc 2014-06-02 22:33:23 +09:00
Tatsuhiro Tsujikawa
7e217511bf nghttpx: Code cleanup
Mainly make nested code block to rather flat style.
2014-06-01 23:44:32 +09:00
Tatsuhiro Tsujikawa
8c67bbe3a8 src: Avoid copy in evbuffer_pullup()
Previously, we use evbuffer_pullup(buf, -1) to linearize the memory
region and it may cause buffer copy.  To avoid this, we use the return
value of evbuffer_get_contiguous_space() as 2nd parameter.  According
to the libevent manual, by doing so evbuffer_pullup() will not copy or
modify any data in evbuffer.
2014-06-01 21:01:01 +09:00
Tatsuhiro Tsujikawa
cc250386df nghttpx: Lower read watermark 2014-06-01 02:32:26 +09:00
Tatsuhiro Tsujikawa
3b7c733246 nghttpx: Fix typo 2014-06-01 02:32:15 +09:00
Tatsuhiro Tsujikawa
7e5567341f nghttpx: Set timeout to underlying bufferevent
Setting write timeout to filter bufferevent does not work as intended.
It timeouts even when there is no data to write.
2014-06-01 02:25:23 +09:00
Tatsuhiro Tsujikawa
4f7223e89f Add note to manual how to submit frames to new stream ID 2014-05-31 22:01:18 +09:00
Tatsuhiro Tsujikawa
88b69bb669 Reduce huffman decoding table
Previously we have uint16_t as state member variable in
nghttp2_huff_decode structure to express -1 as failure.  This is
because we have 256 valid states.  However, we can express failed
state using flags member variable and make state uint8_t.  This commit
does this and as a result the size of decoding table is reduced.
2014-05-31 00:19:30 +09:00
Tatsuhiro Tsujikawa
7a797b2c11 nghttpx: Reduce socket I/O buffer size 2014-05-29 22:24:15 +09:00
Tatsuhiro Tsujikawa
832f2fc00f Call on_data_chunk_recv_callback only when stream is active 2014-05-29 22:18:52 +09:00
Tatsuhiro Tsujikawa
d113055899 nghttp2_hd: Use single buffer for an name/value pair
Previously we use 2 separate buffer for each name and value.  The
problem is we would waste buffer space for name because it is usually
small.  Also tuning buffer size for each buffer separately is not
elegant and current HTTP server practice is that one buffer for 1
name/value pair.  This commit unifies 2 buffers into 1.
2014-05-28 23:33:37 +09:00
Tatsuhiro Tsujikawa
53e75ff0d0 Merge branch 'travis' of https://github.com/alagoutte/nghttp2 into alagoutte-travis 2014-05-28 23:26:02 +09:00
Alexis La Goutte
3921af434a Add .travis.yml to get build by Travis-ci (Github)
Use gcc-4.8 (don't build with gcc-4.6)
Update libstdc++-4.8 to fix Clang build

Don't install cython (Never build...)
2014-05-28 15:52:16 +02:00
Tatsuhiro Tsujikawa
5e6a2fa256 Assert ctx->state >= 0 in huffman decoding 2014-05-28 00:30:11 +09:00
Tatsuhiro Tsujikawa
86ab9f33de nghttpx: Fix regression bug that frame with stream_id = 0 not handled 2014-05-28 00:26:27 +09:00
Tatsuhiro Tsujikawa
d844b0acd0 h2load: Use std::async to dispatch parallel jobs 2014-05-26 23:29:28 +09:00
Tatsuhiro Tsujikawa
d733c87567 Make state in nghttp2_hd_huff_decode_context int16_t to make compiler happy 2014-05-26 21:50:54 +09:00
Tatsuhiro Tsujikawa
589d3e71a3 Merge branch 'misc' of https://github.com/alagoutte/nghttp2 into alagoutte-misc 2014-05-26 21:48:30 +09:00
Alexis La Goutte
db354b228a Remove unused include (stdint.h) 2014-05-26 08:58:15 +02:00
Tatsuhiro Tsujikawa
1fa5852f8f nghttpx: Treat '*' in <HOST> parameter of --frontend as wildcard explicitly
It seems that specifyig '*' to node parameter in getaddrinfo() is
treated as specifying NULL, but it is not documented.  So rather than
relying on this feature, we explicitly treat '*' as "wildcard" address
and specify NULL to node parameter in getaddrinfo().

Now '*,3000' is a default value of --frontend option.  Specyfing '*'
binds all addresses including both IPv4 and IPv6.
2014-05-25 16:15:48 +09:00
Tatsuhiro Tsujikawa
ebf0e4d787 nghttpd, nghttpx: Check END_STREAM flag in HEADERS other than request 2014-05-24 15:02:46 +09:00
Tatsuhiro Tsujikawa
9677788317 Don't count closed streams in nghttp2_session_want_{read,write} 2014-05-23 22:23:38 +09:00
Tatsuhiro Tsujikawa
78a55935ac Define constant for the length of priority related fields 2014-05-22 21:41:43 +09:00
Tatsuhiro Tsujikawa
2aa84019c7 Define constants for ALTSVC frame parsing 2014-05-22 21:36:12 +09:00
Tatsuhiro Tsujikawa
6d942dc0a6 Update doc 2014-05-21 23:01:21 +09:00
Tatsuhiro Tsujikawa
d408ee1783 Update doc
We are currently disabled ALPN in nghttp2.org
2014-05-21 23:00:01 +09:00
Tatsuhiro Tsujikawa
672ad82849 nghttpx: Clarify that --npn-list is used in both ALPN and NPN 2014-05-21 21:28:58 +09:00
Tatsuhiro Tsujikawa
896717f5d4 nghttpx: Make --npn-list option work in ALPN
Previously --npn-list option is ignored in ALPN protocol selection
callback.  This change fixes this issue.
2014-05-21 21:16:44 +09:00
Tatsuhiro Tsujikawa
eba2825286 Handle the case where jemalloc is available without linking extra library 2014-05-18 19:38:33 +09:00
Tatsuhiro Tsujikawa
a4a06947a5 Update doc 2014-05-17 22:20:48 +09:00
Tatsuhiro Tsujikawa
e54e86375b Bump up version number to 0.5.0-DEV 2014-05-17 00:14:07 +09:00
Tatsuhiro Tsujikawa
453e12cd1f Update man pages 2014-05-16 23:54:09 +09:00
Tatsuhiro Tsujikawa
de5c821530 Bump up version number to 0.4.0, LT revision to 3:0:0 2014-05-16 23:51:32 +09:00
Tatsuhiro Tsujikawa
1ac028e166 Take into account that pending_local_max_concurrent_stream could be too large
pending_local_max_concurrent_stream is, once local settings applied,
becomes NGHTTP2_INITIAL_MAX_CONCURRENT_STREAMS, which is very large
number.  When adjusting number of streams, we have to take min of
local effective SETTINGS_MAX_CONCURRENT_STREAMS and pending one.
2014-05-16 22:32:08 +09:00
Tatsuhiro Tsujikawa
2778e4aafc Remove useless debug code in nghttp2_stream_roots_add() 2014-05-16 22:30:59 +09:00
Tatsuhiro Tsujikawa
3f80472e0a nghttpx: Minor tweak to buffer size
Simplified when to send WINDOW_UPDATE to the backend, that is we send
WINDOW_UPDATE when input buffer is empty.
2014-05-16 21:42:30 +09:00
Tatsuhiro Tsujikawa
ec30af9117 Update sphinx_rtd_theme to 54a48b1726ed602c9b5416ee46c639462ec315fe 2014-05-16 00:36:06 +09:00
Tatsuhiro Tsujikawa
3b5b5ce254 Update http-parser to 8d9e5db981b623fffc93657abacdc80270cbee58 2014-05-16 00:23:03 +09:00
Tatsuhiro Tsujikawa
694cd07f1d nghttpx: Remove Connection: close header field from CONNECT response
It appears that some Android client does not like Connection: close in
200 CONNECT response.  Browsers fine with this header field.  It is
better to remove it.  Squid does not emit it too.
2014-05-15 23:45:17 +09:00
Tatsuhiro Tsujikawa
5e71f293e5 Update nghttp and nghttpd example output 2014-05-15 00:27:24 +09:00
Tatsuhiro Tsujikawa
d4ec542107 Update doc 2014-05-15 00:11:40 +09:00
Tatsuhiro Tsujikawa
ffdc764d85 Update doc 2014-05-15 00:10:27 +09:00
Tatsuhiro Tsujikawa
2ae1da113e src: Use C++ style comments for C++ source code 2014-05-14 23:22:23 +09:00
Tatsuhiro Tsujikawa
5b4f02dfe0 src: Rewrite util::format_hex 2014-05-14 23:09:33 +09:00
Tatsuhiro Tsujikawa
e47b976691 src: Eliminate use of snprintf 2014-05-14 22:39:28 +09:00
Tatsuhiro Tsujikawa
be4c75a7e9 src: Use gmtime_r instead of gmtime 2014-05-14 21:23:21 +09:00
Tatsuhiro Tsujikawa
7b9a8acc22 Add HPACK deflation API 2014-05-13 23:42:55 +09:00
Tatsuhiro Tsujikawa
03e2dabea9 doc: Add Python API doc 2014-05-13 21:46:39 +09:00
Tatsuhiro Tsujikawa
2411a08b09 python: Return Handler object for pushed resource from BaseRequestHandler.push
Also update doc
2014-05-13 21:42:58 +09:00
Tatsuhiro Tsujikawa
062d6a8398 Remove outdated comment 2014-05-12 22:58:05 +09:00
Tatsuhiro Tsujikawa
ad4a4ee567 Add missing library error code to nghttp2_error() 2014-05-12 22:58:04 +09:00
Tatsuhiro Tsujikawa
ab76468971 Return NGHTTP2_ERR_BUFFER_ERROR from nghttp2_hd_{deflate,inflate}_hd
It is generally useful to know what is the cause of the error.  Since
we expose HPACK API, it is friendly to tell application the
insufficient buffer size is a culprit.
2014-05-12 22:58:04 +09:00
Tatsuhiro Tsujikawa
bc6d952361 Check max SETTINGS_HEADER_TABLE_SIZE in nghttp2_iv_check()
Hide NGHTTP2_MAX_HEADER_TABLE_SIZE from public API.  Now it is defined
as ((1u << 31) - 1) in nghttp2_frame.h, which is sufficiently big
enough.
2014-05-12 21:28:49 +09:00
Tatsuhiro Tsujikawa
f85c592818 Fix compile error with clang -Wunreachable-code 2014-05-12 21:11:27 +09:00
Tatsuhiro Tsujikawa
c9c9beddeb Merge branch 'add_check_compile_flag' of https://github.com/alagoutte/nghttp2 into alagoutte-add_check_compile_flag 2014-05-12 21:05:18 +09:00
Tatsuhiro Tsujikawa
d3fa938f1f nghttpd: Fix compiler warning 2014-05-11 21:51:25 +09:00
Tatsuhiro Tsujikawa
9683f88e6a Add NGHTTP2_DEFAULT_HEADER_TABLE_SIZE macro
Use this macro in Python sources.  Python module constant
HD_DEFLATE_HD_TABLE_BUFSIZE_MAX was renamed as
DEFLATE_MAX_HEADER_TABLE_SIZE since the previous name was awkward.
2014-05-11 21:38:30 +09:00
Tatsuhiro Tsujikawa
2e5c7f598f Fix bug HPACK deflater does not send context update after table size change 2014-05-11 21:25:27 +09:00
Alexis La Goutte
88234cbac0 Add some news CFLAGS:
* -Wpragmas
* -Wunreachable-code
* -Wpedantic
* -Waddress
* -Wattributes
* -Wdiv-by-zero
* -Wheader-guard
2014-05-11 11:28:29 +02:00
Alexis La Goutte
5b208c6277 Add AX_CHECK_COMPILE_FLAG (from Autotools packages)
It's fix the build with Clang and --enable-werror, don't support -WClobberred and display error about unknown warning option
error: unknown warning option '-Wclobbered'; did you mean '-Wconsumed'? [-Werror,-Wunknown-warning-option]
2014-05-11 11:27:52 +02:00
Tatsuhiro Tsujikawa
4fffd23dd3 Code cleanup 2014-05-11 13:53:42 +09:00
Tatsuhiro Tsujikawa
b187895e1d nghttp2_bufs_remove: Prevent NULL from being passed to memcpy 2014-05-11 13:51:46 +09:00
Tatsuhiro Tsujikawa
6e7d0286e3 python: Utilize return value of nghttp2_submit_push_promise 2014-05-10 23:45:05 +09:00
Tatsuhiro Tsujikawa
f2bb7947ee Update doc 2014-05-10 23:22:06 +09:00
Tatsuhiro Tsujikawa
dc791a641d Update doc 2014-05-10 21:43:16 +09:00
Tatsuhiro Tsujikawa
a93e04c6f8 tests: Add failmalloc HPACK test 2014-05-10 21:14:25 +09:00
Tatsuhiro Tsujikawa
d46e13ae52 tests: Fix failmalloc tests 2014-05-10 19:40:23 +09:00
Tatsuhiro Tsujikawa
0707720b11 Code cleanup 2014-05-10 18:27:53 +09:00
Tatsuhiro Tsujikawa
74ad10c355 nghttpx: Log :authority for CONNECT request in accesslog 2014-05-10 00:55:15 +09:00
Tatsuhiro Tsujikawa
f131705ba4 Add h2load.1 dev version for now to make happy 2014-05-10 00:34:56 +09:00
Tatsuhiro Tsujikawa
6a70584459 doc: Add h2load man page 2014-05-10 00:19:57 +09:00
Tatsuhiro Tsujikawa
4c8d4f8a85 Code cleanup 2014-05-10 00:13:40 +09:00
Tatsuhiro Tsujikawa
3ebb3faf32 Remove nghttp2_ prefix from static function, part 2 2014-05-08 23:54:07 +09:00
Tatsuhiro Tsujikawa
65bbdf56cd Remove nghttp2_ prefix from static function 2014-05-08 23:37:56 +09:00
Tatsuhiro Tsujikawa
3e3d51842b Interleave stream DATA more naturally
We simulate resource sharing by decreasing weight.  The thing is if
weight is wrapped, that item continues to send DATA until its weight
gets lowered under the other items.  This commits fix this issue.
2014-05-08 23:07:29 +09:00
Tatsuhiro Tsujikawa
b041218a2a python: Fix function include path 2014-05-08 01:03:28 +09:00
Tatsuhiro Tsujikawa
29d2386f13 Update doc 2014-05-08 00:59:06 +09:00
Tatsuhiro Tsujikawa
1bd43e094a nghttp: Remove streams from HttpClient 2014-05-08 00:29:46 +09:00
Tatsuhiro Tsujikawa
48fc0c04bc doc: Update tutorial-client.rst 2014-05-08 00:11:36 +09:00
Tatsuhiro Tsujikawa
d2890dfb91 Remove adjust_priority_callback
Since we have stream ID immediately available from nghttp2_submit_*,
we don't need adjust_priority_callback.
2014-05-07 23:43:45 +09:00
Tatsuhiro Tsujikawa
e8de437d5c Return new stream ID from nghttp2_submit_{request, headers, push_promise}
Previously stream ID was assigned just before HEADERS or PUSH_PROMISE
was serialized and nghttp2_submit_{request, headers, push_promise} did
not return stream ID.  The application has to check assigned stream ID
using before_frame_send_callback.  Now it is apparent that priority is
meant to DATA transfer only.  Also application can reorder the
requests if it wants. Therefore we can assign stream ID in
nghttp2_submit_* functions and return stream ID from them.  With this
change, now application does not have to check stream ID using
before_frame_send_callback and its code will be simplified.
2014-05-07 23:24:07 +09:00
Tatsuhiro Tsujikawa
51e79c5a3d Remove debug output 2014-05-07 23:23:43 +09:00
Tatsuhiro Tsujikawa
d11cac48f1 Merge branch 'typo' of https://github.com/alagoutte/nghttp2 into alagoutte-typo 2014-05-07 00:35:07 +09:00
Alexis La Goutte
ed63674b88 Fix GCC build with -Werror
timegm.h:30:8: error: C++ style comments are not allowed in ISO C90 [-Werror]
2014-05-06 17:06:40 +02:00
Alexis La Goutte
8e22eadc76 Fix typo 2014-05-06 17:05:47 +02:00
Tatsuhiro Tsujikawa
9228e223fa Remove NGHTTP2_ERR_GZIP error code 2014-05-06 23:42:57 +09:00
Tatsuhiro Tsujikawa
43fb7f707f Fix unittest build error 2014-05-06 23:42:32 +09:00
Tatsuhiro Tsujikawa
f88599197e Update doc 2014-05-06 23:18:12 +09:00
Tatsuhiro Tsujikawa
4f027c1562 libnghttp2: Remove dependency to zlib
We inherited gzip compression API from spdylay codebase.  In spdylay,
the cost of having such API is almost free because spdylay requires
zlib for header compression.  nghttp2 no longer uses gzip to header
compression.  zlib dependency exists just for gzip compression API,
which is not an essential.  So we decided to move gzip code to under
src and remove zlib dependency from libnghttp2 itself.  As nghttp2
package, we depend on zlib to compile tools under src.
2014-05-06 23:10:50 +09:00
Tatsuhiro Tsujikawa
704f362804 nghttp2.h: Use hex style flag definition 2014-05-06 18:49:24 +09:00
Tatsuhiro Tsujikawa
e2535df505 Code cleanup 2014-05-06 18:39:04 +09:00
Tatsuhiro Tsujikawa
f207089604 Update doc 2014-05-06 18:34:48 +09:00
Tatsuhiro Tsujikawa
7b7b0ebcca Update doc 2014-05-06 18:08:41 +09:00
Tatsuhiro Tsujikawa
8289943a58 nghttp2_frame: Add assertion to available buffer size in first buffer 2014-05-06 18:06:46 +09:00
Tatsuhiro Tsujikawa
56d6784d8d nghttp2_frame: Return NGHTTP2_ERR_FRAME_SIZE_ERROR instead of .._BUFFER_ERROR
Also updates docs
2014-05-06 18:02:26 +09:00
Tatsuhiro Tsujikawa
1d26678934 Enable silent-rules by default 2014-05-05 18:48:26 +09:00
Tatsuhiro Tsujikawa
9125499dd0 src: Implement per-frame DATA compression
Currently, nghttpd server only compresses files whose extensions are
one of .html, .js, .css and .txt.  nghttp advertises its support of
per-frame compression in SETTINGS frame.  To implement this feature,
we added 2 public API: nghttp2_session_get_remote_settings() and
nghttp2_gzip_inflate_finished().
2014-05-03 00:02:17 +09:00
Nicholas Hurley
f3f9210dae Add --disable-threads option for configure
This allows users of OS X 10.9 to run nghttpd (and friends) with
threading entirely disabled, to avoid crashes on startup related to
std::mutex.
2014-05-01 17:18:29 -07:00
Tatsuhiro Tsujikawa
9ca63de9e8 examples: Zero clear callbacks 2014-05-01 10:46:08 +09:00
Tatsuhiro Tsujikawa
813c750c12 Merge branch 'clang' of https://github.com/alagoutte/nghttp2 into alagoutte-clang 2014-05-01 10:45:38 +09:00
Tatsuhiro Tsujikawa
3fc1d2dfaa Merge branch 'gcc' of https://github.com/alagoutte/nghttp2 into alagoutte-gcc 2014-05-01 10:29:40 +09:00
Tatsuhiro Tsujikawa
855f39743a Fix crash when indexed repr index=0 2014-05-01 09:06:54 +09:00
Tatsuhiro Tsujikawa
3c431da6aa Fix bug that server treats reception of ENABLE_PUSH=0 as connection error 2014-05-01 08:38:28 +09:00
Alexis La Goutte
66ed7f6a59 Fix build when use Clang
libevent-server.c:552:43: error: missing field 'recv_callback' initializer [-Werror,-Wmissing-field-initializers]
2014-04-30 17:31:33 +02:00
Alexis La Goutte
8ca2f6aa92 Fix build when use Clang
libevent-client.c:355:43: error: missing field 'recv_callback' initializer [-Werror,-Wmissing-field-initializers]
2014-04-30 17:31:29 +02:00
Alexis La Goutte
fa2fbe944f Fix GCC build with -Werror
libevent-server.c:691:8: error: C++ style comments are not allowed in ISO C90
2014-04-30 17:09:06 +02:00
Alexis La Goutte
33a6851abe Fix GCC build with -Werror
nghttp2_session.c:1615:9: error: C++ style comments are not allowed in ISO C90 [-Werror]
2014-04-30 17:09:06 +02:00
Alexis La Goutte
763cdc3499 Fix GCC when use -Wpedantic
nghttp2_stream.h:94:43: error: comma at end of enumerator list [-Werror=pedantic]
2014-04-30 17:09:05 +02:00
Alexis La Goutte
0f5c28ac46 Fix GCC when use -Wpedantic
nghttp2_hd.h:115:30: error: comma at end of enumerator list [-Werror=pedantic]
2014-04-30 17:09:05 +02:00
Alexis La Goutte
941236948f Fix GCC when use -Wpedantic
nghttp2_int.h:50:33: error: comma at end of enumerator list [-Werror=pedantic]
2014-04-30 17:09:05 +02:00
Tatsuhiro Tsujikawa
660c536275 Extend namelen and valuelen in nghttp2_nv to size_t 2014-04-30 23:08:34 +09:00
Tatsuhiro Tsujikawa
abe74f869f Ditto 7730b13e5a 2014-04-30 22:44:51 +09:00
Tatsuhiro Tsujikawa
52b74144ee Fix 0 size malloc, part 2 2014-04-30 22:40:43 +09:00
Tatsuhiro Tsujikawa
1b79114d2d Fix compiler warnings 2014-04-30 22:16:21 +09:00
Tatsuhiro Tsujikawa
ab634853df Fix 0 size malloc 2014-04-30 22:09:02 +09:00
Tatsuhiro Tsujikawa
d2e64317ba Code cleanup, include nghttp2_int.h explicitly to ensure debug macro 2014-04-30 22:08:32 +09:00
Alexis La Goutte
7730b13e5a Fix Address of stack memory associated with local variable 'flag' is still
referred to by the global variable 'long_options' upon returning to the caller.
This will be a dangling reference

Found by Clang Analyzer
2014-04-30 22:06:42 +09:00
Alexis La Goutte
ed5339953e Fix Dead Store (Dead assignement/Dead increment) warning found by Clang Analyzer 2014-04-30 22:06:42 +09:00
Alexis La Goutte
b2f07b1d8c Fix Dead Store (Dead assignement/Dead increment) warning found by Clang Analyzer 2014-04-30 22:06:42 +09:00
Alexis La Goutte
eff5c7d0d0 Fix Dead Store (Dead assignement/Dead increment) warning found by Clang Analyzer 2014-04-30 22:06:42 +09:00
Alexis La Goutte
e00b8f1f73 Fix Dead Store (Dead assignement/Dead increment) warning found by Clang Analyzer 2014-04-30 22:06:42 +09:00
Tatsuhiro Tsujikawa
fe6b541233 Handle hd inflate buffer allocation failure 2014-04-30 11:32:05 +09:00
Tatsuhiro Tsujikawa
167a1102e0 Remove unused NGHTTP2_HD_MAX_BUFFER_LENGTH macro 2014-04-30 10:55:43 +09:00
Tatsuhiro Tsujikawa
d61208b394 Update doc 2014-04-30 10:49:19 +09:00
Tatsuhiro Tsujikawa
4cf023d94c Update doc 2014-04-30 10:28:50 +09:00
Tatsuhiro Tsujikawa
b5d793dee6 app_helper: Remove redundant line separator after frame debug output 2014-04-30 10:01:19 +09:00
Tatsuhiro Tsujikawa
4caddec9ba nghttp: Align NULL separated header fields 2014-04-30 09:56:33 +09:00
Tatsuhiro Tsujikawa
3b4aedd566 Add HPACK decoder public API 2014-04-29 15:53:46 +09:00
Tatsuhiro Tsujikawa
bc50062964 nghttp: Fix crash on PUSH_PROMISE 2014-04-29 15:08:57 +09:00
Tatsuhiro Tsujikawa
c69f6f4186 Use AC_DEFINE for DEBUG macro instead of adding it to CFLAGS 2014-04-29 12:58:52 +09:00
Tatsuhiro Tsujikawa
8c5db539b3 Change NGHTTP2_MAX_HEADER_TABLE_SIZE to 256MiB 2014-04-28 22:50:43 +09:00
Tatsuhiro Tsujikawa
fa8b310cfd nghttpx: Return SSL_TLSEXT_ERR_OK from servername_callback 2014-04-27 23:17:19 +09:00
Tatsuhiro Tsujikawa
6d5f402380 Add nghttp2_adjust_priority_callback
Callback function invoked to adjust priority value for request
HEADERS.

Since the application doesn’t know stream ID when it submits
requests, it may not be able to add correct priority value to HEADERS
frame and forced to use follwing PRIORITY frame. The purpose of this
callback is give the chance to the application to adjust priority
value with the latest information it has just before transmission so
that correct priority is included in HEADERS frame and it doesn’t
have to send additional PRIORITY frame.
2014-04-27 14:48:43 +09:00
Tatsuhiro Tsujikawa
cc7929bdcc Fix possible SIGFPE 2014-04-27 14:40:10 +09:00
Tatsuhiro Tsujikawa
a82b7f09c8 nghttpx: Drop HTTP/2 backend connection unless TLSv1.2 or TLSv1.1 was negotiated 2014-04-26 23:00:58 +09:00
Tatsuhiro Tsujikawa
75bfbc94dd nghttpx: Require TLSv1.2 or TLSv1.1 for NPN as well 2014-04-26 22:51:39 +09:00
Tatsuhiro Tsujikawa
6c66bd5c7c ALPN: Do not negotiate HTTP/2 unless TLSv1.2 or TLSv1.1 was used 2014-04-26 22:37:48 +09:00
Tatsuhiro Tsujikawa
cd69ed20c3 nghttpx: Select SPDY protocol in ALPN 2014-04-26 19:36:35 +09:00
Tatsuhiro Tsujikawa
a8a2236da9 nghttpx: Add --add-response-header option 2014-04-26 14:56:08 +09:00
Tatsuhiro Tsujikawa
293b717b04 nghttp: Fix bug that -H does not allow single letter header name 2014-04-26 14:53:03 +09:00
Tatsuhiro Tsujikawa
078b1de12e nghttp: Fix uninitialized pri_spec 2014-04-25 21:23:47 +09:00
Tatsuhiro Tsujikawa
d84d0b8c5c h2load: Check return of nghttp2_submit_request 2014-04-25 21:23:31 +09:00
Tatsuhiro Tsujikawa
cb6a3cf4e7 Update README.rst 2014-04-25 20:04:15 +09:00
Tatsuhiro Tsujikawa
59e42c1c69 Update doc 2014-04-25 01:39:40 +09:00
Tatsuhiro Tsujikawa
a5f715963e Update README.rst 2014-04-25 01:37:00 +09:00
Tatsuhiro Tsujikawa
d49733a5c9 Declare h2-12 for now 2014-04-25 01:33:29 +09:00
Tatsuhiro Tsujikawa
052be3296c Implement compressed DATA
The library interface supports compressed DATA.  The library does not
deflate nor inflate data payload.  When sending data, an application
has to compress data and set NGHTTP2_DATA_FLAG_COMPRESSED to
data_flags parameter in nghttp2_data_source_read_callback.  On
receiving, flags parameter in nghttp2_on_data_chunk_recv_callback
includes NGHTTP2_FLAG_COMPRESSED.  An application should check the
flags and inflate data as necessary.  Since compression context is per
frame, when DATA is seen in nghttp2_on_frame_recv_callback, an
application should reset compression context.
2014-04-25 01:27:18 +09:00
Tatsuhiro Tsujikawa
6bb410d603 Implement BLOCKED frame 2014-04-25 00:38:24 +09:00
Tatsuhiro Tsujikawa
2d4b92fc2b Merge branch 'priority' 2014-04-24 23:48:37 +09:00
Tatsuhiro Tsujikawa
ee26469cd9 Handle circular dependency
Handle the situation if a stream is told to depend on its descendant.
This is what
http://tools.ietf.org/html/draft-ietf-httpbis-http2-12#section-5.3.3
says.
2014-04-24 23:44:34 +09:00
Tatsuhiro Tsujikawa
853c9888d9 Distribute effective weight among only streams with marked as top
If stream with dpri value of no_data, we check any its descendant has
stream with dpri value of top.  If so, we have to distribute of its
portion of weight to its descendants.
2014-04-24 23:37:40 +09:00
Tatsuhiro Tsujikawa
85190f3677 Update README.rst 2014-04-24 00:00:54 +09:00
Tatsuhiro Tsujikawa
efd90c349d python: Output seqno in hpackmake.py, utilize it in hpackcheck.py 2014-04-23 00:55:54 +09:00
Tatsuhiro Tsujikawa
5aa0a0d099 Check protocol length so that scanner don't overrun buffer 2014-04-22 23:20:33 +09:00
Tatsuhiro Tsujikawa
80eb988511 h2load: Add -p, --no-tls-proto option to support SPDY without SSL/TLS
Previously h2load supports SPDY only for https URI.  This is because
SPDY has no mechanism to negotiate its protocol version without NPN.
With this change, user can specify the exact protocol version to use
when http URI (without SSL/TLS) is used.
2014-04-21 21:35:45 +09:00
Tatsuhiro Tsujikawa
a8525a131a Update .gitignore 2014-04-21 00:57:27 +09:00
Tatsuhiro Tsujikawa
6a598d8fb8 python: Fix parellel make distcheck and not distribute nghttp2.c
It seems that setup.py gets deleted before python executes it in
clean-local.  To prevent this situation, we just use .NOTPARALLEL.

Previously we distribute nghttp2.c in python, which is cythonized C
source code from nghttp2.pyx.  Since it is distributed in archive it
exists in source directory.  But we use python distutils which
operates in build directory and does not support C source files in out
of tree directory (i.e., not under the build directory).  Copying C
source file to build directory is a bit dirty, so we just decided not
to ship nghttp2.c.
2014-04-21 00:51:12 +09:00
Tatsuhiro Tsujikawa
1d5a1b895b doc: Use autoconf template nghttpx-howto.rst.in properly 2014-04-20 23:42:15 +09:00
Tatsuhiro Tsujikawa
e6fdb3418d doc: Add nghttpx-howto.rst 2014-04-20 23:35:07 +09:00
Tatsuhiro Tsujikawa
5240f8ad7e python: Update to draft version to 7 in hpackmake.py 2014-04-20 23:02:56 +09:00
Tatsuhiro Tsujikawa
91b616dd6f Update doc 2014-04-18 22:55:21 +09:00
Tatsuhiro Tsujikawa
1c1843297c priority: Add tests 2014-04-17 21:34:44 +09:00
Tatsuhiro Tsujikawa
aa4d43f31e Allow exclusive dependency to stream 0 2014-04-17 21:18:18 +09:00
Tatsuhiro Tsujikawa
ac86b51e37 Implement simplified dependency based priority 2014-04-15 22:55:07 +09:00
Tatsuhiro Tsujikawa
27a91fc30e Allow NGHTTP2_PRIORITY_TYPE_NONE in nghttp2_submit_{request,headers} 2014-04-10 23:29:56 +09:00
Tatsuhiro Tsujikawa
ece6521d26 Check stream availability when sending ALTSVC with stream_id != 0 2014-04-10 23:27:10 +09:00
Tatsuhiro Tsujikawa
792938d410 Update doc 2014-04-09 00:16:04 +09:00
Tatsuhiro Tsujikawa
9b3d5a8be5 Harden check for submit functions
nghttp2_submit_{headers,request}: Return NGHTTP2_ERR_INVAILD_ARGUMENT
if pri_spec->type is invalid.

nghttp2_submit_push_promise: Return NGHTTP2_ERR_PROTO if issued by
client.

nghttp2_submit_altsvc: Return NGHTTP2_ERR_PROTO instead of
NGHTTP2_ERR_INVALID_STATE if issued by client.
2014-04-09 00:13:11 +09:00
Tatsuhiro Tsujikawa
8658163aac Update doc 2014-04-08 23:18:59 +09:00
Tatsuhiro Tsujikawa
6326aec089 nghttpx: Return std::unique_ptr from parse_config_str_list 2014-04-08 22:44:30 +09:00
Tatsuhiro Tsujikawa
f9f6cdc93d nghttpx: Specify altsvc info in one option and allow multiple occurrences 2014-04-08 22:28:50 +09:00
Tatsuhiro Tsujikawa
5b3deec186 Fix python build on windows
Patch from Gisle Vanem

"""
I tried to build this extension on Windows, but failed since
ws2_32.lib is needed in libraries
"""
2014-04-07 22:15:15 +09:00
Tatsuhiro Tsujikawa
f3f031f94c Merge branch 'wsgi' of https://github.com/alekstorm/nghttp2 into alekstorm-wsgi 2014-04-07 21:16:24 +09:00
Alek Storm
be7aa8f53a Add experimental WSGI server implementation 2014-04-06 21:33:32 -07:00
Tatsuhiro Tsujikawa
7563839756 Update doc 2014-04-06 21:13:44 +09:00
Tatsuhiro Tsujikawa
ffcbffc28b Revert f763d76110 2014-04-06 17:56:48 +09:00
Tatsuhiro Tsujikawa
d998e79549 h2load: Link with timegm 2014-04-06 17:35:00 +09:00
Tatsuhiro Tsujikawa
1aa69e334d Fix compile error on 32-bit systems 2014-04-06 17:34:44 +09:00
Tatsuhiro Tsujikawa
1c00e715a3 Update doc 2014-04-06 17:23:42 +09:00
Tatsuhiro Tsujikawa
59c9c4511c nghttpx: Use move to insert crumbled cookies 2014-04-05 23:45:07 +09:00
Tatsuhiro Tsujikawa
f763d76110 Revert NGHTTP2_DATA_PAYLOADLEN to 4086 2014-04-05 23:42:37 +09:00
Tatsuhiro Tsujikawa
5b55874d4d Fix static analysis error 2014-04-05 20:04:09 +09:00
Tatsuhiro Tsujikawa
c9f3de5f6b python: Fix compile error 2014-04-05 19:16:40 +09:00
Tatsuhiro Tsujikawa
c2bb9c01a6 nghttp: Update doc for -p option and improve error handling for it 2014-04-05 19:15:45 +09:00
Tatsuhiro Tsujikawa
0a527f16f5 nghttpx: Log when connection was upgraded to HTTP/2 2014-04-05 18:59:22 +09:00
Tatsuhiro Tsujikawa
8f23c0c38b Name unnamed union in nghttp2_priority_spec so that we can be C90 compatible 2014-04-05 18:40:44 +09:00
Tatsuhiro Tsujikawa
c1060f0d48 Announce h2-11 2014-04-05 18:26:48 +09:00
Tatsuhiro Tsujikawa
15e8d0de7b Update tutorial 2014-04-05 18:04:21 +09:00
Tatsuhiro Tsujikawa
e7ad3633c7 nghttp2_data_source_read_callback: Replace eof with uint32_t *data_flags
Replace int *eof with uint32_t *data_flags so that we can easily
extend functionality if we have to (but we don't do if possible).
2014-04-05 17:59:24 +09:00
Tatsuhiro Tsujikawa
a0d93e7744 Fix unit test 2014-04-05 17:55:14 +09:00
Tatsuhiro Tsujikawa
124da7720f Fix compile error 2014-04-05 17:45:06 +09:00
Tatsuhiro Tsujikawa
d668d2448b Hide session option from public API
To make adding new option easier, we decided to make the details of
option struct private and hide it from public API.  We provide
functions to set individual option value.
2014-04-04 21:57:47 +09:00
Tatsuhiro Tsujikawa
21ab2f135b Connection error if client changes SETTINGS_ENABLE_PUSH to nonzero 2014-04-04 20:36:09 +09:00
Tatsuhiro Tsujikawa
1e38ceb1cd Allow empty SETTINGS in upgrade 2014-04-04 20:23:46 +09:00
Tatsuhiro Tsujikawa
2a49e164c8 nghttpx: Fix crash with HTTP/2 downstream 2014-04-03 19:14:05 +09:00
Tatsuhiro Tsujikawa
22c88af1ab nghttpx: Resume deferred DATA after complete DATA frame arrived on backend
If SPDY or HTTP/2 ustream is used and HTTP/2 downstream is used, only
call {spdylay,nghttp2}_resume_data when complete DATA frame was read
in backend to avoid to transmit too small DATA frame to the upstream.
2014-04-03 18:54:15 +09:00
Tatsuhiro Tsujikawa
5d80d18f31 Cosmetic change 2014-04-03 16:06:03 +09:00
Tatsuhiro Tsujikawa
37e1626478 Update doc 2014-04-03 16:01:30 +09:00
Tatsuhiro Tsujikawa
6cddfaf263 nghttp2_stream_resume_deferred_data: Call stream_update_dep_on_attach_data
.. instead of nghttp2_stream_attach_data() internal API
2014-04-03 15:52:21 +09:00
Tatsuhiro Tsujikawa
ac2a8ef4a2 Fix bug that transfer stuck when stream marked as top is deferred 2014-04-03 15:48:51 +09:00
Tatsuhiro Tsujikawa
b671375abc doc: Update tutorial 2014-04-03 15:22:22 +09:00
Tatsuhiro Tsujikawa
db6c41a219 nghttpx: Add altsvc related options
To advertise alternative serive, at least --altsvc-port and
--altsvc-protocol-id must be specified.
2014-04-03 13:20:50 +09:00
Tatsuhiro Tsujikawa
1d38df0a31 nghttp: Don't index authorization header field for debugging purpose 2014-04-03 11:33:15 +09:00
Tatsuhiro Tsujikawa
b1edb1f3ae Don't index name/value pair bearing NO_INDEX flag when forwarding it 2014-04-03 11:22:11 +09:00
Tatsuhiro Tsujikawa
c53c1dc669 nghttp2_session_resume_data: Return error if no deferred data exist 2014-04-03 00:01:35 +09:00
Tatsuhiro Tsujikawa
580a19e097 nghttp2_stream_detach_deferred_data -> nghttp2_stream_resume_deferred_data 2014-04-02 22:58:06 +09:00
Tatsuhiro Tsujikawa
ef40879b5f Refactor nghttp2_stream
Combine deferred_data and data into data_item and merge deferred_flags
into flags.
2014-04-02 22:55:49 +09:00
Tatsuhiro Tsujikawa
35a45f9d47 src: Initialize nghttp2_nv flags 2014-04-02 20:37:33 +09:00
Tatsuhiro Tsujikawa
2685e3405f Rename NGHTTP2_DATA_PAYLOAD_LENGTH as NGHTTP2_DATA_PAYLOADLEN 2014-04-02 20:35:07 +09:00
Tatsuhiro Tsujikawa
9c4c99bf96 Adjust transmission frame buffer size to support maximum payload size 2014-04-02 20:33:01 +09:00
Tatsuhiro Tsujikawa
9d9eb48258 python: Update according to HPACK change, but flags are not used yet 2014-04-02 02:16:39 +09:00
Tatsuhiro Tsujikawa
c9f90924a9 Add flags parameter to nghttp2_on_header_callback 2014-04-02 02:10:35 +09:00
Tatsuhiro Tsujikawa
e5b0303481 Update huffman codes 2014-04-02 01:44:39 +09:00
Tatsuhiro Tsujikawa
b1722cbe28 Update static table 2014-04-02 01:30:50 +09:00
Tatsuhiro Tsujikawa
7877b676e3 Honor NGHTTP2_NV_FLAG_NO_INDEX in deflater and inflater 2014-04-02 01:25:44 +09:00
Tatsuhiro Tsujikawa
c55df4a30b Fix compile error with --enable-werror 2014-04-02 01:18:27 +09:00
Tatsuhiro Tsujikawa
24cb90806d Add flags to nghttp2_nv structure
This is preliminary change for upcoming HPACK updates.  The flags are
used to determine the name/value pair is indexable or not.
2014-04-01 23:17:50 +09:00
Tatsuhiro Tsujikawa
da5db205ca Make group weight range [1, 256], inclusive
We do -+1 on serialization and deserialization since the field is 1
byte.  This change also parameterized range so that we can change it
easily.
2014-04-01 22:54:20 +09:00
Tatsuhiro Tsujikawa
f2d945734e Rename framebuflen as framerv, cause it is not a length 2014-04-01 21:59:26 +09:00
Tatsuhiro Tsujikawa
f5ead55f0e Check payload length when submitting GOAWAY and ALTSVC 2014-04-01 21:55:29 +09:00
Tatsuhiro Tsujikawa
f785e56dba Implement ALTSVC frame 2014-04-01 21:47:51 +09:00
Tatsuhiro Tsujikawa
b143039b60 src: Output debug data in GOAWAY in printable ascii
Non printable ascii is printed as ".".
2014-03-31 23:17:51 +09:00
Tatsuhiro Tsujikawa
6afb7442b5 Adjust weight when pushing data to queue 2014-03-31 23:01:05 +09:00
Tatsuhiro Tsujikawa
b85e2ab7f7 Share stream_group weight among streams marked as top 2014-03-31 22:51:33 +09:00
Tatsuhiro Tsujikawa
f011bda377 src: Compile defaltehd and inflatehd with c++
This commit also fixes defaltehd always reports output length is 0.
2014-03-30 22:41:02 +09:00
Tatsuhiro Tsujikawa
34581d830d Define NGHTTP2_CLEARTEXT_PROTO_VERSION_ID
This identifier string is used if HTTP/2 is used over cleartext TCP.
2014-03-30 21:30:47 +09:00
Tatsuhiro Tsujikawa
334658044e Update tutorial 2014-03-30 21:08:04 +09:00
Tatsuhiro Tsujikawa
60a2c260a5 Define NGHTTP2_CLIENT_CONNECTION_PREFACE macro
NGHTTP2_CLIENT_CONNECTION_PREFACE has the same content with
NGHTTP2_CLIENT_CONNECTION_HEADER, which is now obsoleted by
NGHTTP2_CLIENT_CONNECTION_PREFACE.
2014-03-30 21:02:25 +09:00
Tatsuhiro Tsujikawa
ab2dc5967d Replace HTTP/2.0 with HTTP/2 2014-03-30 19:26:37 +09:00
Tatsuhiro Tsujikawa
705051ceb7 Update doc 2014-03-30 19:00:42 +09:00
Tatsuhiro Tsujikawa
d3962becf4 Ignore priority request if resultant tree has cycle 2014-03-30 18:48:32 +09:00
Tatsuhiro Tsujikawa
21d5986157 Fail nghttp2_submit_settings if there is pending SETTINGS frame in-flight
pending_local_max_concurrent_stream is now set in
nghttp2_session_add_settings, rather than after frame was sent.
2014-03-30 18:07:52 +09:00
Tatsuhiro Tsujikawa
74daa16a1c Retain incoming closed streams for dependency tree
The number of closed stream to keep is limited by
MAX_CONCURRENT_STREAMS - current active stream.
2014-03-30 17:41:54 +09:00
Tatsuhiro Tsujikawa
a9d97d9d35 Update doc 2014-03-30 01:34:13 +09:00
Tatsuhiro Tsujikawa
bd7d335d9a src: Print padlen first 2014-03-30 01:24:17 +09:00
Tatsuhiro Tsujikawa
c12b6bc360 Call on_stream_close_callback for a stream in reserved state
This is useful because application may allocate resources for it and
wants to free the resources if they are not used anymore.
2014-03-30 01:24:16 +09:00
Tatsuhiro Tsujikawa
58da463ad6 Make deflater bad state if parsing HEADERS/PUSH_PROMISE failed 2014-03-30 01:24:16 +09:00
Tatsuhiro Tsujikawa
36c8de9da5 Limit the number of streams in one dependency tree 2014-03-30 01:24:16 +09:00
Tatsuhiro Tsujikawa
f7162ab702 Implement dependency based priority 2014-03-30 01:24:16 +09:00
Tatsuhiro Tsujikawa
8ccb6e463d nghttpx: Use raw-string iteral to output help 2014-03-22 22:03:13 +09:00
Tatsuhiro Tsujikawa
e4dacb2f6f nghttpd: Use raw-string literal to output help 2014-03-22 21:35:00 +09:00
Tatsuhiro Tsujikawa
dbb82b0f9c Make opaque_data parameter in nghttp2_submit_goaway const 2014-03-22 19:05:58 +09:00
Tatsuhiro Tsujikawa
e1eebf08fb Support DEBUG_DATA in GOAWAY again 2014-03-22 18:59:59 +09:00
Tatsuhiro Tsujikawa
01586f473d Wrap small inbound buffer by nghttp_buf 2014-03-22 18:27:38 +09:00
Tatsuhiro Tsujikawa
3c631b5625 Code cleanup 2014-03-22 17:16:25 +09:00
Tatsuhiro Tsujikawa
774cf88f68 Don't add RST_STREAM frame if stream is in NGHTTP2_STREAM_CLOSING 2014-03-22 00:51:40 +09:00
Tatsuhiro Tsujikawa
0a80b0c1aa nghttpd: Set write timeout for stream blocked by flow controll only
This change also reset read timeout when we have sent HEADERS,
PUSH_PROMISE or DATA.
2014-03-22 00:41:01 +09:00
Tatsuhiro Tsujikawa
1dfe2f8670 Add nghttp2_session_get_stream_remote_window_size public API function 2014-03-22 00:34:25 +09:00
Tatsuhiro Tsujikawa
fac42788bc nghttpd: Rename Request as Stream 2014-03-21 23:26:53 +09:00
Tatsuhiro Tsujikawa
464fef7c6e nghttpd: Add HTTP/2 stream read/write timeout 2014-03-21 23:07:20 +09:00
Tatsuhiro Tsujikawa
334656b704 nghttpx: Announce 2.0 in via header field 2014-03-21 19:25:46 +09:00
Tatsuhiro Tsujikawa
ba5d9d3352 nghttpx: Add x-forwarded-proto header field to downstream HTTP/2 request 2014-03-21 18:57:57 +09:00
Tatsuhiro Tsujikawa
d0fbbe6932 Less cryptic debug message 2014-03-20 00:27:39 +09:00
Tatsuhiro Tsujikawa
c945d4ebbe Fix compile error with --enable-debug 2014-03-19 23:24:46 +09:00
Tatsuhiro Tsujikawa
c048ac5eff nghttpd: Avoid to use bufferevent for connection 2014-03-18 00:09:59 +09:00
Tatsuhiro Tsujikawa
68b392817b nghttp2_bufs: Add chunk_keep to specify the number of buffers to keep on reset 2014-03-16 21:38:13 +09:00
Tatsuhiro Tsujikawa
fbfa3adc42 h2load: traffic bytes data should be based on all traffic 2014-03-16 19:36:41 +09:00
Tatsuhiro Tsujikawa
775d07ace4 EvbufferBuffer: Optimize a bit 2014-03-15 16:23:12 +09:00
Tatsuhiro Tsujikawa
fef01a3c39 nghttpd: Honor server's cipher preferece order 2014-03-15 16:11:30 +09:00
Tatsuhiro Tsujikawa
a7eb6502a9 src: Use large transmission buffer to reduce SSL/TLS overhead 2014-03-15 16:10:42 +09:00
Tatsuhiro Tsujikawa
a457d2a138 h2load, nghttp: Use SNI field for non-numeric host 2014-03-15 15:32:38 +09:00
Tatsuhiro Tsujikawa
843ecd8cc1 h2load: Support multiple URIs
Supplying multiple URIs can simulate more real life situation on
server side.  For example, we can supply URIs of html, css and js and
benchmark the server.  The -m option is updated so that it defaults to
the number of supplied URIs.
2014-03-14 23:15:01 +09:00
Tatsuhiro Tsujikawa
5b81f7c713 Don't show PAD_HIGH and PAD_LOW flags to user callback 2014-03-14 21:53:03 +09:00
Tatsuhiro Tsujikawa
2ec4b10805 Add nghttp2_buf tests 2014-03-14 21:40:14 +09:00
Tatsuhiro Tsujikawa
781d1a2b70 Code cleanup 2014-03-14 02:23:50 +09:00
Tatsuhiro Tsujikawa
7ffa594d4c nghttp: Use raw-literal string for help output 2014-03-14 01:53:28 +09:00
Tatsuhiro Tsujikawa
136d997596 h2load: Support -W option for SPDY, if the value >= 16 2014-03-14 01:40:41 +09:00
Tatsuhiro Tsujikawa
2b7627f70c h2load: Use raw-string literal for help output 2014-03-14 01:06:47 +09:00
Tatsuhiro Tsujikawa
0620052f50 src: Use std::numeric_limits<>::max() instead of INT64_MAX 2014-03-14 00:54:10 +09:00
Tatsuhiro Tsujikawa
142b433533 nghttp2_hd: Treat prematurely ended compressed header block as error properly 2014-03-14 00:52:44 +09:00
Tatsuhiro Tsujikawa
b464cb78ac Fix tests to reflect their intent 2014-03-14 00:25:43 +09:00
Tatsuhiro Tsujikawa
344d663e90 deflate_hd: Fix mishandled error return from emit_indexed_block 2014-03-14 00:25:03 +09:00
Tatsuhiro Tsujikawa
d48eca60cf Fix broken nghttp2_bufs_avail 2014-03-14 00:24:34 +09:00
Tatsuhiro Tsujikawa
aefc0d1ebb Use calloc instead of malloc + memset; remove useless memset 2014-03-13 23:27:14 +09:00
Tatsuhiro Tsujikawa
1be8d1b797 inflate_header_block: Issue RST_STREAM if header decompression failed 2014-03-13 23:02:33 +09:00
Tatsuhiro Tsujikawa
0fa4779d38 Don't call on_frame_recv_callback after stream close or being closed 2014-03-13 22:49:37 +09:00
Tatsuhiro Tsujikawa
d07bb1ddff Rework outbound frame buffers 2014-03-13 22:11:02 +09:00
Tatsuhiro Tsujikawa
0666a73e10 Remove nghttp2_buffer 2014-03-11 21:20:51 +09:00
Tatsuhiro Tsujikawa
3f56c938d8 nghttp2_hd: Use nghttp2_bufs, avoiding realloc() 2014-03-11 21:18:28 +09:00
Tatsuhiro Tsujikawa
7b2d585896 Return 0 if nghttp2_session_prep_frame succeeds rather than frame length 2014-03-11 02:15:05 +09:00
Tatsuhiro Tsujikawa
74f899fc01 Replace NGHTTP2_MAX_FRAME_LENGTH with NGHTTP2_MAX_PAYLOADLEN 2014-03-11 02:01:08 +09:00
Tatsuhiro Tsujikawa
e803c6b65e Replace NGHTTP2_FRAME_HEAD_LENGTH with NGHTTP2_FRAME_HDLEN 2014-03-11 01:55:42 +09:00
Tatsuhiro Tsujikawa
358b4386d3 Introduce nghttp2_buf to ease buffer management 2014-03-11 01:47:38 +09:00
Tatsuhiro Tsujikawa
d074cb611f nghttpx: Add rate limit per worker thread
The existing options --{read,write}-{rate,burst} are per connection.
The new options --worker-{read,write}-{rate,burst} are per worker
thread, which is overall rate limit of all connections worker handles.
2014-03-09 14:53:28 +09:00
Tatsuhiro Tsujikawa
54dab50015 Support END_SEGMENT in nghttp2_submit_data() 2014-03-06 00:19:02 +09:00
Tatsuhiro Tsujikawa
b60679808b Filter supported flags in received frame 2014-03-05 23:25:42 +09:00
Tatsuhiro Tsujikawa
547d6d1fb5 Use 4086 as max DATA payload size to make DATA frame fit into 4K buffer 2014-03-05 22:48:17 +09:00
Tatsuhiro Tsujikawa
382024a180 Update README.rst 2014-03-05 21:46:26 +09:00
Tatsuhiro Tsujikawa
12d92a621d Add --with-spdylay configure option 2014-03-05 21:44:28 +09:00
Tatsuhiro Tsujikawa
7f18eced0b src: Use jemalloc if available 2014-03-05 21:38:33 +09:00
Tatsuhiro Tsujikawa
27e161dc31 src: Add EvbufferBuffer class to simplify the code base 2014-03-05 00:23:33 +09:00
Tatsuhiro Tsujikawa
3ca4539f99 nghttpd: Only emit content-encoding: gzip when error-gzip is on 2014-03-04 23:37:42 +09:00
Tatsuhiro Tsujikawa
ddfa93ff5b nghttpx: Make socketpair in internal use non-block 2014-03-04 23:34:48 +09:00
Tatsuhiro Tsujikawa
a61ca763df nghttpd: Add -e option to toggle gzipped error response 2014-03-04 23:29:30 +09:00
Tatsuhiro Tsujikawa
749cc08f52 Update README.rst 2014-03-04 23:16:46 +09:00
Tatsuhiro Tsujikawa
caeeba681f nghttpd: Add multi threading support 2014-03-04 23:14:26 +09:00
Tatsuhiro Tsujikawa
d4ea2418d8 nghttpx: Use LibsslGlobalLock 2014-03-04 21:33:43 +09:00
Tatsuhiro Tsujikawa
73f55e7b7a h2load: Fix crash with multi threading 2014-03-04 21:32:57 +09:00
Tatsuhiro Tsujikawa
13be30e582 Update src/.gitignore 2014-03-04 01:16:42 +09:00
Tatsuhiro Tsujikawa
60fc117c9c Update README.rst 2014-03-04 01:16:15 +09:00
Tatsuhiro Tsujikawa
5cfb51c881 h2load: Support parellel native threads execution with -t option 2014-03-04 01:12:11 +09:00
Tatsuhiro Tsujikawa
f3183efe04 nghttpd: Emit protocol id error only when verbose output is enabled 2014-03-03 23:51:46 +09:00
Tatsuhiro Tsujikawa
b5341ebac6 nghttpd: More SSL_CTX options and support EDCHE cipher 2014-03-03 23:49:13 +09:00
Tatsuhiro Tsujikawa
e34b8ac7fb src: Avoid to call costly evbuffer_add() repeatedly
The profiler and benchmarking showed that calling evbuffer_add()
repeatedly is very costly. To avoid this, we buffer up small writes
into one large chunk and call evbuffer_add() less times.
2014-03-03 23:45:57 +09:00
antbryan
58485bd1d8 Update README.rst
some small additions for clarity. please check to ensure meaning is preserved.
2014-03-02 13:52:08 -05:00
Tatsuhiro Tsujikawa
3d211e1cfd h2load: Fix compiler warning 2014-03-03 00:53:31 +09:00
Tatsuhiro Tsujikawa
79c5032708 nghttp2_hd: Fix crash with multiple threads execution 2014-03-03 00:53:04 +09:00
Tatsuhiro Tsujikawa
e06cc13edb Update README.rst 2014-03-02 23:45:47 +09:00
Tatsuhiro Tsujikawa
1337fa8bfe src: Add h2load, benchmarking tool for HTTP/2 and SPDY 2014-03-02 23:45:47 +09:00
Tatsuhiro Tsujikawa
c1e1a1be5a nghttpx: Cast uint8_t to uint32_t to display it as numeric value 2014-03-02 23:22:28 +09:00
Tatsuhiro Tsujikawa
979feaecc6 Mitigate heap fragmentation when lots of concurrent http2 sessions run 2014-03-02 16:34:23 +09:00
Tatsuhiro Tsujikawa
6f0b9128b4 tests: Fix leak 2014-02-28 03:07:19 +09:00
Tatsuhiro Tsujikawa
a85455ed0b src: Zero clear http_parser_url struct 2014-02-27 22:11:31 +09:00
Tatsuhiro Tsujikawa
227a48cea1 src: Move http_parser_url related functions to util 2014-02-27 21:53:52 +09:00
Tatsuhiro Tsujikawa
ddf6162528 python: Use distutils to build/install python bindings
automake version is a bit picky about installation location and uses
different compiler flags from distutils. We prefer official distutils.
Now nghttp2.c, which is generated by cython, is distributed in
archive.
2014-02-27 00:58:21 +09:00
Tatsuhiro Tsujikawa
abdbd29d5f Update doc 2014-02-27 00:01:35 +09:00
Tatsuhiro Tsujikawa
1fee4fd2df nghttp2_hd: Fail inflate immediately if ctx.bad is nonzero
Doing inflation after error produces invalid results, especially, if
it is in NGHTTP2_HD_STATE_READ_INDEX, the inflater->left could be 0,
which causes assertion error.  Add sanity assertion for index
2014-02-26 23:20:52 +09:00
Tatsuhiro Tsujikawa
18357512ed nghttp2_hd: Fix integer decoding bug 2014-02-26 21:44:48 +09:00
Tatsuhiro Tsujikawa
52cec35906 python: Fix NameError if asyncio is not available 2014-02-26 00:54:16 +09:00
Tatsuhiro Tsujikawa
13cc3f2fe9 src, python: Only produce header_table_size when it is changed 2014-02-25 23:55:06 +09:00
Tatsuhiro Tsujikawa
7cf574d0d8 python: Update doc 2014-02-25 23:29:50 +09:00
Tatsuhiro Tsujikawa
57af995fd0 Update README.rst 2014-02-25 23:29:50 +09:00
Tatsuhiro Tsujikawa
911ffb24fa python: Set NPN in HTTP2Server.__init__ 2014-02-25 21:25:31 +09:00
Tatsuhiro Tsujikawa
add07c4303 python: Encode headers in UTF-8 if they are given in unicode 2014-02-25 21:21:35 +09:00
Tatsuhiro Tsujikawa
4dcb68d128 Update README.rst 2014-02-25 01:47:09 +09:00
Tatsuhiro Tsujikawa
98715f4374 python: Add HTTP/2 server using asyncio 2014-02-25 01:47:09 +09:00
Tatsuhiro Tsujikawa
9cc7f9fb36 nghttp: Wait for pushed resources to complete
The statistics of pushed resources are also calculated.
2014-02-25 01:16:47 +09:00
Tatsuhiro Tsujikawa
d1c1deaf03 Add promised_stream_user_data parameter to nghttp2_submit_push_promise
This is very useful to associate application specific data to promised
stream.

nghttp2_nv_array_copy now does not complain the header field is large.
2014-02-25 00:26:12 +09:00
Tatsuhiro Tsujikawa
86aa905c10 nghttpx: Code cleanup 2014-02-22 11:26:32 +09:00
Tatsuhiro Tsujikawa
09fd95ac5c Revert 6c51bd0979 2014-02-21 23:04:40 +09:00
Tatsuhiro Tsujikawa
5e88be0b2c Update doc 2014-02-21 21:29:23 +09:00
Tatsuhiro Tsujikawa
fc25143418 Remove END_PUSH_PROMISE in favor of END_HEADERS 2014-02-21 21:23:51 +09:00
Tatsuhiro Tsujikawa
a21175398d Add test to verify that deflater can handle initial buf smaller than default 2014-02-21 21:18:46 +09:00
Tatsuhiro Tsujikawa
6c51bd0979 src: Disable strip http-parser mode
Add --enable-strict-http-parser mode to enable it.
2014-02-21 00:20:27 +09:00
Tatsuhiro Tsujikawa
dc82a6026e Add --enable-debug configure option to define DEBUGBUILD macro 2014-02-20 23:19:55 +09:00
Tatsuhiro Tsujikawa
f152dd8881 Rename --enable-maintainer-mode configure option as --enable-werror 2014-02-20 23:17:04 +09:00
Tatsuhiro Tsujikawa
9703c5de5c Code cleanup 2014-02-20 23:12:42 +09:00
Tatsuhiro Tsujikawa
3395f7158f Strict handling of max concurrent streams
Exceeding ACKed max concurrent streams results in connection error.
This change fixes the bug that num_{incoming,outgoing}_streams
is decremented wrongly if a stream is in reserved state and
RST_STREAM is send and its state is changed to NGHTTP2_STREAM_CLOSING.
This change also fixes the bug that transmission of push response
HEADERS does not increase num_outgoing_streams.
2014-02-20 23:10:32 +09:00
Tatsuhiro Tsujikawa
659c3b0aa0 nghttpx: Initialize response_htp_ with 0 2014-02-20 21:30:25 +09:00
Tatsuhiro Tsujikawa
46f5d4b1c4 examples: Check stream_data is null 2014-02-20 21:30:05 +09:00
Tatsuhiro Tsujikawa
bbc09b005b nghttpd: Use nghttp2_session_mem_recv and nghttp2_session_mem_send 2014-02-19 23:27:53 +09:00
Tatsuhiro Tsujikawa
1e1e77ad5e nghttp: Use nghttp2_session_mem_recv and nghttp2_session_mem_send 2014-02-19 23:27:52 +09:00
Tatsuhiro Tsujikawa
cdf5d5402b nghttpx: Code cleanup 2014-02-19 23:11:26 +09:00
Tatsuhiro Tsujikawa
3c96041c43 nghttpx: Fix typo 2014-02-19 22:53:33 +09:00
Tatsuhiro Tsujikawa
6320bd8926 nghttpx: Fix priority bits 2014-02-19 22:52:00 +09:00
Tatsuhiro Tsujikawa
30b3855194 nghttp2_session_mem_send tiny doc fix
Patch from Dave Beckett
2014-02-19 21:18:24 +09:00
Tatsuhiro Tsujikawa
4ced1c1622 Code cleanup 2014-02-19 01:08:52 +09:00
Tatsuhiro Tsujikawa
2966ad2d15 Update doc 2014-02-19 00:16:25 +09:00
Tatsuhiro Tsujikawa
649586fff6 Add nghttp2_session_mem_send() API function
This function behaves like nghttp2_session_send(), but it does not
use nghttp2_send_callback to send data. Instead, it returns the
serialized data to trasmit and its length to the caller.
2014-02-18 23:23:11 +09:00
Tatsuhiro Tsujikawa
a9991133af Add man page generation script using help2man 2014-02-16 19:44:28 +09:00
Tatsuhiro Tsujikawa
f5342494f4 src: Format help message and add --version to make man page generation easier 2014-02-16 19:39:41 +09:00
Tatsuhiro Tsujikawa
1fd5fdd54a src: Remove redundant SETTINGS_ENABLE_PUSH from server side 2014-02-16 16:05:26 +09:00
Tatsuhiro Tsujikawa
88607f09e5 Update doc 2014-02-16 15:50:36 +09:00
Tatsuhiro Tsujikawa
c7c496b029 Update doc 2014-02-16 15:30:46 +09:00
Tatsuhiro Tsujikawa
5cc24cb7c2 Merge branch 'draft-10' 2014-02-16 15:29:21 +09:00
Tatsuhiro Tsujikawa
a5353c22a6 doc: Add link to 0.3.1 release 2014-02-16 15:23:02 +09:00
Tatsuhiro Tsujikawa
b2ab5178a3 Bump up version number to 0.4.0-DEV 2014-02-16 15:20:56 +09:00
Tatsuhiro Tsujikawa
27b3091ab6 Update README.rst 2014-02-15 20:00:51 +09:00
Tatsuhiro Tsujikawa
62b73133e5 Code cleanup 2014-02-15 18:56:20 +09:00
Tatsuhiro Tsujikawa
66832e9f4e Allow NGHTTP2_FLAG_END_SEGMENT in nghttp2_submit_headers() 2014-02-15 18:55:52 +09:00
Tatsuhiro Tsujikawa
53302406d3 Merge branch 'master' into draft-10 2014-02-15 18:43:16 +09:00
Tatsuhiro Tsujikawa
bc0ce40dc2 Update README.rst 2014-02-15 17:20:47 +09:00
Tatsuhiro Tsujikawa
652dc250fd Update README.rst 2014-02-15 17:19:49 +09:00
Tatsuhiro Tsujikawa
0da79865b8 Don't set PAD_HIGH and PAD_LOW flags to HEADERS/PUSH_PROMISE object to user cb 2014-02-15 17:12:17 +09:00
Tatsuhiro Tsujikawa
7504d89f9b src: Add at most N bytes as padding if --padding option is used 2014-02-15 16:40:32 +09:00
Tatsuhiro Tsujikawa
3f3f258cd6 Add padding to PUSH_PROMISE 2014-02-15 16:30:43 +09:00
Tatsuhiro Tsujikawa
1e95c8b313 Allow always max 1024 padding for HEADERS
We need paddings regardless of payload and frame boundary to mitigate
certain attacks.

Since we handles CONTINUATION internally, we don't show FLAG_PAD_HIGH
and PAD_LOW flags of HEADERS in nghttp/nghttpd. We just show the
total paddings in HEADERS + CONTINUATION.
2014-02-15 01:34:04 +09:00
Tatsuhiro Tsujikawa
622f783675 Disallow PUSH_PROMISE from client side 2014-02-14 16:12:04 +09:00
Tatsuhiro Tsujikawa
7ab4206269 Tear down connection if SETTINGS makes window size overflow 2014-02-14 16:08:39 +09:00
Tatsuhiro Tsujikawa
e74fbdf6b4 Merge branch 'master' into draft-10 2014-02-13 23:45:41 +09:00
Tatsuhiro Tsujikawa
fd88c6160d HPACK post -05 updates
* Use 1 Huffman code table for both request and response
* Remove complicated deflater side table size management
* Add encoding context update
* Fix memory leak in inflater
2014-02-13 23:22:52 +09:00
Tatsuhiro Tsujikawa
082876d92d Contribute flow control window for each byte PAD_HIGH and _LOW in DATA
This may help the pathological situation where window is too small.
2014-02-12 21:35:40 +09:00
Tatsuhiro Tsujikawa
c7a17093cb Fix compile errors with --enable-maintainer-mode 2014-02-11 21:39:35 +09:00
Tatsuhiro Tsujikawa
bac31e844a Add more debug output 2014-02-11 21:35:41 +09:00
Tatsuhiro Tsujikawa
067a4d05c3 Merge branch 'master' into draft-10 2014-02-11 21:33:49 +09:00
Tatsuhiro Tsujikawa
7822bbd7e8 Fix PAD_HIGH and PAD_LOW are not counted in flow control 2014-02-11 21:30:44 +09:00
Tatsuhiro Tsujikawa
cd3eae3dd2 src: Fix select_padding_callback which returns value greater than max_payload 2014-02-11 19:19:00 +09:00
Tatsuhiro Tsujikawa
dbb131d13d Simplify framebufmark calculation for DATA frame 2014-02-11 18:55:22 +09:00
Tatsuhiro Tsujikawa
6364ae1a98 Fix nghttp2_active_outbound_item is not reset on DATA deferred 2014-02-11 18:43:45 +09:00
Tatsuhiro Tsujikawa
16b5e99e88 Bitwise-OR last CONTINUATION flags to first HEADERS flags 2014-02-11 17:30:38 +09:00
Tatsuhiro Tsujikawa
c280cc7c4d nghttpx: Add --padding option for debugging purpose 2014-02-11 17:23:22 +09:00
Tatsuhiro Tsujikawa
788072af9b Fix HEADERS padding is not added 2014-02-11 17:23:08 +09:00
Tatsuhiro Tsujikawa
cf0b880b15 Error if undefined SETTINGS ID is detected in nghttp2_iv_check 2014-02-11 16:53:08 +09:00
Tatsuhiro Tsujikawa
39fe7a5cfa Don't set select_padding_callback if padding_boundary is 0 or not set 2014-02-11 16:48:27 +09:00
Tatsuhiro Tsujikawa
3144bcbe20 Remove unused iframe->error_code 2014-02-11 16:34:42 +09:00
Tatsuhiro Tsujikawa
eb2856f3df Add inbound_frame_reset_left() not to forget to reset iframe->buflen 2014-02-11 16:33:07 +09:00
Tatsuhiro Tsujikawa
9865b46905 Don't change state in inbound_frame_handle_pad 2014-02-11 16:24:21 +09:00
Tatsuhiro Tsujikawa
6c40928fed Merge branch 'master' into draft-10
Conflicts:
	lib/nghttp2_session.c
2014-02-11 16:18:22 +09:00
Tatsuhiro Tsujikawa
109b8cedde Fix compile error and test failures 2014-02-11 16:12:26 +09:00
Tatsuhiro Tsujikawa
e78a2100ec Merge branch 'master' into draft-10 2014-02-11 16:03:42 +09:00
Tatsuhiro Tsujikawa
78d202ac30 Callback based padding from application
Now previous padding options are removed and instead we added
select_padding_callback to select padding length for each frame
by application. If this callback is not implemented by application,
no padding is added.

This change also fixes the broken session_detect_idle_stream()
if stream_id is our side.
2014-02-11 15:28:44 +09:00
Tatsuhiro Tsujikawa
118ed09da5 Allow disabling padding 2014-02-09 23:53:53 +09:00
Tatsuhiro Tsujikawa
5b58b4ace5 Add padding if payload length is zero 2014-02-09 22:01:07 +09:00
Tatsuhiro Tsujikawa
68b5ffc1dc Rename padding related names 2014-02-09 21:46:15 +09:00
Tatsuhiro Tsujikawa
ce53d7bd9e src: Don't output priority if NGHTTP2_FLAG_PRIORITY is not set 2014-02-09 21:34:28 +09:00
Tatsuhiro Tsujikawa
c7c283f3a9 nghttpx: Add --frontend-frame-debug option to debug HTTP/2 frame in upstream
The output format is the same one with nghttp/nghttpd. The output
is made into stderr to make it sync with logging.
2014-02-09 18:47:26 +09:00
Tatsuhiro Tsujikawa
909b79e69b Fix test 2014-02-09 18:33:27 +09:00
Tatsuhiro Tsujikawa
256c97d89b Change default padding size to 16 2014-02-09 18:27:34 +09:00
Tatsuhiro Tsujikawa
ba95cd936d Fix flow control error because padding is excluded 2014-02-09 18:26:46 +09:00
Tatsuhiro Tsujikawa
72e2e145c5 Revert 748f6e65bd 2014-02-09 17:42:20 +09:00
Tatsuhiro Tsujikawa
2c4dc08aee Merge branch 'master' into draft-10 2014-02-09 17:40:53 +09:00
Tatsuhiro Tsujikawa
5884794a7f Merge branch 'master' into draft-10 2014-02-09 17:14:07 +09:00
Tatsuhiro Tsujikawa
dffa078c11 Update doc 2014-02-09 16:49:24 +09:00
Tatsuhiro Tsujikawa
945c57c335 Add test for nghttp2_frame_pack_headers with padding 2014-02-09 15:17:26 +09:00
Tatsuhiro Tsujikawa
1db2195389 Implement padding for HEADERS and CONTINUATION 2014-02-09 15:17:26 +09:00
Tatsuhiro Tsujikawa
10feab02e8 Fix bufoff_ptr if no padding is made 2014-02-09 12:39:43 +09:00
Tatsuhiro Tsujikawa
9c30ed1a64 Update flags 2014-02-09 12:39:43 +09:00
Tatsuhiro Tsujikawa
e9d1ba2539 Handle incoming PAD_HIGH and PAD_LOW in inbound_frame_handle_padding 2014-02-09 12:39:43 +09:00
Tatsuhiro Tsujikawa
2ff3d97b2e Add nghttp2_frame_add_pad to deal with adding pads 2014-02-09 12:39:43 +09:00
Tatsuhiro Tsujikawa
748f6e65bd Run test after doc so that we can see test result in terminal 2014-02-08 17:44:34 +09:00
Tatsuhiro Tsujikawa
52a1f56d14 Merge branch 'master' into draft-10 2014-02-08 16:44:09 +09:00
Tatsuhiro Tsujikawa
b6a0eff8a8 Add more DEBUGFs 2014-02-08 00:32:50 +09:00
Tatsuhiro Tsujikawa
be9d5efa4c nghttp: Add --continuation option to test CONTINUATION 2014-02-08 00:23:18 +09:00
Tatsuhiro Tsujikawa
814d0f76f3 Implement DATA frame padding 2014-02-08 00:23:18 +09:00
Tatsuhiro Tsujikawa
f26270b5b4 Change SETTINGS payload format according to the spec 2014-02-06 22:06:42 +09:00
Tatsuhiro Tsujikawa
d584888601 Renumber frame types, flags and error codes 2014-02-06 21:49:16 +09:00
Tatsuhiro Tsujikawa
40a5756564 Terminate connection if unknown frame type is received 2014-02-06 21:42:49 +09:00
Tatsuhiro Tsujikawa
f2c654f898 Fix reception of ENABLE_PUSH ignored; strict check for SETTINGS value 2014-02-06 21:39:58 +09:00
Tatsuhiro Tsujikawa
112b49cb9a Renumber SETTINGS 2014-02-06 00:26:12 +09:00
Tatsuhiro Tsujikawa
c79adf6997 Remove flow control disabling feature 2014-02-06 00:23:20 +09:00
Tatsuhiro Tsujikawa
196406da0e Change protocol identifier to h2-10 2014-02-05 23:37:27 +09:00
296 changed files with 60880 additions and 33143 deletions

57
.clang-format Normal file
View File

@@ -0,0 +1,57 @@
---
Language: Cpp
# BasedOnStyle: LLVM
AccessModifierOffset: -2
ConstructorInitializerIndentWidth: 4
AlignEscapedNewlinesLeft: false
AlignTrailingComments: true
AllowAllParametersOfDeclarationOnNextLine: true
AllowShortBlocksOnASingleLine: false
AllowShortIfStatementsOnASingleLine: false
AllowShortLoopsOnASingleLine: false
AllowShortFunctionsOnASingleLine: All
AlwaysBreakTemplateDeclarations: false
AlwaysBreakBeforeMultilineStrings: false
BreakBeforeBinaryOperators: false
BreakBeforeTernaryOperators: true
BreakConstructorInitializersBeforeComma: false
BinPackParameters: true
ColumnLimit: 80
ConstructorInitializerAllOnOneLineOrOnePerLine: false
DerivePointerAlignment: false
ExperimentalAutoDetectBinPacking: false
IndentCaseLabels: false
IndentWrappedFunctionNames: false
IndentFunctionDeclarationAfterType: false
MaxEmptyLinesToKeep: 1
KeepEmptyLinesAtTheStartOfBlocks: true
NamespaceIndentation: None
ObjCSpaceAfterProperty: false
ObjCSpaceBeforeProtocolList: true
PenaltyBreakBeforeFirstCallParameter: 19
PenaltyBreakComment: 300
PenaltyBreakString: 1000
PenaltyBreakFirstLessLess: 120
PenaltyExcessCharacter: 1000000
PenaltyReturnTypeOnItsOwnLine: 60
PointerAlignment: Right
SpacesBeforeTrailingComments: 1
Cpp11BracedListStyle: true
Standard: Cpp11
IndentWidth: 2
TabWidth: 8
UseTab: Never
BreakBeforeBraces: Attach
SpacesInParentheses: false
SpacesInAngles: false
SpaceInEmptyParentheses: false
SpacesInCStyleCastParentheses: false
SpacesInContainerLiterals: true
SpaceBeforeAssignmentOperators: true
ContinuationIndentWidth: 4
CommentPragmas: '^ IWYU pragma:'
ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ]
SpaceBeforeParens: ControlStatements
DisableFormat: false
...

12
.gitignore vendored
View File

@@ -21,6 +21,7 @@ install-sh
.libs
lib/includes/nghttp2/nghttp2ver.h
lib/libnghttp2.pc
src/libnghttp2_asio.pc
ltmain.sh
stamp-h1
.deps/
@@ -35,3 +36,14 @@ doc/nghttp2ver.h.rst
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/libnghttp2_asio.rst
doc/contribute.rst
python/setup.py
python/dist
python/MANIFEST

37
.travis.yml Normal file
View File

@@ -0,0 +1,37 @@
language: cpp
compiler:
- clang
#Disable gcc build for the moment...
# - gcc
before_install:
- $CC --version
- sudo add-apt-repository --yes ppa:ubuntu-toolchain-r/test
- 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
before_script:
- autoreconf -i
- automake
- autoconf
- ./configure --enable-werror
script:
- make
- make check

19
COPYING
View File

@@ -20,3 +20,22 @@ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
[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!

103
Dockerfile.android Normal file
View File

@@ -0,0 +1,103 @@
# Dockerfile to build nghttp2 android binary
#
# $ sudo docker build -t nghttp2-android - < Dockerfile.android
#
# After successful build, android binaries are located under
# /root/build/nghttp2. You can copy the binary using docker cp. For
# example, to copy nghttpx binary to host file system location
# /path/to/dest, do this:
#
# $ sudo docker run -v /path/to/dest:/out nghttp2-android cp /root/build/nghttp2/src/nghttpx /out
FROM ubuntu
MAINTAINER Tatsuhiro Tsujikawa
ENV ANDROID_HOME /root/android
ENV PREFIX $ANDROID_HOME/usr/local
ENV TOOLCHAIN $ANDROID_HOME/toolchain
ENV PATH $TOOLCHAIN/bin:$PATH
# It would be better to use nearest ubuntu archive mirror for faster
# downloads.
# RUN sed -ie 's/archive\.ubuntu/jp.archive.ubuntu/g' /etc/apt/sources.list
RUN apt-get update
# genisoimage, libc6-i386 and lib32stdc++6 are required to decompress ndk.
RUN apt-get install -y make binutils autoconf automake autotools-dev libtool \
pkg-config git curl dpkg-dev libxml2-dev \
genisoimage libc6-i386 lib32stdc++6
WORKDIR /root/build
RUN curl -L -O http://dl.google.com/android/ndk/android-ndk-r10c-linux-x86_64.bin
RUN chmod a+x android-ndk-r10c-linux-x86_64.bin
RUN ./android-ndk-r10c-linux-x86_64.bin
WORKDIR /root/build/android-ndk-r10c
RUN /bin/bash build/tools/make-standalone-toolchain.sh \
--install-dir=$ANDROID_HOME/toolchain \
--toolchain=arm-linux-androideabi-4.9 --llvm-version=3.5 \
--system=linux-x86_64
WORKDIR /root/build
RUN git clone https://github.com/tatsuhiro-t/spdylay
WORKDIR /root/build/spdylay
RUN autoreconf -i && \
./configure \
--disable-shared \
--host=arm-linux-androideabi \
--build=`dpkg-architecture -qDEB_BUILD_GNU_TYPE` \
--prefix=$PREFIX \
--without-libxml2 \
--disable-src \
--disable-examples \
CPPFLAGS="-I$PREFIX/include" \
PKG_CONFIG_LIBDIR="$PREFIX/lib/pkgconfig" \
LDFLAGS="-L$PREFIX/lib" && \
make install
WORKDIR /root/build
RUN curl -L -O https://www.openssl.org/source/openssl-1.0.1j.tar.gz
RUN tar xf openssl-1.0.1j.tar.gz
WORKDIR /root/build/openssl-1.0.1j
RUN export CROSS_COMPILE=$TOOLCHAIN/bin/arm-linux-androideabi- && \
./Configure --prefix=$PREFIX android && \
make && make install_sw
WORKDIR /root/build
RUN curl -L -O http://dist.schmorp.de/libev/libev-4.19.tar.gz
RUN curl -L -O https://gist.github.com/tatsuhiro-t/48c45f08950f587180ed/raw/80a8f003b5d1091eae497c5995bbaa68096e739b/libev-4.19-android.patch
RUN tar xf libev-4.19.tar.gz
WORKDIR /root/build/libev-4.19
RUN patch -p1 < ../libev-4.19-android.patch
RUN ./configure \
--host=arm-linux-androideabi \
--build=`dpkg-architecture -qDEB_BUILD_GNU_TYPE` \
--prefix=$PREFIX \
--disable-shared \
--enable-static \
CPPFLAGS=-I$PREFIX/include \
LDFLAGS=-L$PREFIX/lib && \
make install
WORKDIR /root/build
RUN git clone https://github.com/tatsuhiro-t/nghttp2
WORKDIR /root/build/nghttp2
RUN autoreconf -i && \
./configure \
--disable-shared \
--host=arm-linux-androideabi \
--build=`dpkg-architecture -qDEB_BUILD_GNU_TYPE` \
--with-xml-prefix="$PREFIX" \
--without-libxml2 \
--disable-python-bindings \
--disable-examples \
--disable-threads \
LIBSPDYLAY_CFLAGS=-I$PREFIX/usr/local/include \
LIBSPDYLAY_LIBS="-L$PREFIX/usr/local/lib -lspdylay" \
CPPFLAGS="-I$PREFIX/include" \
CXXFLAGS="-fno-strict-aliasing" \
PKG_CONFIG_LIBDIR="$PREFIX/lib/pkgconfig" \
LDFLAGS="-L$PREFIX/lib" && \
make && \
arm-linux-androideabi-strip src/nghttpx src/nghttpd src/nghttp

View File

@@ -1,4 +1,4 @@
# nghttp2 - HTTP/2.0 C Library
# nghttp2 - HTTP/2 C Library
# Copyright (c) 2012 Tatsuhiro Tsujikawa
@@ -20,10 +20,23 @@
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
SUBDIRS = lib third-party src examples python tests doc
SUBDIRS = lib third-party src examples python tests doc contrib
ACLOCAL_AMFLAGS = -I m4
dist_doc_DATA = README.rst
EXTRA_DIST = nghttpx.conf.sample proxy.pac.sample android-config android-make
EXTRA_DIST = nghttpx.conf.sample proxy.pac.sample android-config android-make \
Dockerfile.android
.PHONY: clang-format
# Format source files using clang-format. Don't format source files
# under third-party directory since we are not responsible for thier
# coding style.
clang-format:
CLANGFORMAT=`git config --get clangformat.binary`; \
test -z $${CLANGFORMAT} && CLANGFORMAT="clang-format"; \
$${CLANGFORMAT} -i lib/*.{c,h} lib/includes/nghttp2/*.h \
src/*.{c,cc,h} src/includes/nghttp2/*.h examples/*.{c,cc} \
tests/*.{c,h}

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
#!/bin/sh
#
# nghttp2 - HTTP/2.0 C Library
# nghttp2 - HTTP/2 C Library
#
# Copyright (c) 2013 Tatsuhiro Tsujikawa
#
@@ -36,6 +36,11 @@ PATH=$TOOLCHAIN/bin:$PATH
--host=arm-linux-androideabi \
--build=`dpkg-architecture -qDEB_BUILD_GNU_TYPE` \
--with-xml-prefix="$PREFIX" \
--without-libxml2 \
--disable-python-bindings \
--disable-examples \
CC=clang \
CXX=clang++ \
CPPFLAGS="-I$PREFIX/include" \
PKG_CONFIG_LIBDIR="$PREFIX/lib/pkgconfig" \
LDFLAGS="-L$PREFIX/lib"

View File

@@ -1,6 +1,6 @@
#!/bin/sh
#
# nghttp2 - HTTP/2.0 C Library
# nghttp2 - HTTP/2 C Library
#
# Copyright (c) 2013 Tatsuhiro Tsujikawa
#

View File

@@ -1,4 +1,4 @@
dnl nghttp2 - HTTP/2.0 C Library
dnl nghttp2 - HTTP/2 C Library
dnl Copyright (c) 2012, 2013 Tatsuhiro Tsujikawa
@@ -20,15 +20,19 @@ dnl NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
dnl LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
dnl OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
dnl WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
dnl Do not change user variables!
dnl http://www.gnu.org/software/automake/manual/html_node/Flag-Variables-Ordering.html
AC_PREREQ(2.61)
AC_INIT([nghttp2], [0.3.1], [t-tujikawa@users.sourceforge.net])
AC_INIT([nghttp2], [0.7.1], [t-tujikawa@users.sourceforge.net])
LT_PREREQ([2.2.6])
LT_INIT()
dnl See versioning rule:
dnl http://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html
AC_SUBST(LT_CURRENT, 2)
AC_SUBST(LT_CURRENT, 8)
AC_SUBST(LT_REVISION, 1)
AC_SUBST(LT_AGE, 0)
AC_SUBST(LT_AGE, 3)
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"`
@@ -45,13 +49,26 @@ AC_CANONICAL_TARGET
AC_CONFIG_MACRO_DIR([m4])
AM_INIT_AUTOMAKE([subdir-objects])
m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
AC_CONFIG_HEADERS([config.h])
dnl Checks for command-line options
AC_ARG_ENABLE([maintainer-mode],
[AS_HELP_STRING([--enable-maintainer-mode],
AC_ARG_ENABLE([werror],
[AS_HELP_STRING([--enable-werror],
[Turn on compile time warnings])],
[maintainer_mode=$enableval], [maintainer_mode=no])
[werror=$enableval], [werror=no])
AC_ARG_ENABLE([debug],
[AS_HELP_STRING([--enable-debug],
[Turn on debug output])],
[debug=$enableval], [debug=no])
AC_ARG_ENABLE([threads],
[AS_HELP_STRING([--disable-threads],
[Turn off threading in apps])],
[threads=$enableval], [threads=yes])
AC_ARG_ENABLE([app],
[AS_HELP_STRING([--enable-app],
@@ -63,6 +80,11 @@ AC_ARG_ENABLE([hpack-tools],
[Build HPACK tools [default=check]])],
[request_hpack_tools=$enableval], [request_hpack_tools=check])
AC_ARG_ENABLE([asio-lib],
[AS_HELP_STRING([--enable-asio-lib],
[Build C++ libnghttp2_asio library [default=no]])],
[request_asio_lib=$enableval], [request_asio_lib=no])
AC_ARG_ENABLE([examples],
[AS_HELP_STRING([--enable-examples],
[Build examples [default=check]])],
@@ -74,15 +96,25 @@ AC_ARG_ENABLE([python-bindings],
[request_python_bindings=$enableval], [request_python_bindings=check])
AC_ARG_ENABLE([failmalloc],
[AS_HELP_STRING([--enable-failmalloc],
[Build failmalloc test program [default=no]])],
[request_failmalloc=$enableval], [request_failmalloc=no])
[AS_HELP_STRING([--disable-failmalloc],
[Do not build failmalloc test program])],
[request_failmalloc=$enableval], [request_failmalloc=yes])
AC_ARG_WITH([libxml2],
[AS_HELP_STRING([--with-libxml2],
[Use libxml2 [default=check]])],
[request_libxml2=$withval], [request_libxml2=check])
AC_ARG_WITH([jemalloc],
[AS_HELP_STRING([--with-jemalloc],
[Use jemalloc [default=check]])],
[request_jemalloc=$withval], [request_jemalloc=check])
AC_ARG_WITH([spdylay],
[AS_HELP_STRING([--with-spdylay],
[Use spdylay [default=check]])],
[request_spdylay=$withval], [request_spdylay=check])
AC_ARG_WITH([cython],
[AS_HELP_STRING([--with-cython=PATH],
[Use cython in given PATH])],
@@ -112,14 +144,29 @@ else
AC_SUBST([CYTHON])
fi
#
# If we're running GCC or clang define _U_ to be "__attribute__((unused))"
# so we can use _U_ to flag unused function parameters and not get warnings
# about them. Otherwise, define _U_ to be an empty string so that _U_ used
# to flag an unused function parameters will compile with other compilers.
#
# XXX - similar hints for other compilers?
#
if test "x$GCC" = "xyes" -o "x$CC" = "xclang" ; then
AC_DEFINE([_U_], [__attribute__((unused))], [Hint to the compiler that a function parameters is not used])
else
AC_DEFINE([_U_], , [Hint to the compiler that a function parameters is not used])
fi
AX_CXX_COMPILE_STDCXX_11([noext], [optional])
AC_LANG_PUSH(C++)
# Check that std::chrono::steady_clock is available. In particular,
# gcc 4.6 does not have one, but has monotonic_clock which is the old
# name existed in the pre-standard draft. If steady_clock is not
# available, don't define HAVE_STEADY_CLOCK and replace steady_clock
# with monotonic_clock.
AC_LANG_PUSH(C++)
AC_MSG_CHECKING([whether std::chrono::steady_clock is available])
AC_COMPILE_IFELSE([AC_LANG_PROGRAM(
[[
@@ -132,49 +179,71 @@ auto tp = std::chrono::steady_clock::now();
[Define to 1 if you have the `std::chrono::steady_clock`.])
AC_MSG_RESULT([yes])],
[AC_MSG_RESULT([no])])
# Check that std::future is available.
AC_MSG_CHECKING([whether std::future is available])
AC_COMPILE_IFELSE([AC_LANG_PROGRAM(
[[
#include <vector>
#include <future>
]],
[[
std::vector<std::future<int>> v;
]])],
[AC_DEFINE([HAVE_STD_FUTURE], [1],
[Define to 1 if you have the `std::future`.])
have_std_future=yes
AC_MSG_RESULT([yes])],
[have_std_future=no
AC_MSG_RESULT([no])])
AC_LANG_POP()
# Checks for libraries.
# Additional libraries required for tests.
TESTS_LIBS=
TESTLDFLAGS=
# Additional libraries required for programs under src directory.
SRC_LIBS=
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])
TESTS_LIBS="$LIBS $TESTS_LIBS"
TESTLDFLAGS="$LIBS $TESTLDFLAGS"
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`.])])
SRC_LIBS="$LIBS $SRC_LIBS"
APPLDFLAGS="$LIBS $APPLDFLAGS"
LIBS=$LIBS_OLD
case "$host" in
*android*)
android_build=yes
# android does not need -pthread, but needs followng 2 libs for C++
SRC_LIBS="$SRC_LIBS -lstdc++ -lsupc++"
# android does not need -pthread, but needs followng 3 libs for C++
APPLDFLAGS="$APPLDFLAGS -lstdc++ -latomic -lsupc++"
;;
*)
SRC_LIBS="$SRC_LIBS -pthread"
PTHREAD_LDFLAGS="-pthread"
APPLDFLAGS="$APPLDFLAGS $PTHREAD_LDFLAGS"
;;
esac
# zlib
if test "x$android_build" = "xyes"; then
# Use zlib provided by NDK
LIBS="-lz $LIBS"
APPLDFLAGS="-lz $APPLDFLAGS"
have_zlib=yes
else
PKG_CHECK_MODULES([ZLIB], [zlib >= 1.2.3])
LIBS="$ZLIB_LIBS $LIBS"
CFLAGS="$CFLAGS $ZLIB_CFLAGS"
PKG_CHECK_MODULES([ZLIB], [zlib >= 1.2.3], [have_zlib=yes], [have_zlib=no])
if test "x${have_zlib}" = "xno"; then
AC_MSG_NOTICE($ZLIB_PKG_ERRORS)
fi
fi
# cunit
@@ -206,6 +275,22 @@ fi
AM_CONDITIONAL([HAVE_CUNIT], [ test "x${have_cunit}" = "xyes" ])
# libev (for src)
# libev does not have pkg-config file. Check it in an old way.
LIBS_OLD=$LIBS
# android requires -lm for floor
AC_CHECK_LIB([ev], [ev_time], [have_libev=yes], [have_libev=no], [-lm])
if test "x${have_libev}" = "xyes"; then
AC_CHECK_HEADER([ev.h], [have_libev=yes], [have_libev=no])
if test "x${have_libev}" = "xyes"; then
LIBEV_LIBS=-lev
LIBEV_CFLAGS=
AC_SUBST([LIBEV_LIBS])
AC_SUBST([LIBEV_CFLAGS])
fi
fi
LIBS=$LIBS_OLD
# openssl (for src)
PKG_CHECK_MODULES([OPENSSL], [openssl >= 1.0.1],
[have_openssl=yes], [have_openssl=no])
@@ -213,7 +298,7 @@ if test "x${have_openssl}" = "xno"; then
AC_MSG_NOTICE($OPENSSL_PKG_ERRORS)
fi
# libevent_openssl (for src)
# libevent_openssl (for examples)
# 2.0.8 is required because we use evconnlistener_set_error_cb()
PKG_CHECK_MODULES([LIBEVENT_OPENSSL], [libevent_openssl >= 2.0.8],
[have_libevent_openssl=yes], [have_libevent_openssl=no])
@@ -221,10 +306,13 @@ if test "x${have_libevent_openssl}" = "xno"; then
AC_MSG_NOTICE($LIBEVENT_OPENSSL_PKG_ERRORS)
fi
# jansson (for hdtest/deflatehd and hdtest/inflatehd)
# jansson (for src/nghttp, src/deflatehd and src/inflatehd)
PKG_CHECK_MODULES([JANSSON], [jansson >= 2.5],
[have_jansson=yes], [have_jansson=no])
if test "x${have_jansson}" == "xno"; then
if test "x${have_jansson}" == "xyes"; then
AC_DEFINE([HAVE_JANSSON], [1],
[Define to 1 if you have `libjansson` library.])
else
AC_MSG_NOTICE($JANSSON_PKG_ERRORS)
fi
@@ -244,23 +332,71 @@ fi
AM_CONDITIONAL([HAVE_LIBXML2], [ test "x${have_libxml2}" = "xyes" ])
# spdylay (for src/nghttpx)
PKG_CHECK_MODULES([LIBSPDYLAY], [libspdylay >= 1.2.3],
[have_spdylay=yes], [have_spdylay=no])
if test "x${have_spdylay}" = "xyes"; then
AC_DEFINE([HAVE_SPDYLAY], [1], [Define to 1 if you have `spdylay` library.])
else
AC_MSG_NOTICE($LIBSPDYLAY_PKG_ERRORS)
AC_MSG_NOTICE([The SPDY support in nghttpx will be disabled.])
# jemalloc
have_jemalloc=no
if test "x${request_jemalloc}" != "xno"; then
LIBS_OLD=$LIBS
AC_SEARCH_LIBS([malloc_stats_print], [jemalloc], [have_jemalloc=yes], [],
[$PTHREAD_LDFLAGS])
LIBS=$LIBS_OLD
if test "x${have_jemalloc}" = "xyes" &&
test "x${ac_cv_search_malloc_stats_print}" != "xnone required"; then
JEMALLOC_LIBS=${ac_cv_search_malloc_stats_print}
AC_SUBST([JEMALLOC_LIBS])
fi
fi
if test "x${request_jemalloc}" = "xyes" &&
test "x${have_jemalloc}" != "xyes"; then
AC_MSG_ERROR([jemalloc was requested (--with-jemalloc) but not found])
fi
# spdylay (for src/nghttpx and src/h2load)
have_spdylay=no
if test "x${request_spdylay}" != "xno"; then
PKG_CHECK_MODULES([LIBSPDYLAY], [libspdylay >= 1.3.0],
[have_spdylay=yes], [have_spdylay=no])
if test "x${have_spdylay}" = "xyes"; then
AC_DEFINE([HAVE_SPDYLAY], [1], [Define to 1 if you have `spdylay` library.])
else
AC_MSG_NOTICE($LIBSPDYLAY_PKG_ERRORS)
AC_MSG_NOTICE([The SPDY support in nghttpx and h2load will be disabled.])
fi
fi
if test "x${request_spdylay}" = "xyes" &&
test "x${have_spdylay}" != "xyes"; then
AC_MSG_ERROR([spdylay was requested (--with-spdylay) but not found])
fi
AM_CONDITIONAL([HAVE_SPDYLAY], [ test "x${have_spdylay}" = "xyes" ])
# The nghttp, nghttpd and nghttpx under src depend on OpenSSL and
# libevent_openssl
# Check Boost Asio library
have_asio_lib=no
if test "x${request_asio_lib}" = "xyes"; then
AX_BOOST_BASE([1.54.0], [have_boost_base=yes], [have_boost_base=no])
if test "x${have_boost_base}" = "xyes"; then
AX_BOOST_ASIO()
AX_BOOST_SYSTEM()
AX_BOOST_THREAD()
if test "x${ax_cv_boost_asio}" = "xyes" &&
test "x${ax_cv_boost_system}" = "xyes" &&
test "x${ax_cv_boost_thread}" = "xyes"; then
have_asio_lib=yes
fi
fi
fi
# The nghttp, nghttpd and nghttpx under src depend on zlib, OpenSSL
# and libev
enable_app=no
if test "x${request_app}" != "xno" &&
test "x${have_zlib}" = "xyes" &&
test "x${have_openssl}" = "xyes" &&
test "x${have_libevent_openssl}" = "xyes"; then
test "x${have_libev}" = "xyes"; then
enable_app=yes
fi
@@ -285,6 +421,16 @@ fi
AM_CONDITIONAL([ENABLE_HPACK_TOOLS], [ test "x${enable_hpack_tools}" = "xyes" ])
# C++ library libnghttp2_asio
enable_asio_lib=no
if test "x${request_asio_lib}" != "xno" &&
test "x${have_asio_lib}" = "xyes"; then
enable_asio_lib=yes
fi
AM_CONDITIONAL([ENABLE_ASIO_LIB], [ test "x${enable_asio_lib}" = "xyes" ])
# The example programs depend on OpenSSL and libevent_openssl
enable_examples=no
if test "x${request_examples}" != "xno" &&
@@ -317,7 +463,16 @@ fi
AM_CONDITIONAL([ENABLE_PYTHON_BINDINGS],
[test "x${enable_python_bindings}" = "xyes"])
# Produce cython conditional, so that we can distribute generated C
# source
AM_CONDITIONAL([HAVE_CYTHON], [test "x${CYTHON}" != "x"])
# failmalloc tests
enable_failmalloc=no
if test "x${request_failmalloc}" = "xyes"; then
enable_failmalloc=yes
fi
AM_CONDITIONAL([ENABLE_FAILMALLOC], [ test "x${enable_failmalloc}" = "xyes" ])
# Checks for header files.
@@ -352,17 +507,40 @@ AC_CHECK_TYPES([ptrdiff_t])
AC_C_BIGENDIAN
AC_SYS_LARGEFILE
AC_CHECK_MEMBER([struct tm.tm_gmtoff], [have_struct_tm_tm_gmtoff=yes],
[have_struct_tm_tm_gmtoff=no], [[#include <time.h>]])
if test "x$have_struct_tm_tm_gmtoff" = "xyes"; then
AC_DEFINE([HAVE_STRUCT_TM_TM_GMTOFF], [1],
[Define to 1 if you have `struct tm.tm_gmtoff` member.])
fi
# Checks for library functions.
if test "x$cross_compiling" != "xyes"; then
AC_FUNC_MALLOC
fi
AC_CHECK_FUNCS([ \
_Exit \
accept4 \
getpwnam \
memmove \
memset \
timegm \
])
# timerfd_create was added in linux kernel 2.6.25
AC_CHECK_FUNC([timerfd_create],
[have_timerfd_create=yes], [have_timerfd_create=no])
# Checks for epoll availability, primarily for examples/tiny-nghttpd
AX_HAVE_EPOLL([have_epoll=yes], [have_epoll=no])
AM_CONDITIONAL([ENABLE_TINY_NGHTTPD],
[ test "x${have_epoll}" = "xyes" &&
test "x${have_timerfd_create}" = "xyes"])
dnl Windows library for winsock2
case "${host}" in
*mingw*)
@@ -370,20 +548,58 @@ case "${host}" in
;;
esac
if test "x$maintainer_mode" != "xno"; then
CFLAGS="$CFLAGS -Wall -Wextra -Werror"
CFLAGS="$CFLAGS -Wmissing-prototypes -Wstrict-prototypes"
CFLAGS="$CFLAGS -Wmissing-declarations -Wpointer-arith"
CFLAGS="$CFLAGS -Wdeclaration-after-statement"
CFLAGS="$CFLAGS -Wformat-security"
CFLAGS="$CFLAGS -Wwrite-strings -Wshadow -Winline -Wnested-externs"
CFLAGS="$CFLAGS -Wfloat-equal -Wundef -Wendif-labels -Wempty-body"
CFLAGS="$CFLAGS -Wcast-align -Wclobbered -Wvla"
CFLAGS="$CFLAGS -Wno-unused-parameter"
ac_save_CFLAGS=$CFLAGS
CFLAGS=
if test "x$werror" != "xno"; then
AX_CHECK_COMPILE_FLAG([-Wall], [CFLAGS="$CFLAGS -Wall"])
AX_CHECK_COMPILE_FLAG([-Wextra], [CFLAGS="$CFLAGS -Wextra"])
AX_CHECK_COMPILE_FLAG([-Werror], [CFLAGS="$CFLAGS -Werror"])
AX_CHECK_COMPILE_FLAG([-Wmissing-prototypes], [CFLAGS="$CFLAGS -Wmissing-prototypes"])
AX_CHECK_COMPILE_FLAG([-Wstrict-prototypes], [CFLAGS="$CFLAGS -Wstrict-prototypes"])
AX_CHECK_COMPILE_FLAG([-Wmissing-declarations], [CFLAGS="$CFLAGS -Wmissing-declarations"])
AX_CHECK_COMPILE_FLAG([-Wpointer-arith], [CFLAGS="$CFLAGS -Wpointer-arith"])
AX_CHECK_COMPILE_FLAG([-Wdeclaration-after-statement], [CFLAGS="$CFLAGS -Wdeclaration-after-statement"])
AX_CHECK_COMPILE_FLAG([-Wformat-security], [CFLAGS="$CFLAGS -Wformat-security"])
AX_CHECK_COMPILE_FLAG([-Wwrite-strings], [CFLAGS="$CFLAGS -Wwrite-strings"])
AX_CHECK_COMPILE_FLAG([-Wshadow], [CFLAGS="$CFLAGS -Wshadow"])
AX_CHECK_COMPILE_FLAG([-Winline], [CFLAGS="$CFLAGS -Winline"])
AX_CHECK_COMPILE_FLAG([-Wnested-externs], [CFLAGS="$CFLAGS -Wnested-externs"])
AX_CHECK_COMPILE_FLAG([-Wfloat-equal], [CFLAGS="$CFLAGS -Wfloat-equal"])
AX_CHECK_COMPILE_FLAG([-Wundef], [CFLAGS="$CFLAGS -Wundef"])
AX_CHECK_COMPILE_FLAG([-Wendif-labels], [CFLAGS="$CFLAGS -Wendif-labels"])
AX_CHECK_COMPILE_FLAG([-Wempty-body], [CFLAGS="$CFLAGS -Wempty-body"])
AX_CHECK_COMPILE_FLAG([-Wcast-align], [CFLAGS="$CFLAGS -Wcast-align"])
AX_CHECK_COMPILE_FLAG([-Wclobbered], [CFLAGS="$CFLAGS -Wclobbered"])
AX_CHECK_COMPILE_FLAG([-Wvla], [CFLAGS="$CFLAGS -Wvla"])
AX_CHECK_COMPILE_FLAG([-Wpragmas], [CFLAGS="$CFLAGS -Wpragmas"])
AX_CHECK_COMPILE_FLAG([-Wunreachable-code], [CFLAGS="$CFLAGS -Wunreachable-code"])
AX_CHECK_COMPILE_FLAG([-Waddress], [CFLAGS="$CFLAGS -Waddress"])
AX_CHECK_COMPILE_FLAG([-Wattributes], [CFLAGS="$CFLAGS -Wattributes"])
AX_CHECK_COMPILE_FLAG([-Wdiv-by-zero], [CFLAGS="$CFLAGS -Wdiv-by-zero"])
AX_CHECK_COMPILE_FLAG([-Wshorten-64-to-32], [CFLAGS="$CFLAGS -Wshorten-64-to-32"])
# Only work with Clang for the moment
AX_CHECK_COMPILE_FLAG([-Wheader-guard], [CFLAGS="$CFLAGS -Wheader-guard"])
fi
AC_SUBST([TESTS_LIBS])
AC_SUBST([SRC_LIBS])
WARNCFLAGS=$CFLAGS
CFLAGS=$ac_save_CFLAGS
AC_SUBST([WARNCFLAGS])
if test "x$debug" != "xno"; then
AC_DEFINE([DEBUGBUILD], [1], [Define to 1 to enable debug output.])
fi
# Some platform does not have working std::future. We disable
# threading for those platforms to exclude std::future use.
if test "x$threads" != "xyes" || test "x$have_std_future" != "xyes"; then
AC_DEFINE([NOTHREADS], [1], [Define to 1 if you want to disable threads.])
fi
AC_SUBST([TESTLDFLAGS])
AC_SUBST([APPLDFLAGS])
AC_CONFIG_FILES([
Makefile
@@ -395,16 +611,28 @@ AC_CONFIG_FILES([
tests/testdata/Makefile
third-party/Makefile
src/Makefile
src/includes/Makefile
src/libnghttp2_asio.pc
examples/Makefile
python/Makefile
python/setup.py
doc/Makefile
doc/conf.py
doc/index.rst
doc/package_README.rst
doc/tutorial-client.rst
doc/tutorial-server.rst
doc/tutorial-hpack.rst
doc/nghttpx-howto.rst
doc/h2load-howto.rst
doc/libnghttp2_asio.rst
doc/python-apiref.rst
doc/building-android-binary.rst
doc/nghttp2.h.rst
doc/nghttp2ver.h.rst
doc/asio_http2.h.rst
doc/contribute.rst
contrib/Makefile
])
AC_OUTPUT
@@ -415,6 +643,7 @@ AC_MSG_NOTICE([summary of build options:
Install prefix: ${prefix}
C compiler: ${CC}
CFLAGS: ${CFLAGS}
WARNCFLAGS: ${WARNCFLAGS}
LDFLAGS: ${LDFLAGS}
LIBS: ${LIBS}
CPPFLAGS: ${CPPFLAGS}
@@ -423,6 +652,7 @@ AC_MSG_NOTICE([summary of build options:
CXXFLAGS: ${CXXFLAGS}
CXXCPP: ${CXXCPP}
Library types: Shared=${enable_shared}, Static=${enable_static}
Python:
Python: ${PYTHON}
PYTHON_VERSION: ${PYTHON_VERSION}
pyexecdir: ${pyexecdir}
@@ -430,15 +660,26 @@ AC_MSG_NOTICE([summary of build options:
PYTHON_CPPFLAGS:${PYTHON_CPPFLAGS}
PYTHON_LDFLAGS: ${PYTHON_LDFLAGS}
Cython: ${CYTHON}
Test:
CUnit: ${have_cunit}
Failmalloc: ${enable_failmalloc}
Libs:
OpenSSL: ${have_openssl}
Libxml2: ${have_libxml2}
Libev: ${have_libev}
Libevent(SSL): ${have_libevent_openssl}
Spdylay: ${have_spdylay}
Jansson: ${have_jansson}
Jemalloc: ${have_jemalloc}
Boost CPPFLAGS: ${BOOST_CPPFLAGS}
Boost LDFLAGS: ${BOOST_LDFLAGS}
Boost::ASIO: ${BOOST_ASIO_LIB}
Boost::System: ${BOOST_SYSTEM_LIB}
Boost::Thread: ${BOOST_THREAD_LIB}
Features:
Applications: ${enable_app}
HPACK tools: ${enable_hpack_tools}
Libnghttp2_asio:${enable_asio_lib}
Examples: ${enable_examples}
Python bindings:${enable_python_bindings}
Failmalloc: ${request_failmalloc}
])

1
contrib/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
nghttpx-init

39
contrib/Makefile.am Normal file
View File

@@ -0,0 +1,39 @@
# nghttp2 - HTTP/2 C Library
# Copyright (c) 2014 Tatsuhiro Tsujikawa
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
# "Software"), to deal in the Software without restriction, including
# without limitation the rights to use, copy, modify, merge, publish,
# distribute, sublicense, and/or sell copies of the Software, and to
# permit persons to whom the Software is furnished to do so, subject to
# the following conditions:
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
EXTRA_DIST = nghttpx-init.in nghttpx-logrotate
edit = sed -e 's|@bindir[@]|$(bindir)|g'
nghttpx-init: Makefile
rm -f $@ $@.tmp
$(edit) $(srcdir)/$@.in > $@.tmp
chmod +x $@.tmp
mv $@.tmp $@
nghttpx-init: $(srcdir)/nghttpx-init.in
all-local: nghttpx-init
clean-local:
-rm -f nghttpx-init nghttpx-init.tmp

173
contrib/nghttpx-init.in Normal file
View File

@@ -0,0 +1,173 @@
#! /bin/sh
### BEGIN INIT INFO
# Provides: nghttpx
# Required-Start: $remote_fs $syslog
# Required-Stop: $remote_fs $syslog
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: nghttpx initscript
# Description: nghttpx initscript
### END INIT INFO
# Author: Tatsuhiro Tsujikawa <tatsuhiro.t@gmail.com>
#
# Do NOT "set -e"
# PATH should only include /usr/* if it runs after the mountnfs.sh script
PATH=/sbin:/usr/sbin:/bin:/usr/bin:/usr/local/bin
DESC="HTTP/2 reverse proxy"
NAME=nghttpx
# Depending on the configuration, binary may be located under @sbindir@
DAEMON=@bindir@/$NAME
PIDFILE=/var/run/$NAME.pid
DAEMON_ARGS="--conf /etc/nghttpx/nghttpx.conf --pid-file=$PIDFILE"
SCRIPTNAME=/etc/init.d/$NAME
# Exit if the package is not installed
[ -x "$DAEMON" ] || exit 0
# Read configuration variable file if it is present
[ -r /etc/default/$NAME ] && . /etc/default/$NAME
# Load the VERBOSE setting and other rcS variables
. /lib/init/vars.sh
# Define LSB log_* functions.
# Depend on lsb-base (>= 3.2-14) to ensure that this file is present
# and status_of_proc is working.
. /lib/lsb/init-functions
#
# Function that starts the daemon/service
#
do_start()
{
# Return
# 0 if daemon has been started
# 1 if daemon was already running
# 2 if daemon could not be started
start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON --test > /dev/null \
|| return 1
start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON -- \
$DAEMON_ARGS \
|| return 2
# Add code here, if necessary, that waits for the process to be ready
# to handle requests from services started subsequently which depend
# on this one. As a last resort, sleep for some time.
}
#
# Function that stops the daemon/service
#
do_stop()
{
# Return
# 0 if daemon has been stopped
# 1 if daemon was already stopped
# 2 if daemon could not be stopped
# other if a failure occurred
start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile $PIDFILE
RETVAL="$?"
[ "$RETVAL" = 2 ] && return 2
# Wait for children to finish too if this is a daemon that forks
# and if the daemon is only ever run from this initscript.
# If the above conditions are not satisfied then add some other code
# that waits for the process to drop all resources that could be
# needed by services started subsequently. A last resort is to
# sleep for some time.
#start-stop-daemon --stop --quiet --oknodo --retry=0/30/KILL/5 --exec $DAEMON
#[ "$?" = 2 ] && return 2
# Many daemons don't delete their pidfiles when they exit.
rm -f $PIDFILE
return "$RETVAL"
}
#
# Function that sends a SIGHUP to the daemon/service
#
do_reload() {
#
# If the daemon can reload its configuration without
# restarting (for example, when it is sent a SIGHUP),
# then implement that here.
#
start-stop-daemon --stop --signal 1 --quiet --pidfile $PIDFILE --name $NAME
return 0
}
case "$1" in
start)
[ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME"
do_start
case "$?" in
0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
esac
;;
stop)
[ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME"
do_stop
case "$?" in
0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
esac
;;
status)
status_of_proc "$DAEMON" "$NAME" && exit 0 || exit $?
;;
upgrade)
log_daemon_msg "Upgrade $DESC" "$NAME"
pid=`pidofproc -p $PIDFILE $NAME`
case "$?" in
0) echo "Sending USR2 signal to $pid"
kill -USR2 $pid
echo "Waiting for new binary..."
sleep 5
echo "Sending QUIT signal to $pid"
kill -QUIT $pid
log_end_msg 0
;;
*) echo "pidofproc() failed"
log_end_msg 1
;;
esac
;;
#reload|force-reload)
#
# If do_reload() is not implemented then leave this commented out
# and leave 'force-reload' as an alias for 'restart'.
#
#log_daemon_msg "Reloading $DESC" "$NAME"
#do_reload
#log_end_msg $?
#;;
restart|force-reload)
#
# If the "reload" option is implemented then remove the
# 'force-reload' alias
#
log_daemon_msg "Restarting $DESC" "$NAME"
do_stop
case "$?" in
0|1)
do_start
case "$?" in
0) log_end_msg 0 ;;
1) log_end_msg 1 ;; # Old process is still running
*) log_end_msg 1 ;; # Failed to start
esac
;;
*)
# Failed to stop
log_end_msg 1
;;
esac
;;
*)
echo "Usage: $SCRIPTNAME {start|stop|status|restart|force-reload|upgrade}" >&2
exit 3
;;
esac
:

18
contrib/nghttpx-logrotate Normal file
View File

@@ -0,0 +1,18 @@
/var/log/nghttpx/*.log {
weekly
missingok
rotate 52
compress
delaycompress
notifempty
create 0640 www-data adm
sharedscripts
prerotate
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

@@ -1,4 +1,4 @@
# nghttp2 - HTTP/2.0 C Library
# nghttp2 - HTTP/2 C Library
# Copyright (c) 2012 Tatsuhiro Tsujikawa
@@ -21,15 +21,26 @@
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
man_MANS = nghttp.1 nghttpd.1 nghttpx.1
man_MANS = nghttp.1 nghttpd.1 nghttpx.1 h2load.1
EXTRA_DIST = \
mkapiref.py \
README.rst \
apiref-header.rst \
nghttp.1.rst \
nghttpd.1.rst \
nghttpx.1.rst \
h2load.1.rst \
sources/index.rst \
sources/tutorial-client.rst \
sources/tutorial-server.rst \
sources/tutorial-hpack.rst \
sources/nghttpx-howto.rst \
sources/h2load-howto.rst \
sources/libnghttp2_asio.rst \
sources/python-apiref.rst \
sources/building-android-binary.rst \
sources/contribute.rst \
_themes/sphinx_rtd_theme/footer.html \
_themes/sphinx_rtd_theme/theme.conf \
_themes/sphinx_rtd_theme/layout_old.html \
@@ -165,7 +176,7 @@ text:
@echo
@echo "Build finished. The text files are in $(BUILDDIR)/text."
man:
man: apiref.rst
$(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
@echo
@echo "Build finished. The manual pages are in $(BUILDDIR)/man."

View File

@@ -7,9 +7,9 @@
<li>{{ title }}</li>
<li class="wy-breadcrumbs-aside">
{% if display_github %}
<a href="https://github.com/{{ github_user }}/{{ github_repo }}/blob/{{ github_version }}{{ conf_py_path }}{{ pagename }}.rst" class="fa fa-github"> Edit on GitHub</a>
<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>
{% elif display_bitbucket %}
<a href="https://bitbucket.org/{{ bitbucket_user }}/{{ bitbucket_repo }}/src/{{ bitbucket_version}}{{ conf_py_path }}{{ pagename }}.rst" class="fa fa-bitbucket"> Edit on Bitbucket</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 show_source and has_source and sourcename %}
<a href="{{ pathto('_sources/' + sourcename, true)|e }}" rel="nofollow"> View page source</a>
{% endif %}

View File

@@ -2,7 +2,7 @@
{% if next or prev %}
<div class="rst-footer-buttons" role="navigation" aria-label="footer navigation">
{% 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 }}">Next <span class="fa fa-arrow-circle-right"></span></a>
{% endif %}
{% 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>
@@ -28,5 +28,6 @@
</p>
</div>
{% trans %}<a href="https://github.com/snide/sphinx_rtd_theme">Sphinx 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 %}.
</footer>

View File

@@ -23,43 +23,19 @@
{% endif %}
{# CSS #}
<link href='https://fonts.googleapis.com/css?family=Lato:400,700|Roboto+Slab:400,700|Inconsolata:400,700' rel='stylesheet' type='text/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'>
{# JS #}
{# OPENSEARCH #}
{% if not embedded %}
<script type="text/javascript">
var DOCUMENTATION_OPTIONS = {
URL_ROOT:'{{ url_root }}',
VERSION:'{{ release|e }}',
COLLAPSE_INDEX:false,
FILE_SUFFIX:'{{ '' if no_search_suffix else file_suffix }}',
HAS_SOURCE: {{ has_source|lower }}
};
</script>
{%- for scriptfile in script_files %}
<script type="text/javascript" src="{{ pathto(scriptfile, 1) }}"></script>
{%- endfor %}
{% if use_opensearch %}
<link rel="search" type="application/opensearchdescription+xml" title="{% trans docstitle=docstitle|e %}Search within {{ docstitle }}{% endtrans %}" href="{{ pathto('_static/opensearch.xml', 1) }}"/>
{% endif %}
{% endif %}
{# RTD hosts these file themselves, so just load on non RTD builds #}
{# RTD hosts this file, so just load on non RTD builds #}
{% if not READTHEDOCS %}
<link rel="stylesheet" href="{{ pathto('_static/' + style, 1) }}" type="text/css" />
<script type="text/javascript" src="{{ pathto('_static/js/theme.js', 1) }}"></script>
{% endif %}
{# STICKY NAVIGATION #}
{% if theme_sticky_navigation %}
<script type="text/javascript">
jQuery(function () {
SphinxRtdTheme.StickyNav.enable();
});
</script>
{% endif %}
{% for cssfile in css_files %}
@@ -94,6 +70,7 @@
{%- endblock %}
{%- block extrahead %} {% endblock %}
{# 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>
</head>
@@ -105,11 +82,14 @@
{# SIDE NAV, TOGGLES ON MOBILE #}
<nav data-toggle="wy-nav-shift" class="wy-nav-side">
<div class="wy-side-nav-search">
{% block sidebartitle %}
<a href="{{ pathto(master_doc) }}" class="fa fa-home"> {{ project }}</a>
{% endblock %}
{% include "searchbox.html" %}
</div>
<div class="wy-menu wy-menu-vertical" data-spy="affix" role="navigation" aria-label="main navigation">
{% block menu %}
{% set toctree = toctree(maxdepth=2, collapse=False, includehidden=True) %}
{% if toctree %}
{{ toctree }}
@@ -117,6 +97,7 @@
<!-- Local TOC -->
<div class="local-toc">{{ toc }}</div>
{% endif %}
{% endblock %}
</div>
&nbsp;
</nav>
@@ -134,7 +115,7 @@
<div class="wy-nav-content">
<div class="rst-content">
{% include "breadcrumbs.html" %}
<div role="main">
<div role="main" class="document">
{% block body %}{% endblock %}
</div>
{% include "footer.html" %}
@@ -145,5 +126,39 @@
</div>
{% include "versions.html" %}
{% if not embedded %}
<script type="text/javascript">
var DOCUMENTATION_OPTIONS = {
URL_ROOT:'{{ url_root }}',
VERSION:'{{ release|e }}',
COLLAPSE_INDEX:false,
FILE_SUFFIX:'{{ '' if no_search_suffix else file_suffix }}',
HAS_SOURCE: {{ has_source|lower }}
};
</script>
{%- for scriptfile in script_files %}
<script type="text/javascript" src="{{ pathto(scriptfile, 1) }}"></script>
{%- endfor %}
{% endif %}
{# RTD hosts this file, so just load on non RTD builds #}
{% if not READTHEDOCS %}
<script type="text/javascript" src="{{ pathto('_static/js/theme.js', 1) }}"></script>
{% endif %}
{# STICKY NAVIGATION #}
{% if theme_sticky_navigation %}
<script type="text/javascript">
jQuery(function () {
SphinxRtdTheme.StickyNav.enable();
});
</script>
{% endif %}
{%- block footer %} {% endblock %}
</body>
</html>

View File

@@ -10,7 +10,7 @@
{%- extends "layout.html" %}
{% set title = _('Search') %}
{% set script_files = script_files + ['_static/searchtools.js'] %}
{% block extrahead %}
{% block footer %}
<script type="text/javascript">
jQuery(function() { Search.loadIndex("{{ pathto('searchindex.js', 1) }}"); });
</script>

View File

@@ -1,7 +1,9 @@
{%- if builder != 'singlehtml' %}
<div role="search">
<form id ="rtd-search-form" class="wy-form" action="{{ pathto('search') }}" method="get">
<form id="rtd-search-form" class="wy-form" action="{{ pathto('search') }}" method="get">
<input type="text" name="q" placeholder="Search docs" />
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
</form>
</div>
{%- endif %}

View File

@@ -1 +1,2 @@
.font-smooth,.fa:before{-webkit-font-smoothing:antialiased}.clearfix{*zoom:1}.clearfix:before,.clearfix:after{display:table;content:""}.clearfix:after{clear:both}@font-face{font-family:FontAwesome;font-weight:normal;font-style:normal;src:url("../font/fontawesome_webfont.eot");src:url("../font/fontawesome_webfont.eot?#iefix") format("embedded-opentype"),url("../font/fontawesome_webfont.woff") format("woff"),url("../font/fontawesome_webfont.ttf") format("truetype"),url("../font/fontawesome_webfont.svg#FontAwesome") format("svg")}.fa:before{display:inline-block;font-family:FontAwesome;font-style:normal;font-weight:normal;line-height:1;text-decoration:inherit}a .fa{display:inline-block;text-decoration:inherit}li .fa{display:inline-block}li .fa-large:before,li .fa-large:before{width:1.875em}ul.fas{list-style-type:none;margin-left:2em;text-indent:-0.8em}ul.fas li .fa{width:0.8em}ul.fas li .fa-large:before,ul.fas li .fa-large:before{vertical-align:baseline}.fa-book:before{content:"\f02d"}.icon-book:before{content:"\f02d"}.fa-caret-down:before{content:"\f0d7"}.icon-caret-down:before{content:"\f0d7"}.fa-caret-up:before{content:"\f0d8"}.icon-caret-up:before{content:"\f0d8"}.fa-caret-left:before{content:"\f0d9"}.icon-caret-left:before{content:"\f0d9"}.fa-caret-right:before{content:"\f0da"}.icon-caret-right:before{content:"\f0da"}.rst-versions{position:fixed;bottom:0;left:0;width:300px;color:#fcfcfc;background:#1f1d1d;border-top:solid 10px #343131;font-family:"Lato","proxima-nova","Helvetica Neue",Arial,sans-serif;z-index:400}.rst-versions a{color:#2980b9;text-decoration:none}.rst-versions .rst-badge-small{display:none}.rst-versions .rst-current-version{padding:12px;background-color:#272525;display:block;text-align:right;font-size:90%;cursor:pointer;color:#27ae60;*zoom:1}.rst-versions .rst-current-version:before,.rst-versions .rst-current-version:after{display:table;content:""}.rst-versions .rst-current-version:after{clear:both}.rst-versions .rst-current-version .fa{color:#fcfcfc}.rst-versions .rst-current-version .fa-book{float:left}.rst-versions .rst-current-version .icon-book{float:left}.rst-versions .rst-current-version.rst-out-of-date{background-color:#e74c3c;color:#fff}.rst-versions .rst-current-version.rst-active-old-version{background-color:#f1c40f;color:#000}.rst-versions.shift-up .rst-other-versions{display:block}.rst-versions .rst-other-versions{font-size:90%;padding:12px;color:gray;display:none}.rst-versions .rst-other-versions hr{display:block;height:1px;border:0;margin:20px 0;padding:0;border-top:solid 1px #413d3d}.rst-versions .rst-other-versions dd{display:inline-block;margin:0}.rst-versions .rst-other-versions dd a{display:inline-block;padding:6px;color:#fcfcfc}.rst-versions.rst-badge{width:auto;bottom:20px;right:20px;left:auto;border:none;max-width:300px}.rst-versions.rst-badge .icon-book{float:none}.rst-versions.rst-badge .fa-book{float:none}.rst-versions.rst-badge.shift-up .rst-current-version{text-align:right}.rst-versions.rst-badge.shift-up .rst-current-version .fa-book{float:left}.rst-versions.rst-badge.shift-up .rst-current-version .icon-book{float:left}.rst-versions.rst-badge .rst-current-version{width:auto;height:30px;line-height:30px;padding:0 6px;display:block;text-align:center}@media screen and (max-width: 768px){.rst-versions{width:85%;display:none}.rst-versions.shift{display:block}img{width:100%;height:auto}}
.fa:before{-webkit-font-smoothing:antialiased}.clearfix{*zoom:1}.clearfix:before,.clearfix:after{display:table;content:""}.clearfix:after{clear:both}@font-face{font-family:FontAwesome;font-weight:normal;font-style:normal;src:url("../font/fontawesome_webfont.eot");src:url("../font/fontawesome_webfont.eot?#iefix") format("embedded-opentype"),url("../font/fontawesome_webfont.woff") format("woff"),url("../font/fontawesome_webfont.ttf") format("truetype"),url("../font/fontawesome_webfont.svg#FontAwesome") format("svg")}.fa:before{display:inline-block;font-family:FontAwesome;font-style:normal;font-weight:normal;line-height:1;text-decoration:inherit}a .fa{display:inline-block;text-decoration:inherit}li .fa{display:inline-block}li .fa-large:before,li .fa-large:before{width:1.875em}ul.fas{list-style-type:none;margin-left:2em;text-indent:-0.8em}ul.fas li .fa{width:0.8em}ul.fas li .fa-large:before,ul.fas li .fa-large:before{vertical-align:baseline}.fa-book:before{content:""}.icon-book:before{content:""}.fa-caret-down:before{content:""}.icon-caret-down:before{content:""}.fa-caret-up:before{content:""}.icon-caret-up:before{content:""}.fa-caret-left:before{content:""}.icon-caret-left:before{content:""}.fa-caret-right:before{content:""}.icon-caret-right:before{content:""}.rst-versions{position:fixed;bottom:0;left:0;width:300px;color:#fcfcfc;background:#1f1d1d;border-top:solid 10px #343131;font-family:"Lato","proxima-nova","Helvetica Neue",Arial,sans-serif;z-index:400}.rst-versions a{color:#2980B9;text-decoration:none}.rst-versions .rst-badge-small{display:none}.rst-versions .rst-current-version{padding:12px;background-color:#272525;display:block;text-align:right;font-size:90%;cursor:pointer;color:#27AE60;*zoom:1}.rst-versions .rst-current-version:before,.rst-versions .rst-current-version:after{display:table;content:""}.rst-versions .rst-current-version:after{clear:both}.rst-versions .rst-current-version .fa{color:#fcfcfc}.rst-versions .rst-current-version .fa-book{float:left}.rst-versions .rst-current-version .icon-book{float:left}.rst-versions .rst-current-version.rst-out-of-date{background-color:#E74C3C;color:#fff}.rst-versions .rst-current-version.rst-active-old-version{background-color:#F1C40F;color:#000}.rst-versions.shift-up .rst-other-versions{display:block}.rst-versions .rst-other-versions{font-size:90%;padding:12px;color:gray;display:none}.rst-versions .rst-other-versions hr{display:block;height:1px;border:0;margin:20px 0;padding:0;border-top:solid 1px #413d3d}.rst-versions .rst-other-versions dd{display:inline-block;margin:0}.rst-versions .rst-other-versions dd a{display:inline-block;padding:6px;color:#fcfcfc}.rst-versions.rst-badge{width:auto;bottom:20px;right:20px;left:auto;border:none;max-width:300px}.rst-versions.rst-badge .icon-book{float:none}.rst-versions.rst-badge .fa-book{float:none}.rst-versions.rst-badge.shift-up .rst-current-version{text-align:right}.rst-versions.rst-badge.shift-up .rst-current-version .fa-book{float:left}.rst-versions.rst-badge.shift-up .rst-current-version .icon-book{float:left}.rst-versions.rst-badge .rst-current-version{width:auto;height:30px;line-height:30px;padding:0 6px;display:block;text-align:center}@media screen and (max-width: 768px){.rst-versions{width:85%;display:none}.rst-versions.shift{display:block}img{width:100%;height:auto}}
/*# sourceMappingURL=badge_only.css.map */

File diff suppressed because one or more lines are too long

View File

@@ -14,9 +14,20 @@ The header files are also available online: :doc:`nghttp2.h` and
Remarks
-------
Do not call `nghttp2_session_send`, `nghttp2_session_recv` or
`nghttp2_session_mem_recv` from the nghttp2 callback functions
directly or indirectly. It will lead to the crash. You can submit
requests or frames in the callbacks then call `nghttp2_session_send`,
`nghttp2_session_recv` or `nghttp2_session_mem_recv` outside of the
callbacks.
Do not call `nghttp2_session_send()`, `nghttp2_session_mem_send()`,
`nghttp2_session_recv()` or `nghttp2_session_mem_recv()` from the
nghttp2 callback functions directly or indirectly. It will lead to the
crash. You can submit requests or frames in the callbacks then call
these functions outside the callbacks.
Currently, `nghttp2_session_send()` and `nghttp2_session_mem_send()`
do not send client connection preface
(:macro:`NGHTTP2_CLIENT_CONNECTION_PREFACE`). The applications are
responsible to send it before sending any HTTP/2 frames using these
functions if :type:`nghttp2_session` is configured as client.
Similarly, `nghttp2_session_recv()` and `nghttp2_session_mem_recv()`
do not consume client connection preface unless
`nghttp2_option_set_recv_client_preface()` is used with nonzero option
value. The applications are responsible to receive it before calling
these functions if :type:`nghttp2_session` is configured as server and
`nghttp2_option_set_recv_client_preface()` is not used.

5
doc/asio_http2.h.rst.in Normal file
View File

@@ -0,0 +1,5 @@
asio_http2.h
============
.. literalinclude:: @top_srcdir@/src/includes/nghttp2/asio_http2.h
:language: cpp

View File

@@ -0,0 +1 @@
.. include:: @top_srcdir@/doc/sources/building-android-binary.rst

View File

@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
# nghttp2 - HTTP/2.0 C Library
# nghttp2 - HTTP/2 C Library
# Copyright (c) 2012 Tatsuhiro Tsujikawa
@@ -64,7 +64,7 @@ master_doc = 'index'
# General information about the project.
project = u'nghttp2'
copyright = u'2012, 2014, Tatsuhiro Tsujikawa'
copyright = u'2012, 2015, Tatsuhiro Tsujikawa'
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
@@ -155,7 +155,7 @@ html_theme_path = ['@top_srcdir@/doc/_themes']
# If true, SmartyPants will be used to convert quotes and dashes to
# typographically correct entities.
#html_use_smartypants = True
html_use_smartypants = False
# Custom sidebar templates, maps document names to template names.
html_sidebars = {
@@ -242,6 +242,12 @@ latex_documents = [
# One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section).
man_pages = [
('index', 'nghttp2', u'nghttp2 Documentation',
('nghttp.1', 'nghttp', u'HTTP/2 experimental client',
[u'Tatsuhiro Tsujikawa'], 1),
('nghttpd.1', 'nghttpd', u'HTTP/2 experimental server',
[u'Tatsuhiro Tsujikawa'], 1),
('nghttpx.1', 'nghttpx', u'HTTP/2 experimental proxy',
[u'Tatsuhiro Tsujikawa'], 1),
('h2load.1', 'h2load', u'HTTP/2 benchmarking tool',
[u'Tatsuhiro Tsujikawa'], 1)
]

1
doc/contribute.rst.in Normal file
View File

@@ -0,0 +1 @@
.. include:: @top_srcdir@/doc/sources/contribute.rst

1
doc/h2load-howto.rst.in Normal file
View File

@@ -0,0 +1 @@
.. include:: @top_srcdir@/doc/sources/h2load-howto.rst

146
doc/h2load.1 Normal file
View File

@@ -0,0 +1,146 @@
.\" Man page generated from reStructuredText.
.
.TH "H2LOAD" "1" "January 11, 2015" "0.7.1" "nghttp2"
.SH NAME
h2load \- HTTP/2 benchmarking tool
.
.nr rst2man-indent-level 0
.
.de1 rstReportMargin
\\$1 \\n[an-margin]
level \\n[rst2man-indent-level]
level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
-
\\n[rst2man-indent0]
\\n[rst2man-indent1]
\\n[rst2man-indent2]
..
.de1 INDENT
.\" .rstReportMargin pre:
. RS \\$1
. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
. nr rst2man-indent-level +1
.\" .rstReportMargin post:
..
.de UNINDENT
. RE
.\" indent \\n[an-margin]
.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
.nr rst2man-indent-level -1
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
..
.SH SYNOPSIS
.sp
\fBh2load\fP [OPTIONS]... [URI]...
.SH DESCRIPTION
.sp
benchmarking tool for HTTP/2 and SPDY server
.INDENT 0.0
.TP
.B <URI>
Specify URI to access. Multiple URIs can be
specified. URIs are used in this order for each
client. All URIs are used, then first URI is
used and then 2nd URI, and so on. The scheme,
host and port in the subsequent URIs, if present,
are ignored. Those in the first URI are used
solely.
.UNINDENT
.SH OPTIONS:
.INDENT 0.0
.TP
.B \-n, \-\-requests=<N>
Number of requests.
.sp
Default: \fB1\fP
.UNINDENT
.INDENT 0.0
.TP
.B \-c, \-\-clients=<N>
Number of concurrent clients.
.sp
Default: \fB1\fP
.UNINDENT
.INDENT 0.0
.TP
.B \-t, \-\-threads=<N>
Number of native threads.
.sp
Default: \fB1\fP
.UNINDENT
.INDENT 0.0
.TP
.B \-i, \-\-input\-file=<FILE>
Path of a file with multiple URIs are seperated
by EOLs. This option will disable URIs getting
from command\-line. If \(aq\-\(aq is given as <FILE>,
URIs will be read from stdin. URIs are used in
this order for each client. All URIs are used,
then first URI is used and then 2nd URI, and so
on. The scheme, host and port in the subsequent
URIs, if present, are ignored. Those in the
first URI are used solely.
.UNINDENT
.INDENT 0.0
.TP
.B \-m, \-\-max\-concurrent\-streams=(auto|<N>)
Max concurrent streams to issue per session. If
"auto" is given, the number of given URIs is
used.
.sp
Default: \fBauto\fP
.UNINDENT
.INDENT 0.0
.TP
.B \-w, \-\-window\-bits=<N>
Sets the stream level initial window size to
(2**<N>)\-1. For SPDY, 2**<N> is used instead.
.UNINDENT
.INDENT 0.0
.TP
.B \-W, \-\-connection\-window\-bits=<N>
Sets the connection level initial window size to
(2**<N>)\-1. For SPDY, if <N> is strictly less
than 16, this option is ignored. Otherwise
2**<N> is used for SPDY.
.UNINDENT
.INDENT 0.0
.TP
.B \-H, \-\-header=<HEADER>
Add/Override a header to the requests.
.UNINDENT
.INDENT 0.0
.TP
.B \-p, \-\-no\-tls\-proto=<PROTOID>
Specify ALPN identifier of the protocol to be
used when accessing http URI without SSL/TLS.
Available protocols: spdy/2, spdy/3, spdy/3.1 and
h2c\-14
.sp
Default: \fBh2c\-14\fP
.UNINDENT
.INDENT 0.0
.TP
.B \-v, \-\-verbose
Output debug information.
.UNINDENT
.INDENT 0.0
.TP
.B \-\-version
Display version information and exit.
.UNINDENT
.INDENT 0.0
.TP
.B \-h, \-\-help
Display this help and exit.
.UNINDENT
.SH SEE ALSO
.sp
\fInghttp(1)\fP, \fInghttpd(1)\fP, \fInghttpx(1)\fP
.SH AUTHOR
Tatsuhiro Tsujikawa
.SH COPYRIGHT
2012, 2015, Tatsuhiro Tsujikawa
.\" Generated by docutils manpage writer.
.

106
doc/h2load.1.rst Normal file
View File

@@ -0,0 +1,106 @@
h2load(1)
=========
SYNOPSIS
--------
**h2load** [OPTIONS]... [URI]...
DESCRIPTION
-----------
benchmarking tool for HTTP/2 and SPDY server
.. describe:: <URI>
Specify URI to access. Multiple URIs can be
specified. URIs are used in this order for each
client. All URIs are used, then first URI is
used and then 2nd URI, and so on. The scheme,
host and port in the subsequent URIs, if present,
are ignored. Those in the first URI are used
solely.
OPTIONS:
--------
.. option:: -n, --requests=<N>
Number of requests.
Default: ``1``
.. option:: -c, --clients=<N>
Number of concurrent clients.
Default: ``1``
.. option:: -t, --threads=<N>
Number of native threads.
Default: ``1``
.. option:: -i, --input-file=<FILE>
Path of a file with multiple URIs are seperated
by EOLs. This option will disable URIs getting
from command-line. If '-' is given as <FILE>,
URIs will be read from stdin. URIs are used in
this order for each client. All URIs are used,
then first URI is used and then 2nd URI, and so
on. The scheme, host and port in the subsequent
URIs, if present, are ignored. Those in the
first URI are used solely.
.. option:: -m, --max-concurrent-streams=(auto|<N>)
Max concurrent streams to issue per session. If
"auto" is given, the number of given URIs is
used.
Default: ``auto``
.. option:: -w, --window-bits=<N>
Sets the stream level initial window size to
(2**<N>)-1. For SPDY, 2\*\*<N> is used instead.
.. option:: -W, --connection-window-bits=<N>
Sets the connection level initial window size to
(2**<N>)-1. For SPDY, if <N> is strictly less
than 16, this option is ignored. Otherwise
2**<N> is used for SPDY.
.. option:: -H, --header=<HEADER>
Add/Override a header to the requests.
.. option:: -p, --no-tls-proto=<PROTOID>
Specify ALPN identifier of the protocol to be
used when accessing http URI without SSL/TLS.
Available protocols: spdy/2, spdy/3, spdy/3.1 and
h2c-14
Default: ``h2c-14``
.. option:: -v, --verbose
Output debug information.
.. option:: --version
Display version information and exit.
.. option:: -h, --help
Display this help and exit.
SEE ALSO
--------
:manpage:`nghttp(1)`, :manpage:`nghttpd(1)`, :manpage:`nghttpx(1)`

4
doc/h2load.h2r Normal file
View File

@@ -0,0 +1,4 @@
SEE ALSO
--------
:manpage:`nghttp(1)`, :manpage:`nghttpd(1)`, :manpage:`nghttpx(1)`

View File

@@ -0,0 +1 @@
.. include:: @top_srcdir@/doc/sources/libnghttp2_asio.rst

View File

@@ -1,5 +1,5 @@
#!/usr/bin/env python
# nghttp2 - HTTP/2.0 C Library
# nghttp2 - HTTP/2 C Library
# Copyright (c) 2012 Tatsuhiro Tsujikawa

View File

@@ -1,90 +1,217 @@
.\" nghttp2 manual page
.TH nghttp2 "1" "January 2014" "nghttp2" "User Commands"
.\" Man page generated from reStructuredText.
.
.TH "NGHTTP" "1" "January 11, 2015" "0.7.1" "nghttp2"
.SH NAME
nghttp2 \- HTTP2 experimental client
nghttp \- HTTP/2 experimental client
.
.nr rst2man-indent-level 0
.
.de1 rstReportMargin
\\$1 \\n[an-margin]
level \\n[rst2man-indent-level]
level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
-
\\n[rst2man-indent0]
\\n[rst2man-indent1]
\\n[rst2man-indent2]
..
.de1 INDENT
.\" .rstReportMargin pre:
. RS \\$1
. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
. nr rst2man-indent-level +1
.\" .rstReportMargin post:
..
.de UNINDENT
. RE
.\" indent \\n[an-margin]
.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
.nr rst2man-indent-level -1
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
..
.SH SYNOPSIS
\fBnghttp\fP [\fIOPTIONS\fP] \fIURI\fP...
.sp
\fBnghttp\fP [OPTIONS]... <URI>...
.SH DESCRIPTION
Experimental client for HTTP 2.0.
.SH OPTIONS
.sp
HTTP/2 experimental client
.INDENT 0.0
.TP
\fB\-v\fR, \fB\-\-verbose\fR
Print debug information such as reception/
.B <URI>
Specify URI to access.
.UNINDENT
.SH OPTIONS:
.INDENT 0.0
.TP
.B \-v, \-\-verbose
Print debug information such as reception and
transmission of frames and name/value pairs.
Specifying this option multiple times increases
verbosity.
.UNINDENT
.INDENT 0.0
.TP
\fB\-n\fR, \fB\-\-null\-out\fR
.B \-n, \-\-null\-out
Discard downloaded data.
.UNINDENT
.INDENT 0.0
.TP
\fB\-O\fR, \fB\-\-remote\-name\fR
Save download data in the current directory.
The filename is dereived from URI. If URI
ends with '/', 'index.html' is used as a
filename. Not implemented yet.
.B \-O, \-\-remote\-name
Save download data in the current directory. The
filename is dereived from URI. If URI ends with
\(aq\fI/\fP\(aq, \(aqindex.html\(aq is used as a filename. Not
implemented yet.
.UNINDENT
.INDENT 0.0
.TP
\fB\-t\fR, \fB\-\-timeout=\fR<N>
.B \-t, \-\-timeout=<N>
Timeout each request after <N> seconds.
.UNINDENT
.INDENT 0.0
.TP
\fB\-w\fR, \fB\-\-window\-bits=\fR<N>
Sets the stream level initial window size
to 2**<N>\-1.
.B \-w, \-\-window\-bits=<N>
Sets the stream level initial window size to
2**<N>\-1.
.UNINDENT
.INDENT 0.0
.TP
\fB\-W\fR, \fB\-\-connection\-window\-bits=\fR<N>
Sets the connection level initial window
size to 2**<N>\-1.
.B \-W, \-\-connection\-window\-bits=<N>
Sets the connection level initial window size to
2**<N>\-1.
.UNINDENT
.INDENT 0.0
.TP
\fB\-a\fR, \fB\-\-get\-assets\fR
Download assets such as stylesheets, images
and script files linked from the downloaded
resource. Only links whose origins are the
same with the linking resource will be
downloaded.
.B \-a, \-\-get\-assets
Download assets such as stylesheets, images and
script files linked from the downloaded resource.
Only links whose origins are the same with the
linking resource will be downloaded. nghttp
prioritizes resources using HTTP/2 dependency
based priority. The priority order, from highest
to lowest, is html itself, css, javascript and
images.
.UNINDENT
.INDENT 0.0
.TP
\fB\-s\fR, \fB\-\-stat\fR
.B \-s, \-\-stat
Print statistics.
.UNINDENT
.INDENT 0.0
.TP
\fB\-H\fR, \fB\-\-header\fR
Add a header to the requests.
.B \-H, \-\-header=<HEADER>
Add a header to the requests. Example:
\fI\%\-H\fP\(aq:method: PUT\(aq
.UNINDENT
.INDENT 0.0
.TP
\fB\-\-cert=\fR<CERT>
Use the specified client certificate file.
The file must be in PEM format.
.B \-\-cert=<CERT>
Use the specified client certificate file. The
file must be in PEM format.
.UNINDENT
.INDENT 0.0
.TP
\fB\-\-key=\fR<KEY>
Use the client private key file. The file
must be in PEM format.
.B \-\-key=<KEY>
Use the client private key file. The file must
be in PEM format.
.UNINDENT
.INDENT 0.0
.TP
\fB\-d\fR, \fB\-\-data=\fR<FILE>
Post FILE to server. If \- is given, data
will be read from stdin.
.B \-d, \-\-data=<FILE>
Post FILE to server. If \(aq\-\(aq is given, data will
be read from stdin.
.UNINDENT
.INDENT 0.0
.TP
\fB\-m\fR, \fB\-\-multiply=\fR<N> Request each URI <N> times. By default, same
URI is not requested twice. This option
disables it too.
.B \-m, \-\-multiply=<N>
Request each URI <N> times. By default, same URI
is not requested twice. This option disables it
too.
.UNINDENT
.INDENT 0.0
.TP
\fB\-f\fR, \fB\-\-no\-flow\-control\fR
Disables connection and stream level flow
controls.
.B \-u, \-\-upgrade
Perform HTTP Upgrade for HTTP/2. This option is
ignored if the request URI has https scheme. If
\fI\-d\fP is used, the HTTP upgrade request is performed
with OPTIONS method.
.UNINDENT
.INDENT 0.0
.TP
\fB\-u\fR, \fB\-\-upgrade\fR
Perform HTTP Upgrade for HTTP/2.0. This
option is ignored if the request URI has
https scheme.
If \fB\-d\fR is used, the HTTP upgrade request is
performed with OPTIONS method.
.B \-p, \-\-weight=<WEIGHT>
Sets priority group weight. The valid value
range is [1, 256], inclusive.
.sp
Default: \fB16\fP
.UNINDENT
.INDENT 0.0
.TP
\fB\-p\fR, \fB\-\-pri=\fR<PRIORITY>
Sets stream priority. Default: 1073741824
.B \-M, \-\-peer\-max\-concurrent\-streams=<N>
Use <N> as SETTINGS_MAX_CONCURRENT_STREAMS value
of remote endpoint as if it is received in
SETTINGS frame. The default is large enough as
it is seen as unlimited.
.UNINDENT
.INDENT 0.0
.TP
\fB\-M\fR, \fB\-\-peer\-max\-concurrent\-streams=\fR<N>
Use <N> as SETTINGS_MAX_CONCURRENT_STREAMS
value of remote endpoint as if it is
received in SETTINGS frame. The default
is large enough as it is seen as unlimited.
.TP
\fB\-c\fR, \fB\-\-header\-table\-size=\fR<N>
.B \-c, \-\-header\-table\-size=<N>
Specify decoder header table size.
.UNINDENT
.INDENT 0.0
.TP
\fB\-\-color\fR
.B \-b, \-\-padding=<N>
Add at most <N> bytes to a frame payload as
padding. Specify 0 to disable padding.
.UNINDENT
.INDENT 0.0
.TP
.B \-r, \-\-har=<FILE>
Output HTTP transactions <FILE> in HAR format.
If \(aq\-\(aq is given, data is written to stdout.
.UNINDENT
.INDENT 0.0
.TP
.B \-\-color
Force colored log output.
.SH "SEE ALSO"
nghttpd(1), nghttpx(1)
.UNINDENT
.INDENT 0.0
.TP
.B \-\-continuation
Send large header to test CONTINUATION.
.UNINDENT
.INDENT 0.0
.TP
.B \-\-no\-content\-length
Don\(aqt send content\-length header field.
.UNINDENT
.INDENT 0.0
.TP
.B \-\-no\-dep
Don\(aqt send dependency based priority hint to
server.
.UNINDENT
.INDENT 0.0
.TP
.B \-\-dep\-idle
Use idle streams as anchor nodes to express
priority.
.UNINDENT
.INDENT 0.0
.TP
.B \-\-version
Display version information and exit.
.UNINDENT
.INDENT 0.0
.TP
.B \-h, \-\-help
Display this help and exit.
.UNINDENT
.SH SEE ALSO
.sp
\fInghttpd(1)\fP, \fInghttpx(1)\fP, \fIh2load(1)\fP
.SH AUTHOR
Tatsuhiro Tsujikawa
.SH COPYRIGHT
2012, 2015, Tatsuhiro Tsujikawa
.\" Generated by docutils manpage writer.
.

163
doc/nghttp.1.rst Normal file
View File

@@ -0,0 +1,163 @@
nghttp(1)
=========
SYNOPSIS
--------
**nghttp** [OPTIONS]... <URI>...
DESCRIPTION
-----------
HTTP/2 experimental client
.. describe:: <URI>
Specify URI to access.
OPTIONS:
--------
.. option:: -v, --verbose
Print debug information such as reception and
transmission of frames and name/value pairs.
Specifying this option multiple times increases
verbosity.
.. option:: -n, --null-out
Discard downloaded data.
.. option:: -O, --remote-name
Save download data in the current directory. The
filename is dereived from URI. If URI ends with
'*/*', 'index.html' is used as a filename. Not
implemented yet.
.. option:: -t, --timeout=<N>
Timeout each request after <N> seconds.
.. option:: -w, --window-bits=<N>
Sets the stream level initial window size to
2\*\*<N>-1.
.. option:: -W, --connection-window-bits=<N>
Sets the connection level initial window size to
2\*\*<N>-1.
.. option:: -a, --get-assets
Download assets such as stylesheets, images and
script files linked from the downloaded resource.
Only links whose origins are the same with the
linking resource will be downloaded. nghttp
prioritizes resources using HTTP/2 dependency
based priority. The priority order, from highest
to lowest, is html itself, css, javascript and
images.
.. option:: -s, --stat
Print statistics.
.. option:: -H, --header=<HEADER>
Add a header to the requests. Example:
:option:`-H`\':method: PUT'
.. option:: --cert=<CERT>
Use the specified client certificate file. The
file must be in PEM format.
.. option:: --key=<KEY>
Use the client private key file. The file must
be in PEM format.
.. option:: -d, --data=<FILE>
Post FILE to server. If '-' is given, data will
be read from stdin.
.. option:: -m, --multiply=<N>
Request each URI <N> times. By default, same URI
is not requested twice. This option disables it
too.
.. option:: -u, --upgrade
Perform HTTP Upgrade for HTTP/2. This option is
ignored if the request URI has https scheme. If
:option:`-d` is used, the HTTP upgrade request is performed
with OPTIONS method.
.. option:: -p, --weight=<WEIGHT>
Sets priority group weight. The valid value
range is [1, 256], inclusive.
Default: ``16``
.. option:: -M, --peer-max-concurrent-streams=<N>
Use <N> as SETTINGS_MAX_CONCURRENT_STREAMS value
of remote endpoint as if it is received in
SETTINGS frame. The default is large enough as
it is seen as unlimited.
.. option:: -c, --header-table-size=<N>
Specify decoder header table size.
.. option:: -b, --padding=<N>
Add at most <N> bytes to a frame payload as
padding. Specify 0 to disable padding.
.. option:: -r, --har=<FILE>
Output HTTP transactions <FILE> in HAR format.
If '-' is given, data is written to stdout.
.. option:: --color
Force colored log output.
.. option:: --continuation
Send large header to test CONTINUATION.
.. option:: --no-content-length
Don't send content-length header field.
.. option:: --no-dep
Don't send dependency based priority hint to
server.
.. option:: --dep-idle
Use idle streams as anchor nodes to express
priority.
.. option:: --version
Display version information and exit.
.. option:: -h, --help
Display this help and exit.
SEE ALSO
--------
:manpage:`nghttpd(1)`, :manpage:`nghttpx(1)`, :manpage:`h2load(1)`

4
doc/nghttp.h2r Normal file
View File

@@ -0,0 +1,4 @@
SEE ALSO
--------
:manpage:`nghttpd(1)`, :manpage:`nghttpx(1)`, :manpage:`h2load(1)`

View File

@@ -1,55 +1,162 @@
.\" nghttpd manual page
.TH nghttpd "1" "January 2014" "nghttpd" "User Commands"
.\" Man page generated from reStructuredText.
.
.TH "NGHTTPD" "1" "January 11, 2015" "0.7.1" "nghttp2"
.SH NAME
nghttpd \- HTTP 2.0 experimental server
nghttpd \- HTTP/2 experimental server
.
.nr rst2man-indent-level 0
.
.de1 rstReportMargin
\\$1 \\n[an-margin]
level \\n[rst2man-indent-level]
level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
-
\\n[rst2man-indent0]
\\n[rst2man-indent1]
\\n[rst2man-indent2]
..
.de1 INDENT
.\" .rstReportMargin pre:
. RS \\$1
. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
. nr rst2man-indent-level +1
.\" .rstReportMargin post:
..
.de UNINDENT
. RE
.\" indent \\n[an-margin]
.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
.nr rst2man-indent-level -1
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
..
.SH SYNOPSIS
\fBnghttpd\fP [\fIOPTIONS\fP...] [\fIPRIVATE_KEY\fP \fICERT\fP]
.sp
\fBnghttpd\fP [OPTION]... <PORT> [<PRIVATE_KEY> <CERT>]
.SH DESCRIPTION
Experimental HTTP 2.0 server.
.SH "Positional arguments"
.sp
HTTP/2 experimental server
.INDENT 0.0
.TP
\fIPRIVATE_KEY\fP
Set path to server's private key. Required
unless either \fB\-p\fR or \fB\-\-client\fR is specified.
.B <PORT>
Specify listening port number.
.UNINDENT
.INDENT 0.0
.TP
\fICERT\fP
Set path to server's certificate. Required
unless either \fB\-p\fR or \fB\-\-client\fR is specified.
.SH OPTIONS
.B <PRIVATE_KEY>
Set path to server\(aqs private key. Required
unless \fI\%\-\-no\-tls\fP is specified.
.UNINDENT
.INDENT 0.0
.TP
\fB\-D\fR, \fB\-\-daemon\fR
Run in a background. If \fB\-D\fR is used, the
current working directory is changed to '/'.
Therefore if this option is used, \fB\-d\fR option
must be specified.
.B <CERT>
Set path to server\(aqs certificate. Required
unless \fI\%\-\-no\-tls\fP is specified.
.UNINDENT
.SH OPTIONS:
.INDENT 0.0
.TP
\fB\-V\fR, \fB\-\-verify\-client\fR
The server sends a client certificate
request. If the client did not return a
certificate, the handshake is terminated.
Currently, this option just requests a
client certificate and does not verify it.
.B \-D, \-\-daemon
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 is used, \fI\%\-d\fP option must be
specified.
.UNINDENT
.INDENT 0.0
.TP
\fB\-d\fR, \fB\-\-htdocs=\fR<PATH>
Specify document root. If this option is
not specified, the document root is the
current working directory.
.B \-V, \-\-verify\-client
The server sends a client certificate request.
If the client did not return a certificate, the
handshake is terminated. Currently, this option
just requests a client certificate and does not
verify it.
.UNINDENT
.INDENT 0.0
.TP
\fB\-v\fR, \fB\-\-verbose\fR
.B \-d, \-\-htdocs=<PATH>
Specify document root. If this option is not
specified, the document root is the current
working directory.
.UNINDENT
.INDENT 0.0
.TP
.B \-v, \-\-verbose
Print debug information such as reception/
transmission of frames and name/value pairs.
.UNINDENT
.INDENT 0.0
.TP
\fB\-\-no\-tls\fR
.B \-\-no\-tls
Disable SSL/TLS.
.UNINDENT
.INDENT 0.0
.TP
\fB\-f\fR, \fB\-\-no\-flow\-control\fR
Disables connection and stream level flow
controls.
.B \-c, \-\-header\-table\-size=<N>
Specify decoder header table size.
.UNINDENT
.INDENT 0.0
.TP
\fB\-\-color\fR
.B \-\-color
Force colored log output.
.UNINDENT
.INDENT 0.0
.TP
\fB\-h\fR, \fB\-\-help\fR
Print this help.
.SH "SEE ALSO"
nghttp(1), nghttpx(1)
.B \-p, \-\-push=<PATH>=<PUSH_PATH,...>
Push resources <PUSH_PATH>s when <PATH> is
requested. This option can be used repeatedly to
specify multiple push configurations. <PATH> and
<PUSH_PATH>s are relative to document root. See
\fI\%\-\-htdocs\fP option. Example: \fI\-p\fP/=/foo.png
\fI\-p\fP/doc=/bar.css
.UNINDENT
.INDENT 0.0
.TP
.B \-b, \-\-padding=<N>
Add at most <N> bytes to a frame payload as
padding. Specify 0 to disable padding.
.UNINDENT
.INDENT 0.0
.TP
.B \-n, \-\-workers=<CORE>
Set the number of worker threads.
.sp
Default: \fB1\fP
.UNINDENT
.INDENT 0.0
.TP
.B \-e, \-\-error\-gzip
Make error response gzipped.
.UNINDENT
.INDENT 0.0
.TP
.B \-\-dh\-param\-file=<PATH>
Path to file that contains DH parameters in PEM
format. Without this option, DHE cipher suites
are not available.
.UNINDENT
.INDENT 0.0
.TP
.B \-\-early\-response
Start sending response when request HEADERS is
received, rather than complete request is
received.
.UNINDENT
.INDENT 0.0
.TP
.B \-\-version
Display version information and exit.
.UNINDENT
.INDENT 0.0
.TP
.B \-h, \-\-help
Display this help and exit.
.UNINDENT
.SH SEE ALSO
.sp
\fInghttp(1)\fP, \fInghttpx(1)\fP, \fIh2load(1)\fP
.SH AUTHOR
Tatsuhiro Tsujikawa
.SH COPYRIGHT
2012, 2015, Tatsuhiro Tsujikawa
.\" Generated by docutils manpage writer.
.

117
doc/nghttpd.1.rst Normal file
View File

@@ -0,0 +1,117 @@
nghttpd(1)
==========
SYNOPSIS
--------
**nghttpd** [OPTION]... <PORT> [<PRIVATE_KEY> <CERT>]
DESCRIPTION
-----------
HTTP/2 experimental server
.. describe:: <PORT>
Specify listening port number.
.. describe:: <PRIVATE_KEY>
Set path to server's private key. Required
unless :option:`--no-tls` is specified.
.. describe:: <CERT>
Set path to server's certificate. Required
unless :option:`--no-tls` is specified.
OPTIONS:
--------
.. option:: -D, --daemon
Run in a background. If :option:`-D` is used, the current
working directory is changed to '*/*'. Therefore
if this option is used, :option:`-d` option must be
specified.
.. option:: -V, --verify-client
The server sends a client certificate request.
If the client did not return a certificate, the
handshake is terminated. Currently, this option
just requests a client certificate and does not
verify it.
.. option:: -d, --htdocs=<PATH>
Specify document root. If this option is not
specified, the document root is the current
working directory.
.. option:: -v, --verbose
Print debug information such as reception/
transmission of frames and name/value pairs.
.. option:: --no-tls
Disable SSL/TLS.
.. option:: -c, --header-table-size=<N>
Specify decoder header table size.
.. option:: --color
Force colored log output.
.. option:: -p, --push=<PATH>=<PUSH_PATH,...>
Push resources <PUSH_PATH>s when <PATH> is
requested. This option can be used repeatedly to
specify multiple push configurations. <PATH> and
<PUSH_PATH>s are relative to document root. See
:option:`--htdocs` option. Example: :option:`\-p`/=/foo.png
:option:`-p`\/doc=/bar.css
.. option:: -b, --padding=<N>
Add at most <N> bytes to a frame payload as
padding. Specify 0 to disable padding.
.. option:: -n, --workers=<CORE>
Set the number of worker threads.
Default: ``1``
.. option:: -e, --error-gzip
Make error response gzipped.
.. option:: --dh-param-file=<PATH>
Path to file that contains DH parameters in PEM
format. Without this option, DHE cipher suites
are not available.
.. option:: --early-response
Start sending response when request HEADERS is
received, rather than complete request is
received.
.. option:: --version
Display version information and exit.
.. option:: -h, --help
Display this help and exit.
SEE ALSO
--------
:manpage:`nghttp(1)`, :manpage:`nghttpx(1)`, :manpage:`h2load(1)`

4
doc/nghttpd.h2r Normal file
View File

@@ -0,0 +1,4 @@
SEE ALSO
--------
:manpage:`nghttp(1)`, :manpage:`nghttpx(1)`, :manpage:`h2load(1)`

1
doc/nghttpx-howto.rst.in Normal file
View File

@@ -0,0 +1 @@
.. include:: @top_srcdir@/doc/sources/nghttpx-howto.rst

File diff suppressed because it is too large Load Diff

694
doc/nghttpx.1.rst Normal file
View File

@@ -0,0 +1,694 @@
nghttpx(1)
==========
SYNOPSIS
--------
**nghttpx** [OPTIONS]... [<PRIVATE_KEY> <CERT>]
DESCRIPTION
-----------
A reverse proxy for HTTP/2, HTTP/1 and SPDY.
.. describe:: <PRIVATE_KEY>
Set path to server's private key. Required
unless :option:`-p`\, :option:`--client` or :option:`\--frontend-no-tls` are
given.
.. describe:: <CERT>
Set path to server's certificate. Required
unless :option:`-p`\, :option:`--client` or :option:`\--frontend-no-tls` are
given.
OPTIONS:
--------
The options are categorized into several groups.
Connections:
~~~~~~~~~~~~
.. option:: -b, --backend=<HOST,PORT>
Set backend host and port. For HTTP/1 backend,
multiple backend addresses are accepted by
repeating this option. HTTP/2 backend does not
support multiple backend addresses and the first
occurrence of this option is used.
Default: ``127.0.0.1,80``
.. option:: -f, --frontend=<HOST,PORT>
Set frontend host and port. If <HOST> is '\*', it
assumes all addresses including both IPv4 and
IPv6.
Default: ``*,3000``
.. option:: --backlog=<NUM>
Set listen backlog size. If :option:`-1` is given,
libevent will choose suitable value.
Default: ``128``
.. option:: --backend-ipv4
Resolve backend hostname to IPv4 address only.
.. option:: --backend-ipv6
Resolve backend hostname to IPv6 address only.
.. option:: --backend-http-proxy-uri=<URI>
Specify proxy URI in the form
http://[<USER>:<PASS>@]<PROXY>:<PORT>. If a
proxy requires authentication, specify <USER> and
<PASS>. Note that they must be properly
percent-encoded. This proxy is used when the
backend connection is HTTP/2. First, make a
CONNECT request to the proxy and it connects to
the backend on behalf of nghttpx. This forms
tunnel. After that, nghttpx performs SSL/TLS
handshake with the downstream through the tunnel.
The timeouts when connecting and making CONNECT
request can be specified by
:option:`--backend-read-timeout` and
:option:`--backend-write-timeout` options.
Performance:
~~~~~~~~~~~~
.. option:: -n, --workers=<CORES>
Set the number of worker threads.
Default: ``1``
.. option:: --read-rate=<RATE>
Set maximum average read rate on frontend
connection. Setting 0 to this option means read
rate is unlimited.
Default: ``0``
.. option:: --read-burst=<SIZE>
Set maximum read burst size on frontend
connection. Setting 0 to this option means read
burst size is unlimited.
Default: ``0``
.. option:: --write-rate=<RATE>
Set maximum average write rate on frontend
connection. Setting 0 to this option means write
rate is unlimited.
Default: ``0``
.. option:: --write-burst=<SIZE>
Set maximum write burst size on frontend
connection. Setting 0 to this option means write
burst size is unlimited.
Default: ``0``
.. option:: --worker-read-rate=<RATE>
Set maximum average read rate on frontend
connection per worker. Setting 0 to this option
means read rate is unlimited. Not implemented
yet.
Default: ``0``
.. option:: --worker-read-burst=<SIZE>
Set maximum read burst size on frontend
connection per worker. Setting 0 to this option
means read burst size is unlimited. Not
implemented yet.
Default: ``0``
.. option:: --worker-write-rate=<RATE>
Set maximum average write rate on frontend
connection per worker. Setting 0 to this option
means write rate is unlimited. Not implemented
yet.
Default: ``0``
.. option:: --worker-write-burst=<SIZE>
Set maximum write burst size on frontend
connection per worker. Setting 0 to this option
means write burst size is unlimited. Not
implemented yet.
Default: ``0``
.. option:: --worker-frontend-connections=<NUM>
Set maximum number of simultaneous connections
frontend accepts. Setting 0 means unlimited.
Default: ``0``
.. option:: --backend-http1-connections-per-host=<NUM>
Set maximum number of backend concurrent HTTP/1
connections per host. This option is meaningful
when :option:`-s` option is used. To limit the number of
connections per frontend for default mode, use
:option:`--backend-http1-connections-per-frontend`\.
Default: ``8``
.. option:: --backend-http1-connections-per-frontend=<NUM>
Set maximum number of backend concurrent HTTP/1
connections per frontend. This option is only
used for default mode. 0 means unlimited. To
limit the number of connections per host for
HTTP/2 or SPDY proxy mode (-s option), use
:option:`--backend-http1-connections-per-host`\.
Default: ``0``
.. option:: --rlimit-nofile=<N>
Set maximum number of open files (RLIMIT_NOFILE)
to <N>. If 0 is given, nghttpx does not set the
limit.
Default: ``0``
Timeout:
~~~~~~~~
.. option:: --frontend-http2-read-timeout=<SEC>
Specify read timeout for HTTP/2 and SPDY frontend
connection.
Default: ``180``
.. option:: --frontend-read-timeout=<SEC>
Specify read timeout for HTTP/1.1 frontend
connection.
Default: ``180``
.. option:: --frontend-write-timeout=<SEC>
Specify write timeout for all frontend
connections.
Default: ``30``
.. option:: --stream-read-timeout=<SEC>
Specify read timeout for HTTP/2 and SPDY streams.
0 means no timeout.
Default: ``0``
.. option:: --stream-write-timeout=<SEC>
Specify write timeout for HTTP/2 and SPDY
streams. 0 means no timeout.
Default: ``0``
.. option:: --backend-read-timeout=<SEC>
Specify read timeout for backend connection.
Default: ``180``
.. option:: --backend-write-timeout=<SEC>
Specify write timeout for backend connection.
Default: ``30``
.. option:: --backend-keep-alive-timeout=<SEC>
Specify keep-alive timeout for backend
connection.
Default: ``600``
.. option:: --listener-disable-timeout=<SEC>
After accepting connection failed, connection
listener is disabled for a given time in seconds.
Specifying 0 disables this feature.
Default: ``0``
SSL/TLS:
~~~~~~~~
.. option:: --ciphers=<SUITE>
Set allowed cipher list. The format of the
string is described in OpenSSL ciphers(1).
.. option:: -k, --insecure
Don't verify backend server's certificate if :option:`-p`\,
:option:`--client` or :option:`\--http2-bridge` are given and
:option:`--backend-no-tls` is not given.
.. option:: --cacert=<PATH>
Set path to trusted CA certificate file if :option:`-p`\,
:option:`--client` or :option:`\--http2-bridge` are given and
:option:`--backend-no-tls` is not given. The file must be
in PEM format. It can contain multiple
certificates. If the linked OpenSSL is
configured to load system wide certificates, they
are loaded at startup regardless of this option.
.. option:: --private-key-passwd-file=<FILEPATH>
Path to file that contains password for the
server's private key. If none is given and the
private key is password protected it'll be
requested interactively.
.. option:: --subcert=<KEYPATH>:<CERTPATH>
Specify additional certificate and private key
file. nghttpx will choose certificates based on
the hostname indicated by client using TLS SNI
extension. This option can be used multiple
times.
.. option:: --backend-tls-sni-field=<HOST>
Explicitly set the content of the TLS SNI
extension. This will default to the backend HOST
name.
.. option:: --dh-param-file=<PATH>
Path to file that contains DH parameters in PEM
format. Without this option, DHE cipher suites
are not available.
.. option:: --npn-list=<LIST>
Comma delimited list of ALPN protocol identifier
sorted in the order of preference. That means
most desirable protocol comes first. This is
used in both ALPN and NPN. The parameter must be
delimited by a single comma only and any white
spaces are treated as a part of protocol string.
Default: ``h2-16,h2-14,spdy/3.1,http/1.1``
.. option:: --verify-client
Require and verify client certificate.
.. option:: --verify-client-cacert=<PATH>
Path to file that contains CA certificates to
verify client certificate. The file must be in
PEM format. It can contain multiple
certificates.
.. option:: --client-private-key-file=<PATH>
Path to file that contains client private key
used in backend client authentication.
.. option:: --client-cert-file=<PATH>
Path to file that contains client certificate
used in backend client authentication.
.. option:: --tls-proto-list=<LIST>
Comma delimited list of SSL/TLS protocol to be
enabled. The following protocols are available:
TLSv1.2, TLSv1.1 and TLSv1.0. The name matching
is done in case-insensitive manner. The
parameter must be delimited by a single comma
only and any white spaces are treated as a part
of protocol string.
Default: ``TLSv1.2,TLSv1.1``
.. option:: --tls-ticket-key-file=<FILE>
Path to file that contains 48 bytes random data
to construct TLS session ticket parameters. This
options can be used repeatedly to specify
multiple ticket parameters. If several files are
given, only the first key is used to encrypt TLS
session tickets. Other keys are accepted but
server will issue new session ticket with first
key. This allows session key rotation. Please
note that key rotation does not occur
automatically. User should rearrange files or
change options values and restart nghttpx
gracefully. If opening or reading given file
fails, all loaded keys are discarded and it is
treated as if none of this option is given. If
this option is not given or an error occurred
while opening or reading a file, key is generated
automatically and renewed every 12hrs. At most 2
keys are stored in memory.
HTTP/2 and SPDY:
~~~~~~~~~~~~~~~~
.. option:: -c, --http2-max-concurrent-streams=<NUM>
Set the maximum number of the concurrent streams
in one HTTP/2 and SPDY session.
Default: ``100``
.. option:: --frontend-http2-window-bits=<N>
Sets the per-stream initial window size of HTTP/2
SPDY frontend connection. For HTTP/2, the size
is 2**<N>-1. For SPDY, the size is 2\*\*<N>.
Default: ``16``
.. option:: --frontend-http2-connection-window-bits=<N>
Sets the per-connection window size of HTTP/2 and
SPDY frontend connection. For HTTP/2, the size
is 2**<N>-1. For SPDY, the size is 2\*\*<N>.
Default: ``16``
.. option:: --frontend-no-tls
Disable SSL/TLS on frontend connections.
.. option:: --backend-http2-window-bits=<N>
Sets the initial window size of HTTP/2 backend
connection to 2**<N>-1.
Default: ``16``
.. option:: --backend-http2-connection-window-bits=<N>
Sets the per-connection window size of HTTP/2
backend connection to 2\*\*<N>-1.
Default: ``16``
.. option:: --backend-no-tls
Disable SSL/TLS on backend connections.
.. option:: --http2-no-cookie-crumbling
Don't crumble cookie header field.
.. option:: --padding=<N>
Add at most <N> bytes to a HTTP/2 frame payload
as padding. Specify 0 to disable padding. This
option is meant for debugging purpose and not
intended to enhance protocol security.
Mode:
~~~~~
.. describe:: (default mode)
Accept HTTP/2, SPDY and HTTP/1.1 over SSL/TLS.
If :option:`--frontend-no-tls` is used, accept HTTP/2 and
HTTP/1.1. The incoming HTTP/1.1 connection can
be upgraded to HTTP/2 through HTTP Upgrade. The
protocol to the backend is HTTP/1.1.
.. option:: -s, --http2-proxy
Like default mode, but enable secure proxy mode.
.. option:: --http2-bridge
Like default mode, but communicate with the
backend in HTTP/2 over SSL/TLS. Thus the
incoming all connections are converted to HTTP/2
connection and relayed to the backend. See
:option:`--backend-http-proxy-uri` option if you are behind
the proxy and want to connect to the outside
HTTP/2 proxy.
.. option:: --client
Accept HTTP/2 and HTTP/1.1 without SSL/TLS. The
incoming HTTP/1.1 connection can be upgraded to
HTTP/2 connection through HTTP Upgrade. The
protocol to the backend is HTTP/2. To use
nghttpx as a forward proxy, use :option:`-p` option
instead.
.. option:: -p, --client-proxy
Like :option:`--client` option, but it also requires the
request path from frontend must be an absolute
URI, suitable for use as a forward proxy.
Logging:
~~~~~~~~
.. option:: -L, --log-level=<LEVEL>
Set the severity level of log output. <LEVEL>
must be one of INFO, NOTICE, WARN, ERROR and
FATAL.
Default: ``NOTICE``
.. option:: --accesslog-file=<PATH>
Set path to write access log. To reopen file,
send USR1 signal to nghttpx.
.. option:: --accesslog-syslog
Send access log to syslog. If this option is
used, :option:`--accesslog-file` option is ignored.
.. option:: --accesslog-format=<FORMAT>
Specify format string for access log. The
default format is combined format. The following
variables are available:
* $remote_addr: client IP address.
* $time_local: local time in Common Log format.
* $time_iso8601: local time in ISO 8601 format.
* $request: HTTP request line.
* $status: HTTP response status code.
* $body_bytes_sent: the number of bytes sent to
client as response body.
* $http_<VAR>: value of HTTP request header <VAR>
where '_' in <VAR> is replaced with '-'.
* $remote_port: client port.
* $server_port: server port.
* $request_time: request processing time in
seconds with milliseconds resolution.
* $pid: PID of the running process.
* $alpn: ALPN identifier of the protocol which
generates the response. For HTTP/1, ALPN is
always http/1.1, regardless of minor version.
Default: ``$remote_addr - - [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent"``
.. option:: --errorlog-file=<PATH>
Set path to write error log. To reopen file,
send USR1 signal to nghttpx.
Default: ``/dev/stderr``
.. option:: --errorlog-syslog
Send error log to syslog. If this option is
used, :option:`--errorlog-file` option is ignored.
.. option:: --syslog-facility=<FACILITY>
Set syslog facility to <FACILITY>.
Default: ``daemon``
Misc:
~~~~~
.. option:: --add-x-forwarded-for
Append X-Forwarded-For header field to the
downstream request.
.. option:: --strip-incoming-x-forwarded-for
Strip X-Forwarded-For header field from inbound
client requests.
.. option:: --no-via
Don't append to Via header field. If Via header
field is received, it is left unaltered.
.. option:: --no-location-rewrite
Don't rewrite location header field on
:option:`--http2-bridge`\, :option:`--client` and default mode. For
:option:`--http2-proxy` and :option:`\--client-proxy` mode, location
header field will not be altered regardless of
this option.
.. option:: --altsvc=<PROTOID,PORT[,HOST,[ORIGIN]]>
Specify protocol ID, port, host and origin of
alternative service. <HOST> and <ORIGIN> are
optional. They are advertised in alt-svc header
field or HTTP/2 ALTSVC frame. This option can be
used multiple times to specify multiple
alternative services. Example: :option:`--altsvc`\=h2,443
.. option:: --add-response-header=<HEADER>
Specify additional header field to add to
response header set. This option just appends
header field and won't replace anything already
set. This option can be used several times to
specify multiple header fields.
Example: :option:`--add-response-header`\="foo: bar"
.. option:: --frontend-http2-dump-request-header=<PATH>
Dumps request headers received by HTTP/2 frontend
to the file denoted in <PATH>. The output is
done in HTTP/1 header field format and each
header block is followed by an empty line. This
option is not thread safe and MUST NOT be used
with option :option:`-n`\<N>, where <N> >= 2.
.. option:: --frontend-http2-dump-response-header=<PATH>
Dumps response headers sent from HTTP/2 frontend
to the file denoted in <PATH>. The output is
done in HTTP/1 header field format and each
header block is followed by an empty line. This
option is not thread safe and MUST NOT be used
with option :option:`-n`\<N>, where <N> >= 2.
.. option:: -o, --frontend-frame-debug
Print HTTP/2 frames in frontend to stderr. This
option is not thread safe and MUST NOT be used
with option :option:`-n`\=N, where N >= 2.
.. option:: -D, --daemon
Run in a background. If :option:`-D` is used, the current
working directory is changed to '*/*'.
.. option:: --pid-file=<PATH>
Set path to save PID of this program.
.. option:: --user=<USER>
Run this program as <USER>. This option is
intended to be used to drop root privileges.
.. option:: --conf=<PATH>
Load configuration from <PATH>.
Default: ``/etc/nghttpx/nghttpx.conf``
.. option:: -v, --version
Print version and exit.
.. option:: -h, --help
Print this help and exit.
FILES
-----
*/etc/nghttpx/nghttpx.conf*
The default configuration file path nghttpx searches at startup.
The configuration file path can be changed using :option:`--conf`
option.
Those lines which are staring ``#`` are treated as comment.
The option name in the configuration file is the long command-line
option name with leading ``--`` stripped (e.g., ``frontend``). Put
``=`` between option name and value. Don't put extra leading or
trailing spaces.
The options which do not take argument in the command-line *take*
argument in the configuration file. Specify ``yes`` as an argument
(e.g., ``http2-proxy=yes``). If other string is given, it is
ignored.
To specify private key and certificate file which are given as
positional arguments in commnad-line, use ``private-key-file`` and
``certificate-file``.
:option:`--conf` option cannot be used in the configuration file and
will be ignored if specified.
SIGNALS
-------
SIGQUIT
Shutdown gracefully. First accept pending connections and stop
accepting connection. After all connections are handled, nghttpx
exits.
SIGUSR1
Reopen log files.
SIGUSR2
Fork and execute nghttpx. It will execute the binary in the same
path with same command-line arguments and environment variables.
After new process comes up, sending SIGQUIT to the original process
to perform hot swapping.
SEE ALSO
--------
:manpage:`nghttp(1)`, :manpage:`nghttpd(1)`, :manpage:`h2load(1)`

48
doc/nghttpx.h2r Normal file
View File

@@ -0,0 +1,48 @@
FILES
-----
*/etc/nghttpx/nghttpx.conf*
The default configuration file path nghttpx searches at startup.
The configuration file path can be changed using :option:`--conf`
option.
Those lines which are staring ``#`` are treated as comment.
The option name in the configuration file is the long command-line
option name with leading ``--`` stripped (e.g., ``frontend``). Put
``=`` between option name and value. Don't put extra leading or
trailing spaces.
The options which do not take argument in the command-line *take*
argument in the configuration file. Specify ``yes`` as an argument
(e.g., ``http2-proxy=yes``). If other string is given, it is
ignored.
To specify private key and certificate file which are given as
positional arguments in commnad-line, use ``private-key-file`` and
``certificate-file``.
:option:`--conf` option cannot be used in the configuration file and
will be ignored if specified.
SIGNALS
-------
SIGQUIT
Shutdown gracefully. First accept pending connections and stop
accepting connection. After all connections are handled, nghttpx
exits.
SIGUSR1
Reopen log files.
SIGUSR2
Fork and execute nghttpx. It will execute the binary in the same
path with same command-line arguments and environment variables.
After new process comes up, sending SIGQUIT to the original process
to perform hot swapping.
SEE ALSO
--------
:manpage:`nghttp(1)`, :manpage:`nghttpd(1)`, :manpage:`h2load(1)`

1
doc/python-apiref.rst.in Normal file
View File

@@ -0,0 +1 @@
.. include:: @top_srcdir@/doc/sources/python-apiref.rst

View File

@@ -0,0 +1,135 @@
Building Android binary
=======================
In this article, we briefly describe how to build Android binary using
`Android NDK <http://developer.android.com/tools/sdk/ndk/index.html>`_
cross-compiler on Debian Linux.
The easiest way to build android binary is use Dockerfile.android.
See Dockerfile.android for more details. If you cannot use
Dockerfile.android for whatever reason, continue to read the rest of
this article.
We offer ``android-config`` and ``android-make`` scripts to make the
build easier. To make these script work, NDK toolchain must be
installed in the following way. First, let us introduce
``ANDROID_HOME`` environment variable. We need to install toolchain
under ``$ANDROID_HOME/toolchain``. An user can freely choose the path
for ``ANDROID_HOME``. For example, to install toolchain under
``$ANDROID_HOME/toolchain``, do this in the the directory where NDK is
unpacked::
$ build/tools/make-standalone-toolchain.sh \
--install-dir=$ANDROID_HOME/toolchain \
--toolchain=arm-linux-androideabi-4.9 \
--llvm-version=3.5 \
--platform=android-16
The additional flag ``--system=linux-x86_64`` may be required if you
are using x86_64 system.
The platform level is not important here because we don't use Android
specific C/C++ API.
The dependent libraries, such as OpenSSL and libev should be built
with the toolchain and installed under ``$ANDROID_HOME/usr/local``.
We recommend to build these libraries as static library to make the
deployment easier. libxml2 support is currently disabled.
We use zlib which comes with Android NDK, so we don't have to build it
by ourselves.
If SPDY support is required for nghttpx and h2load, build and install
spdylay as well.
Before running ``android-config`` and ``android-make``,
``ANDROID_HOME`` environment variable must be set to point to the
correct path. Also add ``$ANDROID_HOME/toolchain/bin`` to ``PATH``::
$ export PATH=$PATH:$ANDROID_HOME/toolchain/bin
To configure OpenSSL, use the following script:
.. code-block:: sh
#!/bin/sh
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
export CROSS_COMPILE=$TOOLCHAIN/bin/arm-linux-androideabi-
./Configure --prefix=$PREFIX android
And run ``make install`` to build and install.
We cannot compile libev without modification. Apply `this patch
<https://gist.github.com/tatsuhiro-t/48c45f08950f587180ed>`_ before
configuring libev. This patch is for libev-4.19. After applying the
patch, to configure libev, use the following script:
.. code-block:: sh
#!/bin/sh
if [ -z "$ANDROID_HOME" ]; then
echo 'No $ANDROID_HOME specified.'
exit 1
fi
PREFIX=$ANDROID_HOME/usr/local
TOOLCHAIN=$ANDROID_HOME/toolchain
PATH=$TOOLCHAIN/bin:$PATH
./configure \
--host=arm-linux-androideabi \
--build=`dpkg-architecture -qDEB_BUILD_GNU_TYPE` \
--prefix=$PREFIX \
--disable-shared \
--enable-static \
CPPFLAGS=-I$PREFIX/include \
LDFLAGS=-L$PREFIX/lib
And run ``make install`` to build and install.
To configure spdylay, use the following script:
.. code-block:: sh
if [ -z "$ANDROID_HOME" ]; then
echo 'No $ANDROID_HOME specified.'
exit 1
fi
PREFIX=$ANDROID_HOME/usr/local
TOOLCHAIN=$ANDROID_HOME/toolchain
PATH=$TOOLCHAIN/bin:$PATH
./configure \
--disable-shared \
--host=arm-linux-androideabi \
--build=`dpkg-architecture -qDEB_BUILD_GNU_TYPE` \
--prefix=$PREFIX \
--without-libxml2 \
--disable-src \
--disable-examples \
CPPFLAGS="-I$PREFIX/include" \
PKG_CONFIG_LIBDIR="$PREFIX/lib/pkgconfig" \
LDFLAGS="-L$PREFIX/lib"
And run ``make install`` to build and install. After spdylay
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
then ``android-make`` to compile nghttp2 source files.
If all went well, application binaries, such as nghttpx, are created
under src directory. Strip debugging information from the binary
using the following command::
$ arm-linux-androideabi-strip src/nghttpx

View File

@@ -0,0 +1,57 @@
Contribution Guidelines
=======================
[This text 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!
Coding style
------------
We use clang-format to format source code consistently. The
clang-format configuration file .clang-format is located at the root
directory. Since clang-format produces slightly different results
between versions, we currently use clang-format which comes with
clang-3.5.
To detect any violation to the coding style, we recommend to setup git
pre-commit hook to check coding style of the changes you introduced.
The pre-commit file is located at the root directory. Copy it under
.git/hooks and make sure that it is executable. The pre-commit script
uses clang-format-diff.py to detect any style errors. If it is not in
your PATH or it exists under different name (e.g.,
clang-format-diff-3.5 in debian), either add it to PATH variable or
add git option ``clangformatdiff.binary`` to point to the script.
For emacs users, integrating clang-format to emacs is very easy.
clang-format.el should come with clang distribution. If it is not
found, download it from `here
<https://llvm.org/svn/llvm-project/cfe/trunk/tools/clang-format/clang-format.el>`_.
And add these lines to your .emacs file:
.. code-block:: lisp
;; From
;; https://code.google.com/p/chromium/wiki/Emacs#Use_Google's_C++_style!
(load "/<path/to>/clang-format.el")
(add-hook 'c-mode-common-hook
(function (lambda () (local-set-key (kbd "TAB")
'clang-format-region))))
You can find other editor integration in
http://clang.llvm.org/docs/ClangFormat.html.

View File

@@ -0,0 +1,90 @@
h2load - HTTP/2 benchmarking tool - HOW-TO
==========================================
h2load is benchmarking tool for HTTP/2. If built with
spdylay (http://tatsuhiro-t.github.io/spdylay/) library, it also
supports SPDY protocol. It supports SSL/TLS and clear text for both
HTTP/2 and SPDY.
Basic Usage
-----------
In order to set benchmark settings, specify following 3 options.
``-n``
The number of total requests. Default: 1
``-c``
The number of concurrent clients. Default: 1
``-m``
The max concurrent streams to issue per client.
If ``auto`` is given, the number of given URIs is used.
Default: ``auto``
Here is a command-line to perform benchmark to URI \https://localhost
using total 100000 requests, 100 concurrent clients and 10 max
concurrent streams::
$ h2load -n100000 -c100 -m10 https://localhost
The benchmarking result looks like this::
finished in 0 sec, 385 millisec and 851 microsec, 2591 req/s, 1689 kbytes/s
requests: 1000 total, 1000 started, 1000 done, 1000 succeeded, 0 failed, 0 errored
status codes: 1000 2xx, 0 3xx, 0 4xx, 0 5xx
traffic: 667500 bytes total, 28700 bytes headers, 612000 bytes data
The number of ``failed`` is the number of requests returned with non
2xx status. The number of ``error`` is the number of ``failed`` plus
the number of requests which failed with connection error.
The number of ``total`` in ``traffic`` is the received application
data. If SSL/TLS is used, this number is calculated after decryption.
The number of ``headers`` is the sum of payload size of response
HEADERS (or SYN_REPLY for SPDY). This number comes before
decompressing header block. The number of ``data`` is the sum of
response body.
Flow Control
------------
HTTP/2 and SPDY/3 or later employ flow control and it may affect
benchmarking results. To adjust receiver flow control window size,
there is following options:
``-w``
Sets the stream level initial window size to
(2**<N>)-1. For SPDY, 2**<N> is used instead.
``-W``
Sets the connection level initial window size to
(2**<N>)-1. For SPDY, if <N> is strictly less
than 16, this option is ignored. Otherwise
2**<N> is used for SPDY.
Multi-Threading
---------------
Sometimes benchmarking client itself becomes a bottleneck. To remedy
this situation, use ``-t`` option to specify the number of native
thread to use.
``-t``
The number of native threads. Default: 1
Selecting protocol for clear text
---------------------------------
By default, if \http:// URI is given, HTTP/2 protocol is used. To
change the protocol to use for clear text, use ``-p`` option.
Multiple URIs
-------------
If multiple URIs are specified, they are used in round robin manner.
.. note::
Please note that h2load uses sheme, host and port in the first URI
and ignores those parts in the rest of the URIs.

View File

@@ -3,11 +3,11 @@
You can adapt this file completely to your liking, but it should at least
contain the root `toctree` directive.
nghttp2 - HTTP/2.0 C Library
nghttp2 - HTTP/2 C Library
============================
This is an experimental implementation of Hypertext Transfer Protocol
version 2.0.
version 2.
The project is hosted at `github.com/tatsuhiro-t/nghttp2 <https://github.com/tatsuhiro-t/nghttp2>`_.
@@ -17,24 +17,34 @@ Contents:
:maxdepth: 2
package_README
contribute
building-android-binary
tutorial-client
tutorial-server
tutorial-hpack
nghttp.1
nghttpd.1
nghttpx.1
h2load.1
nghttpx-howto
h2load-howto
apiref
libnghttp2_asio
python-apiref
nghttp2.h
nghttp2ver.h
asio_http2.h
Source <https://github.com/tatsuhiro-t/nghttp2>
Issues <https://github.com/tatsuhiro-t/nghttp2/issues>
nghttp2.org <https://nghttp2.org/>
Released Versions
=================
* `v0.3.0 <released-versions/v0.3.0/>`_ `(Download v0.3.0) <https://github.com/tatsuhiro-t/nghttp2/releases/tag/v0.3.0>`_
* `v0.2.0 <released-versions/v0.2.0/>`_ `(Download v0.2.0) <https://github.com/tatsuhiro-t/nghttp2/releases/tag/v0.2.0>`_
* `v0.1.0 <released-versions/v0.1.0/>`_ `(Download v0.1.0) <https://github.com/tatsuhiro-t/nghttp2/releases/tag/v0.1.0>`_
https://github.com/tatsuhiro-t/nghttp2/releases
Resources
---------
* http://tools.ietf.org/html/draft-ietf-httpbis-http2-09
* http://tools.ietf.org/html/draft-ietf-httpbis-header-compression-05
* http://tools.ietf.org/html/draft-ietf-httpbis-http2-14
* http://tools.ietf.org/html/draft-ietf-httpbis-header-compression-09

View File

@@ -0,0 +1,228 @@
libnghttp2_asio: High level HTTP/2 C++ library
==============================================
libnghttp2_asio is C++ library built on top of libnghttp2 and provides
high level abstraction API to build HTTP/2 applications. It depends
on Boost::ASIO library and OpenSSL. Currently libnghttp2_asio
provides server side API.
libnghttp2_asio is not built by default. Use ``--enable-asio-lib``
configure flag to build libnghttp2_asio. The required Boost libraries
are:
* Boost::Asio
* Boost::System
* Boost::Thread
To use libnghttp2_asio, first include following header file:
.. code-block:: cpp
#include <nghttp2/asio_http2.h>
Also take a look at that header file :doc:`asio_http2.h`.
Server API
----------
Server API is designed to build HTTP/2 server very easily to utilize
C++11 anonymous function and closure. The bare minimum example of
HTTP/2 server looks like this:
.. code-block:: cpp
#include <nghttp2/asio_http2.h>
using namespace nghttp2::asio_http2;
using namespace nghttp2::asio_http2::server;
int main(int argc, char *argv[]) {
http2 server;
server.listen("*", 3000, [](const std::shared_ptr<request> &req,
const std::shared_ptr<response> &res) {
res->write_head(200);
res->end("hello, world");
});
}
First we instantiate ``nghttp2::asio_http2::server::http2`` object.
Then call ``nghttp2::asio_http2::server::http2::listen`` function with
address and port to listen to and callback function, namely "request
callback", invoked when request arrives.
The ``req`` and ``res`` represent HTTP request and response
respectively. ``nghttp2::asio_http2_::server::response::write_head``
constructs HTTP response header fields. The first argument is HTTP
status code, in the above example, which is 200. The second argument,
which is omitted in the above example, is additional header fields to
send.
``nghttp2::asio_http2::server::response::end`` sends responde body.
In the above example, we send string "hello, world".
Serving static files and enabling SSL/TLS
+++++++++++++++++++++++++++++++++++++++++
In this example, we serve a couple of static files and also enable
SSL/TLS.
.. code-block:: cpp
#include <nghttp2/asio_http2.h>
using namespace nghttp2::asio_http2;
using namespace nghttp2::asio_http2::server;
int main(int argc, char *argv[]) {
http2 server;
server.tls("server.key", "server.crt");
server.listen("*", 3000, [](const std::shared_ptr<request> &req,
const std::shared_ptr<response> &res) {
if (req->path() == "/" || req->path() == "/index.html") {
res->write_head(200);
res->end(file_reader("index.html"));
} else {
res->write_head(404);
res->end("<html><head><title>404</title></head>"
"<body>404 Not Found</body></html>");
}
});
}
Specifying path to private key file and certificate file in
``nghttp2::asio_http2::server::http2::tls`` will enable SSL/TLS. Both
files must be in PEM format.
In the above example, if request path is either "/" or "/index.html",
we serve index.html file in the current working directory.
``nghttp2::asio_http2::server::response::end`` has overload to take
function of type ``nghttp2::asio_http2::read_cb`` and application pass
its implementation to generate response body. For the convenience,
libnghttp2_asio library provides ``nghttp2::asio_http2::file_reader``
function to generate function to server static file.
Server push
+++++++++++
Server push is also supported.
.. code-block:: cpp
#include <nghttp2/asio_http2.h>
using namespace nghttp2::asio_http2;
using namespace nghttp2::asio_http2::server;
int main(int argc, char *argv[]) {
http2 server;
server.tls("server.key", "server.crt");
server.listen("*", 3000, [](const std::shared_ptr<request> &req,
const std::shared_ptr<response> &res) {
if (req->path() == "/") {
req->push("GET", "/my.css");
res->write_head(200);
res->end(file_reader("index.html"));
return;
}
if (req->path() == "/my.css") {
res->write_head(200);
res->end(file_reader("my.css"));
return;
}
res->write_head(404);
res->end("<html><head><title>404</title></head>"
"<body>404 Not Found</body></html>");
});
}
When client requested "/", we push "/my.css". To push resource, call
``nghttp2::asio_http2::server::request::push`` function with desired
method and path. Later, the callback will be called with the pushed
resource "/my.css".
Enable multi-threading
++++++++++++++++++++++
Enabling multi-threading is very easy. Just call
``nghttp2::asio_http2::server::http2::num_threads`` function with the
desired number of threads:
.. code-block:: cpp
http2 server;
// Use 4 native threads
server.num_threads(4);
Run blocking tasks in background thread
+++++++++++++++++++++++++++++++++++++++
The request callback is called in the same thread where HTTP request
is handled. And many connections shares the same thread, we cannot
directly run blocking tasks in request callback.
To run blocking tasks, use
``nghttp2::asio_http2::server::request::run_task``. The passed
callback will be executed in the different thread from the thread
where request callback was executed. So application can perform
blocking task there. The example follows:
.. code-block:: cpp
#include <unistd.h>
#include <nghttp2/asio_http2.h>
using namespace nghttp2::asio_http2;
using namespace nghttp2::asio_http2::server;
int main(int argc, char *argv[]) {
http2 server;
server.num_concurrent_tasks(16);
server.listen("*", 3000, [](const std::shared_ptr<request> &req,
const std::shared_ptr<response> &res) {
req->run_task([res](channel &channel) {
// executed in different thread than the thread where
// request callback was executed.
// using res directly here is not safe. Capturing it by
// value is safe because it is std::shared_ptr.
sleep(1);
channel.post([res]() {
// executed in the same thread where request callback
// was executed.
res->write_head(200);
res->end("hello, world");
});
});
});
}
First we set the number of background threads which run tasks. By
default it is set to 1. In this example, we set it to 16, so at most
16 tasks can be executed concurrently without blocking handling new
requests.
We call ``req->run_task()`` to execute task in background thread. In
the passed callback, we just simply sleeps 1 second. After sleep is
over, we schedule another callback to send response to the client.
Since the callback passed to ``req->run_task()`` is executed in the
different thread from the thread where request callback is called,
using ``req`` or ``res`` object directly there may cause undefined
behaviour. To avoid this issue, we can use
``nghttp2::asio_http2::channel::post`` by supplying a callback which
in turn get called in the same thread where request callback was
called.

View File

@@ -0,0 +1,295 @@
nghttpx - HTTP/2 proxy - HOW-TO
===============================
nghttpx is a proxy translating protocols between HTTP/2 and other
protocols (e.g., HTTP/1, SPDY). It operates in several modes and each
mode may require additional programs to work with. This article
describes each operation mode and explains the intended use-cases. It
also covers some useful options later.
Default mode
------------
If nghttpx is invoked without any ``-s``, ``-p`` and ``--client``, it
operates in default mode. In this mode, nghttpx frontend listens for
HTTP/2 requests and translates them to HTTP/1 requests. Thus it works
as reverse proxy (gateway) for HTTP/2 clients to HTTP/1 web server.
HTTP/1 requests are also supported in frontend as a fallback. If
nghttpx is linked with spdylay library and frontend connection is
SSL/TLS, the frontend also supports SPDY protocol.
By default, this mode's frontend connection is encrypted using
SSL/TLS. So server's private key and certificate must be supplied to
the command line (or through configuration file). In this case, the
fontend protocol selection will is done via ALPN or NPN.
With ``--frontend-no-tls`` option, user can turn off SSL/TLS in
frontend connection. In this case, SPDY protocol is not available
even if spdylay library is liked to nghttpx. HTTP/2 and HTTP/1 are
available on the frontend and a HTTP/1 connection can be upgraded to
HTTP/2 using HTTP Upgrade. Starting HTTP/2 connection by sending
HTTP/2 connection preface is also supported.
The backend is supposed to be HTTP/1 Web server. For example, to make
nghttpx listen to encrypted HTTP/2 requests at port 8443, and a
backend HTTP/1 web server is configured to listen to HTTP/1 request at
port 8080 in the same host, run nghttpx command-line like this::
$ nghttpx -f0.0.0.0,8443 -b127.0.0.1,8080 /path/to/server.key /path/to/server.crt
Then HTTP/2 enabled client can access to the nghttpx in HTTP/2. For
example, you can send GET request to the server using nghttp::
$ nghttp -nv https://localhost:8443/
HTTP/2 proxy mode
-----------------
If nghttpx is invoked with ``-s`` option, it operates in HTTP/2 proxy
mode. The supported protocols in frontend and backend connections are
the same in `default mode`_. The difference is that this mode acts
like forward proxy and assumes the backend is HTTP/1 proxy server
(e.g., squid, traffic server). So HTTP/1 request must include
absolute URI in request line.
By default, frontend connection is encrypted. So this mode is also
called secure proxy. If nghttpx is linked with spdylay, it supports
SPDY protocols and it works as so called SPDY proxy.
With ``--frontend-no-tls`` option, SSL/TLS is turned off in frontend
connection, so the connection gets insecure.
The backend must be HTTP/1 proxy server. nghttpx only supports
multiple backend server addresses. It translates incoming requests to
HTTP/1 request to backend server. The backend server performs real
proxy work for each request, for example, dispatching requests to the
origin server and caching contents.
For example, to make nghttpx listen to encrypted HTTP/2 requests at
port 8443, and a backend HTTP/1 proxy server is configured to listen
to HTTP/1 request at port 8080 in the same host, run nghttpx
command-line like this::
$ nghttpx -s -f'*,8443' -b127.0.0.1,8080 /path/to/server.key /path/to/server.crt
At the time of this writing, Firefox nightly supports HTTP/2 proxy.
Chromium can use nghttpx as secure (SPDY) proxy and will support
HTTP/2 proxy in the near future.
To make Firefox nightly or Chromium use nghttpx as HTTP/2 or SPDY
proxy, user has to create proxy.pac script file like this:
.. code-block:: javascript
function FindProxyForURL(url, host) {
return "HTTPS SERVERADDR:PORT";
}
``SERVERADDR`` and ``PORT`` is the hostname/address and port of the
machine nghttpx is running. Please note that both Firefox nightly and
Chromium require valid certificate for secure proxy.
For Firefox nightly, open Preference window and select Advanced then
click Network tab. Clicking Connection Settings button will show the
dialog. Select "Automatic proxy configuration URL" and enter the path
to proxy.pac file, something like this::
file:///path/to/proxy.pac
For Chromium, use following command-line::
$ google-chrome --proxy-pac-url=file:///path/to/proxy.pac --use-npn
As HTTP/1 proxy server, Squid may work as out-of-box. Traffic server
requires to be configured as forward proxy. Here is the minimum
configuration items to edit::
CONFIG proxy.config.reverse_proxy.enabled INT 0
CONFIG proxy.config.url_remap.remap_required INT 0
Consult Traffic server `documentation
<https://docs.trafficserver.apache.org/en/latest/admin/forward-proxy.en.html>`_
to know how to configure traffic server as forward proxy and its
security implications.
Client mode
-----------
If nghttpx is invoked with ``--client`` option, it operates in client
mode. In this mode, nghttpx listens for plain, unencrypted HTTP/2 and
HTTP/1 requests and translates them to encrypted HTTP/2 requests to
the backend. User cannot enable SSL/TLS in frontend connection.
HTTP/1 frontend connection can be upgraded to HTTP/2 using HTTP
Upgrade. To disable SSL/TLS in backend connection, use
``--backend-no-tls`` option.
The backend connection is created one per worker (thread).
The backend server is supporsed to be a HTTP/2 web server (e.g.,
nghttpd). The one use-case of this mode is utilize existing HTTP/1
clients to test HTTP/2 deployment. Suppose that HTTP/2 web server
listens to port 80 without encryption. Then run nghttpx as client
mode to access to that web server::
$ nghttpx --client -f127.0.0.1,8080 -b127.0.0.1,80 --backend-no-tls
.. note::
You may need ``-k`` option if HTTP/2 server enables SSL/TLS and
its certificate is self-signed. But please note that it is
insecure.
Then you can use curl to access HTTP/2 server via nghttpx::
$ curl http://localhost:8080/
Client proxy mode
-----------------
If nghttpx is invoked with ``-p`` option, it operates in client proxy
mode. This mode behaves like `client mode`_, but it works like
forward proxy. So HTTP/1 request must include absolute URI in request
line.
HTTP/1 frontend connection can be upgraded to HTTP/2 using HTTP
Upgrade. To disable SSL/TLS in backend connection, use
``--backend-no-tls`` option.
The backend connection is created one per worker (thread).
The backend server must be a HTTP/2 proxy. You can use nghttpx in
`HTTP/2 proxy mode`_ as backend server. The one use-case of this mode
is utilize existing HTTP/1 clients to test HTTP/2 connections between
2 proxies. The another use-case is use this mode to aggregate local
HTTP/1 connections to one HTTP/2 backend encrypted connection. This
makes HTTP/1 clients which does not support secure proxy can use
secure HTTP/2 proxy via nghttpx client mode.
Suppose that HTTP/2 proxy listens to port 8443, just like we saw in
`HTTP/2 proxy mode`_. To run nghttpx in client proxy mode to access
that server, invoke nghttpx like this::
$ nghttpx -p -f127.0.0.1,8080 -b127.0.0.1,8443
.. note::
You may need ``-k`` option if HTTP/2 server's certificate is
self-signed. But please note that it is insecure.
Then you can use curl to issue HTTP request via HTTP/2 proxy::
$ curl --http-proxy=http://localhost:8080 http://www.google.com/
You can configure web browser to use localhost:8080 as forward
proxy.
HTTP/2 bridge mode
------------------
If nghttpx is invoked with ``--http2-bridge`` option, it operates in
HTTP/2 bridge mode. The supported protocols in frontend connections
are the same in `default mode`_. The protocol in backend is HTTP/2
only.
With ``--frontend-no-tls`` option, SSL/TLS is turned off in frontend
connection, so the connection gets insecure. To disable SSL/TLS in
backend connection, use ``--backend-no-tls`` option.
The backend server is supporsed to be a HTTP/2 web server or HTTP/2
proxy. If backend server is HTTP/2 proxy, use
``--no-location-rewrite`` option to disable rewriting location header
field.
The use-case of this mode is aggregate the incoming connections to one
HTTP/2 connection. One backend HTTP/2 connection is created per
worker (thread).
Disable SSL/TLS
---------------
In `default mode`_, `HTTP/2 proxy mode`_ and `HTTP/2 bridge mode`_,
frontend connections are encrypted with SSL/TLS by default. To turn
off SSL/TLS, use ``--frontend-no-tls`` option. If this option is
used, the private key and certificate are not required to run nghttpx.
In `client mode`_, `client proxy mode`_ and `HTTP/2 bridge mode`_,
backend connections are encrypted with SSL/TLS by default. To turn
off SSL/TLS, use ``--backend-no-tls`` option.
Specifying additional CA certificate
------------------------------------
By default, nghttpx tries to read CA certificate from system. But
depending on the system you use, this may fail or is not supported.
To specify CA certificate manually, use ``--cacert`` option. The
specified file must be PEM format and can contain multiple
certificates.
By default, nghttpx validates server's certificate. If you want to
turn off this validation, knowing this is really insecure and what you
are doing, you can use ``-k`` option to disable certificate
validation.
Read/write rate limit
---------------------
nghttpx supports transfer rate limiting on frontend connections. You
can do rate limit per frontend connection for reading and writeing
individually.
To perform rate limit for reading, use ``--read-rate`` and
``--read-burst`` options. For writing, use ``--write-rate`` and
``--write-burst``.
Please note that rate limit is performed on top of TCP and nothing to
do with HTTP/2 flow control.
Rewriting location header field
-------------------------------
nghttpx automatically rewrites location response header field if the
following all conditions satisfy:
* URI in location header field is not absolute URI or is not https URI.
* URI in location header field includes non empty host component.
* host (without port) in URI in location header field must match the
host appearing in :authority or host header field.
When rewrite happens, URI scheme and port are replaced with the ones
used in frontend, and host is replaced with which appears in
:authority or host request header field. :authority header field has
precedence. If the above conditions are not met with the host value
in :authority header field, rewrite is retried with the value in host
header field.
Hot swapping
------------
nghttpx supports hot swapping using signals. The hot swapping in
nghttpx is multi step process. First send USR2 signal to nghttpx
process. It will do fork and execute new executable, using same
command-line arguments and environment variables. At this point, both
current and new processes can accept requests. To gracefully shutdown
current process, send QUIT signal to current nghttpx process. When
all existing frontend connections are done, the current process will
exit. At this point, only new nghttpx process exists and serves
incoming requests.
Re-opening log files
--------------------
When rotating log files, it is desirable to re-open log files after
log rotation daemon renamed existing log files. To tell nghttpx to
re-open log files, send USR1 signal to nghttpx process. It will
re-open files specified by ``--accesslog-file`` and
``--errorlog-file`` options.
Multiple HTTP/1 backend addresses
---------------------------------
nghttpx supports multiple HTTP/1 backend addresses. To specify them,
just use ``-b`` option repeatedly. For example, to use backend1:8080
and backend2:8080, use command-line like this: ``-bbackend1,8080
-bbackend2,8080``. Please note that HTTP/2 backend only supports 1
backend address.

View File

@@ -0,0 +1,319 @@
Python API Reference
====================
.. py:module:: nghttp2
nghttp2 offers some high level Python API to C library. The bindings
currently provide HPACK compressor and decompressor classes and HTTP/2
server class.
The extension module is called ``nghttp2``.
``make`` will build the bindings. The target Python version is
determined by configure script. If the detected Python version is not
what you expect, specify a path to Python executable in ``PYTHON``
variable as an argument to configure script (e.g., ``./configure
PYTHON=/usr/bin/python3.4``).
HPACK API
---------
.. py:class:: HDDeflater(hd_table_bufsize_max=DEFLATE_MAX_HEADER_TABLE_SIZE)
This class is used to perform header compression. The
*hd_table_bufsize_max* limits the usage of header table in the
given amount of bytes. The default value is
:py:data:`DEFLATE_MAX_HEADER_TABLE_SIZE`. This is necessary
because the deflater and inflater share the same amount of header
table and the inflater decides that number. The deflater may not
want to use all header table size because of limited memory
availability. In that case, *hd_table_bufsize_max* can be used to
cap the upper limit of table size whatever the header table size is
chosen by the inflater.
.. py:method:: deflate(headers)
Deflates the *headers*. The *headers* must be sequence of tuple
of name/value pair, which are byte strings (not unicode string).
This method returns the deflated header block in byte string.
Raises the exception if any error occurs.
.. py:method:: set_no_refset(no_refset)
Tells the deflater not to use reference set if *no_refset* is
evaluated to ``True``. If that happens, on each subsequent
invocation of :py:meth:`deflate()`, deflater will clear up
refersent set.
.. py:method:: change_table_size(hd_table_bufsize_max)
Changes header table size to *hd_table_bufsize_max* byte. if
*hd_table_bufsize_max* is strictly larger than
``hd_table_bufsize_max`` given in constructor,
``hd_table_bufsize_max`` is used as header table size instead.
Raises the exception if any error occurs.
.. py:method:: get_hd_table()
Returns copy of current dynamic header table.
The following example shows how to deflate header name/value pairs:
.. code-block:: python
import binascii, nghttp2
deflater = nghttp2.HDDeflater()
res = deflater.deflate([(b'foo', b'bar'),
(b'baz', b'buz')])
print(binascii.b2a_hex(res))
.. py:class:: HDInflater()
This class is used to perform header decompression.
.. py:method:: inflate(data)
Inflates the deflated header block *data*. The *data* must be
byte string.
Raises the exception if any error occurs.
.. py:method:: change_table_size(hd_table_bufsize_max)
Changes header table size to *hd_table_bufsize_max* byte.
Raises the exception if any error occurs.
.. py:method:: get_hd_table()
Returns copy of current dynamic header table.
The following example shows how to inflate deflated header block:
.. code-block:: python
deflater = nghttp2.HDDeflater()
data = deflater.deflate([(b'foo', b'bar'),
(b'baz', b'buz')])
inflater = nghttp2.HDInflater()
hdrs = inflater.inflate(data)
print(hdrs)
.. py:function:: print_hd_table(hdtable)
Convenient function to print *hdtable* to the standard output. The
*hdtable* is the one retrieved by
:py:meth:`HDDeflater.get_hd_table()` or
:py:meth:`HDInflater.get_hd_table()`. This function does not work
if header name/value cannot be decoded using UTF-8 encoding.
In output, ``s=N`` means the entry occupies ``N`` bytes in header
table. If ``r=y``, then the entry is in the reference set.
.. py:data:: DEFAULT_HEADER_TABLE_SIZE
The default header table size, which is 4096 as per HTTP/2
specification.
.. py:data:: DEFLATE_MAX_HEADER_TABLE_SIZE
The default header table size for deflater. The initial value
is 4096.
HTTP/2 servers
--------------
.. note::
We use :py:mod:`asyncio` for HTTP/2 server classes. Therefore,
Python 3.4 or later is required to use these objects. To
explicitly configure nghttp2 build to use Python 3.4, specify the
``PYTHON`` variable to the path to Python 3.4 executable when
invoking configure script like this::
$ ./configure PYTHON=/usr/bin/python3.4
.. py:class:: HTTP2Server(address, RequestHandlerClass, ssl=None)
This class builds on top of the :py:mod:`asyncio` event loop. On
construction, *RequestHandlerClass* must be given, which must be a
subclass of :py:class:`BaseRequestHandler` class.
The *address* must be a tuple of hostname/IP address and port to
bind. If hostname/IP address is ``None``, all interfaces are
assumed.
To enable SSL/TLS, specify instance of :py:class:`ssl.SSLContext`
in *ssl*. Before passing *ssl* to
:py:func:`BaseEventLoop.create_server`, ALPN protocol identifiers
are set using :py:meth:`ssl.SSLContext.set_npn_protocols`.
To disable SSL/TLS, omit *ssl* or specify ``None``.
.. py:method:: serve_forever()
Runs server and processes incoming requests forever.
.. py:class:: BaseRequestHandler(http2, stream_id)
The class is used to handle the single HTTP/2 stream. By default,
it does not nothing. It must be subclassed to handle each event
callback method.
The first callback method invoked is :py:meth:`on_headers()`. It is
called when HEADERS frame, which includes request header fields, is
arrived.
If request has request body, :py:meth:`on_data()` is invoked for
each chunk of received data chunk.
When whole request is received, :py:meth:`on_request_done()` is
invoked.
When stream is closed, :py:meth:`on_close()` is called.
The application can send response using :py:meth:`send_response()`
method. It can be used in :py:meth:`on_headers()`,
:py:meth:`on_data()` or :py:meth:`on_request_done()`.
The application can push resource using :py:meth:`push()` method.
It must be used before :py:meth:`send_response()` call.
A :py:class:`BaseRequestHandler` has the following instance
variables:
.. py:attribute:: client_address
Contains a tuple of the form ``(host, port)`` referring to the
client's address.
.. py:attribute:: stream_id
Stream ID of this stream
.. py:attribute:: scheme
Scheme of the request URI. This is a value of ``:scheme``
header field.
.. py:attribute:: method
Method of this stream. This is a value of ``:method`` header
field.
.. py:attribute:: host
This is a value of ``:authority`` or ``host`` header field.
.. py:attribute:: path
This is a value of ``:path`` header field.
A :py:class:`BaseRequestHandler` has the following methods:
.. py:method:: on_headers()
Called when request HEADERS is arrived. By default, this method
does nothing.
.. py:method:: on_data(data)
Called when a chunk of request body *data* is arrived. This
method will be called multiple times until all data are
received. By default, this method does nothing.
.. py:method:: on_request_done()
Called when whole request was received. By default, this method
does nothing.
.. py:method:: on_close(error_code)
Called when stream is about to close. The *error_code*
indicates the reason of closure. If it is ``0``, the stream is
going to close without error.
.. py:method:: send_response(status=200, headers=None, body=None)
Send response. The *status* is HTTP status code. The *headers*
is additional response headers. The *:status* header field will
be appended by the library. The *body* is the response body.
It could be ``None`` if response body is empty. Or it must be
instance of either ``str``, ``bytes`` or :py:class:`io.IOBase`.
If instance of ``str`` is specified, it will be encoded using
UTF-8.
The *headers* is a list of tuple of the form ``(name,
value)``. The ``name`` and ``value`` can be either byte string
or unicode string. In the latter case, they will be encoded
using UTF-8.
Raises the exception if any error occurs.
.. py:method:: push(path, method='GET', request_headers=None, status=200, headers=None, body=None)
Push a specified resource. The *path* is a path portion of
request URI for this resource. The *method* is a method to
access this resource. The *request_headers* is additional
request headers to access this resource. The ``:scheme``,
``:method``, ``:authority`` and ``:path`` are appended by the
library. The ``:scheme`` and ``:authority`` are inherited from
request header fields of the associated stream.
The *status* is HTTP status code. The *headers* is additional
response headers. The ``:status`` header field is appended by
the library. The *body* is the response body. It could be
``None`` if response body is empty. Or it must be instance of
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
``(name, value)``. The ``name`` and ``value`` can be either byte
string or unicode string. In the latter case, they will be
encoded using UTF-8.
Returns an instance of ``RequestHandlerClass`` specified in
:py:class:`HTTP2Server` constructor for the pushed resource.
Raises the exception if any error occurs.
The following example illustrates :py:class:`HTTP2Server` and
:py:class:`BaseRequestHandler` usage:
.. code-block:: python
#!/usr/bin/env python
import io, ssl
import nghttp2
class Handler(nghttp2.BaseRequestHandler):
def on_headers(self):
self.push(path='/css/style.css',
request_headers = [('content-type', 'text/css')],
status=200,
body='body{margin:0;}')
self.send_response(status=200,
headers = [('content-type', 'text/plain')],
body=io.BytesIO(b'nghttp2-python FTW'))
ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
ctx.options = ssl.OP_ALL | ssl.OP_NO_SSLv2
ctx.load_cert_chain('server.crt', 'server.key')
# give None to ssl to make the server non-SSL/TLS
server = nghttp2.HTTP2Server(('127.0.0.1', 8443), Handler, ssl=ctx)
server.serve_forever()

View File

@@ -1,7 +1,7 @@
Tutorial: HTTP/2.0 client
Tutorial: HTTP/2 client
=========================
In this tutorial, we are going to write very primitive HTTP/2.0
In this tutorial, we are going to write very primitive HTTP/2
client. The complete source code, `libevent-client.c`_, is attached at
the end of this page. It also resides in examples directory in the
archive or repository.
@@ -19,15 +19,13 @@ function ``main()`` and ``run()``, which is not so relevant to nghttp2
library use. The one thing you should look at is setup NPN callback.
The NPN callback is used for the client to select the next application
protocol over the SSL/TLS transport. In this tutorial, we use
`nghttp2_select_next_protocol()` function to select the HTTP/2.0
`nghttp2_select_next_protocol()` function to select the HTTP/2
protocol the library supports::
static int select_next_proto_cb(SSL* ssl,
unsigned char **out, unsigned char *outlen,
const unsigned char *in, unsigned int inlen,
void *arg)
{
if(nghttp2_select_next_protocol(out, outlen, in, inlen) <= 0) {
static int select_next_proto_cb(SSL *ssl _U_, unsigned char **out,
unsigned char *outlen, const unsigned char *in,
unsigned int inlen, void *arg _U_) {
if (nghttp2_select_next_protocol(out, outlen, in, inlen) <= 0) {
errx(1, "Server did not advertise " NGHTTP2_PROTO_VERSION_ID);
}
return SSL_TLSEXT_ERR_OK;
@@ -36,23 +34,23 @@ protocol the library supports::
The callback is set to the SSL_CTX object using
``SSL_CTX_set_next_proto_select_cb()`` function::
static SSL_CTX* create_ssl_ctx(void)
{
static SSL_CTX *create_ssl_ctx(void) {
SSL_CTX *ssl_ctx;
ssl_ctx = SSL_CTX_new(SSLv23_client_method());
if(!ssl_ctx) {
if (!ssl_ctx) {
errx(1, "Could not create SSL/TLS context: %s",
ERR_error_string(ERR_get_error(), NULL));
}
SSL_CTX_set_options(ssl_ctx,
SSL_OP_ALL | SSL_OP_NO_SSLv2 | SSL_OP_NO_COMPRESSION |
SSL_OP_ALL | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 |
SSL_OP_NO_COMPRESSION |
SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION);
SSL_CTX_set_next_proto_select_cb(ssl_ctx, select_next_proto_cb, NULL);
return ssl_ctx;
}
We use ``http2_session_data`` structure to store the data related to
the HTTP/2.0 session::
the HTTP/2 session::
typedef struct {
nghttp2_session *session;
@@ -91,25 +89,22 @@ respectively.
Then we call function ``initiate_connection()`` to start connecting to
the remote server::
static void initiate_connection(struct event_base *evbase,
SSL_CTX *ssl_ctx,
static void initiate_connection(struct event_base *evbase, SSL_CTX *ssl_ctx,
const char *host, uint16_t port,
http2_session_data *session_data)
{
http2_session_data *session_data) {
int rv;
struct bufferevent *bev;
SSL *ssl;
ssl = create_ssl(ssl_ctx);
bev = bufferevent_openssl_socket_new(evbase, -1, ssl,
BUFFEREVENT_SSL_CONNECTING,
BEV_OPT_DEFER_CALLBACKS |
BEV_OPT_CLOSE_ON_FREE);
bev = bufferevent_openssl_socket_new(
evbase, -1, ssl, BUFFEREVENT_SSL_CONNECTING,
BEV_OPT_DEFER_CALLBACKS | BEV_OPT_CLOSE_ON_FREE);
bufferevent_setcb(bev, readcb, writecb, eventcb, session_data);
rv = bufferevent_socket_connect_hostname(bev, session_data->dnsbase,
AF_UNSPEC, host, port);
if(rv != 0) {
if (rv != 0) {
errx(1, "Could not connect to the remote host %s", host);
}
session_data->bev = bev;
@@ -122,10 +117,9 @@ The ``eventcb()`` is invoked by libevent event loop when an event
(e.g., connection has been established, timeout, etc) happens on the
underlying network socket::
static void eventcb(struct bufferevent *bev, short events, void *ptr)
{
http2_session_data *session_data = (http2_session_data*)ptr;
if(events & BEV_EVENT_CONNECTED) {
static void eventcb(struct bufferevent *bev, short events, void *ptr) {
http2_session_data *session_data = (http2_session_data *)ptr;
if (events & BEV_EVENT_CONNECTED) {
int fd = bufferevent_getfd(bev);
int val = 1;
fprintf(stderr, "Connected\n");
@@ -133,16 +127,16 @@ underlying network socket::
initialize_nghttp2_session(session_data);
send_client_connection_header(session_data);
submit_request(session_data);
if(session_send(session_data) != 0) {
if (session_send(session_data) != 0) {
delete_http2_session_data(session_data);
}
return;
}
if(events & BEV_EVENT_EOF) {
if (events & BEV_EVENT_EOF) {
warnx("Disconnected from the remote host");
} else if(events & BEV_EVENT_ERROR) {
} else if (events & BEV_EVENT_ERROR) {
warnx("Network error");
} else if(events & BEV_EVENT_TIMEOUT) {
} else if (events & BEV_EVENT_TIMEOUT) {
warnx("Timeout");
}
delete_http2_session_data(session_data);
@@ -154,18 +148,31 @@ event, we just simply tear down the connection. The
finished successfully. We first initialize nghttp2 session object in
``initialize_nghttp2_session()`` function::
static void initialize_nghttp2_session(http2_session_data *session_data)
{
nghttp2_session_callbacks callbacks = {0};
static void initialize_nghttp2_session(http2_session_data *session_data) {
nghttp2_session_callbacks *callbacks;
callbacks.send_callback = send_callback;
callbacks.before_frame_send_callback = before_frame_send_callback;
callbacks.on_frame_recv_callback = on_frame_recv_callback;
callbacks.on_data_chunk_recv_callback = on_data_chunk_recv_callback;
callbacks.on_stream_close_callback = on_stream_close_callback;
callbacks.on_header_callback = on_header_callback;
callbacks.on_begin_headers_callback = on_begin_headers_callback;
nghttp2_session_client_new(&session_data->session, &callbacks, session_data);
nghttp2_session_callbacks_new(&callbacks);
nghttp2_session_callbacks_set_send_callback(callbacks, send_callback);
nghttp2_session_callbacks_set_on_frame_recv_callback(callbacks,
on_frame_recv_callback);
nghttp2_session_callbacks_set_on_data_chunk_recv_callback(
callbacks, on_data_chunk_recv_callback);
nghttp2_session_callbacks_set_on_stream_close_callback(
callbacks, on_stream_close_callback);
nghttp2_session_callbacks_set_on_header_callback(callbacks,
on_header_callback);
nghttp2_session_callbacks_set_on_begin_headers_callback(
callbacks, on_begin_headers_callback);
nghttp2_session_client_new(&session_data->session, callbacks, session_data);
nghttp2_session_callbacks_del(callbacks);
}
Since we are creating client, we use `nghttp2_session_client_new()` to
@@ -176,25 +183,22 @@ The `delete_http2_session_data()` destroys ``session_data`` and frees
its bufferevent, so it closes underlying connection as well. It also
calls `nghttp2_session_del()` to delete nghttp2 session object.
We begin HTTP/2.0 communication by sending client connection header,
We begin HTTP/2 communication by sending client connection preface,
which is 24 bytes magic byte sequence
(:macro:`NGHTTP2_CLIENT_CONNECTION_HEADER`) followed by SETTINGS
frame. The transmission of client connection header is done in
(:macro:`NGHTTP2_CLIENT_CONNECTION_PREFACE`) and SETTINGS frame. The
transmission of client connection header is done in
``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) {
nghttp2_settings_entry iv[1] = {
{ NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS, 100 }
};
{NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS, 100}};
int rv;
bufferevent_write(session_data->bev,
NGHTTP2_CLIENT_CONNECTION_HEADER,
NGHTTP2_CLIENT_CONNECTION_HEADER_LEN);
rv = nghttp2_submit_settings(session_data->session, NGHTTP2_FLAG_NONE,
iv, ARRLEN(iv));
if(rv != 0) {
bufferevent_write(session_data->bev, NGHTTP2_CLIENT_CONNECTION_PREFACE,
NGHTTP2_CLIENT_CONNECTION_PREFACE_LEN);
rv = nghttp2_submit_settings(session_data->session, NGHTTP2_FLAG_NONE, iv,
ARRLEN(iv));
if (rv != 0) {
errx(1, "Could not submit SETTINGS: %s", nghttp2_strerror(rv));
}
}
@@ -211,26 +215,26 @@ used, which is described about later.
After the transmission of client connection header, we enqueue HTTP
request in ``submit_request()`` function::
static void submit_request(http2_session_data *session_data)
{
int rv;
static void submit_request(http2_session_data *session_data) {
int32_t stream_id;
http2_stream_data *stream_data = session_data->stream_data;
const char *uri = stream_data->uri;
const struct http_parser_url *u = stream_data->u;
nghttp2_nv hdrs[] = {
MAKE_NV2(":method", "GET"),
MAKE_NV(":scheme",
&uri[u->field_data[UF_SCHEMA].off], u->field_data[UF_SCHEMA].len),
MAKE_NV(":scheme", &uri[u->field_data[UF_SCHEMA].off],
u->field_data[UF_SCHEMA].len),
MAKE_NV(":authority", stream_data->authority, stream_data->authoritylen),
MAKE_NV(":path", stream_data->path, stream_data->pathlen)
};
MAKE_NV(":path", stream_data->path, stream_data->pathlen)};
fprintf(stderr, "Request headers:\n");
print_headers(stderr, hdrs, ARRLEN(hdrs));
rv = nghttp2_submit_request(session_data->session, NGHTTP2_PRI_DEFAULT,
hdrs, ARRLEN(hdrs), NULL, stream_data);
if(rv != 0) {
errx(1, "Could not submit HTTP request: %s", nghttp2_strerror(rv));
stream_id = nghttp2_submit_request(session_data->session, NULL, hdrs,
ARRLEN(hdrs), NULL, stream_data);
if (stream_id < 0) {
errx(1, "Could not submit HTTP request: %s", nghttp2_strerror(stream_id));
}
stream_data->stream_id = stream_id;
}
We build HTTP request header fields in ``hdrs`` which is an array of
@@ -239,25 +243,31 @@ We build HTTP request header fields in ``hdrs`` which is an array of
we use `nghttp2_submit_request()` function. The `stream_data` is
passed in *stream_user_data* parameter. It is used in nghttp2
callbacks which we'll describe about later.
`nghttp2_submit_request()` returns the newly assigned stream ID for
this request.
The next bufferevent callback is ``readcb()``, which is invoked when
data is available to read in the bufferevent input buffer::
static void readcb(struct bufferevent *bev, void *ptr)
{
http2_session_data *session_data = (http2_session_data*)ptr;
int rv;
static void readcb(struct bufferevent *bev, void *ptr) {
http2_session_data *session_data = (http2_session_data *)ptr;
ssize_t readlen;
struct evbuffer *input = bufferevent_get_input(bev);
size_t datalen = evbuffer_get_length(input);
unsigned char *data = evbuffer_pullup(input, -1);
rv = nghttp2_session_mem_recv(session_data->session, data, datalen);
if(rv < 0) {
warnx("Fatal error: %s", nghttp2_strerror(rv));
readlen = nghttp2_session_mem_recv(session_data->session, data, datalen);
if (readlen < 0) {
warnx("Fatal error: %s", nghttp2_strerror((int)readlen));
delete_http2_session_data(session_data);
return;
}
evbuffer_drain(input, rv);
if(session_send(session_data) != 0) {
if (evbuffer_drain(input, readlen) != 0) {
warnx("Fatal error: evbuffer_drain failed");
delete_http2_session_data(session_data);
return;
}
if (session_send(session_data) != 0) {
delete_http2_session_data(session_data);
return;
}
@@ -270,12 +280,11 @@ invoke nghttp2 callbacks and also queue frames. Since there may be
pending frames, we call ``session_send()`` function to send those
frames. The ``session_send()`` function is defined as follows::
static int session_send(http2_session_data *session_data)
{
static int session_send(http2_session_data *session_data) {
int rv;
rv = nghttp2_session_send(session_data->session);
if(rv != 0) {
if (rv != 0) {
warnx("Fatal error: %s", nghttp2_strerror(rv));
return -1;
}
@@ -283,17 +292,13 @@ frames. The ``session_send()`` function is defined as follows::
}
The `nghttp2_session_send()` function serializes the frame into wire
format and call :member:`nghttp2_session_callbacks.send_callback` with
it. We set ``send_callback()`` function to
:member:`nghttp2_session_callbacks.send_callback` in
``initialize_nghttp2_session()`` function described earlier. It is
defined as follows::
format and call ``send_callback()`` function of type
:type:`nghttp2_send_callback`. The ``send_callback()`` is defined as
follows::
static ssize_t send_callback(nghttp2_session *session,
const uint8_t *data, size_t length,
int flags, void *user_data)
{
http2_session_data *session_data = (http2_session_data*)user_data;
static ssize_t send_callback(nghttp2_session *session _U_, const uint8_t *data,
size_t length, int flags _U_, void *user_data) {
http2_session_data *session_data = (http2_session_data *)user_data;
struct bufferevent *bev = session_data->bev;
bufferevent_write(bev, data, length);
return length;
@@ -303,23 +308,21 @@ Since we use bufferevent to abstract network I/O, we just write the
data to the bufferevent object. Note that `nghttp2_session_send()`
continues to write all frames queued so far. If we were writing the
data to the non-blocking socket directly using ``write()`` system call
in the :member:`nghttp2_session_callbacks.send_callback`, we will
surely get ``EAGAIN`` or ``EWOULDBLOCK`` since the socket has limited
send buffer. If that happens, we can return
:macro:`NGHTTP2_ERR_WOULDBLOCK` to signal the nghttp2 library to stop
sending further data. But writing to the bufferevent, we have to
regulate the amount data to be buffered by ourselves to avoid possible
huge memory consumption. In this example client, we do not limit
anything. To see how to regulate the amount of buffered data, see the
``send_callback()`` in the server tutorial.
in the ``send_callback()``, we will surely get ``EAGAIN`` or
``EWOULDBLOCK`` since the socket has limited send buffer. If that
happens, we can return :macro:`NGHTTP2_ERR_WOULDBLOCK` to signal the
nghttp2 library to stop sending further data. But writing to the
bufferevent, we have to regulate the amount data to be buffered by
ourselves to avoid possible huge memory consumption. In this example
client, we do not limit anything. To see how to regulate the amount of
buffered data, see the ``send_callback()`` in the server tutorial.
The third bufferevent callback is ``writecb()``, which is invoked when
all data written in the bufferevent output buffer have been sent::
static void writecb(struct bufferevent *bev, void *ptr)
{
http2_session_data *session_data = (http2_session_data*)ptr;
if(nghttp2_session_want_read(session_data->session) == 0 &&
static void writecb(struct bufferevent *bev _U_, void *ptr) {
http2_session_data *session_data = (http2_session_data *)ptr;
if (nghttp2_session_want_read(session_data->session) == 0 &&
nghttp2_session_want_write(session_data->session) == 0 &&
evbuffer_get_length(bufferevent_get_output(session_data->bev)) == 0) {
delete_http2_session_data(session_data);
@@ -344,61 +347,18 @@ We have already described about nghttp2 callback ``send_callback()``.
Let's describe remaining nghttp2 callbacks we setup in
``initialize_nghttp2_setup()`` function.
The `before_frame_send_callback()` function is invoked when a frame is
about to be sent::
static int before_frame_send_callback
(nghttp2_session *session, const nghttp2_frame *frame, void *user_data)
{
http2_session_data *session_data = (http2_session_data*)user_data;
http2_stream_data *stream_data;
if(frame->hd.type == NGHTTP2_HEADERS &&
frame->headers.cat == NGHTTP2_HCAT_REQUEST) {
stream_data =
(http2_stream_data*)nghttp2_session_get_stream_user_data
(session, frame->hd.stream_id);
if(stream_data == session_data->stream_data) {
stream_data->stream_id = frame->hd.stream_id;
}
}
return 0;
}
Remember that we have not get stream ID when we submit HTTP request
using `nghttp2_submit_request()`. Since nghttp2 library reorders the
request based on priority and stream ID must be monotonically
increased, the stream ID is not assigned just before transmission.
The one of the purpose of this callback is get the stream ID assigned
to the frame. First we check that the frame is HEADERS frame. Since
HEADERS has several meanings in HTTP/2.0, we check that it is request
HEADERS (which means that the first HEADERS frame to create a stream).
The assigned stream ID is ``frame->hd.stream_id``. Recall that we
passed ``stream_data`` in the *stream_user_data* parameter of
`nghttp2_submit_request()` function. We can get it using
`nghttp2_session_get_stream_user_data()` function. To really sure that
this HEADERS frame is the request HEADERS we have queued, we check
that ``session_data->stream_data`` and ``stream_data`` returned from
`nghttp2_session_get_stream_user_data()` are pointing the same
location. In this example program, we just only uses 1 stream, it is
unnecessary to compare them, but real applications surely deal with
multiple streams, and *stream_user_data* is very handy to identify
which HEADERS we are seeing in the callback. Therefore we just show
how to use it here.
Each request header name/value pair is emitted via
``on_header_callback`` function::
static int on_header_callback(nghttp2_session *session,
const nghttp2_frame *frame,
const uint8_t *name, size_t namelen,
const uint8_t *value, size_t valuelen,
void *user_data)
{
http2_session_data *session_data = (http2_session_data*)user_data;
switch(frame->hd.type) {
static int on_header_callback(nghttp2_session *session _U_,
const nghttp2_frame *frame, const uint8_t *name,
size_t namelen, const uint8_t *value,
size_t valuelen, uint8_t flags _U_,
void *user_data) {
http2_session_data *session_data = (http2_session_data *)user_data;
switch (frame->hd.type) {
case NGHTTP2_HEADERS:
if(frame->headers.cat == NGHTTP2_HCAT_RESPONSE &&
if (frame->headers.cat == NGHTTP2_HCAT_RESPONSE &&
session_data->stream_data->stream_id == frame->hd.stream_id) {
/* Print response headers for the initiated request. */
print_header(stderr, name, namelen, value, valuelen);
@@ -408,18 +368,17 @@ Each request header name/value pair is emitted via
return 0;
}
In this turotial, we just print the name/value pair.
In this tutorial, we just print the name/value pair.
After all name/value pairs are emitted for a frame,
``on_frame_recv_callback`` function is called::
static int on_frame_recv_callback(nghttp2_session *session,
const nghttp2_frame *frame, void *user_data)
{
http2_session_data *session_data = (http2_session_data*)user_data;
switch(frame->hd.type) {
static int on_frame_recv_callback(nghttp2_session *session _U_,
const nghttp2_frame *frame, void *user_data) {
http2_session_data *session_data = (http2_session_data *)user_data;
switch (frame->hd.type) {
case NGHTTP2_HEADERS:
if(frame->headers.cat == NGHTTP2_HCAT_RESPONSE &&
if (frame->headers.cat == NGHTTP2_HCAT_RESPONSE &&
session_data->stream_data->stream_id == frame->hd.stream_id) {
fprintf(stderr, "All headers received\n");
}
@@ -436,13 +395,12 @@ its stream ID.
The ``on_data_chunk_recv_callback()`` function is invoked when a chunk
of data is received from the remote peer::
static int on_data_chunk_recv_callback(nghttp2_session *session, uint8_t flags,
int32_t stream_id,
static int on_data_chunk_recv_callback(nghttp2_session *session _U_,
uint8_t flags _U_, int32_t stream_id,
const uint8_t *data, size_t len,
void *user_data)
{
http2_session_data *session_data = (http2_session_data*)user_data;
if(session_data->stream_data->stream_id == stream_id) {
void *user_data) {
http2_session_data *session_data = (http2_session_data *)user_data;
if (session_data->stream_data->stream_id == stream_id) {
fwrite(data, len, 1, stdout);
}
return 0;
@@ -456,19 +414,17 @@ some binary data.
The ``on_stream_close_callback()`` function is invoked when the stream
is about to close::
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,
nghttp2_error_code error_code,
void *user_data)
{
http2_session_data *session_data = (http2_session_data*)user_data;
void *user_data) {
http2_session_data *session_data = (http2_session_data *)user_data;
int rv;
if(session_data->stream_data->stream_id == stream_id) {
fprintf(stderr, "Stream %d closed with error_code=%d\n",
stream_id, error_code);
if (session_data->stream_data->stream_id == stream_id) {
fprintf(stderr, "Stream %d closed with error_code=%d\n", stream_id,
error_code);
rv = nghttp2_session_terminate_session(session, NGHTTP2_NO_ERROR);
if(rv != 0) {
if (rv != 0) {
return NGHTTP2_ERR_CALLBACK_FAILURE;
}
}
@@ -479,6 +435,6 @@ If the stream ID matches the one we initiated, it means that its
stream is going to be closed. Since we have finished to get the
resource we want (or the stream was reset by RST_STREAM from the
remote peer), we call `nghttp2_session_terminate_session()` to
commencing the closure of the HTTP/2.0 session gracefully. If you have
commencing the closure of the HTTP/2 session gracefully. If you have
some data associated for the stream to be closed, you may delete it
here.

View File

@@ -0,0 +1,118 @@
Tutorial: HPACK API
===================
In this tutorial, we describe basic use of HPACK API in nghttp2
library. We briefly describe APIs for deflating and inflating header
fields. The example of using these APIs are presented as complete
source code `deflate.c`_.
Deflating (encoding) headers
----------------------------
First we need to initialize :type:`nghttp2_hd_deflater` object using
`nghttp2_hd_deflate_new()` function::
int nghttp2_hd_deflate_new(nghttp2_hd_deflater **deflater_ptr,
size_t deflate_hd_table_bufsize_max);
This function allocates :type:`nghttp2_hd_deflater` object and
initializes it and assigns its pointer to ``*deflater_ptr`` passed by
parameter. The *deflate_hd_table_bufsize_max* is the upper bound of
header table size the deflater will use. This will limit the memory
usage in deflater object for dynamic header table. If you doubt, just
specify 4096 here, which is the default upper bound of dynamic header
table buffer size.
To encode header fields, `nghttp2_hd_deflate_hd()` function::
ssize_t nghttp2_hd_deflate_hd(nghttp2_hd_deflater *deflater,
uint8_t *buf, size_t buflen,
const nghttp2_nv *nva, size_t nvlen);
The *deflater* is the deflater object initialized by
`nghttp2_hd_deflate_new()` function described above. The *buf* is a
pointer to buffer to store encoded byte string. The *buflen* is
capacity of *buf*. The *nva* is a pointer to :type:`nghttp2_nv`,
which is an array of header fields to deflate. The *nvlen* is the
number of header fields which *nva* contains.
It is important to initialize and assign all members of
:type:`nghttp2_nv`. If a header field should not be inserted in
dynamic header table for a security reason, set
:macro:`NGHTTP2_NV_FLAG_NO_INDEX` flag in :member:`nghttp2_nv.flags`.
`nghttp2_hd_deflate_hd()` processes all headers given in *nva*. The
*nva* must include all request or response header fields to be sent in
one HEADERS (or optionally following (multiple) CONTINUATION
frame(s)). The *buf* must have enough space to store the encoded
result. Otherwise, the function will fail. To estimate the upper
bound of encoded result, use `nghttp2_hd_deflate_bound()` function::
size_t nghttp2_hd_deflate_bound(nghttp2_hd_deflater *deflater,
const nghttp2_nv *nva, size_t nvlen);
Pass this function with the same paramters *deflater*, *nva* and
*nvlen* which will be passed to `nghttp2_hd_deflate_hd()`.
The subsequent call of `nghttp2_hd_deflate_hd()` will use current
encoder state and perform differential encoding which is the
fundamental compression gain for HPACK.
Once `nghttp2_hd_deflate_hd()` fails, it cannot be undone and its
further call with the same deflater object shall fail. So it is very
important to use `nghttp2_hd_deflate_bound()` to know the required
size of buffer.
To delete :type:`nghttp2_hd_deflater` object, use `nghttp2_hd_deflate_del()`
function.
Inflating (decoding) headers
----------------------------
We use :type:`nghttp2_hd_inflater` object to inflate compressed header
data. To initialize the object, use `nghttp2_hd_inflate_new()`::
int nghttp2_hd_inflate_new(nghttp2_hd_inflater **inflater_ptr);
To inflate header data, use `nghttp2_hd_inflate_hd()` function::
ssize_t nghttp2_hd_inflate_hd(nghttp2_hd_inflater *inflater,
nghttp2_nv *nv_out, int *inflate_flags,
uint8_t *in, size_t inlen, int in_final);
The *inflater* is the inflater object initialized above. The *nv_out*
is a pointer to :type:`nghttp2_nv` to store the result. The *in* is a
pointer to input data and *inlen* is its length. The caller is not
required to specify whole deflated header data to *in* at once. It
can call this function multiple times for portion of the data in
streaming way. If *in_final* is nonzero, it tells the function that
the passed data is the final sequence of deflated header data. The
*inflate_flags* is output parameter and successful call of this
function stores a set of flags in it. It will be described later.
This function returns when each header field is inflated. When this
happens, the function sets :macro:`NGHTTP2_HD_INFLATE_EMIT` flag to
*inflate_flag* parameter and header field is stored in *nv_out*. The
return value indicates the number of data read from *in* to processed
so far. It may be less than *inlen*. The caller should call the
function repeatedly until all data are processed by adjusting *in* and
*inlen* with the processed bytes.
If *in_final* is nonzero and all given data was processed, the
function sets :macro:`NGHTTP2_HD_INFLATE_FINAL` flag to
*inflate_flag*. If the caller sees this flag set, call
`nghttp2_hd_inflate_end_headers()` function.
If *in_final* is zero and :macro:`NGHTTP2_HD_INFLATE_EMIT` flag is not
set, it indicates that all given data was processed. The caller is
required to pass subsequent data.
It is important to note that the function may produce one or more
header fields even if *inlen* is 0 when *in_final* is nonzero, due to
differential encoding.
The example use of `nghttp2_hd_inflate_hd()` is shown in
`inflate_header_block()` function in `deflate.c`_.
To delete :type:`nghttp2_hd_inflater` object, use `nghttp2_hd_inflate_del()`
function.

View File

@@ -1,47 +1,45 @@
Tutorial: HTTP/2.0 server
Tutorial: HTTP/2 server
=========================
In this tutorial, we are going to write single-threaded, event-based
HTTP/2.0 web server, which supports HTTPS only. It can handle
concurrent multiple requests, but only GET method is supported. The
HTTP/2 web server, which supports HTTPS only. It can handle
concurrent multiple requests, but only the GET method is supported. The
complete source code, `libevent-server.c`_, is attached at the end of
this page. It also resides in examples directory in the archive or
repository.
This simple server takes 3 arguments, a port number to listen to, a
path to SSL/TLS private key file and certificate file. Its synopsis
is like this::
This simple server takes 3 arguments, a port number to listen to, a path to
your SSL/TLS private key file and a path to your certificate file. Its
synopsis is like this::
$ libevent-server PORT /path/to/server.key /path/to/server.crt
We use libevent in this tutorial to handle networking I/O. Please
note that nghttp2 itself does not depend on libevent.
First we do some setup routine for libevent and OpenSSL library in
function ``main()`` and ``run()``, which is not so relevant to nghttp2
library use. The one thing you should look at is setup NPN callback.
The NPN callback is used for the server to advertise the application
protocols the server supports to a client. In this example program,
when creating ``SSL_CTX`` object, we stores the application protocol
name in the wire format of NPN in statically allocated buffer. This is
safe because we only create 1 ``SSL_CTX`` object in the entire program
life time::
First we create a setup routine for libevent and OpenSSL in the functions
``main()`` and ``run()``. One thing in there you should look at, is the setup
of the NPN callback. The NPN callback is used for the server to advertise
which application protocols the server supports to a client. In this example
program, when creating ``SSL_CTX`` object, we store the application protocol
name in the wire format of NPN in a statically allocated buffer. This is safe
because we only create one ``SSL_CTX`` object in the program's entire life
time::
static unsigned char next_proto_list[256];
static size_t next_proto_list_len;
static int next_proto_cb(SSL *s, const unsigned char **data, unsigned int *len,
void *arg)
{
static int next_proto_cb(SSL *s _U_, const unsigned char **data,
unsigned int *len, void *arg _U_) {
*data = next_proto_list;
*len = next_proto_list_len;
*len = (unsigned int)next_proto_list_len;
return SSL_TLSEXT_ERR_OK;
}
static SSL_CTX* create_ssl_ctx(const char *key_file, const char *cert_file)
{
static SSL_CTX *create_ssl_ctx(const char *key_file, const char *cert_file) {
SSL_CTX *ssl_ctx;
EC_KEY *ecdh;
ssl_ctx = SSL_CTX_new(SSLv23_server_method());
...
@@ -55,25 +53,25 @@ life time::
return ssl_ctx;
}
The wire format of NPN is a sequence of length prefixed string. The
exactly one byte is used to specify the length of each protocol
identifier. In this tutorial, we advertise the HTTP/2.0 protocol the
nghttp2 library supports. The nghttp2 library exports its identifier
in :macro:`NGHTTP2_PROTO_VERSION_ID`. The ``next_proto_cb()`` function
is the server-side NPN callback. In OpenSSL implementation, we just
assign the pointer to the NPN buffers we filled earlier. The NPN
callback function is set to ``SSL_CTX`` object using
The wire format of NPN is a sequence of length prefixed string. Exactly one
byte is used to specify the length of each protocol identifier. In this
tutorial, we advertise the specific HTTP/2 protocol version the current
nghttp2 library supports. The nghttp2 library exports its identifier in
:macro:`NGHTTP2_PROTO_VERSION_ID`. The ``next_proto_cb()`` function is the
server-side NPN callback. In the OpenSSL implementation, we just assign the
pointer to the NPN buffers we filled in earlier. The NPN callback function is
set to the ``SSL_CTX`` object using
``SSL_CTX_set_next_protos_advertised_cb()``.
We use ``app_content`` structure to store the application-wide data::
We use the ``app_content`` structure to store application-wide data::
struct app_context {
SSL_CTX *ssl_ctx;
struct event_base *evbase;
};
We use ``http2_session_data`` structure to store the session-level
(which corresponds to 1 HTTP/2.0 connection) data::
We use the ``http2_session_data`` structure to store session-level
(which corresponds to one HTTP/2 connection) data::
typedef struct http2_session_data {
struct http2_stream_data root;
@@ -81,11 +79,9 @@ We use ``http2_session_data`` structure to store the session-level
app_context *app_ctx;
nghttp2_session *session;
char *client_addr;
size_t handshake_leftlen;
} http2_session_data;
We use ``http2_stream_data`` structure to store the stream-level
data::
We use the ``http2_stream_data`` structure to store stream-level data::
typedef struct http2_stream_data {
struct http2_stream_data *prev, *next;
@@ -94,26 +90,21 @@ data::
int fd;
} http2_stream_data;
1 HTTP/2.0 session can have multiple streams. We manage these
multiple streams by intrusive doubly linked list to add and remove the
object in O(1). The first element of this list is pointed by the
``root->next`` in ``http2_session_data``. Initially, ``root->next``
is ``NULL``. The ``handshake_leftlen`` member of
``http2_session_data`` is used to track the number of bytes remaining
when receiving first 24 bytes magic value
(:macro:`NGHTTP2_CLIENT_CONNECTION_HEADER`) from the client. We use
libevent's bufferevent structure to perform network I/O. Notice that
bufferevent object is in ``http2_session_data`` and not in
``http2_stream_data``. This is because ``http2_stream_data`` is just a
logical stream multiplexed over the single connection managed by
bufferevent in ``http2_session_data``.
A single HTTP/2 session can have multiple streams. We manage these
multiple streams with a doubly linked list. The first element of this
list is pointed to by the ``root->next`` in ``http2_session_data``.
Initially, ``root->next`` is ``NULL``. We use libevent's bufferevent
structure to perform network I/O. Note that the bufferevent object is
kept in ``http2_session_data`` and not in ``http2_stream_data``. This
is because ``http2_stream_data`` is just a logical stream multiplexed
over the single connection managed by bufferevent in
``http2_session_data``.
We first create listener object to accept incoming connections.
We use libevent's ``struct evconnlistener`` for this purpose::
We first create a listener object to accept incoming connections. We use
libevent's ``struct evconnlistener`` for this purpose::
static void start_listen(struct event_base *evbase, const char *service,
app_context *app_ctx)
{
app_context *app_ctx) {
int rv;
struct addrinfo hints;
struct addrinfo *res, *rp;
@@ -124,196 +115,188 @@ We use libevent's ``struct evconnlistener`` for this purpose::
hints.ai_flags = AI_PASSIVE;
#ifdef AI_ADDRCONFIG
hints.ai_flags |= AI_ADDRCONFIG;
#endif // AI_ADDRCONFIG
#endif /* AI_ADDRCONFIG */
rv = getaddrinfo(NULL, service, &hints, &res);
if(rv != 0) {
if (rv != 0) {
errx(1, NULL);
}
for(rp = res; rp; rp = rp->ai_next) {
for (rp = res; rp; rp = rp->ai_next) {
struct evconnlistener *listener;
listener = evconnlistener_new_bind(evbase, acceptcb, app_ctx,
LEV_OPT_CLOSE_ON_FREE |
LEV_OPT_REUSEABLE, -1,
rp->ai_addr, rp->ai_addrlen);
if(listener) {
listener = evconnlistener_new_bind(
evbase, acceptcb, app_ctx, LEV_OPT_CLOSE_ON_FREE | LEV_OPT_REUSEABLE,
16, rp->ai_addr, rp->ai_addrlen);
if (listener) {
freeaddrinfo(res);
return;
}
}
errx(1, "Could not start listener");
}
We specify ``acceptcb`` callback which is called when a new connection
is accepted::
We specify the ``acceptcb`` callback which is called when a new connection is
accepted::
static void acceptcb(struct evconnlistener *listener, int fd,
struct sockaddr *addr, int addrlen, void *arg)
{
app_context *app_ctx = (app_context*)arg;
static void acceptcb(struct evconnlistener *listener _U_, int fd,
struct sockaddr *addr, int addrlen, void *arg) {
app_context *app_ctx = (app_context *)arg;
http2_session_data *session_data;
session_data = create_http2_session_data(app_ctx, fd, addr, addrlen);
bufferevent_setcb(session_data->bev, handshake_readcb, NULL, eventcb,
session_data);
bufferevent_setcb(session_data->bev, readcb, writecb, eventcb, session_data);
}
Here we create ``http2_session_data`` object. The bufferevent for this
connection is also initialized at this time. We specify 2 callbacks
for the bufferevent: ``handshake_readcb`` and ``eventcb``.
Here we create the ``http2_session_data`` object. The bufferevent for
this connection is also initialized at this time. We specify three
callbacks for the bufferevent: ``readcb``, ``writecb`` and
``eventcb``.
The ``eventcb()`` is invoked by libevent event loop when an event
The ``eventcb()`` callback is invoked by the libevent event loop when an event
(e.g., connection has been established, timeout, etc) happens on the
underlying network socket::
static void eventcb(struct bufferevent *bev, short events, void *ptr)
{
http2_session_data *session_data = (http2_session_data*)ptr;
if(events & BEV_EVENT_CONNECTED) {
static void eventcb(struct bufferevent *bev _U_, short events, void *ptr) {
http2_session_data *session_data = (http2_session_data *)ptr;
if (events & BEV_EVENT_CONNECTED) {
fprintf(stderr, "%s connected\n", session_data->client_addr);
initialize_nghttp2_session(session_data);
if (send_server_connection_header(session_data) != 0) {
delete_http2_session_data(session_data);
return;
}
if(events & BEV_EVENT_EOF) {
return;
}
if (events & BEV_EVENT_EOF) {
fprintf(stderr, "%s EOF\n", session_data->client_addr);
} else if(events & BEV_EVENT_ERROR) {
} else if (events & BEV_EVENT_ERROR) {
fprintf(stderr, "%s network error\n", session_data->client_addr);
} else if(events & BEV_EVENT_TIMEOUT) {
} else if (events & BEV_EVENT_TIMEOUT) {
fprintf(stderr, "%s timeout\n", session_data->client_addr);
}
delete_http2_session_data(session_data);
}
For ``BEV_EVENT_EOF``, ``BEV_EVENT_ERROR`` and ``BEV_EVENT_TIMEOUT``
event, we just simply tear down the connection. The
``delete_http2_session_data()`` function destroys
``http2_session_data`` object and thus its bufferevent member. As a
result, the underlying connection is closed. The
For the ``BEV_EVENT_EOF``, ``BEV_EVENT_ERROR`` and
``BEV_EVENT_TIMEOUT`` events, we just simply tear down the connection.
The ``delete_http2_session_data()`` function destroys the
``http2_session_data`` object and thus also its bufferevent member.
As a result, the underlying connection is closed. The
``BEV_EVENT_CONNECTED`` event is invoked when SSL/TLS handshake is
finished successfully.
finished successfully. Now we are ready to start the HTTP/2
communication.
The ``handshake_readcb()`` is a callback function to handle 24 bytes
magic byte string from a client, since nghttp2 library does not handle
it::
static void handshake_readcb(struct bufferevent *bev, void *ptr)
{
http2_session_data *session_data = (http2_session_data*)ptr;
uint8_t data[24];
struct evbuffer *input = bufferevent_get_input(session_data->bev);
int readlen = evbuffer_remove(input, data, session_data->handshake_leftlen);
const char *conhead = NGHTTP2_CLIENT_CONNECTION_HEADER;
if(memcmp(conhead + NGHTTP2_CLIENT_CONNECTION_HEADER_LEN
- session_data->handshake_leftlen, data, readlen) != 0) {
delete_http2_session_data(session_data);
return;
}
session_data->handshake_leftlen -= readlen;
if(session_data->handshake_leftlen == 0) {
bufferevent_setcb(session_data->bev, readcb, writecb, eventcb, ptr);
/* Process pending data in buffer since they are not notified
further */
initialize_nghttp2_session(session_data);
if(send_server_connection_header(session_data) != 0) {
delete_http2_session_data(session_data);
return;
}
if(session_recv(session_data) != 0) {
delete_http2_session_data(session_data);
return;
}
}
}
We check that the received byte string matches
:macro:`NGHTTP2_CLIENT_CONNECTION_HEADER`. When they match, the
connection state is ready for starting HTTP/2.0 communication. First
we change the callback functions for the bufferevent object. We use
same ``eventcb`` as before. But we specify new ``readcb`` and
``writecb`` function to handle HTTP/2.0 communication. We describe
these 2 functions later.
We initialize nghttp2 session object which is done in
We initialize a nghttp2 session object which is done in
``initialize_nghttp2_session()``::
static void initialize_nghttp2_session(http2_session_data *session_data)
{
nghttp2_session_callbacks callbacks = {0};
static void initialize_nghttp2_session(http2_session_data *session_data) {
nghttp2_option *option;
nghttp2_session_callbacks *callbacks;
callbacks.send_callback = send_callback;
callbacks.on_frame_recv_callback = on_frame_recv_callback;
callbacks.on_stream_close_callback = on_stream_close_callback;
callbacks.on_header_callback = on_header_callback;
callbacks.on_begin_headers_callback = on_begin_headers_callback;
nghttp2_session_server_new(&session_data->session, &callbacks, session_data);
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_set_send_callback(callbacks, send_callback);
nghttp2_session_callbacks_set_on_frame_recv_callback(callbacks,
on_frame_recv_callback);
nghttp2_session_callbacks_set_on_stream_close_callback(
callbacks, on_stream_close_callback);
nghttp2_session_callbacks_set_on_header_callback(callbacks,
on_header_callback);
nghttp2_session_callbacks_set_on_begin_headers_callback(
callbacks, on_begin_headers_callback);
nghttp2_session_server_new2(&session_data->session, callbacks, session_data,
option);
nghttp2_session_callbacks_del(callbacks);
nghttp2_option_del(option);
}
Since we are creating server, nghttp2 session object is created using
`nghttp2_session_server_new()` function. We registers 5 callbacks to
nghttp2 session object. We'll talk about these callbacks later.
Since we are creating a server and uses options, the nghttp2 session
object is created using `nghttp2_session_server_new2()` function. We
registers five callbacks for nghttp2 session object. We'll talk about
these callbacks later. Our server only speaks HTTP/2. In this case,
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 nghttp2 session object, we are going to send
server connection header in ``send_server_connection_header()``::
After initialization of the nghttp2 session object, we are going to send
a server connection header in ``send_server_connection_header()``::
static int send_server_connection_header(http2_session_data *session_data)
{
static int send_server_connection_header(http2_session_data *session_data) {
nghttp2_settings_entry iv[1] = {
{ NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS, 100 }
};
{NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS, 100}};
int rv;
rv = nghttp2_submit_settings(session_data->session, NGHTTP2_FLAG_NONE,
iv, ARRLEN(iv));
if(rv != 0) {
rv = nghttp2_submit_settings(session_data->session, NGHTTP2_FLAG_NONE, iv,
ARRLEN(iv));
if (rv != 0) {
warnx("Fatal error: %s", nghttp2_strerror(rv));
return -1;
}
return 0;
}
The server connection header is SETTINGS frame. We specify
SETTINGS_MAX_CONCURRENT_STREAMS to 100 in SETTINGS frame. To queue
The server connection header is a SETTINGS frame. We specify
SETTINGS_MAX_CONCURRENT_STREAMS to 100 in the SETTINGS frame. To queue
the SETTINGS frame for the transmission, we use
`nghttp2_submit_settings()`. Note that `nghttp2_submit_settings()`
function only queues the frame and not actually send it. All
``nghttp2_submit_*()`` family functions have this property. To
actually send the frame, `nghttp2_session_send()` is used, which is
described about later.
function only queues the frame and it does not actually send it. All
functions in the ``nghttp2_submit_*()`` family have this property. To
actually send the frame, `nghttp2_session_send()` should be used, as
described later.
Since bufferevent may buffer more than first 24 bytes from the client,
we have to process them here since libevent won't invoke callback
functions for these pending data. To process received data, we call
Since bufferevent may buffer more than the first 24 bytes from the client, we
have to process them here since libevent won't invoke callback functions for
this pending data. To process the received data, we call the
``session_recv()`` function::
static int session_recv(http2_session_data *session_data)
{
int rv;
static int session_recv(http2_session_data *session_data) {
ssize_t readlen;
struct evbuffer *input = bufferevent_get_input(session_data->bev);
size_t datalen = evbuffer_get_length(input);
unsigned char *data = evbuffer_pullup(input, -1);
rv = nghttp2_session_mem_recv(session_data->session, data, datalen);
if(rv < 0) {
warnx("Fatal error: %s", nghttp2_strerror(rv));
readlen = nghttp2_session_mem_recv(session_data->session, data, datalen);
if (readlen < 0) {
warnx("Fatal error: %s", nghttp2_strerror((int)readlen));
return -1;
}
evbuffer_drain(input, rv);
if(session_send(session_data) != 0) {
if (evbuffer_drain(input, readlen) != 0) {
warnx("Fatal error: evbuffer_drain failed");
return -1;
}
if (session_send(session_data) != 0) {
return -1;
}
return 0;
}
In this function, we feed all unprocessed, received data to nghttp2
session object using `nghttp2_session_mem_recv()` function. The
`nghttp2_session_mem_recv()` processes the received data and may
invoke nghttp2 callbacks and also queue outgoing frames. Since there
may be pending frames, we call ``session_send()`` function to send
those frames. The ``session_send()`` function is defined as follows::
In this function, we feed all unprocessed but already received data to the
nghttp2 session object using the `nghttp2_session_mem_recv()` function. The
`nghttp2_session_mem_recv()` function processes the data and may invoke the
nghttp2 callbacks and also queue outgoing frames. Since there may be pending
outgoing frames, we call ``session_send()`` function to send off those
frames. The ``session_send()`` function is defined as follows::
static int session_send(http2_session_data *session_data)
{
static int session_send(http2_session_data *session_data) {
int rv;
rv = nghttp2_session_send(session_data->session);
if(rv != 0) {
if (rv != 0) {
warnx("Fatal error: %s", nghttp2_strerror(rv));
return -1;
}
@@ -321,20 +304,16 @@ those frames. The ``session_send()`` function is defined as follows::
}
The `nghttp2_session_send()` function serializes the frame into wire
format and call :member:`nghttp2_session_callbacks.send_callback` with
it. We set ``send_callback()`` function to
:member:`nghttp2_session_callbacks.send_callback` in
``initialize_nghttp2_session()`` function described earlier. It is
defined as follows::
format and calls ``send_callback()`` of type
:type:`nghttp2_send_callback`. The ``send_callback()`` is defined as
follows::
static ssize_t send_callback(nghttp2_session *session,
const uint8_t *data, size_t length,
int flags, void *user_data)
{
http2_session_data *session_data = (http2_session_data*)user_data;
static ssize_t send_callback(nghttp2_session *session _U_, const uint8_t *data,
size_t length, int flags _U_, void *user_data) {
http2_session_data *session_data = (http2_session_data *)user_data;
struct bufferevent *bev = session_data->bev;
/* Avoid excessive buffering in server side. */
if(evbuffer_get_length(bufferevent_get_output(session_data->bev)) >=
if (evbuffer_get_length(bufferevent_get_output(session_data->bev)) >=
OUTPUT_WOULDBLOCK_THRESHOLD) {
return NGHTTP2_ERR_WOULDBLOCK;
}
@@ -345,26 +324,24 @@ defined as follows::
Since we use bufferevent to abstract network I/O, we just write the
data to the bufferevent object. Note that `nghttp2_session_send()`
continues to write all frames queued so far. If we were writing the
data to the non-blocking socket directly using ``write()`` system call
in the :member:`nghttp2_session_callbacks.send_callback`, we will
surely get ``EAGAIN`` or ``EWOULDBLOCK`` since the socket has limited
send buffer. If that happens, we can return
:macro:`NGHTTP2_ERR_WOULDBLOCK` to signal the nghttp2 library to stop
sending further data. But writing to the bufferevent, we have to
regulate the amount data to be buffered by ourselves to avoid possible
huge memory consumption. To achieve this, we check the size of output
buffer and if it is more than or equal to
``OUTPUT_WOULDBLOCK_THRESHOLD`` bytes, we stop writing data and return
:macro:`NGHTTP2_ERR_WOULDBLOCK` to tell the library to stop calling
send_callback.
data to a non-blocking socket directly using ``write()`` system call
in the ``send_callback()``, we would surely get ``EAGAIN`` or
``EWOULDBLOCK`` back since the socket has limited send buffer. If that
happens, we can return :macro:`NGHTTP2_ERR_WOULDBLOCK` to signal the
nghttp2 library to stop sending further data. But when writing to the
bufferevent, we have to regulate the amount data to get buffered
ourselves to avoid using huge amounts of memory. To achieve this, we
check the size of the output buffer and if it reaches more than or
equal to ``OUTPUT_WOULDBLOCK_THRESHOLD`` bytes, we stop writing data
and return :macro:`NGHTTP2_ERR_WOULDBLOCK` to tell the library to stop
calling send_callback.
The next bufferevent callback is ``readcb()``, which is invoked when
data is available to read in the bufferevent input buffer::
static void readcb(struct bufferevent *bev, void *ptr)
{
http2_session_data *session_data = (http2_session_data*)ptr;
if(session_recv(session_data) != 0) {
static void readcb(struct bufferevent *bev _U_, void *ptr) {
http2_session_data *session_data = (http2_session_data *)ptr;
if (session_recv(session_data) != 0) {
delete_http2_session_data(session_data);
return;
}
@@ -373,58 +350,55 @@ data is available to read in the bufferevent input buffer::
In this function, we just call ``session_recv()`` to process incoming
data.
The third bufferevent callback is ``writecb()``, which is invoked when
all data written in the bufferevent output buffer have been sent::
The third bufferevent callback is ``writecb()``, which is invoked when all
data in the bufferevent output buffer has been sent::
static void writecb(struct bufferevent *bev, void *ptr)
{
http2_session_data *session_data = (http2_session_data*)ptr;
if(evbuffer_get_length(bufferevent_get_output(bev)) > 0) {
static void writecb(struct bufferevent *bev, void *ptr) {
http2_session_data *session_data = (http2_session_data *)ptr;
if (evbuffer_get_length(bufferevent_get_output(bev)) > 0) {
return;
}
if(nghttp2_session_want_read(session_data->session) == 0 &&
if (nghttp2_session_want_read(session_data->session) == 0 &&
nghttp2_session_want_write(session_data->session) == 0) {
delete_http2_session_data(session_data);
return;
}
if(session_send(session_data) != 0) {
if (session_send(session_data) != 0) {
delete_http2_session_data(session_data);
return;
}
}
First we check whether we should drop connection or not. The nghttp2
session object keeps track of reception and transmission of GOAWAY
frame and other error conditions as well. Using these information,
nghttp2 session object will tell whether the connection should be
dropped or not. More specifically, both `nghttp2_session_want_read()`
and `nghttp2_session_want_write()` return 0, we have no business in
the connection. But since we are using bufferevent and its deferred
callback option, the bufferevent output buffer may contain the pending
data when the ``writecb()`` is called. To handle this situation, we
also check whether the output buffer is empty or not. If these
conditions are met, we drop connection.
First we check whether we should drop the connection or not. The nghttp2
session object keeps track of reception and transmission of GOAWAY frames and
other error conditions as well. Using this information, the nghttp2 session
object will tell whether the connection should be dropped or not. More
specifically, if both `nghttp2_session_want_read()` and
`nghttp2_session_want_write()` return 0, we have no business left in the
connection. But since we are using bufferevent and its deferred callback
option, the bufferevent output buffer may contain pending data when the
``writecb()`` is called. To handle this, we check whether the output buffer is
empty or not. If all these conditions are met, we drop connection.
Otherwise, we call ``session_send()`` to process pending output
data. Remember that in ``send_callback()``, we may not write all data
to bufferevent to avoid excessive buffering. We continue process
pending data when output buffer becomes empty.
Otherwise, we call ``session_send()`` to process the pending output
data. Remember that in ``send_callback()``, we must not write all data to
bufferevent to avoid excessive buffering. We continue processing pending data
when the output buffer becomes empty.
We have already described about nghttp2 callback ``send_callback()``.
Let's describe remaining nghttp2 callbacks we setup in
We have already described the nghttp2 callback ``send_callback()``. Let's
learn about the remaining nghttp2 callbacks we setup in
``initialize_nghttp2_setup()`` function.
The ``on_begin_headers_callback()`` function is invoked when reception
of header block in HEADERS or PUSH_PROMISE frame is started::
The ``on_begin_headers_callback()`` function is invoked when the reception of
a header block in HEADERS or PUSH_PROMISE frame is started::
static int on_begin_headers_callback(nghttp2_session *session,
const nghttp2_frame *frame,
void *user_data)
{
http2_session_data *session_data = (http2_session_data*)user_data;
void *user_data) {
http2_session_data *session_data = (http2_session_data *)user_data;
http2_stream_data *stream_data;
if(frame->hd.type != NGHTTP2_HEADERS ||
if (frame->hd.type != NGHTTP2_HEADERS ||
frame->headers.cat != NGHTTP2_HCAT_REQUEST) {
return 0;
}
@@ -434,40 +408,40 @@ of header block in HEADERS or PUSH_PROMISE frame is started::
return 0;
}
We only interested in HEADERS frame in this function. Since HEADERS
frame has several roles in HTTP/2.0 protocol, we check that it is a
request HEADERS, which opens new stream. If frame is request HEADERS,
then we create ``http2_stream_data`` object to store stream related
data. We associate created ``http2_stream_data`` object to the stream
in nghttp2 session object using `nghttp2_set_stream_user_data()` in
order to get the object without searching through doubly linked list.
We are only interested in the HEADERS frame in this function. Since the
HEADERS frame has several roles in the HTTP/2 protocol, we check that it is a
request HEADERS, which opens new stream. If the frame is a request HEADERS, we
create a ``http2_stream_data`` object to store the stream related data. We
associate the created ``http2_stream_data`` object with the stream in the
nghttp2 session object using `nghttp2_set_stream_user_data()` to get the
object without searching through the doubly linked list.
In this example server, we want to serve files relative to the current
working directory the program was invoked. Each header name/value pair
is emitted via ``on_header_callback`` function, which is called after
In this example server, we want to serve files relative to the current working
directory in which the program was invoked. Each header name/value pair is
emitted via ``on_header_callback`` function, which is called after
``on_begin_headers_callback()``::
static int on_header_callback(nghttp2_session *session,
const nghttp2_frame *frame,
const uint8_t *name, size_t namelen,
const uint8_t *value, size_t valuelen,
void *user_data)
{
const nghttp2_frame *frame, const uint8_t *name,
size_t namelen, const uint8_t *value,
size_t valuelen, uint8_t flags _U_,
void *user_data _U_) {
http2_stream_data *stream_data;
const char PATH[] = ":path";
switch(frame->hd.type) {
switch (frame->hd.type) {
case NGHTTP2_HEADERS:
if(frame->headers.cat != NGHTTP2_HCAT_REQUEST) {
if (frame->headers.cat != NGHTTP2_HCAT_REQUEST) {
break;
}
stream_data = nghttp2_session_get_stream_user_data(session,
frame->hd.stream_id);
if(stream_data->request_path) {
stream_data =
nghttp2_session_get_stream_user_data(session, frame->hd.stream_id);
if (!stream_data || stream_data->request_path) {
break;
}
if(namelen == sizeof(PATH) - 1 && memcmp(PATH, name, namelen) == 0) {
if (namelen == sizeof(PATH) - 1 && memcmp(PATH, name, namelen) == 0) {
size_t j;
for(j = 0; j < valuelen && value[j] != '?'; ++j);
for (j = 0; j < valuelen && value[j] != '?'; ++j)
;
stream_data->request_path = percent_decode(value, j);
}
break;
@@ -475,29 +449,28 @@ is emitted via ``on_header_callback`` function, which is called after
return 0;
}
We search ``:path`` header field in request headers and keep the
requested path in ``http2_stream_data`` object. In this example
program, we ignore ``:method`` header field and always treat the
request as GET request.
We search for the ``:path`` header field among the request headers and store
the requested path in the ``http2_stream_data`` object. In this example
program, we ignore ``:method`` header field and always treat the request as a
GET request.
The ``on_frame_recv_callback()`` function is invoked when a frame is
fully received::
static int on_frame_recv_callback(nghttp2_session *session,
const nghttp2_frame *frame, void *user_data)
{
http2_session_data *session_data = (http2_session_data*)user_data;
const nghttp2_frame *frame, void *user_data) {
http2_session_data *session_data = (http2_session_data *)user_data;
http2_stream_data *stream_data;
switch(frame->hd.type) {
switch (frame->hd.type) {
case NGHTTP2_DATA:
case NGHTTP2_HEADERS:
/* Check that the client request has finished */
if(frame->hd.flags & NGHTTP2_FLAG_END_STREAM) {
stream_data = nghttp2_session_get_stream_user_data(session,
frame->hd.stream_id);
if (frame->hd.flags & NGHTTP2_FLAG_END_STREAM) {
stream_data =
nghttp2_session_get_stream_user_data(session, frame->hd.stream_id);
/* For DATA and HEADERS frame, this callback may be called after
on_stream_close_callback. Check that stream still alive. */
if(!stream_data) {
if (!stream_data) {
return 0;
}
return on_request_recv(session, session_data, stream_data);
@@ -509,81 +482,81 @@ fully received::
return 0;
}
First we retrieve ``http2_stream_data`` object associated to the
stream in ``on_begin_headers_callback()``. It is done using
`nghttp2_session_get_stream_user_data()`. If the requested path cannot
be served for some reasons (e.g., file is not found), we send 404
response, which is done in ``error_reply()``. Otherwise, we open
requested file and send its content. We send 1 header field
``:status`` as a response header.
First we retrieve the ``http2_stream_data`` object associated with the stream
in ``on_begin_headers_callback()``. It is done using
`nghttp2_session_get_stream_user_data()`. If the requested path cannot be
served for some reason (e.g., file is not found), we send a 404 response,
which is done in ``error_reply()``. Otherwise, we open the requested file and
send its content. We send the header field ``:status`` as a single response
header.
Sending content of a file is done in ``send_response()`` function::
Sending the content of the file is done in ``send_response()`` function::
static int send_response(nghttp2_session *session, int32_t stream_id,
nghttp2_nv *nva, size_t nvlen, int fd)
{
nghttp2_nv *nva, size_t nvlen, int fd) {
int rv;
nghttp2_data_provider data_prd;
data_prd.source.fd = fd;
data_prd.read_callback = file_read_callback;
rv = nghttp2_submit_response(session, stream_id, nva, nvlen, &data_prd);
if(rv != 0) {
if (rv != 0) {
warnx("Fatal error: %s", nghttp2_strerror(rv));
return -1;
}
return 0;
}
The nghttp2 library uses :type:`nghttp2_data_provider` structure to
The nghttp2 library uses the :type:`nghttp2_data_provider` structure to
send entity body to the remote peer. The ``source`` member of this
structure is a union and it can be either void pointer or int which is
intended to be used as file descriptor. In this example server, we use
file descriptor. We also set ``file_read_callback()`` callback
function to read content of the file::
the file descriptor. We also set the ``file_read_callback()`` callback
function to read the contents of the file::
static ssize_t file_read_callback
(nghttp2_session *session, int32_t stream_id,
uint8_t *buf, size_t length, int *eof,
nghttp2_data_source *source, void *user_data)
{
static ssize_t file_read_callback(nghttp2_session *session _U_,
int32_t stream_id _U_, uint8_t *buf,
size_t length, uint32_t *data_flags,
nghttp2_data_source *source,
void *user_data _U_) {
int fd = source->fd;
ssize_t r;
while((r = read(fd, buf, length)) == -1 && errno == EINTR);
if(r == -1) {
while ((r = read(fd, buf, length)) == -1 && errno == EINTR)
;
if (r == -1) {
return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
}
if(r == 0) {
*eof = 1;
if (r == 0) {
*data_flags |= NGHTTP2_DATA_FLAG_EOF;
}
return r;
}
If error happens while reading file, we return
:macro:`NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE`. This tells the library
to send RST_STREAM to the stream. When all data is read, set 1 to
``*eof`` to tell the nghttp2 library that we have finished reading
file.
If an error happens while reading the file, we return
:macro:`NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE`. This tells the
library to send RST_STREAM to the stream. When all data has been read, set
the :macro:`NGHTTP2_DATA_FLAG_EOF` flag to ``*data_flags`` to tell the
nghttp2 library that we have finished reading the file.
The `nghttp2_submit_response()` is used to send response to the remote
peer.
The `nghttp2_submit_response()` function is used to send the response to the
remote peer.
The ``on_stream_close_callback()`` function is invoked when the stream
is about to close::
static int on_stream_close_callback(nghttp2_session *session,
int32_t stream_id,
nghttp2_error_code error_code,
void *user_data)
{
http2_session_data *session_data = (http2_session_data*)user_data;
static int on_stream_close_callback(nghttp2_session *session, int32_t stream_id,
uint32_t error_code _U_, void *user_data) {
http2_session_data *session_data = (http2_session_data *)user_data;
http2_stream_data *stream_data;
stream_data = nghttp2_session_get_stream_user_data(session, stream_id);
if (!stream_data) {
return 0;
}
remove_stream(session_data, stream_data);
delete_http2_stream_data(stream_data);
return 0;
}
We destroy ``http2_stream_data`` object in this function since the
stream is about to close and we no longer use that object.
We destroy the ``http2_stream_data`` object in this function since the stream
is about to close and we no longer use that object.

View File

@@ -0,0 +1,6 @@
.. include:: @top_srcdir@/doc/sources/tutorial-hpack.rst
deflate.c
---------
.. literalinclude:: @top_srcdir@/examples/deflate.c

5
examples/.gitignore vendored
View File

@@ -1,3 +1,8 @@
client
libevent-client
libevent-server
deflate
asio-sv
tiny-nghttpd
asio-sv2
asio-sv3

View File

@@ -1,4 +1,4 @@
# nghttp2 - HTTP/2.0 C Library
# nghttp2 - HTTP/2 C Library
# Copyright (c) 2012 Tatsuhiro Tsujikawa
@@ -23,10 +23,12 @@
if ENABLE_EXAMPLES
AM_CFLAGS = $(WARNCFLAGS)
AM_CPPFLAGS = \
-Wall \
-I$(top_srcdir)/lib/includes \
-I$(top_builddir)/lib/includes \
-I$(top_srcdir)/src/includes \
-I$(top_srcdir)/third-party \
@LIBEVENT_OPENSSL_CFLAGS@ \
@OPENSSL_CFLAGS@ \
@@ -38,7 +40,7 @@ LDADD = \
$(top_builddir)/lib/libnghttp2.la \
$(top_builddir)/third-party/libhttp-parser.la
noinst_PROGRAMS = client libevent-client libevent-server
noinst_PROGRAMS = client libevent-client libevent-server deflate
client_SOURCES = client.c
@@ -46,4 +48,39 @@ libevent_client_SOURCES = libevent-client.c
libevent_server_SOURCES = libevent-server.c
deflate_SOURCES = deflate.c
if ENABLE_TINY_NGHTTPD
noinst_PROGRAMS += tiny-nghttpd
tiny_nghttpd_SOURCES = tiny-nghttpd.c
endif # ENABLE_TINY_NGHTTPD
if ENABLE_ASIO_LIB
noinst_PROGRAMS += asio-sv asio-sv2 asio-sv3
ASIOCPPFLAGS = ${BOOST_CPPFLAGS} ${AM_CPPFLAGS}
ASIOLDFLAGS = @JEMALLOC_LIBS@
ASIOLDADD = $(top_builddir)/src/libnghttp2_asio.la
asio_sv_SOURCES = asio-sv.cc
asio_sv_CPPFLAGS = ${ASIOCPPFLAGS}
asio_sv_LDFLAGS = ${ASIOLDFLAGS}
asio_sv_LDADD = ${ASIOLDADD}
asio_sv2_SOURCES = asio-sv2.cc
asio_sv2_CPPFLAGS = ${ASIOCPPFLAGS}
asio_sv2_LDFLAGS = ${ASIOLDFLAGS}
asio_sv2_LDADD = ${ASIOLDADD}
asio_sv3_SOURCES = asio-sv3.cc
asio_sv3_CPPFLAGS = ${ASIOCPPFLAGS}
asio_sv3_LDFLAGS = ${ASIOLDFLAGS}
asio_sv3_LDADD = ${ASIOLDADD}
endif # ENABLE_ASIO_LIB
endif # ENABLE_EXAMPLES

75
examples/asio-sv.cc Normal file
View File

@@ -0,0 +1,75 @@
/*
* nghttp2 - HTTP/2 C Library
*
* Copyright (c) 2014 Tatsuhiro Tsujikawa
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
// We wrote this code based on the original code which has the
// following license:
//
// main.cpp
// ~~~~~~~~
//
// Copyright (c) 2003-2013 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#include <iostream>
#include <string>
#include <nghttp2/asio_http2.h>
using namespace nghttp2::asio_http2;
using namespace nghttp2::asio_http2::server;
int main(int argc, char *argv[]) {
try {
// Check command line arguments.
if (argc < 3) {
std::cerr << "Usage: asio-sv <port> <threads> <private-key-file> "
<< "<cert-file>\n";
return 1;
}
uint16_t port = std::stoi(argv[1]);
std::size_t num_threads = std::stoi(argv[2]);
http2 server;
server.num_threads(num_threads);
if (argc >= 5) {
server.tls(argv[3], argv[4]);
}
server.listen("*", port, [](const std::shared_ptr<request> &req,
const std::shared_ptr<response> &res) {
res->write_head(200, {header{"foo", "bar"}});
res->end("hello, world");
});
} catch (std::exception &e) {
std::cerr << "exception: " << e.what() << "\n";
}
return 0;
}

107
examples/asio-sv2.cc Normal file
View File

@@ -0,0 +1,107 @@
/*
* nghttp2 - HTTP/2 C Library
*
* Copyright (c) 2014 Tatsuhiro Tsujikawa
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
// We wrote this code based on the original code which has the
// following license:
//
// main.cpp
// ~~~~~~~~
//
// Copyright (c) 2003-2013 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <iostream>
#include <string>
#include <nghttp2/asio_http2.h>
using namespace nghttp2::asio_http2;
using namespace nghttp2::asio_http2::server;
int main(int argc, char *argv[]) {
try {
// Check command line arguments.
if (argc < 4) {
std::cerr << "Usage: asio-sv2 <port> <threads> <doc-root> "
<< "<private-key-file> <cert-file>\n";
return 1;
}
uint16_t port = std::stoi(argv[1]);
std::size_t num_threads = std::stoi(argv[2]);
std::string docroot = argv[3];
http2 server;
server.num_threads(num_threads);
if (argc >= 6) {
server.tls(argv[4], argv[5]);
}
server.listen("*", port, [&docroot](const std::shared_ptr<request> &req,
const std::shared_ptr<response> &res) {
auto path = percent_decode(req->path());
if (!check_path(path)) {
res->write_head(404);
res->end();
return;
}
if (path == "/") {
path = "/index.html";
}
path = docroot + path;
auto fd = open(path.c_str(), O_RDONLY);
if (fd == -1) {
res->write_head(404);
res->end();
return;
}
auto headers = std::vector<header>();
struct stat stbuf;
if (stat(path.c_str(), &stbuf) == 0) {
headers.push_back(
header{"content-length", std::to_string(stbuf.st_size)});
headers.push_back(
header{"last-modified", http_date(stbuf.st_mtim.tv_sec)});
}
res->write_head(200, std::move(headers));
res->end(file_reader_from_fd(fd));
});
} catch (std::exception &e) {
std::cerr << "exception: " << e.what() << "\n";
}
return 0;
}

142
examples/asio-sv3.cc Normal file
View File

@@ -0,0 +1,142 @@
/*
* nghttp2 - HTTP/2 C Library
*
* Copyright (c) 2014 Tatsuhiro Tsujikawa
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
// We wrote this code based on the original code which has the
// following license:
//
// main.cpp
// ~~~~~~~~
//
// Copyright (c) 2003-2013 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#include <unistd.h>
#include <iostream>
#include <string>
#include <deque>
#include <nghttp2/asio_http2.h>
using namespace nghttp2::asio_http2;
using namespace nghttp2::asio_http2::server;
int main(int argc, char *argv[]) {
try {
// Check command line arguments.
if (argc < 4) {
std::cerr << "Usage: asio-sv3 <port> <threads> <tasks> "
<< " <private-key-file> <cert-file>\n";
return 1;
}
uint16_t port = std::stoi(argv[1]);
std::size_t num_threads = std::stoi(argv[2]);
std::size_t num_concurrent_tasks = std::stoi(argv[3]);
http2 server;
server.num_threads(num_threads);
if (argc >= 5) {
server.tls(argv[4], argv[5]);
}
server.num_concurrent_tasks(num_concurrent_tasks);
server.listen("*", port, [](const std::shared_ptr<request> &req,
const std::shared_ptr<response> &res) {
res->write_head(200);
auto msgq = std::make_shared<std::deque<std::string>>();
res->end([msgq](uint8_t * buf, std::size_t len)
-> std::pair<ssize_t, bool> {
if (msgq->empty()) {
// if msgq is empty, tells the library that don't call
// this callback until we call res->resume(). This is
// done by returing std::make_pair(0, false).
return std::make_pair(0, false);
}
auto msg = std::move(msgq->front());
msgq->pop_front();
if (msg.empty()) {
// The empty message signals the end of response in
// this simple protocol.
return std::make_pair(0, true);
}
auto nwrite = std::min(len, msg.size());
std::copy(std::begin(msg), std::begin(msg) + nwrite, buf);
if (msg.size() > nwrite) {
msgq->push_front(msg.substr(nwrite));
}
return std::make_pair(nwrite, false);
});
req->run_task([res, msgq](channel &channel) {
// executed in different thread from request callback
// was called.
// Using res and msgq is not safe inside this callback.
// But using them in callback passed to channel::post is
// safe.
// We just emit simple message "message N\n" in every 1
// second and 3 times in total.
for (std::size_t i = 0; i < 3; ++i) {
msgq->push_back("message " + std::to_string(i + 1) + "\n");
channel.post([res]() {
// executed in same thread where
// request callback was called.
// Tells library we have new message.
res->resume();
});
sleep(1);
}
// Send empty message to signal the end of response
// body.
msgq->push_back("");
channel.post([res]() {
// executed in same thread where request
// callback was called.
res->resume();
});
});
});
} catch (std::exception &e) {
std::cerr << "exception: " << e.what() << "\n";
}
return 0;
}

View File

@@ -1,5 +1,5 @@
/*
* nghttp2 - HTTP/2.0 C Library
* nghttp2 - HTTP/2 C Library
*
* Copyright (c) 2013 Tatsuhiro Tsujikawa
*
@@ -26,6 +26,10 @@
* This program is written to show how to use nghttp2 API in C and
* intentionally made simple.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif /* !HAVE_CONFIG_H */
#include <stdint.h>
#include <stdlib.h>
#include <unistd.h>
@@ -44,20 +48,21 @@
#include <openssl/ssl.h>
#include <openssl/err.h>
#include <openssl/conf.h>
enum {
IO_NONE,
WANT_READ,
WANT_WRITE
};
enum { IO_NONE, WANT_READ, WANT_WRITE };
#define MAKE_NV(NAME, VALUE) \
{(uint8_t*)NAME, (uint8_t*)VALUE, \
(uint16_t)(sizeof(NAME) - 1), (uint16_t)(sizeof(VALUE) - 1) }
{ \
(uint8_t *) NAME, (uint8_t *)VALUE, sizeof(NAME) - 1, sizeof(VALUE) - 1, \
NGHTTP2_NV_FLAG_NONE \
}
#define MAKE_NV_CS(NAME, VALUE) \
{(uint8_t*)NAME, (uint8_t*)VALUE, \
(uint16_t)(sizeof(NAME) - 1), (uint16_t)(strlen(VALUE)) }
{ \
(uint8_t *) NAME, (uint8_t *)VALUE, sizeof(NAME) - 1, strlen(VALUE), \
NGHTTP2_NV_FLAG_NONE \
}
struct Connection {
SSL *ssl;
@@ -72,8 +77,6 @@ struct Connection {
};
struct Request {
/* The gzip stream inflater for the compressed response. */
nghttp2_gzip *inflater;
char *host;
/* In this program, path contains query component as well. */
char *path;
@@ -100,10 +103,9 @@ struct URI {
* Returns copy of string |s| with the length |len|. The returned
* string is NULL-terminated.
*/
static char* strcopy(const char *s, size_t len)
{
static char *strcopy(const char *s, size_t len) {
char *dst;
dst = malloc(len+1);
dst = malloc(len + 1);
memcpy(dst, s, len);
dst[len] = '\0';
return dst;
@@ -112,8 +114,7 @@ static char* strcopy(const char *s, size_t len)
/*
* Prints error message |msg| and exit.
*/
static void die(const char *msg)
{
static void die(const char *msg) {
fprintf(stderr, "FATAL: %s\n", msg);
exit(EXIT_FAILURE);
}
@@ -122,8 +123,7 @@ static void die(const char *msg)
* Prints error containing the function name |func| and message |msg|
* and exit.
*/
static void dief(const char *func, const char *msg)
{
static void dief(const char *func, const char *msg) {
fprintf(stderr, "FATAL: %s: %s\n", func, msg);
exit(EXIT_FAILURE);
}
@@ -132,64 +132,31 @@ static void dief(const char *func, const char *msg)
* Prints error containing the function name |func| and error code
* |error_code| and exit.
*/
static void diec(const char *func, int error_code)
{
static void diec(const char *func, int error_code) {
fprintf(stderr, "FATAL: %s: error_code=%d, msg=%s\n", func, error_code,
nghttp2_strerror(error_code));
exit(EXIT_FAILURE);
}
static char CONTENT_LENGTH[] = "content-encoding";
static size_t CONTENT_LENGTH_LEN = sizeof(CONTENT_LENGTH) - 1;
static char GZIP[] = "gzip";
static size_t GZIP_LEN = sizeof(GZIP) - 1;
/*
* Check response is content-encoding: gzip. We need this because
* HTTP/2.0 client is required to support gzip.
*/
static void check_gzip(struct Request *req, nghttp2_nv *nva, size_t nvlen)
{
size_t i;
if(req->inflater) {
return;
}
for(i = 0; i < nvlen; ++i) {
if(CONTENT_LENGTH_LEN == nva[i].namelen &&
memcmp(CONTENT_LENGTH, nva[i].name, nva[i].namelen) == 0 &&
GZIP_LEN == nva[i].valuelen &&
memcmp(GZIP, nva[i].value, nva[i].valuelen) == 0) {
int rv;
rv = nghttp2_gzip_inflate_new(&req->inflater);
if(rv != 0) {
die("Can't allocate inflate stream.");
}
break;
}
}
}
/*
* The implementation of nghttp2_send_callback type. Here we write
* |data| with size |length| to the network and return the number of
* bytes actually written. See the documentation of
* nghttp2_send_callback for the details.
*/
static ssize_t send_callback(nghttp2_session *session,
const uint8_t *data, size_t length, int flags,
void *user_data)
{
static ssize_t send_callback(nghttp2_session *session _U_, const uint8_t *data,
size_t length, int flags _U_, void *user_data) {
struct Connection *connection;
ssize_t rv;
connection = (struct Connection*)user_data;
int rv;
connection = (struct Connection *)user_data;
connection->want_io = IO_NONE;
ERR_clear_error();
rv = SSL_write(connection->ssl, data, length);
if(rv < 0) {
rv = SSL_write(connection->ssl, data, (int)length);
if (rv <= 0) {
int err = SSL_get_error(connection->ssl, rv);
if(err == SSL_ERROR_WANT_WRITE || err == SSL_ERROR_WANT_READ) {
connection->want_io = (err == SSL_ERROR_WANT_READ ?
WANT_READ : WANT_WRITE);
if (err == SSL_ERROR_WANT_WRITE || err == SSL_ERROR_WANT_READ) {
connection->want_io =
(err == SSL_ERROR_WANT_READ ? WANT_READ : WANT_WRITE);
rv = NGHTTP2_ERR_WOULDBLOCK;
} else {
rv = NGHTTP2_ERR_CALLBACK_FAILURE;
@@ -204,64 +171,39 @@ static ssize_t send_callback(nghttp2_session *session,
* |length| bytes. Returns the number of bytes stored in |buf|. See
* the documentation of nghttp2_recv_callback for the details.
*/
static ssize_t recv_callback(nghttp2_session *session,
uint8_t *buf, size_t length, int flags,
void *user_data)
{
static ssize_t recv_callback(nghttp2_session *session _U_, uint8_t *buf,
size_t length, int flags _U_, void *user_data) {
struct Connection *connection;
ssize_t rv;
connection = (struct Connection*)user_data;
int rv;
connection = (struct Connection *)user_data;
connection->want_io = IO_NONE;
ERR_clear_error();
rv = SSL_read(connection->ssl, buf, length);
if(rv < 0) {
rv = SSL_read(connection->ssl, buf, (int)length);
if (rv < 0) {
int err = SSL_get_error(connection->ssl, rv);
if(err == SSL_ERROR_WANT_WRITE || err == SSL_ERROR_WANT_READ) {
connection->want_io = (err == SSL_ERROR_WANT_READ ?
WANT_READ : WANT_WRITE);
if (err == SSL_ERROR_WANT_WRITE || err == SSL_ERROR_WANT_READ) {
connection->want_io =
(err == SSL_ERROR_WANT_READ ? WANT_READ : WANT_WRITE);
rv = NGHTTP2_ERR_WOULDBLOCK;
} else {
rv = NGHTTP2_ERR_CALLBACK_FAILURE;
}
} else if(rv == 0) {
} else if (rv == 0) {
rv = NGHTTP2_ERR_EOF;
}
return rv;
}
/*
* The implementation of nghttp2_before_frame_send_callback type. We
* use this function to get stream ID of the request. This is because
* stream ID is not known when we submit the request
* (nghttp2_submit_request).
*/
static int before_frame_send_callback(nghttp2_session *session,
const nghttp2_frame *frame,
void *user_data)
{
if(frame->hd.type == NGHTTP2_HEADERS &&
frame->headers.cat == NGHTTP2_HCAT_REQUEST) {
struct Request *req;
int32_t stream_id = frame->hd.stream_id;
req = nghttp2_session_get_stream_user_data(session, stream_id);
if(req && req->stream_id == -1) {
req->stream_id = stream_id;
printf("[INFO] Stream ID = %d\n", stream_id);
}
}
return 0;
}
static int on_frame_send_callback(nghttp2_session *session,
const nghttp2_frame *frame, void *user_data)
{
const nghttp2_frame *frame,
void *user_data _U_) {
size_t i;
switch(frame->hd.type) {
switch (frame->hd.type) {
case NGHTTP2_HEADERS:
if(nghttp2_session_get_stream_user_data(session, frame->hd.stream_id)) {
if (nghttp2_session_get_stream_user_data(session, frame->hd.stream_id)) {
const nghttp2_nv *nva = frame->headers.nva;
printf("[INFO] C ----------------------------> S (HEADERS)\n");
for(i = 0; i < frame->headers.nvlen; ++i) {
for (i = 0; i < frame->headers.nvlen; ++i) {
fwrite(nva[i].name, nva[i].namelen, 1, stdout);
printf(": ");
fwrite(nva[i].value, nva[i].valuelen, 1, stdout);
@@ -280,19 +222,18 @@ static int on_frame_send_callback(nghttp2_session *session,
}
static int on_frame_recv_callback(nghttp2_session *session,
const nghttp2_frame *frame, void *user_data)
{
const nghttp2_frame *frame,
void *user_data _U_) {
size_t i;
switch(frame->hd.type) {
switch (frame->hd.type) {
case NGHTTP2_HEADERS:
if(frame->headers.cat == NGHTTP2_HCAT_RESPONSE) {
if (frame->headers.cat == NGHTTP2_HCAT_RESPONSE) {
const nghttp2_nv *nva = frame->headers.nva;
struct Request *req;
req = nghttp2_session_get_stream_user_data(session, frame->hd.stream_id);
if(req) {
check_gzip(req, frame->headers.nva, frame->headers.nvlen);
if (req) {
printf("[INFO] C <---------------------------- S (HEADERS)\n");
for(i = 0; i < frame->headers.nvlen; ++i) {
for (i = 0; i < frame->headers.nvlen; ++i) {
fwrite(nva[i].name, nva[i].namelen, 1, stdout);
printf(": ");
fwrite(nva[i].value, nva[i].valuelen, 1, stdout);
@@ -317,19 +258,17 @@ static int on_frame_recv_callback(nghttp2_session *session,
* fetch 1 resource in this program, after reception of the response,
* we submit GOAWAY and close the session.
*/
static int on_stream_close_callback(nghttp2_session *session,
int32_t stream_id,
nghttp2_error_code error_code,
void *user_data)
{
static int on_stream_close_callback(nghttp2_session *session, int32_t stream_id,
uint32_t error_code _U_,
void *user_data _U_) {
struct Request *req;
req = nghttp2_session_get_stream_user_data(session, stream_id);
if(req) {
if (req) {
int rv;
rv = nghttp2_submit_goaway(session, NGHTTP2_FLAG_NONE, NGHTTP2_NO_ERROR,
NULL, 0);
if(rv != 0) {
diec("nghttp2_submit_goaway", rv);
rv = nghttp2_session_terminate_session(session, NGHTTP2_NO_ERROR);
if (rv != 0) {
diec("nghttp2_session_terminate_session", rv);
}
}
return 0;
@@ -341,35 +280,17 @@ static int on_stream_close_callback(nghttp2_session *session,
* The implementation of nghttp2_on_data_chunk_recv_callback type. We
* use this function to print the received response body.
*/
static int on_data_chunk_recv_callback(nghttp2_session *session, uint8_t flags,
int32_t stream_id,
static int on_data_chunk_recv_callback(nghttp2_session *session,
uint8_t flags _U_, int32_t stream_id,
const uint8_t *data, size_t len,
void *user_data)
{
void *user_data _U_) {
struct Request *req;
req = nghttp2_session_get_stream_user_data(session, stream_id);
if(req) {
if (req) {
printf("[INFO] C <---------------------------- S (DATA chunk)\n"
"%lu bytes\n", (unsigned long int)len);
if(req->inflater) {
while(len > 0) {
uint8_t out[MAX_OUTLEN];
size_t outlen = MAX_OUTLEN;
size_t tlen = len;
int rv;
rv = nghttp2_gzip_inflate(req->inflater, out, &outlen, data, &tlen);
if(rv == -1) {
nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, stream_id,
NGHTTP2_INTERNAL_ERROR);
break;
}
fwrite(out, 1, outlen, stdout);
data += tlen;
len -= tlen;
}
} else {
"%lu bytes\n",
(unsigned long int)len);
fwrite(data, 1, len, stdout);
}
printf("\n");
}
return 0;
@@ -381,34 +302,38 @@ static int on_data_chunk_recv_callback(nghttp2_session *session, uint8_t flags,
* always required. Since we use nghttp2_session_recv(), the
* recv_callback is also required.
*/
static void setup_nghttp2_callbacks(nghttp2_session_callbacks *callbacks)
{
memset(callbacks, 0, sizeof(nghttp2_session_callbacks));
callbacks->send_callback = send_callback;
callbacks->recv_callback = recv_callback;
callbacks->before_frame_send_callback = before_frame_send_callback;
callbacks->on_frame_send_callback = on_frame_send_callback;
callbacks->on_frame_recv_callback = on_frame_recv_callback;
callbacks->on_stream_close_callback = on_stream_close_callback;
callbacks->on_data_chunk_recv_callback = on_data_chunk_recv_callback;
static void setup_nghttp2_callbacks(nghttp2_session_callbacks *callbacks) {
nghttp2_session_callbacks_set_send_callback(callbacks, send_callback);
nghttp2_session_callbacks_set_recv_callback(callbacks, recv_callback);
nghttp2_session_callbacks_set_on_frame_send_callback(callbacks,
on_frame_send_callback);
nghttp2_session_callbacks_set_on_frame_recv_callback(callbacks,
on_frame_recv_callback);
nghttp2_session_callbacks_set_on_stream_close_callback(
callbacks, on_stream_close_callback);
nghttp2_session_callbacks_set_on_data_chunk_recv_callback(
callbacks, on_data_chunk_recv_callback);
}
/*
* Callback function for TLS NPN. Since this program only supports
* HTTP/2.0 protocol, if server does not offer HTTP/2.0 the nghttp2
* HTTP/2 protocol, if server does not offer HTTP/2 the nghttp2
* library supports, we terminate program.
*/
static int select_next_proto_cb(SSL* ssl,
unsigned char **out, unsigned char *outlen,
const unsigned char *in, unsigned int inlen,
void *arg)
{
static int select_next_proto_cb(SSL *ssl _U_, unsigned char **out,
unsigned char *outlen, const unsigned char *in,
unsigned int inlen, void *arg _U_) {
int rv;
/* nghttp2_select_next_protocol() selects HTTP/2.0 protocol the
/* nghttp2_select_next_protocol() selects HTTP/2 protocol the
nghttp2 library supports. */
rv = nghttp2_select_next_protocol(out, outlen, in, inlen);
if(rv <= 0) {
die("Server did not advertise HTTP/2.0 protocol");
if (rv <= 0) {
die("Server did not advertise HTTP/2 protocol");
}
return SSL_TLSEXT_ERR_OK;
}
@@ -416,25 +341,23 @@ static int select_next_proto_cb(SSL* ssl,
/*
* Setup SSL/TLS context.
*/
static void init_ssl_ctx(SSL_CTX *ssl_ctx)
{
static void init_ssl_ctx(SSL_CTX *ssl_ctx) {
/* Disable SSLv2 and enable all workarounds for buggy servers */
SSL_CTX_set_options(ssl_ctx, SSL_OP_ALL|SSL_OP_NO_SSLv2);
SSL_CTX_set_options(ssl_ctx, SSL_OP_ALL | SSL_OP_NO_SSLv2);
SSL_CTX_set_mode(ssl_ctx, SSL_MODE_AUTO_RETRY);
SSL_CTX_set_mode(ssl_ctx, SSL_MODE_RELEASE_BUFFERS);
/* Set NPN callback */
SSL_CTX_set_next_proto_select_cb(ssl_ctx, select_next_proto_cb, NULL);
}
static void ssl_handshake(SSL *ssl, int fd)
{
static void ssl_handshake(SSL *ssl, int fd) {
int rv;
if(SSL_set_fd(ssl, fd) == 0) {
if (SSL_set_fd(ssl, fd) == 0) {
dief("SSL_set_fd", ERR_error_string(ERR_get_error(), NULL));
}
ERR_clear_error();
rv = SSL_connect(ssl);
if(rv <= 0) {
if (rv <= 0) {
dief("SSL_connect", ERR_error_string(ERR_get_error(), NULL));
}
}
@@ -443,8 +366,7 @@ static void ssl_handshake(SSL *ssl, int fd)
* Connects to the host |host| and port |port|. This function returns
* the file descriptor of the client socket.
*/
static int connect_to(const char *host, uint16_t port)
{
static int connect_to(const char *host, uint16_t port) {
struct addrinfo hints;
int fd = -1;
int rv;
@@ -455,17 +377,18 @@ static int connect_to(const char *host, uint16_t port)
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
rv = getaddrinfo(host, service, &hints, &res);
if(rv != 0) {
if (rv != 0) {
dief("getaddrinfo", gai_strerror(rv));
}
for(rp = res; rp; rp = rp->ai_next) {
for (rp = res; rp; rp = rp->ai_next) {
fd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
if(fd == -1) {
if (fd == -1) {
continue;
}
while((rv = connect(fd, rp->ai_addr, rp->ai_addrlen)) == -1 &&
errno == EINTR);
if(rv == 0) {
while ((rv = connect(fd, rp->ai_addr, rp->ai_addrlen)) == -1 &&
errno == EINTR)
;
if (rv == 0) {
break;
}
close(fd);
@@ -475,25 +398,25 @@ static int connect_to(const char *host, uint16_t port)
return fd;
}
static void make_non_block(int fd)
{
static void make_non_block(int fd) {
int flags, rv;
while((flags = fcntl(fd, F_GETFL, 0)) == -1 && errno == EINTR);
if(flags == -1) {
while ((flags = fcntl(fd, F_GETFL, 0)) == -1 && errno == EINTR)
;
if (flags == -1) {
dief("fcntl", strerror(errno));
}
while((rv = fcntl(fd, F_SETFL, flags | O_NONBLOCK)) == -1 && errno == EINTR);
if(rv == -1) {
while ((rv = fcntl(fd, F_SETFL, flags | O_NONBLOCK)) == -1 && errno == EINTR)
;
if (rv == -1) {
dief("fcntl", strerror(errno));
}
}
static void set_tcp_nodelay(int fd)
{
static void set_tcp_nodelay(int fd) {
int val = 1;
int rv;
rv = setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &val, (socklen_t)sizeof(val));
if(rv == -1) {
if (rv == -1) {
dief("setsockopt", strerror(errno));
}
}
@@ -501,14 +424,13 @@ static void set_tcp_nodelay(int fd)
/*
* Update |pollfd| based on the state of |connection|.
*/
static void ctl_poll(struct pollfd *pollfd, struct Connection *connection)
{
static void ctl_poll(struct pollfd *pollfd, struct Connection *connection) {
pollfd->events = 0;
if(nghttp2_session_want_read(connection->session) ||
if (nghttp2_session_want_read(connection->session) ||
connection->want_io == WANT_READ) {
pollfd->events |= POLLIN;
}
if(nghttp2_session_want_write(connection->session) ||
if (nghttp2_session_want_write(connection->session) ||
connection->want_io == WANT_WRITE) {
pollfd->events |= POLLOUT;
}
@@ -519,66 +441,61 @@ static void ctl_poll(struct pollfd *pollfd, struct Connection *connection)
* function does not send packets; just append the request to the
* internal queue in |connection->session|.
*/
static void submit_request(struct Connection *connection, struct Request *req)
{
int pri = 0;
int rv;
const nghttp2_nv nva[] = {
static void submit_request(struct Connection *connection, struct Request *req) {
int32_t stream_id;
/* Make sure that the last item is NULL */
MAKE_NV(":method", "GET"),
const nghttp2_nv nva[] = {MAKE_NV(":method", "GET"),
MAKE_NV_CS(":path", req->path),
MAKE_NV(":scheme", "https"),
MAKE_NV_CS(":authority", req->hostport),
MAKE_NV("accept", "*/*"),
MAKE_NV("user-agent", "nghttp2/"NGHTTP2_VERSION)
};
rv = nghttp2_submit_request(connection->session, pri,
nva, sizeof(nva)/sizeof(nva[0]), NULL, req);
if(rv != 0) {
diec("nghttp2_submit_request", rv);
MAKE_NV("user-agent", "nghttp2/" NGHTTP2_VERSION)};
stream_id = nghttp2_submit_request(connection->session, NULL, nva,
sizeof(nva) / sizeof(nva[0]), NULL, req);
if (stream_id < 0) {
diec("nghttp2_submit_request", stream_id);
}
req->stream_id = stream_id;
printf("[INFO] Stream ID = %d\n", stream_id);
}
/*
* Performs the network I/O.
*/
static void exec_io(struct Connection *connection)
{
static void exec_io(struct Connection *connection) {
int rv;
rv = nghttp2_session_recv(connection->session);
if(rv != 0) {
if (rv != 0) {
diec("nghttp2_session_recv", rv);
}
rv = nghttp2_session_send(connection->session);
if(rv != 0) {
if (rv != 0) {
diec("nghttp2_session_send", rv);
}
}
static void request_init(struct Request *req, const struct URI *uri)
{
static void request_init(struct Request *req, const struct URI *uri) {
req->host = strcopy(uri->host, uri->hostlen);
req->port = uri->port;
req->path = strcopy(uri->path, uri->pathlen);
req->hostport = strcopy(uri->hostport, uri->hostportlen);
req->stream_id = -1;
req->inflater = NULL;
}
static void request_free(struct Request *req)
{
static void request_free(struct Request *req) {
free(req->host);
free(req->path);
free(req->hostport);
nghttp2_gzip_inflate_del(req->inflater);
}
/*
* Fetches the resource denoted by |uri|.
*/
static void fetch_uri(const struct URI *uri)
{
nghttp2_session_callbacks callbacks;
static void fetch_uri(const struct URI *uri) {
nghttp2_session_callbacks *callbacks;
int fd;
SSL_CTX *ssl_ctx;
SSL *ssl;
@@ -590,20 +507,18 @@ static void fetch_uri(const struct URI *uri)
request_init(&req, uri);
setup_nghttp2_callbacks(&callbacks);
/* Establish connection and setup SSL */
fd = connect_to(req.host, req.port);
if(fd == -1) {
if (fd == -1) {
die("Could not open file descriptor");
}
ssl_ctx = SSL_CTX_new(SSLv23_client_method());
if(ssl_ctx == NULL) {
if (ssl_ctx == NULL) {
dief("SSL_CTX_new", ERR_error_string(ERR_get_error(), NULL));
}
init_ssl_ctx(ssl_ctx);
ssl = SSL_new(ssl_ctx);
if(ssl == NULL) {
if (ssl == NULL) {
dief("SSL_new", ERR_error_string(ERR_get_error(), NULL));
}
/* To simplify the program, we perform SSL/TLS handshake in blocking
@@ -614,17 +529,32 @@ static void fetch_uri(const struct URI *uri)
connection.want_io = IO_NONE;
/* Send connection header in blocking I/O mode */
SSL_write(ssl, NGHTTP2_CLIENT_CONNECTION_HEADER,
NGHTTP2_CLIENT_CONNECTION_HEADER_LEN);
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 */
make_non_block(fd);
set_tcp_nodelay(fd);
printf("[INFO] SSL/TLS handshake completed\n");
rv = nghttp2_session_client_new(&connection.session, &callbacks,
&connection);
if(rv != 0) {
rv = nghttp2_session_callbacks_new(&callbacks);
if (rv != 0) {
diec("nghttp2_session_callbacks_new", rv);
}
setup_nghttp2_callbacks(callbacks);
rv = nghttp2_session_client_new(&connection.session, callbacks, &connection);
nghttp2_session_callbacks_del(callbacks);
if (rv != 0) {
diec("nghttp2_session_client_new", rv);
}
@@ -635,16 +565,16 @@ static void fetch_uri(const struct URI *uri)
ctl_poll(pollfds, &connection);
/* Event loop */
while(nghttp2_session_want_read(connection.session) ||
while (nghttp2_session_want_read(connection.session) ||
nghttp2_session_want_write(connection.session)) {
int nfds = poll(pollfds, npollfds, -1);
if(nfds == -1) {
if (nfds == -1) {
dief("poll", strerror(errno));
}
if(pollfds[0].revents & (POLLIN | POLLOUT)) {
if (pollfds[0].revents & (POLLIN | POLLOUT)) {
exec_io(&connection);
}
if((pollfds[0].revents & POLLHUP) || (pollfds[0].revents & POLLERR)) {
if ((pollfds[0].revents & POLLHUP) || (pollfds[0].revents & POLLERR)) {
die("Connection error");
}
ctl_poll(pollfds, &connection);
@@ -660,96 +590,94 @@ static void fetch_uri(const struct URI *uri)
request_free(&req);
}
static int parse_uri(struct URI *res, const char *uri)
{
static int parse_uri(struct URI *res, const char *uri) {
/* We only interested in https */
size_t len, i, offset;
int ipv6addr = 0;
memset(res, 0, sizeof(struct URI));
len = strlen(uri);
if(len < 9 || memcmp("https://", uri, 8) != 0) {
if (len < 9 || memcmp("https://", uri, 8) != 0) {
return -1;
}
offset = 8;
res->host = res->hostport = &uri[offset];
res->hostlen = 0;
if(uri[offset] == '[') {
if (uri[offset] == '[') {
/* IPv6 literal address */
++offset;
++res->host;
ipv6addr = 1;
for(i = offset; i < len; ++i) {
if(uri[i] == ']') {
res->hostlen = i-offset;
offset = i+1;
for (i = offset; i < len; ++i) {
if (uri[i] == ']') {
res->hostlen = i - offset;
offset = i + 1;
break;
}
}
} else {
const char delims[] = ":/?#";
for(i = offset; i < len; ++i) {
if(strchr(delims, uri[i]) != NULL) {
for (i = offset; i < len; ++i) {
if (strchr(delims, uri[i]) != NULL) {
break;
}
}
res->hostlen = i-offset;
res->hostlen = i - offset;
offset = i;
}
if(res->hostlen == 0) {
if (res->hostlen == 0) {
return -1;
}
/* Assuming https */
res->port = 443;
if(offset < len) {
if(uri[offset] == ':') {
if (offset < len) {
if (uri[offset] == ':') {
/* port */
const char delims[] = "/?#";
int port = 0;
++offset;
for(i = offset; i < len; ++i) {
if(strchr(delims, uri[i]) != NULL) {
for (i = offset; i < len; ++i) {
if (strchr(delims, uri[i]) != NULL) {
break;
}
if('0' <= uri[i] && uri[i] <= '9') {
if ('0' <= uri[i] && uri[i] <= '9') {
port *= 10;
port += uri[i]-'0';
if(port > 65535) {
port += uri[i] - '0';
if (port > 65535) {
return -1;
}
} else {
return -1;
}
}
if(port == 0) {
if (port == 0) {
return -1;
}
offset = i;
res->port = port;
}
}
res->hostportlen = uri+offset+ipv6addr-res->host;
for(i = offset; i < len; ++i) {
if(uri[i] == '#') {
res->hostportlen = uri + offset + ipv6addr - res->host;
for (i = offset; i < len; ++i) {
if (uri[i] == '#') {
break;
}
}
if(i-offset == 0) {
if (i - offset == 0) {
res->path = "/";
res->pathlen = 1;
} else {
res->path = &uri[offset];
res->pathlen = i-offset;
res->pathlen = i - offset;
}
return 0;
}
int main(int argc, char **argv)
{
int main(int argc, char **argv) {
struct URI uri;
struct sigaction act;
int rv;
if(argc < 2) {
if (argc < 2) {
die("Specify a https URI");
}
@@ -757,11 +685,13 @@ int main(int argc, char **argv)
act.sa_handler = SIG_IGN;
sigaction(SIGPIPE, &act, 0);
OPENSSL_config(NULL);
OpenSSL_add_all_algorithms();
SSL_load_error_strings();
SSL_library_init();
rv = parse_uri(&uri, argv[1]);
if(rv != 0) {
if (rv != 0) {
die("parse_uri failed");
}
fetch_uri(&uri);

206
examples/deflate.c Normal file
View File

@@ -0,0 +1,206 @@
/*
* nghttp2 - HTTP/2 C Library
*
* Copyright (c) 2014 Tatsuhiro Tsujikawa
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif /* !HAVE_CONFIG_H */
#include <stdio.h>
#include <string.h>
#include <nghttp2/nghttp2.h>
#define MAKE_NV(K, V) \
{ \
(uint8_t *) K, (uint8_t *)V, sizeof(K) - 1, sizeof(V) - 1, \
NGHTTP2_NV_FLAG_NONE \
}
static void deflate(nghttp2_hd_deflater *deflater,
nghttp2_hd_inflater *inflater, const nghttp2_nv *const nva,
size_t nvlen);
static int inflate_header_block(nghttp2_hd_inflater *inflater, uint8_t *in,
size_t inlen, int final);
int main(int argc _U_, char **argv _U_) {
int rv;
nghttp2_hd_deflater *deflater;
nghttp2_hd_inflater *inflater;
/* Define 1st header set. This is looks like a HTTP request. */
nghttp2_nv nva1[] = {
MAKE_NV(":scheme", "https"), MAKE_NV(":authority", "example.org"),
MAKE_NV(":path", "/"), MAKE_NV("user-agent", "libnghttp2"),
MAKE_NV("accept-encoding", "gzip, deflate")};
/* Define 2nd header set */
nghttp2_nv nva2[] = {MAKE_NV(":scheme", "https"),
MAKE_NV(":authority", "example.org"),
MAKE_NV(":path", "/stylesheet/style.css"),
MAKE_NV("user-agent", "libnghttp2"),
MAKE_NV("accept-encoding", "gzip, deflate"),
MAKE_NV("referer", "https://example.org")};
rv = nghttp2_hd_deflate_new(&deflater, 4096);
if (rv != 0) {
fprintf(stderr, "nghttp2_hd_deflate_init failed with error: %s\n",
nghttp2_strerror(rv));
exit(EXIT_FAILURE);
}
rv = nghttp2_hd_inflate_new(&inflater);
if (rv != 0) {
fprintf(stderr, "nghttp2_hd_inflate_init failed with error: %s\n",
nghttp2_strerror(rv));
exit(EXIT_FAILURE);
}
/* Encode and decode 1st header set */
deflate(deflater, inflater, nva1, sizeof(nva1) / sizeof(nva1[0]));
/* Encode and decode 2nd header set, using differential encoding
using state after encoding 1st header set. */
deflate(deflater, inflater, nva2, sizeof(nva2) / sizeof(nva2[0]));
nghttp2_hd_inflate_del(inflater);
nghttp2_hd_deflate_del(deflater);
return 0;
}
static void deflate(nghttp2_hd_deflater *deflater,
nghttp2_hd_inflater *inflater, const nghttp2_nv *const nva,
size_t nvlen) {
ssize_t rv;
uint8_t *buf;
size_t buflen;
size_t outlen;
size_t i;
size_t sum;
sum = 0;
for (i = 0; i < nvlen; ++i) {
sum += nva[i].namelen + nva[i].valuelen;
}
printf("Input (%zu byte(s)):\n\n", sum);
for (i = 0; i < nvlen; ++i) {
fwrite(nva[i].name, nva[i].namelen, 1, stdout);
printf(": ");
fwrite(nva[i].value, nva[i].valuelen, 1, stdout);
printf("\n");
}
buflen = nghttp2_hd_deflate_bound(deflater, nva, nvlen);
buf = malloc(buflen);
rv = nghttp2_hd_deflate_hd(deflater, buf, buflen, nva, nvlen);
if (rv < 0) {
fprintf(stderr, "nghttp2_hd_deflate_hd() failed with error: %s\n",
nghttp2_strerror((int)rv));
free(buf);
exit(EXIT_FAILURE);
}
outlen = rv;
printf("\nDeflate (%zu byte(s), ratio %.02f):\n\n", outlen,
sum == 0 ? 0 : (double)outlen / sum);
for (i = 0; i < outlen; ++i) {
if ((i & 0x0fu) == 0) {
printf("%08zX: ", i);
}
printf("%02X ", buf[i]);
if (((i + 1) & 0x0fu) == 0) {
printf("\n");
}
}
printf("\n\nInflate:\n\n");
/* We pass 1 to final parameter, because buf contains whole deflated
header data. */
rv = inflate_header_block(inflater, buf, outlen, 1);
if (rv != 0) {
free(buf);
exit(EXIT_FAILURE);
}
printf("\n-----------------------------------------------------------"
"--------------------\n");
free(buf);
}
int inflate_header_block(nghttp2_hd_inflater *inflater, uint8_t *in,
size_t inlen, int final) {
ssize_t rv;
for (;;) {
nghttp2_nv nv;
int inflate_flags = 0;
size_t proclen;
rv = nghttp2_hd_inflate_hd(inflater, &nv, &inflate_flags, in, inlen, final);
if (rv < 0) {
fprintf(stderr, "inflate failed with error code %zd", rv);
return -1;
}
proclen = rv;
in += proclen;
inlen -= proclen;
if (inflate_flags & NGHTTP2_HD_INFLATE_EMIT) {
fwrite(nv.name, nv.namelen, 1, stderr);
fprintf(stderr, ": ");
fwrite(nv.value, nv.valuelen, 1, stderr);
fprintf(stderr, "\n");
}
if (inflate_flags & NGHTTP2_HD_INFLATE_FINAL) {
nghttp2_hd_inflate_end_headers(inflater);
break;
}
if ((inflate_flags & NGHTTP2_HD_INFLATE_EMIT) == 0 && inlen == 0) {
break;
}
}
return 0;
}

View File

@@ -1,5 +1,5 @@
/*
* nghttp2 - HTTP/2.0 C Library
* nghttp2 - HTTP/2 C Library
*
* Copyright (c) 2013 Tatsuhiro Tsujikawa
*
@@ -22,6 +22,10 @@
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif /* !HAVE_CONFIG_H */
#include <sys/types.h>
#include <unistd.h>
#include <sys/socket.h>
@@ -32,6 +36,7 @@
#include <openssl/ssl.h>
#include <openssl/err.h>
#include <openssl/conf.h>
#include <event.h>
#include <event2/event.h>
@@ -42,7 +47,7 @@
#include "http-parser/http_parser.h"
#define ARRLEN(x) (sizeof(x)/sizeof(x[0]))
#define ARRLEN(x) (sizeof(x) / sizeof(x[0]))
typedef struct {
/* The NULL-terminated URI string to retreive. */
@@ -69,9 +74,8 @@ typedef struct {
http2_stream_data *stream_data;
} http2_session_data;
static http2_stream_data* create_http2_stream_data(const char *uri,
struct http_parser_url *u)
{
static http2_stream_data *create_http2_stream_data(const char *uri,
struct http_parser_url *u) {
/* MAX 5 digits (max 65535) + 1 ':' + 1 NULL (because of snprintf) */
size_t extra = 7;
http2_stream_data *stream_data = malloc(sizeof(http2_stream_data));
@@ -82,29 +86,29 @@ static http2_stream_data* create_http2_stream_data(const char *uri,
stream_data->authoritylen = u->field_data[UF_HOST].len;
stream_data->authority = malloc(stream_data->authoritylen + extra);
memcpy(stream_data->authority,
&uri[u->field_data[UF_HOST].off], u->field_data[UF_HOST].len);
if(u->field_set & (1 << UF_PORT)) {
memcpy(stream_data->authority, &uri[u->field_data[UF_HOST].off],
u->field_data[UF_HOST].len);
if (u->field_set & (1 << UF_PORT)) {
stream_data->authoritylen +=
snprintf(stream_data->authority + u->field_data[UF_HOST].len, extra,
":%u", u->port);
}
stream_data->pathlen = 0;
if(u->field_set & (1 << UF_PATH)) {
if (u->field_set & (1 << UF_PATH)) {
stream_data->pathlen = u->field_data[UF_PATH].len;
}
if(u->field_set & (1 << UF_QUERY)) {
if (u->field_set & (1 << UF_QUERY)) {
/* +1 for '?' character */
stream_data->pathlen += u->field_data[UF_QUERY].len + 1;
}
if(stream_data->pathlen > 0) {
if (stream_data->pathlen > 0) {
stream_data->path = malloc(stream_data->pathlen);
if(u->field_set & (1 << UF_PATH)) {
memcpy(stream_data->path,
&uri[u->field_data[UF_PATH].off], u->field_data[UF_PATH].len);
if (u->field_set & (1 << UF_PATH)) {
memcpy(stream_data->path, &uri[u->field_data[UF_PATH].off],
u->field_data[UF_PATH].len);
}
if(u->field_set & (1 << UF_QUERY)) {
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);
}
@@ -114,16 +118,15 @@ static http2_stream_data* create_http2_stream_data(const char *uri,
return stream_data;
}
static void delete_http2_stream_data(http2_stream_data *stream_data)
{
static void delete_http2_stream_data(http2_stream_data *stream_data) {
free(stream_data->path);
free(stream_data->authority);
free(stream_data);
}
/* Initializes |session_data| */
static http2_session_data *create_http2_session_data(struct event_base *evbase)
{
static http2_session_data *
create_http2_session_data(struct event_base *evbase) {
http2_session_data *session_data = malloc(sizeof(http2_session_data));
memset(session_data, 0, sizeof(http2_session_data));
@@ -131,11 +134,10 @@ static http2_session_data *create_http2_session_data(struct event_base *evbase)
return session_data;
}
static void delete_http2_session_data(http2_session_data *session_data)
{
static void delete_http2_session_data(http2_session_data *session_data) {
SSL *ssl = bufferevent_openssl_get_ssl(session_data->bev);
if(ssl) {
if (ssl) {
SSL_shutdown(ssl);
}
bufferevent_free(session_data->bev);
@@ -144,17 +146,15 @@ static void delete_http2_session_data(http2_session_data *session_data)
session_data->dnsbase = NULL;
nghttp2_session_del(session_data->session);
session_data->session = NULL;
if(session_data->stream_data) {
if (session_data->stream_data) {
delete_http2_stream_data(session_data->stream_data);
session_data->stream_data = NULL;
}
free(session_data);
}
static void print_header(FILE *f,
const uint8_t *name, size_t namelen,
const uint8_t *value, size_t valuelen)
{
static void print_header(FILE *f, const uint8_t *name, size_t namelen,
const uint8_t *value, size_t valuelen) {
fwrite(name, namelen, 1, f);
fprintf(f, ": ");
fwrite(value, valuelen, 1, f);
@@ -164,13 +164,10 @@ static void print_header(FILE *f,
/* Print HTTP headers to |f|. Please note that this function does not
take into account that header name and value are sequence of
octets, therefore they may contain non-printable characters. */
static void print_headers(FILE *f, nghttp2_nv *nva, size_t nvlen)
{
static void print_headers(FILE *f, nghttp2_nv *nva, size_t nvlen) {
size_t i;
for(i = 0; i < nvlen; ++i) {
print_header(f,
nva[i].name, nva[i].namelen,
nva[i].value, nva[i].valuelen);
for (i = 0; i < nvlen; ++i) {
print_header(f, nva[i].name, nva[i].namelen, nva[i].value, nva[i].valuelen);
}
fprintf(f, "\n");
}
@@ -178,50 +175,25 @@ static void print_headers(FILE *f, nghttp2_nv *nva, size_t nvlen)
/* nghttp2_send_callback. Here we transmit the |data|, |length| bytes,
to the network. Because we are using libevent bufferevent, we just
write those bytes into bufferevent buffer. */
static ssize_t send_callback(nghttp2_session *session,
const uint8_t *data, size_t length,
int flags, void *user_data)
{
http2_session_data *session_data = (http2_session_data*)user_data;
static ssize_t send_callback(nghttp2_session *session _U_, const uint8_t *data,
size_t length, int flags _U_, void *user_data) {
http2_session_data *session_data = (http2_session_data *)user_data;
struct bufferevent *bev = session_data->bev;
bufferevent_write(bev, data, length);
return length;
}
/* nghttp2_before_frame_send_callback: Called when nghttp2 library is
about to send a frame. We use this callback to get stream ID of new
stream. Since HEADERS in HTTP/2.0 has several roles, we check that
it is a HTTP request HEADERS. */
static int before_frame_send_callback
(nghttp2_session *session, const nghttp2_frame *frame, void *user_data)
{
http2_session_data *session_data = (http2_session_data*)user_data;
http2_stream_data *stream_data;
if(frame->hd.type == NGHTTP2_HEADERS &&
frame->headers.cat == NGHTTP2_HCAT_REQUEST) {
stream_data =
(http2_stream_data*)nghttp2_session_get_stream_user_data
(session, frame->hd.stream_id);
if(stream_data == session_data->stream_data) {
stream_data->stream_id = frame->hd.stream_id;
}
}
return 0;
}
/* nghttp2_on_header_callback: Called when nghttp2 library emits
single header name/value pair. */
static int on_header_callback(nghttp2_session *session,
const nghttp2_frame *frame,
const uint8_t *name, size_t namelen,
const uint8_t *value, size_t valuelen,
void *user_data)
{
http2_session_data *session_data = (http2_session_data*)user_data;
switch(frame->hd.type) {
static int on_header_callback(nghttp2_session *session _U_,
const nghttp2_frame *frame, const uint8_t *name,
size_t namelen, const uint8_t *value,
size_t valuelen, uint8_t flags _U_,
void *user_data) {
http2_session_data *session_data = (http2_session_data *)user_data;
switch (frame->hd.type) {
case NGHTTP2_HEADERS:
if(frame->headers.cat == NGHTTP2_HCAT_RESPONSE &&
if (frame->headers.cat == NGHTTP2_HCAT_RESPONSE &&
session_data->stream_data->stream_id == frame->hd.stream_id) {
/* Print response headers for the initiated request. */
print_header(stderr, name, namelen, value, valuelen);
@@ -233,14 +205,13 @@ static int on_header_callback(nghttp2_session *session,
/* nghttp2_on_begin_headers_callback: Called when nghttp2 library gets
started to receive header block. */
static int on_begin_headers_callback(nghttp2_session *session,
static int on_begin_headers_callback(nghttp2_session *session _U_,
const nghttp2_frame *frame,
void *user_data)
{
http2_session_data *session_data = (http2_session_data*)user_data;
switch(frame->hd.type) {
void *user_data) {
http2_session_data *session_data = (http2_session_data *)user_data;
switch (frame->hd.type) {
case NGHTTP2_HEADERS:
if(frame->headers.cat == NGHTTP2_HCAT_RESPONSE &&
if (frame->headers.cat == NGHTTP2_HCAT_RESPONSE &&
session_data->stream_data->stream_id == frame->hd.stream_id) {
fprintf(stderr, "Response headers for stream ID=%d:\n",
frame->hd.stream_id);
@@ -252,13 +223,12 @@ static int on_begin_headers_callback(nghttp2_session *session,
/* nghttp2_on_frame_recv_callback: Called when nghttp2 library
received a complete frame from the remote peer. */
static int on_frame_recv_callback(nghttp2_session *session,
const nghttp2_frame *frame, void *user_data)
{
http2_session_data *session_data = (http2_session_data*)user_data;
switch(frame->hd.type) {
static int on_frame_recv_callback(nghttp2_session *session _U_,
const nghttp2_frame *frame, void *user_data) {
http2_session_data *session_data = (http2_session_data *)user_data;
switch (frame->hd.type) {
case NGHTTP2_HEADERS:
if(frame->headers.cat == NGHTTP2_HCAT_RESPONSE &&
if (frame->headers.cat == NGHTTP2_HCAT_RESPONSE &&
session_data->stream_data->stream_id == frame->hd.stream_id) {
fprintf(stderr, "All headers received\n");
}
@@ -272,13 +242,12 @@ static int on_frame_recv_callback(nghttp2_session *session,
is meant to the stream we initiated, print the received data in
stdout, so that the user can redirect its output to the file
easily. */
static int on_data_chunk_recv_callback(nghttp2_session *session, uint8_t flags,
int32_t stream_id,
static int on_data_chunk_recv_callback(nghttp2_session *session _U_,
uint8_t flags _U_, int32_t stream_id,
const uint8_t *data, size_t len,
void *user_data)
{
http2_session_data *session_data = (http2_session_data*)user_data;
if(session_data->stream_data->stream_id == stream_id) {
void *user_data) {
http2_session_data *session_data = (http2_session_data *)user_data;
if (session_data->stream_data->stream_id == stream_id) {
fwrite(data, len, 1, stdout);
}
return 0;
@@ -288,19 +257,17 @@ static int on_data_chunk_recv_callback(nghttp2_session *session, uint8_t flags,
closed. This example program only deals with 1 HTTP request (1
stream), if it is closed, we send GOAWAY and tear down the
session */
static int on_stream_close_callback(nghttp2_session *session,
int32_t stream_id,
nghttp2_error_code error_code,
void *user_data)
{
http2_session_data *session_data = (http2_session_data*)user_data;
static int on_stream_close_callback(nghttp2_session *session, int32_t stream_id,
uint32_t error_code,
void *user_data) {
http2_session_data *session_data = (http2_session_data *)user_data;
int rv;
if(session_data->stream_data->stream_id == stream_id) {
fprintf(stderr, "Stream %d closed with error_code=%d\n",
stream_id, error_code);
if (session_data->stream_data->stream_id == stream_id) {
fprintf(stderr, "Stream %d closed with error_code=%d\n", stream_id,
error_code);
rv = nghttp2_session_terminate_session(session, NGHTTP2_NO_ERROR);
if(rv != 0) {
if (rv != 0) {
return NGHTTP2_ERR_CALLBACK_FAILURE;
}
}
@@ -308,115 +275,127 @@ static int on_stream_close_callback(nghttp2_session *session,
}
/* NPN TLS extension client callback. We check that server advertised
the HTTP/2.0 protocol the nghttp2 library supports. If not, exit
the HTTP/2 protocol the nghttp2 library supports. If not, exit
the program. */
static int select_next_proto_cb(SSL* ssl,
unsigned char **out, unsigned char *outlen,
const unsigned char *in, unsigned int inlen,
void *arg)
{
if(nghttp2_select_next_protocol(out, outlen, in, inlen) <= 0) {
static int select_next_proto_cb(SSL *ssl _U_, unsigned char **out,
unsigned char *outlen, const unsigned char *in,
unsigned int inlen, void *arg _U_) {
if (nghttp2_select_next_protocol(out, outlen, in, inlen) <= 0) {
errx(1, "Server did not advertise " NGHTTP2_PROTO_VERSION_ID);
}
return SSL_TLSEXT_ERR_OK;
}
/* Create SSL_CTX. */
static SSL_CTX* create_ssl_ctx(void)
{
static SSL_CTX *create_ssl_ctx(void) {
SSL_CTX *ssl_ctx;
ssl_ctx = SSL_CTX_new(SSLv23_client_method());
if(!ssl_ctx) {
if (!ssl_ctx) {
errx(1, "Could not create SSL/TLS context: %s",
ERR_error_string(ERR_get_error(), NULL));
}
SSL_CTX_set_options(ssl_ctx,
SSL_OP_ALL | SSL_OP_NO_SSLv2 | SSL_OP_NO_COMPRESSION |
SSL_OP_ALL | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 |
SSL_OP_NO_COMPRESSION |
SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION);
SSL_CTX_set_next_proto_select_cb(ssl_ctx, select_next_proto_cb, NULL);
return ssl_ctx;
}
/* Create SSL object */
static SSL* create_ssl(SSL_CTX *ssl_ctx)
{
static SSL *create_ssl(SSL_CTX *ssl_ctx) {
SSL *ssl;
ssl = SSL_new(ssl_ctx);
if(!ssl) {
if (!ssl) {
errx(1, "Could not create SSL/TLS session object: %s",
ERR_error_string(ERR_get_error(), NULL));
}
return ssl;
}
static void initialize_nghttp2_session(http2_session_data *session_data)
{
nghttp2_session_callbacks callbacks = {0};
static void initialize_nghttp2_session(http2_session_data *session_data) {
nghttp2_session_callbacks *callbacks;
callbacks.send_callback = send_callback;
callbacks.before_frame_send_callback = before_frame_send_callback;
callbacks.on_frame_recv_callback = on_frame_recv_callback;
callbacks.on_data_chunk_recv_callback = on_data_chunk_recv_callback;
callbacks.on_stream_close_callback = on_stream_close_callback;
callbacks.on_header_callback = on_header_callback;
callbacks.on_begin_headers_callback = on_begin_headers_callback;
nghttp2_session_client_new(&session_data->session, &callbacks, session_data);
nghttp2_session_callbacks_new(&callbacks);
nghttp2_session_callbacks_set_send_callback(callbacks, send_callback);
nghttp2_session_callbacks_set_on_frame_recv_callback(callbacks,
on_frame_recv_callback);
nghttp2_session_callbacks_set_on_data_chunk_recv_callback(
callbacks, on_data_chunk_recv_callback);
nghttp2_session_callbacks_set_on_stream_close_callback(
callbacks, on_stream_close_callback);
nghttp2_session_callbacks_set_on_header_callback(callbacks,
on_header_callback);
nghttp2_session_callbacks_set_on_begin_headers_callback(
callbacks, on_begin_headers_callback);
nghttp2_session_client_new(&session_data->session, callbacks, session_data);
nghttp2_session_callbacks_del(callbacks);
}
static void send_client_connection_header(http2_session_data *session_data)
{
static void send_client_connection_header(http2_session_data *session_data) {
nghttp2_settings_entry iv[1] = {
{ NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS, 100 }
};
{NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS, 100}};
int rv;
bufferevent_write(session_data->bev,
NGHTTP2_CLIENT_CONNECTION_HEADER,
NGHTTP2_CLIENT_CONNECTION_HEADER_LEN);
rv = nghttp2_submit_settings(session_data->session, NGHTTP2_FLAG_NONE,
iv, ARRLEN(iv));
if(rv != 0) {
bufferevent_write(session_data->bev, NGHTTP2_CLIENT_CONNECTION_PREFACE,
NGHTTP2_CLIENT_CONNECTION_PREFACE_LEN);
rv = nghttp2_submit_settings(session_data->session, NGHTTP2_FLAG_NONE, iv,
ARRLEN(iv));
if (rv != 0) {
errx(1, "Could not submit SETTINGS: %s", nghttp2_strerror(rv));
}
}
#define MAKE_NV(NAME, VALUE, VALUELEN) \
{ (uint8_t*)NAME, (uint8_t*)VALUE, sizeof(NAME) - 1, VALUELEN }
{ \
(uint8_t *) NAME, (uint8_t *)VALUE, sizeof(NAME) - 1, VALUELEN, \
NGHTTP2_NV_FLAG_NONE \
}
#define MAKE_NV2(NAME, VALUE) \
{ (uint8_t*)NAME, (uint8_t*)VALUE, sizeof(NAME) - 1, sizeof(VALUE) - 1 }
{ \
(uint8_t *) NAME, (uint8_t *)VALUE, sizeof(NAME) - 1, sizeof(VALUE) - 1, \
NGHTTP2_NV_FLAG_NONE \
}
/* Send HTTP request to the remote peer */
static void submit_request(http2_session_data *session_data)
{
int rv;
static void submit_request(http2_session_data *session_data) {
int32_t stream_id;
http2_stream_data *stream_data = session_data->stream_data;
const char *uri = stream_data->uri;
const struct http_parser_url *u = stream_data->u;
nghttp2_nv hdrs[] = {
MAKE_NV2(":method", "GET"),
MAKE_NV(":scheme",
&uri[u->field_data[UF_SCHEMA].off], u->field_data[UF_SCHEMA].len),
MAKE_NV(":scheme", &uri[u->field_data[UF_SCHEMA].off],
u->field_data[UF_SCHEMA].len),
MAKE_NV(":authority", stream_data->authority, stream_data->authoritylen),
MAKE_NV(":path", stream_data->path, stream_data->pathlen)
};
MAKE_NV(":path", stream_data->path, stream_data->pathlen)};
fprintf(stderr, "Request headers:\n");
print_headers(stderr, hdrs, ARRLEN(hdrs));
rv = nghttp2_submit_request(session_data->session, NGHTTP2_PRI_DEFAULT,
hdrs, ARRLEN(hdrs), NULL, stream_data);
if(rv != 0) {
errx(1, "Could not submit HTTP request: %s", nghttp2_strerror(rv));
stream_id = nghttp2_submit_request(session_data->session, NULL, hdrs,
ARRLEN(hdrs), NULL, stream_data);
if (stream_id < 0) {
errx(1, "Could not submit HTTP request: %s", nghttp2_strerror(stream_id));
}
stream_data->stream_id = stream_id;
}
/* Serialize the frame and send (or buffer) the data to
bufferevent. */
static int session_send(http2_session_data *session_data)
{
static int session_send(http2_session_data *session_data) {
int rv;
rv = nghttp2_session_send(session_data->session);
if(rv != 0) {
if (rv != 0) {
warnx("Fatal error: %s", nghttp2_strerror(rv));
return -1;
}
@@ -427,21 +406,25 @@ static int session_send(http2_session_data *session_data)
of bufferevent and feed them to nghttp2 library. This may invoke
nghttp2 callbacks. It may also queues the frame in nghttp2 session
context. To send them, we call session_send() in the end. */
static void readcb(struct bufferevent *bev, void *ptr)
{
http2_session_data *session_data = (http2_session_data*)ptr;
int rv;
static void readcb(struct bufferevent *bev, void *ptr) {
http2_session_data *session_data = (http2_session_data *)ptr;
ssize_t readlen;
struct evbuffer *input = bufferevent_get_input(bev);
size_t datalen = evbuffer_get_length(input);
unsigned char *data = evbuffer_pullup(input, -1);
rv = nghttp2_session_mem_recv(session_data->session, data, datalen);
if(rv < 0) {
warnx("Fatal error: %s", nghttp2_strerror(rv));
readlen = nghttp2_session_mem_recv(session_data->session, data, datalen);
if (readlen < 0) {
warnx("Fatal error: %s", nghttp2_strerror((int)readlen));
delete_http2_session_data(session_data);
return;
}
evbuffer_drain(input, rv);
if(session_send(session_data) != 0) {
if (evbuffer_drain(input, readlen) != 0) {
warnx("Fatal error: evbuffer_drain failed");
delete_http2_session_data(session_data);
return;
}
if (session_send(session_data) != 0) {
delete_http2_session_data(session_data);
return;
}
@@ -451,10 +434,9 @@ static void readcb(struct bufferevent *bev, void *ptr)
receiving GOAWAY, we check the some conditions on the nghttp2
library and output buffer of bufferevent. If it indicates we have
no business to this session, tear down the connection. */
static void writecb(struct bufferevent *bev, void *ptr)
{
http2_session_data *session_data = (http2_session_data*)ptr;
if(nghttp2_session_want_read(session_data->session) == 0 &&
static void writecb(struct bufferevent *bev _U_, void *ptr) {
http2_session_data *session_data = (http2_session_data *)ptr;
if (nghttp2_session_want_read(session_data->session) == 0 &&
nghttp2_session_want_write(session_data->session) == 0 &&
evbuffer_get_length(bufferevent_get_output(session_data->bev)) == 0) {
delete_http2_session_data(session_data);
@@ -466,10 +448,9 @@ static void writecb(struct bufferevent *bev, void *ptr)
peer verification. After SSL/TLS handshake is over, initialize
nghttp2 library session, and send client connection header. Then
send HTTP request. */
static void eventcb(struct bufferevent *bev, short events, void *ptr)
{
http2_session_data *session_data = (http2_session_data*)ptr;
if(events & BEV_EVENT_CONNECTED) {
static void eventcb(struct bufferevent *bev, short events, void *ptr) {
http2_session_data *session_data = (http2_session_data *)ptr;
if (events & BEV_EVENT_CONNECTED) {
int fd = bufferevent_getfd(bev);
int val = 1;
fprintf(stderr, "Connected\n");
@@ -477,41 +458,38 @@ static void eventcb(struct bufferevent *bev, short events, void *ptr)
initialize_nghttp2_session(session_data);
send_client_connection_header(session_data);
submit_request(session_data);
if(session_send(session_data) != 0) {
if (session_send(session_data) != 0) {
delete_http2_session_data(session_data);
}
return;
}
if(events & BEV_EVENT_EOF) {
if (events & BEV_EVENT_EOF) {
warnx("Disconnected from the remote host");
} else if(events & BEV_EVENT_ERROR) {
} else if (events & BEV_EVENT_ERROR) {
warnx("Network error");
} else if(events & BEV_EVENT_TIMEOUT) {
} else if (events & BEV_EVENT_TIMEOUT) {
warnx("Timeout");
}
delete_http2_session_data(session_data);
}
/* Start connecting to the remote peer |host:port| */
static void initiate_connection(struct event_base *evbase,
SSL_CTX *ssl_ctx,
static void initiate_connection(struct event_base *evbase, SSL_CTX *ssl_ctx,
const char *host, uint16_t port,
http2_session_data *session_data)
{
http2_session_data *session_data) {
int rv;
struct bufferevent *bev;
SSL *ssl;
ssl = create_ssl(ssl_ctx);
bev = bufferevent_openssl_socket_new(evbase, -1, ssl,
BUFFEREVENT_SSL_CONNECTING,
BEV_OPT_DEFER_CALLBACKS |
BEV_OPT_CLOSE_ON_FREE);
bev = bufferevent_openssl_socket_new(
evbase, -1, ssl, BUFFEREVENT_SSL_CONNECTING,
BEV_OPT_DEFER_CALLBACKS | BEV_OPT_CLOSE_ON_FREE);
bufferevent_setcb(bev, readcb, writecb, eventcb, session_data);
rv = bufferevent_socket_connect_hostname(bev, session_data->dnsbase,
AF_UNSPEC, host, port);
if(rv != 0) {
if (rv != 0) {
errx(1, "Could not connect to the remote host %s", host);
}
session_data->bev = bev;
@@ -519,8 +497,7 @@ static void initiate_connection(struct event_base *evbase,
/* Get resource denoted by the |uri|. The debug and error messages are
printed in stderr, while the response body is printed in stdout. */
static void run(const char *uri)
{
static void run(const char *uri) {
struct http_parser_url u;
char *host;
uint16_t port;
@@ -531,11 +508,11 @@ static void run(const char *uri)
/* Parse the |uri| and stores its components in |u| */
rv = http_parser_parse_url(uri, strlen(uri), 0, &u);
if(rv != 0) {
if (rv != 0) {
errx(1, "Could not parse URI %s", uri);
}
host = strndup(&uri[u.field_data[UF_HOST].off], u.field_data[UF_HOST].len);
if(!(u.field_set & (1 << UF_PORT))) {
if (!(u.field_set & (1 << UF_PORT))) {
port = 443;
} else {
port = u.port;
@@ -558,11 +535,10 @@ static void run(const char *uri)
SSL_CTX_free(ssl_ctx);
}
int main(int argc, char **argv)
{
int main(int argc, char **argv) {
struct sigaction act;
if(argc < 2) {
if (argc < 2) {
fprintf(stderr, "Usage: libevent-client HTTPS_URI\n");
exit(EXIT_FAILURE);
}
@@ -571,6 +547,8 @@ int main(int argc, char **argv)
act.sa_handler = SIG_IGN;
sigaction(SIGPIPE, &act, NULL);
OPENSSL_config(NULL);
OpenSSL_add_all_algorithms();
SSL_load_error_strings();
SSL_library_init();

View File

@@ -1,5 +1,5 @@
/*
* nghttp2 - HTTP/2.0 C Library
* nghttp2 - HTTP/2 C Library
*
* Copyright (c) 2013 Tatsuhiro Tsujikawa
*
@@ -22,6 +22,10 @@
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif /* !HAVE_CONFIG_H */
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
@@ -36,6 +40,7 @@
#include <openssl/ssl.h>
#include <openssl/err.h>
#include <openssl/conf.h>
#include <event.h>
#include <event2/event.h>
@@ -46,10 +51,13 @@
#define OUTPUT_WOULDBLOCK_THRESHOLD (1 << 16)
#define ARRLEN(x) (sizeof(x)/sizeof(x[0]))
#define ARRLEN(x) (sizeof(x) / sizeof(x[0]))
#define MAKE_NV(NAME, VALUE) \
{ (uint8_t*)NAME, (uint8_t*)VALUE, sizeof(NAME) - 1, sizeof(VALUE) - 1 }
{ \
(uint8_t *) NAME, (uint8_t *)VALUE, sizeof(NAME) - 1, sizeof(VALUE) - 1, \
NGHTTP2_NV_FLAG_NONE \
}
struct app_context;
typedef struct app_context app_context;
@@ -67,7 +75,6 @@ typedef struct http2_session_data {
app_context *app_ctx;
nghttp2_session *session;
char *client_addr;
size_t handshake_leftlen;
} http2_session_data;
struct app_context {
@@ -78,32 +85,40 @@ struct app_context {
static unsigned char next_proto_list[256];
static size_t next_proto_list_len;
static int next_proto_cb(SSL *s, const unsigned char **data, unsigned int *len,
void *arg)
{
static int next_proto_cb(SSL *s _U_, const unsigned char **data,
unsigned int *len, void *arg _U_) {
*data = next_proto_list;
*len = next_proto_list_len;
*len = (unsigned int)next_proto_list_len;
return SSL_TLSEXT_ERR_OK;
}
/* Create SSL_CTX. */
static SSL_CTX* create_ssl_ctx(const char *key_file, const char *cert_file)
{
static SSL_CTX *create_ssl_ctx(const char *key_file, const char *cert_file) {
SSL_CTX *ssl_ctx;
EC_KEY *ecdh;
ssl_ctx = SSL_CTX_new(SSLv23_server_method());
if(!ssl_ctx) {
if (!ssl_ctx) {
errx(1, "Could not create SSL/TLS context: %s",
ERR_error_string(ERR_get_error(), NULL));
}
SSL_CTX_set_options(ssl_ctx,
SSL_OP_ALL | SSL_OP_NO_SSLv2 | SSL_OP_NO_COMPRESSION |
SSL_OP_ALL | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 |
SSL_OP_NO_COMPRESSION |
SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION);
if(SSL_CTX_use_PrivateKey_file(ssl_ctx, key_file,
SSL_FILETYPE_PEM) != 1) {
ecdh = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
if (!ecdh) {
errx(1, "EC_KEY_new_by_curv_name failed: %s",
ERR_error_string(ERR_get_error(), NULL));
}
SSL_CTX_set_tmp_ecdh(ssl_ctx, ecdh);
EC_KEY_free(ecdh);
if (SSL_CTX_use_PrivateKey_file(ssl_ctx, key_file, SSL_FILETYPE_PEM) != 1) {
errx(1, "Could not read private key file %s", key_file);
}
if(SSL_CTX_use_certificate_chain_file(ssl_ctx, cert_file) != 1) {
if (SSL_CTX_use_certificate_chain_file(ssl_ctx, cert_file) != 1) {
errx(1, "Could not read certificate file %s", cert_file);
}
@@ -117,11 +132,10 @@ static SSL_CTX* create_ssl_ctx(const char *key_file, const char *cert_file)
}
/* Create SSL object */
static SSL* create_ssl(SSL_CTX *ssl_ctx)
{
static SSL *create_ssl(SSL_CTX *ssl_ctx) {
SSL *ssl;
ssl = SSL_new(ssl_ctx);
if(!ssl) {
if (!ssl) {
errx(1, "Could not create SSL/TLS session object: %s",
ERR_error_string(ERR_get_error(), NULL));
}
@@ -129,28 +143,25 @@ static SSL* create_ssl(SSL_CTX *ssl_ctx)
}
static void add_stream(http2_session_data *session_data,
http2_stream_data *stream_data)
{
http2_stream_data *stream_data) {
stream_data->next = session_data->root.next;
session_data->root.next = stream_data;
stream_data->prev = &session_data->root;
if(stream_data->next) {
if (stream_data->next) {
stream_data->next->prev = stream_data;
}
}
static void remove_stream(http2_session_data *session_data,
http2_stream_data *stream_data)
{
static void remove_stream(http2_session_data *session_data _U_,
http2_stream_data *stream_data) {
stream_data->prev->next = stream_data->next;
if(stream_data->next) {
if (stream_data->next) {
stream_data->next->prev = stream_data->prev;
}
}
static http2_stream_data* create_http2_stream_data
(http2_session_data *session_data, int32_t stream_id)
{
static http2_stream_data *
create_http2_stream_data(http2_session_data *session_data, int32_t stream_id) {
http2_stream_data *stream_data;
stream_data = malloc(sizeof(http2_stream_data));
memset(stream_data, 0, sizeof(http2_stream_data));
@@ -161,20 +172,18 @@ static http2_stream_data* create_http2_stream_data
return stream_data;
}
static void delete_http2_stream_data(http2_stream_data *stream_data)
{
if(stream_data->fd != -1) {
static void delete_http2_stream_data(http2_stream_data *stream_data) {
if (stream_data->fd != -1) {
close(stream_data->fd);
}
free(stream_data->request_path);
free(stream_data);
}
static http2_session_data* create_http2_session_data(app_context *app_ctx,
static http2_session_data *create_http2_session_data(app_context *app_ctx,
int fd,
struct sockaddr *addr,
int addrlen)
{
int addrlen) {
int rv;
http2_session_data *session_data;
SSL *ssl;
@@ -186,13 +195,11 @@ static http2_session_data* create_http2_session_data(app_context *app_ctx,
memset(session_data, 0, sizeof(http2_session_data));
session_data->app_ctx = app_ctx;
setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char *)&val, sizeof(val));
session_data->bev = bufferevent_openssl_socket_new
(app_ctx->evbase, fd, ssl,
BUFFEREVENT_SSL_ACCEPTING,
session_data->bev = bufferevent_openssl_socket_new(
app_ctx->evbase, fd, ssl, BUFFEREVENT_SSL_ACCEPTING,
BEV_OPT_CLOSE_ON_FREE | BEV_OPT_DEFER_CALLBACKS);
session_data->handshake_leftlen = NGHTTP2_CLIENT_CONNECTION_HEADER_LEN;
rv = getnameinfo(addr, addrlen, host, sizeof(host), NULL, 0, NI_NUMERICHOST);
if(rv != 0) {
if (rv != 0) {
session_data->client_addr = strdup("(unknown)");
} else {
session_data->client_addr = strdup(host);
@@ -201,17 +208,16 @@ static http2_session_data* create_http2_session_data(app_context *app_ctx,
return session_data;
}
static void delete_http2_session_data(http2_session_data *session_data)
{
static void delete_http2_session_data(http2_session_data *session_data) {
http2_stream_data *stream_data;
SSL *ssl = bufferevent_openssl_get_ssl(session_data->bev);
fprintf(stderr, "%s disconnected\n", session_data->client_addr);
if(ssl) {
if (ssl) {
SSL_shutdown(ssl);
}
bufferevent_free(session_data->bev);
nghttp2_session_del(session_data->session);
for(stream_data = session_data->root.next; stream_data;) {
for (stream_data = session_data->root.next; stream_data;) {
http2_stream_data *next = stream_data->next;
delete_http2_stream_data(stream_data);
stream_data = next;
@@ -222,11 +228,10 @@ static void delete_http2_session_data(http2_session_data *session_data)
/* Serialize the frame and send (or buffer) the data to
bufferevent. */
static int session_send(http2_session_data *session_data)
{
static int session_send(http2_session_data *session_data) {
int rv;
rv = nghttp2_session_send(session_data->session);
if(rv != 0) {
if (rv != 0) {
warnx("Fatal error: %s", nghttp2_strerror(rv));
return -1;
}
@@ -237,32 +242,33 @@ static int session_send(http2_session_data *session_data)
function. Invocation of nghttp2_session_mem_recv() may make
additional pending frames, so call session_send() at the end of the
function. */
static int session_recv(http2_session_data *session_data)
{
int rv;
static int session_recv(http2_session_data *session_data) {
ssize_t readlen;
struct evbuffer *input = bufferevent_get_input(session_data->bev);
size_t datalen = evbuffer_get_length(input);
unsigned char *data = evbuffer_pullup(input, -1);
rv = nghttp2_session_mem_recv(session_data->session, data, datalen);
if(rv < 0) {
warnx("Fatal error: %s", nghttp2_strerror(rv));
readlen = nghttp2_session_mem_recv(session_data->session, data, datalen);
if (readlen < 0) {
warnx("Fatal error: %s", nghttp2_strerror((int)readlen));
return -1;
}
evbuffer_drain(input, rv);
if(session_send(session_data) != 0) {
if (evbuffer_drain(input, readlen) != 0) {
warnx("Fatal error: evbuffer_drain failed");
return -1;
}
if (session_send(session_data) != 0) {
return -1;
}
return 0;
}
static ssize_t send_callback(nghttp2_session *session,
const uint8_t *data, size_t length,
int flags, void *user_data)
{
http2_session_data *session_data = (http2_session_data*)user_data;
static ssize_t send_callback(nghttp2_session *session _U_, const uint8_t *data,
size_t length, int flags _U_, void *user_data) {
http2_session_data *session_data = (http2_session_data *)user_data;
struct bufferevent *bev = session_data->bev;
/* Avoid excessive buffering in server side. */
if(evbuffer_get_length(bufferevent_get_output(session_data->bev)) >=
if (evbuffer_get_length(bufferevent_get_output(session_data->bev)) >=
OUTPUT_WOULDBLOCK_THRESHOLD) {
return NGHTTP2_ERR_WOULDBLOCK;
}
@@ -271,26 +277,24 @@ static ssize_t send_callback(nghttp2_session *session,
}
/* Returns nonzero if the string |s| ends with the substring |sub| */
static int ends_with(const char *s, const char *sub)
{
static int ends_with(const char *s, const char *sub) {
size_t slen = strlen(s);
size_t sublen = strlen(sub);
if(slen < sublen) {
if (slen < sublen) {
return 0;
}
return memcmp(s + slen - sublen, sub, sublen) == 0;
}
/* Returns int value of hex string character |c| */
static uint8_t hex_to_uint(uint8_t c)
{
if('0' <= c && c <= '9') {
static uint8_t hex_to_uint(uint8_t c) {
if ('0' <= c && c <= '9') {
return c - '0';
}
if('A' <= c && c <= 'F') {
if ('A' <= c && c <= 'F') {
return c - 'A' + 10;
}
if('a' <= c && c <= 'f') {
if ('a' <= c && c <= 'f') {
return c - 'a' + 10;
}
return 0;
@@ -300,16 +304,15 @@ static uint8_t hex_to_uint(uint8_t c)
and returns the decoded byte string in allocated buffer. The return
value is NULL terminated. The caller must free the returned
string. */
static char* percent_decode(const uint8_t *value, size_t valuelen)
{
static char *percent_decode(const uint8_t *value, size_t valuelen) {
char *res;
res = malloc(valuelen + 1);
if(valuelen > 3) {
if (valuelen > 3) {
size_t i, j;
for(i = 0, j = 0; i < valuelen - 2;) {
if(value[i] != '%' ||
!isxdigit(value[i + 1]) || !isxdigit(value[i + 2])) {
for (i = 0, j = 0; i < valuelen - 2;) {
if (value[i] != '%' || !isxdigit(value[i + 1]) ||
!isxdigit(value[i + 2])) {
res[j++] = value[i++];
continue;
}
@@ -325,33 +328,33 @@ static char* percent_decode(const uint8_t *value, size_t valuelen)
return res;
}
static ssize_t file_read_callback
(nghttp2_session *session, int32_t stream_id,
uint8_t *buf, size_t length, int *eof,
nghttp2_data_source *source, void *user_data)
{
static ssize_t file_read_callback(nghttp2_session *session _U_,
int32_t stream_id _U_, uint8_t *buf,
size_t length, uint32_t *data_flags,
nghttp2_data_source *source,
void *user_data _U_) {
int fd = source->fd;
ssize_t r;
while((r = read(fd, buf, length)) == -1 && errno == EINTR);
if(r == -1) {
while ((r = read(fd, buf, length)) == -1 && errno == EINTR)
;
if (r == -1) {
return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
}
if(r == 0) {
*eof = 1;
if (r == 0) {
*data_flags |= NGHTTP2_DATA_FLAG_EOF;
}
return r;
}
static int send_response(nghttp2_session *session, int32_t stream_id,
nghttp2_nv *nva, size_t nvlen, int fd)
{
nghttp2_nv *nva, size_t nvlen, int fd) {
int rv;
nghttp2_data_provider data_prd;
data_prd.source.fd = fd;
data_prd.read_callback = file_read_callback;
rv = nghttp2_submit_response(session, stream_id, nva, nvlen, &data_prd);
if(rv != 0) {
if (rv != 0) {
warnx("Fatal error: %s", nghttp2_strerror(rv));
return -1;
}
@@ -362,30 +365,36 @@ const char ERROR_HTML[] = "<html><head><title>404</title></head>"
"<body><h1>404 Not Found</h1></body></html>";
static int error_reply(nghttp2_session *session,
http2_stream_data *stream_data)
{
http2_stream_data *stream_data) {
int rv;
ssize_t writelen;
int pipefd[2];
nghttp2_nv hdrs[] = {
MAKE_NV(":status", "404")
};
nghttp2_nv hdrs[] = {MAKE_NV(":status", "404")};
rv = pipe(pipefd);
if(rv != 0) {
if (rv != 0) {
warn("Could not create pipe");
rv = nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE,
stream_data->stream_id,
NGHTTP2_INTERNAL_ERROR);
if(rv != 0) {
if (rv != 0) {
warnx("Fatal error: %s", nghttp2_strerror(rv));
return -1;
}
return 0;
}
write(pipefd[1], ERROR_HTML, sizeof(ERROR_HTML) - 1);
writelen = write(pipefd[1], ERROR_HTML, sizeof(ERROR_HTML) - 1);
close(pipefd[1]);
if (writelen != sizeof(ERROR_HTML) - 1) {
close(pipefd[0]);
return -1;
}
stream_data->fd = pipefd[0];
if(send_response(session, stream_data->stream_id, hdrs, ARRLEN(hdrs),
if (send_response(session, stream_data->stream_id, hdrs, ARRLEN(hdrs),
pipefd[0]) != 0) {
close(pipefd[0]);
return -1;
@@ -396,26 +405,26 @@ static int error_reply(nghttp2_session *session,
/* nghttp2_on_header_callback: Called when nghttp2 library emits
single header name/value pair. */
static int on_header_callback(nghttp2_session *session,
const nghttp2_frame *frame,
const uint8_t *name, size_t namelen,
const uint8_t *value, size_t valuelen,
void *user_data)
{
const nghttp2_frame *frame, const uint8_t *name,
size_t namelen, const uint8_t *value,
size_t valuelen, uint8_t flags _U_,
void *user_data _U_) {
http2_stream_data *stream_data;
const char PATH[] = ":path";
switch(frame->hd.type) {
switch (frame->hd.type) {
case NGHTTP2_HEADERS:
if(frame->headers.cat != NGHTTP2_HCAT_REQUEST) {
if (frame->headers.cat != NGHTTP2_HCAT_REQUEST) {
break;
}
stream_data = nghttp2_session_get_stream_user_data(session,
frame->hd.stream_id);
if(stream_data->request_path) {
stream_data =
nghttp2_session_get_stream_user_data(session, frame->hd.stream_id);
if (!stream_data || stream_data->request_path) {
break;
}
if(namelen == sizeof(PATH) - 1 && memcmp(PATH, name, namelen) == 0) {
if (namelen == sizeof(PATH) - 1 && memcmp(PATH, name, namelen) == 0) {
size_t j;
for(j = 0; j < valuelen && value[j] != '?'; ++j);
for (j = 0; j < valuelen && value[j] != '?'; ++j)
;
stream_data->request_path = percent_decode(value, j);
}
break;
@@ -425,12 +434,11 @@ static int on_header_callback(nghttp2_session *session,
static int on_begin_headers_callback(nghttp2_session *session,
const nghttp2_frame *frame,
void *user_data)
{
http2_session_data *session_data = (http2_session_data*)user_data;
void *user_data) {
http2_session_data *session_data = (http2_session_data *)user_data;
http2_stream_data *stream_data;
if(frame->hd.type != NGHTTP2_HEADERS ||
if (frame->hd.type != NGHTTP2_HEADERS ||
frame->headers.cat != NGHTTP2_HCAT_REQUEST) {
return 0;
}
@@ -442,52 +450,47 @@ static int on_begin_headers_callback(nghttp2_session *session,
/* Minimum check for directory traversal. Returns nonzero if it is
safe. */
static int check_path(const char *path)
{
static int check_path(const char *path) {
/* We don't like '\' in url. */
return path[0] && path[0] == '/' &&
strchr(path, '\\') == NULL &&
strstr(path, "/../") == NULL &&
strstr(path, "/./") == NULL &&
return path[0] && path[0] == '/' && strchr(path, '\\') == NULL &&
strstr(path, "/../") == NULL && strstr(path, "/./") == NULL &&
!ends_with(path, "/..") && !ends_with(path, "/.");
}
static int on_request_recv(nghttp2_session *session,
http2_session_data *session_data,
http2_stream_data *stream_data)
{
http2_stream_data *stream_data) {
int fd;
nghttp2_nv hdrs[] = {
MAKE_NV(":status", "200")
};
nghttp2_nv hdrs[] = {MAKE_NV(":status", "200")};
char *rel_path;
if(!stream_data->request_path) {
if(error_reply(session, stream_data) != 0) {
if (!stream_data->request_path) {
if (error_reply(session, stream_data) != 0) {
return NGHTTP2_ERR_CALLBACK_FAILURE;
}
return 0;
}
fprintf(stderr, "%s GET %s\n", session_data->client_addr,
stream_data->request_path);
if(!check_path(stream_data->request_path)) {
if(error_reply(session, stream_data) != 0) {
if (!check_path(stream_data->request_path)) {
if (error_reply(session, stream_data) != 0) {
return NGHTTP2_ERR_CALLBACK_FAILURE;
}
return 0;
}
for(rel_path = stream_data->request_path; *rel_path == '/'; ++rel_path);
for (rel_path = stream_data->request_path; *rel_path == '/'; ++rel_path)
;
fd = open(rel_path, O_RDONLY);
if(fd == -1) {
if(error_reply(session, stream_data) != 0) {
if (fd == -1) {
if (error_reply(session, stream_data) != 0) {
return NGHTTP2_ERR_CALLBACK_FAILURE;
}
return 0;
}
stream_data->fd = fd;
if(send_response(session, stream_data->stream_id, hdrs,
ARRLEN(hdrs), fd) != 0) {
if (send_response(session, stream_data->stream_id, hdrs, ARRLEN(hdrs), fd) !=
0) {
close(fd);
return NGHTTP2_ERR_CALLBACK_FAILURE;
}
@@ -495,20 +498,19 @@ static int on_request_recv(nghttp2_session *session,
}
static int on_frame_recv_callback(nghttp2_session *session,
const nghttp2_frame *frame, void *user_data)
{
http2_session_data *session_data = (http2_session_data*)user_data;
const nghttp2_frame *frame, void *user_data) {
http2_session_data *session_data = (http2_session_data *)user_data;
http2_stream_data *stream_data;
switch(frame->hd.type) {
switch (frame->hd.type) {
case NGHTTP2_DATA:
case NGHTTP2_HEADERS:
/* Check that the client request has finished */
if(frame->hd.flags & NGHTTP2_FLAG_END_STREAM) {
stream_data = nghttp2_session_get_stream_user_data(session,
frame->hd.stream_id);
if (frame->hd.flags & NGHTTP2_FLAG_END_STREAM) {
stream_data =
nghttp2_session_get_stream_user_data(session, frame->hd.stream_id);
/* For DATA and HEADERS frame, this callback may be called after
on_stream_close_callback. Check that stream still alive. */
if(!stream_data) {
if (!stream_data) {
return 0;
}
return on_request_recv(session, session_data, stream_data);
@@ -520,44 +522,63 @@ static int on_frame_recv_callback(nghttp2_session *session,
return 0;
}
static int on_stream_close_callback(nghttp2_session *session,
int32_t stream_id,
nghttp2_error_code error_code,
void *user_data)
{
http2_session_data *session_data = (http2_session_data*)user_data;
static int on_stream_close_callback(nghttp2_session *session, int32_t stream_id,
uint32_t error_code _U_, void *user_data) {
http2_session_data *session_data = (http2_session_data *)user_data;
http2_stream_data *stream_data;
stream_data = nghttp2_session_get_stream_user_data(session, stream_id);
if (!stream_data) {
return 0;
}
remove_stream(session_data, stream_data);
delete_http2_stream_data(stream_data);
return 0;
}
static void initialize_nghttp2_session(http2_session_data *session_data)
{
nghttp2_session_callbacks callbacks = {0};
static void initialize_nghttp2_session(http2_session_data *session_data) {
nghttp2_option *option;
nghttp2_session_callbacks *callbacks;
callbacks.send_callback = send_callback;
callbacks.on_frame_recv_callback = on_frame_recv_callback;
callbacks.on_stream_close_callback = on_stream_close_callback;
callbacks.on_header_callback = on_header_callback;
callbacks.on_begin_headers_callback = on_begin_headers_callback;
nghttp2_session_server_new(&session_data->session, &callbacks, session_data);
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_set_send_callback(callbacks, send_callback);
nghttp2_session_callbacks_set_on_frame_recv_callback(callbacks,
on_frame_recv_callback);
nghttp2_session_callbacks_set_on_stream_close_callback(
callbacks, on_stream_close_callback);
nghttp2_session_callbacks_set_on_header_callback(callbacks,
on_header_callback);
nghttp2_session_callbacks_set_on_begin_headers_callback(
callbacks, on_begin_headers_callback);
nghttp2_session_server_new2(&session_data->session, callbacks, session_data,
option);
nghttp2_session_callbacks_del(callbacks);
nghttp2_option_del(option);
}
/* Send HTTP/2.0 client connection header, which includes 24 bytes
/* Send HTTP/2 client connection header, which includes 24 bytes
magic octets and SETTINGS frame */
static int send_server_connection_header(http2_session_data *session_data)
{
static int send_server_connection_header(http2_session_data *session_data) {
nghttp2_settings_entry iv[1] = {
{ NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS, 100 }
};
{NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS, 100}};
int rv;
rv = nghttp2_submit_settings(session_data->session, NGHTTP2_FLAG_NONE,
iv, ARRLEN(iv));
if(rv != 0) {
rv = nghttp2_submit_settings(session_data->session, NGHTTP2_FLAG_NONE, iv,
ARRLEN(iv));
if (rv != 0) {
warnx("Fatal error: %s", nghttp2_strerror(rv));
return -1;
}
@@ -566,10 +587,9 @@ static int send_server_connection_header(http2_session_data *session_data)
/* readcb for bufferevent after client connection header was
checked. */
static void readcb(struct bufferevent *bev, void *ptr)
{
http2_session_data *session_data = (http2_session_data*)ptr;
if(session_recv(session_data) != 0) {
static void readcb(struct bufferevent *bev _U_, void *ptr) {
http2_session_data *session_data = (http2_session_data *)ptr;
if (session_recv(session_data) != 0) {
delete_http2_session_data(session_data);
return;
}
@@ -583,88 +603,60 @@ static void readcb(struct bufferevent *bev, void *ptr)
process pending data in the output buffer. This is necessary
because we have a threshold on the buffer size to avoid too much
buffering. See send_callback(). */
static void writecb(struct bufferevent *bev, void *ptr)
{
http2_session_data *session_data = (http2_session_data*)ptr;
if(evbuffer_get_length(bufferevent_get_output(bev)) > 0) {
static void writecb(struct bufferevent *bev, void *ptr) {
http2_session_data *session_data = (http2_session_data *)ptr;
if (evbuffer_get_length(bufferevent_get_output(bev)) > 0) {
return;
}
if(nghttp2_session_want_read(session_data->session) == 0 &&
if (nghttp2_session_want_read(session_data->session) == 0 &&
nghttp2_session_want_write(session_data->session) == 0) {
delete_http2_session_data(session_data);
return;
}
if(session_send(session_data) != 0) {
if (session_send(session_data) != 0) {
delete_http2_session_data(session_data);
return;
}
}
/* eventcb for bufferevent */
static void eventcb(struct bufferevent *bev, short events, void *ptr)
{
http2_session_data *session_data = (http2_session_data*)ptr;
if(events & BEV_EVENT_CONNECTED) {
static void eventcb(struct bufferevent *bev _U_, short events, void *ptr) {
http2_session_data *session_data = (http2_session_data *)ptr;
if (events & BEV_EVENT_CONNECTED) {
fprintf(stderr, "%s connected\n", session_data->client_addr);
initialize_nghttp2_session(session_data);
if (send_server_connection_header(session_data) != 0) {
delete_http2_session_data(session_data);
return;
}
if(events & BEV_EVENT_EOF) {
return;
}
if (events & BEV_EVENT_EOF) {
fprintf(stderr, "%s EOF\n", session_data->client_addr);
} else if(events & BEV_EVENT_ERROR) {
} else if (events & BEV_EVENT_ERROR) {
fprintf(stderr, "%s network error\n", session_data->client_addr);
} else if(events & BEV_EVENT_TIMEOUT) {
} else if (events & BEV_EVENT_TIMEOUT) {
fprintf(stderr, "%s timeout\n", session_data->client_addr);
}
delete_http2_session_data(session_data);
}
/* readcb for bufferevent to check first 24 bytes client connection
header. */
static void handshake_readcb(struct bufferevent *bev, void *ptr)
{
http2_session_data *session_data = (http2_session_data*)ptr;
uint8_t data[24];
struct evbuffer *input = bufferevent_get_input(session_data->bev);
int readlen = evbuffer_remove(input, data, session_data->handshake_leftlen);
const char *conhead = NGHTTP2_CLIENT_CONNECTION_HEADER;
if(memcmp(conhead + NGHTTP2_CLIENT_CONNECTION_HEADER_LEN
- session_data->handshake_leftlen, data, readlen) != 0) {
delete_http2_session_data(session_data);
return;
}
session_data->handshake_leftlen -= readlen;
if(session_data->handshake_leftlen == 0) {
bufferevent_setcb(session_data->bev, readcb, writecb, eventcb, ptr);
/* Process pending data in buffer since they are not notified
further */
initialize_nghttp2_session(session_data);
if(send_server_connection_header(session_data) != 0) {
delete_http2_session_data(session_data);
return;
}
if(session_recv(session_data) != 0) {
delete_http2_session_data(session_data);
return;
}
}
}
/* callback for evconnlistener */
static void acceptcb(struct evconnlistener *listener, int fd,
struct sockaddr *addr, int addrlen, void *arg)
{
app_context *app_ctx = (app_context*)arg;
static void acceptcb(struct evconnlistener *listener _U_, int fd,
struct sockaddr *addr, int addrlen, void *arg) {
app_context *app_ctx = (app_context *)arg;
http2_session_data *session_data;
session_data = create_http2_session_data(app_ctx, fd, addr, addrlen);
bufferevent_setcb(session_data->bev, handshake_readcb, NULL, eventcb,
session_data);
bufferevent_setcb(session_data->bev, readcb, writecb, eventcb, session_data);
}
static void start_listen(struct event_base *evbase, const char *service,
app_context *app_ctx)
{
app_context *app_ctx) {
int rv;
struct addrinfo hints;
struct addrinfo *res, *rp;
@@ -675,19 +667,20 @@ static void start_listen(struct event_base *evbase, const char *service,
hints.ai_flags = AI_PASSIVE;
#ifdef AI_ADDRCONFIG
hints.ai_flags |= AI_ADDRCONFIG;
#endif // AI_ADDRCONFIG
#endif /* AI_ADDRCONFIG */
rv = getaddrinfo(NULL, service, &hints, &res);
if(rv != 0) {
if (rv != 0) {
errx(1, NULL);
}
for(rp = res; rp; rp = rp->ai_next) {
for (rp = res; rp; rp = rp->ai_next) {
struct evconnlistener *listener;
listener = evconnlistener_new_bind(evbase, acceptcb, app_ctx,
LEV_OPT_CLOSE_ON_FREE |
LEV_OPT_REUSEABLE, 16,
rp->ai_addr, rp->ai_addrlen);
if(listener) {
listener = evconnlistener_new_bind(
evbase, acceptcb, app_ctx, LEV_OPT_CLOSE_ON_FREE | LEV_OPT_REUSEABLE,
16, rp->ai_addr, rp->ai_addrlen);
if (listener) {
freeaddrinfo(res);
return;
}
}
@@ -695,16 +688,14 @@ static void start_listen(struct event_base *evbase, const char *service,
}
static void initialize_app_context(app_context *app_ctx, SSL_CTX *ssl_ctx,
struct event_base *evbase)
{
struct event_base *evbase) {
memset(app_ctx, 0, sizeof(app_context));
app_ctx->ssl_ctx = ssl_ctx;
app_ctx->evbase = evbase;
}
static void run(const char *service,
const char *key_file, const char *cert_file)
{
static void run(const char *service, const char *key_file,
const char *cert_file) {
SSL_CTX *ssl_ctx;
app_context app_ctx;
struct event_base *evbase;
@@ -720,11 +711,10 @@ static void run(const char *service,
SSL_CTX_free(ssl_ctx);
}
int main(int argc, char **argv)
{
int main(int argc, char **argv) {
struct sigaction act;
if(argc < 4) {
if (argc < 4) {
fprintf(stderr, "Usage: libevent-server PORT KEY_FILE CERT_FILE\n");
exit(EXIT_FAILURE);
}
@@ -733,6 +723,8 @@ int main(int argc, char **argv)
act.sa_handler = SIG_IGN;
sigaction(SIGPIPE, &act, NULL);
OPENSSL_config(NULL);
OpenSSL_add_all_algorithms();
SSL_load_error_strings();
SSL_library_init();

1301
examples/tiny-nghttpd.c Normal file

File diff suppressed because it is too large Load Diff

30
gendowncasetbl.py Executable file
View File

@@ -0,0 +1,30 @@
#!/usr/bin/env python
import sys
def name(i):
if i < 0x20:
return \
['NUL ', 'SOH ', 'STX ', 'ETX ', 'EOT ', 'ENQ ', 'ACK ', 'BEL ',
'BS ', 'HT ', 'LF ', 'VT ', 'FF ', 'CR ', 'SO ', 'SI ',
'DLE ', 'DC1 ', 'DC2 ', 'DC3 ', 'DC4 ', 'NAK ', 'SYN ', 'ETB ',
'CAN ', 'EM ', 'SUB ', 'ESC ', 'FS ', 'GS ', 'RS ', 'US '][i]
elif i == 0x7f:
return 'DEL '
for i in range(256):
if chr(i) == ' ':
sys.stdout.write('{} /* SPC */, '.format(i))
elif chr(i) == '\t':
sys.stdout.write('{} /* HT */, '.format(i))
elif 'A' <= chr(i) and chr(i) <= 'Z':
sys.stdout.write('{} /* {} */, '.format(i - ord('A') + ord('a'), chr(i)))
elif (0x21 <= i and i < 0x7f):
sys.stdout.write('{} /* {} */, '.format(i, chr(i)))
elif 0x80 <= i:
sys.stdout.write('{} /* {} */, '.format(i, hex(i)))
elif 0 == i:
sys.stdout.write('{} /* NUL */, '.format(i))
else:
sys.stdout.write('{} /* {} */, '.format(i, name(i)))
if (i + 1)%4 == 0:
sys.stdout.write('\n')

97
genheaderfunc.py Executable file
View File

@@ -0,0 +1,97 @@
#!/usr/bin/env python
HEADERS = [
':authority',
':method',
':path',
':scheme',
':status',
':host', # for spdy
'expect',
'host',
'if-modified-since',
"te",
"cookie",
"http2-settings",
"server",
"via",
"x-forwarded-for",
"x-forwarded-proto",
"alt-svc",
"content-length",
"location",
# disallowed h1 headers
'connection',
'keep-alive',
'proxy-connection',
'transfer-encoding',
'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("{}", name, {})) {{
return {};
}}'''.format(k[:-1], size - 1, to_enum_hd(k))
print '''\
break;'''
print '''\
}
break;'''
print '''\
}
return -1;
}'''
if __name__ == '__main__':
gen_enum()
print ''
gen_index_header()

0
gennmchartbl.py Normal file → Executable file
View File

0
genvchartbl.py Normal file → Executable file
View File

484
git-clang-format Executable file
View File

@@ -0,0 +1,484 @@
#!/usr/bin/env python
#
#===- git-clang-format - ClangFormat Git Integration ---------*- python -*--===#
#
# The LLVM Compiler Infrastructure
#
# This file is distributed under the University of Illinois Open Source
# License. See LICENSE.TXT for details.
#
#===------------------------------------------------------------------------===#
r"""
clang-format git integration
============================
This file provides a clang-format integration for git. Put it somewhere in your
path and ensure that it is executable. Then, "git clang-format" will invoke
clang-format on the changes in current files or a specific commit.
For further details, run:
git clang-format -h
Requires Python 2.7
"""
import argparse
import collections
import contextlib
import errno
import os
import re
import subprocess
import sys
usage = 'git clang-format [OPTIONS] [<commit>] [--] [<file>...]'
desc = '''
Run clang-format on all lines that differ between the working directory
and <commit>, which defaults to HEAD. Changes are only applied to the working
directory.
The following git-config settings set the default of the corresponding option:
clangFormat.binary
clangFormat.commit
clangFormat.extension
clangFormat.style
'''
# Name of the temporary index file in which save the output of clang-format.
# This file is created within the .git directory.
temp_index_basename = 'clang-format-index'
Range = collections.namedtuple('Range', 'start, count')
def main():
config = load_git_config()
# In order to keep '--' yet allow options after positionals, we need to
# check for '--' ourselves. (Setting nargs='*' throws away the '--', while
# nargs=argparse.REMAINDER disallows options after positionals.)
argv = sys.argv[1:]
try:
idx = argv.index('--')
except ValueError:
dash_dash = []
else:
dash_dash = argv[idx:]
argv = argv[:idx]
default_extensions = ','.join([
# From clang/lib/Frontend/FrontendOptions.cpp, all lower case
'c', 'h', # C
'm', # ObjC
'mm', # ObjC++
'cc', 'cp', 'cpp', 'c++', 'cxx', 'hpp', # C++
# Other languages that clang-format supports
'proto', 'protodevel', # Protocol Buffers
'js', # JavaScript
])
p = argparse.ArgumentParser(
usage=usage, formatter_class=argparse.RawDescriptionHelpFormatter,
description=desc)
p.add_argument('--binary',
default=config.get('clangformat.binary', 'clang-format'),
help='path to clang-format'),
p.add_argument('--commit',
default=config.get('clangformat.commit', 'HEAD'),
help='default commit to use if none is specified'),
p.add_argument('--diff', action='store_true',
help='print a diff instead of applying the changes')
p.add_argument('--extensions',
default=config.get('clangformat.extensions',
default_extensions),
help=('comma-separated list of file extensions to format, '
'excluding the period and case-insensitive')),
p.add_argument('-f', '--force', action='store_true',
help='allow changes to unstaged files')
p.add_argument('-p', '--patch', action='store_true',
help='select hunks interactively')
p.add_argument('-q', '--quiet', action='count', default=0,
help='print less information')
p.add_argument('--style',
default=config.get('clangformat.style', None),
help='passed to clang-format'),
p.add_argument('-v', '--verbose', action='count', default=0,
help='print extra information')
# We gather all the remaining positional arguments into 'args' since we need
# to use some heuristics to determine whether or not <commit> was present.
# However, to print pretty messages, we make use of metavar and help.
p.add_argument('args', nargs='*', metavar='<commit>',
help='revision from which to compute the diff')
p.add_argument('ignored', nargs='*', metavar='<file>...',
help='if specified, only consider differences in these files')
opts = p.parse_args(argv)
opts.verbose -= opts.quiet
del opts.quiet
commit, files = interpret_args(opts.args, dash_dash, opts.commit)
changed_lines = compute_diff_and_extract_lines(commit, files)
if opts.verbose >= 1:
ignored_files = set(changed_lines)
filter_by_extension(changed_lines, opts.extensions.lower().split(','))
if opts.verbose >= 1:
ignored_files.difference_update(changed_lines)
if ignored_files:
print 'Ignoring changes in the following files (wrong extension):'
for filename in ignored_files:
print ' ', filename
if changed_lines:
print 'Running clang-format on the following files:'
for filename in changed_lines:
print ' ', filename
if not changed_lines:
print 'no modified files to format'
return
# The computed diff outputs absolute paths, so we must cd before accessing
# those files.
cd_to_toplevel()
old_tree = create_tree_from_workdir(changed_lines)
new_tree = run_clang_format_and_save_to_tree(changed_lines,
binary=opts.binary,
style=opts.style)
if opts.verbose >= 1:
print 'old tree:', old_tree
print 'new tree:', new_tree
if old_tree == new_tree:
if opts.verbose >= 0:
print 'clang-format did not modify any files'
elif opts.diff:
print_diff(old_tree, new_tree)
else:
changed_files = apply_changes(old_tree, new_tree, force=opts.force,
patch_mode=opts.patch)
if (opts.verbose >= 0 and not opts.patch) or opts.verbose >= 1:
print 'changed files:'
for filename in changed_files:
print ' ', filename
def load_git_config(non_string_options=None):
"""Return the git configuration as a dictionary.
All options are assumed to be strings unless in `non_string_options`, in which
is a dictionary mapping option name (in lower case) to either "--bool" or
"--int"."""
if non_string_options is None:
non_string_options = {}
out = {}
for entry in run('git', 'config', '--list', '--null').split('\0'):
if entry:
name, value = entry.split('\n', 1)
if name in non_string_options:
value = run('git', 'config', non_string_options[name], name)
out[name] = value
return out
def interpret_args(args, dash_dash, default_commit):
"""Interpret `args` as "[commit] [--] [files...]" and return (commit, files).
It is assumed that "--" and everything that follows has been removed from
args and placed in `dash_dash`.
If "--" is present (i.e., `dash_dash` is non-empty), the argument to its
left (if present) is taken as commit. Otherwise, the first argument is
checked if it is a commit or a file. If commit is not given,
`default_commit` is used."""
if dash_dash:
if len(args) == 0:
commit = default_commit
elif len(args) > 1:
die('at most one commit allowed; %d given' % len(args))
else:
commit = args[0]
object_type = get_object_type(commit)
if object_type not in ('commit', 'tag'):
if object_type is None:
die("'%s' is not a commit" % commit)
else:
die("'%s' is a %s, but a commit was expected" % (commit, object_type))
files = dash_dash[1:]
elif args:
if disambiguate_revision(args[0]):
commit = args[0]
files = args[1:]
else:
commit = default_commit
files = args
else:
commit = default_commit
files = []
return commit, files
def disambiguate_revision(value):
"""Returns True if `value` is a revision, False if it is a file, or dies."""
# If `value` is ambiguous (neither a commit nor a file), the following
# command will die with an appropriate error message.
run('git', 'rev-parse', value, verbose=False)
object_type = get_object_type(value)
if object_type is None:
return False
if object_type in ('commit', 'tag'):
return True
die('`%s` is a %s, but a commit or filename was expected' %
(value, object_type))
def get_object_type(value):
"""Returns a string description of an object's type, or None if it is not
a valid git object."""
cmd = ['git', 'cat-file', '-t', value]
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
stdout, stderr = p.communicate()
if p.returncode != 0:
return None
return stdout.strip()
def compute_diff_and_extract_lines(commit, files):
"""Calls compute_diff() followed by extract_lines()."""
diff_process = compute_diff(commit, files)
changed_lines = extract_lines(diff_process.stdout)
diff_process.stdout.close()
diff_process.wait()
if diff_process.returncode != 0:
# Assume error was already printed to stderr.
sys.exit(2)
return changed_lines
def compute_diff(commit, files):
"""Return a subprocess object producing the diff from `commit`.
The return value's `stdin` file object will produce a patch with the
differences between the working directory and `commit`, filtered on `files`
(if non-empty). Zero context lines are used in the patch."""
cmd = ['git', 'diff-index', '-p', '-U0', commit, '--']
cmd.extend(files)
p = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE)
p.stdin.close()
return p
def extract_lines(patch_file):
"""Extract the changed lines in `patch_file`.
The return value is a dictionary mapping filename to a list of (start_line,
line_count) pairs.
The input must have been produced with ``-U0``, meaning unidiff format with
zero lines of context. The return value is a dict mapping filename to a
list of line `Range`s."""
matches = {}
for line in patch_file:
match = re.search(r'^\+\+\+\ [^/]+/(.*)', line)
if match:
filename = match.group(1).rstrip('\r\n')
match = re.search(r'^@@ -[0-9,]+ \+(\d+)(,(\d+))?', line)
if match:
start_line = int(match.group(1))
line_count = 1
if match.group(3):
line_count = int(match.group(3))
if line_count > 0:
matches.setdefault(filename, []).append(Range(start_line, line_count))
return matches
def filter_by_extension(dictionary, allowed_extensions):
"""Delete every key in `dictionary` that doesn't have an allowed extension.
`allowed_extensions` must be a collection of lowercase file extensions,
excluding the period."""
allowed_extensions = frozenset(allowed_extensions)
for filename in dictionary.keys():
base_ext = filename.rsplit('.', 1)
if len(base_ext) == 1 or base_ext[1].lower() not in allowed_extensions:
del dictionary[filename]
def cd_to_toplevel():
"""Change to the top level of the git repository."""
toplevel = run('git', 'rev-parse', '--show-toplevel')
os.chdir(toplevel)
def create_tree_from_workdir(filenames):
"""Create a new git tree with the given files from the working directory.
Returns the object ID (SHA-1) of the created tree."""
return create_tree(filenames, '--stdin')
def run_clang_format_and_save_to_tree(changed_lines, binary='clang-format',
style=None):
"""Run clang-format on each file and save the result to a git tree.
Returns the object ID (SHA-1) of the created tree."""
def index_info_generator():
for filename, line_ranges in changed_lines.iteritems():
mode = oct(os.stat(filename).st_mode)
blob_id = clang_format_to_blob(filename, line_ranges, binary=binary,
style=style)
yield '%s %s\t%s' % (mode, blob_id, filename)
return create_tree(index_info_generator(), '--index-info')
def create_tree(input_lines, mode):
"""Create a tree object from the given input.
If mode is '--stdin', it must be a list of filenames. If mode is
'--index-info' is must be a list of values suitable for "git update-index
--index-info", such as "<mode> <SP> <sha1> <TAB> <filename>". Any other mode
is invalid."""
assert mode in ('--stdin', '--index-info')
cmd = ['git', 'update-index', '--add', '-z', mode]
with temporary_index_file():
p = subprocess.Popen(cmd, stdin=subprocess.PIPE)
for line in input_lines:
p.stdin.write('%s\0' % line)
p.stdin.close()
if p.wait() != 0:
die('`%s` failed' % ' '.join(cmd))
tree_id = run('git', 'write-tree')
return tree_id
def clang_format_to_blob(filename, line_ranges, binary='clang-format',
style=None):
"""Run clang-format on the given file and save the result to a git blob.
Returns the object ID (SHA-1) of the created blob."""
clang_format_cmd = [binary, filename]
if style:
clang_format_cmd.extend(['-style='+style])
clang_format_cmd.extend([
'-lines=%s:%s' % (start_line, start_line+line_count-1)
for start_line, line_count in line_ranges])
try:
clang_format = subprocess.Popen(clang_format_cmd, stdin=subprocess.PIPE,
stdout=subprocess.PIPE)
except OSError as e:
if e.errno == errno.ENOENT:
die('cannot find executable "%s"' % binary)
else:
raise
clang_format.stdin.close()
hash_object_cmd = ['git', 'hash-object', '-w', '--path='+filename, '--stdin']
hash_object = subprocess.Popen(hash_object_cmd, stdin=clang_format.stdout,
stdout=subprocess.PIPE)
clang_format.stdout.close()
stdout = hash_object.communicate()[0]
if hash_object.returncode != 0:
die('`%s` failed' % ' '.join(hash_object_cmd))
if clang_format.wait() != 0:
die('`%s` failed' % ' '.join(clang_format_cmd))
return stdout.rstrip('\r\n')
@contextlib.contextmanager
def temporary_index_file(tree=None):
"""Context manager for setting GIT_INDEX_FILE to a temporary file and deleting
the file afterward."""
index_path = create_temporary_index(tree)
old_index_path = os.environ.get('GIT_INDEX_FILE')
os.environ['GIT_INDEX_FILE'] = index_path
try:
yield
finally:
if old_index_path is None:
del os.environ['GIT_INDEX_FILE']
else:
os.environ['GIT_INDEX_FILE'] = old_index_path
os.remove(index_path)
def create_temporary_index(tree=None):
"""Create a temporary index file and return the created file's path.
If `tree` is not None, use that as the tree to read in. Otherwise, an
empty index is created."""
gitdir = run('git', 'rev-parse', '--git-dir')
path = os.path.join(gitdir, temp_index_basename)
if tree is None:
tree = '--empty'
run('git', 'read-tree', '--index-output='+path, tree)
return path
def print_diff(old_tree, new_tree):
"""Print the diff between the two trees to stdout."""
# We use the porcelain 'diff' and not plumbing 'diff-tree' because the output
# is expected to be viewed by the user, and only the former does nice things
# like color and pagination.
subprocess.check_call(['git', 'diff', old_tree, new_tree, '--'])
def apply_changes(old_tree, new_tree, force=False, patch_mode=False):
"""Apply the changes in `new_tree` to the working directory.
Bails if there are local changes in those files and not `force`. If
`patch_mode`, runs `git checkout --patch` to select hunks interactively."""
changed_files = run('git', 'diff-tree', '-r', '-z', '--name-only', old_tree,
new_tree).rstrip('\0').split('\0')
if not force:
unstaged_files = run('git', 'diff-files', '--name-status', *changed_files)
if unstaged_files:
print >>sys.stderr, ('The following files would be modified but '
'have unstaged changes:')
print >>sys.stderr, unstaged_files
print >>sys.stderr, 'Please commit, stage, or stash them first.'
sys.exit(2)
if patch_mode:
# In patch mode, we could just as well create an index from the new tree
# and checkout from that, but then the user will be presented with a
# message saying "Discard ... from worktree". Instead, we use the old
# tree as the index and checkout from new_tree, which gives the slightly
# better message, "Apply ... to index and worktree". This is not quite
# right, since it won't be applied to the user's index, but oh well.
with temporary_index_file(old_tree):
subprocess.check_call(['git', 'checkout', '--patch', new_tree])
index_tree = old_tree
else:
with temporary_index_file(new_tree):
run('git', 'checkout-index', '-a', '-f')
return changed_files
def run(*args, **kwargs):
stdin = kwargs.pop('stdin', '')
verbose = kwargs.pop('verbose', True)
strip = kwargs.pop('strip', True)
for name in kwargs:
raise TypeError("run() got an unexpected keyword argument '%s'" % name)
p = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
stdin=subprocess.PIPE)
stdout, stderr = p.communicate(input=stdin)
if p.returncode == 0:
if stderr:
if verbose:
print >>sys.stderr, '`%s` printed to stderr:' % ' '.join(args)
print >>sys.stderr, stderr.rstrip()
if strip:
stdout = stdout.rstrip('\r\n')
return stdout
if verbose:
print >>sys.stderr, '`%s` returned %s' % (' '.join(args), p.returncode)
if stderr:
print >>sys.stderr, stderr.rstrip()
sys.exit(2)
def die(message):
print >>sys.stderr, 'error:', message
sys.exit(2)
if __name__ == '__main__':
main()

178
help2rst.py Executable file
View File

@@ -0,0 +1,178 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# script to produce rst file from program's help output.
from __future__ import unicode_literals
import sys
import re
import argparse
arg_indent = ' ' * 21
def help2man(infile):
# We assume that first line is usage line like this:
#
# Usage: nghttp [OPTIONS]... URI...
#
# The second line is description of the command. Multiple lines
# are permitted. The blank line signals the end of this section.
# After that, we parses positional and optional arguments.
#
# The positional argument is enclosed with < and >:
#
# <PRIVATE_KEY>
#
# We may describe default behavior without any options by encoding
# ( and ):
#
# (default mode)
#
# "Options:" is treated specially and produces "OPTIONS" section.
# We allow subsection under OPTIONS. Lines not starting with (, <
# and Options: are treated as subsection name and produces section
# one level down:
#
# TLS/SSL:
#
# The above is an example of subsection.
#
# The description of arguments must be indented by len(arg_indent)
# characters. The default value should be placed in separate line
# and should be start with "Default: " after indentation.
line = infile.readline().strip()
m = re.match(r'^Usage: (.*)', line)
if not m:
print 'usage line is invalid. Expected following lines:'
print 'Usage: cmdname ...'
sys.exit(1)
synopsis = m.group(1).split(' ', 1)
if len(synopsis) == 2:
cmdname, args = synopsis
else:
cmdname, args = synopsis[0], ''
description = []
for line in infile:
line = line.strip()
if not line:
break
description.append(line)
print '''
{cmdname}(1)
{cmdnameunderline}
SYNOPSIS
--------
**{cmdname}** {args}
DESCRIPTION
-----------
{description}
'''.format(cmdname=cmdname, args=args,
cmdnameunderline='=' * (len(cmdname) + 3),
synopsis=synopsis, description=format_text('\n'.join(description)))
in_arg = False
for line in infile:
line = line.rstrip()
if not line.strip() and in_arg:
print ''
continue
if line.startswith(' ') and in_arg:
if not line.startswith(arg_indent):
sys.stderr.write('warning: argument description is not indented correctly. We need {} spaces as indentation.'.format(len(arg_indent)))
print '{}'.format(format_arg_text(line[len(arg_indent):]))
continue
if in_arg:
print ''
in_arg = False
if line == 'Options:':
print 'OPTIONS:'
print '--------'
print ''
continue
if line.startswith(' <'):
# positional argument
m = re.match(r'^(?:\s+)([a-zA-Z0-9-_<>]+)(.*)', line)
argname, rest = m.group(1), m.group(2)
print '.. describe:: {}'.format(argname)
print ''
print '{}'.format(format_arg_text(rest.strip()))
in_arg = True
continue
if line.startswith(' ('):
# positional argument
m = re.match(r'^(?:\s+)(\([a-zA-Z0-9-_<> ]+\))(.*)', line)
argname, rest = m.group(1), m.group(2)
print '.. describe:: {}'.format(argname)
print ''
print '{}'.format(format_arg_text(rest.strip()))
in_arg = True
continue
if line.startswith(' -'):
# optional argument
m = re.match(
r'^(?:\s+)(-\S+?(?:, -\S+?)*)($| .*)',
line)
argname, rest = m.group(1), m.group(2)
print '.. option:: {}'.format(argname)
print ''
rest = rest.strip()
if len(rest):
print '{}'.format(format_arg_text(rest))
in_arg = True
continue
if not line.startswith(' ') and line.endswith(':'):
# subsection
subsec = line.strip()
print '{}'.format(subsec)
print '{}'.format('~' * len(subsec))
print ''
continue
print line.strip()
def format_text(text):
# escape *
if len(text) > len(arg_indent):
text = text[:len(arg_indent) + 1] + re.sub(r'\*', r'\*', text[len(arg_indent) + 1:])
else:
text = re.sub(r'\*', r'\*', text)
# markup option reference
text = re.sub(r'(^|\s)(-[a-zA-Z0-9-]+)', r'\1:option:`\2`', text)
# sphinx does not like markup like ':option:`-f`='. We need
# backslash between ` and =.
text = re.sub(r'(:option:`.*?`)(\S)', r'\1\\\2', text)
# file path should be italic
text = re.sub(r'(^|\s|\'|")(/[^\s\'"]*)', r'\1*\2*', text)
return text
def format_arg_text(text):
if text.strip().startswith('Default: '):
return '\n ' + re.sub(r'^(\s*Default: )(.*)$', r'\1``\2``', text)
return ' {}'.format(format_text(text))
if __name__ == '__main__':
parser = argparse.ArgumentParser(
description='Produces rst document from help output.')
parser.add_argument('-i', '--include', metavar='FILE',
help='include content of <FILE> as verbatim. It should be ReST formatted text.')
args = parser.parse_args()
help2man(sys.stdin)
if args.include:
print ''
with open(args.include) as f:
sys.stdout.write(f.read())

View File

@@ -1,4 +1,4 @@
# nghttp2 - HTTP/2.0 C Library
# nghttp2 - HTTP/2 C Library
# Copyright (c) 2012, 2013 Tatsuhiro Tsujikawa
@@ -22,7 +22,9 @@
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
SUBDIRS = includes
AM_CFLAGS = -Wall
EXTRA_DIST = Makefile.msvc
AM_CFLAGS = $(WARNCFLAGS)
AM_CPPFLAGS = -I$(srcdir)/includes -I$(builddir)/includes @DEFS@
pkgconfigdir = $(libdir)/pkgconfig
@@ -32,21 +34,31 @@ DISTCLEANFILES = $(pkgconfig_DATA)
lib_LTLIBRARIES = libnghttp2.la
OBJECTS = nghttp2_pq.c nghttp2_map.c nghttp2_queue.c \
nghttp2_buffer.c nghttp2_frame.c \
nghttp2_frame.c \
nghttp2_buf.c \
nghttp2_stream.c nghttp2_outbound_item.c \
nghttp2_session.c nghttp2_submit.c \
nghttp2_helper.c \
nghttp2_npn.c nghttp2_gzip.c \
nghttp2_npn.c \
nghttp2_hd.c nghttp2_hd_huffman.c nghttp2_hd_huffman_data.c \
nghttp2_version.c
nghttp2_version.c \
nghttp2_priority_spec.c \
nghttp2_option.c \
nghttp2_callbacks.c \
nghttp2_mem.c
HFILES = nghttp2_pq.h nghttp2_int.h nghttp2_map.h nghttp2_queue.h \
nghttp2_buffer.h nghttp2_frame.h \
nghttp2_frame.h \
nghttp2_buf.h \
nghttp2_session.h nghttp2_helper.h nghttp2_stream.h nghttp2_int.h \
nghttp2_npn.h nghttp2_gzip.h \
nghttp2_npn.h \
nghttp2_submit.h nghttp2_outbound_item.h \
nghttp2_net.h \
nghttp2_hd.h nghttp2_hd_huffman.h
nghttp2_hd.h nghttp2_hd_huffman.h \
nghttp2_priority_spec.h \
nghttp2_option.h \
nghttp2_callbacks.h \
nghttp2_mem.h
libnghttp2_la_SOURCES = $(HFILES) $(OBJECTS)
libnghttp2_la_LDFLAGS = -no-undefined \

266
lib/Makefile.msvc Normal file
View File

@@ -0,0 +1,266 @@
#
# GNU Makefile for nghttp2 / MSVC.
#
# By G. Vanem <gvanem@yahoo.no> 2013
# The MIT License apply.
#
#
# Choose your weapons:
# Set 'ZLIB_ROOT' to the root of zlib.
# 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
_VERSION := $(shell grep AC_INIT ../configure.ac | cut -d'[' -f3 | sed -e 's/-DEV], //g')
_VERSION := $(subst ., ,$(_VERSION))
VER_MAJOR = $(word 1,$(_VERSION))
VER_MINOR = $(word 2,$(_VERSION))
VER_MICRO = $(word 3,$(_VERSION))
VERSION = $(VER_MAJOR).$(VER_MINOR).$(VER_MICRO)
VERSION_NUM = ($(VER_MAJOR) << 16) + ($(VER_MINOR) << 8) + $(VER_MICRO)
GENERATED = 'Generated by $(realpath Makefile.MSVC)'
#
# Where to copy nghttp2.dll + lib + headers to.
# Note: 'make install' is not in default targets. Do it explicitly.
#
VC_ROOT = $(realpath $(VCINSTALLDIR))
INSTALL_BIN = $(VC_ROOT)/bin
INSTALL_LIB = $(VC_ROOT)/lib
INSTALL_HDR = $(VC_ROOT)/include
#
# Build for DEBUG-model and RELEASE at the same time.
#
TARGETS = nghttp2.lib nghttp2.dll nghttp2_imp.lib \
nghttp2d.lib nghttp2d.dll nghttp2d_imp.lib
EXT_LIBS = $(ZLIB_ROOT)/zlib.lib ws2_32.lib
OBJ_DIR = MSVC_obj
NGHTTP2_PDB_R = $(OBJ_DIR)/nghttp2.pdb
NGHTTP2_PDB_D = $(OBJ_DIR)/nghttp2d.pdb
CC = cl
CFLAGS = -I./includes -I$(ZLIB_ROOT) -DHAVE_WINSOCK2_H -Dssize_t=long
CFLAGS_R = -nologo -MD -W3 -Zi -Fd./$(NGHTTP2_PDB_R)
CFLAGS_D = -nologo -MDd -W3 -Zi -Fd./$(NGHTTP2_PDB_D) \
-Ot -D_DEBUG -GF -RTCs -RTCu # -RTCc -GS
LDFLAGS = -nologo -machine:i386 -map -debug -incremental:no # -verbose
NGHTTP2_SRC = nghttp2_buf.c \
nghttp2_callbacks.c \
nghttp2_frame.c \
nghttp2_helper.c \
nghttp2_hd.c \
nghttp2_hd_huffman.c \
nghttp2_hd_huffman_data.c \
nghttp2_map.c \
nghttp2_npn.c \
nghttp2_option.c \
nghttp2_outbound_item.c \
nghttp2_priority_spec.c \
nghttp2_pq.c \
nghttp2_queue.c \
nghttp2_session.c \
nghttp2_stream.c \
nghttp2_submit.c \
nghttp2_version.c
NGHTTP2_OBJ_R = $(addprefix $(OBJ_DIR)/r_, $(notdir $(NGHTTP2_SRC:.c=.obj)))
NGHTTP2_OBJ_D = $(addprefix $(OBJ_DIR)/d_, $(notdir $(NGHTTP2_SRC:.c=.obj)))
all: intro $(OBJ_DIR) $(TARGETS)
@echo 'Welcome to NgHTTP2 (release + debug).'
@echo 'Do a "make -f Makefile.MSVC install" at own risk!'
intro:
@echo 'Building NgHTTP (MSVC) ver. "$(VERSION)".'
test_ver:
@echo '$$(VERSION): "$(VERSION)".'
@echo '$$(_VERSION): "$(_VERSION)".'
@echo '$$(VER_MAJOR): "$(VER_MAJOR)".'
@echo '$$(VER_MINOR): "$(VER_MINOR)".'
@echo '$$(VER_MICRO): "$(VER_MICRO)".'
$(OBJ_DIR):
- mkdir $(OBJ_DIR)
install: includes/nghttp2/nghttp2.h includes/nghttp2/nghttp2ver.h \
nghttp2.dll nghttp2.lib nghttp2_imp.lib \
nghttp2d.dll nghttp2d.lib nghttp2d_imp.lib \
copy_headers_and_libs install_nghttp2_pyd_$(USE_CYTHON)
#
# This MUST be done before using the 'install_nghttp2_pyd_1' rule.
#
copy_headers_and_libs:
- mkdir $(INSTALL_HDR)/nghttp2
cp --update $(addprefix includes/nghttp2/, nghttp2.h nghttp2ver.h) $(INSTALL_HDR)/nghttp2
cp --update nghttp2.dll nghttp2d.dll $(NGHTTP2_PDB_R) $(NGHTTP2_PDB_D) $(INSTALL_BIN)
cp --update nghttp2.lib nghttp2d.lib nghttp2_imp.lib nghttp2d_imp.lib $(INSTALL_LIB)
@echo
nghttp2.lib: $(NGHTTP2_OBJ_R)
lib -nologo -out:$@ $^
@echo
nghttp2d.lib: $(NGHTTP2_OBJ_D)
lib -nologo -out:$@ $^
@echo
nghttp2.dll nghttp2_imp.lib: $(NGHTTP2_OBJ_R) $(OBJ_DIR)/r_nghttp2.res $(OBJ_DIR)/r_nghttp2.def
link $(LDFLAGS) -dll -out:nghttp2.dll -implib:nghttp2_imp.lib -def:$(OBJ_DIR)/r_nghttp2.def \
$(NGHTTP2_OBJ_R) $(OBJ_DIR)/r_nghttp2.res $(EXT_LIBS)
@echo
nghttp2d.dll nghttp2d_imp.lib: $(NGHTTP2_OBJ_D) $(OBJ_DIR)/d_nghttp2.res $(OBJ_DIR)/d_nghttp2.def
link $(LDFLAGS) -dll -out:nghttp2d.dll -implib:nghttp2d_imp.lib -def:$(OBJ_DIR)/d_nghttp2.def \
$(NGHTTP2_OBJ_D) $(OBJ_DIR)/d_nghttp2.res $(EXT_LIBS)
@echo
install_nghttp2_pyd_0: ;
install_nghttp2_pyd_1: $(addprefix ../python/, setup.py.in nghttp2.pyx)
cd ../python ; \
echo '# $(GENERATED). DO NOT EDIT.' > setup.py ; \
sed -e 's/@top_srcdir@/../' \
-e 's/@top_builddir@/../' \
-e 's/@PACKAGE_VERSION@/$(VERSION)/' setup.py.in >> setup.py ; \
cython -v nghttp2.pyx ; \
python setup.py install
clean_nghttp2_pyd_0: ;
clean_nghttp2_pyd_1:
cd ../python ; \
rm -f setup.py nghttp2.c ; \
rm -fR build/*
$(OBJ_DIR)/r_%.obj: %.c
$(CC) $(CFLAGS_R) $(CFLAGS) -Fo$@ -c $<
@echo
$(OBJ_DIR)/d_%.obj: %.c
$(CC) $(CFLAGS_D) $(CFLAGS) -Fo$@ -c $<
@echo
$(OBJ_DIR)/r_nghttp2.res: nghttp2.rc
rc -nologo -D_RELEASE -Fo $@ $<
@echo
$(OBJ_DIR)/d_nghttp2.res: nghttp2.rc
rc -nologo -D_DEBUG -Fo $@ $<
@echo
includes/nghttp2/nghttp2ver.h: includes/nghttp2/nghttp2ver.h.in
sed < includes/nghttp2/nghttp2ver.h.in \
-e 's/@PACKAGE_VERSION@/$(VERSION)/g' \
-e 's/@PACKAGE_VERSION_NUM@/($(VERSION_NUM))/g' > $@
touch --reference=includes/nghttp2/nghttp2ver.h.in $@
define RES_FILE
#include <winver.h>
VS_VERSION_INFO VERSIONINFO
FILEVERSION $(VER_MAJOR), $(VER_MINOR), $(VER_MICRO), 0
PRODUCTVERSION $(VER_MAJOR), $(VER_MINOR), $(VER_MICRO), 0
FILEFLAGSMASK 0x3fL
FILEOS 0x40004L
FILETYPE 0x2L
FILESUBTYPE 0x0L
#ifdef _DEBUG
#define VER_STR "$(VERSION).0 (MSVC debug)"
#define DBG "d"
FILEFLAGS 0x1L
#else
#define VER_STR "$(VERSION).0 (MSVC release)"
#define DBG ""
FILEFLAGS 0x0L
#endif
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904b0"
BEGIN
VALUE "CompanyName", "http://tatsuhiro-t.github.io/nghttp2/"
VALUE "FileDescription", "nghttp2; HTTP/2 C library"
VALUE "FileVersion", VER_STR
VALUE "InternalName", "nghttp2" DBG
VALUE "LegalCopyright", "The MIT License"
VALUE "LegalTrademarks", ""
VALUE "OriginalFilename", "nghttp2" DBG ".dll"
VALUE "ProductName", "NGHTTP2."
VALUE "ProductVersion", VER_STR
VALUE "PrivateBuild", "The privat build of <gvanem@yahoo.no>."
VALUE "SpecialBuild", ""
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x409, 1200
END
END
endef
export RES_FILE
nghttp2.rc: Makefile.MSVC
@echo 'Generating $@...'
@echo ' /* $(GENERATED). DO NOT EDIT.' > $@
@echo ' */' >> $@
@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:
rm -f $(OBJ_DIR)/* nghttp2_imp.exp nghttp2_imp.exp \
nghttp2.map nghttp2d.map nghttp2.rc includes/nghttp2/nghttp2ver.h
@echo
vclean realclean: clean clean_nghttp2_pyd_$(USE_CYTHON)
rm -f $(TARGETS) nghttp2.pdb nghttp2d.pdb nghttp2_imp.exp nghttp2d_imp.exp .depend.MSVC
- rmdir $(OBJ_DIR)
#
# Use gcc to generated the dependencies. No MSVC specific args please!
#
REPLACE_R = 's/\(.*\)\.o: /\n$$(OBJ_DIR)\/r_\1.obj: /'
REPLACE_D = 's/\(.*\)\.o: /\n$$(OBJ_DIR)\/d_\1.obj: /'
depend: includes/nghttp2/nghttp2ver.h
@echo '# $(GENERATED). DO NOT EDIT.' > .depend.MSVC
gcc -MM $(CFLAGS) $(NGHTTP2_SRC) >> .depend.tmp
@echo '#' >> .depend.MSVC
@echo '# Release lib objects:' >> .depend.MSVC
sed -e $(REPLACE_R) .depend.tmp >> .depend.MSVC
@echo '#' >> .depend.MSVC
@echo '# Debug lib objects:' >> .depend.MSVC
sed -e $(REPLACE_D) .depend.tmp >> .depend.MSVC
rm -f .depend.tmp
-include .depend.MSVC

View File

@@ -1,4 +1,4 @@
# nghttp2 - HTTP/2.0 C Library
# nghttp2 - HTTP/2 C Library
# Copyright (c) 2012 Tatsuhiro Tsujikawa

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,5 @@
/*
* nghttp2 - HTTP/2.0 C Library
* nghttp2 - HTTP/2 C Library
*
* Copyright (c) 2012, 2013 Tatsuhiro Tsujikawa
*

View File

@@ -1,4 +1,4 @@
# nghttp2 - HTTP/2.0 C Library
# nghttp2 - HTTP/2 C Library
# Copyright (c) 2012, 2013 Tatsuhiro Tsujikawa
@@ -26,9 +26,8 @@ libdir=@libdir@
includedir=@includedir@
Name: libnghttp2
Description: HTTP/2.0 C library
Description: HTTP/2 C library
URL: https://github.com/tatsuhiro-t/nghttp2
Version: @VERSION@
Libs: -L${libdir} -lnghttp2
Libs.private: -lz
Cflags: -I${includedir}

484
lib/nghttp2_buf.c Normal file
View File

@@ -0,0 +1,484 @@
/*
* nghttp2 - HTTP/2 C Library
*
* Copyright (c) 2014 Tatsuhiro Tsujikawa
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "nghttp2_buf.h"
#include <stdio.h>
#include "nghttp2_helper.h"
void nghttp2_buf_init(nghttp2_buf *buf) {
buf->begin = NULL;
buf->end = NULL;
buf->pos = NULL;
buf->last = NULL;
buf->mark = NULL;
}
int nghttp2_buf_init2(nghttp2_buf *buf, size_t initial, nghttp2_mem *mem) {
nghttp2_buf_init(buf);
return nghttp2_buf_reserve(buf, initial, mem);
}
void nghttp2_buf_free(nghttp2_buf *buf, nghttp2_mem *mem) {
if (buf == NULL) {
return;
}
nghttp2_mem_free(mem, buf->begin);
buf->begin = NULL;
}
int nghttp2_buf_reserve(nghttp2_buf *buf, size_t new_cap, nghttp2_mem *mem) {
uint8_t *ptr;
size_t cap;
cap = nghttp2_buf_cap(buf);
if (cap >= new_cap) {
return 0;
}
new_cap = nghttp2_max(new_cap, cap * 2);
ptr = nghttp2_mem_realloc(mem, buf->begin, new_cap);
if (ptr == NULL) {
return NGHTTP2_ERR_NOMEM;
}
buf->pos = ptr + (buf->pos - buf->begin);
buf->last = ptr + (buf->last - buf->begin);
buf->mark = ptr + (buf->mark - buf->begin);
buf->begin = ptr;
buf->end = ptr + new_cap;
return 0;
}
void nghttp2_buf_reset(nghttp2_buf *buf) {
buf->pos = buf->last = buf->mark = buf->begin;
}
void nghttp2_buf_wrap_init(nghttp2_buf *buf, uint8_t *begin, size_t len) {
buf->begin = buf->pos = buf->last = buf->mark = begin;
buf->end = begin + len;
}
static int buf_chain_new(nghttp2_buf_chain **chain, size_t chunk_length,
nghttp2_mem *mem) {
int rv;
*chain = nghttp2_mem_malloc(mem, sizeof(nghttp2_buf_chain));
if (*chain == NULL) {
return NGHTTP2_ERR_NOMEM;
}
(*chain)->next = NULL;
rv = nghttp2_buf_init2(&(*chain)->buf, chunk_length, mem);
if (rv != 0) {
nghttp2_mem_free(mem, *chain);
return NGHTTP2_ERR_NOMEM;
}
return 0;
}
static void buf_chain_del(nghttp2_buf_chain *chain, nghttp2_mem *mem) {
nghttp2_buf_free(&chain->buf, mem);
nghttp2_mem_free(mem, chain);
}
int nghttp2_bufs_init(nghttp2_bufs *bufs, size_t chunk_length, size_t max_chunk,
nghttp2_mem *mem) {
return nghttp2_bufs_init2(bufs, chunk_length, max_chunk, 0, mem);
}
int nghttp2_bufs_init2(nghttp2_bufs *bufs, size_t chunk_length,
size_t max_chunk, size_t offset, nghttp2_mem *mem) {
return nghttp2_bufs_init3(bufs, chunk_length, max_chunk, max_chunk, offset,
mem);
}
int nghttp2_bufs_init3(nghttp2_bufs *bufs, size_t chunk_length,
size_t max_chunk, size_t chunk_keep, size_t offset,
nghttp2_mem *mem) {
int rv;
nghttp2_buf_chain *chain;
if (chunk_keep == 0 || max_chunk < chunk_keep || chunk_length < offset) {
return NGHTTP2_ERR_INVALID_ARGUMENT;
}
rv = buf_chain_new(&chain, chunk_length, mem);
if (rv != 0) {
return rv;
}
bufs->mem = mem;
bufs->offset = offset;
bufs->head = chain;
bufs->cur = bufs->head;
nghttp2_buf_shift_right(&bufs->cur->buf, offset);
bufs->chunk_length = chunk_length;
bufs->chunk_used = 1;
bufs->max_chunk = max_chunk;
bufs->chunk_keep = chunk_keep;
return 0;
}
int nghttp2_bufs_realloc(nghttp2_bufs *bufs, size_t chunk_length) {
int rv;
nghttp2_buf_chain *chain;
if (chunk_length < bufs->offset) {
return NGHTTP2_ERR_INVALID_ARGUMENT;
}
rv = buf_chain_new(&chain, chunk_length, bufs->mem);
if (rv != 0) {
return rv;
}
nghttp2_bufs_free(bufs);
bufs->head = chain;
bufs->cur = bufs->head;
nghttp2_buf_shift_right(&bufs->cur->buf, bufs->offset);
bufs->chunk_length = chunk_length;
bufs->chunk_used = 1;
return 0;
}
void nghttp2_bufs_free(nghttp2_bufs *bufs) {
nghttp2_buf_chain *chain, *next_chain;
if (bufs == NULL) {
return;
}
for (chain = bufs->head; chain;) {
next_chain = chain->next;
buf_chain_del(chain, bufs->mem);
chain = next_chain;
}
bufs->head = NULL;
}
int nghttp2_bufs_wrap_init(nghttp2_bufs *bufs, uint8_t *begin, size_t len,
nghttp2_mem *mem) {
nghttp2_buf_chain *chain;
chain = nghttp2_mem_malloc(mem, sizeof(nghttp2_buf_chain));
if (chain == NULL) {
return NGHTTP2_ERR_NOMEM;
}
chain->next = NULL;
nghttp2_buf_wrap_init(&chain->buf, begin, len);
bufs->mem = mem;
bufs->offset = 0;
bufs->head = chain;
bufs->cur = bufs->head;
bufs->chunk_length = len;
bufs->chunk_used = 1;
bufs->max_chunk = 1;
bufs->chunk_keep = 1;
return 0;
}
void nghttp2_bufs_wrap_free(nghttp2_bufs *bufs) {
if (bufs == NULL) {
return;
}
nghttp2_mem_free(bufs->mem, bufs->head);
bufs->head = NULL;
}
void nghttp2_bufs_seek_last_present(nghttp2_bufs *bufs) {
nghttp2_buf_chain *ci;
for (ci = bufs->cur; ci; ci = ci->next) {
if (nghttp2_buf_len(&ci->buf) == 0) {
return;
} else {
bufs->cur = ci;
}
}
}
ssize_t nghttp2_bufs_len(nghttp2_bufs *bufs) {
nghttp2_buf_chain *ci;
ssize_t len;
len = 0;
for (ci = bufs->head; ci; ci = ci->next) {
len += nghttp2_buf_len(&ci->buf);
}
return len;
}
static ssize_t bufs_avail(nghttp2_bufs *bufs) {
return (ssize_t)(nghttp2_buf_avail(&bufs->cur->buf) +
(bufs->chunk_length - bufs->offset) *
(bufs->max_chunk - bufs->chunk_used));
}
static int bufs_alloc_chain(nghttp2_bufs *bufs) {
int rv;
nghttp2_buf_chain *chain;
if (bufs->cur->next) {
bufs->cur = bufs->cur->next;
return 0;
}
if (bufs->max_chunk == bufs->chunk_used) {
return NGHTTP2_ERR_BUFFER_ERROR;
}
rv = buf_chain_new(&chain, bufs->chunk_length, bufs->mem);
if (rv != 0) {
return rv;
}
DEBUGF(fprintf(stderr,
"new buffer %zu bytes allocated for bufs %p, used %zu\n",
bufs->chunk_length, bufs, bufs->chunk_used));
++bufs->chunk_used;
bufs->cur->next = chain;
bufs->cur = chain;
nghttp2_buf_shift_right(&bufs->cur->buf, bufs->offset);
return 0;
}
int nghttp2_bufs_add(nghttp2_bufs *bufs, const void *data, size_t len) {
int rv;
size_t nwrite;
nghttp2_buf *buf;
const uint8_t *p;
if (bufs_avail(bufs) < (ssize_t)len) {
return NGHTTP2_ERR_BUFFER_ERROR;
}
p = data;
while (len) {
buf = &bufs->cur->buf;
nwrite = nghttp2_min((size_t)nghttp2_buf_avail(buf), len);
if (nwrite == 0) {
rv = bufs_alloc_chain(bufs);
if (rv != 0) {
return rv;
}
continue;
}
buf->last = nghttp2_cpymem(buf->last, p, nwrite);
p += len;
len -= nwrite;
}
return 0;
}
static int bufs_ensure_addb(nghttp2_bufs *bufs) {
int rv;
nghttp2_buf *buf;
buf = &bufs->cur->buf;
if (nghttp2_buf_avail(buf) > 0) {
return 0;
}
rv = bufs_alloc_chain(bufs);
if (rv != 0) {
return rv;
}
return 0;
}
int nghttp2_bufs_addb(nghttp2_bufs *bufs, uint8_t b) {
int rv;
rv = bufs_ensure_addb(bufs);
if (rv != 0) {
return rv;
}
*bufs->cur->buf.last++ = b;
return 0;
}
int nghttp2_bufs_addb_hold(nghttp2_bufs *bufs, uint8_t b) {
int rv;
rv = bufs_ensure_addb(bufs);
if (rv != 0) {
return rv;
}
*bufs->cur->buf.last = b;
return 0;
}
int nghttp2_bufs_orb(nghttp2_bufs *bufs, uint8_t b) {
int rv;
rv = bufs_ensure_addb(bufs);
if (rv != 0) {
return rv;
}
*bufs->cur->buf.last++ |= b;
return 0;
}
int nghttp2_bufs_orb_hold(nghttp2_bufs *bufs, uint8_t b) {
int rv;
rv = bufs_ensure_addb(bufs);
if (rv != 0) {
return rv;
}
*bufs->cur->buf.last |= b;
return 0;
}
ssize_t nghttp2_bufs_remove(nghttp2_bufs *bufs, uint8_t **out) {
size_t len;
nghttp2_buf_chain *chain;
nghttp2_buf *buf;
uint8_t *res;
nghttp2_buf resbuf;
len = 0;
for (chain = bufs->head; chain; chain = chain->next) {
len += nghttp2_buf_len(&chain->buf);
}
if (!len) {
res = NULL;
} else {
res = nghttp2_mem_malloc(bufs->mem, len);
if (res == NULL) {
return NGHTTP2_ERR_NOMEM;
}
}
nghttp2_buf_wrap_init(&resbuf, res, len);
for (chain = bufs->head; chain; chain = chain->next) {
buf = &chain->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;
return (ssize_t)len;
}
void nghttp2_bufs_reset(nghttp2_bufs *bufs) {
nghttp2_buf_chain *chain, *ci;
size_t k;
k = bufs->chunk_keep;
for (ci = bufs->head; ci; ci = ci->next) {
nghttp2_buf_reset(&ci->buf);
nghttp2_buf_shift_right(&ci->buf, bufs->offset);
if (--k == 0) {
break;
}
}
if (ci) {
chain = ci->next;
ci->next = NULL;
for (ci = chain; ci;) {
chain = ci->next;
buf_chain_del(ci, bufs->mem);
ci = chain;
}
bufs->chunk_used = bufs->chunk_keep;
}
bufs->cur = bufs->head;
}
int nghttp2_bufs_advance(nghttp2_bufs *bufs) { return bufs_alloc_chain(bufs); }
int nghttp2_bufs_next_present(nghttp2_bufs *bufs) {
nghttp2_buf_chain *chain;
chain = bufs->cur->next;
return chain && nghttp2_buf_len(&chain->buf);
}

375
lib/nghttp2_buf.h Normal file
View File

@@ -0,0 +1,375 @@
/*
* nghttp2 - HTTP/2 C Library
*
* Copyright (c) 2014 Tatsuhiro Tsujikawa
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef NGHTTP2_BUF_H
#define NGHTTP2_BUF_H
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif /* HAVE_CONFIG_H */
#include <nghttp2/nghttp2.h>
#include "nghttp2_int.h"
#include "nghttp2_mem.h"
typedef struct {
/* This points to the beginning of the buffer. The effective range
of buffer is [begin, end). */
uint8_t *begin;
/* This points to the memory one byte beyond the end of the
buffer. */
uint8_t *end;
/* The position indicator for effective start of the buffer. pos <=
last must be hold. */
uint8_t *pos;
/* The position indicator for effective one beyond of the end of the
buffer. last <= end must be hold. */
uint8_t *last;
/* Mark arbitrary position in buffer [begin, end) */
uint8_t *mark;
} nghttp2_buf;
#define nghttp2_buf_len(BUF) ((ssize_t)((BUF)->last - (BUF)->pos))
#define nghttp2_buf_avail(BUF) ((ssize_t)((BUF)->end - (BUF)->last))
#define nghttp2_buf_mark_avail(BUF) ((ssize_t)((BUF)->mark - (BUF)->last))
#define nghttp2_buf_cap(BUF) ((ssize_t)((BUF)->end - (BUF)->begin))
#define nghttp2_buf_pos_offset(BUF) ((ssize_t)((BUF)->pos - (BUF)->begin))
#define nghttp2_buf_last_offset(BUF) ((ssize_t)((BUF)->last - (BUF)->begin))
#define nghttp2_buf_shift_right(BUF, AMT) \
do { \
(BUF)->pos += AMT; \
(BUF)->last += AMT; \
} while (0)
#define nghttp2_buf_shift_left(BUF, AMT) \
do { \
(BUF)->pos -= AMT; \
(BUF)->last -= AMT; \
} while (0)
/*
* Initializes the |buf|. No memory is allocated in this function. Use
* nghttp2_buf_reserve() or nghttp2_buf_reserve2() to allocate memory.
*/
void nghttp2_buf_init(nghttp2_buf *buf);
/*
* Initializes the |buf| and allocates at least |initial| bytes of
* memory.
*
* This function returns 0 if it succeeds, or one of the following
* negative error codes:
*
* NGHTTP2_ERR_NOMEM
* Out of memory
*/
int nghttp2_buf_init2(nghttp2_buf *buf, size_t initial, nghttp2_mem *mem);
/*
* Frees buffer in |buf|.
*/
void nghttp2_buf_free(nghttp2_buf *buf, nghttp2_mem *mem);
/*
* Extends buffer so that nghttp2_buf_cap() returns at least
* |new_cap|. If extensions took place, buffer pointers in |buf| will
* change.
*
* This function returns 0 if it succeeds, or one of the followings
* negative error codes:
*
* NGHTTP2_ERR_NOMEM
* Out of memory
*/
int nghttp2_buf_reserve(nghttp2_buf *buf, size_t new_cap, nghttp2_mem *mem);
/*
* Resets pos, last, mark member of |buf| to buf->begin.
*/
void nghttp2_buf_reset(nghttp2_buf *buf);
/*
* Initializes |buf| using supplied buffer |begin| of length
* |len|. Semantically, the application should not call *_reserve() or
* nghttp2_free() functions for |buf|.
*/
void nghttp2_buf_wrap_init(nghttp2_buf *buf, uint8_t *begin, size_t len);
struct nghttp2_buf_chain;
typedef struct nghttp2_buf_chain nghttp2_buf_chain;
/* Chains 2 buffers */
struct nghttp2_buf_chain {
/* Points to the subsequent buffer. NULL if there is no such
buffer. */
nghttp2_buf_chain *next;
nghttp2_buf buf;
};
typedef struct {
/* Points to the first buffer */
nghttp2_buf_chain *head;
/* Buffer pointer where write occurs. */
nghttp2_buf_chain *cur;
/* Memory allocator */
nghttp2_mem *mem;
/* The buffer capacity of each buf */
size_t chunk_length;
/* The maximum number of nghttp2_buf_chain */
size_t max_chunk;
/* The number of nghttp2_buf_chain allocated */
size_t chunk_used;
/* The number of nghttp2_buf_chain to keep on reset */
size_t chunk_keep;
/* pos offset from begin in each buffers. On initialization and
reset, buf->pos and buf->last are positioned at buf->begin +
offset. */
size_t offset;
} nghttp2_bufs;
/*
* This is the same as calling nghttp2_bufs_init2 with the given
* arguments and offset = 0.
*/
int nghttp2_bufs_init(nghttp2_bufs *bufs, size_t chunk_length, size_t max_chunk,
nghttp2_mem *mem);
/*
* This is the same as calling nghttp2_bufs_init3 with the given
* arguments and chunk_keep = max_chunk.
*/
int nghttp2_bufs_init2(nghttp2_bufs *bufs, size_t chunk_length,
size_t max_chunk, size_t offset, nghttp2_mem *mem);
/*
* Initializes |bufs|. Each buffer size is given in the
* |chunk_length|. The maximum number of buffers is given in the
* |max_chunk|. On reset, first |chunk_keep| buffers are kept and
* remaining buffers are deleted. Each buffer will have bufs->pos and
* bufs->last shifted to left by |offset| bytes on creation and reset.
*
* This function allocates first buffer. bufs->head and bufs->cur
* will point to the first buffer after this call.
*
* This function returns 0 if it succeeds, or one of the following
* negative error codes:
*
* NGHTTP2_ERR_NOMEM
* Out of memory.
* NGHTTP2_ERR_INVALID_ARGUMENT
* chunk_keep is 0; or max_chunk < chunk_keep; or offset is too
* long.
*/
int nghttp2_bufs_init3(nghttp2_bufs *bufs, size_t chunk_length,
size_t max_chunk, size_t chunk_keep, size_t offset,
nghttp2_mem *mem);
/*
* Frees any related resources to the |bufs|.
*/
void nghttp2_bufs_free(nghttp2_bufs *bufs);
/*
* Initializes |bufs| using supplied buffer |begin| of length |len|.
* The first buffer bufs->head uses buffer |begin|. The buffer size
* is fixed and no allocate extra chunk buffer is allocated. In other
* words, max_chunk = chunk_keep = 1. To free the resource allocated
* for |bufs|, use nghttp2_bufs_wrap_free().
*
* This function returns 0 if it succeeds, or one of the following
* negative error codes:
*
* NGHTTP2_ERR_NOMEM
* Out of memory.
*/
int nghttp2_bufs_wrap_init(nghttp2_bufs *bufs, uint8_t *begin, size_t len,
nghttp2_mem *mem);
/*
* Frees any related resource to the |bufs|. This function does not
* free supplied buffer provided in nghttp2_bufs_wrap_init().
*/
void nghttp2_bufs_wrap_free(nghttp2_bufs *bufs);
/*
* Reallocates internal buffer using |chunk_length|. The max_chunk,
* chunk_keep and offset do not change. After successful allocation
* of new buffer, previous buffers are deallocated without copying
* anything into new buffers. chunk_used is reset to 1.
*
* This function returns 0 if it succeeds, or one of the following
* negative error codes:
*
* NGHTTP2_ERR_NOMEM
* Out of memory.
* NGHTTP2_ERR_INVALID_ARGUMENT
* chunk_length < offset
*/
int nghttp2_bufs_realloc(nghttp2_bufs *bufs, size_t chunk_length);
/*
* Appends the |data| of length |len| to the |bufs|. The write starts
* at bufs->cur->buf.last. A new buffers will be allocated to store
* all data.
*
* This function returns 0 if it succeeds, or one of the following
* negative error codes:
*
* NGHTTP2_ERR_NOMEM
* Out of memory.
* NGHTTP2_ERR_BUFFER_ERROR
* Out of buffer space.
*/
int nghttp2_bufs_add(nghttp2_bufs *bufs, const void *data, size_t len);
/*
* Appends a single byte |b| to the |bufs|. The write starts at
* bufs->cur->buf.last. A new buffers will be allocated to store all
* data.
*
* This function returns 0 if it succeeds, or one of the following
* negative error codes:
*
* NGHTTP2_ERR_NOMEM
* Out of memory.
* NGHTTP2_ERR_BUFFER_ERROR
* Out of buffer space.
*/
int nghttp2_bufs_addb(nghttp2_bufs *bufs, uint8_t b);
/*
* Behaves like nghttp2_bufs_addb(), but this does not update
* buf->last pointer.
*/
int nghttp2_bufs_addb_hold(nghttp2_bufs *bufs, uint8_t b);
#define nghttp2_bufs_fast_addb(BUFS, B) \
do { \
*(BUFS)->cur->buf.last++ = B; \
} while (0)
#define nghttp2_bufs_fast_addb_hold(BUFS, B) \
do { \
*(BUFS)->cur->buf.last = B; \
} while (0)
/*
* Performs bitwise-OR of |b| at bufs->cur->buf.last. A new buffers
* will be allocated if necessary.
*
* This function returns 0 if it succeeds, or one of the following
* negative error codes:
*
* NGHTTP2_ERR_NOMEM
* Out of memory.
* NGHTTP2_ERR_BUFFER_ERROR
* Out of buffer space.
*/
int nghttp2_bufs_orb(nghttp2_bufs *bufs, uint8_t b);
/*
* Behaves like nghttp2_bufs_orb(), but does not update buf->last
* pointer.
*/
int nghttp2_bufs_orb_hold(nghttp2_bufs *bufs, uint8_t b);
#define nghttp2_bufs_fast_orb(BUFS, B) \
do { \
*(BUFS)->cur->buf.last++ |= B; \
} while (0)
#define nghttp2_bufs_fast_orb_hold(BUFS, B) \
do { \
*(BUFS)->cur->buf.last |= B; \
} while (0)
/*
* Copies all data stored in |bufs| to the contagious buffer. This
* function allocates the contagious memory to store all data in
* |bufs| and assigns it to |*out|.
*
* On successful return, nghttp2_bufs_len(bufs) returns 0, just like
* after calling nghttp2_bufs_reset().
* This function returns the length of copied data and assigns the
* pointer to copied data to |*out| if it succeeds, or one of the
* following negative error codes:
*
* NGHTTP2_ERR_NOMEM
* Out of memory
*/
ssize_t nghttp2_bufs_remove(nghttp2_bufs *bufs, uint8_t **out);
/*
* Resets |bufs| and makes the buffers empty.
*/
void nghttp2_bufs_reset(nghttp2_bufs *bufs);
/*
* Moves bufs->cur to bufs->cur->next. If resulting bufs->cur is
* NULL, this function allocates new buffers and bufs->cur points to
* it.
*
* This function returns 0 if it succeeds, or one of the following
* negative error codes:
*
* NGHTTP2_ERR_NOMEM
* Out of memory
* NGHTTP2_ERR_BUFFER_ERROR
* Out of buffer space.
*/
int nghttp2_bufs_advance(nghttp2_bufs *bufs);
/* Sets bufs->cur to bufs->head */
#define nghttp2_bufs_rewind(BUFS) \
do { \
(BUFS)->cur = (BUFS)->head; \
} while (0)
/*
* Move bufs->cur, from the current position, using next member, to
* the last buf which has nghttp2_buf_len(buf) > 0 without seeing buf
* which satisfies nghttp2_buf_len(buf) == 0. If
* nghttp2_buf_len(&bufs->cur->buf) == 0 or bufs->cur->next is NULL,
* bufs->cur is unchanged.
*/
void nghttp2_bufs_seek_last_present(nghttp2_bufs *bufs);
/*
* Returns nonzero if bufs->cur->next is not emtpy.
*/
int nghttp2_bufs_next_present(nghttp2_bufs *bufs);
#define nghttp2_bufs_cur_avail(BUFS) nghttp2_buf_avail(&(BUFS)->cur->buf)
/*
* Returns the buffer length of |bufs|.
*/
ssize_t nghttp2_bufs_len(nghttp2_bufs *bufs);
#endif /* NGHTTP2_BUF_H */

View File

@@ -1,94 +0,0 @@
/*
* nghttp2 - HTTP/2.0 C Library
*
* Copyright (c) 2014 Tatsuhiro Tsujikawa
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "nghttp2_buffer.h"
#include <assert.h>
#include <string.h>
#include "nghttp2_helper.h"
void nghttp2_buffer_init(nghttp2_buffer *buffer, size_t max_capacity)
{
buffer->buf = NULL;
buffer->len = 0;
buffer->capacity = 0;
buffer->max_capacity = max_capacity;
}
void nghttp2_buffer_free(nghttp2_buffer *buffer)
{
free(buffer->buf);
}
int nghttp2_buffer_reserve(nghttp2_buffer *buffer, size_t len)
{
if(len > buffer->max_capacity) {
return NGHTTP2_ERR_BUFFER_ERROR;
}
if(buffer->capacity < len) {
uint8_t *new_buf;
size_t new_cap = buffer->capacity == 0 ? 8 : buffer->capacity * 3 / 2;
new_cap = nghttp2_min(buffer->max_capacity, nghttp2_max(new_cap, len));
new_buf = realloc(buffer->buf, new_cap);
if(new_buf == NULL) {
return NGHTTP2_ERR_NOMEM;
}
buffer->buf = new_buf;
buffer->capacity = new_cap;
}
return 0;
}
int nghttp2_buffer_add(nghttp2_buffer *buffer,
const uint8_t *data, size_t len)
{
int rv;
rv = nghttp2_buffer_reserve(buffer, buffer->len + len);
if(rv != 0) {
return rv;
}
memcpy(buffer->buf + buffer->len, data, len);
buffer->len += len;
return 0;
}
int nghttp2_buffer_add_byte(nghttp2_buffer *buffer, uint8_t b)
{
int rv;
rv = nghttp2_buffer_reserve(buffer, buffer->len + 1);
if(rv != 0) {
return rv;
}
buffer->buf[buffer->len] = b;
++buffer->len;
return 0;
}
void nghttp2_buffer_release(nghttp2_buffer *buffer)
{
buffer->buf = NULL;
buffer->len = 0;
buffer->capacity = 0;
}

View File

@@ -1,103 +0,0 @@
/*
* nghttp2 - HTTP/2.0 C Library
*
* Copyright (c) 2014 Tatsuhiro Tsujikawa
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef NGHTTP2_BUFFER_H
#define NGHTTP2_BUFFER_H
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include <nghttp2/nghttp2.h>
#include "nghttp2_int.h"
/*
* Byte array buffer
*/
typedef struct {
uint8_t *buf;
/* Capacity of this buffer */
size_t capacity;
/* How many bytes are written to buf. len <= capacity must hold. */
size_t len;
/* Maximum capacity this buffer can grow up */
size_t max_capacity;
} nghttp2_buffer;
void nghttp2_buffer_init(nghttp2_buffer *buffer, size_t max_capacity);
void nghttp2_buffer_free(nghttp2_buffer *buffer);
/*
* Expands capacity so that it can contain at least |len| bytes of
* data. If buffer->capacity >= len, no action is taken. If len >
* buffer->max_capacity, NGHTTP2_ERR_BUFFER_ERROR is returned.
*
* This function returns 0 if it succeeds, or one of the following
* negative error codes:
*
* NGHTTP2_ERR_BUFFER_ERROR
* The |len| is strictly larger than buffer->max_capacity
* NGHTTP2_ERR_NOMEM
* Out of memory
*/
int nghttp2_buffer_reserve(nghttp2_buffer *buffer, size_t len);
/*
* Appends the |data| with |len| bytes to the buffer. The data is
* copied. The |buffer| will be expanded as needed.
*
* This function returns 0 if it succeeds, or one of the following
* negative error codes:
*
* NGHTTP2_ERR_BUFFER_ERROR
* The |len| is strictly larger than buffer->max_capacity
* NGHTTP2_ERR_NOMEM
* Out of memory
*/
int nghttp2_buffer_add(nghttp2_buffer *buffer,
const uint8_t *data, size_t len);
/*
* Appends the a single byte|b| to the buffer. The data is copied. The
* |buffer| will be expanded as needed.
*
* This function returns 0 if it succeeds, or one of the following
* negative error codes:
*
* NGHTTP2_ERR_BUFFER_ERROR
* The |len| is strictly larger than buffer->max_capacity
* NGHTTP2_ERR_NOMEM
* Out of memory
*/
int nghttp2_buffer_add_byte(nghttp2_buffer *buffer, uint8_t b);
/*
* Releases the buffer without freeing it. The data members in buffer
* is initialized.
*/
void nghttp2_buffer_release(nghttp2_buffer *buffer);
#endif /* NGHTTP2_BUFFER_H */

123
lib/nghttp2_callbacks.c Normal file
View File

@@ -0,0 +1,123 @@
/*
* nghttp2 - HTTP/2 C Library
*
* Copyright (c) 2014 Tatsuhiro Tsujikawa
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "nghttp2_callbacks.h"
#include <stdlib.h>
int nghttp2_session_callbacks_new(nghttp2_session_callbacks **callbacks_ptr) {
*callbacks_ptr = calloc(1, sizeof(nghttp2_session_callbacks));
if (*callbacks_ptr == NULL) {
return NGHTTP2_ERR_NOMEM;
}
return 0;
}
void nghttp2_session_callbacks_del(nghttp2_session_callbacks *callbacks) {
free(callbacks);
}
void nghttp2_session_callbacks_set_send_callback(
nghttp2_session_callbacks *cbs, nghttp2_send_callback send_callback) {
cbs->send_callback = send_callback;
}
void nghttp2_session_callbacks_set_recv_callback(
nghttp2_session_callbacks *cbs, nghttp2_recv_callback recv_callback) {
cbs->recv_callback = recv_callback;
}
void nghttp2_session_callbacks_set_on_frame_recv_callback(
nghttp2_session_callbacks *cbs,
nghttp2_on_frame_recv_callback on_frame_recv_callback) {
cbs->on_frame_recv_callback = on_frame_recv_callback;
}
void nghttp2_session_callbacks_set_on_invalid_frame_recv_callback(
nghttp2_session_callbacks *cbs,
nghttp2_on_invalid_frame_recv_callback on_invalid_frame_recv_callback) {
cbs->on_invalid_frame_recv_callback = on_invalid_frame_recv_callback;
}
void nghttp2_session_callbacks_set_on_data_chunk_recv_callback(
nghttp2_session_callbacks *cbs,
nghttp2_on_data_chunk_recv_callback on_data_chunk_recv_callback) {
cbs->on_data_chunk_recv_callback = on_data_chunk_recv_callback;
}
void nghttp2_session_callbacks_set_before_frame_send_callback(
nghttp2_session_callbacks *cbs,
nghttp2_before_frame_send_callback before_frame_send_callback) {
cbs->before_frame_send_callback = before_frame_send_callback;
}
void nghttp2_session_callbacks_set_on_frame_send_callback(
nghttp2_session_callbacks *cbs,
nghttp2_on_frame_send_callback on_frame_send_callback) {
cbs->on_frame_send_callback = on_frame_send_callback;
}
void nghttp2_session_callbacks_set_on_frame_not_send_callback(
nghttp2_session_callbacks *cbs,
nghttp2_on_frame_not_send_callback on_frame_not_send_callback) {
cbs->on_frame_not_send_callback = on_frame_not_send_callback;
}
void nghttp2_session_callbacks_set_on_stream_close_callback(
nghttp2_session_callbacks *cbs,
nghttp2_on_stream_close_callback on_stream_close_callback) {
cbs->on_stream_close_callback = on_stream_close_callback;
}
void nghttp2_session_callbacks_set_on_begin_headers_callback(
nghttp2_session_callbacks *cbs,
nghttp2_on_begin_headers_callback on_begin_headers_callback) {
cbs->on_begin_headers_callback = on_begin_headers_callback;
}
void nghttp2_session_callbacks_set_on_header_callback(
nghttp2_session_callbacks *cbs,
nghttp2_on_header_callback on_header_callback) {
cbs->on_header_callback = on_header_callback;
}
void nghttp2_session_callbacks_set_select_padding_callback(
nghttp2_session_callbacks *cbs,
nghttp2_select_padding_callback select_padding_callback) {
cbs->select_padding_callback = select_padding_callback;
}
void nghttp2_session_callbacks_set_data_source_read_length_callback(
nghttp2_session_callbacks *cbs,
nghttp2_data_source_read_length_callback data_source_read_length_callback) {
cbs->read_length_callback = data_source_read_length_callback;
}
void nghttp2_session_callbacks_set_on_begin_frame_callback(
nghttp2_session_callbacks *cbs,
nghttp2_on_begin_frame_callback on_begin_frame_callback) {
cbs->on_begin_frame_callback = on_begin_frame_callback;
}

111
lib/nghttp2_callbacks.h Normal file
View File

@@ -0,0 +1,111 @@
/*
* nghttp2 - HTTP/2 C Library
*
* Copyright (c) 2014 Tatsuhiro Tsujikawa
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef NGHTTP2_CALLBACKS_H
#define NGHTTP2_CALLBACKS_H
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif /* HAVE_CONFIG_H */
#include <nghttp2/nghttp2.h>
/*
* Callback functions.
*/
struct nghttp2_session_callbacks {
/**
* Callback function invoked when the session wants to send data to
* the remote peer. This callback is not necessary if the
* application uses solely `nghttp2_session_mem_send()` to serialize
* data to transmit.
*/
nghttp2_send_callback send_callback;
/**
* Callback function invoked when the session wants to receive data
* from the remote peer. This callback is not necessary if the
* application uses solely `nghttp2_session_mem_recv()` to process
* received data.
*/
nghttp2_recv_callback recv_callback;
/**
* Callback function invoked by `nghttp2_session_recv()` when a
* frame is received.
*/
nghttp2_on_frame_recv_callback on_frame_recv_callback;
/**
* Callback function invoked by `nghttp2_session_recv()` when an
* invalid non-DATA frame is received.
*/
nghttp2_on_invalid_frame_recv_callback on_invalid_frame_recv_callback;
/**
* Callback function invoked when a chunk of data in DATA frame is
* received.
*/
nghttp2_on_data_chunk_recv_callback on_data_chunk_recv_callback;
/**
* Callback function invoked before a non-DATA frame is sent.
*/
nghttp2_before_frame_send_callback before_frame_send_callback;
/**
* Callback function invoked after a frame is sent.
*/
nghttp2_on_frame_send_callback on_frame_send_callback;
/**
* The callback function invoked when a non-DATA frame is not sent
* because of an error.
*/
nghttp2_on_frame_not_send_callback on_frame_not_send_callback;
/**
* Callback function invoked when the stream is closed.
*/
nghttp2_on_stream_close_callback on_stream_close_callback;
/**
* Callback function invoked when the reception of header block in
* HEADERS or PUSH_PROMISE is started.
*/
nghttp2_on_begin_headers_callback on_begin_headers_callback;
/**
* Callback function invoked when a header name/value pair is
* received.
*/
nghttp2_on_header_callback on_header_callback;
/**
* Callback function invoked when the library asks application how
* many padding bytes are required for the transmission of the given
* frame.
*/
nghttp2_select_padding_callback select_padding_callback;
/**
* The callback function used to determine the length allowed in
* `nghttp2_data_source_read_callback()`
*/
nghttp2_data_source_read_length_callback read_length_callback;
/**
* Sets callback function invoked when a frame header is received.
*/
nghttp2_on_begin_frame_callback on_begin_frame_callback;
};
#endif /* NGHTTP2_CALLBACKS_H */

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,5 @@
/*
* nghttp2 - HTTP/2.0 C Library
* nghttp2 - HTTP/2 C Library
*
* Copyright (c) 2012 Tatsuhiro Tsujikawa
*
@@ -26,61 +26,93 @@
#define NGHTTP2_FRAME_H
#ifdef HAVE_CONFIG_H
# include <config.h>
#include <config.h>
#endif /* HAVE_CONFIG_H */
#include <nghttp2/nghttp2.h>
#include "nghttp2_hd.h"
#include "nghttp2_buffer.h"
#include "nghttp2_buf.h"
#define NGHTTP2_FRAME_LENGTH_MASK ((1 << 14) - 1)
#define NGHTTP2_STREAM_ID_MASK ((1u << 31) - 1)
#define NGHTTP2_PRI_GROUP_ID_MASK ((1u << 31) - 1)
#define NGHTTP2_PRIORITY_MASK ((1u << 31) - 1)
#define NGHTTP2_WINDOW_SIZE_INCREMENT_MASK ((1u << 31) - 1)
#define NGHTTP2_SETTINGS_ID_MASK ((1 << 24) - 1)
/* The maximum payload length of a frame */
#define NGHTTP2_MAX_FRAME_LENGTH ((1 << 14) - 1)
/* The maximum length of DATA frame payload. */
#define NGHTTP2_DATA_PAYLOAD_LENGTH 4096
/* The number of bytes of frame header. */
#define NGHTTP2_FRAME_HEAD_LENGTH 8
#define NGHTTP2_FRAME_HDLEN 9
/* Category of frames. */
typedef enum {
/* non-DATA frame */
NGHTTP2_CAT_CTRL,
/* DATA frame */
NGHTTP2_CAT_DATA
} nghttp2_frame_category;
#define NGHTTP2_MAX_FRAME_SIZE_MAX ((1 << 24) - 1)
#define NGHTTP2_MAX_FRAME_SIZE_MIN (1 << 14)
/**
* @struct
*
* The DATA frame used in the library privately. It has the following
* members:
*/
typedef struct {
nghttp2_frame_hd hd;
/**
* The data to be sent for this DATA frame.
*/
nghttp2_data_provider data_prd;
/**
* The flag to indicate whether EOF was reached or not. Initially
* |eof| is 0. It becomes 1 after all data were read. This is used
* exclusively by nghttp2 library and not in the spec.
*/
uint8_t eof;
} nghttp2_private_data;
#define NGHTTP2_MAX_PAYLOADLEN 16384
/* The one frame buffer length for tranmission. We may use several of
them to support CONTINUATION. To account for Pad Length field, we
allocate extra 1 byte, which saves extra large memcopying. */
#define NGHTTP2_FRAMEBUF_CHUNKLEN \
(NGHTTP2_FRAME_HDLEN + 1 + NGHTTP2_MAX_PAYLOADLEN)
int nghttp2_frame_is_data_frame(uint8_t *head);
/* Number of inbound buffer */
#define NGHTTP2_FRAMEBUF_MAX_NUM 5
/* The default length of DATA frame payload. This should be small enough
* for the data payload and the header to fit into 1 TLS record */
#define NGHTTP2_DATA_PAYLOADLEN \
((NGHTTP2_MAX_FRAME_SIZE_MIN) - (NGHTTP2_FRAME_HDLEN))
/* Maximum headers payload length, calculated in compressed form.
This applies to transmission only. */
#define NGHTTP2_MAX_HEADERSLEN 65536
/* The number of bytes for each SETTINGS entry */
#define NGHTTP2_FRAME_SETTINGS_ENTRY_LENGTH 6
/* The maximum header table size in SETTINGS_HEADER_TABLE_SIZE */
#define NGHTTP2_MAX_HEADER_TABLE_SIZE ((1u << 31) - 1)
/* Length of priority related fields in HEADERS/PRIORITY frames */
#define NGHTTP2_PRIORITY_SPECLEN 5
/* Maximum length of padding in bytes. */
#define NGHTTP2_MAX_PADLEN 256
/* Union of extension frame payload */
typedef union { nghttp2_ext_altsvc altsvc; } nghttp2_ext_frame_payload;
void nghttp2_frame_pack_frame_hd(uint8_t *buf, const nghttp2_frame_hd *hd);
void nghttp2_frame_unpack_frame_hd(nghttp2_frame_hd *hd, const uint8_t* buf);
void nghttp2_frame_unpack_frame_hd(nghttp2_frame_hd *hd, const uint8_t *buf);
/**
* Initializes frame header |hd| with given parameters. Reserved bit
* is set to 0.
*/
void nghttp2_frame_hd_init(nghttp2_frame_hd *hd, size_t length, uint8_t type,
uint8_t flags, int32_t stream_id);
/**
* Returns the number of priority field depending on the |flags|. If
* |flags| has neither NGHTTP2_FLAG_PRIORITY_GROUP nor
* NGHTTP2_FLAG_PRIORITY_DEPENDENCY set, return 0.
*/
size_t nghttp2_frame_priority_len(uint8_t flags);
/**
* Packs the |pri_spec| in |buf|. This function assumes |buf| has
* enough space for serialization.
*/
void nghttp2_frame_pack_priority_spec(uint8_t *buf,
const nghttp2_priority_spec *pri_spec);
/**
* Unpacks the priority specification from payload |payload| of length
* |payloadlen| to |pri_spec|. The |flags| is used to determine what
* kind of priority specification is in |payload|. This function
* assumes the |payload| contains whole priority specification.
*/
void nghttp2_frame_unpack_priority_spec(nghttp2_priority_spec *pri_spec,
uint8_t flags, const uint8_t *payload,
size_t payloadlen);
/*
* Returns the offset from the HEADERS frame payload where the
@@ -90,42 +122,33 @@ void nghttp2_frame_unpack_frame_hd(nghttp2_frame_hd *hd, const uint8_t* buf);
size_t nghttp2_frame_headers_payload_nv_offset(nghttp2_headers *frame);
/*
* Packs HEADERS frame |frame| in wire format and store it in
* |*buf_ptr|. The capacity of |*buf_ptr| is |*buflen_ptr| bytes.
* This function expands |*buf_ptr| as necessary to store frame. When
* expansion occurred, memory previously pointed by |*buf_ptr| may
* change. |*buf_ptr| and |*buflen_ptr| are updated accordingly.
* Packs HEADERS frame |frame| in wire format and store it in |bufs|.
* This function expands |bufs| as necessary to store frame.
*
* The caller must make sure that nghttp2_bufs_reset(bufs) is called
* before calling this function.
*
* frame->hd.length is assigned after length is determined during
* packing process. If payload length is strictly larger than
* NGHTTP2_MAX_FRAME_LENGTH, payload data is still serialized as is,
* but frame->hd.length is set to NGHTTP2_MAX_FRAME_LENGTH and
* NGHTTP2_FLAG_END_HEADERS flag is cleared from frame->hd.flags.
* packing process. CONTINUATION frames are also serialized in this
* function. This function does not handle padding.
*
* This function returns the size of packed frame if it succeeds, or
* returns one of the following negative error codes:
* This function returns 0 if it succeeds, or returns one of the
* following negative error codes:
*
* NGHTTP2_ERR_HEADER_COMP
* The deflate operation failed.
* NGHTTP2_ERR_FRAME_TOO_LARGE
* The length of the frame is too large.
* NGHTTP2_ERR_NOMEM
* Out of memory.
*/
ssize_t nghttp2_frame_pack_headers(uint8_t **buf_ptr,
size_t *buflen_ptr,
nghttp2_headers *frame,
int nghttp2_frame_pack_headers(nghttp2_bufs *bufs, nghttp2_headers *frame,
nghttp2_hd_deflater *deflater);
/*
* Unpacks HEADERS frame byte sequence into |frame|. This function
* only unapcks bytes that come before name/value header block.
* only unapcks bytes that come before name/value header block and
* after possible Pad Length field.
*
* This function returns 0 if it succeeds or one of the following
* negative error codes:
*
* NGHTTP2_ERR_PROTO
* TODO END_HEADERS flag is not set
* This function always succeeds and returns 0.
*/
int nghttp2_frame_unpack_headers_payload(nghttp2_headers *frame,
const uint8_t *payload,
@@ -133,18 +156,14 @@ int nghttp2_frame_unpack_headers_payload(nghttp2_headers *frame,
/*
* Packs PRIORITY frame |frame| in wire format and store it in
* |*buf_ptr|. The capacity of |*buf_ptr| is |*buflen_ptr|
* length. This function expands |*buf_ptr| as necessary to store
* given |frame|.
* |bufs|.
*
* This function returns 0 if it succeeds or one of the following
* negative error codes:
* The caller must make sure that nghttp2_bufs_reset(bufs) is called
* before calling this function.
*
* NGHTTP2_ERR_NOMEM
* Out of memory.
* This function always succeeds and returns 0.
*/
ssize_t nghttp2_frame_pack_priority(uint8_t **buf_ptr, size_t *buflen_ptr,
nghttp2_priority *frame);
int nghttp2_frame_pack_priority(nghttp2_bufs *bufs, nghttp2_priority *frame);
/*
* Unpacks PRIORITY wire format into |frame|.
@@ -155,18 +174,14 @@ void nghttp2_frame_unpack_priority_payload(nghttp2_priority *frame,
/*
* Packs RST_STREAM frame |frame| in wire frame format and store it in
* |*buf_ptr|. The capacity of |*buf_ptr| is |*buflen_ptr|
* length. This function expands |*buf_ptr| as necessary to store
* given |frame|. In spdy/2 spec, RST_STREAM wire format is always 16
* bytes long.
* |bufs|.
*
* This function returns the size of packed frame if it succeeds, or
* returns one of the following negative error codes:
* The caller must make sure that nghttp2_bufs_reset(bufs) is called
* before calling this function.
*
* NGHTTP2_ERR_NOMEM
* Out of memory.
* This function always succeeds and returns 0.
*/
ssize_t nghttp2_frame_pack_rst_stream(uint8_t **buf_ptr, size_t *buflen_ptr,
int nghttp2_frame_pack_rst_stream(nghttp2_bufs *bufs,
nghttp2_rst_stream *frame);
/*
@@ -178,18 +193,18 @@ void nghttp2_frame_unpack_rst_stream_payload(nghttp2_rst_stream *frame,
/*
* Packs SETTINGS frame |frame| in wire format and store it in
* |*buf_ptr|. The capacity of |*buf_ptr| is |*buflen_ptr|
* length. This function expands |*buf_ptr| as necessary to store
* given |frame|.
* |bufs|.
*
* This function returns the size of packed frame if it succeeds, or
* returns one of the following negative error codes:
* The caller must make sure that nghttp2_bufs_reset(bufs) is called
* before calling this function.
*
* NGHTTP2_ERR_NOMEM
* Out of memory.
* This function returns 0 if it succeeds, or returns one of the
* following negative error codes:
*
* NGHTTP2_ERR_FRAME_SIZE_ERROR
* The length of the frame is too large.
*/
ssize_t nghttp2_frame_pack_settings(uint8_t **buf_ptr, size_t *buflen_ptr,
nghttp2_settings *frame);
int nghttp2_frame_pack_settings(nghttp2_bufs *bufs, nghttp2_settings *frame);
/*
* Packs the |iv|, which includes |niv| entries, in the |buf|,
@@ -216,7 +231,7 @@ void nghttp2_frame_unpack_settings_entry(nghttp2_settings_entry *iv,
*/
int nghttp2_frame_unpack_settings_payload(nghttp2_settings *frame,
nghttp2_settings_entry *iv,
size_t niv);
size_t niv, nghttp2_mem *mem);
/*
* Unpacks SETTINGS payload into |*iv_ptr|. The number of entries are
@@ -233,39 +248,36 @@ int nghttp2_frame_unpack_settings_payload(nghttp2_settings *frame,
int nghttp2_frame_unpack_settings_payload2(nghttp2_settings_entry **iv_ptr,
size_t *niv_ptr,
const uint8_t *payload,
size_t payloadlen);
size_t payloadlen, nghttp2_mem *mem);
/*
* Packs PUSH_PROMISE frame |frame| in wire format and store it in
* |*buf_ptr|. The capacity of |*buf_ptr| is |*buflen_ptr| bytes.
* This function expands |*buf_ptr| as necessary to store frame. When
* expansion occurred, memory previously pointed by |*buf_ptr| may
* change. |*buf_ptr| and |*buflen_ptr| are updated accordingly.
* |bufs|. This function expands |bufs| as necessary to store
* frame.
*
* The caller must make sure that nghttp2_bufs_reset(bufs) is called
* before calling this function.
*
* frame->hd.length is assigned after length is determined during
* packing process. If payload length is strictly larger than
* NGHTTP2_MAX_FRAME_LENGTH, payload data is still serialized as is,
* but frame->hd.length is set to NGHTTP2_MAX_FRAME_LENGTH and
* NGHTTP2_FLAG_END_HEADERS flag is cleared from frame->hd.flags.
* packing process. CONTINUATION frames are also serialized in this
* function. This function does not handle padding.
*
* This function returns the size of packed frame if it succeeds, or
* returns one of the following negative error codes:
* This function returns 0 if it succeeds, or returns one of the
* following negative error codes:
*
* NGHTTP2_ERR_HEADER_COMP
* The deflate operation failed.
* NGHTTP2_ERR_FRAME_TOO_LARGE
* The length of the frame is too large.
* NGHTTP2_ERR_NOMEM
* Out of memory.
*/
ssize_t nghttp2_frame_pack_push_promise(uint8_t **buf_ptr,
size_t *buflen_ptr,
int nghttp2_frame_pack_push_promise(nghttp2_bufs *bufs,
nghttp2_push_promise *frame,
nghttp2_hd_deflater *deflater);
/*
* Unpacks PUSH_PROMISE frame byte sequence into |frame|. This function
* only unapcks bytes that come before name/value header block.
* Unpacks PUSH_PROMISE frame byte sequence into |frame|. This
* function only unapcks bytes that come before name/value header
* block and after possible Pad Length field.
*
* This function returns 0 if it succeeds or one of the following
* negative error codes:
@@ -279,18 +291,14 @@ int nghttp2_frame_unpack_push_promise_payload(nghttp2_push_promise *frame,
/*
* Packs PING frame |frame| in wire format and store it in
* |*buf_ptr|. The capacity of |*buf_ptr| is |*buflen_ptr|
* length. This function expands |*buf_ptr| as necessary to store
* given |frame|.
* |bufs|.
*
* This function returns 0 if it succeeds or one of the following
* negative error codes:
* The caller must make sure that nghttp2_bufs_reset(bufs) is called
* before calling this function.
*
* NGHTTP2_ERR_NOMEM
* Out of memory.
* This function always succeeds and returns 0.
*/
ssize_t nghttp2_frame_pack_ping(uint8_t **buf_ptr, size_t *buflen_ptr,
nghttp2_ping *frame);
int nghttp2_frame_pack_ping(nghttp2_bufs *bufs, nghttp2_ping *frame);
/*
* Unpacks PING wire format into |frame|.
@@ -300,40 +308,61 @@ void nghttp2_frame_unpack_ping_payload(nghttp2_ping *frame,
size_t payloadlen);
/*
* Packs GOAWAY frame |frame | in wire format and store it in
* |*buf_ptr|. The capacity of |*buf_ptr| is |*buflen_ptr|
* length. This function expands |*buf_ptr| as necessary to store
* given |frame|.
* Packs GOAWAY frame |frame| in wire format and store it in |bufs|.
* This function expands |bufs| as necessary to store frame.
*
* The caller must make sure that nghttp2_bufs_reset(bufs) is called
* before calling this function.
*
* This function returns 0 if it succeeds or one of the following
* negative error codes:
*
* NGHTTP2_ERR_NOMEM
* Out of memory.
* NGHTTP2_ERR_FRAME_SIZE_ERROR
* The length of the frame is too large.
*/
ssize_t nghttp2_frame_pack_goaway(uint8_t **buf_ptr, size_t *buflen_ptr,
nghttp2_goaway *frame);
int nghttp2_frame_pack_goaway(nghttp2_bufs *bufs, nghttp2_goaway *frame);
/*
* Unpacks GOAWAY wire format into |frame|.
* Unpacks GOAWAY wire format into |frame|. The |payload| of length
* |payloadlen| contains first 8 bytes of payload. The
* |var_gift_payload| of length |var_gift_payloadlen| contains
* remaining payload and its buffer is gifted to the function and then
* |frame|. The |var_gift_payloadlen| must be freed by
* nghttp2_frame_goaway_free().
*/
void nghttp2_frame_unpack_goaway_payload(nghttp2_goaway *frame,
const uint8_t *payload,
size_t payloadlen);
size_t payloadlen,
uint8_t *var_gift_payload,
size_t var_gift_payloadlen);
/*
* Packs WINDOW_UPDATE frame |frame| in wire frame format and store it
* in |*buf_ptr|. The capacity of |*buf_ptr| is |*buflen_ptr|
* length. This function expands |*buf_ptr| as necessary to store
* given |frame|.
* Unpacks GOAWAY wire format into |frame|. This function only exists
* for unit test. After allocating buffer for debug data, this
* function internally calls nghttp2_frame_unpack_goaway_payload().
*
* This function returns the size of packed frame if it succeeds, or
* returns one of the following negative error codes:
* This function returns 0 if it succeeds, or one of the following
* negative error codes:
*
* NGHTTP2_ERR_NOMEM
* Out of memory.
*/
ssize_t nghttp2_frame_pack_window_update(uint8_t **buf_ptr, size_t *buflen_ptr,
int nghttp2_frame_unpack_goaway_payload2(nghttp2_goaway *frame,
const uint8_t *payload,
size_t payloadlen, nghttp2_mem *mem);
/*
* Packs WINDOW_UPDATE frame |frame| in wire frame format and store it
* in |bufs|.
*
* The caller must make sure that nghttp2_bufs_reset(bufs) is called
* before calling this function.
*
* This function always succeeds and returns 0.
*/
int nghttp2_frame_pack_window_update(nghttp2_bufs *bufs,
nghttp2_window_update *frame);
/*
@@ -348,21 +377,20 @@ void nghttp2_frame_unpack_window_update_payload(nghttp2_window_update *frame,
* ownership of |nva|, so caller must not free it. If |stream_id| is
* not assigned yet, it must be -1.
*/
void nghttp2_frame_headers_init(nghttp2_headers *frame,
uint8_t flags, int32_t stream_id, int32_t pri,
void nghttp2_frame_headers_init(nghttp2_headers *frame, uint8_t flags,
int32_t stream_id, nghttp2_headers_category cat,
const nghttp2_priority_spec *pri_spec,
nghttp2_nv *nva, size_t nvlen);
void nghttp2_frame_headers_free(nghttp2_headers *frame);
void nghttp2_frame_headers_free(nghttp2_headers *frame, nghttp2_mem *mem);
void nghttp2_frame_priority_init(nghttp2_priority *frame, int32_t stream_id,
int32_t pri);
const nghttp2_priority_spec *pri_spec);
void nghttp2_frame_priority_free(nghttp2_priority *frame);
void nghttp2_frame_rst_stream_init(nghttp2_rst_stream *frame,
int32_t stream_id,
nghttp2_error_code error_code);
void nghttp2_frame_rst_stream_init(nghttp2_rst_stream *frame, int32_t stream_id,
uint32_t error_code);
void nghttp2_frame_rst_stream_free(nghttp2_rst_stream *frame);
@@ -370,12 +398,13 @@ void nghttp2_frame_rst_stream_free(nghttp2_rst_stream *frame);
* Initializes PUSH_PROMISE frame |frame| with given values. |frame|
* takes ownership of |nva|, so caller must not free it.
*/
void nghttp2_frame_push_promise_init(nghttp2_push_promise *frame,
uint8_t flags, int32_t stream_id,
void nghttp2_frame_push_promise_init(nghttp2_push_promise *frame, uint8_t flags,
int32_t stream_id,
int32_t promised_stream_id,
nghttp2_nv *nva, size_t nvlen);
void nghttp2_frame_push_promise_free(nghttp2_push_promise *frame);
void nghttp2_frame_push_promise_free(nghttp2_push_promise *frame,
nghttp2_mem *mem);
/*
* Initializes SETTINGS frame |frame| with given values. |frame| takes
@@ -385,7 +414,7 @@ void nghttp2_frame_push_promise_free(nghttp2_push_promise *frame);
void nghttp2_frame_settings_init(nghttp2_settings *frame, uint8_t flags,
nghttp2_settings_entry *iv, size_t niv);
void nghttp2_frame_settings_free(nghttp2_settings *frame);
void nghttp2_frame_settings_free(nghttp2_settings *frame, nghttp2_mem *mem);
/*
* Initializes PING frame |frame| with given values. If the
@@ -404,34 +433,36 @@ void nghttp2_frame_ping_free(nghttp2_ping *frame);
* free it. If the |opaque_data_len| is 0, opaque_data could be NULL.
*/
void nghttp2_frame_goaway_init(nghttp2_goaway *frame, int32_t last_stream_id,
nghttp2_error_code error_code,
uint8_t *opaque_data, size_t opaque_data_len);
uint32_t error_code, uint8_t *opaque_data,
size_t opaque_data_len);
void nghttp2_frame_goaway_free(nghttp2_goaway *frame);
void nghttp2_frame_goaway_free(nghttp2_goaway *frame, nghttp2_mem *mem);
void nghttp2_frame_window_update_init(nghttp2_window_update *frame,
uint8_t flags,
int32_t stream_id,
uint8_t flags, int32_t stream_id,
int32_t window_size_increment);
void nghttp2_frame_window_update_free(nghttp2_window_update *frame);
void nghttp2_frame_data_init(nghttp2_data *frame, nghttp2_private_data *pdata);
/*
* Returns the number of padding bytes after payload. The total
* padding length is given in the |padlen|. The returned value does
* not include the Pad Length field.
*/
size_t nghttp2_frame_trail_padlen(nghttp2_frame *frame, size_t padlen);
void nghttp2_frame_private_data_init(nghttp2_private_data *frame,
uint8_t flags,
int32_t stream_id,
const nghttp2_data_provider *data_prd);
void nghttp2_frame_data_init(nghttp2_data *frame, uint8_t flags,
int32_t stream_id);
void nghttp2_frame_private_data_free(nghttp2_private_data *frame);
void nghttp2_frame_data_free(nghttp2_data *frame);
/*
* Makes copy of |iv| and return the copy. The |niv| is the number of
* entries in |iv|. This function returns the pointer to the copy if
* it succeeds, or NULL.
*/
nghttp2_settings_entry* nghttp2_frame_iv_copy(const nghttp2_settings_entry *iv,
size_t niv);
nghttp2_settings_entry *nghttp2_frame_iv_copy(const nghttp2_settings_entry *iv,
size_t niv, nghttp2_mem *mem);
/*
* Sorts the |nva| in ascending order of name and value. If names are
@@ -446,17 +477,14 @@ void nghttp2_nv_array_sort(nghttp2_nv *nva, size_t nvlen);
*
* The |*nva_ptr| must be freed using nghttp2_nv_array_del().
*
* This function returns the number of name/value pairs in |*nva_ptr|,
* or one of the following negative error codes:
* This function returns 0 if it succeeds or one of the following
* negative error codes:
*
* NGHTTP2_ERR_NOMEM
* Out of memory.
* NGHTTP2_ERR_INVALID_ARGUMENT
* The length of name or value in |nva| is strictly larger than
* NGHTTP2_MAX_HD_VALUE_LENGTH.
*/
ssize_t nghttp2_nv_array_copy(nghttp2_nv **nva_ptr,
const nghttp2_nv *nva, size_t nvlen);
int nghttp2_nv_array_copy(nghttp2_nv **nva_ptr, const nghttp2_nv *nva,
size_t nvlen, nghttp2_mem *mem);
/*
* Returns nonzero if the name/value pair |a| equals to |b|. The name
@@ -468,16 +496,31 @@ int nghttp2_nv_equal(const nghttp2_nv *a, const nghttp2_nv *b);
/*
* Frees |nva|.
*/
void nghttp2_nv_array_del(nghttp2_nv *nva);
void nghttp2_nv_array_del(nghttp2_nv *nva, nghttp2_mem *mem);
/*
* Checks that the |iv|, which includes |niv| entries, does not have
* invalid values. The |flow_control_opt| is current flow control
* option value.
* invalid values.
*
* This function returns nonzero if it succeeds, or 0.
*/
int nghttp2_iv_check(const nghttp2_settings_entry *iv, size_t niv,
int32_t flow_control_opt);
int nghttp2_iv_check(const nghttp2_settings_entry *iv, size_t niv);
/*
* Sets Pad Length field and flags and adjusts frame header position
* of each buffers in |bufs|. The number of padding is given in the
* |padlen| including Pad Length field. The |hd| is the frame header
* for the serialized data.
*
* This function returns 0 if it succeeds, or one of the following
* negative error codes:
*
* NGHTTP2_ERR_NOMEM
* Out of memory.
* NGHTTP2_ERR_FRAME_SIZE_ERROR
* The length of the resulting frame is too large.
*/
int nghttp2_frame_add_pad(nghttp2_bufs *bufs, nghttp2_frame_hd *hd,
size_t padlen);
#endif /* NGHTTP2_FRAME_H */

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,5 @@
/*
* nghttp2 - HTTP/2.0 C Library
* nghttp2 - HTTP/2 C Library
*
* Copyright (c) 2013 Tatsuhiro Tsujikawa
*
@@ -22,41 +22,34 @@
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef NGHTTP2_HD_COMP_H
#define NGHTTP2_HD_COMP_H
#ifndef NGHTTP2_HD_H
#define NGHTTP2_HD_H
#ifdef HAVE_CONFIG_H
# include <config.h>
#include <config.h>
#endif /* HAVE_CONFIG_H */
#include <nghttp2/nghttp2.h>
#include "nghttp2_hd_huffman.h"
#include "nghttp2_buffer.h"
#include "nghttp2_buf.h"
#include "nghttp2_mem.h"
#define NGHTTP2_HD_DEFAULT_MAX_BUFFER_SIZE (1 << 12)
#define NGHTTP2_HD_DEFAULT_MAX_BUFFER_SIZE NGHTTP2_DEFAULT_HEADER_TABLE_SIZE
#define NGHTTP2_HD_ENTRY_OVERHEAD 32
/* The maximum value length of name/value pair. This is not specified
by the spec. We just chose the arbitrary size */
#define NGHTTP2_HD_MAX_NAME 256
#define NGHTTP2_HD_MAX_VALUE 4096
#define NGHTTP2_HD_MAX_BUFFER_LENGTH (1 << 15)
/* The maximum length of one name/value pair. This is the sum of the
length of name and value. This is not specified by the spec. We
just chose the arbitrary size */
#define NGHTTP2_HD_MAX_NV 65536
/* Default size of maximum table buffer size for encoder. Even if
remote decoder notifies larger buffer size for its decoding,
encoder only uses the memory up to this value. */
#define NGHTTP2_HD_DEFAULT_MAX_DEFLATE_BUFFER_SIZE (1 << 12)
typedef enum {
NGHTTP2_HD_SIDE_REQUEST = 0,
NGHTTP2_HD_SIDE_RESPONSE = 1
} nghttp2_hd_side;
typedef enum {
NGHTTP2_HD_ROLE_DEFLATE,
NGHTTP2_HD_ROLE_INFLATE
} nghttp2_hd_role;
/* Exported for unit test */
extern const size_t NGHTTP2_STATIC_TABLE_LENGTH;
typedef enum {
NGHTTP2_HD_FLAG_NONE = 0,
@@ -64,18 +57,12 @@ typedef enum {
NGHTTP2_HD_FLAG_NAME_ALLOC = 1,
/* Indicates value was dynamically allocated and must be freed */
NGHTTP2_HD_FLAG_VALUE_ALLOC = 1 << 1,
/* Indicates that the entry is in the reference set */
NGHTTP2_HD_FLAG_REFSET = 1 << 2,
/* Indicates that the entry is emitted in the current header
processing. */
NGHTTP2_HD_FLAG_EMIT = 1 << 3,
NGHTTP2_HD_FLAG_IMPLICIT_EMIT = 1 << 4,
/* Indicates that the name was gifted to the entry and no copying
necessary. */
NGHTTP2_HD_FLAG_NAME_GIFT = 1 << 5,
NGHTTP2_HD_FLAG_NAME_GIFT = 1 << 2,
/* Indicates that the value was gifted to the entry and no copying
necessary. */
NGHTTP2_HD_FLAG_VALUE_GIFT = 1 << 6
NGHTTP2_HD_FLAG_VALUE_GIFT = 1 << 3
} nghttp2_hd_flags;
typedef struct {
@@ -108,6 +95,7 @@ typedef enum {
typedef enum {
NGHTTP2_HD_STATE_OPCODE,
NGHTTP2_HD_STATE_READ_TABLE_SIZE,
NGHTTP2_HD_STATE_READ_INDEX,
NGHTTP2_HD_STATE_NEWNAME_CHECK_NAMELEN,
NGHTTP2_HD_STATE_NEWNAME_READ_NAMELEN,
@@ -116,93 +104,81 @@ typedef enum {
NGHTTP2_HD_STATE_CHECK_VALUELEN,
NGHTTP2_HD_STATE_READ_VALUELEN,
NGHTTP2_HD_STATE_READ_VALUEHUFF,
NGHTTP2_HD_STATE_READ_VALUE,
NGHTTP2_HD_STATE_READ_VALUE
} nghttp2_hd_inflate_state;
typedef struct {
/* dynamic header table */
nghttp2_hd_ringbuf hd_table;
/* Memory allocator */
nghttp2_mem *mem;
/* Abstract buffer size of hd_table as described in the spec. This
is the sum of length of name/value in hd_table +
NGHTTP2_HD_ENTRY_OVERHEAD bytes overhead per each entry. */
size_t hd_table_bufsize;
/* The header table size for decoding. If the context is initialized
as encoder, this value is advertised by remote endpoint
decoder. */
/* The effective header table size. */
size_t hd_table_bufsize_max;
/* The current effective header table size for encoding. This value
is always equal to |hd_table_bufsize| on decoder
context. |deflate_hd_table_bufsize| <= |hd_table_bufsize| must be
hold. */
size_t deflate_hd_table_bufsize;
/* The maximum effective header table for encoding. Although header
table size is bounded by |hd_table_bufsize_max|, the encoder can
use smaller buffer by not retaining the header name/values beyond
the |deflate_hd_table_bufsize_max| and not referencing those
entries. This value is always equal to |hd_table_bufsize_max| on
decoder context. */
size_t deflate_hd_table_bufsize_max;
/* The number of effective entry in |hd_table|. This value is always
equal to hd_table.len on decoder side. */
size_t deflate_hd_tablelen;
/* Role of this context; deflate or infalte */
nghttp2_hd_role role;
/* NGHTTP2_HD_SIDE_REQUEST for processing request, otherwise
response. */
nghttp2_hd_side side;
/* If inflate/deflate error occurred, this value is set to 1 and
further invocation of inflate/deflate will fail with
NGHTTP2_ERR_HEADER_COMP. */
uint8_t bad;
} nghttp2_hd_context;
typedef struct {
struct nghttp2_hd_deflater {
nghttp2_hd_context ctx;
/* Set to this nonzero to clear reference set on each deflation each
time. */
uint8_t no_refset;
} nghttp2_hd_deflater;
/* The upper limit of the header table size the deflater accepts. */
size_t deflate_hd_table_bufsize_max;
/* Minimum header table size notified in the next context update */
size_t min_hd_table_bufsize_max;
/* If nonzero, send header table size using encoding context update
in the next deflate process */
uint8_t notify_table_size_change;
};
typedef struct {
struct nghttp2_hd_inflater {
nghttp2_hd_context ctx;
/* header name buffer */
nghttp2_buffer namebuf;
/* header value buffer */
nghttp2_buffer valuebuf;
/* header buffer */
nghttp2_bufs nvbufs;
/* Stores current state of huffman decoding */
nghttp2_hd_huff_decode_context huff_decode_ctx;
/* Pointer to the nghttp2_hd_entry which is used current header
emission. This is required because in some cases the
ent_keep->ref == 0 and we have to keep track of it. */
nghttp2_hd_entry *ent_keep;
/* Pointers to the name/value pair which are used current header
emission. They are usually used to keep track of malloc'ed memory
for huffman decoding. */
uint8_t *name_keep, *value_keep;
/* Pointers to the name/value pair which is referred as indexed
name. This entry must be in header table. */
nghttp2_hd_entry *ent_name;
/* Pointer to the name/value pair buffer which is used in the
current header emission. */
uint8_t *nv_keep;
/* The number of bytes to read */
ssize_t left;
size_t left;
/* The index in indexed repr or indexed name */
size_t index;
/* The index of header table to toggle off the entry from reference
set at the end of decompression. */
size_t end_headers_index;
/* The length of new name encoded in literal. For huffman encoded
string, this is the length after it is decoded. */
size_t newnamelen;
/* The maximum header table size the inflater supports. This is the
same value transmitted in SETTINGS_HEADER_TABLE_SIZE */
size_t settings_hd_table_bufsize_max;
/* The number of next shift to decode integer */
size_t shift;
nghttp2_hd_opcode opcode;
nghttp2_hd_inflate_state state;
/* nonzero if string is huffman encoded */
uint8_t huffman_encoded;
/* nonzero if deflater requires that current entry is indexed */
uint8_t index_required;
} nghttp2_hd_inflater;
/* nonzero if deflater requires that current entry must not be
indexed */
uint8_t no_index;
};
/*
* Initializes the |ent| members. If NGHTTP2_HD_FLAG_NAME_ALLOC bit
* set in the |flags|, the content pointed by the |name| with length
* |namelen| is copied. Likewise, if NGHTTP2_HD_FLAG_VALUE_ALLOC bit
* set in the |flags|, the content pointed by the |value| with length
* |valuelen| is copied.
* |valuelen| is copied. The |name_hash| and |value_hash| are hash
* value for |name| and |value| respectively. The hash function is
* defined in nghttp2_hd.c.
*
* This function returns 0 if it succeeds, or one of the following
* negative error codes:
@@ -210,11 +186,12 @@ typedef struct {
* NGHTTP2_ERR_NOMEM
* Out of memory.
*/
int nghttp2_hd_entry_init(nghttp2_hd_entry *ent, uint8_t flags,
uint8_t *name, uint16_t namelen,
uint8_t *value, uint16_t valuelen);
int nghttp2_hd_entry_init(nghttp2_hd_entry *ent, uint8_t flags, uint8_t *name,
size_t namelen, uint8_t *value, size_t valuelen,
uint32_t name_hash, uint32_t value_hash,
nghttp2_mem *mem);
void nghttp2_hd_entry_free(nghttp2_hd_entry *ent);
void nghttp2_hd_entry_free(nghttp2_hd_entry *ent, nghttp2_mem *mem);
/*
* Initializes |deflater| for deflating name/values pairs.
@@ -230,8 +207,7 @@ void nghttp2_hd_entry_free(nghttp2_hd_entry *ent);
* NGHTTP2_ERR_NOMEM
* Out of memory.
*/
int nghttp2_hd_deflate_init(nghttp2_hd_deflater *deflater,
nghttp2_hd_side side);
int nghttp2_hd_deflate_init(nghttp2_hd_deflater *deflater, nghttp2_mem *mem);
/*
* Initializes |deflater| for deflating name/values pairs.
@@ -247,20 +223,8 @@ int nghttp2_hd_deflate_init(nghttp2_hd_deflater *deflater,
* Out of memory.
*/
int nghttp2_hd_deflate_init2(nghttp2_hd_deflater *deflater,
nghttp2_hd_side side,
size_t deflate_hd_table_bufsize_max);
/*
* Initializes |inflater| for inflating name/values pairs.
*
* This function returns 0 if it succeeds, or one of the following
* negative error codes:
*
* NGHTTP2_ERR_NOMEM
* Out of memory.
*/
int nghttp2_hd_inflate_init(nghttp2_hd_inflater *inflater,
nghttp2_hd_side side);
size_t deflate_hd_table_bufsize_max,
nghttp2_mem *mem);
/*
* Deallocates any resources allocated for |deflater|.
@@ -268,171 +232,100 @@ int nghttp2_hd_inflate_init(nghttp2_hd_inflater *inflater,
void nghttp2_hd_deflate_free(nghttp2_hd_deflater *deflater);
/*
* Deallocates any resources allocated for |inflater|.
*/
void nghttp2_hd_inflate_free(nghttp2_hd_inflater *inflater);
/*
* Sets the availability of reference set in the |deflater|. If
* |no_refset| is nonzero, the deflater will first emit index=0 in the
* each invocation of nghttp2_hd_deflate_hd() to clear up reference
* set. By default, the deflater uses reference set.
*/
void nghttp2_hd_deflate_set_no_refset(nghttp2_hd_deflater *deflater,
uint8_t no_refset);
/*
* Changes header table size in |context|. This may trigger eviction
* in the dynamic table.
* Deflates the |nva|, which has the |nvlen| name/value pairs, into
* the |bufs|.
*
* This function can be used for deflater and inflater.
* This function expands |bufs| as necessary to store the result. If
* buffers is full and the process still requires more space, this
* funtion fails and returns NGHTTP2_ERR_HEADER_COMP.
*
* After this function returns, it is safe to delete the |nva|.
*
* This function returns 0 if it succeeds, or one of the following
* negative error codes:
*
* NGHTTP2_ERR_NOMEM
* Out of memory.
*/
int nghttp2_hd_change_table_size(nghttp2_hd_context *context,
size_t hd_table_bufsize_max);
/*
* Deflates the |nva|, which has the |nvlen| name/value pairs, into
* the buffer pointed by the |*buf_ptr| with the length |*buflen_ptr|.
* The output starts after |nv_offset| bytes from |*buf_ptr|.
*
* This function expands |*buf_ptr| as necessary to store the
* result. When expansion occurred, memory previously pointed by
* |*buf_ptr| may change. |*buf_ptr| and |*buflen_ptr| are updated
* accordingly.
*
* This function copies necessary data into |*buf_ptr|. After this
* function returns, it is safe to delete the |nva|.
*
* TODO: The rest of the code call nghttp2_hd_end_headers() after this
* call, but it is just a regacy of the first implementation. Now it
* is not required to be called as of now.
*
* This function returns the number of bytes outputted if it succeeds,
* or one of the following negative error codes:
*
* NGHTTP2_ERR_NOMEM
* Out of memory.
* NGHTTP2_ERR_HEADER_COMP
* Deflation process has failed.
* NGHTTP2_ERR_BUFFER_ERROR
* Out of buffer space.
*/
ssize_t nghttp2_hd_deflate_hd(nghttp2_hd_deflater *deflater,
uint8_t **buf_ptr, size_t *buflen_ptr,
size_t nv_offset,
nghttp2_nv *nva, size_t nvlen);
typedef enum {
NGHTTP2_HD_INFLATE_NONE = 0,
NGHTTP2_HD_INFLATE_FINAL = 1,
NGHTTP2_HD_INFLATE_EMIT = (1 << 1)
} nghttp2_hd_inflate_flag;
int nghttp2_hd_deflate_hd_bufs(nghttp2_hd_deflater *deflater,
nghttp2_bufs *bufs, const nghttp2_nv *nva,
size_t nvlen);
/*
* Inflates name/value block stored in |in| with length |inlen|. This
* function performs decompression. For each successful emission of
* header name/value pair, NGHTTP2_HD_INFLATE_EMIT is set in
* |*inflate_flags| and name/value pair is assigned to the |nv_out|
* and the function returns. The caller must not free the members of
* |nv_out|.
* Initializes |inflater| for inflating name/values pairs.
*
* The |nv_out| may include pointers to the memory region in the
* |in|. The caller must retain the |in| while the |nv_out| is used.
* This function returns 0 if it succeeds, or one of the following
* negative error codes:
*
* The application should call this function repeatedly until the
* |(*inflate_flags) & NGHTTP2_HD_INFLATE_FINAL| is nonzero and return
* value is non-negative. This means the all input values are
* processed successfully. Then the application must call
* `nghttp2_hd_inflate_end_headers()` to prepare for the next header
* block input.
*
* The caller can feed complete compressed header block. It also can
* feed it in several chunks. The caller must set |in_final| to
* nonzero if the given input is the last block of the compressed
* header.
*
* This function returns the number of bytes processed if it succeeds,
* or one of the following negative error codes:
*
* NGHTTP2_ERR_NOMEM
* :enum:`NGHTTP2_ERR_NOMEM`
* Out of memory.
* NGHTTP2_ERR_HEADER_COMP
* Inflation process has failed.
*/
ssize_t nghttp2_hd_inflate_hd(nghttp2_hd_inflater *inflater,
nghttp2_nv *nv_out, int *inflate_flags,
uint8_t *in, size_t inlen, int in_final);
int nghttp2_hd_inflate_init(nghttp2_hd_inflater *inflater, nghttp2_mem *mem);
/*
* Signals the end of decompression for one header block.
*
* This function returns 0 if it succeeds. Currently this function
* always succeeds.
* Deallocates any resources allocated for |inflater|.
*/
int nghttp2_hd_inflate_end_headers(nghttp2_hd_inflater *inflater);
void nghttp2_hd_inflate_free(nghttp2_hd_inflater *inflater);
/* For unittesting purpose */
int nghttp2_hd_emit_indname_block(uint8_t **buf_ptr, size_t *buflen_ptr,
size_t *offset_ptr, size_t index,
const uint8_t *value, size_t valuelen,
int inc_indexing,
nghttp2_hd_side side);
int nghttp2_hd_emit_indname_block(nghttp2_bufs *bufs, size_t index,
nghttp2_nv *nv, int inc_indexing);
/* For unittesting purpose */
int nghttp2_hd_emit_newname_block(uint8_t **buf_ptr, size_t *buflen_ptr,
size_t *offset_ptr, nghttp2_nv *nv,
int inc_indexing,
nghttp2_hd_side side);
int nghttp2_hd_emit_newname_block(nghttp2_bufs *bufs, nghttp2_nv *nv,
int inc_indexing);
/* For unittesting purpose */
nghttp2_hd_entry* nghttp2_hd_table_get(nghttp2_hd_context *context,
int nghttp2_hd_emit_table_size(nghttp2_bufs *bufs, size_t table_size);
/* For unittesting purpose */
nghttp2_hd_entry *nghttp2_hd_table_get(nghttp2_hd_context *context,
size_t index);
/* For unittesting purpose */
ssize_t nghttp2_hd_decode_length(uint32_t *res, size_t *shift_ptr, int *final,
uint32_t initial, size_t shift, uint8_t *in,
uint8_t *last, size_t prefix);
/* Huffman encoding/decoding functions */
/*
* Counts the required bytes to encode |src| with length |len|. If
* |side| is NGHTTP2_HD_SIDE_REQUEST, the request huffman code table
* is used. Otherwise, the response code table is used.
* Counts the required bytes to encode |src| with length |len|.
*
* This function returns the number of required bytes to encode given
* data, including padding of prefix of terminal symbol code. This
* function always succeeds.
*/
size_t nghttp2_hd_huff_encode_count(const uint8_t *src, size_t len,
nghttp2_hd_side side);
size_t nghttp2_hd_huff_encode_count(const uint8_t *src, size_t len);
/*
* Encodes the given data |src| with length |srclen| to the given
* memory location pointed by |dest|, allocated at lest |destlen|
* bytes. The caller is responsible to specify |destlen| at least the
* length that nghttp2_hd_huff_encode_count() returns. If |side| is
* NGHTTP2_HD_SIDE_REQUEST, the request huffman code table is
* used. Otherwise, the response code table is used.
* Encodes the given data |src| with length |srclen| to the |bufs|.
* This function expands extra buffers in |bufs| if necessary.
*
* This function returns the number of written bytes, including
* padding of prefix of terminal symbol code. This return value is
* exactly the same with the return value of
* nghttp2_hd_huff_encode_count() if it is given with the same |src|,
* |srclen|, and |side|. This function always succeeds.
* This function returns 0 if it succeeds, or one of the following
* negative error codes:
*
* NGHTTP2_ERR_NOMEM
* Out of memory.
* NGHTTP2_ERR_BUFFER_ERROR
* Out of buffer space.
*/
ssize_t nghttp2_hd_huff_encode(uint8_t *dest, size_t destlen,
const uint8_t *src, size_t srclen,
nghttp2_hd_side side);
int nghttp2_hd_huff_encode(nghttp2_bufs *bufs, const uint8_t *src,
size_t srclen);
void nghttp2_hd_huff_decode_context_init(nghttp2_hd_huff_decode_context *ctx,
nghttp2_hd_side side);
void nghttp2_hd_huff_decode_context_init(nghttp2_hd_huff_decode_context *ctx);
/*
* Decodes the given data |src| with length |srclen|. The |ctx| must
* be initialized by nghttp2_hd_huff_decode_context_init(). The result
* will be added to |dest|. This function may expand |dest| as
* needed. The caller is responsible to release the memory of |dest|
* by calling nghttp2_buffer_free().
* by calling nghttp2_bufs_free() or export its content using
* nghttp2_bufs_remove().
*
* The caller must set the |final| to nonzero if the given input is
* the final block.
@@ -450,7 +343,7 @@ void nghttp2_hd_huff_decode_context_init(nghttp2_hd_huff_decode_context *ctx,
* Decoding process has failed.
*/
ssize_t nghttp2_hd_huff_decode(nghttp2_hd_huff_decode_context *ctx,
nghttp2_buffer *dest,
const uint8_t *src, size_t srclen, int final);
nghttp2_bufs *bufs, const uint8_t *src,
size_t srclen, int final);
#endif /* NGHTTP2_HD_COMP_H */
#endif /* NGHTTP2_HD_H */

View File

@@ -1,5 +1,5 @@
/*
* nghttp2 - HTTP/2.0 C Library
* nghttp2 - HTTP/2 C Library
*
* Copyright (c) 2013 Tatsuhiro Tsujikawa
*
@@ -30,11 +30,8 @@
#include "nghttp2_hd.h"
extern const nghttp2_huff_sym req_huff_sym_table[];
extern const nghttp2_huff_decode req_huff_decode_table[][16];
extern const nghttp2_huff_sym res_huff_sym_table[];
extern const nghttp2_huff_decode res_huff_decode_table[][16];
extern const nghttp2_huff_sym huff_sym_table[];
extern const nghttp2_huff_decode huff_decode_table[][16];
/*
* Encodes huffman code |sym| into |*dest_ptr|, whose least |rembits|
@@ -43,117 +40,173 @@ extern const nghttp2_huff_decode res_huff_decode_table[][16];
* and points where next output should be placed. The number of
* unfilled bits in the pointed location is returned.
*/
static size_t huff_encode_sym(uint8_t **dest_ptr, size_t rembits,
const nghttp2_huff_sym *sym)
{
static ssize_t huff_encode_sym(nghttp2_bufs *bufs, size_t *avail_ptr,
size_t rembits, const nghttp2_huff_sym *sym) {
int rv;
size_t nbits = sym->nbits;
for(;;) {
if(rembits > nbits) {
**dest_ptr |= sym->code << (rembits - nbits);
rembits -= nbits;
break;
uint32_t code = sym->code;
/* We assume that sym->nbits <= 32 */
if (rembits > nbits) {
nghttp2_bufs_fast_orb_hold(bufs, code << (rembits - nbits));
return (ssize_t)(rembits - nbits);
}
**dest_ptr |= sym->code >> (nbits - rembits);
++*dest_ptr;
if (rembits == nbits) {
nghttp2_bufs_fast_orb(bufs, code);
--*avail_ptr;
return 8;
}
nghttp2_bufs_fast_orb(bufs, code >> (nbits - rembits));
--*avail_ptr;
nbits -= rembits;
rembits = 8;
if(nbits == 0) {
break;
if (nbits & 0x7) {
/* align code to MSB byte boundary */
code <<= 8 - (nbits & 0x7);
}
**dest_ptr = 0;
/* we lose at most 3 bytes, but it is not critical in practice */
if (*avail_ptr < (nbits + 7) / 8) {
rv = nghttp2_bufs_advance(bufs);
if (rv != 0) {
return rv;
}
return rembits;
*avail_ptr = nghttp2_bufs_cur_avail(bufs);
/* we assume that we at least 3 buffer space available */
assert(*avail_ptr >= 3);
}
/* fast path, since most code is less than 8 */
if (nbits < 8) {
nghttp2_bufs_fast_addb_hold(bufs, code);
*avail_ptr = nghttp2_bufs_cur_avail(bufs);
return (ssize_t)(8 - nbits);
}
/* handle longer code path */
if (nbits > 24) {
nghttp2_bufs_fast_addb(bufs, code >> 24);
nbits -= 8;
}
if (nbits > 16) {
nghttp2_bufs_fast_addb(bufs, code >> 16);
nbits -= 8;
}
if (nbits > 8) {
nghttp2_bufs_fast_addb(bufs, code >> 8);
nbits -= 8;
}
if (nbits == 8) {
nghttp2_bufs_fast_addb(bufs, code);
*avail_ptr = nghttp2_bufs_cur_avail(bufs);
return 8;
}
nghttp2_bufs_fast_addb_hold(bufs, code);
*avail_ptr = nghttp2_bufs_cur_avail(bufs);
return (ssize_t)(8 - nbits);
}
size_t nghttp2_hd_huff_encode_count(const uint8_t *src, size_t len,
nghttp2_hd_side side)
{
size_t nghttp2_hd_huff_encode_count(const uint8_t *src, size_t len) {
size_t i;
size_t nbits = 0;
const nghttp2_huff_sym *huff_sym_table;
if(side == NGHTTP2_HD_SIDE_REQUEST) {
huff_sym_table = req_huff_sym_table;
} else {
huff_sym_table = res_huff_sym_table;
}
for(i = 0; i < len; ++i) {
for (i = 0; i < len; ++i) {
nbits += huff_sym_table[src[i]].nbits;
}
/* pad the prefix of EOS (256) */
return (nbits + 7) / 8;
}
ssize_t nghttp2_hd_huff_encode(uint8_t *dest, size_t destlen,
const uint8_t *src, size_t srclen,
nghttp2_hd_side side)
{
int rembits = 8;
uint8_t *dest_first = dest;
int nghttp2_hd_huff_encode(nghttp2_bufs *bufs, const uint8_t *src,
size_t srclen) {
int rv;
ssize_t rembits = 8;
size_t i;
const nghttp2_huff_sym *huff_sym_table;
size_t avail;
if(side == NGHTTP2_HD_SIDE_REQUEST) {
huff_sym_table = req_huff_sym_table;
} else {
huff_sym_table = res_huff_sym_table;
}
for(i = 0; i < srclen; ++i) {
avail = nghttp2_bufs_cur_avail(bufs);
for (i = 0; i < srclen; ++i) {
const nghttp2_huff_sym *sym = &huff_sym_table[src[i]];
if(rembits == 8) {
*dest = 0;
if (rembits == 8) {
if (avail) {
nghttp2_bufs_fast_addb_hold(bufs, 0);
} else {
rv = nghttp2_bufs_addb_hold(bufs, 0);
if (rv != 0) {
return rv;
}
avail = nghttp2_bufs_cur_avail(bufs);
}
}
rembits = huff_encode_sym(bufs, &avail, rembits, sym);
if (rembits < 0) {
return (int)rembits;
}
rembits = huff_encode_sym(&dest, rembits, sym);
}
/* 256 is special terminal symbol, pad with its prefix */
if(rembits < 8) {
if (rembits < 8) {
/* if rembits < 8, we should have at least 1 buffer space
available */
const nghttp2_huff_sym *sym = &huff_sym_table[256];
*dest |= sym->code >> (sym->nbits - rembits);
++dest;
assert(avail);
/* Caution we no longer adjust avail here */
nghttp2_bufs_fast_orb(bufs, sym->code >> (sym->nbits - rembits));
}
return dest - dest_first;
return 0;
}
void nghttp2_hd_huff_decode_context_init(nghttp2_hd_huff_decode_context *ctx,
nghttp2_hd_side side)
{
if(side == NGHTTP2_HD_SIDE_REQUEST) {
ctx->huff_decode_table = req_huff_decode_table;
} else {
ctx->huff_decode_table = res_huff_decode_table;
}
void nghttp2_hd_huff_decode_context_init(nghttp2_hd_huff_decode_context *ctx) {
ctx->state = 0;
ctx->accept = 1;
}
ssize_t nghttp2_hd_huff_decode(nghttp2_hd_huff_decode_context *ctx,
nghttp2_buffer *dest,
const uint8_t *src, size_t srclen, int final)
{
nghttp2_bufs *bufs, const uint8_t *src,
size_t srclen, int final) {
size_t i, j;
int rv;
size_t avail;
avail = nghttp2_bufs_cur_avail(bufs);
/* We use the decoding algorithm described in
http://graphics.ics.uci.edu/pub/Prefix.pdf */
for(i = 0; i < srclen; ++i) {
for (i = 0; i < srclen; ++i) {
uint8_t in = src[i] >> 4;
for(j = 0; j < 2; ++j) {
const nghttp2_huff_decode *t = &ctx->huff_decode_table[ctx->state][in];
if(t->state == -1) {
for (j = 0; j < 2; ++j) {
const nghttp2_huff_decode *t;
t = &huff_decode_table[ctx->state][in];
if (t->flags & NGHTTP2_HUFF_FAIL) {
return NGHTTP2_ERR_HEADER_COMP;
}
if(t->flags & NGHTTP2_HUFF_SYM) {
rv = nghttp2_buffer_add_byte(dest, t->sym);
if(rv != 0) {
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(final && !ctx->accept) {
if (final && !ctx->accept) {
return NGHTTP2_ERR_HEADER_COMP;
}
return i;
return (ssize_t)i;
}

View File

@@ -1,5 +1,5 @@
/*
* nghttp2 - HTTP/2.0 C Library
* nghttp2 - HTTP/2 C Library
*
* Copyright (c) 2013 Tatsuhiro Tsujikawa
*
@@ -26,7 +26,7 @@
#define NGHTTP2_HD_HUFFMAN_H
#ifdef HAVE_CONFIG_H
# include <config.h>
#include <config.h>
#endif /* HAVE_CONFIG_H */
#include <nghttp2/nghttp2.h>
@@ -36,13 +36,17 @@ typedef enum {
sequence. */
NGHTTP2_HUFF_ACCEPTED = 1,
/* This state emits symbol */
NGHTTP2_HUFF_SYM = (1 << 1)
NGHTTP2_HUFF_SYM = (1 << 1),
/* If state machine reaches this state, decoding fails. */
NGHTTP2_HUFF_FAIL = (1 << 2)
} nghttp2_huff_decode_flag;
typedef struct {
/* huffman decoding state, which is actually the node ID of internal
huffman tree */
int16_t state;
huffman tree. We have 257 leaf nodes, but they are identical to
root node other than emitting a symbol, so we have 256 internal
nodes [1..255], inclusive. */
uint8_t state;
/* bitwise OR of zero or more of the nghttp2_huff_decode_flag */
uint8_t flags;
/* symbol if NGHTTP2_HUFF_SYM flag set */
@@ -52,7 +56,6 @@ typedef struct {
typedef nghttp2_huff_decode huff_decode_table_type[16];
typedef struct {
const huff_decode_table_type *huff_decode_table;
/* Current huffman decoding state. We stripped leaf nodes, so the
value range is [0..255], inclusive. */
uint8_t state;

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,5 @@
/*
* nghttp2 - HTTP/2.0 C Library
* nghttp2 - HTTP/2 C Library
*
* Copyright (c) 2012 Tatsuhiro Tsujikawa
*
@@ -29,109 +29,189 @@
#include "nghttp2_net.h"
void nghttp2_put_uint16be(uint8_t *buf, uint16_t n)
{
void nghttp2_put_uint16be(uint8_t *buf, uint16_t n) {
uint16_t x = htons(n);
memcpy(buf, &x, sizeof(uint16_t));
}
void nghttp2_put_uint32be(uint8_t *buf, uint32_t n)
{
void nghttp2_put_uint32be(uint8_t *buf, uint32_t n) {
uint32_t x = htonl(n);
memcpy(buf, &x, sizeof(uint32_t));
}
uint16_t nghttp2_get_uint16(const uint8_t *data)
{
uint16_t nghttp2_get_uint16(const uint8_t *data) {
uint16_t n;
memcpy(&n, data, sizeof(uint16_t));
return ntohs(n);
}
uint32_t nghttp2_get_uint32(const uint8_t *data)
{
uint32_t nghttp2_get_uint32(const uint8_t *data) {
uint32_t n;
memcpy(&n, data, sizeof(uint32_t));
return ntohl(n);
}
int nghttp2_reserve_buffer(uint8_t **buf_ptr, size_t *buflen_ptr,
size_t min_length)
{
if(min_length > *buflen_ptr) {
uint8_t *temp;
min_length = (min_length+4095)/4096*4096;
temp = realloc(*buf_ptr, min_length);
if(temp == NULL) {
return NGHTTP2_ERR_NOMEM;
} else {
*buf_ptr = temp;
*buflen_ptr = min_length;
}
}
return 0;
}
void *nghttp2_memdup(const void *src, size_t n, nghttp2_mem *mem) {
void *dest;
void* nghttp2_memdup(const void* src, size_t n)
{
void* dest = malloc(n);
if(dest == NULL) {
if (n == 0) {
return NULL;
}
dest = nghttp2_mem_malloc(mem, n);
if (dest == NULL) {
return NULL;
}
memcpy(dest, src, n);
return dest;
}
void nghttp2_downcase(uint8_t *s, size_t len)
{
/* Generated by gendowncasetbl.py */
static const int DOWNCASE_TBL[] = {
0 /* NUL */, 1 /* SOH */, 2 /* STX */, 3 /* ETX */,
4 /* EOT */, 5 /* ENQ */, 6 /* ACK */, 7 /* BEL */,
8 /* BS */, 9 /* HT */, 10 /* LF */, 11 /* VT */,
12 /* FF */, 13 /* CR */, 14 /* SO */, 15 /* SI */,
16 /* DLE */, 17 /* DC1 */, 18 /* DC2 */, 19 /* DC3 */,
20 /* DC4 */, 21 /* NAK */, 22 /* SYN */, 23 /* ETB */,
24 /* CAN */, 25 /* EM */, 26 /* SUB */, 27 /* ESC */,
28 /* FS */, 29 /* GS */, 30 /* RS */, 31 /* US */,
32 /* SPC */, 33 /* ! */, 34 /* " */, 35 /* # */,
36 /* $ */, 37 /* % */, 38 /* & */, 39 /* ' */,
40 /* ( */, 41 /* ) */, 42 /* * */, 43 /* + */,
44 /* , */, 45 /* - */, 46 /* . */, 47 /* / */,
48 /* 0 */, 49 /* 1 */, 50 /* 2 */, 51 /* 3 */,
52 /* 4 */, 53 /* 5 */, 54 /* 6 */, 55 /* 7 */,
56 /* 8 */, 57 /* 9 */, 58 /* : */, 59 /* ; */,
60 /* < */, 61 /* = */, 62 /* > */, 63 /* ? */,
64 /* @ */, 97 /* A */, 98 /* B */, 99 /* C */,
100 /* D */, 101 /* E */, 102 /* F */, 103 /* G */,
104 /* H */, 105 /* I */, 106 /* J */, 107 /* K */,
108 /* L */, 109 /* M */, 110 /* N */, 111 /* O */,
112 /* P */, 113 /* Q */, 114 /* R */, 115 /* S */,
116 /* T */, 117 /* U */, 118 /* V */, 119 /* W */,
120 /* X */, 121 /* Y */, 122 /* Z */, 91 /* [ */,
92 /* \ */, 93 /* ] */, 94 /* ^ */, 95 /* _ */,
96 /* ` */, 97 /* a */, 98 /* b */, 99 /* c */,
100 /* d */, 101 /* e */, 102 /* f */, 103 /* g */,
104 /* h */, 105 /* i */, 106 /* j */, 107 /* k */,
108 /* l */, 109 /* m */, 110 /* n */, 111 /* o */,
112 /* p */, 113 /* q */, 114 /* r */, 115 /* s */,
116 /* t */, 117 /* u */, 118 /* v */, 119 /* w */,
120 /* x */, 121 /* y */, 122 /* z */, 123 /* { */,
124 /* | */, 125 /* } */, 126 /* ~ */, 127 /* DEL */,
128 /* 0x80 */, 129 /* 0x81 */, 130 /* 0x82 */, 131 /* 0x83 */,
132 /* 0x84 */, 133 /* 0x85 */, 134 /* 0x86 */, 135 /* 0x87 */,
136 /* 0x88 */, 137 /* 0x89 */, 138 /* 0x8a */, 139 /* 0x8b */,
140 /* 0x8c */, 141 /* 0x8d */, 142 /* 0x8e */, 143 /* 0x8f */,
144 /* 0x90 */, 145 /* 0x91 */, 146 /* 0x92 */, 147 /* 0x93 */,
148 /* 0x94 */, 149 /* 0x95 */, 150 /* 0x96 */, 151 /* 0x97 */,
152 /* 0x98 */, 153 /* 0x99 */, 154 /* 0x9a */, 155 /* 0x9b */,
156 /* 0x9c */, 157 /* 0x9d */, 158 /* 0x9e */, 159 /* 0x9f */,
160 /* 0xa0 */, 161 /* 0xa1 */, 162 /* 0xa2 */, 163 /* 0xa3 */,
164 /* 0xa4 */, 165 /* 0xa5 */, 166 /* 0xa6 */, 167 /* 0xa7 */,
168 /* 0xa8 */, 169 /* 0xa9 */, 170 /* 0xaa */, 171 /* 0xab */,
172 /* 0xac */, 173 /* 0xad */, 174 /* 0xae */, 175 /* 0xaf */,
176 /* 0xb0 */, 177 /* 0xb1 */, 178 /* 0xb2 */, 179 /* 0xb3 */,
180 /* 0xb4 */, 181 /* 0xb5 */, 182 /* 0xb6 */, 183 /* 0xb7 */,
184 /* 0xb8 */, 185 /* 0xb9 */, 186 /* 0xba */, 187 /* 0xbb */,
188 /* 0xbc */, 189 /* 0xbd */, 190 /* 0xbe */, 191 /* 0xbf */,
192 /* 0xc0 */, 193 /* 0xc1 */, 194 /* 0xc2 */, 195 /* 0xc3 */,
196 /* 0xc4 */, 197 /* 0xc5 */, 198 /* 0xc6 */, 199 /* 0xc7 */,
200 /* 0xc8 */, 201 /* 0xc9 */, 202 /* 0xca */, 203 /* 0xcb */,
204 /* 0xcc */, 205 /* 0xcd */, 206 /* 0xce */, 207 /* 0xcf */,
208 /* 0xd0 */, 209 /* 0xd1 */, 210 /* 0xd2 */, 211 /* 0xd3 */,
212 /* 0xd4 */, 213 /* 0xd5 */, 214 /* 0xd6 */, 215 /* 0xd7 */,
216 /* 0xd8 */, 217 /* 0xd9 */, 218 /* 0xda */, 219 /* 0xdb */,
220 /* 0xdc */, 221 /* 0xdd */, 222 /* 0xde */, 223 /* 0xdf */,
224 /* 0xe0 */, 225 /* 0xe1 */, 226 /* 0xe2 */, 227 /* 0xe3 */,
228 /* 0xe4 */, 229 /* 0xe5 */, 230 /* 0xe6 */, 231 /* 0xe7 */,
232 /* 0xe8 */, 233 /* 0xe9 */, 234 /* 0xea */, 235 /* 0xeb */,
236 /* 0xec */, 237 /* 0xed */, 238 /* 0xee */, 239 /* 0xef */,
240 /* 0xf0 */, 241 /* 0xf1 */, 242 /* 0xf2 */, 243 /* 0xf3 */,
244 /* 0xf4 */, 245 /* 0xf5 */, 246 /* 0xf6 */, 247 /* 0xf7 */,
248 /* 0xf8 */, 249 /* 0xf9 */, 250 /* 0xfa */, 251 /* 0xfb */,
252 /* 0xfc */, 253 /* 0xfd */, 254 /* 0xfe */, 255 /* 0xff */,
};
void nghttp2_downcase(uint8_t *s, size_t len) {
size_t i;
for(i = 0; i < len; ++i) {
if('A' <= s[i] && s[i] <= 'Z') {
s[i] += 'a'-'A';
}
for (i = 0; i < len; ++i) {
s[i] = DOWNCASE_TBL[s[i]];
}
}
/*
* local_window_size
* ^ *
* | * recv_window_size
* | * * ^
* | * * |
* 0+++++++++
* | * * \
* | * * | This rage is hidden in flow control. But it must be
* v * * / kept in order to restore it when window size is enlarged.
* recv_reduction
* (+ for negative direction)
*
* recv_window_size could be negative if we decrease
* local_window_size more than recv_window_size:
*
* local_window_size
* ^ *
* | *
* | *
* 0++++++++
* | * ^ recv_window_size (negative)
* | * |
* v * *
* recv_reduction
*/
int nghttp2_adjust_local_window_size(int32_t *local_window_size_ptr,
int32_t *recv_window_size_ptr,
int32_t *recv_reduction_ptr,
int32_t *delta_ptr)
{
if(*delta_ptr > 0) {
int32_t *delta_ptr) {
if (*delta_ptr > 0) {
int32_t recv_reduction_delta;
int32_t delta;
int32_t new_recv_window_size =
nghttp2_max(0, *recv_window_size_ptr) - *delta_ptr;
if(new_recv_window_size < 0) {
if (new_recv_window_size >= 0) {
*recv_window_size_ptr = new_recv_window_size;
return 0;
}
delta = -new_recv_window_size;
/* The delta size is strictly more than received bytes. Increase
local_window_size by that difference. */
int32_t recv_reduction_diff;
if(*local_window_size_ptr >
NGHTTP2_MAX_WINDOW_SIZE + new_recv_window_size) {
local_window_size by that difference |delta|. */
if (*local_window_size_ptr > NGHTTP2_MAX_WINDOW_SIZE - delta) {
return NGHTTP2_ERR_FLOW_CONTROL;
}
*local_window_size_ptr -= new_recv_window_size;
*local_window_size_ptr += delta;
/* If there is recv_reduction due to earlier window_size
reduction, we have to adjust it too. */
recv_reduction_diff = nghttp2_min(*recv_reduction_ptr,
-new_recv_window_size);
*recv_reduction_ptr -= recv_reduction_diff;
if(*recv_window_size_ptr < 0) {
*recv_window_size_ptr += recv_reduction_diff;
recv_reduction_delta = nghttp2_min(*recv_reduction_ptr, delta);
*recv_reduction_ptr -= recv_reduction_delta;
if (*recv_window_size_ptr < 0) {
*recv_window_size_ptr += recv_reduction_delta;
} else {
/* If *recv_window_size_ptr > 0, then those bytes are
considered to be backed to the remote peer (by
WINDOW_UPDATE with the adjusted *delta_ptr), so it is
effectively 0 now. */
*recv_window_size_ptr = recv_reduction_diff;
/* If *recv_window_size_ptr > 0, then those bytes are going to
be returned to the remote peer (by WINDOW_UPDATE with the
adjusted *delta_ptr), so it is effectively 0 now. We set to
*recv_reduction_delta, because caller does not take into
account it in *delta_ptr. */
*recv_window_size_ptr = recv_reduction_delta;
}
/* recv_reduction_diff must be paied from *delta_ptr, since it
/* recv_reduction_delta must be paied from *delta_ptr, since it
was added in window size reduction (see below). */
*delta_ptr -= recv_reduction_diff;
} else {
*recv_window_size_ptr = new_recv_window_size;
}
*delta_ptr -= recv_reduction_delta;
return 0;
} else {
if(*local_window_size_ptr + *delta_ptr < 0 ||
}
if (*local_window_size_ptr + *delta_ptr < 0 ||
*recv_window_size_ptr < INT32_MIN - *delta_ptr ||
*recv_reduction_ptr > INT32_MAX + *delta_ptr) {
return NGHTTP2_ERR_FLOW_CONTROL;
@@ -144,23 +224,23 @@ int nghttp2_adjust_local_window_size(int32_t *local_window_size_ptr,
*recv_window_size_ptr += *delta_ptr;
*recv_reduction_ptr -= *delta_ptr;
*delta_ptr = 0;
}
return 0;
}
int nghttp2_should_send_window_update(int32_t local_window_size,
int32_t recv_window_size)
{
int32_t recv_window_size) {
return recv_window_size >= local_window_size / 2;
}
const char* nghttp2_strerror(int error_code)
{
switch(error_code) {
const char *nghttp2_strerror(int error_code) {
switch (error_code) {
case 0:
return "Success";
case NGHTTP2_ERR_INVALID_ARGUMENT:
return "Invalid argument";
case NGHTTP2_ERR_BUFFER_ERROR:
return "Out of buffer space";
case NGHTTP2_ERR_UNSUPPORTED_VERSION:
return "Unsupported SPDY version";
case NGHTTP2_ERR_WOULDBLOCK:
@@ -195,190 +275,179 @@ const char* nghttp2_strerror(int error_code)
return "Invalid header block";
case NGHTTP2_ERR_INVALID_STATE:
return "Invalid state";
case NGHTTP2_ERR_GZIP:
return "Gzip error";
case NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE:
return "The user callback function failed due to the temporal error";
case NGHTTP2_ERR_FRAME_SIZE_ERROR:
return "The length of the frame is invalid";
case NGHTTP2_ERR_HEADER_COMP:
return "Header compression/decompression error";
case NGHTTP2_ERR_FLOW_CONTROL:
return "Flow control error";
case NGHTTP2_ERR_INSUFF_BUFSIZE:
return "Insufficient buffer size given to function";
case NGHTTP2_ERR_PAUSE:
return "Callback was paused by the application";
case NGHTTP2_ERR_TOO_MANY_INFLIGHT_SETTINGS:
return "Too many inflight SETTINGS";
case NGHTTP2_ERR_PUSH_DISABLED:
return "Server push is disabled by peer";
case NGHTTP2_ERR_DATA_EXIST:
return "DATA frame already exists";
case NGHTTP2_ERR_NOMEM:
return "Out of memory";
case NGHTTP2_ERR_CALLBACK_FAILURE:
return "The user callback function failed";
case NGHTTP2_ERR_BAD_PREFACE:
return "Received bad connection preface";
default:
return "Unknown error code";
}
}
void nghttp2_free(void *ptr)
{
free(ptr);
}
/* Generated by gennmchartbl.py */
static int VALID_HD_NAME_CHARS[] = {
0 /* NUL */, 0 /* SOH */, 0 /* STX */, 0 /* ETX */,
0 /* EOT */, 0 /* ENQ */, 0 /* ACK */, 0 /* BEL */,
0 /* BS */, 0 /* HT */, 0 /* LF */, 0 /* VT */,
0 /* FF */, 0 /* CR */, 0 /* SO */, 0 /* SI */,
0 /* DLE */, 0 /* DC1 */, 0 /* DC2 */, 0 /* DC3 */,
0 /* DC4 */, 0 /* NAK */, 0 /* SYN */, 0 /* ETB */,
0 /* CAN */, 0 /* EM */, 0 /* SUB */, 0 /* ESC */,
0 /* FS */, 0 /* GS */, 0 /* RS */, 0 /* US */,
0 /* SPC */, 1 /* ! */, 0 /* " */, 1 /* # */,
1 /* $ */, 1 /* % */, 1 /* & */, 1 /* ' */,
0 /* ( */, 0 /* ) */, 1 /* * */, 1 /* + */,
0 /* , */, 1 /* - */, 1 /* . */, 0 /* / */,
1 /* 0 */, 1 /* 1 */, 1 /* 2 */, 1 /* 3 */,
1 /* 4 */, 1 /* 5 */, 1 /* 6 */, 1 /* 7 */,
1 /* 8 */, 1 /* 9 */, 0 /* : */, 0 /* ; */,
0 /* < */, 0 /* = */, 0 /* > */, 0 /* ? */,
0 /* @ */, 0 /* A */, 0 /* B */, 0 /* C */,
0 /* D */, 0 /* E */, 0 /* F */, 0 /* G */,
0 /* H */, 0 /* I */, 0 /* J */, 0 /* K */,
0 /* L */, 0 /* M */, 0 /* N */, 0 /* O */,
0 /* P */, 0 /* Q */, 0 /* R */, 0 /* S */,
0 /* T */, 0 /* U */, 0 /* V */, 0 /* W */,
0 /* X */, 0 /* Y */, 0 /* Z */, 0 /* [ */,
0 /* \ */, 0 /* ] */, 1 /* ^ */, 1 /* _ */,
1 /* ` */, 1 /* a */, 1 /* b */, 1 /* c */,
1 /* d */, 1 /* e */, 1 /* f */, 1 /* g */,
1 /* h */, 1 /* i */, 1 /* j */, 1 /* k */,
1 /* l */, 1 /* m */, 1 /* n */, 1 /* o */,
1 /* p */, 1 /* q */, 1 /* r */, 1 /* s */,
1 /* t */, 1 /* u */, 1 /* v */, 1 /* w */,
1 /* x */, 1 /* y */, 1 /* z */, 0 /* { */,
1 /* | */, 0 /* } */, 1 /* ~ */, 0 /* DEL */,
0 /* 0x80 */, 0 /* 0x81 */, 0 /* 0x82 */, 0 /* 0x83 */,
0 /* 0x84 */, 0 /* 0x85 */, 0 /* 0x86 */, 0 /* 0x87 */,
0 /* 0x88 */, 0 /* 0x89 */, 0 /* 0x8a */, 0 /* 0x8b */,
0 /* 0x8c */, 0 /* 0x8d */, 0 /* 0x8e */, 0 /* 0x8f */,
0 /* 0x90 */, 0 /* 0x91 */, 0 /* 0x92 */, 0 /* 0x93 */,
0 /* 0x94 */, 0 /* 0x95 */, 0 /* 0x96 */, 0 /* 0x97 */,
0 /* 0x98 */, 0 /* 0x99 */, 0 /* 0x9a */, 0 /* 0x9b */,
0 /* 0x9c */, 0 /* 0x9d */, 0 /* 0x9e */, 0 /* 0x9f */,
0 /* 0xa0 */, 0 /* 0xa1 */, 0 /* 0xa2 */, 0 /* 0xa3 */,
0 /* 0xa4 */, 0 /* 0xa5 */, 0 /* 0xa6 */, 0 /* 0xa7 */,
0 /* 0xa8 */, 0 /* 0xa9 */, 0 /* 0xaa */, 0 /* 0xab */,
0 /* 0xac */, 0 /* 0xad */, 0 /* 0xae */, 0 /* 0xaf */,
0 /* 0xb0 */, 0 /* 0xb1 */, 0 /* 0xb2 */, 0 /* 0xb3 */,
0 /* 0xb4 */, 0 /* 0xb5 */, 0 /* 0xb6 */, 0 /* 0xb7 */,
0 /* 0xb8 */, 0 /* 0xb9 */, 0 /* 0xba */, 0 /* 0xbb */,
0 /* 0xbc */, 0 /* 0xbd */, 0 /* 0xbe */, 0 /* 0xbf */,
0 /* 0xc0 */, 0 /* 0xc1 */, 0 /* 0xc2 */, 0 /* 0xc3 */,
0 /* 0xc4 */, 0 /* 0xc5 */, 0 /* 0xc6 */, 0 /* 0xc7 */,
0 /* 0xc8 */, 0 /* 0xc9 */, 0 /* 0xca */, 0 /* 0xcb */,
0 /* 0xcc */, 0 /* 0xcd */, 0 /* 0xce */, 0 /* 0xcf */,
0 /* 0xd0 */, 0 /* 0xd1 */, 0 /* 0xd2 */, 0 /* 0xd3 */,
0 /* 0xd4 */, 0 /* 0xd5 */, 0 /* 0xd6 */, 0 /* 0xd7 */,
0 /* 0xd8 */, 0 /* 0xd9 */, 0 /* 0xda */, 0 /* 0xdb */,
0 /* 0xdc */, 0 /* 0xdd */, 0 /* 0xde */, 0 /* 0xdf */,
0 /* 0xe0 */, 0 /* 0xe1 */, 0 /* 0xe2 */, 0 /* 0xe3 */,
0 /* 0xe4 */, 0 /* 0xe5 */, 0 /* 0xe6 */, 0 /* 0xe7 */,
0 /* 0xe8 */, 0 /* 0xe9 */, 0 /* 0xea */, 0 /* 0xeb */,
0 /* 0xec */, 0 /* 0xed */, 0 /* 0xee */, 0 /* 0xef */,
0 /* 0xf0 */, 0 /* 0xf1 */, 0 /* 0xf2 */, 0 /* 0xf3 */,
0 /* 0xf4 */, 0 /* 0xf5 */, 0 /* 0xf6 */, 0 /* 0xf7 */,
0 /* 0xf8 */, 0 /* 0xf9 */, 0 /* 0xfa */, 0 /* 0xfb */,
0 /* 0xfc */, 0 /* 0xfd */, 0 /* 0xfe */, 0 /* 0xff */
0 /* NUL */, 0 /* SOH */, 0 /* STX */, 0 /* ETX */, 0 /* EOT */,
0 /* ENQ */, 0 /* ACK */, 0 /* BEL */, 0 /* BS */, 0 /* HT */,
0 /* LF */, 0 /* VT */, 0 /* FF */, 0 /* CR */, 0 /* SO */,
0 /* SI */, 0 /* DLE */, 0 /* DC1 */, 0 /* DC2 */, 0 /* DC3 */,
0 /* DC4 */, 0 /* NAK */, 0 /* SYN */, 0 /* ETB */, 0 /* CAN */,
0 /* EM */, 0 /* SUB */, 0 /* ESC */, 0 /* FS */, 0 /* GS */,
0 /* RS */, 0 /* US */, 0 /* SPC */, 1 /* ! */, 0 /* " */,
1 /* # */, 1 /* $ */, 1 /* % */, 1 /* & */, 1 /* ' */,
0 /* ( */, 0 /* ) */, 1 /* * */, 1 /* + */, 0 /* , */,
1 /* - */, 1 /* . */, 0 /* / */, 1 /* 0 */, 1 /* 1 */,
1 /* 2 */, 1 /* 3 */, 1 /* 4 */, 1 /* 5 */, 1 /* 6 */,
1 /* 7 */, 1 /* 8 */, 1 /* 9 */, 0 /* : */, 0 /* ; */,
0 /* < */, 0 /* = */, 0 /* > */, 0 /* ? */, 0 /* @ */,
0 /* A */, 0 /* B */, 0 /* C */, 0 /* D */, 0 /* E */,
0 /* F */, 0 /* G */, 0 /* H */, 0 /* I */, 0 /* J */,
0 /* K */, 0 /* L */, 0 /* M */, 0 /* N */, 0 /* O */,
0 /* P */, 0 /* Q */, 0 /* R */, 0 /* S */, 0 /* T */,
0 /* U */, 0 /* V */, 0 /* W */, 0 /* X */, 0 /* Y */,
0 /* Z */, 0 /* [ */, 0 /* \ */, 0 /* ] */, 1 /* ^ */,
1 /* _ */, 1 /* ` */, 1 /* a */, 1 /* b */, 1 /* c */,
1 /* d */, 1 /* e */, 1 /* f */, 1 /* g */, 1 /* h */,
1 /* i */, 1 /* j */, 1 /* k */, 1 /* l */, 1 /* m */,
1 /* n */, 1 /* o */, 1 /* p */, 1 /* q */, 1 /* r */,
1 /* s */, 1 /* t */, 1 /* u */, 1 /* v */, 1 /* w */,
1 /* x */, 1 /* y */, 1 /* z */, 0 /* { */, 1 /* | */,
0 /* } */, 1 /* ~ */, 0 /* DEL */, 0 /* 0x80 */, 0 /* 0x81 */,
0 /* 0x82 */, 0 /* 0x83 */, 0 /* 0x84 */, 0 /* 0x85 */, 0 /* 0x86 */,
0 /* 0x87 */, 0 /* 0x88 */, 0 /* 0x89 */, 0 /* 0x8a */, 0 /* 0x8b */,
0 /* 0x8c */, 0 /* 0x8d */, 0 /* 0x8e */, 0 /* 0x8f */, 0 /* 0x90 */,
0 /* 0x91 */, 0 /* 0x92 */, 0 /* 0x93 */, 0 /* 0x94 */, 0 /* 0x95 */,
0 /* 0x96 */, 0 /* 0x97 */, 0 /* 0x98 */, 0 /* 0x99 */, 0 /* 0x9a */,
0 /* 0x9b */, 0 /* 0x9c */, 0 /* 0x9d */, 0 /* 0x9e */, 0 /* 0x9f */,
0 /* 0xa0 */, 0 /* 0xa1 */, 0 /* 0xa2 */, 0 /* 0xa3 */, 0 /* 0xa4 */,
0 /* 0xa5 */, 0 /* 0xa6 */, 0 /* 0xa7 */, 0 /* 0xa8 */, 0 /* 0xa9 */,
0 /* 0xaa */, 0 /* 0xab */, 0 /* 0xac */, 0 /* 0xad */, 0 /* 0xae */,
0 /* 0xaf */, 0 /* 0xb0 */, 0 /* 0xb1 */, 0 /* 0xb2 */, 0 /* 0xb3 */,
0 /* 0xb4 */, 0 /* 0xb5 */, 0 /* 0xb6 */, 0 /* 0xb7 */, 0 /* 0xb8 */,
0 /* 0xb9 */, 0 /* 0xba */, 0 /* 0xbb */, 0 /* 0xbc */, 0 /* 0xbd */,
0 /* 0xbe */, 0 /* 0xbf */, 0 /* 0xc0 */, 0 /* 0xc1 */, 0 /* 0xc2 */,
0 /* 0xc3 */, 0 /* 0xc4 */, 0 /* 0xc5 */, 0 /* 0xc6 */, 0 /* 0xc7 */,
0 /* 0xc8 */, 0 /* 0xc9 */, 0 /* 0xca */, 0 /* 0xcb */, 0 /* 0xcc */,
0 /* 0xcd */, 0 /* 0xce */, 0 /* 0xcf */, 0 /* 0xd0 */, 0 /* 0xd1 */,
0 /* 0xd2 */, 0 /* 0xd3 */, 0 /* 0xd4 */, 0 /* 0xd5 */, 0 /* 0xd6 */,
0 /* 0xd7 */, 0 /* 0xd8 */, 0 /* 0xd9 */, 0 /* 0xda */, 0 /* 0xdb */,
0 /* 0xdc */, 0 /* 0xdd */, 0 /* 0xde */, 0 /* 0xdf */, 0 /* 0xe0 */,
0 /* 0xe1 */, 0 /* 0xe2 */, 0 /* 0xe3 */, 0 /* 0xe4 */, 0 /* 0xe5 */,
0 /* 0xe6 */, 0 /* 0xe7 */, 0 /* 0xe8 */, 0 /* 0xe9 */, 0 /* 0xea */,
0 /* 0xeb */, 0 /* 0xec */, 0 /* 0xed */, 0 /* 0xee */, 0 /* 0xef */,
0 /* 0xf0 */, 0 /* 0xf1 */, 0 /* 0xf2 */, 0 /* 0xf3 */, 0 /* 0xf4 */,
0 /* 0xf5 */, 0 /* 0xf6 */, 0 /* 0xf7 */, 0 /* 0xf8 */, 0 /* 0xf9 */,
0 /* 0xfa */, 0 /* 0xfb */, 0 /* 0xfc */, 0 /* 0xfd */, 0 /* 0xfe */,
0 /* 0xff */
};
int nghttp2_check_header_name(const uint8_t *name, size_t len)
{
int nghttp2_check_header_name(const uint8_t *name, size_t len) {
const uint8_t *last;
if(len == 0) {
if (len == 0) {
return 0;
}
if(*name == ':') {
if(len == 1) {
if (*name == ':') {
if (len == 1) {
return 0;
}
++name;
--len;
}
for(last = name + len; name != last; ++name) {
if(!VALID_HD_NAME_CHARS[*name]) {
for (last = name + len; name != last; ++name) {
if (!VALID_HD_NAME_CHARS[*name]) {
return 0;
}
}
return 1;
}
/* Generated by genvchartbl.py */
static int VALID_HD_VALUE_CHARS[] = {
1 /* NUL */, 0 /* SOH */, 0 /* STX */, 0 /* ETX */,
0 /* EOT */, 0 /* ENQ */, 0 /* ACK */, 0 /* BEL */,
0 /* BS */, 1 /* HT */, 0 /* LF */, 0 /* VT */,
0 /* FF */, 0 /* CR */, 0 /* SO */, 0 /* SI */,
0 /* DLE */, 0 /* DC1 */, 0 /* DC2 */, 0 /* DC3 */,
0 /* DC4 */, 0 /* NAK */, 0 /* SYN */, 0 /* ETB */,
0 /* CAN */, 0 /* EM */, 0 /* SUB */, 0 /* ESC */,
0 /* FS */, 0 /* GS */, 0 /* RS */, 0 /* US */,
1 /* SPC */, 1 /* ! */, 1 /* " */, 1 /* # */,
1 /* $ */, 1 /* % */, 1 /* & */, 1 /* ' */,
1 /* ( */, 1 /* ) */, 1 /* * */, 1 /* + */,
1 /* , */, 1 /* - */, 1 /* . */, 1 /* / */,
1 /* 0 */, 1 /* 1 */, 1 /* 2 */, 1 /* 3 */,
1 /* 4 */, 1 /* 5 */, 1 /* 6 */, 1 /* 7 */,
1 /* 8 */, 1 /* 9 */, 1 /* : */, 1 /* ; */,
1 /* < */, 1 /* = */, 1 /* > */, 1 /* ? */,
1 /* @ */, 1 /* A */, 1 /* B */, 1 /* C */,
1 /* D */, 1 /* E */, 1 /* F */, 1 /* G */,
1 /* H */, 1 /* I */, 1 /* J */, 1 /* K */,
1 /* L */, 1 /* M */, 1 /* N */, 1 /* O */,
1 /* P */, 1 /* Q */, 1 /* R */, 1 /* S */,
1 /* T */, 1 /* U */, 1 /* V */, 1 /* W */,
1 /* X */, 1 /* Y */, 1 /* Z */, 1 /* [ */,
1 /* \ */, 1 /* ] */, 1 /* ^ */, 1 /* _ */,
1 /* ` */, 1 /* a */, 1 /* b */, 1 /* c */,
1 /* d */, 1 /* e */, 1 /* f */, 1 /* g */,
1 /* h */, 1 /* i */, 1 /* j */, 1 /* k */,
1 /* l */, 1 /* m */, 1 /* n */, 1 /* o */,
1 /* p */, 1 /* q */, 1 /* r */, 1 /* s */,
1 /* t */, 1 /* u */, 1 /* v */, 1 /* w */,
1 /* x */, 1 /* y */, 1 /* z */, 1 /* { */,
1 /* | */, 1 /* } */, 1 /* ~ */, 0 /* DEL */,
1 /* 0x80 */, 1 /* 0x81 */, 1 /* 0x82 */, 1 /* 0x83 */,
1 /* 0x84 */, 1 /* 0x85 */, 1 /* 0x86 */, 1 /* 0x87 */,
1 /* 0x88 */, 1 /* 0x89 */, 1 /* 0x8a */, 1 /* 0x8b */,
1 /* 0x8c */, 1 /* 0x8d */, 1 /* 0x8e */, 1 /* 0x8f */,
1 /* 0x90 */, 1 /* 0x91 */, 1 /* 0x92 */, 1 /* 0x93 */,
1 /* 0x94 */, 1 /* 0x95 */, 1 /* 0x96 */, 1 /* 0x97 */,
1 /* 0x98 */, 1 /* 0x99 */, 1 /* 0x9a */, 1 /* 0x9b */,
1 /* 0x9c */, 1 /* 0x9d */, 1 /* 0x9e */, 1 /* 0x9f */,
1 /* 0xa0 */, 1 /* 0xa1 */, 1 /* 0xa2 */, 1 /* 0xa3 */,
1 /* 0xa4 */, 1 /* 0xa5 */, 1 /* 0xa6 */, 1 /* 0xa7 */,
1 /* 0xa8 */, 1 /* 0xa9 */, 1 /* 0xaa */, 1 /* 0xab */,
1 /* 0xac */, 1 /* 0xad */, 1 /* 0xae */, 1 /* 0xaf */,
1 /* 0xb0 */, 1 /* 0xb1 */, 1 /* 0xb2 */, 1 /* 0xb3 */,
1 /* 0xb4 */, 1 /* 0xb5 */, 1 /* 0xb6 */, 1 /* 0xb7 */,
1 /* 0xb8 */, 1 /* 0xb9 */, 1 /* 0xba */, 1 /* 0xbb */,
1 /* 0xbc */, 1 /* 0xbd */, 1 /* 0xbe */, 1 /* 0xbf */,
1 /* 0xc0 */, 1 /* 0xc1 */, 1 /* 0xc2 */, 1 /* 0xc3 */,
1 /* 0xc4 */, 1 /* 0xc5 */, 1 /* 0xc6 */, 1 /* 0xc7 */,
1 /* 0xc8 */, 1 /* 0xc9 */, 1 /* 0xca */, 1 /* 0xcb */,
1 /* 0xcc */, 1 /* 0xcd */, 1 /* 0xce */, 1 /* 0xcf */,
1 /* 0xd0 */, 1 /* 0xd1 */, 1 /* 0xd2 */, 1 /* 0xd3 */,
1 /* 0xd4 */, 1 /* 0xd5 */, 1 /* 0xd6 */, 1 /* 0xd7 */,
1 /* 0xd8 */, 1 /* 0xd9 */, 1 /* 0xda */, 1 /* 0xdb */,
1 /* 0xdc */, 1 /* 0xdd */, 1 /* 0xde */, 1 /* 0xdf */,
1 /* 0xe0 */, 1 /* 0xe1 */, 1 /* 0xe2 */, 1 /* 0xe3 */,
1 /* 0xe4 */, 1 /* 0xe5 */, 1 /* 0xe6 */, 1 /* 0xe7 */,
1 /* 0xe8 */, 1 /* 0xe9 */, 1 /* 0xea */, 1 /* 0xeb */,
1 /* 0xec */, 1 /* 0xed */, 1 /* 0xee */, 1 /* 0xef */,
1 /* 0xf0 */, 1 /* 0xf1 */, 1 /* 0xf2 */, 1 /* 0xf3 */,
1 /* 0xf4 */, 1 /* 0xf5 */, 1 /* 0xf6 */, 1 /* 0xf7 */,
1 /* 0xf8 */, 1 /* 0xf9 */, 1 /* 0xfa */, 1 /* 0xfb */,
1 /* 0xfc */, 1 /* 0xfd */, 1 /* 0xfe */, 1 /* 0xff */
0 /* NUL */, 0 /* SOH */, 0 /* STX */, 0 /* ETX */, 0 /* EOT */,
0 /* ENQ */, 0 /* ACK */, 0 /* BEL */, 0 /* BS */, 1 /* HT */,
0 /* LF */, 0 /* VT */, 0 /* FF */, 0 /* CR */, 0 /* SO */,
0 /* SI */, 0 /* DLE */, 0 /* DC1 */, 0 /* DC2 */, 0 /* DC3 */,
0 /* DC4 */, 0 /* NAK */, 0 /* SYN */, 0 /* ETB */, 0 /* CAN */,
0 /* EM */, 0 /* SUB */, 0 /* ESC */, 0 /* FS */, 0 /* GS */,
0 /* RS */, 0 /* US */, 1 /* SPC */, 1 /* ! */, 1 /* " */,
1 /* # */, 1 /* $ */, 1 /* % */, 1 /* & */, 1 /* ' */,
1 /* ( */, 1 /* ) */, 1 /* * */, 1 /* + */, 1 /* , */,
1 /* - */, 1 /* . */, 1 /* / */, 1 /* 0 */, 1 /* 1 */,
1 /* 2 */, 1 /* 3 */, 1 /* 4 */, 1 /* 5 */, 1 /* 6 */,
1 /* 7 */, 1 /* 8 */, 1 /* 9 */, 1 /* : */, 1 /* ; */,
1 /* < */, 1 /* = */, 1 /* > */, 1 /* ? */, 1 /* @ */,
1 /* A */, 1 /* B */, 1 /* C */, 1 /* D */, 1 /* E */,
1 /* F */, 1 /* G */, 1 /* H */, 1 /* I */, 1 /* J */,
1 /* K */, 1 /* L */, 1 /* M */, 1 /* N */, 1 /* O */,
1 /* P */, 1 /* Q */, 1 /* R */, 1 /* S */, 1 /* T */,
1 /* U */, 1 /* V */, 1 /* W */, 1 /* X */, 1 /* Y */,
1 /* Z */, 1 /* [ */, 1 /* \ */, 1 /* ] */, 1 /* ^ */,
1 /* _ */, 1 /* ` */, 1 /* a */, 1 /* b */, 1 /* c */,
1 /* d */, 1 /* e */, 1 /* f */, 1 /* g */, 1 /* h */,
1 /* i */, 1 /* j */, 1 /* k */, 1 /* l */, 1 /* m */,
1 /* n */, 1 /* o */, 1 /* p */, 1 /* q */, 1 /* r */,
1 /* s */, 1 /* t */, 1 /* u */, 1 /* v */, 1 /* w */,
1 /* x */, 1 /* y */, 1 /* z */, 1 /* { */, 1 /* | */,
1 /* } */, 1 /* ~ */, 0 /* DEL */, 1 /* 0x80 */, 1 /* 0x81 */,
1 /* 0x82 */, 1 /* 0x83 */, 1 /* 0x84 */, 1 /* 0x85 */, 1 /* 0x86 */,
1 /* 0x87 */, 1 /* 0x88 */, 1 /* 0x89 */, 1 /* 0x8a */, 1 /* 0x8b */,
1 /* 0x8c */, 1 /* 0x8d */, 1 /* 0x8e */, 1 /* 0x8f */, 1 /* 0x90 */,
1 /* 0x91 */, 1 /* 0x92 */, 1 /* 0x93 */, 1 /* 0x94 */, 1 /* 0x95 */,
1 /* 0x96 */, 1 /* 0x97 */, 1 /* 0x98 */, 1 /* 0x99 */, 1 /* 0x9a */,
1 /* 0x9b */, 1 /* 0x9c */, 1 /* 0x9d */, 1 /* 0x9e */, 1 /* 0x9f */,
1 /* 0xa0 */, 1 /* 0xa1 */, 1 /* 0xa2 */, 1 /* 0xa3 */, 1 /* 0xa4 */,
1 /* 0xa5 */, 1 /* 0xa6 */, 1 /* 0xa7 */, 1 /* 0xa8 */, 1 /* 0xa9 */,
1 /* 0xaa */, 1 /* 0xab */, 1 /* 0xac */, 1 /* 0xad */, 1 /* 0xae */,
1 /* 0xaf */, 1 /* 0xb0 */, 1 /* 0xb1 */, 1 /* 0xb2 */, 1 /* 0xb3 */,
1 /* 0xb4 */, 1 /* 0xb5 */, 1 /* 0xb6 */, 1 /* 0xb7 */, 1 /* 0xb8 */,
1 /* 0xb9 */, 1 /* 0xba */, 1 /* 0xbb */, 1 /* 0xbc */, 1 /* 0xbd */,
1 /* 0xbe */, 1 /* 0xbf */, 1 /* 0xc0 */, 1 /* 0xc1 */, 1 /* 0xc2 */,
1 /* 0xc3 */, 1 /* 0xc4 */, 1 /* 0xc5 */, 1 /* 0xc6 */, 1 /* 0xc7 */,
1 /* 0xc8 */, 1 /* 0xc9 */, 1 /* 0xca */, 1 /* 0xcb */, 1 /* 0xcc */,
1 /* 0xcd */, 1 /* 0xce */, 1 /* 0xcf */, 1 /* 0xd0 */, 1 /* 0xd1 */,
1 /* 0xd2 */, 1 /* 0xd3 */, 1 /* 0xd4 */, 1 /* 0xd5 */, 1 /* 0xd6 */,
1 /* 0xd7 */, 1 /* 0xd8 */, 1 /* 0xd9 */, 1 /* 0xda */, 1 /* 0xdb */,
1 /* 0xdc */, 1 /* 0xdd */, 1 /* 0xde */, 1 /* 0xdf */, 1 /* 0xe0 */,
1 /* 0xe1 */, 1 /* 0xe2 */, 1 /* 0xe3 */, 1 /* 0xe4 */, 1 /* 0xe5 */,
1 /* 0xe6 */, 1 /* 0xe7 */, 1 /* 0xe8 */, 1 /* 0xe9 */, 1 /* 0xea */,
1 /* 0xeb */, 1 /* 0xec */, 1 /* 0xed */, 1 /* 0xee */, 1 /* 0xef */,
1 /* 0xf0 */, 1 /* 0xf1 */, 1 /* 0xf2 */, 1 /* 0xf3 */, 1 /* 0xf4 */,
1 /* 0xf5 */, 1 /* 0xf6 */, 1 /* 0xf7 */, 1 /* 0xf8 */, 1 /* 0xf9 */,
1 /* 0xfa */, 1 /* 0xfb */, 1 /* 0xfc */, 1 /* 0xfd */, 1 /* 0xfe */,
1 /* 0xff */
};
int nghttp2_check_header_value(const uint8_t *value, size_t len)
{
int nghttp2_check_header_value(const uint8_t *value, size_t len) {
const uint8_t *last;
for(last = value + len; value != last; ++value) {
if(!VALID_HD_VALUE_CHARS[*value]) {
for (last = value + len; value != last; ++value) {
if (!VALID_HD_VALUE_CHARS[*value]) {
return 0;
}
}
return 1;
}
uint8_t *nghttp2_cpymem(uint8_t *dest, const void *src, size_t len) {
memcpy(dest, src, len);
return dest + len;
}

View File

@@ -1,5 +1,5 @@
/*
* nghttp2 - HTTP/2.0 C Library
* nghttp2 - HTTP/2 C Library
*
* Copyright (c) 2012 Tatsuhiro Tsujikawa
*
@@ -26,10 +26,11 @@
#define NGHTTP2_HELPER_H
#ifdef HAVE_CONFIG_H
# include <config.h>
#include <config.h>
#endif /* HAVE_CONFIG_H */
#include <nghttp2/nghttp2.h>
#include "nghttp2_mem.h"
#define nghttp2_min(A, B) ((A) < (B) ? (A) : (B))
#define nghttp2_max(A, B) ((A) > (B) ? (A) : (B))
@@ -59,26 +60,7 @@ uint16_t nghttp2_get_uint16(const uint8_t *data);
uint32_t nghttp2_get_uint32(const uint8_t *data);
/*
* Ensures that buffer |*buf_ptr| with |*buflen_ptr| length has at
* least |min_length| bytes. If |min_length| > |*buflen_ptr|,
* allocates new buffer having at least |min_length| bytes and assigns
* its pointer to |*buf_ptr| and allocated number of bytes to
* |*buflen_ptr|. The memory pointed by |*buf_ptr| previously may
* change. No memory copy is done between old and new buffer.
* |*buf_ptr| and |*buflen_ptr| are only updated iff this function
* succeeds.
*
* This function returns 0 if it succeeds, or one of the following
* negative error codes:
*
* NGHTTP2_ERR_NOMEM
* Out of memory.
*/
int nghttp2_reserve_buffer(uint8_t **buf_ptr, size_t *buflen_ptr,
size_t min_length);
/*
* Allocates |n| bytes of memory and copy the meory region pointed by
* Allocates |n| bytes of memory and copy the memory region pointed by
* |src| with the length |n| bytes into it. Returns the allocated memory.
*
* This function returns pointer to allocated memory, or one of the
@@ -87,7 +69,7 @@ int nghttp2_reserve_buffer(uint8_t **buf_ptr, size_t *buflen_ptr,
* NGHTTP2_ERR_NOMEM
* Out of memory.
*/
void* nghttp2_memdup(const void* src, size_t n);
void *nghttp2_memdup(const void *src, size_t n, nghttp2_mem *mem);
void nghttp2_downcase(uint8_t *s, size_t len);
@@ -119,11 +101,10 @@ int nghttp2_should_send_window_update(int32_t local_window_size,
int32_t recv_window_size);
/*
* Deallocates memory space pointed by |ptr|. This function exists for
* the application to free the memory space allocated by the library
* functions. Currently this function is hidden from the public API,
* but may be exposed as public API.
* Copies the buffer |src| of length |len| to the destination pointed
* by the |dest|, assuming that the |dest| is at lest |len| bytes long
* . Returns dest + len.
*/
void nghttp2_free(void *ptr);
uint8_t *nghttp2_cpymem(uint8_t *dest, const void *src, size_t len);
#endif /* NGHTTP2_HELPER_H */

View File

@@ -1,5 +1,5 @@
/*
* nghttp2 - HTTP/2.0 C Library
* nghttp2 - HTTP/2 C Library
*
* Copyright (c) 2012 Tatsuhiro Tsujikawa
*
@@ -26,17 +26,17 @@
#define NGHTTP2_INT_H
#ifdef HAVE_CONFIG_H
# include <config.h>
#include <config.h>
#endif /* HAVE_CONFIG_H */
#include <stdint.h>
/* Macros, types and constants for internal use */
#ifdef DEBUGBUILD
#define DEBUGF(x) x
#else
#define DEBUGF(x) do { } while(0)
#define DEBUGF(x) \
do { \
} while (0)
#endif
typedef int (*nghttp2_compar)(const void *lhs, const void *rhs);
@@ -45,9 +45,8 @@ typedef int (*nghttp2_compar)(const void *lhs, const void *rhs);
inclusive. */
typedef enum {
NGHTTP2_ERR_CREDENTIAL_PENDING = -101,
NGHTTP2_ERR_BUFFER_ERROR = -102,
NGHTTP2_ERR_IGN_HEADER_BLOCK = -103,
NGHTTP2_ERR_IGN_PAYLOAD = -104,
NGHTTP2_ERR_IGN_PAYLOAD = -104
} nghttp2_internal_error;
#endif /* NGHTTP2_INT_H */

View File

@@ -1,5 +1,5 @@
/*
* nghttp2 - HTTP/2.0 C Library
* nghttp2 - HTTP/2 C Library
*
* Copyright (c) 2012 Tatsuhiro Tsujikawa
*
@@ -26,33 +26,33 @@
#include <string.h>
#define INITIAL_TABLE_LENGTH 16
#define INITIAL_TABLE_LENGTH 256
int nghttp2_map_init(nghttp2_map *map)
{
int nghttp2_map_init(nghttp2_map *map, nghttp2_mem *mem) {
map->mem = mem;
map->tablelen = INITIAL_TABLE_LENGTH;
map->table = malloc(sizeof(nghttp2_map_entry*) * map->tablelen);
if(map->table == NULL) {
map->table =
nghttp2_mem_calloc(mem, map->tablelen, sizeof(nghttp2_map_entry *));
if (map->table == NULL) {
return NGHTTP2_ERR_NOMEM;
}
memset(map->table, 0, sizeof(nghttp2_map_entry*) * map->tablelen);
map->size = 0;
return 0;
}
void nghttp2_map_free(nghttp2_map *map)
{
free(map->table);
void nghttp2_map_free(nghttp2_map *map) {
nghttp2_mem_free(map->mem, map->table);
}
void nghttp2_map_each_free(nghttp2_map *map,
int (*func)(nghttp2_map_entry *entry, void *ptr),
void *ptr)
{
void *ptr) {
size_t i;
for(i = 0; i < map->tablelen; ++i) {
for (i = 0; i < map->tablelen; ++i) {
nghttp2_map_entry *entry;
for(entry = map->table[i]; entry;) {
for (entry = map->table[i]; entry;) {
nghttp2_map_entry *next = entry->next;
func(entry, ptr);
entry = next;
@@ -63,15 +63,14 @@ void nghttp2_map_each_free(nghttp2_map *map,
int nghttp2_map_each(nghttp2_map *map,
int (*func)(nghttp2_map_entry *entry, void *ptr),
void *ptr)
{
void *ptr) {
int rv;
size_t i;
for(i = 0; i < map->tablelen; ++i) {
for (i = 0; i < map->tablelen; ++i) {
nghttp2_map_entry *entry;
for(entry = map->table[i]; entry; entry = entry->next) {
for (entry = map->table[i]; entry; entry = entry->next) {
rv = func(entry, ptr);
if(rv != 0) {
if (rv != 0) {
return rv;
}
}
@@ -79,31 +78,29 @@ int nghttp2_map_each(nghttp2_map *map,
return 0;
}
void nghttp2_map_entry_init(nghttp2_map_entry *entry, key_type key)
{
void nghttp2_map_entry_init(nghttp2_map_entry *entry, key_type key) {
entry->key = key;
entry->next = NULL;
}
/* Same hash function in openjdk HashMap source code. */
/* Same hash function in android HashMap source code. */
/* The |mod| must be power of 2 */
static int32_t hash(int32_t h, int32_t mod)
{
static int32_t hash(int32_t h, size_t mod) {
h ^= (h >> 20) ^ (h >> 12);
return (h ^ (h >> 7) ^ (h >> 4)) & (mod - 1);
h ^= (h >> 7) ^ (h >> 4);
return h & (mod - 1);
}
static int insert(nghttp2_map_entry **table, size_t tablelen,
nghttp2_map_entry *entry)
{
nghttp2_map_entry *entry) {
int32_t h = hash(entry->key, tablelen);
if(table[h] == NULL) {
if (table[h] == NULL) {
table[h] = entry;
} else {
nghttp2_map_entry *p;
/* We won't allow duplicated key, so check it out. */
for(p = table[h]; p; p = p->next) {
if(p->key == entry->key) {
for (p = table[h]; p; p = p->next) {
if (p->key == entry->key) {
return NGHTTP2_ERR_INVALID_ARGUMENT;
}
}
@@ -114,18 +111,19 @@ static int insert(nghttp2_map_entry **table, size_t tablelen,
}
/* new_tablelen must be power of 2 */
static int resize(nghttp2_map *map, size_t new_tablelen)
{
static int resize(nghttp2_map *map, size_t new_tablelen) {
size_t i;
nghttp2_map_entry **new_table;
new_table = malloc(sizeof(nghttp2_map_entry*) * new_tablelen);
if(new_table == NULL) {
new_table =
nghttp2_mem_calloc(map->mem, new_tablelen, sizeof(nghttp2_map_entry *));
if (new_table == NULL) {
return NGHTTP2_ERR_NOMEM;
}
memset(new_table, 0, sizeof(nghttp2_map_entry*) * new_tablelen);
for(i = 0; i < map->tablelen; ++i) {
for (i = 0; i < map->tablelen; ++i) {
nghttp2_map_entry *entry;
for(entry = map->table[i]; entry;) {
for (entry = map->table[i]; entry;) {
nghttp2_map_entry *next = entry->next;
entry->next = NULL;
/* This function must succeed */
@@ -133,52 +131,50 @@ static int resize(nghttp2_map *map, size_t new_tablelen)
entry = next;
}
}
free(map->table);
nghttp2_mem_free(map->mem, map->table);
map->tablelen = new_tablelen;
map->table = new_table;
return 0;
}
int nghttp2_map_insert(nghttp2_map *map, nghttp2_map_entry *new_entry)
{
int nghttp2_map_insert(nghttp2_map *map, nghttp2_map_entry *new_entry) {
int rv;
/* Load factor is 0.75 */
if((map->size + 1) * 4 > map->tablelen * 3) {
if ((map->size + 1) * 4 > map->tablelen * 3) {
rv = resize(map, map->tablelen * 2);
if(rv != 0) {
if (rv != 0) {
return rv;
}
}
rv = insert(map->table, map->tablelen, new_entry);
if(rv != 0) {
if (rv != 0) {
return rv;
}
++map->size;
return 0;
}
nghttp2_map_entry* nghttp2_map_find(nghttp2_map *map, key_type key)
{
nghttp2_map_entry *nghttp2_map_find(nghttp2_map *map, key_type key) {
int32_t h;
nghttp2_map_entry *entry;
h = hash(key, map->tablelen);
for(entry = map->table[h]; entry; entry = entry->next) {
if(entry->key == key) {
for (entry = map->table[h]; entry; entry = entry->next) {
if (entry->key == key) {
return entry;
}
}
return NULL;
}
int nghttp2_map_remove(nghttp2_map *map, key_type key)
{
int nghttp2_map_remove(nghttp2_map *map, key_type key) {
int32_t h;
nghttp2_map_entry *entry, *prev;
h = hash(key, map->tablelen);
prev = NULL;
for(entry = map->table[h]; entry; entry = entry->next) {
if(entry->key == key) {
if(prev == NULL) {
for (entry = map->table[h]; entry; entry = entry->next) {
if (entry->key == key) {
if (prev == NULL) {
map->table[h] = entry->next;
} else {
prev->next = entry->next;
@@ -191,7 +187,4 @@ int nghttp2_map_remove(nghttp2_map *map, key_type key)
return NGHTTP2_ERR_INVALID_ARGUMENT;
}
size_t nghttp2_map_size(nghttp2_map *map)
{
return map->size;
}
size_t nghttp2_map_size(nghttp2_map *map) { return map->size; }

View File

@@ -1,5 +1,5 @@
/*
* nghttp2 - HTTP/2.0 C Library
* nghttp2 - HTTP/2 C Library
*
* Copyright (c) 2012 Tatsuhiro Tsujikawa
*
@@ -26,11 +26,12 @@
#define NGHTTP2_MAP_H
#ifdef HAVE_CONFIG_H
# include <config.h>
#include <config.h>
#endif /* HAVE_CONFIG_H */
#include <nghttp2/nghttp2.h>
#include "nghttp2_int.h"
#include "nghttp2_mem.h"
/* Implementation of unordered map */
@@ -43,6 +44,7 @@ typedef struct nghttp2_map_entry {
typedef struct {
nghttp2_map_entry **table;
nghttp2_mem *mem;
size_t tablelen;
size_t size;
} nghttp2_map;
@@ -56,7 +58,7 @@ typedef struct {
* NGHTTP2_ERR_NOMEM
* Out of memory
*/
int nghttp2_map_init(nghttp2_map *map);
int nghttp2_map_init(nghttp2_map *map, nghttp2_mem *mem);
/*
* Deallocates any resources allocated for |map|. The stored entries
@@ -98,7 +100,7 @@ int nghttp2_map_insert(nghttp2_map *map, nghttp2_map_entry *entry);
* Returns the entry associated by the key |key|. If there is no such
* entry, this function returns NULL.
*/
nghttp2_map_entry* nghttp2_map_find(nghttp2_map *map, key_type key);
nghttp2_map_entry *nghttp2_map_find(nghttp2_map *map, key_type key);
/*
* Removes the entry associated by the key |key| from the |map|. The

61
lib/nghttp2_mem.c Normal file
View File

@@ -0,0 +1,61 @@
/*
* nghttp2 - HTTP/2 C Library
*
* Copyright (c) 2014 Tatsuhiro Tsujikawa
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "nghttp2_mem.h"
static void *default_malloc(size_t size, void *mem_user_data _U_) {
return malloc(size);
}
static void default_free(void *ptr, void *mem_user_data _U_) { free(ptr); }
static void *default_calloc(size_t nmemb, size_t size,
void *mem_user_data _U_) {
return calloc(nmemb, size);
}
static void *default_realloc(void *ptr, size_t size, void *mem_user_data _U_) {
return realloc(ptr, size);
}
static nghttp2_mem mem_default = {NULL, default_malloc, default_free,
default_calloc, default_realloc};
nghttp2_mem *nghttp2_mem_default(void) { return &mem_default; }
void *nghttp2_mem_malloc(nghttp2_mem *mem, size_t size) {
return mem->malloc(size, mem->mem_user_data);
}
void nghttp2_mem_free(nghttp2_mem *mem, void *ptr) {
mem->free(ptr, mem->mem_user_data);
}
void *nghttp2_mem_calloc(nghttp2_mem *mem, size_t nmemb, size_t size) {
return mem->calloc(nmemb, size, mem->mem_user_data);
}
void *nghttp2_mem_realloc(nghttp2_mem *mem, void *ptr, size_t size) {
return mem->realloc(ptr, size, mem->mem_user_data);
}

44
lib/nghttp2_mem.h Normal file
View File

@@ -0,0 +1,44 @@
/*
* nghttp2 - HTTP/2 C Library
*
* Copyright (c) 2014 Tatsuhiro Tsujikawa
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef NGHTTP2_MEM_H
#define NGHTTP2_MEM_H
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif /* HAVE_CONFIG_H */
#include <nghttp2/nghttp2.h>
/* The default, system standard memory allocator */
nghttp2_mem *nghttp2_mem_default(void);
/* Convenient wrapper functions to call allocator function in
|mem|. */
void *nghttp2_mem_malloc(nghttp2_mem *mem, size_t size);
void nghttp2_mem_free(nghttp2_mem *mem, void *ptr);
void *nghttp2_mem_calloc(nghttp2_mem *mem, size_t nmemb, size_t size);
void *nghttp2_mem_realloc(nghttp2_mem *mem, void *ptr, size_t size);
#endif /* NGHTTP2_MEM_H */

View File

@@ -1,5 +1,5 @@
/*
* nghttp2 - HTTP/2.0 C Library
* nghttp2 - HTTP/2 C Library
*
* Copyright (c) 2012 Tatsuhiro Tsujikawa
*
@@ -26,19 +26,19 @@
#define NGHTTP2_NET_H
#ifdef HAVE_CONFIG_H
# include <config.h>
#include <config.h>
#endif /* HAVE_CONFIG_H */
#ifdef HAVE_ARPA_INET_H
# include <arpa/inet.h>
#include <arpa/inet.h>
#endif /* HAVE_ARPA_INET_H */
#ifdef HAVE_NETINET_IN_H
# include <netinet/in.h>
#include <netinet/in.h>
#endif /* HAVE_NETINET_IN_H */
#ifdef HAVE_WINSOCK2_H
# include <winsock2.h>
#include <winsock2.h>
#endif /* HAVE_WINSOCK2_H */
#endif /* NGHTTP2_NET_H */

View File

@@ -1,5 +1,5 @@
/*
* nghttp2 - HTTP/2.0 C Library
* nghttp2 - HTTP/2 C Library
*
* Copyright (c) 2012 Tatsuhiro Tsujikawa
*
@@ -27,26 +27,26 @@
#include <string.h>
int nghttp2_select_next_protocol(unsigned char **out, unsigned char *outlen,
const unsigned char *in, unsigned int inlen)
{
const unsigned char *in, unsigned int inlen) {
int http_selected = 0;
unsigned int i = 0;
for(; i < inlen; i += in[i]+1) {
if(in[i] == NGHTTP2_PROTO_VERSION_ID_LEN &&
memcmp(&in[i+1], NGHTTP2_PROTO_VERSION_ID, in[i]) == 0) {
*out = (unsigned char*)&in[i+1];
for (; i < inlen; i += in [i] + 1) {
if (in[i] == NGHTTP2_PROTO_VERSION_ID_LEN && i + 1 + in[i] <= inlen &&
memcmp(&in[i + 1], NGHTTP2_PROTO_VERSION_ID, in[i]) == 0) {
*out = (unsigned char *)&in[i + 1];
*outlen = in[i];
return 1;
}
if(in[i] == 8 && memcmp(&in[i+1], "http/1.1", in[i]) == 0) {
if (in[i] == 8 && i + 1 + in[i] <= inlen &&
memcmp(&in[i + 1], "http/1.1", in[i]) == 0) {
http_selected = 1;
*out = (unsigned char*)&in[i+1];
*out = (unsigned char *)&in[i + 1];
*outlen = in[i];
/* Go through to the next iteration, because "HTTP/2.0" may be
/* Go through to the next iteration, because "HTTP/2" may be
there */
}
}
if(http_selected) {
if (http_selected) {
return 0;
} else {
return -1;

View File

@@ -1,5 +1,5 @@
/*
* nghttp2 - HTTP/2.0 C Library
* nghttp2 - HTTP/2 C Library
*
* Copyright (c) 2012 Tatsuhiro Tsujikawa
*
@@ -26,7 +26,7 @@
#define NGHTTP2_NPN_H
#ifdef HAVE_CONFIG
# include <config.h>
#include <config.h>
#endif /* HAVE_CONFIG */
#include <nghttp2/nghttp2.h>

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