Fix PAD_HIGH and PAD_LOW are not counted in flow control
This commit is contained in:
parent
cd3eae3dd2
commit
7822bbd7e8
|
@ -3204,7 +3204,8 @@ static int adjust_recv_window_size(int32_t *recv_window_size_ptr,
|
|||
static int nghttp2_session_update_recv_stream_window_size
|
||||
(nghttp2_session *session,
|
||||
nghttp2_stream *stream,
|
||||
int32_t delta_size)
|
||||
int32_t delta_size,
|
||||
int send_window_update)
|
||||
{
|
||||
int rv;
|
||||
rv = adjust_recv_window_size(&stream->recv_window_size, delta_size,
|
||||
|
@ -3213,7 +3214,10 @@ static int nghttp2_session_update_recv_stream_window_size
|
|||
return nghttp2_session_add_rst_stream(session, stream->stream_id,
|
||||
NGHTTP2_FLOW_CONTROL_ERROR);
|
||||
}
|
||||
if(!(session->opt_flags & NGHTTP2_OPTMASK_NO_AUTO_STREAM_WINDOW_UPDATE)) {
|
||||
/* We don't have to send WINDOW_UPDATE if the data received is the
|
||||
last chunk in the incoming stream. */
|
||||
if(send_window_update &&
|
||||
!(session->opt_flags & NGHTTP2_OPTMASK_NO_AUTO_STREAM_WINDOW_UPDATE)) {
|
||||
/* We have to use local_settings here because it is the constraint
|
||||
the remote endpoint should honor. */
|
||||
if(nghttp2_should_send_window_update(stream->local_window_size,
|
||||
|
@ -3478,6 +3482,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session,
|
|||
int rv;
|
||||
int busy = 0;
|
||||
nghttp2_frame_hd cont_hd;
|
||||
nghttp2_stream *stream;
|
||||
|
||||
for(;;) {
|
||||
switch(iframe->state) {
|
||||
|
@ -3657,6 +3662,23 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session,
|
|||
}
|
||||
iframe->frame.data.padlen = rv;
|
||||
iframe->state = NGHTTP2_IB_READ_DATA;
|
||||
/* PAD_HIGH and PAD_LOW are subject to flow control */
|
||||
rv = nghttp2_session_update_recv_connection_window_size
|
||||
(session, iframe->buflen);
|
||||
if(nghttp2_is_fatal(rv)) {
|
||||
return rv;
|
||||
}
|
||||
stream = nghttp2_session_get_stream(session,
|
||||
iframe->frame.hd.stream_id);
|
||||
if(stream) {
|
||||
rv = nghttp2_session_update_recv_stream_window_size
|
||||
(session, stream, iframe->buflen,
|
||||
iframe->payloadleft ||
|
||||
(iframe->frame.hd.flags & NGHTTP2_FLAG_END_STREAM) == 0);
|
||||
if(nghttp2_is_fatal(rv)) {
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case NGHTTP2_HEADERS:
|
||||
if(iframe->padlen == 0 &&
|
||||
|
@ -4037,19 +4059,17 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session,
|
|||
if(nghttp2_is_fatal(rv)) {
|
||||
return rv;
|
||||
}
|
||||
if(iframe->payloadleft ||
|
||||
(iframe->frame.hd.flags & NGHTTP2_FLAG_END_STREAM) == 0) {
|
||||
nghttp2_stream *stream;
|
||||
stream = nghttp2_session_get_stream(session,
|
||||
iframe->frame.hd.stream_id);
|
||||
if(stream) {
|
||||
rv = nghttp2_session_update_recv_stream_window_size
|
||||
(session, stream, readlen);
|
||||
(session, stream, readlen,
|
||||
iframe->payloadleft ||
|
||||
(iframe->frame.hd.flags & NGHTTP2_FLAG_END_STREAM) == 0);
|
||||
if(nghttp2_is_fatal(rv)) {
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
}
|
||||
data_readlen = inbound_frame_effective_readlen
|
||||
(iframe, iframe->payloadleft, readlen);
|
||||
DEBUGF(fprintf(stderr, "data_readlen=%zu\n", data_readlen));
|
||||
|
|
|
@ -181,6 +181,8 @@ int main(int argc, char* argv[])
|
|||
test_nghttp2_session_flow_control) ||
|
||||
!CU_add_test(pSuite, "session_flow_control_data_recv",
|
||||
test_nghttp2_session_flow_control_data_recv) ||
|
||||
!CU_add_test(pSuite, "session_flow_control_data_with_padding_recv",
|
||||
test_nghttp2_session_flow_control_data_with_padding_recv) ||
|
||||
!CU_add_test(pSuite, "session_data_read_temporal_failure",
|
||||
test_nghttp2_session_data_read_temporal_failure) ||
|
||||
!CU_add_test(pSuite, "session_on_stream_close",
|
||||
|
|
|
@ -3542,6 +3542,46 @@ void test_nghttp2_session_flow_control_data_recv(void)
|
|||
nghttp2_session_del(session);
|
||||
}
|
||||
|
||||
void test_nghttp2_session_flow_control_data_with_padding_recv(void)
|
||||
{
|
||||
nghttp2_session *session;
|
||||
nghttp2_session_callbacks callbacks;
|
||||
uint8_t data[1024];
|
||||
nghttp2_frame_hd hd;
|
||||
nghttp2_stream *stream;
|
||||
|
||||
memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
|
||||
callbacks.send_callback = null_send_callback;
|
||||
|
||||
/* Initial window size to 64KiB - 1*/
|
||||
nghttp2_session_client_new(&session, &callbacks, NULL);
|
||||
|
||||
stream = nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE,
|
||||
NGHTTP2_PRI_DEFAULT,
|
||||
NGHTTP2_STREAM_OPENED, NULL);
|
||||
|
||||
/* Create DATA frame */
|
||||
memset(data, 0, sizeof(data));
|
||||
hd.length = 357;
|
||||
hd.type = NGHTTP2_DATA;
|
||||
hd.flags = NGHTTP2_FLAG_END_STREAM |
|
||||
NGHTTP2_FLAG_PAD_HIGH | NGHTTP2_FLAG_PAD_LOW;;
|
||||
hd.stream_id = 1;
|
||||
nghttp2_frame_pack_frame_hd(data, &hd);
|
||||
/* Add 2 byte padding (PAD_LOW itself is padding) */
|
||||
data[NGHTTP2_FRAME_HEAD_LENGTH] = 1;
|
||||
data[NGHTTP2_FRAME_HEAD_LENGTH + 1] = 1;
|
||||
|
||||
CU_ASSERT(NGHTTP2_FRAME_HEAD_LENGTH + hd.length ==
|
||||
nghttp2_session_mem_recv(session, data,
|
||||
NGHTTP2_FRAME_HEAD_LENGTH + hd.length));
|
||||
|
||||
CU_ASSERT(hd.length == session->recv_window_size);
|
||||
CU_ASSERT(hd.length == stream->recv_window_size);
|
||||
|
||||
nghttp2_session_del(session);
|
||||
}
|
||||
|
||||
void test_nghttp2_session_data_read_temporal_failure(void)
|
||||
{
|
||||
nghttp2_session *session;
|
||||
|
|
|
@ -81,6 +81,7 @@ 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_data_recv(void);
|
||||
void test_nghttp2_session_flow_control_data_with_padding_recv(void);
|
||||
void test_nghttp2_session_data_read_temporal_failure(void);
|
||||
void test_nghttp2_session_on_stream_close(void);
|
||||
void test_nghttp2_session_on_ctrl_not_send(void);
|
||||
|
|
Loading…
Reference in New Issue