Commit Graph

217 Commits

Author SHA1 Message Date
Tatsuhiro Tsujikawa 16c46114dc More strict stream state handling
Previously, in server side, we used closed streams to detect the error
that the misbehaving client sends a frame on the incoming stream it
explicitly closed.  With this commit, we make a further step, and
detect one more error case.  Since we retain closed streams as long as
the sum of its size and the number of opened streams are equal or less
than max concurrent streams, we can safely say that if we get a frame
which is sent on the stream that is not found in either closed or
opened stream, it is already closed or has not existed.  Then we can
send GOAWAY.

The previous code shrinks closed streams when we closed another
stream, but now it is removed.  It is enough to adjust closed streams
when new incoming stream is created.

While creating this commit, we noticed that
NGHTTP2_INITIAL_MAX_CONCURRENT_STREAMS is defined as INT32_MAX.  But
since SETTINGS can contain value up to UINT32_MAX, it is not enough.
However, since the stream ID space is limited to INT32_MAX, it is high
enough.  We could keep this value, but this time we deprecate
NGHTTP2_INITIAL_MAX_CONCURRENT_STREAMS macro.  While it is in public
header, the effect of deprecating it is negligible because of the
reason we wrote above, and usually application sets much smaller value
(say, 100) as SETTINGS_MAX_CONCURRENT_STREAMS.
2016-08-07 19:31:00 +09:00
Tatsuhiro Tsujikawa 110ca3131a Cancel frame transmission from before_frame_send_callback
We define the behaviour when NGHTTP2_ERR_CANCEL is returned from
before_frame_send_callback.  That is to cancel the frame passed to the
callback.
2016-07-02 19:21:08 +09:00
Tatsuhiro Tsujikawa c7b0e04498 Add nghttp2_option_set_max_send_header_block_length API function
This function sets the maximum length of header block (a set of header
fields per HEADERS frame) to send.  The length of given set of header
fields is calculated using nghttp2_hd_deflate_bound().  Previously,
this is hard-coded, and is 64KiB.
2016-06-15 00:05:15 +09:00
Tatsuhiro Tsujikawa 204f9a3ec7 Add nghttp2_session_set_local_window_size() API function 2016-05-29 23:13:11 +09:00
Tatsuhiro Tsujikawa d88f962565 Add test for altsvc frame 2016-04-09 22:32:48 +09:00
Tatsuhiro Tsujikawa d4144a7475 altsvc: Add tests, ignore altsvc if stream does not exist 2016-04-09 19:14:15 +09:00
Tatsuhiro Tsujikawa efbd48b122 altsvc: Add tx tests 2016-04-08 23:25:56 +09:00
Tatsuhiro Tsujikawa 0caefe20ef Merge branch 'master' into simple-extensions 2016-01-09 19:08:28 +09:00
Tatsuhiro Tsujikawa 894c1bd02e Create idle stream on client side
With the presence of idle stream related API (e.g.,
nghttp2_create_idle_stream()), it is more predictable for client to
create idle streams with its dependency to another idle stream.
Previously, we didn't create complete parent idle stream in this case.
Now we create idle streams as we do on server side.
2015-12-25 00:10:37 +09:00
Tatsuhiro Tsujikawa bd9a19e23b Add test for 92a56d034f 2015-12-23 17:10:33 +09:00
Tatsuhiro Tsujikawa feae76fbc0 Remove unused commented lines 2015-12-18 22:44:08 +09:00
Tatsuhiro Tsujikawa 9f8fc7b2bb Strict error handling for frames which are not allowed after closed (remote)
This makes h2spec strict mode a bit happier.  We still one failing
test with h2spec -S (strict mode).
2015-12-17 21:31:20 +09:00
Tatsuhiro Tsujikawa ab93db2259 Add test when client sends push response to server 2015-12-11 00:18:27 +09:00
Tatsuhiro Tsujikawa 9c84f60ba0 Merge branch 'master' into simple-extensions 2015-12-04 23:48:40 +09:00
Tatsuhiro Tsujikawa f23e34fa3c Handle response in nghttp2_on_begin_frame_callback
Previously, nghttp2_session_end_request_headers_received assumes
stream is still writable (in other words, local endpoint has not sent
END_STREAM).  But this assumption is false, because application can
send response in nghttp2_on_begin_frame_callback.  Probably, this
assumption was made before the callback was introduced.  This commit
addresses this issue.  Since all
nghttp2_session_end_*_headers_received functions are identical, we
refactored them into one function.
2015-11-27 22:50:13 +09:00
Tatsuhiro Tsujikawa b53b1381b7 Fix bug that nghttp2_session_find_stream(session, 0) returned NULL
Previously, nghttp2_session_find_stream(session, 0) returned NULL
despite the fact that documentation said that it should return root
stream.  Now it is corrected, and it returns root stream as
documented.
2015-11-24 22:30:12 +09:00
Tatsuhiro Tsujikawa d62bc26b62 Add test for nghttp2_session_change_stream_priority() 2015-11-23 19:48:51 +09:00
Tatsuhiro Tsujikawa b918f9650a Don't send push response if GOAWAY has been received 2015-11-16 22:47:12 +09:00
Tatsuhiro Tsujikawa eb4e402aae Merge branch 'master' into simple-extensions 2015-11-14 22:31:52 +09:00
Tatsuhiro Tsujikawa 269a100081 Add nghttp2_session_upgrade2(), deprecate nghttp2_session_upgrade()
To validate actual response body length against the value declared in
content-length response header field, we first check request method.
If request method is HEAD, respose body must be 0 regardless of the
value in content-length.  nghttp2_session_upgrade() has no parameter
to indicate the request method is HEAD, so we failed to validate
response body if HEAD is used with HTTP Upgrade.  New
nghttp2_session_upgrade2() accepts new parameter to indicate that
request method is HEAD or not to fix this issue.  Although, this issue
affects client side only, we deprecate nghttp2_session_upgrade() in
favor of nghttp2_session_upgrade2() for both client and server side.
2015-11-07 16:13:06 +09:00
Tatsuhiro Tsujikawa 5e7e479c6c Workaround HTTP upgrade with HEAD request
By default, we check the length of response body matches
content-length.  For HEAD request, this is not necessarily true, so we
sniff request method, and if it is HEAD, make sure that response body
length is 0.  But this does not work for HTTP Upgrade, since
nghttp2_session_upgrade() has no parameter to tell the request method
was HEAD.  This commit disables this response body length validation
for the stream upgraded by HTTP Upgrade.  We will add new version of
nghttp2_session_upgrade with the parameter to pass the request method
information so that we can handle this situation properly.
2015-11-07 10:56:40 +09:00
Tatsuhiro Tsujikawa d9893d014c Add tests 2015-10-11 17:46:23 +09:00
Tatsuhiro Tsujikawa a0e884836e Fix wrong test name 2015-10-11 17:28:40 +09:00
Tatsuhiro Tsujikawa 0cb8c82125 Detect flooding and tear down session 2015-09-30 00:44:08 +09:00
Tatsuhiro Tsujikawa 28fe3e7e89 More warning flags for --enable-werror 2015-09-23 16:49:45 +09:00
Tatsuhiro Tsujikawa 647e30619f Remove nghttp2_pq_increase_key 2015-08-21 23:35:17 +09:00
Tatsuhiro Tsujikawa 059280d1a5 Add stream public API
The intention of this stream API is give server application about
stream dependency information, so that it can utilize it for better
scheduling of stream processing.  We have no plan to add object
oriented API based on stream object.
2015-08-19 23:04:06 +09:00
Tatsuhiro Tsujikawa 5b59e46e2b Rewrite priority handling
We now use priority queue per stream, which contains the stream which
has ready to send a frame, or one of its descendants have a frame to
send.  We maintain invariant that if a stream is queued, then its
ancestors are also queued (except for root).  When we re-schedule
stream after transmission, we re-schedule all ancestors, so that
streams on the other path can get a chance to send.  This is basically
the same mechanism h2o project uses, but there are differences in the
details.
2015-08-17 22:35:50 +09:00
Tatsuhiro Tsujikawa e66bd490a4 Fix crash if response or data is submitted to closing stream 2015-07-31 21:11:16 +09:00
Tatsuhiro Tsujikawa 7f71fed963 Allow multiple in-flight SETTINGS 2015-07-23 00:36:00 +09:00
Tatsuhiro Tsujikawa f3288092e8 Strictly check occurrence of dynamic table size update
RFC 7541 requires that dynamic table size update must occur at the
beginning of the first header block, and is signaled as SETTINGS
acknowledgement.  This commit checks these conditions.  If dynamic
table size update appears other than the beginning of the first header
block, it is treated as error.  If SETTINGS ACK is received, and next
HEADERS header block does not have dynamic table size update, it is
treated as error.
2015-07-22 00:11:23 +09:00
Tatsuhiro Tsujikawa 1945d0f02a Fix assertion failure in nghttp2_stream.c
This is regression introduced in
46b70c1db8.
2015-06-23 23:04:53 +09:00
Tatsuhiro Tsujikawa b5717cd288 Fix bug that data are not consumed for connection in race condition
When we know that stream is closed at time we read DATA frame header,
we use NGHTTP2_IB_IGN_DATA, and consume data for connection if
nghttp2_option_set_no_auto_window_update() is used.  However, if
stream is closed while we are in NGHTTP2_IB_READ_DATA, those bytes are
not consumed for connection, nor notified to application via callback,
so it eventually fills up connection window and connection will
freeze.  This commit fixes this issue by consuming these data for
connection when stream is closed or does not exist.
2015-06-11 23:34:30 +09:00
Tatsuhiro Tsujikawa 0b27f005e0 Merge branch 'master' into v1.0.0
Conflicts:
	src/HttpServer.cc
2015-05-15 23:24:19 +09:00
Tatsuhiro Tsujikawa 252aeb43e1 Add test for GH-232 2015-05-15 01:00:09 +09:00
Tatsuhiro Tsujikawa db4a68454a Merge branch 'master' into v1.0.0
Conflicts:
	lib/includes/nghttp2/nghttp2.h
2015-04-24 00:13:15 +09:00
Tatsuhiro Tsujikawa 514558afc0 Allow NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE from nghttp2_on_begin_headers_callback
Since application most likely allocates the stream object in
nghttp2_on_begin_headers_callback, it is desirable to handle its
failure as stream error.  But previously it only signals success or
fatal error.  Submitting RST_STREAM does not prevent
nghttp2_on_header_callback from being invoked.  This commit improves
this situation by allowing NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE from
nghttp2_on_begin_headers_callback.  If that value is returned, library
submits RST_STREAM with error code INTERNAL_ERROR, and
nghttp2_on_header_callback and nghttp2_on_frame_recv_callback for that
frame are not invoked.  Note that for PUSH_PROMISE frame, the stream
to be reset is promised stream.
2015-04-23 23:43:30 +09:00
Tatsuhiro Tsujikawa d0c27d5229 Send 24 bytes client magic byte string by library
Previously nghttp2_session_send() and nghttp2_session_mem_send() did
not send 24 bytes client magic byte string (MAGIC).  We made
nghttp2_session_recv() and nghttp2_session_mem_recv() process MAGIC by
default, so it is natural to make library send MAGIC as well.  This
commit makes nghttp2_session_send() and nghttp2_session_mem_send()
send MAGIC.  This commit also replace "connection preface" with
"client magic", since we call MAGIC as "connection preface" but it is
just a part of connection preface.  NGHTTP2_CLIENT_CONNECTION_PREFACE
macro was replaced with NGHTTP2_CLIENT_MAGIC.  The already deprecated
NGHTTP2_CLIENT_CONNECTION_HEADER macro was removed permanently.
nghttp2_option_set_no_recv_client_preface() was renamed as
nghttp2_option_set_no_recv_client_magic().  NGHTTP2_ERR_BAD_PREFACE
was renamed as NGHTTP2_ERR_BAD_CLIENT_MAGIC.
2015-04-05 23:15:20 +09:00
Tatsuhiro Tsujikawa 250ea53e4b Deal with 24 bytes client connection preface by default
Since HTTP/2 spec requires for client to send connection preface, it
is reasonable to make this option enabled by default.  It is still a
use case to disable this, so replace this option with
nghttp2_option_set_no_recv_client_preface().
2015-04-05 23:15:20 +09:00
Tatsuhiro Tsujikawa 9eff511c5e Add nghttp2_send_data_callback to send DATA payload without copying
To avoid buffer copy in nghttp2_data_source_read_callback, this commit
introduces NGHTTP2_DATA_FLAG_NO_COPY and nghttp2_send_data_callback.
By using NGHTTP2_DATA_FLAG_NO_COPY in
nghttp2_data_source_read_callback, application can avoid to copy
application data to given buffer.  Instead, application has to
implement nghttp2_send_data_callback to send complete DATA frame by
itself.  We see noticeable performance increase in nghttpd and
tiny-nghttpd using this new feature.  On the other hand, nghttpx does
not show such difference, probably because buffer copy is not
bottleneck.  Using nghttp2_send_data_callback adds complexity, so it
is recommended to measure the performance to see whether this extra
complexity worth it.
2015-04-04 21:23:50 +09:00
Tatsuhiro Tsujikawa 2f2a535113 Add a way to send trailer with nghttp2_submit_request/nghttp2_submit_response
nghttp2_submit_request and nghttp2_submit_response will set
NGHTTP2_FLAG_END_STREAM after all given data is sent (data could be
0).  This means we have no way to send trailers.  In this commit, we
added NGHTTP2_DATA_FLAG_NO_END_STREAM flag.  The application can set
this flag in *data_flags inside nghttp2_data_source_read_callback.  If
NGHTTP2_DATA_FLAG_EOF is set, library automatically set
NGHTTP2_FLAG_END_STREAM.  But if both NGHTTP2_DATA_FLAG_EOF and
NGHTTP2_DATA_FLAG_NO_END_STREAM are set, NGHTTP2_FLAG_END_STREAM will
not set by library.  Then application can use new
nghttp2_submit_trailer() to send trailers.  nghttp2_submit_trailer()
will set NGHTTP2_FLAG_END_STREAM and it is actually thing wrapper of
nghttp2_submit_headers().
2015-03-07 17:09:29 +09:00
Tatsuhiro Tsujikawa 814c7e68e0 Ignore regular headers if it includes illegal characters.
This commit only affects the library behaviour unless
nghttp2_option_set_no_http_messaging() is used.

We like strict validation against header field name and value against
RFC 7230, but we have already so much web sites and libraries in
public internet which do not obey these rules.  Simply just
terminating stream because of this may break web sites and it is too
disruptive.  So we decided that we should be conservative here so
those header fields containing illegal characters are just ignored.
But we are conservative only for regular headers.  We are strict for
pseudo headers since it is new to HTTP/2 and new implementations
should know the rules better.
2015-02-22 23:13:27 +09:00
Tatsuhiro Tsujikawa b157d4ebb2 Validate HTTP semantics by default
Previously we did not check HTTP semantics and it is left out for
application.  Although checking is relatively easy, but they are
scattered and error prone.  We have implemented these checks in our
applications and also feel they are tedious.  To make application
development a bit easier, this commit adds basic HTTP semantics
validation to library code.  We do following checks:

server:

* HEADERS is either request header or trailer header.  Other type of
header is disallowed.

client:

* HEADERS is either zero or more non-final response header or final
  response header or trailer header.  Other type of header is
  disallowed.

For both:

* Check mandatory pseudo header fields.
* Make sure that content-length matches the amount of DATA we
  received.

If validation fails, RST_STREAM of type PROTOCOL_ERROR is issued.
2015-02-20 01:01:10 +09:00
Tatsuhiro Tsujikawa 7d4a6aa179 Add test for submission ordering of HEADERS and its RST_STREAM 2015-02-12 21:28:20 +09:00
Tatsuhiro Tsujikawa eec8870ac1 Fix bug that client may send PROTOCOL_ERROR upon canceled push stream
Previously we treat stream in NGHTTP2_STREAM_RESERVED state specially,
that is we don't increment or decrement streams counts if stream is in
that state.  Because of this, we don't change the stream state to
NGHTTP2_STREAM_CLOSING if stream is in NGHTTP2_STREAM_RESERVED.  But
it turns out that it causes a problem.  If client canceled pushed
stream before push response HEADERS, stream is still in
NGHTTP2_STREAM_RESERVED state.  If push response HEADERS arrived in
this state, library happily accepts it and passed to application.

With this commit, this bug was corrected.  We now change stream state
to NGHTTP2_STREAM_CLOSING even if it was in NGHTTP2_STREAM_RESERVED
state.  We now use NGHTTP2_STREAM_FLAG_PUSH to determine whether we
have to increase/decrase stream count.
2015-02-09 22:23:20 +09:00
Tatsuhiro Tsujikawa b685747643 Add nghttp2_submit_shutdown_notice() to start graceful shutdown
nghttp2_submit_shutdown_notice() is used to notify the client that
graceful shutdown is started.  We expect that after this call, the
server application should send another GOAWAY using
nghttp2_submit_goaway() with appropriate last_stream_id.  In this
commit, we also added nghttp2_session_get_last_proc_stream_id(), which
can be used as last_stream_id parameter.

This commit implements graceful shutdown in nghttpx.  The integration
test for graceful shutdown is also added.
2015-01-22 23:21:58 +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 e8513b3241 Make huffman encoding faster 2014-12-19 23:22:55 +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 21b48d24e4 Remove altsvc 2014-12-07 23:11:54 +09:00