Project import generated by Copybara.
PiperOrigin-RevId: 237361882
Change-Id: I109a68f44db867b20f8c6a7732b0ce657133e52a
diff --git a/quic/core/quic_control_frame_manager.h b/quic/core/quic_control_frame_manager.h
new file mode 100644
index 0000000..618f3f9
--- /dev/null
+++ b/quic/core/quic_control_frame_manager.h
@@ -0,0 +1,152 @@
+// 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 "net/third_party/quiche/src/quic/core/frames/quic_frame.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_containers.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_string.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 QuicString& 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 STREAM_ID_BLOCKED Frame. Buffers the frame if it cannot be
+ // sent immediately.
+ void WriteOrBufferStreamIdBlocked(QuicStreamId id);
+
+ // Tries to send a MAX_STREAM_ID Frame. Buffers the frame if it cannot be sent
+ // immediately.
+ void WriteOrBufferMaxStreamId(QuicStreamId id);
+
+ // 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_;
+};
+
+} // namespace quic
+
+#endif // QUICHE_QUIC_CORE_QUIC_CONTROL_FRAME_MANAGER_H_