| // 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_frames. |
| const bool add_upper_limit_; |
| }; |
| |
| } // namespace quic |
| |
| #endif // QUICHE_QUIC_CORE_QUIC_CONTROL_FRAME_MANAGER_H_ |