Add QuicPathValidator implementation.
PiperOrigin-RevId: 338150507
Change-Id: I96f0f70e5037a854618da69387d6002dc5e716e4
diff --git a/quic/core/quic_path_validator.h b/quic/core/quic_path_validator.h
new file mode 100644
index 0000000..8cfa81d
--- /dev/null
+++ b/quic/core/quic_path_validator.h
@@ -0,0 +1,135 @@
+// 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 "net/third_party/quiche/src/quic/core/crypto/quic_random.h"
+#include "net/third_party/quiche/src/quic/core/quic_alarm.h"
+#include "net/third_party/quiche/src/quic/core/quic_alarm_factory.h"
+#include "net/third_party/quiche/src/quic/core/quic_arena_scoped_ptr.h"
+#include "net/third_party/quiche/src/quic/core/quic_clock.h"
+#include "net/third_party/quiche/src/quic/core/quic_one_block_arena.h"
+#include "net/third_party/quiche/src/quic/core/quic_packet_writer.h"
+#include "net/third_party/quiche/src/quic/core/quic_types.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_socket_address.h"
+#include "net/quic/platform/impl/quic_export_impl.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) {}
+
+ virtual ~QuicPathValidationContext() = default;
+
+ virtual QuicPacketWriter* WriterToUse() = 0;
+
+ const QuicSocketAddress& self_address() const { return self_address_; }
+ const QuicSocketAddress& peer_address() const { return peer_address_; }
+
+ private:
+ QUIC_EXPORT_PRIVATE friend std::ostream& operator<<(
+ std::ostream& os,
+ const QuicPathValidationContext& context);
+
+ QuicSocketAddress self_address_;
+ QuicSocketAddress 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,
+ 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.
+ class QUIC_EXPORT_PRIVATE ResultDelegate {
+ public:
+ 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);
+
+ // Send PATH_CHALLENGE and start the retry timer.
+ void StartValidingPath(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;
+
+ // Send another PATH_CHALLENGE on the same path. After retrying
+ // |kMaxRetryTimes| times, fail the current path validation.
+ void OnRetryTimeout();
+
+ private:
+ 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.
+ QuicInlinedVector<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
+
+#endif // QUICHE_QUIC_CORE_QUIC_PATH_VALIDATOR_H_