blob: 17108e9f027861a5fd9abbf058840f8536229339 [file] [log] [blame]
Jakub Pawlowski86aa2252017-04-05 09:22:29 -07001// 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_CORE_CHANNEL_H_
6#define MOJO_CORE_CHANNEL_H_
7
8#include <vector>
9
10#include "base/macros.h"
11#include "base/memory/ref_counted.h"
12#include "base/process/process_handle.h"
13#include "base/task_runner.h"
14#include "build/build_config.h"
15#include "mojo/core/connection_params.h"
16#include "mojo/core/platform_handle_in_transit.h"
17#include "mojo/core/scoped_process_handle.h"
18#include "mojo/public/cpp/platform/platform_handle.h"
19
20namespace mojo {
21namespace core {
22
23const size_t kChannelMessageAlignment = 8;
24
25constexpr bool IsAlignedForChannelMessage(size_t n) {
26 return n % kChannelMessageAlignment == 0;
27}
28
29// Channel provides a thread-safe interface to read and write arbitrary
30// delimited messages over an underlying I/O channel, optionally transferring
31// one or more platform handles in the process.
32class MOJO_SYSTEM_IMPL_EXPORT Channel
33 : public base::RefCountedThreadSafe<Channel> {
34 public:
35 struct Message;
36
37 using MessagePtr = std::unique_ptr<Message>;
38
39 // A message to be written to a channel.
40 struct MOJO_SYSTEM_IMPL_EXPORT Message {
41 enum class MessageType : uint16_t {
42 // An old format normal message, that uses the LegacyHeader.
43 // Only used on Android and ChromeOS.
44 // TODO(https://crbug.com/695645): remove legacy support when Arc++ has
45 // updated to Mojo with normal versioned messages.
46 NORMAL_LEGACY = 0,
47#if defined(OS_MACOSX)
48 // A control message containing handles to echo back.
49 HANDLES_SENT,
50 // A control message containing handles that can now be closed.
51 HANDLES_SENT_ACK,
52#endif
53 // A normal message that uses Header and can contain extra header values.
54 NORMAL,
55 };
56
57#pragma pack(push, 1)
58 // Old message wire format for ChromeOS and Android, used by NORMAL_LEGACY
59 // messages.
60 struct LegacyHeader {
61 // Message size in bytes, including the header.
62 uint32_t num_bytes;
63
64 // Number of attached handles.
65 uint16_t num_handles;
66
67 MessageType message_type;
68 };
69
70 // Header used by NORMAL messages.
71 // To preserve backward compatibility with LegacyHeader, the num_bytes and
72 // message_type field must be at the same offset as in LegacyHeader.
73 struct Header {
74 // Message size in bytes, including the header.
75 uint32_t num_bytes;
76
77 // Total size of header, including extra header data (i.e. HANDLEs on
78 // windows).
79 uint16_t num_header_bytes;
80
81 MessageType message_type;
82
83 // Number of attached handles. May be less than the reserved handle
84 // storage size in this message on platforms that serialise handles as
85 // data (i.e. HANDLEs on Windows, Mach ports on OSX).
86 uint16_t num_handles;
87
88 char padding[6];
89 };
90
91#if defined(OS_MACOSX) && !defined(OS_IOS)
92 struct MachPortsEntry {
93 // Index of Mach port in the original vector of PlatformHandleInTransits.
94 uint16_t index;
95
96 // Mach port name.
97 uint32_t mach_port;
98 static_assert(sizeof(mach_port_t) <= sizeof(uint32_t),
99 "mach_port_t must be no larger than uint32_t");
100 };
101 static_assert(sizeof(MachPortsEntry) == 6,
102 "sizeof(MachPortsEntry) must be 6 bytes");
103
104 // Structure of the extra header field when present on OSX.
105 struct MachPortsExtraHeader {
106 // Actual number of Mach ports encoded in the extra header.
107 uint16_t num_ports;
108
109 // Array of encoded Mach ports. If |num_ports| > 0, |entries[0]| through
110 // to |entries[num_ports-1]| inclusive are valid.
111 MachPortsEntry entries[0];
112 };
113 static_assert(sizeof(MachPortsExtraHeader) == 2,
114 "sizeof(MachPortsExtraHeader) must be 2 bytes");
115#elif defined(OS_FUCHSIA)
116 struct HandleInfoEntry {
117 // The FDIO type associated with one or more handles, or zero for handles
118 // that do not belong to FDIO.
119 uint8_t type;
120 // Zero for non-FDIO handles, otherwise the number of handles to consume
121 // to generate an FDIO file-descriptor wrapper.
122 uint8_t count;
123 };
124#elif defined(OS_WIN)
125 struct HandleEntry {
126 // The windows HANDLE. HANDLEs are guaranteed to fit inside 32-bits.
127 // See: https://msdn.microsoft.com/en-us/library/aa384203(VS.85).aspx
128 uint32_t handle;
129 };
130 static_assert(sizeof(HandleEntry) == 4,
131 "sizeof(HandleEntry) must be 4 bytes");
132#endif
133#pragma pack(pop)
134
135 // Allocates and owns a buffer for message data with enough capacity for
136 // |payload_size| bytes plus a header, plus |max_handles| platform handles.
137 Message(size_t payload_size, size_t max_handles);
138 Message(size_t payload_size, size_t max_handles, MessageType message_type);
139 Message(size_t capacity, size_t payload_size, size_t max_handles);
140 Message(size_t capacity,
141 size_t max_handles,
142 size_t payload_size,
143 MessageType message_type);
144 ~Message();
145
146 // Constructs a Message from serialized message data, optionally coming from
147 // a known remote process.
148 static MessagePtr Deserialize(
149 const void* data,
150 size_t data_num_bytes,
151 base::ProcessHandle from_process = base::kNullProcessHandle);
152
153 const void* data() const { return data_; }
154 size_t data_num_bytes() const { return size_; }
155
156 // The current capacity of the message buffer, not counting internal header
157 // data.
158 size_t capacity() const;
159
160 // Extends the portion of the total message capacity which contains
161 // meaningful payload data. Storage capacity which falls outside of this
162 // range is not transmitted when the message is sent.
163 //
164 // If the message's current capacity is not large enough to accommodate the
165 // new payload size, it will be reallocated accordingly.
166 void ExtendPayload(size_t new_payload_size);
167
168 const void* extra_header() const;
169 void* mutable_extra_header();
170 size_t extra_header_size() const;
171
172 void* mutable_payload();
173 const void* payload() const;
174 size_t payload_size() const;
175
176 size_t num_handles() const;
177 bool has_handles() const;
178#if defined(OS_MACOSX) && !defined(OS_IOS)
179 bool has_mach_ports() const;
180#endif
181
182 bool is_legacy_message() const;
183 LegacyHeader* legacy_header() const;
184 Header* header() const;
185
186 // Note: SetHandles() and TakeHandles() invalidate any previous value of
187 // handles().
188 void SetHandles(std::vector<PlatformHandle> new_handles);
189 void SetHandles(std::vector<PlatformHandleInTransit> new_handles);
190 std::vector<PlatformHandleInTransit> TakeHandles();
191 // Version of TakeHandles that returns a vector of platform handles suitable
192 // for transfer over an underlying OS mechanism. i.e. file descriptors over
193 // a unix domain socket. Any handle that cannot be transferred this way,
194 // such as Mach ports, will be removed.
195 std::vector<PlatformHandleInTransit> TakeHandlesForTransport();
196
197 void SetVersionForTest(uint16_t version_number);
198
199 private:
200 // The message data buffer.
201 char* data_ = nullptr;
202
203 // The capacity of the buffer at |data_|.
204 size_t capacity_ = 0;
205
206 // The size of the message. This is the portion of |data_| that should
207 // be transmitted if the message is written to a channel. Includes all
208 // headers and user payload.
209 size_t size_ = 0;
210
211 // Maximum number of handles which may be attached to this message.
212 size_t max_handles_ = 0;
213
214 std::vector<PlatformHandleInTransit> handle_vector_;
215
216#if defined(OS_WIN)
217 // On Windows, handles are serialised into the extra header section.
218 HandleEntry* handles_ = nullptr;
219#elif defined(OS_MACOSX) && !defined(OS_IOS)
220 // On OSX, handles are serialised into the extra header section.
221 MachPortsExtraHeader* mach_ports_header_ = nullptr;
222#endif
223
224 DISALLOW_COPY_AND_ASSIGN(Message);
225 };
226
227 // Error types which may be reported by a Channel instance to its delegate.
228 enum class Error {
229 // The remote end of the channel has been closed, either explicitly or
230 // because the process which hosted it is gone.
231 kDisconnected,
232
233 // For connection-oriented channels (e.g. named pipes), an unexpected error
234 // occurred during channel connection.
235 kConnectionFailed,
236
237 // Some incoming data failed validation, implying either a buggy or
238 // compromised sender.
239 kReceivedMalformedData,
240 };
241
242 // Delegate methods are called from the I/O task runner with which the Channel
243 // was created (see Channel::Create).
244 class Delegate {
245 public:
246 virtual ~Delegate() {}
247
248 // Notify of a received message. |payload| is not owned and must not be
249 // retained; it will be null if |payload_size| is 0. |handles| are
250 // transferred to the callee.
251 virtual void OnChannelMessage(const void* payload,
252 size_t payload_size,
253 std::vector<PlatformHandle> handles) = 0;
254
255 // Notify that an error has occured and the Channel will cease operation.
256 virtual void OnChannelError(Error error) = 0;
257 };
258
259 // Creates a new Channel around a |platform_handle|, taking ownership of the
260 // handle. All I/O on the handle will be performed on |io_task_runner|.
261 // Note that ShutDown() MUST be called on the Channel some time before
262 // |delegate| is destroyed.
263 static scoped_refptr<Channel> Create(
264 Delegate* delegate,
265 ConnectionParams connection_params,
266 scoped_refptr<base::TaskRunner> io_task_runner);
267
268 // Request that the channel be shut down. This should always be called before
269 // releasing the last reference to a Channel to ensure that it's cleaned up
270 // on its I/O task runner's thread.
271 //
272 // Delegate methods will no longer be invoked after this call.
273 void ShutDown();
274
275 // Sets the process handle of the remote endpoint to which this Channel is
276 // connected. If called at all, must be called only once, and before Start().
277 void set_remote_process(ScopedProcessHandle remote_process) {
278 DCHECK(!remote_process_.is_valid());
279 remote_process_ = std::move(remote_process);
280 }
281 const ScopedProcessHandle& remote_process() const { return remote_process_; }
282
283 // Begin processing I/O events. Delegate methods must only be invoked after
284 // this call.
285 virtual void Start() = 0;
286
287 // Stop processing I/O events.
288 virtual void ShutDownImpl() = 0;
289
290 // Queues an outgoing message on the Channel. This message will either
291 // eventually be written or will fail to write and trigger
292 // Delegate::OnChannelError.
293 virtual void Write(MessagePtr message) = 0;
294
295 // Causes the platform handle to leak when this channel is shut down instead
296 // of closing it.
297 virtual void LeakHandle() = 0;
298
299 protected:
300 explicit Channel(Delegate* delegate);
301 virtual ~Channel();
302
303 Delegate* delegate() const { return delegate_; }
304
305 // Called by the implementation when it wants somewhere to stick data.
306 // |*buffer_capacity| may be set by the caller to indicate the desired buffer
307 // size. If 0, a sane default size will be used instead.
308 //
309 // Returns the address of a buffer which can be written to, and indicates its
310 // actual capacity in |*buffer_capacity|.
311 char* GetReadBuffer(size_t* buffer_capacity);
312
313 // Called by the implementation when new data is available in the read
314 // buffer. Returns false to indicate an error. Upon success,
315 // |*next_read_size_hint| will be set to a recommended size for the next
316 // read done by the implementation.
317 bool OnReadComplete(size_t bytes_read, size_t* next_read_size_hint);
318
319 // Called by the implementation when something goes horribly wrong. It is NOT
320 // OK to call this synchronously from any public interface methods.
321 void OnError(Error error);
322
323 // Retrieves the set of platform handles read for a given message.
324 // |extra_header| and |extra_header_size| correspond to the extra header data.
325 // Depending on the Channel implementation, this body may encode platform
326 // handles, or handles may be stored and managed elsewhere by the
327 // implementation.
328 //
329 // Returns |false| on unrecoverable error (i.e. the Channel should be closed).
330 // Returns |true| otherwise. Note that it is possible on some platforms for an
331 // insufficient number of handles to be available when this call is made, but
332 // this is not necessarily an error condition. In such cases this returns
333 // |true| but |*handles| will also be reset to null.
334 //
335 // If the implementation sets |*deferred| to |true|, it assumes responsibility
336 // for dispatching the message eventually. It must copy |payload| to retain
337 // it for later transmission.
338 virtual bool GetReadPlatformHandles(const void* payload,
339 size_t payload_size,
340 size_t num_handles,
341 const void* extra_header,
342 size_t extra_header_size,
343 std::vector<PlatformHandle>* handles,
344 bool* deferred) = 0;
345
346 // Handles a received control message. Returns |true| if the message is
347 // accepted, or |false| otherwise.
348 virtual bool OnControlMessage(Message::MessageType message_type,
349 const void* payload,
350 size_t payload_size,
351 std::vector<PlatformHandle> handles);
352
353 private:
354 friend class base::RefCountedThreadSafe<Channel>;
355
356 class ReadBuffer;
357
358 Delegate* delegate_;
359 const std::unique_ptr<ReadBuffer> read_buffer_;
360
361 // Handle to the process on the other end of this Channel, iff known.
362 ScopedProcessHandle remote_process_;
363
364 DISALLOW_COPY_AND_ASSIGN(Channel);
365};
366
367} // namespace core
368} // namespace mojo
369
370#endif // MOJO_CORE_CHANNEL_H_