1 // Copyright (c) 2012 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 5 // QuicPeerIssuedConnectionIdManager handles the states associated with receving 6 // and retiring peer issued connection Ids. 7 // QuicSelfIssuedConnectionIdManager handles the states associated with 8 // connection Ids issued by the current end point. 9 10 #ifndef QUICHE_QUIC_CORE_QUIC_CONNECTION_ID_MANAGER_H_ 11 #define QUICHE_QUIC_CORE_QUIC_CONNECTION_ID_MANAGER_H_ 12 13 #include <cstddef> 14 #include <memory> 15 #include <optional> 16 17 #include "quiche/quic/core/connection_id_generator.h" 18 #include "quiche/quic/core/frames/quic_new_connection_id_frame.h" 19 #include "quiche/quic/core/frames/quic_retire_connection_id_frame.h" 20 #include "quiche/quic/core/quic_alarm.h" 21 #include "quiche/quic/core/quic_alarm_factory.h" 22 #include "quiche/quic/core/quic_clock.h" 23 #include "quiche/quic/core/quic_connection_id.h" 24 #include "quiche/quic/core/quic_interval_set.h" 25 #include "quiche/quic/core/quic_types.h" 26 #include "quiche/quic/platform/api/quic_export.h" 27 28 namespace quic { 29 30 namespace test { 31 class QuicConnectionIdManagerPeer; 32 } // namespace test 33 34 struct QUICHE_EXPORT QuicConnectionIdData { 35 QuicConnectionIdData(const QuicConnectionId& connection_id, 36 uint64_t sequence_number, 37 const StatelessResetToken& stateless_reset_token); 38 39 QuicConnectionId connection_id; 40 uint64_t sequence_number; 41 StatelessResetToken stateless_reset_token; 42 }; 43 44 // Used by QuicSelfIssuedConnectionIdManager 45 // and QuicPeerIssuedConnectionIdManager. 46 class QUICHE_EXPORT QuicConnectionIdManagerVisitorInterface { 47 public: 48 virtual ~QuicConnectionIdManagerVisitorInterface() = default; 49 virtual void OnPeerIssuedConnectionIdRetired() = 0; 50 virtual bool SendNewConnectionId(const QuicNewConnectionIdFrame& frame) = 0; 51 virtual bool MaybeReserveConnectionId( 52 const QuicConnectionId& connection_id) = 0; 53 virtual void OnSelfIssuedConnectionIdRetired( 54 const QuicConnectionId& connection_id) = 0; 55 }; 56 57 class QUICHE_EXPORT QuicPeerIssuedConnectionIdManager { 58 public: 59 // QuicPeerIssuedConnectionIdManager should be instantiated only when a peer 60 // issued-non empty connection ID is received. 61 QuicPeerIssuedConnectionIdManager( 62 size_t active_connection_id_limit, 63 const QuicConnectionId& initial_peer_issued_connection_id, 64 const QuicClock* clock, QuicAlarmFactory* alarm_factory, 65 QuicConnectionIdManagerVisitorInterface* visitor, 66 QuicConnectionContext* context); 67 68 ~QuicPeerIssuedConnectionIdManager(); 69 70 QuicErrorCode OnNewConnectionIdFrame(const QuicNewConnectionIdFrame& frame, 71 std::string* error_detail, 72 bool* is_duplicate_frame); 73 HasUnusedConnectionId()74 bool HasUnusedConnectionId() const { 75 return !unused_connection_id_data_.empty(); 76 } 77 78 // Returns the data associated with an unused connection Id. After the call, 79 // the Id is marked as used. Returns nullptr if there is no unused connection 80 // Id. 81 const QuicConnectionIdData* ConsumeOneUnusedConnectionId(); 82 83 // Add each active connection Id that is no longer on path to the pending 84 // retirement connection Id list. 85 void MaybeRetireUnusedConnectionIds( 86 const std::vector<QuicConnectionId>& active_connection_ids_on_path); 87 88 bool IsConnectionIdActive(const QuicConnectionId& cid) const; 89 90 // Get the sequence numbers of all the connection Ids pending retirement when 91 // it is safe to retires these Ids. 92 std::vector<uint64_t> ConsumeToBeRetiredConnectionIdSequenceNumbers(); 93 94 // If old_connection_id is still tracked by QuicPeerIssuedConnectionIdManager, 95 // replace it with new_connection_id. Otherwise, this is a no-op. 96 void ReplaceConnectionId(const QuicConnectionId& old_connection_id, 97 const QuicConnectionId& new_connection_id); 98 99 private: 100 friend class test::QuicConnectionIdManagerPeer; 101 102 // Add the connection Id to the pending retirement connection Id list and 103 // schedule an alarm if needed. 104 void PrepareToRetireActiveConnectionId(const QuicConnectionId& cid); 105 106 bool IsConnectionIdNew(const QuicNewConnectionIdFrame& frame); 107 108 void PrepareToRetireConnectionIdPriorTo( 109 uint64_t retire_prior_to, 110 std::vector<QuicConnectionIdData>* cid_data_vector); 111 112 size_t active_connection_id_limit_; 113 const QuicClock* clock_; 114 std::unique_ptr<QuicAlarm> retire_connection_id_alarm_; 115 std::vector<QuicConnectionIdData> active_connection_id_data_; 116 std::vector<QuicConnectionIdData> unused_connection_id_data_; 117 std::vector<QuicConnectionIdData> to_be_retired_connection_id_data_; 118 // Track sequence numbers of recent NEW_CONNECTION_ID frames received from 119 // the peer. 120 QuicIntervalSet<uint64_t> recent_new_connection_id_sequence_numbers_; 121 uint64_t max_new_connection_id_frame_retire_prior_to_ = 0u; 122 }; 123 124 class QUICHE_EXPORT QuicSelfIssuedConnectionIdManager { 125 public: 126 QuicSelfIssuedConnectionIdManager( 127 size_t active_connection_id_limit, 128 const QuicConnectionId& initial_connection_id, const QuicClock* clock, 129 QuicAlarmFactory* alarm_factory, 130 QuicConnectionIdManagerVisitorInterface* visitor, 131 QuicConnectionContext* context, 132 ConnectionIdGeneratorInterface& generator); 133 134 virtual ~QuicSelfIssuedConnectionIdManager(); 135 136 std::optional<QuicNewConnectionIdFrame> 137 MaybeIssueNewConnectionIdForPreferredAddress(); 138 139 QuicErrorCode OnRetireConnectionIdFrame( 140 const QuicRetireConnectionIdFrame& frame, QuicTime::Delta pto_delay, 141 std::string* error_detail); 142 143 std::vector<QuicConnectionId> GetUnretiredConnectionIds() const; 144 145 QuicConnectionId GetOneActiveConnectionId() const; 146 147 // Called when the retire_connection_id alarm_ fires. Removes the to be 148 // retired connection ID locally. 149 void RetireConnectionId(); 150 151 // Sends new connection IDs if more can be sent. 152 void MaybeSendNewConnectionIds(); 153 154 // The two functions are called on the client side to associate a client 155 // connection ID with a new probing/migration path when client uses 156 // non-empty connection ID. 157 bool HasConnectionIdToConsume() const; 158 std::optional<QuicConnectionId> ConsumeOneConnectionId(); 159 160 // Returns true if the given connection ID is issued by the 161 // QuicSelfIssuedConnectionIdManager and not retired locally yet. Called to 162 // tell if a received packet has a valid connection ID. 163 bool IsConnectionIdInUse(const QuicConnectionId& cid) const; 164 165 private: 166 friend class test::QuicConnectionIdManagerPeer; 167 168 // Issue a new connection ID. Can return nullopt. 169 std::optional<QuicNewConnectionIdFrame> MaybeIssueNewConnectionId(); 170 171 // This should be set to the min of: 172 // (1) # of active connection IDs that peer can maintain. 173 // (2) maximum # of active connection IDs self plans to issue. 174 size_t active_connection_id_limit_; 175 const QuicClock* clock_; 176 QuicConnectionIdManagerVisitorInterface* visitor_; 177 // This tracks connection IDs issued to the peer but not retired by the peer. 178 // Each pair is a connection ID and its sequence number. 179 std::vector<std::pair<QuicConnectionId, uint64_t>> active_connection_ids_; 180 // This tracks connection IDs retired by the peer but has not been retired 181 // locally. Each pair is a connection ID and the time by which it should be 182 // retired. 183 std::vector<std::pair<QuicConnectionId, QuicTime>> 184 to_be_retired_connection_ids_; 185 // An alarm that fires when a connection ID should be retired. 186 std::unique_ptr<QuicAlarm> retire_connection_id_alarm_; 187 // State of the last issued connection Id. 188 QuicConnectionId last_connection_id_; 189 uint64_t next_connection_id_sequence_number_; 190 // The sequence number of last connection ID consumed. 191 uint64_t last_connection_id_consumed_by_self_sequence_number_; 192 193 ConnectionIdGeneratorInterface& connection_id_generator_; 194 }; 195 196 } // namespace quic 197 198 #endif // QUICHE_QUIC_CORE_QUIC_CONNECTION_ID_MANAGER_H_ 199