| // 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. | |
| #ifndef QUICHE_QUIC_CORE_QUIC_STREAM_ID_MANAGER_H_ | |
| #define QUICHE_QUIC_CORE_QUIC_STREAM_ID_MANAGER_H_ | |
| #include "absl/container/flat_hash_set.h" | |
| #include "absl/strings/str_cat.h" | |
| #include "quiche/quic/core/frames/quic_frame.h" | |
| #include "quiche/quic/core/quic_types.h" | |
| #include "quiche/quic/core/quic_versions.h" | |
| #include "quiche/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 { | |
| public: | |
| class QUIC_EXPORT_PRIVATE DelegateInterface { | |
| public: | |
| 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); | |
| ~QuicStreamIdManager(); | |
| // 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_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_; | |
| } | |
| private: | |
| 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_; | |
| // FOR INCOMING STREAMS | |
| // 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 | |
| #endif // QUICHE_QUIC_CORE_QUIC_STREAM_ID_MANAGER_H_ |