// Copyright 2020 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 "runtime_probe/function_templates/network.h"

#include <memory>
#include <utility>
#include <vector>

#include <base/containers/span.h>
#include <base/files/file_path.h>
#include <base/files/file_util.h>
#include <base/logging.h>
#include <base/values.h>
#include <brillo/dbus/dbus_connection.h>
#include <brillo/variant_dictionary.h>
#include <chromeos/dbus/service_constants.h>
#include <shill/dbus-proxies.h>

#include "runtime_probe/utils/file_utils.h"
#include "runtime_probe/utils/type_utils.h"
#include "runtime_probe/utils/value_utils.h"

namespace runtime_probe {
namespace {
constexpr auto kNetworkDirPath("/sys/class/net/");

constexpr auto kBusTypePci("pci");
constexpr auto kBusTypeSdio("sdio");
constexpr auto kBusTypeUsb("usb");

using FieldType = std::pair<std::string, std::string>;

const std::vector<FieldType> kPciFields = {{"vendor_id", "vendor"},
                                           {"device_id", "device"}};
const std::vector<FieldType> kPciOptionalFields = {
    {"revision", "revision"}, {"subsystem", "subsystem_device"}};
const std::vector<FieldType> kSdioFields = {{"vendor_id", "vendor"},
                                            {"device_id", "device"}};
const std::vector<FieldType> kSdioOptionalFields = {};
const std::vector<FieldType> kUsbFields = {{"vendor_id", "idVendor"},
                                           {"product_id", "idProduct"}};
const std::vector<FieldType> kUsbOptionalFields = {{"bcd_device", "bcdDevice"}};

constexpr int PCI_REVISION_ID_OFFSET = 0x08;

// For linux kernels of versions before 4.10-rc1, there is no standalone file
// `revision` describing the revision id of the PCI component.  The revision is
// still available at offset 8 of the binary file `config`.
base::Optional<uint8_t> GetPciRevisionIdFromConfig(base::FilePath node_path) {
  const auto file_path = node_path.Append("config");
  if (!base::PathExists(file_path)) {
    LOG(ERROR) << file_path.value() << " doesn't exist.";
    return base::nullopt;
  }
  base::File config{file_path, base::File::FLAG_OPEN | base::File::FLAG_READ};
  uint8_t revision_array[1];
  base::span<uint8_t> revision_span(revision_array);
  if (!config.ReadAndCheck(PCI_REVISION_ID_OFFSET, revision_span)) {
    LOG(ERROR) << "Cannot read file " << file_path << " at offset "
               << PCI_REVISION_ID_OFFSET;
    return base::nullopt;
  }
  return revision_array[0];
}

std::vector<brillo::VariantDictionary> GetDevicesProps(
    base::Optional<std::string> type) {
  std::vector<brillo::VariantDictionary> devices_props{};

  brillo::DBusConnection dbus_connection;
  const auto bus = dbus_connection.Connect();
  if (bus == nullptr) {
    LOG(ERROR) << "Failed to connect to system D-Bus service.";
    return {};
  }

  auto shill_proxy =
      std::make_unique<org::chromium::flimflam::ManagerProxy>(bus);
  brillo::VariantDictionary props;
  if (!shill_proxy->GetProperties(&props, nullptr)) {
    LOG(ERROR) << "Unable to get manager properties.";
    return {};
  }
  const auto it = props.find(shill::kDevicesProperty);
  if (it == props.end()) {
    LOG(ERROR) << "Manager properties is missing devices.";
    return {};
  }

  for (const auto& path : it->second.TryGet<std::vector<dbus::ObjectPath>>()) {
    auto device =
        std::make_unique<org::chromium::flimflam::DeviceProxy>(bus, path);
    brillo::VariantDictionary device_props;
    if (!device->GetProperties(&device_props, nullptr)) {
      VLOG(2) << "Unable to get device properties of " << path.value()
              << ". Skipped.";
      continue;
    }
    auto device_type = device_props[shill::kTypeProperty].TryGet<std::string>();
    if (!type || device_type == type) {
      devices_props.push_back(std::move(device_props));
    }
  }

  return devices_props;
}

base::Optional<base::Value> GetNetworkData(const base::FilePath& node_path) {
  const auto dev_path = node_path.Append("device");
  const auto dev_subsystem_path = dev_path.Append("subsystem");
  base::FilePath dev_subsystem_link_path;
  if (!base::ReadSymbolicLink(dev_subsystem_path, &dev_subsystem_link_path)) {
    LOG(ERROR) << "Cannot get real path of " << dev_subsystem_path.value();
    return base::nullopt;
  }

  auto bus_type_idx = dev_subsystem_link_path.value().find_last_of('/') + 1;
  const std::string bus_type =
      dev_subsystem_link_path.value().substr(bus_type_idx);

  const std::vector<FieldType>*fields, *optional_fields;
  base::FilePath field_path;
  if (bus_type == kBusTypePci) {
    field_path = dev_path;
    fields = &kPciFields;
    optional_fields = &kPciOptionalFields;
  } else if (bus_type == kBusTypeSdio) {
    field_path = dev_path;
    fields = &kSdioFields;
    optional_fields = &kSdioOptionalFields;
  } else if (bus_type == kBusTypeUsb) {
    field_path = base::MakeAbsoluteFilePath(dev_path.Append(".."));
    fields = &kUsbFields;
    optional_fields = &kUsbOptionalFields;
  } else {
    LOG(ERROR) << "Unknown bus_type " << bus_type;
    return base::nullopt;
  }

  auto res = MapFilesToDict(field_path, *fields, *optional_fields);
  if (!res) {
    LOG(ERROR) << "Cannot find " << bus_type << "-specific fields on network \""
               << dev_path.value() << "\"";
    return base::nullopt;
  }

  if (bus_type == kBusTypePci && !res->FindKey("revision")) {
    auto revision_id = GetPciRevisionIdFromConfig(dev_path);
    if (revision_id) {
      res->SetStringKey("revision", ByteToHexString(*revision_id));
    }
  }
  PrependToDVKey(&*res, std::string(bus_type) + "_");
  res->SetStringKey("bus_type", bus_type);

  return res;
}

}  // namespace

NetworkFunction::DataType NetworkFunction::EvalImpl() const {
  const auto devices_props = GetDevicesProps(GetNetworkType());
  NetworkFunction::DataType result{};

  for (const auto& device_props : devices_props) {
    base::FilePath node_path(
        kNetworkDirPath +
        device_props.at(shill::kInterfaceProperty).TryGet<std::string>());
    std::string device_type =
        device_props.at(shill::kTypeProperty).TryGet<std::string>();

    VLOG(2) << "Processing the node \"" << node_path.value() << "\".";

    // Get type specific fields and their values.
    auto node_res = GetNetworkData(node_path);
    if (!node_res)
      continue;

    // Report the absolute path we probe the reported info from.
    VLOG_IF(2, node_res->FindStringKey("path"))
        << "Attribute \"path\" already existed. Overrided.";
    node_res->SetStringKey("path", node_path.value());

    VLOG_IF(2, node_res->FindStringKey("type"))
        << "Attribute \"type\" already existed. Overrided.";
    // Align with the category name.
    if (device_type == shill::kTypeWifi) {
      node_res->SetStringKey("type", kTypeWireless);
    } else {
      node_res->SetStringKey("type", device_type);
    }

    result.push_back(std::move(*node_res));
  }

  return result;
}

}  // namespace runtime_probe
