| // Copyright 2017 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_SVC_CPP_SERVICE_NAMESPACE_H_ |
| #define LIB_SVC_CPP_SERVICE_NAMESPACE_H_ |
| |
| #include <fbl/ref_ptr.h> |
| #include <fs/pseudo-dir.h> |
| #include <fs/synchronous-vfs.h> |
| #include <lib/fit/function.h> |
| #include <lib/zx/channel.h> |
| |
| #include <string> |
| #include <unordered_map> |
| #include <utility> |
| |
| #include <fuchsia/sys/cpp/fidl.h> |
| #include "lib/fidl/cpp/binding_set.h" |
| #include "lib/fxl/macros.h" |
| |
| namespace component { |
| |
| // ServiceNamespace lets a client to publish services in the form of a |
| // directory and provides compatibility with ServiceProvider. |
| // |
| // This class will be deprecated and removed once ServiceProvider is replaced |
| // by direct use of directories for publishing and discoverying services. |
| class ServiceNamespace : public fuchsia::sys::ServiceProvider { |
| public: |
| // |ServiceConnector| is the generic, type-unsafe interface for objects used |
| // by |ServiceNamespace| to connect generic "interface requests" (i.e., |
| // just channels) specified by service name to service implementations. |
| using ServiceConnector = fit::function<void(zx::channel)>; |
| |
| // Constructs this service namespace implementation in an unbound state. |
| ServiceNamespace(); |
| |
| // Constructs this service provider implementation, binding it to the given |
| // interface request. Note: If |request| is not valid ("pending"), then the |
| // object will be put into an unbound state. |
| explicit ServiceNamespace( |
| fidl::InterfaceRequest<fuchsia::sys::ServiceProvider> request); |
| |
| explicit ServiceNamespace(fbl::RefPtr<fs::PseudoDir> directory); |
| |
| ~ServiceNamespace() override; |
| |
| // Gets the underlying pseudo-directory. |
| const fbl::RefPtr<fs::PseudoDir>& directory() const { return directory_; } |
| |
| // Binds this service provider implementation to the given interface request. |
| // Multiple bindings may be added. They are automatically removed when closed |
| // remotely. |
| void AddBinding( |
| fidl::InterfaceRequest<fuchsia::sys::ServiceProvider> request); |
| |
| // Disconnect this service provider implementation and put it in a state where |
| // it can be rebound to a new request (i.e., restores this object to an |
| // unbound state). This may be called even if this object is already unbound. |
| void Close(); |
| |
| // Adds a supported service with the given |service_name|, using the given |
| // |service_connector|. |
| void AddServiceForName(ServiceConnector connector, |
| const std::string& service_name); |
| |
| // Adds a supported service with the given |service_name|, using the given |
| // |InterfaceRequestHandler|, which should remain valid for the lifetime of |
| // this object. |
| // |
| // A typical usage may be: |
| // |
| // service_namespace_->AddService(foobar_bindings_.GetHandler(this)); |
| template <typename Interface> |
| void AddService(fidl::InterfaceRequestHandler<Interface> handler, |
| const std::string& service_name = Interface::Name_) { |
| AddServiceForName( |
| [handler = std::move(handler)](zx::channel channel) { |
| handler(fidl::InterfaceRequest<Interface>(std::move(channel))); |
| }, |
| service_name); |
| } |
| |
| // Removes support for the service with the given |service_name|. |
| void RemoveServiceForName(const std::string& service_name); |
| |
| // Like |RemoveServiceForName()| (above), but designed so that it can be used |
| // like |RemoveService<Interface>()| or even |
| // |RemoveService<Interface>(service_name)| (to parallel |
| // |AddService<Interface>()|). |
| template <typename Interface> |
| void RemoveService(const std::string& service_name = Interface::Name_) { |
| RemoveServiceForName(service_name); |
| } |
| |
| private: |
| // Overridden from |ServiceProvider|: |
| void ConnectToService(fidl::StringPtr service_name, |
| zx::channel channel) override; |
| |
| void Connect(fbl::StringPiece name, zx::channel channel); |
| void ConnectCommon(const std::string& service_name, zx::channel channel); |
| |
| std::unordered_map<std::string, ServiceConnector> name_to_service_connector_; |
| |
| fbl::RefPtr<fs::PseudoDir> directory_; |
| fidl::BindingSet<fuchsia::sys::ServiceProvider> bindings_; |
| |
| FXL_DISALLOW_COPY_AND_ASSIGN(ServiceNamespace); |
| }; |
| |
| } // namespace component |
| |
| #endif // LIB_SVC_CPP_SERVICE_NAMESPACE_H_ |