| // Copyright 2016 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include <stdlib.h> |
| |
| #include <limits> |
| |
| #include "base/logging.h" |
| #include "mojo/edk/system/ports/event.h" |
| |
| namespace mojo { |
| namespace edk { |
| namespace ports { |
| |
| // static |
| bool Message::Parse(const void* bytes, |
| size_t num_bytes, |
| size_t* num_header_bytes, |
| size_t* num_payload_bytes, |
| size_t* num_ports_bytes) { |
| if (num_bytes < sizeof(EventHeader)) |
| return false; |
| const EventHeader* header = static_cast<const EventHeader*>(bytes); |
| switch (header->type) { |
| case EventType::kUser: |
| // See below. |
| break; |
| case EventType::kPortAccepted: |
| *num_header_bytes = sizeof(EventHeader); |
| break; |
| case EventType::kObserveProxy: |
| *num_header_bytes = sizeof(EventHeader) + sizeof(ObserveProxyEventData); |
| break; |
| case EventType::kObserveProxyAck: |
| *num_header_bytes = |
| sizeof(EventHeader) + sizeof(ObserveProxyAckEventData); |
| break; |
| case EventType::kObserveClosure: |
| *num_header_bytes = sizeof(EventHeader) + sizeof(ObserveClosureEventData); |
| break; |
| case EventType::kMergePort: |
| *num_header_bytes = sizeof(EventHeader) + sizeof(MergePortEventData); |
| break; |
| default: |
| return false; |
| } |
| |
| if (header->type == EventType::kUser) { |
| if (num_bytes < sizeof(EventHeader) + sizeof(UserEventData)) |
| return false; |
| const UserEventData* event_data = |
| reinterpret_cast<const UserEventData*>( |
| reinterpret_cast<const char*>(header + 1)); |
| if (event_data->num_ports > std::numeric_limits<uint16_t>::max()) |
| return false; |
| *num_header_bytes = sizeof(EventHeader) + |
| sizeof(UserEventData) + |
| event_data->num_ports * sizeof(PortDescriptor); |
| *num_ports_bytes = event_data->num_ports * sizeof(PortName); |
| if (num_bytes < *num_header_bytes + *num_ports_bytes) |
| return false; |
| *num_payload_bytes = num_bytes - *num_header_bytes - *num_ports_bytes; |
| } else { |
| if (*num_header_bytes != num_bytes) |
| return false; |
| *num_payload_bytes = 0; |
| *num_ports_bytes = 0; |
| } |
| |
| return true; |
| } |
| |
| Message::Message(size_t num_payload_bytes, size_t num_ports) |
| : Message(sizeof(EventHeader) + sizeof(UserEventData) + |
| num_ports * sizeof(PortDescriptor), |
| num_payload_bytes, num_ports * sizeof(PortName)) { |
| num_ports_ = num_ports; |
| } |
| |
| Message::Message(size_t num_header_bytes, |
| size_t num_payload_bytes, |
| size_t num_ports_bytes) |
| : start_(nullptr), |
| num_header_bytes_(num_header_bytes), |
| num_ports_bytes_(num_ports_bytes), |
| num_payload_bytes_(num_payload_bytes) { |
| } |
| |
| void Message::InitializeUserMessageHeader(void* start) { |
| start_ = static_cast<char*>(start); |
| memset(start_, 0, num_header_bytes_); |
| GetMutableEventHeader(this)->type = EventType::kUser; |
| GetMutableEventData<UserEventData>(this)->num_ports = |
| static_cast<uint32_t>(num_ports_); |
| } |
| |
| } // namespace ports |
| } // namespace edk |
| } // namespace mojo |