blob: 0a842c54716e520c003e6f617a8a61c69f58b360 [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_FIDL_LLCPP_CONNECT_SERVICE_H_
#define LIB_FIDL_LLCPP_CONNECT_SERVICE_H_
#include <lib/fidl/llcpp/client_end.h>
#include <lib/fidl/llcpp/server_end.h>
#include <lib/fidl/llcpp/string_view.h>
#include <lib/fidl/llcpp/wire_messaging.h>
#include <lib/fit/result.h>
#include <zircon/fidl.h>
#ifdef __Fuchsia__
#include <lib/zx/channel.h>
#include <lib/zx/status.h>
#endif // __Fuchsia__
namespace fidl {
#ifdef __Fuchsia__
// Creates a synchronous FIDL client for the FIDL protocol `FidlProtocol`, bound to the
// given channel.
template <typename FidlProtocol>
typename fidl::WireSyncClient<FidlProtocol> BindSyncClient(ClientEnd<FidlProtocol> client_end) {
return typename fidl::WireSyncClient<FidlProtocol>(std::move(client_end));
}
template <typename Protocol>
struct Endpoints {
fidl::ClientEnd<Protocol> client;
fidl::ServerEnd<Protocol> server;
};
// Creates a pair of Zircon channel endpoints speaking the |Protocol| protocol.
// Whenever interacting with LLCPP, using this method should be encouraged over
// |zx::channel::create|, because this method encodes the precise protocol type
// into its results at compile time.
//
// The return value is a result type wrapping the client and server endpoints.
// Given the following:
//
// auto endpoints = fidl::CreateEndpoints<MyProtocol>();
//
// The caller should first ensure that |endpoints.is_ok() == true|, after which
// the channel endpoints may be accessed in one of two ways:
//
// - Direct:
// endpoints->client;
// endpoints->server;
//
// - Structured Binding:
// auto [client_end, server_end] = std::move(endpoints.value());
template <typename Protocol>
zx::status<Endpoints<Protocol>> CreateEndpoints() {
zx::channel local, remote;
zx_status_t status = zx::channel::create(0, &local, &remote);
if (status != ZX_OK) {
return zx::error_status(status);
}
return zx::ok(Endpoints<Protocol>{
fidl::ClientEnd<Protocol>(std::move(local)),
fidl::ServerEnd<Protocol>(std::move(remote)),
});
}
// Creates a pair of Zircon channel endpoints speaking the |Protocol| protocol.
// Whenever interacting with LLCPP, using this method should be encouraged over
// |zx::channel::create|, because this method encodes the precise protocol type
// into its results at compile time.
//
// This overload of |CreateEndpoints| may lead to more concise code when the
// caller already has the client endpoint defined as an instance variable.
// It will replace the destination of |out_client| with a newly created client
// endpoint, and return the corresponding server endpoint in a |zx::status|:
//
// // |client_end_| is an instance variable.
// auto server_end = fidl::CreateEndpoints(&client_end_);
// if (server_end.is_ok()) { ... }
template <typename Protocol>
zx::status<fidl::ServerEnd<Protocol>> CreateEndpoints(fidl::ClientEnd<Protocol>* out_client) {
auto endpoints = fidl::CreateEndpoints<Protocol>();
if (!endpoints.is_ok()) {
return endpoints.take_error();
}
*out_client = fidl::ClientEnd<Protocol>(std::move(endpoints->client));
return zx::ok(fidl::ServerEnd<Protocol>(std::move(endpoints->server)));
}
namespace internal {
// The method signature required to implement the method that issues the Directory::Open
// FIDL call for a Service's member protocol.
using ConnectMemberFunc = zx::status<> (*)(zx::unowned_channel service_dir,
fidl::StringView member_name, zx::channel channel);
} // namespace internal
#endif // __Fuchsia__
namespace internal {
// This struct template is specialized in generated bindings to include the following
// protocol-specific members:
// - static constexpr char DiscoverableName[] - the discoverable name if any exists.
template <typename Protocol>
struct ProtocolDetails;
// Helper type for compile-time string concatenation.
template <const char*, typename>
struct default_service_path;
template <const char* n, size_t... i>
struct default_service_path<n, std::integer_sequence<size_t, i...>> {
static constexpr const char value[]{'/', 's', 'v', 'c', '/', n[i]...};
};
} // namespace internal
// DiscoverableProtocolName<Protocol> evaluates to a string containing the name of the protocol,
// including its library.
template <typename Protocol>
constexpr const char* DiscoverableProtocolName =
fidl::internal::ProtocolDetails<Protocol>::DiscoverableName;
// DiscoverableProtocolDefaultPath<Protocol> evaluates to a string containing the default path for
// the protocol endpoint, something like "/svc/fuchsia.library.Protocol".
template <typename Protocol>
constexpr const char* DiscoverableProtocolDefaultPath = fidl::internal::default_service_path<
fidl::internal::ProtocolDetails<Protocol>::DiscoverableName,
std::make_integer_sequence<
size_t, sizeof(fidl::internal::ProtocolDetails<Protocol>::DiscoverableName)>>::value;
} // namespace fidl
#endif // LIB_FIDL_LLCPP_CONNECT_SERVICE_H_