Commit Graph

394 Commits

Author SHA1 Message Date
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 c925c32233 Fix bug that promised stream is not reset on temporal failure from on_header_callback 2015-04-23 23:57:39 +09:00
Tatsuhiro Tsujikawa 514558afc0 Allow NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE from nghttp2_on_begin_headers_callback
Since application most likely allocates the stream object in
nghttp2_on_begin_headers_callback, it is desirable to handle its
failure as stream error.  But previously it only signals success or
fatal error.  Submitting RST_STREAM does not prevent
nghttp2_on_header_callback from being invoked.  This commit improves
this situation by allowing NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE from
nghttp2_on_begin_headers_callback.  If that value is returned, library
submits RST_STREAM with error code INTERNAL_ERROR, and
nghttp2_on_header_callback and nghttp2_on_frame_recv_callback for that
frame are not invoked.  Note that for PUSH_PROMISE frame, the stream
to be reset is promised stream.
2015-04-23 23:43:30 +09:00
Tatsuhiro Tsujikawa 5937b4b6f7 Merge branch 'master' into v1.0.0 2015-04-19 23:13:38 +09:00
Tatsuhiro Tsujikawa 85671a69bf Update doc 2015-04-18 16:49:34 +09:00
Tatsuhiro Tsujikawa 1a12a9b397 Penalize cycle according to effective weight 2015-04-17 21:17:22 +09:00
Tatsuhiro Tsujikawa 7323d4c639 Fix bug that nghttp2_session_set_next_stream_id accepts invalid stream_id 2015-04-17 00:12:47 +09:00
Tatsuhiro Tsujikawa e6ad2eb14f We can assert this 2015-04-16 22:58:25 +09:00
Tatsuhiro Tsujikawa dc335b9025 Improve weight handling a bit 2015-04-16 21:38:13 +09:00
Tatsuhiro Tsujikawa 93afbc7d2f Rewrite static header table handling
We rewrite static header table handling in nghttp2_hd.c.  We expand
nghttp2_token to include all static header table entries, and fully
use them in header compression and decompression.  The lookup function
is now located in nghttp2_hd.c.  We add new nghttp2_hd_inflate_hd2()
function to export token value for header name, then we pass it to
nghttp2_http_on_header function, so that we don't have to look up
token there.  We carefully set enum value of token to static table
index, so looking up static table is now O(1), assuming we have token.
2015-04-15 23:58:56 +09:00
Tatsuhiro Tsujikawa cf0576253f Merge branch 'master' into v1.0.0 2015-04-08 18:10:04 +09:00
Tatsuhiro Tsujikawa d56ecd7414 Add nghttp2_session_consume_{connection,stream} to consume bytes independently
The existing nghttp2_session_consume() affects both connection and
stream level flow control windows.  The new functions only affects
either connection or stream.  There is some interesting use cases.
For example, we may want to pause a stream by not sending
WINDOW_UPDATE, meanwhile we want to continue to process other streams.
In this case, we use nghttp2_session_consume_connection() to tell
library that only connection level window is recovered.  The relevant
discussion: https://code.google.com/p/chromium/issues/detail?id=473259
2015-04-07 00:14:18 +09:00
Tatsuhiro Tsujikawa 87602e5d72 Use NGHTTP2_PROTOCOL_ERROR for NGHTTP2_ERR_HTTP_{HEADER,MESSAGING} 2015-04-05 23:15:20 +09:00
Tatsuhiro Tsujikawa d0c27d5229 Send 24 bytes client magic byte string by library
Previously nghttp2_session_send() and nghttp2_session_mem_send() did
not send 24 bytes client magic byte string (MAGIC).  We made
nghttp2_session_recv() and nghttp2_session_mem_recv() process MAGIC by
default, so it is natural to make library send MAGIC as well.  This
commit makes nghttp2_session_send() and nghttp2_session_mem_send()
send MAGIC.  This commit also replace "connection preface" with
"client magic", since we call MAGIC as "connection preface" but it is
just a part of connection preface.  NGHTTP2_CLIENT_CONNECTION_PREFACE
macro was replaced with NGHTTP2_CLIENT_MAGIC.  The already deprecated
NGHTTP2_CLIENT_CONNECTION_HEADER macro was removed permanently.
nghttp2_option_set_no_recv_client_preface() was renamed as
nghttp2_option_set_no_recv_client_magic().  NGHTTP2_ERR_BAD_PREFACE
was renamed as NGHTTP2_ERR_BAD_CLIENT_MAGIC.
2015-04-05 23:15:20 +09:00
Tatsuhiro Tsujikawa ebf214c8fc nghttp2_on_invalid_frame_recv_callback should have lib_error_code as param
nghttp2_error_code is HTTP/2 standard error code and is too coarse to
know what's going on.
2015-04-05 23:15:20 +09:00
Tatsuhiro Tsujikawa 250ea53e4b Deal with 24 bytes client connection preface by default
Since HTTP/2 spec requires for client to send connection preface, it
is reasonable to make this option enabled by default.  It is still a
use case to disable this, so replace this option with
nghttp2_option_set_no_recv_client_preface().
2015-04-05 23:15:20 +09:00
Tatsuhiro Tsujikawa cc03a12b75 Don't call nghttp2_send_data_callback if stream has already closed
This is more inline with other callback function invocations where if
stream was closed, they are not invoked.
2015-04-05 12:40:21 +09:00
Tatsuhiro Tsujikawa 9eff511c5e Add nghttp2_send_data_callback to send DATA payload without copying
To avoid buffer copy in nghttp2_data_source_read_callback, this commit
introduces NGHTTP2_DATA_FLAG_NO_COPY and nghttp2_send_data_callback.
By using NGHTTP2_DATA_FLAG_NO_COPY in
nghttp2_data_source_read_callback, application can avoid to copy
application data to given buffer.  Instead, application has to
implement nghttp2_send_data_callback to send complete DATA frame by
itself.  We see noticeable performance increase in nghttpd and
tiny-nghttpd using this new feature.  On the other hand, nghttpx does
not show such difference, probably because buffer copy is not
bottleneck.  Using nghttp2_send_data_callback adds complexity, so it
is recommended to measure the performance to see whether this extra
complexity worth it.
2015-04-04 21:23:50 +09:00
Tatsuhiro Tsujikawa 7ae6e6b4c5 Exclude num_idle_streams when counting active stream 2015-03-29 00:59:15 +09:00
Tatsuhiro Tsujikawa 3fd5d0af79 Don't consider num_active_streams in nghttp2_session_want_write() 2015-03-28 19:00:24 +09:00
Tatsuhiro Tsujikawa 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 505a300d93 Refuse PUSH_PROMISE while unacked local ENABLE_PUSH is 0
After we sent SETTINGS including ENABLE_PUSH = 0, peer may already
issue PUSH_PROMISE before receiving our SETTINGS and react it to
SETTINGS ACK.  Previously we accept this PUSH_PROMISE.  In this
commit, we check the pending ENABLE_PUSH value and if it means
disabling push, we refuse PUSH_PROMISE with RST_STREAM of error
REFUSED_STREAM.
2015-03-07 16:17:40 +09:00
Tatsuhiro Tsujikawa 05b8901d69 Call on_invalid_frame_recv_callback on bad HTTP messaging 2015-02-26 22:59:07 +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 e45c523dc7 Add nghttp2_option_set_no_http_messaging() API function
This API function with nonzero |val| parameter disables HTTP Messaging
validation in nghttp2 library, so that application can use nghttp2
library for non-HTTP use.
2015-02-20 23:26:56 +09:00
Tatsuhiro Tsujikawa b3846d6c27 Rename NGHTTP2_OPTMASK_NO_HTTP_SEMANTICS with NGHTTP2_OPTMASK_NO_HTTP_MESSAGING 2015-02-20 23:07:48 +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 9c30211da9 Ignore all incoming bytes when first SETTINGS is not received 2015-02-15 01:20:10 +09:00
Tatsuhiro Tsujikawa 442572c1f4 Handle situation where request HEADERS in queue is reset by RST_STREAM
Previously we did not handle the situation where RST_STREAM is
submitted against a stream while requet HEADERS which opens that
stream is still in queue.  Due to max concurrent streams limit,
RST_STREAM is sent first, and then request HEADERS, which effectively
voids RST_STREAM.

In this commit, we checks RST_STREAM against currently pending request
HEADERS in queue and if stream ID matches, we mark that HEADERS as
canceled and RST_STREAM is not sent in this case.  The library will
call on_frame_not_sent_callback for the canceled HEADERS with error
code from RST_STREAM.
2015-02-13 23:48:16 +09:00
Tatsuhiro Tsujikawa 0bdacd3e77 Code cleanup 2015-02-12 23:02:17 +09:00
Tatsuhiro Tsujikawa 57a50f981b Refactor session_prep_frame to eliminate framerv 2015-02-12 22:58:43 +09:00
Tatsuhiro Tsujikawa eb94603c51 Make nghttp2_session_get_stream_user_data work inside nghttp2_on_frame_not_send_callback 2015-02-12 22:41:57 +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 f93a2b71a1 Treat first SETTINGS bearing ACK as connection error 2015-02-06 01:22:41 +09:00
Tatsuhiro Tsujikawa 208abd8cc5 Fix debug output 2015-02-06 01:18:23 +09:00
Tatsuhiro Tsujikawa e2bbc94616 Use NGHTTP2_PROTOCOL_ERROR when peer exceeds MAX_CONCURRENT_STREAMS limit
Kudos to h2spec to find this details
2015-02-02 00:14:17 +09:00
Tatsuhiro Tsujikawa bbc34904c1 Workaround stream treated inferior when it hits connection window limit 2015-01-31 15:49:10 +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 b0078a2379 Suppress to send frames other than GOAWAY if NGHTTP2_GOAWAY_TERM_ON_SEND is set
This change makes sure that GOAWAY which terminates session is
immediately sent without blocked by other frames.
NGHTTP2_ERR_SESSION_CLOSING library error code was added to indicate
this situation to callback.
2015-01-15 22:32:29 +09:00
Tatsuhiro Tsujikawa 50109bb307 Use NGHTTP2_STREAM_CLOSED when DATA arrived to stream which is not open 2015-01-14 23:31:21 +09:00
Tatsuhiro Tsujikawa b313068cab Fix compile error with --enable-werror 2015-01-08 01:33: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 c3215af5f6 Fix missing error handling for session_after_frame_sent1 2015-01-02 14:49:36 +09: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 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 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 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 f705b2aec4 Use NGHTTP2_PROTOCOL_ERROR for WINDOW_UPDATE with increments == 0 2014-12-10 01:02:30 +09:00
Tatsuhiro Tsujikawa e0a2353c56 Fix crash with custom memory allocator 2014-12-08 21:22:20 +09:00