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 <stdlib.h>
6
7 #include <limits>
8
9 #include "base/logging.h"
10 #include "mojo/edk/system/ports/event.h"
11
12 namespace mojo {
13 namespace edk {
14 namespace ports {
15
16 // static
Parse(const void * bytes,size_t num_bytes,size_t * num_header_bytes,size_t * num_payload_bytes,size_t * num_ports_bytes)17 bool Message::Parse(const void* bytes,
18 size_t num_bytes,
19 size_t* num_header_bytes,
20 size_t* num_payload_bytes,
21 size_t* num_ports_bytes) {
22 if (num_bytes < sizeof(EventHeader))
23 return false;
24 const EventHeader* header = static_cast<const EventHeader*>(bytes);
25 switch (header->type) {
26 case EventType::kUser:
27 // See below.
28 break;
29 case EventType::kPortAccepted:
30 *num_header_bytes = sizeof(EventHeader);
31 break;
32 case EventType::kObserveProxy:
33 *num_header_bytes = sizeof(EventHeader) + sizeof(ObserveProxyEventData);
34 break;
35 case EventType::kObserveProxyAck:
36 *num_header_bytes =
37 sizeof(EventHeader) + sizeof(ObserveProxyAckEventData);
38 break;
39 case EventType::kObserveClosure:
40 *num_header_bytes = sizeof(EventHeader) + sizeof(ObserveClosureEventData);
41 break;
42 case EventType::kMergePort:
43 *num_header_bytes = sizeof(EventHeader) + sizeof(MergePortEventData);
44 break;
45 default:
46 return false;
47 }
48
49 if (header->type == EventType::kUser) {
50 if (num_bytes < sizeof(EventHeader) + sizeof(UserEventData))
51 return false;
52 const UserEventData* event_data =
53 reinterpret_cast<const UserEventData*>(
54 reinterpret_cast<const char*>(header + 1));
55 if (event_data->num_ports > std::numeric_limits<uint16_t>::max())
56 return false;
57 *num_header_bytes = sizeof(EventHeader) +
58 sizeof(UserEventData) +
59 event_data->num_ports * sizeof(PortDescriptor);
60 *num_ports_bytes = event_data->num_ports * sizeof(PortName);
61 if (num_bytes < *num_header_bytes + *num_ports_bytes)
62 return false;
63 *num_payload_bytes = num_bytes - *num_header_bytes - *num_ports_bytes;
64 } else {
65 if (*num_header_bytes != num_bytes)
66 return false;
67 *num_payload_bytes = 0;
68 *num_ports_bytes = 0;
69 }
70
71 return true;
72 }
73
Message(size_t num_payload_bytes,size_t num_ports)74 Message::Message(size_t num_payload_bytes, size_t num_ports)
75 : Message(sizeof(EventHeader) + sizeof(UserEventData) +
76 num_ports * sizeof(PortDescriptor),
77 num_payload_bytes, num_ports * sizeof(PortName)) {
78 num_ports_ = num_ports;
79 }
80
Message(size_t num_header_bytes,size_t num_payload_bytes,size_t num_ports_bytes)81 Message::Message(size_t num_header_bytes,
82 size_t num_payload_bytes,
83 size_t num_ports_bytes)
84 : start_(nullptr),
85 num_header_bytes_(num_header_bytes),
86 num_ports_bytes_(num_ports_bytes),
87 num_payload_bytes_(num_payload_bytes) {
88 }
89
InitializeUserMessageHeader(void * start)90 void Message::InitializeUserMessageHeader(void* start) {
91 start_ = static_cast<char*>(start);
92 memset(start_, 0, num_header_bytes_);
93 GetMutableEventHeader(this)->type = EventType::kUser;
94 GetMutableEventData<UserEventData>(this)->num_ports =
95 static_cast<uint32_t>(num_ports_);
96 }
97
98 } // namespace ports
99 } // namespace edk
100 } // namespace mojo
101