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