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