// Copyright (c) 2012 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/proxy_resolution/dhcp_pac_file_fetcher_win.h"

#include <memory>
#include <vector>

#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/containers/queue.h"
#include "base/memory/free_deleter.h"
#include "base/synchronization/lock.h"
#include "base/task/post_task.h"
#include "base/task_runner.h"
#include "base/threading/scoped_blocking_call.h"
#include "base/values.h"
#include "net/base/net_errors.h"
#include "net/log/net_log.h"
#include "net/proxy_resolution/dhcp_pac_file_adapter_fetcher_win.h"

#include <winsock2.h>
#include <iphlpapi.h>

namespace net {

namespace {

// Returns true if |adapter| should be considered when probing for WPAD via
// DHCP.
bool IsDhcpCapableAdapter(IP_ADAPTER_ADDRESSES* adapter) {
  if (adapter->IfType == IF_TYPE_SOFTWARE_LOOPBACK)
    return false;
  if ((adapter->Flags & IP_ADAPTER_DHCP_ENABLED) == 0)
    return false;

  // Don't probe interfaces which are not up and ready to pass packets.
  //
  // This is a speculative fix for https://crbug.com/770201, in case calling
  // dhcpsvc!DhcpRequestParams on interfaces that aren't ready yet blocks for
  // a long time.
  //
  // Since ProxyResolutionService restarts WPAD probes in response to other
  // network level changes, this will likely get called again once the
  // interface is up.
  if (adapter->OperStatus != IfOperStatusUp)
    return false;

  return true;
}

}  // namespace

// This struct contains logging information describing how
// GetCandidateAdapterNames() performed, for output to NetLog.
struct DhcpAdapterNamesLoggingInfo {
  DhcpAdapterNamesLoggingInfo() = default;
  ~DhcpAdapterNamesLoggingInfo() = default;

  // The error that iphlpapi!GetAdaptersAddresses returned.
  ULONG error;

  // The adapters list that iphlpapi!GetAdaptersAddresses returned.
  std::unique_ptr<IP_ADAPTER_ADDRESSES, base::FreeDeleter> adapters;

  // The time immediately before GetCandidateAdapterNames was posted to a worker
  // thread from the origin thread.
  base::TimeTicks origin_thread_start_time;

  // The time when GetCandidateAdapterNames began running on the worker thread.
  base::TimeTicks worker_thread_start_time;

  // The time when GetCandidateAdapterNames completed running on the worker
  // thread.
  base::TimeTicks worker_thread_end_time;

  // The time when control returned to the origin thread
  // (OnGetCandidateAdapterNamesDone)
  base::TimeTicks origin_thread_end_time;

 private:
  DISALLOW_COPY_AND_ASSIGN(DhcpAdapterNamesLoggingInfo);
};

namespace {

// Maximum number of DHCP lookup tasks running concurrently. This is chosen
// based on the following UMA data:
// - When OnWaitTimer fires, ~99.8% of users have 6 or fewer network
//   adapters enabled for DHCP in total.
// - At the same measurement point, ~99.7% of users have 3 or fewer pending
//   DHCP adapter lookups.
// - There is however a very long and thin tail of users who have
//   systems reporting up to 100+ adapters (this must be some very weird
//   OS bug (?), probably the cause of http://crbug.com/240034).
//
// Th value is chosen such that DHCP lookup tasks don't prevent other tasks from
// running even on systems that report a huge number of network adapters, while
// giving a good chance of getting back results for any responsive adapters.
constexpr int kMaxConcurrentDhcpLookupTasks = 12;

// How long to wait at maximum after we get results (a PAC file or
// knowledge that no PAC file is configured) from whichever network
// adapter finishes first.
constexpr base::TimeDelta kMaxWaitAfterFirstResult =
    base::TimeDelta::FromMilliseconds(400);

// A TaskRunner that never schedules more than |kMaxConcurrentDhcpLookupTasks|
// tasks concurrently.
class TaskRunnerWithCap : public base::TaskRunner {
 public:
  TaskRunnerWithCap() = default;

  bool PostDelayedTask(const base::Location& from_here,
                       base::OnceClosure task,
                       base::TimeDelta delay) override {
    // Delayed tasks are not supported.
    DCHECK(delay.is_zero());

    // Wrap the task in a callback that runs |task|, then tries to schedule a
    // task from |pending_tasks_|.
    base::OnceClosure wrapped_task =
        base::BindOnce(&TaskRunnerWithCap::RunTaskAndSchedulePendingTask, this,
                       std::move(task));

    {
      base::AutoLock auto_lock(lock_);

      // If |kMaxConcurrentDhcpLookupTasks| tasks are scheduled, move the task
      // to |pending_tasks_|.
      DCHECK_LE(num_scheduled_tasks_, kMaxConcurrentDhcpLookupTasks);
      if (num_scheduled_tasks_ == kMaxConcurrentDhcpLookupTasks) {
        pending_tasks_.emplace(from_here, std::move(wrapped_task));
        return true;
      }

      // If less than |kMaxConcurrentDhcpLookupTasks| tasks are scheduled,
      // increment |num_scheduled_tasks_| and schedule the task.
      ++num_scheduled_tasks_;
    }

    task_runner_->PostTask(from_here, std::move(wrapped_task));
    return true;
  }

  bool RunsTasksInCurrentSequence() const override {
    return task_runner_->RunsTasksInCurrentSequence();
  }

 private:
  struct LocationAndTask {
    LocationAndTask() = default;
    LocationAndTask(const base::Location& from_here, base::OnceClosure task)
        : from_here(from_here), task(std::move(task)) {}
    base::Location from_here;
    base::OnceClosure task;
  };

  ~TaskRunnerWithCap() override = default;

  void RunTaskAndSchedulePendingTask(base::OnceClosure task) {
    // Run |task|.
    std::move(task).Run();

    // If |pending_tasks_| is non-empty, schedule a task from it. Otherwise,
    // decrement |num_scheduled_tasks_|.
    LocationAndTask task_to_schedule;

    {
      base::AutoLock auto_lock(lock_);

      DCHECK_GT(num_scheduled_tasks_, 0);
      if (pending_tasks_.empty()) {
        --num_scheduled_tasks_;
        return;
      }

      task_to_schedule = std::move(pending_tasks_.front());
      pending_tasks_.pop();
    }

    DCHECK(task_to_schedule.task);
    task_runner_->PostTask(task_to_schedule.from_here,
                           std::move(task_to_schedule.task));
  }

  const scoped_refptr<base::TaskRunner> task_runner_ =
      base::CreateTaskRunnerWithTraits(
          {base::MayBlock(), base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN,
           base::TaskPriority::USER_VISIBLE});

  // Synchronizes access to members below.
  base::Lock lock_;

  // Number of tasks that are currently scheduled.
  int num_scheduled_tasks_ = 0;

  // Tasks that are waiting to be scheduled.
  base::queue<LocationAndTask> pending_tasks_;

  DISALLOW_COPY_AND_ASSIGN(TaskRunnerWithCap);
};

// Helper to set an integer value into a base::DictionaryValue. Because of
// C++'s implicit narrowing casts to |int|, this can be called with int64_t and
// ULONG too.
void SetInt(base::StringPiece key, int value, base::DictionaryValue* dict) {
  dict->SetKey(key, base::Value(value));
}

std::unique_ptr<base::Value> NetLogGetAdaptersDoneCallback(
    DhcpAdapterNamesLoggingInfo* info,
    NetLogCaptureMode /* capture_mode */) {
  std::unique_ptr<base::DictionaryValue> result =
      std::make_unique<base::DictionaryValue>();

  // Add information on each of the adapters enumerated (including those that
  // were subsequently skipped).
  base::ListValue adapters_value;
  for (IP_ADAPTER_ADDRESSES* adapter = info->adapters.get(); adapter;
       adapter = adapter->Next) {
    base::DictionaryValue adapter_value;

    adapter_value.SetKey("AdapterName", base::Value(adapter->AdapterName));
    SetInt("IfType", adapter->IfType, &adapter_value);
    SetInt("Flags", adapter->Flags, &adapter_value);
    SetInt("OperStatus", adapter->OperStatus, &adapter_value);
    SetInt("TunnelType", adapter->TunnelType, &adapter_value);

    // "skipped" means the adapter was not ultimately chosen as a candidate for
    // testing WPAD.
    bool skipped = !IsDhcpCapableAdapter(adapter);
    adapter_value.SetKey("skipped", base::Value(skipped));

    adapters_value.GetList().push_back(std::move(adapter_value));
  }
  result->SetKey("adapters", std::move(adapters_value));

  SetInt("origin_to_worker_thread_hop_dt",
         (info->worker_thread_start_time - info->origin_thread_start_time)
             .InMilliseconds(),
         result.get());
  SetInt("worker_to_origin_thread_hop_dt",
         (info->origin_thread_end_time - info->worker_thread_end_time)
             .InMilliseconds(),
         result.get());
  SetInt("worker_dt",
         (info->worker_thread_end_time - info->worker_thread_start_time)
             .InMilliseconds(),
         result.get());

  if (info->error != ERROR_SUCCESS)
    SetInt("error", info->error, result.get());

  return result;
}

std::unique_ptr<base::Value> NetLogFetcherDoneCallback(
    int fetcher_index,
    int net_error,
    NetLogCaptureMode /* capture_mode */) {
  std::unique_ptr<base::DictionaryValue> result =
      std::make_unique<base::DictionaryValue>();

  result->SetKey("fetcher_index", base::Value(fetcher_index));
  result->SetKey("net_error", base::Value(net_error));

  return result;
}

}  // namespace

DhcpPacFileFetcherWin::DhcpPacFileFetcherWin(
    URLRequestContext* url_request_context)
    : state_(STATE_START),
      num_pending_fetchers_(0),
      destination_string_(NULL),
      url_request_context_(url_request_context),
      task_runner_(base::MakeRefCounted<TaskRunnerWithCap>()) {
  DCHECK(url_request_context_);
}

DhcpPacFileFetcherWin::~DhcpPacFileFetcherWin() {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  // Count as user-initiated if we are not yet in STATE_DONE.
  Cancel();
}

int DhcpPacFileFetcherWin::Fetch(
    base::string16* utf16_text,
    CompletionOnceCallback callback,
    const NetLogWithSource& net_log,
    const NetworkTrafficAnnotationTag traffic_annotation) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  if (state_ != STATE_START && state_ != STATE_DONE) {
    NOTREACHED();
    return ERR_UNEXPECTED;
  }

  net_log_ = net_log;

  if (!url_request_context_)
    return ERR_CONTEXT_SHUT_DOWN;

  state_ = STATE_WAIT_ADAPTERS;
  callback_ = std::move(callback);
  destination_string_ = utf16_text;

  net_log.BeginEvent(NetLogEventType::WPAD_DHCP_WIN_FETCH);

  // TODO(eroman): This event is not ended in the case of cancellation.
  net_log.BeginEvent(NetLogEventType::WPAD_DHCP_WIN_GET_ADAPTERS);

  last_query_ = ImplCreateAdapterQuery();
  last_query_->logging_info()->origin_thread_start_time =
      base::TimeTicks::Now();

  task_runner_->PostTaskAndReply(
      FROM_HERE,
      base::Bind(&DhcpPacFileFetcherWin::AdapterQuery::GetCandidateAdapterNames,
                 last_query_.get()),
      base::Bind(&DhcpPacFileFetcherWin::OnGetCandidateAdapterNamesDone,
                 AsWeakPtr(), last_query_, traffic_annotation));

  return ERR_IO_PENDING;
}

void DhcpPacFileFetcherWin::Cancel() {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);

  CancelImpl();
}

void DhcpPacFileFetcherWin::OnShutdown() {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);

  // Back up callback, if there is one, as CancelImpl() will destroy it.
  net::CompletionOnceCallback callback = std::move(callback_);

  // Cancel current request, if there is one.
  CancelImpl();

  // Prevent future network requests.
  url_request_context_ = nullptr;

  // Invoke callback with error, if present.
  if (callback)
    std::move(callback).Run(ERR_CONTEXT_SHUT_DOWN);
}

void DhcpPacFileFetcherWin::CancelImpl() {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);

  if (state_ != STATE_DONE) {
    callback_.Reset();
    wait_timer_.Stop();
    state_ = STATE_DONE;

    for (FetcherVector::iterator it = fetchers_.begin();
         it != fetchers_.end();
         ++it) {
      (*it)->Cancel();
    }

    fetchers_.clear();
  }
}

void DhcpPacFileFetcherWin::OnGetCandidateAdapterNamesDone(
    scoped_refptr<AdapterQuery> query,
    const NetworkTrafficAnnotationTag traffic_annotation) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);

  // This can happen if this object is reused for multiple queries,
  // and a previous query was cancelled before it completed.
  if (query.get() != last_query_.get())
    return;
  last_query_ = NULL;

  DhcpAdapterNamesLoggingInfo* logging_info = query->logging_info();
  logging_info->origin_thread_end_time = base::TimeTicks::Now();

  net_log_.EndEvent(NetLogEventType::WPAD_DHCP_WIN_GET_ADAPTERS,
                    base::Bind(&NetLogGetAdaptersDoneCallback,
                               base::Unretained(logging_info)));

  // Enable unit tests to wait for this to happen; in production this function
  // call is a no-op.
  ImplOnGetCandidateAdapterNamesDone();

  // We may have been cancelled.
  if (state_ != STATE_WAIT_ADAPTERS)
    return;

  state_ = STATE_NO_RESULTS;

  const std::set<std::string>& adapter_names = query->adapter_names();

  if (adapter_names.empty()) {
    TransitionToDone();
    return;
  }

  for (const std::string& adapter_name : adapter_names) {
    std::unique_ptr<DhcpPacFileAdapterFetcher> fetcher(
        ImplCreateAdapterFetcher());
    size_t fetcher_index = fetchers_.size();
    fetcher->Fetch(adapter_name,
                   base::Bind(&DhcpPacFileFetcherWin::OnFetcherDone,
                              base::Unretained(this), fetcher_index),
                   traffic_annotation);
    fetchers_.push_back(std::move(fetcher));
  }
  num_pending_fetchers_ = fetchers_.size();
}

std::string DhcpPacFileFetcherWin::GetFetcherName() const {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  return "win";
}

const GURL& DhcpPacFileFetcherWin::GetPacURL() const {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  DCHECK_EQ(state_, STATE_DONE);

  return pac_url_;
}

void DhcpPacFileFetcherWin::OnFetcherDone(size_t fetcher_index,
                                          int result) {
  DCHECK(state_ == STATE_NO_RESULTS || state_ == STATE_SOME_RESULTS);

  net_log_.AddEvent(
      NetLogEventType::WPAD_DHCP_WIN_ON_FETCHER_DONE,
      base::Bind(&NetLogFetcherDoneCallback, fetcher_index, result));

  if (--num_pending_fetchers_ == 0) {
    TransitionToDone();
    return;
  }

  // If the only pending adapters are those less preferred than one
  // with a valid PAC script, we do not need to wait any longer.
  for (FetcherVector::iterator it = fetchers_.begin();
       it != fetchers_.end();
       ++it) {
    bool did_finish = (*it)->DidFinish();
    int result = (*it)->GetResult();
    if (did_finish && result == OK) {
      TransitionToDone();
      return;
    }
    if (!did_finish || result != ERR_PAC_NOT_IN_DHCP) {
      break;
    }
  }

  // Once we have a single result, we set a maximum on how long to wait
  // for the rest of the results.
  if (state_ == STATE_NO_RESULTS) {
    state_ = STATE_SOME_RESULTS;
    net_log_.AddEvent(NetLogEventType::WPAD_DHCP_WIN_START_WAIT_TIMER);
    wait_timer_.Start(FROM_HERE,
        ImplGetMaxWait(), this, &DhcpPacFileFetcherWin::OnWaitTimer);
  }
}

void DhcpPacFileFetcherWin::OnWaitTimer() {
  DCHECK_EQ(state_, STATE_SOME_RESULTS);

  net_log_.AddEvent(NetLogEventType::WPAD_DHCP_WIN_ON_WAIT_TIMER);
  TransitionToDone();
}

void DhcpPacFileFetcherWin::TransitionToDone() {
  DCHECK(state_ == STATE_NO_RESULTS || state_ == STATE_SOME_RESULTS);

  int used_fetcher_index = -1;
  int result = ERR_PAC_NOT_IN_DHCP;  // Default if no fetchers.
  if (!fetchers_.empty()) {
    // Scan twice for the result; once through the whole list for success,
    // then if no success, return result for most preferred network adapter,
    // preferring "real" network errors to the ERR_PAC_NOT_IN_DHCP error.
    // Default to ERR_ABORTED if no fetcher completed.
    result = ERR_ABORTED;
    for (size_t i = 0; i < fetchers_.size(); ++i) {
      const auto& fetcher = fetchers_[i];
      if (fetcher->DidFinish() && fetcher->GetResult() == OK) {
        result = OK;
        *destination_string_ = fetcher->GetPacScript();
        pac_url_ = fetcher->GetPacURL();
        used_fetcher_index = i;
        break;
      }
    }
    if (result != OK) {
      destination_string_->clear();
      for (size_t i = 0; i < fetchers_.size(); ++i) {
        const auto& fetcher = fetchers_[i];
        if (fetcher->DidFinish()) {
          result = fetcher->GetResult();
          used_fetcher_index = i;
          if (result != ERR_PAC_NOT_IN_DHCP) {
            break;
          }
        }
      }
    }
  }

  CompletionOnceCallback callback = std::move(callback_);
  CancelImpl();
  DCHECK_EQ(state_, STATE_DONE);
  DCHECK(fetchers_.empty());

  net_log_.EndEvent(
      NetLogEventType::WPAD_DHCP_WIN_FETCH,
      base::Bind(&NetLogFetcherDoneCallback, used_fetcher_index, result));

  // We may be deleted re-entrantly within this outcall.
  std::move(callback).Run(result);
}

int DhcpPacFileFetcherWin::num_pending_fetchers() const {
  return num_pending_fetchers_;
}

URLRequestContext* DhcpPacFileFetcherWin::url_request_context() const {
  return url_request_context_;
}

scoped_refptr<base::TaskRunner> DhcpPacFileFetcherWin::GetTaskRunner() {
  return task_runner_;
}

DhcpPacFileAdapterFetcher* DhcpPacFileFetcherWin::ImplCreateAdapterFetcher() {
  return new DhcpPacFileAdapterFetcher(url_request_context_, task_runner_);
}

DhcpPacFileFetcherWin::AdapterQuery*
DhcpPacFileFetcherWin::ImplCreateAdapterQuery() {
  return new AdapterQuery();
}

base::TimeDelta DhcpPacFileFetcherWin::ImplGetMaxWait() {
  return kMaxWaitAfterFirstResult;
}

bool DhcpPacFileFetcherWin::GetCandidateAdapterNames(
    std::set<std::string>* adapter_names,
    DhcpAdapterNamesLoggingInfo* info) {
  DCHECK(adapter_names);
  adapter_names->clear();

  // The GetAdaptersAddresses MSDN page recommends using a size of 15000 to
  // avoid reallocation.
  ULONG adapters_size = 15000;
  std::unique_ptr<IP_ADAPTER_ADDRESSES, base::FreeDeleter> adapters;
  ULONG error = ERROR_SUCCESS;
  int num_tries = 0;

  do {
    adapters.reset(static_cast<IP_ADAPTER_ADDRESSES*>(malloc(adapters_size)));
    // Return only unicast addresses, and skip information we do not need.
    base::ScopedBlockingCall scoped_blocking_call(
        base::BlockingType::MAY_BLOCK);
    error = GetAdaptersAddresses(AF_UNSPEC,
                                 GAA_FLAG_SKIP_ANYCAST |
                                 GAA_FLAG_SKIP_MULTICAST |
                                 GAA_FLAG_SKIP_DNS_SERVER |
                                 GAA_FLAG_SKIP_FRIENDLY_NAME,
                                 NULL,
                                 adapters.get(),
                                 &adapters_size);
    ++num_tries;
  } while (error == ERROR_BUFFER_OVERFLOW && num_tries <= 3);

  if (info)
    info->error = error;

  if (error == ERROR_NO_DATA) {
    // There are no adapters that we care about.
    return true;
  }

  if (error != ERROR_SUCCESS) {
    LOG(WARNING) << "Unexpected error retrieving WPAD configuration from DHCP.";
    return false;
  }

  IP_ADAPTER_ADDRESSES* adapter = NULL;
  for (adapter = adapters.get(); adapter; adapter = adapter->Next) {
    if (IsDhcpCapableAdapter(adapter)) {
      DCHECK(adapter->AdapterName);
      adapter_names->insert(adapter->AdapterName);
    }
  }

  // Transfer the buffer containing the adapters, so it can be used later for
  // emitting NetLog parameters from the origin thread.
  if (info)
    info->adapters = std::move(adapters);
  return true;
}

DhcpPacFileFetcherWin::AdapterQuery::AdapterQuery()
    : logging_info_(new DhcpAdapterNamesLoggingInfo()) {}

void DhcpPacFileFetcherWin::AdapterQuery::GetCandidateAdapterNames() {
  logging_info_->error = ERROR_NO_DATA;
  logging_info_->adapters.reset();
  logging_info_->worker_thread_start_time = base::TimeTicks::Now();

  ImplGetCandidateAdapterNames(&adapter_names_, logging_info_.get());

  logging_info_->worker_thread_end_time = base::TimeTicks::Now();
}

const std::set<std::string>&
DhcpPacFileFetcherWin::AdapterQuery::adapter_names() const {
  return adapter_names_;
}

bool DhcpPacFileFetcherWin::AdapterQuery::ImplGetCandidateAdapterNames(
    std::set<std::string>* adapter_names,
    DhcpAdapterNamesLoggingInfo* info) {
  return DhcpPacFileFetcherWin::GetCandidateAdapterNames(adapter_names,
                                                         info);
}

DhcpPacFileFetcherWin::AdapterQuery::~AdapterQuery() {}

}  // namespace net
