xref: /aosp_15_r20/external/cronet/net/third_party/quiche/src/quiche/quic/core/quic_path_validator.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright (c) 2020 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 #ifndef QUICHE_QUIC_CORE_QUIC_PATH_VALIDATOR_H_
6 #define QUICHE_QUIC_CORE_QUIC_PATH_VALIDATOR_H_
7 
8 #include <memory>
9 #include <ostream>
10 
11 #include "absl/container/inlined_vector.h"
12 #include "quiche/quic/core/crypto/quic_random.h"
13 #include "quiche/quic/core/quic_alarm.h"
14 #include "quiche/quic/core/quic_alarm_factory.h"
15 #include "quiche/quic/core/quic_arena_scoped_ptr.h"
16 #include "quiche/quic/core/quic_clock.h"
17 #include "quiche/quic/core/quic_connection_context.h"
18 #include "quiche/quic/core/quic_one_block_arena.h"
19 #include "quiche/quic/core/quic_packet_writer.h"
20 #include "quiche/quic/core/quic_time.h"
21 #include "quiche/quic/core/quic_types.h"
22 #include "quiche/quic/platform/api/quic_export.h"
23 #include "quiche/quic/platform/api/quic_socket_address.h"
24 
25 namespace quic {
26 
27 namespace test {
28 class QuicPathValidatorPeer;
29 }
30 
31 class QuicConnection;
32 
33 enum class PathValidationReason {
34   kReasonUnknown,
35   kMultiPort,
36   kReversePathValidation,
37   kServerPreferredAddressMigration,
38   kPortMigration,
39   kConnectionMigration,
40   kMaxValue,
41 };
42 
43 // Interface to provide the information of the path to be validated.
44 class QUICHE_EXPORT QuicPathValidationContext {
45  public:
QuicPathValidationContext(const QuicSocketAddress & self_address,const QuicSocketAddress & peer_address)46   QuicPathValidationContext(const QuicSocketAddress& self_address,
47                             const QuicSocketAddress& peer_address)
48       : self_address_(self_address),
49         peer_address_(peer_address),
50         effective_peer_address_(peer_address) {}
51 
QuicPathValidationContext(const QuicSocketAddress & self_address,const QuicSocketAddress & peer_address,const QuicSocketAddress & effective_peer_address)52   QuicPathValidationContext(const QuicSocketAddress& self_address,
53                             const QuicSocketAddress& peer_address,
54                             const QuicSocketAddress& effective_peer_address)
55       : self_address_(self_address),
56         peer_address_(peer_address),
57         effective_peer_address_(effective_peer_address) {}
58 
59   virtual ~QuicPathValidationContext() = default;
60 
61   virtual QuicPacketWriter* WriterToUse() = 0;
62 
self_address()63   const QuicSocketAddress& self_address() const { return self_address_; }
peer_address()64   const QuicSocketAddress& peer_address() const { return peer_address_; }
effective_peer_address()65   const QuicSocketAddress& effective_peer_address() const {
66     return effective_peer_address_;
67   }
68 
69  private:
70   QUICHE_EXPORT friend std::ostream& operator<<(
71       std::ostream& os, const QuicPathValidationContext& context);
72 
73   QuicSocketAddress self_address_;
74   // The address to send PATH_CHALLENGE.
75   QuicSocketAddress peer_address_;
76   // The actual peer address which is different from |peer_address_| if the peer
77   // is behind a proxy.
78   QuicSocketAddress effective_peer_address_;
79 };
80 
81 // Used to validate a path by sending up to 3 PATH_CHALLENGE frames before
82 // declaring a path validation failure.
83 class QUICHE_EXPORT QuicPathValidator {
84  public:
85   static const uint16_t kMaxRetryTimes = 2;
86 
87   // Used to write PATH_CHALLENGE on the path to be validated and to get retry
88   // timeout.
89   class QUICHE_EXPORT SendDelegate {
90    public:
91     virtual ~SendDelegate() = default;
92 
93     // Send a PATH_CHALLENGE with |data_buffer| as the frame payload using given
94     // path information. Return false if the delegate doesn't want to continue
95     // the validation.
96     virtual bool SendPathChallenge(
97         const QuicPathFrameBuffer& data_buffer,
98         const QuicSocketAddress& self_address,
99         const QuicSocketAddress& peer_address,
100         const QuicSocketAddress& effective_peer_address,
101         QuicPacketWriter* writer) = 0;
102     // Return the time to retry sending PATH_CHALLENGE again based on given peer
103     // address and writer.
104     virtual QuicTime GetRetryTimeout(const QuicSocketAddress& peer_address,
105                                      QuicPacketWriter* writer) const = 0;
106   };
107 
108   // Handles the validation result.
109   // TODO(danzh) consider to simplify this interface and its life time to
110   // outlive a validation.
111   class QUICHE_EXPORT ResultDelegate {
112    public:
113     virtual ~ResultDelegate() = default;
114 
115     // Called when a PATH_RESPONSE is received with a matching PATH_CHALLANGE.
116     // |start_time| is the time when the matching PATH_CHALLANGE was sent.
117     virtual void OnPathValidationSuccess(
118         std::unique_ptr<QuicPathValidationContext> context,
119         QuicTime start_time) = 0;
120 
121     virtual void OnPathValidationFailure(
122         std::unique_ptr<QuicPathValidationContext> context) = 0;
123   };
124 
125   QuicPathValidator(QuicAlarmFactory* alarm_factory, QuicConnectionArena* arena,
126                     SendDelegate* delegate, QuicRandom* random,
127                     const QuicClock* clock, QuicConnectionContext* context);
128 
129   // Send PATH_CHALLENGE and start the retry timer.
130   void StartPathValidation(std::unique_ptr<QuicPathValidationContext> context,
131                            std::unique_ptr<ResultDelegate> result_delegate,
132                            PathValidationReason reason);
133 
134   // Called when a PATH_RESPONSE frame has been received. Matches the received
135   // PATH_RESPONSE payload with the payloads previously sent in PATH_CHALLANGE
136   // frames and the self address on which it was sent.
137   void OnPathResponse(const QuicPathFrameBuffer& probing_data,
138                       QuicSocketAddress self_address);
139 
140   // Cancel the retry timer and reset the path and result delegate.
141   void CancelPathValidation();
142 
143   bool HasPendingPathValidation() const;
144 
145   QuicPathValidationContext* GetContext() const;
146 
147   // Pass the ownership of path_validation context to the caller and reset the
148   // validator.
149   std::unique_ptr<QuicPathValidationContext> ReleaseContext();
150 
GetPathValidationReason()151   PathValidationReason GetPathValidationReason() const { return reason_; }
152 
153   // Send another PATH_CHALLENGE on the same path. After retrying
154   // |kMaxRetryTimes| times, fail the current path validation.
155   void OnRetryTimeout();
156 
157   bool IsValidatingPeerAddress(const QuicSocketAddress& effective_peer_address);
158 
159   // Called to send packet to |peer_address| if the path validation to this
160   // address is pending.
161   void MaybeWritePacketToAddress(const char* buffer, size_t buf_len,
162                                  const QuicSocketAddress& peer_address);
163 
164  private:
165   friend class test::QuicPathValidatorPeer;
166 
167   // Return the payload to be used in the next PATH_CHALLENGE frame.
168   const QuicPathFrameBuffer& GeneratePathChallengePayload();
169 
170   void SendPathChallengeAndSetAlarm();
171 
172   void ResetPathValidation();
173 
174   struct QUICHE_EXPORT ProbingData {
ProbingDataProbingData175     explicit ProbingData(QuicTime send_time) : send_time(send_time) {}
176     QuicPathFrameBuffer frame_buffer;
177     QuicTime send_time;
178   };
179 
180   // Has at most 3 entries due to validation timeout.
181   absl::InlinedVector<ProbingData, 3> probing_data_;
182   SendDelegate* send_delegate_;
183   QuicRandom* random_;
184   const QuicClock* clock_;
185   std::unique_ptr<QuicPathValidationContext> path_context_;
186   std::unique_ptr<ResultDelegate> result_delegate_;
187   QuicArenaScopedPtr<QuicAlarm> retry_timer_;
188   size_t retry_count_;
189   PathValidationReason reason_ = PathValidationReason::kReasonUnknown;
190 };
191 
192 }  // namespace quic
193 
194 #endif  // QUICHE_QUIC_CORE_QUIC_PATH_VALIDATOR_H_
195