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

#ifndef LIB_SYS_COMPONENT_LLCPP_OUTGOING_DIRECTORY_H_
#define LIB_SYS_COMPONENT_LLCPP_OUTGOING_DIRECTORY_H_

#include <fidl/fuchsia.io/cpp/wire.h>
#include <lib/async/dispatcher.h>
#include <lib/fit/function.h>
#include <lib/stdcompat/string_view.h>
#include <lib/svc/dir.h>
#include <lib/sys/component/llcpp/constants.h>
#include <lib/sys/component/llcpp/handlers.h>
#include <zircon/assert.h>
#include <zircon/errors.h>
#include <zircon/types.h>

#include <map>
#include <memory>
#include <stack>

namespace component {

// The directory containing handles to capabilities this component provides.
// Entries served from this outgoing directory should correspond to the
// component manifest's `capabilities` declarations.
//
// The outgoing directory contains one special subdirectory, named `svc`. This
// directory contains the FIDL Services and Protocols offered by this component
// to other components. For example the FIDL Protocol `fuchsia.foo.Bar` will be
// hosted under the path `/svc/fuchsia.foo.Bar`.
//
// This class is thread-hostile.
//
// # Simple usage
//
// Instances of this class should be owned and managed on the same thread
// that services their connections.
//
// # Advanced usage
//
// You can use a background thread to service connections provided:
// async_dispatcher_t for the background thread is stopped or suspended
// prior to destroying the class object.
//
// # Maintainer's Note
//
// This class' API is semantically identical to the one found in
// `//sdk/lib/sys/cpp`. This exists in order to offer equivalent facilities to
// LLCPP (Low-level C++) FIDL bindings support. The other class is designed for
// HLCPP( High-Level C++) FIDL bindings.
class OutgoingDirectory final {
 public:
  // Creates an OutgoingDirectory which will serve requests when
  // |Serve(zx::channel)| or |ServeFromStartupInfo()| is called.
  //
  // |dispatcher| must not be nullptr. If it is, this method will panic.
  static OutgoingDirectory Create(async_dispatcher_t* dispatcher);

  OutgoingDirectory() = delete;

  // OutgoingDirectory can be moved. Once moved, invoking a method on an
  // instance will yield undefined behavior.
  OutgoingDirectory(OutgoingDirectory&&) noexcept;
  OutgoingDirectory& operator=(OutgoingDirectory&&) noexcept;

  // OutgoingDirectory cannot be copied.
  OutgoingDirectory(const OutgoingDirectory&) = delete;
  OutgoingDirectory& operator=(const OutgoingDirectory&) = delete;

  ~OutgoingDirectory();

  // Starts serving the outgoing directory on the given channel. This should
  // be invoked after the outgoing directory has been populated, e.g. via
  // |AddProtocol|.
  //
  // This object will implement the |fuchsia.io.Directory| interface using this
  // channel.
  //
  // # Errors
  //
  // ZX_ERR_BAD_HANDLE: |directory_request| is not a valid handle.
  //
  // ZX_ERR_ACCESS_DENIED: |directory_request| has insufficient rights.
  zx::status<> Serve(fidl::ServerEnd<fuchsia_io::Directory> directory_request);

  // Starts serving the outgoing directory on the channel provided to this
  // process at startup as |PA_DIRECTORY_REQUEST|.
  //
  // This object will implement the |fuchsia.io.Directory| interface using this
  // channel.
  //
  // If |dispatcher| is nullptr, then the global dispatcher set via
  // |async_get_default_dispatcher| will be used.
  //
  // # Errors
  //
  // ZX_ERR_BAD_HANDLE: the process did not receive a |PA_DIRECTORY_REQUEST|
  // startup handle or it was already taken.
  //
  // ZX_ERR_ACCESS_DENIED: |directory_request| has insufficient rights.
  zx::status<> ServeFromStartupInfo();

  // Adds a FIDL Protocol instance.
  //
  // |impl| will be used to handle requests for this protocol.
  // |name| is used to determine where to host the protocol. This protocol will
  // be hosted under the path /svc/{name} where name is the discoverable name
  // of the protocol.
  //
  // Note, if and when |RemoveProtocol| is called for the provided |name|, this
  // object will asynchronously close down the associated server end channel and
  // stop receiving requests. This method provides no facilities for waiting
  // until teardown is complete. If such control is desired, then the
  // |TypedHandler| overload of this method listed below ought to be used.
  //
  // # Errors
  //
  // ZX_ERR_ALREADY_EXISTS: An entry already exists for this protocol.
  //
  // ZX_ERR_INVALID_ARGS: |impl| is nullptr or |name| is an empty string.
  //
  // # Examples
  //
  // See sample use cases in test case(s) located at
  // //sdk/lib/sys/component/llcpp/outgoing_directory_test.cc
  template <typename Protocol>
  zx::status<> AddProtocol(fidl::WireServer<Protocol>* impl,
                           cpp17::string_view name = fidl::DiscoverableProtocolName<Protocol>) {
    return AddProtocolAt(kServiceDirectory, impl, name);
  }

  // Same as above but allows overriding the parent directory in which the
  // protocol will be hosted.
  template <typename Protocol>
  zx::status<> AddProtocolAt(cpp17::string_view path, fidl::WireServer<Protocol>* impl,
                             cpp17::string_view name = fidl::DiscoverableProtocolName<Protocol>) {
    if (impl == nullptr || dispatcher_ == nullptr) {
      return zx::make_status(ZX_ERR_INVALID_ARGS);
    }

    return AddProtocolAt<Protocol>(
        path,
        [=](fidl::ServerEnd<Protocol> request) {
          fidl::ServerBindingRef<Protocol> server =
              fidl::BindServer(dispatcher_, std::move(request), impl);

          auto cb = [server = std::move(server)]() mutable { server.Unbind(); };
          // We don't have to check for entry existing because the |AddProtocol|
          // overload being invoked here will do that internally.
          AppendUnbindConnectionCallback(name, std::move(cb));
        },
        name);
  }

  // Same as above but overloaded to support servers implementations speaking
  // FIDL C++ natural types: |fidl::Server<P>|, part of the unified bindings.
  template <typename Protocol>
  zx::status<> AddProtocol(fidl::Server<Protocol>* impl,
                           cpp17::string_view name = fidl::DiscoverableProtocolName<Protocol>) {
    if (impl == nullptr || dispatcher_ == nullptr) {
      return zx::make_status(ZX_ERR_INVALID_ARGS);
    }

    return AddProtocol<Protocol>(
        [=](fidl::ServerEnd<Protocol> request) {
          // This object is safe to drop. Server will still begin to operate
          // past its lifetime.
          auto _server = fidl::BindServer(dispatcher_, std::move(request), impl);
        },
        name);
  }

  // Adds a FIDL Protocol instance.
  //
  // A |handler| is added to handle connection requests for the this particular
  // protocol. |name| is used to determine where to host the protocol.
  // This protocol will be hosted under the path /svc/{name} where name
  // is the discoverable name of the protocol.
  //
  // # Note
  //
  // Active connections are never torn down when/if |RemoveProtocol| is invoked
  // with the same |name|. Users of this method should manage teardown of
  // all active connections.
  //
  // # Errors
  //
  // ZX_ERR_ALREADY_EXISTS: An entry already exists for this protocol.
  //
  // ZX_ERR_INVALID_ARGS: |name| is an empty string.
  //
  // # Examples
  //
  // See sample use cases in test case(s) located at
  // //sdk/lib/sys/component/llcpp/outgoing_directory_test.cc
  template <typename Protocol>
  zx::status<> AddProtocol(TypedHandler<Protocol> handler,
                           cpp17::string_view name = fidl::DiscoverableProtocolName<Protocol>) {
    return AddProtocolAt<Protocol>(kServiceDirectory, std::move(handler), name);
  }

  template <typename Protocol>
  zx::status<> AddProtocolAt(cpp17::string_view path, TypedHandler<Protocol> handler,
                             cpp17::string_view name = fidl::DiscoverableProtocolName<Protocol>) {
    auto bridge_func = [handler = std::move(handler)](zx::channel request) {
      fidl::ServerEnd<Protocol> server_end(std::move(request));
      (void)handler(std::move(server_end));
    };

    return AddNamedProtocolAt(path, name, std::move(bridge_func));
  }

  // Same as above but is untyped. This method is generally discouraged but
  // is made available if a generic handler needs to be provided.
  zx::status<> AddNamedProtocol(AnyHandler handler, cpp17::string_view name);

  zx::status<> AddNamedProtocolAt(cpp17::string_view path, cpp17::string_view name,
                                  AnyHandler handler);

  // Adds an instance of a FIDL Service.
  //
  // A |handler| is added to provide an |instance| of a service.
  //
  // The template type |Service| must be the generated type representing a FIDL Service.
  // The generated class |Service::Handler| helps the caller populate a |ServiceHandler|.
  //
  // # Errors
  //
  // ZX_ERR_ALREADY_EXISTS: The instance already exists.
  //
  // ZX_ERR_INVALID_ARGS: |instance| is an empty string or |handler| is empty.
  //
  // # Example
  //
  // See sample use cases in test case(s) located at
  // //sdk/lib/sys/component/llcpp/outgoing_directory_test.cc
  template <typename Service>
  zx::status<> AddService(ServiceHandler handler, cpp17::string_view instance = kDefaultInstance) {
    return AddNamedService(std::move(handler), Service::Name, instance);
  }

  // Adds an instance of a FIDL Service.
  //
  // A |handler| is added to provide an |instance| of a |service|.
  //
  // # Errors
  //
  // ZX_ERR_ALREADY_EXISTS: The instance already exists.
  //
  // ZX_ERR_INVALID_ARGS: |service| or |instance| is an empty string. Also,
  // if |handler| is empty.
  //
  // # Example
  //
  // See sample use cases in test case(s) located at
  // //sdk/lib/sys/component/llcpp/outgoing_directory_test.cc
  zx::status<> AddNamedService(ServiceHandler handler, cpp17::string_view service,
                               cpp17::string_view instance = kDefaultInstance);

  // Serve a subdirectory at the root of this outgoing directory.
  //
  // The directory will be installed under the path |directory_name|. When
  // a request is received under this path, then it will be forwarded to
  // |remote_dir|.
  //
  // # Errors
  //
  // ZX_ERR_ALREADY_EXISTS: An entry with the provided name already exists.
  //
  // ZX_ERR_BAD_HANDLE: |remote_dir| is an invalid handle.
  //
  // ZX_ERR_INVALID_ARGS: |directory_name| is an empty string.
  zx::status<> AddDirectory(fidl::ClientEnd<fuchsia_io::Directory> remote_dir,
                            cpp17::string_view directory_name);

  // Removes a FIDL Protocol entry.
  //
  // # Errors
  //
  // ZX_ERR_NOT_FOUND: The protocol entry was not found.
  //
  // # Example
  //
  // ```
  // outgoing.RemoveProtocol<lib_example::MyProtocol>();
  // ```
  template <typename Protocol>
  zx::status<> RemoveProtocol(cpp17::string_view name = fidl::DiscoverableProtocolName<Protocol>) {
    return RemoveNamedProtocol(name);
  }

  // Same as above but untyped.
  zx::status<> RemoveNamedProtocol(cpp17::string_view name);

  template <typename Protocol>
  zx::status<> RemoveProtocolAt(
      cpp17::string_view directory,
      cpp17::string_view name = fidl::DiscoverableProtocolName<Protocol>) {
    return RemoveNamedProtocolAt(directory, name);
  }

  zx::status<> RemoveNamedProtocolAt(cpp17::string_view directory, cpp17::string_view name);

  // Removes an instance of a FIDL Service.
  //
  // # Errors
  //
  // ZX_ERR_NOT_FOUND: The instance was not found.
  //
  // # Example
  //
  // ```
  // outgoing.RemoveService<lib_example::MyService>("my-instance");
  // ```
  template <typename Service>
  zx::status<> RemoveService(cpp17::string_view instance = kDefaultInstance) {
    return RemoveNamedService(Service::Name, instance);
  }

  // Removes an instance of a FIDL Service.
  //
  // # Errors
  //
  // ZX_ERR_NOT_FOUND: The instance was not found.
  zx::status<> RemoveNamedService(cpp17::string_view service,
                                  cpp17::string_view instance = kDefaultInstance);

  // Removes the subdirectory on the provided |directory_name|.
  //
  // # Errors
  //
  // ZX_ERR_NOT_FOUND: No entry was found with provided name.
  zx::status<> RemoveDirectory(cpp17::string_view directory_name);

 private:
  OutgoingDirectory(async_dispatcher_t* dispatcher, svc_dir_t* root);

  // |svc_dir_add_service_by_path| takes in a void* |context| that is passed to
  // the |handler| callback passed as the last argument to the function call.
  // This library will pass in a casted void* pointer to this object, and when
  // the `svc` library invokes this library's connection handler, the |context|
  // will be casted back to |OnConnectContext*|.
  struct OnConnectContext {
    AnyHandler handler;
    OutgoingDirectory* self;
  };

  // Function pointer that matches type of |svc_dir_add_service| handler.
  // Internally, it calls the |AnyMemberHandler| instance populated via |AddAnyMember|.
  static void OnConnect(void* context, const char* service_name, zx_handle_t handle);

  // Callback invoked during teardown of a FIDL protocol entry. This callback
  // will close all active connections on the associated channel.
  using UnbindConnectionCallback = fit::callback<void()>;

  void AppendUnbindConnectionCallback(cpp17::string_view name, UnbindConnectionCallback callback);

  void UnbindAllConnections(cpp17::string_view name);

  static std::string MakePath(cpp17::string_view service, cpp17::string_view instance);

  async_dispatcher_t* dispatcher_ = nullptr;

  svc_dir_t* root_ = nullptr;

  // Mapping of all registered protocol handlers. Key represents a path to
  // the directory in which the protocol ought to be installed. For example,
  // a path may look like "svc/fuchsia.FooService/some_instance".
  // The value contains a map of each of the entry's handlers.
  //
  // For FIDL Protocols, entries will be stored under "svc" entry
  // of this type, and then their name will be used as a key for the internal
  // map.
  //
  // For FIDL Services, entries will be stored by instance,
  // e.g. `svc/fuchsia.FooService/default`, and then the member names will be
  // used as the keys for the internal maps.
  //
  // The OnConnectContext has to be stored in the heap because its pointer
  // is used by |OnConnect|, a static function, during channel connection attempt.
  std::map<std::string, std::map<std::string, std::unique_ptr<OnConnectContext>>>
      registered_handlers_ = {};

  // Protocol bindings used to initiate teardown when protocol is removed. We
  // store this in a callback as opposed to a map of fidl::ServerBindingRef<T>
  // because that object is template parameterized and therefore can't be
  // stored in a homogeneous container.
  std::map<std::string, std::vector<UnbindConnectionCallback>> unbind_protocol_callbacks_ = {};
};

}  // namespace component

#endif  // LIB_SYS_COMPONENT_LLCPP_OUTGOING_DIRECTORY_H_
