Bug 1858509 add thread-safety annotations around MediaSourceDemuxer::mMonitor r=alwu
[gecko.git] / ipc / glue / NodeController.h
blob5356b8508400e38e607b4596b92cdb8d24f0273f
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/. */
7 #ifndef mozilla_ipc_NodeController_h
8 #define mozilla_ipc_NodeController_h
10 #include "mojo/core/ports/event.h"
11 #include "mojo/core/ports/name.h"
12 #include "mojo/core/ports/node.h"
13 #include "mojo/core/ports/node_delegate.h"
14 #include "chrome/common/ipc_message.h"
15 #include "mozilla/ipc/ProtocolUtils.h"
16 #include "nsTHashMap.h"
17 #include "mozilla/Queue.h"
18 #include "mozilla/DataMutex.h"
19 #include "mozilla/UniquePtr.h"
20 #include "mozilla/ipc/NodeChannel.h"
22 namespace mozilla::ipc {
24 class GeckoChildProcessHost;
26 class NodeController final : public mojo::core::ports::NodeDelegate,
27 public NodeChannel::Listener {
28 using NodeName = mojo::core::ports::NodeName;
29 using PortName = mojo::core::ports::PortName;
30 using PortRef = mojo::core::ports::PortRef;
31 using Event = mojo::core::ports::Event;
32 using Node = mojo::core::ports::Node;
33 using UserData = mojo::core::ports::UserData;
34 using PortStatus = mojo::core::ports::PortStatus;
35 using UserMessageEvent = mojo::core::ports::UserMessageEvent;
36 using UserMessage = mojo::core::ports::UserMessage;
38 public:
39 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(NodeController, override)
41 // Return the global singleton instance. The returned value is only valid
42 // while the IO thread is alive.
43 static NodeController* GetSingleton();
45 class PortObserver : public UserData {
46 public:
47 virtual void OnPortStatusChanged() = 0;
49 protected:
50 ~PortObserver() override = default;
53 // NOTE: For now there will always be a single broker process, and all
54 // processes in the graph need to be able to talk to it (the parent process).
55 // Give it a fixed node name for now to simplify things.
57 // If we ever decide to have multiple node networks intercommunicating (e.g.
58 // multiple instances or background services), we may need to change this.
59 static constexpr NodeName kBrokerNodeName{0x1, 0x1};
61 bool IsBroker() const { return mName == kBrokerNodeName; }
63 // Mint a new connected pair of ports within the current process.
64 std::pair<ScopedPort, ScopedPort> CreatePortPair();
66 // Get a reference to the port with the given name. Returns an invalid
67 // `PortRef` if the name wasn't found.
68 PortRef GetPort(const PortName& aName);
70 // Set the observer for the given port. This observer will be notified when
71 // the status of the port changes.
72 void SetPortObserver(const PortRef& aPort, PortObserver* aObserver);
74 // See `mojo::core::ports::Node::GetStatus`
75 Maybe<PortStatus> GetStatus(const PortRef& aPort);
77 // See `mojo::core::ports::Node::ClosePort`
78 void ClosePort(const PortRef& aPort);
80 // Send a message to the the port's connected peer.
81 bool SendUserMessage(const PortRef& aPort, UniquePtr<IPC::Message> aMessage);
83 // Get the next message from the port's message queue.
84 // Will set `*aMessage` to the found message, or `nullptr`.
85 // Returns `false` and sets `*aMessage` to `nullptr` if no further messages
86 // will be delivered to this port as its peer has been closed.
87 bool GetMessage(const PortRef& aPort, UniquePtr<IPC::Message>* aMessage);
89 // Called in the broker process from GeckoChildProcessHost to introduce a new
90 // child process into the network. Returns a `PortRef` which can be used to
91 // communicate with the `PortRef` returned from `InitChildProcess`, and a
92 // reference to the `NodeChannel` created for the new process. The port can
93 // immediately have messages sent to it.
94 std::tuple<ScopedPort, RefPtr<NodeChannel>> InviteChildProcess(
95 UniquePtr<IPC::Channel> aChannel,
96 GeckoChildProcessHost* aChildProcessHost);
98 // Called as the IO thread is started in the parent process.
99 static void InitBrokerProcess();
101 // Called as the IO thread is started in a child process.
102 static ScopedPort InitChildProcess(UniquePtr<IPC::Channel> aChannel,
103 base::ProcessId aParentPid);
105 // Called when the IO thread is torn down.
106 static void CleanUp();
108 private:
109 explicit NodeController(const NodeName& aName);
110 ~NodeController();
112 UniquePtr<IPC::Message> SerializeEventMessage(
113 UniquePtr<Event> aEvent, const NodeName* aRelayTarget = nullptr,
114 uint32_t aType = EVENT_MESSAGE_TYPE);
115 UniquePtr<Event> DeserializeEventMessage(UniquePtr<IPC::Message> aMessage,
116 NodeName* aRelayTarget = nullptr);
118 // Get the `NodeChannel` for the named node.
119 already_AddRefed<NodeChannel> GetNodeChannel(const NodeName& aName);
121 // Stop communicating with this peer. Must be called on the IO thread.
122 void DropPeer(NodeName aNodeName);
124 // Message Handlers
125 void OnEventMessage(const NodeName& aFromNode,
126 UniquePtr<IPC::Message> aMessage) override;
127 void OnBroadcast(const NodeName& aFromNode,
128 UniquePtr<IPC::Message> aMessage) override;
129 void OnIntroduce(const NodeName& aFromNode,
130 NodeChannel::Introduction aIntroduction) override;
131 void OnRequestIntroduction(const NodeName& aFromNode,
132 const NodeName& aName) override;
133 void OnAcceptInvite(const NodeName& aFromNode, const NodeName& aRealName,
134 const PortName& aInitialPort) override;
135 void OnChannelError(const NodeName& aFromNode) override;
137 // NodeDelegate Implementation
138 void ForwardEvent(const NodeName& aNode, UniquePtr<Event> aEvent) override;
139 void BroadcastEvent(UniquePtr<Event> aEvent) override;
140 void PortStatusChanged(const PortRef& aPortRef) override;
142 const NodeName mName;
143 const UniquePtr<Node> mNode;
145 template <class T>
146 using NodeMap = nsTHashMap<NodeNameHashKey, T>;
148 struct Invite {
149 // The channel which is being invited. This will have a temporary name until
150 // the invite is completed.
151 RefPtr<NodeChannel> mChannel;
152 // The port which will be merged with the port information from the new
153 // child process when recieved.
154 PortRef mToMerge;
157 struct State {
158 // Channels for connecting to all known peers.
159 NodeMap<RefPtr<NodeChannel>> mPeers;
161 // Messages which are queued for peers which we been introduced to yet.
162 NodeMap<Queue<UniquePtr<IPC::Message>, 64>> mPendingMessages;
164 // Connections for peers being invited to the network.
165 NodeMap<Invite> mInvites;
167 // Ports which are waiting to be merged by a particular peer node.
168 NodeMap<nsTArray<PortRef>> mPendingMerges;
171 DataMutex<State> mState{"NodeController::mState"};
174 } // namespace mozilla::ipc
176 #endif