代码拉取完成,页面将自动刷新
同步操作将从 src-openEuler/trafficserver 强制同步,此操作会覆盖自 Fork 仓库以来所做的任何修改,且无法恢复!!!
确定后同步将在后台操作,完成时将刷新页面,请耐心等待。
From b8c6a23b74af1772e5cb0de25b38c234a418cb1d Mon Sep 17 00:00:00 2001
From: Masakazu Kitajo <maskit@apache.org>
Date: Wed, 3 Apr 2024 09:31:37 -0600
Subject: [PATCH] proxy.config.http2.max_continuation_frames_per_minute
(#11206)
Origin: https://github.com/apache/trafficserver/commit/b8c6a23b74af1772e5cb0de25b38c234a418cb1d
This adds the ability to rate limite HTTP/2 CONTINUATION frames per
stream per minute.
Co-authored-by: Brian Neradt <brian.neradt@gmail.com>
---
doc/admin-guide/files/records.config.en.rst | 11 +++-
.../statistics/core/http-connection.en.rst | 11 +++-
iocore/net/P_SNIActionPerformer.h | 17 +++++
iocore/net/SSLSNIConfig.cc | 4 ++
iocore/net/TLSSNISupport.h | 1 +
iocore/net/YamlSNIConfig.cc | 4 ++
iocore/net/YamlSNIConfig.h | 2 +
mgmt/RecordsConfig.cc | 2 +
proxy/http2/HTTP2.cc | 66 ++++++++++---------
proxy/http2/HTTP2.h | 2 +
proxy/http2/Http2ConnectionState.cc | 36 ++++++++--
proxy/http2/Http2ConnectionState.h | 12 ++--
12 files changed, 126 insertions(+), 42 deletions(-)
diff --git a/doc/admin-guide/files/records.config.en.rst b/doc/admin-guide/files/records.config.en.rst
index f3df888708e..979c8bda2f4 100644
--- a/doc/admin-guide/files/records.config.en.rst
+++ b/doc/admin-guide/files/records.config.en.rst
@@ -4287,8 +4287,15 @@ HTTP/2 Configuration
-.. ts:cv:: CONFIG proxy.config.http2.max_rst_stream_frames_per_minute INT 14
+.. ts:cv:: CONFIG proxy.config.http2.max_rst_stream_frames_per_minute INT 200
:reloadable:
- Specifies how many RST_STREAM frames |TS| receives for a minute at maximum.
- Clients exceeded this limit will be immediately disconnected with an error
+ Specifies how many RST_STREAM frames |TS| receives per minute at maximum.
+ Clients exceeding this limit will be immediately disconnected with an error
+ code of ENHANCE_YOUR_CALM.
+
+.. ts:cv:: CONFIG proxy.config.http2.max_continuation_frames_per_minute INT 120
+ :reloadable:
+
+ Specifies how many CONTINUATION frames |TS| receives per minute at maximum.
+ Clients exceeding this limit will be immediately disconnected with an error
code of ENHANCE_YOUR_CALM.
.. ts:cv:: CONFIG proxy.config.http2.min_avg_window_update FLOAT 2560.0
diff --git a/doc/admin-guide/monitoring/statistics/core/http-connection.en.rst b/doc/admin-guide/monitoring/statistics/core/http-connection.en.rst
index b22da8e1c66..ee47a147c01 100644
--- a/doc/admin-guide/monitoring/statistics/core/http-connection.en.rst
+++ b/doc/admin-guide/monitoring/statistics/core/http-connection.en.rst
@@ -263,10 +263,17 @@ HTTP/2
.. ts:stat:: global proxy.process.http2.max_rst_stream_frames_per_minute_exceeded integer
:type: counter
- Represents the total number of closed HTTP/2 connections for exceeding the
- maximum allowed number of rst_stream frames per minute limit which is configured by
+ Represents the total number of HTTP/2 connections closed for exceeding the
+ maximum allowed number of ``RST_STREAM`` frames per minute limit which is configured by
:ts:cv:`proxy.config.http2.max_rst_stream_frames_per_minute`.
+.. ts:stat:: global proxy.process.http2.max_continuation_frames_per_minute_exceeded integer
+ :type: counter
+
+ Represents the total number of HTTP/2 connections closed for exceeding the
+ maximum allowed number of ``CONTINUATION`` frames per minute limit which is
+ configured by :ts:cv:`proxy.config.http2.max_continuation_frames_per_minute`.
+
.. ts:stat:: global proxy.process.http2.insufficient_avg_window_update integer
:type: counter
diff --git a/iocore/net/P_SNIActionPerformer.h b/iocore/net/P_SNIActionPerformer.h
index e223ac7d0ba..eebe44b75a1 100644
--- a/iocore/net/P_SNIActionPerformer.h
+++ b/iocore/net/P_SNIActionPerformer.h
@@ -186,6 +186,23 @@ class HTTP2MaxRstStreamFramesPerMinute : public ActionItem
int value = -1;
};
+class HTTP2MaxContinuationFramesPerMinute : public ActionItem
+{
+public:
+ HTTP2MaxContinuationFramesPerMinute(int value) : value(value) {}
+ ~HTTP2MaxContinuationFramesPerMinute() override {}
+
+ int
+ SNIAction(TLSSNISupport *snis, const Context &ctx) const override
+ {
+ snis->hints_from_sni.http2_max_continuation_frames_per_minute = value;
+ return SSL_TLSEXT_ERR_OK;
+ }
+
+private:
+ int value = -1;
+};
+
class TunnelDestination : public ActionItem
{
public:
diff --git a/iocore/net/SSLSNIConfig.cc b/iocore/net/SSLSNIConfig.cc
index a7071013f6a..942e6c420f0 100644
--- a/iocore/net/SSLSNIConfig.cc
+++ b/iocore/net/SSLSNIConfig.cc
@@ -151,6 +151,10 @@ SNIConfigParams::load_sni_config()
ai->actions.push_back(
std::make_unique<HTTP2MaxRstStreamFramesPerMinute>(item.http2_max_rst_stream_frames_per_minute.value()));
}
+ if (item.http2_max_continuation_frames_per_minute.has_value()) {
+ ai->actions.push_back(
+ std::make_unique<HTTP2MaxContinuationFramesPerMinute>(item.http2_max_continuation_frames_per_minute.value()));
+ }
ai->actions.push_back(std::make_unique<SNI_IpAllow>(item.ip_allow, item.fqdn));
diff --git a/iocore/net/TLSSNISupport.h b/iocore/net/TLSSNISupport.h
index ba2d13e9300..e8614ffa9b8 100644
--- a/iocore/net/TLSSNISupport.h
+++ b/iocore/net/TLSSNISupport.h
@@ -56,6 +56,7 @@ class TLSSNISupport
std::optional<uint32_t> http2_max_ping_frames_per_minute;
std::optional<uint32_t> http2_max_priority_frames_per_minute;
std::optional<uint32_t> http2_max_rst_stream_frames_per_minute;
+ std::optional<uint32_t> http2_max_continuation_frames_per_minute;
} hints_from_sni;
protected:
diff --git a/iocore/net/YamlSNIConfig.cc b/iocore/net/YamlSNIConfig.cc
index 9a777b806f2..7286197c9c7 100644
--- a/iocore/net/YamlSNIConfig.cc
+++ b/iocore/net/YamlSNIConfig.cc
@@ -148,6 +148,7 @@ std::set<std::string> valid_sni_config_keys = {TS_fqdn,
TS_http2_max_ping_frames_per_minute,
TS_http2_max_priority_frames_per_minute,
TS_http2_max_rst_stream_frames_per_minute,
+ TS_http2_max_continuation_frames_per_minute,
TS_ip_allow,
#if TS_USE_HELLO_CB || defined(OPENSSL_IS_BORINGSSL)
TS_valid_tls_versions_in,
@@ -193,6 +194,9 @@ template <> struct convert<YamlSNIConfig::Item> {
if (node[TS_http2_max_rst_stream_frames_per_minute]) {
item.http2_max_rst_stream_frames_per_minute = node[TS_http2_max_rst_stream_frames_per_minute].as<int>();
}
+ if (node[TS_http2_max_continuation_frames_per_minute]) {
+ item.http2_max_continuation_frames_per_minute = node[TS_http2_max_continuation_frames_per_minute].as<int>();
+ }
// enum
if (node[TS_verify_client]) {
diff --git a/iocore/net/YamlSNIConfig.h b/iocore/net/YamlSNIConfig.h
index b297bd5c16e..8165dc336c5 100644
--- a/iocore/net/YamlSNIConfig.h
+++ b/iocore/net/YamlSNIConfig.h
@@ -60,6 +60,7 @@ TSDECL(http2_max_settings_frames_per_minute);
TSDECL(http2_max_ping_frames_per_minute);
TSDECL(http2_max_priority_frames_per_minute);
TSDECL(http2_max_rst_stream_frames_per_minute);
+TSDECL(http2_max_continuation_frames_per_minute);
TSDECL(host_sni_policy);
#undef TSDECL
@@ -94,6 +95,7 @@ struct YamlSNIConfig {
std::optional<int> http2_max_ping_frames_per_minute;
std::optional<int> http2_max_priority_frames_per_minute;
std::optional<int> http2_max_rst_stream_frames_per_minute;
+ std::optional<int> http2_max_continuation_frames_per_minute;
bool tunnel_prewarm_srv = false;
uint32_t tunnel_prewarm_min = 0;
diff --git a/mgmt/RecordsConfig.cc b/mgmt/RecordsConfig.cc
index b63e0523c2b..a3752ea8359 100644
--- a/mgmt/RecordsConfig.cc
+++ b/mgmt/RecordsConfig.cc
@@ -1395,6 +1395,8 @@ static const RecordElement RecordsConfig[] =
,
{RECT_CONFIG, "proxy.config.http2.max_rst_stream_frames_per_minute", RECD_INT, "200", RECU_DYNAMIC, RR_NULL, RECC_STR, "^[0-9]+$", RECA_NULL}
,
+ {RECT_CONFIG, "proxy.config.http2.max_continuation_frames_per_minute", RECD_INT, "120", RECU_DYNAMIC, RR_NULL, RECC_STR, "^[0-9]+$", RECA_NULL}
+ ,
{RECT_CONFIG, "proxy.config.http2.min_avg_window_update", RECD_FLOAT, "2560.0", RECU_DYNAMIC, RR_NULL, RECC_NULL, nullptr, RECA_NULL}
,
{RECT_CONFIG, "proxy.config.http2.header_table_size_limit", RECD_INT, "65536", RECU_DYNAMIC, RR_NULL, RECC_STR, "^[0-9]+$", RECA_NULL}
diff --git a/proxy/http2/HTTP2.cc b/proxy/http2/HTTP2.cc
index 04813d2212b..a3a5a0ac781 100644
--- a/proxy/http2/HTTP2.cc
+++ b/proxy/http2/HTTP2.cc
@@ -85,6 +85,8 @@ static const char *const HTTP2_STAT_MAX_PRIORITY_FRAMES_PER_MINUTE_EXCEEDED_NAME
"proxy.process.http2.max_priority_frames_per_minute_exceeded";
static const char *const HTTP2_STAT_MAX_RST_STREAM_FRAMES_PER_MINUTE_EXCEEDED_NAME =
"proxy.process.http2.max_rst_stream_frames_per_minute_exceeded";
+static const char *const HTTP2_STAT_MAX_CONTINUATION_FRAMES_PER_MINUTE_EXCEEDED_NAME =
+ "proxy.process.http2.max_continuation_frames_per_minute_exceeded";
static const char *const HTTP2_STAT_INSUFFICIENT_AVG_WINDOW_UPDATE_NAME = "proxy.process.http2.insufficient_avg_window_update";
static const char *const HTTP2_STAT_MAX_CONCURRENT_STREAMS_EXCEEDED_IN_NAME =
"proxy.process.http2.max_concurrent_streams_exceeded_in";
@@ -798,36 +800,37 @@ http2_decode_header_blocks(HTTPHdr *hdr, const uint8_t *buf_start, const uint32_
}
// Initialize this subsystem with librecords configs (for now)
-uint32_t Http2::max_concurrent_streams_in = 100;
-uint32_t Http2::min_concurrent_streams_in = 10;
-uint32_t Http2::max_active_streams_in = 0;
-bool Http2::throttling = false;
-uint32_t Http2::stream_priority_enabled = 0;
-uint32_t Http2::initial_window_size = 65535;
-uint32_t Http2::max_frame_size = 16384;
-uint32_t Http2::header_table_size = 4096;
-uint32_t Http2::max_header_list_size = 4294967295;
-uint32_t Http2::accept_no_activity_timeout = 120;
-uint32_t Http2::no_activity_timeout_in = 120;
-uint32_t Http2::active_timeout_in = 0;
-uint32_t Http2::push_diary_size = 256;
-uint32_t Http2::zombie_timeout_in = 0;
-float Http2::stream_error_rate_threshold = 0.1;
-uint32_t Http2::stream_error_sampling_threshold = 10;
-uint32_t Http2::max_settings_per_frame = 7;
-uint32_t Http2::max_settings_per_minute = 14;
-uint32_t Http2::max_settings_frames_per_minute = 14;
-uint32_t Http2::max_ping_frames_per_minute = 60;
-uint32_t Http2::max_priority_frames_per_minute = 120;
-uint32_t Http2::max_rst_stream_frames_per_minute = 200;
-float Http2::min_avg_window_update = 2560.0;
-uint32_t Http2::con_slow_log_threshold = 0;
-uint32_t Http2::stream_slow_log_threshold = 0;
-uint32_t Http2::header_table_size_limit = 65536;
-uint32_t Http2::write_buffer_block_size = 262144;
-float Http2::write_size_threshold = 0.5;
-uint32_t Http2::write_time_threshold = 100;
-uint32_t Http2::buffer_water_mark = 0;
+uint32_t Http2::max_concurrent_streams_in = 100;
+uint32_t Http2::min_concurrent_streams_in = 10;
+uint32_t Http2::max_active_streams_in = 0;
+bool Http2::throttling = false;
+uint32_t Http2::stream_priority_enabled = 0;
+uint32_t Http2::initial_window_size = 65535;
+uint32_t Http2::max_frame_size = 16384;
+uint32_t Http2::header_table_size = 4096;
+uint32_t Http2::max_header_list_size = 4294967295;
+uint32_t Http2::accept_no_activity_timeout = 120;
+uint32_t Http2::no_activity_timeout_in = 120;
+uint32_t Http2::active_timeout_in = 0;
+uint32_t Http2::push_diary_size = 256;
+uint32_t Http2::zombie_timeout_in = 0;
+float Http2::stream_error_rate_threshold = 0.1;
+uint32_t Http2::stream_error_sampling_threshold = 10;
+uint32_t Http2::max_settings_per_frame = 7;
+uint32_t Http2::max_settings_per_minute = 14;
+uint32_t Http2::max_settings_frames_per_minute = 14;
+uint32_t Http2::max_ping_frames_per_minute = 60;
+uint32_t Http2::max_priority_frames_per_minute = 120;
+uint32_t Http2::max_rst_stream_frames_per_minute = 200;
+uint32_t Http2::max_continuation_frames_per_minute = 120;
+float Http2::min_avg_window_update = 2560.0;
+uint32_t Http2::con_slow_log_threshold = 0;
+uint32_t Http2::stream_slow_log_threshold = 0;
+uint32_t Http2::header_table_size_limit = 65536;
+uint32_t Http2::write_buffer_block_size = 262144;
+float Http2::write_size_threshold = 0.5;
+uint32_t Http2::write_time_threshold = 100;
+uint32_t Http2::buffer_water_mark = 0;
void
Http2::init()
@@ -853,6 +856,7 @@ Http2::init()
REC_EstablishStaticConfigInt32U(max_ping_frames_per_minute, "proxy.config.http2.max_ping_frames_per_minute");
REC_EstablishStaticConfigInt32U(max_priority_frames_per_minute, "proxy.config.http2.max_priority_frames_per_minute");
REC_EstablishStaticConfigInt32U(max_rst_stream_frames_per_minute, "proxy.config.http2.max_rst_stream_frames_per_minute");
+ REC_EstablishStaticConfigInt32U(max_continuation_frames_per_minute, "proxy.config.http2.max_continuation_frames_per_minute");
REC_EstablishStaticConfigFloat(min_avg_window_update, "proxy.config.http2.min_avg_window_update");
REC_EstablishStaticConfigInt32U(con_slow_log_threshold, "proxy.config.http2.connection.slow.log.threshold");
REC_EstablishStaticConfigInt32U(stream_slow_log_threshold, "proxy.config.http2.stream.slow.log.threshold");
@@ -923,6 +927,8 @@ Http2::init()
static_cast<int>(HTTP2_STAT_MAX_PRIORITY_FRAMES_PER_MINUTE_EXCEEDED), RecRawStatSyncSum);
RecRegisterRawStat(http2_rsb, RECT_PROCESS, HTTP2_STAT_MAX_RST_STREAM_FRAMES_PER_MINUTE_EXCEEDED_NAME, RECD_INT, RECP_PERSISTENT,
static_cast<int>(HTTP2_STAT_MAX_RST_STREAM_FRAMES_PER_MINUTE_EXCEEDED), RecRawStatSyncSum);
+ RecRegisterRawStat(http2_rsb, RECT_PROCESS, HTTP2_STAT_MAX_CONTINUATION_FRAMES_PER_MINUTE_EXCEEDED_NAME, RECD_INT,
+ RECP_PERSISTENT, static_cast<int>(HTTP2_STAT_MAX_CONTINUATION_FRAMES_PER_MINUTE_EXCEEDED), RecRawStatSyncSum);
RecRegisterRawStat(http2_rsb, RECT_PROCESS, HTTP2_STAT_INSUFFICIENT_AVG_WINDOW_UPDATE_NAME, RECD_INT, RECP_PERSISTENT,
static_cast<int>(HTTP2_STAT_INSUFFICIENT_AVG_WINDOW_UPDATE), RecRawStatSyncSum);
RecRegisterRawStat(http2_rsb, RECT_PROCESS, HTTP2_STAT_MAX_CONCURRENT_STREAMS_EXCEEDED_IN_NAME, RECD_INT, RECP_PERSISTENT,
diff --git a/proxy/http2/HTTP2.h b/proxy/http2/HTTP2.h
index 5847865a9a4..857b199c05d 100644
--- a/proxy/http2/HTTP2.h
+++ b/proxy/http2/HTTP2.h
@@ -105,6 +105,7 @@ enum {
HTTP2_STAT_MAX_PING_FRAMES_PER_MINUTE_EXCEEDED,
HTTP2_STAT_MAX_PRIORITY_FRAMES_PER_MINUTE_EXCEEDED,
HTTP2_STAT_MAX_RST_STREAM_FRAMES_PER_MINUTE_EXCEEDED,
+ HTTP2_STAT_MAX_CONTINUATION_FRAMES_PER_MINUTE_EXCEEDED,
HTTP2_STAT_INSUFFICIENT_AVG_WINDOW_UPDATE,
HTTP2_STAT_MAX_CONCURRENT_STREAMS_EXCEEDED_IN,
HTTP2_STAT_MAX_CONCURRENT_STREAMS_EXCEEDED_OUT,
@@ -404,6 +405,7 @@ class Http2
static uint32_t max_ping_frames_per_minute;
static uint32_t max_priority_frames_per_minute;
static uint32_t max_rst_stream_frames_per_minute;
+ static uint32_t max_continuation_frames_per_minute;
static float min_avg_window_update;
static uint32_t con_slow_log_threshold;
static uint32_t stream_slow_log_threshold;
diff --git a/proxy/http2/Http2ConnectionState.cc b/proxy/http2/Http2ConnectionState.cc
index b36e5c11793..b089048eb1d 100644
--- a/proxy/http2/Http2ConnectionState.cc
+++ b/proxy/http2/Http2ConnectionState.cc
@@ -924,6 +924,18 @@ rcv_continuation_frame(Http2ConnectionState &cstate, const Http2Frame &frame)
}
}
+ // Update CONTINUATION frame count per minute.
+ cstate.increment_received_continuation_frame_count();
+ // Close this connection if its CONTINUATION frame count exceeds a limit.
+ if (cstate.configured_max_continuation_frames_per_minute != 0 &&
+ cstate.get_received_continuation_frame_count() > cstate.configured_max_continuation_frames_per_minute) {
+ HTTP2_INCREMENT_THREAD_DYN_STAT(HTTP2_STAT_MAX_CONTINUATION_FRAMES_PER_MINUTE_EXCEEDED, this_ethread());
+ Http2StreamDebug(cstate.session, stream_id, "Observed too frequent CONTINUATION frames: %u frames within a last minute",
+ cstate.get_received_continuation_frame_count());
+ return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_ENHANCE_YOUR_CALM,
+ "reset too frequent CONTINUATION frames");
+ }
+
uint32_t header_blocks_offset = stream->header_blocks_length;
stream->header_blocks_length += payload_length;
@@ -1088,10 +1100,11 @@ Http2ConnectionState::init(Http2CommonSession *ssn)
dependency_tree = new DependencyTree(Http2::max_concurrent_streams_in);
}
- configured_max_settings_frames_per_minute = Http2::max_settings_frames_per_minute;
- configured_max_ping_frames_per_minute = Http2::max_ping_frames_per_minute;
- configured_max_priority_frames_per_minute = Http2::max_priority_frames_per_minute;
- configured_max_rst_stream_frames_per_minute = Http2::max_rst_stream_frames_per_minute;
+ configured_max_settings_frames_per_minute = Http2::max_settings_frames_per_minute;
+ configured_max_ping_frames_per_minute = Http2::max_ping_frames_per_minute;
+ configured_max_priority_frames_per_minute = Http2::max_priority_frames_per_minute;
+ configured_max_rst_stream_frames_per_minute = Http2::max_rst_stream_frames_per_minute;
+ configured_max_continuation_frames_per_minute = Http2::max_continuation_frames_per_minute;
if (auto snis = dynamic_cast<TLSSNISupport *>(session->get_netvc()); snis) {
if (snis->hints_from_sni.http2_max_settings_frames_per_minute.has_value()) {
configured_max_settings_frames_per_minute = snis->hints_from_sni.http2_max_settings_frames_per_minute.value();
@@ -1105,6 +1118,9 @@ Http2ConnectionState::init(Http2CommonSession *ssn)
if (snis->hints_from_sni.http2_max_rst_stream_frames_per_minute.has_value()) {
configured_max_rst_stream_frames_per_minute = snis->hints_from_sni.http2_max_rst_stream_frames_per_minute.value();
}
+ if (snis->hints_from_sni.http2_max_continuation_frames_per_minute.has_value()) {
+ configured_max_continuation_frames_per_minute = snis->hints_from_sni.http2_max_continuation_frames_per_minute.value();
+ }
}
_cop = ActivityCop<Http2Stream>(this->mutex, &stream_list, 1);
@@ -2140,6 +2156,18 @@ Http2ConnectionState::get_received_rst_stream_frame_count()
return this->_received_rst_stream_frame_counter.get_count();
}
+void
+Http2ConnectionState::increment_received_continuation_frame_count()
+{
+ this->_received_continuation_frame_counter.increment();
+}
+
+uint32_t
+Http2ConnectionState::get_received_continuation_frame_count()
+{
+ return this->_received_continuation_frame_counter.get_count();
+}
+
// Return min_concurrent_streams_in when current client streams number is larger than max_active_streams_in.
// Main purpose of this is preventing DDoS Attacks.
unsigned
diff --git a/proxy/http2/Http2ConnectionState.h b/proxy/http2/Http2ConnectionState.h
index 76d2e2a8e17..fff7763f2a1 100644
--- a/proxy/http2/Http2ConnectionState.h
+++ b/proxy/http2/Http2ConnectionState.h
@@ -102,10 +102,11 @@ class Http2ConnectionState : public Continuation
Http2ConnectionSettings server_settings;
Http2ConnectionSettings client_settings;
- uint32_t configured_max_settings_frames_per_minute = 0;
- uint32_t configured_max_ping_frames_per_minute = 0;
- uint32_t configured_max_priority_frames_per_minute = 0;
- uint32_t configured_max_rst_stream_frames_per_minute = 0;
+ uint32_t configured_max_settings_frames_per_minute = 0;
+ uint32_t configured_max_ping_frames_per_minute = 0;
+ uint32_t configured_max_priority_frames_per_minute = 0;
+ uint32_t configured_max_rst_stream_frames_per_minute = 0;
+ uint32_t configured_max_continuation_frames_per_minute = 0;
void init(Http2CommonSession *ssn);
void send_connection_preface();
@@ -174,6 +175,8 @@ class Http2ConnectionState : public Continuation
uint32_t get_received_priority_frame_count();
void increment_received_rst_stream_frame_count();
uint32_t get_received_rst_stream_frame_count();
+ void increment_received_continuation_frame_count();
+ uint32_t get_received_continuation_frame_count();
ssize_t client_rwnd() const;
Http2ErrorCode increment_client_rwnd(size_t amount);
@@ -220,6 +223,7 @@ class Http2ConnectionState : public Continuation
Http2FrequencyCounter _received_ping_frame_counter;
Http2FrequencyCounter _received_priority_frame_counter;
Http2FrequencyCounter _received_rst_stream_frame_counter;
+ Http2FrequencyCounter _received_continuation_frame_counter;
// NOTE: Id of stream which MUST receive CONTINUATION frame.
// - [RFC 7540] 6.2 HEADERS
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。