| // 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. |
| |
| #ifndef LIB_SYS_CPP_SERVICE_DIRECTORY_H_ |
| #define LIB_SYS_CPP_SERVICE_DIRECTORY_H_ |
| |
| #include <fuchsia/io/cpp/fidl.h> |
| #include <lib/fidl/cpp/interface_ptr.h> |
| #include <lib/fidl/cpp/interface_request.h> |
| #include <lib/zx/channel.h> |
| |
| #include <memory> |
| #include <string> |
| #include <utility> |
| |
| namespace sys { |
| |
| // A directory of services provided by another component. |
| // |
| // These services are typically received by the component through its namespace, |
| // specifically through the "/svc" entry. |
| // |
| // Instances of this class are thread-safe. |
| class ServiceDirectory final { |
| public: |
| // Create an directory of services backed by given |directory|. |
| // |
| // Requests for services are routed to entries in this directory. |
| // |
| // The directory is expected to implement the |fuchsia.io.Directory| protocol. |
| explicit ServiceDirectory(zx::channel directory); |
| explicit ServiceDirectory(fidl::InterfaceHandle<fuchsia::io::Directory> directory); |
| |
| ~ServiceDirectory(); |
| |
| // ServiceDirectory objects cannot be copied. |
| ServiceDirectory(const ServiceDirectory&) = delete; |
| ServiceDirectory& operator=(const ServiceDirectory&) = delete; |
| |
| // ServiceDirectory objects can be moved. |
| ServiceDirectory(ServiceDirectory&& other) : directory_(std::move(other.directory_)) {} |
| ServiceDirectory& operator=(ServiceDirectory&& other) { |
| directory_ = std::move(other.directory_); |
| return *this; |
| } |
| |
| // Create an directory of services from this component's namespace. |
| // |
| // Uses the "/svc" entry in the namespace as the backing directory for the |
| // returned directory of services. |
| // |
| // Rather than creating a new |ServiceDirectory| consider passing |svc()| from |
| // your |ComponentContext| around as that makes your code unit testable and |
| // consumes one less kernel handle. |
| static std::shared_ptr<ServiceDirectory> CreateFromNamespace(); |
| |
| // Create a directory of services and return a request for an implementation |
| // of the underlying directory in |out_request|. |
| // |
| // Useful when creating components. |
| static std::shared_ptr<ServiceDirectory> CreateWithRequest(zx::channel* out_request); |
| static std::shared_ptr<ServiceDirectory> CreateWithRequest( |
| fidl::InterfaceRequest<fuchsia::io::Directory>* out_request); |
| |
| // Connect to an interface in the directory. |
| // |
| // The discovery name of the interface is inferred from the C++ type of the |
| // interface. Callers can supply an interface name explicitly to override |
| // the default name. |
| // |
| // This overload for |Connect| discards the status of the underlying |
| // connection operation. Callers that wish to recieve that status should use |
| // one of the other overloads that returns a |zx_status_t|. |
| // |
| // # Example |
| // |
| // ``` |
| // auto controller = directory.Connect<fuchsia::foo::Controller>(); |
| // ``` |
| template <typename Interface> |
| fidl::InterfacePtr<Interface> Connect( |
| const std::string& interface_name = Interface::Name_) const { |
| fidl::InterfacePtr<Interface> result; |
| Connect(result.NewRequest(), interface_name); |
| return std::move(result); |
| } |
| |
| // Connect to an interface in the directory. |
| // |
| // The discovery name of the interface is inferred from the C++ type of the |
| // interface request. Callers can supply an interface name explicitly to |
| // override the default name. |
| // |
| // Returns whether the request was successfully sent to the remote directory |
| // backing this service bundle. |
| // |
| // # Errors |
| // |
| // ZX_ERR_UNAVAILABLE: The directory backing this service bundle is invalid. |
| // |
| // ZX_ERR_ACCESS_DENIED: This service bundle has insufficient rights to |
| // connect to services. |
| // |
| // # Example |
| // |
| // ``` |
| // fuchsia::foo::ControllerPtr controller; |
| // directory.Connect(controller.NewRequest()); |
| // ``` |
| template <typename Interface> |
| zx_status_t Connect(fidl::InterfaceRequest<Interface> request, |
| const std::string& interface_name = Interface::Name_) const { |
| return Connect(interface_name, request.TakeChannel()); |
| } |
| |
| // Connect to an interface in the directory. |
| // |
| // The interface name and the channel must be supplied explicitly. |
| // |
| // Returns whether the request was successfully sent to the remote directory |
| // backing this service bundle. |
| // |
| // # Errors |
| // |
| // ZX_ERR_UNAVAILABLE: The directory backing this service bundle is invalid. |
| // |
| // ZX_ERR_ACCESS_DENIED: This service bundle has insufficient rights to |
| // connect to services. |
| // |
| // # Example |
| // |
| // ``` |
| // zx::channel controller, request; |
| // zx_status_t status = zx::channel::create(0, &controller, &request); |
| // if (status != ZX_OK) { |
| // [...] |
| // } |
| // directory.Connect("fuchsia.foo.Controller", std::move(request)); |
| // ``` |
| zx_status_t Connect(const std::string& interface_name, zx::channel request) const; |
| |
| // Clone underlying directory channel. |
| // |
| // This overload for |CloneHandle| discards the status of the underlying |
| // operation. Callers that wish to recieve that status should use |
| // other overload that returns a |zx_status_t|. |
| fidl::InterfaceHandle<fuchsia::io::Directory> CloneChannel() const; |
| |
| // Clone underlying directory channel. |
| // |
| // Returns whether the request was successfully sent to the remote directory |
| // backing this service bundle. |
| // |
| // # Errors |
| // |
| // ZX_ERR_UNAVAILABLE: The directory backing this service bundle is invalid. |
| // |
| // Other transport and application-level errors associated with |
| // |fuchsia.io.Node/Clone|. |
| // |
| // # Example |
| // |
| // ``` |
| // fuchsia::io::DirectoryPtr dir; |
| // directory.CloneHandle(dir.NewRequest()); |
| // ``` |
| zx_status_t CloneChannel(fidl::InterfaceRequest<fuchsia::io::Directory>) const; |
| |
| private: |
| // The directory to which connection requests are routed. |
| // |
| // Implements |fuchsia.io.Directory| protocol. |
| zx::channel directory_; |
| }; |
| |
| } // namespace sys |
| |
| #endif // LIB_SYS_CPP_SERVICE_DIRECTORY_H_ |