// Copyright 2023 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/fuchsia/network_interface_cache.h"

#include <fuchsia/net/interfaces/cpp/fidl.h>

#include <utility>

#include "base/containers/flat_map.h"
#include "base/logging.h"
#include "base/sequence_checker.h"
#include "base/synchronization/lock.h"
#include "net/base/network_change_notifier.h"
#include "net/base/network_interfaces.h"
#include "net/base/network_interfaces_fuchsia.h"
#include "third_party/abseil-cpp/absl/types/optional.h"

namespace net::internal {
namespace {

// Returns a ConnectionType derived from the supplied InterfaceProperties:
// - CONNECTION_NONE if the interface is not publicly routable.
// - Otherwise, returns a type derived from the interface's device_class.
NetworkChangeNotifier::ConnectionType GetEffectiveConnectionType(
    const InterfaceProperties& properties,
    bool require_wlan) {
  if (!properties.IsPubliclyRoutable()) {
    return NetworkChangeNotifier::CONNECTION_NONE;
  }

  NetworkChangeNotifier::ConnectionType connection_type =
      ConvertConnectionType(properties.device_class());
  if (require_wlan &&
      connection_type != NetworkChangeNotifier::CONNECTION_WIFI) {
    return NetworkChangeNotifier::CONNECTION_NONE;
  }
  return connection_type;
}

bool CanReachExternalNetwork(const InterfaceProperties& interface,
                             bool require_wlan) {
  return GetEffectiveConnectionType(interface, require_wlan) !=
         NetworkChangeNotifier::CONNECTION_NONE;
}

}  // namespace

NetworkInterfaceCache::NetworkInterfaceCache(bool require_wlan)
    : require_wlan_(require_wlan) {}

NetworkInterfaceCache::~NetworkInterfaceCache() = default;

absl::optional<NetworkInterfaceCache::ChangeBits>
NetworkInterfaceCache::AddInterfaces(
    std::vector<fuchsia::net::interfaces::Properties> interfaces) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);

  base::AutoLock auto_lock(lock_);

  ChangeBits combined_changes = kNoChange;
  for (auto& interface : interfaces) {
    auto change_bits = AddInterfaceWhileLocked(std::move(interface));
    if (!change_bits.has_value()) {
      return absl::nullopt;
    }
    combined_changes |= change_bits.value();
  }
  return combined_changes;
}

absl::optional<NetworkInterfaceCache::ChangeBits>
NetworkInterfaceCache::AddInterface(
    fuchsia::net::interfaces::Properties properties) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);

  base::AutoLock auto_lock(lock_);

  return AddInterfaceWhileLocked(std::move(properties));
}

absl::optional<NetworkInterfaceCache::ChangeBits>
NetworkInterfaceCache::AddInterfaceWhileLocked(
    fuchsia::net::interfaces::Properties properties)
    EXCLUSIVE_LOCKS_REQUIRED(lock_) VALID_CONTEXT_REQUIRED(sequence_checker_) {
  if (error_state_) {
    return absl::nullopt;
  }

  auto interface = InterfaceProperties::VerifyAndCreate(std::move(properties));
  if (!interface) {
    LOG(ERROR) << "Incomplete interface properties.";
    SetErrorWhileLocked();
    return absl::nullopt;
  }

  if (interfaces_.find(interface->id()) != interfaces_.end()) {
    LOG(ERROR) << "Unexpected duplicate interface ID " << interface->id();
    SetErrorWhileLocked();
    return absl::nullopt;
  }

  ChangeBits change_bits = kNoChange;
  if (CanReachExternalNetwork(*interface, require_wlan_)) {
    change_bits |= kIpAddressChanged;
  }
  interfaces_.emplace(interface->id(), std::move(*interface));
  if (UpdateConnectionTypeWhileLocked()) {
    change_bits |= kConnectionTypeChanged;
  }
  return change_bits;
}

absl::optional<NetworkInterfaceCache::ChangeBits>
NetworkInterfaceCache::ChangeInterface(
    fuchsia::net::interfaces::Properties properties) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);

  base::AutoLock auto_lock(lock_);
  if (error_state_) {
    return absl::nullopt;
  }

  auto cache_entry = interfaces_.find(properties.id());
  if (cache_entry == interfaces_.end()) {
    LOG(ERROR) << "Unknown interface ID " << properties.id();
    SetErrorWhileLocked();
    return absl::nullopt;
  }

  const bool old_can_reach =
      CanReachExternalNetwork(cache_entry->second, require_wlan_);
  const bool has_addresses = properties.has_addresses();

  if (!cache_entry->second.Update(std::move(properties))) {
    LOG(ERROR) << "Update failed";
    SetErrorWhileLocked();
    return absl::nullopt;
  }

  const bool new_can_reach =
      CanReachExternalNetwork(cache_entry->second, require_wlan_);

  ChangeBits change_bits = kNoChange;
  if (has_addresses || old_can_reach != new_can_reach) {
    change_bits |= kIpAddressChanged;
  }
  if (UpdateConnectionTypeWhileLocked()) {
    change_bits |= kConnectionTypeChanged;
  }
  return change_bits;
}

absl::optional<NetworkInterfaceCache::ChangeBits>
NetworkInterfaceCache::RemoveInterface(
    InterfaceProperties::InterfaceId interface_id) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);

  base::AutoLock auto_lock(lock_);
  if (error_state_) {
    return absl::nullopt;
  }

  auto cache_entry = interfaces_.find(interface_id);
  if (cache_entry == interfaces_.end()) {
    LOG(ERROR) << "Unknown interface ID " << interface_id;
    SetErrorWhileLocked();
    return absl::nullopt;
  }

  ChangeBits change_bits = kNoChange;
  if (CanReachExternalNetwork(cache_entry->second, require_wlan_)) {
    change_bits |= kIpAddressChanged;
  }
  interfaces_.erase(cache_entry);
  if (UpdateConnectionTypeWhileLocked()) {
    change_bits |= kConnectionTypeChanged;
  }
  return change_bits;
}

bool NetworkInterfaceCache::GetOnlineInterfaces(
    NetworkInterfaceList* networks) const {
  DCHECK(networks);

  base::AutoLock auto_lock(lock_);
  if (error_state_) {
    return false;
  }

  for (const auto& [_, interface] : interfaces_) {
    if (!interface.online()) {
      continue;
    }
    if (interface.device_class().is_loopback()) {
      continue;
    }
    interface.AppendNetworkInterfaces(networks);
  }
  return true;
}

NetworkChangeNotifier::ConnectionType NetworkInterfaceCache::GetConnectionType()
    const {
  base::AutoLock auto_lock(lock_);
  if (error_state_) {
    return NetworkChangeNotifier::CONNECTION_UNKNOWN;
  }

  return connection_type_;
}

void NetworkInterfaceCache::SetError() {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);

  base::AutoLock auto_lock(lock_);
  SetErrorWhileLocked();
}

bool NetworkInterfaceCache::UpdateConnectionTypeWhileLocked()
    EXCLUSIVE_LOCKS_REQUIRED(lock_) VALID_CONTEXT_REQUIRED(sequence_checker_) {
  NetworkChangeNotifier::ConnectionType connection_type =
      NetworkChangeNotifier::ConnectionType::CONNECTION_NONE;
  for (const auto& [_, interface] : interfaces_) {
    connection_type = GetEffectiveConnectionType(interface, require_wlan_);
    if (connection_type != NetworkChangeNotifier::CONNECTION_NONE) {
      break;
    }
  }
  if (connection_type != connection_type_) {
    connection_type_ = connection_type;
    return true;
  }
  return false;
}

void NetworkInterfaceCache::SetErrorWhileLocked()
    EXCLUSIVE_LOCKS_REQUIRED(lock_) VALID_CONTEXT_REQUIRED(sequence_checker_) {
  error_state_ = true;
  interfaces_.clear();
  interfaces_.shrink_to_fit();
}

}  // namespace net::internal
