Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(60)

Side by Side Diff: mojo/edk/system/channel.cc

Issue 2710193003: Adding a new message type to the Mojo channel. (Closed)
Patch Set: Fix Mac build. Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698