blob: de5373d0967c214b08a37bca887b21c9e16577a2 [file] [log] [blame]
Avi Drissmand387f0922022-09-14 20:51:311// Copyright 2016 The Chromium Authors
rockotce69a042016-01-26 19:23:212// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
Ken Rockotdba46db2018-07-04 18:41:045#ifndef MOJO_CORE_NODE_CHANNEL_H_
6#define MOJO_CORE_NODE_CHANNEL_H_
rockotce69a042016-01-26 19:23:217
amistryba362cd2016-03-17 00:53:468#include <utility>
Wez6d83a0b2017-11-28 01:17:159#include <vector>
rockotce69a042016-01-26 19:23:2110
Brett Wilsonb02c0a22017-09-25 22:34:4211#include "base/containers/queue.h"
Avi Drissmand70f89a2023-01-11 23:52:5512#include "base/functional/callback.h"
Keishi Hattori0e45c022021-11-27 09:25:5213#include "base/memory/raw_ptr.h"
Ken Rockot9f9ebab32020-08-17 20:09:1914#include "base/memory/ref_counted_delete_on_sequence.h"
Robert Sesek0e7f165a2020-11-20 21:31:4515#include "base/process/process.h"
rockotce69a042016-01-26 19:23:2116#include "base/process/process_handle.h"
17#include "base/synchronization/lock.h"
Patrick Monette643cdf62021-10-15 19:13:4218#include "base/task/single_thread_task_runner.h"
rockotce69a042016-01-26 19:23:2119#include "build/build_config.h"
Ken Rockotdba46db2018-07-04 18:41:0420#include "mojo/core/channel.h"
21#include "mojo/core/connection_params.h"
22#include "mojo/core/embedder/process_error_callback.h"
23#include "mojo/core/ports/name.h"
Ken Rockot9f9ebab32020-08-17 20:09:1924#include "mojo/core/system_impl_export.h"
rockotce69a042016-01-26 19:23:2125
26namespace mojo {
Ken Rockotdba46db2018-07-04 18:41:0427namespace core {
rockotce69a042016-01-26 19:23:2128
Andrea Orru96e94342024-03-16 01:45:3329inline constexpr uint64_t kNodeCapabilityNone = 0;
30inline constexpr uint64_t kNodeCapabilitySupportsUpgrade = 1;
31
32inline constexpr uint32_t kNodeChannelHeaderSize = 8;
Brian Geffon12b581a2021-02-03 23:48:0333
rockotce69a042016-01-26 19:23:2134// Wraps a Channel to send and receive Node control messages.
Ken Rockot9f9ebab32020-08-17 20:09:1935class MOJO_SYSTEM_IMPL_EXPORT NodeChannel
36 : public base::RefCountedDeleteOnSequence<NodeChannel>,
37 public Channel::Delegate {
rockotce69a042016-01-26 19:23:2138 public:
39 class Delegate {
40 public:
Anand K Mistry48d93df2020-06-18 00:04:2241 virtual ~Delegate() = default;
Ken Rockot029898542018-02-21 15:13:4342 virtual void OnAcceptInvitee(const ports::NodeName& from_node,
43 const ports::NodeName& inviter_name,
44 const ports::NodeName& token) = 0;
45 virtual void OnAcceptInvitation(const ports::NodeName& from_node,
46 const ports::NodeName& token,
47 const ports::NodeName& invitee_name) = 0;
rockot905ba7f2016-02-08 21:16:2548 virtual void OnAddBrokerClient(const ports::NodeName& from_node,
49 const ports::NodeName& client_name,
amistrye1fcd6a2016-02-27 01:49:4050 base::ProcessHandle process_handle) = 0;
Ken Rockot29b0a322018-06-29 17:38:0751 virtual void OnBrokerClientAdded(const ports::NodeName& from_node,
52 const ports::NodeName& client_name,
53 PlatformHandle broker_channel) = 0;
54 virtual void OnAcceptBrokerClient(const ports::NodeName& from_node,
55 const ports::NodeName& broker_name,
Brian Geffon12b581a2021-02-03 23:48:0356 PlatformHandle broker_channel,
57 const uint64_t broker_capabilities) = 0;
Ken Rockot5d983722017-05-31 04:46:5758 virtual void OnEventMessage(const ports::NodeName& from_node,
rockot73af3952016-05-17 05:19:3359 Channel::MessagePtr message) = 0;
rockot7f38d5b2016-02-09 20:16:4760 virtual void OnRequestPortMerge(const ports::NodeName& from_node,
61 const ports::PortName& connector_port_name,
62 const std::string& token) = 0;
rockotce69a042016-01-26 19:23:2163 virtual void OnRequestIntroduction(const ports::NodeName& from_node,
64 const ports::NodeName& name) = 0;
65 virtual void OnIntroduce(const ports::NodeName& from_node,
66 const ports::NodeName& name,
Brian Geffon12b581a2021-02-03 23:48:0367 PlatformHandle channel_handle,
68 const uint64_t remote_capabilities) = 0;
rockot3a915752016-06-23 20:14:3269 virtual void OnBroadcast(const ports::NodeName& from_node,
70 Channel::MessagePtr message) = 0;
Xiaohan Wangaa41c682022-01-14 18:50:4971#if BUILDFLAG(IS_WIN)
Ken Rockot5d983722017-05-31 04:46:5772 virtual void OnRelayEventMessage(const ports::NodeName& from_node,
rockotce69a042016-01-26 19:23:2173 base::ProcessHandle from_process,
74 const ports::NodeName& destination,
75 Channel::MessagePtr message) = 0;
Ken Rockot5d983722017-05-31 04:46:5776 virtual void OnEventMessageFromRelay(const ports::NodeName& from_node,
rockotb46bf912016-06-11 23:18:1677 const ports::NodeName& source_node,
78 Channel::MessagePtr message) = 0;
rockotce69a042016-01-26 19:23:2179#endif
sammcb0a39f8c2016-08-10 06:29:5480 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;
amistry121c8802016-07-13 05:39:2784 virtual void OnChannelError(const ports::NodeName& node,
85 NodeChannel* channel) = 0;
rockotce69a042016-01-26 19:23:2186 };
87
88 static scoped_refptr<NodeChannel> Create(
89 Delegate* delegate,
jcivelliaba5a612017-03-10 00:28:3790 ConnectionParams connection_params,
Ken Rockotfada58122018-12-11 16:49:5491 Channel::HandlePolicy channel_handle_policy,
Gabriel Charettee926fc12019-12-16 19:00:0292 scoped_refptr<base::SingleThreadTaskRunner> io_task_runner,
rockotb46bf912016-06-11 23:18:1693 const ProcessErrorCallback& process_error_callback);
rockotce69a042016-01-26 19:23:2194
Peter Boströmfeef05a2021-10-05 21:35:0895 NodeChannel(const NodeChannel&) = delete;
96 NodeChannel& operator=(const NodeChannel&) = delete;
97
Ken Rockot559b70d2017-07-17 22:35:2498 static Channel::MessagePtr CreateEventMessage(size_t capacity,
99 size_t payload_size,
rockotce69a042016-01-26 19:23:21100 void** payload,
101 size_t num_handles);
102
Ken Rockot6740adb282021-04-07 22:18:36103 // Retrieves address and size of an Event message's underlying message data.
104 // Returns `false` if the message is not a valid Event message.
105 static bool GetEventMessageData(Channel::Message& message,
Ken Rockot5d983722017-05-31 04:46:57106 void** data,
rockotce69a042016-01-26 19:23:21107 size_t* num_data_bytes);
108
109 // Start receiving messages.
110 void Start();
111
112 // Permanently stop the channel from sending or receiving messages.
113 void ShutDown();
114
amistrye64e2962016-06-15 17:57:27115 // Leaks the pipe handle instead of closing it on shutdown.
116 void LeakHandleOnShutdown();
117
Lukasz Anforowicz07cdf1152020-03-24 20:52:50118 // Invokes the bad message callback for this channel. To avoid losing error
119 // reports the caller should ensure that the channel |HasBadMessageHandler|
120 // before calling |NotifyBadMessage|.
rockotb46bf912016-06-11 23:18:16121 void NotifyBadMessage(const std::string& error);
122
Lukasz Anforowicz07cdf1152020-03-24 20:52:50123 // Returns whether the channel has a bad message handler.
124 bool HasBadMessageHandler() { return !process_error_callback_.is_null(); }
125
Robert Sesek0e7f165a2020-11-20 21:31:45126 void SetRemoteProcessHandle(base::Process process_handle);
rockot905ba7f2016-02-08 21:16:25127 bool HasRemoteProcessHandle();
Robert Sesek0e7f165a2020-11-20 21:31:45128 base::Process CloneRemoteProcessHandle();
rockotce69a042016-01-26 19:23:21129
130 // Used for context in Delegate calls (via |from_node| arguments.)
131 void SetRemoteNodeName(const ports::NodeName& name);
132
Ken Rockot029898542018-02-21 15:13:43133 void AcceptInvitee(const ports::NodeName& inviter_name,
134 const ports::NodeName& token);
135 void AcceptInvitation(const ports::NodeName& token,
136 const ports::NodeName& invitee_name);
sammcb0a39f8c2016-08-10 06:29:54137 void AcceptPeer(const ports::NodeName& sender_name,
138 const ports::NodeName& token,
139 const ports::PortName& port_name);
rockot905ba7f2016-02-08 21:16:25140 void AddBrokerClient(const ports::NodeName& client_name,
Robert Sesek0e7f165a2020-11-20 21:31:45141 base::Process process_handle);
rockot905ba7f2016-02-08 21:16:25142 void BrokerClientAdded(const ports::NodeName& client_name,
Ken Rockot29b0a322018-06-29 17:38:07143 PlatformHandle broker_channel);
rockot905ba7f2016-02-08 21:16:25144 void AcceptBrokerClient(const ports::NodeName& broker_name,
Brian Geffon12b581a2021-02-03 23:48:03145 PlatformHandle broker_channel,
146 const uint64_t broker_capabilities);
rockot7f38d5b2016-02-09 20:16:47147 void RequestPortMerge(const ports::PortName& connector_port_name,
rockot90fc3e52016-02-10 02:36:07148 const std::string& token);
rockotce69a042016-01-26 19:23:21149 void RequestIntroduction(const ports::NodeName& name);
Brian Geffon12b581a2021-02-03 23:48:03150 void Introduce(const ports::NodeName& name,
151 PlatformHandle channel_handle,
152 uint64_t capabilities);
Ken Rockot5d983722017-05-31 04:46:57153 void SendChannelMessage(Channel::MessagePtr message);
rockot3a915752016-06-23 20:14:32154 void Broadcast(Channel::MessagePtr message);
Ken Rockoted81c772019-09-20 06:41:17155 void BindBrokerHost(PlatformHandle broker_host_handle);
rockotce69a042016-01-26 19:23:21156
Brian Geffon12b581a2021-02-03 23:48:03157 uint64_t RemoteCapabilities() const;
158 bool HasRemoteCapability(const uint64_t capability) const;
159 void SetRemoteCapabilities(const uint64_t capability);
160
161 uint64_t LocalCapabilities() const;
162 bool HasLocalCapability(const uint64_t capability) const;
163 void SetLocalCapabilities(const uint64_t capability);
164
Xiaohan Wangaa41c682022-01-14 18:50:49165#if BUILDFLAG(IS_WIN)
rockotce69a042016-01-26 19:23:21166 // Relay the message to the specified node via this channel. This is used to
167 // pass windows handles between two processes that do not have permission to
168 // duplicate handles into the other's address space. The relay process is
169 // assumed to have that permission.
Ken Rockot5d983722017-05-31 04:46:57170 void RelayEventMessage(const ports::NodeName& destination,
rockotce69a042016-01-26 19:23:21171 Channel::MessagePtr message);
rockotb46bf912016-06-11 23:18:16172
173 // Sends a message to its destination from a relay. This is interpreted by the
Ken Rockot5d983722017-05-31 04:46:57174 // receiver similarly to EventMessage, but the original source node is
rockotb46bf912016-06-11 23:18:16175 // provided as additional message metadata from the (trusted) relay node.
Ken Rockot5d983722017-05-31 04:46:57176 void EventMessageFromRelay(const ports::NodeName& source,
rockotb46bf912016-06-11 23:18:16177 Channel::MessagePtr message);
rockotce69a042016-01-26 19:23:21178#endif
179
Brian Geffon12b581a2021-02-03 23:48:03180 void OfferChannelUpgrade();
181
rockotce69a042016-01-26 19:23:21182 private:
Ken Rockot9f9ebab32020-08-17 20:09:19183 friend class base::RefCountedDeleteOnSequence<NodeChannel>;
184 friend class base::DeleteHelper<NodeChannel>;
rockotce69a042016-01-26 19:23:21185
Brett Wilsonb02c0a22017-09-25 22:34:42186 using PendingMessageQueue = base::queue<Channel::MessagePtr>;
amistryba362cd2016-03-17 00:53:46187 using PendingRelayMessageQueue =
Brett Wilsonb02c0a22017-09-25 22:34:42188 base::queue<std::pair<ports::NodeName, Channel::MessagePtr>>;
amistryba362cd2016-03-17 00:53:46189
rockotce69a042016-01-26 19:23:21190 NodeChannel(Delegate* delegate,
jcivelliaba5a612017-03-10 00:28:37191 ConnectionParams connection_params,
Ken Rockotfada58122018-12-11 16:49:54192 Channel::HandlePolicy channel_handle_policy,
Gabriel Charettee926fc12019-12-16 19:00:02193 scoped_refptr<base::SingleThreadTaskRunner> io_task_runner,
rockotb46bf912016-06-11 23:18:16194 const ProcessErrorCallback& process_error_callback);
rockotce69a042016-01-26 19:23:21195 ~NodeChannel() override;
196
Ken Rockoted81c772019-09-20 06:41:17197 // Creates a BrokerHost to satisfy a |BindBrokerHost()| request from the other
198 // end of the channel.
199 void CreateAndBindLocalBrokerHost(PlatformHandle broker_host_handle);
200
rockotce69a042016-01-26 19:23:21201 // Channel::Delegate:
Ken Rockot043152da62018-06-29 03:22:16202 void OnChannelMessage(const void* payload,
203 size_t payload_size,
Scott Violetdd480bc2024-10-16 21:15:14204 std::vector<PlatformHandle> handles,
205 scoped_refptr<ipcz_driver::Envelope> envelope) override;
Ken Rockot7f49ca42017-07-13 00:17:26206 void OnChannelError(Channel::Error error) override;
rockotce69a042016-01-26 19:23:21207
208 void WriteChannelMessage(Channel::MessagePtr message);
209
Brian Geffon12b581a2021-02-03 23:48:03210 // This method is responsible for setting up the default set of capabilities
211 // for this channel.
212 void InitializeLocalCapabilities();
213
Pâris146ae0c12023-06-08 17:43:43214 // This dangling raw_ptr occurred in:
215 // mojo_unittests: NodeChannelTest.MessagesCannotBeSmallerThanOldestVersion
216 // https://ci.chromium.org/ui/p/chromium/builders/try/linux-rel/1425190/test-results?q=ExactID%3Aninja%3A%2F%2Fmojo%3Amojo_unittests%2FNodeChannelTest.MessagesCannotBeSmallerThanOldestVersion+VHash%3A589215eb23c7875a
217 const raw_ptr<Delegate, FlakyDanglingUntriaged> delegate_;
rockotb46bf912016-06-11 23:18:16218 const ProcessErrorCallback process_error_callback_;
rockotce69a042016-01-26 19:23:21219
220 base::Lock channel_lock_;
Ken Rockot9f9ebab32020-08-17 20:09:19221 scoped_refptr<Channel> channel_ GUARDED_BY(channel_lock_);
rockotce69a042016-01-26 19:23:21222
Ken Rockot9f9ebab32020-08-17 20:09:19223 // Must only be accessed from the owning task runner's thread.
rockotce69a042016-01-26 19:23:21224 ports::NodeName remote_node_name_;
225
Brian Geffon12b581a2021-02-03 23:48:03226 uint64_t remote_capabilities_ = kNodeCapabilityNone;
227 uint64_t local_capabilities_ = kNodeCapabilityNone;
228
rockotce69a042016-01-26 19:23:21229 base::Lock remote_process_handle_lock_;
Robert Sesek0e7f165a2020-11-20 21:31:45230 base::Process remote_process_handle_;
rockotce69a042016-01-26 19:23:21231};
232
Ken Rockotdba46db2018-07-04 18:41:04233} // namespace core
rockotce69a042016-01-26 19:23:21234} // namespace mojo
235
Ken Rockotdba46db2018-07-04 18:41:04236#endif // MOJO_CORE_NODE_CHANNEL_H_