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_controller.h" | 5 #include "mojo/edk/system/node_controller.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <limits> | 8 #include <limits> |
| 9 | 9 |
| 10 #include "base/bind.h" | 10 #include "base/bind.h" |
| (...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 134 void NodeController::SetIOTaskRunner( | 134 void NodeController::SetIOTaskRunner( |
| 135 scoped_refptr<base::TaskRunner> task_runner) { | 135 scoped_refptr<base::TaskRunner> task_runner) { |
| 136 io_task_runner_ = task_runner; | 136 io_task_runner_ = task_runner; |
| 137 ThreadDestructionObserver::Create( | 137 ThreadDestructionObserver::Create( |
| 138 io_task_runner_, | 138 io_task_runner_, |
| 139 base::Bind(&NodeController::DropAllPeers, base::Unretained(this))); | 139 base::Bind(&NodeController::DropAllPeers, base::Unretained(this))); |
| 140 } | 140 } |
| 141 | 141 |
| 142 void NodeController::ConnectToChild(base::ProcessHandle process_handle, | 142 void NodeController::ConnectToChild(base::ProcessHandle process_handle, |
| 143 ScopedPlatformHandle platform_handle, | 143 ScopedPlatformHandle platform_handle, |
| 144 const std::string& child_token) { | 144 const std::string& child_token, |
| 145 const base::Closure& bad_message_callback) { | |
| 145 // Generate the temporary remote node name here so that it can be associated | 146 // Generate the temporary remote node name here so that it can be associated |
| 146 // with the embedder's child_token. If an error occurs in the child process | 147 // with the embedder's child_token. If an error occurs in the child process |
| 147 // after it is launched, but before any reserved ports are connected, this can | 148 // after it is launched, but before any reserved ports are connected, this can |
| 148 // be used to clean up any dangling ports. | 149 // be used to clean up any dangling ports. |
| 149 ports::NodeName node_name; | 150 ports::NodeName node_name; |
| 150 GenerateRandomName(&node_name); | 151 GenerateRandomName(&node_name); |
| 151 | 152 |
| 152 { | 153 { |
| 153 base::AutoLock lock(reserved_ports_lock_); | 154 base::AutoLock lock(reserved_ports_lock_); |
| 154 bool inserted = pending_child_tokens_.insert( | 155 bool inserted = pending_child_tokens_.insert( |
| 155 std::make_pair(node_name, child_token)).second; | 156 std::make_pair(node_name, child_token)).second; |
| 156 DCHECK(inserted); | 157 DCHECK(inserted); |
| 157 } | 158 } |
| 158 | 159 |
| 159 io_task_runner_->PostTask( | 160 io_task_runner_->PostTask( |
| 160 FROM_HERE, | 161 FROM_HERE, |
| 161 base::Bind(&NodeController::ConnectToChildOnIOThread, | 162 base::Bind(&NodeController::ConnectToChildOnIOThread, |
| 162 base::Unretained(this), | 163 base::Unretained(this), |
| 163 process_handle, | 164 process_handle, |
| 164 base::Passed(&platform_handle), | 165 base::Passed(&platform_handle), |
| 165 node_name)); | 166 node_name, |
| 167 bad_message_callback)); | |
| 166 } | 168 } |
| 167 | 169 |
| 168 void NodeController::CloseChildPorts(const std::string& child_token) { | 170 void NodeController::CloseChildPorts(const std::string& child_token) { |
| 169 std::vector<ports::PortRef> ports_to_close; | 171 std::vector<ports::PortRef> ports_to_close; |
| 170 { | 172 { |
| 171 std::vector<std::string> port_tokens; | 173 std::vector<std::string> port_tokens; |
| 172 base::AutoLock lock(reserved_ports_lock_); | 174 base::AutoLock lock(reserved_ports_lock_); |
| 173 for (const auto& port : reserved_ports_) { | 175 for (const auto& port : reserved_ports_) { |
| 174 if (port.second.child_token == child_token) { | 176 if (port.second.child_token == child_token) { |
| 175 DVLOG(1) << "Closing reserved port " << port.second.port.name(); | 177 DVLOG(1) << "Closing reserved port " << port.second.port.name(); |
| (...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 303 void NodeController::RequestShutdown(const base::Closure& callback) { | 305 void NodeController::RequestShutdown(const base::Closure& callback) { |
| 304 { | 306 { |
| 305 base::AutoLock lock(shutdown_lock_); | 307 base::AutoLock lock(shutdown_lock_); |
| 306 shutdown_callback_ = callback; | 308 shutdown_callback_ = callback; |
| 307 shutdown_callback_flag_.Set(true); | 309 shutdown_callback_flag_.Set(true); |
| 308 } | 310 } |
| 309 | 311 |
| 310 AttemptShutdownIfRequested(); | 312 AttemptShutdownIfRequested(); |
| 311 } | 313 } |
| 312 | 314 |
| 315 void NodeController::NotifyBadMessageFrom(const ports::NodeName& source_node) { | |
| 316 scoped_refptr<NodeChannel> peer = GetPeerChannel(source_node); | |
| 317 peer->NotifyBadMessage(); | |
|
Anand Mistry (off Chromium)
2016/06/10 10:28:20
Check peer != nullptr. The peer could have closed
| |
| 318 } | |
| 319 | |
| 313 void NodeController::ConnectToChildOnIOThread( | 320 void NodeController::ConnectToChildOnIOThread( |
| 314 base::ProcessHandle process_handle, | 321 base::ProcessHandle process_handle, |
| 315 ScopedPlatformHandle platform_handle, | 322 ScopedPlatformHandle platform_handle, |
| 316 ports::NodeName token) { | 323 ports::NodeName token, |
| 324 const base::Closure& bad_message_callback) { | |
| 317 DCHECK(io_task_runner_->RunsTasksOnCurrentThread()); | 325 DCHECK(io_task_runner_->RunsTasksOnCurrentThread()); |
| 318 | 326 |
| 319 #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_NACL) | 327 #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_NACL) |
| 320 PlatformChannelPair node_channel; | 328 PlatformChannelPair node_channel; |
| 321 // BrokerHost owns itself. | 329 // BrokerHost owns itself. |
| 322 BrokerHost* broker_host = new BrokerHost(std::move(platform_handle)); | 330 BrokerHost* broker_host = new BrokerHost(std::move(platform_handle)); |
| 323 broker_host->SendChannel(node_channel.PassClientHandle()); | 331 broker_host->SendChannel(node_channel.PassClientHandle()); |
| 324 scoped_refptr<NodeChannel> channel = NodeChannel::Create( | 332 scoped_refptr<NodeChannel> channel = NodeChannel::Create( |
| 325 this, node_channel.PassServerHandle(), io_task_runner_); | 333 this, node_channel.PassServerHandle(), io_task_runner_, |
| 334 bad_message_callback); | |
| 326 #else | 335 #else |
| 327 scoped_refptr<NodeChannel> channel = | 336 scoped_refptr<NodeChannel> channel = |
| 328 NodeChannel::Create(this, std::move(platform_handle), io_task_runner_); | 337 NodeChannel::Create(this, std::move(platform_handle), io_task_runner_, |
| 338 bad_message_callback); | |
| 329 #endif | 339 #endif |
| 330 | 340 |
| 331 // We set up the child channel with a temporary name so it can be identified | 341 // We set up the child channel with a temporary name so it can be identified |
| 332 // as a pending child if it writes any messages to the channel. We may start | 342 // as a pending child if it writes any messages to the channel. We may start |
| 333 // receiving messages from it (though we shouldn't) as soon as Start() is | 343 // receiving messages from it (though we shouldn't) as soon as Start() is |
| 334 // called below. | 344 // called below. |
| 335 | 345 |
| 336 pending_children_.insert(std::make_pair(token, channel)); | 346 pending_children_.insert(std::make_pair(token, channel)); |
| 337 RecordPendingChildCount(pending_children_.size()); | 347 RecordPendingChildCount(pending_children_.size()); |
| 338 | 348 |
| 339 channel->SetRemoteNodeName(token); | 349 channel->SetRemoteNodeName(token); |
| 340 channel->SetRemoteProcessHandle(process_handle); | 350 channel->SetRemoteProcessHandle(process_handle); |
| 341 channel->Start(); | 351 channel->Start(); |
| 342 | 352 |
| 343 channel->AcceptChild(name_, token); | 353 channel->AcceptChild(name_, token); |
| 344 } | 354 } |
| 345 | 355 |
| 346 void NodeController::ConnectToParentOnIOThread( | 356 void NodeController::ConnectToParentOnIOThread( |
| 347 ScopedPlatformHandle platform_handle) { | 357 ScopedPlatformHandle platform_handle) { |
| 348 DCHECK(io_task_runner_->RunsTasksOnCurrentThread()); | 358 DCHECK(io_task_runner_->RunsTasksOnCurrentThread()); |
| 349 | 359 |
| 350 { | 360 { |
| 351 base::AutoLock lock(parent_lock_); | 361 base::AutoLock lock(parent_lock_); |
| 352 DCHECK(parent_name_ == ports::kInvalidNodeName); | 362 DCHECK(parent_name_ == ports::kInvalidNodeName); |
| 353 | 363 |
| 354 // At this point we don't know the parent's name, so we can't yet insert it | 364 // At this point we don't know the parent's name, so we can't yet insert it |
| 355 // into our |peers_| map. That will happen as soon as we receive an | 365 // into our |peers_| map. That will happen as soon as we receive an |
| 356 // AcceptChild message from them. | 366 // AcceptChild message from them. |
| 357 bootstrap_parent_channel_ = | 367 bootstrap_parent_channel_ = |
| 358 NodeChannel::Create(this, std::move(platform_handle), io_task_runner_); | 368 NodeChannel::Create(this, std::move(platform_handle), io_task_runner_, |
| 369 base::Closure()); | |
| 359 } | 370 } |
| 360 bootstrap_parent_channel_->Start(); | 371 bootstrap_parent_channel_->Start(); |
| 361 } | 372 } |
| 362 | 373 |
| 363 scoped_refptr<NodeChannel> NodeController::GetPeerChannel( | 374 scoped_refptr<NodeChannel> NodeController::GetPeerChannel( |
| 364 const ports::NodeName& name) { | 375 const ports::NodeName& name) { |
| 365 base::AutoLock lock(peers_lock_); | 376 base::AutoLock lock(peers_lock_); |
| 366 auto it = peers_.find(name); | 377 auto it = peers_.find(name); |
| 367 if (it == peers_.end()) | 378 if (it == peers_.end()) |
| 368 return nullptr; | 379 return nullptr; |
| (...skipping 380 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 749 } | 760 } |
| 750 | 761 |
| 751 if (GetPeerChannel(client_name)) { | 762 if (GetPeerChannel(client_name)) { |
| 752 DLOG(ERROR) << "Ignoring AddBrokerClient for known client."; | 763 DLOG(ERROR) << "Ignoring AddBrokerClient for known client."; |
| 753 DropPeer(from_node); | 764 DropPeer(from_node); |
| 754 return; | 765 return; |
| 755 } | 766 } |
| 756 | 767 |
| 757 PlatformChannelPair broker_channel; | 768 PlatformChannelPair broker_channel; |
| 758 scoped_refptr<NodeChannel> client = NodeChannel::Create( | 769 scoped_refptr<NodeChannel> client = NodeChannel::Create( |
| 759 this, broker_channel.PassServerHandle(), io_task_runner_); | 770 this, broker_channel.PassServerHandle(), io_task_runner_, |
| 771 base::Closure()); | |
| 760 | 772 |
| 761 #if defined(OS_WIN) | 773 #if defined(OS_WIN) |
| 762 // The broker must have a working handle to the client process in order to | 774 // The broker must have a working handle to the client process in order to |
| 763 // properly copy other handles to and from the client. | 775 // properly copy other handles to and from the client. |
| 764 if (!scoped_process_handle.is_valid()) { | 776 if (!scoped_process_handle.is_valid()) { |
| 765 DLOG(ERROR) << "Broker rejecting client with invalid process handle."; | 777 DLOG(ERROR) << "Broker rejecting client with invalid process handle."; |
| 766 return; | 778 return; |
| 767 } | 779 } |
| 768 client->SetRemoteProcessHandle(scoped_process_handle.release().handle); | 780 client->SetRemoteProcessHandle(scoped_process_handle.release().handle); |
| 769 #else | 781 #else |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 826 | 838 |
| 827 // It's now possible to add both the broker and the parent as peers. | 839 // It's now possible to add both the broker and the parent as peers. |
| 828 // Note that the broker and parent may be the same node. | 840 // Note that the broker and parent may be the same node. |
| 829 scoped_refptr<NodeChannel> broker; | 841 scoped_refptr<NodeChannel> broker; |
| 830 if (broker_name == parent_name) { | 842 if (broker_name == parent_name) { |
| 831 DCHECK(!broker_channel.is_valid()); | 843 DCHECK(!broker_channel.is_valid()); |
| 832 broker = parent; | 844 broker = parent; |
| 833 } else { | 845 } else { |
| 834 DCHECK(broker_channel.is_valid()); | 846 DCHECK(broker_channel.is_valid()); |
| 835 broker = NodeChannel::Create(this, std::move(broker_channel), | 847 broker = NodeChannel::Create(this, std::move(broker_channel), |
| 836 io_task_runner_); | 848 io_task_runner_, base::Closure()); |
| 837 AddPeer(broker_name, broker, true /* start_channel */); | 849 AddPeer(broker_name, broker, true /* start_channel */); |
| 838 } | 850 } |
| 839 | 851 |
| 840 AddPeer(parent_name, parent, false /* start_channel */); | 852 AddPeer(parent_name, parent, false /* start_channel */); |
| 841 | 853 |
| 842 { | 854 { |
| 843 // Complete any port merge requests we have waiting for the parent. | 855 // Complete any port merge requests we have waiting for the parent. |
| 844 base::AutoLock lock(pending_port_merges_lock_); | 856 base::AutoLock lock(pending_port_merges_lock_); |
| 845 for (const auto& request : pending_port_merges_) | 857 for (const auto& request : pending_port_merges_) |
| 846 parent->RequestPortMerge(request.second.name(), request.first); | 858 parent->RequestPortMerge(request.second.name(), request.first); |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 888 if (!ports::Message::Parse(data, | 900 if (!ports::Message::Parse(data, |
| 889 num_data_bytes, | 901 num_data_bytes, |
| 890 &num_header_bytes, | 902 &num_header_bytes, |
| 891 &num_payload_bytes, | 903 &num_payload_bytes, |
| 892 &num_ports_bytes)) { | 904 &num_ports_bytes)) { |
| 893 DropPeer(from_node); | 905 DropPeer(from_node); |
| 894 return; | 906 return; |
| 895 } | 907 } |
| 896 | 908 |
| 897 CHECK(channel_message); | 909 CHECK(channel_message); |
| 898 ports::ScopedMessage message( | 910 std::unique_ptr<PortsMessage> ports_message( |
| 899 new PortsMessage(num_header_bytes, | 911 new PortsMessage(num_header_bytes, |
| 900 num_payload_bytes, | 912 num_payload_bytes, |
| 901 num_ports_bytes, | 913 num_ports_bytes, |
| 902 std::move(channel_message))); | 914 std::move(channel_message))); |
| 903 | 915 ports_message->set_source_node(from_node); |
| 904 node_->AcceptMessage(std::move(message)); | 916 node_->AcceptMessage(ports::ScopedMessage(ports_message.release())); |
| 905 AcceptIncomingMessages(); | 917 AcceptIncomingMessages(); |
| 906 } | 918 } |
| 907 | 919 |
| 908 void NodeController::OnRequestPortMerge( | 920 void NodeController::OnRequestPortMerge( |
| 909 const ports::NodeName& from_node, | 921 const ports::NodeName& from_node, |
| 910 const ports::PortName& connector_port_name, | 922 const ports::PortName& connector_port_name, |
| 911 const std::string& token) { | 923 const std::string& token) { |
| 912 DCHECK(io_task_runner_->RunsTasksOnCurrentThread()); | 924 DCHECK(io_task_runner_->RunsTasksOnCurrentThread()); |
| 913 | 925 |
| 914 DVLOG(2) << "Node " << name_ << " received RequestPortMerge for token " | 926 DVLOG(2) << "Node " << name_ << " received RequestPortMerge for token " |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 962 if (!channel_handle.is_valid()) { | 974 if (!channel_handle.is_valid()) { |
| 963 node_->LostConnectionToNode(name); | 975 node_->LostConnectionToNode(name); |
| 964 | 976 |
| 965 DLOG(ERROR) << "Could not be introduced to peer " << name; | 977 DLOG(ERROR) << "Could not be introduced to peer " << name; |
| 966 base::AutoLock lock(peers_lock_); | 978 base::AutoLock lock(peers_lock_); |
| 967 pending_peer_messages_.erase(name); | 979 pending_peer_messages_.erase(name); |
| 968 return; | 980 return; |
| 969 } | 981 } |
| 970 | 982 |
| 971 scoped_refptr<NodeChannel> channel = | 983 scoped_refptr<NodeChannel> channel = |
| 972 NodeChannel::Create(this, std::move(channel_handle), io_task_runner_); | 984 NodeChannel::Create(this, std::move(channel_handle), io_task_runner_, |
| 985 base::Closure()); | |
| 973 | 986 |
| 974 DVLOG(1) << "Adding new peer " << name << " via parent introduction."; | 987 DVLOG(1) << "Adding new peer " << name << " via parent introduction."; |
| 975 AddPeer(name, channel, true /* start_channel */); | 988 AddPeer(name, channel, true /* start_channel */); |
| 976 } | 989 } |
| 977 | 990 |
| 978 #if defined(OS_WIN) || (defined(OS_MACOSX) && !defined(OS_IOS)) | 991 #if defined(OS_WIN) || (defined(OS_MACOSX) && !defined(OS_IOS)) |
| 979 void NodeController::OnRelayPortsMessage(const ports::NodeName& from_node, | 992 void NodeController::OnRelayPortsMessage(const ports::NodeName& from_node, |
| 980 base::ProcessHandle from_process, | 993 base::ProcessHandle from_process, |
| 981 const ports::NodeName& destination, | 994 const ports::NodeName& destination, |
| 982 Channel::MessagePtr message) { | 995 Channel::MessagePtr message) { |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1029 #endif // defined(OS_WIN) | 1042 #endif // defined(OS_WIN) |
| 1030 | 1043 |
| 1031 if (destination == name_) { | 1044 if (destination == name_) { |
| 1032 // Great, we can deliver this message locally. | 1045 // Great, we can deliver this message locally. |
| 1033 OnPortsMessage(from_node, std::move(message)); | 1046 OnPortsMessage(from_node, std::move(message)); |
| 1034 return; | 1047 return; |
| 1035 } | 1048 } |
| 1036 | 1049 |
| 1037 scoped_refptr<NodeChannel> peer = GetPeerChannel(destination); | 1050 scoped_refptr<NodeChannel> peer = GetPeerChannel(destination); |
| 1038 if (peer) | 1051 if (peer) |
| 1039 peer->PortsMessage(std::move(message)); | 1052 peer->PortsMessageFromRelay(from_node, std::move(message)); |
| 1040 else | 1053 else |
| 1041 DLOG(ERROR) << "Dropping relay message for unknown node " << destination; | 1054 DLOG(ERROR) << "Dropping relay message for unknown node " << destination; |
| 1042 } | 1055 } |
| 1056 | |
| 1057 void NodeController::OnPortsMessageFromRelay(const ports::NodeName& from_node, | |
| 1058 const ports::NodeName& source_node, | |
| 1059 Channel::MessagePtr message) { | |
| 1060 if (GetPeerChannel(from_node) != GetBrokerChannel()) { | |
| 1061 LOG(ERROR) << "Refusing relayed message from non-broker node."; | |
| 1062 DropPeer(from_node); | |
| 1063 return; | |
| 1064 } | |
| 1065 | |
| 1066 OnPortsMessage(source_node, std::move(message)); | |
| 1067 } | |
| 1043 #endif | 1068 #endif |
| 1044 | 1069 |
| 1045 void NodeController::OnChannelError(const ports::NodeName& from_node) { | 1070 void NodeController::OnChannelError(const ports::NodeName& from_node) { |
| 1046 if (io_task_runner_->RunsTasksOnCurrentThread()) { | 1071 if (io_task_runner_->RunsTasksOnCurrentThread()) { |
| 1047 DropPeer(from_node); | 1072 DropPeer(from_node); |
| 1048 // DropPeer may have caused local port closures, so be sure to process any | 1073 // DropPeer may have caused local port closures, so be sure to process any |
| 1049 // pending local messages. | 1074 // pending local messages. |
| 1050 AcceptIncomingMessages(); | 1075 AcceptIncomingMessages(); |
| 1051 } else { | 1076 } else { |
| 1052 io_task_runner_->PostTask( | 1077 io_task_runner_->PostTask( |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1093 shutdown_callback_flag_.Set(false); | 1118 shutdown_callback_flag_.Set(false); |
| 1094 } | 1119 } |
| 1095 | 1120 |
| 1096 DCHECK(!callback.is_null()); | 1121 DCHECK(!callback.is_null()); |
| 1097 | 1122 |
| 1098 callback.Run(); | 1123 callback.Run(); |
| 1099 } | 1124 } |
| 1100 | 1125 |
| 1101 } // namespace edk | 1126 } // namespace edk |
| 1102 } // namespace mojo | 1127 } // namespace mojo |
| OLD | NEW |