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 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 132 const void* data() const { return data_; } 133 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: 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