// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "mojo/edk/system/transport_data.h"

#include <string.h>

#include <utility>

#include "base/logging.h"
#include "mojo/edk/system/channel.h"
#include "mojo/edk/system/configuration.h"
#include "mojo/edk/system/message_in_transit.h"

namespace mojo {
namespace system {

// The maximum amount of space needed per platform handle.
// (|{Channel,RawChannel}::GetSerializedPlatformHandleSize()| should always
// return a value which is at most this. This is only used to calculate
// |TransportData::kMaxBufferSize|. This value should be a multiple of the
// alignment in order to simplify calculations, even though the actual amount of
// space needed need not be a multiple of the alignment.
const size_t kMaxSizePerPlatformHandle = 8;
static_assert(kMaxSizePerPlatformHandle % MessageInTransit::kMessageAlignment ==
                  0,
              "kMaxSizePerPlatformHandle not a multiple of alignment");

MOJO_STATIC_CONST_MEMBER_DEFINITION const size_t
    TransportData::kMaxSerializedDispatcherSize;
MOJO_STATIC_CONST_MEMBER_DEFINITION const size_t
    TransportData::kMaxSerializedDispatcherPlatformHandles;

// static
size_t TransportData::GetMaxBufferSize() {
  // In additional to the header, for each attached (Mojo) handle there'll be a
  // handle table entry and serialized dispatcher data.
  return sizeof(Header) +
         GetConfiguration().max_message_num_handles *
             (sizeof(HandleTableEntry) + kMaxSerializedDispatcherSize) +
         GetMaxPlatformHandles() * kMaxSizePerPlatformHandle;
}

// static
size_t TransportData::GetMaxPlatformHandles() {
  return GetConfiguration().max_message_num_handles *
         kMaxSerializedDispatcherPlatformHandles;
}

struct TransportData::PrivateStructForCompileAsserts {
  static_assert(sizeof(Header) % MessageInTransit::kMessageAlignment == 0,
                "sizeof(MessageInTransit::Header) not a multiple of alignment");
  static_assert(kMaxSerializedDispatcherSize %
                        MessageInTransit::kMessageAlignment ==
                    0,
                "kMaxSerializedDispatcherSize not a multiple of alignment");
  static_assert(sizeof(HandleTableEntry) %
                        MessageInTransit::kMessageAlignment ==
                    0,
                "sizeof(MessageInTransit::HandleTableEntry) not a multiple of "
                "alignment");
};

TransportData::TransportData(std::unique_ptr<DispatcherVector> dispatchers,
                             Channel* channel)
    : buffer_size_() {
  DCHECK(dispatchers);
  DCHECK(channel);

  const size_t num_handles = dispatchers->size();
  DCHECK_GT(num_handles, 0u);

  // The offset to the start of the (Mojo) handle table.
  const size_t handle_table_start_offset = sizeof(Header);
  // The offset to the start of the serialized dispatcher data.
  const size_t serialized_dispatcher_start_offset =
      handle_table_start_offset + num_handles * sizeof(HandleTableEntry);
  // The estimated size of the secondary buffer. We compute this estimate below.
  // It must be at least as big as the (eventual) actual size.
  size_t estimated_size = serialized_dispatcher_start_offset;
  size_t estimated_num_platform_handles = 0;
#if DCHECK_IS_ON()
  std::vector<size_t> all_max_sizes(num_handles);
  std::vector<size_t> all_max_platform_handles(num_handles);
#endif
  for (size_t i = 0; i < num_handles; i++) {
    if (Dispatcher* dispatcher = (*dispatchers)[i].get()) {
      size_t max_size = 0;
      size_t max_platform_handles = 0;
      Dispatcher::TransportDataAccess::StartSerialize(
          dispatcher, channel, &max_size, &max_platform_handles);

      DCHECK_LE(max_size, kMaxSerializedDispatcherSize);
      estimated_size += MessageInTransit::RoundUpMessageAlignment(max_size);
      DCHECK_LE(estimated_size, GetMaxBufferSize());

      DCHECK_LE(max_platform_handles, kMaxSerializedDispatcherPlatformHandles);
      estimated_num_platform_handles += max_platform_handles;
      DCHECK_LE(estimated_num_platform_handles, GetMaxPlatformHandles());

#if DCHECK_IS_ON()
      all_max_sizes[i] = max_size;
      all_max_platform_handles[i] = max_platform_handles;
#endif
    }
  }

  size_t size_per_platform_handle = 0;
  if (estimated_num_platform_handles > 0) {
    size_per_platform_handle = channel->GetSerializedPlatformHandleSize();
    DCHECK_LE(size_per_platform_handle, kMaxSizePerPlatformHandle);
    estimated_size += estimated_num_platform_handles * size_per_platform_handle;
    estimated_size = MessageInTransit::RoundUpMessageAlignment(estimated_size);
    DCHECK_LE(estimated_size, GetMaxBufferSize());
  }

  buffer_.reset(static_cast<char*>(
      base::AlignedAlloc(estimated_size, MessageInTransit::kMessageAlignment)));
  // Entirely clear out the secondary buffer, since then we won't have to worry
  // about clearing padding or unused space (e.g., if a dispatcher fails to
  // serialize).
  memset(buffer_.get(), 0, estimated_size);

  if (estimated_num_platform_handles > 0) {
    DCHECK(!platform_handles_);
    platform_handles_.reset(new embedder::PlatformHandleVector());
  }

  Header* header = reinterpret_cast<Header*>(buffer_.get());
  header->num_handles = static_cast<uint32_t>(num_handles);
  // (Okay to leave |platform_handle_table_offset|, |num_platform_handles|, and
  // |unused| be zero; we'll set the former two later if necessary.)

  HandleTableEntry* handle_table = reinterpret_cast<HandleTableEntry*>(
      buffer_.get() + handle_table_start_offset);
  size_t current_offset = serialized_dispatcher_start_offset;
  for (size_t i = 0; i < num_handles; i++) {
    Dispatcher* dispatcher = (*dispatchers)[i].get();
    if (!dispatcher) {
      static_assert(static_cast<int32_t>(Dispatcher::Type::UNKNOWN) == 0,
                    "Value of Dispatcher::Type::UNKNOWN must be 0");
      continue;
    }

#if DCHECK_IS_ON()
    size_t old_platform_handles_size =
        platform_handles_ ? platform_handles_->size() : 0;
#endif

    void* destination = buffer_.get() + current_offset;
    size_t actual_size = 0;
    if (Dispatcher::TransportDataAccess::EndSerializeAndClose(
            dispatcher, channel, destination, &actual_size,
            platform_handles_.get())) {
      handle_table[i].type = static_cast<int32_t>(dispatcher->GetType());
      handle_table[i].offset = static_cast<uint32_t>(current_offset);
      handle_table[i].size = static_cast<uint32_t>(actual_size);
// (Okay to not set |unused| since we cleared the entire buffer.)

#if DCHECK_IS_ON()
      DCHECK_LE(actual_size, all_max_sizes[i]);
      DCHECK_LE(platform_handles_
                    ? (platform_handles_->size() - old_platform_handles_size)
                    : 0,
                all_max_platform_handles[i]);
#endif
    } else {
      // Nothing to do on failure, since |buffer_| was cleared, and
      // |Type::UNKNOWN| is zero. The handle was simply closed.
      LOG(ERROR) << "Failed to serialize handle to remote message pipe";
    }

    current_offset += MessageInTransit::RoundUpMessageAlignment(actual_size);
    DCHECK_LE(current_offset, estimated_size);
    DCHECK_LE(platform_handles_ ? platform_handles_->size() : 0,
              estimated_num_platform_handles);
  }

  if (platform_handles_ && platform_handles_->size() > 0) {
    header->platform_handle_table_offset =
        static_cast<uint32_t>(current_offset);
    header->num_platform_handles =
        static_cast<uint32_t>(platform_handles_->size());
    current_offset += platform_handles_->size() * size_per_platform_handle;
    current_offset = MessageInTransit::RoundUpMessageAlignment(current_offset);
  }

  // There's no aligned realloc, so it's no good way to release unused space (if
  // we overshot our estimated space requirements).
  buffer_size_ = current_offset;

  // |dispatchers_| will be destroyed as it goes out of scope.
}

TransportData::TransportData(
    embedder::ScopedPlatformHandleVectorPtr platform_handles,
    size_t serialized_platform_handle_size)
    : buffer_size_(), platform_handles_(std::move(platform_handles)) {
  buffer_size_ = MessageInTransit::RoundUpMessageAlignment(
      sizeof(Header) +
      platform_handles_->size() * serialized_platform_handle_size);
  buffer_.reset(static_cast<char*>(
      base::AlignedAlloc(buffer_size_, MessageInTransit::kMessageAlignment)));
  memset(buffer_.get(), 0, buffer_size_);

  Header* header = reinterpret_cast<Header*>(buffer_.get());
  header->platform_handle_table_offset = static_cast<uint32_t>(sizeof(Header));
  header->num_platform_handles =
      static_cast<uint32_t>(platform_handles_->size());
}

TransportData::~TransportData() {
}

// static
const char* TransportData::ValidateBuffer(
    size_t serialized_platform_handle_size,
    const void* buffer,
    size_t buffer_size) {
  DCHECK(buffer);
  DCHECK_GT(buffer_size, 0u);

  // Always make sure that the buffer size is sane; if it's not, someone's
  // messing with us.
  if (buffer_size < sizeof(Header) || buffer_size > GetMaxBufferSize() ||
      buffer_size % MessageInTransit::kMessageAlignment != 0)
    return "Invalid message secondary buffer size";

  const Header* header = static_cast<const Header*>(buffer);
  const size_t num_handles = header->num_handles;

  // Sanity-check |num_handles| (before multiplying it against anything).
  if (num_handles > GetConfiguration().max_message_num_handles)
    return "Message handle payload too large";

  if (buffer_size < sizeof(Header) + num_handles * sizeof(HandleTableEntry))
    return "Message secondary buffer too small";

  if (header->num_platform_handles == 0) {
    // Then |platform_handle_table_offset| should also be zero.
    if (header->platform_handle_table_offset != 0) {
      return "Message has no handles attached, but platform handle table "
             "present";
    }
  } else {
    if (header->num_platform_handles >
        GetConfiguration().max_message_num_handles *
            kMaxSerializedDispatcherPlatformHandles)
      return "Message has too many platform handles attached";

    static const char kInvalidPlatformHandleTableOffset[] =
        "Message has invalid platform handle table offset";
    // This doesn't check that the platform handle table doesn't alias other
    // stuff, but it doesn't matter, since it's all read-only.
    if (header->platform_handle_table_offset %
            MessageInTransit::kMessageAlignment !=
        0)
      return kInvalidPlatformHandleTableOffset;

    // ">" instead of ">=" since the size per handle may be zero.
    if (header->platform_handle_table_offset > buffer_size)
      return kInvalidPlatformHandleTableOffset;

    // We already checked |platform_handle_table_offset| and
    // |num_platform_handles|, so the addition and multiplication are okay.
    if (header->platform_handle_table_offset +
            header->num_platform_handles * serialized_platform_handle_size >
        buffer_size)
      return kInvalidPlatformHandleTableOffset;
  }

  const HandleTableEntry* handle_table =
      reinterpret_cast<const HandleTableEntry*>(
          static_cast<const char*>(buffer) + sizeof(Header));
  static const char kInvalidSerializedDispatcher[] =
      "Message contains invalid serialized dispatcher";
  for (size_t i = 0; i < num_handles; i++) {
    size_t offset = handle_table[i].offset;
    if (offset % MessageInTransit::kMessageAlignment != 0)
      return kInvalidSerializedDispatcher;

    size_t size = handle_table[i].size;
    if (size > kMaxSerializedDispatcherSize || size > buffer_size)
      return kInvalidSerializedDispatcher;

    // Note: This is an overflow-safe check for |offset + size > buffer_size|
    // (we know that |size <= buffer_size| from the previous check).
    if (offset > buffer_size - size)
      return kInvalidSerializedDispatcher;
  }

  return nullptr;
}

// static
void TransportData::GetPlatformHandleTable(const void* transport_data_buffer,
                                           size_t* num_platform_handles,
                                           const void** platform_handle_table) {
  DCHECK(transport_data_buffer);
  DCHECK(num_platform_handles);
  DCHECK(platform_handle_table);

  const Header* header = static_cast<const Header*>(transport_data_buffer);
  *num_platform_handles = header->num_platform_handles;
  *platform_handle_table = static_cast<const char*>(transport_data_buffer) +
                           header->platform_handle_table_offset;
}

// static
std::unique_ptr<DispatcherVector> TransportData::DeserializeDispatchers(
    const void* buffer,
    size_t buffer_size,
    embedder::ScopedPlatformHandleVectorPtr platform_handles,
    Channel* channel) {
  DCHECK(buffer);
  DCHECK_GT(buffer_size, 0u);
  DCHECK(channel);

  const Header* header = static_cast<const Header*>(buffer);
  const size_t num_handles = header->num_handles;
  std::unique_ptr<DispatcherVector> dispatchers(
      new DispatcherVector(num_handles));

  const HandleTableEntry* handle_table =
      reinterpret_cast<const HandleTableEntry*>(
          static_cast<const char*>(buffer) + sizeof(Header));
  for (size_t i = 0; i < num_handles; i++) {
    size_t offset = handle_table[i].offset;
    size_t size = handle_table[i].size;
    // Should already have been checked by |ValidateBuffer()|:
    DCHECK_EQ(offset % MessageInTransit::kMessageAlignment, 0u);
    DCHECK_LE(offset, buffer_size);
    DCHECK_LE(offset + size, buffer_size);

    const void* source = static_cast<const char*>(buffer) + offset;
    (*dispatchers)[i] = Dispatcher::TransportDataAccess::Deserialize(
        channel, handle_table[i].type, source, size, platform_handles.get());
  }

  return dispatchers;
}

}  // namespace system
}  // namespace mojo
