blob: 07cbddc6e27eef1b5644ada736f83a1650cedf9d [file] [log] [blame]
// 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 "src/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(std::string 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_