blob: 4261f43982bd947a881f602bebd748d8a78fb380 [file] [log] [blame]
QUICHE teama6ef0a62019-03-07 20:34:33 -05001// 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
vasilvvcb250b92021-02-10 18:14:12 -08007#include "absl/container/flat_hash_set.h"
vasilvv9edb31e2020-12-03 19:32:58 -08008#include "absl/strings/str_cat.h"
QUICHE team5be974e2020-12-29 18:35:24 -05009#include "quic/core/frames/quic_frame.h"
10#include "quic/core/quic_types.h"
11#include "quic/core/quic_versions.h"
12#include "quic/platform/api/quic_logging.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -050013
14namespace quic {
15
16namespace test {
17class QuicSessionPeer;
18class QuicStreamIdManagerPeer;
19} // namespace test
20
renjietang53570412020-04-07 06:32:17 -070021// This class manages the stream ids for IETF QUIC.
QUICHE teama6ef0a62019-03-07 20:34:33 -050022class QUIC_EXPORT_PRIVATE QuicStreamIdManager {
23 public:
dschinazif25169a2019-10-23 08:12:18 -070024 class QUIC_EXPORT_PRIVATE DelegateInterface {
rcha8b56e42019-09-20 10:41:48 -070025 public:
26 virtual ~DelegateInterface() = default;
27
rcha8b56e42019-09-20 10:41:48 -070028 // Send a MAX_STREAMS frame.
29 virtual void SendMaxStreams(QuicStreamCount stream_count,
30 bool unidirectional) = 0;
rcha8b56e42019-09-20 10:41:48 -070031 };
32
33 QuicStreamIdManager(DelegateInterface* delegate,
fkastenholz3c4eabf2019-04-22 07:49:59 -070034 bool unidirectional,
rcha8b56e42019-09-20 10:41:48 -070035 Perspective perspective,
renjietang40038f52020-04-08 11:30:31 -070036 ParsedQuicVersion version,
fkastenholz3c4eabf2019-04-22 07:49:59 -070037 QuicStreamCount max_allowed_outgoing_streams,
38 QuicStreamCount max_allowed_incoming_streams);
QUICHE teama6ef0a62019-03-07 20:34:33 -050039
40 ~QuicStreamIdManager();
41
42 // Generate a string suitable for sending to the log/etc to show current state
43 // of the stream ID manager.
vasilvvc48c8712019-03-11 13:38:16 -070044 std::string DebugString() const {
vasilvv9edb31e2020-12-03 19:32:58 -080045 return absl::StrCat(
fkastenholz3c4eabf2019-04-22 07:49:59 -070046 " { unidirectional_: ", unidirectional_,
renjietang7b51ec02020-04-07 16:07:09 -070047 ", perspective: ", perspective_,
fkastenholz3c4eabf2019-04-22 07:49:59 -070048 ", outgoing_max_streams_: ", outgoing_max_streams_,
49 ", next_outgoing_stream_id_: ", next_outgoing_stream_id_,
50 ", outgoing_stream_count_: ", outgoing_stream_count_,
fkastenholz3c4eabf2019-04-22 07:49:59 -070051 ", incoming_actual_max_streams_: ", incoming_actual_max_streams_,
52 ", incoming_advertised_max_streams_: ",
53 incoming_advertised_max_streams_,
fkastenholz3c4eabf2019-04-22 07:49:59 -070054 ", incoming_stream_count_: ", incoming_stream_count_,
55 ", available_streams_.size(): ", available_streams_.size(),
56 ", largest_peer_created_stream_id_: ", largest_peer_created_stream_id_,
renjietang22305852020-04-06 15:05:18 -070057 " }");
QUICHE teama6ef0a62019-03-07 20:34:33 -050058 }
59
renjietang7133ea92020-04-01 12:49:36 -070060 // 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);
QUICHE teama6ef0a62019-03-07 20:34:33 -050064
renjietang7b51ec02020-04-07 16:07:09 -070065 // Returns whether the next outgoing stream ID can be allocated or not.
fayang769172b2020-03-19 14:27:39 -070066 bool CanOpenNextOutgoingStream() const;
QUICHE teama6ef0a62019-03-07 20:34:33 -050067
fkastenholz3c4eabf2019-04-22 07:49:59 -070068 // Generate and send a MAX_STREAMS frame.
69 void SendMaxStreamsFrame();
QUICHE teama6ef0a62019-03-07 20:34:33 -050070
fkastenholz3c4eabf2019-04-22 07:49:59 -070071 // 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.
QUICHE teama6ef0a62019-03-07 20:34:33 -050075 void OnStreamClosed(QuicStreamId stream_id);
76
fkastenholz3c4eabf2019-04-22 07:49:59 -070077 // Returns the next outgoing stream id. Applications must call
renjietang7b51ec02020-04-07 16:07:09 -070078 // CanOpenNextOutgoingStream() first.
QUICHE teama6ef0a62019-03-07 20:34:33 -050079 QuicStreamId GetNextOutgoingStreamId();
80
renjietang52e13382019-12-16 15:58:04 -080081 void SetMaxOpenIncomingStreams(QuicStreamCount max_open_streams);
QUICHE teama6ef0a62019-03-07 20:34:33 -050082
renjietangab9039a2020-03-30 14:53:19 -070083 // 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);
QUICHE teama6ef0a62019-03-07 20:34:33 -050087
fkastenholz3c4eabf2019-04-22 07:49:59 -070088 // Checks if the incoming stream ID exceeds the MAX_STREAMS limit. If the
renjietang7b51ec02020-04-07 16:07:09 -070089 // limit is exceeded, populates |error_detials| and returns false.
renjietang7133ea92020-04-01 12:49:36 -070090 bool MaybeIncreaseLargestPeerStreamId(const QuicStreamId stream_id,
91 std::string* error_details);
QUICHE teama6ef0a62019-03-07 20:34:33 -050092
93 // Returns true if |id| is still available.
94 bool IsAvailableStream(QuicStreamId id) const;
95
renjietang52e13382019-12-16 15:58:04 -080096 QuicStreamCount incoming_initial_max_open_streams() const {
fkastenholz3c4eabf2019-04-22 07:49:59 -070097 return incoming_initial_max_open_streams_;
QUICHE teama6ef0a62019-03-07 20:34:33 -050098 }
fkastenholz3c4eabf2019-04-22 07:49:59 -070099
QUICHE teama6ef0a62019-03-07 20:34:33 -0500100 QuicStreamId next_outgoing_stream_id() const {
101 return next_outgoing_stream_id_;
102 }
103
fkastenholz3c4eabf2019-04-22 07:49:59 -0700104 // Number of streams that the peer believes that it can still create.
renjietang40038f52020-04-08 11:30:31 -0700105 QuicStreamCount available_incoming_streams() const;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500106
renjietang686ce582019-10-17 14:28:16 -0700107 QuicStreamId largest_peer_created_stream_id() const {
108 return largest_peer_created_stream_id_;
109 }
110
fkastenholz3c4eabf2019-04-22 07:49:59 -0700111 QuicStreamCount outgoing_max_streams() const { return outgoing_max_streams_; }
112 QuicStreamCount incoming_actual_max_streams() const {
113 return incoming_actual_max_streams_;
114 }
115 QuicStreamCount incoming_advertised_max_streams() const {
116 return incoming_advertised_max_streams_;
117 }
renjietang40038f52020-04-08 11:30:31 -0700118 QuicStreamCount outgoing_stream_count() const {
119 return outgoing_stream_count_;
120 }
fkastenholz3c4eabf2019-04-22 07:49:59 -0700121
QUICHE teama6ef0a62019-03-07 20:34:33 -0500122 private:
123 friend class test::QuicSessionPeer;
124 friend class test::QuicStreamIdManagerPeer;
125
fkastenholz3c4eabf2019-04-22 07:49:59 -0700126 // Check whether the MAX_STREAMS window has opened up enough and, if so,
127 // generate and send a MAX_STREAMS frame.
128 void MaybeSendMaxStreamsFrame();
129
130 // Get what should be the first incoming/outgoing stream ID that
131 // this stream id manager will manage, taking into account directionality and
132 // client/server perspective.
133 QuicStreamId GetFirstOutgoingStreamId() const;
134 QuicStreamId GetFirstIncomingStreamId() const;
135
QUICHE teama6ef0a62019-03-07 20:34:33 -0500136 // Back reference to the session containing this Stream ID Manager.
rcha8b56e42019-09-20 10:41:48 -0700137 DelegateInterface* delegate_;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500138
fkastenholz3c4eabf2019-04-22 07:49:59 -0700139 // Whether this stream id manager is for unidrectional (true) or bidirectional
140 // (false) streams.
rcha8b56e42019-09-20 10:41:48 -0700141 const bool unidirectional_;
142
143 // Is this manager a client or a server.
144 const Perspective perspective_;
145
renjietang40038f52020-04-08 11:30:31 -0700146 // QUIC version used for this manager.
147 const ParsedQuicVersion version_;
rcha8b56e42019-09-20 10:41:48 -0700148
renjietang7b51ec02020-04-07 16:07:09 -0700149 // The number of streams that this node can initiate.
150 // This limit is first set when config is negotiated, but may be updated upon
151 // receiving MAX_STREAMS frame.
fkastenholz3c4eabf2019-04-22 07:49:59 -0700152 QuicStreamCount outgoing_max_streams_;
153
QUICHE teama6ef0a62019-03-07 20:34:33 -0500154 // The ID to use for the next outgoing stream.
155 QuicStreamId next_outgoing_stream_id_;
156
fkastenholz3c4eabf2019-04-22 07:49:59 -0700157 // The number of outgoing streams that have ever been opened, including those
158 // that have been closed. This number must never be larger than
159 // outgoing_max_streams_.
160 QuicStreamCount outgoing_stream_count_;
161
fkastenholz3c4eabf2019-04-22 07:49:59 -0700162 // FOR INCOMING STREAMS
163
renjietang7b51ec02020-04-07 16:07:09 -0700164 // The actual maximum number of streams that can be opened by the peer.
fkastenholz3c4eabf2019-04-22 07:49:59 -0700165 QuicStreamCount incoming_actual_max_streams_;
renjietang7b51ec02020-04-07 16:07:09 -0700166 // Max incoming stream number that has been advertised to the peer and is <=
167 // incoming_actual_max_streams_. It is set to incoming_actual_max_streams_
168 // when a MAX_STREAMS is sent.
fkastenholz3c4eabf2019-04-22 07:49:59 -0700169 QuicStreamCount incoming_advertised_max_streams_;
170
171 // Initial maximum on the number of open streams allowed.
172 QuicStreamCount incoming_initial_max_open_streams_;
173
renjietang7b51ec02020-04-07 16:07:09 -0700174 // The number of streams that have been created, including open ones and
175 // closed ones.
fkastenholz3c4eabf2019-04-22 07:49:59 -0700176 QuicStreamCount incoming_stream_count_;
177
QUICHE teama6ef0a62019-03-07 20:34:33 -0500178 // Set of stream ids that are less than the largest stream id that has been
179 // received, but are nonetheless available to be created.
vasilvvcb250b92021-02-10 18:14:12 -0800180 absl::flat_hash_set<QuicStreamId> available_streams_;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500181
182 QuicStreamId largest_peer_created_stream_id_;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500183};
QUICHE teama6ef0a62019-03-07 20:34:33 -0500184} // namespace quic
185
186#endif // QUICHE_QUIC_CORE_QUIC_STREAM_ID_MANAGER_H_