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