OLD | NEW |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #ifndef MOJO_EDK_SYSTEM_CHANNEL_H_ | 5 #ifndef MOJO_EDK_SYSTEM_CHANNEL_H_ |
6 #define MOJO_EDK_SYSTEM_CHANNEL_H_ | 6 #define MOJO_EDK_SYSTEM_CHANNEL_H_ |
7 | 7 |
8 #include "base/logging.h" | 8 #include "base/logging.h" |
9 #include "base/macros.h" | 9 #include "base/macros.h" |
10 #include "base/memory/ref_counted.h" | 10 #include "base/memory/ref_counted.h" |
11 #include "base/process/process_handle.h" | 11 #include "base/process/process_handle.h" |
12 #include "base/task_runner.h" | 12 #include "base/task_runner.h" |
13 #include "mojo/edk/embedder/platform_handle_vector.h" | 13 #include "mojo/edk/embedder/platform_handle_vector.h" |
14 #include "mojo/edk/embedder/scoped_platform_handle.h" | 14 #include "mojo/edk/embedder/scoped_platform_handle.h" |
15 | 15 |
16 namespace mojo { | 16 namespace mojo { |
17 namespace edk { | 17 namespace edk { |
18 | 18 |
19 const size_t kChannelMessageAlignment = 8; | 19 const size_t kChannelMessageAlignment = 8; |
20 | 20 |
| 21 constexpr bool IsAlignedForChannelMessage(size_t n) { |
| 22 return n % kChannelMessageAlignment == 0; |
| 23 } |
| 24 |
21 // Channel provides a thread-safe interface to read and write arbitrary | 25 // Channel provides a thread-safe interface to read and write arbitrary |
22 // delimited messages over an underlying I/O channel, optionally transferring | 26 // delimited messages over an underlying I/O channel, optionally transferring |
23 // one or more platform handles in the process. | 27 // one or more platform handles in the process. |
24 class Channel : public base::RefCountedThreadSafe<Channel> { | 28 class MOJO_SYSTEM_IMPL_EXPORT Channel |
| 29 : public base::RefCountedThreadSafe<Channel> { |
25 public: | 30 public: |
26 struct Message; | 31 struct Message; |
27 | 32 |
28 using MessagePtr = std::unique_ptr<Message>; | 33 using MessagePtr = std::unique_ptr<Message>; |
29 | 34 |
30 // A message to be written to a channel. | 35 // A message to be written to a channel. |
31 struct Message { | 36 struct MOJO_SYSTEM_IMPL_EXPORT Message { |
| 37 enum class MessageType : uint16_t { |
| 38 // An old format normal message, that uses the LegacyHeader. |
| 39 // Only used on Android and ChromeOS. |
| 40 // TODO(jcivelli): remove legacy support when Arc++ has updated to Mojo |
| 41 // with normal versioned messages. crbug.com/695645 |
| 42 NORMAL_LEGACY = 0, |
| 43 #if defined(OS_MACOSX) |
| 44 // A control message containing handles to echo back. |
| 45 HANDLES_SENT, |
| 46 // A control message containing handles that can now be closed. |
| 47 HANDLES_SENT_ACK, |
| 48 #endif |
| 49 // A normal message that uses Header and can contain extra header values. |
| 50 NORMAL, |
| 51 }; |
| 52 |
32 #pragma pack(push, 1) | 53 #pragma pack(push, 1) |
33 struct Header { | 54 // Old message wire format for ChromeOS and Android, used by NORMAL_LEGACY |
34 enum class MessageType : uint16_t { | 55 // messages. |
35 // A normal message. | 56 struct LegacyHeader { |
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. | 57 // Message size in bytes, including the header. |
46 uint32_t num_bytes; | 58 uint32_t num_bytes; |
47 | 59 |
48 #if defined(MOJO_EDK_LEGACY_PROTOCOL) | |
49 // Old message wire format for ChromeOS and Android. | |
50 // Number of attached handles. | 60 // Number of attached handles. |
51 uint16_t num_handles; | 61 uint16_t num_handles; |
52 | 62 |
53 MessageType message_type; | 63 MessageType message_type; |
54 #else | 64 }; |
| 65 |
| 66 // Header used by NORMAL messages. |
| 67 // To preserve backward compatibility with LegacyHeader, the num_bytes and |
| 68 // message_type field must be at the same offset as in LegacyHeader. |
| 69 struct Header { |
| 70 // Message size in bytes, including the header. |
| 71 uint32_t num_bytes; |
| 72 |
55 // Total size of header, including extra header data (i.e. HANDLEs on | 73 // Total size of header, including extra header data (i.e. HANDLEs on |
56 // windows). | 74 // windows). |
57 uint16_t num_header_bytes; | 75 uint16_t num_header_bytes; |
58 | 76 |
| 77 MessageType message_type; |
| 78 |
59 // Number of attached handles. May be less than the reserved handle | 79 // Number of attached handles. May be less than the reserved handle |
60 // storage size in this message on platforms that serialise handles as | 80 // storage size in this message on platforms that serialise handles as |
61 // data (i.e. HANDLEs on Windows, Mach ports on OSX). | 81 // data (i.e. HANDLEs on Windows, Mach ports on OSX). |
62 uint16_t num_handles; | 82 uint16_t num_handles; |
63 | 83 |
64 MessageType message_type; | |
65 | |
66 char padding[6]; | 84 char padding[6]; |
67 #endif // defined(MOJO_EDK_LEGACY_PROTOCOL) | |
68 }; | 85 }; |
69 | 86 |
70 #if defined(OS_MACOSX) && !defined(OS_IOS) | 87 #if defined(OS_MACOSX) && !defined(OS_IOS) |
71 struct MachPortsEntry { | 88 struct MachPortsEntry { |
72 // Index of Mach port in the original vector of PlatformHandles. | 89 // Index of Mach port in the original vector of PlatformHandles. |
73 uint16_t index; | 90 uint16_t index; |
74 | 91 |
75 // Mach port name. | 92 // Mach port name. |
76 uint32_t mach_port; | 93 uint32_t mach_port; |
77 static_assert(sizeof(mach_port_t) <= sizeof(uint32_t), | 94 static_assert(sizeof(mach_port_t) <= sizeof(uint32_t), |
(...skipping 19 matching lines...) Expand all Loading... |
97 // See: https://msdn.microsoft.com/en-us/library/aa384203(VS.85).aspx | 114 // See: https://msdn.microsoft.com/en-us/library/aa384203(VS.85).aspx |
98 uint32_t handle; | 115 uint32_t handle; |
99 }; | 116 }; |
100 static_assert(sizeof(HandleEntry) == 4, | 117 static_assert(sizeof(HandleEntry) == 4, |
101 "sizeof(HandleEntry) must be 4 bytes"); | 118 "sizeof(HandleEntry) must be 4 bytes"); |
102 #endif | 119 #endif |
103 #pragma pack(pop) | 120 #pragma pack(pop) |
104 | 121 |
105 // Allocates and owns a buffer for message data with enough capacity for | 122 // Allocates and owns a buffer for message data with enough capacity for |
106 // |payload_size| bytes plus a header, plus |max_handles| platform handles. | 123 // |payload_size| bytes plus a header, plus |max_handles| platform handles. |
107 Message(size_t payload_size, | 124 Message(size_t payload_size, size_t max_handles); |
108 size_t max_handles, | 125 Message(size_t payload_size, size_t max_handles, MessageType message_type); |
109 Header::MessageType message_type = Header::MessageType::NORMAL); | |
110 | |
111 ~Message(); | 126 ~Message(); |
112 | 127 |
113 // Constructs a Message from serialized message data. | 128 // Constructs a Message from serialized message data. |
114 static MessagePtr Deserialize(const void* data, size_t data_num_bytes); | 129 static MessagePtr Deserialize(const void* data, size_t data_num_bytes); |
115 | 130 |
116 const void* data() const { return data_; } | 131 const void* data() const { return data_; } |
117 size_t data_num_bytes() const { return size_; } | 132 size_t data_num_bytes() const { return size_; } |
118 | 133 |
119 #if defined(MOJO_EDK_LEGACY_PROTOCOL) | 134 const void* extra_header() const; |
120 void* mutable_payload() { return static_cast<void*>(header_ + 1); } | 135 void* mutable_extra_header(); |
121 const void* payload() const { | 136 size_t extra_header_size() const; |
122 return static_cast<const void*>(header_ + 1); | 137 |
123 } | 138 void* mutable_payload(); |
| 139 const void* payload() const; |
124 size_t payload_size() const; | 140 size_t payload_size() const; |
125 #else | |
126 const void* extra_header() const { return data_ + sizeof(Header); } | |
127 void* mutable_extra_header() { return data_ + sizeof(Header); } | |
128 size_t extra_header_size() const { | |
129 return header_->num_header_bytes - sizeof(Header); | |
130 } | |
131 | 141 |
132 void* mutable_payload() { return data_ + header_->num_header_bytes; } | 142 size_t num_handles() const; |
133 const void* payload() const { return data_ + header_->num_header_bytes; } | 143 bool has_handles() const; |
134 size_t payload_size() const; | |
135 #endif // defined(MOJO_EDK_LEGACY_PROTOCOL) | |
136 | |
137 size_t num_handles() const { return header_->num_handles; } | |
138 bool has_handles() const { return header_->num_handles > 0; } | |
139 #if defined(OS_MACOSX) && !defined(OS_IOS) | 144 #if defined(OS_MACOSX) && !defined(OS_IOS) |
140 bool has_mach_ports() const; | 145 bool has_mach_ports() const; |
141 #endif | 146 #endif |
142 | 147 |
| 148 bool is_legacy_message() const; |
| 149 LegacyHeader* legacy_header() const; |
| 150 Header* header() const; |
| 151 |
143 // Note: SetHandles() and TakeHandles() invalidate any previous value of | 152 // Note: SetHandles() and TakeHandles() invalidate any previous value of |
144 // handles(). | 153 // handles(). |
145 void SetHandles(ScopedPlatformHandleVectorPtr new_handles); | 154 void SetHandles(ScopedPlatformHandleVectorPtr new_handles); |
146 ScopedPlatformHandleVectorPtr TakeHandles(); | 155 ScopedPlatformHandleVectorPtr TakeHandles(); |
147 // Version of TakeHandles that returns a vector of platform handles suitable | 156 // Version of TakeHandles that returns a vector of platform handles suitable |
148 // for transfer over an underlying OS mechanism. i.e. file descriptors over | 157 // 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, | 158 // a unix domain socket. Any handle that cannot be transferred this way, |
150 // such as Mach ports, will be removed. | 159 // such as Mach ports, will be removed. |
151 ScopedPlatformHandleVectorPtr TakeHandlesForTransport(); | 160 ScopedPlatformHandleVectorPtr TakeHandlesForTransport(); |
152 | 161 |
153 #if defined(OS_WIN) | 162 #if defined(OS_WIN) |
154 // Prepares the handles in this message for use in a different process. | 163 // 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 | 164 // 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 | 165 // 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 | 166 // closed by this call. Returns false iff one or more handles failed |
158 // duplication. | 167 // duplication. |
159 static bool RewriteHandles(base::ProcessHandle from_process, | 168 static bool RewriteHandles(base::ProcessHandle from_process, |
160 base::ProcessHandle to_process, | 169 base::ProcessHandle to_process, |
161 PlatformHandleVector* handles); | 170 PlatformHandleVector* handles); |
162 #endif | 171 #endif |
163 | 172 |
| 173 void SetVersionForTest(uint16_t version_number); |
| 174 |
164 private: | 175 private: |
165 size_t size_; | 176 size_t size_ = 0; |
166 size_t max_handles_; | 177 size_t max_handles_ = 0; |
167 char* data_; | 178 char* data_ = nullptr; |
168 Header* header_; | |
169 | 179 |
170 ScopedPlatformHandleVectorPtr handle_vector_; | 180 ScopedPlatformHandleVectorPtr handle_vector_; |
171 | 181 |
172 #if defined(OS_WIN) | 182 #if defined(OS_WIN) |
173 // On Windows, handles are serialised into the extra header section. | 183 // On Windows, handles are serialised into the extra header section. |
174 HandleEntry* handles_ = nullptr; | 184 HandleEntry* handles_ = nullptr; |
175 #elif defined(OS_MACOSX) && !defined(OS_IOS) | 185 #elif defined(OS_MACOSX) && !defined(OS_IOS) |
176 // On OSX, handles are serialised into the extra header section. | 186 // On OSX, handles are serialised into the extra header section. |
177 MachPortsExtraHeader* mach_ports_header_ = nullptr; | 187 MachPortsExtraHeader* mach_ports_header_ = nullptr; |
178 #endif | 188 #endif |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
263 // this is not necessarily an error condition. In such cases this returns | 273 // this is not necessarily an error condition. In such cases this returns |
264 // |true| but |*handles| will also be reset to null. | 274 // |true| but |*handles| will also be reset to null. |
265 virtual bool GetReadPlatformHandles( | 275 virtual bool GetReadPlatformHandles( |
266 size_t num_handles, | 276 size_t num_handles, |
267 const void* extra_header, | 277 const void* extra_header, |
268 size_t extra_header_size, | 278 size_t extra_header_size, |
269 ScopedPlatformHandleVectorPtr* handles) = 0; | 279 ScopedPlatformHandleVectorPtr* handles) = 0; |
270 | 280 |
271 // Handles a received control message. Returns |true| if the message is | 281 // Handles a received control message. Returns |true| if the message is |
272 // accepted, or |false| otherwise. | 282 // accepted, or |false| otherwise. |
273 virtual bool OnControlMessage(Message::Header::MessageType message_type, | 283 virtual bool OnControlMessage(Message::MessageType message_type, |
274 const void* payload, | 284 const void* payload, |
275 size_t payload_size, | 285 size_t payload_size, |
276 ScopedPlatformHandleVectorPtr handles); | 286 ScopedPlatformHandleVectorPtr handles); |
277 | 287 |
278 private: | 288 private: |
279 friend class base::RefCountedThreadSafe<Channel>; | 289 friend class base::RefCountedThreadSafe<Channel>; |
280 | 290 |
281 class ReadBuffer; | 291 class ReadBuffer; |
282 | 292 |
283 Delegate* delegate_; | 293 Delegate* delegate_; |
284 const std::unique_ptr<ReadBuffer> read_buffer_; | 294 const std::unique_ptr<ReadBuffer> read_buffer_; |
285 | 295 |
286 DISALLOW_COPY_AND_ASSIGN(Channel); | 296 DISALLOW_COPY_AND_ASSIGN(Channel); |
287 }; | 297 }; |
288 | 298 |
289 } // namespace edk | 299 } // namespace edk |
290 } // namespace mojo | 300 } // namespace mojo |
291 | 301 |
292 #endif // MOJO_EDK_SYSTEM_CHANNEL_H_ | 302 #endif // MOJO_EDK_SYSTEM_CHANNEL_H_ |
OLD | NEW |