blob: 54ca4794405fcee7aab374bbe9c79dec6abc44b8 [file] [log] [blame]
// 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_