blob: e83fc3b1760ca25f84ad70bc69a213fab72cd920 [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 <cstdint>
#include <string>
#include "absl/container/flat_hash_map.h"
#include "quic/core/frames/quic_frame.h"
#include "quic/core/quic_connection_id.h"
#include "quic/core/quic_error_codes.h"
#include "quic/core/quic_types.h"
#include "common/quiche_circular_deque.h"
#include "common/quiche_linked_hash_map.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:
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;
~QuicControlFrameManager();
// Tries to send a WINDOW_UPDATE_FRAME. Buffers the frame if it cannot be sent
// immediately.
void WriteOrBufferRstStream(QuicControlFrameId id, QuicResetStreamError 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(QuicResetStreamError error,
QuicStreamId stream_id);
// Tries to send an HANDSHAKE_DONE frame. The frame is buffered if it can not
// be sent immediately.
void WriteOrBufferHandshakeDone();
// Tries to send an AckFrequencyFrame. The frame is buffered if it cannot be
// sent immediately.
void WriteOrBufferAckFrequency(
const QuicAckFrequencyFrame& ack_frequency_frame);
// Tries to send a NEW_CONNECTION_ID frame. The frame is buffered if it cannot
// be sent immediately.
void WriteOrBufferNewConnectionId(
const QuicConnectionId& connection_id, uint64_t sequence_number,
uint64_t retire_prior_to,
const StatelessResetToken& stateless_reset_token);
// Tries to send a RETIRE_CONNNECTION_ID frame. The frame is buffered if it
// cannot be sent immediately.
void WriteOrBufferRetireConnectionId(uint64_t sequence_number);
// Tries to send a NEW_TOKEN frame. Buffers the frame if it cannot be sent
// immediately.
void WriteOrBufferNewToken(absl::string_view token);
// 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, TransmissionType type);
// 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);
quiche::QuicheCircularDeque<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.
quiche::QuicheLinkedHashMap<QuicControlFrameId, bool>
pending_retransmissions_;
DelegateInterface* delegate_;
// Last sent window update frame for each stream.
absl::flat_hash_map<QuicStreamId, QuicControlFrameId> window_update_frames_;
};
} // namespace quic
#endif // QUICHE_QUIC_CORE_QUIC_CONTROL_FRAME_MANAGER_H_