blob: 3a0e4480a20c9b38f95b6c4a4a135ee8ada57d22 [file] [log] [blame]
// 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_