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