Add nghttp2_option_set_server_fallback_rfc7540_priorities. If it is
set to nonzero, and server submits SETTINGS_NO_RFC7540_PRIORITIES = 1,
but it does not receive SETTINGS_NO_RFC7540_PRIORITIES from client,
server falls back to RFC 7540 priorities. Only minimal set of
features are enabled in this fallback case.
This commit adds PRIORITY_UPDATE frame support. Applying incoming
PRIORITY_UPDATE frame to server push stream is not implemented.
Client can send PRIORITY_UPDATE frame by calling
nghttp2_submit_priority_update.
Server opts to receive PRIORITY_UPDATE frame by the call
nghttp2_option_set_builtin_recv_extension_type(option,
NGHTTP2_PRIORITY_UPDATE), and passing the option to
nghttp2_session_server_new2 or nghttp2_session_server_new3.
This commit implements RFC 9218 extensible prioritization scheme. It
is enabled when a local endpoint submits
SETTINGS_NO_RFC7540_PRIORITIES = 1. This commit only handles priority
signal in HTTP request header field. Priority header field in
PUSH_PROMISE is not supported.
HTTP messaging must be enabled to take advantage of this
prioritization scheme because HTTP fields are not parsed if HTTP
messaging is disabled.
Fix the bug that causes a stream to stall when a receiver, which
enables nghttp2_option_set_no_auto_window_update() option on, sends
SETTINGS_INITIAL_WINDOW_SIZE with the value that is less than or equal
to the amount of data received. Previously, in this particular case,
when SETTINGS is acknowledged by the sender, the receiver does not try
to send WINDOW_UPDATE frame. The sender is unable to send more data
because its stream-level window size is smaller than or equal to the
amount of data it has sent.
When applying new header table size acknowledged with SETTINGS ACK by
an encoder, change the header table size on a decoder only when it
strictly lowers the current maximum table size set by Dynamic Table
Size Update from the encoder or the default size 4096 if no Dynamic
Table Size Update is received.
Previously, the header table size on a decoder is always changed. If
a maximum size in SETTINGS are increased (e.g., 4096 -> 8192), and
then decreased to the previous value, the decoder incorrectly requires
Dynamic Table Size Update from an encoder.
Previously, if automatic window update is enabled (which is default),
after window size is set to 0 by
nghttp2_session_set_local_window_size, once the receiving window is
exhausted, even after window size is increased by
nghttp2_session_set_local_window_size, no more data cannot be
received. This is because nghttp2_session_set_local_window_size does
not submit WINDOW_UPDATE. It is only triggered when new data arrives
but since window is filled up, no more data cannot be received, thus
dead lock happens.
This commit fixes this issue. nghttp2_session_set_local_window_size
submits WINDOW_UPDATE if necessary.
https://github.com/curl/curl/issues/4939
Add the currently-unused `test_nghttp2_session_create_idle_stream()`
function to the test suite definition.
Modify the test in two places to make it pass:
* Use stream ID=10 as the priority stream ID to test automatic creation
of streams for priority specs. The code below checks against stream
ID=10 so I assume this was a typo in the test.
* Set the `last_sent_stream_id` instead of the `next_stream_id` to test
that idle streams cannot be created with smaller numbers than the
most-recently-seen stream ID. Looking at the validation path in
`session_detect_idle_stream()`, I think this was another test typo.
This commit fixes the bug that stream is closed with wrong error code
(0). This happens when STREAM or DATA frame with END_STREAM flag set
is received and it violates HTTP messaging rule (i.e., content-length
does not match) and the other side of stream has been closed. In this
case, nghttp2_on_stream_close_callback should be called with nonzero
error code, but previously it is called with 0 (NO_ERROR).
The maximum number of outgoing concurrent streams is initially
limited to 100 to avoid issues when the local endpoint submits
lots of requests before receiving initial SETTINGS frame from
the remote endpoint, since sending them at once to the remote
endpoint could lead to rejection of some of the requests.
This initial limit is overwritten with the value advertised in
SETTINGS_MAX_CONCURRENT_STREAMS setting by the remote endpoint,
but previously, it wasn't lifted if the remote endpoint didn't
advertise that setting (implying no limits), in which case the
limit of 100 was retained, even though it was never advertised
by the remote endpoint.
Signed-off-by: Piotr Sikora <piotrsikora@google.com>
Previously, the incoming invalid regular header field was ignored by
default. With this commit, they are now treated as stream error, and
the stream is reset by default. The error code used is now
PROTOCOL_ERROR, instead of INTERNAL_ERROR.
nghttp2_option_no_closed_streams controls whether closed streams are
retained or not. If nonzero is passed to that function's parameter
val, a session does not retain closed streams. It may hurt the shape
of priority tree, but can save memory.
Revert part of 16c46114dc to fix race
condition that incoming stream after sending GOAWAY causes connection
error. The strict stream handling introduced in the above commit does
not handle several cases well (e.g., GOAWAY race, and refusing streams
because of concurrency limit).
2 APIs are added. nghttp2_session_get_local_window_size() returns the
amount of data that the remote endpoint can send without receiving
connection level WINDOW_UPDATE.
nghttp2_session_get_stream_local_window_size() returns the amount of
data that the remote endpoint can send without receiving stream level
WINDOW_UPDATE.
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.
https://tools.ietf.org/html/rfc7540#section-5.3.3 explains how to
transform dependency tree to avoid circular dependency. Previously,
we wrongly always moved the dependent stream under the root stream.
The correct destination is the parent stream of the stream to
reprioritize. This commit fixes this bug.
nghttp2_on_invalid_header_callback is similar to
nghttp2_on_header_callback, but the former is only called when the
invalid header field is received which is silently ignored when the
callback is not set. With this callback, application inspects the
incoming invalid field, and it also can reset stream from this
callback by returning NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE, or using
nghttp2_submit_rst_stream() directly with the error code of choice.
We also added nghttp2_on_invalid_header_callback2, which uses
reference counted header fields.