// Copyright 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/dns/dns_server_iterator.h"

#include "base/optional.h"
#include "base/time/time.h"
#include "net/dns/dns_config.h"
#include "net/dns/dns_session.h"
#include "net/dns/resolve_context.h"

namespace net {
DnsServerIterator::DnsServerIterator(size_t nameservers_size,
                                     size_t starting_index,
                                     int max_times_returned,
                                     int max_failures,
                                     const ResolveContext* resolve_context,
                                     const DnsSession* session)
    : times_returned_(nameservers_size, 0),
      max_times_returned_(max_times_returned),
      max_failures_(max_failures),
      resolve_context_(resolve_context),
      next_index_(starting_index),
      session_(session) {}

DnsServerIterator::~DnsServerIterator() = default;

size_t DohDnsServerIterator::GetNextAttemptIndex() {
  DCHECK(resolve_context_->IsCurrentSession(session_));
  DCHECK(AttemptAvailable());

  // Because AttemptAvailable() should always be true before running this
  // function we can assume that an attemptable DoH server exists.

  // Check if the next index is available and hasn't hit its failure limit. If
  // not, try the next one and so on until we've tried them all.
  base::Optional<size_t> least_recently_failed_index;
  base::TimeTicks least_recently_failed_time;

  size_t previous_index = next_index_;
  size_t curr_index;

  do {
    curr_index = next_index_;
    next_index_ = (next_index_ + 1) % times_returned_.size();

    // If the DoH mode is "secure" then don't check GetDohServerAvailability()
    // because we try every server regardless of availability.
    bool secure_or_available_server =
        secure_dns_mode_ == DnsConfig::SecureDnsMode::SECURE ||
        resolve_context_->GetDohServerAvailability(curr_index, session_);

    // If we've tried this server |max_times_returned_| already, then we're done
    // with it. Similarly skip this server if it isn't available and we're not
    // in secure mode.
    if (times_returned_[curr_index] >= max_times_returned_ ||
        !secure_or_available_server)
      continue;

    if (resolve_context_->doh_server_stats_[curr_index].last_failure_count <
        max_failures_) {
      times_returned_[curr_index]++;
      return curr_index;
    }

    // Update the least recently failed server if needed.
    base::TimeTicks curr_index_failure_time =
        resolve_context_->doh_server_stats_[curr_index].last_failure;
    if (!least_recently_failed_index ||
        curr_index_failure_time < least_recently_failed_time) {
      least_recently_failed_time = curr_index_failure_time;
      least_recently_failed_index = curr_index;
    }

  } while (next_index_ != previous_index);

  // At this point the only available servers we haven't attempted
  // |max_times_returned_| times are at their failure limit. Return the server
  // with the least recent failure.

  DCHECK(least_recently_failed_index.has_value());
  times_returned_[least_recently_failed_index.value()]++;
  return least_recently_failed_index.value();
}

bool DohDnsServerIterator::AttemptAvailable() {
  if (!resolve_context_->IsCurrentSession(session_))
    return false;

  for (size_t i = 0; i < times_returned_.size(); i++) {
    // If the DoH mode is "secure" then don't check GetDohServerAvailability()
    // because we try every server regardless of availability.
    bool secure_or_available_server =
        secure_dns_mode_ == DnsConfig::SecureDnsMode::SECURE ||
        resolve_context_->GetDohServerAvailability(i, session_);

    if (times_returned_[i] < max_times_returned_ && secure_or_available_server)
      return true;
  }
  return false;
}

size_t ClassicDnsServerIterator::GetNextAttemptIndex() {
  DCHECK(resolve_context_->IsCurrentSession(session_));
  DCHECK(AttemptAvailable());

  // Because AttemptAvailable() should always be true before running this
  // function we can assume that an attemptable DNS server exists.

  // Check if the next index is available and hasn't hit its failure limit. If
  // not, try the next one and so on until we've tried them all.
  base::Optional<size_t> least_recently_failed_index;
  base::TimeTicks least_recently_failed_time;

  size_t previous_index = next_index_;
  size_t curr_index;

  do {
    curr_index = next_index_;
    next_index_ = (next_index_ + 1) % times_returned_.size();

    // If we've tried this server |max_times_returned_| already, then we're done
    // with it.
    if (times_returned_[curr_index] >= max_times_returned_)
      continue;

    if (resolve_context_->classic_server_stats_[curr_index].last_failure_count <
        max_failures_) {
      times_returned_[curr_index]++;
      return curr_index;
    }

    // Update the least recently failed server if needed.
    base::TimeTicks curr_index_failure_time =
        resolve_context_->classic_server_stats_[curr_index].last_failure;
    if (!least_recently_failed_index ||
        curr_index_failure_time < least_recently_failed_time) {
      least_recently_failed_time = curr_index_failure_time;
      least_recently_failed_index = curr_index;
    }

  } while (next_index_ != previous_index);

  // At this point the only servers we haven't attempted |max_times_returned_|
  // times are at their failure limit. Return the server with the least recent
  // failure.

  DCHECK(least_recently_failed_index.has_value());
  times_returned_[least_recently_failed_index.value()]++;
  return least_recently_failed_index.value();
}

bool ClassicDnsServerIterator::AttemptAvailable() {
  if (!resolve_context_->IsCurrentSession(session_))
    return false;

  for (int i : times_returned_) {
    if (i < max_times_returned_)
      return true;
  }
  return false;
}

}  // namespace net
