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 <limits> | 10 #include <limits> |
11 #include <utility> | 11 #include <utility> |
12 | 12 |
13 #include "base/logging.h" | 13 #include "base/logging.h" |
14 #include "base/memory/scoped_ptr.h" | 14 #include "base/memory/scoped_ptr.h" |
15 #include "mojo/edk/embedder/embedder_internal.h" | 15 #include "mojo/edk/embedder/embedder_internal.h" |
16 #include "mojo/edk/system/configuration.h" | 16 #include "mojo/edk/system/configuration.h" |
17 #include "mojo/edk/system/node_controller.h" | 17 #include "mojo/edk/system/node_controller.h" |
18 #include "mojo/edk/system/options_validation.h" | 18 #include "mojo/edk/system/options_validation.h" |
19 | 19 |
20 namespace mojo { | 20 namespace mojo { |
21 namespace edk { | 21 namespace edk { |
22 | 22 |
23 namespace { | 23 namespace { |
24 | 24 |
25 #pragma pack(push, 1) | 25 #pragma pack(push, 1) |
26 | 26 |
27 struct SerializedState { | 27 struct SerializedState { |
28 uint64_t num_bytes; | 28 uint64_t num_bytes; |
| 29 uint32_t flags; |
| 30 uint32_t padding; |
29 }; | 31 }; |
30 | 32 |
| 33 const uint32_t kSerializedStateFlagsReadOnly = 1 << 0; |
| 34 |
31 #pragma pack(pop) | 35 #pragma pack(pop) |
32 | 36 |
33 static_assert(sizeof(SerializedState) % 8 == 0, | 37 static_assert(sizeof(SerializedState) % 8 == 0, |
34 "Invalid SerializedState size."); | 38 "Invalid SerializedState size."); |
35 | 39 |
36 } // namespace | 40 } // namespace |
37 | 41 |
38 // static | 42 // static |
39 const MojoCreateSharedBufferOptions | 43 const MojoCreateSharedBufferOptions |
40 SharedBufferDispatcher::kDefaultCreateOptions = { | 44 SharedBufferDispatcher::kDefaultCreateOptions = { |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
134 } | 138 } |
135 | 139 |
136 // Starts off invalid, which is what we want. | 140 // Starts off invalid, which is what we want. |
137 PlatformHandle platform_handle; | 141 PlatformHandle platform_handle; |
138 // We take ownership of the handle, so we have to invalidate the one in | 142 // We take ownership of the handle, so we have to invalidate the one in |
139 // |platform_handles|. | 143 // |platform_handles|. |
140 std::swap(platform_handle, *platform_handles); | 144 std::swap(platform_handle, *platform_handles); |
141 | 145 |
142 // Wrapping |platform_handle| in a |ScopedPlatformHandle| means that it'll be | 146 // Wrapping |platform_handle| in a |ScopedPlatformHandle| means that it'll be |
143 // closed even if creation fails. | 147 // closed even if creation fails. |
| 148 bool read_only = (serialization->flags & kSerializedStateFlagsReadOnly); |
144 scoped_refptr<PlatformSharedBuffer> shared_buffer( | 149 scoped_refptr<PlatformSharedBuffer> shared_buffer( |
145 PlatformSharedBuffer::CreateFromPlatformHandle( | 150 PlatformSharedBuffer::CreateFromPlatformHandle( |
146 static_cast<size_t>(serialization->num_bytes), | 151 static_cast<size_t>(serialization->num_bytes), read_only, |
147 ScopedPlatformHandle(platform_handle))); | 152 ScopedPlatformHandle(platform_handle))); |
148 if (!shared_buffer) { | 153 if (!shared_buffer) { |
149 LOG(ERROR) | 154 LOG(ERROR) |
150 << "Invalid serialized shared buffer dispatcher (invalid num_bytes?)"; | 155 << "Invalid serialized shared buffer dispatcher (invalid num_bytes?)"; |
151 return nullptr; | 156 return nullptr; |
152 } | 157 } |
153 | 158 |
154 return CreateInternal(std::move(shared_buffer)); | 159 return CreateInternal(std::move(shared_buffer)); |
155 } | 160 } |
156 | 161 |
(...skipping 26 matching lines...) Expand all Loading... |
183 scoped_refptr<Dispatcher>* new_dispatcher) { | 188 scoped_refptr<Dispatcher>* new_dispatcher) { |
184 MojoDuplicateBufferHandleOptions validated_options; | 189 MojoDuplicateBufferHandleOptions validated_options; |
185 MojoResult result = ValidateDuplicateOptions(options, &validated_options); | 190 MojoResult result = ValidateDuplicateOptions(options, &validated_options); |
186 if (result != MOJO_RESULT_OK) | 191 if (result != MOJO_RESULT_OK) |
187 return result; | 192 return result; |
188 | 193 |
189 // Note: Since this is "duplicate", we keep our ref to |shared_buffer_|. | 194 // Note: Since this is "duplicate", we keep our ref to |shared_buffer_|. |
190 base::AutoLock lock(lock_); | 195 base::AutoLock lock(lock_); |
191 if (in_transit_) | 196 if (in_transit_) |
192 return MOJO_RESULT_INVALID_ARGUMENT; | 197 return MOJO_RESULT_INVALID_ARGUMENT; |
| 198 |
| 199 if ((validated_options.flags & |
| 200 MOJO_DUPLICATE_BUFFER_HANDLE_OPTIONS_FLAG_READ_ONLY) && |
| 201 (!shared_buffer_->IsReadOnly())) { |
| 202 // If a read-only duplicate is requested and |shared_buffer_| is not |
| 203 // read-only, make a read-only duplicate of |shared_buffer_|. |
| 204 scoped_refptr<PlatformSharedBuffer> read_only_buffer = |
| 205 shared_buffer_->CreateReadOnlyDuplicate(); |
| 206 if (!read_only_buffer) |
| 207 return MOJO_RESULT_FAILED_PRECONDITION; |
| 208 DCHECK(read_only_buffer->IsReadOnly()); |
| 209 *new_dispatcher = CreateInternal(std::move(read_only_buffer)); |
| 210 return MOJO_RESULT_OK; |
| 211 } |
| 212 |
193 *new_dispatcher = CreateInternal(shared_buffer_); | 213 *new_dispatcher = CreateInternal(shared_buffer_); |
194 return MOJO_RESULT_OK; | 214 return MOJO_RESULT_OK; |
195 } | 215 } |
196 | 216 |
197 MojoResult SharedBufferDispatcher::MapBuffer( | 217 MojoResult SharedBufferDispatcher::MapBuffer( |
198 uint64_t offset, | 218 uint64_t offset, |
199 uint64_t num_bytes, | 219 uint64_t num_bytes, |
200 MojoMapBufferFlags flags, | 220 MojoMapBufferFlags flags, |
201 scoped_ptr<PlatformSharedBufferMapping>* mapping) { | 221 scoped_ptr<PlatformSharedBufferMapping>* mapping) { |
202 if (offset > static_cast<uint64_t>(std::numeric_limits<size_t>::max())) | 222 if (offset > static_cast<uint64_t>(std::numeric_limits<size_t>::max())) |
203 return MOJO_RESULT_INVALID_ARGUMENT; | 223 return MOJO_RESULT_INVALID_ARGUMENT; |
204 if (num_bytes > static_cast<uint64_t>(std::numeric_limits<size_t>::max())) | 224 if (num_bytes > static_cast<uint64_t>(std::numeric_limits<size_t>::max())) |
205 return MOJO_RESULT_INVALID_ARGUMENT; | 225 return MOJO_RESULT_INVALID_ARGUMENT; |
206 | 226 |
207 base::AutoLock lock(lock_); | 227 base::AutoLock lock(lock_); |
208 DCHECK(shared_buffer_); | 228 DCHECK(shared_buffer_); |
209 if (in_transit_ || | 229 if (in_transit_ || |
210 !shared_buffer_->IsValidMap(static_cast<size_t>(offset), | 230 !shared_buffer_->IsValidMap(static_cast<size_t>(offset), |
211 static_cast<size_t>(num_bytes))) { | 231 static_cast<size_t>(num_bytes))) { |
212 return MOJO_RESULT_INVALID_ARGUMENT; | 232 return MOJO_RESULT_INVALID_ARGUMENT; |
213 } | 233 } |
214 | 234 |
215 DCHECK(mapping); | 235 DCHECK(mapping); |
216 *mapping = shared_buffer_->MapNoCheck(static_cast<size_t>(offset), | 236 *mapping = shared_buffer_->MapNoCheck(static_cast<size_t>(offset), |
217 static_cast<size_t>(num_bytes)); | 237 static_cast<size_t>(num_bytes)); |
218 if (!*mapping) | 238 if (!*mapping) { |
| 239 LOG(ERROR) << "Unable to map: read_only" << shared_buffer_->IsReadOnly(); |
219 return MOJO_RESULT_RESOURCE_EXHAUSTED; | 240 return MOJO_RESULT_RESOURCE_EXHAUSTED; |
| 241 } |
220 | 242 |
221 return MOJO_RESULT_OK; | 243 return MOJO_RESULT_OK; |
222 } | 244 } |
223 | 245 |
224 void SharedBufferDispatcher::StartSerialize(uint32_t* num_bytes, | 246 void SharedBufferDispatcher::StartSerialize(uint32_t* num_bytes, |
225 uint32_t* num_ports, | 247 uint32_t* num_ports, |
226 uint32_t* num_platform_handles) { | 248 uint32_t* num_platform_handles) { |
227 *num_bytes = sizeof(SerializedState); | 249 *num_bytes = sizeof(SerializedState); |
228 *num_ports = 0; | 250 *num_ports = 0; |
229 *num_platform_handles = 1; | 251 *num_platform_handles = 1; |
230 } | 252 } |
231 | 253 |
232 bool SharedBufferDispatcher::EndSerialize(void* destination, | 254 bool SharedBufferDispatcher::EndSerialize(void* destination, |
233 ports::PortName* ports, | 255 ports::PortName* ports, |
234 PlatformHandle* handles) { | 256 PlatformHandle* handles) { |
235 SerializedState* serialization = | 257 SerializedState* serialization = |
236 static_cast<SerializedState*>(destination); | 258 static_cast<SerializedState*>(destination); |
237 base::AutoLock lock(lock_); | 259 base::AutoLock lock(lock_); |
238 serialization->num_bytes = | 260 serialization->num_bytes = |
239 static_cast<uint64_t>(shared_buffer_->GetNumBytes()); | 261 static_cast<uint64_t>(shared_buffer_->GetNumBytes()); |
| 262 serialization->flags = |
| 263 (shared_buffer_->IsReadOnly() ? kSerializedStateFlagsReadOnly : 0); |
| 264 serialization->padding = 0; |
240 | 265 |
241 handle_for_transit_ = shared_buffer_->DuplicatePlatformHandle(); | 266 handle_for_transit_ = shared_buffer_->DuplicatePlatformHandle(); |
242 if (!handle_for_transit_.is_valid()) { | 267 if (!handle_for_transit_.is_valid()) { |
243 shared_buffer_ = nullptr; | 268 shared_buffer_ = nullptr; |
244 return false; | 269 return false; |
245 } | 270 } |
246 handles[0] = handle_for_transit_.get(); | 271 handles[0] = handle_for_transit_.get(); |
247 return true; | 272 return true; |
248 } | 273 } |
249 | 274 |
(...skipping 26 matching lines...) Expand all Loading... |
276 | 301 |
277 SharedBufferDispatcher::~SharedBufferDispatcher() { | 302 SharedBufferDispatcher::~SharedBufferDispatcher() { |
278 DCHECK(!shared_buffer_ && !in_transit_); | 303 DCHECK(!shared_buffer_ && !in_transit_); |
279 } | 304 } |
280 | 305 |
281 // static | 306 // static |
282 MojoResult SharedBufferDispatcher::ValidateDuplicateOptions( | 307 MojoResult SharedBufferDispatcher::ValidateDuplicateOptions( |
283 const MojoDuplicateBufferHandleOptions* in_options, | 308 const MojoDuplicateBufferHandleOptions* in_options, |
284 MojoDuplicateBufferHandleOptions* out_options) { | 309 MojoDuplicateBufferHandleOptions* out_options) { |
285 const MojoDuplicateBufferHandleOptionsFlags kKnownFlags = | 310 const MojoDuplicateBufferHandleOptionsFlags kKnownFlags = |
286 MOJO_DUPLICATE_BUFFER_HANDLE_OPTIONS_FLAG_NONE; | 311 MOJO_DUPLICATE_BUFFER_HANDLE_OPTIONS_FLAG_READ_ONLY; |
287 static const MojoDuplicateBufferHandleOptions kDefaultOptions = { | 312 static const MojoDuplicateBufferHandleOptions kDefaultOptions = { |
288 static_cast<uint32_t>(sizeof(MojoDuplicateBufferHandleOptions)), | 313 static_cast<uint32_t>(sizeof(MojoDuplicateBufferHandleOptions)), |
289 MOJO_DUPLICATE_BUFFER_HANDLE_OPTIONS_FLAG_NONE}; | 314 MOJO_DUPLICATE_BUFFER_HANDLE_OPTIONS_FLAG_NONE}; |
290 | 315 |
291 *out_options = kDefaultOptions; | 316 *out_options = kDefaultOptions; |
292 if (!in_options) | 317 if (!in_options) |
293 return MOJO_RESULT_OK; | 318 return MOJO_RESULT_OK; |
294 | 319 |
295 UserOptionsReader<MojoDuplicateBufferHandleOptions> reader(in_options); | 320 UserOptionsReader<MojoDuplicateBufferHandleOptions> reader(in_options); |
296 if (!reader.is_valid()) | 321 if (!reader.is_valid()) |
297 return MOJO_RESULT_INVALID_ARGUMENT; | 322 return MOJO_RESULT_INVALID_ARGUMENT; |
298 | 323 |
299 if (!OPTIONS_STRUCT_HAS_MEMBER(MojoDuplicateBufferHandleOptions, flags, | 324 if (!OPTIONS_STRUCT_HAS_MEMBER(MojoDuplicateBufferHandleOptions, flags, |
300 reader)) | 325 reader)) |
301 return MOJO_RESULT_OK; | 326 return MOJO_RESULT_OK; |
302 if ((reader.options().flags & ~kKnownFlags)) | 327 if ((reader.options().flags & ~kKnownFlags)) |
303 return MOJO_RESULT_UNIMPLEMENTED; | 328 return MOJO_RESULT_UNIMPLEMENTED; |
304 out_options->flags = reader.options().flags; | 329 out_options->flags = reader.options().flags; |
305 | 330 |
306 // Checks for fields beyond |flags|: | 331 // Checks for fields beyond |flags|: |
307 | 332 |
308 // (Nothing here yet.) | 333 // (Nothing here yet.) |
309 | 334 |
310 return MOJO_RESULT_OK; | 335 return MOJO_RESULT_OK; |
311 } | 336 } |
312 | 337 |
313 } // namespace edk | 338 } // namespace edk |
314 } // namespace mojo | 339 } // namespace mojo |
OLD | NEW |