QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 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 "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" |
ianswett | c1f530d | 2019-12-10 05:14:30 -0800 | [diff] [blame] | 7 | #include "net/third_party/quiche/src/quic/core/quic_types.h" |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 8 | #include "net/third_party/quiche/src/quic/core/quic_utils.h" |
ianswett | c1f530d | 2019-12-10 05:14:30 -0800 | [diff] [blame] | 9 | #include "net/third_party/quiche/src/quic/core/quic_versions.h" |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 10 | #include "net/third_party/quiche/src/quic/platform/api/quic_map_util.h" |
dmcardle | cf0bfcf | 2019-12-13 08:08:21 -0800 | [diff] [blame] | 11 | #include "net/third_party/quiche/src/common/platform/api/quiche_str_cat.h" |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 12 | |
| 13 | namespace quic { |
| 14 | |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 15 | LegacyQuicStreamIdManager::LegacyQuicStreamIdManager( |
ianswett | c1f530d | 2019-12-10 05:14:30 -0800 | [diff] [blame] | 16 | Perspective perspective, |
| 17 | QuicTransportVersion transport_version, |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 18 | size_t max_open_outgoing_streams, |
| 19 | size_t max_open_incoming_streams) |
ianswett | c1f530d | 2019-12-10 05:14:30 -0800 | [diff] [blame] | 20 | : perspective_(perspective), |
| 21 | transport_version_(transport_version), |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 22 | max_open_outgoing_streams_(max_open_outgoing_streams), |
| 23 | max_open_incoming_streams_(max_open_incoming_streams), |
renjietang | d1d0085 | 2019-09-06 10:43:12 -0700 | [diff] [blame] | 24 | next_outgoing_stream_id_( |
ianswett | c1f530d | 2019-12-10 05:14:30 -0800 | [diff] [blame] | 25 | QuicUtils::GetFirstBidirectionalStreamId(transport_version_, |
| 26 | perspective_)), |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 27 | largest_peer_created_stream_id_( |
ianswett | c1f530d | 2019-12-10 05:14:30 -0800 | [diff] [blame] | 28 | perspective_ == Perspective::IS_SERVER |
| 29 | ? (QuicVersionUsesCryptoFrames(transport_version_) |
| 30 | ? QuicUtils::GetInvalidStreamId(transport_version_) |
| 31 | : QuicUtils::GetCryptoStreamId(transport_version_)) |
| 32 | : QuicUtils::GetInvalidStreamId(transport_version_)) {} |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 33 | |
ianswett | c1f530d | 2019-12-10 05:14:30 -0800 | [diff] [blame] | 34 | LegacyQuicStreamIdManager::~LegacyQuicStreamIdManager() {} |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 35 | |
| 36 | bool 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 | |
| 47 | bool 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 | |
| 54 | bool LegacyQuicStreamIdManager::MaybeIncreaseLargestPeerStreamId( |
| 55 | const QuicStreamId stream_id) { |
| 56 | available_streams_.erase(stream_id); |
| 57 | |
| 58 | if (largest_peer_created_stream_id_ != |
ianswett | c1f530d | 2019-12-10 05:14:30 -0800 | [diff] [blame] | 59 | QuicUtils::GetInvalidStreamId(transport_version_) && |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 60 | 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; |
nharper | f309f3e | 2019-06-26 21:49:26 -0700 | [diff] [blame] | 69 | if (largest_peer_created_stream_id_ == |
ianswett | c1f530d | 2019-12-10 05:14:30 -0800 | [diff] [blame] | 70 | QuicUtils::GetInvalidStreamId(transport_version_)) { |
nharper | f309f3e | 2019-06-26 21:49:26 -0700 | [diff] [blame] | 71 | additional_available_streams = (stream_id + 1) / 2 - 1; |
| 72 | } |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 73 | size_t new_num_available_streams = |
| 74 | GetNumAvailableStreams() + additional_available_streams; |
| 75 | if (new_num_available_streams > MaxAvailableStreams()) { |
ianswett | c1f530d | 2019-12-10 05:14:30 -0800 | [diff] [blame] | 76 | QUIC_DLOG(INFO) << perspective_ |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 77 | << "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 team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 83 | return false; |
| 84 | } |
nharper | f309f3e | 2019-06-26 21:49:26 -0700 | [diff] [blame] | 85 | QuicStreamId first_available_stream = largest_peer_created_stream_id_ + 2; |
| 86 | if (largest_peer_created_stream_id_ == |
ianswett | c1f530d | 2019-12-10 05:14:30 -0800 | [diff] [blame] | 87 | QuicUtils::GetInvalidStreamId(transport_version_)) { |
nharper | f309f3e | 2019-06-26 21:49:26 -0700 | [diff] [blame] | 88 | first_available_stream = QuicUtils::GetFirstBidirectionalStreamId( |
ianswett | c1f530d | 2019-12-10 05:14:30 -0800 | [diff] [blame] | 89 | transport_version_, QuicUtils::InvertPerspective(perspective_)); |
nharper | f309f3e | 2019-06-26 21:49:26 -0700 | [diff] [blame] | 90 | } |
| 91 | for (QuicStreamId id = first_available_stream; id < stream_id; id += 2) { |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 92 | available_streams_.insert(id); |
| 93 | } |
| 94 | largest_peer_created_stream_id_ = stream_id; |
| 95 | |
| 96 | return true; |
| 97 | } |
| 98 | |
| 99 | QuicStreamId LegacyQuicStreamIdManager::GetNextOutgoingStreamId() { |
| 100 | QuicStreamId id = next_outgoing_stream_id_; |
| 101 | next_outgoing_stream_id_ += 2; |
| 102 | return id; |
| 103 | } |
| 104 | |
| 105 | bool 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_ == |
ianswett | c1f530d | 2019-12-10 05:14:30 -0800 | [diff] [blame] | 113 | QuicUtils::GetInvalidStreamId(transport_version_) || |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 114 | id > largest_peer_created_stream_id_ || |
| 115 | QuicContainsKey(available_streams_, id); |
| 116 | } |
| 117 | |
| 118 | bool LegacyQuicStreamIdManager::IsIncomingStream(QuicStreamId id) const { |
| 119 | return id % 2 != next_outgoing_stream_id_ % 2; |
| 120 | } |
| 121 | |
| 122 | size_t LegacyQuicStreamIdManager::GetNumAvailableStreams() const { |
| 123 | return available_streams_.size(); |
| 124 | } |
| 125 | |
| 126 | size_t LegacyQuicStreamIdManager::MaxAvailableStreams() const { |
| 127 | return max_open_incoming_streams_ * kMaxAvailableStreamsMultiplier; |
| 128 | } |
| 129 | |
| 130 | } // namespace quic |