Make QuicControlFrameManager talk to QuicSession via a delegate.

This makes the ownership clear and prevents the control frame manager from unnecessarily accessing the session.

Refactor only. not protected.

PiperOrigin-RevId: 321460931
Change-Id: Iff7f35f9626a46f6afe37f9a02c8ff653aa9437e
diff --git a/quic/core/quic_control_frame_manager.cc b/quic/core/quic_control_frame_manager.cc
index ba00b88..ba00015 100644
--- a/quic/core/quic_control_frame_manager.cc
+++ b/quic/core/quic_control_frame_manager.cc
@@ -24,14 +24,11 @@
 
 }  // namespace
 
-#define ENDPOINT \
-  (session_->perspective() == Perspective::IS_SERVER ? "Server: " : "Client: ")
-
 QuicControlFrameManager::QuicControlFrameManager(QuicSession* session)
     : last_control_frame_id_(kInvalidControlFrameId),
       least_unacked_(1),
       least_unsent_(1),
-      session_(session) {}
+      delegate_(session) {}
 
 QuicControlFrameManager::~QuicControlFrameManager() {
   while (!control_frames_.empty()) {
@@ -44,13 +41,12 @@
   const bool had_buffered_frames = HasBufferedFrames();
   control_frames_.emplace_back(frame);
   if (control_frames_.size() > kMaxNumControlFrames) {
-    session_->connection()->CloseConnection(
+    delegate_->OnControlFrameManagerError(
         QUIC_TOO_MANY_BUFFERED_CONTROL_FRAMES,
         quiche::QuicheStrCat(
             "More than ", kMaxNumControlFrames,
             "buffered control frames, least_unacked: ", least_unacked_,
-            ", least_unsent_: ", least_unsent_),
-        ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
+            ", least_unsent_: ", least_unsent_));
     return;
   }
   if (had_buffered_frames) {
@@ -131,13 +127,12 @@
   control_frames_.emplace_back(
       QuicFrame(QuicPingFrame(++last_control_frame_id_)));
   if (control_frames_.size() > kMaxNumControlFrames) {
-    session_->connection()->CloseConnection(
+    delegate_->OnControlFrameManagerError(
         QUIC_TOO_MANY_BUFFERED_CONTROL_FRAMES,
         quiche::QuicheStrCat(
             "More than ", kMaxNumControlFrames,
             "buffered control frames, least_unacked: ", least_unacked_,
-            ", least_unsent_: ", least_unsent_),
-        ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
+            ", least_unsent_: ", least_unsent_));
     return;
   }
   WriteBufferedFrames();
@@ -167,9 +162,8 @@
   if (id > least_unsent_) {
     QUIC_BUG << "Try to send control frames out of order, id: " << id
              << " least_unsent: " << least_unsent_;
-    session_->connection()->CloseConnection(
-        QUIC_INTERNAL_ERROR, "Try to send control frames out of order",
-        ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
+    delegate_->OnControlFrameManagerError(
+        QUIC_INTERNAL_ERROR, "Try to send control frames out of order");
     return;
   }
   ++least_unsent_;
@@ -198,9 +192,8 @@
   }
   if (id >= least_unsent_) {
     QUIC_BUG << "Try to mark unsent control frame as lost";
-    session_->connection()->CloseConnection(
-        QUIC_INTERNAL_ERROR, "Try to mark unsent control frame as lost",
-        ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
+    delegate_->OnControlFrameManagerError(
+        QUIC_INTERNAL_ERROR, "Try to mark unsent control frame as lost");
     return;
   }
   if (id < least_unacked_ ||
@@ -267,9 +260,8 @@
   }
   if (id >= least_unsent_) {
     QUIC_BUG << "Try to retransmit unsent control frame";
-    session_->connection()->CloseConnection(
-        QUIC_INTERNAL_ERROR, "Try to retransmit unsent control frame",
-        ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
+    delegate_->OnControlFrameManagerError(
+        QUIC_INTERNAL_ERROR, "Try to retransmit unsent control frame");
     return false;
   }
   if (id < least_unacked_ ||
@@ -281,7 +273,7 @@
   QuicFrame copy = CopyRetransmittableControlFrame(frame);
   QUIC_DVLOG(1) << "control frame manager is forced to retransmit frame: "
                 << frame;
-  if (session_->WriteControlFrame(copy, type)) {
+  if (delegate_->WriteControlFrame(copy, type)) {
     return true;
   }
   DeleteFrame(&copy);
@@ -289,13 +281,11 @@
 }
 
 void QuicControlFrameManager::WriteBufferedFrames() {
-  DCHECK(session_->connection()->connected())
-      << ENDPOINT << "Try to write control frames when connection is closed.";
   while (HasBufferedFrames()) {
     QuicFrame frame_to_send =
         control_frames_.at(least_unsent_ - least_unacked_);
     QuicFrame copy = CopyRetransmittableControlFrame(frame_to_send);
-    if (!session_->WriteControlFrame(copy, NOT_RETRANSMISSION)) {
+    if (!delegate_->WriteControlFrame(copy, NOT_RETRANSMISSION)) {
       // Connection is write blocked.
       DeleteFrame(&copy);
       break;
@@ -308,7 +298,7 @@
   while (HasPendingRetransmission()) {
     QuicFrame pending = NextPendingRetransmission();
     QuicFrame copy = CopyRetransmittableControlFrame(pending);
-    if (!session_->WriteControlFrame(copy, LOSS_RETRANSMISSION)) {
+    if (!delegate_->WriteControlFrame(copy, LOSS_RETRANSMISSION)) {
       // Connection is write blocked.
       DeleteFrame(&copy);
       break;
@@ -324,9 +314,8 @@
   }
   if (id >= least_unsent_) {
     QUIC_BUG << "Try to ack unsent control frame";
-    session_->connection()->CloseConnection(
-        QUIC_INTERNAL_ERROR, "Try to ack unsent control frame",
-        ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
+    delegate_->OnControlFrameManagerError(QUIC_INTERNAL_ERROR,
+                                          "Try to ack unsent control frame");
     return false;
   }
   if (id < least_unacked_ ||
diff --git a/quic/core/quic_control_frame_manager.h b/quic/core/quic_control_frame_manager.h
index ffd378c..7615754 100644
--- a/quic/core/quic_control_frame_manager.h
+++ b/quic/core/quic_control_frame_manager.h
@@ -30,6 +30,18 @@
 // which need to be retransmitted.
 class QUIC_EXPORT_PRIVATE QuicControlFrameManager {
  public:
+  class QUIC_EXPORT_PRIVATE DelegateInterface {
+   public:
+    virtual ~DelegateInterface() = default;
+
+    // Notifies the delegate of errors.
+    virtual void OnControlFrameManagerError(QuicErrorCode error_code,
+                                            std::string error_details) = 0;
+
+    virtual bool WriteControlFrame(const QuicFrame& frame,
+                                   TransmissionType type) = 0;
+  };
+
   explicit QuicControlFrameManager(QuicSession* session);
   QuicControlFrameManager(const QuicControlFrameManager& other) = delete;
   QuicControlFrameManager(QuicControlFrameManager&& other) = delete;
@@ -146,8 +158,7 @@
   // Lost control frames waiting to be retransmitted.
   QuicLinkedHashMap<QuicControlFrameId, bool> pending_retransmissions_;
 
-  // Pointer to the owning QuicSession object.
-  QuicSession* session_;
+  DelegateInterface* delegate_;
 
   // Last sent window update frame for each stream.
   QuicSmallMap<QuicStreamId, QuicControlFrameId, 10> window_update_frames_;
diff --git a/quic/core/quic_session.cc b/quic/core/quic_session.cc
index e09decf..d63006c 100644
--- a/quic/core/quic_session.cc
+++ b/quic/core/quic_session.cc
@@ -739,8 +739,17 @@
   return bytes_consumed;
 }
 
+void QuicSession::OnControlFrameManagerError(QuicErrorCode error_code,
+                                             std::string error_details) {
+  connection_->CloseConnection(
+      error_code, error_details,
+      ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
+}
+
 bool QuicSession::WriteControlFrame(const QuicFrame& frame,
                                     TransmissionType type) {
+  DCHECK(connection()->connected())
+      << ENDPOINT << "Try to write control frames when connection is closed.";
   SetTransmissionType(type);
   return connection_->SendControlFrame(frame);
 }
diff --git a/quic/core/quic_session.h b/quic/core/quic_session.h
index 54a1426..88e4412 100644
--- a/quic/core/quic_session.h
+++ b/quic/core/quic_session.h
@@ -53,7 +53,8 @@
       public QuicStreamFrameDataProducer,
       public QuicStreamIdManager::DelegateInterface,
       public HandshakerDelegateInterface,
-      public StreamDelegateInterface {
+      public StreamDelegateInterface,
+      public QuicControlFrameManager::DelegateInterface {
  public:
   // An interface from the session to the entity owning the session.
   // This lets the session notify its owner (the Dispatcher) when the connection
@@ -199,10 +200,15 @@
   // Called when message with |message_id| is considered as lost.
   virtual void OnMessageLost(QuicMessageId message_id);
 
+  // QuicControlFrameManager::DelegateInterface
+  // Close the connection on error.
+  void OnControlFrameManagerError(QuicErrorCode error_code,
+                                  std::string error_details) override;
   // Called by control frame manager when it wants to write control frames to
   // the peer. Returns true if |frame| is consumed, false otherwise. The frame
   // will be sent in specified transmission |type|.
-  bool WriteControlFrame(const QuicFrame& frame, TransmissionType type);
+  bool WriteControlFrame(const QuicFrame& frame,
+                         TransmissionType type) override;
 
   // Called by stream to send RST_STREAM (and STOP_SENDING).
   virtual void SendRstStream(QuicStreamId id,
diff --git a/quic/core/stream_delegate_interface.h b/quic/core/stream_delegate_interface.h
index de77bad..9f27147 100644
--- a/quic/core/stream_delegate_interface.h
+++ b/quic/core/stream_delegate_interface.h
@@ -14,6 +14,8 @@
 
 class QuicStream;
 
+// Pure virtual class to get notified when particular QuicStream events
+// occurred.
 class QUIC_EXPORT_PRIVATE StreamDelegateInterface {
  public:
   virtual ~StreamDelegateInterface() {}