• 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_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