Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "mojo/edk/system/shared_buffer_dispatcher.h" | 5 #include "mojo/edk/system/shared_buffer_dispatcher.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 #include <stdint.h> | 8 #include <stdint.h> |
| 9 | 9 |
| 10 #include <algorithm> | |
| 11 #include <limits> | 10 #include <limits> |
| 12 #include <utility> | 11 #include <utility> |
| 13 | 12 |
| 14 #include "base/logging.h" | 13 #include "base/logging.h" |
| 15 #include "base/memory/scoped_ptr.h" | 14 #include "base/memory/scoped_ptr.h" |
| 16 #include "mojo/edk/embedder/embedder_internal.h" | 15 #include "mojo/edk/embedder/embedder_internal.h" |
| 17 #include "mojo/edk/embedder/platform_support.h" | 16 #include "mojo/edk/embedder/platform_support.h" |
| 18 #include "mojo/edk/system/configuration.h" | 17 #include "mojo/edk/system/configuration.h" |
| 19 #include "mojo/edk/system/options_validation.h" | 18 #include "mojo/edk/system/options_validation.h" |
| 20 #include "mojo/public/c/system/macros.h" | 19 #include "mojo/public/c/system/macros.h" |
| 21 | 20 |
| 22 namespace mojo { | 21 namespace mojo { |
| 23 namespace edk { | 22 namespace edk { |
| 24 | 23 |
| 25 namespace { | 24 namespace { |
| 26 | 25 |
| 27 struct MOJO_ALIGNAS(8) SerializedSharedBufferDispatcher { | 26 struct MOJO_ALIGNAS(8) SerializedSharedBufferDispatcher { |
| 28 MOJO_ALIGNAS(4) uint32_t num_bytes; | 27 size_t num_bytes; |
|
Anand Mistry (off Chromium)
2016/01/28 02:26:24
Please don't use size_t in serialised messages.
| |
| 29 MOJO_ALIGNAS(4) uint32_t platform_handle_index; | |
| 30 }; | 28 }; |
| 31 | 29 |
| 32 } // namespace | 30 } // namespace |
| 33 | 31 |
| 34 // static | 32 // static |
| 35 const MojoCreateSharedBufferOptions | 33 const MojoCreateSharedBufferOptions |
| 36 SharedBufferDispatcher::kDefaultCreateOptions = { | 34 SharedBufferDispatcher::kDefaultCreateOptions = { |
| 37 static_cast<uint32_t>(sizeof(MojoCreateSharedBufferOptions)), | 35 static_cast<uint32_t>(sizeof(MojoCreateSharedBufferOptions)), |
| 38 MOJO_CREATE_SHARED_BUFFER_OPTIONS_FLAG_NONE}; | 36 MOJO_CREATE_SHARED_BUFFER_OPTIONS_FLAG_NONE}; |
| 39 | 37 |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 78 | 76 |
| 79 scoped_refptr<PlatformSharedBuffer> shared_buffer( | 77 scoped_refptr<PlatformSharedBuffer> shared_buffer( |
| 80 platform_support->CreateSharedBuffer(static_cast<size_t>(num_bytes))); | 78 platform_support->CreateSharedBuffer(static_cast<size_t>(num_bytes))); |
| 81 if (!shared_buffer) | 79 if (!shared_buffer) |
| 82 return MOJO_RESULT_RESOURCE_EXHAUSTED; | 80 return MOJO_RESULT_RESOURCE_EXHAUSTED; |
| 83 | 81 |
| 84 *result = CreateInternal(std::move(shared_buffer)); | 82 *result = CreateInternal(std::move(shared_buffer)); |
| 85 return MOJO_RESULT_OK; | 83 return MOJO_RESULT_OK; |
| 86 } | 84 } |
| 87 | 85 |
| 88 Dispatcher::Type SharedBufferDispatcher::GetType() const { | |
| 89 return Type::SHARED_BUFFER; | |
| 90 } | |
| 91 | |
| 92 // static | 86 // static |
| 93 scoped_refptr<SharedBufferDispatcher> SharedBufferDispatcher::Deserialize( | 87 scoped_refptr<SharedBufferDispatcher> SharedBufferDispatcher::Deserialize( |
| 94 const void* source, | 88 const void* bytes, |
| 95 size_t size, | 89 size_t num_bytes, |
| 96 PlatformHandleVector* platform_handles) { | 90 const ports::PortName* ports, |
| 97 | 91 size_t num_ports, |
| 98 if (size != sizeof(SerializedSharedBufferDispatcher)) { | 92 PlatformHandle* platform_handles, |
| 93 size_t num_platform_handles) { | |
| 94 if (num_bytes != sizeof(SerializedSharedBufferDispatcher)) { | |
| 99 LOG(ERROR) << "Invalid serialized shared buffer dispatcher (bad size)"; | 95 LOG(ERROR) << "Invalid serialized shared buffer dispatcher (bad size)"; |
| 100 return nullptr; | 96 return nullptr; |
| 101 } | 97 } |
| 102 | 98 |
| 103 const SerializedSharedBufferDispatcher* serialization = | 99 const SerializedSharedBufferDispatcher* serialization = |
| 104 static_cast<const SerializedSharedBufferDispatcher*>(source); | 100 static_cast<const SerializedSharedBufferDispatcher*>(bytes); |
| 105 size_t num_bytes = serialization->num_bytes; | 101 if (!serialization->num_bytes) { |
| 106 size_t platform_handle_index = serialization->platform_handle_index; | |
| 107 | |
| 108 if (!num_bytes) { | |
| 109 LOG(ERROR) | 102 LOG(ERROR) |
| 110 << "Invalid serialized shared buffer dispatcher (invalid num_bytes)"; | 103 << "Invalid serialized shared buffer dispatcher (invalid num_bytes)"; |
| 111 return nullptr; | 104 return nullptr; |
| 112 } | 105 } |
| 113 | 106 |
| 114 if (!platform_handles || platform_handle_index >= platform_handles->size()) { | 107 if (!platform_handles || num_platform_handles != 1 || num_ports) { |
| 115 LOG(ERROR) | 108 LOG(ERROR) |
| 116 << "Invalid serialized shared buffer dispatcher (missing handles)"; | 109 << "Invalid serialized shared buffer dispatcher (missing handles)"; |
| 117 return nullptr; | 110 return nullptr; |
| 118 } | 111 } |
| 119 | 112 |
| 120 // Starts off invalid, which is what we want. | 113 // Starts off invalid, which is what we want. |
| 121 PlatformHandle platform_handle; | 114 PlatformHandle platform_handle; |
| 122 // We take ownership of the handle, so we have to invalidate the one in | 115 // We take ownership of the handle, so we have to invalidate the one in |
| 123 // |platform_handles|. | 116 // |platform_handles|. |
| 124 std::swap(platform_handle, (*platform_handles)[platform_handle_index]); | 117 std::swap(platform_handle, *platform_handles); |
| 125 | 118 |
| 126 // Wrapping |platform_handle| in a |ScopedPlatformHandle| means that it'll be | 119 // Wrapping |platform_handle| in a |ScopedPlatformHandle| means that it'll be |
| 127 // closed even if creation fails. | 120 // closed even if creation fails. |
| 128 scoped_refptr<PlatformSharedBuffer> shared_buffer( | 121 scoped_refptr<PlatformSharedBuffer> shared_buffer( |
| 129 internal::g_platform_support->CreateSharedBufferFromHandle( | 122 internal::g_platform_support->CreateSharedBufferFromHandle( |
| 130 num_bytes, ScopedPlatformHandle(platform_handle))); | 123 serialization->num_bytes, ScopedPlatformHandle(platform_handle))); |
| 131 if (!shared_buffer) { | 124 if (!shared_buffer) { |
| 132 LOG(ERROR) | 125 LOG(ERROR) |
| 133 << "Invalid serialized shared buffer dispatcher (invalid num_bytes?)"; | 126 << "Invalid serialized shared buffer dispatcher (invalid num_bytes?)"; |
| 134 return nullptr; | 127 return nullptr; |
| 135 } | 128 } |
| 136 | 129 |
| 137 return CreateInternal(std::move(shared_buffer)); | 130 return CreateInternal(std::move(shared_buffer)); |
| 138 } | 131 } |
| 139 | 132 |
| 140 SharedBufferDispatcher::SharedBufferDispatcher( | 133 Dispatcher::Type SharedBufferDispatcher::GetType() const { |
| 141 scoped_refptr<PlatformSharedBuffer> shared_buffer) | 134 return Type::SHARED_BUFFER; |
| 142 : shared_buffer_(shared_buffer) { | |
| 143 DCHECK(shared_buffer_); | |
| 144 } | 135 } |
| 145 | 136 |
| 146 SharedBufferDispatcher::~SharedBufferDispatcher() { | 137 MojoResult SharedBufferDispatcher::Close() { |
| 147 } | 138 base::AutoLock lock(lock_); |
| 148 | 139 if (!shared_buffer_ || in_transit_) |
| 149 // static | |
| 150 MojoResult SharedBufferDispatcher::ValidateDuplicateOptions( | |
| 151 const MojoDuplicateBufferHandleOptions* in_options, | |
| 152 MojoDuplicateBufferHandleOptions* out_options) { | |
| 153 const MojoDuplicateBufferHandleOptionsFlags kKnownFlags = | |
| 154 MOJO_DUPLICATE_BUFFER_HANDLE_OPTIONS_FLAG_NONE; | |
| 155 static const MojoDuplicateBufferHandleOptions kDefaultOptions = { | |
| 156 static_cast<uint32_t>(sizeof(MojoDuplicateBufferHandleOptions)), | |
| 157 MOJO_DUPLICATE_BUFFER_HANDLE_OPTIONS_FLAG_NONE}; | |
| 158 | |
| 159 *out_options = kDefaultOptions; | |
| 160 if (!in_options) | |
| 161 return MOJO_RESULT_OK; | |
| 162 | |
| 163 UserOptionsReader<MojoDuplicateBufferHandleOptions> reader(in_options); | |
| 164 if (!reader.is_valid()) | |
| 165 return MOJO_RESULT_INVALID_ARGUMENT; | 140 return MOJO_RESULT_INVALID_ARGUMENT; |
| 166 | 141 |
| 167 if (!OPTIONS_STRUCT_HAS_MEMBER(MojoDuplicateBufferHandleOptions, flags, | 142 shared_buffer_ = nullptr; |
| 168 reader)) | |
| 169 return MOJO_RESULT_OK; | |
| 170 if ((reader.options().flags & ~kKnownFlags)) | |
| 171 return MOJO_RESULT_UNIMPLEMENTED; | |
| 172 out_options->flags = reader.options().flags; | |
| 173 | |
| 174 // Checks for fields beyond |flags|: | |
| 175 | |
| 176 // (Nothing here yet.) | |
| 177 | |
| 178 return MOJO_RESULT_OK; | 143 return MOJO_RESULT_OK; |
| 179 } | 144 } |
| 180 | 145 |
| 181 void SharedBufferDispatcher::CloseImplNoLock() { | 146 MojoResult SharedBufferDispatcher::DuplicateBufferHandle( |
| 182 lock().AssertAcquired(); | |
| 183 DCHECK(shared_buffer_); | |
| 184 shared_buffer_ = nullptr; | |
| 185 } | |
| 186 | |
| 187 scoped_refptr<Dispatcher> | |
| 188 SharedBufferDispatcher::CreateEquivalentDispatcherAndCloseImplNoLock() { | |
| 189 lock().AssertAcquired(); | |
| 190 DCHECK(shared_buffer_); | |
| 191 return CreateInternal(std::move(shared_buffer_)); | |
| 192 } | |
| 193 | |
| 194 MojoResult SharedBufferDispatcher::DuplicateBufferHandleImplNoLock( | |
| 195 const MojoDuplicateBufferHandleOptions* options, | 147 const MojoDuplicateBufferHandleOptions* options, |
| 196 scoped_refptr<Dispatcher>* new_dispatcher) { | 148 scoped_refptr<Dispatcher>* new_dispatcher) { |
| 197 lock().AssertAcquired(); | |
| 198 | |
| 199 MojoDuplicateBufferHandleOptions validated_options; | 149 MojoDuplicateBufferHandleOptions validated_options; |
| 200 MojoResult result = ValidateDuplicateOptions(options, &validated_options); | 150 MojoResult result = ValidateDuplicateOptions(options, &validated_options); |
| 201 if (result != MOJO_RESULT_OK) | 151 if (result != MOJO_RESULT_OK) |
| 202 return result; | 152 return result; |
| 203 | 153 |
| 204 // Note: Since this is "duplicate", we keep our ref to |shared_buffer_|. | 154 // Note: Since this is "duplicate", we keep our ref to |shared_buffer_|. |
| 155 base::AutoLock lock(lock_); | |
| 156 if (in_transit_) | |
| 157 return MOJO_RESULT_INVALID_ARGUMENT; | |
| 205 *new_dispatcher = CreateInternal(shared_buffer_); | 158 *new_dispatcher = CreateInternal(shared_buffer_); |
| 206 return MOJO_RESULT_OK; | 159 return MOJO_RESULT_OK; |
| 207 } | 160 } |
| 208 | 161 |
| 209 MojoResult SharedBufferDispatcher::MapBufferImplNoLock( | 162 MojoResult SharedBufferDispatcher::MapBuffer( |
| 210 uint64_t offset, | 163 uint64_t offset, |
| 211 uint64_t num_bytes, | 164 uint64_t num_bytes, |
| 212 MojoMapBufferFlags flags, | 165 MojoMapBufferFlags flags, |
| 213 scoped_ptr<PlatformSharedBufferMapping>* mapping) { | 166 scoped_ptr<PlatformSharedBufferMapping>* mapping) { |
| 214 lock().AssertAcquired(); | |
| 215 DCHECK(shared_buffer_); | |
| 216 | |
| 217 if (offset > static_cast<uint64_t>(std::numeric_limits<size_t>::max())) | 167 if (offset > static_cast<uint64_t>(std::numeric_limits<size_t>::max())) |
| 218 return MOJO_RESULT_INVALID_ARGUMENT; | 168 return MOJO_RESULT_INVALID_ARGUMENT; |
| 219 if (num_bytes > static_cast<uint64_t>(std::numeric_limits<size_t>::max())) | 169 if (num_bytes > static_cast<uint64_t>(std::numeric_limits<size_t>::max())) |
| 220 return MOJO_RESULT_INVALID_ARGUMENT; | 170 return MOJO_RESULT_INVALID_ARGUMENT; |
| 221 | 171 |
| 222 if (!shared_buffer_->IsValidMap(static_cast<size_t>(offset), | 172 base::AutoLock lock(lock_); |
| 223 static_cast<size_t>(num_bytes))) | 173 DCHECK(shared_buffer_); |
| 174 if (in_transit_ || | |
| 175 !shared_buffer_->IsValidMap(static_cast<size_t>(offset), | |
| 176 static_cast<size_t>(num_bytes))) { | |
| 224 return MOJO_RESULT_INVALID_ARGUMENT; | 177 return MOJO_RESULT_INVALID_ARGUMENT; |
| 178 } | |
| 225 | 179 |
| 226 DCHECK(mapping); | 180 DCHECK(mapping); |
| 227 *mapping = shared_buffer_->MapNoCheck(static_cast<size_t>(offset), | 181 *mapping = shared_buffer_->MapNoCheck(static_cast<size_t>(offset), |
| 228 static_cast<size_t>(num_bytes)); | 182 static_cast<size_t>(num_bytes)); |
| 229 if (!*mapping) | 183 if (!*mapping) |
| 230 return MOJO_RESULT_RESOURCE_EXHAUSTED; | 184 return MOJO_RESULT_RESOURCE_EXHAUSTED; |
| 231 | 185 |
| 232 return MOJO_RESULT_OK; | 186 return MOJO_RESULT_OK; |
| 233 } | 187 } |
| 234 | 188 |
| 235 void SharedBufferDispatcher::StartSerializeImplNoLock( | 189 void SharedBufferDispatcher::StartSerialize(uint32_t* num_bytes, |
| 236 size_t* max_size, | 190 uint32_t* num_ports, |
| 237 size_t* max_platform_handles) { | 191 uint32_t* num_platform_handles) { |
| 238 *max_size = sizeof(SerializedSharedBufferDispatcher); | 192 *num_bytes = sizeof(SerializedSharedBufferDispatcher); |
| 239 *max_platform_handles = 1; | 193 *num_ports = 0; |
| 194 *num_platform_handles = 1; | |
| 240 } | 195 } |
| 241 | 196 |
| 242 bool SharedBufferDispatcher::EndSerializeAndCloseImplNoLock( | 197 bool SharedBufferDispatcher::EndSerialize(void* destination, |
| 243 void* destination, | 198 ports::PortName* ports, |
| 244 size_t* actual_size, | 199 PlatformHandle* handles) { |
| 245 PlatformHandleVector* platform_handles) { | |
| 246 DCHECK(shared_buffer_); | |
| 247 | |
| 248 SerializedSharedBufferDispatcher* serialization = | 200 SerializedSharedBufferDispatcher* serialization = |
| 249 static_cast<SerializedSharedBufferDispatcher*>(destination); | 201 static_cast<SerializedSharedBufferDispatcher*>(destination); |
| 250 // If there's only one reference to |shared_buffer_|, then it's ours (and no | 202 base::AutoLock lock(lock_); |
| 251 // one else can make any more references to it), so we can just take its | 203 serialization->num_bytes = shared_buffer_->GetNumBytes(); |
| 252 // handle. | 204 |
| 253 ScopedPlatformHandle platform_handle( | 205 handle_for_transit_ = shared_buffer_->DuplicatePlatformHandle(); |
| 254 shared_buffer_->HasOneRef() ? shared_buffer_->PassPlatformHandle() | 206 if (!handle_for_transit_.is_valid()) { |
| 255 : shared_buffer_->DuplicatePlatformHandle()); | |
| 256 if (!platform_handle.is_valid()) { | |
| 257 shared_buffer_ = nullptr; | 207 shared_buffer_ = nullptr; |
| 258 return false; | 208 return false; |
| 259 } | 209 } |
| 260 | 210 handles[0] = handle_for_transit_.get(); |
| 261 DCHECK(shared_buffer_->GetNumBytes() < std::numeric_limits<uint32_t>::max()); | |
| 262 serialization->num_bytes = | |
| 263 static_cast<uint32_t>(shared_buffer_->GetNumBytes()); | |
| 264 DCHECK(platform_handles->size() < std::numeric_limits<uint32_t>::max()); | |
| 265 serialization->platform_handle_index = | |
| 266 static_cast<uint32_t>(platform_handles->size()); | |
| 267 platform_handles->push_back(platform_handle.release()); | |
| 268 *actual_size = sizeof(SerializedSharedBufferDispatcher); | |
| 269 | |
| 270 shared_buffer_ = nullptr; | |
| 271 | |
| 272 return true; | 211 return true; |
| 273 } | 212 } |
| 274 | 213 |
| 214 bool SharedBufferDispatcher::BeginTransit() { | |
| 215 base::AutoLock lock(lock_); | |
| 216 if (in_transit_) | |
| 217 return false; | |
| 218 in_transit_ = shared_buffer_ != nullptr; | |
| 219 return in_transit_; | |
| 220 } | |
| 221 | |
| 222 void SharedBufferDispatcher::CompleteTransitAndClose() { | |
| 223 base::AutoLock lock(lock_); | |
| 224 in_transit_ = false; | |
| 225 shared_buffer_ = nullptr; | |
| 226 ignore_result(handle_for_transit_.release()); | |
| 227 } | |
| 228 | |
| 229 void SharedBufferDispatcher::CancelTransit() { | |
| 230 base::AutoLock lock(lock_); | |
| 231 in_transit_ = false; | |
| 232 handle_for_transit_.reset(); | |
| 233 } | |
| 234 | |
| 235 SharedBufferDispatcher::SharedBufferDispatcher( | |
| 236 scoped_refptr<PlatformSharedBuffer> shared_buffer) | |
| 237 : shared_buffer_(shared_buffer) { | |
| 238 DCHECK(shared_buffer_); | |
| 239 } | |
| 240 | |
| 241 SharedBufferDispatcher::~SharedBufferDispatcher() { | |
| 242 DCHECK(!shared_buffer_ && !in_transit_); | |
| 243 } | |
| 244 | |
| 245 // static | |
| 246 MojoResult SharedBufferDispatcher::ValidateDuplicateOptions( | |
| 247 const MojoDuplicateBufferHandleOptions* in_options, | |
| 248 MojoDuplicateBufferHandleOptions* out_options) { | |
| 249 const MojoDuplicateBufferHandleOptionsFlags kKnownFlags = | |
| 250 MOJO_DUPLICATE_BUFFER_HANDLE_OPTIONS_FLAG_NONE; | |
| 251 static const MojoDuplicateBufferHandleOptions kDefaultOptions = { | |
| 252 static_cast<uint32_t>(sizeof(MojoDuplicateBufferHandleOptions)), | |
| 253 MOJO_DUPLICATE_BUFFER_HANDLE_OPTIONS_FLAG_NONE}; | |
| 254 | |
| 255 *out_options = kDefaultOptions; | |
| 256 if (!in_options) | |
| 257 return MOJO_RESULT_OK; | |
| 258 | |
| 259 UserOptionsReader<MojoDuplicateBufferHandleOptions> reader(in_options); | |
| 260 if (!reader.is_valid()) | |
| 261 return MOJO_RESULT_INVALID_ARGUMENT; | |
| 262 | |
| 263 if (!OPTIONS_STRUCT_HAS_MEMBER(MojoDuplicateBufferHandleOptions, flags, | |
| 264 reader)) | |
| 265 return MOJO_RESULT_OK; | |
| 266 if ((reader.options().flags & ~kKnownFlags)) | |
| 267 return MOJO_RESULT_UNIMPLEMENTED; | |
| 268 out_options->flags = reader.options().flags; | |
| 269 | |
| 270 // Checks for fields beyond |flags|: | |
| 271 | |
| 272 // (Nothing here yet.) | |
| 273 | |
| 274 return MOJO_RESULT_OK; | |
| 275 } | |
| 275 | 276 |
| 276 } // namespace edk | 277 } // namespace edk |
| 277 } // namespace mojo | 278 } // namespace mojo |
| OLD | NEW |