blob: 4261f43982bd947a881f602bebd748d8a78fb380 [file] [log] [blame]
// Copyright (c) 2018 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.
#include "absl/container/flat_hash_set.h"
#include "absl/strings/str_cat.h"
#include "quic/core/frames/quic_frame.h"
#include "quic/core/quic_types.h"
#include "quic/core/quic_versions.h"
#include "quic/platform/api/quic_logging.h"
namespace quic {
namespace test {
class QuicSessionPeer;
class QuicStreamIdManagerPeer;
} // namespace test
// This class manages the stream ids for IETF QUIC.
class QUIC_EXPORT_PRIVATE QuicStreamIdManager {
class QUIC_EXPORT_PRIVATE DelegateInterface {
virtual ~DelegateInterface() = default;
// Send a MAX_STREAMS frame.
virtual void SendMaxStreams(QuicStreamCount stream_count,
bool unidirectional) = 0;
QuicStreamIdManager(DelegateInterface* delegate,
bool unidirectional,
Perspective perspective,
ParsedQuicVersion version,
QuicStreamCount max_allowed_outgoing_streams,
QuicStreamCount max_allowed_incoming_streams);
// Generate a string suitable for sending to the log/etc to show current state
// of the stream ID manager.
std::string DebugString() const {
return absl::StrCat(
" { unidirectional_: ", unidirectional_,
", perspective: ", perspective_,
", outgoing_max_streams_: ", outgoing_max_streams_,
", next_outgoing_stream_id_: ", next_outgoing_stream_id_,
", outgoing_stream_count_: ", outgoing_stream_count_,
", incoming_actual_max_streams_: ", incoming_actual_max_streams_,
", incoming_advertised_max_streams_: ",
", incoming_stream_count_: ", incoming_stream_count_,
", available_streams_.size(): ", available_streams_.size(),
", largest_peer_created_stream_id_: ", largest_peer_created_stream_id_,
" }");
// Processes the STREAMS_BLOCKED frame. If error is encountered, populates
// |error_details| and returns false.
bool OnStreamsBlockedFrame(const QuicStreamsBlockedFrame& frame,
std::string* error_details);
// Returns whether the next outgoing stream ID can be allocated or not.
bool CanOpenNextOutgoingStream() const;
// Generate and send a MAX_STREAMS frame.
void SendMaxStreamsFrame();
// Invoked to deal with releasing a stream. Does nothing if the stream is
// outgoing. If the stream is incoming, the number of streams that the peer
// can open will be updated and a MAX_STREAMS frame, informing the peer of
// the additional streams, may be sent.
void OnStreamClosed(QuicStreamId stream_id);
// Returns the next outgoing stream id. Applications must call
// CanOpenNextOutgoingStream() first.
QuicStreamId GetNextOutgoingStreamId();
void SetMaxOpenIncomingStreams(QuicStreamCount max_open_streams);
// Called on |max_open_streams| outgoing streams can be created because of 1)
// config negotiated or 2) MAX_STREAMS received. Returns true if new
// streams can be created.
bool MaybeAllowNewOutgoingStreams(QuicStreamCount max_open_streams);
// Checks if the incoming stream ID exceeds the MAX_STREAMS limit. If the
// limit is exceeded, populates |error_detials| and returns false.
bool MaybeIncreaseLargestPeerStreamId(const QuicStreamId stream_id,
std::string* error_details);
// Returns true if |id| is still available.
bool IsAvailableStream(QuicStreamId id) const;
QuicStreamCount incoming_initial_max_open_streams() const {
return incoming_initial_max_open_streams_;
QuicStreamId next_outgoing_stream_id() const {
return next_outgoing_stream_id_;
// Number of streams that the peer believes that it can still create.
QuicStreamCount available_incoming_streams() const;
QuicStreamId largest_peer_created_stream_id() const {
return largest_peer_created_stream_id_;
QuicStreamCount outgoing_max_streams() const { return outgoing_max_streams_; }
QuicStreamCount incoming_actual_max_streams() const {
return incoming_actual_max_streams_;
QuicStreamCount incoming_advertised_max_streams() const {
return incoming_advertised_max_streams_;
QuicStreamCount outgoing_stream_count() const {
return outgoing_stream_count_;
friend class test::QuicSessionPeer;
friend class test::QuicStreamIdManagerPeer;
// Check whether the MAX_STREAMS window has opened up enough and, if so,
// generate and send a MAX_STREAMS frame.
void MaybeSendMaxStreamsFrame();
// Get what should be the first incoming/outgoing stream ID that
// this stream id manager will manage, taking into account directionality and
// client/server perspective.
QuicStreamId GetFirstOutgoingStreamId() const;
QuicStreamId GetFirstIncomingStreamId() const;
// Back reference to the session containing this Stream ID Manager.
DelegateInterface* delegate_;
// Whether this stream id manager is for unidrectional (true) or bidirectional
// (false) streams.
const bool unidirectional_;
// Is this manager a client or a server.
const Perspective perspective_;
// QUIC version used for this manager.
const ParsedQuicVersion version_;
// The number of streams that this node can initiate.
// This limit is first set when config is negotiated, but may be updated upon
// receiving MAX_STREAMS frame.
QuicStreamCount outgoing_max_streams_;
// The ID to use for the next outgoing stream.
QuicStreamId next_outgoing_stream_id_;
// The number of outgoing streams that have ever been opened, including those
// that have been closed. This number must never be larger than
// outgoing_max_streams_.
QuicStreamCount outgoing_stream_count_;
// The actual maximum number of streams that can be opened by the peer.
QuicStreamCount incoming_actual_max_streams_;
// Max incoming stream number that has been advertised to the peer and is <=
// incoming_actual_max_streams_. It is set to incoming_actual_max_streams_
// when a MAX_STREAMS is sent.
QuicStreamCount incoming_advertised_max_streams_;
// Initial maximum on the number of open streams allowed.
QuicStreamCount incoming_initial_max_open_streams_;
// The number of streams that have been created, including open ones and
// closed ones.
QuicStreamCount incoming_stream_count_;
// Set of stream ids that are less than the largest stream id that has been
// received, but are nonetheless available to be created.
absl::flat_hash_set<QuicStreamId> available_streams_;
QuicStreamId largest_peer_created_stream_id_;
} // namespace quic