| 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..78ac36e056a7093caa91451a0faa7190e469301c
|
| --- /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 edk {
|
| +
|
| +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,
|
| + ScopedPlatformHandle channel_handle,
|
| + ScopedPlatformHandle shared_memory_handle,
|
| + size_t shared_memory_size,
|
| + void* destination,
|
| + size_t* actual_size,
|
| + 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);
|
| +}
|
| +
|
| +ScopedPlatformHandle DataPipe::Deserialize(
|
| + const void* source,
|
| + size_t size,
|
| + PlatformHandleVector* platform_handles,
|
| + MojoCreateDataPipeOptions* options,
|
| + ScopedPlatformHandle* shared_memory_handle,
|
| + size_t* shared_memory_size) {
|
| + if (size != sizeof(SerializedDataPipeHandleDispatcher)) {
|
| + LOG(ERROR) << "Invalid serialized platform handle dispatcher (bad size)";
|
| + return 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.
|
| + 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 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 ScopedPlatformHandle();
|
| + }
|
| +
|
| + PlatformHandle temp_shared_memory_handle;
|
| + std::swap(temp_shared_memory_handle,
|
| + (*platform_handles)[serialization->shared_memory_handle_index]);
|
| + *shared_memory_handle =
|
| + ScopedPlatformHandle(temp_shared_memory_handle);
|
| + }
|
| + }
|
| +
|
| + size -= sizeof(SerializedDataPipeHandleDispatcher);
|
| +
|
| + return ScopedPlatformHandle(platform_handle);
|
| +}
|
| +
|
| +} // namespace edk
|
| +} // namespace mojo
|
|
|