// Copyright (c) 2020 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef QUICHE_QUIC_CORE_QUIC_PATH_VALIDATOR_H_ #define QUICHE_QUIC_CORE_QUIC_PATH_VALIDATOR_H_ #include #include "absl/container/inlined_vector.h" #include "quiche/quic/core/crypto/quic_random.h" #include "quiche/quic/core/quic_alarm.h" #include "quiche/quic/core/quic_alarm_factory.h" #include "quiche/quic/core/quic_arena_scoped_ptr.h" #include "quiche/quic/core/quic_clock.h" #include "quiche/quic/core/quic_connection_context.h" #include "quiche/quic/core/quic_one_block_arena.h" #include "quiche/quic/core/quic_packet_writer.h" #include "quiche/quic/core/quic_time.h" #include "quiche/quic/core/quic_types.h" #include "quiche/quic/platform/api/quic_export.h" #include "quiche/quic/platform/api/quic_socket_address.h" namespace quic { namespace test { class QuicPathValidatorPeer; } class QuicConnection; // Interface to provide the information of the path to be validated. class QUIC_EXPORT_PRIVATE QuicPathValidationContext { public: QuicPathValidationContext(const QuicSocketAddress& self_address, const QuicSocketAddress& peer_address) : self_address_(self_address), peer_address_(peer_address), effective_peer_address_(peer_address) {} QuicPathValidationContext(const QuicSocketAddress& self_address, const QuicSocketAddress& peer_address, const QuicSocketAddress& effective_peer_address) : self_address_(self_address), peer_address_(peer_address), effective_peer_address_(effective_peer_address) {} virtual ~QuicPathValidationContext() = default; virtual QuicPacketWriter* WriterToUse() = 0; const QuicSocketAddress& self_address() const { return self_address_; } const QuicSocketAddress& peer_address() const { return peer_address_; } const QuicSocketAddress& effective_peer_address() const { return effective_peer_address_; } private: QUIC_EXPORT_PRIVATE friend std::ostream& operator<<( std::ostream& os, const QuicPathValidationContext& context); QuicSocketAddress self_address_; // The address to send PATH_CHALLENGE. QuicSocketAddress peer_address_; // The actual peer address which is different from |peer_address_| if the peer // is behind a proxy. QuicSocketAddress effective_peer_address_; }; // Used to validate a path by sending up to 3 PATH_CHALLENGE frames before // declaring a path validation failure. class QUIC_EXPORT_PRIVATE QuicPathValidator { public: static const uint16_t kMaxRetryTimes = 2; // Used to write PATH_CHALLENGE on the path to be validated and to get retry // timeout. class QUIC_EXPORT_PRIVATE SendDelegate { public: virtual ~SendDelegate() = default; // Send a PATH_CHALLENGE with |data_buffer| as the frame payload using given // path information. Return false if the delegate doesn't want to continue // the validation. virtual bool SendPathChallenge( const QuicPathFrameBuffer& data_buffer, const QuicSocketAddress& self_address, const QuicSocketAddress& peer_address, const QuicSocketAddress& effective_peer_address, QuicPacketWriter* writer) = 0; // Return the time to retry sending PATH_CHALLENGE again based on given peer // address and writer. virtual QuicTime GetRetryTimeout(const QuicSocketAddress& peer_address, QuicPacketWriter* writer) const = 0; }; // Handles the validation result. // TODO(danzh) consider to simplify this interface and its life time to // outlive a validation. class QUIC_EXPORT_PRIVATE ResultDelegate { public: virtual ~ResultDelegate() = default; // Called when a PATH_RESPONSE is received with a matching PATH_CHALLANGE. // |start_time| is the time when the matching PATH_CHALLANGE was sent. virtual void OnPathValidationSuccess( std::unique_ptr context, QuicTime start_time) = 0; virtual void OnPathValidationFailure( std::unique_ptr context) = 0; }; QuicPathValidator(QuicAlarmFactory* alarm_factory, QuicConnectionArena* arena, SendDelegate* delegate, QuicRandom* random, const QuicClock* clock, QuicConnectionContext* context); // Send PATH_CHALLENGE and start the retry timer. void StartPathValidation(std::unique_ptr context, std::unique_ptr result_delegate); // Called when a PATH_RESPONSE frame has been received. Matches the received // PATH_RESPONSE payload with the payloads previously sent in PATH_CHALLANGE // frames and the self address on which it was sent. void OnPathResponse(const QuicPathFrameBuffer& probing_data, QuicSocketAddress self_address); // Cancel the retry timer and reset the path and result delegate. void CancelPathValidation(); bool HasPendingPathValidation() const; QuicPathValidationContext* GetContext() const; // Send another PATH_CHALLENGE on the same path. After retrying // |kMaxRetryTimes| times, fail the current path validation. void OnRetryTimeout(); bool IsValidatingPeerAddress(const QuicSocketAddress& effective_peer_address); private: friend class test::QuicPathValidatorPeer; // Return the payload to be used in the next PATH_CHALLENGE frame. const QuicPathFrameBuffer& GeneratePathChallengePayload(); void SendPathChallengeAndSetAlarm(); void ResetPathValidation(); struct QUIC_NO_EXPORT ProbingData { explicit ProbingData(QuicTime send_time) : send_time(send_time) {} QuicPathFrameBuffer frame_buffer; QuicTime send_time; }; // Has at most 3 entries due to validation timeout. absl::InlinedVector probing_data_; SendDelegate* send_delegate_; QuicRandom* random_; const QuicClock* clock_; std::unique_ptr path_context_; std::unique_ptr result_delegate_; QuicArenaScopedPtr retry_timer_; size_t retry_count_; }; } // namespace quic #endif // QUICHE_QUIC_CORE_QUIC_PATH_VALIDATOR_H_