// Copyright 2015 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/remote_consumer_data_pipe_impl.h"

#include <string.h>

#include <algorithm>
#include <memory>
#include <utility>

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

namespace mojo {
namespace system {

namespace {

bool ValidateIncomingMessage(size_t element_num_bytes,
                             size_t capacity_num_bytes,
                             size_t consumer_num_bytes,
                             const MessageInTransit* message) {
  // We should only receive endpoint client messages.
  DCHECK_EQ(message->type(), MessageInTransit::Type::ENDPOINT_CLIENT);

  // But we should check the subtype; only take data pipe acks.
  if (message->subtype() !=
      MessageInTransit::Subtype::ENDPOINT_CLIENT_DATA_PIPE_ACK) {
    LOG(WARNING) << "Received message of unexpected subtype: "
                 << message->subtype();
    return false;
  }

  if (message->num_bytes() != sizeof(RemoteDataPipeAck)) {
    LOG(WARNING) << "Incorrect message size: " << message->num_bytes()
                 << " bytes (expected: " << sizeof(RemoteDataPipeAck)
                 << " bytes)";
    return false;
  }

  const RemoteDataPipeAck* ack =
      static_cast<const RemoteDataPipeAck*>(message->bytes());
  size_t num_bytes_consumed = ack->num_bytes_consumed;

  if (num_bytes_consumed > consumer_num_bytes) {
    LOG(WARNING) << "Number of bytes consumed too large: " << num_bytes_consumed
                 << " bytes (outstanding: " << consumer_num_bytes << " bytes)";
    return false;
  }

  if (num_bytes_consumed % element_num_bytes != 0) {
    LOG(WARNING) << "Number of bytes consumed not a multiple of element size: "
                 << num_bytes_consumed
                 << " bytes (element size: " << element_num_bytes << " bytes)";
    return false;
  }

  return true;
}

}  // namespace

RemoteConsumerDataPipeImpl::RemoteConsumerDataPipeImpl(
    ChannelEndpoint* channel_endpoint,
    size_t consumer_num_bytes,
    std::unique_ptr<char, base::AlignedFreeDeleter> buffer,
    size_t start_index)
    : channel_endpoint_(channel_endpoint),
      consumer_num_bytes_(consumer_num_bytes),
      buffer_(std::move(buffer)),
      start_index_(start_index) {
  // Note: |buffer_| may be null (in which case it'll be lazily allocated).
}

RemoteConsumerDataPipeImpl::~RemoteConsumerDataPipeImpl() {
}

void RemoteConsumerDataPipeImpl::ProducerClose() {
  if (!consumer_open()) {
    DCHECK(!channel_endpoint_);
    return;
  }

  Disconnect();
}

// static
bool RemoteConsumerDataPipeImpl::ProcessMessagesFromIncomingEndpoint(
    const MojoCreateDataPipeOptions& validated_options,
    size_t* consumer_num_bytes,
    MessageInTransitQueue* messages) {
  const size_t element_num_bytes = validated_options.element_num_bytes;
  const size_t capacity_num_bytes = validated_options.capacity_num_bytes;

  if (messages) {
    while (!messages->IsEmpty()) {
      std::unique_ptr<MessageInTransit> message(messages->GetMessage());
      if (!ValidateIncomingMessage(element_num_bytes, capacity_num_bytes,
                                   *consumer_num_bytes, message.get())) {
        messages->Clear();
        return false;
      }

      const RemoteDataPipeAck* ack =
          static_cast<const RemoteDataPipeAck*>(message->bytes());
      size_t num_bytes_consumed = ack->num_bytes_consumed;
      *consumer_num_bytes -= num_bytes_consumed;
    }
  }

  return true;
}

MojoResult RemoteConsumerDataPipeImpl::ProducerWriteData(
    UserPointer<const void> elements,
    UserPointer<uint32_t> num_bytes,
    uint32_t max_num_bytes_to_write,
    uint32_t min_num_bytes_to_write) {
  DCHECK_EQ(max_num_bytes_to_write % element_num_bytes(), 0u);
  DCHECK_EQ(min_num_bytes_to_write % element_num_bytes(), 0u);
  DCHECK_GT(max_num_bytes_to_write, 0u);
  DCHECK_GE(max_num_bytes_to_write, min_num_bytes_to_write);
  DCHECK(consumer_open());
  DCHECK(channel_endpoint_);

  DCHECK_LE(consumer_num_bytes_, capacity_num_bytes());
  DCHECK_EQ(consumer_num_bytes_ % element_num_bytes(), 0u);

  if (min_num_bytes_to_write > capacity_num_bytes() - consumer_num_bytes_)
    return MOJO_RESULT_OUT_OF_RANGE;

  size_t num_bytes_to_write =
      std::min(static_cast<size_t>(max_num_bytes_to_write),
               capacity_num_bytes() - consumer_num_bytes_);
  if (num_bytes_to_write == 0)
    return MOJO_RESULT_SHOULD_WAIT;

  // The maximum amount of data to send per message (make it a multiple of the
  // element size.
  // TODO(vtl): Copied from |LocalDataPipeImpl::ConvertDataToMessages()|.
  size_t max_message_num_bytes = GetConfiguration().max_message_num_bytes;
  max_message_num_bytes -= max_message_num_bytes % element_num_bytes();
  DCHECK_GT(max_message_num_bytes, 0u);

  size_t offset = 0;
  while (offset < num_bytes_to_write) {
    size_t message_num_bytes =
        std::min(max_message_num_bytes, num_bytes_to_write - offset);
    std::unique_ptr<MessageInTransit> message(new MessageInTransit(
        MessageInTransit::Type::ENDPOINT_CLIENT,
        MessageInTransit::Subtype::ENDPOINT_CLIENT_DATA,
        static_cast<uint32_t>(message_num_bytes), elements.At(offset)));
    if (!channel_endpoint_->EnqueueMessage(std::move(message))) {
      Disconnect();
      break;
    }

    offset += message_num_bytes;
    consumer_num_bytes_ += message_num_bytes;
  }

  DCHECK_LE(consumer_num_bytes_, capacity_num_bytes());
  // TODO(vtl): We report |num_bytes_to_write|, instead of |offset|, even if we
  // failed at some point. This is consistent with the idea that writes either
  // "succeed" or "fail" (and since some bytes may have been sent, we opt for
  // "succeed"). Think about this some more.
  num_bytes.Put(static_cast<uint32_t>(num_bytes_to_write));
  return MOJO_RESULT_OK;
}

MojoResult RemoteConsumerDataPipeImpl::ProducerBeginWriteData(
    UserPointer<void*> buffer,
    UserPointer<uint32_t> buffer_num_bytes) {
  DCHECK(consumer_open());
  DCHECK(channel_endpoint_);

  DCHECK_LE(consumer_num_bytes_, capacity_num_bytes());
  DCHECK_EQ(consumer_num_bytes_ % element_num_bytes(), 0u);

  size_t max_num_bytes_to_write = capacity_num_bytes() - consumer_num_bytes_;
  // Don't go into a two-phase write if there's no room.
  if (max_num_bytes_to_write == 0)
    return MOJO_RESULT_SHOULD_WAIT;

  EnsureBuffer();
  start_index_ = 0;  // We always have the full buffer.
  buffer.Put(buffer_.get());
  buffer_num_bytes.Put(static_cast<uint32_t>(max_num_bytes_to_write));
  set_producer_two_phase_max_num_bytes_written(
      static_cast<uint32_t>(max_num_bytes_to_write));
  return MOJO_RESULT_OK;
}

MojoResult RemoteConsumerDataPipeImpl::ProducerEndWriteData(
    uint32_t num_bytes_written) {
  DCHECK(buffer_);
  DCHECK_LE(num_bytes_written, producer_two_phase_max_num_bytes_written());
  DCHECK_EQ(num_bytes_written % element_num_bytes(), 0u);
  DCHECK_LE(num_bytes_written, capacity_num_bytes() - consumer_num_bytes_);

  if (!consumer_open()) {
    set_producer_two_phase_max_num_bytes_written(0);
    DestroyBuffer();
    return MOJO_RESULT_OK;
  }

  // TODO(vtl): The following code is copied almost verbatim from
  // |ProducerWriteData()| (it's touchy to factor it out since it uses a
  // |UserPointer| while we have a plain pointer.

  // The maximum amount of data to send per message (make it a multiple of the
  // element size.
  // TODO(vtl): Mostly copied from |LocalDataPipeImpl::ConvertDataToMessages()|.
  size_t max_message_num_bytes = GetConfiguration().max_message_num_bytes;
  max_message_num_bytes -= max_message_num_bytes % element_num_bytes();
  DCHECK_GT(max_message_num_bytes, 0u);

  size_t offset = 0;
  while (offset < num_bytes_written) {
    size_t message_num_bytes =
        std::min(max_message_num_bytes, num_bytes_written - offset);
    std::unique_ptr<MessageInTransit> message(
        new MessageInTransit(MessageInTransit::Type::ENDPOINT_CLIENT,
                             MessageInTransit::Subtype::ENDPOINT_CLIENT_DATA,
                             static_cast<uint32_t>(message_num_bytes),
                             buffer_.get() + start_index_ + offset));
    if (!channel_endpoint_->EnqueueMessage(std::move(message))) {
      set_producer_two_phase_max_num_bytes_written(0);
      Disconnect();
      return MOJO_RESULT_OK;
    }

    offset += message_num_bytes;
    consumer_num_bytes_ += message_num_bytes;
  }

  DCHECK_LE(consumer_num_bytes_, capacity_num_bytes());
  // TODO(vtl): (End of mostly copied code.)

  set_producer_two_phase_max_num_bytes_written(0);
  return MOJO_RESULT_OK;
}

HandleSignalsState RemoteConsumerDataPipeImpl::ProducerGetHandleSignalsState()
    const {
  HandleSignalsState rv;
  if (consumer_open()) {
    if (consumer_num_bytes_ < capacity_num_bytes() &&
        !producer_in_two_phase_write())
      rv.satisfied_signals |= MOJO_HANDLE_SIGNAL_WRITABLE;
    rv.satisfiable_signals |= MOJO_HANDLE_SIGNAL_WRITABLE;
  } else {
    rv.satisfied_signals |= MOJO_HANDLE_SIGNAL_PEER_CLOSED;
  }
  rv.satisfiable_signals |= MOJO_HANDLE_SIGNAL_PEER_CLOSED;
  return rv;
}

void RemoteConsumerDataPipeImpl::ProducerStartSerialize(
    Channel* channel,
    size_t* max_size,
    size_t* max_platform_handles) {
  *max_size = sizeof(SerializedDataPipeProducerDispatcher) +
              channel->GetSerializedEndpointSize();
  *max_platform_handles = 0;
}

bool RemoteConsumerDataPipeImpl::ProducerEndSerialize(
    Channel* channel,
    void* destination,
    size_t* actual_size,
    embedder::PlatformHandleVector* platform_handles) {
  SerializedDataPipeProducerDispatcher* s =
      static_cast<SerializedDataPipeProducerDispatcher*>(destination);
  s->validated_options = validated_options();
  void* destination_for_endpoint = static_cast<char*>(destination) +
                                   sizeof(SerializedDataPipeProducerDispatcher);

  if (!consumer_open()) {
    // Case 1: The consumer is closed.
    s->consumer_num_bytes = static_cast<size_t>(-1);
    *actual_size = sizeof(SerializedDataPipeProducerDispatcher);
    return true;
  }

  // Case 2: The consumer isn't closed. We pass |channel_endpoint| back to the
  // |Channel|. There's no reason for us to continue to exist afterwards.

  s->consumer_num_bytes = consumer_num_bytes_;
  // Note: We don't use |port|.
  scoped_refptr<ChannelEndpoint> channel_endpoint;
  channel_endpoint.swap(channel_endpoint_);
  channel->SerializeEndpointWithRemotePeer(destination_for_endpoint, nullptr,
                                           channel_endpoint);
  SetConsumerClosed();

  *actual_size = sizeof(SerializedDataPipeProducerDispatcher) +
                 channel->GetSerializedEndpointSize();
  return true;
}

void RemoteConsumerDataPipeImpl::ConsumerClose() {
  NOTREACHED();
}

MojoResult RemoteConsumerDataPipeImpl::ConsumerReadData(
    UserPointer<void> /*elements*/,
    UserPointer<uint32_t> /*num_bytes*/,
    uint32_t /*max_num_bytes_to_read*/,
    uint32_t /*min_num_bytes_to_read*/,
    bool /*peek*/) {
  NOTREACHED();
  return MOJO_RESULT_INTERNAL;
}

MojoResult RemoteConsumerDataPipeImpl::ConsumerDiscardData(
    UserPointer<uint32_t> /*num_bytes*/,
    uint32_t /*max_num_bytes_to_discard*/,
    uint32_t /*min_num_bytes_to_discard*/) {
  NOTREACHED();
  return MOJO_RESULT_INTERNAL;
}

MojoResult RemoteConsumerDataPipeImpl::ConsumerQueryData(
    UserPointer<uint32_t> /*num_bytes*/) {
  NOTREACHED();
  return MOJO_RESULT_INTERNAL;
}

MojoResult RemoteConsumerDataPipeImpl::ConsumerBeginReadData(
    UserPointer<const void*> /*buffer*/,
    UserPointer<uint32_t> /*buffer_num_bytes*/) {
  NOTREACHED();
  return MOJO_RESULT_INTERNAL;
}

MojoResult RemoteConsumerDataPipeImpl::ConsumerEndReadData(
    uint32_t /*num_bytes_read*/) {
  NOTREACHED();
  return MOJO_RESULT_INTERNAL;
}

HandleSignalsState RemoteConsumerDataPipeImpl::ConsumerGetHandleSignalsState()
    const {
  return HandleSignalsState();
}

void RemoteConsumerDataPipeImpl::ConsumerStartSerialize(
    Channel* /*channel*/,
    size_t* /*max_size*/,
    size_t* /*max_platform_handles*/) {
  NOTREACHED();
}

bool RemoteConsumerDataPipeImpl::ConsumerEndSerialize(
    Channel* /*channel*/,
    void* /*destination*/,
    size_t* /*actual_size*/,
    embedder::PlatformHandleVector* /*platform_handles*/) {
  NOTREACHED();
  return false;
}

bool RemoteConsumerDataPipeImpl::OnReadMessage(unsigned /*port*/,
                                               MessageInTransit* message) {
  // Always take ownership of the message. (This means that we should always
  // return true.)
  std::unique_ptr<MessageInTransit> msg(message);

  if (!ValidateIncomingMessage(element_num_bytes(), capacity_num_bytes(),
                               consumer_num_bytes_, msg.get())) {
    Disconnect();
    return true;
  }

  const RemoteDataPipeAck* ack =
      static_cast<const RemoteDataPipeAck*>(msg->bytes());
  size_t num_bytes_consumed = ack->num_bytes_consumed;
  consumer_num_bytes_ -= num_bytes_consumed;
  return true;
}

void RemoteConsumerDataPipeImpl::OnDetachFromChannel(unsigned /*port*/) {
  if (!consumer_open()) {
    DCHECK(!channel_endpoint_);
    return;
  }

  Disconnect();
}

void RemoteConsumerDataPipeImpl::EnsureBuffer() {
  DCHECK(producer_open());
  if (buffer_)
    return;
  buffer_.reset(static_cast<char*>(
      base::AlignedAlloc(capacity_num_bytes(),
                         GetConfiguration().data_pipe_buffer_alignment_bytes)));
}

void RemoteConsumerDataPipeImpl::DestroyBuffer() {
#ifndef NDEBUG
  // Scribble on the buffer to help detect use-after-frees. (This also helps the
  // unit test detect certain bugs without needing ASAN or similar.)
  if (buffer_)
    memset(buffer_.get(), 0xcd, capacity_num_bytes());
#endif
  buffer_.reset();
}

void RemoteConsumerDataPipeImpl::Disconnect() {
  DCHECK(consumer_open());
  DCHECK(channel_endpoint_);
  SetConsumerClosed();
  channel_endpoint_->DetachFromClient();
  channel_endpoint_ = nullptr;
  if (!producer_in_two_phase_write())
    DestroyBuffer();
}

}  // namespace system
}  // namespace mojo
