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
3 // found in the LICENSE file.
4
5 #include "mojo/core/ports/event.h"
6
7 #include <stdint.h>
8 #include <string.h>
9
10 #include "base/logging.h"
11 #include "mojo/core/ports/user_message.h"
12 #include "mozilla/Assertions.h"
13 #include "mozilla/CheckedInt.h"
14
15 namespace mojo {
16 namespace core {
17 namespace ports {
18
19 namespace {
20
21 const size_t kPortsMessageAlignment = 8;
22
23 #pragma pack(push, 1)
24
25 struct SerializedHeader {
26 Event::Type type;
27 uint32_t padding;
28 PortName port_name;
29 };
30
31 struct UserMessageEventData {
32 uint64_t sequence_num;
33 uint32_t num_ports;
34 uint32_t padding;
35 };
36
37 struct ObserveProxyEventData {
38 NodeName proxy_node_name;
39 PortName proxy_port_name;
40 NodeName proxy_target_node_name;
41 PortName proxy_target_port_name;
42 };
43
44 struct ObserveProxyAckEventData {
45 uint64_t last_sequence_num;
46 };
47
48 struct ObserveClosureEventData {
49 uint64_t last_sequence_num;
50 };
51
52 struct MergePortEventData {
53 PortName new_port_name;
54 Event::PortDescriptor new_port_descriptor;
55 };
56
57 struct UserMessageReadAckRequestEventData {
58 uint64_t sequence_num_to_acknowledge;
59 };
60
61 struct UserMessageReadAckEventData {
62 uint64_t sequence_num_acknowledged;
63 };
64
65 #pragma pack(pop)
66
67 static_assert(sizeof(Event::PortDescriptor) % kPortsMessageAlignment == 0,
68 "Invalid PortDescriptor size.");
69
70 static_assert(sizeof(SerializedHeader) % kPortsMessageAlignment == 0,
71 "Invalid SerializedHeader size.");
72
73 static_assert(sizeof(UserMessageEventData) % kPortsMessageAlignment == 0,
74 "Invalid UserEventData size.");
75
76 static_assert(sizeof(ObserveProxyEventData) % kPortsMessageAlignment == 0,
77 "Invalid ObserveProxyEventData size.");
78
79 static_assert(sizeof(ObserveProxyAckEventData) % kPortsMessageAlignment == 0,
80 "Invalid ObserveProxyAckEventData size.");
81
82 static_assert(sizeof(ObserveClosureEventData) % kPortsMessageAlignment == 0,
83 "Invalid ObserveClosureEventData size.");
84
85 static_assert(sizeof(MergePortEventData) % kPortsMessageAlignment == 0,
86 "Invalid MergePortEventData size.");
87
88 static_assert(sizeof(UserMessageReadAckRequestEventData) %
89 kPortsMessageAlignment ==
90 0,
91 "Invalid UserMessageReadAckRequestEventData size.");
92
93 static_assert(sizeof(UserMessageReadAckEventData) % kPortsMessageAlignment == 0,
94 "Invalid UserMessageReadAckEventData size.");
95
96 } // namespace
97
PortDescriptor()98 Event::PortDescriptor::PortDescriptor() { memset(padding, 0, sizeof(padding)); }
99
100 Event::~Event() = default;
101
102 // static
Deserialize(const void * buffer,size_t num_bytes)103 ScopedEvent Event::Deserialize(const void* buffer, size_t num_bytes) {
104 if (num_bytes < sizeof(SerializedHeader)) {
105 return nullptr;
106 }
107
108 const auto* header = static_cast<const SerializedHeader*>(buffer);
109 const PortName& port_name = header->port_name;
110 const size_t data_size = num_bytes - sizeof(*header);
111 switch (header->type) {
112 case Type::kUserMessage:
113 return UserMessageEvent::Deserialize(port_name, header + 1, data_size);
114 case Type::kPortAccepted:
115 return PortAcceptedEvent::Deserialize(port_name, header + 1, data_size);
116 case Type::kObserveProxy:
117 return ObserveProxyEvent::Deserialize(port_name, header + 1, data_size);
118 case Type::kObserveProxyAck:
119 return ObserveProxyAckEvent::Deserialize(port_name, header + 1,
120 data_size);
121 case Type::kObserveClosure:
122 return ObserveClosureEvent::Deserialize(port_name, header + 1, data_size);
123 case Type::kMergePort:
124 return MergePortEvent::Deserialize(port_name, header + 1, data_size);
125 case Type::kUserMessageReadAckRequest:
126 return UserMessageReadAckRequestEvent::Deserialize(port_name, header + 1,
127 data_size);
128 case Type::kUserMessageReadAck:
129 return UserMessageReadAckEvent::Deserialize(port_name, header + 1,
130 data_size);
131 default:
132 DVLOG(2) << "Ingoring unknown port event type: "
133 << static_cast<uint32_t>(header->type);
134 return nullptr;
135 }
136 }
137
Event(Type type,const PortName & port_name)138 Event::Event(Type type, const PortName& port_name)
139 : type_(type), port_name_(port_name) {}
140
GetSerializedSize() const141 size_t Event::GetSerializedSize() const {
142 return sizeof(SerializedHeader) + GetSerializedDataSize();
143 }
144
Serialize(void * buffer) const145 void Event::Serialize(void* buffer) const {
146 auto* header = static_cast<SerializedHeader*>(buffer);
147 header->type = type_;
148 header->padding = 0;
149 header->port_name = port_name_;
150 SerializeData(header + 1);
151 }
152
Clone() const153 ScopedEvent Event::Clone() const { return nullptr; }
154
155 UserMessageEvent::~UserMessageEvent() = default;
156
UserMessageEvent(size_t num_ports)157 UserMessageEvent::UserMessageEvent(size_t num_ports)
158 : Event(Type::kUserMessage, kInvalidPortName) {
159 ReservePorts(num_ports);
160 }
161
AttachMessage(mozilla::UniquePtr<UserMessage> message)162 void UserMessageEvent::AttachMessage(mozilla::UniquePtr<UserMessage> message) {
163 DCHECK(!message_);
164 message_ = std::move(message);
165 }
166
ReservePorts(size_t num_ports)167 void UserMessageEvent::ReservePorts(size_t num_ports) {
168 port_descriptors_.resize(num_ports);
169 ports_.resize(num_ports);
170 }
171
NotifyWillBeRoutedExternally()172 bool UserMessageEvent::NotifyWillBeRoutedExternally() {
173 DCHECK(message_);
174 return message_->WillBeRoutedExternally(*this);
175 }
176
177 // static
Deserialize(const PortName & port_name,const void * buffer,size_t num_bytes)178 ScopedEvent UserMessageEvent::Deserialize(const PortName& port_name,
179 const void* buffer,
180 size_t num_bytes) {
181 if (num_bytes < sizeof(UserMessageEventData)) {
182 return nullptr;
183 }
184
185 const auto* data = static_cast<const UserMessageEventData*>(buffer);
186 mozilla::CheckedInt<size_t> port_data_size = data->num_ports;
187 port_data_size *= sizeof(PortDescriptor) + sizeof(PortName);
188 if (!port_data_size.isValid()) {
189 return nullptr;
190 }
191
192 mozilla::CheckedInt<size_t> total_size = port_data_size.value();
193 total_size += sizeof(UserMessageEventData);
194 if (!total_size.isValid() || num_bytes < total_size.value()) {
195 return nullptr;
196 }
197
198 auto event =
199 mozilla::WrapUnique(new UserMessageEvent(port_name, data->sequence_num));
200 event->ReservePorts(data->num_ports);
201 const auto* in_descriptors =
202 reinterpret_cast<const PortDescriptor*>(data + 1);
203 std::copy(in_descriptors, in_descriptors + data->num_ports,
204 event->port_descriptors());
205
206 const auto* in_names =
207 reinterpret_cast<const PortName*>(in_descriptors + data->num_ports);
208 std::copy(in_names, in_names + data->num_ports, event->ports());
209 return event;
210 }
211
UserMessageEvent(const PortName & port_name,uint64_t sequence_num)212 UserMessageEvent::UserMessageEvent(const PortName& port_name,
213 uint64_t sequence_num)
214 : Event(Type::kUserMessage, port_name), sequence_num_(sequence_num) {}
215
GetSizeIfSerialized() const216 size_t UserMessageEvent::GetSizeIfSerialized() const {
217 if (!message_) {
218 return 0;
219 }
220 return message_->GetSizeIfSerialized();
221 }
222
GetSerializedDataSize() const223 size_t UserMessageEvent::GetSerializedDataSize() const {
224 DCHECK_EQ(ports_.size(), port_descriptors_.size());
225 mozilla::CheckedInt<size_t> size = sizeof(UserMessageEventData);
226 mozilla::CheckedInt<size_t> ports_size =
227 sizeof(PortDescriptor) + sizeof(PortName);
228 ports_size *= ports_.size();
229 mozilla::CheckedInt<size_t> combined = size + ports_size;
230 MOZ_RELEASE_ASSERT(combined.isValid());
231 return combined.value();
232 }
233
SerializeData(void * buffer) const234 void UserMessageEvent::SerializeData(void* buffer) const {
235 DCHECK_EQ(ports_.size(), port_descriptors_.size());
236 auto* data = static_cast<UserMessageEventData*>(buffer);
237 data->sequence_num = sequence_num_;
238 mozilla::CheckedInt<uint32_t> num_ports{ports_.size()};
239 DCHECK(num_ports.isValid());
240 data->num_ports = num_ports.value();
241 data->padding = 0;
242
243 auto* ports_data = reinterpret_cast<PortDescriptor*>(data + 1);
244 std::copy(port_descriptors_.begin(), port_descriptors_.end(), ports_data);
245
246 auto* port_names_data =
247 reinterpret_cast<PortName*>(ports_data + ports_.size());
248 std::copy(ports_.begin(), ports_.end(), port_names_data);
249 }
250
PortAcceptedEvent(const PortName & port_name)251 PortAcceptedEvent::PortAcceptedEvent(const PortName& port_name)
252 : Event(Type::kPortAccepted, port_name) {}
253
254 PortAcceptedEvent::~PortAcceptedEvent() = default;
255
256 // static
Deserialize(const PortName & port_name,const void * buffer,size_t num_bytes)257 ScopedEvent PortAcceptedEvent::Deserialize(const PortName& port_name,
258 const void* buffer,
259 size_t num_bytes) {
260 return mozilla::MakeUnique<PortAcceptedEvent>(port_name);
261 }
262
GetSerializedDataSize() const263 size_t PortAcceptedEvent::GetSerializedDataSize() const { return 0; }
264
SerializeData(void * buffer) const265 void PortAcceptedEvent::SerializeData(void* buffer) const {}
266
ObserveProxyEvent(const PortName & port_name,const NodeName & proxy_node_name,const PortName & proxy_port_name,const NodeName & proxy_target_node_name,const PortName & proxy_target_port_name)267 ObserveProxyEvent::ObserveProxyEvent(const PortName& port_name,
268 const NodeName& proxy_node_name,
269 const PortName& proxy_port_name,
270 const NodeName& proxy_target_node_name,
271 const PortName& proxy_target_port_name)
272 : Event(Type::kObserveProxy, port_name),
273 proxy_node_name_(proxy_node_name),
274 proxy_port_name_(proxy_port_name),
275 proxy_target_node_name_(proxy_target_node_name),
276 proxy_target_port_name_(proxy_target_port_name) {}
277
278 ObserveProxyEvent::~ObserveProxyEvent() = default;
279
280 // static
Deserialize(const PortName & port_name,const void * buffer,size_t num_bytes)281 ScopedEvent ObserveProxyEvent::Deserialize(const PortName& port_name,
282 const void* buffer,
283 size_t num_bytes) {
284 if (num_bytes < sizeof(ObserveProxyEventData)) {
285 return nullptr;
286 }
287
288 const auto* data = static_cast<const ObserveProxyEventData*>(buffer);
289 return mozilla::MakeUnique<ObserveProxyEvent>(
290 port_name, data->proxy_node_name, data->proxy_port_name,
291 data->proxy_target_node_name, data->proxy_target_port_name);
292 }
293
GetSerializedDataSize() const294 size_t ObserveProxyEvent::GetSerializedDataSize() const {
295 return sizeof(ObserveProxyEventData);
296 }
297
SerializeData(void * buffer) const298 void ObserveProxyEvent::SerializeData(void* buffer) const {
299 auto* data = static_cast<ObserveProxyEventData*>(buffer);
300 data->proxy_node_name = proxy_node_name_;
301 data->proxy_port_name = proxy_port_name_;
302 data->proxy_target_node_name = proxy_target_node_name_;
303 data->proxy_target_port_name = proxy_target_port_name_;
304 }
305
Clone() const306 ScopedEvent ObserveProxyEvent::Clone() const {
307 return mozilla::MakeUnique<ObserveProxyEvent>(
308 port_name(), proxy_node_name_, proxy_port_name_, proxy_target_node_name_,
309 proxy_target_port_name_);
310 }
311
ObserveProxyAckEvent(const PortName & port_name,uint64_t last_sequence_num)312 ObserveProxyAckEvent::ObserveProxyAckEvent(const PortName& port_name,
313 uint64_t last_sequence_num)
314 : Event(Type::kObserveProxyAck, port_name),
315 last_sequence_num_(last_sequence_num) {}
316
317 ObserveProxyAckEvent::~ObserveProxyAckEvent() = default;
318
319 // static
Deserialize(const PortName & port_name,const void * buffer,size_t num_bytes)320 ScopedEvent ObserveProxyAckEvent::Deserialize(const PortName& port_name,
321 const void* buffer,
322 size_t num_bytes) {
323 if (num_bytes < sizeof(ObserveProxyAckEventData)) {
324 return nullptr;
325 }
326
327 const auto* data = static_cast<const ObserveProxyAckEventData*>(buffer);
328 return mozilla::MakeUnique<ObserveProxyAckEvent>(port_name,
329 data->last_sequence_num);
330 }
331
GetSerializedDataSize() const332 size_t ObserveProxyAckEvent::GetSerializedDataSize() const {
333 return sizeof(ObserveProxyAckEventData);
334 }
335
SerializeData(void * buffer) const336 void ObserveProxyAckEvent::SerializeData(void* buffer) const {
337 auto* data = static_cast<ObserveProxyAckEventData*>(buffer);
338 data->last_sequence_num = last_sequence_num_;
339 }
340
Clone() const341 ScopedEvent ObserveProxyAckEvent::Clone() const {
342 return mozilla::MakeUnique<ObserveProxyAckEvent>(port_name(),
343 last_sequence_num_);
344 }
345
ObserveClosureEvent(const PortName & port_name,uint64_t last_sequence_num)346 ObserveClosureEvent::ObserveClosureEvent(const PortName& port_name,
347 uint64_t last_sequence_num)
348 : Event(Type::kObserveClosure, port_name),
349 last_sequence_num_(last_sequence_num) {}
350
351 ObserveClosureEvent::~ObserveClosureEvent() = default;
352
353 // static
Deserialize(const PortName & port_name,const void * buffer,size_t num_bytes)354 ScopedEvent ObserveClosureEvent::Deserialize(const PortName& port_name,
355 const void* buffer,
356 size_t num_bytes) {
357 if (num_bytes < sizeof(ObserveClosureEventData)) {
358 return nullptr;
359 }
360
361 const auto* data = static_cast<const ObserveClosureEventData*>(buffer);
362 return mozilla::MakeUnique<ObserveClosureEvent>(port_name,
363 data->last_sequence_num);
364 }
365
GetSerializedDataSize() const366 size_t ObserveClosureEvent::GetSerializedDataSize() const {
367 return sizeof(ObserveClosureEventData);
368 }
369
SerializeData(void * buffer) const370 void ObserveClosureEvent::SerializeData(void* buffer) const {
371 auto* data = static_cast<ObserveClosureEventData*>(buffer);
372 data->last_sequence_num = last_sequence_num_;
373 }
374
Clone() const375 ScopedEvent ObserveClosureEvent::Clone() const {
376 return mozilla::MakeUnique<ObserveClosureEvent>(port_name(),
377 last_sequence_num_);
378 }
379
MergePortEvent(const PortName & port_name,const PortName & new_port_name,const PortDescriptor & new_port_descriptor)380 MergePortEvent::MergePortEvent(const PortName& port_name,
381 const PortName& new_port_name,
382 const PortDescriptor& new_port_descriptor)
383 : Event(Type::kMergePort, port_name),
384 new_port_name_(new_port_name),
385 new_port_descriptor_(new_port_descriptor) {}
386
387 MergePortEvent::~MergePortEvent() = default;
388
389 // static
Deserialize(const PortName & port_name,const void * buffer,size_t num_bytes)390 ScopedEvent MergePortEvent::Deserialize(const PortName& port_name,
391 const void* buffer, size_t num_bytes) {
392 if (num_bytes < sizeof(MergePortEventData)) {
393 return nullptr;
394 }
395
396 const auto* data = static_cast<const MergePortEventData*>(buffer);
397 return mozilla::MakeUnique<MergePortEvent>(port_name, data->new_port_name,
398 data->new_port_descriptor);
399 }
400
GetSerializedDataSize() const401 size_t MergePortEvent::GetSerializedDataSize() const {
402 return sizeof(MergePortEventData);
403 }
404
SerializeData(void * buffer) const405 void MergePortEvent::SerializeData(void* buffer) const {
406 auto* data = static_cast<MergePortEventData*>(buffer);
407 data->new_port_name = new_port_name_;
408 data->new_port_descriptor = new_port_descriptor_;
409 }
410
UserMessageReadAckRequestEvent(const PortName & port_name,uint64_t sequence_num_to_acknowledge)411 UserMessageReadAckRequestEvent::UserMessageReadAckRequestEvent(
412 const PortName& port_name, uint64_t sequence_num_to_acknowledge)
413 : Event(Type::kUserMessageReadAckRequest, port_name),
414 sequence_num_to_acknowledge_(sequence_num_to_acknowledge) {}
415
416 UserMessageReadAckRequestEvent::~UserMessageReadAckRequestEvent() = default;
417
418 // static
Deserialize(const PortName & port_name,const void * buffer,size_t num_bytes)419 ScopedEvent UserMessageReadAckRequestEvent::Deserialize(
420 const PortName& port_name, const void* buffer, size_t num_bytes) {
421 if (num_bytes < sizeof(UserMessageReadAckRequestEventData)) {
422 return nullptr;
423 }
424
425 const auto* data =
426 static_cast<const UserMessageReadAckRequestEventData*>(buffer);
427 return mozilla::MakeUnique<UserMessageReadAckRequestEvent>(
428 port_name, data->sequence_num_to_acknowledge);
429 }
430
GetSerializedDataSize() const431 size_t UserMessageReadAckRequestEvent::GetSerializedDataSize() const {
432 return sizeof(UserMessageReadAckRequestEventData);
433 }
434
SerializeData(void * buffer) const435 void UserMessageReadAckRequestEvent::SerializeData(void* buffer) const {
436 auto* data = static_cast<UserMessageReadAckRequestEventData*>(buffer);
437 data->sequence_num_to_acknowledge = sequence_num_to_acknowledge_;
438 }
439
UserMessageReadAckEvent(const PortName & port_name,uint64_t sequence_num_acknowledged)440 UserMessageReadAckEvent::UserMessageReadAckEvent(
441 const PortName& port_name, uint64_t sequence_num_acknowledged)
442 : Event(Type::kUserMessageReadAck, port_name),
443 sequence_num_acknowledged_(sequence_num_acknowledged) {}
444
445 UserMessageReadAckEvent::~UserMessageReadAckEvent() = default;
446
447 // static
Deserialize(const PortName & port_name,const void * buffer,size_t num_bytes)448 ScopedEvent UserMessageReadAckEvent::Deserialize(const PortName& port_name,
449 const void* buffer,
450 size_t num_bytes) {
451 if (num_bytes < sizeof(UserMessageReadAckEventData)) {
452 return nullptr;
453 }
454
455 const auto* data = static_cast<const UserMessageReadAckEventData*>(buffer);
456 return mozilla::MakeUnique<UserMessageReadAckEvent>(
457 port_name, data->sequence_num_acknowledged);
458 }
459
GetSerializedDataSize() const460 size_t UserMessageReadAckEvent::GetSerializedDataSize() const {
461 return sizeof(UserMessageReadAckEventData);
462 }
463
SerializeData(void * buffer) const464 void UserMessageReadAckEvent::SerializeData(void* buffer) const {
465 auto* data = static_cast<UserMessageReadAckEventData*>(buffer);
466 data->sequence_num_acknowledged = sequence_num_acknowledged_;
467 }
468
469 } // namespace ports
470 } // namespace core
471 } // namespace mojo
472