xref: /aosp_15_r20/external/cronet/net/third_party/quiche/src/quiche/quic/core/legacy_quic_stream_id_manager.cc (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 #include "quiche/quic/core/legacy_quic_stream_id_manager.h"
5 
6 #include "quiche/quic/core/quic_session.h"
7 #include "quiche/quic/core/quic_types.h"
8 #include "quiche/quic/core/quic_utils.h"
9 #include "quiche/quic/core/quic_versions.h"
10 
11 namespace quic {
12 
LegacyQuicStreamIdManager(Perspective perspective,QuicTransportVersion transport_version,size_t max_open_outgoing_streams,size_t max_open_incoming_streams)13 LegacyQuicStreamIdManager::LegacyQuicStreamIdManager(
14     Perspective perspective, QuicTransportVersion transport_version,
15     size_t max_open_outgoing_streams, size_t max_open_incoming_streams)
16     : perspective_(perspective),
17       transport_version_(transport_version),
18       max_open_outgoing_streams_(max_open_outgoing_streams),
19       max_open_incoming_streams_(max_open_incoming_streams),
20       next_outgoing_stream_id_(QuicUtils::GetFirstBidirectionalStreamId(
21           transport_version_, perspective_)),
22       largest_peer_created_stream_id_(
23           perspective_ == Perspective::IS_SERVER
24               ? (QuicVersionUsesCryptoFrames(transport_version_)
25                      ? QuicUtils::GetInvalidStreamId(transport_version_)
26                      : QuicUtils::GetCryptoStreamId(transport_version_))
27               : QuicUtils::GetInvalidStreamId(transport_version_)),
28       num_open_incoming_streams_(0),
29       num_open_outgoing_streams_(0) {}
30 
~LegacyQuicStreamIdManager()31 LegacyQuicStreamIdManager::~LegacyQuicStreamIdManager() {}
32 
CanOpenNextOutgoingStream() const33 bool LegacyQuicStreamIdManager::CanOpenNextOutgoingStream() const {
34   QUICHE_DCHECK_LE(num_open_outgoing_streams_, max_open_outgoing_streams_);
35   QUIC_DLOG_IF(INFO, num_open_outgoing_streams_ == max_open_outgoing_streams_)
36       << "Failed to create a new outgoing stream. "
37       << "Already " << num_open_outgoing_streams_ << " open.";
38   return num_open_outgoing_streams_ < max_open_outgoing_streams_;
39 }
40 
CanOpenIncomingStream() const41 bool LegacyQuicStreamIdManager::CanOpenIncomingStream() const {
42   return num_open_incoming_streams_ < max_open_incoming_streams_;
43 }
44 
MaybeIncreaseLargestPeerStreamId(const QuicStreamId stream_id)45 bool LegacyQuicStreamIdManager::MaybeIncreaseLargestPeerStreamId(
46     const QuicStreamId stream_id) {
47   available_streams_.erase(stream_id);
48 
49   if (largest_peer_created_stream_id_ !=
50           QuicUtils::GetInvalidStreamId(transport_version_) &&
51       stream_id <= largest_peer_created_stream_id_) {
52     return true;
53   }
54 
55   // Check if the new number of available streams would cause the number of
56   // available streams to exceed the limit.  Note that the peer can create
57   // only alternately-numbered streams.
58   size_t additional_available_streams =
59       (stream_id - largest_peer_created_stream_id_) / 2 - 1;
60   if (largest_peer_created_stream_id_ ==
61       QuicUtils::GetInvalidStreamId(transport_version_)) {
62     additional_available_streams = (stream_id + 1) / 2 - 1;
63   }
64   size_t new_num_available_streams =
65       GetNumAvailableStreams() + additional_available_streams;
66   if (new_num_available_streams > MaxAvailableStreams()) {
67     QUIC_DLOG(INFO) << perspective_
68                     << "Failed to create a new incoming stream with id:"
69                     << stream_id << ".  There are already "
70                     << GetNumAvailableStreams()
71                     << " streams available, which would become "
72                     << new_num_available_streams << ", which exceeds the limit "
73                     << MaxAvailableStreams() << ".";
74     return false;
75   }
76   QuicStreamId first_available_stream = largest_peer_created_stream_id_ + 2;
77   if (largest_peer_created_stream_id_ ==
78       QuicUtils::GetInvalidStreamId(transport_version_)) {
79     first_available_stream = QuicUtils::GetFirstBidirectionalStreamId(
80         transport_version_, QuicUtils::InvertPerspective(perspective_));
81   }
82   for (QuicStreamId id = first_available_stream; id < stream_id; id += 2) {
83     available_streams_.insert(id);
84   }
85   largest_peer_created_stream_id_ = stream_id;
86 
87   return true;
88 }
89 
GetNextOutgoingStreamId()90 QuicStreamId LegacyQuicStreamIdManager::GetNextOutgoingStreamId() {
91   QuicStreamId id = next_outgoing_stream_id_;
92   next_outgoing_stream_id_ += 2;
93   return id;
94 }
95 
ActivateStream(bool is_incoming)96 void LegacyQuicStreamIdManager::ActivateStream(bool is_incoming) {
97   if (is_incoming) {
98     ++num_open_incoming_streams_;
99     return;
100   }
101   ++num_open_outgoing_streams_;
102 }
103 
OnStreamClosed(bool is_incoming)104 void LegacyQuicStreamIdManager::OnStreamClosed(bool is_incoming) {
105   if (is_incoming) {
106     QUIC_BUG_IF(quic_bug_12720_1, num_open_incoming_streams_ == 0);
107     --num_open_incoming_streams_;
108     return;
109   }
110   QUIC_BUG_IF(quic_bug_12720_2, num_open_outgoing_streams_ == 0);
111   --num_open_outgoing_streams_;
112 }
113 
IsAvailableStream(QuicStreamId id) const114 bool LegacyQuicStreamIdManager::IsAvailableStream(QuicStreamId id) const {
115   if (!IsIncomingStream(id)) {
116     // Stream IDs under next_ougoing_stream_id_ are either open or previously
117     // open but now closed.
118     return id >= next_outgoing_stream_id_;
119   }
120   // For peer created streams, we also need to consider available streams.
121   return largest_peer_created_stream_id_ ==
122              QuicUtils::GetInvalidStreamId(transport_version_) ||
123          id > largest_peer_created_stream_id_ ||
124          available_streams_.contains(id);
125 }
126 
IsIncomingStream(QuicStreamId id) const127 bool LegacyQuicStreamIdManager::IsIncomingStream(QuicStreamId id) const {
128   return id % 2 != next_outgoing_stream_id_ % 2;
129 }
130 
GetNumAvailableStreams() const131 size_t LegacyQuicStreamIdManager::GetNumAvailableStreams() const {
132   return available_streams_.size();
133 }
134 
MaxAvailableStreams() const135 size_t LegacyQuicStreamIdManager::MaxAvailableStreams() const {
136   return max_open_incoming_streams_ * kMaxAvailableStreamsMultiplier;
137 }
138 
139 }  // namespace quic
140