Merge pull request #1184 from PiotrSikora/max_streams

Fix handling of SETTINGS_MAX_CONCURRENT_STREAMS.
This commit is contained in:
Tatsuhiro Tsujikawa 2018-06-05 22:02:02 +09:00 committed by GitHub
commit 159c5e446a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 37 additions and 11 deletions

View File

@ -2478,15 +2478,15 @@ nghttp2_option_set_no_auto_window_update(nghttp2_option *option, int val);
*
* This option sets the SETTINGS_MAX_CONCURRENT_STREAMS value of
* remote endpoint as if it is received in SETTINGS frame. Without
* specifying this option, before the local endpoint receives
* SETTINGS_MAX_CONCURRENT_STREAMS in SETTINGS frame from remote
* endpoint, SETTINGS_MAX_CONCURRENT_STREAMS is unlimited. This may
* cause problem if local endpoint submits lots of requests initially
* and sending them at once to the remote peer may lead to the
* rejection of some requests. Specifying this option to the sensible
* value, say 100, may avoid this kind of issue. This value will be
* overwritten if the local endpoint receives
* SETTINGS_MAX_CONCURRENT_STREAMS from the remote endpoint.
* specifying this option, 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 value will be overwritten when the local endpoint receives
* initial SETTINGS frame from the remote endpoint, either to the
* value advertised in SETTINGS_MAX_CONCURRENT_STREAMS or to the
* default value (unlimited) if none was advertised.
*/
NGHTTP2_EXTERN void
nghttp2_option_set_peer_max_concurrent_streams(nghttp2_option *option,

View File

@ -4410,6 +4410,12 @@ int nghttp2_session_on_settings_received(nghttp2_session *session,
return session_call_on_frame_received(session, frame);
}
if (!session->remote_settings_received) {
session->remote_settings.max_concurrent_streams =
NGHTTP2_DEFAULT_MAX_CONCURRENT_STREAMS;
session->remote_settings_received = 1;
}
for (i = 0; i < frame->settings.niv; ++i) {
nghttp2_settings_entry *entry = &frame->settings.iv[i];

View File

@ -303,8 +303,10 @@ struct nghttp2_session {
increased/decreased by submitting WINDOW_UPDATE. See
nghttp2_submit_window_update(). */
int32_t local_window_size;
/* Settings value received from the remote endpoint. We just use ID
as index. The index = 0 is unused. */
/* This flag is used to indicate that the local endpoint received initial
SETTINGS frame from the remote endpoint. */
uint8_t remote_settings_received;
/* Settings value received from the remote endpoint. */
nghttp2_settings_storage remote_settings;
/* Settings value of the local endpoint. */
nghttp2_settings_storage local_settings;

View File

@ -3294,6 +3294,7 @@ void test_nghttp2_session_on_settings_received(void) {
nghttp2_outbound_item *item;
nghttp2_nv nv = MAKE_NV(":authority", "example.org");
nghttp2_mem *mem;
nghttp2_option *option;
mem = nghttp2_mem_default();
@ -3406,6 +3407,23 @@ void test_nghttp2_session_on_settings_received(void) {
nghttp2_frame_settings_free(&frame.settings, mem);
nghttp2_session_del(session);
/* Check that remote SETTINGS_MAX_CONCURRENT_STREAMS is set to a value set by
nghttp2_option_set_peer_max_concurrent_streams() and reset to the default
value (unlimited) after receiving initial SETTINGS frame from the peer. */
nghttp2_option_new(&option);
nghttp2_option_set_peer_max_concurrent_streams(option, 1000);
nghttp2_session_client_new2(&session, &callbacks, NULL, option);
CU_ASSERT(1000 == session->remote_settings.max_concurrent_streams);
nghttp2_frame_settings_init(&frame.settings, NGHTTP2_FLAG_NONE, NULL, 0);
CU_ASSERT(0 == nghttp2_session_on_settings_received(session, &frame, 0));
CU_ASSERT(NGHTTP2_DEFAULT_MAX_CONCURRENT_STREAMS ==
session->remote_settings.max_concurrent_streams);
nghttp2_frame_settings_free(&frame.settings, mem);
nghttp2_session_del(session);
nghttp2_option_del(option);
/* Check too large SETTINGS_MAX_FRAME_SIZE */
nghttp2_session_server_new(&session, &callbacks, NULL);