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

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::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() {
  mutex().AssertHeld();

  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
