| Index: mojo/edk/system/data_pipe.cc
 | 
| diff --git a/mojo/edk/system/data_pipe.cc b/mojo/edk/system/data_pipe.cc
 | 
| new file mode 100644
 | 
| index 0000000000000000000000000000000000000000..886d229e349ddd9188e4c7771a1aa3c11119b7dd
 | 
| --- /dev/null
 | 
| +++ b/mojo/edk/system/data_pipe.cc
 | 
| @@ -0,0 +1,203 @@
 | 
| +// 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.h"
 | 
| +
 | 
| +#include <string.h>
 | 
| +
 | 
| +#include "mojo/edk/system/configuration.h"
 | 
| +#include "mojo/edk/system/options_validation.h"
 | 
| +#include "mojo/edk/system/raw_channel.h"
 | 
| +#include "mojo/edk/system/transport_data.h"
 | 
| +
 | 
| +namespace mojo {
 | 
| +namespace system {
 | 
| +
 | 
| +namespace {
 | 
| +
 | 
| +const size_t kInvalidDataPipeHandleIndex = static_cast<size_t>(-1);
 | 
| +
 | 
| +struct MOJO_ALIGNAS(8) SerializedDataPipeHandleDispatcher {
 | 
| +  size_t platform_handle_index;  // (Or |kInvalidDataPipeHandleIndex|.)
 | 
| +
 | 
| +  // These are from MojoCreateDataPipeOptions
 | 
| +  MojoCreateDataPipeOptionsFlags flags;
 | 
| +  uint32_t element_num_bytes;
 | 
| +  uint32_t capacity_num_bytes;
 | 
| +
 | 
| +  size_t shared_memory_handle_index;  // (Or |kInvalidDataPipeHandleIndex|.)
 | 
| +  uint32_t shared_memory_size;
 | 
| +};
 | 
| +
 | 
| +}  // namespace
 | 
| +
 | 
| +MojoCreateDataPipeOptions DataPipe::GetDefaultCreateOptions() {
 | 
| +  MojoCreateDataPipeOptions result = {
 | 
| +      static_cast<uint32_t>(sizeof(MojoCreateDataPipeOptions)),
 | 
| +      MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE,
 | 
| +      1u,
 | 
| +      static_cast<uint32_t>(
 | 
| +          GetConfiguration().default_data_pipe_capacity_bytes)};
 | 
| +  return result;
 | 
| +}
 | 
| +
 | 
| +MojoResult DataPipe::ValidateCreateOptions(
 | 
| +    UserPointer<const MojoCreateDataPipeOptions> in_options,
 | 
| +    MojoCreateDataPipeOptions* out_options) {
 | 
| +  const MojoCreateDataPipeOptionsFlags kKnownFlags =
 | 
| +      MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE;
 | 
| +
 | 
| +  *out_options = GetDefaultCreateOptions();
 | 
| +  if (in_options.IsNull())
 | 
| +    return MOJO_RESULT_OK;
 | 
| +
 | 
| +  UserOptionsReader<MojoCreateDataPipeOptions> reader(in_options);
 | 
| +  if (!reader.is_valid())
 | 
| +    return MOJO_RESULT_INVALID_ARGUMENT;
 | 
| +
 | 
| +  if (!OPTIONS_STRUCT_HAS_MEMBER(MojoCreateDataPipeOptions, flags, reader))
 | 
| +    return MOJO_RESULT_OK;
 | 
| +  if ((reader.options().flags & ~kKnownFlags))
 | 
| +    return MOJO_RESULT_UNIMPLEMENTED;
 | 
| +  out_options->flags = reader.options().flags;
 | 
| +
 | 
| +  // Checks for fields beyond |flags|:
 | 
| +
 | 
| +  if (!OPTIONS_STRUCT_HAS_MEMBER(MojoCreateDataPipeOptions, element_num_bytes,
 | 
| +                                 reader))
 | 
| +    return MOJO_RESULT_OK;
 | 
| +  if (reader.options().element_num_bytes == 0)
 | 
| +    return MOJO_RESULT_INVALID_ARGUMENT;
 | 
| +  out_options->element_num_bytes = reader.options().element_num_bytes;
 | 
| +
 | 
| +  if (!OPTIONS_STRUCT_HAS_MEMBER(MojoCreateDataPipeOptions, capacity_num_bytes,
 | 
| +                                 reader) ||
 | 
| +      reader.options().capacity_num_bytes == 0) {
 | 
| +    // Round the default capacity down to a multiple of the element size (but at
 | 
| +    // least one element).
 | 
| +    size_t default_data_pipe_capacity_bytes =
 | 
| +        GetConfiguration().default_data_pipe_capacity_bytes;
 | 
| +    out_options->capacity_num_bytes =
 | 
| +        std::max(static_cast<uint32_t>(default_data_pipe_capacity_bytes -
 | 
| +                                       (default_data_pipe_capacity_bytes %
 | 
| +                                        out_options->element_num_bytes)),
 | 
| +                 out_options->element_num_bytes);
 | 
| +    return MOJO_RESULT_OK;
 | 
| +  }
 | 
| +  if (reader.options().capacity_num_bytes % out_options->element_num_bytes != 0)
 | 
| +    return MOJO_RESULT_INVALID_ARGUMENT;
 | 
| +  if (reader.options().capacity_num_bytes >
 | 
| +      GetConfiguration().max_data_pipe_capacity_bytes)
 | 
| +    return MOJO_RESULT_RESOURCE_EXHAUSTED;
 | 
| +  out_options->capacity_num_bytes = reader.options().capacity_num_bytes;
 | 
| +
 | 
| +  return MOJO_RESULT_OK;
 | 
| +}
 | 
| +
 | 
| +void DataPipe::StartSerialize(bool have_channel_handle,
 | 
| +                              bool have_shared_memory,
 | 
| +                              size_t* max_size,
 | 
| +                              size_t* max_platform_handles) {
 | 
| +  *max_size = sizeof(SerializedDataPipeHandleDispatcher);
 | 
| +  *max_platform_handles = 0;
 | 
| +  if (have_channel_handle)
 | 
| +    (*max_platform_handles)++;
 | 
| +  if (have_shared_memory)
 | 
| +    (*max_platform_handles)++;
 | 
| +  DCHECK_LE(*max_size, TransportData::kMaxSerializedDispatcherSize);
 | 
| +}
 | 
| +
 | 
| +void DataPipe::EndSerialize(const MojoCreateDataPipeOptions& options,
 | 
| +                            embedder::ScopedPlatformHandle channel_handle,
 | 
| +                            embedder::ScopedPlatformHandle shared_memory_handle,
 | 
| +                            size_t shared_memory_size,
 | 
| +                            void* destination,
 | 
| +                            size_t* actual_size,
 | 
| +                            embedder::PlatformHandleVector* platform_handles) {
 | 
| +  SerializedDataPipeHandleDispatcher* serialization =
 | 
| +      static_cast<SerializedDataPipeHandleDispatcher*>(destination);
 | 
| +  if (channel_handle.is_valid()) {
 | 
| +    serialization->platform_handle_index = platform_handles->size();
 | 
| +    platform_handles->push_back(channel_handle.release());
 | 
| +  } else {
 | 
| +    serialization->platform_handle_index = kInvalidDataPipeHandleIndex;
 | 
| +  }
 | 
| +
 | 
| +  serialization->flags = options.flags;
 | 
| +  serialization->element_num_bytes = options.element_num_bytes;
 | 
| +  serialization->capacity_num_bytes = options.capacity_num_bytes;
 | 
| +
 | 
| +  serialization->shared_memory_size = shared_memory_size;
 | 
| +  if (serialization->shared_memory_size) {
 | 
| +    serialization->shared_memory_handle_index = platform_handles->size();
 | 
| +    platform_handles->push_back(shared_memory_handle.release());
 | 
| +  }
 | 
| +
 | 
| +  *actual_size = sizeof(SerializedDataPipeHandleDispatcher);
 | 
| +}
 | 
| +
 | 
| +embedder::ScopedPlatformHandle DataPipe::Deserialize(
 | 
| +    const void* source,
 | 
| +    size_t size,
 | 
| +    embedder::PlatformHandleVector* platform_handles,
 | 
| +    MojoCreateDataPipeOptions* options,
 | 
| +    embedder::ScopedPlatformHandle* shared_memory_handle,
 | 
| +    size_t* shared_memory_size) {
 | 
| +  if (size != sizeof(SerializedDataPipeHandleDispatcher)) {
 | 
| +    LOG(ERROR) << "Invalid serialized platform handle dispatcher (bad size)";
 | 
| +    return embedder::ScopedPlatformHandle();
 | 
| +  }
 | 
| +
 | 
| +  const SerializedDataPipeHandleDispatcher* serialization =
 | 
| +      static_cast<const SerializedDataPipeHandleDispatcher*>(source);
 | 
| +  size_t platform_handle_index = serialization->platform_handle_index;
 | 
| +
 | 
| +  // Starts off invalid, which is what we want.
 | 
| +  embedder::PlatformHandle platform_handle;
 | 
| +  if (platform_handle_index != kInvalidDataPipeHandleIndex) {
 | 
| +    if (!platform_handles ||
 | 
| +        platform_handle_index >= platform_handles->size()) {
 | 
| +      LOG(ERROR)
 | 
| +          << "Invalid serialized platform handle dispatcher (missing handles)";
 | 
| +      return embedder::ScopedPlatformHandle();
 | 
| +    }
 | 
| +
 | 
| +    // We take ownership of the handle, so we have to invalidate the one in
 | 
| +    // |platform_handles|.
 | 
| +    std::swap(platform_handle, (*platform_handles)[platform_handle_index]);
 | 
| +  }
 | 
| +
 | 
| +  options->struct_size = sizeof(MojoCreateDataPipeOptions);
 | 
| +  options->flags = serialization->flags;
 | 
| +  options->element_num_bytes = serialization->element_num_bytes;
 | 
| +  options->capacity_num_bytes = serialization->capacity_num_bytes;
 | 
| +
 | 
| +  if (shared_memory_size) {
 | 
| +    *shared_memory_size = serialization->shared_memory_size;
 | 
| +    if (*shared_memory_size) {
 | 
| +      DCHECK(serialization->shared_memory_handle_index !=
 | 
| +             kInvalidDataPipeHandleIndex);
 | 
| +      if (!serialization->shared_memory_handle_index ||
 | 
| +          serialization->shared_memory_handle_index >=
 | 
| +              platform_handles->size()) {
 | 
| +        LOG(ERROR) << "Invalid serialized platform handle dispatcher "
 | 
| +                   << "(missing handles)";
 | 
| +        return embedder::ScopedPlatformHandle();
 | 
| +      }
 | 
| +
 | 
| +      embedder::PlatformHandle temp_shared_memory_handle;
 | 
| +      std::swap(temp_shared_memory_handle,
 | 
| +                (*platform_handles)[serialization->shared_memory_handle_index]);
 | 
| +      *shared_memory_handle =
 | 
| +          embedder::ScopedPlatformHandle(temp_shared_memory_handle);
 | 
| +    }
 | 
| +  }
 | 
| +
 | 
| +  size -= sizeof(SerializedDataPipeHandleDispatcher);
 | 
| +
 | 
| +  return embedder::ScopedPlatformHandle(platform_handle);
 | 
| +}
 | 
| +
 | 
| +}  // namespace system
 | 
| +}  // namespace mojo
 | 
| 
 |