// Copyright 2020 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/devices/bin/driver_manager/package_resolver.h"

#include <fuchsia/io/llcpp/fidl.h>
#include <fuchsia/pkg/llcpp/fidl.h>
#include <lib/fdio/directory.h>

#include <fbl/string_printf.h>

#include "src/devices/lib/log/log.h"
#include "src/lib/pkg_url/fuchsia_pkg_url.h"
#include "src/lib/storage/vfs/cpp/vfs.h"

namespace fio = fuchsia_io;

namespace internal {

zx::status<PackageResolver::FetchDriverVmoResult> PackageResolver::FetchDriverVmo(
    const std::string& package_url) {
  if (!resolver_client_.channel().is_valid()) {
    zx_status_t status = ConnectToResolverService();
    if (status != ZX_OK) {
      LOGF(ERROR, "Failed to connect to package resolver service");
      return zx::error(status);
    }
  }
  auto result = Resolve(package_url);
  if (!result.is_ok()) {
    LOGF(ERROR, "Failed to resolve package url %s, err %d", package_url.c_str(),
         result.status_value());
    return zx::error(result.status_value());
  }

  return LoadDriverPackage(&result.value() /* package_dir */);
}

zx_status_t PackageResolver::ConnectToResolverService() {
  zx::channel local, remote;
  zx_status_t status = zx::channel::create(0u, &local, &remote);
  if (status != ZX_OK) {
    return status;
  }
  const auto path =
      fbl::StringPrintf("/svc/%s", fidl::DiscoverableProtocolName<fuchsia_pkg::PackageResolver>);
  status = fdio_service_connect(path.c_str(), remote.release());
  if (status != ZX_OK) {
    return status;
  }
  resolver_client_ = fidl::WireSyncClient<fuchsia_pkg::PackageResolver>(std::move(local));
  return ZX_OK;
}

zx::status<fidl::WireSyncClient<fio::Directory>> PackageResolver::Resolve(
    const std::string_view& package_url) {
  zx::channel local, remote;
  zx_status_t status = zx::channel::create(0u, &local, &remote);
  if (status != ZX_OK) {
    return zx::error(status);
  }
  component::FuchsiaPkgUrl fp;
  bool parse = fp.Parse(std::string(package_url));
  if (!parse) {
    LOGF(ERROR, "Failed to parse package url: %s", package_url.data());
    return zx::error(ZX_ERR_INTERNAL);
  }
  ::fidl::VectorView<::fidl::StringView> selectors;

  // This is synchronous for now so we can get the proof of concept working.
  // Eventually we will want to do this asynchronously.
  auto result = resolver_client_.Resolve(
      ::fidl::StringView(fidl::StringView::FromExternal(fp.package_path())), std::move(selectors),
      std::move(remote));
  if (!result.ok() || result.Unwrap()->result.is_err()) {
    LOGF(ERROR, "Failed to resolve package");
    return zx::error(!result.ok() ? ZX_ERR_INTERNAL : result.Unwrap()->result.err());
  }
  return zx::ok(fidl::WireSyncClient<fio::Directory>(std::move(local)));
}

zx::status<PackageResolver::FetchDriverVmoResult> PackageResolver::LoadDriverPackage(
    fidl::WireSyncClient<fio::Directory>* package_dir) {
  const uint32_t kFileRights = fio::wire::OPEN_RIGHT_READABLE | fio::wire::OPEN_RIGHT_EXECUTABLE;
  const uint32_t kDriverVmoFlags = fio::wire::VMO_FLAG_READ | fio::wire::VMO_FLAG_EXEC;
  constexpr char kLibDir[] = "lib";

  // Open the lib directory.
  zx::channel local, remote;
  zx_status_t status = zx::channel::create(0u, &local, &remote);
  if (status != ZX_OK) {
    return zx::error(status);
  }
  auto open_result = package_dir->Open(kFileRights, 0u, kLibDir, std::move(remote));
  if (!open_result.ok()) {
    LOGF(ERROR, "Failed to open driver package directory");
    return zx::error(ZX_ERR_INTERNAL);
  }
  // This could be simplified by using POSIX APIs instead.
  fidl::WireSyncClient<fio::Directory> lib_dir(std::move(local));

  auto libname_result = GetDriverLibname(&lib_dir);
  if (!libname_result.is_ok()) {
    LOGF(ERROR, "Failed to get driver libname");
    return zx::error(libname_result.status_value());
  }

  // Open and duplicate the driver vmo.
  status = zx::channel::create(0u, &local, &remote);
  if (status != ZX_OK) {
    return zx::error(status);
  }
  auto file_open_result =
      lib_dir.Open(kFileRights, 0u /* mode */,
                   ::fidl::StringView(fidl::StringView::FromExternal(libname_result.value())),
                   std::move(remote));
  if (!file_open_result.ok()) {
    LOGF(ERROR, "Failed to open driver file: %s", libname_result.value().c_str());
    return zx::error(ZX_ERR_INTERNAL);
  }
  fidl::WireSyncClient<fio::File> file_client(std::move(local));
  auto file_res = file_client.GetBuffer(kDriverVmoFlags);
  if (!file_res.ok() || file_res.Unwrap()->s != ZX_OK) {
    LOGF(ERROR, "Failed to get driver vmo");
    return zx::error(ZX_ERR_INTERNAL);
  }
  auto buf = file_res.Unwrap()->buffer.get();
  if (!buf->vmo.is_valid()) {
    return zx::error(ZX_ERR_INTERNAL);
  }
  return zx::ok(PackageResolver::FetchDriverVmoResult{libname_result.value(), std::move(buf->vmo)});
}

zx::status<std::string> PackageResolver::GetDriverLibname(
    fidl::WireSyncClient<fio::Directory>* lib_dir) {
  auto dirent_result = lib_dir->ReadDirents(fio::wire::MAX_BUF);
  if (!dirent_result.ok() || dirent_result.status() != ZX_OK) {
    return zx::error(dirent_result.status());
  }
  fidl::WireResponse<fio::Directory::ReadDirents>* dirent_response = dirent_result.Unwrap();
  if (dirent_response->dirents.count() == 0) {
    return zx::error(ZX_ERR_INTERNAL);
  }

  size_t offset = 0;
  auto data_ptr = dirent_response->dirents.data();
  // For now just assume only one driver shared library is included in the package.
  while (sizeof(vdirent_t) < dirent_response->dirents.count() - offset) {
    const vdirent_t* entry = reinterpret_cast<const vdirent_t*>(data_ptr + offset);
    std::string entry_name(entry->name, entry->size);
    offset += sizeof(vdirent_t) + entry->size;
    if (entry_name == "." || entry_name == "..") {
      continue;
    }
    return zx::ok(std::move(entry_name));
  }
  return zx::error(ZX_ERR_NOT_FOUND);
}

}  // namespace internal
