gfe-relnote: Close QUIC connection is there are too many (> 1000) buffered control frames in control frame manager. Protected by gfe2_reloadable_flag_quic_add_upper_limit_of_buffered_control_frames.

PiperOrigin-RevId: 261002263
Change-Id: I4dd92d5c1ea159d05cf35719f1a7ccc36f7b3fd3
diff --git a/quic/core/quic_control_frame_manager.cc b/quic/core/quic_control_frame_manager.cc
index 511ef2b..ac4488b 100644
--- a/quic/core/quic_control_frame_manager.cc
+++ b/quic/core/quic_control_frame_manager.cc
@@ -14,11 +14,25 @@
 
 namespace quic {
 
+namespace {
+
+// The maximum number of buffered control frames which are waiting to be ACKed
+// or sent for the first time.
+const size_t kMaxNumControlFrames = 1000;
+
+}  // namespace
+
 QuicControlFrameManager::QuicControlFrameManager(QuicSession* session)
     : last_control_frame_id_(kInvalidControlFrameId),
       least_unacked_(1),
       least_unsent_(1),
-      session_(session) {}
+      session_(session),
+      add_upper_limit_(GetQuicReloadableFlag(
+          quic_add_upper_limit_of_buffered_control_frames)) {
+  if (add_upper_limit_) {
+    QUIC_RELOADABLE_FLAG_COUNT(quic_add_upper_limit_of_buffered_control_frames);
+  }
+}
 
 QuicControlFrameManager::~QuicControlFrameManager() {
   while (!control_frames_.empty()) {
@@ -30,6 +44,15 @@
 void QuicControlFrameManager::WriteOrBufferQuicFrame(QuicFrame frame) {
   const bool had_buffered_frames = HasBufferedFrames();
   control_frames_.emplace_back(frame);
+  if (add_upper_limit_ && control_frames_.size() > kMaxNumControlFrames) {
+    session_->connection()->CloseConnection(
+        QUIC_TOO_MANY_BUFFERED_CONTROL_FRAMES,
+        QuicStrCat("More than ", kMaxNumControlFrames,
+                   "buffered control frames, least_unacked: ", least_unacked_,
+                   ", least_unsent_: ", least_unsent_),
+        ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
+    return;
+  }
   if (had_buffered_frames) {
     return;
   }
@@ -101,6 +124,15 @@
   }
   control_frames_.emplace_back(
       QuicFrame(QuicPingFrame(++last_control_frame_id_)));
+  if (add_upper_limit_ && control_frames_.size() > kMaxNumControlFrames) {
+    session_->connection()->CloseConnection(
+        QUIC_TOO_MANY_BUFFERED_CONTROL_FRAMES,
+        QuicStrCat("More than ", kMaxNumControlFrames,
+                   "buffered control frames, least_unacked: ", least_unacked_,
+                   ", least_unsent_: ", least_unsent_),
+        ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
+    return;
+  }
   WriteBufferedFrames();
 }
 
@@ -172,6 +204,9 @@
   }
   if (!QuicContainsKey(pending_retransmissions_, id)) {
     pending_retransmissions_[id] = true;
+    QUIC_BUG_IF(pending_retransmissions_.size() > control_frames_.size())
+        << "least_unacked_: " << least_unacked_
+        << ", least_unsent_: " << least_unsent_;
   }
 }