| // Copyright (c) 2017 The Chromium Authors. All rights reserved. | 
 | // Use of this source code is governed by a BSD-style license that can be | 
 | // found in the LICENSE file. | 
 |  | 
 | #ifndef QUICHE_QUIC_CORE_QUIC_CONTROL_FRAME_MANAGER_H_ | 
 | #define QUICHE_QUIC_CORE_QUIC_CONTROL_FRAME_MANAGER_H_ | 
 |  | 
 | #include <string> | 
 |  | 
 | #include "net/third_party/quiche/src/quic/core/frames/quic_frame.h" | 
 | #include "net/third_party/quiche/src/quic/platform/api/quic_containers.h" | 
 |  | 
 | namespace quic { | 
 |  | 
 | class QuicSession; | 
 |  | 
 | namespace test { | 
 | class QuicControlFrameManagerPeer; | 
 | }  // namespace test | 
 |  | 
 | // Control frame manager contains a list of sent control frames with valid | 
 | // control frame IDs. Control frames without valid control frame IDs include: | 
 | // (1) non-retransmittable frames (e.g., ACK_FRAME, PADDING_FRAME, | 
 | // STOP_WAITING_FRAME, etc.), (2) CONNECTION_CLOSE and IETF Quic | 
 | // APPLICATION_CLOSE frames. | 
 | // New control frames are added to the tail of the list when they are added to | 
 | // the generator. Control frames are removed from the head of the list when they | 
 | // get acked. Control frame manager also keeps track of lost control frames | 
 | // which need to be retransmitted. | 
 | class QUIC_EXPORT_PRIVATE QuicControlFrameManager { | 
 |  public: | 
 |   explicit QuicControlFrameManager(QuicSession* session); | 
 |   QuicControlFrameManager(const QuicControlFrameManager& other) = delete; | 
 |   QuicControlFrameManager(QuicControlFrameManager&& other) = delete; | 
 |   ~QuicControlFrameManager(); | 
 |  | 
 |   // Tries to send a WINDOW_UPDATE_FRAME. Buffers the frame if it cannot be sent | 
 |   // immediately. | 
 |   void WriteOrBufferRstStream(QuicControlFrameId id, | 
 |                               QuicRstStreamErrorCode error, | 
 |                               QuicStreamOffset bytes_written); | 
 |  | 
 |   // Tries to send a GOAWAY_FRAME. Buffers the frame if it cannot be sent | 
 |   // immediately. | 
 |   void WriteOrBufferGoAway(QuicErrorCode error, | 
 |                            QuicStreamId last_good_stream_id, | 
 |                            const std::string& reason); | 
 |  | 
 |   // Tries to send a WINDOW_UPDATE_FRAME. Buffers the frame if it cannot be sent | 
 |   // immediately. | 
 |   void WriteOrBufferWindowUpdate(QuicStreamId id, QuicStreamOffset byte_offset); | 
 |  | 
 |   // Tries to send a BLOCKED_FRAME. Buffers the frame if it cannot be sent | 
 |   // immediately. | 
 |   void WriteOrBufferBlocked(QuicStreamId id); | 
 |  | 
 |   // Tries to send a STREAMS_BLOCKED Frame. Buffers the frame if it cannot be | 
 |   // sent immediately. | 
 |   void WriteOrBufferStreamsBlocked(QuicStreamCount count, bool unidirectional); | 
 |  | 
 |   // Tries to send a MAX_STREAMS Frame. Buffers the frame if it cannot be sent | 
 |   // immediately. | 
 |   void WriteOrBufferMaxStreams(QuicStreamCount count, bool unidirectional); | 
 |  | 
 |   // Tries to send an IETF-QUIC STOP_SENDING frame. The frame is buffered if it | 
 |   // can not be sent immediately. | 
 |   void WriteOrBufferStopSending(uint16_t code, QuicStreamId stream_id); | 
 |  | 
 |   // Sends a PING_FRAME. Do not send PING if there is buffered frames. | 
 |   void WritePing(); | 
 |  | 
 |   // Called when |frame| gets acked. Returns true if |frame| gets acked for the | 
 |   // first time, return false otherwise. | 
 |   bool OnControlFrameAcked(const QuicFrame& frame); | 
 |  | 
 |   // Called when |frame| is considered as lost. | 
 |   void OnControlFrameLost(const QuicFrame& frame); | 
 |  | 
 |   // Called by the session when the connection becomes writable. | 
 |   void OnCanWrite(); | 
 |  | 
 |   // Retransmit |frame| if it is still outstanding. Returns false if the frame | 
 |   // does not get retransmitted because the connection is blocked. Otherwise, | 
 |   // returns true. | 
 |   bool RetransmitControlFrame(const QuicFrame& frame); | 
 |  | 
 |   // Returns true if |frame| is outstanding and waiting to be acked. Returns | 
 |   // false otherwise. | 
 |   bool IsControlFrameOutstanding(const QuicFrame& frame) const; | 
 |  | 
 |   // Returns true if there is any lost control frames waiting to be | 
 |   // retransmitted. | 
 |   bool HasPendingRetransmission() const; | 
 |  | 
 |   // Returns true if there are any lost or new control frames waiting to be | 
 |   // sent. | 
 |   bool WillingToWrite() const; | 
 |  | 
 |  private: | 
 |   friend class test::QuicControlFrameManagerPeer; | 
 |  | 
 |   // Tries to write buffered control frames to the peer. | 
 |   void WriteBufferedFrames(); | 
 |  | 
 |   // Called when |frame| is sent for the first time or gets retransmitted. | 
 |   void OnControlFrameSent(const QuicFrame& frame); | 
 |  | 
 |   // Writes pending retransmissions if any. | 
 |   void WritePendingRetransmission(); | 
 |  | 
 |   // Called when frame with |id| gets acked. Returns true if |id| gets acked for | 
 |   // the first time, return false otherwise. | 
 |   bool OnControlFrameIdAcked(QuicControlFrameId id); | 
 |  | 
 |   // Retrieves the next pending retransmission. This must only be called when | 
 |   // there are pending retransmissions. | 
 |   QuicFrame NextPendingRetransmission() const; | 
 |  | 
 |   // Returns true if there are buffered frames waiting to be sent for the first | 
 |   // time. | 
 |   bool HasBufferedFrames() const; | 
 |  | 
 |   // Writes or buffers a control frame.  Frame is buffered if there already | 
 |   // are frames waiting to be sent. If no others waiting, will try to send the | 
 |   // frame. | 
 |   void WriteOrBufferQuicFrame(QuicFrame frame); | 
 |  | 
 |   QuicDeque<QuicFrame> control_frames_; | 
 |  | 
 |   // Id of latest saved control frame. 0 if no control frame has been saved. | 
 |   QuicControlFrameId last_control_frame_id_; | 
 |  | 
 |   // The control frame at the 0th index of control_frames_. | 
 |   QuicControlFrameId least_unacked_; | 
 |  | 
 |   // ID of the least unsent control frame. | 
 |   QuicControlFrameId least_unsent_; | 
 |  | 
 |   // TODO(fayang): switch to linked_hash_set when chromium supports it. The bool | 
 |   // is not used here. | 
 |   // Lost control frames waiting to be retransmitted. | 
 |   QuicLinkedHashMap<QuicControlFrameId, bool> pending_retransmissions_; | 
 |  | 
 |   // Pointer to the owning QuicSession object. | 
 |   QuicSession* session_; | 
 |  | 
 |   // Last sent window update frame for each stream. | 
 |   QuicSmallMap<QuicStreamId, QuicControlFrameId, 10> window_update_frames_; | 
 |  | 
 |   // Latched value of quic_add_upper_limit_of_buffered_control_frames3. | 
 |   const bool add_upper_limit_; | 
 | }; | 
 |  | 
 | }  // namespace quic | 
 |  | 
 | #endif  // QUICHE_QUIC_CORE_QUIC_CONTROL_FRAME_MANAGER_H_ |