// 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_V2(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(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
