| 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 |