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