Add NGHTTP2_OPT_PEER_MAX_CONCURRENT_STREAMS option
And utilize it in nghttp to limit initial max concurrent streams.
This commit is contained in:
parent
c5d7d570e3
commit
99ba622fed
|
@ -1202,7 +1202,21 @@ typedef enum {
|
||||||
* is responsible for sending WINDOW_UPDATE with stream ID 0 using
|
* is responsible for sending WINDOW_UPDATE with stream ID 0 using
|
||||||
* `nghttp2_submit_window_update`.
|
* `nghttp2_submit_window_update`.
|
||||||
*/
|
*/
|
||||||
NGHTTP2_OPT_NO_AUTO_CONNECTION_WINDOW_UPDATE = 2
|
NGHTTP2_OPT_NO_AUTO_CONNECTION_WINDOW_UPDATE = 2,
|
||||||
|
/**
|
||||||
|
* This option sets the SETTINGS_MAX_CONCURRENT_STREAMS value of
|
||||||
|
* remote endpoint as if it is received in SETTINGS frame. Without
|
||||||
|
* specifying this option, before the local endpoint receives
|
||||||
|
* SETTINGS_MAX_CONCURRENT_STREAMS in SETTINGS frame from remote
|
||||||
|
* endpoint, SETTINGS_MAX_CONCURRENT_STREAMS is unlimited. This may
|
||||||
|
* cause problem if local endpoint submits lots of requests
|
||||||
|
* initially and sending them at once to the remote peer may lead to
|
||||||
|
* the rejection of some requests. Specifying this option to the
|
||||||
|
* sensible value, say 100, may avoid this kind of issue. This value
|
||||||
|
* will be overwritten if the local endpoint receives
|
||||||
|
* SETTINGS_MAX_CONCURRENT_STREAMS from the remote endpoint.
|
||||||
|
*/
|
||||||
|
NGHTTP2_OPT_PEER_MAX_CONCURRENT_STREAMS = 3
|
||||||
} nghttp2_opt;
|
} nghttp2_opt;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1230,6 +1244,10 @@ typedef enum {
|
||||||
* sending WINDOW_UPDATE using
|
* sending WINDOW_UPDATE using
|
||||||
* `nghttp2_submit_window_update`. This option defaults to 0.
|
* `nghttp2_submit_window_update`. This option defaults to 0.
|
||||||
*
|
*
|
||||||
|
* :enum:`NGHTTP2_OPT_PEER_MAX_CONCURRENT_STREAMS`
|
||||||
|
* The |optval| must be a pointer to ``ssize_t``. It is an error
|
||||||
|
* if |*optval| is 0 or negative.
|
||||||
|
*
|
||||||
* 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:
|
||||||
*
|
*
|
||||||
|
|
|
@ -3264,6 +3264,19 @@ int nghttp2_session_set_option(nghttp2_session *session,
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case NGHTTP2_OPT_PEER_MAX_CONCURRENT_STREAMS: {
|
||||||
|
ssize_t sszval;
|
||||||
|
if(optlen != sizeof(ssize_t)) {
|
||||||
|
return NGHTTP2_ERR_INVALID_ARGUMENT;
|
||||||
|
}
|
||||||
|
sszval = *(ssize_t*)optval;
|
||||||
|
if(sszval <= 0) {
|
||||||
|
return NGHTTP2_ERR_INVALID_ARGUMENT;
|
||||||
|
}
|
||||||
|
session->remote_settings[NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS] =
|
||||||
|
sszval;
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
return NGHTTP2_ERR_INVALID_ARGUMENT;
|
return NGHTTP2_ERR_INVALID_ARGUMENT;
|
||||||
}
|
}
|
||||||
|
|
|
@ -91,6 +91,7 @@ struct Config {
|
||||||
std::map<std::string, std::string> headers;
|
std::map<std::string, std::string> headers;
|
||||||
std::string datafile;
|
std::string datafile;
|
||||||
size_t output_upper_thres;
|
size_t output_upper_thres;
|
||||||
|
ssize_t peer_max_concurrent_streams;
|
||||||
Config()
|
Config()
|
||||||
: null_out(false),
|
: null_out(false),
|
||||||
remote_name(false),
|
remote_name(false),
|
||||||
|
@ -103,7 +104,8 @@ struct Config {
|
||||||
multiply(1),
|
multiply(1),
|
||||||
timeout(-1),
|
timeout(-1),
|
||||||
window_bits(-1),
|
window_bits(-1),
|
||||||
output_upper_thres(1024*1024)
|
output_upper_thres(1024*1024),
|
||||||
|
peer_max_concurrent_streams(NGHTTP2_INITIAL_MAX_CONCURRENT_STREAMS)
|
||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -623,6 +625,13 @@ struct HttpClient {
|
||||||
if(rv != 0) {
|
if(rv != 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
rv = nghttp2_session_set_option(session,
|
||||||
|
NGHTTP2_OPT_PEER_MAX_CONCURRENT_STREAMS,
|
||||||
|
&config.peer_max_concurrent_streams,
|
||||||
|
sizeof(config.peer_max_concurrent_streams));
|
||||||
|
if(rv != 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
if(need_upgrade()) {
|
if(need_upgrade()) {
|
||||||
// Adjust stream user-data depending on the existence of upload
|
// Adjust stream user-data depending on the existence of upload
|
||||||
// data
|
// data
|
||||||
|
@ -1471,6 +1480,11 @@ void print_help(std::ostream& out)
|
||||||
<< " -p, --pri=<PRIORITY>\n"
|
<< " -p, --pri=<PRIORITY>\n"
|
||||||
<< " Sets stream priority. Default: "
|
<< " Sets stream priority. Default: "
|
||||||
<< NGHTTP2_PRI_DEFAULT << "\n"
|
<< NGHTTP2_PRI_DEFAULT << "\n"
|
||||||
|
<< " --peer-max-concurrent-streams=<N>\n"
|
||||||
|
<< " Use <N> as SETTINGS_MAX_CONCURRENT_STREAMS\n"
|
||||||
|
<< " value of remote endpoint as if it is\n"
|
||||||
|
<< " received in SETTINGS frame. The default\n"
|
||||||
|
<< " is large enough as it is seen as unlimited.\n"
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1495,6 +1509,7 @@ int main(int argc, char **argv)
|
||||||
{"no-flow-control", no_argument, nullptr, 'f'},
|
{"no-flow-control", no_argument, nullptr, 'f'},
|
||||||
{"upgrade", no_argument, nullptr, 'u'},
|
{"upgrade", no_argument, nullptr, 'u'},
|
||||||
{"pri", required_argument, nullptr, 'p'},
|
{"pri", required_argument, nullptr, 'p'},
|
||||||
|
{"peer-max-concurrent-streams", required_argument, &flag, 3},
|
||||||
{nullptr, 0, nullptr, 0 }
|
{nullptr, 0, nullptr, 0 }
|
||||||
};
|
};
|
||||||
int option_index = 0;
|
int option_index = 0;
|
||||||
|
@ -1602,6 +1617,10 @@ int main(int argc, char **argv)
|
||||||
// key option
|
// key option
|
||||||
config.keyfile = optarg;
|
config.keyfile = optarg;
|
||||||
break;
|
break;
|
||||||
|
case 3:
|
||||||
|
// peer-max-concurrent-streams option
|
||||||
|
config.peer_max_concurrent_streams = strtoul(optarg, nullptr, 10);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -3248,6 +3248,7 @@ void test_nghttp2_session_set_option(void)
|
||||||
nghttp2_session_callbacks callbacks;
|
nghttp2_session_callbacks callbacks;
|
||||||
int intval;
|
int intval;
|
||||||
char charval;
|
char charval;
|
||||||
|
ssize_t sszval;
|
||||||
memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
|
memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
|
||||||
nghttp2_session_client_new(&session, &callbacks, NULL);
|
nghttp2_session_client_new(&session, &callbacks, NULL);
|
||||||
|
|
||||||
|
@ -3288,6 +3289,29 @@ void test_nghttp2_session_set_option(void)
|
||||||
CU_ASSERT(session->opt_flags &
|
CU_ASSERT(session->opt_flags &
|
||||||
NGHTTP2_OPTMASK_NO_AUTO_CONNECTION_WINDOW_UPDATE);
|
NGHTTP2_OPTMASK_NO_AUTO_CONNECTION_WINDOW_UPDATE);
|
||||||
|
|
||||||
|
sszval = 100;
|
||||||
|
CU_ASSERT(0 ==
|
||||||
|
nghttp2_session_set_option
|
||||||
|
(session,
|
||||||
|
NGHTTP2_OPT_PEER_MAX_CONCURRENT_STREAMS,
|
||||||
|
&sszval, sizeof(sszval)));
|
||||||
|
CU_ASSERT(sszval ==
|
||||||
|
session->remote_settings[NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS]);
|
||||||
|
|
||||||
|
sszval = 0;
|
||||||
|
CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT ==
|
||||||
|
nghttp2_session_set_option
|
||||||
|
(session,
|
||||||
|
NGHTTP2_OPT_PEER_MAX_CONCURRENT_STREAMS,
|
||||||
|
&sszval, sizeof(sszval)));
|
||||||
|
|
||||||
|
intval = 100;
|
||||||
|
CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT ==
|
||||||
|
nghttp2_session_set_option
|
||||||
|
(session,
|
||||||
|
NGHTTP2_OPT_PEER_MAX_CONCURRENT_STREAMS,
|
||||||
|
&intval, sizeof(intval)));
|
||||||
|
|
||||||
nghttp2_session_del(session);
|
nghttp2_session_del(session);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue