// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "net/base/network_change_notifier_win.h"

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

#include <utility>

#include "base/functional/bind.h"
#include "base/location.h"
#include "base/logging.h"
#include "base/metrics/histogram_macros.h"
#include "base/task/sequenced_task_runner.h"
#include "base/task/single_thread_task_runner.h"
#include "base/task/task_traits.h"
#include "base/task/thread_pool.h"
#include "base/threading/thread.h"
#include "base/time/time.h"
#include "net/base/winsock_init.h"
#include "net/base/winsock_util.h"

namespace net {

namespace {

// Time between NotifyAddrChange retries, on failure.
const int kWatchForAddressChangeRetryIntervalMs = 500;

HRESULT GetConnectionPoints(IUnknown* manager,
                            REFIID IIDSyncInterface,
                            IConnectionPoint** connection_point_raw) {
  *connection_point_raw = nullptr;
  Microsoft::WRL::ComPtr<IConnectionPointContainer> connection_point_container;
  HRESULT hr =
      manager->QueryInterface(IID_PPV_ARGS(&connection_point_container));
  if (FAILED(hr))
    return hr;

  // Find the interface
  Microsoft::WRL::ComPtr<IConnectionPoint> connection_point;
  hr = connection_point_container->FindConnectionPoint(IIDSyncInterface,
                                                       &connection_point);
  if (FAILED(hr))
    return hr;

  *connection_point_raw = connection_point.Get();
  (*connection_point_raw)->AddRef();

  return hr;
}

}  // namespace

// This class is used as an event sink to register for notifications from the
// INetworkCostManagerEvents interface. In particular, we are focused on getting
// notified when the Connection Cost changes. This is only supported on Win10+.
class NetworkCostManagerEventSink
    : public Microsoft::WRL::RuntimeClass<
          Microsoft::WRL::RuntimeClassFlags<Microsoft::WRL::ClassicCom>,
          INetworkCostManagerEvents> {
 public:
  using CostChangedCallback = base::RepeatingCallback<void()>;

  NetworkCostManagerEventSink(INetworkCostManager* cost_manager,
                              const CostChangedCallback& callback)
      : network_cost_manager_(cost_manager), cost_changed_callback_(callback) {}
  ~NetworkCostManagerEventSink() override = default;

  // INetworkCostManagerEvents members
  IFACEMETHODIMP CostChanged(_In_ DWORD cost,
                             _In_opt_ NLM_SOCKADDR* /*pSockAddr*/) override {
    cost_changed_callback_.Run();
    return S_OK;
  }

  IFACEMETHODIMP DataPlanStatusChanged(
      _In_opt_ NLM_SOCKADDR* /*pSockAddr*/) override {
    return S_OK;
  }

  HRESULT RegisterForNotifications() {
    Microsoft::WRL::ComPtr<IUnknown> unknown;
    HRESULT hr = QueryInterface(IID_PPV_ARGS(&unknown));
    if (hr != S_OK)
      return hr;

    hr = GetConnectionPoints(network_cost_manager_.Get(),
                             IID_INetworkCostManagerEvents, &connection_point_);
    if (hr != S_OK)
      return hr;

    hr = connection_point_->Advise(unknown.Get(), &cookie_);
    return hr;
  }

  void UnRegisterForNotifications() {
    if (connection_point_) {
      connection_point_->Unadvise(cookie_);
      connection_point_ = nullptr;
      cookie_ = 0;
    }
  }

 private:
  Microsoft::WRL::ComPtr<INetworkCostManager> network_cost_manager_;
  Microsoft::WRL::ComPtr<IConnectionPoint> connection_point_;
  DWORD cookie_ = 0;
  CostChangedCallback cost_changed_callback_;
};

NetworkChangeNotifierWin::NetworkChangeNotifierWin()
    : NetworkChangeNotifier(NetworkChangeCalculatorParamsWin()),
      blocking_task_runner_(
          base::ThreadPool::CreateSequencedTaskRunner({base::MayBlock()})),
      last_computed_connection_type_(RecomputeCurrentConnectionType()),
      last_announced_offline_(last_computed_connection_type_ ==
                              CONNECTION_NONE),
      sequence_runner_for_registration_(
          base::SequencedTaskRunner::GetCurrentDefault()) {
  memset(&addr_overlapped_, 0, sizeof addr_overlapped_);
  addr_overlapped_.hEvent = WSACreateEvent();
}

NetworkChangeNotifierWin::~NetworkChangeNotifierWin() {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  ClearGlobalPointer();
  if (is_watching_) {
    CancelIPChangeNotify(&addr_overlapped_);
    addr_watcher_.StopWatching();
  }
  WSACloseEvent(addr_overlapped_.hEvent);

  if (network_cost_manager_event_sink_) {
    network_cost_manager_event_sink_->UnRegisterForNotifications();
    network_cost_manager_event_sink_ = nullptr;
  }
}

// static
NetworkChangeNotifier::NetworkChangeCalculatorParams
NetworkChangeNotifierWin::NetworkChangeCalculatorParamsWin() {
  NetworkChangeCalculatorParams params;
  // Delay values arrived at by simple experimentation and adjusted so as to
  // produce a single signal when switching between network connections.
  params.ip_address_offline_delay_ = base::Milliseconds(1500);
  params.ip_address_online_delay_ = base::Milliseconds(1500);
  params.connection_type_offline_delay_ = base::Milliseconds(1500);
  params.connection_type_online_delay_ = base::Milliseconds(500);
  return params;
}

// This implementation does not return the actual connection type but merely
// determines if the user is "online" (in which case it returns
// CONNECTION_UNKNOWN) or "offline" (and then it returns CONNECTION_NONE).
// This is challenging since the only thing we can test with certainty is
// whether a *particular* host is reachable.
//
// While we can't conclusively determine when a user is "online", we can at
// least reliably recognize some of the situtations when they are clearly
// "offline". For example, if the user's laptop is not plugged into an ethernet
// network and is not connected to any wireless networks, it must be offline.
//
// There are a number of different ways to implement this on Windows, each with
// their pros and cons. Here is a comparison of various techniques considered:
//
// (1) Use InternetGetConnectedState (wininet.dll). This function is really easy
// to use (literally a one-liner), and runs quickly. The drawback is it adds a
// dependency on the wininet DLL.
//
// (2) Enumerate all of the network interfaces using GetAdaptersAddresses
// (iphlpapi.dll), and assume we are "online" if there is at least one interface
// that is connected, and that interface is not a loopback or tunnel.
//
// Safari on Windows has a fairly simple implementation that does this:
// http://trac.webkit.org/browser/trunk/WebCore/platform/network/win/NetworkStateNotifierWin.cpp.
//
// Mozilla similarly uses this approach:
// http://mxr.mozilla.org/mozilla1.9.2/source/netwerk/system/win32/nsNotifyAddrListener.cpp
//
// The biggest drawback to this approach is it is quite complicated.
// WebKit's implementation for example doesn't seem to test for ICS gateways
// (internet connection sharing), whereas Mozilla's implementation has extra
// code to guess that.
//
// (3) The method used in this file comes from google talk, and is similar to
// method (2). The main difference is it enumerates the winsock namespace
// providers rather than the actual adapters.
//
// I ran some benchmarks comparing the performance of each on my Windows 7
// workstation. Here is what I found:
//   * Approach (1) was pretty much zero-cost after the initial call.
//   * Approach (2) took an average of 3.25 milliseconds to enumerate the
//     adapters.
//   * Approach (3) took an average of 0.8 ms to enumerate the providers.
//
// In terms of correctness, all three approaches were comparable for the simple
// experiments I ran... However none of them correctly returned "offline" when
// executing 'ipconfig /release'.
//
// static
NetworkChangeNotifier::ConnectionType
NetworkChangeNotifierWin::RecomputeCurrentConnectionType() {
  EnsureWinsockInit();

  // The following code was adapted from:
  // http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/net/notifier/base/win/async_network_alive_win32.cc?view=markup&pathrev=47343
  // The main difference is we only call WSALookupServiceNext once, whereas
  // the earlier code would traverse the entire list and pass LUP_FLUSHPREVIOUS
  // to skip past the large results.

  HANDLE ws_handle;
  WSAQUERYSET query_set = {0};
  query_set.dwSize = sizeof(WSAQUERYSET);
  query_set.dwNameSpace = NS_NLA;
  // Initiate a client query to iterate through the
  // currently connected networks.
  if (0 != WSALookupServiceBegin(&query_set, LUP_RETURN_ALL, &ws_handle)) {
    LOG(ERROR) << "WSALookupServiceBegin failed with: " << WSAGetLastError();
    return NetworkChangeNotifier::CONNECTION_UNKNOWN;
  }

  bool found_connection = false;

  // Retrieve the first available network. In this function, we only
  // need to know whether or not there is network connection.
  // Allocate 256 bytes for name, it should be enough for most cases.
  // If the name is longer, it is OK as we will check the code returned and
  // set correct network status.
  char result_buffer[sizeof(WSAQUERYSET) + 256] = {0};
  DWORD length = sizeof(result_buffer);
  reinterpret_cast<WSAQUERYSET*>(&result_buffer[0])->dwSize =
      sizeof(WSAQUERYSET);
  int result =
      WSALookupServiceNext(ws_handle, LUP_RETURN_NAME, &length,
                           reinterpret_cast<WSAQUERYSET*>(&result_buffer[0]));

  if (result == 0) {
    // Found a connection!
    found_connection = true;
  } else {
    DCHECK_EQ(SOCKET_ERROR, result);
    result = WSAGetLastError();

    // Error code WSAEFAULT means there is a network connection but the
    // result_buffer size is too small to contain the results. The
    // variable "length" returned from WSALookupServiceNext is the minimum
    // number of bytes required. We do not need to retrieve detail info,
    // it is enough knowing there was a connection.
    if (result == WSAEFAULT) {
      found_connection = true;
    } else if (result == WSA_E_NO_MORE || result == WSAENOMORE) {
      // There was nothing to iterate over!
    } else {
      LOG(WARNING) << "WSALookupServiceNext() failed with:" << result;
    }
  }

  result = WSALookupServiceEnd(ws_handle);
  LOG_IF(ERROR, result != 0) << "WSALookupServiceEnd() failed with: " << result;

  // TODO(droger): Return something more detailed than CONNECTION_UNKNOWN.
  return found_connection ? ConnectionTypeFromInterfaces()
                          : NetworkChangeNotifier::CONNECTION_NONE;
}

void NetworkChangeNotifierWin::RecomputeCurrentConnectionTypeOnBlockingSequence(
    base::OnceCallback<void(ConnectionType)> reply_callback) const {
  // Unretained is safe in this call because this object owns the thread and the
  // thread is stopped in this object's destructor.
  blocking_task_runner_->PostTaskAndReplyWithResult(
      FROM_HERE,
      base::BindOnce(&NetworkChangeNotifierWin::RecomputeCurrentConnectionType),
      std::move(reply_callback));
}

NetworkChangeNotifier::ConnectionCost
NetworkChangeNotifierWin::GetCurrentConnectionCost() {
  InitializeConnectionCost();

  // If we don't have the event sink we aren't registered for automatic updates.
  // In that case, we need to update the value at the time it is requested.
  if (!network_cost_manager_event_sink_)
    UpdateConnectionCostFromCostManager();

  return last_computed_connection_cost_;
}

bool NetworkChangeNotifierWin::InitializeConnectionCostOnce() {
  HRESULT hr =
      ::CoCreateInstance(CLSID_NetworkListManager, nullptr, CLSCTX_ALL,
                         IID_INetworkCostManager, &network_cost_manager_);
  if (FAILED(hr)) {
    SetCurrentConnectionCost(CONNECTION_COST_UNKNOWN);
    return true;
  }

  UpdateConnectionCostFromCostManager();

  return true;
}

void NetworkChangeNotifierWin::InitializeConnectionCost() {
  static bool g_connection_cost_initialized = InitializeConnectionCostOnce();
  DCHECK(g_connection_cost_initialized);
}

HRESULT NetworkChangeNotifierWin::UpdateConnectionCostFromCostManager() {
  if (!network_cost_manager_)
    return E_ABORT;

  DWORD cost = NLM_CONNECTION_COST_UNKNOWN;
  HRESULT hr = network_cost_manager_->GetCost(&cost, nullptr);
  if (FAILED(hr)) {
    SetCurrentConnectionCost(CONNECTION_COST_UNKNOWN);
  } else {
    SetCurrentConnectionCost(
        ConnectionCostFromNlmCost((NLM_CONNECTION_COST)cost));
  }
  return hr;
}

// static
NetworkChangeNotifier::ConnectionCost
NetworkChangeNotifierWin::ConnectionCostFromNlmCost(NLM_CONNECTION_COST cost) {
  if (cost == NLM_CONNECTION_COST_UNKNOWN)
    return CONNECTION_COST_UNKNOWN;
  else if ((cost & NLM_CONNECTION_COST_UNRESTRICTED) != 0)
    return CONNECTION_COST_UNMETERED;
  else
    return CONNECTION_COST_METERED;
}

void NetworkChangeNotifierWin::SetCurrentConnectionCost(
    ConnectionCost connection_cost) {
  last_computed_connection_cost_ = connection_cost;
}

void NetworkChangeNotifierWin::OnCostChanged() {
  ConnectionCost old_cost = last_computed_connection_cost_;
  // It is possible to get multiple notifications in a short period of time.
  // Rather than worrying about whether this notification represents the latest,
  // just get the current value from the CostManager so we know that we're
  // actually getting the correct value.
  UpdateConnectionCostFromCostManager();
  // Only notify if there's actually a change.
  if (old_cost != GetCurrentConnectionCost())
    NotifyObserversOfConnectionCostChange();
}

void NetworkChangeNotifierWin::ConnectionCostObserverAdded() {
  sequence_runner_for_registration_->PostTask(
      FROM_HERE,
      base::BindOnce(&NetworkChangeNotifierWin::OnConnectionCostObserverAdded,
                     weak_factory_.GetWeakPtr()));
}

void NetworkChangeNotifierWin::OnConnectionCostObserverAdded() {
  DCHECK(sequence_runner_for_registration_->RunsTasksInCurrentSequence());
  InitializeConnectionCost();

  // No need to register if we don't have a cost manager or if we're already
  // registered.
  if (!network_cost_manager_ || network_cost_manager_event_sink_)
    return;

  network_cost_manager_event_sink_ =
      Microsoft::WRL::Make<net::NetworkCostManagerEventSink>(
          network_cost_manager_.Get(),
          base::BindRepeating(&NetworkChangeNotifierWin::OnCostChanged,
                              weak_factory_.GetWeakPtr()));
  HRESULT hr = network_cost_manager_event_sink_->RegisterForNotifications();
  if (hr != S_OK) {
    // If registration failed for any reason, just destroy the event sink. The
    // observer will remain connected but will not receive any updates. If
    // another observer gets added later, we can re-attempt registration.
    network_cost_manager_event_sink_ = nullptr;
  }
}

NetworkChangeNotifier::ConnectionType
NetworkChangeNotifierWin::GetCurrentConnectionType() const {
  base::AutoLock auto_lock(last_computed_connection_type_lock_);
  return last_computed_connection_type_;
}

void NetworkChangeNotifierWin::SetCurrentConnectionType(
    ConnectionType connection_type) {
  base::AutoLock auto_lock(last_computed_connection_type_lock_);
  last_computed_connection_type_ = connection_type;
}

void NetworkChangeNotifierWin::OnObjectSignaled(HANDLE object) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  DCHECK(is_watching_);
  is_watching_ = false;

  // Start watching for the next address change.
  WatchForAddressChange();

  RecomputeCurrentConnectionTypeOnBlockingSequence(base::BindOnce(
      &NetworkChangeNotifierWin::NotifyObservers, weak_factory_.GetWeakPtr()));
}

void NetworkChangeNotifierWin::NotifyObservers(ConnectionType connection_type) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  SetCurrentConnectionType(connection_type);
  NotifyObserversOfIPAddressChange();

  // Calling GetConnectionType() at this very moment is likely to give
  // the wrong result, so we delay that until a little bit later.
  //
  // The one second delay chosen here was determined experimentally
  // by adamk on Windows 7.
  // If after one second we determine we are still offline, we will
  // delay again.
  offline_polls_ = 0;
  timer_.Start(FROM_HERE, base::Seconds(1), this,
               &NetworkChangeNotifierWin::NotifyParentOfConnectionTypeChange);
}

void NetworkChangeNotifierWin::WatchForAddressChange() {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  DCHECK(!is_watching_);

  // NotifyAddrChange occasionally fails with ERROR_OPEN_FAILED for unknown
  // reasons.  More rarely, it's also been observed failing with
  // ERROR_NO_SYSTEM_RESOURCES.  When either of these happens, we retry later.
  if (!WatchForAddressChangeInternal()) {
    ++sequential_failures_;

    base::SingleThreadTaskRunner::GetCurrentDefault()->PostDelayedTask(
        FROM_HERE,
        base::BindOnce(&NetworkChangeNotifierWin::WatchForAddressChange,
                       weak_factory_.GetWeakPtr()),
        base::Milliseconds(kWatchForAddressChangeRetryIntervalMs));
    return;
  }

  // Treat the transition from NotifyAddrChange failing to succeeding as a
  // network change event, since network changes were not being observed in
  // that interval.
  if (sequential_failures_ > 0) {
    RecomputeCurrentConnectionTypeOnBlockingSequence(
        base::BindOnce(&NetworkChangeNotifierWin::NotifyObservers,
                       weak_factory_.GetWeakPtr()));
  }

  is_watching_ = true;
  sequential_failures_ = 0;
}

bool NetworkChangeNotifierWin::WatchForAddressChangeInternal() {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);

  ResetEventIfSignaled(addr_overlapped_.hEvent);
  HANDLE handle = nullptr;
  DWORD ret = NotifyAddrChange(&handle, &addr_overlapped_);
  if (ret != ERROR_IO_PENDING)
    return false;

  addr_watcher_.StartWatchingOnce(addr_overlapped_.hEvent, this);
  return true;
}

void NetworkChangeNotifierWin::NotifyParentOfConnectionTypeChange() {
  RecomputeCurrentConnectionTypeOnBlockingSequence(base::BindOnce(
      &NetworkChangeNotifierWin::NotifyParentOfConnectionTypeChangeImpl,
      weak_factory_.GetWeakPtr()));
}

void NetworkChangeNotifierWin::NotifyParentOfConnectionTypeChangeImpl(
    ConnectionType connection_type) {
  SetCurrentConnectionType(connection_type);
  bool current_offline = IsOffline();
  offline_polls_++;
  // If we continue to appear offline, delay sending out the notification in
  // case we appear to go online within 20 seconds.  UMA histogram data shows
  // we may not detect the transition to online state after 1 second but within
  // 20 seconds we generally do.
  if (last_announced_offline_ && current_offline && offline_polls_ <= 20) {
    timer_.Start(FROM_HERE, base::Seconds(1), this,
                 &NetworkChangeNotifierWin::NotifyParentOfConnectionTypeChange);
    return;
  }
  if (last_announced_offline_)
    UMA_HISTOGRAM_CUSTOM_COUNTS("NCN.OfflinePolls", offline_polls_, 1, 50, 50);
  last_announced_offline_ = current_offline;

  NotifyObserversOfConnectionTypeChange();
  double max_bandwidth_mbps = 0.0;
  ConnectionType max_connection_type = CONNECTION_NONE;
  GetCurrentMaxBandwidthAndConnectionType(&max_bandwidth_mbps,
                                          &max_connection_type);
  NotifyObserversOfMaxBandwidthChange(max_bandwidth_mbps, max_connection_type);
}

}  // namespace net
