xref: /aosp_15_r20/external/cronet/net/third_party/quiche/src/quiche/quic/core/quic_stream_id_manager.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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