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