| OLD | NEW | 
| (Empty) |  | 
 |    1 // Copyright 2013 The Chromium Authors. All rights reserved. | 
 |    2 // Use of this source code is governed by a BSD-style license that can be | 
 |    3 // found in the LICENSE file. | 
 |    4  | 
 |    5 #include "mojo/edk/system/data_pipe.h" | 
 |    6  | 
 |    7 #include <string.h> | 
 |    8  | 
 |    9 #include "mojo/edk/system/configuration.h" | 
 |   10 #include "mojo/edk/system/options_validation.h" | 
 |   11 #include "mojo/edk/system/raw_channel.h" | 
 |   12 #include "mojo/edk/system/transport_data.h" | 
 |   13  | 
 |   14 namespace mojo { | 
 |   15 namespace system { | 
 |   16  | 
 |   17 namespace { | 
 |   18  | 
 |   19 const size_t kInvalidDataPipeHandleIndex = static_cast<size_t>(-1); | 
 |   20  | 
 |   21 struct MOJO_ALIGNAS(8) SerializedDataPipeHandleDispatcher { | 
 |   22   size_t platform_handle_index;  // (Or |kInvalidDataPipeHandleIndex|.) | 
 |   23  | 
 |   24   // These are from MojoCreateDataPipeOptions | 
 |   25   MojoCreateDataPipeOptionsFlags flags; | 
 |   26   uint32_t element_num_bytes; | 
 |   27   uint32_t capacity_num_bytes; | 
 |   28  | 
 |   29   size_t shared_memory_handle_index;  // (Or |kInvalidDataPipeHandleIndex|.) | 
 |   30   uint32_t shared_memory_size; | 
 |   31 }; | 
 |   32  | 
 |   33 }  // namespace | 
 |   34  | 
 |   35 MojoCreateDataPipeOptions DataPipe::GetDefaultCreateOptions() { | 
 |   36   MojoCreateDataPipeOptions result = { | 
 |   37       static_cast<uint32_t>(sizeof(MojoCreateDataPipeOptions)), | 
 |   38       MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, | 
 |   39       1u, | 
 |   40       static_cast<uint32_t>( | 
 |   41           GetConfiguration().default_data_pipe_capacity_bytes)}; | 
 |   42   return result; | 
 |   43 } | 
 |   44  | 
 |   45 MojoResult DataPipe::ValidateCreateOptions( | 
 |   46     UserPointer<const MojoCreateDataPipeOptions> in_options, | 
 |   47     MojoCreateDataPipeOptions* out_options) { | 
 |   48   const MojoCreateDataPipeOptionsFlags kKnownFlags = | 
 |   49       MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE; | 
 |   50  | 
 |   51   *out_options = GetDefaultCreateOptions(); | 
 |   52   if (in_options.IsNull()) | 
 |   53     return MOJO_RESULT_OK; | 
 |   54  | 
 |   55   UserOptionsReader<MojoCreateDataPipeOptions> reader(in_options); | 
 |   56   if (!reader.is_valid()) | 
 |   57     return MOJO_RESULT_INVALID_ARGUMENT; | 
 |   58  | 
 |   59   if (!OPTIONS_STRUCT_HAS_MEMBER(MojoCreateDataPipeOptions, flags, reader)) | 
 |   60     return MOJO_RESULT_OK; | 
 |   61   if ((reader.options().flags & ~kKnownFlags)) | 
 |   62     return MOJO_RESULT_UNIMPLEMENTED; | 
 |   63   out_options->flags = reader.options().flags; | 
 |   64  | 
 |   65   // Checks for fields beyond |flags|: | 
 |   66  | 
 |   67   if (!OPTIONS_STRUCT_HAS_MEMBER(MojoCreateDataPipeOptions, element_num_bytes, | 
 |   68                                  reader)) | 
 |   69     return MOJO_RESULT_OK; | 
 |   70   if (reader.options().element_num_bytes == 0) | 
 |   71     return MOJO_RESULT_INVALID_ARGUMENT; | 
 |   72   out_options->element_num_bytes = reader.options().element_num_bytes; | 
 |   73  | 
 |   74   if (!OPTIONS_STRUCT_HAS_MEMBER(MojoCreateDataPipeOptions, capacity_num_bytes, | 
 |   75                                  reader) || | 
 |   76       reader.options().capacity_num_bytes == 0) { | 
 |   77     // Round the default capacity down to a multiple of the element size (but at | 
 |   78     // least one element). | 
 |   79     size_t default_data_pipe_capacity_bytes = | 
 |   80         GetConfiguration().default_data_pipe_capacity_bytes; | 
 |   81     out_options->capacity_num_bytes = | 
 |   82         std::max(static_cast<uint32_t>(default_data_pipe_capacity_bytes - | 
 |   83                                        (default_data_pipe_capacity_bytes % | 
 |   84                                         out_options->element_num_bytes)), | 
 |   85                  out_options->element_num_bytes); | 
 |   86     return MOJO_RESULT_OK; | 
 |   87   } | 
 |   88   if (reader.options().capacity_num_bytes % out_options->element_num_bytes != 0) | 
 |   89     return MOJO_RESULT_INVALID_ARGUMENT; | 
 |   90   if (reader.options().capacity_num_bytes > | 
 |   91       GetConfiguration().max_data_pipe_capacity_bytes) | 
 |   92     return MOJO_RESULT_RESOURCE_EXHAUSTED; | 
 |   93   out_options->capacity_num_bytes = reader.options().capacity_num_bytes; | 
 |   94  | 
 |   95   return MOJO_RESULT_OK; | 
 |   96 } | 
 |   97  | 
 |   98 void DataPipe::StartSerialize(bool have_channel_handle, | 
 |   99                               bool have_shared_memory, | 
 |  100                               size_t* max_size, | 
 |  101                               size_t* max_platform_handles) { | 
 |  102   *max_size = sizeof(SerializedDataPipeHandleDispatcher); | 
 |  103   *max_platform_handles = 0; | 
 |  104   if (have_channel_handle) | 
 |  105     (*max_platform_handles)++; | 
 |  106   if (have_shared_memory) | 
 |  107     (*max_platform_handles)++; | 
 |  108   DCHECK_LE(*max_size, TransportData::kMaxSerializedDispatcherSize); | 
 |  109 } | 
 |  110  | 
 |  111 void DataPipe::EndSerialize(const MojoCreateDataPipeOptions& options, | 
 |  112                             embedder::ScopedPlatformHandle channel_handle, | 
 |  113                             embedder::ScopedPlatformHandle shared_memory_handle, | 
 |  114                             size_t shared_memory_size, | 
 |  115                             void* destination, | 
 |  116                             size_t* actual_size, | 
 |  117                             embedder::PlatformHandleVector* platform_handles) { | 
 |  118   SerializedDataPipeHandleDispatcher* serialization = | 
 |  119       static_cast<SerializedDataPipeHandleDispatcher*>(destination); | 
 |  120   if (channel_handle.is_valid()) { | 
 |  121     serialization->platform_handle_index = platform_handles->size(); | 
 |  122     platform_handles->push_back(channel_handle.release()); | 
 |  123   } else { | 
 |  124     serialization->platform_handle_index = kInvalidDataPipeHandleIndex; | 
 |  125   } | 
 |  126  | 
 |  127   serialization->flags = options.flags; | 
 |  128   serialization->element_num_bytes = options.element_num_bytes; | 
 |  129   serialization->capacity_num_bytes = options.capacity_num_bytes; | 
 |  130  | 
 |  131   serialization->shared_memory_size = shared_memory_size; | 
 |  132   if (serialization->shared_memory_size) { | 
 |  133     serialization->shared_memory_handle_index = platform_handles->size(); | 
 |  134     platform_handles->push_back(shared_memory_handle.release()); | 
 |  135   } | 
 |  136  | 
 |  137   *actual_size = sizeof(SerializedDataPipeHandleDispatcher); | 
 |  138 } | 
 |  139  | 
 |  140 embedder::ScopedPlatformHandle DataPipe::Deserialize( | 
 |  141     const void* source, | 
 |  142     size_t size, | 
 |  143     embedder::PlatformHandleVector* platform_handles, | 
 |  144     MojoCreateDataPipeOptions* options, | 
 |  145     embedder::ScopedPlatformHandle* shared_memory_handle, | 
 |  146     size_t* shared_memory_size) { | 
 |  147   if (size != sizeof(SerializedDataPipeHandleDispatcher)) { | 
 |  148     LOG(ERROR) << "Invalid serialized platform handle dispatcher (bad size)"; | 
 |  149     return embedder::ScopedPlatformHandle(); | 
 |  150   } | 
 |  151  | 
 |  152   const SerializedDataPipeHandleDispatcher* serialization = | 
 |  153       static_cast<const SerializedDataPipeHandleDispatcher*>(source); | 
 |  154   size_t platform_handle_index = serialization->platform_handle_index; | 
 |  155  | 
 |  156   // Starts off invalid, which is what we want. | 
 |  157   embedder::PlatformHandle platform_handle; | 
 |  158   if (platform_handle_index != kInvalidDataPipeHandleIndex) { | 
 |  159     if (!platform_handles || | 
 |  160         platform_handle_index >= platform_handles->size()) { | 
 |  161       LOG(ERROR) | 
 |  162           << "Invalid serialized platform handle dispatcher (missing handles)"; | 
 |  163       return embedder::ScopedPlatformHandle(); | 
 |  164     } | 
 |  165  | 
 |  166     // We take ownership of the handle, so we have to invalidate the one in | 
 |  167     // |platform_handles|. | 
 |  168     std::swap(platform_handle, (*platform_handles)[platform_handle_index]); | 
 |  169   } | 
 |  170  | 
 |  171   options->struct_size = sizeof(MojoCreateDataPipeOptions); | 
 |  172   options->flags = serialization->flags; | 
 |  173   options->element_num_bytes = serialization->element_num_bytes; | 
 |  174   options->capacity_num_bytes = serialization->capacity_num_bytes; | 
 |  175  | 
 |  176   if (shared_memory_size) { | 
 |  177     *shared_memory_size = serialization->shared_memory_size; | 
 |  178     if (*shared_memory_size) { | 
 |  179       DCHECK(serialization->shared_memory_handle_index != | 
 |  180              kInvalidDataPipeHandleIndex); | 
 |  181       if (!serialization->shared_memory_handle_index || | 
 |  182           serialization->shared_memory_handle_index >= | 
 |  183               platform_handles->size()) { | 
 |  184         LOG(ERROR) << "Invalid serialized platform handle dispatcher " | 
 |  185                    << "(missing handles)"; | 
 |  186         return embedder::ScopedPlatformHandle(); | 
 |  187       } | 
 |  188  | 
 |  189       embedder::PlatformHandle temp_shared_memory_handle; | 
 |  190       std::swap(temp_shared_memory_handle, | 
 |  191                 (*platform_handles)[serialization->shared_memory_handle_index]); | 
 |  192       *shared_memory_handle = | 
 |  193           embedder::ScopedPlatformHandle(temp_shared_memory_handle); | 
 |  194     } | 
 |  195   } | 
 |  196  | 
 |  197   size -= sizeof(SerializedDataPipeHandleDispatcher); | 
 |  198  | 
 |  199   return embedder::ScopedPlatformHandle(platform_handle); | 
 |  200 } | 
 |  201  | 
 |  202 }  // namespace system | 
 |  203 }  // namespace mojo | 
| OLD | NEW |