普通文本  |  69行  |  2.63 KB

// Copyright 2013 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 "mojo/system/message_in_transit.h"

#include <stdlib.h>
#include <string.h>

#include <new>

#include "base/basictypes.h"
#include "base/compiler_specific.h"
#include "base/logging.h"
#include "mojo/system/constants.h"

namespace mojo {
namespace system {

// Avoid dangerous situations, but making sure that the size of the "header" +
// the size of the data fits into a 31-bit number.
COMPILE_ASSERT(static_cast<uint64_t>(sizeof(MessageInTransit)) +
                   kMaxMessageNumBytes <= 0x7fffffff,
               kMaxMessageNumBytes_too_big);

COMPILE_ASSERT(sizeof(MessageInTransit) %
                   MessageInTransit::kMessageAlignment == 0,
               sizeof_MessageInTransit_not_a_multiple_of_alignment);

STATIC_CONST_MEMBER_DEFINITION const MessageInTransit::Type
    MessageInTransit::kTypeMessagePipeEndpoint;
STATIC_CONST_MEMBER_DEFINITION const MessageInTransit::Type
    MessageInTransit::kTypeMessagePipe;
STATIC_CONST_MEMBER_DEFINITION const MessageInTransit::Type
    MessageInTransit::TYPE_CHANNEL;
STATIC_CONST_MEMBER_DEFINITION const MessageInTransit::Subtype
    MessageInTransit::kSubtypeMessagePipeEndpointData;
STATIC_CONST_MEMBER_DEFINITION const MessageInTransit::Subtype
    MessageInTransit::kSubtypeMessagePipePeerClosed;
STATIC_CONST_MEMBER_DEFINITION const MessageInTransit::EndpointId
    MessageInTransit::kInvalidEndpointId;
STATIC_CONST_MEMBER_DEFINITION const size_t MessageInTransit::kMessageAlignment;

// static
MessageInTransit* MessageInTransit::Create(Type type,
                                           Subtype subtype,
                                           const void* bytes,
                                           uint32_t num_bytes) {
  const size_t size_with_header = sizeof(MessageInTransit) + num_bytes;
  const size_t size_with_header_and_padding =
      RoundUpMessageAlignment(size_with_header);

  char* buffer = static_cast<char*>(malloc(size_with_header_and_padding));
  DCHECK_EQ(reinterpret_cast<size_t>(buffer) %
                MessageInTransit::kMessageAlignment, 0u);

  // The buffer consists of the header (a |MessageInTransit|, constructed using
  // a placement new), followed by the data, followed by padding (of zeros).
  MessageInTransit* rv =
      new (buffer) MessageInTransit(num_bytes, type, subtype);
  memcpy(buffer + sizeof(MessageInTransit), bytes, num_bytes);
  memset(buffer + size_with_header, 0,
         size_with_header_and_padding - size_with_header);
  return rv;
}

}  // namespace system
}  // namespace mojo