1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this file, 5 * You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #ifndef mozilla_ipc_NodeChannel_h 8 #define mozilla_ipc_NodeChannel_h 9 10 #include "mojo/core/ports/node.h" 11 #include "mojo/core/ports/node_delegate.h" 12 #include "chrome/common/ipc_message.h" 13 #include "chrome/common/ipc_channel.h" 14 #include "mozilla/ipc/ProtocolUtils.h" 15 #include "nsISupports.h" 16 #include "nsTHashMap.h" 17 #include "mozilla/Queue.h" 18 #include "mozilla/DataMutex.h" 19 #include "mozilla/UniquePtr.h" 20 21 namespace mozilla::ipc { 22 23 class NodeController; 24 25 // Represents a live connection between our Node and a remote process. This 26 // object acts as an IPC::Channel listener and performs basic processing on 27 // messages as they're passed between processes. 28 29 class NodeChannel final : public IPC::Channel::Listener { 30 using NodeName = mojo::core::ports::NodeName; 31 using PortName = mojo::core::ports::PortName; 32 33 public: 34 NS_INLINE_DECL_THREADSAFE_REFCOUNTING_WITH_DESTROY(NodeChannel, Destroy()) 35 36 struct Introduction { 37 NodeName mName; 38 IPC::Channel::ChannelHandle mHandle; 39 IPC::Channel::Mode mMode; 40 int32_t mMyPid = -1; 41 int32_t mOtherPid = -1; 42 }; 43 44 class Listener { 45 public: 46 virtual ~Listener() = default; 47 48 NS_INLINE_DECL_PURE_VIRTUAL_REFCOUNTING 49 50 virtual void OnEventMessage(const NodeName& aFromNode, 51 UniquePtr<IPC::Message> aMessage) = 0; 52 virtual void OnBroadcast(const NodeName& aFromNode, 53 UniquePtr<IPC::Message> aMessage) = 0; 54 virtual void OnIntroduce(const NodeName& aFromNode, 55 Introduction aIntroduction) = 0; 56 virtual void OnRequestIntroduction(const NodeName& aFromNode, 57 const NodeName& aName) = 0; 58 virtual void OnAcceptInvite(const NodeName& aFromNode, 59 const NodeName& aRealName, 60 const PortName& aInitialPort) = 0; 61 virtual void OnChannelError(const NodeName& aFromNode) = 0; 62 }; 63 64 NodeChannel(const NodeName& aName, UniquePtr<IPC::Channel> aChannel, 65 Listener* aListener, int32_t aPid = -1); 66 67 // Send the given message over this peer channel link. May be called from any 68 // thread. 69 void SendEventMessage(UniquePtr<IPC::Message> aMessage); 70 71 // Ask the broker process to broadcast this message to every node. May be 72 // called from any thread. 73 void Broadcast(UniquePtr<IPC::Message> aMessage); 74 75 // Ask the broker process to introduce this node to another node with the 76 // given name. May be called from any thread. 77 void RequestIntroduction(const NodeName& aPeerName); 78 79 // Send an introduction to the target node. May be called from any thread. 80 void Introduce(Introduction aIntroduction); 81 82 void AcceptInvite(const NodeName& aRealName, const PortName& aInitialPort); 83 84 // The PID of the remote process, once known. May be called from any thread. OtherPid()85 int32_t OtherPid() const { return mOtherPid; } 86 87 // Start communicating with the remote process using this NodeChannel. MUST BE 88 // CALLED FROM THE IO THREAD. 89 void Start(bool aCallConnect = true); 90 91 // Stop communicating with the remote process using this NodeChannel, MUST BE 92 // CALLED FROM THE IO THREAD. 93 void Close(); 94 95 // Only ever called by NodeController to update the name after an invite has 96 // completed. MUST BE CALLED FROM THE IO THREAD. SetName(const NodeName & aNewName)97 void SetName(const NodeName& aNewName) { mName = aNewName; } 98 99 #ifdef XP_MACOSX 100 // Called by the GeckoChildProcessHost to provide the task_t for the peer 101 // process. MUST BE CALLED FROM THE IO THREAD. 102 void SetMachTaskPort(task_t aTask); 103 #endif 104 105 private: 106 ~NodeChannel(); 107 108 void Destroy(); 109 void FinalDestroy(); 110 111 // Update the known PID for the remote process. IO THREAD ONLY 112 void SetOtherPid(int32_t aNewPid); 113 114 void SendMessage(UniquePtr<IPC::Message> aMessage); 115 void DoSendMessage(UniquePtr<IPC::Message> aMessage); 116 117 // IPC::Channel::Listener implementation 118 void OnMessageReceived(IPC::Message&& aMessage) override; 119 void OnChannelConnected(int32_t aPeerPid) override; 120 void OnChannelError() override; 121 122 // NOTE: This strong reference will create a reference cycle between the 123 // listener and the NodeChannel while it is in use. The Listener must clear 124 // its reference to the NodeChannel to avoid leaks before shutdown. 125 const RefPtr<Listener> mListener; 126 127 // The apparent name of this Node. This may change during the invite process 128 // while waiting for the remote node name to be communicated to us. 129 130 // WARNING: This must only be accessed on the IO thread. 131 NodeName mName; 132 133 // NOTE: This won't change once the connection has been established, but may 134 // be `-1` until then. This will only be written to on the IO thread, but may 135 // be read from other threads. 136 std::atomic<int32_t> mOtherPid; 137 138 // WARNING: This must only be accessed on the IO thread. 139 mozilla::UniquePtr<IPC::Channel> mChannel; 140 141 // WARNING: This must only be accessed on the IO thread. 142 bool mClosed = false; 143 144 // WARNING: Must only be accessed on the IO thread. 145 WeakPtr<IPC::Channel::Listener> mExistingListener; 146 }; 147 148 } // namespace mozilla::ipc 149 150 #endif 151