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

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

Issue 1759033002: Re-land: [mojo-edk] Serialise windows handles into an "extra header" section. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 9 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 11
12 #include "base/macros.h" 12 #include "base/macros.h"
13 #include "base/memory/aligned_memory.h" 13 #include "base/memory/aligned_memory.h"
14 #include "mojo/edk/embedder/platform_handle.h" 14 #include "mojo/edk/embedder/platform_handle.h"
15 15
16 namespace mojo { 16 namespace mojo {
17 namespace edk { 17 namespace edk {
18 18
19 namespace { 19 namespace {
20 20
21 static_assert(sizeof(Channel::Message::Header) % kChannelMessageAlignment == 0, 21 static_assert(sizeof(Channel::Message::Header) % kChannelMessageAlignment == 0,
22 "Invalid Header size."); 22 "Invalid Header size.");
23 23
24 #if defined(OS_CHROMEOS)
25 static_assert(sizeof(Channel::Message::Header) == 8,
26 "Header must be 8 bytes on ChromeOS");
27 #endif
28
24 } // namespace 29 } // namespace
25 30
26 const size_t kReadBufferSize = 4096; 31 const size_t kReadBufferSize = 4096;
27 const size_t kMaxUnusedReadBufferCapacity = 256 * 1024; 32 const size_t kMaxUnusedReadBufferCapacity = 256 * 1024;
28 const size_t kMaxChannelMessageSize = 256 * 1024 * 1024; 33 const size_t kMaxChannelMessageSize = 256 * 1024 * 1024;
34 const size_t kMaxAttachedHandles = 128;
29 35
30 Channel::Message::Message(size_t payload_size, 36 Channel::Message::Message(size_t payload_size,
31 size_t num_handles, 37 size_t max_handles,
32 Header::MessageType message_type) { 38 Header::MessageType message_type)
33 size_ = payload_size + sizeof(Header); 39 : max_handles_(max_handles) {
40 DCHECK_LE(max_handles_, kMaxAttachedHandles);
41
42 size_t extra_header_size = 0;
34 #if defined(OS_WIN) 43 #if defined(OS_WIN)
35 // On Windows we serialize platform handles directly into the message buffer. 44 // On Windows we serialize platform handles into the extra header space.
36 size_ += num_handles * sizeof(PlatformHandle); 45 extra_header_size = max_handles_ * sizeof(PlatformHandle);
46 #endif
47 // Pad extra header data to be aliged to |kChannelMessageAlignment| bytes.
48 if (extra_header_size % kChannelMessageAlignment) {
49 extra_header_size += kChannelMessageAlignment -
50 (extra_header_size % kChannelMessageAlignment);
51 }
52 DCHECK_EQ(0u, extra_header_size % kChannelMessageAlignment);
53 #if defined(OS_CHROMEOS)
54 DCHECK_EQ(0u, extra_header_size);
37 #endif 55 #endif
38 56
57 size_ = sizeof(Header) + extra_header_size + payload_size;
39 data_ = static_cast<char*>(base::AlignedAlloc(size_, 58 data_ = static_cast<char*>(base::AlignedAlloc(size_,
40 kChannelMessageAlignment)); 59 kChannelMessageAlignment));
41 memset(data_, 0, size_); 60 memset(data_, 0, size_);
42 header_ = reinterpret_cast<Header*>(data_); 61 header_ = reinterpret_cast<Header*>(data_);
43 62
44 DCHECK_LE(size_, std::numeric_limits<uint32_t>::max()); 63 DCHECK_LE(size_, std::numeric_limits<uint32_t>::max());
45 header_->num_bytes = static_cast<uint32_t>(size_); 64 header_->num_bytes = static_cast<uint32_t>(size_);
46 65
47 DCHECK_LE(num_handles, std::numeric_limits<uint16_t>::max()); 66 DCHECK_LE(sizeof(Header) + extra_header_size,
48 header_->num_handles = static_cast<uint16_t>(num_handles); 67 std::numeric_limits<uint16_t>::max());
49
50 header_->message_type = message_type; 68 header_->message_type = message_type;
69 #if defined(OS_CHROMEOS)
70 header_->num_handles = static_cast<uint16_t>(max_handles);
71 #else
72 header_->num_header_bytes =
73 static_cast<uint16_t>(sizeof(Header) + extra_header_size);
74 #endif
51 75
52 #if defined(OS_WIN) 76 #if defined(OS_WIN)
53 if (num_handles > 0) { 77 if (max_handles_ > 0) {
54 handles_ = reinterpret_cast<PlatformHandle*>( 78 handles_ = reinterpret_cast<PlatformHandle*>(mutable_extra_header());
55 data_ + sizeof(Header) + payload_size);
56 // Initialize all handles to invalid values. 79 // Initialize all handles to invalid values.
57 for (size_t i = 0; i < header_->num_handles; ++i) 80 for (size_t i = 0; i < max_handles_; ++i)
58 handles()[i] = PlatformHandle(); 81 handles()[i] = PlatformHandle();
59 } 82 }
60 #endif 83 #endif
61 } 84 }
62 85
63 Channel::Message::~Message() { 86 Channel::Message::~Message() {
64 #if defined(OS_WIN) 87 #if defined(OS_WIN)
65 // On POSIX the ScopedPlatformHandleVectorPtr will do this for us. 88 // On POSIX the ScopedPlatformHandleVectorPtr will do this for us.
66 for (size_t i = 0; i < header_->num_handles; ++i) 89 for (size_t i = 0; i < header_->num_handles; ++i)
67 handles()[i].CloseIfNecessary(); 90 handles()[i].CloseIfNecessary();
68 #endif 91 #endif
69 base::AlignedFree(data_); 92 base::AlignedFree(data_);
70 } 93 }
71 94
72 // static 95 // static
73 Channel::MessagePtr Channel::Message::Deserialize(const void* data, 96 Channel::MessagePtr Channel::Message::Deserialize(const void* data,
74 size_t data_num_bytes) { 97 size_t data_num_bytes) {
75 #if !defined(OS_WIN) 98 #if !defined(OS_WIN)
76 // We only serialize messages into other messages when performing message 99 // We only serialize messages into other messages when performing message
77 // relay on Windows. 100 // relay on Windows.
78 NOTREACHED(); 101 NOTREACHED();
79 #endif 102 return nullptr;
103 #else
80 if (data_num_bytes < sizeof(Header)) 104 if (data_num_bytes < sizeof(Header))
81 return nullptr; 105 return nullptr;
82 106
83 const Header* header = reinterpret_cast<const Header*>(data); 107 const Header* header = reinterpret_cast<const Header*>(data);
84 if (header->num_bytes != data_num_bytes) { 108 if (header->num_bytes != data_num_bytes) {
85 DLOG(ERROR) << "Decoding invalid message: " << header->num_bytes 109 DLOG(ERROR) << "Decoding invalid message: " << header->num_bytes
86 << " != " << data_num_bytes; 110 << " != " << data_num_bytes;
87 return nullptr; 111 return nullptr;
88 } 112 }
89 113
90 uint32_t handles_size = header->num_handles * sizeof(PlatformHandle); 114 if (header->num_bytes < header->num_header_bytes) {
91 if (data_num_bytes < sizeof(Header) + handles_size) { 115 DLOG(ERROR) << "Decoding invalid message: " << header->num_bytes << " < "
92 DLOG(ERROR) << "Decoding invalid message:" << data_num_bytes 116 << header->num_header_bytes;
93 << " < " << (sizeof(Header) + handles_size);
94 return nullptr; 117 return nullptr;
95 } 118 }
96 119
97 DCHECK_LE(handles_size, data_num_bytes - sizeof(Header)); 120 uint32_t extra_header_size = header->num_header_bytes - sizeof(Header);
121 uint32_t max_handles = extra_header_size / sizeof(PlatformHandle);
122 if (header->num_handles > max_handles) {
123 DLOG(ERROR) << "Decoding invalid message:" << header->num_handles << " > "
124 << max_handles;
125 return nullptr;
126 }
98 127
99 MessagePtr message(new Message(data_num_bytes - sizeof(Header) - handles_size, 128 MessagePtr message(
100 header->num_handles)); 129 new Message(data_num_bytes - header->num_header_bytes, max_handles));
101 130
102 DCHECK_EQ(message->data_num_bytes(), data_num_bytes); 131 DCHECK_EQ(message->data_num_bytes(), data_num_bytes);
132 DCHECK_EQ(message->extra_header_size(), extra_header_size);
133 DCHECK_EQ(message->header_->num_header_bytes, header->num_header_bytes);
103 134
104 // Copy all bytes, including the serialized handles. 135 // Copy all payload bytes.
105 memcpy(message->mutable_payload(), 136 memcpy(message->mutable_payload(),
137 static_cast<const char*>(data) + header->num_header_bytes,
138 data_num_bytes - header->num_header_bytes);
139 // Copy extra header bytes.
140 memcpy(message->mutable_extra_header(),
106 static_cast<const char*>(data) + sizeof(Header), 141 static_cast<const char*>(data) + sizeof(Header),
107 data_num_bytes - sizeof(Header)); 142 message->extra_header_size());
143 message->header_->num_handles = header->num_handles;
108 144
109 return message; 145 return message;
146 #endif
110 } 147 }
111 148
112 size_t Channel::Message::payload_size() const { 149 size_t Channel::Message::payload_size() const {
113 #if defined(OS_WIN) 150 #if defined(OS_CHROMEOS)
114 return size_ - sizeof(Header) - 151 return header_->num_bytes - sizeof(Header);
115 sizeof(PlatformHandle) * header_->num_handles;
116 #else 152 #else
117 return header_->num_bytes - sizeof(Header); 153 return size_ - header_->num_header_bytes;
118 #endif 154 #endif
119 } 155 }
120 156
121 PlatformHandle* Channel::Message::handles() { 157 PlatformHandle* Channel::Message::handles() {
158 #if defined(OS_CHROMEOS)
159 // Old semantics for ChromeOS.
122 if (header_->num_handles == 0) 160 if (header_->num_handles == 0)
123 return nullptr; 161 return nullptr;
162 CHECK(handle_vector_);
163 return handle_vector_->data();
164 #else
165 if (max_handles_ == 0)
166 return nullptr;
124 #if defined(OS_WIN) 167 #if defined(OS_WIN)
125 return reinterpret_cast<PlatformHandle*>(static_cast<char*>(data_) + 168 return handles_;
126 sizeof(Header) + payload_size());
127 #else 169 #else
128 CHECK(handle_vector_); 170 CHECK(handle_vector_);
129 return handle_vector_->data(); 171 return handle_vector_->data();
130 #endif 172 #endif // defined(OS_WIN)
173 #endif // defined(OS_CHROMEOS)
131 } 174 }
132 175
176 #if defined(OS_MACOSX) && !defined(OS_IOS)
177 bool Channel::Message::has_mach_ports() const {
178 if (!has_handles())
179 return false;
180
181 for (const auto& handle : (*handle_vector_)) {
182 if (handle.type == PlatformHandle::Type::MACH)
183 return true;
184 }
185 return false;
186 }
187 #endif
188
133 void Channel::Message::SetHandles(ScopedPlatformHandleVectorPtr new_handles) { 189 void Channel::Message::SetHandles(ScopedPlatformHandleVectorPtr new_handles) {
190 #if defined(OS_CHROMEOS)
191 // Old semantics for ChromeOS.
134 if (header_->num_handles == 0) { 192 if (header_->num_handles == 0) {
135 CHECK(!new_handles || new_handles->size() == 0); 193 CHECK(!new_handles || new_handles->size() == 0);
136 return; 194 return;
137 } 195 }
196 CHECK(new_handles && new_handles->size() == header_->num_handles);
197 std::swap(handle_vector_, new_handles);
138 198
139 CHECK(new_handles && new_handles->size() == header_->num_handles); 199 #else
200 if (max_handles_ == 0) {
201 CHECK(!new_handles || new_handles->size() == 0);
202 return;
203 }
204
205 CHECK(new_handles && new_handles->size() <= max_handles_);
206 header_->num_handles = static_cast<uint16_t>(new_handles->size());
140 #if defined(OS_WIN) 207 #if defined(OS_WIN)
141 memcpy(handles(), new_handles->data(), 208 memcpy(handles(), new_handles->data(),
142 sizeof(PlatformHandle) * header_->num_handles); 209 sizeof(PlatformHandle) * new_handles->size());
143 new_handles->clear(); 210 new_handles->clear();
144 #else 211 #else
145 std::swap(handle_vector_, new_handles); 212 std::swap(handle_vector_, new_handles);
146 #endif 213 #endif // defined(OS_WIN)
214 #endif // defined(OS_CHROMEOS)
147 } 215 }
148 216
149 ScopedPlatformHandleVectorPtr Channel::Message::TakeHandles() { 217 ScopedPlatformHandleVectorPtr Channel::Message::TakeHandles() {
150 #if defined(OS_WIN) 218 #if defined(OS_WIN)
151 if (header_->num_handles == 0) 219 if (header_->num_handles == 0)
152 return ScopedPlatformHandleVectorPtr(); 220 return ScopedPlatformHandleVectorPtr();
153 ScopedPlatformHandleVectorPtr moved_handles( 221 ScopedPlatformHandleVectorPtr moved_handles(
154 new PlatformHandleVector(header_->num_handles)); 222 new PlatformHandleVector(header_->num_handles));
155 for (size_t i = 0; i < header_->num_handles; ++i) 223 for (size_t i = 0; i < header_->num_handles; ++i)
156 std::swap(moved_handles->at(i), handles()[i]); 224 std::swap(moved_handles->at(i), handles()[i]);
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after
322 } 390 }
323 391
324 if (read_buffer_->num_occupied_bytes() < header->num_bytes) { 392 if (read_buffer_->num_occupied_bytes() < header->num_bytes) {
325 // Not enough data available to read the full message. Hint to the 393 // Not enough data available to read the full message. Hint to the
326 // implementation that it should try reading the full size of the message. 394 // implementation that it should try reading the full size of the message.
327 *next_read_size_hint = 395 *next_read_size_hint =
328 header->num_bytes - read_buffer_->num_occupied_bytes(); 396 header->num_bytes - read_buffer_->num_occupied_bytes();
329 return true; 397 return true;
330 } 398 }
331 399
400 #if defined(OS_CHROMEOS)
401 size_t extra_header_size = 0;
402 const void* extra_header = nullptr;
332 size_t payload_size = header->num_bytes - sizeof(Message::Header); 403 size_t payload_size = header->num_bytes - sizeof(Message::Header);
333 void* payload = payload_size ? const_cast<Message::Header*>(&header[1]) 404 void* payload = payload_size ? const_cast<Message::Header*>(&header[1])
334 : nullptr; 405 : nullptr;
406 #else
407 size_t extra_header_size =
408 header->num_header_bytes - sizeof(Message::Header);
409 const void* extra_header = header + 1;
410 size_t payload_size = header->num_bytes - header->num_header_bytes;
411 void* payload =
412 payload_size ? reinterpret_cast<Message::Header*>(
413 const_cast<char*>(read_buffer_->occupied_bytes()) +
414 header->num_header_bytes)
415 : nullptr;
416 #endif
335 417
336 ScopedPlatformHandleVectorPtr handles; 418 ScopedPlatformHandleVectorPtr handles;
337 if (header->num_handles > 0) { 419 if (header->num_handles > 0) {
338 handles = GetReadPlatformHandles(header->num_handles, 420 handles = GetReadPlatformHandles(header->num_handles, extra_header,
339 &payload, &payload_size); 421 extra_header_size);
340 if (!handles) { 422 if (!handles) {
341 // Not enough handles available for this message. 423 // Not enough handles available for this message.
342 break; 424 break;
343 } 425 }
344 } 426 }
345 427
346 // We've got a complete message! Dispatch it and try another. 428 // We've got a complete message! Dispatch it and try another.
347 if (header->message_type != Message::Header::MessageType::NORMAL) { 429 if (header->message_type != Message::Header::MessageType::NORMAL) {
348 OnControlMessage(header->message_type, payload, payload_size, 430 OnControlMessage(header->message_type, payload, payload_size,
349 std::move(handles)); 431 std::move(handles));
(...skipping 10 matching lines...) Expand all
360 return true; 442 return true;
361 } 443 }
362 444
363 void Channel::OnError() { 445 void Channel::OnError() {
364 if (delegate_) 446 if (delegate_)
365 delegate_->OnChannelError(); 447 delegate_->OnChannelError();
366 } 448 }
367 449
368 } // namespace edk 450 } // namespace edk
369 } // namespace mojo 451 } // namespace mojo
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698