// Copyright 2016 The Fuchsia Authors
//
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT

#ifndef ZIRCON_KERNEL_OBJECT_INCLUDE_OBJECT_MESSAGE_PACKET_H_
#define ZIRCON_KERNEL_OBJECT_INCLUDE_OBJECT_MESSAGE_PACKET_H_

#include <lib/user_copy/user_ptr.h>
#include <stdint.h>
#include <zircon/types.h>

#include <cstdint>

#include <fbl/intrusive_double_list.h>
#include <fbl/intrusive_single_list.h>
#include <ktl/unique_ptr.h>
#include <object/buffer_chain.h>
#include <object/handle.h>

constexpr uint32_t kMaxMessageSize = 65536u;
constexpr uint32_t kMaxMessageHandles = 64u;
constexpr uint32_t kMaxIovecsCount = 8192u;

// ensure public constants are aligned
static_assert(ZX_CHANNEL_MAX_MSG_BYTES == kMaxMessageSize, "");
static_assert(ZX_CHANNEL_MAX_MSG_HANDLES == kMaxMessageHandles, "");
static_assert(ZX_CHANNEL_MAX_MSG_IOVECS == kMaxIovecsCount, "");

class Handle;
class MessagePacket;
namespace internal {
struct MessagePacketDeleter;
}  // namespace internal

// Definition of a MessagePacket's specific pointer type.  Message packets must
// be managed using this specific type of pointer, because MessagePackets have a
// specific custom deletion requirement.
using MessagePacketPtr = ktl::unique_ptr<MessagePacket, internal::MessagePacketDeleter>;

class MessagePacket final : public fbl::DoublyLinkedListable<MessagePacketPtr> {
 public:
  // The number of iovecs to read and process at a time.
  // If number of iovecs <= kIovecChunkSize, then the message buf size will be computed and the
  // minimum required number of pages will be allocated. Otherwise, a large enough buffer for
  // the largest possible message will be allocated.
  static constexpr uint32_t kIovecChunkSize = 16;

  // Creates a message packet containing the provided data and space for
  // |num_handles| handles. The handles array is uninitialized and must
  // be completely overwritten by clients.
  static zx_status_t Create(user_in_ptr<const char> data, uint32_t data_size, uint32_t num_handles,
                            MessagePacketPtr* msg);
  static zx_status_t Create(user_in_ptr<const zx_channel_iovec_t> iovecs, uint32_t num_iovecs,
                            uint32_t num_handles, MessagePacketPtr* msg);
  static zx_status_t Create(const char* data, uint32_t data_size, uint32_t num_handles,
                            MessagePacketPtr* msg);

  uint32_t data_size() const { return data_size_; }

  // Copies the packet's |data_size()| bytes to |buf|.
  // Returns an error if |buf| points to a bad user address.
  zx_status_t CopyDataTo(user_out_ptr<char> buf) const {
    return buffer_chain_->CopyOut(buf, payload_offset_, data_size_);
  }

  uint32_t num_handles() const { return num_handles_; }
  Handle* const* handles() const { return handles_; }
  Handle** mutable_handles() { return handles_; }

  void set_owns_handles(bool own_handles) { owns_handles_ = own_handles; }

  // zx_channel_call treats the leading bytes of the payload as
  // a transaction id of type zx_txid_t.
  zx_txid_t get_txid() const {
    if (data_size_ < sizeof(zx_txid_t)) {
      return 0;
    }
    // The first few bytes of the payload are a zx_txid_t.
    void* payload_start = buffer_chain_->buffers()->front().data() + payload_offset_;
    return *reinterpret_cast<zx_txid_t*>(payload_start);
  }

  void set_txid(zx_txid_t txid) {
    if (data_size_ >= sizeof(zx_txid_t)) {
      void* payload_start = buffer_chain_->buffers()->front().data() + payload_offset_;
      *(reinterpret_cast<zx_txid_t*>(payload_start)) = txid;
    }
  }

 private:
  // A private constructor ensures that users must use the static factory
  // Create method to create a MessagePacket.  This, in turn, guarantees that
  // when a user creates a MessagePacket, they end up with the proper
  // MessagePacket::UPtr type for managing the message packet's life cycle.
  MessagePacket(BufferChain* chain, uint32_t data_size, uint32_t payload_offset,
                uint16_t num_handles, Handle** handles)
      : buffer_chain_(chain),
        handles_(handles),
        data_size_(data_size),
        payload_offset_(payload_offset),
        num_handles_(num_handles),
        owns_handles_(false) {}

  // A private destructor helps to make sure that only our custom deleter is
  // ever used to destroy this object which, in turn, makes it very difficult
  // to not properly recycle the object.
  ~MessagePacket() {
    DEBUG_ASSERT(!InContainer());
    if (owns_handles_) {
      for (size_t ix = 0; ix != num_handles_; ++ix) {
        // Delete the handle via HandleOwner dtor.
        HandleOwner ho(handles_[ix]);
      }
    }
  }

  friend struct internal::MessagePacketDeleter;
  static void recycle(MessagePacket* packet);

  static zx_status_t CreateIovecBounded(user_in_ptr<const zx_channel_iovec_t> iovecs,
                                        uint32_t num_iovecs, uint32_t num_handles,
                                        MessagePacketPtr* msg);
  static zx_status_t CreateIovecUnbounded(user_in_ptr<const zx_channel_iovec_t> iovecs,
                                          uint32_t num_iovecs, uint32_t num_handles,
                                          MessagePacketPtr* msg);
  static zx_status_t CreateCommon(uint32_t data_size, uint32_t num_handles, MessagePacketPtr* msg);

  void set_data_size(uint32_t data_size) { data_size_ = data_size; }

  BufferChain* buffer_chain_;
  Handle** const handles_;
  uint32_t data_size_;
  const uint32_t payload_offset_;
  const uint16_t num_handles_;
  bool owns_handles_;
};

namespace internal {
struct MessagePacketDeleter {
  void operator()(MessagePacket* packet) const noexcept { MessagePacket::recycle(packet); }
};
}  // namespace internal

#endif  // ZIRCON_KERNEL_OBJECT_INCLUDE_OBJECT_MESSAGE_PACKET_H_
