• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_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 
20 namespace mojo {
21 namespace core {
22 
23 const size_t kChannelMessageAlignment = 8;
24 
IsAlignedForChannelMessage(size_t n)25 constexpr 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.
32 class 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 
dataMessage153     const void* data() const { return data_; }
data_num_bytesMessage154     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:
~Delegate()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().
set_remote_process(ScopedProcessHandle remote_process)277   void set_remote_process(ScopedProcessHandle remote_process) {
278     DCHECK(!remote_process_.is_valid());
279     remote_process_ = std::move(remote_process);
280   }
remote_process()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 
delegate()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_
371