Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 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/node_channel.h" | 5 #include "mojo/edk/system/node_channel.h" |
| 6 | 6 |
| 7 #include <cstring> | 7 #include <cstring> |
| 8 #include <limits> | 8 #include <limits> |
| 9 #include <sstream> | 9 #include <sstream> |
| 10 | 10 |
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 120 Channel::MessagePtr message( | 120 Channel::MessagePtr message( |
| 121 new Channel::Message(sizeof(Header) + payload_size, num_handles)); | 121 new Channel::Message(sizeof(Header) + payload_size, num_handles)); |
| 122 Header* header = reinterpret_cast<Header*>(message->mutable_payload()); | 122 Header* header = reinterpret_cast<Header*>(message->mutable_payload()); |
| 123 header->type = type; | 123 header->type = type; |
| 124 header->padding = 0; | 124 header->padding = 0; |
| 125 *out_data = reinterpret_cast<DataType*>(&header[1]); | 125 *out_data = reinterpret_cast<DataType*>(&header[1]); |
| 126 return message; | 126 return message; |
| 127 } | 127 } |
| 128 | 128 |
| 129 template <typename DataType> | 129 template <typename DataType> |
| 130 void GetMessagePayload(const void* bytes, DataType** out_data) { | 130 bool GetMessagePayload(const void* bytes, |
| 131 size_t num_bytes, | |
| 132 DataType** out_data) { | |
| 133 static_assert(sizeof(DataType) > 0, "DataType must have non-zero size."); | |
| 134 if (num_bytes < sizeof(Header) + sizeof(DataType)) | |
| 135 return false; | |
| 131 *out_data = reinterpret_cast<const DataType*>( | 136 *out_data = reinterpret_cast<const DataType*>( |
| 132 static_cast<const char*>(bytes) + sizeof(Header)); | 137 static_cast<const char*>(bytes) + sizeof(Header)); |
| 138 return true; | |
| 133 } | 139 } |
| 134 | 140 |
| 135 } // namespace | 141 } // namespace |
| 136 | 142 |
| 137 // static | 143 // static |
| 138 scoped_refptr<NodeChannel> NodeChannel::Create( | 144 scoped_refptr<NodeChannel> NodeChannel::Create( |
| 139 Delegate* delegate, | 145 Delegate* delegate, |
| 140 ScopedPlatformHandle platform_handle, | 146 ScopedPlatformHandle platform_handle, |
| 141 scoped_refptr<base::TaskRunner> io_task_runner) { | 147 scoped_refptr<base::TaskRunner> io_task_runner) { |
| 142 return new NodeChannel(delegate, std::move(platform_handle), io_task_runner); | 148 return new NodeChannel(delegate, std::move(platform_handle), io_task_runner); |
| (...skipping 275 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 418 { | 424 { |
| 419 MachPortRelay* relay = delegate_->GetMachPortRelay(); | 425 MachPortRelay* relay = delegate_->GetMachPortRelay(); |
| 420 if (handles && !relay) { | 426 if (handles && !relay) { |
| 421 if (!MachPortRelay::ReceivePorts(handles.get())) { | 427 if (!MachPortRelay::ReceivePorts(handles.get())) { |
| 422 LOG(ERROR) << "Error receiving mach ports."; | 428 LOG(ERROR) << "Error receiving mach ports."; |
| 423 } | 429 } |
| 424 } | 430 } |
| 425 } | 431 } |
| 426 #endif // defined(OS_WIN) | 432 #endif // defined(OS_WIN) |
| 427 | 433 |
| 434 | |
| 435 if (payload_size <= sizeof(Header)) { | |
| 436 delegate_->OnChannelError(remote_node_name_); | |
| 437 return; | |
| 438 } | |
| 439 | |
| 428 const Header* header = static_cast<const Header*>(payload); | 440 const Header* header = static_cast<const Header*>(payload); |
| 429 switch (header->type) { | 441 switch (header->type) { |
| 430 case MessageType::ACCEPT_CHILD: { | 442 case MessageType::ACCEPT_CHILD: { |
| 431 const AcceptChildData* data; | 443 const AcceptChildData* data; |
| 432 GetMessagePayload(payload, &data); | 444 if (GetMessagePayload(payload, payload_size, &data)) { |
| 433 delegate_->OnAcceptChild(remote_node_name_, data->parent_name, | 445 delegate_->OnAcceptChild(remote_node_name_, data->parent_name, |
| 434 data->token); | 446 data->token); |
| 447 return; | |
| 448 } | |
| 435 break; | 449 break; |
| 436 } | 450 } |
| 437 | 451 |
| 438 case MessageType::ACCEPT_PARENT: { | 452 case MessageType::ACCEPT_PARENT: { |
| 439 const AcceptParentData* data; | 453 const AcceptParentData* data; |
| 440 GetMessagePayload(payload, &data); | 454 if (GetMessagePayload(payload, payload_size, &data)) { |
| 441 delegate_->OnAcceptParent(remote_node_name_, data->token, | 455 delegate_->OnAcceptParent(remote_node_name_, data->token, |
| 442 data->child_name); | 456 data->child_name); |
| 457 return; | |
| 458 } | |
| 443 break; | 459 break; |
| 444 } | 460 } |
| 445 | 461 |
| 446 case MessageType::ADD_BROKER_CLIENT: { | 462 case MessageType::ADD_BROKER_CLIENT: { |
| 447 const AddBrokerClientData* data; | 463 const AddBrokerClientData* data; |
| 448 GetMessagePayload(payload, &data); | 464 if (GetMessagePayload(payload, payload_size, &data)) { |
| 449 ScopedPlatformHandle process_handle; | 465 ScopedPlatformHandle process_handle; |
| 450 #if defined(OS_WIN) | 466 #if defined(OS_WIN) |
| 451 if (!handles || handles->size() != 1) { | 467 if (!handles || handles->size() != 1) { |
| 452 DLOG(ERROR) << "Dropping invalid AddBrokerClient message."; | 468 DLOG(ERROR) << "Dropping invalid AddBrokerClient message."; |
| 453 break; | 469 break; |
| 470 } | |
| 471 process_handle = ScopedPlatformHandle(handles->at(0)); | |
| 472 handles->clear(); | |
| 473 delegate_->OnAddBrokerClient(remote_node_name_, data->client_name, | |
| 474 process_handle.release().handle); | |
| 475 #else | |
| 476 if (handles && handles->size() != 0) { | |
| 477 DLOG(ERROR) << "Dropping invalid AddBrokerClient message."; | |
| 478 break; | |
| 479 } | |
| 480 delegate_->OnAddBrokerClient(remote_node_name_, data->client_name, | |
| 481 data->process_handle); | |
| 482 #endif | |
| 483 return; | |
| 454 } | 484 } |
| 455 process_handle = ScopedPlatformHandle(handles->at(0)); | |
| 456 handles->clear(); | |
| 457 delegate_->OnAddBrokerClient(remote_node_name_, data->client_name, | |
| 458 process_handle.release().handle); | |
| 459 #else | |
| 460 if (handles && handles->size() != 0) { | |
| 461 DLOG(ERROR) << "Dropping invalid AddBrokerClient message."; | |
| 462 break; | |
| 463 } | |
| 464 delegate_->OnAddBrokerClient(remote_node_name_, data->client_name, | |
| 465 data->process_handle); | |
| 466 #endif | |
| 467 break; | 485 break; |
| 468 } | 486 } |
| 469 | 487 |
| 470 case MessageType::BROKER_CLIENT_ADDED: { | 488 case MessageType::BROKER_CLIENT_ADDED: { |
| 471 const BrokerClientAddedData* data; | 489 const BrokerClientAddedData* data; |
| 472 GetMessagePayload(payload, &data); | 490 if (GetMessagePayload(payload, payload_size, &data)) { |
| 473 ScopedPlatformHandle broker_channel; | 491 ScopedPlatformHandle broker_channel; |
| 474 if (!handles || handles->size() != 1) { | 492 if (!handles || handles->size() != 1) { |
| 475 DLOG(ERROR) << "Dropping invalid BrokerClientAdded message."; | 493 DLOG(ERROR) << "Dropping invalid BrokerClientAdded message."; |
| 476 break; | 494 break; |
| 495 } | |
| 496 broker_channel = ScopedPlatformHandle(handles->at(0)); | |
| 497 handles->clear(); | |
| 498 delegate_->OnBrokerClientAdded(remote_node_name_, data->client_name, | |
| 499 std::move(broker_channel)); | |
| 500 return; | |
| 477 } | 501 } |
| 478 broker_channel = ScopedPlatformHandle(handles->at(0)); | |
| 479 handles->clear(); | |
| 480 delegate_->OnBrokerClientAdded(remote_node_name_, data->client_name, | |
| 481 std::move(broker_channel)); | |
| 482 break; | 502 break; |
| 483 } | 503 } |
| 484 | 504 |
| 485 case MessageType::ACCEPT_BROKER_CLIENT: { | 505 case MessageType::ACCEPT_BROKER_CLIENT: { |
| 486 const AcceptBrokerClientData* data; | 506 const AcceptBrokerClientData* data; |
| 487 GetMessagePayload(payload, &data); | 507 if (GetMessagePayload(payload, payload_size, &data)) { |
| 488 ScopedPlatformHandle broker_channel; | 508 ScopedPlatformHandle broker_channel; |
| 489 if (handles && handles->size() > 1) { | 509 if (handles && handles->size() > 1) { |
| 490 DLOG(ERROR) << "Dropping invalid AcceptBrokerClient message."; | 510 DLOG(ERROR) << "Dropping invalid AcceptBrokerClient message."; |
| 491 break; | 511 break; |
| 512 } | |
| 513 if (handles && handles->size() == 1) { | |
| 514 broker_channel = ScopedPlatformHandle(handles->at(0)); | |
| 515 handles->clear(); | |
| 516 } | |
| 517 delegate_->OnAcceptBrokerClient(remote_node_name_, data->broker_name, | |
| 518 std::move(broker_channel)); | |
| 519 return; | |
| 492 } | 520 } |
| 493 if (handles && handles->size() == 1) { | |
| 494 broker_channel = ScopedPlatformHandle(handles->at(0)); | |
| 495 handles->clear(); | |
| 496 } | |
| 497 delegate_->OnAcceptBrokerClient(remote_node_name_, data->broker_name, | |
| 498 std::move(broker_channel)); | |
| 499 break; | 521 break; |
| 500 } | 522 } |
| 501 | 523 |
| 502 case MessageType::PORTS_MESSAGE: { | 524 case MessageType::PORTS_MESSAGE: { |
| 503 size_t num_handles = handles ? handles->size() : 0; | 525 size_t num_handles = handles ? handles->size() : 0; |
| 504 Channel::MessagePtr message( | 526 Channel::MessagePtr message( |
| 505 new Channel::Message(payload_size, num_handles)); | 527 new Channel::Message(payload_size, num_handles)); |
| 506 message->SetHandles(std::move(handles)); | 528 message->SetHandles(std::move(handles)); |
| 507 memcpy(message->mutable_payload(), payload, payload_size); | 529 memcpy(message->mutable_payload(), payload, payload_size); |
| 508 delegate_->OnPortsMessage(std::move(message)); | 530 delegate_->OnPortsMessage(std::move(message)); |
| 509 break; | 531 return; |
| 510 } | 532 } |
| 511 | 533 |
| 512 case MessageType::REQUEST_PORT_MERGE: { | 534 case MessageType::REQUEST_PORT_MERGE: { |
| 513 const RequestPortMergeData* data; | 535 const RequestPortMergeData* data; |
| 514 GetMessagePayload(payload, &data); | 536 if (GetMessagePayload(payload, payload_size, &data)) { |
| 515 | 537 |
| 516 const char* token_data = reinterpret_cast<const char*>(data + 1); | 538 const char* token_data = reinterpret_cast<const char*>(data + 1); |
| 517 const size_t token_size = payload_size - sizeof(*data) - sizeof(Header); | 539 const size_t token_size = payload_size - sizeof(*data) - sizeof(Header); |
| 518 std::string token(token_data, token_size); | 540 std::string token(token_data, token_size); |
|
Oliver Chang
2016/05/13 23:32:43
does it make sense for token_size to be 0 here?
| |
| 519 | 541 |
| 520 delegate_->OnRequestPortMerge(remote_node_name_, | 542 delegate_->OnRequestPortMerge(remote_node_name_, |
| 521 data->connector_port_name, token); | 543 data->connector_port_name, token); |
| 544 return; | |
| 545 } | |
| 522 break; | 546 break; |
| 523 } | 547 } |
| 524 | 548 |
| 525 case MessageType::REQUEST_INTRODUCTION: { | 549 case MessageType::REQUEST_INTRODUCTION: { |
| 526 const IntroductionData* data; | 550 const IntroductionData* data; |
| 527 GetMessagePayload(payload, &data); | 551 if (GetMessagePayload(payload, payload_size, &data)) { |
| 528 delegate_->OnRequestIntroduction(remote_node_name_, data->name); | 552 delegate_->OnRequestIntroduction(remote_node_name_, data->name); |
| 553 return; | |
| 554 } | |
| 529 break; | 555 break; |
| 530 } | 556 } |
| 531 | 557 |
| 532 case MessageType::INTRODUCE: { | 558 case MessageType::INTRODUCE: { |
| 533 const IntroductionData* data; | 559 const IntroductionData* data; |
| 534 GetMessagePayload(payload, &data); | 560 if (GetMessagePayload(payload, payload_size, &data)) { |
| 535 if (handles && handles->size() > 1) { | 561 if (handles && handles->size() > 1) { |
| 536 DLOG(ERROR) << "Dropping invalid introduction message."; | 562 DLOG(ERROR) << "Dropping invalid introduction message."; |
| 537 break; | 563 break; |
| 564 } | |
| 565 ScopedPlatformHandle channel_handle; | |
| 566 if (handles && handles->size() == 1) { | |
| 567 channel_handle = ScopedPlatformHandle(handles->at(0)); | |
| 568 handles->clear(); | |
| 569 } | |
| 570 delegate_->OnIntroduce(remote_node_name_, data->name, | |
| 571 std::move(channel_handle)); | |
| 572 return; | |
| 538 } | 573 } |
| 539 ScopedPlatformHandle channel_handle; | |
| 540 if (handles && handles->size() == 1) { | |
| 541 channel_handle = ScopedPlatformHandle(handles->at(0)); | |
| 542 handles->clear(); | |
| 543 } | |
| 544 delegate_->OnIntroduce(remote_node_name_, data->name, | |
| 545 std::move(channel_handle)); | |
| 546 break; | 574 break; |
| 547 } | 575 } |
| 548 | 576 |
| 549 #if defined(OS_WIN) || (defined(OS_MACOSX) && !defined(OS_IOS)) | 577 #if defined(OS_WIN) || (defined(OS_MACOSX) && !defined(OS_IOS)) |
| 550 case MessageType::RELAY_PORTS_MESSAGE: { | 578 case MessageType::RELAY_PORTS_MESSAGE: { |
| 551 base::ProcessHandle from_process; | 579 base::ProcessHandle from_process; |
| 552 { | 580 { |
| 553 base::AutoLock lock(remote_process_handle_lock_); | 581 base::AutoLock lock(remote_process_handle_lock_); |
| 554 from_process = remote_process_handle_; | 582 from_process = remote_process_handle_; |
| 555 } | 583 } |
| 556 const RelayPortsMessageData* data; | 584 const RelayPortsMessageData* data; |
| 557 GetMessagePayload(payload, &data); | 585 if (GetMessagePayload(payload, payload_size, &data)) { |
| 558 const void* message_start = data + 1; | 586 // Don't try to relay an empty message. |
| 559 Channel::MessagePtr message = Channel::Message::Deserialize( | 587 if (payload_size <= sizeof(Header) + sizeof(RelayPortsMessageData)) |
| 560 message_start, payload_size - sizeof(Header) - sizeof(*data)); | 588 break; |
| 561 if (!message) { | 589 |
| 562 DLOG(ERROR) << "Dropping invalid relay message."; | 590 const void* message_start = data + 1; |
| 563 break; | 591 Channel::MessagePtr message = Channel::Message::Deserialize( |
| 564 } | 592 message_start, payload_size - sizeof(Header) - sizeof(*data)); |
| 565 #if defined(OS_MACOSX) && !defined(OS_IOS) | 593 if (!message) { |
| 566 message->SetHandles(std::move(handles)); | 594 DLOG(ERROR) << "Dropping invalid relay message."; |
| 567 MachPortRelay* relay = delegate_->GetMachPortRelay(); | |
| 568 if (!relay) { | |
| 569 LOG(ERROR) << "Receiving mach ports without a port relay from " | |
| 570 << remote_node_name_ << ". Dropping message."; | |
| 571 break; | |
| 572 } | |
| 573 { | |
| 574 base::AutoLock lock(pending_mach_messages_lock_); | |
| 575 if (relay->port_provider()->TaskForPid(from_process) == | |
| 576 MACH_PORT_NULL) { | |
| 577 pending_relay_messages_.push( | |
| 578 std::make_pair(data->destination, std::move(message))); | |
| 579 break; | 595 break; |
| 580 } | 596 } |
| 597 #if defined(OS_MACOSX) && !defined(OS_IOS) | |
| 598 message->SetHandles(std::move(handles)); | |
| 599 MachPortRelay* relay = delegate_->GetMachPortRelay(); | |
| 600 if (!relay) { | |
| 601 LOG(ERROR) << "Receiving mach ports without a port relay from " | |
| 602 << remote_node_name_ << ". Dropping message."; | |
| 603 break; | |
| 604 } | |
| 605 { | |
| 606 base::AutoLock lock(pending_mach_messages_lock_); | |
| 607 if (relay->port_provider()->TaskForPid(from_process) == | |
| 608 MACH_PORT_NULL) { | |
| 609 pending_relay_messages_.push( | |
| 610 std::make_pair(data->destination, std::move(message))); | |
| 611 break; | |
| 612 } | |
| 613 } | |
| 614 #endif | |
| 615 delegate_->OnRelayPortsMessage(remote_node_name_, from_process, | |
| 616 data->destination, std::move(message)); | |
| 617 return; | |
| 581 } | 618 } |
| 582 #endif | |
| 583 delegate_->OnRelayPortsMessage(remote_node_name_, from_process, | |
| 584 data->destination, std::move(message)); | |
| 585 break; | 619 break; |
| 586 } | 620 } |
| 587 #endif | 621 #endif |
| 588 | 622 |
| 589 default: | 623 default: |
| 590 DLOG(ERROR) << "Received unknown message type " | |
| 591 << static_cast<uint32_t>(header->type) << " from node " | |
| 592 << remote_node_name_; | |
| 593 delegate_->OnChannelError(remote_node_name_); | |
| 594 break; | 624 break; |
| 595 } | 625 } |
| 626 | |
| 627 DLOG(ERROR) << "Received invalid message. Closing channel."; | |
| 628 delegate_->OnChannelError(remote_node_name_); | |
| 596 } | 629 } |
| 597 | 630 |
| 598 void NodeChannel::OnChannelError() { | 631 void NodeChannel::OnChannelError() { |
| 599 DCHECK(io_task_runner_->RunsTasksOnCurrentThread()); | 632 DCHECK(io_task_runner_->RunsTasksOnCurrentThread()); |
| 600 | 633 |
| 601 RequestContext request_context(RequestContext::Source::SYSTEM); | 634 RequestContext request_context(RequestContext::Source::SYSTEM); |
| 602 | 635 |
| 603 ShutDown(); | 636 ShutDown(); |
| 604 // |OnChannelError()| may cause |this| to be destroyed, but still need access | 637 // |OnChannelError()| may cause |this| to be destroyed, but still need access |
| 605 // to the name name after that destruction. So may a copy of | 638 // to the name name after that destruction. So may a copy of |
| (...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 721 | 754 |
| 722 base::AutoLock lock(channel_lock_); | 755 base::AutoLock lock(channel_lock_); |
| 723 if (!channel_) | 756 if (!channel_) |
| 724 DLOG(ERROR) << "Dropping message on closed channel."; | 757 DLOG(ERROR) << "Dropping message on closed channel."; |
| 725 else | 758 else |
| 726 channel_->Write(std::move(message)); | 759 channel_->Write(std::move(message)); |
| 727 } | 760 } |
| 728 | 761 |
| 729 } // namespace edk | 762 } // namespace edk |
| 730 } // namespace mojo | 763 } // namespace mojo |
| OLD | NEW |