xref: /aosp_15_r20/external/cronet/net/third_party/quiche/src/quiche/quic/core/quic_connection_id_manager.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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