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