blob: 9fe2cef988470d2ccfc07165df21df9e3d47c5b2 [file] [log] [blame]
// 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.
#include <ostream>
#include "absl/container/inlined_vector.h"
#include "quic/core/crypto/quic_random.h"
#include "quic/core/quic_alarm.h"
#include "quic/core/quic_alarm_factory.h"
#include "quic/core/quic_arena_scoped_ptr.h"
#include "quic/core/quic_clock.h"
#include "quic/core/quic_connection_context.h"
#include "quic/core/quic_one_block_arena.h"
#include "quic/core/quic_packet_writer.h"
#include "quic/core/quic_types.h"
#include "quic/platform/api/quic_export.h"
#include "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 {
QuicPathValidationContext(const QuicSocketAddress& self_address,
const QuicSocketAddress& peer_address)
: self_address_(self_address),
effective_peer_address_(peer_address) {}
QuicPathValidationContext(const QuicSocketAddress& self_address,
const QuicSocketAddress& peer_address,
const QuicSocketAddress& effective_peer_address)
: self_address_(self_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_;
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 {
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 {
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 {
virtual ~ResultDelegate() = default;
virtual void OnPathValidationSuccess(
std::unique_ptr<QuicPathValidationContext> context) = 0;
virtual void OnPathValidationFailure(
std::unique_ptr<QuicPathValidationContext> context) = 0;
QuicPathValidator(QuicAlarmFactory* alarm_factory, QuicConnectionArena* arena,
SendDelegate* delegate, QuicRandom* random,
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);
friend class test::QuicPathValidatorPeer;
// Return the payload to be used in the next PATH_CHALLENGE frame.
const QuicPathFrameBuffer& GeneratePathChallengePayload();
void SendPathChallengeAndSetAlarm();
void ResetPathValidation();
// Has at most 3 entries due to validation timeout.
absl::InlinedVector<QuicPathFrameBuffer, 3> probing_data_;
SendDelegate* send_delegate_;
QuicRandom* random_;
std::unique_ptr<QuicPathValidationContext> path_context_;
std::unique_ptr<ResultDelegate> result_delegate_;
QuicArenaScopedPtr<QuicAlarm> retry_timer_;
size_t retry_count_;
} // namespace quic