bugfix: initial settings ack for settings lowering stream window size must send window update frame even in manual mode; otherwise the stream can get stuck

FIXME: this broke other test...
This commit is contained in:
Ondřej Koláček 2022-03-11 12:59:17 +01:00
parent 072784c9ee
commit c76aa066e1
4 changed files with 82 additions and 2 deletions

View File

@ -4259,8 +4259,7 @@ static int update_local_initial_window_size_func(void *entry, void *ptr) {
return nghttp2_session_add_rst_stream(arg->session, stream->stream_id,
NGHTTP2_FLOW_CONTROL_ERROR);
}
if (!(arg->session->opt_flags & NGHTTP2_OPTMASK_NO_AUTO_WINDOW_UPDATE) &&
stream->window_update_queued == 0 &&
if (stream->window_update_queued == 0 &&
nghttp2_should_send_window_update(stream->local_window_size,
stream->recv_window_size)) {

View File

@ -196,6 +196,8 @@ int main(void) {
test_nghttp2_submit_settings) ||
!CU_add_test(pSuite, "session_submit_settings_update_local_window_size",
test_nghttp2_submit_settings_update_local_window_size) ||
!CU_add_test(pSuite, "test_nghttp2_submit_settings_update_local_window_size_before_initial_settings_ack",
test_nghttp2_submit_settings_update_local_window_size_before_initial_settings_ack) ||
!CU_add_test(pSuite, "session_submit_settings_multiple_times",
test_nghttp2_submit_settings_multiple_times) ||
!CU_add_test(pSuite, "session_submit_push_promise",

View File

@ -5823,6 +5823,84 @@ void test_nghttp2_submit_settings_update_local_window_size(void) {
nghttp2_frame_settings_free(&ack_frame.settings, mem);
}
void test_nghttp2_submit_settings_update_local_window_size_before_initial_settings_ack(void) {
nghttp2_session *session;
nghttp2_session_callbacks callbacks;
nghttp2_settings_entry iv[4];
nghttp2_stream *stream;
nghttp2_frame ack_frame;
nghttp2_mem *mem;
nghttp2_option *option;
my_user_data ud;
nghttp2_outbound_item *item;
ssize_t rv;
mem = nghttp2_mem_default();
nghttp2_frame_settings_init(&ack_frame.settings, NGHTTP2_FLAG_ACK, NULL, 0);
iv[0].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
iv[0].value = 1024;
uint8_t data[8092];
nghttp2_frame_hd hd;
/* Create DATA frame with length 4KiB */
memset(data, 0, sizeof(data));
hd.length = 4096;
hd.type = NGHTTP2_DATA;
hd.flags = NGHTTP2_FLAG_NONE;
hd.stream_id = 1;
nghttp2_frame_pack_frame_hd(data, &hd);
memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
callbacks.send_callback = null_send_callback;
callbacks.on_data_chunk_recv_callback = on_data_chunk_recv_callback;
callbacks.on_frame_recv_callback = on_frame_recv_callback;
callbacks.on_frame_send_callback = on_frame_send_callback;
/* Without auto-window update */
nghttp2_option_new(&option);
nghttp2_option_set_no_auto_window_update(option, 1);
nghttp2_session_server_new2(&session, &callbacks, &ud, option);
nghttp2_option_del(option);
/* Submit settings which lower the window size */
CU_ASSERT(0 == nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, iv, 1));
CU_ASSERT(0 == nghttp2_session_send(session));
stream = open_recv_stream(session, 1);
ud.data_chunk_recv_cb_called = 0;
ud.frame_recv_cb_called = 0;
rv = nghttp2_session_mem_recv(session, data, NGHTTP2_FRAME_HDLEN + 4000);
CU_ASSERT(NGHTTP2_FRAME_HDLEN + 4000 == rv);
CU_ASSERT(1 == ud.data_chunk_recv_cb_called);
CU_ASSERT(0 == ud.frame_recv_cb_called);
CU_ASSERT(0 == nghttp2_session_consume_connection(session, 4000));
CU_ASSERT(0 == nghttp2_session_consume_stream(session, 1, 4000));
/* Not yet worth it to send NGHTTP2_WINDOW_UPDATE */
CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
/* This causes NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE change to be applied */
CU_ASSERT(0 == nghttp2_session_on_settings_received(session, &ack_frame, 0));
item = nghttp2_session_get_next_ob_item(session);
CU_ASSERT(NGHTTP2_WINDOW_UPDATE == item->frame.hd.type);
CU_ASSERT(1 == item->frame.window_update.hd.stream_id);
CU_ASSERT(0 == nghttp2_session_send(session));
nghttp2_session_del(session);
nghttp2_frame_settings_free(&ack_frame.settings, mem);
}
void test_nghttp2_submit_settings_multiple_times(void) {
nghttp2_session *session;
nghttp2_session_callbacks callbacks;

View File

@ -94,6 +94,7 @@ void test_nghttp2_submit_headers_continuation_extra_large(void);
void test_nghttp2_submit_priority(void);
void test_nghttp2_submit_settings(void);
void test_nghttp2_submit_settings_update_local_window_size(void);
void test_nghttp2_submit_settings_update_local_window_size_before_initial_settings_ack(void);
void test_nghttp2_submit_settings_multiple_times(void);
void test_nghttp2_submit_push_promise(void);
void test_nghttp2_submit_window_update(void);