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