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 #include "mojo/edk/system/channel.h" | 5 #include "mojo/edk/system/channel.h" |
6 | 6 |
7 #include <string.h> | 7 #include <string.h> |
8 | 8 |
9 #include <algorithm> | 9 #include <algorithm> |
10 #include <limits> | 10 #include <limits> |
11 #include <utility> | |
11 | 12 |
12 #include "base/macros.h" | 13 #include "base/macros.h" |
13 #include "base/memory/aligned_memory.h" | 14 #include "base/memory/aligned_memory.h" |
14 #include "mojo/edk/embedder/platform_handle.h" | 15 #include "mojo/edk/embedder/platform_handle.h" |
15 | 16 |
17 #if defined(OS_MACOSX) | |
erikchen
2016/03/09 19:13:17
it seems you're inconsistent on whether to include
Anand Mistry (off Chromium)
2016/03/11 07:44:17
Oops. I thought I standardised these. I'll take an
| |
18 #include "base/mac/mach_logging.h" | |
19 #endif | |
20 | |
16 namespace mojo { | 21 namespace mojo { |
17 namespace edk { | 22 namespace edk { |
18 | 23 |
19 namespace { | 24 namespace { |
20 | 25 |
21 static_assert(sizeof(Channel::Message::Header) % kChannelMessageAlignment == 0, | 26 static_assert(sizeof(Channel::Message::Header) % kChannelMessageAlignment == 0, |
22 "Invalid Header size."); | 27 "Invalid Header size."); |
23 | 28 |
24 #if defined(OS_CHROMEOS) | 29 #if defined(OS_CHROMEOS) |
25 static_assert(sizeof(Channel::Message::Header) == 8, | 30 static_assert(sizeof(Channel::Message::Header) == 8, |
(...skipping 10 matching lines...) Expand all Loading... | |
36 Channel::Message::Message(size_t payload_size, | 41 Channel::Message::Message(size_t payload_size, |
37 size_t max_handles, | 42 size_t max_handles, |
38 Header::MessageType message_type) | 43 Header::MessageType message_type) |
39 : max_handles_(max_handles) { | 44 : max_handles_(max_handles) { |
40 DCHECK_LE(max_handles_, kMaxAttachedHandles); | 45 DCHECK_LE(max_handles_, kMaxAttachedHandles); |
41 | 46 |
42 size_t extra_header_size = 0; | 47 size_t extra_header_size = 0; |
43 #if defined(OS_WIN) | 48 #if defined(OS_WIN) |
44 // On Windows we serialize platform handles into the extra header space. | 49 // On Windows we serialize platform handles into the extra header space. |
45 extra_header_size = max_handles_ * sizeof(PlatformHandle); | 50 extra_header_size = max_handles_ * sizeof(PlatformHandle); |
51 #elif defined(OS_MACOSX) | |
52 // On OSX, some of the platform handles may be mach ports, which are | |
53 // serialised into the message buffer. Since there could be a mix of fds and | |
54 // mach ports, we store the mach ports as an <index, port> pair (of uint32_t), | |
55 // so that the original ordering of handles can be re-created. | |
56 extra_header_size = max_handles * sizeof(MachPortsEntry); | |
46 #endif | 57 #endif |
47 // Pad extra header data to be aliged to |kChannelMessageAlignment| bytes. | 58 // Pad extra header data to be aliged to |kChannelMessageAlignment| bytes. |
48 if (extra_header_size % kChannelMessageAlignment) { | 59 if (extra_header_size % kChannelMessageAlignment) { |
49 extra_header_size += kChannelMessageAlignment - | 60 extra_header_size += kChannelMessageAlignment - |
50 (extra_header_size % kChannelMessageAlignment); | 61 (extra_header_size % kChannelMessageAlignment); |
51 } | 62 } |
52 DCHECK_EQ(0u, extra_header_size % kChannelMessageAlignment); | 63 DCHECK_EQ(0u, extra_header_size % kChannelMessageAlignment); |
53 #if defined(OS_CHROMEOS) | 64 #if defined(OS_CHROMEOS) |
54 DCHECK_EQ(0u, extra_header_size); | 65 DCHECK_EQ(0u, extra_header_size); |
55 #endif | 66 #endif |
(...skipping 10 matching lines...) Expand all Loading... | |
66 DCHECK_LE(sizeof(Header) + extra_header_size, | 77 DCHECK_LE(sizeof(Header) + extra_header_size, |
67 std::numeric_limits<uint16_t>::max()); | 78 std::numeric_limits<uint16_t>::max()); |
68 header_->message_type = message_type; | 79 header_->message_type = message_type; |
69 #if defined(OS_CHROMEOS) | 80 #if defined(OS_CHROMEOS) |
70 header_->num_handles = static_cast<uint16_t>(max_handles); | 81 header_->num_handles = static_cast<uint16_t>(max_handles); |
71 #else | 82 #else |
72 header_->num_header_bytes = | 83 header_->num_header_bytes = |
73 static_cast<uint16_t>(sizeof(Header) + extra_header_size); | 84 static_cast<uint16_t>(sizeof(Header) + extra_header_size); |
74 #endif | 85 #endif |
75 | 86 |
87 if (max_handles_ > 0) { | |
76 #if defined(OS_WIN) | 88 #if defined(OS_WIN) |
77 if (max_handles_ > 0) { | |
78 handles_ = reinterpret_cast<PlatformHandle*>(mutable_extra_header()); | 89 handles_ = reinterpret_cast<PlatformHandle*>(mutable_extra_header()); |
79 // Initialize all handles to invalid values. | 90 // Initialize all handles to invalid values. |
80 for (size_t i = 0; i < max_handles_; ++i) | 91 for (size_t i = 0; i < max_handles_; ++i) |
81 handles()[i] = PlatformHandle(); | 92 handles()[i] = PlatformHandle(); |
93 #elif defined(OS_MACOSX) && !defined(OS_IOS) | |
94 mach_ports_ = reinterpret_cast<MachPortsEntry*>(mutable_extra_header()); | |
95 // Initialize all handles to invalid values. | |
96 for (size_t i = 0; i < max_handles_; ++i) | |
97 mach_ports_[i] = {0, static_cast<uint32_t>(MACH_PORT_NULL)}; | |
98 #endif | |
82 } | 99 } |
83 #endif | |
84 } | 100 } |
85 | 101 |
86 Channel::Message::~Message() { | 102 Channel::Message::~Message() { |
87 #if defined(OS_WIN) | 103 #if defined(OS_WIN) |
88 // On POSIX the ScopedPlatformHandleVectorPtr will do this for us. | 104 // On POSIX the ScopedPlatformHandleVectorPtr will do this for us. |
89 for (size_t i = 0; i < header_->num_handles; ++i) | 105 for (size_t i = 0; i < header_->num_handles; ++i) |
90 handles()[i].CloseIfNecessary(); | 106 handles()[i].CloseIfNecessary(); |
91 #endif | 107 #endif |
92 base::AlignedFree(data_); | 108 base::AlignedFree(data_); |
93 } | 109 } |
94 | 110 |
95 // static | 111 // static |
96 Channel::MessagePtr Channel::Message::Deserialize(const void* data, | 112 Channel::MessagePtr Channel::Message::Deserialize(const void* data, |
97 size_t data_num_bytes) { | 113 size_t data_num_bytes) { |
98 #if !defined(OS_WIN) | 114 #if !defined(OS_WIN) && (!defined(OS_MACOSX) || defined(OS_IOS)) |
erikchen
2016/03/09 19:13:17
could you rewrite as !(defined(OS_MACOSX) && !defi
Anand Mistry (off Chromium)
2016/03/11 07:44:17
Done.
| |
99 // We only serialize messages into other messages when performing message | 115 // We only serialize messages into other messages when performing message |
100 // relay on Windows. | 116 // relay on Windows and OSX. |
101 NOTREACHED(); | 117 NOTREACHED(); |
102 return nullptr; | 118 return nullptr; |
103 #else | 119 #else |
104 if (data_num_bytes < sizeof(Header)) | 120 if (data_num_bytes < sizeof(Header)) |
105 return nullptr; | 121 return nullptr; |
106 | 122 |
107 const Header* header = reinterpret_cast<const Header*>(data); | 123 const Header* header = reinterpret_cast<const Header*>(data); |
108 if (header->num_bytes != data_num_bytes) { | 124 if (header->num_bytes != data_num_bytes) { |
109 DLOG(ERROR) << "Decoding invalid message: " << header->num_bytes | 125 DLOG(ERROR) << "Decoding invalid message: " << header->num_bytes |
110 << " != " << data_num_bytes; | 126 << " != " << data_num_bytes; |
111 return nullptr; | 127 return nullptr; |
112 } | 128 } |
113 | 129 |
114 if (header->num_bytes < header->num_header_bytes) { | 130 if (header->num_bytes < header->num_header_bytes) { |
115 DLOG(ERROR) << "Decoding invalid message: " << header->num_bytes << " < " | 131 DLOG(ERROR) << "Decoding invalid message: " << header->num_bytes << " < " |
116 << header->num_header_bytes; | 132 << header->num_header_bytes; |
117 return nullptr; | 133 return nullptr; |
118 } | 134 } |
119 | 135 |
120 uint32_t extra_header_size = header->num_header_bytes - sizeof(Header); | 136 uint32_t extra_header_size = header->num_header_bytes - sizeof(Header); |
137 #if defined(OS_WIN) | |
121 uint32_t max_handles = extra_header_size / sizeof(PlatformHandle); | 138 uint32_t max_handles = extra_header_size / sizeof(PlatformHandle); |
139 #elif defined(OS_MACOSX) | |
140 uint32_t max_handles = extra_header_size / sizeof(MachPortsEntry); | |
141 #endif | |
122 if (header->num_handles > max_handles) { | 142 if (header->num_handles > max_handles) { |
123 DLOG(ERROR) << "Decoding invalid message:" << header->num_handles << " > " | 143 DLOG(ERROR) << "Decoding invalid message:" << header->num_handles |
124 << max_handles; | 144 << " > " << max_handles; |
125 return nullptr; | 145 return nullptr; |
126 } | 146 } |
127 | 147 |
128 MessagePtr message( | 148 MessagePtr message(new Message(data_num_bytes - header->num_header_bytes, |
129 new Message(data_num_bytes - header->num_header_bytes, max_handles)); | 149 max_handles)); |
130 | |
131 DCHECK_EQ(message->data_num_bytes(), data_num_bytes); | 150 DCHECK_EQ(message->data_num_bytes(), data_num_bytes); |
132 DCHECK_EQ(message->extra_header_size(), extra_header_size); | 151 DCHECK_EQ(message->extra_header_size(), extra_header_size); |
133 DCHECK_EQ(message->header_->num_header_bytes, header->num_header_bytes); | 152 DCHECK_EQ(message->header_->num_header_bytes, header->num_header_bytes); |
134 | 153 |
135 // Copy all payload bytes. | 154 // Copy all payload bytes. |
136 memcpy(message->mutable_payload(), | 155 memcpy(message->mutable_payload(), |
137 static_cast<const char*>(data) + header->num_header_bytes, | 156 static_cast<const char*>(data) + header->num_header_bytes, |
138 data_num_bytes - header->num_header_bytes); | 157 data_num_bytes - header->num_header_bytes); |
139 // Copy extra header bytes. | 158 // Copy extra header bytes. |
140 memcpy(message->mutable_extra_header(), | 159 memcpy(message->mutable_extra_header(), |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
205 CHECK(new_handles && new_handles->size() <= max_handles_); | 224 CHECK(new_handles && new_handles->size() <= max_handles_); |
206 header_->num_handles = static_cast<uint16_t>(new_handles->size()); | 225 header_->num_handles = static_cast<uint16_t>(new_handles->size()); |
207 #if defined(OS_WIN) | 226 #if defined(OS_WIN) |
208 memcpy(handles(), new_handles->data(), | 227 memcpy(handles(), new_handles->data(), |
209 sizeof(PlatformHandle) * new_handles->size()); | 228 sizeof(PlatformHandle) * new_handles->size()); |
210 new_handles->clear(); | 229 new_handles->clear(); |
211 #else | 230 #else |
212 std::swap(handle_vector_, new_handles); | 231 std::swap(handle_vector_, new_handles); |
213 #endif // defined(OS_WIN) | 232 #endif // defined(OS_WIN) |
214 #endif // defined(OS_CHROMEOS) | 233 #endif // defined(OS_CHROMEOS) |
234 | |
235 #if defined(OS_MACOSX) && !defined(OS_IOS) | |
236 size_t mach_port_index = 0; | |
237 for (size_t i = 0; i < max_handles_; ++i) | |
238 mach_ports_[i] = {0, static_cast<uint32_t>(MACH_PORT_NULL)}; | |
239 for (size_t i = 0; i < handle_vector_->size(); i++) { | |
240 if ((*handle_vector_)[i].type == PlatformHandle::Type::MACH) { | |
241 mach_port_t port = (*handle_vector_)[i].port; | |
242 mach_ports_[mach_port_index].index = i; | |
243 mach_ports_[mach_port_index].mach_port = port; | |
244 mach_port_index++; | |
245 } | |
246 } | |
247 #endif | |
215 } | 248 } |
216 | 249 |
217 ScopedPlatformHandleVectorPtr Channel::Message::TakeHandles() { | 250 ScopedPlatformHandleVectorPtr Channel::Message::TakeHandles() { |
218 #if defined(OS_WIN) | 251 #if defined(OS_WIN) |
219 if (header_->num_handles == 0) | 252 if (header_->num_handles == 0) |
220 return ScopedPlatformHandleVectorPtr(); | 253 return ScopedPlatformHandleVectorPtr(); |
221 ScopedPlatformHandleVectorPtr moved_handles( | 254 ScopedPlatformHandleVectorPtr moved_handles( |
222 new PlatformHandleVector(header_->num_handles)); | 255 new PlatformHandleVector(header_->num_handles)); |
223 for (size_t i = 0; i < header_->num_handles; ++i) | 256 for (size_t i = 0; i < header_->num_handles; ++i) |
224 std::swap(moved_handles->at(i), handles()[i]); | 257 std::swap(moved_handles->at(i), handles()[i]); |
258 header_->num_handles = 0; | |
225 return moved_handles; | 259 return moved_handles; |
260 #elif defined(OS_MACOSX) && !defined(OS_IOS) | |
261 for (size_t i = 0; i < max_handles_; ++i) | |
262 mach_ports_[i] = {0, static_cast<uint32_t>(MACH_PORT_NULL)}; | |
263 header_->num_handles = 0; | |
264 return std::move(handle_vector_); | |
265 #else | |
266 header_->num_handles = 0; | |
267 return std::move(handle_vector_); | |
268 #endif | |
269 } | |
270 | |
271 ScopedPlatformHandleVectorPtr Channel::Message::TakeHandlesForTransport() { | |
272 #if defined(OS_WIN) | |
273 // Not necessary on Windows. | |
274 NOTREACHED(); | |
275 return nullptr; | |
276 #elif defined(OS_MACOSX) && !defined(OS_IOS) | |
277 if (handle_vector_) { | |
278 for (auto it = handle_vector_->begin(); it != handle_vector_->end(); ) { | |
279 if (it->type == PlatformHandle::Type::MACH) { | |
280 it = handle_vector_->erase(it); | |
281 } else { | |
282 ++it; | |
283 } | |
284 } | |
285 } | |
286 return std::move(handle_vector_); | |
226 #else | 287 #else |
227 return std::move(handle_vector_); | 288 return std::move(handle_vector_); |
228 #endif | 289 #endif |
229 } | 290 } |
230 | 291 |
231 #if defined(OS_WIN) | 292 #if defined(OS_WIN) |
232 // static | 293 // static |
233 bool Channel::Message::RewriteHandles(base::ProcessHandle from_process, | 294 bool Channel::Message::RewriteHandles(base::ProcessHandle from_process, |
234 base::ProcessHandle to_process, | 295 base::ProcessHandle to_process, |
235 PlatformHandle* handles, | 296 PlatformHandle* handles, |
(...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
442 return true; | 503 return true; |
443 } | 504 } |
444 | 505 |
445 void Channel::OnError() { | 506 void Channel::OnError() { |
446 if (delegate_) | 507 if (delegate_) |
447 delegate_->OnChannelError(); | 508 delegate_->OnChannelError(); |
448 } | 509 } |
449 | 510 |
450 } // namespace edk | 511 } // namespace edk |
451 } // namespace mojo | 512 } // namespace mojo |
OLD | NEW |