// Copyright 2017 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.

#pragma once

#include <zircon/compiler.h>
#include <zircon/types.h>
#include <lib/zx/channel.h>
#include <fbl/intrusive_double_list.h>
#include <fbl/intrusive_wavl_tree.h>
#include <fbl/mutex.h>
#include <fbl/ref_counted.h>
#include <fbl/ref_ptr.h>
#include <unistd.h>

#include <type_traits>

#include <dispatcher-pool/dispatcher-event-source.h>

namespace dispatcher {

// class Channel
//
// Channel is one of the EventSources in the dispatcher framework used to manage
// a zircon channel object.
//
// :: Handlers ::
//
// Two handlers are defined for channel event sources,
// one which becomes dispatched any time the channel has messages to read (the
// ProcessHandler), and one which becomes dispatched when a channel becomes
// closed (the ChannelClosedHandler).
//
// Returning an error from the process handler will cause the channel to
// automatically become deactivated.
//
// The ChannelClosedHandler is optional, but will be called from the execution
// domain context in the event that the peer's endpoint is closed, or if an
// error is returned during processing.  It will not be called if the user's own
// code explicitly deactivates the channel, either by deactivating the channel
// object itself, or by deactivating the execution domain that the channel is
// bound to.
//
// :: Activation ::
//
// Two forms of the Activate method are provided.  One requires that a valid
// zx::channel handle be supplied to the Channel object; this is the handle
// which will be monitored and dispatched by the Channel object.  The other form
// attempts to create a channel pair and use one half of the pair while
// returning the other half to the caller via an out-parameter, presumably so
// that they can hand this handle off to some other process which needs to
// communicate with the user.  A ProcessHandler must be provided during
// activation, a ChannelClosedHandler is optional.
//
// :: Reading/Writing ::
//
// Reading and writing on the channel is done using the Read and Write methods.
// Internally, the handle itself is protected with a lock making it safe to call
// Read or Write on a Channel object from any thread.  Attempts to read or write
// a channel which either has not been activated yet, or which has been
// deactivated, will fail.
//
// :: A Simple Example of Activation ::
//
// class Thingy : public fbl::RefCounted<Thingy> {
//   public:
//     zx_status_t ConnectToClient(zx::channel ch_handle);
//   ...
//   private:
//     fbl::RefPtr<dispatcher::ExecutionDomain> my_domain_;
//     zx_status_t ProcessClientMessage(Channel* ch) TA_REQ(my_domain_.token());
//     void ClientDisconnected(const Channel* ch) TA_REQ(my_domain_.token());
//   ...
// };
//
// zx_status_t Thingy::ConnectToClient(zx::channel ch_handle) {
//   fbl::RefPtr<Channel> ch = Channel::Create();
//   if (!ch) return ZX_ERR_NO_MEMORY;
//
//   Channel::ProcessHandler phandler(
//   [thingy = fbl::MakeRefPtr(this)](Channel* ch) {
//      OBTAIN_EXECUTION_DOMAIN_TOKEN(t, thingy->my_domain_->token());
//      return thingy->ProcessClientMessage(ch);
//   }
//
//   Channel::ChannelCloseHandler chandler(
//   [thingy = fbl::MakeRefPtr(this)](const Channel* ch) {
//      OBTAIN_EXECUTION_DOMAIN_TOKEN(t, thingy->my_domain_->token());
//      thingy->ClientDisconnected(ch);
//   }
//
//   return ch->Activate(std::move(ch_handle),
//                       my_domain_,
//                       std::move(phandler),
//                       std::move(dhandler));
// }
//
class Channel : public EventSource {
 public:
  // Definitions of process and deactivation handlers.
  static constexpr size_t MAX_HANDLER_CAPTURE_SIZE = sizeof(void*) * 2;
  using ProcessHandler = fbl::InlineFunction<zx_status_t(Channel*), MAX_HANDLER_CAPTURE_SIZE>;
  using ChannelClosedHandler = fbl::InlineFunction<void(const Channel*), MAX_HANDLER_CAPTURE_SIZE>;

  // Create
  //
  // General method handles construction/initialization of a Channel subclass.
  // Given an implementation called 'MyChannel', invocation should look like:
  //
  //   auto my_channel = Channel::Create<MyChannel>(arg1, arg2, ...);
  //
  // Note: Implementers are encouraged to keep their constructor/destructor
  // protected/private. In order to do so, they should make sure to specify
  // 'friend class Channel' and 'friend class fbl::RefPtr<T>'.
  template <typename T = Channel, typename... ConstructorSignature>
  static fbl::RefPtr<T> Create(ConstructorSignature&&... args) {
    static_assert(std::is_base_of<Channel, T>::value, "Class must derive from Channel!");

    fbl::AllocChecker ac;
    auto ptr = fbl::AdoptRef(new (&ac) T(std::forward<ConstructorSignature>(args)...));

    if (!ac.check()) {
      return nullptr;
    }

    return ptr;
  }

  // Activate a channel, creating the channel pair and retuning the client's
  // channel endpoint in the process.
  //
  // This operation binds the Channel object to an ExecutionDomain, a
  // processing handler, and an optional deactivation handler.  The operation
  // will fail if the Channel has already been bound, or either the domain
  // reference or processing handler is invalid.
  zx_status_t Activate(zx::channel* client_channel_out, fbl::RefPtr<ExecutionDomain> domain,
                       ProcessHandler process_handler,
                       ChannelClosedHandler channel_closed_handler = nullptr)
      __TA_EXCLUDES(obj_lock_);

  // Activate a channel, binding to the user supplied channel endpoint in the
  // process.
  zx_status_t Activate(zx::channel channel, fbl::RefPtr<ExecutionDomain> domain,
                       ProcessHandler process_handler,
                       ChannelClosedHandler channel_closed_handler = nullptr)
      __TA_EXCLUDES(obj_lock_);

  void Deactivate() __TA_EXCLUDES(obj_lock_) override;

  zx_status_t Read(void* buf, uint32_t buf_len, uint32_t* bytes_read_out,
                   zx::handle* rxed_handle = nullptr) __TA_EXCLUDES(obj_lock_);

  zx_status_t Write(const void* buf, uint32_t buf_len, zx::handle&& tx_handle = zx::handle())
      __TA_EXCLUDES(obj_lock_);

 protected:
  Channel() : EventSource(ZX_CHANNEL_READABLE | ZX_CHANNEL_PEER_CLOSED) {}
  friend class fbl::RefPtr<Channel>;

  void Dispatch(ExecutionDomain* domain) __TA_EXCLUDES(obj_lock_) override;

 private:
  zx_status_t ActivateLocked(zx::channel channel, fbl::RefPtr<ExecutionDomain> domain)
      __TA_REQUIRES(obj_lock_);

  ProcessHandler process_handler_;
  ChannelClosedHandler channel_closed_handler_;
};

}  // namespace dispatcher
