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