// 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_
