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/core.h" 6 7 #include <string.h> 8 9 #include <utility> 10 11 #include "base/bind.h" 12 #include "base/containers/stack_container.h" 13 #include "base/location.h" 14 #include "base/logging.h" 15 #include "base/macros.h" 16 #include "base/memory/ptr_util.h" 17 #include "base/message_loop/message_loop.h" 18 #include "base/rand_util.h" 19 #include "base/threading/thread_task_runner_handle.h" 20 #include "base/time/time.h" 21 #include "mojo/edk/embedder/embedder.h" 22 #include "mojo/edk/embedder/embedder_internal.h" 23 #include "mojo/edk/embedder/platform_shared_buffer.h" 24 #include "mojo/edk/system/channel.h" 25 #include "mojo/edk/system/configuration.h" 26 #include "mojo/edk/system/data_pipe_consumer_dispatcher.h" 27 #include "mojo/edk/system/data_pipe_producer_dispatcher.h" 28 #include "mojo/edk/system/handle_signals_state.h" 29 #include "mojo/edk/system/message_for_transit.h" 30 #include "mojo/edk/system/message_pipe_dispatcher.h" 31 #include "mojo/edk/system/platform_handle_dispatcher.h" 32 #include "mojo/edk/system/ports/name.h" 33 #include "mojo/edk/system/ports/node.h" 34 #include "mojo/edk/system/request_context.h" 35 #include "mojo/edk/system/shared_buffer_dispatcher.h" 36 #include "mojo/edk/system/wait_set_dispatcher.h" 37 #include "mojo/edk/system/waiter.h" 38 39 namespace mojo { 40 namespace edk { 41 42 namespace { 43 44 // This is an unnecessarily large limit that is relatively easy to enforce. 45 const uint32_t kMaxHandlesPerMessage = 1024 * 1024; 46 47 // TODO: Maybe we could negotiate a debugging pipe ID for cross-process pipes 48 // too; for now we just use a constant. This only affects bootstrap pipes. 49 const uint64_t kUnknownPipeIdForDebug = 0x7f7f7f7f7f7f7f7fUL; 50 51 void CallWatchCallback(MojoWatchCallback callback, 52 uintptr_t context, 53 MojoResult result, 54 const HandleSignalsState& signals_state, 55 MojoWatchNotificationFlags flags) { 56 callback(context, result, static_cast<MojoHandleSignalsState>(signals_state), 57 flags); 58 } 59 60 MojoResult MojoPlatformHandleToScopedPlatformHandle( 61 const MojoPlatformHandle* platform_handle, 62 ScopedPlatformHandle* out_handle) { 63 if (platform_handle->struct_size != sizeof(MojoPlatformHandle)) 64 return MOJO_RESULT_INVALID_ARGUMENT; 65 66 if (platform_handle->type == MOJO_PLATFORM_HANDLE_TYPE_INVALID) { 67 out_handle->reset(); 68 return MOJO_RESULT_OK; 69 } 70 71 PlatformHandle handle; 72 switch (platform_handle->type) { 73 #if defined(OS_POSIX) 74 case MOJO_PLATFORM_HANDLE_TYPE_FILE_DESCRIPTOR: 75 handle.handle = static_cast<int>(platform_handle->value); 76 break; 77 #endif 78 79 #if defined(OS_MACOSX) && !defined(OS_IOS) 80 case MOJO_PLATFORM_HANDLE_TYPE_MACH_PORT: 81 handle.type = PlatformHandle::Type::MACH; 82 handle.port = static_cast<mach_port_t>(platform_handle->value); 83 break; 84 #endif 85 86 #if defined(OS_WIN) 87 case MOJO_PLATFORM_HANDLE_TYPE_WINDOWS_HANDLE: 88 handle.handle = reinterpret_cast<HANDLE>(platform_handle->value); 89 break; 90 #endif 91 92 default: 93 return MOJO_RESULT_INVALID_ARGUMENT; 94 } 95 96 out_handle->reset(handle); 97 return MOJO_RESULT_OK; 98 } 99 100 MojoResult ScopedPlatformHandleToMojoPlatformHandle( 101 ScopedPlatformHandle handle, 102 MojoPlatformHandle* platform_handle) { 103 if (platform_handle->struct_size != sizeof(MojoPlatformHandle)) 104 return MOJO_RESULT_INVALID_ARGUMENT; 105 106 if (!handle.is_valid()) { 107 platform_handle->type = MOJO_PLATFORM_HANDLE_TYPE_INVALID; 108 return MOJO_RESULT_OK; 109 } 110 111 #if defined(OS_POSIX) 112 switch (handle.get().type) { 113 case PlatformHandle::Type::POSIX: 114 platform_handle->type = MOJO_PLATFORM_HANDLE_TYPE_FILE_DESCRIPTOR; 115 platform_handle->value = static_cast<uint64_t>(handle.release().handle); 116 break; 117 118 #if defined(OS_MACOSX) && !defined(OS_IOS) 119 case PlatformHandle::Type::MACH: 120 platform_handle->type = MOJO_PLATFORM_HANDLE_TYPE_MACH_PORT; 121 platform_handle->value = static_cast<uint64_t>(handle.release().port); 122 break; 123 #endif // defined(OS_MACOSX) && !defined(OS_IOS) 124 125 default: 126 return MOJO_RESULT_INVALID_ARGUMENT; 127 } 128 #elif defined(OS_WIN) 129 platform_handle->type = MOJO_PLATFORM_HANDLE_TYPE_WINDOWS_HANDLE; 130 platform_handle->value = reinterpret_cast<uint64_t>(handle.release().handle); 131 #endif // defined(OS_WIN) 132 133 return MOJO_RESULT_OK; 134 } 135 136 } // namespace 137 138 Core::Core() {} 139 140 Core::~Core() { 141 if (node_controller_ && node_controller_->io_task_runner()) { 142 // If this races with IO thread shutdown the callback will be dropped and 143 // the NodeController will be shutdown on this thread anyway, which is also 144 // just fine. 145 scoped_refptr<base::TaskRunner> io_task_runner = 146 node_controller_->io_task_runner(); 147 io_task_runner->PostTask(FROM_HERE, 148 base::Bind(&Core::PassNodeControllerToIOThread, 149 base::Passed(&node_controller_))); 150 } 151 } 152 153 void Core::SetIOTaskRunner(scoped_refptr<base::TaskRunner> io_task_runner) { 154 GetNodeController()->SetIOTaskRunner(io_task_runner); 155 } 156 157 NodeController* Core::GetNodeController() { 158 base::AutoLock lock(node_controller_lock_); 159 if (!node_controller_) 160 node_controller_.reset(new NodeController(this)); 161 return node_controller_.get(); 162 } 163 164 scoped_refptr<Dispatcher> Core::GetDispatcher(MojoHandle handle) { 165 base::AutoLock lock(handles_lock_); 166 return handles_.GetDispatcher(handle); 167 } 168 169 void Core::AddChild(base::ProcessHandle process_handle, 170 ScopedPlatformHandle platform_handle, 171 const std::string& child_token, 172 const ProcessErrorCallback& process_error_callback) { 173 GetNodeController()->ConnectToChild(process_handle, 174 std::move(platform_handle), 175 child_token, 176 process_error_callback); 177 } 178 179 void Core::ChildLaunchFailed(const std::string& child_token) { 180 RequestContext request_context; 181 GetNodeController()->CloseChildPorts(child_token); 182 } 183 184 void Core::InitChild(ScopedPlatformHandle platform_handle) { 185 GetNodeController()->ConnectToParent(std::move(platform_handle)); 186 } 187 188 void Core::SetMachPortProvider(base::PortProvider* port_provider) { 189 #if defined(OS_MACOSX) && !defined(OS_IOS) 190 GetNodeController()->CreateMachPortRelay(port_provider); 191 #endif 192 } 193 194 MojoHandle Core::AddDispatcher(scoped_refptr<Dispatcher> dispatcher) { 195 base::AutoLock lock(handles_lock_); 196 return handles_.AddDispatcher(dispatcher); 197 } 198 199 bool Core::AddDispatchersFromTransit( 200 const std::vector<Dispatcher::DispatcherInTransit>& dispatchers, 201 MojoHandle* handles) { 202 bool failed = false; 203 { 204 base::AutoLock lock(handles_lock_); 205 if (!handles_.AddDispatchersFromTransit(dispatchers, handles)) 206 failed = true; 207 } 208 if (failed) { 209 for (auto d : dispatchers) 210 d.dispatcher->Close(); 211 return false; 212 } 213 return true; 214 } 215 216 MojoResult Core::CreatePlatformHandleWrapper( 217 ScopedPlatformHandle platform_handle, 218 MojoHandle* wrapper_handle) { 219 MojoHandle h = AddDispatcher( 220 PlatformHandleDispatcher::Create(std::move(platform_handle))); 221 if (h == MOJO_HANDLE_INVALID) 222 return MOJO_RESULT_RESOURCE_EXHAUSTED; 223 *wrapper_handle = h; 224 return MOJO_RESULT_OK; 225 } 226 227 MojoResult Core::PassWrappedPlatformHandle( 228 MojoHandle wrapper_handle, 229 ScopedPlatformHandle* platform_handle) { 230 base::AutoLock lock(handles_lock_); 231 scoped_refptr<Dispatcher> d; 232 MojoResult result = handles_.GetAndRemoveDispatcher(wrapper_handle, &d); 233 if (result != MOJO_RESULT_OK) 234 return result; 235 if (d->GetType() == Dispatcher::Type::PLATFORM_HANDLE) { 236 PlatformHandleDispatcher* phd = 237 static_cast<PlatformHandleDispatcher*>(d.get()); 238 *platform_handle = phd->PassPlatformHandle(); 239 } else { 240 result = MOJO_RESULT_INVALID_ARGUMENT; 241 } 242 d->Close(); 243 return result; 244 } 245 246 MojoResult Core::CreateSharedBufferWrapper( 247 base::SharedMemoryHandle shared_memory_handle, 248 size_t num_bytes, 249 bool read_only, 250 MojoHandle* mojo_wrapper_handle) { 251 DCHECK(num_bytes); 252 scoped_refptr<PlatformSharedBuffer> platform_buffer = 253 PlatformSharedBuffer::CreateFromSharedMemoryHandle(num_bytes, read_only, 254 shared_memory_handle); 255 if (!platform_buffer) 256 return MOJO_RESULT_UNKNOWN; 257 258 scoped_refptr<SharedBufferDispatcher> dispatcher; 259 MojoResult result = SharedBufferDispatcher::CreateFromPlatformSharedBuffer( 260 platform_buffer, &dispatcher); 261 if (result != MOJO_RESULT_OK) 262 return result; 263 MojoHandle h = AddDispatcher(dispatcher); 264 if (h == MOJO_HANDLE_INVALID) 265 return MOJO_RESULT_RESOURCE_EXHAUSTED; 266 *mojo_wrapper_handle = h; 267 return MOJO_RESULT_OK; 268 } 269 270 MojoResult Core::PassSharedMemoryHandle( 271 MojoHandle mojo_handle, 272 base::SharedMemoryHandle* shared_memory_handle, 273 size_t* num_bytes, 274 bool* read_only) { 275 if (!shared_memory_handle) 276 return MOJO_RESULT_INVALID_ARGUMENT; 277 278 scoped_refptr<Dispatcher> dispatcher; 279 MojoResult result = MOJO_RESULT_OK; 280 { 281 base::AutoLock lock(handles_lock_); 282 // Get the dispatcher and check it before removing it from the handle table 283 // to ensure that the dispatcher is of the correct type. This ensures we 284 // don't close and remove the wrong type of dispatcher. 285 dispatcher = handles_.GetDispatcher(mojo_handle); 286 if (!dispatcher || dispatcher->GetType() != Dispatcher::Type::SHARED_BUFFER) 287 return MOJO_RESULT_INVALID_ARGUMENT; 288 289 result = handles_.GetAndRemoveDispatcher(mojo_handle, &dispatcher); 290 if (result != MOJO_RESULT_OK) 291 return result; 292 } 293 294 SharedBufferDispatcher* shm_dispatcher = 295 static_cast<SharedBufferDispatcher*>(dispatcher.get()); 296 scoped_refptr<PlatformSharedBuffer> platform_shared_buffer = 297 shm_dispatcher->PassPlatformSharedBuffer(); 298 299 if (!platform_shared_buffer) 300 return MOJO_RESULT_INVALID_ARGUMENT; 301 302 if (num_bytes) 303 *num_bytes = platform_shared_buffer->GetNumBytes(); 304 if (read_only) 305 *read_only = platform_shared_buffer->IsReadOnly(); 306 *shared_memory_handle = platform_shared_buffer->DuplicateSharedMemoryHandle(); 307 308 shm_dispatcher->Close(); 309 return result; 310 } 311 312 void Core::RequestShutdown(const base::Closure& callback) { 313 base::Closure on_shutdown; 314 if (base::ThreadTaskRunnerHandle::IsSet()) { 315 on_shutdown = base::Bind(base::IgnoreResult(&base::TaskRunner::PostTask), 316 base::ThreadTaskRunnerHandle::Get(), 317 FROM_HERE, callback); 318 } else { 319 on_shutdown = callback; 320 } 321 GetNodeController()->RequestShutdown(on_shutdown); 322 } 323 324 ScopedMessagePipeHandle Core::CreateParentMessagePipe( 325 const std::string& token, const std::string& child_token) { 326 RequestContext request_context; 327 ports::PortRef port0, port1; 328 GetNodeController()->node()->CreatePortPair(&port0, &port1); 329 MojoHandle handle = AddDispatcher( 330 new MessagePipeDispatcher(GetNodeController(), port0, 331 kUnknownPipeIdForDebug, 0)); 332 GetNodeController()->ReservePort(token, port1, child_token); 333 return ScopedMessagePipeHandle(MessagePipeHandle(handle)); 334 } 335 336 ScopedMessagePipeHandle Core::CreateChildMessagePipe(const std::string& token) { 337 RequestContext request_context; 338 ports::PortRef port0, port1; 339 GetNodeController()->node()->CreatePortPair(&port0, &port1); 340 MojoHandle handle = AddDispatcher( 341 new MessagePipeDispatcher(GetNodeController(), port0, 342 kUnknownPipeIdForDebug, 1)); 343 GetNodeController()->MergePortIntoParent(token, port1); 344 return ScopedMessagePipeHandle(MessagePipeHandle(handle)); 345 } 346 347 MojoResult Core::SetProperty(MojoPropertyType type, const void* value) { 348 base::AutoLock locker(property_lock_); 349 switch (type) { 350 case MOJO_PROPERTY_TYPE_SYNC_CALL_ALLOWED: 351 property_sync_call_allowed_ = *static_cast<const bool*>(value); 352 return MOJO_RESULT_OK; 353 default: 354 return MOJO_RESULT_INVALID_ARGUMENT; 355 } 356 } 357 358 MojoTimeTicks Core::GetTimeTicksNow() { 359 return base::TimeTicks::Now().ToInternalValue(); 360 } 361 362 MojoResult Core::Close(MojoHandle handle) { 363 RequestContext request_context; 364 scoped_refptr<Dispatcher> dispatcher; 365 { 366 base::AutoLock lock(handles_lock_); 367 MojoResult rv = handles_.GetAndRemoveDispatcher(handle, &dispatcher); 368 if (rv != MOJO_RESULT_OK) 369 return rv; 370 } 371 dispatcher->Close(); 372 return MOJO_RESULT_OK; 373 } 374 375 MojoResult Core::Wait(MojoHandle handle, 376 MojoHandleSignals signals, 377 MojoDeadline deadline, 378 MojoHandleSignalsState* signals_state) { 379 RequestContext request_context; 380 uint32_t unused = static_cast<uint32_t>(-1); 381 HandleSignalsState hss; 382 MojoResult rv = WaitManyInternal(&handle, &signals, 1, deadline, &unused, 383 signals_state ? &hss : nullptr); 384 if (rv != MOJO_RESULT_INVALID_ARGUMENT && signals_state) 385 *signals_state = hss; 386 return rv; 387 } 388 389 MojoResult Core::WaitMany(const MojoHandle* handles, 390 const MojoHandleSignals* signals, 391 uint32_t num_handles, 392 MojoDeadline deadline, 393 uint32_t* result_index, 394 MojoHandleSignalsState* signals_state) { 395 RequestContext request_context; 396 if (num_handles < 1) 397 return MOJO_RESULT_INVALID_ARGUMENT; 398 if (num_handles > GetConfiguration().max_wait_many_num_handles) 399 return MOJO_RESULT_RESOURCE_EXHAUSTED; 400 401 uint32_t index = static_cast<uint32_t>(-1); 402 MojoResult rv; 403 if (!signals_state) { 404 rv = WaitManyInternal(handles, signals, num_handles, deadline, &index, 405 nullptr); 406 } else { 407 // Note: The |reinterpret_cast| is safe, since |HandleSignalsState| is a 408 // subclass of |MojoHandleSignalsState| that doesn't add any data members. 409 rv = WaitManyInternal(handles, signals, num_handles, deadline, &index, 410 reinterpret_cast<HandleSignalsState*>(signals_state)); 411 } 412 if (index != static_cast<uint32_t>(-1) && result_index) 413 *result_index = index; 414 return rv; 415 } 416 417 MojoResult Core::Watch(MojoHandle handle, 418 MojoHandleSignals signals, 419 MojoWatchCallback callback, 420 uintptr_t context) { 421 RequestContext request_context; 422 scoped_refptr<Dispatcher> dispatcher = GetDispatcher(handle); 423 if (!dispatcher) 424 return MOJO_RESULT_INVALID_ARGUMENT; 425 return dispatcher->Watch( 426 signals, base::Bind(&CallWatchCallback, callback, context), context); 427 } 428 429 MojoResult Core::CancelWatch(MojoHandle handle, uintptr_t context) { 430 RequestContext request_context; 431 scoped_refptr<Dispatcher> dispatcher = GetDispatcher(handle); 432 if (!dispatcher) 433 return MOJO_RESULT_INVALID_ARGUMENT; 434 return dispatcher->CancelWatch(context); 435 } 436 437 MojoResult Core::AllocMessage(uint32_t num_bytes, 438 const MojoHandle* handles, 439 uint32_t num_handles, 440 MojoAllocMessageFlags flags, 441 MojoMessageHandle* message) { 442 if (!message) 443 return MOJO_RESULT_INVALID_ARGUMENT; 444 445 if (num_handles == 0) { // Fast path: no handles. 446 std::unique_ptr<MessageForTransit> msg; 447 MojoResult rv = MessageForTransit::Create(&msg, num_bytes, nullptr, 0); 448 if (rv != MOJO_RESULT_OK) 449 return rv; 450 451 *message = reinterpret_cast<MojoMessageHandle>(msg.release()); 452 return MOJO_RESULT_OK; 453 } 454 455 if (!handles) 456 return MOJO_RESULT_INVALID_ARGUMENT; 457 458 if (num_handles > kMaxHandlesPerMessage) 459 return MOJO_RESULT_RESOURCE_EXHAUSTED; 460 461 std::vector<Dispatcher::DispatcherInTransit> dispatchers; 462 { 463 base::AutoLock lock(handles_lock_); 464 MojoResult rv = handles_.BeginTransit(handles, num_handles, &dispatchers); 465 if (rv != MOJO_RESULT_OK) { 466 handles_.CancelTransit(dispatchers); 467 return rv; 468 } 469 } 470 DCHECK_EQ(num_handles, dispatchers.size()); 471 472 std::unique_ptr<MessageForTransit> msg; 473 MojoResult rv = MessageForTransit::Create( 474 &msg, num_bytes, dispatchers.data(), num_handles); 475 476 { 477 base::AutoLock lock(handles_lock_); 478 if (rv == MOJO_RESULT_OK) { 479 handles_.CompleteTransitAndClose(dispatchers); 480 *message = reinterpret_cast<MojoMessageHandle>(msg.release()); 481 } else { 482 handles_.CancelTransit(dispatchers); 483 } 484 } 485 486 return rv; 487 } 488 489 MojoResult Core::FreeMessage(MojoMessageHandle message) { 490 if (!message) 491 return MOJO_RESULT_INVALID_ARGUMENT; 492 493 delete reinterpret_cast<MessageForTransit*>(message); 494 495 return MOJO_RESULT_OK; 496 } 497 498 MojoResult Core::GetMessageBuffer(MojoMessageHandle message, void** buffer) { 499 if (!message) 500 return MOJO_RESULT_INVALID_ARGUMENT; 501 502 *buffer = reinterpret_cast<MessageForTransit*>(message)->mutable_bytes(); 503 504 return MOJO_RESULT_OK; 505 } 506 507 MojoResult Core::GetProperty(MojoPropertyType type, void* value) { 508 base::AutoLock locker(property_lock_); 509 switch (type) { 510 case MOJO_PROPERTY_TYPE_SYNC_CALL_ALLOWED: 511 *static_cast<bool*>(value) = property_sync_call_allowed_; 512 return MOJO_RESULT_OK; 513 default: 514 return MOJO_RESULT_INVALID_ARGUMENT; 515 } 516 } 517 518 MojoResult Core::CreateWaitSet(MojoHandle* wait_set_handle) { 519 RequestContext request_context; 520 if (!wait_set_handle) 521 return MOJO_RESULT_INVALID_ARGUMENT; 522 523 scoped_refptr<WaitSetDispatcher> dispatcher = new WaitSetDispatcher(); 524 MojoHandle h = AddDispatcher(dispatcher); 525 if (h == MOJO_HANDLE_INVALID) { 526 LOG(ERROR) << "Handle table full"; 527 dispatcher->Close(); 528 return MOJO_RESULT_RESOURCE_EXHAUSTED; 529 } 530 531 *wait_set_handle = h; 532 return MOJO_RESULT_OK; 533 } 534 535 MojoResult Core::AddHandle(MojoHandle wait_set_handle, 536 MojoHandle handle, 537 MojoHandleSignals signals) { 538 RequestContext request_context; 539 scoped_refptr<Dispatcher> wait_set_dispatcher(GetDispatcher(wait_set_handle)); 540 if (!wait_set_dispatcher) 541 return MOJO_RESULT_INVALID_ARGUMENT; 542 543 scoped_refptr<Dispatcher> dispatcher(GetDispatcher(handle)); 544 if (!dispatcher) 545 return MOJO_RESULT_INVALID_ARGUMENT; 546 547 return wait_set_dispatcher->AddWaitingDispatcher(dispatcher, signals, handle); 548 } 549 550 MojoResult Core::RemoveHandle(MojoHandle wait_set_handle, 551 MojoHandle handle) { 552 RequestContext request_context; 553 scoped_refptr<Dispatcher> wait_set_dispatcher(GetDispatcher(wait_set_handle)); 554 if (!wait_set_dispatcher) 555 return MOJO_RESULT_INVALID_ARGUMENT; 556 557 scoped_refptr<Dispatcher> dispatcher(GetDispatcher(handle)); 558 if (!dispatcher) 559 return MOJO_RESULT_INVALID_ARGUMENT; 560 561 return wait_set_dispatcher->RemoveWaitingDispatcher(dispatcher); 562 } 563 564 MojoResult Core::GetReadyHandles(MojoHandle wait_set_handle, 565 uint32_t* count, 566 MojoHandle* handles, 567 MojoResult* results, 568 MojoHandleSignalsState* signals_states) { 569 RequestContext request_context; 570 if (!handles || !count || !(*count) || !results) 571 return MOJO_RESULT_INVALID_ARGUMENT; 572 573 scoped_refptr<Dispatcher> wait_set_dispatcher(GetDispatcher(wait_set_handle)); 574 if (!wait_set_dispatcher) 575 return MOJO_RESULT_INVALID_ARGUMENT; 576 577 DispatcherVector awoken_dispatchers; 578 base::StackVector<uintptr_t, 16> contexts; 579 contexts->assign(*count, MOJO_HANDLE_INVALID); 580 581 MojoResult result = wait_set_dispatcher->GetReadyDispatchers( 582 count, &awoken_dispatchers, results, contexts->data()); 583 584 if (result == MOJO_RESULT_OK) { 585 for (size_t i = 0; i < *count; i++) { 586 handles[i] = static_cast<MojoHandle>(contexts[i]); 587 if (signals_states) 588 signals_states[i] = awoken_dispatchers[i]->GetHandleSignalsState(); 589 } 590 } 591 592 return result; 593 } 594 595 MojoResult Core::CreateMessagePipe( 596 const MojoCreateMessagePipeOptions* options, 597 MojoHandle* message_pipe_handle0, 598 MojoHandle* message_pipe_handle1) { 599 RequestContext request_context; 600 ports::PortRef port0, port1; 601 GetNodeController()->node()->CreatePortPair(&port0, &port1); 602 603 CHECK(message_pipe_handle0); 604 CHECK(message_pipe_handle1); 605 606 uint64_t pipe_id = base::RandUint64(); 607 608 *message_pipe_handle0 = AddDispatcher( 609 new MessagePipeDispatcher(GetNodeController(), port0, pipe_id, 0)); 610 if (*message_pipe_handle0 == MOJO_HANDLE_INVALID) 611 return MOJO_RESULT_RESOURCE_EXHAUSTED; 612 613 *message_pipe_handle1 = AddDispatcher( 614 new MessagePipeDispatcher(GetNodeController(), port1, pipe_id, 1)); 615 if (*message_pipe_handle1 == MOJO_HANDLE_INVALID) { 616 scoped_refptr<Dispatcher> unused; 617 unused->Close(); 618 619 base::AutoLock lock(handles_lock_); 620 handles_.GetAndRemoveDispatcher(*message_pipe_handle0, &unused); 621 return MOJO_RESULT_RESOURCE_EXHAUSTED; 622 } 623 624 return MOJO_RESULT_OK; 625 } 626 627 MojoResult Core::WriteMessage(MojoHandle message_pipe_handle, 628 const void* bytes, 629 uint32_t num_bytes, 630 const MojoHandle* handles, 631 uint32_t num_handles, 632 MojoWriteMessageFlags flags) { 633 if (num_bytes && !bytes) 634 return MOJO_RESULT_INVALID_ARGUMENT; 635 636 MojoMessageHandle message; 637 MojoResult rv = AllocMessage(num_bytes, handles, num_handles, 638 MOJO_ALLOC_MESSAGE_FLAG_NONE, &message); 639 if (rv != MOJO_RESULT_OK) 640 return rv; 641 642 if (num_bytes) { 643 void* buffer = nullptr; 644 rv = GetMessageBuffer(message, &buffer); 645 DCHECK_EQ(rv, MOJO_RESULT_OK); 646 memcpy(buffer, bytes, num_bytes); 647 } 648 649 return WriteMessageNew(message_pipe_handle, message, flags); 650 } 651 652 MojoResult Core::WriteMessageNew(MojoHandle message_pipe_handle, 653 MojoMessageHandle message, 654 MojoWriteMessageFlags flags) { 655 RequestContext request_context; 656 std::unique_ptr<MessageForTransit> message_for_transit( 657 reinterpret_cast<MessageForTransit*>(message)); 658 auto dispatcher = GetDispatcher(message_pipe_handle); 659 if (!dispatcher) 660 return MOJO_RESULT_INVALID_ARGUMENT; 661 662 return dispatcher->WriteMessage(std::move(message_for_transit), flags); 663 } 664 665 MojoResult Core::ReadMessage(MojoHandle message_pipe_handle, 666 void* bytes, 667 uint32_t* num_bytes, 668 MojoHandle* handles, 669 uint32_t* num_handles, 670 MojoReadMessageFlags flags) { 671 CHECK((!num_handles || !*num_handles || handles) && 672 (!num_bytes || !*num_bytes || bytes)); 673 RequestContext request_context; 674 auto dispatcher = GetDispatcher(message_pipe_handle); 675 if (!dispatcher) 676 return MOJO_RESULT_INVALID_ARGUMENT; 677 std::unique_ptr<MessageForTransit> message; 678 MojoResult rv = 679 dispatcher->ReadMessage(&message, num_bytes, handles, num_handles, flags, 680 false /* ignore_num_bytes */); 681 if (rv != MOJO_RESULT_OK) 682 return rv; 683 684 if (message && message->num_bytes()) 685 memcpy(bytes, message->bytes(), message->num_bytes()); 686 687 return MOJO_RESULT_OK; 688 } 689 690 MojoResult Core::ReadMessageNew(MojoHandle message_pipe_handle, 691 MojoMessageHandle* message, 692 uint32_t* num_bytes, 693 MojoHandle* handles, 694 uint32_t* num_handles, 695 MojoReadMessageFlags flags) { 696 CHECK(message); 697 CHECK(!num_handles || !*num_handles || handles); 698 RequestContext request_context; 699 auto dispatcher = GetDispatcher(message_pipe_handle); 700 if (!dispatcher) 701 return MOJO_RESULT_INVALID_ARGUMENT; 702 std::unique_ptr<MessageForTransit> msg; 703 MojoResult rv = 704 dispatcher->ReadMessage(&msg, num_bytes, handles, num_handles, flags, 705 true /* ignore_num_bytes */); 706 if (rv != MOJO_RESULT_OK) 707 return rv; 708 *message = reinterpret_cast<MojoMessageHandle>(msg.release()); 709 return MOJO_RESULT_OK; 710 } 711 712 MojoResult Core::FuseMessagePipes(MojoHandle handle0, MojoHandle handle1) { 713 RequestContext request_context; 714 scoped_refptr<Dispatcher> dispatcher0; 715 scoped_refptr<Dispatcher> dispatcher1; 716 717 bool valid_handles = true; 718 { 719 base::AutoLock lock(handles_lock_); 720 MojoResult result0 = handles_.GetAndRemoveDispatcher(handle0, &dispatcher0); 721 MojoResult result1 = handles_.GetAndRemoveDispatcher(handle1, &dispatcher1); 722 if (result0 != MOJO_RESULT_OK || result1 != MOJO_RESULT_OK || 723 dispatcher0->GetType() != Dispatcher::Type::MESSAGE_PIPE || 724 dispatcher1->GetType() != Dispatcher::Type::MESSAGE_PIPE) 725 valid_handles = false; 726 } 727 728 if (!valid_handles) { 729 if (dispatcher0) 730 dispatcher0->Close(); 731 if (dispatcher1) 732 dispatcher1->Close(); 733 return MOJO_RESULT_INVALID_ARGUMENT; 734 } 735 736 MessagePipeDispatcher* mpd0 = 737 static_cast<MessagePipeDispatcher*>(dispatcher0.get()); 738 MessagePipeDispatcher* mpd1 = 739 static_cast<MessagePipeDispatcher*>(dispatcher1.get()); 740 741 if (!mpd0->Fuse(mpd1)) 742 return MOJO_RESULT_FAILED_PRECONDITION; 743 744 return MOJO_RESULT_OK; 745 } 746 747 MojoResult Core::NotifyBadMessage(MojoMessageHandle message, 748 const char* error, 749 size_t error_num_bytes) { 750 if (!message) 751 return MOJO_RESULT_INVALID_ARGUMENT; 752 753 const PortsMessage& ports_message = 754 reinterpret_cast<MessageForTransit*>(message)->ports_message(); 755 if (ports_message.source_node() == ports::kInvalidNodeName) { 756 DVLOG(1) << "Received invalid message from unknown node."; 757 return MOJO_RESULT_OK; 758 } 759 760 GetNodeController()->NotifyBadMessageFrom( 761 ports_message.source_node(), std::string(error, error_num_bytes)); 762 return MOJO_RESULT_OK; 763 } 764 765 MojoResult Core::CreateDataPipe( 766 const MojoCreateDataPipeOptions* options, 767 MojoHandle* data_pipe_producer_handle, 768 MojoHandle* data_pipe_consumer_handle) { 769 RequestContext request_context; 770 if (options && options->struct_size != sizeof(MojoCreateDataPipeOptions)) 771 return MOJO_RESULT_INVALID_ARGUMENT; 772 773 MojoCreateDataPipeOptions create_options; 774 create_options.struct_size = sizeof(MojoCreateDataPipeOptions); 775 create_options.flags = options ? options->flags : 0; 776 create_options.element_num_bytes = options ? options->element_num_bytes : 1; 777 // TODO: Use Configuration to get default data pipe capacity. 778 create_options.capacity_num_bytes = 779 options && options->capacity_num_bytes ? options->capacity_num_bytes 780 : 64 * 1024; 781 782 // TODO: Broker through the parent when necessary. 783 scoped_refptr<PlatformSharedBuffer> ring_buffer = 784 GetNodeController()->CreateSharedBuffer( 785 create_options.capacity_num_bytes); 786 if (!ring_buffer) 787 return MOJO_RESULT_RESOURCE_EXHAUSTED; 788 789 ports::PortRef port0, port1; 790 GetNodeController()->node()->CreatePortPair(&port0, &port1); 791 792 CHECK(data_pipe_producer_handle); 793 CHECK(data_pipe_consumer_handle); 794 795 uint64_t pipe_id = base::RandUint64(); 796 797 scoped_refptr<Dispatcher> producer = new DataPipeProducerDispatcher( 798 GetNodeController(), port0, ring_buffer, create_options, 799 true /* initialized */, pipe_id); 800 scoped_refptr<Dispatcher> consumer = new DataPipeConsumerDispatcher( 801 GetNodeController(), port1, ring_buffer, create_options, 802 true /* initialized */, pipe_id); 803 804 *data_pipe_producer_handle = AddDispatcher(producer); 805 *data_pipe_consumer_handle = AddDispatcher(consumer); 806 if (*data_pipe_producer_handle == MOJO_HANDLE_INVALID || 807 *data_pipe_consumer_handle == MOJO_HANDLE_INVALID) { 808 if (*data_pipe_producer_handle != MOJO_HANDLE_INVALID) { 809 scoped_refptr<Dispatcher> unused; 810 base::AutoLock lock(handles_lock_); 811 handles_.GetAndRemoveDispatcher(*data_pipe_producer_handle, &unused); 812 } 813 producer->Close(); 814 consumer->Close(); 815 return MOJO_RESULT_RESOURCE_EXHAUSTED; 816 } 817 818 return MOJO_RESULT_OK; 819 } 820 821 MojoResult Core::WriteData(MojoHandle data_pipe_producer_handle, 822 const void* elements, 823 uint32_t* num_bytes, 824 MojoWriteDataFlags flags) { 825 RequestContext request_context; 826 scoped_refptr<Dispatcher> dispatcher( 827 GetDispatcher(data_pipe_producer_handle)); 828 if (!dispatcher) 829 return MOJO_RESULT_INVALID_ARGUMENT; 830 831 return dispatcher->WriteData(elements, num_bytes, flags); 832 } 833 834 MojoResult Core::BeginWriteData(MojoHandle data_pipe_producer_handle, 835 void** buffer, 836 uint32_t* buffer_num_bytes, 837 MojoWriteDataFlags flags) { 838 RequestContext request_context; 839 scoped_refptr<Dispatcher> dispatcher( 840 GetDispatcher(data_pipe_producer_handle)); 841 if (!dispatcher) 842 return MOJO_RESULT_INVALID_ARGUMENT; 843 844 return dispatcher->BeginWriteData(buffer, buffer_num_bytes, flags); 845 } 846 847 MojoResult Core::EndWriteData(MojoHandle data_pipe_producer_handle, 848 uint32_t num_bytes_written) { 849 RequestContext request_context; 850 scoped_refptr<Dispatcher> dispatcher( 851 GetDispatcher(data_pipe_producer_handle)); 852 if (!dispatcher) 853 return MOJO_RESULT_INVALID_ARGUMENT; 854 855 return dispatcher->EndWriteData(num_bytes_written); 856 } 857 858 MojoResult Core::ReadData(MojoHandle data_pipe_consumer_handle, 859 void* elements, 860 uint32_t* num_bytes, 861 MojoReadDataFlags flags) { 862 RequestContext request_context; 863 scoped_refptr<Dispatcher> dispatcher( 864 GetDispatcher(data_pipe_consumer_handle)); 865 if (!dispatcher) 866 return MOJO_RESULT_INVALID_ARGUMENT; 867 868 return dispatcher->ReadData(elements, num_bytes, flags); 869 } 870 871 MojoResult Core::BeginReadData(MojoHandle data_pipe_consumer_handle, 872 const void** buffer, 873 uint32_t* buffer_num_bytes, 874 MojoReadDataFlags flags) { 875 RequestContext request_context; 876 scoped_refptr<Dispatcher> dispatcher( 877 GetDispatcher(data_pipe_consumer_handle)); 878 if (!dispatcher) 879 return MOJO_RESULT_INVALID_ARGUMENT; 880 881 return dispatcher->BeginReadData(buffer, buffer_num_bytes, flags); 882 } 883 884 MojoResult Core::EndReadData(MojoHandle data_pipe_consumer_handle, 885 uint32_t num_bytes_read) { 886 RequestContext request_context; 887 scoped_refptr<Dispatcher> dispatcher( 888 GetDispatcher(data_pipe_consumer_handle)); 889 if (!dispatcher) 890 return MOJO_RESULT_INVALID_ARGUMENT; 891 892 return dispatcher->EndReadData(num_bytes_read); 893 } 894 895 MojoResult Core::CreateSharedBuffer( 896 const MojoCreateSharedBufferOptions* options, 897 uint64_t num_bytes, 898 MojoHandle* shared_buffer_handle) { 899 RequestContext request_context; 900 MojoCreateSharedBufferOptions validated_options = {}; 901 MojoResult result = SharedBufferDispatcher::ValidateCreateOptions( 902 options, &validated_options); 903 if (result != MOJO_RESULT_OK) 904 return result; 905 906 scoped_refptr<SharedBufferDispatcher> dispatcher; 907 result = SharedBufferDispatcher::Create( 908 validated_options, GetNodeController(), num_bytes, &dispatcher); 909 if (result != MOJO_RESULT_OK) { 910 DCHECK(!dispatcher); 911 return result; 912 } 913 914 *shared_buffer_handle = AddDispatcher(dispatcher); 915 if (*shared_buffer_handle == MOJO_HANDLE_INVALID) { 916 LOG(ERROR) << "Handle table full"; 917 dispatcher->Close(); 918 return MOJO_RESULT_RESOURCE_EXHAUSTED; 919 } 920 921 return MOJO_RESULT_OK; 922 } 923 924 MojoResult Core::DuplicateBufferHandle( 925 MojoHandle buffer_handle, 926 const MojoDuplicateBufferHandleOptions* options, 927 MojoHandle* new_buffer_handle) { 928 RequestContext request_context; 929 scoped_refptr<Dispatcher> dispatcher(GetDispatcher(buffer_handle)); 930 if (!dispatcher) 931 return MOJO_RESULT_INVALID_ARGUMENT; 932 933 // Don't verify |options| here; that's the dispatcher's job. 934 scoped_refptr<Dispatcher> new_dispatcher; 935 MojoResult result = 936 dispatcher->DuplicateBufferHandle(options, &new_dispatcher); 937 if (result != MOJO_RESULT_OK) 938 return result; 939 940 *new_buffer_handle = AddDispatcher(new_dispatcher); 941 if (*new_buffer_handle == MOJO_HANDLE_INVALID) { 942 LOG(ERROR) << "Handle table full"; 943 dispatcher->Close(); 944 return MOJO_RESULT_RESOURCE_EXHAUSTED; 945 } 946 947 return MOJO_RESULT_OK; 948 } 949 950 MojoResult Core::MapBuffer(MojoHandle buffer_handle, 951 uint64_t offset, 952 uint64_t num_bytes, 953 void** buffer, 954 MojoMapBufferFlags flags) { 955 RequestContext request_context; 956 scoped_refptr<Dispatcher> dispatcher(GetDispatcher(buffer_handle)); 957 if (!dispatcher) 958 return MOJO_RESULT_INVALID_ARGUMENT; 959 960 std::unique_ptr<PlatformSharedBufferMapping> mapping; 961 MojoResult result = dispatcher->MapBuffer(offset, num_bytes, flags, &mapping); 962 if (result != MOJO_RESULT_OK) 963 return result; 964 965 DCHECK(mapping); 966 void* address = mapping->GetBase(); 967 { 968 base::AutoLock locker(mapping_table_lock_); 969 result = mapping_table_.AddMapping(std::move(mapping)); 970 } 971 if (result != MOJO_RESULT_OK) 972 return result; 973 974 *buffer = address; 975 return MOJO_RESULT_OK; 976 } 977 978 MojoResult Core::UnmapBuffer(void* buffer) { 979 RequestContext request_context; 980 base::AutoLock lock(mapping_table_lock_); 981 return mapping_table_.RemoveMapping(buffer); 982 } 983 984 MojoResult Core::WrapPlatformHandle(const MojoPlatformHandle* platform_handle, 985 MojoHandle* mojo_handle) { 986 ScopedPlatformHandle handle; 987 MojoResult result = MojoPlatformHandleToScopedPlatformHandle(platform_handle, 988 &handle); 989 if (result != MOJO_RESULT_OK) 990 return result; 991 992 return CreatePlatformHandleWrapper(std::move(handle), mojo_handle); 993 } 994 995 MojoResult Core::UnwrapPlatformHandle(MojoHandle mojo_handle, 996 MojoPlatformHandle* platform_handle) { 997 ScopedPlatformHandle handle; 998 MojoResult result = PassWrappedPlatformHandle(mojo_handle, &handle); 999 if (result != MOJO_RESULT_OK) 1000 return result; 1001 1002 return ScopedPlatformHandleToMojoPlatformHandle(std::move(handle), 1003 platform_handle); 1004 } 1005 1006 MojoResult Core::WrapPlatformSharedBufferHandle( 1007 const MojoPlatformHandle* platform_handle, 1008 size_t size, 1009 MojoPlatformSharedBufferHandleFlags flags, 1010 MojoHandle* mojo_handle) { 1011 DCHECK(size); 1012 ScopedPlatformHandle handle; 1013 MojoResult result = MojoPlatformHandleToScopedPlatformHandle(platform_handle, 1014 &handle); 1015 if (result != MOJO_RESULT_OK) 1016 return result; 1017 1018 bool read_only = flags & MOJO_PLATFORM_SHARED_BUFFER_HANDLE_FLAG_READ_ONLY; 1019 scoped_refptr<PlatformSharedBuffer> platform_buffer = 1020 PlatformSharedBuffer::CreateFromPlatformHandle(size, read_only, 1021 std::move(handle)); 1022 if (!platform_buffer) 1023 return MOJO_RESULT_UNKNOWN; 1024 1025 scoped_refptr<SharedBufferDispatcher> dispatcher; 1026 result = SharedBufferDispatcher::CreateFromPlatformSharedBuffer( 1027 platform_buffer, &dispatcher); 1028 if (result != MOJO_RESULT_OK) 1029 return result; 1030 1031 MojoHandle h = AddDispatcher(dispatcher); 1032 if (h == MOJO_HANDLE_INVALID) { 1033 dispatcher->Close(); 1034 return MOJO_RESULT_RESOURCE_EXHAUSTED; 1035 } 1036 1037 *mojo_handle = h; 1038 return MOJO_RESULT_OK; 1039 } 1040 1041 MojoResult Core::UnwrapPlatformSharedBufferHandle( 1042 MojoHandle mojo_handle, 1043 MojoPlatformHandle* platform_handle, 1044 size_t* size, 1045 MojoPlatformSharedBufferHandleFlags* flags) { 1046 scoped_refptr<Dispatcher> dispatcher; 1047 MojoResult result = MOJO_RESULT_OK; 1048 { 1049 base::AutoLock lock(handles_lock_); 1050 result = handles_.GetAndRemoveDispatcher(mojo_handle, &dispatcher); 1051 if (result != MOJO_RESULT_OK) 1052 return result; 1053 } 1054 1055 if (dispatcher->GetType() != Dispatcher::Type::SHARED_BUFFER) { 1056 dispatcher->Close(); 1057 return MOJO_RESULT_INVALID_ARGUMENT; 1058 } 1059 1060 SharedBufferDispatcher* shm_dispatcher = 1061 static_cast<SharedBufferDispatcher*>(dispatcher.get()); 1062 scoped_refptr<PlatformSharedBuffer> platform_shared_buffer = 1063 shm_dispatcher->PassPlatformSharedBuffer(); 1064 CHECK(platform_shared_buffer); 1065 1066 CHECK(size); 1067 *size = platform_shared_buffer->GetNumBytes(); 1068 1069 CHECK(flags); 1070 *flags = MOJO_PLATFORM_SHARED_BUFFER_HANDLE_FLAG_NONE; 1071 if (platform_shared_buffer->IsReadOnly()) 1072 *flags |= MOJO_PLATFORM_SHARED_BUFFER_HANDLE_FLAG_READ_ONLY; 1073 1074 ScopedPlatformHandle handle = platform_shared_buffer->PassPlatformHandle(); 1075 return ScopedPlatformHandleToMojoPlatformHandle(std::move(handle), 1076 platform_handle); 1077 } 1078 1079 void Core::GetActiveHandlesForTest(std::vector<MojoHandle>* handles) { 1080 base::AutoLock lock(handles_lock_); 1081 handles_.GetActiveHandlesForTest(handles); 1082 } 1083 1084 MojoResult Core::WaitManyInternal(const MojoHandle* handles, 1085 const MojoHandleSignals* signals, 1086 uint32_t num_handles, 1087 MojoDeadline deadline, 1088 uint32_t *result_index, 1089 HandleSignalsState* signals_states) { 1090 CHECK(handles); 1091 CHECK(signals); 1092 DCHECK_GT(num_handles, 0u); 1093 if (result_index) { 1094 DCHECK_EQ(*result_index, static_cast<uint32_t>(-1)); 1095 } 1096 1097 // The primary caller of |WaitManyInternal()| is |Wait()|, which only waits on 1098 // a single handle. In the common case of a single handle, this avoid a heap 1099 // allocation. 1100 base::StackVector<scoped_refptr<Dispatcher>, 1> dispatchers; 1101 dispatchers->reserve(num_handles); 1102 for (uint32_t i = 0; i < num_handles; i++) { 1103 scoped_refptr<Dispatcher> dispatcher = GetDispatcher(handles[i]); 1104 if (!dispatcher) { 1105 if (result_index) 1106 *result_index = i; 1107 return MOJO_RESULT_INVALID_ARGUMENT; 1108 } 1109 dispatchers->push_back(dispatcher); 1110 } 1111 1112 // TODO(vtl): Should make the waiter live (permanently) in TLS. 1113 Waiter waiter; 1114 waiter.Init(); 1115 1116 uint32_t i; 1117 MojoResult rv = MOJO_RESULT_OK; 1118 for (i = 0; i < num_handles; i++) { 1119 rv = dispatchers[i]->AddAwakable( 1120 &waiter, signals[i], i, signals_states ? &signals_states[i] : nullptr); 1121 if (rv != MOJO_RESULT_OK) { 1122 if (result_index) 1123 *result_index = i; 1124 break; 1125 } 1126 } 1127 uint32_t num_added = i; 1128 1129 if (rv == MOJO_RESULT_ALREADY_EXISTS) { 1130 rv = MOJO_RESULT_OK; // The i-th one is already "triggered". 1131 } else if (rv == MOJO_RESULT_OK) { 1132 uintptr_t uintptr_result = *result_index; 1133 rv = waiter.Wait(deadline, &uintptr_result); 1134 *result_index = static_cast<uint32_t>(uintptr_result); 1135 } 1136 1137 // Make sure no other dispatchers try to wake |waiter| for the current 1138 // |Wait()|/|WaitMany()| call. (Only after doing this can |waiter| be 1139 // destroyed, but this would still be required if the waiter were in TLS.) 1140 for (i = 0; i < num_added; i++) { 1141 dispatchers[i]->RemoveAwakable( 1142 &waiter, signals_states ? &signals_states[i] : nullptr); 1143 } 1144 if (signals_states) { 1145 for (; i < num_handles; i++) 1146 signals_states[i] = dispatchers[i]->GetHandleSignalsState(); 1147 } 1148 1149 return rv; 1150 } 1151 1152 // static 1153 void Core::PassNodeControllerToIOThread( 1154 std::unique_ptr<NodeController> node_controller) { 1155 // It's OK to leak this reference. At this point we know the IO loop is still 1156 // running, and we know the NodeController will observe its eventual 1157 // destruction. This tells the NodeController to delete itself when that 1158 // happens. 1159 node_controller.release()->DestroyOnIOThreadShutdown(); 1160 } 1161 1162 } // namespace edk 1163 } // namespace mojo 1164