// 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 "net/third_party/quiche/src/quic/core/quic_path_validator.h"

#include "net/third_party/quiche/src/quic/core/quic_constants.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"

namespace quic {

class RetryAlarmDelegate : public QuicAlarm::Delegate {
 public:
  explicit RetryAlarmDelegate(QuicPathValidator* path_validator)
      : path_validator_(path_validator) {}
  RetryAlarmDelegate(const RetryAlarmDelegate&) = delete;
  RetryAlarmDelegate& operator=(const RetryAlarmDelegate&) = delete;

  void OnAlarm() override { path_validator_->OnRetryTimeout(); }

 private:
  QuicPathValidator* path_validator_;
};

std::ostream& operator<<(std::ostream& os,
                         const QuicPathValidationContext& context) {
  return os << " from " << context.self_address_ << " to "
            << context.peer_address_;
}

QuicPathValidator::QuicPathValidator(QuicAlarmFactory* alarm_factory,
                                     QuicOneBlockArena<1024>* arena,
                                     SendDelegate* send_delegate,
                                     QuicRandom* random)
    : send_delegate_(send_delegate),
      random_(random),
      retry_timer_(
          alarm_factory->CreateAlarm(arena->New<RetryAlarmDelegate>(this),
                                     arena)),
      retry_count_(0u) {}

void QuicPathValidator::OnPathResponse(const QuicPathFrameBuffer& probing_data,
                                       QuicSocketAddress self_address) {
  if (!HasPendingPathValidation()) {
    return;
  }

  QUIC_DVLOG(1) << "Match PATH_RESPONSE received on " << self_address;
  QUIC_BUG_IF(!path_context_->self_address().IsInitialized())
      << "Self address should have been known by now";
  if (self_address != path_context_->self_address()) {
    QUIC_DVLOG(1) << "Expect the response to be received on "
                  << path_context_->self_address();
    return;
  }
  // This iterates at most 3 times.
  if (std::find(probing_data_.begin(), probing_data_.end(), probing_data) !=
      probing_data_.end()) {
    result_delegate_->OnPathValidationSuccess(std::move(path_context_));
    ResetPathValidation();
  }
}

void QuicPathValidator::StartPathValidation(
    std::unique_ptr<QuicPathValidationContext> context,
    std::unique_ptr<ResultDelegate> result_delegate) {
  CancelPathValidation();
  DCHECK_NE(nullptr, context);
  QUIC_DLOG(INFO) << "Start validating path " << *context
                  << " via writer: " << context->WriterToUse();

  path_context_ = std::move(context);
  result_delegate_ = std::move(result_delegate);
  SendPathChallengeAndSetAlarm();
}

void QuicPathValidator::ResetPathValidation() {
  path_context_ = nullptr;
  result_delegate_ = nullptr;
  retry_timer_->Cancel();
  retry_count_ = 0;
}

void QuicPathValidator::CancelPathValidation() {
  if (path_context_ == nullptr) {
    return;
  }
  QUIC_DVLOG(1) << "Cancel validation on path" << *path_context_;
  ResetPathValidation();
}

bool QuicPathValidator::HasPendingPathValidation() const {
  return path_context_ != nullptr;
}

const QuicPathFrameBuffer& QuicPathValidator::GeneratePathChallengePayload() {
  probing_data_.push_back(QuicPathFrameBuffer());
  random_->RandBytes(probing_data_.back().data(), sizeof(QuicPathFrameBuffer));
  return probing_data_.back();
}

void QuicPathValidator::OnRetryTimeout() {
  ++retry_count_;
  if (retry_count_ > kMaxRetryTimes) {
    result_delegate_->OnPathValidationFailure(std::move(path_context_));
    CancelPathValidation();
    return;
  }
  QUIC_DVLOG(1) << "Send another PATH_CHALLENGE on path " << *path_context_;
  SendPathChallengeAndSetAlarm();
}

void QuicPathValidator::SendPathChallengeAndSetAlarm() {
  bool should_continue = send_delegate_->SendPathChallenge(
      GeneratePathChallengePayload(), path_context_->self_address(),
      path_context_->peer_address(), path_context_->WriterToUse());

  if (!should_continue) {
    // The delegate doesn't want to continue the path validation.
    CancelPathValidation();
    return;
  }
  retry_timer_->Set(send_delegate_->GetRetryTimeout(
      path_context_->peer_address(), path_context_->WriterToUse()));
}

}  // namespace quic
