blob: 2ddf4b2498abf3aba753711f5e6f0deb30124efc [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.
QUICHE team5be974e2020-12-29 18:35:24 -05004#include "quic/core/legacy_quic_stream_id_manager.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -05005
QUICHE team5be974e2020-12-29 18:35:24 -05006#include "quic/core/quic_session.h"
7#include "quic/core/quic_types.h"
8#include "quic/core/quic_utils.h"
9#include "quic/core/quic_versions.h"
10#include "quic/platform/api/quic_map_util.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -050011
12namespace quic {
13
QUICHE teama6ef0a62019-03-07 20:34:33 -050014LegacyQuicStreamIdManager::LegacyQuicStreamIdManager(
ianswettc1f530d2019-12-10 05:14:30 -080015 Perspective perspective,
16 QuicTransportVersion transport_version,
QUICHE teama6ef0a62019-03-07 20:34:33 -050017 size_t max_open_outgoing_streams,
18 size_t max_open_incoming_streams)
ianswettc1f530d2019-12-10 05:14:30 -080019 : perspective_(perspective),
20 transport_version_(transport_version),
QUICHE teama6ef0a62019-03-07 20:34:33 -050021 max_open_outgoing_streams_(max_open_outgoing_streams),
22 max_open_incoming_streams_(max_open_incoming_streams),
renjietangd1d00852019-09-06 10:43:12 -070023 next_outgoing_stream_id_(
ianswettc1f530d2019-12-10 05:14:30 -080024 QuicUtils::GetFirstBidirectionalStreamId(transport_version_,
25 perspective_)),
QUICHE teama6ef0a62019-03-07 20:34:33 -050026 largest_peer_created_stream_id_(
ianswettc1f530d2019-12-10 05:14:30 -080027 perspective_ == Perspective::IS_SERVER
28 ? (QuicVersionUsesCryptoFrames(transport_version_)
29 ? QuicUtils::GetInvalidStreamId(transport_version_)
30 : QuicUtils::GetCryptoStreamId(transport_version_))
fayang01591ae2020-04-23 14:14:56 -070031 : QuicUtils::GetInvalidStreamId(transport_version_)),
32 num_open_incoming_streams_(0),
fayangbd94f4c2020-06-01 14:36:37 -070033 num_open_outgoing_streams_(0) {}
QUICHE teama6ef0a62019-03-07 20:34:33 -050034
ianswettc1f530d2019-12-10 05:14:30 -080035LegacyQuicStreamIdManager::~LegacyQuicStreamIdManager() {}
QUICHE teama6ef0a62019-03-07 20:34:33 -050036
fayangbd94f4c2020-06-01 14:36:37 -070037bool LegacyQuicStreamIdManager::CanOpenNextOutgoingStream() const {
vasilvvf8035162021-02-01 14:49:14 -080038 QUICHE_DCHECK_LE(num_open_outgoing_streams_, max_open_outgoing_streams_);
fayangbd94f4c2020-06-01 14:36:37 -070039 QUIC_DLOG_IF(INFO, num_open_outgoing_streams_ == max_open_outgoing_streams_)
40 << "Failed to create a new outgoing stream. "
41 << "Already " << num_open_outgoing_streams_ << " open.";
42 return num_open_outgoing_streams_ < max_open_outgoing_streams_;
QUICHE teama6ef0a62019-03-07 20:34:33 -050043}
44
fayangbd94f4c2020-06-01 14:36:37 -070045bool LegacyQuicStreamIdManager::CanOpenIncomingStream() const {
46 return num_open_incoming_streams_ < max_open_incoming_streams_;
QUICHE teama6ef0a62019-03-07 20:34:33 -050047}
48
49bool LegacyQuicStreamIdManager::MaybeIncreaseLargestPeerStreamId(
50 const QuicStreamId stream_id) {
51 available_streams_.erase(stream_id);
52
53 if (largest_peer_created_stream_id_ !=
ianswettc1f530d2019-12-10 05:14:30 -080054 QuicUtils::GetInvalidStreamId(transport_version_) &&
QUICHE teama6ef0a62019-03-07 20:34:33 -050055 stream_id <= largest_peer_created_stream_id_) {
56 return true;
57 }
58
59 // Check if the new number of available streams would cause the number of
60 // available streams to exceed the limit. Note that the peer can create
61 // only alternately-numbered streams.
62 size_t additional_available_streams =
63 (stream_id - largest_peer_created_stream_id_) / 2 - 1;
nharperf309f3e2019-06-26 21:49:26 -070064 if (largest_peer_created_stream_id_ ==
ianswettc1f530d2019-12-10 05:14:30 -080065 QuicUtils::GetInvalidStreamId(transport_version_)) {
nharperf309f3e2019-06-26 21:49:26 -070066 additional_available_streams = (stream_id + 1) / 2 - 1;
67 }
QUICHE teama6ef0a62019-03-07 20:34:33 -050068 size_t new_num_available_streams =
69 GetNumAvailableStreams() + additional_available_streams;
70 if (new_num_available_streams > MaxAvailableStreams()) {
ianswettc1f530d2019-12-10 05:14:30 -080071 QUIC_DLOG(INFO) << perspective_
QUICHE teama6ef0a62019-03-07 20:34:33 -050072 << "Failed to create a new incoming stream with id:"
73 << stream_id << ". There are already "
74 << GetNumAvailableStreams()
75 << " streams available, which would become "
76 << new_num_available_streams << ", which exceeds the limit "
77 << MaxAvailableStreams() << ".";
QUICHE teama6ef0a62019-03-07 20:34:33 -050078 return false;
79 }
nharperf309f3e2019-06-26 21:49:26 -070080 QuicStreamId first_available_stream = largest_peer_created_stream_id_ + 2;
81 if (largest_peer_created_stream_id_ ==
ianswettc1f530d2019-12-10 05:14:30 -080082 QuicUtils::GetInvalidStreamId(transport_version_)) {
nharperf309f3e2019-06-26 21:49:26 -070083 first_available_stream = QuicUtils::GetFirstBidirectionalStreamId(
ianswettc1f530d2019-12-10 05:14:30 -080084 transport_version_, QuicUtils::InvertPerspective(perspective_));
nharperf309f3e2019-06-26 21:49:26 -070085 }
86 for (QuicStreamId id = first_available_stream; id < stream_id; id += 2) {
QUICHE teama6ef0a62019-03-07 20:34:33 -050087 available_streams_.insert(id);
88 }
89 largest_peer_created_stream_id_ = stream_id;
90
91 return true;
92}
93
94QuicStreamId LegacyQuicStreamIdManager::GetNextOutgoingStreamId() {
95 QuicStreamId id = next_outgoing_stream_id_;
96 next_outgoing_stream_id_ += 2;
97 return id;
98}
99
fayang01591ae2020-04-23 14:14:56 -0700100void LegacyQuicStreamIdManager::ActivateStream(bool is_incoming) {
fayang01591ae2020-04-23 14:14:56 -0700101 if (is_incoming) {
102 ++num_open_incoming_streams_;
103 return;
104 }
105 ++num_open_outgoing_streams_;
106}
107
108void LegacyQuicStreamIdManager::OnStreamClosed(bool is_incoming) {
fayang01591ae2020-04-23 14:14:56 -0700109 if (is_incoming) {
QUICHE teamd6d05e52021-03-16 14:22:01 -0700110 QUIC_BUG_IF(quic_bug_12720_1, num_open_incoming_streams_ == 0);
fayang01591ae2020-04-23 14:14:56 -0700111 --num_open_incoming_streams_;
112 return;
113 }
QUICHE teamd6d05e52021-03-16 14:22:01 -0700114 QUIC_BUG_IF(quic_bug_12720_2, num_open_outgoing_streams_ == 0);
fayang01591ae2020-04-23 14:14:56 -0700115 --num_open_outgoing_streams_;
116}
117
QUICHE teama6ef0a62019-03-07 20:34:33 -0500118bool LegacyQuicStreamIdManager::IsAvailableStream(QuicStreamId id) const {
119 if (!IsIncomingStream(id)) {
120 // Stream IDs under next_ougoing_stream_id_ are either open or previously
121 // open but now closed.
122 return id >= next_outgoing_stream_id_;
123 }
124 // For peer created streams, we also need to consider available streams.
125 return largest_peer_created_stream_id_ ==
ianswettc1f530d2019-12-10 05:14:30 -0800126 QuicUtils::GetInvalidStreamId(transport_version_) ||
QUICHE teama6ef0a62019-03-07 20:34:33 -0500127 id > largest_peer_created_stream_id_ ||
128 QuicContainsKey(available_streams_, id);
129}
130
131bool LegacyQuicStreamIdManager::IsIncomingStream(QuicStreamId id) const {
132 return id % 2 != next_outgoing_stream_id_ % 2;
133}
134
135size_t LegacyQuicStreamIdManager::GetNumAvailableStreams() const {
136 return available_streams_.size();
137}
138
139size_t LegacyQuicStreamIdManager::MaxAvailableStreams() const {
140 return max_open_incoming_streams_ * kMaxAvailableStreamsMultiplier;
141}
142
143} // namespace quic