Add nghttp2_option_set_max_outbound_ack
This commit is contained in:
parent
2aa79fa91d
commit
0a6ce87c22
|
@ -67,6 +67,7 @@ APIDOCS= \
|
|||
nghttp2_option_set_no_recv_client_magic.rst \
|
||||
nghttp2_option_set_peer_max_concurrent_streams.rst \
|
||||
nghttp2_option_set_user_recv_extension_type.rst \
|
||||
nghttp2_option_set_max_outbound_ack.rst \
|
||||
nghttp2_pack_settings_payload.rst \
|
||||
nghttp2_priority_spec_check_default.rst \
|
||||
nghttp2_priority_spec_default_init.rst \
|
||||
|
|
|
@ -2648,6 +2648,17 @@ nghttp2_option_set_max_deflate_dynamic_table_size(nghttp2_option *option,
|
|||
NGHTTP2_EXTERN void nghttp2_option_set_no_closed_streams(nghttp2_option *option,
|
||||
int val);
|
||||
|
||||
/**
|
||||
* @function
|
||||
*
|
||||
* This function sets the maximum number of outgoing SETTINGS ACK and
|
||||
* PING ACK frames retained in :type:`nghttp2_session` object. If
|
||||
* more than those frames are retained, the peer is considered to be
|
||||
* misbehaving and session will be closed. The default value is 1000.
|
||||
*/
|
||||
NGHTTP2_EXTERN void nghttp2_option_set_max_outbound_ack(nghttp2_option *option,
|
||||
size_t val);
|
||||
|
||||
/**
|
||||
* @function
|
||||
*
|
||||
|
|
|
@ -116,3 +116,8 @@ void nghttp2_option_set_no_closed_streams(nghttp2_option *option, int val) {
|
|||
option->opt_set_mask |= NGHTTP2_OPT_NO_CLOSED_STREAMS;
|
||||
option->no_closed_streams = val;
|
||||
}
|
||||
|
||||
void nghttp2_option_set_max_outbound_ack(nghttp2_option *option, size_t val) {
|
||||
option->opt_set_mask |= NGHTTP2_OPT_MAX_OUTBOUND_ACK;
|
||||
option->max_outbound_ack = val;
|
||||
}
|
||||
|
|
|
@ -66,6 +66,7 @@ typedef enum {
|
|||
NGHTTP2_OPT_MAX_SEND_HEADER_BLOCK_LENGTH = 1 << 8,
|
||||
NGHTTP2_OPT_MAX_DEFLATE_DYNAMIC_TABLE_SIZE = 1 << 9,
|
||||
NGHTTP2_OPT_NO_CLOSED_STREAMS = 1 << 10,
|
||||
NGHTTP2_OPT_MAX_OUTBOUND_ACK = 1 << 11,
|
||||
} nghttp2_option_flag;
|
||||
|
||||
/**
|
||||
|
@ -80,6 +81,10 @@ struct nghttp2_option {
|
|||
* NGHTTP2_OPT_MAX_DEFLATE_DYNAMIC_TABLE_SIZE
|
||||
*/
|
||||
size_t max_deflate_dynamic_table_size;
|
||||
/**
|
||||
* NGHTTP2_OPT_MAX_OUTBOUND_ACK
|
||||
*/
|
||||
size_t max_outbound_ack;
|
||||
/**
|
||||
* Bitwise OR of nghttp2_option_flag to determine that which fields
|
||||
* are specified.
|
||||
|
|
|
@ -457,6 +457,7 @@ static int session_new(nghttp2_session **session_ptr,
|
|||
(*session_ptr)->remote_settings.max_concurrent_streams = 100;
|
||||
|
||||
(*session_ptr)->max_send_header_block_length = NGHTTP2_MAX_HEADERSLEN;
|
||||
(*session_ptr)->max_outbound_ack = NGHTTP2_DEFAULT_MAX_OBQ_FLOOD_ITEM;
|
||||
|
||||
if (option) {
|
||||
if ((option->opt_set_mask & NGHTTP2_OPT_NO_AUTO_WINDOW_UPDATE) &&
|
||||
|
@ -516,6 +517,10 @@ static int session_new(nghttp2_session **session_ptr,
|
|||
option->no_closed_streams) {
|
||||
(*session_ptr)->opt_flags |= NGHTTP2_OPTMASK_NO_CLOSED_STREAMS;
|
||||
}
|
||||
|
||||
if (option->opt_set_mask & NGHTTP2_OPT_MAX_OUTBOUND_ACK) {
|
||||
(*session_ptr)->max_outbound_ack = option->max_outbound_ack;
|
||||
}
|
||||
}
|
||||
|
||||
rv = nghttp2_hd_deflate_init2(&(*session_ptr)->hd_deflater,
|
||||
|
@ -6857,7 +6862,7 @@ int nghttp2_session_add_ping(nghttp2_session *session, uint8_t flags,
|
|||
mem = &session->mem;
|
||||
|
||||
if ((flags & NGHTTP2_FLAG_ACK) &&
|
||||
session->obq_flood_counter_ >= NGHTTP2_MAX_OBQ_FLOOD_ITEM) {
|
||||
session->obq_flood_counter_ >= session->max_outbound_ack) {
|
||||
return NGHTTP2_ERR_FLOODED;
|
||||
}
|
||||
|
||||
|
@ -7002,7 +7007,7 @@ int nghttp2_session_add_settings(nghttp2_session *session, uint8_t flags,
|
|||
return NGHTTP2_ERR_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
if (session->obq_flood_counter_ >= NGHTTP2_MAX_OBQ_FLOOD_ITEM) {
|
||||
if (session->obq_flood_counter_ >= session->max_outbound_ack) {
|
||||
return NGHTTP2_ERR_FLOODED;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -97,7 +97,7 @@ typedef struct {
|
|||
response frames are stacked up, which leads to memory exhaustion.
|
||||
The value selected here is arbitrary, but safe value and if we have
|
||||
these frames in this number, it is considered suspicious. */
|
||||
#define NGHTTP2_MAX_OBQ_FLOOD_ITEM 10000
|
||||
#define NGHTTP2_DEFAULT_MAX_OBQ_FLOOD_ITEM 1000
|
||||
|
||||
/* The default value of maximum number of concurrent streams. */
|
||||
#define NGHTTP2_DEFAULT_MAX_CONCURRENT_STREAMS 0xffffffffu
|
||||
|
@ -258,8 +258,12 @@ struct nghttp2_session {
|
|||
size_t num_idle_streams;
|
||||
/* The number of bytes allocated for nvbuf */
|
||||
size_t nvbuflen;
|
||||
/* Counter for detecting flooding in outbound queue */
|
||||
/* Counter for detecting flooding in outbound queue. If it exceeds
|
||||
max_outbound_ack, session will be closed. */
|
||||
size_t obq_flood_counter_;
|
||||
/* The maximum number of outgoing SETTINGS ACK and PING ACK in
|
||||
outbound queue. */
|
||||
size_t max_outbound_ack;
|
||||
/* The maximum length of header block to send. Calculated by the
|
||||
same way as nghttp2_hd_deflate_bound() does. */
|
||||
size_t max_send_header_block_length;
|
||||
|
|
|
@ -10002,7 +10002,7 @@ void test_nghttp2_session_flooding(void) {
|
|||
|
||||
buf = &bufs.head->buf;
|
||||
|
||||
for (i = 0; i < NGHTTP2_MAX_OBQ_FLOOD_ITEM; ++i) {
|
||||
for (i = 0; i < NGHTTP2_DEFAULT_MAX_OBQ_FLOOD_ITEM; ++i) {
|
||||
CU_ASSERT(
|
||||
(ssize_t)nghttp2_buf_len(buf) ==
|
||||
nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf)));
|
||||
|
@ -10024,7 +10024,7 @@ void test_nghttp2_session_flooding(void) {
|
|||
|
||||
buf = &bufs.head->buf;
|
||||
|
||||
for (i = 0; i < NGHTTP2_MAX_OBQ_FLOOD_ITEM; ++i) {
|
||||
for (i = 0; i < NGHTTP2_DEFAULT_MAX_OBQ_FLOOD_ITEM; ++i) {
|
||||
CU_ASSERT(
|
||||
(ssize_t)nghttp2_buf_len(buf) ==
|
||||
nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf)));
|
||||
|
|
Loading…
Reference in New Issue