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(©); @@ -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(©); 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(©); 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() {}