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 | 11 |
12 #include "base/macros.h" | 12 #include "base/macros.h" |
13 #include "base/memory/aligned_memory.h" | 13 #include "base/memory/aligned_memory.h" |
14 #include "mojo/edk/embedder/platform_handle.h" | 14 #include "mojo/edk/embedder/platform_handle.h" |
15 | 15 |
16 namespace mojo { | 16 namespace mojo { |
17 namespace edk { | 17 namespace edk { |
18 | 18 |
19 namespace { | 19 namespace { |
20 | 20 |
21 static_assert(sizeof(Channel::Message::Header) % kChannelMessageAlignment == 0, | 21 static_assert(sizeof(Channel::Message::Header) % kChannelMessageAlignment == 0, |
22 "Invalid Header size."); | 22 "Invalid Header size."); |
23 | 23 |
24 #if defined(OS_CHROMEOS) | 24 #if defined(OS_CHROMEOS) || defined(OS_ANDROID) |
25 static_assert(sizeof(Channel::Message::Header) == 8, | 25 static_assert(sizeof(Channel::Message::Header) == 8, |
26 "Header must be 8 bytes on ChromeOS"); | 26 "Header must be 8 bytes on ChromeOS and Android"); |
27 #endif | 27 #endif |
28 | 28 |
29 } // namespace | 29 } // namespace |
30 | 30 |
31 const size_t kReadBufferSize = 4096; | 31 const size_t kReadBufferSize = 4096; |
32 const size_t kMaxUnusedReadBufferCapacity = 256 * 1024; | 32 const size_t kMaxUnusedReadBufferCapacity = 256 * 1024; |
33 const size_t kMaxChannelMessageSize = 256 * 1024 * 1024; | 33 const size_t kMaxChannelMessageSize = 256 * 1024 * 1024; |
34 const size_t kMaxAttachedHandles = 128; | 34 const size_t kMaxAttachedHandles = 128; |
35 | 35 |
36 Channel::Message::Message(size_t payload_size, | 36 Channel::Message::Message(size_t payload_size, |
37 size_t max_handles, | 37 size_t max_handles, |
38 Header::MessageType message_type) | 38 Header::MessageType message_type) |
39 : max_handles_(max_handles) { | 39 : max_handles_(max_handles) { |
40 DCHECK_LE(max_handles_, kMaxAttachedHandles); | 40 DCHECK_LE(max_handles_, kMaxAttachedHandles); |
41 | 41 |
42 size_t extra_header_size = 0; | 42 size_t extra_header_size = 0; |
43 #if defined(OS_WIN) | 43 #if defined(OS_WIN) |
44 // On Windows we serialize platform handles into the extra header space. | 44 // On Windows we serialize platform handles into the extra header space. |
45 extra_header_size = max_handles_ * sizeof(PlatformHandle); | 45 extra_header_size = max_handles_ * sizeof(PlatformHandle); |
46 #endif | 46 #endif |
47 // Pad extra header data to be aliged to |kChannelMessageAlignment| bytes. | 47 // Pad extra header data to be aliged to |kChannelMessageAlignment| bytes. |
48 if (extra_header_size % kChannelMessageAlignment) { | 48 if (extra_header_size % kChannelMessageAlignment) { |
49 extra_header_size += kChannelMessageAlignment - | 49 extra_header_size += kChannelMessageAlignment - |
50 (extra_header_size % kChannelMessageAlignment); | 50 (extra_header_size % kChannelMessageAlignment); |
51 } | 51 } |
52 DCHECK_EQ(0u, extra_header_size % kChannelMessageAlignment); | 52 DCHECK_EQ(0u, extra_header_size % kChannelMessageAlignment); |
53 #if defined(OS_CHROMEOS) | 53 #if defined(OS_CHROMEOS) || defined(OS_ANDROID) |
54 DCHECK_EQ(0u, extra_header_size); | 54 DCHECK_EQ(0u, extra_header_size); |
55 #endif | 55 #endif |
56 | 56 |
57 size_ = sizeof(Header) + extra_header_size + payload_size; | 57 size_ = sizeof(Header) + extra_header_size + payload_size; |
58 data_ = static_cast<char*>(base::AlignedAlloc(size_, | 58 data_ = static_cast<char*>(base::AlignedAlloc(size_, |
59 kChannelMessageAlignment)); | 59 kChannelMessageAlignment)); |
60 // Only zero out the header and not the payload. Since the payload is going to | 60 // Only zero out the header and not the payload. Since the payload is going to |
61 // be memcpy'd, zeroing the payload is unnecessary work and a significant | 61 // be memcpy'd, zeroing the payload is unnecessary work and a significant |
62 // performance issue when dealing with large messages. Any sanitizer errors | 62 // performance issue when dealing with large messages. Any sanitizer errors |
63 // complaining about an uninitialized read in the payload area should be | 63 // complaining about an uninitialized read in the payload area should be |
64 // treated as an error and fixed. | 64 // treated as an error and fixed. |
65 memset(data_, 0, sizeof(Header) + extra_header_size); | 65 memset(data_, 0, sizeof(Header) + extra_header_size); |
66 header_ = reinterpret_cast<Header*>(data_); | 66 header_ = reinterpret_cast<Header*>(data_); |
67 | 67 |
68 DCHECK_LE(size_, std::numeric_limits<uint32_t>::max()); | 68 DCHECK_LE(size_, std::numeric_limits<uint32_t>::max()); |
69 header_->num_bytes = static_cast<uint32_t>(size_); | 69 header_->num_bytes = static_cast<uint32_t>(size_); |
70 | 70 |
71 DCHECK_LE(sizeof(Header) + extra_header_size, | 71 DCHECK_LE(sizeof(Header) + extra_header_size, |
72 std::numeric_limits<uint16_t>::max()); | 72 std::numeric_limits<uint16_t>::max()); |
73 header_->message_type = message_type; | 73 header_->message_type = message_type; |
74 #if defined(OS_CHROMEOS) | 74 #if defined(OS_CHROMEOS) || defined(OS_ANDROID) |
75 header_->num_handles = static_cast<uint16_t>(max_handles); | 75 header_->num_handles = static_cast<uint16_t>(max_handles); |
76 #else | 76 #else |
77 header_->num_header_bytes = | 77 header_->num_header_bytes = |
78 static_cast<uint16_t>(sizeof(Header) + extra_header_size); | 78 static_cast<uint16_t>(sizeof(Header) + extra_header_size); |
79 #endif | 79 #endif |
80 | 80 |
81 #if defined(OS_WIN) | 81 #if defined(OS_WIN) |
82 if (max_handles_ > 0) { | 82 if (max_handles_ > 0) { |
83 handles_ = reinterpret_cast<PlatformHandle*>(mutable_extra_header()); | 83 handles_ = reinterpret_cast<PlatformHandle*>(mutable_extra_header()); |
84 // Initialize all handles to invalid values. | 84 // Initialize all handles to invalid values. |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
145 memcpy(message->mutable_extra_header(), | 145 memcpy(message->mutable_extra_header(), |
146 static_cast<const char*>(data) + sizeof(Header), | 146 static_cast<const char*>(data) + sizeof(Header), |
147 message->extra_header_size()); | 147 message->extra_header_size()); |
148 message->header_->num_handles = header->num_handles; | 148 message->header_->num_handles = header->num_handles; |
149 | 149 |
150 return message; | 150 return message; |
151 #endif | 151 #endif |
152 } | 152 } |
153 | 153 |
154 size_t Channel::Message::payload_size() const { | 154 size_t Channel::Message::payload_size() const { |
155 #if defined(OS_CHROMEOS) | 155 #if defined(OS_CHROMEOS) || defined(OS_ANDROID) |
156 return header_->num_bytes - sizeof(Header); | 156 return header_->num_bytes - sizeof(Header); |
157 #else | 157 #else |
158 return size_ - header_->num_header_bytes; | 158 return size_ - header_->num_header_bytes; |
159 #endif | 159 #endif |
160 } | 160 } |
161 | 161 |
162 PlatformHandle* Channel::Message::handles() { | 162 PlatformHandle* Channel::Message::handles() { |
163 #if defined(OS_CHROMEOS) | 163 #if defined(OS_CHROMEOS) || defined(OS_ANDROID) |
164 // Old semantics for ChromeOS. | 164 // Old semantics for ChromeOS and Android. |
165 if (header_->num_handles == 0) | 165 if (header_->num_handles == 0) |
166 return nullptr; | 166 return nullptr; |
167 CHECK(handle_vector_); | 167 CHECK(handle_vector_); |
168 return handle_vector_->data(); | 168 return handle_vector_->data(); |
169 #else | 169 #else |
170 if (max_handles_ == 0) | 170 if (max_handles_ == 0) |
171 return nullptr; | 171 return nullptr; |
172 #if defined(OS_WIN) | 172 #if defined(OS_WIN) |
173 return handles_; | 173 return handles_; |
174 #else | 174 #else |
175 CHECK(handle_vector_); | 175 CHECK(handle_vector_); |
176 return handle_vector_->data(); | 176 return handle_vector_->data(); |
177 #endif // defined(OS_WIN) | 177 #endif // defined(OS_WIN) |
178 #endif // defined(OS_CHROMEOS) | 178 #endif // defined(OS_CHROMEOS) || defined(OS_ANDROID) |
179 } | 179 } |
180 | 180 |
181 #if defined(OS_MACOSX) && !defined(OS_IOS) | 181 #if defined(OS_MACOSX) && !defined(OS_IOS) |
182 bool Channel::Message::has_mach_ports() const { | 182 bool Channel::Message::has_mach_ports() const { |
183 if (!has_handles()) | 183 if (!has_handles()) |
184 return false; | 184 return false; |
185 | 185 |
186 for (const auto& handle : (*handle_vector_)) { | 186 for (const auto& handle : (*handle_vector_)) { |
187 if (handle.type == PlatformHandle::Type::MACH) | 187 if (handle.type == PlatformHandle::Type::MACH) |
188 return true; | 188 return true; |
189 } | 189 } |
190 return false; | 190 return false; |
191 } | 191 } |
192 #endif | 192 #endif |
193 | 193 |
194 void Channel::Message::SetHandles(ScopedPlatformHandleVectorPtr new_handles) { | 194 void Channel::Message::SetHandles(ScopedPlatformHandleVectorPtr new_handles) { |
195 #if defined(OS_CHROMEOS) | 195 #if defined(OS_CHROMEOS) || defined(OS_ANDROID) |
196 // Old semantics for ChromeOS. | 196 // Old semantics for ChromeOS and Android |
197 if (header_->num_handles == 0) { | 197 if (header_->num_handles == 0) { |
198 CHECK(!new_handles || new_handles->size() == 0); | 198 CHECK(!new_handles || new_handles->size() == 0); |
199 return; | 199 return; |
200 } | 200 } |
201 CHECK(new_handles && new_handles->size() == header_->num_handles); | 201 CHECK(new_handles && new_handles->size() == header_->num_handles); |
202 std::swap(handle_vector_, new_handles); | 202 std::swap(handle_vector_, new_handles); |
203 | 203 |
204 #else | 204 #else |
205 if (max_handles_ == 0) { | 205 if (max_handles_ == 0) { |
206 CHECK(!new_handles || new_handles->size() == 0); | 206 CHECK(!new_handles || new_handles->size() == 0); |
207 return; | 207 return; |
208 } | 208 } |
209 | 209 |
210 CHECK(new_handles && new_handles->size() <= max_handles_); | 210 CHECK(new_handles && new_handles->size() <= max_handles_); |
211 header_->num_handles = static_cast<uint16_t>(new_handles->size()); | 211 header_->num_handles = static_cast<uint16_t>(new_handles->size()); |
212 #if defined(OS_WIN) | 212 #if defined(OS_WIN) |
213 memcpy(handles(), new_handles->data(), | 213 memcpy(handles(), new_handles->data(), |
214 sizeof(PlatformHandle) * new_handles->size()); | 214 sizeof(PlatformHandle) * new_handles->size()); |
215 new_handles->clear(); | 215 new_handles->clear(); |
216 #else | 216 #else |
217 std::swap(handle_vector_, new_handles); | 217 std::swap(handle_vector_, new_handles); |
218 #endif // defined(OS_WIN) | 218 #endif // defined(OS_WIN) |
219 #endif // defined(OS_CHROMEOS) | 219 #endif // defined(OS_CHROMEOS) || defined(OS_ANDROID) |
220 } | 220 } |
221 | 221 |
222 ScopedPlatformHandleVectorPtr Channel::Message::TakeHandles() { | 222 ScopedPlatformHandleVectorPtr Channel::Message::TakeHandles() { |
223 #if defined(OS_WIN) | 223 #if defined(OS_WIN) |
224 if (header_->num_handles == 0) | 224 if (header_->num_handles == 0) |
225 return ScopedPlatformHandleVectorPtr(); | 225 return ScopedPlatformHandleVectorPtr(); |
226 ScopedPlatformHandleVectorPtr moved_handles( | 226 ScopedPlatformHandleVectorPtr moved_handles( |
227 new PlatformHandleVector(header_->num_handles)); | 227 new PlatformHandleVector(header_->num_handles)); |
228 for (size_t i = 0; i < header_->num_handles; ++i) | 228 for (size_t i = 0; i < header_->num_handles; ++i) |
229 std::swap(moved_handles->at(i), handles()[i]); | 229 std::swap(moved_handles->at(i), handles()[i]); |
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
395 } | 395 } |
396 | 396 |
397 if (read_buffer_->num_occupied_bytes() < header->num_bytes) { | 397 if (read_buffer_->num_occupied_bytes() < header->num_bytes) { |
398 // Not enough data available to read the full message. Hint to the | 398 // Not enough data available to read the full message. Hint to the |
399 // implementation that it should try reading the full size of the message. | 399 // implementation that it should try reading the full size of the message. |
400 *next_read_size_hint = | 400 *next_read_size_hint = |
401 header->num_bytes - read_buffer_->num_occupied_bytes(); | 401 header->num_bytes - read_buffer_->num_occupied_bytes(); |
402 return true; | 402 return true; |
403 } | 403 } |
404 | 404 |
405 #if defined(OS_CHROMEOS) | 405 #if defined(OS_CHROMEOS) || defined(OS_ANDROID) |
406 size_t extra_header_size = 0; | 406 size_t extra_header_size = 0; |
407 const void* extra_header = nullptr; | 407 const void* extra_header = nullptr; |
408 size_t payload_size = header->num_bytes - sizeof(Message::Header); | 408 size_t payload_size = header->num_bytes - sizeof(Message::Header); |
409 void* payload = payload_size ? const_cast<Message::Header*>(&header[1]) | 409 void* payload = payload_size ? const_cast<Message::Header*>(&header[1]) |
410 : nullptr; | 410 : nullptr; |
411 #else | 411 #else |
412 size_t extra_header_size = | 412 size_t extra_header_size = |
413 header->num_header_bytes - sizeof(Message::Header); | 413 header->num_header_bytes - sizeof(Message::Header); |
414 const void* extra_header = header + 1; | 414 const void* extra_header = header + 1; |
415 size_t payload_size = header->num_bytes - header->num_header_bytes; | 415 size_t payload_size = header->num_bytes - header->num_header_bytes; |
416 void* payload = | 416 void* payload = |
417 payload_size ? reinterpret_cast<Message::Header*>( | 417 payload_size ? reinterpret_cast<Message::Header*>( |
418 const_cast<char*>(read_buffer_->occupied_bytes()) + | 418 const_cast<char*>(read_buffer_->occupied_bytes()) + |
419 header->num_header_bytes) | 419 header->num_header_bytes) |
420 : nullptr; | 420 : nullptr; |
421 #endif | 421 #endif // defined(OS_CHROMEOS) || defined(OS_ANDROID) |
422 | 422 |
423 ScopedPlatformHandleVectorPtr handles; | 423 ScopedPlatformHandleVectorPtr handles; |
424 if (header->num_handles > 0) { | 424 if (header->num_handles > 0) { |
425 handles = GetReadPlatformHandles(header->num_handles, extra_header, | 425 handles = GetReadPlatformHandles(header->num_handles, extra_header, |
426 extra_header_size); | 426 extra_header_size); |
427 if (!handles) { | 427 if (!handles) { |
428 // Not enough handles available for this message. | 428 // Not enough handles available for this message. |
429 break; | 429 break; |
430 } | 430 } |
431 } | 431 } |
(...skipping 15 matching lines...) Expand all Loading... |
447 return true; | 447 return true; |
448 } | 448 } |
449 | 449 |
450 void Channel::OnError() { | 450 void Channel::OnError() { |
451 if (delegate_) | 451 if (delegate_) |
452 delegate_->OnChannelError(); | 452 delegate_->OnChannelError(); |
453 } | 453 } |
454 | 454 |
455 } // namespace edk | 455 } // namespace edk |
456 } // namespace mojo | 456 } // namespace mojo |
OLD | NEW |