// 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 "quic/core/quic_network_blackhole_detector.h"

#include "quic/core/quic_constants.h"

namespace quic {

namespace {

class AlarmDelegate : public QuicAlarm::Delegate {
 public:
  explicit AlarmDelegate(QuicNetworkBlackholeDetector* detector)
      : detector_(detector) {}
  AlarmDelegate(const AlarmDelegate&) = delete;
  AlarmDelegate& operator=(const AlarmDelegate&) = delete;

  void OnAlarm() override { detector_->OnAlarm(); }

 private:
  QuicNetworkBlackholeDetector* detector_;
};

}  // namespace

QuicNetworkBlackholeDetector::QuicNetworkBlackholeDetector(
    Delegate* delegate,
    QuicConnectionArena* arena,
    QuicAlarmFactory* alarm_factory)
    : delegate_(delegate),
      alarm_(
          alarm_factory->CreateAlarm(arena->New<AlarmDelegate>(this), arena)) {}

void QuicNetworkBlackholeDetector::OnAlarm() {
  QuicTime next_deadline = GetEarliestDeadline();
  if (!next_deadline.IsInitialized()) {
    QUIC_BUG(quic_bug_10328_1) << "BlackholeDetector alarm fired unexpectedly";
    return;
  }

  QUIC_DVLOG(1) << "BlackholeDetector alarm firing. next_deadline:"
                << next_deadline
                << ", path_degrading_deadline_:" << path_degrading_deadline_
                << ", path_mtu_reduction_deadline_:"
                << path_mtu_reduction_deadline_
                << ", blackhole_deadline_:" << blackhole_deadline_;
  if (path_degrading_deadline_ == next_deadline) {
    path_degrading_deadline_ = QuicTime::Zero();
    delegate_->OnPathDegradingDetected();
  }

  if (path_mtu_reduction_deadline_ == next_deadline) {
    path_mtu_reduction_deadline_ = QuicTime::Zero();
    delegate_->OnPathMtuReductionDetected();
  }

  if (blackhole_deadline_ == next_deadline) {
    blackhole_deadline_ = QuicTime::Zero();
    delegate_->OnBlackholeDetected();
  }

  UpdateAlarm();
}

void QuicNetworkBlackholeDetector::StopDetection() {
  alarm_->Cancel();
  path_degrading_deadline_ = QuicTime::Zero();
  blackhole_deadline_ = QuicTime::Zero();
  path_mtu_reduction_deadline_ = QuicTime::Zero();
}

void QuicNetworkBlackholeDetector::RestartDetection(
    QuicTime path_degrading_deadline,
    QuicTime blackhole_deadline,
    QuicTime path_mtu_reduction_deadline) {
  path_degrading_deadline_ = path_degrading_deadline;
  blackhole_deadline_ = blackhole_deadline;
  path_mtu_reduction_deadline_ = path_mtu_reduction_deadline;

  QUIC_BUG_IF(quic_bug_12708_1, blackhole_deadline_.IsInitialized() &&
                                    blackhole_deadline_ != GetLastDeadline())
      << "Blackhole detection deadline should be the last deadline.";

  UpdateAlarm();
}

QuicTime QuicNetworkBlackholeDetector::GetEarliestDeadline() const {
  QuicTime result = QuicTime::Zero();
  for (QuicTime t : {path_degrading_deadline_, blackhole_deadline_,
                     path_mtu_reduction_deadline_}) {
    if (!t.IsInitialized()) {
      continue;
    }

    if (!result.IsInitialized() || t < result) {
      result = t;
    }
  }

  return result;
}

QuicTime QuicNetworkBlackholeDetector::GetLastDeadline() const {
  return std::max({path_degrading_deadline_, blackhole_deadline_,
                   path_mtu_reduction_deadline_});
}

void QuicNetworkBlackholeDetector::UpdateAlarm() const {
  QuicTime next_deadline = GetEarliestDeadline();

  QUIC_DVLOG(1) << "Updating alarm. next_deadline:" << next_deadline
                << ", path_degrading_deadline_:" << path_degrading_deadline_
                << ", path_mtu_reduction_deadline_:"
                << path_mtu_reduction_deadline_
                << ", blackhole_deadline_:" << blackhole_deadline_;

  alarm_->Update(next_deadline, kAlarmGranularity);
}

bool QuicNetworkBlackholeDetector::IsDetectionInProgress() const {
  return alarm_->IsSet();
}

}  // namespace quic
