// Copyright 2019 The Fuchsia 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 "src/bringup/bin/netsvc/netifc-discover.h"

#include <fcntl.h>
#include <fidl/fuchsia.device/cpp/wire.h>
#include <lib/async-loop/cpp/loop.h>
#include <lib/async/cpp/wait.h>
#include <lib/component/incoming/cpp/protocol.h>
#include <lib/fdio/cpp/caller.h>
#include <lib/fdio/directory.h>
#include <lib/fit/defer.h>
#include <lib/stdcompat/string_view.h>
#include <stdio.h>

#include <fbl/unique_fd.h>

#include "src/lib/fsl/io/device_watcher.h"

namespace {

cpp17::string_view SkipInstanceSigil(cpp17::string_view v) {
  if (!v.empty() && v.at(0) == '@') {
    return v.substr(1);
  }
  return v;
}

struct Netdevice {
  struct Info {
    fidl::ClientEnd<fuchsia_hardware_network::Device> device;
    fidl::ClientEnd<fuchsia_hardware_network::PortWatcher> port_watcher;
  };
  static constexpr const char* kDirectory = "/class/network";

  static std::optional<Info> get_interface_if_matching(
      fidl::ClientEnd<fuchsia_hardware_network::DeviceInstance> instance,
      const std::string& filename) {
    auto [client_end, server_end] = fidl::Endpoints<fuchsia_hardware_network::Device>::Create();

    {
      fidl::Status result = fidl::WireCall(instance)->GetDevice(std::move(server_end));
      if (!result.ok()) {
        printf("netifc: failed to get NetworkDevice from instance %s: %s\n", filename.c_str(),
               result.status_string());
        return std::nullopt;
      }
    }

    auto [watcher_client_end, watcher_server_end] =
        fidl::Endpoints<fuchsia_hardware_network::PortWatcher>::Create();

    {
      fidl::Status result =
          fidl::WireCall(client_end)->GetPortWatcher(std::move(watcher_server_end));
      if (!result.ok()) {
        printf("netifc: failed to get port watcher %s: %s\n", filename.c_str(),
               result.status_string());
        return std::nullopt;
      }
    }

    return Info{
        .device = std::move(client_end),
        .port_watcher = std::move(watcher_client_end),
    };
  }

  static void Process(std::optional<NetdeviceInterface>& discovered, async_dispatcher_t* dispatcher,
                      Info info) {
    auto [device, watcher] = std::move(info);
    std::shared_ptr client_ptr =
        std::make_shared<fidl::WireClient<fuchsia_hardware_network::PortWatcher>>(
            std::move(watcher), dispatcher);

    Watch(discovered, client_ptr, std::move(device));
  }

  static void Watch(
      std::optional<NetdeviceInterface>& discovered,
      const std::shared_ptr<fidl::WireClient<fuchsia_hardware_network::PortWatcher>>& watcher,
      fidl::ClientEnd<fuchsia_hardware_network::Device> dev) {
    (*watcher)->Watch().ThenExactlyOnce(
        [&discovered, watcher, dev = std::move(dev)](
            fidl::WireUnownedResult<fuchsia_hardware_network::PortWatcher::Watch>& r) mutable {
          if (!r.ok()) {
            printf("netifc: failed to watch for netdevice ports: %s\n",
                   r.FormatDescription().c_str());
            return;
          }

          auto defer = fit::defer([&discovered, &watcher, &dev]() {
            // Watch next.
            Watch(discovered, watcher, std::move(dev));
          });

          const fuchsia_hardware_network::wire::DevicePortEvent& event = r.value().event;
          fuchsia_hardware_network::wire::PortId port_id;
          switch (event.Which()) {
            case fuchsia_hardware_network::wire::DevicePortEvent::Tag::kAdded:
              port_id = event.added();
              break;
            case fuchsia_hardware_network::wire::DevicePortEvent::Tag::kExisting:
              port_id = event.existing();
              break;
            case fuchsia_hardware_network::wire::DevicePortEvent::Tag::kIdle:
            case fuchsia_hardware_network::wire::DevicePortEvent::Tag::kRemoved:
              return;
          }

          auto [port_client_end, port_server_end] =
              fidl::Endpoints<fuchsia_hardware_network::Port>::Create();
          {
            fidl::Status result = fidl::WireCall(dev)->GetPort(port_id, std::move(port_server_end));
            if (!result.ok()) {
              printf("netifc: failed to get netdevice port (%d:%d): %s\n", port_id.base,
                     port_id.salt, result.FormatDescription().c_str());
              return;
            }
          }
          {
            fidl::WireResult result = fidl::WireCall(port_client_end)->GetInfo();
            if (!result.ok()) {
              printf("netifc: failed to get netdevice port info (%d:%d): %s\n", port_id.base,
                     port_id.salt, result.FormatDescription().c_str());
              return;
            }
            const fuchsia_hardware_network::wire::PortInfo& port_info = result.value().info;
            if (!(port_info.has_base_info() && port_info.base_info().has_port_class())) {
              printf("netifc: missing port class in netdevice port info (%d:%d): %s\n",
                     port_id.base, port_id.salt, result.FormatDescription().c_str());
              return;
            }
            switch (port_info.base_info().port_class()) {
              case fuchsia_hardware_network::DeviceClass::kEthernet:
              case fuchsia_hardware_network::DeviceClass::kVirtual:
                // NB: Historically this only netifc only accepts Ethernet
                // device. We allow virtual interfaces as well which are used in
                // testing.
                break;
              case fuchsia_hardware_network::DeviceClass::kBridge:
              case fuchsia_hardware_network::DeviceClass::kWlan:
              case fuchsia_hardware_network::DeviceClass::kPpp:
              case fuchsia_hardware_network::DeviceClass::kWlanAp:
                printf("netifc: ignoring netdevice port (%d:%d) with class %hu\n", port_id.base,
                       port_id.salt,
                       static_cast<unsigned short>(port_info.base_info().port_class()));
                return;
            }
          }

          // This is a good candidate port, but we need to retrieve the MAC
          // address.
          auto [mac_client_end, mac_server_end] =
              fidl::Endpoints<fuchsia_hardware_network::MacAddressing>::Create();
          {
            fidl::Status result =
                fidl::WireCall(port_client_end)->GetMac(std::move(mac_server_end));
            if (!result.ok()) {
              printf("netifc: failed to get mac addressing for port (%d:%d): %s\n", port_id.base,
                     port_id.salt, result.FormatDescription().c_str());
              return;
            }
          }

          fidl::WireResult result = fidl::WireCall(mac_client_end)->GetUnicastAddress();
          if (!result.ok()) {
            printf("netifc: failed to get mac address for port (%d:%d): %s\n", port_id.base,
                   port_id.salt, result.FormatDescription().c_str());
            return;
          }
          const fuchsia_net::wire::MacAddress& mac = result.value().address;

          // We have our device, store it and stop watching.
          NetdeviceInterface& discovered_interface = discovered.emplace(NetdeviceInterface{
              .device = std::move(dev),
              .port_id = port_id,
          });
          static_assert(sizeof(mac.octets) == sizeof(discovered_interface.mac.x));
          std::copy(mac.octets.begin(), mac.octets.end(), std::begin(discovered_interface.mac.x));
          defer.cancel();
        });
  }
};

std::optional<Netdevice::Info> netifc_evaluate(cpp17::string_view topological_path,
                                               fidl::UnownedClientEnd<fuchsia_io::Directory> dir,
                                               const std::string& dirname,
                                               const std::string& filename) {
  printf("netifc: ? %s/%s\n", dirname.c_str(), filename.c_str());

  fidl::ClientEnd<fuchsia_hardware_network::DeviceInstance> dev;
  {
    zx::result status =
        component::ConnectAt<fuchsia_hardware_network::DeviceInstance>(dir, filename);
    if (status.is_error()) {
      printf("netifc: failed to connect to %s/%s: %s\n", dirname.c_str(), filename.c_str(),
             status.status_string());
      return std::nullopt;
    }
    dev = std::move(status.value());
  }

  // If an interface was specified, check the topological path of this device and reject it if it
  // doesn't match.
  if (!topological_path.empty()) {
    std::string controller_path = filename + "/device_controller";
    zx::result controller = component::ConnectAt<fuchsia_device::Controller>(dir, controller_path);
    if (controller.is_error()) {
      printf("netifc: failed to connect to %s/%s: %s\n", dirname.c_str(), controller_path.c_str(),
             controller.status_string());
      return std::nullopt;
    }
    fidl::WireResult result = fidl::WireCall(controller.value())->GetTopologicalPath();

    if (!result.ok()) {
      printf("netifc: failed to get topological path %s: %s\n", filename.c_str(),
             result.status_string());
      return std::nullopt;
    }
    auto& resp = result.value();
    if (resp.is_error()) {
      printf("netifc: GetTopologicalPath returned error %s: %s\n", filename.c_str(),
             zx_status_get_string(resp.error_value()));
      return std::nullopt;
    }

    cpp17::string_view topo_path = SkipInstanceSigil(resp.value()->path.get());
    // Look for a suffix to avoid coupling too tightly.
    if (!cpp20::ends_with(topo_path, topological_path)) {
      return std::nullopt;
    }
  }

  std::optional result = Netdevice::get_interface_if_matching(std::move(dev), filename);
  if (result.has_value()) {
    printf("netsvc: using %s/%s\n", dirname.c_str(), filename.c_str());
  }
  return result;
}

zx::result<std::unique_ptr<fsl::DeviceWatcher>> CreateWatcher(
    async_dispatcher_t* dispatcher, std::optional<NetdeviceInterface>& selected_ifc,
    const std::string& devdir, cpp17::string_view topological_path) {
  const std::string classdir = devdir + Netdevice::kDirectory;
  fbl::unique_fd dir(open(classdir.c_str(), O_DIRECTORY | O_RDONLY));
  if (!dir.is_valid()) {
    printf("failed to open %s: %s\n", classdir.c_str(), strerror(errno));
    return zx::error(ZX_ERR_INVALID_ARGS);
  }
  fdio_cpp::FdioCaller caller(std::move(dir));

  zx::result dir_channel = caller.take_directory();
  if (dir_channel.is_error()) {
    return dir_channel.take_error();
  }

  std::unique_ptr watcher = fsl::DeviceWatcher::Create(
      classdir,
      [dispatcher, classdir, topological_path, &selected_ifc](
          const fidl::ClientEnd<fuchsia_io::Directory>& dir, const std::string& filename) {
        std::optional r = netifc_evaluate(topological_path, dir, classdir, filename);
        if (r.has_value()) {
          Netdevice::Process(selected_ifc, dispatcher, std::move(r.value()));
        }
      },
      dispatcher);

  return zx::ok(std::move(watcher));
}

}  // namespace

zx::result<NetdeviceInterface> netifc_discover(const std::string& devdir,
                                               cpp17::string_view topological_path) {
  topological_path = SkipInstanceSigil(topological_path);
  async::Loop loop(&kAsyncLoopConfigNeverAttachToThread);
  std::optional<NetdeviceInterface> selected_ifc;

  zx::result netdevice_watcher =
      CreateWatcher(loop.dispatcher(), selected_ifc, devdir, topological_path);
  if (netdevice_watcher.is_error()) {
    return netdevice_watcher.take_error();
  }

  for (;;) {
    zx_status_t status = loop.Run(zx::time::infinite(), /* once */ true);
    if (status != ZX_OK) {
      printf("run loop error: %s\n", zx_status_get_string(status));
      return zx::error(status);
    }
    if (selected_ifc.has_value()) {
      return zx::ok(std::move(selected_ifc.value()));
    }
  }
}
