// 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/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
