1 // Copyright (c) 2018 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 #ifndef QUICHE_QUIC_CORE_QUIC_STREAM_ID_MANAGER_H_ 5 #define QUICHE_QUIC_CORE_QUIC_STREAM_ID_MANAGER_H_ 6 7 #include "absl/container/flat_hash_set.h" 8 #include "absl/strings/str_cat.h" 9 #include "quiche/quic/core/frames/quic_frame.h" 10 #include "quiche/quic/core/quic_types.h" 11 #include "quiche/quic/core/quic_versions.h" 12 #include "quiche/quic/platform/api/quic_logging.h" 13 14 namespace quic { 15 16 namespace test { 17 class QuicSessionPeer; 18 class QuicStreamIdManagerPeer; 19 } // namespace test 20 21 // This class manages the stream ids for IETF QUIC. 22 class QUICHE_EXPORT QuicStreamIdManager { 23 public: 24 class QUICHE_EXPORT DelegateInterface { 25 public: 26 virtual ~DelegateInterface() = default; 27 28 // Returns true if a MAX_STREAMS frame can be sent. 29 virtual bool CanSendMaxStreams() = 0; 30 // Send a MAX_STREAMS frame. 31 virtual void SendMaxStreams(QuicStreamCount stream_count, 32 bool unidirectional) = 0; 33 }; 34 35 QuicStreamIdManager(DelegateInterface* delegate, bool unidirectional, 36 Perspective perspective, ParsedQuicVersion version, 37 QuicStreamCount max_allowed_outgoing_streams, 38 QuicStreamCount max_allowed_incoming_streams); 39 40 ~QuicStreamIdManager(); 41 42 // Generate a string suitable for sending to the log/etc to show current state 43 // of the stream ID manager. DebugString()44 std::string DebugString() const { 45 return absl::StrCat( 46 " { unidirectional_: ", unidirectional_, 47 ", perspective: ", perspective_, 48 ", outgoing_max_streams_: ", outgoing_max_streams_, 49 ", next_outgoing_stream_id_: ", next_outgoing_stream_id_, 50 ", outgoing_stream_count_: ", outgoing_stream_count_, 51 ", incoming_actual_max_streams_: ", incoming_actual_max_streams_, 52 ", incoming_advertised_max_streams_: ", 53 incoming_advertised_max_streams_, 54 ", incoming_stream_count_: ", incoming_stream_count_, 55 ", available_streams_.size(): ", available_streams_.size(), 56 ", largest_peer_created_stream_id_: ", largest_peer_created_stream_id_, 57 " }"); 58 } 59 60 // Processes the STREAMS_BLOCKED frame. If error is encountered, populates 61 // |error_details| and returns false. 62 bool OnStreamsBlockedFrame(const QuicStreamsBlockedFrame& frame, 63 std::string* error_details); 64 65 // Returns whether the next outgoing stream ID can be allocated or not. 66 bool CanOpenNextOutgoingStream() const; 67 68 // Generate and send a MAX_STREAMS frame. 69 void SendMaxStreamsFrame(); 70 71 // Invoked to deal with releasing a stream. Does nothing if the stream is 72 // outgoing. If the stream is incoming, the number of streams that the peer 73 // can open will be updated and a MAX_STREAMS frame, informing the peer of 74 // the additional streams, may be sent. 75 void OnStreamClosed(QuicStreamId stream_id); 76 77 // Returns the next outgoing stream id. Applications must call 78 // CanOpenNextOutgoingStream() first. 79 QuicStreamId GetNextOutgoingStreamId(); 80 81 void SetMaxOpenIncomingStreams(QuicStreamCount max_open_streams); 82 83 // Called on |max_open_streams| outgoing streams can be created because of 1) 84 // config negotiated or 2) MAX_STREAMS received. Returns true if new 85 // streams can be created. 86 bool MaybeAllowNewOutgoingStreams(QuicStreamCount max_open_streams); 87 88 // Checks if the incoming stream ID exceeds the MAX_STREAMS limit. If the 89 // limit is exceeded, populates |error_detials| and returns false. 90 bool MaybeIncreaseLargestPeerStreamId(const QuicStreamId stream_id, 91 std::string* error_details); 92 93 // Returns true if |id| is still available. 94 bool IsAvailableStream(QuicStreamId id) const; 95 96 // Once called, the incoming max streams limit will never be increased. StopIncreasingIncomingMaxStreams()97 void StopIncreasingIncomingMaxStreams() { 98 stop_increasing_incoming_max_streams_ = true; 99 } 100 incoming_initial_max_open_streams()101 QuicStreamCount incoming_initial_max_open_streams() const { 102 return incoming_initial_max_open_streams_; 103 } 104 next_outgoing_stream_id()105 QuicStreamId next_outgoing_stream_id() const { 106 return next_outgoing_stream_id_; 107 } 108 109 // Number of streams that the peer believes that it can still create. 110 QuicStreamCount available_incoming_streams() const; 111 largest_peer_created_stream_id()112 QuicStreamId largest_peer_created_stream_id() const { 113 return largest_peer_created_stream_id_; 114 } 115 outgoing_max_streams()116 QuicStreamCount outgoing_max_streams() const { return outgoing_max_streams_; } incoming_actual_max_streams()117 QuicStreamCount incoming_actual_max_streams() const { 118 return incoming_actual_max_streams_; 119 } incoming_advertised_max_streams()120 QuicStreamCount incoming_advertised_max_streams() const { 121 return incoming_advertised_max_streams_; 122 } outgoing_stream_count()123 QuicStreamCount outgoing_stream_count() const { 124 return outgoing_stream_count_; 125 } 126 127 // Check whether the MAX_STREAMS window has opened up enough and, if so, 128 // generate and send a MAX_STREAMS frame. 129 void MaybeSendMaxStreamsFrame(); 130 131 private: 132 friend class test::QuicSessionPeer; 133 friend class test::QuicStreamIdManagerPeer; 134 135 // Get what should be the first incoming/outgoing stream ID that 136 // this stream id manager will manage, taking into account directionality and 137 // client/server perspective. 138 QuicStreamId GetFirstOutgoingStreamId() const; 139 QuicStreamId GetFirstIncomingStreamId() const; 140 141 // Back reference to the session containing this Stream ID Manager. 142 DelegateInterface* delegate_; 143 144 // Whether this stream id manager is for unidrectional (true) or bidirectional 145 // (false) streams. 146 const bool unidirectional_; 147 148 // Is this manager a client or a server. 149 const Perspective perspective_; 150 151 // QUIC version used for this manager. 152 const ParsedQuicVersion version_; 153 154 // The number of streams that this node can initiate. 155 // This limit is first set when config is negotiated, but may be updated upon 156 // receiving MAX_STREAMS frame. 157 QuicStreamCount outgoing_max_streams_; 158 159 // The ID to use for the next outgoing stream. 160 QuicStreamId next_outgoing_stream_id_; 161 162 // The number of outgoing streams that have ever been opened, including those 163 // that have been closed. This number must never be larger than 164 // outgoing_max_streams_. 165 QuicStreamCount outgoing_stream_count_; 166 167 // FOR INCOMING STREAMS 168 169 // The actual maximum number of streams that can be opened by the peer. 170 QuicStreamCount incoming_actual_max_streams_; 171 // Max incoming stream number that has been advertised to the peer and is <= 172 // incoming_actual_max_streams_. It is set to incoming_actual_max_streams_ 173 // when a MAX_STREAMS is sent. 174 QuicStreamCount incoming_advertised_max_streams_; 175 176 // Initial maximum on the number of open streams allowed. 177 QuicStreamCount incoming_initial_max_open_streams_; 178 179 // The number of streams that have been created, including open ones and 180 // closed ones. 181 QuicStreamCount incoming_stream_count_; 182 183 // Set of stream ids that are less than the largest stream id that has been 184 // received, but are nonetheless available to be created. 185 absl::flat_hash_set<QuicStreamId> available_streams_; 186 187 QuicStreamId largest_peer_created_stream_id_; 188 189 // If true, then the stream limit will never be increased. 190 bool stop_increasing_incoming_max_streams_; 191 }; 192 193 } // namespace quic 194 195 #endif // QUICHE_QUIC_CORE_QUIC_STREAM_ID_MANAGER_H_ 196