// Copyright 2022 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 <fidl/fuchsia.posix.socket.packet/cpp/wire.h>
#include <lib/async-loop/cpp/loop.h>
#include <lib/async-loop/default.h>
#include <lib/fdio/namespace.h>
#include <lib/fidl/cpp/interface_handle.h>
#include <lib/service/llcpp/service.h>
#include <lib/vfs/cpp/composed_service_dir.h>
#include <lib/zx/channel.h>
#include <zircon/assert.h>
#include <zircon/status.h>

#include <filesystem>

namespace {

constexpr char kServiceDirectory[] = "/svc";
constexpr char kNetstackExposeDir[] =
    "/hub-v2/children/core/children/network/children/netstack/exec/expose";
constexpr const char* kPacketSocketProviderName =
    fidl::DiscoverableProtocolName<fuchsia_posix_socket_packet::Provider>;

}  // namespace

// Attempts to make a packet socket provider available to this program if not
// already available.
//
// The packet socket provider exposed by the core realm's netstack is used if it
// is available.
__attribute__((constructor)) void init_packet_socket_provider() {
  if (std::filesystem::exists(std::filesystem::path(kServiceDirectory) /
                              kPacketSocketProviderName)) {
    // Packet socket provider is already available.
    return;
  }

  zx::status netstack_expose_dir = service::OpenServiceRoot(kNetstackExposeDir);
  switch (zx_status_t status = netstack_expose_dir.status_value(); status) {
    case ZX_OK:
      break;
    case ZX_ERR_NOT_FOUND:
      // Most likely in the non-root realm.
      return;
    default:
      ZX_PANIC("Failed to open netstack expose directory at %s: %s", kNetstackExposeDir,
               zx_status_get_string(status));
  }

  static vfs::ComposedServiceDir composed_svc_dir;

  // Our composed service directory should be a superset of the default service
  // directory.
  {
    zx::status result = service::OpenServiceRoot();
    ZX_ASSERT_MSG(result.is_ok(), "Failed to open root service directory: %s",
                  result.status_string());
    // TODO(https://fxbug.dev/72980): Avoid this type-unsafe conversion.
    composed_svc_dir.set_fallback(
        fidl::InterfaceHandle<fuchsia::io::Directory>(result->TakeChannel()));
  }

  // Add the packet socket provider service to our composed service directory
  // by reaching into netstack's exposed directory via hub(-v2).
  //
  // https://fuchsia.dev/fuchsia-src/concepts/components/v2/hub?hl=en
  composed_svc_dir.AddService(
      kPacketSocketProviderName,
      std::make_unique<vfs::Service>(
          [netstack_expose_dir = std::move(netstack_expose_dir.value())](
              zx::channel request, async_dispatcher_t* dispatcher) mutable {
            zx::status result = service::ConnectAt(
                netstack_expose_dir.borrow(),
                fidl::ServerEnd<fuchsia_posix_socket_packet::Provider>(std::move(request)));
            ZX_ASSERT_MSG(result.is_ok(), "Failed to connect to packet socker provider: %s",
                          result.status_string());
          }));

  static async::Loop composed_svc_dir_loop(&kAsyncLoopConfigNoAttachToCurrentThread);

  // Replace the default service directory with our composed service directory
  // to make packet socket provider available to the program and start serving
  // requests to the composed service directory.
  {
    zx_status_t status;
    zx::channel client, server;
    ZX_ASSERT_MSG((status = zx::channel::create(0, &client, &server)) == ZX_OK,
                  "Failed to create channels: %s", zx_status_get_string(status));

    // TODO(https://fxbug.dev/77059): Drop writable right.
    ZX_ASSERT_MSG(
        (status = composed_svc_dir.Serve(
             fuchsia::io::OpenFlags::RIGHT_READABLE | fuchsia::io::OpenFlags::RIGHT_WRITABLE |
                 fuchsia::io::OpenFlags::DIRECTORY,
             std::move(server), composed_svc_dir_loop.dispatcher())) == ZX_OK,
        "Failed to start serving requsts for composed service directory: %s",
        zx_status_get_string(status));

    fdio_ns_t* ns;
    ZX_ASSERT_MSG((status = fdio_ns_get_installed(&ns)) == ZX_OK,
                  "Failed to get installed namespace: %s", zx_status_get_string(status));
    ZX_ASSERT_MSG((status = fdio_ns_unbind(ns, kServiceDirectory)) == ZX_OK,
                  "Failed to unbind svc: %s", zx_status_get_string(status));
    ZX_ASSERT_MSG((status = fdio_ns_bind(ns, kServiceDirectory, client.release())) == ZX_OK,
                  "Failed to bind svc: %s", zx_status_get_string(status));
  }

  zx_status_t status;
  ZX_ASSERT_MSG((status = composed_svc_dir_loop.StartThread()) == ZX_OK,
                "Failed to start async loop thread: %s", zx_status_get_string(status));
}
