// Copyright 2013 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/data_pipe_consumer_dispatcher.h"

#include <utility>

#include "base/logging.h"
#include "mojo/edk/system/data_pipe.h"
#include "mojo/edk/system/memory.h"
#include "mojo/edk/system/options_validation.h"

using mojo::platform::ScopedPlatformHandle;
using mojo::util::MutexLocker;
using mojo::util::RefPtr;

namespace mojo {
namespace system {

// static
constexpr MojoHandleRights DataPipeConsumerDispatcher::kDefaultHandleRights;

void DataPipeConsumerDispatcher::Init(RefPtr<DataPipe>&& data_pipe) {
  DCHECK(data_pipe);
  data_pipe_ = std::move(data_pipe);
}

Dispatcher::Type DataPipeConsumerDispatcher::GetType() const {
  return Type::DATA_PIPE_CONSUMER;
}

bool DataPipeConsumerDispatcher::SupportsEntrypointClass(
    EntrypointClass entrypoint_class) const {
  return (entrypoint_class == EntrypointClass::NONE ||
          entrypoint_class == EntrypointClass::DATA_PIPE_CONSUMER);
}

// static
RefPtr<DataPipeConsumerDispatcher> DataPipeConsumerDispatcher::Deserialize(
    Channel* channel,
    const void* source,
    size_t size) {
  RefPtr<DataPipe> data_pipe;
  if (!DataPipe::ConsumerDeserialize(channel, source, size, &data_pipe))
    return nullptr;
  DCHECK(data_pipe);

  auto dispatcher = DataPipeConsumerDispatcher::Create();
  dispatcher->Init(std::move(data_pipe));
  return dispatcher;
}

DataPipe* DataPipeConsumerDispatcher::GetDataPipeForTest() {
  MutexLocker locker(&mutex());
  return data_pipe_.get();
}

DataPipeConsumerDispatcher::DataPipeConsumerDispatcher() {
}

DataPipeConsumerDispatcher::~DataPipeConsumerDispatcher() {
  // |Close()|/|CloseImplNoLock()| should have taken care of the pipe.
  DCHECK(!data_pipe_);
}

void DataPipeConsumerDispatcher::CancelAllAwakablesNoLock() {
  mutex().AssertHeld();
  data_pipe_->ConsumerCancelAllAwakables();
}

void DataPipeConsumerDispatcher::CloseImplNoLock() {
  mutex().AssertHeld();
  data_pipe_->ConsumerClose();
  data_pipe_ = nullptr;
}

RefPtr<Dispatcher>
DataPipeConsumerDispatcher::CreateEquivalentDispatcherAndCloseImplNoLock(
    MessagePipe* /*message_pipe*/,
    unsigned /*port*/) {
  mutex().AssertHeld();

  CancelAllAwakablesNoLock();

  auto dispatcher = DataPipeConsumerDispatcher::Create();
  dispatcher->Init(std::move(data_pipe_));
  return dispatcher;
}

MojoResult DataPipeConsumerDispatcher::SetDataPipeConsumerOptionsImplNoLock(
    UserPointer<const MojoDataPipeConsumerOptions> options) {
  mutex().AssertHeld();

  // The default of 0 means 1 element (however big that is).
  uint32_t read_threshold_num_bytes = 0;
  if (!options.IsNull()) {
    UserOptionsReader<MojoDataPipeConsumerOptions> reader(options);
    if (!reader.is_valid())
      return MOJO_RESULT_INVALID_ARGUMENT;

    if (!OPTIONS_STRUCT_HAS_MEMBER(MojoDataPipeConsumerOptions,
                                   read_threshold_num_bytes, reader))
      return MOJO_RESULT_OK;

    read_threshold_num_bytes = reader.options().read_threshold_num_bytes;
  }

  return data_pipe_->ConsumerSetOptions(read_threshold_num_bytes);
}

MojoResult DataPipeConsumerDispatcher::GetDataPipeConsumerOptionsImplNoLock(
    UserPointer<MojoDataPipeConsumerOptions> options,
    uint32_t options_num_bytes) {
  mutex().AssertHeld();

  // Note: If/when |MojoDataPipeConsumerOptions| is extended beyond its initial
  // definition, more work will be necessary. (See the definition of
  // |MojoGetDataPipeConsumerOptions()| in mojo/public/c/system/data_pipe.h.)
  static_assert(sizeof(MojoDataPipeConsumerOptions) == 8u,
                "MojoDataPipeConsumerOptions has been extended!");

  if (options_num_bytes < sizeof(MojoDataPipeConsumerOptions))
    return MOJO_RESULT_INVALID_ARGUMENT;

  uint32_t read_threshold_num_bytes = 0;
  data_pipe_->ConsumerGetOptions(&read_threshold_num_bytes);
  MojoDataPipeConsumerOptions model_options = {
      sizeof(MojoDataPipeConsumerOptions),  // |struct_size|.
      read_threshold_num_bytes,             // |read_threshold_num_bytes|.
  };
  options.Put(model_options);
  return MOJO_RESULT_OK;
}

MojoResult DataPipeConsumerDispatcher::ReadDataImplNoLock(
    UserPointer<void> elements,
    UserPointer<uint32_t> num_bytes,
    MojoReadDataFlags flags) {
  mutex().AssertHeld();

  if ((flags & MOJO_READ_DATA_FLAG_DISCARD)) {
    // These flags are mutally exclusive.
    if ((flags & MOJO_READ_DATA_FLAG_QUERY) ||
        (flags & MOJO_READ_DATA_FLAG_PEEK))
      return MOJO_RESULT_INVALID_ARGUMENT;
    DVLOG_IF(2, !elements.IsNull())
        << "Discard mode: ignoring non-null |elements|";
    return data_pipe_->ConsumerDiscardData(
        num_bytes, (flags & MOJO_READ_DATA_FLAG_ALL_OR_NONE));
  }

  if ((flags & MOJO_READ_DATA_FLAG_QUERY)) {
    if ((flags & MOJO_READ_DATA_FLAG_PEEK))
      return MOJO_RESULT_INVALID_ARGUMENT;
    DCHECK(!(flags & MOJO_READ_DATA_FLAG_DISCARD));  // Handled above.
    DVLOG_IF(2, !elements.IsNull())
        << "Query mode: ignoring non-null |elements|";
    return data_pipe_->ConsumerQueryData(num_bytes);
  }

  return data_pipe_->ConsumerReadData(
      elements, num_bytes, !!(flags & MOJO_READ_DATA_FLAG_ALL_OR_NONE),
      !!(flags & MOJO_READ_DATA_FLAG_PEEK));
}

MojoResult DataPipeConsumerDispatcher::BeginReadDataImplNoLock(
    UserPointer<const void*> buffer,
    UserPointer<uint32_t> buffer_num_bytes,
    MojoReadDataFlags flags) {
  mutex().AssertHeld();

  // These flags may not be used in two-phase mode.
  if ((flags & MOJO_READ_DATA_FLAG_ALL_OR_NONE) ||
      (flags & MOJO_READ_DATA_FLAG_DISCARD) ||
      (flags & MOJO_READ_DATA_FLAG_QUERY) || (flags & MOJO_READ_DATA_FLAG_PEEK))
    return MOJO_RESULT_INVALID_ARGUMENT;

  return data_pipe_->ConsumerBeginReadData(buffer, buffer_num_bytes);
}

MojoResult DataPipeConsumerDispatcher::EndReadDataImplNoLock(
    uint32_t num_bytes_read) {
  mutex().AssertHeld();

  return data_pipe_->ConsumerEndReadData(num_bytes_read);
}

HandleSignalsState DataPipeConsumerDispatcher::GetHandleSignalsStateImplNoLock()
    const {
  mutex().AssertHeld();
  return data_pipe_->ConsumerGetHandleSignalsState();
}

MojoResult DataPipeConsumerDispatcher::AddAwakableImplNoLock(
    Awakable* awakable,
    MojoHandleSignals signals,
    uint32_t context,
    HandleSignalsState* signals_state) {
  mutex().AssertHeld();
  return data_pipe_->ConsumerAddAwakable(awakable, signals, context,
                                         signals_state);
}

void DataPipeConsumerDispatcher::RemoveAwakableImplNoLock(
    Awakable* awakable,
    HandleSignalsState* signals_state) {
  mutex().AssertHeld();
  data_pipe_->ConsumerRemoveAwakable(awakable, signals_state);
}

void DataPipeConsumerDispatcher::StartSerializeImplNoLock(
    Channel* channel,
    size_t* max_size,
    size_t* max_platform_handles) {
  AssertHasOneRef();  // Only one ref => no need to take the lock.
  data_pipe_->ConsumerStartSerialize(channel, max_size, max_platform_handles);
}

bool DataPipeConsumerDispatcher::EndSerializeAndCloseImplNoLock(
    Channel* channel,
    void* destination,
    size_t* actual_size,
    std::vector<ScopedPlatformHandle>* platform_handles) {
  AssertHasOneRef();  // Only one ref => no need to take the lock.

  bool rv = data_pipe_->ConsumerEndSerialize(channel, destination, actual_size,
                                             platform_handles);
  data_pipe_ = nullptr;
  return rv;
}

bool DataPipeConsumerDispatcher::IsBusyNoLock() const {
  mutex().AssertHeld();
  return data_pipe_->ConsumerIsBusy();
}

}  // namespace system
}  // namespace mojo
