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

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

Issue 1740953002: [mojo-edk] Serialise windows handles into an "extra header" section. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Build 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
« no previous file with comments | « mojo/edk/system/channel.h ('k') | mojo/edk/system/channel_posix.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 } // namespace 24 } // namespace
25 25
26 const size_t kReadBufferSize = 4096; 26 const size_t kReadBufferSize = 4096;
27 const size_t kMaxUnusedReadBufferCapacity = 256 * 1024; 27 const size_t kMaxUnusedReadBufferCapacity = 256 * 1024;
28 const size_t kMaxChannelMessageSize = 256 * 1024 * 1024; 28 const size_t kMaxChannelMessageSize = 256 * 1024 * 1024;
29 const size_t kMaxAttachedHandles = 128;
29 30
30 Channel::Message::Message(size_t payload_size, 31 Channel::Message::Message(size_t payload_size,
31 size_t num_handles, 32 size_t max_handles,
32 Header::MessageType message_type) { 33 Header::MessageType message_type)
33 size_ = payload_size + sizeof(Header); 34 : max_handles_(max_handles) {
35 DCHECK_LE(max_handles_, kMaxAttachedHandles);
36
37 size_t extra_header_size = 0;
34 #if defined(OS_WIN) 38 #if defined(OS_WIN)
35 // On Windows we serialize platform handles directly into the message buffer. 39 // On Windows we serialize platform handles into the extra header space.
36 size_ += num_handles * sizeof(PlatformHandle); 40 extra_header_size = max_handles_ * sizeof(PlatformHandle);
37 #endif 41 #endif
42 // Pad extra header data to be aliged to |kChannelMessageAlignment| bytes.
43 if (extra_header_size % kChannelMessageAlignment) {
44 extra_header_size += kChannelMessageAlignment -
45 (extra_header_size % kChannelMessageAlignment);
46 }
47 DCHECK_EQ(0u, extra_header_size % kChannelMessageAlignment);
38 48
49 size_ = sizeof(Header) + extra_header_size + payload_size;
39 data_ = static_cast<char*>(base::AlignedAlloc(size_, 50 data_ = static_cast<char*>(base::AlignedAlloc(size_,
40 kChannelMessageAlignment)); 51 kChannelMessageAlignment));
41 memset(data_, 0, size_); 52 memset(data_, 0, size_);
42 header_ = reinterpret_cast<Header*>(data_); 53 header_ = reinterpret_cast<Header*>(data_);
43 54
44 DCHECK_LE(size_, std::numeric_limits<uint32_t>::max()); 55 DCHECK_LE(size_, std::numeric_limits<uint32_t>::max());
45 header_->num_bytes = static_cast<uint32_t>(size_); 56 header_->num_bytes = static_cast<uint32_t>(size_);
46 57
47 DCHECK_LE(num_handles, std::numeric_limits<uint16_t>::max()); 58 DCHECK_LE(sizeof(Header) + extra_header_size,
48 header_->num_handles = static_cast<uint16_t>(num_handles); 59 std::numeric_limits<uint16_t>::max());
60 header_->num_header_bytes =
61 static_cast<uint16_t>(sizeof(Header) + extra_header_size);
49 62
50 header_->message_type = message_type; 63 header_->message_type = message_type;
51 64
52 #if defined(OS_WIN) 65 #if defined(OS_WIN)
53 if (num_handles > 0) { 66 if (max_handles_ > 0) {
54 handles_ = reinterpret_cast<PlatformHandle*>( 67 handles_ = reinterpret_cast<PlatformHandle*>(mutable_extra_header());
55 data_ + sizeof(Header) + payload_size);
56 // Initialize all handles to invalid values. 68 // Initialize all handles to invalid values.
57 for (size_t i = 0; i < header_->num_handles; ++i) 69 for (size_t i = 0; i < max_handles_; ++i)
58 handles()[i] = PlatformHandle(); 70 handles()[i] = PlatformHandle();
59 } 71 }
60 #endif 72 #endif
61 } 73 }
62 74
63 Channel::Message::~Message() { 75 Channel::Message::~Message() {
64 #if defined(OS_WIN) 76 #if defined(OS_WIN)
65 // On POSIX the ScopedPlatformHandleVectorPtr will do this for us. 77 // On POSIX the ScopedPlatformHandleVectorPtr will do this for us.
66 for (size_t i = 0; i < header_->num_handles; ++i) 78 for (size_t i = 0; i < header_->num_handles; ++i)
67 handles()[i].CloseIfNecessary(); 79 handles()[i].CloseIfNecessary();
(...skipping 12 matching lines...) Expand all
80 if (data_num_bytes < sizeof(Header)) 92 if (data_num_bytes < sizeof(Header))
81 return nullptr; 93 return nullptr;
82 94
83 const Header* header = reinterpret_cast<const Header*>(data); 95 const Header* header = reinterpret_cast<const Header*>(data);
84 if (header->num_bytes != data_num_bytes) { 96 if (header->num_bytes != data_num_bytes) {
85 DLOG(ERROR) << "Decoding invalid message: " << header->num_bytes 97 DLOG(ERROR) << "Decoding invalid message: " << header->num_bytes
86 << " != " << data_num_bytes; 98 << " != " << data_num_bytes;
87 return nullptr; 99 return nullptr;
88 } 100 }
89 101
90 uint32_t handles_size = header->num_handles * sizeof(PlatformHandle); 102 if (header->num_bytes < header->num_header_bytes) {
91 if (data_num_bytes < sizeof(Header) + handles_size) { 103 DLOG(ERROR) << "Decoding invalid message: " << header->num_bytes << " < "
92 DLOG(ERROR) << "Decoding invalid message:" << data_num_bytes 104 << header->num_header_bytes;
93 << " < " << (sizeof(Header) + handles_size);
94 return nullptr; 105 return nullptr;
95 } 106 }
96 107
97 DCHECK_LE(handles_size, data_num_bytes - sizeof(Header)); 108 uint32_t extra_header_size = header->num_header_bytes - sizeof(Header);
109 uint32_t max_handles = extra_header_size / sizeof(PlatformHandle);
110 if (header->num_handles > max_handles) {
111 DLOG(ERROR) << "Decoding invalid message:" << header->num_handles << " > "
112 << max_handles;
113 return nullptr;
114 }
98 115
99 MessagePtr message(new Message(data_num_bytes - sizeof(Header) - handles_size, 116 MessagePtr message(
100 header->num_handles)); 117 new Message(data_num_bytes - header->num_header_bytes, max_handles));
101 118
102 DCHECK_EQ(message->data_num_bytes(), data_num_bytes); 119 DCHECK_EQ(message->data_num_bytes(), data_num_bytes);
120 DCHECK_EQ(message->extra_header_size(), extra_header_size);
121 DCHECK_EQ(message->header_->num_header_bytes, header->num_header_bytes);
103 122
104 // Copy all bytes, including the serialized handles. 123 // Copy all payload bytes.
105 memcpy(message->mutable_payload(), 124 memcpy(message->mutable_payload(),
125 static_cast<const char*>(data) + header->num_header_bytes,
126 data_num_bytes - header->num_header_bytes);
127 // Copy extra header bytes.
128 memcpy(message->mutable_extra_header(),
106 static_cast<const char*>(data) + sizeof(Header), 129 static_cast<const char*>(data) + sizeof(Header),
107 data_num_bytes - sizeof(Header)); 130 message->extra_header_size());
131 message->header_->num_handles = header->num_handles;
108 132
109 return message; 133 return message;
110 } 134 }
111 135
112 size_t Channel::Message::payload_size() const { 136 size_t Channel::Message::payload_size() const {
113 #if defined(OS_WIN) 137 return size_ - header_->num_header_bytes;
114 return size_ - sizeof(Header) -
115 sizeof(PlatformHandle) * header_->num_handles;
116 #else
117 return header_->num_bytes - sizeof(Header);
118 #endif
119 } 138 }
120 139
121 PlatformHandle* Channel::Message::handles() { 140 PlatformHandle* Channel::Message::handles() {
122 if (header_->num_handles == 0) 141 if (max_handles_ == 0)
123 return nullptr; 142 return nullptr;
124 #if defined(OS_WIN) 143 #if defined(OS_WIN)
125 return reinterpret_cast<PlatformHandle*>(static_cast<char*>(data_) + 144 return handles_;
126 sizeof(Header) + payload_size());
127 #else 145 #else
128 CHECK(handle_vector_); 146 CHECK(handle_vector_);
129 return handle_vector_->data(); 147 return handle_vector_->data();
130 #endif 148 #endif
131 } 149 }
132 150
151 #if defined(OS_MACOSX) && !defined(OS_IOS)
152 bool Channel::Message::has_mach_ports() const {
153 if (!has_handles())
154 return false;
155
156 for (const auto& handle : (*handle_vector_)) {
157 if (handle.type == PlatformHandle::Type::MACH)
158 return true;
159 }
160 return false;
161 }
162 #endif
163
133 void Channel::Message::SetHandles(ScopedPlatformHandleVectorPtr new_handles) { 164 void Channel::Message::SetHandles(ScopedPlatformHandleVectorPtr new_handles) {
134 if (header_->num_handles == 0) { 165 if (max_handles_ == 0) {
135 CHECK(!new_handles || new_handles->size() == 0); 166 CHECK(!new_handles || new_handles->size() == 0);
136 return; 167 return;
137 } 168 }
138 169
139 CHECK(new_handles && new_handles->size() == header_->num_handles); 170 CHECK(new_handles && new_handles->size() <= max_handles_);
171 header_->num_handles = static_cast<uint16_t>(new_handles->size());
140 #if defined(OS_WIN) 172 #if defined(OS_WIN)
141 memcpy(handles(), new_handles->data(), 173 memcpy(handles(), new_handles->data(),
142 sizeof(PlatformHandle) * header_->num_handles); 174 sizeof(PlatformHandle) * new_handles->size());
143 new_handles->clear(); 175 new_handles->clear();
144 #else 176 #else
145 std::swap(handle_vector_, new_handles); 177 std::swap(handle_vector_, new_handles);
146 #endif 178 #endif
147 } 179 }
148 180
149 ScopedPlatformHandleVectorPtr Channel::Message::TakeHandles() { 181 ScopedPlatformHandleVectorPtr Channel::Message::TakeHandles() {
150 #if defined(OS_WIN) 182 #if defined(OS_WIN)
151 if (header_->num_handles == 0) 183 if (header_->num_handles == 0)
152 return ScopedPlatformHandleVectorPtr(); 184 return ScopedPlatformHandleVectorPtr();
(...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after
322 } 354 }
323 355
324 if (read_buffer_->num_occupied_bytes() < header->num_bytes) { 356 if (read_buffer_->num_occupied_bytes() < header->num_bytes) {
325 // Not enough data available to read the full message. Hint to the 357 // 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. 358 // implementation that it should try reading the full size of the message.
327 *next_read_size_hint = 359 *next_read_size_hint =
328 header->num_bytes - read_buffer_->num_occupied_bytes(); 360 header->num_bytes - read_buffer_->num_occupied_bytes();
329 return true; 361 return true;
330 } 362 }
331 363
332 size_t payload_size = header->num_bytes - sizeof(Message::Header); 364 size_t extra_header_size =
333 void* payload = payload_size ? const_cast<Message::Header*>(&header[1]) 365 header->num_header_bytes - sizeof(Message::Header);
334 : nullptr; 366 const void* extra_header = header + 1;
367 size_t payload_size = header->num_bytes - header->num_header_bytes;
368 void* payload =
369 payload_size ? reinterpret_cast<Message::Header*>(
370 const_cast<char*>(read_buffer_->occupied_bytes()) +
371 header->num_header_bytes)
372 : nullptr;
335 373
336 ScopedPlatformHandleVectorPtr handles; 374 ScopedPlatformHandleVectorPtr handles;
337 if (header->num_handles > 0) { 375 if (header->num_handles > 0) {
338 handles = GetReadPlatformHandles(header->num_handles, 376 handles = GetReadPlatformHandles(header->num_handles, extra_header,
339 &payload, &payload_size); 377 extra_header_size);
340 if (!handles) { 378 if (!handles) {
341 // Not enough handles available for this message. 379 // Not enough handles available for this message.
342 break; 380 break;
343 } 381 }
344 } 382 }
345 383
346 // We've got a complete message! Dispatch it and try another. 384 // We've got a complete message! Dispatch it and try another.
347 if (header->message_type != Message::Header::MessageType::NORMAL) { 385 if (header->message_type != Message::Header::MessageType::NORMAL) {
348 OnControlMessage(header->message_type, payload, payload_size, 386 OnControlMessage(header->message_type, payload, payload_size,
349 std::move(handles)); 387 std::move(handles));
(...skipping 10 matching lines...) Expand all
360 return true; 398 return true;
361 } 399 }
362 400
363 void Channel::OnError() { 401 void Channel::OnError() {
364 if (delegate_) 402 if (delegate_)
365 delegate_->OnChannelError(); 403 delegate_->OnChannelError();
366 } 404 }
367 405
368 } // namespace edk 406 } // namespace edk
369 } // namespace mojo 407 } // namespace mojo
OLDNEW
« no previous file with comments | « mojo/edk/system/channel.h ('k') | mojo/edk/system/channel_posix.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698