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