Disable local flow control on FLOW_CONTROL_OPTIONS = 1

This commit is contained in:
Tatsuhiro Tsujikawa 2013-07-28 19:05:51 +09:00
parent 49519a06b3
commit 8033152e80
4 changed files with 87 additions and 18 deletions

View File

@ -1908,7 +1908,7 @@ static int nghttp2_session_update_initial_window_size
&arg);
}
static int nghttp2_disable_flow_control_func(nghttp2_map_entry *entry,
static int nghttp2_disable_remote_flow_control_func(nghttp2_map_entry *entry,
void *ptr)
{
nghttp2_session *session;
@ -1934,14 +1934,38 @@ static int nghttp2_disable_flow_control_func(nghttp2_map_entry *entry,
}
/*
* Disable connection-level flow control and stream-level flow control
* of existing streams.
* Disable remote side connection-level flow control and stream-level
* flow control of existing streams.
*/
static int nghttp2_session_disable_flow_control(nghttp2_session *session)
static int nghttp2_session_disable_remote_flow_control
(nghttp2_session *session)
{
session->remote_flow_control = 0;
return nghttp2_map_each(&session->streams,
nghttp2_disable_flow_control_func, session);
nghttp2_disable_remote_flow_control_func, session);
}
static int nghttp2_disable_local_flow_control_func(nghttp2_map_entry *entry,
void *ptr)
{
nghttp2_stream *stream;
stream = (nghttp2_stream*)entry;
stream->local_flow_control = 0;
return 0;
}
/*
* Disable stream-level flow control in local side of existing
* streams.
*/
static void nghttp2_session_disable_local_flow_control
(nghttp2_session *session)
{
int rv;
session->local_flow_control = 0;
rv = nghttp2_map_each(&session->streams,
nghttp2_disable_local_flow_control_func, NULL);
assert(rv == 0);
}
void nghttp2_session_update_local_settings(nghttp2_session *session,
@ -1949,10 +1973,17 @@ void nghttp2_session_update_local_settings(nghttp2_session *session,
size_t niv)
{
size_t i;
uint8_t old_flow_control =
session->local_settings[NGHTTP2_SETTINGS_FLOW_CONTROL_OPTIONS];
for(i = 0; i < niv; ++i) {
assert(iv[i].settings_id > 0 && iv[i].settings_id <= NGHTTP2_SETTINGS_MAX);
session->local_settings[iv[i].settings_id] = iv[i].value;
}
if(old_flow_control == 0 &&
session->local_settings[NGHTTP2_SETTINGS_FLOW_CONTROL_OPTIONS]) {
nghttp2_session_disable_local_flow_control(session);
}
}
int nghttp2_session_on_settings_received(nghttp2_session *session,
@ -1993,7 +2024,7 @@ int nghttp2_session_on_settings_received(nghttp2_session *session,
case NGHTTP2_SETTINGS_FLOW_CONTROL_OPTIONS:
if(entry->value & 0x1) {
if(session->remote_settings[entry->settings_id] == 0) {
rv = nghttp2_session_disable_flow_control(session);
rv = nghttp2_session_disable_remote_flow_control(session);
if(rv != 0) {
return rv;
}

View File

@ -165,8 +165,10 @@ int main(int argc, char* argv[])
test_nghttp2_session_defer_data) ||
!CU_add_test(pSuite, "session_flow_control",
test_nghttp2_session_flow_control) ||
!CU_add_test(pSuite, "session_flow_control_disable",
test_nghttp2_session_flow_control_disable) ||
!CU_add_test(pSuite, "session_flow_control_disable_remote",
test_nghttp2_session_flow_control_disable_remote) ||
!CU_add_test(pSuite, "session_flow_control_disable_local",
test_nghttp2_session_flow_control_disable_local) ||
!CU_add_test(pSuite, "session_data_read_temporal_failure",
test_nghttp2_session_data_read_temporal_failure) ||
!CU_add_test(pSuite, "session_on_request_recv_callback",

View File

@ -1770,7 +1770,7 @@ void test_nghttp2_submit_settings(void)
my_user_data ud;
nghttp2_outbound_item *item;
nghttp2_frame *frame;
nghttp2_settings_entry iv[3];
nghttp2_settings_entry iv[4];
iv[0].settings_id = NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS;
iv[0].value = 50;
@ -1778,9 +1778,12 @@ void test_nghttp2_submit_settings(void)
iv[1].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
iv[1].value = 16*1024;
iv[2].settings_id = NGHTTP2_SETTINGS_FLOW_CONTROL_OPTIONS;
iv[2].value = 1;
/* This is duplicate entry */
iv[2].settings_id = NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS;
iv[2].value = 150;
iv[3].settings_id = NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS;
iv[3].value = 150;
memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
callbacks.send_callback = null_send_callback;
@ -1788,29 +1791,34 @@ void test_nghttp2_submit_settings(void)
nghttp2_session_server_new(&session, &callbacks, &ud);
CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT ==
nghttp2_submit_settings(session, iv, 3));
nghttp2_submit_settings(session, iv, 4));
/* Make sure that local settings are not changed */
CU_ASSERT(NGHTTP2_INITIAL_MAX_CONCURRENT_STREAMS ==
session->local_settings[NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS]);
CU_ASSERT(NGHTTP2_INITIAL_WINDOW_SIZE ==
session->local_settings[NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE]);
CU_ASSERT(0 ==
session->local_settings[NGHTTP2_SETTINGS_FLOW_CONTROL_OPTIONS]);
/* Now sends without 3rd one */
CU_ASSERT(0 == nghttp2_submit_settings(session, iv, 2));
/* Now sends without 4th one */
CU_ASSERT(0 == nghttp2_submit_settings(session, iv, 3));
/* Make sure that local settings are changed */
CU_ASSERT(50 ==
session->local_settings[NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS]);
CU_ASSERT(16*1024 ==
session->local_settings[NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE]);
CU_ASSERT(1 ==
session->local_settings[NGHTTP2_SETTINGS_FLOW_CONTROL_OPTIONS]);
CU_ASSERT(0 == session->local_flow_control);
item = nghttp2_session_get_next_ob_item(session);
CU_ASSERT(NGHTTP2_SETTINGS == OB_CTRL_TYPE(item));
frame = item->frame;
CU_ASSERT(2 == frame->settings.niv);
CU_ASSERT(3 == frame->settings.niv);
CU_ASSERT(50 == frame->settings.iv[0].value);
CU_ASSERT(NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS ==
frame->settings.iv[0].settings_id);
@ -2433,7 +2441,7 @@ void test_nghttp2_session_flow_control(void)
nghttp2_session_del(session);
}
void test_nghttp2_session_flow_control_disable(void)
void test_nghttp2_session_flow_control_disable_remote(void)
{
nghttp2_session *session;
nghttp2_session_callbacks callbacks;
@ -2487,6 +2495,33 @@ void test_nghttp2_session_flow_control_disable(void)
nghttp2_session_del(session);
}
void test_nghttp2_session_flow_control_disable_local(void)
{
nghttp2_session *session;
nghttp2_session_callbacks callbacks;
nghttp2_stream *stream;
nghttp2_settings_entry iv[1];
memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
callbacks.send_callback = null_send_callback;
nghttp2_session_client_new(&session, &callbacks, NULL);
stream = nghttp2_session_open_stream(session, 1, NGHTTP2_FLAG_NONE,
NGHTTP2_PRI_DEFAULT,
NGHTTP2_STREAM_OPENING, NULL);
iv[0].settings_id = NGHTTP2_SETTINGS_FLOW_CONTROL_OPTIONS;
iv[0].value = 1;
CU_ASSERT(0 == nghttp2_submit_settings(session, iv,
sizeof(iv)/sizeof(iv[0])));
CU_ASSERT(0 == stream->local_flow_control);
CU_ASSERT(0 == session->local_flow_control);
nghttp2_session_del(session);
}
void test_nghttp2_session_data_read_temporal_failure(void)
{
nghttp2_session *session;

View File

@ -73,7 +73,8 @@ void test_nghttp2_session_stream_close_on_headers_push(void);
void test_nghttp2_session_stop_data_with_rst_stream(void);
void test_nghttp2_session_defer_data(void);
void test_nghttp2_session_flow_control(void);
void test_nghttp2_session_flow_control_disable(void);
void test_nghttp2_session_flow_control_disable_remote(void);
void test_nghttp2_session_flow_control_disable_local(void);
void test_nghttp2_session_data_read_temporal_failure(void);
void test_nghttp2_session_on_request_recv_callback(void);
void test_nghttp2_session_on_stream_close(void);