Home | History | Annotate | Download | only in ports
      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