// Copyright 2016 The Chromium OS 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 "patchpanel/shill_client.h"

#include <base/bind.h>
#include <base/check.h>
#include <base/logging.h>
#include <base/strings/string_util.h>
#include <brillo/variant_dictionary.h>
#include <chromeos/dbus/service_constants.h>

namespace patchpanel {

namespace {

ShillClient::Device::Type ParseDeviceType(const std::string& type_str) {
  static const std::map<std::string, ShillClient::Device::Type> str2enum{
      {shill::kTypeCellular, ShillClient::Device::Type::kCellular},
      {shill::kTypeEthernet, ShillClient::Device::Type::kEthernet},
      {shill::kTypeEthernetEap, ShillClient::Device::Type::kEthernetEap},
      {shill::kTypeGuestInterface, ShillClient::Device::Type::kGuestInterface},
      {shill::kTypeLoopback, ShillClient::Device::Type::kLoopback},
      {shill::kTypePPP, ShillClient::Device::Type::kPPP},
      {shill::kTypePPPoE, ShillClient::Device::Type::kPPPoE},
      {shill::kTypeTunnel, ShillClient::Device::Type::kTunnel},
      {shill::kTypeWifi, ShillClient::Device::Type::kWifi},
      {shill::kTypeVPN, ShillClient::Device::Type::kVPN},
  };

  const auto it = str2enum.find(type_str);
  return it != str2enum.end() ? it->second
                              : ShillClient::Device::Type::kUnknown;
}

const std::string DeviceTypeName(ShillClient::Device::Type type) {
  static const std::map<ShillClient::Device::Type, std::string> enum2str{
      {ShillClient::Device::Type::kUnknown, "Unknown"},
      {ShillClient::Device::Type::kCellular, "Cellular"},
      {ShillClient::Device::Type::kEthernet, "Ethernet"},
      {ShillClient::Device::Type::kEthernetEap, "EthernetEap"},
      {ShillClient::Device::Type::kGuestInterface, "GuestInterface"},
      {ShillClient::Device::Type::kLoopback, "Loopback"},
      {ShillClient::Device::Type::kPPP, "PPP"},
      {ShillClient::Device::Type::kPPPoE, "PPPoE"},
      {ShillClient::Device::Type::kTunnel, "Tunnel"},
      {ShillClient::Device::Type::kVPN, "VPN"},
      {ShillClient::Device::Type::kWifi, "Wifi"},
  };

  const auto it = enum2str.find(type);
  return it != enum2str.end() ? it->second : "Unknown";
}

}  // namespace

ShillClient::ShillClient(const scoped_refptr<dbus::Bus>& bus) : bus_(bus) {
  manager_proxy_.reset(new org::chromium::flimflam::ManagerProxy(bus_));
  manager_proxy_->RegisterPropertyChangedSignalHandler(
      base::BindRepeating(&ShillClient::OnManagerPropertyChange,
                          weak_factory_.GetWeakPtr()),
      base::BindOnce(&ShillClient::OnManagerPropertyChangeRegistration,
                     weak_factory_.GetWeakPtr()));
}

const std::string& ShillClient::default_logical_interface() const {
  return default_logical_device_.ifname;
}

const std::string& ShillClient::default_physical_interface() const {
  return default_physical_device_.ifname;
}

const ShillClient::Device& ShillClient::default_logical_device() const {
  return default_logical_device_;
}

const ShillClient::Device& ShillClient::default_physical_device() const {
  return default_physical_device_;
}

const std::vector<std::string> ShillClient::get_interfaces() const {
  std::vector<std::string> ifnames;
  for (const auto& [_, ifname] : devices_) {
    ifnames.push_back(ifname);
  }
  return ifnames;
}

bool ShillClient::has_interface(const std::string& ifname) const {
  for (const auto& kv : devices_) {
    if (kv.second == ifname) {
      return true;
    }
  }
  return false;
}

void ShillClient::ScanDevices() {
  brillo::VariantDictionary props;
  if (!manager_proxy_->GetProperties(&props, nullptr)) {
    LOG(ERROR) << "Unable to get Manager properties";
    return;
  }
  const auto it = props.find(shill::kDevicesProperty);
  if (it == props.end()) {
    LOG(WARNING) << "Manager properties is missing " << shill::kDevicesProperty;
    return;
  }
  UpdateDevices(it->second);
}

std::pair<ShillClient::Device, ShillClient::Device>
ShillClient::GetDefaultDevices() {
  brillo::VariantDictionary properties;
  if (!manager_proxy_->GetProperties(&properties, nullptr)) {
    LOG(ERROR) << "Unable to get manager properties";
    return {};
  }
  auto services =
      brillo::GetVariantValueOrDefault<std::vector<dbus::ObjectPath>>(
          properties, shill::kServicesProperty);

  Device default_logical_device = {};
  Device default_physical_device = {};
  for (const auto& service_path : services) {
    properties = GetServiceProperties(service_path);

    auto device_path = brillo::GetVariantValueOrDefault<dbus::ObjectPath>(
        properties, shill::kDeviceProperty);
    if (!device_path.IsValid()) {
      LOG(WARNING) << "Failed to obtain device for service ["
                   << service_path.value() << "]";
      return {};
    }

    auto it = properties.find(shill::kIsConnectedProperty);
    if (it == properties.end()) {
      LOG(ERROR) << "Service " << service_path.value() << " missing property "
                 << shill::kIsConnectedProperty;
      return {};
    }

    if (!it->second.TryGet<bool>()) {
      LOG(INFO) << "Ignoring non-connected Service " << service_path.value();
      return {};
    }

    std::string service_type = brillo::GetVariantValueOrDefault<std::string>(
        properties, shill::kTypeProperty);
    if (service_type.empty()) {
      LOG(ERROR) << "Service " << service_path.value() << " missing property "
                 << shill::kTypeProperty;
      return {};
    }

    auto device = GetDevice(service_path, device_path, service_type);
    if (device.type == ShillClient::Device::Type::kVPN) {
      default_logical_device = device;
    } else {
      default_physical_device = device;
      if (default_logical_device.type == ShillClient::Device::Type::kUnknown) {
        default_logical_device = device;
      }
      break;
    }
  }
  return std::make_pair(default_logical_device, default_physical_device);
}

void ShillClient::OnManagerPropertyChangeRegistration(
    const std::string& interface,
    const std::string& signal_name,
    bool success) {
  if (!success)
    LOG(FATAL) << "Unable to register for interface change events";
}

void ShillClient::OnManagerPropertyChange(const std::string& property_name,
                                          const brillo::Any& property_value) {
  if (property_name == shill::kDevicesProperty) {
    UpdateDevices(property_value);
  } else if (property_name != shill::kDefaultServiceProperty &&
             property_name != shill::kServicesProperty &&
             property_name != shill::kConnectionStateProperty) {
    return;
  }

  // All registered DefaultDeviceChangeHandler objects should be called if
  // the default network has changed or if shill::kDevicesProperty has changed.
  SetDefaultDevices(GetDefaultDevices());
}

void ShillClient::SetDefaultDevices(const std::pair<Device, Device>& devices) {
  auto default_logical_device = devices.first;
  auto default_physical_device = devices.second;
  if (default_logical_device_.ifname != default_logical_device.ifname) {
    LOG(INFO) << "Default network changed from " << default_logical_device_
              << " to " << default_logical_device;

    for (const auto& h : default_logical_device_handlers_) {
      if (!h.is_null())
        h.Run(default_logical_device, default_logical_device_);
    }
    default_logical_device_ = default_logical_device;
  }

  if (default_physical_device_.ifname != default_physical_device.ifname) {
    LOG(INFO) << "Default physical device changed from "
              << default_physical_device_ << " to " << default_physical_device;

    for (const auto& h : default_physical_device_handlers_) {
      if (!h.is_null())
        h.Run(default_physical_device, default_physical_device_);
    }
    default_physical_device_ = default_physical_device;
  }
}

brillo::VariantDictionary ShillClient::GetServiceProperties(
    const dbus::ObjectPath& service_path) {
  brillo::ErrorPtr error;
  brillo::VariantDictionary properties;
  org::chromium::flimflam::ServiceProxy service_proxy(bus_, service_path);
  if (!service_proxy.GetProperties(&properties, &error)) {
    LOG(ERROR) << "Failed to obtain service [" << service_path.value()
               << "] properties: " << error->GetMessage();
  }
  return properties;
}

brillo::VariantDictionary ShillClient::GetDeviceProperties(
    const dbus::ObjectPath& device_path) {
  brillo::VariantDictionary properties;
  org::chromium::flimflam::DeviceProxy device_proxy(bus_, device_path);
  if (!device_proxy.GetProperties(&properties, nullptr)) {
    LOG(ERROR) << "Can't retrieve properties for device";
  }
  return properties;
}

ShillClient::Device ShillClient::GetDevice(const dbus::ObjectPath& service_path,
                                           const dbus::ObjectPath& device_path,
                                           const std::string& service_type) {
  Device device = {};

  auto properties = GetDeviceProperties(device_path);
  device.ifname = brillo::GetVariantValueOrDefault<std::string>(
      properties, shill::kInterfaceProperty);
  if (device.ifname.empty()) {
    LOG(ERROR) << "Empty interface name for shill Device "
               << device_path.value();
    return {};
  }

  device.type = ParseDeviceType(service_type);
  device.service_path = service_path.value();
  return device;
}

void ShillClient::RegisterDefaultLogicalDeviceChangedHandler(
    const DefaultDeviceChangeHandler& handler) {
  default_logical_device_handlers_.emplace_back(handler);
  // Explicitly trigger the callback once to let it know of the the current
  // default interface. The previous interface is left empty.
  handler.Run(default_logical_device_, {});
}

void ShillClient::RegisterDefaultPhysicalDeviceChangedHandler(
    const DefaultDeviceChangeHandler& handler) {
  default_physical_device_handlers_.emplace_back(handler);
  // Explicitly trigger the callback once to let it know of the the current
  // default interface. The previous interface is left empty.
  handler.Run(default_physical_device_, {});
}

void ShillClient::RegisterDevicesChangedHandler(
    const DevicesChangeHandler& handler) {
  device_handlers_.emplace_back(handler);
}

void ShillClient::RegisterIPConfigsChangedHandler(
    const IPConfigsChangeHandler& handler) {
  ipconfigs_handlers_.emplace_back(handler);
}

void ShillClient::UpdateDevices(const brillo::Any& property_value) {
  std::map<std::string, std::string> new_devices;
  std::vector<std::string> added, removed;
  for (const auto& path :
       property_value.TryGet<std::vector<dbus::ObjectPath>>()) {
    std::string device = path.value();
    // Strip "/device/" prefix.
    device = device.substr(device.find_last_of('/') + 1);
    const std::string ifname = GetIfname(path);
    if (ifname.empty()) {
      LOG(WARNING) << "Found empty interface name for Device " << device;
      continue;
    }

    new_devices[device] = ifname;
    if (devices_.find(device) == devices_.end()) {
      added.push_back(ifname);
    }

    // Registers handler if we see this device for the first time.
    if (known_device_paths_.insert(std::make_pair(device, path)).second) {
      org::chromium::flimflam::DeviceProxy proxy(bus_, path);
      proxy.RegisterPropertyChangedSignalHandler(
          base::BindRepeating(&ShillClient::OnDevicePropertyChange,
                              weak_factory_.GetWeakPtr(), device),
          base::BindOnce(&ShillClient::OnDevicePropertyChangeRegistration,
                         weak_factory_.GetWeakPtr()));
      known_device_paths_[device] = path;
    }
  }

  for (const auto& [d, ifname] : devices_) {
    if (new_devices.find(d) == new_devices.end()) {
      removed.push_back(ifname);
    }
  }

  devices_ = new_devices;

  // This can happen if the default network switched from one device to another.
  if (added.empty() && removed.empty())
    return;

  LOG(INFO) << "shill Devices changed: added={" << base::JoinString(added, ",")
            << "}, removed={" << base::JoinString(removed, ",") << "}";

  for (const auto& h : device_handlers_)
    h.Run(added, removed);
}

ShillClient::IPConfig ShillClient::ParseIPConfigsProperty(
    const std::string& device, const brillo::Any& property_value) {
  IPConfig ipconfig;
  for (const auto& path :
       property_value.TryGet<std::vector<dbus::ObjectPath>>()) {
    std::unique_ptr<org::chromium::flimflam::IPConfigProxy> ipconfig_proxy(
        new org::chromium::flimflam::IPConfigProxy(bus_, path));
    brillo::VariantDictionary ipconfig_props;

    if (!ipconfig_proxy->GetProperties(&ipconfig_props, nullptr)) {
      // It is possible that an IPConfig object is removed after we know its
      // path, especially when the interface is going down.
      LOG(WARNING) << "[" << device << "]: "
                   << "Unable to get properties for " << path.value();
      continue;
    }

    // Detects the type of IPConfig. For ipv4 and ipv6 configurations, there
    // should be at most one for each type.
    auto it = ipconfig_props.find(shill::kMethodProperty);
    if (it == ipconfig_props.end()) {
      LOG(WARNING) << "[" << device << "]: "
                   << "IPConfig properties is missing Method";
      continue;
    }
    const std::string& method = it->second.TryGet<std::string>();
    const bool is_ipv4_type =
        (method == shill::kTypeIPv4 || method == shill::kTypeDHCP ||
         method == shill::kTypeBOOTP || method == shill::kTypeZeroConf);
    const bool is_ipv6_type = (method == shill::kTypeIPv6);
    if (!is_ipv4_type && !is_ipv6_type) {
      LOG(WARNING) << "[" << device << "]: "
                   << "unknown type \"" << method << "\" for " << path.value();
      continue;
    }
    if ((is_ipv4_type && !ipconfig.ipv4_address.empty()) ||
        (is_ipv6_type && !ipconfig.ipv6_address.empty())) {
      LOG(WARNING) << "[" << device << "]: "
                   << "Duplicated ipconfig for " << method;
      continue;
    }

    // Gets the value of address, prefix_length, gateway, and dns_servers.
    it = ipconfig_props.find(shill::kAddressProperty);
    if (it == ipconfig_props.end()) {
      LOG(WARNING) << "[" << device << "]: "
                   << "IPConfig properties is missing Address";
      continue;
    }
    const std::string& address = it->second.TryGet<std::string>();

    it = ipconfig_props.find(shill::kPrefixlenProperty);
    if (it == ipconfig_props.end()) {
      LOG(WARNING) << "[" << device << "]: "
                   << "IPConfig properties is missing Prefixlen";
      continue;
    }
    int prefix_length = it->second.TryGet<int>();

    it = ipconfig_props.find(shill::kGatewayProperty);
    if (it == ipconfig_props.end()) {
      LOG(WARNING) << "[" << device << "]: "
                   << "IPConfig properties is missing Gateway";
      continue;
    }
    const std::string& gateway = it->second.TryGet<std::string>();

    it = ipconfig_props.find(shill::kNameServersProperty);
    if (it == ipconfig_props.end()) {
      LOG(WARNING) << "[" << device << "]: "
                   << "IPConfig properties is missing NameServers";
      // Shill will emit this property with empty value if it has no dns for
      // this device, so missing this property indicates an error.
      continue;
    }
    const std::vector<std::string>& dns_addresses =
        it->second.TryGet<std::vector<std::string>>();

    // Checks if this ipconfig is valid: address, gateway, and prefix_length
    // should not be empty.
    if (address.empty() || gateway.empty() || prefix_length == 0) {
      LOG(WARNING) << "[" << device << "]: "
                   << "Skipped invalid ipconfig: "
                   << "address.length()=" << address.length()
                   << ", gateway.length()=" << gateway.length()
                   << ", prefix_length=" << prefix_length;
      continue;
    }

    // Fills the IPConfig struct according to the type.
    if (is_ipv4_type) {
      ipconfig.ipv4_prefix_length = prefix_length;
      ipconfig.ipv4_address = address;
      ipconfig.ipv4_gateway = gateway;
      ipconfig.ipv4_dns_addresses = dns_addresses;
    } else {  // is_ipv6_type
      ipconfig.ipv6_prefix_length = prefix_length;
      ipconfig.ipv6_address = address;
      ipconfig.ipv6_gateway = gateway;
      ipconfig.ipv6_dns_addresses = dns_addresses;
    }
  }

  return ipconfig;
}

bool ShillClient::GetDeviceProperties(const std::string& ifname,
                                      Device* output) {
  DCHECK(output);

  std::string device = "";
  for (const auto& kv : devices_) {
    if (kv.second == ifname) {
      device = kv.first;
      break;
    }
  }
  if (device.empty()) {
    LOG(ERROR) << "Unknown interface name " << ifname;
    return false;
  }

  const auto& device_it = known_device_paths_.find(device);
  if (device_it == known_device_paths_.end()) {
    LOG(ERROR) << "Unknown shill Device " << device;
    return false;
  }

  org::chromium::flimflam::DeviceProxy proxy(bus_, device_it->second);
  brillo::VariantDictionary props;
  if (!proxy.GetProperties(&props, nullptr)) {
    LOG(WARNING) << "Unable to get shill Device properties for " << device;
    return false;
  }

  const auto& type_it = props.find(shill::kTypeProperty);
  if (type_it == props.end()) {
    LOG(WARNING) << "shill Device properties is missing Type for " << device;
    return false;
  }
  const std::string& type_str = type_it->second.TryGet<std::string>();
  output->type = ParseDeviceType(type_str);
  if (output->type == Device::Type::kUnknown)
    LOG(WARNING) << "Unknown shill Device type " << type_str << " for "
                 << device;

  const auto& interface_it = props.find(shill::kInterfaceProperty);
  if (interface_it == props.end()) {
    LOG(WARNING) << "shill Device properties is missing Interface for "
                 << device;
    return false;
  }
  output->ifname = interface_it->second.TryGet<std::string>();

  const auto& ipconfigs_it = props.find(shill::kIPConfigsProperty);
  if (ipconfigs_it == props.end()) {
    LOG(WARNING) << "shill Device properties is missing IPConfigs for "
                 << device;
    return false;
  }
  output->ipconfig = ParseIPConfigsProperty(device, ipconfigs_it->second);

  return true;
}

std::string ShillClient::GetIfname(const dbus::ObjectPath& device_path) {
  org::chromium::flimflam::DeviceProxy device_proxy(bus_, device_path);
  brillo::VariantDictionary props;
  if (!device_proxy.GetProperties(&props, nullptr)) {
    LOG(WARNING) << "Unable to get Device properties for "
                 << device_path.value();
    return "";
  }

  const auto& interface_it = props.find(shill::kInterfaceProperty);
  if (interface_it == props.end()) {
    LOG(WARNING) << "shill Device properties is missing Interface for "
                 << device_path.value();
    return "";
  }

  return interface_it->second.TryGet<std::string>();
}

void ShillClient::OnDevicePropertyChangeRegistration(
    const std::string& interface,
    const std::string& signal_name,
    bool success) {
  if (!success)
    LOG(ERROR) << "[" << interface << "]: "
               << "Unable to register listener for " << signal_name;
}

void ShillClient::OnDevicePropertyChange(const std::string& device,
                                         const std::string& property_name,
                                         const brillo::Any& property_value) {
  if (property_name != shill::kIPConfigsProperty)
    return;

  const IPConfig& ipconfig = ParseIPConfigsProperty(device, property_value);
  const auto& it = devices_.find(device);
  if (it == devices_.end()) {
    LOG(WARNING) << "Failed to obtain interface name for shill Device "
                 << device;
    return;
  }

  // TODO(jiejiang): Keep a cache of the last parsed IPConfig, and only
  // trigger handlers if there is an actual change.
  for (const auto& handler : ipconfigs_handlers_)
    handler.Run(it->second, ipconfig);
}

std::ostream& operator<<(std::ostream& stream, const ShillClient::Device& dev) {
  return stream << "{ifname: " << dev.ifname
                << ", type: " << DeviceTypeName(dev.type)
                << ", service: " << dev.service_path << "}";
}

std::ostream& operator<<(std::ostream& stream,
                         const ShillClient::Device::Type type) {
  return stream << DeviceTypeName(type);
}

}  // namespace patchpanel
