Home | History | Annotate | Download | only in system
      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:
     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