blob: 6e8f13a10d635cd353fbee034d9de4aa925f008a [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#include "net/third_party/quiche/src/quic/core/legacy_quic_stream_id_manager.h"
5
6#include "net/third_party/quiche/src/quic/core/quic_session.h"
ianswettc1f530d2019-12-10 05:14:30 -08007#include "net/third_party/quiche/src/quic/core/quic_types.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -05008#include "net/third_party/quiche/src/quic/core/quic_utils.h"
ianswettc1f530d2019-12-10 05:14:30 -08009#include "net/third_party/quiche/src/quic/core/quic_versions.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -050010#include "net/third_party/quiche/src/quic/platform/api/quic_map_util.h"
dmcardlecf0bfcf2019-12-13 08:08:21 -080011#include "net/third_party/quiche/src/common/platform/api/quiche_str_cat.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -050012
13namespace quic {
14
QUICHE teama6ef0a62019-03-07 20:34:33 -050015LegacyQuicStreamIdManager::LegacyQuicStreamIdManager(
ianswettc1f530d2019-12-10 05:14:30 -080016 Perspective perspective,
17 QuicTransportVersion transport_version,
QUICHE teama6ef0a62019-03-07 20:34:33 -050018 size_t max_open_outgoing_streams,
19 size_t max_open_incoming_streams)
ianswettc1f530d2019-12-10 05:14:30 -080020 : perspective_(perspective),
21 transport_version_(transport_version),
QUICHE teama6ef0a62019-03-07 20:34:33 -050022 max_open_outgoing_streams_(max_open_outgoing_streams),
23 max_open_incoming_streams_(max_open_incoming_streams),
renjietangd1d00852019-09-06 10:43:12 -070024 next_outgoing_stream_id_(
ianswettc1f530d2019-12-10 05:14:30 -080025 QuicUtils::GetFirstBidirectionalStreamId(transport_version_,
26 perspective_)),
QUICHE teama6ef0a62019-03-07 20:34:33 -050027 largest_peer_created_stream_id_(
ianswettc1f530d2019-12-10 05:14:30 -080028 perspective_ == Perspective::IS_SERVER
29 ? (QuicVersionUsesCryptoFrames(transport_version_)
30 ? QuicUtils::GetInvalidStreamId(transport_version_)
31 : QuicUtils::GetCryptoStreamId(transport_version_))
32 : QuicUtils::GetInvalidStreamId(transport_version_)) {}
QUICHE teama6ef0a62019-03-07 20:34:33 -050033
ianswettc1f530d2019-12-10 05:14:30 -080034LegacyQuicStreamIdManager::~LegacyQuicStreamIdManager() {}
QUICHE teama6ef0a62019-03-07 20:34:33 -050035
36bool LegacyQuicStreamIdManager::CanOpenNextOutgoingStream(
37 size_t current_num_open_outgoing_streams) const {
38 if (current_num_open_outgoing_streams >= max_open_outgoing_streams_) {
39 QUIC_DLOG(INFO) << "Failed to create a new outgoing stream. "
40 << "Already " << current_num_open_outgoing_streams
41 << " open.";
42 return false;
43 }
44 return true;
45}
46
47bool LegacyQuicStreamIdManager::CanOpenIncomingStream(
48 size_t current_num_open_incoming_streams) const {
49 // Check if the new number of open streams would cause the number of
50 // open streams to exceed the limit.
51 return current_num_open_incoming_streams < max_open_incoming_streams_;
52}
53
54bool LegacyQuicStreamIdManager::MaybeIncreaseLargestPeerStreamId(
55 const QuicStreamId stream_id) {
56 available_streams_.erase(stream_id);
57
58 if (largest_peer_created_stream_id_ !=
ianswettc1f530d2019-12-10 05:14:30 -080059 QuicUtils::GetInvalidStreamId(transport_version_) &&
QUICHE teama6ef0a62019-03-07 20:34:33 -050060 stream_id <= largest_peer_created_stream_id_) {
61 return true;
62 }
63
64 // Check if the new number of available streams would cause the number of
65 // available streams to exceed the limit. Note that the peer can create
66 // only alternately-numbered streams.
67 size_t additional_available_streams =
68 (stream_id - largest_peer_created_stream_id_) / 2 - 1;
nharperf309f3e2019-06-26 21:49:26 -070069 if (largest_peer_created_stream_id_ ==
ianswettc1f530d2019-12-10 05:14:30 -080070 QuicUtils::GetInvalidStreamId(transport_version_)) {
nharperf309f3e2019-06-26 21:49:26 -070071 additional_available_streams = (stream_id + 1) / 2 - 1;
72 }
QUICHE teama6ef0a62019-03-07 20:34:33 -050073 size_t new_num_available_streams =
74 GetNumAvailableStreams() + additional_available_streams;
75 if (new_num_available_streams > MaxAvailableStreams()) {
ianswettc1f530d2019-12-10 05:14:30 -080076 QUIC_DLOG(INFO) << perspective_
QUICHE teama6ef0a62019-03-07 20:34:33 -050077 << "Failed to create a new incoming stream with id:"
78 << stream_id << ". There are already "
79 << GetNumAvailableStreams()
80 << " streams available, which would become "
81 << new_num_available_streams << ", which exceeds the limit "
82 << MaxAvailableStreams() << ".";
QUICHE teama6ef0a62019-03-07 20:34:33 -050083 return false;
84 }
nharperf309f3e2019-06-26 21:49:26 -070085 QuicStreamId first_available_stream = largest_peer_created_stream_id_ + 2;
86 if (largest_peer_created_stream_id_ ==
ianswettc1f530d2019-12-10 05:14:30 -080087 QuicUtils::GetInvalidStreamId(transport_version_)) {
nharperf309f3e2019-06-26 21:49:26 -070088 first_available_stream = QuicUtils::GetFirstBidirectionalStreamId(
ianswettc1f530d2019-12-10 05:14:30 -080089 transport_version_, QuicUtils::InvertPerspective(perspective_));
nharperf309f3e2019-06-26 21:49:26 -070090 }
91 for (QuicStreamId id = first_available_stream; id < stream_id; id += 2) {
QUICHE teama6ef0a62019-03-07 20:34:33 -050092 available_streams_.insert(id);
93 }
94 largest_peer_created_stream_id_ = stream_id;
95
96 return true;
97}
98
99QuicStreamId LegacyQuicStreamIdManager::GetNextOutgoingStreamId() {
100 QuicStreamId id = next_outgoing_stream_id_;
101 next_outgoing_stream_id_ += 2;
102 return id;
103}
104
105bool LegacyQuicStreamIdManager::IsAvailableStream(QuicStreamId id) const {
106 if (!IsIncomingStream(id)) {
107 // Stream IDs under next_ougoing_stream_id_ are either open or previously
108 // open but now closed.
109 return id >= next_outgoing_stream_id_;
110 }
111 // For peer created streams, we also need to consider available streams.
112 return largest_peer_created_stream_id_ ==
ianswettc1f530d2019-12-10 05:14:30 -0800113 QuicUtils::GetInvalidStreamId(transport_version_) ||
QUICHE teama6ef0a62019-03-07 20:34:33 -0500114 id > largest_peer_created_stream_id_ ||
115 QuicContainsKey(available_streams_, id);
116}
117
118bool LegacyQuicStreamIdManager::IsIncomingStream(QuicStreamId id) const {
119 return id % 2 != next_outgoing_stream_id_ % 2;
120}
121
122size_t LegacyQuicStreamIdManager::GetNumAvailableStreams() const {
123 return available_streams_.size();
124}
125
126size_t LegacyQuicStreamIdManager::MaxAvailableStreams() const {
127 return max_open_incoming_streams_ * kMaxAvailableStreamsMultiplier;
128}
129
130} // namespace quic