Chromium Code Reviews| 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 #include <utility> |
| 12 | 12 |
| 13 #include "base/macros.h" | 13 #include "base/macros.h" |
| 14 #include "base/memory/aligned_memory.h" | 14 #include "base/memory/aligned_memory.h" |
| 15 #include "base/process/process_handle.h" | 15 #include "base/process/process_handle.h" |
| 16 #include "mojo/edk/embedder/platform_handle.h" | 16 #include "mojo/edk/embedder/platform_handle.h" |
| 17 | 17 |
| 18 #if defined(OS_MACOSX) && !defined(OS_IOS) | 18 #if defined(OS_MACOSX) && !defined(OS_IOS) |
| 19 #include "base/mac/mach_logging.h" | 19 #include "base/mac/mach_logging.h" |
| 20 #elif defined(OS_WIN) | 20 #elif defined(OS_WIN) |
| 21 #include "base/win/win_util.h" | 21 #include "base/win/win_util.h" |
| 22 #endif | 22 #endif |
| 23 | 23 |
| 24 namespace mojo { | 24 namespace mojo { |
| 25 namespace edk { | 25 namespace edk { |
| 26 | 26 |
| 27 namespace { | 27 namespace { |
| 28 | 28 |
| 29 static_assert(sizeof(Channel::Message::Header) % kChannelMessageAlignment == 0, | 29 // Version number of the message currently supported for deserialization. |
| 30 "Invalid Header size."); | 30 // Bump this number when you add new fields to the extra header. |
| 31 const uint16_t kMessageCurrentVersion = 1; | |
|
Ken Rockot(use gerrit already)
2017/02/23 22:07:04
nit: s/const/constexpr/
Jay Civelli
2017/02/27 17:07:03
Done.
| |
| 31 | 32 |
| 32 #if defined(MOJO_EDK_LEGACY_PROTOCOL) | 33 static_assert(sizeof(Channel::Message::VersionedHeader) % |
| 33 static_assert(sizeof(Channel::Message::Header) == 8, | 34 kChannelMessageAlignment == |
| 34 "Header must be 8 bytes on ChromeOS and Android"); | 35 0, |
| 35 #endif | 36 "Invalid VersionedHeader size."); |
| 37 | |
| 38 static_assert(sizeof(Channel::Message::LegacyHeader) == 8, | |
| 39 "LegacyHeader must be 8 bytes on ChromeOS and Android"); | |
| 36 | 40 |
| 37 } // namespace | 41 } // namespace |
| 38 | 42 |
| 39 const size_t kReadBufferSize = 4096; | 43 const size_t kReadBufferSize = 4096; |
| 40 const size_t kMaxUnusedReadBufferCapacity = 4096; | 44 const size_t kMaxUnusedReadBufferCapacity = 4096; |
| 41 const size_t kMaxChannelMessageSize = 256 * 1024 * 1024; | 45 const size_t kMaxChannelMessageSize = 256 * 1024 * 1024; |
| 42 const size_t kMaxAttachedHandles = 128; | 46 const size_t kMaxAttachedHandles = 128; |
| 43 | 47 |
| 44 Channel::Message::Message(size_t payload_size, | 48 Channel::Message::Message(size_t payload_size, |
| 45 size_t max_handles, | 49 size_t max_handles, |
| 46 Header::MessageType message_type) | 50 MessageType message_type) |
| 47 : max_handles_(max_handles) { | 51 : max_handles_(max_handles) { |
| 48 DCHECK_LE(max_handles_, kMaxAttachedHandles); | 52 DCHECK_LE(max_handles_, kMaxAttachedHandles); |
| 49 | 53 |
| 54 const bool is_legacy_message = (message_type == MessageType::NORMAL_LEGACY); | |
| 50 size_t extra_header_size = 0; | 55 size_t extra_header_size = 0; |
| 51 #if defined(OS_WIN) | 56 #if defined(OS_WIN) |
| 52 // On Windows we serialize HANDLEs into the extra header space. | 57 // On Windows we serialize HANDLEs into the extra header space. |
| 53 extra_header_size = max_handles_ * sizeof(HandleEntry); | 58 extra_header_size = max_handles_ * sizeof(HandleEntry); |
| 54 #elif defined(OS_MACOSX) && !defined(OS_IOS) | 59 #elif defined(OS_MACOSX) && !defined(OS_IOS) |
| 55 // On OSX, some of the platform handles may be mach ports, which are | 60 // On OSX, some of the platform handles may be mach ports, which are |
| 56 // serialised into the message buffer. Since there could be a mix of fds and | 61 // serialised into the message buffer. Since there could be a mix of fds and |
| 57 // mach ports, we store the mach ports as an <index, port> pair (of uint32_t), | 62 // mach ports, we store the mach ports as an <index, port> pair (of uint32_t), |
| 58 // so that the original ordering of handles can be re-created. | 63 // so that the original ordering of handles can be re-created. |
| 59 if (max_handles) { | 64 if (max_handles) { |
| 60 extra_header_size = | 65 extra_header_size = |
| 61 sizeof(MachPortsExtraHeader) + (max_handles * sizeof(MachPortsEntry)); | 66 sizeof(MachPortsExtraHeader) + (max_handles * sizeof(MachPortsEntry)); |
| 62 } | 67 } |
| 63 #endif | 68 #endif |
| 64 // Pad extra header data to be aliged to |kChannelMessageAlignment| bytes. | 69 // Pad extra header data to be aliged to |kChannelMessageAlignment| bytes. |
| 65 if (extra_header_size % kChannelMessageAlignment) { | 70 if (extra_header_size % kChannelMessageAlignment) { |
| 66 extra_header_size += kChannelMessageAlignment - | 71 extra_header_size += kChannelMessageAlignment - |
| 67 (extra_header_size % kChannelMessageAlignment); | 72 (extra_header_size % kChannelMessageAlignment); |
| 68 } | 73 } |
| 69 DCHECK_EQ(0u, extra_header_size % kChannelMessageAlignment); | 74 DCHECK_EQ(0u, extra_header_size % kChannelMessageAlignment); |
| 70 #if defined(MOJO_EDK_LEGACY_PROTOCOL) | 75 size_t header_size; |
| 71 DCHECK_EQ(0u, extra_header_size); | 76 if (is_legacy_message) { |
| 72 #endif | 77 header_size = sizeof(LegacyHeader); |
| 78 DCHECK_EQ(0u, extra_header_size); | |
| 79 } else { | |
| 80 header_size = sizeof(VersionedHeader); | |
| 81 } | |
| 73 | 82 |
| 74 size_ = sizeof(Header) + extra_header_size + payload_size; | 83 size_ = header_size + extra_header_size + payload_size; |
| 75 data_ = static_cast<char*>(base::AlignedAlloc(size_, | 84 data_ = static_cast<char*>(base::AlignedAlloc(size_, |
| 76 kChannelMessageAlignment)); | 85 kChannelMessageAlignment)); |
| 77 // Only zero out the header and not the payload. Since the payload is going to | 86 // Only zero out the header and not the payload. Since the payload is going to |
| 78 // be memcpy'd, zeroing the payload is unnecessary work and a significant | 87 // be memcpy'd, zeroing the payload is unnecessary work and a significant |
| 79 // performance issue when dealing with large messages. Any sanitizer errors | 88 // performance issue when dealing with large messages. Any sanitizer errors |
| 80 // complaining about an uninitialized read in the payload area should be | 89 // complaining about an uninitialized read in the payload area should be |
| 81 // treated as an error and fixed. | 90 // treated as an error and fixed. |
| 82 memset(data_, 0, sizeof(Header) + extra_header_size); | 91 memset(data_, 0, header_size + extra_header_size); |
| 83 header_ = reinterpret_cast<Header*>(data_); | 92 legacy_header_ = reinterpret_cast<LegacyHeader*>(data_); |
| 93 if (!is_legacy_message) { | |
| 94 versioned_header_ = reinterpret_cast<VersionedHeader*>(data_); | |
| 95 } | |
| 84 | 96 |
| 85 DCHECK_LE(size_, std::numeric_limits<uint32_t>::max()); | 97 DCHECK_LE(size_, std::numeric_limits<uint32_t>::max()); |
| 86 header_->num_bytes = static_cast<uint32_t>(size_); | 98 legacy_header_->num_bytes = static_cast<uint32_t>(size_); |
| 87 | 99 |
| 88 DCHECK_LE(sizeof(Header) + extra_header_size, | 100 DCHECK_LE(header_size + extra_header_size, |
| 89 std::numeric_limits<uint16_t>::max()); | 101 std::numeric_limits<uint16_t>::max()); |
| 90 header_->message_type = message_type; | 102 legacy_header_->message_type = message_type; |
| 91 #if defined(MOJO_EDK_LEGACY_PROTOCOL) | 103 |
| 92 header_->num_handles = static_cast<uint16_t>(max_handles); | 104 if (is_legacy_message) { |
| 93 #else | 105 legacy_header_->num_handles = static_cast<uint16_t>(max_handles); |
| 94 header_->num_header_bytes = | 106 } else { |
| 95 static_cast<uint16_t>(sizeof(Header) + extra_header_size); | 107 versioned_header_->version_number = kMessageCurrentVersion; |
| 96 #endif | 108 versioned_header_->num_header_bytes = |
| 109 static_cast<uint16_t>(header_size + extra_header_size); | |
| 110 } | |
| 97 | 111 |
| 98 if (max_handles_ > 0) { | 112 if (max_handles_ > 0) { |
| 99 #if defined(OS_WIN) | 113 #if defined(OS_WIN) |
| 100 handles_ = reinterpret_cast<HandleEntry*>(mutable_extra_header()); | 114 handles_ = reinterpret_cast<HandleEntry*>(mutable_extra_header()); |
| 101 // Initialize all handles to invalid values. | 115 // Initialize all handles to invalid values. |
| 102 for (size_t i = 0; i < max_handles_; ++i) | 116 for (size_t i = 0; i < max_handles_; ++i) |
| 103 handles_[i].handle = base::win::HandleToUint32(INVALID_HANDLE_VALUE); | 117 handles_[i].handle = base::win::HandleToUint32(INVALID_HANDLE_VALUE); |
| 104 #elif defined(OS_MACOSX) && !defined(OS_IOS) | 118 #elif defined(OS_MACOSX) && !defined(OS_IOS) |
| 105 mach_ports_header_ = | 119 mach_ports_header_ = |
| 106 reinterpret_cast<MachPortsExtraHeader*>(mutable_extra_header()); | 120 reinterpret_cast<MachPortsExtraHeader*>(mutable_extra_header()); |
| 107 mach_ports_header_->num_ports = 0; | 121 mach_ports_header_->num_ports = 0; |
| 108 // Initialize all handles to invalid values. | 122 // Initialize all handles to invalid values. |
| 109 for (size_t i = 0; i < max_handles_; ++i) { | 123 for (size_t i = 0; i < max_handles_; ++i) { |
| 110 mach_ports_header_->entries[i] = | 124 mach_ports_header_->entries[i] = |
| 111 {0, static_cast<uint32_t>(MACH_PORT_NULL)}; | 125 {0, static_cast<uint32_t>(MACH_PORT_NULL)}; |
| 112 } | 126 } |
| 113 #endif | 127 #endif |
| 114 } | 128 } |
| 115 } | 129 } |
| 116 | 130 |
| 117 Channel::Message::~Message() { | 131 Channel::Message::~Message() { |
| 118 base::AlignedFree(data_); | 132 base::AlignedFree(data_); |
| 119 } | 133 } |
| 120 | 134 |
| 121 // static | 135 // static |
| 122 Channel::MessagePtr Channel::Message::Deserialize(const void* data, | 136 Channel::MessagePtr Channel::Message::Deserialize(const void* data, |
| 123 size_t data_num_bytes) { | 137 size_t data_num_bytes) { |
| 124 if (data_num_bytes < sizeof(Header)) | 138 if (data_num_bytes < sizeof(LegacyHeader)) |
| 125 return nullptr; | 139 return nullptr; |
| 126 | 140 |
| 127 const Header* header = reinterpret_cast<const Header*>(data); | 141 const LegacyHeader* legacy_header = |
| 128 if (header->num_bytes != data_num_bytes) { | 142 reinterpret_cast<const LegacyHeader*>(data); |
| 129 DLOG(ERROR) << "Decoding invalid message: " << header->num_bytes | 143 if (legacy_header->num_bytes != data_num_bytes) { |
| 144 DLOG(ERROR) << "Decoding invalid message: " << legacy_header->num_bytes | |
| 130 << " != " << data_num_bytes; | 145 << " != " << data_num_bytes; |
| 131 return nullptr; | 146 return nullptr; |
| 132 } | 147 } |
| 133 | 148 |
| 134 #if defined(MOJO_EDK_LEGACY_PROTOCOL) | 149 const VersionedHeader* versioned_header = nullptr; |
| 135 size_t payload_size = data_num_bytes - sizeof(Header); | 150 if (legacy_header->message_type == MessageType::NORMAL_VERSIONED) |
| 136 const char* payload = static_cast<const char*>(data) + sizeof(Header); | 151 versioned_header = reinterpret_cast<const VersionedHeader*>(data); |
| 137 #else | 152 |
| 138 if (header->num_bytes < header->num_header_bytes || | 153 uint32_t extra_header_size = 0; |
| 139 header->num_header_bytes < sizeof(Header)) { | 154 size_t payload_size = 0; |
| 140 DLOG(ERROR) << "Decoding invalid message: " << header->num_bytes << " < " | 155 const char* payload = nullptr; |
| 141 << header->num_header_bytes; | 156 if (!versioned_header) { |
| 142 return nullptr; | 157 payload_size = data_num_bytes - sizeof(LegacyHeader); |
| 158 payload = static_cast<const char*>(data) + sizeof(LegacyHeader); | |
| 159 } else { | |
| 160 if (versioned_header->num_bytes < versioned_header->num_header_bytes || | |
| 161 versioned_header->num_header_bytes < sizeof(VersionedHeader)) { | |
| 162 DLOG(ERROR) << "Decoding invalid message: " << versioned_header->num_bytes | |
| 163 << " < " << versioned_header->num_header_bytes; | |
| 164 return nullptr; | |
| 165 } | |
| 166 if (versioned_header->version_number != kMessageCurrentVersion) { | |
| 167 DLOG(ERROR) << "Decoding message from incompatible version " | |
| 168 << versioned_header->version_number | |
| 169 << " when current version is " << kMessageCurrentVersion; | |
| 170 return nullptr; | |
| 171 } | |
| 172 extra_header_size = | |
| 173 versioned_header->num_header_bytes - sizeof(VersionedHeader); | |
| 174 payload_size = data_num_bytes - versioned_header->num_header_bytes; | |
| 175 payload = | |
| 176 static_cast<const char*>(data) + versioned_header->num_header_bytes; | |
| 143 } | 177 } |
| 144 | 178 |
| 145 uint32_t extra_header_size = header->num_header_bytes - sizeof(Header); | |
| 146 size_t payload_size = data_num_bytes - header->num_header_bytes; | |
| 147 const char* payload = | |
| 148 static_cast<const char*>(data) + header->num_header_bytes; | |
| 149 #endif // defined(MOJO_EDK_LEGACY_PROTOCOL) | |
| 150 | |
| 151 #if defined(OS_WIN) | 179 #if defined(OS_WIN) |
| 152 uint32_t max_handles = extra_header_size / sizeof(HandleEntry); | 180 uint32_t max_handles = extra_header_size / sizeof(HandleEntry); |
| 153 #elif defined(OS_MACOSX) && !defined(OS_IOS) | 181 #elif defined(OS_MACOSX) && !defined(OS_IOS) |
| 154 if (extra_header_size < sizeof(MachPortsExtraHeader)) { | 182 if (extra_header_size < sizeof(MachPortsExtraHeader)) { |
| 155 DLOG(ERROR) << "Decoding invalid message: " << extra_header_size << " < " | 183 DLOG(ERROR) << "Decoding invalid message: " << extra_header_size << " < " |
| 156 << sizeof(MachPortsExtraHeader); | 184 << sizeof(MachPortsExtraHeader); |
| 157 return nullptr; | 185 return nullptr; |
| 158 } | 186 } |
| 159 uint32_t max_handles = (extra_header_size - sizeof(MachPortsExtraHeader)) / | 187 uint32_t max_handles = (extra_header_size - sizeof(MachPortsExtraHeader)) / |
| 160 sizeof(MachPortsEntry); | 188 sizeof(MachPortsEntry); |
| 161 #else | 189 #else |
| 162 const uint32_t max_handles = 0; | 190 const uint32_t max_handles = 0; |
| 163 #endif // defined(OS_WIN) | 191 #endif // defined(OS_WIN) |
| 164 | 192 |
| 165 if (header->num_handles > max_handles || max_handles > kMaxAttachedHandles) { | 193 const uint16_t num_handles = versioned_header ? versioned_header->num_handles |
| 166 DLOG(ERROR) << "Decoding invalid message:" << header->num_handles | 194 : legacy_header->num_handles; |
| 167 << " > " << max_handles; | 195 if (num_handles > max_handles || max_handles > kMaxAttachedHandles) { |
| 196 DLOG(ERROR) << "Decoding invalid message: " << num_handles << " > " | |
| 197 << max_handles; | |
| 168 return nullptr; | 198 return nullptr; |
| 169 } | 199 } |
| 170 | 200 |
| 171 MessagePtr message(new Message(payload_size, max_handles)); | 201 MessagePtr message( |
| 202 new Message(payload_size, max_handles, legacy_header->message_type)); | |
| 172 DCHECK_EQ(message->data_num_bytes(), data_num_bytes); | 203 DCHECK_EQ(message->data_num_bytes(), data_num_bytes); |
| 173 | 204 |
| 174 // Copy all payload bytes. | 205 // Copy all payload bytes. |
| 175 if (payload_size) | 206 if (payload_size) |
| 176 memcpy(message->mutable_payload(), payload, payload_size); | 207 memcpy(message->mutable_payload(), payload, payload_size); |
| 177 | 208 |
| 178 #if !defined(MOJO_EDK_LEGACY_PROTOCOL) | 209 if (versioned_header) { |
| 179 DCHECK_EQ(message->extra_header_size(), extra_header_size); | 210 DCHECK_EQ(message->extra_header_size(), extra_header_size); |
| 180 DCHECK_EQ(message->header_->num_header_bytes, header->num_header_bytes); | 211 DCHECK_EQ(message->versioned_header_->num_header_bytes, |
| 212 versioned_header->num_header_bytes); | |
| 181 | 213 |
| 182 if (message->extra_header_size()) { | 214 if (message->extra_header_size()) { |
| 183 // Copy extra header bytes. | 215 // Copy extra header bytes. |
| 184 memcpy(message->mutable_extra_header(), | 216 memcpy(message->mutable_extra_header(), |
| 185 static_cast<const char*>(data) + sizeof(Header), | 217 static_cast<const char*>(data) + sizeof(VersionedHeader), |
| 186 message->extra_header_size()); | 218 message->extra_header_size()); |
| 219 } | |
| 220 message->versioned_header_->num_handles = versioned_header->num_handles; | |
| 221 } else { | |
| 222 message->legacy_header_->num_handles = legacy_header->num_handles; | |
| 187 } | 223 } |
| 188 #endif | |
| 189 | 224 |
| 190 message->header_->num_handles = header->num_handles; | |
| 191 #if defined(OS_WIN) | 225 #if defined(OS_WIN) |
| 192 ScopedPlatformHandleVectorPtr handles( | 226 ScopedPlatformHandleVectorPtr handles(new PlatformHandleVector(num_handles)); |
| 193 new PlatformHandleVector(header->num_handles)); | 227 for (size_t i = 0; i < num_handles; i++) { |
| 194 for (size_t i = 0; i < header->num_handles; i++) { | |
| 195 (*handles)[i].handle = | 228 (*handles)[i].handle = |
| 196 base::win::Uint32ToHandle(message->handles_[i].handle); | 229 base::win::Uint32ToHandle(message->handles_[i].handle); |
| 197 } | 230 } |
| 198 message->SetHandles(std::move(handles)); | 231 message->SetHandles(std::move(handles)); |
| 199 #endif | 232 #endif |
| 200 | 233 |
| 201 return message; | 234 return message; |
| 202 } | 235 } |
| 203 | 236 |
| 237 const void* Channel::Message::extra_header() const { | |
| 238 DCHECK(versioned_header_ != nullptr); | |
| 239 return data_ + sizeof(VersionedHeader); | |
| 240 } | |
| 241 | |
| 242 void* Channel::Message::mutable_extra_header() { | |
| 243 DCHECK(versioned_header_ != nullptr); | |
| 244 return data_ + sizeof(VersionedHeader); | |
| 245 } | |
| 246 | |
| 247 size_t Channel::Message::extra_header_size() const { | |
| 248 return versioned_header_->num_header_bytes - sizeof(VersionedHeader); | |
| 249 } | |
| 250 | |
| 251 void* Channel::Message::mutable_payload() { | |
| 252 if (versioned_header_) | |
| 253 return data_ + versioned_header_->num_header_bytes; | |
| 254 return static_cast<void*>(legacy_header_ + 1); | |
| 255 } | |
| 256 | |
| 257 const void* Channel::Message::payload() const { | |
| 258 if (versioned_header_) | |
| 259 return data_ + versioned_header_->num_header_bytes; | |
| 260 return static_cast<const void*>(legacy_header_ + 1); | |
| 261 } | |
| 262 | |
| 204 size_t Channel::Message::payload_size() const { | 263 size_t Channel::Message::payload_size() const { |
| 205 #if defined(MOJO_EDK_LEGACY_PROTOCOL) | 264 if (versioned_header_) |
| 206 return header_->num_bytes - sizeof(Header); | 265 return size_ - versioned_header_->num_header_bytes; |
| 207 #else | 266 return legacy_header_->num_bytes - sizeof(LegacyHeader); |
| 208 return size_ - header_->num_header_bytes; | 267 } |
| 209 #endif | 268 |
| 269 size_t Channel::Message::num_handles() const { | |
| 270 return versioned_header_ ? versioned_header_->num_handles | |
| 271 : legacy_header_->num_handles; | |
| 272 } | |
| 273 | |
| 274 bool Channel::Message::has_handles() const { | |
| 275 return (versioned_header_ ? versioned_header_->num_handles | |
| 276 : legacy_header_->num_handles) > 0; | |
| 210 } | 277 } |
| 211 | 278 |
| 212 #if defined(OS_MACOSX) && !defined(OS_IOS) | 279 #if defined(OS_MACOSX) && !defined(OS_IOS) |
| 213 bool Channel::Message::has_mach_ports() const { | 280 bool Channel::Message::has_mach_ports() const { |
| 214 if (!has_handles()) | 281 if (!has_handles()) |
| 215 return false; | 282 return false; |
| 216 | 283 |
| 217 for (const auto& handle : (*handle_vector_)) { | 284 for (const auto& handle : (*handle_vector_)) { |
| 218 if (handle.type == PlatformHandle::Type::MACH || | 285 if (handle.type == PlatformHandle::Type::MACH || |
| 219 handle.type == PlatformHandle::Type::MACH_NAME) { | 286 handle.type == PlatformHandle::Type::MACH_NAME) { |
| 220 return true; | 287 return true; |
| 221 } | 288 } |
| 222 } | 289 } |
| 223 return false; | 290 return false; |
| 224 } | 291 } |
| 225 #endif | 292 #endif |
| 226 | 293 |
| 227 void Channel::Message::SetHandles(ScopedPlatformHandleVectorPtr new_handles) { | 294 void Channel::Message::SetHandles(ScopedPlatformHandleVectorPtr new_handles) { |
| 228 #if defined(MOJO_EDK_LEGACY_PROTOCOL) | 295 if (!versioned_header_) { |
| 229 // Old semantics for ChromeOS and Android | 296 // Old semantics for ChromeOS and Android |
| 230 if (header_->num_handles == 0) { | 297 if (legacy_header_->num_handles == 0) { |
| 231 CHECK(!new_handles || new_handles->size() == 0); | 298 CHECK(!new_handles || new_handles->size() == 0); |
| 299 return; | |
| 300 } | |
| 301 CHECK(new_handles && new_handles->size() == legacy_header_->num_handles); | |
| 302 std::swap(handle_vector_, new_handles); | |
| 232 return; | 303 return; |
| 233 } | 304 } |
| 234 CHECK(new_handles && new_handles->size() == header_->num_handles); | |
| 235 std::swap(handle_vector_, new_handles); | |
| 236 | 305 |
| 237 #else | |
| 238 if (max_handles_ == 0) { | 306 if (max_handles_ == 0) { |
| 239 CHECK(!new_handles || new_handles->size() == 0); | 307 CHECK(!new_handles || new_handles->size() == 0); |
| 240 return; | 308 return; |
| 241 } | 309 } |
| 242 | 310 |
| 243 CHECK(new_handles && new_handles->size() <= max_handles_); | 311 CHECK(new_handles && new_handles->size() <= max_handles_); |
| 244 header_->num_handles = static_cast<uint16_t>(new_handles->size()); | 312 versioned_header_->num_handles = static_cast<uint16_t>(new_handles->size()); |
| 245 std::swap(handle_vector_, new_handles); | 313 std::swap(handle_vector_, new_handles); |
| 246 #if defined(OS_WIN) | 314 #if defined(OS_WIN) |
| 247 memset(handles_, 0, extra_header_size()); | 315 memset(handles_, 0, extra_header_size()); |
| 248 for (size_t i = 0; i < handle_vector_->size(); i++) | 316 for (size_t i = 0; i < handle_vector_->size(); i++) |
| 249 handles_[i].handle = base::win::HandleToUint32((*handle_vector_)[i].handle); | 317 handles_[i].handle = base::win::HandleToUint32((*handle_vector_)[i].handle); |
| 250 #endif // defined(OS_WIN) | 318 #endif // defined(OS_WIN) |
| 251 #endif // defined(MOJO_EDK_LEGACY_PROTOCOL) | |
| 252 | 319 |
| 253 #if defined(OS_MACOSX) && !defined(OS_IOS) | 320 #if defined(OS_MACOSX) && !defined(OS_IOS) |
| 254 size_t mach_port_index = 0; | 321 size_t mach_port_index = 0; |
| 255 if (mach_ports_header_) { | 322 if (mach_ports_header_) { |
| 256 for (size_t i = 0; i < max_handles_; ++i) { | 323 for (size_t i = 0; i < max_handles_; ++i) { |
| 257 mach_ports_header_->entries[i] = | 324 mach_ports_header_->entries[i] = |
| 258 {0, static_cast<uint32_t>(MACH_PORT_NULL)}; | 325 {0, static_cast<uint32_t>(MACH_PORT_NULL)}; |
| 259 } | 326 } |
| 260 for (size_t i = 0; i < handle_vector_->size(); i++) { | 327 for (size_t i = 0; i < handle_vector_->size(); i++) { |
| 261 if ((*handle_vector_)[i].type == PlatformHandle::Type::MACH || | 328 if ((*handle_vector_)[i].type == PlatformHandle::Type::MACH || |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 273 | 340 |
| 274 ScopedPlatformHandleVectorPtr Channel::Message::TakeHandles() { | 341 ScopedPlatformHandleVectorPtr Channel::Message::TakeHandles() { |
| 275 #if defined(OS_MACOSX) && !defined(OS_IOS) | 342 #if defined(OS_MACOSX) && !defined(OS_IOS) |
| 276 if (mach_ports_header_) { | 343 if (mach_ports_header_) { |
| 277 for (size_t i = 0; i < max_handles_; ++i) { | 344 for (size_t i = 0; i < max_handles_; ++i) { |
| 278 mach_ports_header_->entries[i] = | 345 mach_ports_header_->entries[i] = |
| 279 {0, static_cast<uint32_t>(MACH_PORT_NULL)}; | 346 {0, static_cast<uint32_t>(MACH_PORT_NULL)}; |
| 280 } | 347 } |
| 281 mach_ports_header_->num_ports = 0; | 348 mach_ports_header_->num_ports = 0; |
| 282 } | 349 } |
| 283 header_->num_handles = 0; | 350 #endif |
| 351 if (versioned_header_) | |
| 352 versioned_header_->num_handles = 0; | |
| 353 else | |
| 354 legacy_header_->num_handles = 0; | |
| 284 return std::move(handle_vector_); | 355 return std::move(handle_vector_); |
| 285 #else | |
| 286 header_->num_handles = 0; | |
| 287 return std::move(handle_vector_); | |
| 288 #endif | |
| 289 } | 356 } |
| 290 | 357 |
| 291 ScopedPlatformHandleVectorPtr Channel::Message::TakeHandlesForTransport() { | 358 ScopedPlatformHandleVectorPtr Channel::Message::TakeHandlesForTransport() { |
| 292 #if defined(OS_WIN) | 359 #if defined(OS_WIN) |
| 293 // Not necessary on Windows. | 360 // Not necessary on Windows. |
| 294 NOTREACHED(); | 361 NOTREACHED(); |
| 295 return nullptr; | 362 return nullptr; |
| 296 #elif defined(OS_MACOSX) && !defined(OS_IOS) | 363 #elif defined(OS_MACOSX) && !defined(OS_IOS) |
| 297 if (handle_vector_) { | 364 if (handle_vector_) { |
| 298 for (auto it = handle_vector_->begin(); it != handle_vector_->end(); ) { | 365 for (auto it = handle_vector_->begin(); it != handle_vector_->end(); ) { |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 338 // due to DUPLICATE_CLOSE_SOURCE. Replace the handle in the message with | 405 // due to DUPLICATE_CLOSE_SOURCE. Replace the handle in the message with |
| 339 // an invalid handle. | 406 // an invalid handle. |
| 340 (*handles)[i].handle = INVALID_HANDLE_VALUE; | 407 (*handles)[i].handle = INVALID_HANDLE_VALUE; |
| 341 (*handles)[i].owning_process = base::GetCurrentProcessHandle(); | 408 (*handles)[i].owning_process = base::GetCurrentProcessHandle(); |
| 342 } | 409 } |
| 343 } | 410 } |
| 344 return success; | 411 return success; |
| 345 } | 412 } |
| 346 #endif | 413 #endif |
| 347 | 414 |
| 415 void Channel::Message::SetVersionForTest(uint16_t version_number) { | |
| 416 versioned_header_->version_number = version_number; | |
| 417 } | |
| 418 | |
| 348 // Helper class for managing a Channel's read buffer allocations. This maintains | 419 // Helper class for managing a Channel's read buffer allocations. This maintains |
| 349 // a single contiguous buffer with the layout: | 420 // a single contiguous buffer with the layout: |
| 350 // | 421 // |
| 351 // [discarded bytes][occupied bytes][unoccupied bytes] | 422 // [discarded bytes][occupied bytes][unoccupied bytes] |
| 352 // | 423 // |
| 353 // The Reserve() method ensures that a certain capacity of unoccupied bytes are | 424 // The Reserve() method ensures that a certain capacity of unoccupied bytes are |
| 354 // available. It does not claim that capacity and only allocates new capacity | 425 // available. It does not claim that capacity and only allocates new capacity |
| 355 // when strictly necessary. | 426 // when strictly necessary. |
| 356 // | 427 // |
| 357 // Claim() marks unoccupied bytes as occupied. | 428 // Claim() marks unoccupied bytes as occupied. |
| (...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 484 if (!required_capacity) | 555 if (!required_capacity) |
| 485 required_capacity = kReadBufferSize; | 556 required_capacity = kReadBufferSize; |
| 486 | 557 |
| 487 *buffer_capacity = required_capacity; | 558 *buffer_capacity = required_capacity; |
| 488 return read_buffer_->Reserve(required_capacity); | 559 return read_buffer_->Reserve(required_capacity); |
| 489 } | 560 } |
| 490 | 561 |
| 491 bool Channel::OnReadComplete(size_t bytes_read, size_t *next_read_size_hint) { | 562 bool Channel::OnReadComplete(size_t bytes_read, size_t *next_read_size_hint) { |
| 492 bool did_dispatch_message = false; | 563 bool did_dispatch_message = false; |
| 493 read_buffer_->Claim(bytes_read); | 564 read_buffer_->Claim(bytes_read); |
| 494 while (read_buffer_->num_occupied_bytes() >= sizeof(Message::Header)) { | 565 while (read_buffer_->num_occupied_bytes() >= sizeof(Message::LegacyHeader)) { |
| 495 // Ensure the occupied data is properly aligned. If it isn't, a SIGBUS could | 566 // Ensure the occupied data is properly aligned. If it isn't, a SIGBUS could |
| 496 // happen on architectures that don't allow misaligned words access (i.e. | 567 // happen on architectures that don't allow misaligned words access (i.e. |
| 497 // anything other than x86). Only re-align when necessary to avoid copies. | 568 // anything other than x86). Only re-align when necessary to avoid copies. |
| 498 if (reinterpret_cast<uintptr_t>(read_buffer_->occupied_bytes()) % | 569 if (reinterpret_cast<uintptr_t>(read_buffer_->occupied_bytes()) % |
| 499 kChannelMessageAlignment != 0) | 570 kChannelMessageAlignment != 0) |
| 500 read_buffer_->Realign(); | 571 read_buffer_->Realign(); |
| 501 | 572 |
| 502 // We have at least enough data available for a MessageHeader. | 573 // We have at least enough data available for a MessageHeader. |
| 503 const Message::Header* header = reinterpret_cast<const Message::Header*>( | 574 const Message::LegacyHeader* legacy_header = |
| 504 read_buffer_->occupied_bytes()); | 575 reinterpret_cast<const Message::LegacyHeader*>( |
| 505 if (header->num_bytes < sizeof(Message::Header) || | 576 read_buffer_->occupied_bytes()); |
| 506 header->num_bytes > kMaxChannelMessageSize) { | 577 |
| 507 LOG(ERROR) << "Invalid message size: " << header->num_bytes; | 578 if (legacy_header->num_bytes < sizeof(Message::LegacyHeader) || |
| 579 legacy_header->num_bytes > kMaxChannelMessageSize) { | |
| 580 LOG(ERROR) << "Invalid message size: " << legacy_header->num_bytes; | |
| 508 return false; | 581 return false; |
| 509 } | 582 } |
| 510 | 583 |
| 511 if (read_buffer_->num_occupied_bytes() < header->num_bytes) { | 584 if (read_buffer_->num_occupied_bytes() < legacy_header->num_bytes) { |
| 512 // Not enough data available to read the full message. Hint to the | 585 // Not enough data available to read the full message. Hint to the |
| 513 // implementation that it should try reading the full size of the message. | 586 // implementation that it should try reading the full size of the message. |
| 514 *next_read_size_hint = | 587 *next_read_size_hint = |
| 515 header->num_bytes - read_buffer_->num_occupied_bytes(); | 588 legacy_header->num_bytes - read_buffer_->num_occupied_bytes(); |
| 516 return true; | 589 return true; |
| 517 } | 590 } |
| 518 | 591 |
| 519 #if defined(MOJO_EDK_LEGACY_PROTOCOL) | 592 const Message::VersionedHeader* versioned_header = nullptr; |
| 593 if (legacy_header->message_type == Message::MessageType::NORMAL_VERSIONED) { | |
| 594 versioned_header = | |
| 595 reinterpret_cast<const Message::VersionedHeader*>(legacy_header); | |
| 596 } | |
| 597 | |
| 520 size_t extra_header_size = 0; | 598 size_t extra_header_size = 0; |
| 521 const void* extra_header = nullptr; | 599 const void* extra_header = nullptr; |
| 522 size_t payload_size = header->num_bytes - sizeof(Message::Header); | 600 size_t payload_size = 0; |
| 523 void* payload = payload_size ? const_cast<Message::Header*>(&header[1]) | 601 void* payload = nullptr; |
| 524 : nullptr; | 602 if (versioned_header) { |
| 525 #else | 603 if (versioned_header->num_header_bytes < |
| 526 if (header->num_header_bytes < sizeof(Message::Header) || | 604 sizeof(Message::VersionedHeader) || |
| 527 header->num_header_bytes > header->num_bytes) { | 605 versioned_header->num_header_bytes > versioned_header->num_bytes) { |
| 528 LOG(ERROR) << "Invalid message header size: " << header->num_header_bytes; | 606 LOG(ERROR) << "Invalid message header size: " |
| 529 return false; | 607 << versioned_header->num_header_bytes; |
| 608 return false; | |
| 609 } | |
| 610 if (versioned_header->version_number != kMessageCurrentVersion) { | |
| 611 LOG(ERROR) << "Invalid message version: " | |
| 612 << versioned_header->version_number | |
| 613 << " current version: " << kMessageCurrentVersion; | |
| 614 return false; | |
| 615 } | |
| 616 extra_header_size = | |
| 617 versioned_header->num_header_bytes - sizeof(Message::VersionedHeader); | |
| 618 extra_header = extra_header_size ? versioned_header + 1 : nullptr; | |
| 619 payload_size = | |
| 620 versioned_header->num_bytes - versioned_header->num_header_bytes; | |
| 621 payload = payload_size | |
| 622 ? reinterpret_cast<Message::VersionedHeader*>( | |
| 623 const_cast<char*>(read_buffer_->occupied_bytes()) + | |
| 624 versioned_header->num_header_bytes) | |
| 625 : nullptr; | |
| 626 | |
| 627 } else { | |
| 628 payload_size = legacy_header->num_bytes - sizeof(Message::LegacyHeader); | |
| 629 payload = payload_size | |
| 630 ? const_cast<Message::LegacyHeader*>(&legacy_header[1]) | |
| 631 : nullptr; | |
| 530 } | 632 } |
| 531 size_t extra_header_size = | |
| 532 header->num_header_bytes - sizeof(Message::Header); | |
| 533 const void* extra_header = extra_header_size ? header + 1 : nullptr; | |
| 534 size_t payload_size = header->num_bytes - header->num_header_bytes; | |
| 535 void* payload = | |
| 536 payload_size ? reinterpret_cast<Message::Header*>( | |
| 537 const_cast<char*>(read_buffer_->occupied_bytes()) + | |
| 538 header->num_header_bytes) | |
| 539 : nullptr; | |
| 540 #endif // defined(MOJO_EDK_LEGACY_PROTOCOL) | |
| 541 | 633 |
| 634 const uint16_t num_handles = versioned_header | |
| 635 ? versioned_header->num_handles | |
| 636 : legacy_header->num_handles; | |
| 542 ScopedPlatformHandleVectorPtr handles; | 637 ScopedPlatformHandleVectorPtr handles; |
| 543 if (header->num_handles > 0) { | 638 if (num_handles > 0) { |
| 544 if (!GetReadPlatformHandles(header->num_handles, extra_header, | 639 if (!GetReadPlatformHandles(num_handles, extra_header, extra_header_size, |
| 545 extra_header_size, &handles)) { | 640 &handles)) { |
| 546 return false; | 641 return false; |
| 547 } | 642 } |
| 548 | 643 |
| 549 if (!handles) { | 644 if (!handles) { |
| 550 // Not enough handles available for this message. | 645 // Not enough handles available for this message. |
| 551 break; | 646 break; |
| 552 } | 647 } |
| 553 } | 648 } |
| 554 | 649 |
| 555 // We've got a complete message! Dispatch it and try another. | 650 // We've got a complete message! Dispatch it and try another. |
| 556 if (header->message_type != Message::Header::MessageType::NORMAL) { | 651 if (legacy_header->message_type != Message::MessageType::NORMAL_LEGACY && |
| 557 if (!OnControlMessage(header->message_type, payload, payload_size, | 652 legacy_header->message_type != Message::MessageType::NORMAL_VERSIONED) { |
| 653 if (!OnControlMessage(legacy_header->message_type, payload, payload_size, | |
| 558 std::move(handles))) { | 654 std::move(handles))) { |
| 559 return false; | 655 return false; |
| 560 } | 656 } |
| 561 did_dispatch_message = true; | 657 did_dispatch_message = true; |
| 562 } else if (delegate_) { | 658 } else if (delegate_) { |
| 563 delegate_->OnChannelMessage(payload, payload_size, std::move(handles)); | 659 delegate_->OnChannelMessage(payload, payload_size, std::move(handles)); |
| 564 did_dispatch_message = true; | 660 did_dispatch_message = true; |
| 565 } | 661 } |
| 566 | 662 |
| 567 read_buffer_->Discard(header->num_bytes); | 663 read_buffer_->Discard(legacy_header->num_bytes); |
| 568 } | 664 } |
| 569 | 665 |
| 570 *next_read_size_hint = did_dispatch_message ? 0 : kReadBufferSize; | 666 *next_read_size_hint = did_dispatch_message ? 0 : kReadBufferSize; |
| 571 return true; | 667 return true; |
| 572 } | 668 } |
| 573 | 669 |
| 574 void Channel::OnError() { | 670 void Channel::OnError() { |
| 575 if (delegate_) | 671 if (delegate_) |
| 576 delegate_->OnChannelError(); | 672 delegate_->OnChannelError(); |
| 577 } | 673 } |
| 578 | 674 |
| 579 bool Channel::OnControlMessage(Message::Header::MessageType message_type, | 675 bool Channel::OnControlMessage(Message::MessageType message_type, |
| 580 const void* payload, | 676 const void* payload, |
| 581 size_t payload_size, | 677 size_t payload_size, |
| 582 ScopedPlatformHandleVectorPtr handles) { | 678 ScopedPlatformHandleVectorPtr handles) { |
| 583 return false; | 679 return false; |
| 584 } | 680 } |
| 585 | 681 |
| 586 } // namespace edk | 682 } // namespace edk |
| 587 } // namespace mojo | 683 } // namespace mojo |
| OLD | NEW |