14e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
24e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
34e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// found in the LICENSE file.
44e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
54e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "mojo/system/message_in_transit.h"
64e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
74e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include <string.h>
84e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
9f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "base/compiler_specific.h"
104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "base/logging.h"
115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "mojo/system/constants.h"
12010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "mojo/system/transport_data.h"
134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)namespace mojo {
154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)namespace system {
164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
175c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuSTATIC_CONST_MEMBER_DEFINITION const MessageInTransit::Type
185c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    MessageInTransit::kTypeMessagePipeEndpoint;
195c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuSTATIC_CONST_MEMBER_DEFINITION const MessageInTransit::Type
205c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    MessageInTransit::kTypeMessagePipe;
215c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuSTATIC_CONST_MEMBER_DEFINITION const MessageInTransit::Type
225c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    MessageInTransit::kTypeChannel;
23cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)STATIC_CONST_MEMBER_DEFINITION const MessageInTransit::Type
24cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    MessageInTransit::kTypeRawChannel;
255c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuSTATIC_CONST_MEMBER_DEFINITION const MessageInTransit::Subtype
265c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    MessageInTransit::kSubtypeMessagePipeEndpointData;
275c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuSTATIC_CONST_MEMBER_DEFINITION const MessageInTransit::Subtype
285c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    MessageInTransit::kSubtypeChannelRunMessagePipeEndpoint;
295c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuSTATIC_CONST_MEMBER_DEFINITION const MessageInTransit::Subtype
305c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    MessageInTransit::kSubtypeChannelRemoveMessagePipeEndpoint;
315c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuSTATIC_CONST_MEMBER_DEFINITION const MessageInTransit::Subtype
325c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    MessageInTransit::kSubtypeChannelRemoveMessagePipeEndpointAck;
33cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)STATIC_CONST_MEMBER_DEFINITION const MessageInTransit::Subtype
34cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    MessageInTransit::kSubtypeRawChannelPosixExtraPlatformHandles;
355c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuSTATIC_CONST_MEMBER_DEFINITION const MessageInTransit::EndpointId
365c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    MessageInTransit::kInvalidEndpointId;
375c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuSTATIC_CONST_MEMBER_DEFINITION const size_t MessageInTransit::kMessageAlignment;
385c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
39a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)struct MessageInTransit::PrivateStructForCompileAsserts {
40c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // The size of |Header| must be a multiple of the alignment.
411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  static_assert(sizeof(Header) % kMessageAlignment == 0,
421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                "sizeof(MessageInTransit::Header) invalid");
43a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Avoid dangerous situations, but making sure that the size of the "header" +
44a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // the size of the data fits into a 31-bit number.
451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  static_assert(static_cast<uint64_t>(sizeof(Header)) + kMaxMessageNumBytes <=
461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                    0x7fffffffULL,
471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                "kMaxMessageNumBytes too big");
484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
49effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  // We assume (to avoid extra rounding code) that the maximum message (data)
50effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  // size is a multiple of the alignment.
511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  static_assert(kMaxMessageNumBytes % kMessageAlignment == 0,
521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                "kMessageAlignment not a multiple of alignment");
53a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)};
544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
55a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)MessageInTransit::View::View(size_t message_size, const void* buffer)
56a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    : buffer_(buffer) {
57a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  size_t next_message_size = 0;
585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  DCHECK(MessageInTransit::GetNextMessageSize(
595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      buffer_, message_size, &next_message_size));
60a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DCHECK_EQ(message_size, next_message_size);
61a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // This should be equivalent.
62a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DCHECK_EQ(message_size, total_size());
63a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
64a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
65cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)bool MessageInTransit::View::IsValid(size_t serialized_platform_handle_size,
66cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                     const char** error_message) const {
67effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  // Note: This also implies a check on the |main_buffer_size()|, which is just
68effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  // |RoundUpMessageAlignment(sizeof(Header) + num_bytes())|.
69effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  if (num_bytes() > kMaxMessageNumBytes) {
70effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    *error_message = "Message data payload too large";
71effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    return false;
72effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  }
73effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
74010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (transport_data_buffer_size() > 0) {
75cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const char* e =
76cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        TransportData::ValidateBuffer(serialized_platform_handle_size,
77cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                      transport_data_buffer(),
78cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                      transport_data_buffer_size());
79010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    if (e) {
80010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      *error_message = e;
81010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      return false;
82010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    }
83effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  }
84effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
85effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  return true;
86effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch}
87effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
88a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)MessageInTransit::MessageInTransit(Type type,
89a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                   Subtype subtype,
90a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                   uint32_t num_bytes,
91a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                   const void* bytes)
92a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    : main_buffer_size_(RoundUpMessageAlignment(sizeof(Header) + num_bytes)),
935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      main_buffer_(static_cast<char*>(
945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)          base::AlignedAlloc(main_buffer_size_, kMessageAlignment))) {
955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ConstructorHelper(type, subtype, num_bytes);
96a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (bytes) {
97a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    memcpy(MessageInTransit::bytes(), bytes, num_bytes);
985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    memset(static_cast<char*>(MessageInTransit::bytes()) + num_bytes,
995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)           0,
100a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)           main_buffer_size_ - sizeof(Header) - num_bytes);
101a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  } else {
102a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    memset(MessageInTransit::bytes(), 0, main_buffer_size_ - sizeof(Header));
103a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
1044e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
1054e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)MessageInTransit::MessageInTransit(Type type,
1075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                   Subtype subtype,
1085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                   uint32_t num_bytes,
1095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                   UserPointer<const void> bytes)
1105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    : main_buffer_size_(RoundUpMessageAlignment(sizeof(Header) + num_bytes)),
1115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      main_buffer_(static_cast<char*>(
1125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)          base::AlignedAlloc(main_buffer_size_, kMessageAlignment))) {
1135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ConstructorHelper(type, subtype, num_bytes);
1145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  bytes.GetArray(MessageInTransit::bytes(), num_bytes);
1155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
1165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
117a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)MessageInTransit::MessageInTransit(const View& message_view)
118a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    : main_buffer_size_(message_view.main_buffer_size()),
1195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      main_buffer_(static_cast<char*>(
1205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)          base::AlignedAlloc(main_buffer_size_, kMessageAlignment))) {
121a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DCHECK_GE(main_buffer_size_, sizeof(Header));
122a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DCHECK_EQ(main_buffer_size_ % kMessageAlignment, 0u);
123a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
124010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  memcpy(main_buffer_.get(), message_view.main_buffer(), main_buffer_size_);
125a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DCHECK_EQ(main_buffer_size_,
126a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)            RoundUpMessageAlignment(sizeof(Header) + num_bytes()));
1275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
129a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)MessageInTransit::~MessageInTransit() {
130c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (dispatchers_) {
131a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    for (size_t i = 0; i < dispatchers_->size(); i++) {
1321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      if (!(*dispatchers_)[i].get())
133a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        continue;
134a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
135a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      DCHECK((*dispatchers_)[i]->HasOneRef());
136a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      (*dispatchers_)[i]->Close();
137a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    }
138a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
139a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
140a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
141a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// static
142a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)bool MessageInTransit::GetNextMessageSize(const void* buffer,
143a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                          size_t buffer_size,
144a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                          size_t* next_message_size) {
145a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DCHECK(next_message_size);
146a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!buffer_size)
147a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return false;
148a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DCHECK(buffer);
1495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  DCHECK_EQ(
1505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      reinterpret_cast<uintptr_t>(buffer) % MessageInTransit::kMessageAlignment,
1515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      0u);
152a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
153a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (buffer_size < sizeof(Header))
154a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return false;
155a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
156a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  const Header* header = static_cast<const Header*>(buffer);
157a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  *next_message_size = header->total_size;
158a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DCHECK_EQ(*next_message_size % kMessageAlignment, 0u);
159a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return true;
160a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
161a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
162a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void MessageInTransit::SetDispatchers(
163010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    scoped_ptr<DispatcherVector> dispatchers) {
164c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  DCHECK(dispatchers);
165c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  DCHECK(!dispatchers_);
166cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK(!transport_data_);
167a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
168a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  dispatchers_ = dispatchers.Pass();
169a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#ifndef NDEBUG
170a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  for (size_t i = 0; i < dispatchers_->size(); i++)
1711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    DCHECK(!(*dispatchers_)[i].get() || (*dispatchers_)[i]->HasOneRef());
172a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#endif
173a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
174a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
175cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void MessageInTransit::SetTransportData(
176cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    scoped_ptr<TransportData> transport_data) {
177cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK(transport_data);
178cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK(!transport_data_);
179cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK(!dispatchers_);
180cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
181cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  transport_data_ = transport_data.Pass();
182cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
183cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
184a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void MessageInTransit::SerializeAndCloseDispatchers(Channel* channel) {
185a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DCHECK(channel);
186010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  DCHECK(!transport_data_);
187a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
188010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (!dispatchers_ || !dispatchers_->size())
189a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return;
190a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
191010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  transport_data_.reset(new TransportData(dispatchers_.Pass(), channel));
192a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
193010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // Update the sizes in the message header.
194a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  UpdateTotalSize();
195a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
196a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
1975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void MessageInTransit::ConstructorHelper(Type type,
1985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                         Subtype subtype,
1995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                         uint32_t num_bytes) {
2005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  DCHECK_LE(num_bytes, kMaxMessageNumBytes);
2015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
2025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // |total_size| is updated below, from the other values.
2035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  header()->type = type;
2045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  header()->subtype = subtype;
2055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  header()->source_id = kInvalidEndpointId;
2065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  header()->destination_id = kInvalidEndpointId;
2075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  header()->num_bytes = num_bytes;
2085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  header()->unused = 0;
2095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // Note: If dispatchers are subsequently attached, then |total_size| will have
2105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // to be adjusted.
2115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  UpdateTotalSize();
2125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
2135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
214a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void MessageInTransit::UpdateTotalSize() {
215a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DCHECK_EQ(main_buffer_size_ % kMessageAlignment, 0u);
216010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  header()->total_size = static_cast<uint32_t>(main_buffer_size_);
217010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (transport_data_) {
218010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    header()->total_size +=
219010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        static_cast<uint32_t>(transport_data_->buffer_size());
220010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
2215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2234e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}  // namespace system
2244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}  // namespace mojo
225