Allow disabling auto WINDOW_UPDATE for connection and stream individually
Now NGHTTP2_OPT_NO_AUTO_WINDOW_UPDATE is split into 2 options: NGHTTP2_OPT_NO_AUTO_STREAM_WINDOW_UPDATE and NGHTTP2_OPT_NO_AUTO_CONNECTION_WINDOW_UPDATE. This is preparation for the upcoming removal of END_FLOW_CONTROL flag. For nghttpx, instead of using END_FLOW_CONTROL to disable connection-level flow control, increase window size by large enough value, which is friendly way to current chromium implementation.
This commit is contained in:
parent
b979d2e8d2
commit
19377fb3cd
|
@ -1063,12 +1063,19 @@ void nghttp2_session_del(nghttp2_session *session);
|
||||||
*/
|
*/
|
||||||
typedef enum {
|
typedef enum {
|
||||||
/**
|
/**
|
||||||
* This option prevents the library from sending WINDOW_UPDATE
|
* This option prevents the library from sending WINDOW_UPDATE for a
|
||||||
* automatically. If this option is set, the application is
|
* stream automatically. If this option is set, the application is
|
||||||
* responsible for sending WINDOW_UPDATE using
|
* responsible for sending WINDOW_UPDATE using
|
||||||
* `nghttp2_submit_window_update`.
|
* `nghttp2_submit_window_update`.
|
||||||
*/
|
*/
|
||||||
NGHTTP2_OPT_NO_AUTO_WINDOW_UPDATE = 1,
|
NGHTTP2_OPT_NO_AUTO_STREAM_WINDOW_UPDATE = 1,
|
||||||
|
/**
|
||||||
|
* This option prevents the library from sending WINDOW_UPDATE for a
|
||||||
|
* connection automatically. If this option is set, the application
|
||||||
|
* is responsible for sending WINDOW_UPDATE with stream ID 0 using
|
||||||
|
* `nghttp2_submit_window_update`.
|
||||||
|
*/
|
||||||
|
NGHTTP2_OPT_NO_AUTO_CONNECTION_WINDOW_UPDATE = 2
|
||||||
} nghttp2_opt;
|
} nghttp2_opt;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -1935,7 +1935,8 @@ static int nghttp2_update_local_initial_window_size_func
|
||||||
return nghttp2_session_add_rst_stream(arg->session, stream->stream_id,
|
return nghttp2_session_add_rst_stream(arg->session, stream->stream_id,
|
||||||
NGHTTP2_FLOW_CONTROL_ERROR);
|
NGHTTP2_FLOW_CONTROL_ERROR);
|
||||||
}
|
}
|
||||||
if(!(arg->session->opt_flags & NGHTTP2_OPTMASK_NO_AUTO_WINDOW_UPDATE)) {
|
if(!(arg->session->opt_flags &
|
||||||
|
NGHTTP2_OPTMASK_NO_AUTO_STREAM_WINDOW_UPDATE)) {
|
||||||
if(nghttp2_should_send_window_update(stream->local_window_size,
|
if(nghttp2_should_send_window_update(stream->local_window_size,
|
||||||
stream->recv_window_size)) {
|
stream->recv_window_size)) {
|
||||||
rv = nghttp2_session_add_window_update(arg->session,
|
rv = nghttp2_session_add_window_update(arg->session,
|
||||||
|
@ -2651,8 +2652,8 @@ static int adjust_recv_window_size(int32_t *recv_window_size_ptr,
|
||||||
/*
|
/*
|
||||||
* Accumulates received bytes |delta_size| for stream-level flow
|
* Accumulates received bytes |delta_size| for stream-level flow
|
||||||
* control and decides whether to send WINDOW_UPDATE to that
|
* control and decides whether to send WINDOW_UPDATE to that
|
||||||
* stream. If NGHTTP2_OPT_NO_AUTO_WINDOW_UPDATE is set, WINDOW_UPDATE
|
* stream. If NGHTTP2_OPT_NO_AUTO_STREAM_WINDOW_UPDATE is set,
|
||||||
* will not be sent.
|
* WINDOW_UPDATE will not be sent.
|
||||||
*
|
*
|
||||||
* This function returns 0 if it succeeds, or one of the following
|
* This function returns 0 if it succeeds, or one of the following
|
||||||
* negative error codes:
|
* negative error codes:
|
||||||
|
@ -2671,7 +2672,7 @@ 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_ERR_FLOW_CONTROL);
|
NGHTTP2_ERR_FLOW_CONTROL);
|
||||||
}
|
}
|
||||||
if(!(session->opt_flags & NGHTTP2_OPTMASK_NO_AUTO_WINDOW_UPDATE)) {
|
if(!(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,
|
||||||
|
@ -2693,8 +2694,8 @@ static int nghttp2_session_update_recv_stream_window_size
|
||||||
/*
|
/*
|
||||||
* Accumulates received bytes |delta_size| for connection-level flow
|
* Accumulates received bytes |delta_size| for connection-level flow
|
||||||
* control and decides whether to send WINDOW_UPDATE to the
|
* control and decides whether to send WINDOW_UPDATE to the
|
||||||
* connection. If NGHTTP2_OPT_NO_AUTO_WINDOW_UPDATE is set,
|
* connection. If NGHTTP2_OPT_NO_AUTO_CONNECTION_WINDOW_UPDATE is
|
||||||
* WINDOW_UPDATE will not be sent.
|
* set, WINDOW_UPDATE will not be sent.
|
||||||
*
|
*
|
||||||
* This function returns 0 if it succeeds, or one of the following
|
* This function returns 0 if it succeeds, or one of the following
|
||||||
* negative error codes:
|
* negative error codes:
|
||||||
|
@ -2711,7 +2712,8 @@ static int nghttp2_session_update_recv_connection_window_size
|
||||||
if(rv != 0) {
|
if(rv != 0) {
|
||||||
return nghttp2_session_fail_session(session, NGHTTP2_ERR_FLOW_CONTROL);
|
return nghttp2_session_fail_session(session, NGHTTP2_ERR_FLOW_CONTROL);
|
||||||
}
|
}
|
||||||
if(!(session->opt_flags & NGHTTP2_OPTMASK_NO_AUTO_WINDOW_UPDATE)) {
|
if(!(session->opt_flags &
|
||||||
|
NGHTTP2_OPTMASK_NO_AUTO_CONNECTION_WINDOW_UPDATE)) {
|
||||||
if(nghttp2_should_send_window_update(session->local_window_size,
|
if(nghttp2_should_send_window_update(session->local_window_size,
|
||||||
session->recv_window_size)) {
|
session->recv_window_size)) {
|
||||||
/* Use stream ID 0 to update connection-level flow control
|
/* Use stream ID 0 to update connection-level flow control
|
||||||
|
@ -3094,18 +3096,26 @@ int nghttp2_session_set_option(nghttp2_session *session,
|
||||||
int optname, void *optval, size_t optlen)
|
int optname, void *optval, size_t optlen)
|
||||||
{
|
{
|
||||||
switch(optname) {
|
switch(optname) {
|
||||||
case NGHTTP2_OPT_NO_AUTO_WINDOW_UPDATE:
|
case NGHTTP2_OPT_NO_AUTO_STREAM_WINDOW_UPDATE:
|
||||||
|
case NGHTTP2_OPT_NO_AUTO_CONNECTION_WINDOW_UPDATE: {
|
||||||
|
int flag;
|
||||||
|
if(optname == NGHTTP2_OPT_NO_AUTO_STREAM_WINDOW_UPDATE) {
|
||||||
|
flag = NGHTTP2_OPTMASK_NO_AUTO_STREAM_WINDOW_UPDATE;
|
||||||
|
} else {
|
||||||
|
flag = NGHTTP2_OPTMASK_NO_AUTO_CONNECTION_WINDOW_UPDATE;
|
||||||
|
}
|
||||||
if(optlen == sizeof(int)) {
|
if(optlen == sizeof(int)) {
|
||||||
int intval = *(int*)optval;
|
int intval = *(int*)optval;
|
||||||
if(intval) {
|
if(intval) {
|
||||||
session->opt_flags |= NGHTTP2_OPTMASK_NO_AUTO_WINDOW_UPDATE;
|
session->opt_flags |= flag;
|
||||||
} else {
|
} else {
|
||||||
session->opt_flags &= ~NGHTTP2_OPTMASK_NO_AUTO_WINDOW_UPDATE;
|
session->opt_flags &= ~flag;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return NGHTTP2_ERR_INVALID_ARGUMENT;
|
return NGHTTP2_ERR_INVALID_ARGUMENT;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
return NGHTTP2_ERR_INVALID_ARGUMENT;
|
return NGHTTP2_ERR_INVALID_ARGUMENT;
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,7 +42,8 @@
|
||||||
* Option flags.
|
* Option flags.
|
||||||
*/
|
*/
|
||||||
typedef enum {
|
typedef enum {
|
||||||
NGHTTP2_OPTMASK_NO_AUTO_WINDOW_UPDATE = 1 << 0
|
NGHTTP2_OPTMASK_NO_AUTO_STREAM_WINDOW_UPDATE = 1 << 0,
|
||||||
|
NGHTTP2_OPTMASK_NO_AUTO_CONNECTION_WINDOW_UPDATE = 1 << 1
|
||||||
} nghttp2_optmask;
|
} nghttp2_optmask;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
|
|
@ -241,7 +241,8 @@ int nghttp2_submit_window_update(nghttp2_session *session, uint8_t flags,
|
||||||
if(rv != 0) {
|
if(rv != 0) {
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
if(!(session->opt_flags & NGHTTP2_OPTMASK_NO_AUTO_WINDOW_UPDATE) &&
|
if(!(session->opt_flags &
|
||||||
|
NGHTTP2_OPTMASK_NO_AUTO_CONNECTION_WINDOW_UPDATE) &&
|
||||||
window_size_increment < 0 &&
|
window_size_increment < 0 &&
|
||||||
nghttp2_should_send_window_update(session->local_window_size,
|
nghttp2_should_send_window_update(session->local_window_size,
|
||||||
session->recv_window_size)) {
|
session->recv_window_size)) {
|
||||||
|
@ -260,7 +261,8 @@ int nghttp2_submit_window_update(nghttp2_session *session, uint8_t flags,
|
||||||
if(rv != 0) {
|
if(rv != 0) {
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
if(!(session->opt_flags & NGHTTP2_OPTMASK_NO_AUTO_WINDOW_UPDATE) &&
|
if(!(session->opt_flags &
|
||||||
|
NGHTTP2_OPTMASK_NO_AUTO_STREAM_WINDOW_UPDATE) &&
|
||||||
window_size_increment < 0 &&
|
window_size_increment < 0 &&
|
||||||
nghttp2_should_send_window_update(stream->local_window_size,
|
nghttp2_should_send_window_update(stream->local_window_size,
|
||||||
stream->recv_window_size)) {
|
stream->recv_window_size)) {
|
||||||
|
|
|
@ -403,8 +403,8 @@ Http2Upstream::Http2Upstream(ClientHandler *handler)
|
||||||
flow_control_ = true;
|
flow_control_ = true;
|
||||||
initial_window_size_ = (1 << get_config()->spdy_upstream_window_bits) - 1;
|
initial_window_size_ = (1 << get_config()->spdy_upstream_window_bits) - 1;
|
||||||
rv = nghttp2_session_set_option(session_,
|
rv = nghttp2_session_set_option(session_,
|
||||||
NGHTTP2_OPT_NO_AUTO_WINDOW_UPDATE, &val,
|
NGHTTP2_OPT_NO_AUTO_STREAM_WINDOW_UPDATE,
|
||||||
sizeof(val));
|
&val, sizeof(val));
|
||||||
assert(rv == 0);
|
assert(rv == 0);
|
||||||
|
|
||||||
// TODO Maybe call from outside?
|
// TODO Maybe call from outside?
|
||||||
|
@ -418,9 +418,10 @@ Http2Upstream::Http2Upstream(ClientHandler *handler)
|
||||||
rv = nghttp2_submit_settings
|
rv = nghttp2_submit_settings
|
||||||
(session_, entry, sizeof(entry)/sizeof(nghttp2_settings_entry));
|
(session_, entry, sizeof(entry)/sizeof(nghttp2_settings_entry));
|
||||||
assert(rv == 0);
|
assert(rv == 0);
|
||||||
// Disable connection-level flow control
|
// Set large connection-level window size to effectively disable
|
||||||
rv = nghttp2_submit_window_update(session_, NGHTTP2_FLAG_END_FLOW_CONTROL,
|
// connection-level flow control.
|
||||||
0, 0);
|
rv = nghttp2_submit_window_update(session_, NGHTTP2_FLAG_NONE,
|
||||||
|
0, 1000000007);
|
||||||
assert(rv == 0);
|
assert(rv == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1057,8 +1057,8 @@ int SpdySession::on_connect()
|
||||||
int val = 1;
|
int val = 1;
|
||||||
flow_control_ = true;
|
flow_control_ = true;
|
||||||
rv = nghttp2_session_set_option(session_,
|
rv = nghttp2_session_set_option(session_,
|
||||||
NGHTTP2_OPT_NO_AUTO_WINDOW_UPDATE, &val,
|
NGHTTP2_OPT_NO_AUTO_STREAM_WINDOW_UPDATE,
|
||||||
sizeof(val));
|
&val, sizeof(val));
|
||||||
assert(rv == 0);
|
assert(rv == 0);
|
||||||
|
|
||||||
nghttp2_settings_entry entry[2];
|
nghttp2_settings_entry entry[2];
|
||||||
|
@ -1073,9 +1073,10 @@ int SpdySession::on_connect()
|
||||||
if(rv != 0) {
|
if(rv != 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
// Disable connection-level flow control
|
// Set large connection-level window size to effectively disable
|
||||||
rv = nghttp2_submit_window_update(session_, NGHTTP2_FLAG_END_FLOW_CONTROL,
|
// connection-level flow control.
|
||||||
0, 0);
|
rv = nghttp2_submit_window_update(session_, NGHTTP2_FLAG_NONE,
|
||||||
|
0, 1000000007);
|
||||||
if(rv != 0) {
|
if(rv != 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3091,17 +3091,20 @@ void test_nghttp2_session_set_option(void)
|
||||||
|
|
||||||
intval = 1;
|
intval = 1;
|
||||||
CU_ASSERT(0 ==
|
CU_ASSERT(0 ==
|
||||||
nghttp2_session_set_option(session,
|
nghttp2_session_set_option
|
||||||
NGHTTP2_OPT_NO_AUTO_WINDOW_UPDATE,
|
(session,
|
||||||
|
NGHTTP2_OPT_NO_AUTO_STREAM_WINDOW_UPDATE,
|
||||||
&intval, sizeof(intval)));
|
&intval, sizeof(intval)));
|
||||||
CU_ASSERT(session->opt_flags & NGHTTP2_OPTMASK_NO_AUTO_WINDOW_UPDATE);
|
CU_ASSERT(session->opt_flags & NGHTTP2_OPTMASK_NO_AUTO_STREAM_WINDOW_UPDATE);
|
||||||
|
|
||||||
intval = 0;
|
intval = 0;
|
||||||
CU_ASSERT(0 ==
|
CU_ASSERT(0 ==
|
||||||
nghttp2_session_set_option(session,
|
nghttp2_session_set_option
|
||||||
NGHTTP2_OPT_NO_AUTO_WINDOW_UPDATE,
|
(session,
|
||||||
|
NGHTTP2_OPT_NO_AUTO_STREAM_WINDOW_UPDATE,
|
||||||
&intval, sizeof(intval)));
|
&intval, sizeof(intval)));
|
||||||
CU_ASSERT((session->opt_flags & NGHTTP2_OPTMASK_NO_AUTO_WINDOW_UPDATE) == 0);
|
CU_ASSERT((session->opt_flags &
|
||||||
|
NGHTTP2_OPTMASK_NO_AUTO_STREAM_WINDOW_UPDATE) == 0);
|
||||||
|
|
||||||
CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT ==
|
CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT ==
|
||||||
nghttp2_session_set_option(session, 0, /* 0 is invalid optname */
|
nghttp2_session_set_option(session, 0, /* 0 is invalid optname */
|
||||||
|
@ -3109,10 +3112,20 @@ void test_nghttp2_session_set_option(void)
|
||||||
|
|
||||||
charval = 1;
|
charval = 1;
|
||||||
CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT ==
|
CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT ==
|
||||||
nghttp2_session_set_option(session,
|
nghttp2_session_set_option
|
||||||
NGHTTP2_OPT_NO_AUTO_WINDOW_UPDATE,
|
(session,
|
||||||
|
NGHTTP2_OPT_NO_AUTO_STREAM_WINDOW_UPDATE,
|
||||||
&charval, sizeof(charval)));
|
&charval, sizeof(charval)));
|
||||||
|
|
||||||
|
intval = 1;
|
||||||
|
CU_ASSERT(0 ==
|
||||||
|
nghttp2_session_set_option
|
||||||
|
(session,
|
||||||
|
NGHTTP2_OPT_NO_AUTO_CONNECTION_WINDOW_UPDATE,
|
||||||
|
&intval, sizeof(intval)));
|
||||||
|
CU_ASSERT(session->opt_flags &
|
||||||
|
NGHTTP2_OPTMASK_NO_AUTO_CONNECTION_WINDOW_UPDATE);
|
||||||
|
|
||||||
nghttp2_session_del(session);
|
nghttp2_session_del(session);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue