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 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 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 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 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