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.
after a call to nghttp2_session_mem_send_internal() which should
set it, however in nghttp2_session_mem_send_internal() it is
possible to return before setting the pointer.
This change initializes the variable to NULL where delcared and
sets the variable in nghttp2_session_mem_send_internal() to
NULL before possibly returning rather than after.
both options are not necessary but are both ideal practice
This option prevents the nghttp2 library from sending PING frame with
ACK flag set in the reply to incoming PING frame. To allow the
application to send PING with ACK flag set, nghttp2_submit_ping() now
recognizes NGHTTP2_FLAG_PING in its flags parameter.
Previously, we use session->next_stream_id to detect that given stream
ID was idle or not. But this was suboptimal, since it was updated
when stream ID was assigned, and it did not necessarily mean that it
actually has been sent to the peer. Now we introduced
session->sent_stream_id, which only updated when HEADERS/PUSH_PROMISE
has sent. Using sent_stream_id instead of next_stream_id tightens
idle stream detection, and misbehaved peer which sends frame with
stream ID that has not been generated.
This commit also overhauls test code which involves opening streams.
Now we have some wrapper functions for nghttp2_session_open_stream()
which also take care of updating next_stream_id and
last_recv_stream_id. They are crucial for some tests.
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.
Previously we scheduled the transmission of response HEADERS using
priority tree in the belief that it allows more better utilization of
bandwidth for prioritized streams. But to reduce the overhead of
reconstruction of priority queue when connection level flow control
window is depleted, we just don't check priority tree in this case.
This means that response HEADERS frames are not sent even though they
are not flow controlled. This could waste bandwidth. To improve this
situation, we stop scheduling response HEADERS with priority tree for
now. Now they are just sent in the order they submitted. The
response body DATA continued to be scheduled with priority tree as
before.
return session_inflate_handle_invalid_stream(...) case is for streams
for INITIAL state, but this is rare case. In general, we'd like to
reduce RST_STREAM transmission, and it is suffice to ignore this frame
for now.
Previously, we only updated stream's weight field when only weight was
changed by PRIORITY frame. If stream is queued, it would be better to
actually reschedule it based on new weight. This could be especially
useful if weight is increased.
Previously, stream object for pushed resource was not created during
nghttp2_submit_push_promise(). It was created just before
nghttp2_before_frame_send_callback was called for that PUSH_PROMISE
frame. This means that application could not call
nghttp2_submit_response for the pushed resource before
nghttp2_before_frame_send_callback was called. This could be solved
by callback chaining, but for web server with back pressure from
backend stream, it is a bit unnecessarily hard to use.
This commit changes nghttp2_submit_push_promise() behaviour so that
stream object is created during that call. It makes application call
nghttp2_submit_response right after successful
nghttp2_submit_push_promise call.
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.
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.
The added API is nghttp2_session_change_stream_priority(). This
provides the same functionality to re-prioritize stream when PRIORITY
frame. is received, but we do it without PRIORITY frame. This could
be useful for server to change pushed stream's priority silently.
It has no usecase at the moment. It is most likely that applications
know the flags when it submitted extension frame, no need to modify it
later. Possibly feature bloat.
For clients, CANCEL is more appropriate for both incoming/outgoing
streams. For servers, CANCEL is appropriate for its pushed stream
(outgoing), but REFUSED_STREAM is more appropriate for incoming
stream.
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.
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.
This function is useful for the client application to know that there
is a chance that request can be sent. If this function returns 0,
there is zero chance to make a request.
This commit also set error_code passed to
nghttp2_on_stream_close_callback to NGHTTP2_REFUSED_STREAM if request
is not sent.
Application can utilize this framework to send/receive user defined
extension frames. These frames are expected not to change existing
protocol behaviour.
If application returns NGHTTP2_ERR_PAUSE from send_data_callback, it
means application processed all data, but wants to make
nghttp2_session_mem_send or nghttp2_session_send return immediately.
This is useful if application writes to fixed sized buffers, and there
is no room to write more data.
This change adds new return error code from nghttp2_session_mem_recv
and nghttp2_session_recv functions, namely NGHTTP2_ERR_FLOODED. It is
fatal error, and is returned when flooding was detected.
RFC 7540 does not enforce any limit on the number of incoming reserved
streams (in RFC 7540 terms, streams in reserved (remote) state). This
only affects client side, since only server can push streams.
Malicious server can push arbitrary number of streams, and make
client's memory exhausted. The new option,
nghttp2_set_max_reserved_remote_streams, can set the maximum number of
such incoming streams to avoid possible memory exhaustion. If this
option is set, and pushed streams are automatically closed on
reception, without calling user provided callback, if they exceed the
given limit. The default value is 200. If session is configured as
server side, this option has no effect. Server can control the number
of streams to push.
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.
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.