// 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 <fcntl.h>
#include <fidl/fuchsia.io/cpp/wire.h>
#include <lib/async-loop/cpp/loop.h>
#include <lib/async-loop/default.h>
#include <lib/fdio/directory.h>
#include <lib/sys/cpp/component_context.h>
#include <lib/syslog/cpp/macros.h>
#include <lib/vfs/cpp/remote_dir.h>

#include <iostream>
#include <string_view>

#include <fbl/ref_ptr.h>

#include "isolated_devmgr.h"
#include "src/lib/fxl/command_line.h"
#include "src/lib/fxl/strings/split_string.h"
#include "src/lib/fxl/strings/string_number_conversions.h"

#define DEVICE_IDS_VID_LOC 0
#define DEVICE_IDS_PID_LOC 1
#define DEVICE_IDS_DID_LOC 2
#define DEVICE_IDS_SIZE 3
#define ISO_DEV_MGR_RET_OK 0
#define ISO_DEV_MGR_RET_ERR 1

using namespace isolated_devmgr;

void Usage() {
  std::cerr <<
      R"(
Usage:
   isolated_devmgr [options]

Options:
   --svc_name=[svc_name]: service name to expose, defaults to fuchsia.io.Directory
   --load_driver=[driver_path]: loads a driver into isolated manager. May be informed multiple
                                times.
   --sys_device=[sys_device_driver]: path to sys device driver, defaults to
                                     /boot/driver/sysdev.so
   --wait_for=[device]: wait for isolated manager to have |device| exposed before serving any
                        requests. May be informed multiple times.
   --add_namespace=[ns]: make the namespace 'ns' from this component available to the devmgr
                         under the same path.
   --device_vid_pid_did=[dev_vid:dev_pid:dev_did]: adding a device with hex dev_vid, dev_pid
                                                   and dev_did. May be informed multiple times.
   --enable_block_watcher: Enable block watcher.
   --help: displays this help page.

Note: isolated_devmgr runs as a component, so all paths must be relative to the component's
namespace. Since the devmgr libraries and executables are currently under /boot, the components
sandbox metadata must include the "/boot/bin" and "/boot/lib". Additionally, it's common to load
drivers out of "/boot/driver" and this directory must also be specificed in the components sandbox
metadata to make these drivers available to isolated_devmgr.

Example sandbox metadata:

    "sandbox": {
        "boot": [
            "bin",
            "driver",
            "lib"
        ]
    }
)";
}

static int process_device_ids(const char* str,
                              fbl::Vector<board_test::DeviceEntry>* dev_entry_list_ptr) {
  board_test::DeviceEntry dev_entry = {};
  uint32_t key;
  std::string_view sv_str = std::string_view(str);
  auto params = fxl::SplitString(sv_str, ":", fxl::kKeepWhitespace, fxl::kSplitWantNonEmpty);
  if ((dev_entry_list_ptr == nullptr) || (params.size() < DEVICE_IDS_SIZE)) {
    return ISO_DEV_MGR_RET_ERR;
  }
  if (!fxl::StringToNumberWithError(params.at(DEVICE_IDS_VID_LOC), &key, fxl::Base::k16)) {
    return ISO_DEV_MGR_RET_ERR;
  }
  dev_entry.vid = key;
  if (!fxl::StringToNumberWithError(params.at(DEVICE_IDS_PID_LOC), &key, fxl::Base::k16)) {
    return ISO_DEV_MGR_RET_ERR;
  }
  dev_entry.pid = key;
  if (!fxl::StringToNumberWithError(params.at(DEVICE_IDS_DID_LOC), &key, fxl::Base::k16)) {
    return ISO_DEV_MGR_RET_ERR;
  }
  dev_entry.did = key;
  dev_entry_list_ptr->push_back(dev_entry);
  return ISO_DEV_MGR_RET_OK;
}

int main(int argc, const char** argv) {
  async::Loop loop(&kAsyncLoopConfigAttachToCurrentThread);
  devmgr_launcher::Args args;
  auto device_list_unique_ptr = std::unique_ptr<fbl::Vector<board_test::DeviceEntry>>(
      new fbl::Vector<board_test::DeviceEntry>());

  // fill up defaults:
  args.stdio = fbl::unique_fd(open("/dev/null", O_RDWR));
  args.disable_block_watcher = true;

  std::string svc_name = "fuchsia.io.Directory";
  std::vector<std::string> wait;
  std::vector<std::string> namespaces;

  // load options from command line
  auto cl = fxl::CommandLineFromArgcArgv(argc, argv);
  for (const auto& opt : cl.options()) {
    if (opt.name == "svc_name") {
      svc_name = opt.value;
    } else if (opt.name == "load_driver") {
      args.load_drivers.push_back(opt.value.c_str());
    } else if (opt.name == "sys_device") {
      args.sys_device_driver = opt.value.c_str();
    } else if (opt.name == "wait_for") {
      wait.push_back(opt.value);
    } else if (opt.name == "add_namespace") {
      namespaces.push_back(opt.value);
    } else if (opt.name == "device_vid_pid_did") {
      int status = process_device_ids(opt.value.c_str(), device_list_unique_ptr.get());
      if (status != 0) {
        Usage();
        return status;
      }
    } else if (opt.name == "enable_block_watcher") {
      args.disable_block_watcher = false;
    } else if (opt.name == "help") {
      Usage();
      return ISO_DEV_MGR_RET_OK;
    } else {
      Usage();
      return ISO_DEV_MGR_RET_ERR;
    }
  }

  // Fallback if sys_device is not specified.
  if (args.sys_device_driver == nullptr) {
    args.sys_device_driver = "/boot/driver/sysdev.so";
    // If the test only loads specific drivers then add sys_device.
    if (!args.load_drivers.is_empty()) {
      args.load_drivers.push_back("/boot/driver/sysdev.so");
    }
  }

  // Pass-through any additional namespaces that we want to provide to the devmgr. These are
  // exposed to devmgr under the same local path. Ex: if you share '/pkg', you could provide a
  // driver as '/pkg/data/my_driver.so'.
  for (const auto& ns : namespaces) {
    zx::channel client, server;
    zx_status_t status = zx::channel::create(0, &client, &server);
    if (status != ZX_OK) {
      FX_PLOGS(ERROR, status) << "Failed to create channel";
      return ISO_DEV_MGR_RET_ERR;
    }
    status = fdio_open(ns.c_str(),
                       static_cast<uint32_t>(fuchsia_io::wire::OpenFlags::kRightReadable |
                                             fuchsia_io::wire::OpenFlags::kRightExecutable),
                       server.release());
    if (status != ZX_OK) {
      FX_PLOGS(ERROR, status) << "Failed to open namespace " << ns;
      return ISO_DEV_MGR_RET_ERR;
    }
    args.flat_namespace.push_back({ns.c_str(), std::move(client)});
  }

  auto devmgr =
      IsolatedDevmgr::Create(std::move(args), std::move(device_list_unique_ptr), loop.dispatcher());
  if (!devmgr) {
    return ISO_DEV_MGR_RET_ERR;
  }

  devmgr->SetExceptionCallback([](zx_exception_info_t) {
    FX_LOGS(ERROR) << "Isolated Devmgr crashed";
    zx_process_exit(ISO_DEV_MGR_RET_ERR);
  });

  for (const auto& path : wait) {
    if (devmgr->WaitForFile(path.c_str()) != ZX_OK) {
      FX_LOGS(ERROR) << "Isolated Devmgr failed while waiting for path " << path;
      return ISO_DEV_MGR_RET_ERR;
    }
  }

  auto context = sys::ComponentContext::CreateAndServeOutgoingDirectory();
  auto service =
      std::make_unique<vfs::Service>([&devmgr](zx::channel chan, async_dispatcher_t* dispatcher) {
        devmgr->Connect(std::move(chan));
      });
  context->outgoing()->AddPublicService(std::move(service), std::move(svc_name));

  // Add devfs to out directory
  zx::channel client, server;
  auto status = zx::channel::create(0, &client, &server);
  if (status != ZX_OK) {
    return status;
  }
  devmgr->Connect(std::move(server));
  auto devfs_out = std::make_unique<vfs::RemoteDir>(std::move(client));
  context->outgoing()->root_dir()->AddEntry("dev", std::move(devfs_out));

  loop.Run();

  return ISO_DEV_MGR_RET_OK;
}
