OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 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 | 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/core.h" | 5 #include "mojo/edk/system/core.h" |
6 | 6 |
7 #include <string.h> | 7 #include <string.h> |
8 | 8 |
9 #include <utility> | 9 #include <utility> |
10 | 10 |
11 #include "base/bind.h" | 11 #include "base/bind.h" |
12 #include "base/containers/stack_container.h" | 12 #include "base/containers/stack_container.h" |
13 #include "base/location.h" | 13 #include "base/location.h" |
14 #include "base/logging.h" | 14 #include "base/logging.h" |
15 #include "base/macros.h" | 15 #include "base/macros.h" |
16 #include "base/message_loop/message_loop.h" | 16 #include "base/message_loop/message_loop.h" |
17 #include "base/rand_util.h" | 17 #include "base/rand_util.h" |
18 #include "base/thread_task_runner_handle.h" | 18 #include "base/thread_task_runner_handle.h" |
19 #include "base/time/time.h" | 19 #include "base/time/time.h" |
20 #include "crypto/random.h" | 20 #include "crypto/random.h" |
21 #include "mojo/edk/embedder/embedder.h" | 21 #include "mojo/edk/embedder/embedder.h" |
22 #include "mojo/edk/embedder/embedder_internal.h" | 22 #include "mojo/edk/embedder/embedder_internal.h" |
23 #include "mojo/edk/embedder/platform_shared_buffer.h" | 23 #include "mojo/edk/embedder/platform_shared_buffer.h" |
24 #include "mojo/edk/system/async_waiter.h" | 24 #include "mojo/edk/system/async_waiter.h" |
25 #include "mojo/edk/system/channel.h" | 25 #include "mojo/edk/system/channel.h" |
26 #include "mojo/edk/system/configuration.h" | 26 #include "mojo/edk/system/configuration.h" |
27 #include "mojo/edk/system/data_pipe_consumer_dispatcher.h" | 27 #include "mojo/edk/system/data_pipe_consumer_dispatcher.h" |
28 #include "mojo/edk/system/data_pipe_producer_dispatcher.h" | 28 #include "mojo/edk/system/data_pipe_producer_dispatcher.h" |
29 #include "mojo/edk/system/handle_signals_state.h" | 29 #include "mojo/edk/system/handle_signals_state.h" |
| 30 #include "mojo/edk/system/message_for_transit.h" |
30 #include "mojo/edk/system/message_pipe_dispatcher.h" | 31 #include "mojo/edk/system/message_pipe_dispatcher.h" |
31 #include "mojo/edk/system/platform_handle_dispatcher.h" | 32 #include "mojo/edk/system/platform_handle_dispatcher.h" |
32 #include "mojo/edk/system/ports/node.h" | 33 #include "mojo/edk/system/ports/node.h" |
33 #include "mojo/edk/system/remote_message_pipe_bootstrap.h" | 34 #include "mojo/edk/system/remote_message_pipe_bootstrap.h" |
34 #include "mojo/edk/system/request_context.h" | 35 #include "mojo/edk/system/request_context.h" |
35 #include "mojo/edk/system/shared_buffer_dispatcher.h" | 36 #include "mojo/edk/system/shared_buffer_dispatcher.h" |
36 #include "mojo/edk/system/wait_set_dispatcher.h" | 37 #include "mojo/edk/system/wait_set_dispatcher.h" |
37 #include "mojo/edk/system/waiter.h" | 38 #include "mojo/edk/system/waiter.h" |
38 | 39 |
39 namespace mojo { | 40 namespace mojo { |
(...skipping 310 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
350 } | 351 } |
351 | 352 |
352 MojoResult Core::CancelWatch(MojoHandle handle, uintptr_t context) { | 353 MojoResult Core::CancelWatch(MojoHandle handle, uintptr_t context) { |
353 RequestContext request_context; | 354 RequestContext request_context; |
354 scoped_refptr<Dispatcher> dispatcher = GetDispatcher(handle); | 355 scoped_refptr<Dispatcher> dispatcher = GetDispatcher(handle); |
355 if (!dispatcher) | 356 if (!dispatcher) |
356 return MOJO_RESULT_INVALID_ARGUMENT; | 357 return MOJO_RESULT_INVALID_ARGUMENT; |
357 return dispatcher->CancelWatch(context); | 358 return dispatcher->CancelWatch(context); |
358 } | 359 } |
359 | 360 |
| 361 MojoResult Core::CreateMessage(uint32_t num_bytes, |
| 362 const MojoHandle* handles, |
| 363 uint32_t num_handles, |
| 364 MojoCreateMessageFlags flags, |
| 365 void** message) { |
| 366 if (!message) |
| 367 return MOJO_RESULT_INVALID_ARGUMENT; |
| 368 |
| 369 if (num_handles == 0) { // Fast path: no handles. |
| 370 MessageForTransit* msg; |
| 371 MojoResult rv = MessageForTransit::Create(&msg, num_bytes, nullptr, 0); |
| 372 if (rv != MOJO_RESULT_OK) |
| 373 return rv; |
| 374 |
| 375 *message = static_cast<void*>(msg); |
| 376 return MOJO_RESULT_OK; |
| 377 } |
| 378 |
| 379 if (!handles) |
| 380 return MOJO_RESULT_INVALID_ARGUMENT; |
| 381 |
| 382 if (num_handles > kMaxHandlesPerMessage) |
| 383 return MOJO_RESULT_RESOURCE_EXHAUSTED; |
| 384 |
| 385 std::vector<Dispatcher::DispatcherInTransit> dispatchers; |
| 386 { |
| 387 base::AutoLock lock(handles_lock_); |
| 388 MojoResult rv = handles_.BeginTransit(handles, num_handles, &dispatchers); |
| 389 if (rv != MOJO_RESULT_OK) { |
| 390 handles_.CancelTransit(dispatchers); |
| 391 return rv; |
| 392 } |
| 393 } |
| 394 DCHECK_EQ(num_handles, dispatchers.size()); |
| 395 |
| 396 MessageForTransit* msg = nullptr; |
| 397 MojoResult rv = MessageForTransit::Create( |
| 398 &msg, num_bytes, dispatchers.data(), num_handles); |
| 399 |
| 400 { |
| 401 base::AutoLock lock(handles_lock_); |
| 402 if (rv == MOJO_RESULT_OK) { |
| 403 handles_.CompleteTransitAndClose(dispatchers); |
| 404 *message = static_cast<void*>(msg); |
| 405 } else { |
| 406 handles_.CancelTransit(dispatchers); |
| 407 } |
| 408 } |
| 409 |
| 410 return rv; |
| 411 } |
| 412 |
| 413 MojoResult Core::DestroyMessage(void* message_ptr) { |
| 414 if (!message_ptr) |
| 415 return MOJO_RESULT_INVALID_ARGUMENT; |
| 416 |
| 417 MessageForTransit* message = static_cast<MessageForTransit*>(message_ptr); |
| 418 delete message; |
| 419 |
| 420 return MOJO_RESULT_OK; |
| 421 } |
| 422 |
| 423 MojoResult Core::GetMessageBuffer(void* message_ptr, void** buffer) { |
| 424 if (!message_ptr) |
| 425 return MOJO_RESULT_INVALID_ARGUMENT; |
| 426 |
| 427 MessageForTransit* message = static_cast<MessageForTransit*>(message_ptr); |
| 428 *buffer = message->mutable_bytes(); |
| 429 return MOJO_RESULT_OK; |
| 430 } |
| 431 |
360 MojoResult Core::CreateWaitSet(MojoHandle* wait_set_handle) { | 432 MojoResult Core::CreateWaitSet(MojoHandle* wait_set_handle) { |
361 RequestContext request_context; | 433 RequestContext request_context; |
362 if (!wait_set_handle) | 434 if (!wait_set_handle) |
363 return MOJO_RESULT_INVALID_ARGUMENT; | 435 return MOJO_RESULT_INVALID_ARGUMENT; |
364 | 436 |
365 scoped_refptr<WaitSetDispatcher> dispatcher = new WaitSetDispatcher(); | 437 scoped_refptr<WaitSetDispatcher> dispatcher = new WaitSetDispatcher(); |
366 MojoHandle h = AddDispatcher(dispatcher); | 438 MojoHandle h = AddDispatcher(dispatcher); |
367 if (h == MOJO_HANDLE_INVALID) { | 439 if (h == MOJO_HANDLE_INVALID) { |
368 LOG(ERROR) << "Handle table full"; | 440 LOG(ERROR) << "Handle table full"; |
369 dispatcher->Close(); | 441 dispatcher->Close(); |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
465 | 537 |
466 return MOJO_RESULT_OK; | 538 return MOJO_RESULT_OK; |
467 } | 539 } |
468 | 540 |
469 MojoResult Core::WriteMessage(MojoHandle message_pipe_handle, | 541 MojoResult Core::WriteMessage(MojoHandle message_pipe_handle, |
470 const void* bytes, | 542 const void* bytes, |
471 uint32_t num_bytes, | 543 uint32_t num_bytes, |
472 const MojoHandle* handles, | 544 const MojoHandle* handles, |
473 uint32_t num_handles, | 545 uint32_t num_handles, |
474 MojoWriteMessageFlags flags) { | 546 MojoWriteMessageFlags flags) { |
475 RequestContext request_context; | 547 MessageForTransit* msg = nullptr; |
476 auto dispatcher = GetDispatcher(message_pipe_handle); | 548 MojoResult rv = MOJO_RESULT_OK; |
477 if (!dispatcher) | 549 std::vector<Dispatcher::DispatcherInTransit> dispatchers; |
478 return MOJO_RESULT_INVALID_ARGUMENT; | |
479 | 550 |
480 if (num_handles == 0) // Fast path: no handles. | 551 if (num_handles == 0) { // Fast path: no handles. |
481 return dispatcher->WriteMessage(bytes, num_bytes, nullptr, 0, flags); | 552 rv = MessageForTransit::Create(&msg, num_bytes, nullptr, 0); |
| 553 if (rv != MOJO_RESULT_OK) |
| 554 return rv; |
| 555 } else { |
| 556 CHECK(handles); |
482 | 557 |
483 CHECK(handles); | 558 if (num_handles > kMaxHandlesPerMessage) |
| 559 return MOJO_RESULT_RESOURCE_EXHAUSTED; |
484 | 560 |
485 if (num_handles > kMaxHandlesPerMessage) | 561 for (size_t i = 0; i < num_handles; ++i) { |
486 return MOJO_RESULT_RESOURCE_EXHAUSTED; | 562 if (handles[i] == message_pipe_handle) |
| 563 return MOJO_RESULT_BUSY; |
| 564 } |
487 | 565 |
488 for (size_t i = 0; i < num_handles; ++i) { | 566 { |
489 if (message_pipe_handle == handles[i]) | 567 base::AutoLock lock(handles_lock_); |
490 return MOJO_RESULT_BUSY; | 568 MojoResult rv = handles_.BeginTransit(handles, num_handles, &dispatchers); |
| 569 if (rv != MOJO_RESULT_OK) { |
| 570 handles_.CancelTransit(dispatchers); |
| 571 return rv; |
| 572 } |
| 573 } |
| 574 DCHECK_EQ(num_handles, dispatchers.size()); |
| 575 |
| 576 rv = MessageForTransit::Create( |
| 577 &msg, num_bytes, dispatchers.data(), num_handles); |
491 } | 578 } |
492 | 579 |
493 std::vector<Dispatcher::DispatcherInTransit> dispatchers; | 580 std::unique_ptr<MessageForTransit> message(msg); |
494 { | 581 if (rv == MOJO_RESULT_OK) { |
495 base::AutoLock lock(handles_lock_); | 582 DCHECK(message); |
496 MojoResult rv = handles_.BeginTransit(handles, num_handles, &dispatchers); | 583 if (num_bytes) |
497 if (rv != MOJO_RESULT_OK) { | 584 memcpy(message->mutable_bytes(), bytes, num_bytes); |
498 handles_.CancelTransit(dispatchers); | 585 |
499 return rv; | 586 rv = WriteMessageNew( |
500 } | 587 message_pipe_handle, static_cast<void*>(message.release()), flags); |
501 } | 588 } |
502 DCHECK_EQ(num_handles, dispatchers.size()); | |
503 | 589 |
504 MojoResult rv = dispatcher->WriteMessage( | 590 if (num_handles) { |
505 bytes, num_bytes, dispatchers.data(), num_handles, flags); | |
506 | |
507 { | |
508 base::AutoLock lock(handles_lock_); | 591 base::AutoLock lock(handles_lock_); |
509 if (rv == MOJO_RESULT_OK) { | 592 if (rv == MOJO_RESULT_OK) { |
510 handles_.CompleteTransitAndClose(dispatchers); | 593 handles_.CompleteTransitAndClose(dispatchers); |
511 } else { | 594 } else { |
512 handles_.CancelTransit(dispatchers); | 595 handles_.CancelTransit(dispatchers); |
513 } | 596 } |
514 } | 597 } |
515 | 598 |
516 return rv; | 599 return rv; |
517 } | 600 } |
518 | 601 |
| 602 MojoResult Core::WriteMessageNew(MojoHandle message_pipe_handle, |
| 603 void* message_ptr, |
| 604 MojoWriteMessageFlags flags) { |
| 605 RequestContext request_context; |
| 606 std::unique_ptr<MessageForTransit> message( |
| 607 static_cast<MessageForTransit*>(message_ptr)); |
| 608 auto dispatcher = GetDispatcher(message_pipe_handle); |
| 609 if (!dispatcher) |
| 610 return MOJO_RESULT_INVALID_ARGUMENT; |
| 611 |
| 612 return dispatcher->WriteMessage(std::move(message), flags); |
| 613 } |
| 614 |
519 MojoResult Core::ReadMessage(MojoHandle message_pipe_handle, | 615 MojoResult Core::ReadMessage(MojoHandle message_pipe_handle, |
520 void* bytes, | 616 void* bytes, |
521 uint32_t* num_bytes, | 617 uint32_t* num_bytes, |
522 MojoHandle* handles, | 618 MojoHandle* handles, |
523 uint32_t* num_handles, | 619 uint32_t* num_handles, |
524 MojoReadMessageFlags flags) { | 620 MojoReadMessageFlags flags) { |
525 RequestContext request_context; | |
526 CHECK((!num_handles || !*num_handles || handles) && | 621 CHECK((!num_handles || !*num_handles || handles) && |
527 (!num_bytes || !*num_bytes || bytes)); | 622 (!num_bytes || !*num_bytes || bytes)); |
| 623 RequestContext request_context; |
528 auto dispatcher = GetDispatcher(message_pipe_handle); | 624 auto dispatcher = GetDispatcher(message_pipe_handle); |
529 if (!dispatcher) | 625 if (!dispatcher) |
530 return MOJO_RESULT_INVALID_ARGUMENT; | 626 return MOJO_RESULT_INVALID_ARGUMENT; |
531 return dispatcher->ReadMessage(bytes, num_bytes, handles, num_handles, flags); | 627 std::unique_ptr<MessageForTransit> message; |
| 628 MojoResult rv = |
| 629 dispatcher->ReadMessage(&message, num_bytes, handles, num_handles, flags, |
| 630 false /* ignore_num_bytes */); |
| 631 if (rv != MOJO_RESULT_OK) |
| 632 return rv; |
| 633 |
| 634 if (message && message->num_bytes()) |
| 635 memcpy(bytes, message->bytes(), message->num_bytes()); |
| 636 |
| 637 return MOJO_RESULT_OK; |
| 638 } |
| 639 |
| 640 MojoResult Core::ReadMessageNew(MojoHandle message_pipe_handle, |
| 641 void** message, |
| 642 uint32_t* num_bytes, |
| 643 MojoHandle* handles, |
| 644 uint32_t* num_handles, |
| 645 MojoReadMessageFlags flags) { |
| 646 CHECK(message); |
| 647 CHECK(!num_handles || !*num_handles || handles); |
| 648 RequestContext request_context; |
| 649 auto dispatcher = GetDispatcher(message_pipe_handle); |
| 650 if (!dispatcher) |
| 651 return MOJO_RESULT_INVALID_ARGUMENT; |
| 652 std::unique_ptr<MessageForTransit> msg; |
| 653 MojoResult rv = |
| 654 dispatcher->ReadMessage(&msg, num_bytes, handles, num_handles, flags, |
| 655 true /* ignore_num_bytes */); |
| 656 if (rv != MOJO_RESULT_OK) |
| 657 return rv; |
| 658 *message = static_cast<void*>(msg.release()); |
| 659 return MOJO_RESULT_OK; |
532 } | 660 } |
533 | 661 |
534 MojoResult Core::FuseMessagePipes(MojoHandle handle0, MojoHandle handle1) { | 662 MojoResult Core::FuseMessagePipes(MojoHandle handle0, MojoHandle handle1) { |
535 RequestContext request_context; | 663 RequestContext request_context; |
536 scoped_refptr<Dispatcher> dispatcher0; | 664 scoped_refptr<Dispatcher> dispatcher0; |
537 scoped_refptr<Dispatcher> dispatcher1; | 665 scoped_refptr<Dispatcher> dispatcher1; |
538 | 666 |
539 bool valid_handles = true; | 667 bool valid_handles = true; |
540 { | 668 { |
541 base::AutoLock lock(handles_lock_); | 669 base::AutoLock lock(handles_lock_); |
(...skipping 321 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
863 scoped_ptr<NodeController> node_controller) { | 991 scoped_ptr<NodeController> node_controller) { |
864 // It's OK to leak this reference. At this point we know the IO loop is still | 992 // It's OK to leak this reference. At this point we know the IO loop is still |
865 // running, and we know the NodeController will observe its eventual | 993 // running, and we know the NodeController will observe its eventual |
866 // destruction. This tells the NodeController to delete itself when that | 994 // destruction. This tells the NodeController to delete itself when that |
867 // happens. | 995 // happens. |
868 node_controller.release()->DestroyOnIOThreadShutdown(); | 996 node_controller.release()->DestroyOnIOThreadShutdown(); |
869 } | 997 } |
870 | 998 |
871 } // namespace edk | 999 } // namespace edk |
872 } // namespace mojo | 1000 } // namespace mojo |
OLD | NEW |