| // 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 <ostream> | |
| #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<QuicPathValidationContext> context, | |
| QuicTime start_time) = 0; | |
| virtual void OnPathValidationFailure( | |
| std::unique_ptr<QuicPathValidationContext> 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<QuicPathValidationContext> context, | |
| std::unique_ptr<ResultDelegate> 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<ProbingData, 3> probing_data_; | |
| SendDelegate* send_delegate_; | |
| QuicRandom* random_; | |
| const QuicClock* clock_; | |
| std::unique_ptr<QuicPathValidationContext> path_context_; | |
| std::unique_ptr<ResultDelegate> result_delegate_; | |
| QuicArenaScopedPtr<QuicAlarm> retry_timer_; | |
| size_t retry_count_; | |
| }; | |
| } // namespace quic | |
| #endif // QUICHE_QUIC_CORE_QUIC_PATH_VALIDATOR_H_ |