• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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