blob: 7131f81ff86a82b0f37e1e7052fe0ef059b0ba6f [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_ASYNC_CPP_BIND_H_
#define LIB_FIDL_ASYNC_CPP_BIND_H_
#include <lib/async/wait.h>
#include <lib/fidl-async/cpp/channel_transaction.h>
#include <lib/fidl/llcpp/server.h>
#include <lib/fidl/llcpp/transaction.h>
#include <lib/fit/function.h>
#include <lib/zx/channel.h>
#include <zircon/fidl.h>
namespace fidl {
template <typename ServerImpl>
using OnChannelClosedFn = fit::callback<void(ServerImpl*)>;
namespace internal {
using AnyOnChannelClosedFn = fit::callback<void(fidl::internal::IncomingMessageDispatcher*)>;
zx_status_t BindSingleInFlightOnlyImpl(async_dispatcher_t* dispatcher, zx::channel channel,
fidl::internal::IncomingMessageDispatcher* interface,
AnyOnChannelClosedFn on_channel_closed_fn);
class SimpleBinding : private async_wait_t {
public:
SimpleBinding(async_dispatcher_t* dispatcher, zx::channel channel,
fidl::internal::IncomingMessageDispatcher* interface,
AnyOnChannelClosedFn on_channel_closed_fn);
~SimpleBinding();
static void MessageHandler(async_dispatcher_t* dispatcher, async_wait_t* wait, zx_status_t status,
const zx_packet_signal_t* signal);
private:
friend fidl::internal::ChannelTransaction;
friend zx_status_t BeginWait(std::unique_ptr<SimpleBinding>* unique_binding);
zx::unowned_channel channel() const { return zx::unowned_channel(async_wait_t::object); }
async_dispatcher_t* dispatcher_;
fidl::internal::IncomingMessageDispatcher* interface_;
AnyOnChannelClosedFn on_channel_closed_fn_;
};
// Attempts to attach the binding onto the async dispatcher.
// Upon success, the binding ownership is transferred to the async dispatcher.
// Upon failure, the binding ownership stays in the |unique_ptr|.
// Returns the status of |async_begin_wait|.
zx_status_t BeginWait(std::unique_ptr<SimpleBinding>* unique_binding);
} // namespace internal
// (Deprecated) Binds an implementation of a low-level C++ server interface to
// |server_end| using |dispatcher|.
//
// Note: This function is preserved for backwards compatibility reasons only.
// It would not dispatch a second message on a channel if there were already
// another message being handled or whose response deferred asynchronously.
// New clients should use the |fidl::BindServer| API from
// `zircon/system/ulib/fidl/include/lib/fidl/llcpp/server.h`.
//
// This function adds an |async_wait_t| to the given |dispatcher| that waits
// asynchronously for new messages to arrive on |server_end|. When a message
// arrives, the dispatch function corresponding to the interface is called
// on one of the threads associated with the |dispatcher|.
//
// Typically, the dispatch function is generated by the low-level C++ backend
// for FIDL interfaces. These dispatch functions decode the |fidl_incoming_msg_t| and
// call into the implementation of the FIDL interface, via its C++ vtable.
//
// When an error occurs in the server implementation as part of handling the message, it may call
// |Close(error)| on the completer to indicate the error condition to the dispatcher.
// The dispatcher will send an epitaph with this error code before closing the channel.
//
// Returns whether |fidl::BindSingleInFlightOnly| was able to begin waiting on the given
// |server_end|.
// Upon any error, |server_end| is closed and the binding is terminated.
//
// The |dispatcher| takes ownership of the channel. Shutting down the |dispatcher|
// results in |server_end| being closed.
//
// It is safe to shutdown the dispatcher at any time.
//
// It is unsafe to destroy the dispatcher from within a dispatch function.
// It is unsafe to destroy the dispatcher while any fidl::Transaction objects are alive.
template <typename ServerImpl>
zx_status_t BindSingleInFlightOnly(
async_dispatcher_t* dispatcher,
fidl::ServerEnd<typename ServerImpl::_EnclosingProtocol> server_end, ServerImpl* impl) {
return internal::BindSingleInFlightOnlyImpl(dispatcher, server_end.TakeChannel(), impl, nullptr);
}
// As above, but will invoke |on_channel_close_fn| on |impl| when either end of the channel
// is closed.
template <typename ServerImpl>
zx_status_t BindSingleInFlightOnly(
async_dispatcher_t* dispatcher,
fidl::ServerEnd<typename ServerImpl::_EnclosingProtocol> server_end, ServerImpl* impl,
OnChannelClosedFn<ServerImpl> on_channel_close_fn) {
return internal::BindSingleInFlightOnlyImpl(
dispatcher, server_end.TakeChannel(), impl,
[fn = std::move(on_channel_close_fn)](
fidl::internal::IncomingMessageDispatcher* interface) mutable {
fn(static_cast<ServerImpl*>(interface));
});
}
// As above, but will destroy |impl| when either end of the channel is closed.
template <typename ServerImpl>
zx_status_t BindSingleInFlightOnly(
async_dispatcher_t* dispatcher,
fidl::ServerEnd<typename ServerImpl::_EnclosingProtocol> server_end,
std::unique_ptr<ServerImpl> impl) {
OnChannelClosedFn<ServerImpl> fn = [](fidl::internal::IncomingMessageDispatcher* interface) {
auto* impl = static_cast<ServerImpl*>(interface);
delete impl;
};
return BindSingleInFlightOnly(dispatcher, server_end.TakeChannel(), impl.release(),
std::move(fn));
}
} // namespace fidl
#endif // LIB_FIDL_ASYNC_CPP_BIND_H_