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 3 // found in the LICENSE file. 4 5 #ifndef MOJO_EDK_SYSTEM_NODE_CHANNEL_H_ 6 #define MOJO_EDK_SYSTEM_NODE_CHANNEL_H_ 7 8 #include <queue> 9 #include <unordered_map> 10 #include <utility> 11 12 #include "base/callback.h" 13 #include "base/macros.h" 14 #include "base/memory/ref_counted.h" 15 #include "base/process/process_handle.h" 16 #include "base/synchronization/lock.h" 17 #include "base/task_runner.h" 18 #include "build/build_config.h" 19 #include "mojo/edk/embedder/connection_params.h" 20 #include "mojo/edk/embedder/embedder.h" 21 #include "mojo/edk/embedder/platform_handle_vector.h" 22 #include "mojo/edk/embedder/scoped_platform_handle.h" 23 #include "mojo/edk/system/channel.h" 24 #include "mojo/edk/system/ports/name.h" 25 26 #if defined(OS_MACOSX) && !defined(OS_IOS) 27 #include "mojo/edk/system/mach_port_relay.h" 28 #endif 29 30 namespace mojo { 31 namespace edk { 32 33 // Wraps a Channel to send and receive Node control messages. 34 class NodeChannel : public base::RefCountedThreadSafe<NodeChannel>, 35 public Channel::Delegate 36 #if defined(OS_MACOSX) && !defined(OS_IOS) 37 , public MachPortRelay::Observer 38 #endif 39 { 40 public: 41 class Delegate { 42 public: ~Delegate()43 virtual ~Delegate() {} 44 virtual void OnAcceptChild(const ports::NodeName& from_node, 45 const ports::NodeName& parent_name, 46 const ports::NodeName& token) = 0; 47 virtual void OnAcceptParent(const ports::NodeName& from_node, 48 const ports::NodeName& token, 49 const ports::NodeName& child_name) = 0; 50 virtual void OnAddBrokerClient(const ports::NodeName& from_node, 51 const ports::NodeName& client_name, 52 base::ProcessHandle process_handle) = 0; 53 virtual void OnBrokerClientAdded(const ports::NodeName& from_node, 54 const ports::NodeName& client_name, 55 ScopedPlatformHandle broker_channel) = 0; 56 virtual void OnAcceptBrokerClient(const ports::NodeName& from_node, 57 const ports::NodeName& broker_name, 58 ScopedPlatformHandle broker_channel) = 0; 59 virtual void OnPortsMessage(const ports::NodeName& from_node, 60 Channel::MessagePtr message) = 0; 61 virtual void OnRequestPortMerge(const ports::NodeName& from_node, 62 const ports::PortName& connector_port_name, 63 const std::string& token) = 0; 64 virtual void OnRequestIntroduction(const ports::NodeName& from_node, 65 const ports::NodeName& name) = 0; 66 virtual void OnIntroduce(const ports::NodeName& from_node, 67 const ports::NodeName& name, 68 ScopedPlatformHandle channel_handle) = 0; 69 virtual void OnBroadcast(const ports::NodeName& from_node, 70 Channel::MessagePtr message) = 0; 71 #if defined(OS_WIN) || (defined(OS_MACOSX) && !defined(OS_IOS)) 72 virtual void OnRelayPortsMessage(const ports::NodeName& from_node, 73 base::ProcessHandle from_process, 74 const ports::NodeName& destination, 75 Channel::MessagePtr message) = 0; 76 virtual void OnPortsMessageFromRelay(const ports::NodeName& from_node, 77 const ports::NodeName& source_node, 78 Channel::MessagePtr message) = 0; 79 #endif 80 virtual void OnAcceptPeer(const ports::NodeName& from_node, 81 const ports::NodeName& token, 82 const ports::NodeName& peer_name, 83 const ports::PortName& port_name) = 0; 84 virtual void OnChannelError(const ports::NodeName& node, 85 NodeChannel* channel) = 0; 86 87 #if defined(OS_MACOSX) && !defined(OS_IOS) 88 virtual MachPortRelay* GetMachPortRelay() = 0; 89 #endif 90 }; 91 92 static scoped_refptr<NodeChannel> Create( 93 Delegate* delegate, 94 ConnectionParams connection_params, 95 scoped_refptr<base::TaskRunner> io_task_runner, 96 const ProcessErrorCallback& process_error_callback); 97 98 static Channel::MessagePtr CreatePortsMessage(size_t payload_size, 99 void** payload, 100 size_t num_handles); 101 102 static void GetPortsMessageData(Channel::Message* message, void** data, 103 size_t* num_data_bytes); 104 105 // Start receiving messages. 106 void Start(); 107 108 // Permanently stop the channel from sending or receiving messages. 109 void ShutDown(); 110 111 // Leaks the pipe handle instead of closing it on shutdown. 112 void LeakHandleOnShutdown(); 113 114 // Invokes the bad message callback for this channel, if any. 115 void NotifyBadMessage(const std::string& error); 116 117 // Note: On Windows, we take ownership of the remote process handle. 118 void SetRemoteProcessHandle(base::ProcessHandle process_handle); 119 bool HasRemoteProcessHandle(); 120 // Note: The returned |ProcessHandle| is owned by the caller and should be 121 // freed if necessary. 122 base::ProcessHandle CopyRemoteProcessHandle(); 123 124 // Used for context in Delegate calls (via |from_node| arguments.) 125 void SetRemoteNodeName(const ports::NodeName& name); 126 127 void AcceptChild(const ports::NodeName& parent_name, 128 const ports::NodeName& token); 129 void AcceptParent(const ports::NodeName& token, 130 const ports::NodeName& child_name); 131 void AcceptPeer(const ports::NodeName& sender_name, 132 const ports::NodeName& token, 133 const ports::PortName& port_name); 134 void AddBrokerClient(const ports::NodeName& client_name, 135 base::ProcessHandle process_handle); 136 void BrokerClientAdded(const ports::NodeName& client_name, 137 ScopedPlatformHandle broker_channel); 138 void AcceptBrokerClient(const ports::NodeName& broker_name, 139 ScopedPlatformHandle broker_channel); 140 void PortsMessage(Channel::MessagePtr message); 141 void RequestPortMerge(const ports::PortName& connector_port_name, 142 const std::string& token); 143 void RequestIntroduction(const ports::NodeName& name); 144 void Introduce(const ports::NodeName& name, 145 ScopedPlatformHandle channel_handle); 146 void Broadcast(Channel::MessagePtr message); 147 148 #if defined(OS_WIN) || (defined(OS_MACOSX) && !defined(OS_IOS)) 149 // Relay the message to the specified node via this channel. This is used to 150 // pass windows handles between two processes that do not have permission to 151 // duplicate handles into the other's address space. The relay process is 152 // assumed to have that permission. 153 void RelayPortsMessage(const ports::NodeName& destination, 154 Channel::MessagePtr message); 155 156 // Sends a message to its destination from a relay. This is interpreted by the 157 // receiver similarly to PortsMessage, but the original source node is 158 // provided as additional message metadata from the (trusted) relay node. 159 void PortsMessageFromRelay(const ports::NodeName& source, 160 Channel::MessagePtr message); 161 #endif 162 163 private: 164 friend class base::RefCountedThreadSafe<NodeChannel>; 165 166 using PendingMessageQueue = std::queue<Channel::MessagePtr>; 167 using PendingRelayMessageQueue = 168 std::queue<std::pair<ports::NodeName, Channel::MessagePtr>>; 169 170 NodeChannel(Delegate* delegate, 171 ConnectionParams connection_params, 172 scoped_refptr<base::TaskRunner> io_task_runner, 173 const ProcessErrorCallback& process_error_callback); 174 ~NodeChannel() override; 175 176 // Channel::Delegate: 177 void OnChannelMessage(const void* payload, 178 size_t payload_size, 179 ScopedPlatformHandleVectorPtr handles) override; 180 void OnChannelError() override; 181 182 #if defined(OS_MACOSX) && !defined(OS_IOS) 183 // MachPortRelay::Observer: 184 void OnProcessReady(base::ProcessHandle process) override; 185 186 void ProcessPendingMessagesWithMachPorts(); 187 #endif 188 189 void WriteChannelMessage(Channel::MessagePtr message); 190 191 Delegate* const delegate_; 192 const scoped_refptr<base::TaskRunner> io_task_runner_; 193 const ProcessErrorCallback process_error_callback_; 194 195 base::Lock channel_lock_; 196 scoped_refptr<Channel> channel_; 197 198 // Must only be accessed from |io_task_runner_|'s thread. 199 ports::NodeName remote_node_name_; 200 201 base::Lock remote_process_handle_lock_; 202 base::ProcessHandle remote_process_handle_ = base::kNullProcessHandle; 203 #if defined(OS_WIN) 204 ScopedPlatformHandle scoped_remote_process_handle_; 205 #endif 206 207 #if defined(OS_MACOSX) && !defined(OS_IOS) 208 base::Lock pending_mach_messages_lock_; 209 PendingMessageQueue pending_write_messages_; 210 PendingRelayMessageQueue pending_relay_messages_; 211 #endif 212 213 DISALLOW_COPY_AND_ASSIGN(NodeChannel); 214 }; 215 216 } // namespace edk 217 } // namespace mojo 218 219 #endif // MOJO_EDK_SYSTEM_NODE_CHANNEL_H_ 220