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
|
static int nghttp2_session_update_recv_stream_window_size
|
||||||
(nghttp2_session *session,
|
(nghttp2_session *session,
|
||||||
nghttp2_stream *stream,
|
nghttp2_stream *stream,
|
||||||
int32_t delta_size)
|
int32_t delta_size,
|
||||||
|
int send_window_update)
|
||||||
{
|
{
|
||||||
int rv;
|
int rv;
|
||||||
rv = adjust_recv_window_size(&stream->recv_window_size, delta_size,
|
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,
|
return nghttp2_session_add_rst_stream(session, stream->stream_id,
|
||||||
NGHTTP2_FLOW_CONTROL_ERROR);
|
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
|
/* We have to use local_settings here because it is the constraint
|
||||||
the remote endpoint should honor. */
|
the remote endpoint should honor. */
|
||||||
if(nghttp2_should_send_window_update(stream->local_window_size,
|
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 rv;
|
||||||
int busy = 0;
|
int busy = 0;
|
||||||
nghttp2_frame_hd cont_hd;
|
nghttp2_frame_hd cont_hd;
|
||||||
|
nghttp2_stream *stream;
|
||||||
|
|
||||||
for(;;) {
|
for(;;) {
|
||||||
switch(iframe->state) {
|
switch(iframe->state) {
|
||||||
|
@ -3657,6 +3662,23 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session,
|
||||||
}
|
}
|
||||||
iframe->frame.data.padlen = rv;
|
iframe->frame.data.padlen = rv;
|
||||||
iframe->state = NGHTTP2_IB_READ_DATA;
|
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;
|
break;
|
||||||
case NGHTTP2_HEADERS:
|
case NGHTTP2_HEADERS:
|
||||||
if(iframe->padlen == 0 &&
|
if(iframe->padlen == 0 &&
|
||||||
|
@ -4037,19 +4059,17 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session,
|
||||||
if(nghttp2_is_fatal(rv)) {
|
if(nghttp2_is_fatal(rv)) {
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
if(iframe->payloadleft ||
|
|
||||||
(iframe->frame.hd.flags & NGHTTP2_FLAG_END_STREAM) == 0) {
|
|
||||||
nghttp2_stream *stream;
|
|
||||||
stream = nghttp2_session_get_stream(session,
|
stream = nghttp2_session_get_stream(session,
|
||||||
iframe->frame.hd.stream_id);
|
iframe->frame.hd.stream_id);
|
||||||
if(stream) {
|
if(stream) {
|
||||||
rv = nghttp2_session_update_recv_stream_window_size
|
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)) {
|
if(nghttp2_is_fatal(rv)) {
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
data_readlen = inbound_frame_effective_readlen
|
data_readlen = inbound_frame_effective_readlen
|
||||||
(iframe, iframe->payloadleft, readlen);
|
(iframe, iframe->payloadleft, readlen);
|
||||||
DEBUGF(fprintf(stderr, "data_readlen=%zu\n", data_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) ||
|
test_nghttp2_session_flow_control) ||
|
||||||
!CU_add_test(pSuite, "session_flow_control_data_recv",
|
!CU_add_test(pSuite, "session_flow_control_data_recv",
|
||||||
test_nghttp2_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",
|
!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_stream_close",
|
!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);
|
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)
|
void test_nghttp2_session_data_read_temporal_failure(void)
|
||||||
{
|
{
|
||||||
nghttp2_session *session;
|
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_defer_data(void);
|
||||||
void test_nghttp2_session_flow_control(void);
|
void test_nghttp2_session_flow_control(void);
|
||||||
void test_nghttp2_session_flow_control_data_recv(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_data_read_temporal_failure(void);
|
||||||
void test_nghttp2_session_on_stream_close(void);
|
void test_nghttp2_session_on_stream_close(void);
|
||||||
void test_nghttp2_session_on_ctrl_not_send(void);
|
void test_nghttp2_session_on_ctrl_not_send(void);
|
||||||
|
|
Loading…
Reference in New Issue