blob: 1526ea080171d9ae1d793958937ab8cf9f758f59 [file] [log] [blame]
// Copyright 2023 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_COMPONENT_INCOMING_CPP_INTERNAL_H_
#define LIB_COMPONENT_INCOMING_CPP_INTERNAL_H_
#include <fidl/fuchsia.io/cpp/wire.h>
#include <fidl/fuchsia.unknown/cpp/wire.h>
#include <lib/component/incoming/cpp/constants.h>
#include <lib/zx/channel.h>
#include <lib/zx/result.h>
#include <type_traits>
#include <utility>
namespace component::internal {
// Implementation of |component::Connect| that delegates to |fdio_service_connect|.
zx::result<> ConnectRaw(zx::channel server_end, std::string_view path);
// Implementation of |component::ConnectAt| for a service directory that delegates to
// |fdio_service_connect_at|.
zx::result<> ConnectAtRaw(fidl::UnownedClientEnd<fuchsia_io::Directory> svc_dir,
zx::channel server_end, std::string_view protocol_name);
// Implementation of |component::OpenDirectory| that delegates to |fdio_open3|.
zx::result<fidl::ClientEnd<fuchsia_io::Directory>> OpenDirectory(std::string_view path,
fuchsia_io::wire::Flags flags);
// Implementation of |component::OpenDirectoryAt| that delegates to |fdio_open3_at|.
zx::result<fidl::ClientEnd<fuchsia_io::Directory>> OpenDirectoryAt(
fidl::UnownedClientEnd<fuchsia_io::Directory> dir, std::string_view path,
fuchsia_io::wire::Flags flags);
// Implementation of |component::Clone| for |fuchsia.unknown/Cloneable|.
zx::result<> CloneRaw(fidl::UnownedClientEnd<fuchsia_unknown::Cloneable>&& cloneable,
zx::channel server_end);
template <typename Protocol>
zx::result<zx::channel> CloneRaw(fidl::UnownedClientEnd<Protocol>&& client) {
zx::channel client_end, server_end;
if (zx_status_t status = zx::channel::create(0, &client_end, &server_end); status != ZX_OK) {
return zx::error(status);
}
if (zx::result<> status = CloneRaw(std::move(client), std::move(server_end)); status.is_error()) {
return status.take_error();
}
return zx::ok(std::move(client_end));
}
// Implementation of |component::OpenService| that is independent from the
// actual |Service|.
zx::result<> OpenNamedServiceRaw(std::string_view service, std::string_view instance,
zx::channel remote);
// Implementation of |component::OpenServiceAt| that is independent from the
// actual |Service|.
zx::result<> OpenNamedServiceAtRaw(fidl::UnownedClientEnd<fuchsia_io::Directory> dir,
std::string_view service_path, std::string_view instance,
zx::channel remote);
// The internal |ProtocolOpenFunc| needs to take raw Zircon channels because
// the FIDL runtime that interfaces with it cannot depend on the |fuchsia.io|
// FIDL library.
zx::result<> ProtocolOpenFunc(zx::unowned_channel dir, fidl::StringView path,
fidl::internal::AnyTransport remote);
zx::result<fidl::ClientEnd<fuchsia_io::Directory>> GetGlobalServiceDirectory();
// Determines if |Protocol| contains the |fuchsia.unknown/Cloneable.Clone| method.
template <typename Protocol, typename = void>
struct has_fidl_method_fuchsia_unknown_clone : public ::std::false_type {};
template <typename Protocol>
struct has_fidl_method_fuchsia_unknown_clone<
Protocol, std::void_t<decltype(fidl::WireRequest<typename Protocol::Clone>{
std::declval<fidl::ServerEnd<fuchsia_unknown::Cloneable>&&>() /* request */})>>
: public std::true_type {};
template <typename Protocol>
constexpr inline auto has_fidl_method_fuchsia_unknown_clone_v =
has_fidl_method_fuchsia_unknown_clone<Protocol>::value;
// Determines if |T| is fully defined i.e. |sizeof(T)| can be evaluated.
template <typename T, typename = void>
struct is_complete : public ::std::false_type {};
template <typename T>
struct is_complete<T, std::void_t<std::integral_constant<std::size_t, sizeof(T)>>>
: public std::true_type {};
template <typename T>
constexpr inline auto is_complete_v = is_complete<T>::value;
// Ensures that |Protocol| is *not* a fuchsia.io protocol. Unlike most services/protocols,
// fuchsia.io connections require a set of flags to be passed during opening that set the expected
// rights on the resulting connection.
//
// This is not a type trait so that we can provide a consistent error message.
template <typename Protocol>
constexpr void EnsureCanConnectToProtocol() {
constexpr bool is_directory_protocol = std::is_same_v<Protocol, fuchsia_io::Directory>;
constexpr bool is_other_node_protocol = std::is_same_v<Protocol, fuchsia_io::Node> ||
std::is_same_v<Protocol, fuchsia_io::File> ||
std::is_same_v<Protocol, fuchsia_io::Symlink>;
static_assert(!is_directory_protocol,
"Use component::OpenDirectory or component::OpenDirectoryAt to open a directory.");
static_assert(!is_other_node_protocol, "Use std::filesystem or fdio to open a file/symlink.");
}
} // namespace component::internal
#endif // LIB_COMPONENT_INCOMING_CPP_INTERNAL_H_