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

#include "object/message_packet.h"

#include <stdint.h>
#include <string.h>
#include <zircon/errors.h>
#include <zircon/types.h>

#include <cstddef>
#include <cstdint>
#include <new>

#include <fbl/algorithm.h>
#include <ktl/algorithm.h>

#include <ktl/enforce.h>

// MessagePackets have special allocation requirements because they can contain a variable number of
// handles and a variable size payload.
//
// To reduce heap fragmentation, MessagePackets are stored in a lists of fixed size buffers
// (BufferChains) rather than a contiguous blocks of memory.  These lists and buffers are allocated
// from the PMM.
//
// The first buffer in a MessagePacket's BufferChain contains the MessagePacket object, followed by
// its handles (if any), and finally its payload data (if any).

// The MessagePacket object, its handles and zx_txid_t must all fit in the first buffer.
static constexpr size_t kContiguousBytes =
    sizeof(MessagePacket) + (kMaxMessageHandles * sizeof(Handle*)) + sizeof(zx_txid_t);
static_assert(kContiguousBytes <= BufferChain::kContig, "");

// Handles are stored just after the MessagePacket.
static constexpr uint32_t kHandlesOffset = static_cast<uint32_t>(sizeof(MessagePacket));

// PayloadOffset returns the offset of the data payload from the start of the first buffer.
static inline size_t PayloadOffset(size_t num_handles) {
  // The payload comes after the handles.
  return kHandlesOffset + num_handles * sizeof(Handle*);
}

// Creates a MessagePacket in |msg| sufficient to hold |data_size| bytes and |num_handles|.
//
// Note: This method does not write the payload into the MessagePacket.
//
// Returns ZX_OK on success.
//
// static
inline zx_status_t MessagePacket::CreateCommon(size_t data_size, size_t num_handles,
                                               MessagePacketPtr* msg) {
  if (unlikely(data_size > kMaxMessageSize || num_handles > kMaxMessageHandles)) {
    return ZX_ERR_OUT_OF_RANGE;
  }

  const size_t payload_offset = PayloadOffset(num_handles);

  // MessagePackets lives *inside* a list of buffers.  The first buffer holds the MessagePacket
  // object, followed by its handles (if any), and finally the payload data.
  BufferChain* chain = BufferChain::Alloc(payload_offset + data_size);
  if (unlikely(!chain)) {
    return ZX_ERR_NO_MEMORY;
  }
  DEBUG_ASSERT(!chain->buffers()->is_empty());
  chain->Skip(payload_offset);

  char* const data = chain->buffers()->front().data();
  Handle** const handles = reinterpret_cast<Handle**>(data + kHandlesOffset);

  // Construct the MessagePacket into the first buffer.
  MessagePacket* const packet = reinterpret_cast<MessagePacket*>(data);
  static_assert(kMaxMessageHandles <= UINT16_MAX, "");
  msg->reset(new (packet) MessagePacket(chain, static_cast<uint32_t>(data_size),
                                        static_cast<uint32_t>(payload_offset),
                                        static_cast<uint16_t>(num_handles), handles));
  // The MessagePacket now owns the BufferChain and msg owns the MessagePacket.

  return ZX_OK;
}

// static
zx_status_t MessagePacket::Create(user_in_ptr<const char> data, uint32_t data_size,
                                  uint32_t num_handles, MessagePacketPtr* msg) {
  MessagePacketPtr new_msg;
  zx_status_t status = CreateCommon(data_size, num_handles, &new_msg);
  if (unlikely(status != ZX_OK)) {
    return status;
  }
  status = new_msg->buffer_chain_->Append(data, data_size);
  if (unlikely(status != ZX_OK)) {
    return status;
  }
  *msg = ktl::move(new_msg);
  return ZX_OK;
}

// static
zx_status_t MessagePacket::Create(user_in_ptr<const zx_channel_iovec_t> iovecs, uint32_t num_iovecs,
                                  uint32_t num_handles, MessagePacketPtr* msg) {
  if (unlikely(num_iovecs > kMaxIovecsCount)) {
    return ZX_ERR_OUT_OF_RANGE;
  }

  if (num_iovecs <= kIovecChunkSize) {
    return CreateIovecBounded(iovecs, num_iovecs, num_handles, msg);
  }
  return CreateIovecUnbounded(iovecs, num_iovecs, num_handles, msg);
}

// static
zx_status_t MessagePacket::CreateIovecBounded(user_in_ptr<const zx_channel_iovec_t> user_iovecs,
                                              uint32_t num_iovecs, uint32_t num_handles,
                                              MessagePacketPtr* msg) {
  DEBUG_ASSERT(num_iovecs <= kIovecChunkSize);
  zx_channel_iovec_t iovecs[kIovecChunkSize];
  if (num_iovecs > 0) {
    zx_status_t status = user_iovecs.copy_array_from_user(iovecs, num_iovecs);
    if (unlikely(status != ZX_OK)) {
      return status;
    }
  }

  size_t message_size = 0;
  for (uint32_t i = 0; i < num_iovecs; i++) {
    if (unlikely(iovecs[i].reserved != 0)) {
      return ZX_ERR_INVALID_ARGS;
    }

    static_assert(sizeof(message_size) > sizeof(iovecs[i].capacity), "avoid overflow");
    message_size += iovecs[i].capacity;
  }

  MessagePacketPtr new_msg;
  zx_status_t status = CreateCommon(message_size, num_handles, &new_msg);
  if (unlikely(status != ZX_OK)) {
    return status;
  }

  for (uint32_t i = 0; i < num_iovecs; i++) {
    user_in_ptr<const char> src(reinterpret_cast<const char*>(iovecs[i].buffer));
    status = new_msg->buffer_chain_->Append(src, iovecs[i].capacity);
    if (unlikely(status != ZX_OK)) {
      return status;
    }
  }

  *msg = ktl::move(new_msg);
  return ZX_OK;
}

// static
zx_status_t MessagePacket::CreateIovecUnbounded(user_in_ptr<const zx_channel_iovec_t> user_iovecs,
                                                uint32_t num_iovecs, uint32_t num_handles,
                                                MessagePacketPtr* msg) {
  MessagePacketPtr new_msg;
  zx_status_t status = CreateCommon(kMaxMessageSize, num_handles, &new_msg);
  if (unlikely(status != ZX_OK)) {
    return status;
  }

  size_t message_size = 0;
  while (num_iovecs > 0) {
    uint32_t chunk_iovecs = ktl::min(num_iovecs, kIovecChunkSize);

    zx_channel_iovec_t iovecs[kIovecChunkSize];
    status = user_iovecs.copy_array_from_user(iovecs, chunk_iovecs);
    if (unlikely(status != ZX_OK)) {
      return status;
    }

    for (uint32_t i = 0; i < chunk_iovecs; i++) {
      const zx_channel_iovec_t* iovec = &iovecs[i];
      if (unlikely(iovec->reserved != 0)) {
        return ZX_ERR_INVALID_ARGS;
      }
      static_assert(sizeof(message_size) > sizeof(iovec->capacity), "avoid overflow");
      message_size += iovec->capacity;
      user_in_ptr<const char> src(reinterpret_cast<const char*>(iovec->buffer));
      status = new_msg->buffer_chain_->Append(src, iovec->capacity);
      if (unlikely(status != ZX_OK)) {
        return status;
      }
    }

    num_iovecs -= chunk_iovecs;
    user_iovecs = user_iovecs.element_offset(chunk_iovecs);
  }

  new_msg->buffer_chain_->FreeUnusedBuffers();
  new_msg->set_data_size(static_cast<uint32_t>(message_size));

  *msg = ktl::move(new_msg);
  return ZX_OK;
}

// static
zx_status_t MessagePacket::Create(const char* data, uint32_t data_size, uint32_t num_handles,
                                  MessagePacketPtr* msg) {
  MessagePacketPtr new_msg;
  zx_status_t status = CreateCommon(data_size, num_handles, &new_msg);
  if (unlikely(status != ZX_OK)) {
    return status;
  }
  status = new_msg->buffer_chain_->AppendKernel(data, data_size);
  if (unlikely(status != ZX_OK)) {
    return status;
  }
  *msg = ktl::move(new_msg);
  return ZX_OK;
}

void MessagePacket::recycle(MessagePacket* packet) {
  // Grab the buffer chain for this packet
  BufferChain* chain = packet->buffer_chain_;

  // Manually destruct the packet.  Do not delete it; its memory did not come
  // from new, it is contained as part of the buffer chain.
  packet->~MessagePacket();

  // Now return the buffer chain to where it came from.
  BufferChain::Free(chain);
}
