1 // 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_EDK_SYSTEM_CHANNEL_H_
6 #define MOJO_EDK_SYSTEM_CHANNEL_H_
7
8 #include "base/logging.h"
9 #include "base/macros.h"
10 #include "base/memory/ref_counted.h"
11 #include "base/process/process_handle.h"
12 #include "base/task_runner.h"
13 #include "mojo/edk/embedder/connection_params.h"
14 #include "mojo/edk/embedder/platform_handle_vector.h"
15 #include "mojo/edk/embedder/scoped_platform_handle.h"
16
17 namespace mojo {
18 namespace edk {
19
20 const size_t kChannelMessageAlignment = 8;
21
IsAlignedForChannelMessage(size_t n)22 constexpr bool IsAlignedForChannelMessage(size_t n) {
23 return n % kChannelMessageAlignment == 0;
24 }
25
26 // Channel provides a thread-safe interface to read and write arbitrary
27 // delimited messages over an underlying I/O channel, optionally transferring
28 // one or more platform handles in the process.
29 class MOJO_SYSTEM_IMPL_EXPORT Channel
30 : public base::RefCountedThreadSafe<Channel> {
31 public:
32 struct Message;
33
34 using MessagePtr = std::unique_ptr<Message>;
35
36 // A message to be written to a channel.
37 struct MOJO_SYSTEM_IMPL_EXPORT Message {
38 enum class MessageType : uint16_t {
39 // An old format normal message, that uses the LegacyHeader.
40 // Only used on Android and ChromeOS.
41 // TODO(jcivelli): remove legacy support when Arc++ has updated to Mojo
42 // with normal versioned messages. crbug.com/695645
43 NORMAL_LEGACY = 0,
44 #if defined(OS_MACOSX)
45 // A control message containing handles to echo back.
46 HANDLES_SENT,
47 // A control message containing handles that can now be closed.
48 HANDLES_SENT_ACK,
49 #endif
50 // A normal message that uses Header and can contain extra header values.
51 NORMAL,
52 };
53
54 #pragma pack(push, 1)
55 // Old message wire format for ChromeOS and Android, used by NORMAL_LEGACY
56 // messages.
57 struct LegacyHeader {
58 // Message size in bytes, including the header.
59 uint32_t num_bytes;
60
61 // Number of attached handles.
62 uint16_t num_handles;
63
64 MessageType message_type;
65 };
66
67 // Header used by NORMAL messages.
68 // To preserve backward compatibility with LegacyHeader, the num_bytes and
69 // message_type field must be at the same offset as in LegacyHeader.
70 struct Header {
71 // Message size in bytes, including the header.
72 uint32_t num_bytes;
73
74 // Total size of header, including extra header data (i.e. HANDLEs on
75 // windows).
76 uint16_t num_header_bytes;
77
78 MessageType message_type;
79
80 // Number of attached handles. May be less than the reserved handle
81 // storage size in this message on platforms that serialise handles as
82 // data (i.e. HANDLEs on Windows, Mach ports on OSX).
83 uint16_t num_handles;
84
85 char padding[6];
86 };
87
88 #if defined(OS_MACOSX) && !defined(OS_IOS)
89 struct MachPortsEntry {
90 // Index of Mach port in the original vector of PlatformHandles.
91 uint16_t index;
92
93 // Mach port name.
94 uint32_t mach_port;
95 static_assert(sizeof(mach_port_t) <= sizeof(uint32_t),
96 "mach_port_t must be no larger than uint32_t");
97 };
98 static_assert(sizeof(MachPortsEntry) == 6,
99 "sizeof(MachPortsEntry) must be 6 bytes");
100
101 // Structure of the extra header field when present on OSX.
102 struct MachPortsExtraHeader {
103 // Actual number of Mach ports encoded in the extra header.
104 uint16_t num_ports;
105
106 // Array of encoded Mach ports. If |num_ports| > 0, |entries[0]| through
107 // to |entries[num_ports-1]| inclusive are valid.
108 MachPortsEntry entries[0];
109 };
110 static_assert(sizeof(MachPortsExtraHeader) == 2,
111 "sizeof(MachPortsExtraHeader) must be 2 bytes");
112 #elif defined(OS_WIN)
113 struct HandleEntry {
114 // The windows HANDLE. HANDLEs are guaranteed to fit inside 32-bits.
115 // See: https://msdn.microsoft.com/en-us/library/aa384203(VS.85).aspx
116 uint32_t handle;
117 };
118 static_assert(sizeof(HandleEntry) == 4,
119 "sizeof(HandleEntry) must be 4 bytes");
120 #endif
121 #pragma pack(pop)
122
123 // Allocates and owns a buffer for message data with enough capacity for
124 // |payload_size| bytes plus a header, plus |max_handles| platform handles.
125 Message(size_t payload_size, size_t max_handles);
126 Message(size_t payload_size, size_t max_handles, MessageType message_type);
127 ~Message();
128
129 // Constructs a Message from serialized message data.
130 static MessagePtr Deserialize(const void* data, size_t data_num_bytes);
131
dataMessage132 const void* data() const { return data_; }
data_num_bytesMessage133 size_t data_num_bytes() const { return size_; }
134
135 const void* extra_header() const;
136 void* mutable_extra_header();
137 size_t extra_header_size() const;
138
139 void* mutable_payload();
140 const void* payload() const;
141 size_t payload_size() const;
142
143 size_t num_handles() const;
144 bool has_handles() const;
145 #if defined(OS_MACOSX) && !defined(OS_IOS)
146 bool has_mach_ports() const;
147 #endif
148
149 bool is_legacy_message() const;
150 LegacyHeader* legacy_header() const;
151 Header* header() const;
152
153 // Note: SetHandles() and TakeHandles() invalidate any previous value of
154 // handles().
155 void SetHandles(ScopedPlatformHandleVectorPtr new_handles);
156 ScopedPlatformHandleVectorPtr TakeHandles();
157 // Version of TakeHandles that returns a vector of platform handles suitable
158 // for transfer over an underlying OS mechanism. i.e. file descriptors over
159 // a unix domain socket. Any handle that cannot be transferred this way,
160 // such as Mach ports, will be removed.
161 ScopedPlatformHandleVectorPtr TakeHandlesForTransport();
162
163 #if defined(OS_WIN)
164 // Prepares the handles in this message for use in a different process.
165 // Upon calling this the handles should belong to |from_process|; after the
166 // call they'll belong to |to_process|. The source handles are always
167 // closed by this call. Returns false iff one or more handles failed
168 // duplication.
169 static bool RewriteHandles(base::ProcessHandle from_process,
170 base::ProcessHandle to_process,
171 PlatformHandleVector* handles);
172 #endif
173
174 void SetVersionForTest(uint16_t version_number);
175
176 private:
177 size_t size_ = 0;
178 size_t max_handles_ = 0;
179 char* data_ = nullptr;
180
181 ScopedPlatformHandleVectorPtr handle_vector_;
182
183 #if defined(OS_WIN)
184 // On Windows, handles are serialised into the extra header section.
185 HandleEntry* handles_ = nullptr;
186 #elif defined(OS_MACOSX) && !defined(OS_IOS)
187 // On OSX, handles are serialised into the extra header section.
188 MachPortsExtraHeader* mach_ports_header_ = nullptr;
189 #endif
190
191 DISALLOW_COPY_AND_ASSIGN(Message);
192 };
193
194 // Delegate methods are called from the I/O task runner with which the Channel
195 // was created (see Channel::Create).
196 class Delegate {
197 public:
~Delegate()198 virtual ~Delegate() {}
199
200 // Notify of a received message. |payload| is not owned and must not be
201 // retained; it will be null if |payload_size| is 0. |handles| are
202 // transferred to the callee.
203 virtual void OnChannelMessage(const void* payload,
204 size_t payload_size,
205 ScopedPlatformHandleVectorPtr handles) = 0;
206
207 // Notify that an error has occured and the Channel will cease operation.
208 virtual void OnChannelError() = 0;
209 };
210
211 // Creates a new Channel around a |platform_handle|, taking ownership of the
212 // handle. All I/O on the handle will be performed on |io_task_runner|.
213 // Note that ShutDown() MUST be called on the Channel some time before
214 // |delegate| is destroyed.
215 static scoped_refptr<Channel> Create(
216 Delegate* delegate,
217 ConnectionParams connection_params,
218 scoped_refptr<base::TaskRunner> io_task_runner);
219
220 // Request that the channel be shut down. This should always be called before
221 // releasing the last reference to a Channel to ensure that it's cleaned up
222 // on its I/O task runner's thread.
223 //
224 // Delegate methods will no longer be invoked after this call.
225 void ShutDown();
226
227 // Begin processing I/O events. Delegate methods must only be invoked after
228 // this call.
229 virtual void Start() = 0;
230
231 // Stop processing I/O events.
232 virtual void ShutDownImpl() = 0;
233
234 // Queues an outgoing message on the Channel. This message will either
235 // eventually be written or will fail to write and trigger
236 // Delegate::OnChannelError.
237 virtual void Write(MessagePtr message) = 0;
238
239 // Causes the platform handle to leak when this channel is shut down instead
240 // of closing it.
241 virtual void LeakHandle() = 0;
242
243 protected:
244 explicit Channel(Delegate* delegate);
245 virtual ~Channel();
246
247 // Called by the implementation when it wants somewhere to stick data.
248 // |*buffer_capacity| may be set by the caller to indicate the desired buffer
249 // size. If 0, a sane default size will be used instead.
250 //
251 // Returns the address of a buffer which can be written to, and indicates its
252 // actual capacity in |*buffer_capacity|.
253 char* GetReadBuffer(size_t* buffer_capacity);
254
255 // Called by the implementation when new data is available in the read
256 // buffer. Returns false to indicate an error. Upon success,
257 // |*next_read_size_hint| will be set to a recommended size for the next
258 // read done by the implementation.
259 bool OnReadComplete(size_t bytes_read, size_t* next_read_size_hint);
260
261 // Called by the implementation when something goes horribly wrong. It is NOT
262 // OK to call this synchronously from any public interface methods.
263 void OnError();
264
265 // Retrieves the set of platform handles read for a given message.
266 // |extra_header| and |extra_header_size| correspond to the extra header data.
267 // Depending on the Channel implementation, this body may encode platform
268 // handles, or handles may be stored and managed elsewhere by the
269 // implementation.
270 //
271 // Returns |false| on unrecoverable error (i.e. the Channel should be closed).
272 // Returns |true| otherwise. Note that it is possible on some platforms for an
273 // insufficient number of handles to be available when this call is made, but
274 // this is not necessarily an error condition. In such cases this returns
275 // |true| but |*handles| will also be reset to null.
276 virtual bool GetReadPlatformHandles(
277 size_t num_handles,
278 const void* extra_header,
279 size_t extra_header_size,
280 ScopedPlatformHandleVectorPtr* handles) = 0;
281
282 // Handles a received control message. Returns |true| if the message is
283 // accepted, or |false| otherwise.
284 virtual bool OnControlMessage(Message::MessageType message_type,
285 const void* payload,
286 size_t payload_size,
287 ScopedPlatformHandleVectorPtr handles);
288
289 private:
290 friend class base::RefCountedThreadSafe<Channel>;
291
292 class ReadBuffer;
293
294 Delegate* delegate_;
295 const std::unique_ptr<ReadBuffer> read_buffer_;
296
297 DISALLOW_COPY_AND_ASSIGN(Channel);
298 };
299
300 } // namespace edk
301 } // namespace mojo
302
303 #endif // MOJO_EDK_SYSTEM_CHANNEL_H_
304