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,8 +1908,8 @@ static int nghttp2_session_update_initial_window_size
&arg); &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) void *ptr)
{ {
nghttp2_session *session; nghttp2_session *session;
nghttp2_stream *stream; nghttp2_stream *stream;
@ -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 * Disable remote side connection-level flow control and stream-level
* of existing streams. * 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; session->remote_flow_control = 0;
return nghttp2_map_each(&session->streams, 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, 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 niv)
{ {
size_t i; size_t i;
uint8_t old_flow_control =
session->local_settings[NGHTTP2_SETTINGS_FLOW_CONTROL_OPTIONS];
for(i = 0; i < niv; ++i) { for(i = 0; i < niv; ++i) {
assert(iv[i].settings_id > 0 && iv[i].settings_id <= NGHTTP2_SETTINGS_MAX); assert(iv[i].settings_id > 0 && iv[i].settings_id <= NGHTTP2_SETTINGS_MAX);
session->local_settings[iv[i].settings_id] = iv[i].value; 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, 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: case NGHTTP2_SETTINGS_FLOW_CONTROL_OPTIONS:
if(entry->value & 0x1) { if(entry->value & 0x1) {
if(session->remote_settings[entry->settings_id] == 0) { 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) { if(rv != 0) {
return rv; return rv;
} }

View File

@ -165,8 +165,10 @@ int main(int argc, char* argv[])
test_nghttp2_session_defer_data) || test_nghttp2_session_defer_data) ||
!CU_add_test(pSuite, "session_flow_control", !CU_add_test(pSuite, "session_flow_control",
test_nghttp2_session_flow_control) || test_nghttp2_session_flow_control) ||
!CU_add_test(pSuite, "session_flow_control_disable", !CU_add_test(pSuite, "session_flow_control_disable_remote",
test_nghttp2_session_flow_control_disable) || 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", !CU_add_test(pSuite, "session_data_read_temporal_failure",
test_nghttp2_session_data_read_temporal_failure) || test_nghttp2_session_data_read_temporal_failure) ||
!CU_add_test(pSuite, "session_on_request_recv_callback", !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; my_user_data ud;
nghttp2_outbound_item *item; nghttp2_outbound_item *item;
nghttp2_frame *frame; nghttp2_frame *frame;
nghttp2_settings_entry iv[3]; nghttp2_settings_entry iv[4];
iv[0].settings_id = NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS; iv[0].settings_id = NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS;
iv[0].value = 50; 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].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
iv[1].value = 16*1024; iv[1].value = 16*1024;
iv[2].settings_id = NGHTTP2_SETTINGS_FLOW_CONTROL_OPTIONS;
iv[2].value = 1;
/* This is duplicate entry */ /* This is duplicate entry */
iv[2].settings_id = NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS; iv[3].settings_id = NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS;
iv[2].value = 150; iv[3].value = 150;
memset(&callbacks, 0, sizeof(nghttp2_session_callbacks)); memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
callbacks.send_callback = null_send_callback; callbacks.send_callback = null_send_callback;
@ -1788,29 +1791,34 @@ void test_nghttp2_submit_settings(void)
nghttp2_session_server_new(&session, &callbacks, &ud); nghttp2_session_server_new(&session, &callbacks, &ud);
CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT == 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 */ /* Make sure that local settings are not changed */
CU_ASSERT(NGHTTP2_INITIAL_MAX_CONCURRENT_STREAMS == CU_ASSERT(NGHTTP2_INITIAL_MAX_CONCURRENT_STREAMS ==
session->local_settings[NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS]); session->local_settings[NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS]);
CU_ASSERT(NGHTTP2_INITIAL_WINDOW_SIZE == CU_ASSERT(NGHTTP2_INITIAL_WINDOW_SIZE ==
session->local_settings[NGHTTP2_SETTINGS_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 */ /* Now sends without 4th one */
CU_ASSERT(0 == nghttp2_submit_settings(session, iv, 2)); CU_ASSERT(0 == nghttp2_submit_settings(session, iv, 3));
/* Make sure that local settings are changed */ /* Make sure that local settings are changed */
CU_ASSERT(50 == CU_ASSERT(50 ==
session->local_settings[NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS]); session->local_settings[NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS]);
CU_ASSERT(16*1024 == CU_ASSERT(16*1024 ==
session->local_settings[NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE]); 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); item = nghttp2_session_get_next_ob_item(session);
CU_ASSERT(NGHTTP2_SETTINGS == OB_CTRL_TYPE(item)); CU_ASSERT(NGHTTP2_SETTINGS == OB_CTRL_TYPE(item));
frame = item->frame; 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(50 == frame->settings.iv[0].value);
CU_ASSERT(NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS == CU_ASSERT(NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS ==
frame->settings.iv[0].settings_id); frame->settings.iv[0].settings_id);
@ -2433,7 +2441,7 @@ void test_nghttp2_session_flow_control(void)
nghttp2_session_del(session); 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 *session;
nghttp2_session_callbacks callbacks; nghttp2_session_callbacks callbacks;
@ -2487,6 +2495,33 @@ void test_nghttp2_session_flow_control_disable(void)
nghttp2_session_del(session); 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) void test_nghttp2_session_data_read_temporal_failure(void)
{ {
nghttp2_session *session; 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_stop_data_with_rst_stream(void);
void test_nghttp2_session_defer_data(void); void test_nghttp2_session_defer_data(void);
void test_nghttp2_session_flow_control(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_data_read_temporal_failure(void);
void test_nghttp2_session_on_request_recv_callback(void); void test_nghttp2_session_on_request_recv_callback(void);
void test_nghttp2_session_on_stream_close(void); void test_nghttp2_session_on_stream_close(void);