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