普通文本  |  101行  |  3.14 KB

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