channel.cc revision 645501c2ab19a559ce82a1d5a29ced159a4c30fb
1645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// Copyright 2016 The Chromium Authors. All rights reserved.
2645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// Use of this source code is governed by a BSD-style license that can be
3645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// found in the LICENSE file.
4645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
5645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#include "mojo/edk/system/channel.h"
6645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
7645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#include <string.h>
8645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
9645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#include <algorithm>
10645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#include <limits>
11645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#include <utility>
12645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
13645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#include "base/macros.h"
14645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#include "base/memory/aligned_memory.h"
15645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#include "base/process/process_handle.h"
16645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#include "mojo/edk/embedder/platform_handle.h"
17645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
18645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#if defined(OS_MACOSX) && !defined(OS_IOS)
19645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#include "base/mac/mach_logging.h"
20645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#elif defined(OS_WIN)
21645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#include "base/win/win_util.h"
22645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#endif
23645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
24645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chaveznamespace mojo {
25645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chaveznamespace edk {
26645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
27645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chaveznamespace {
28645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
29645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezstatic_assert(sizeof(Channel::Message::Header) % kChannelMessageAlignment == 0,
30645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    "Invalid Header size.");
31645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
32645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#if defined(MOJO_EDK_LEGACY_PROTOCOL)
33645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezstatic_assert(sizeof(Channel::Message::Header) == 8,
34645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez              "Header must be 8 bytes on ChromeOS and Android");
35645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#endif
36645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
37645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez}  // namespace
38645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
39645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezconst size_t kReadBufferSize = 4096;
40645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezconst size_t kMaxUnusedReadBufferCapacity = 64 * 1024;
41645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezconst size_t kMaxChannelMessageSize = 256 * 1024 * 1024;
42645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezconst size_t kMaxAttachedHandles = 128;
43645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
44645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector ChavezChannel::Message::Message(size_t payload_size,
45645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez                          size_t max_handles,
46645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez                          Header::MessageType message_type)
47645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    : max_handles_(max_handles) {
48645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  DCHECK_LE(max_handles_, kMaxAttachedHandles);
49645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
50645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  size_t extra_header_size = 0;
51645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#if defined(OS_WIN)
52645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  // On Windows we serialize HANDLEs into the extra header space.
53645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  extra_header_size = max_handles_ * sizeof(HandleEntry);
54645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#elif defined(OS_MACOSX) && !defined(OS_IOS)
55645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  // On OSX, some of the platform handles may be mach ports, which are
56645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  // serialised into the message buffer. Since there could be a mix of fds and
57645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  // mach ports, we store the mach ports as an <index, port> pair (of uint32_t),
58645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  // so that the original ordering of handles can be re-created.
59645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  if (max_handles) {
60645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    extra_header_size =
61645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        sizeof(MachPortsExtraHeader) + (max_handles * sizeof(MachPortsEntry));
62645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  }
63645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#endif
64645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  // Pad extra header data to be aliged to |kChannelMessageAlignment| bytes.
65645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  if (extra_header_size % kChannelMessageAlignment) {
66645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    extra_header_size += kChannelMessageAlignment -
67645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez                         (extra_header_size % kChannelMessageAlignment);
68645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  }
69645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  DCHECK_EQ(0u, extra_header_size % kChannelMessageAlignment);
70645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#if defined(MOJO_EDK_LEGACY_PROTOCOL)
71645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  DCHECK_EQ(0u, extra_header_size);
72645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#endif
73645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
74645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  size_ = sizeof(Header) + extra_header_size + payload_size;
75645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  data_ = static_cast<char*>(base::AlignedAlloc(size_,
76645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez                                                kChannelMessageAlignment));
77645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  // Only zero out the header and not the payload. Since the payload is going to
78645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  // be memcpy'd, zeroing the payload is unnecessary work and a significant
79645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  // performance issue when dealing with large messages. Any sanitizer errors
80645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  // complaining about an uninitialized read in the payload area should be
81645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  // treated as an error and fixed.
82645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  memset(data_, 0, sizeof(Header) + extra_header_size);
83645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  header_ = reinterpret_cast<Header*>(data_);
84645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
85645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  DCHECK_LE(size_, std::numeric_limits<uint32_t>::max());
86645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  header_->num_bytes = static_cast<uint32_t>(size_);
87645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
88645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  DCHECK_LE(sizeof(Header) + extra_header_size,
89645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez            std::numeric_limits<uint16_t>::max());
90645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  header_->message_type = message_type;
91645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#if defined(MOJO_EDK_LEGACY_PROTOCOL)
92645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  header_->num_handles = static_cast<uint16_t>(max_handles);
93645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#else
94645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  header_->num_header_bytes =
95645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      static_cast<uint16_t>(sizeof(Header) + extra_header_size);
96645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#endif
97645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
98645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  if (max_handles_ > 0) {
99645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#if defined(OS_WIN)
100645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    handles_ = reinterpret_cast<HandleEntry*>(mutable_extra_header());
101645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    // Initialize all handles to invalid values.
102645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    for (size_t i = 0; i < max_handles_; ++i)
103645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      handles_[i].handle = base::win::HandleToUint32(INVALID_HANDLE_VALUE);
104645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#elif defined(OS_MACOSX) && !defined(OS_IOS)
105645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    mach_ports_header_ =
106645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        reinterpret_cast<MachPortsExtraHeader*>(mutable_extra_header());
107645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    mach_ports_header_->num_ports = 0;
108645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    // Initialize all handles to invalid values.
109645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    for (size_t i = 0; i < max_handles_; ++i) {
110645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      mach_ports_header_->entries[i] =
111645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez          {0, static_cast<uint32_t>(MACH_PORT_NULL)};
112645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    }
113645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#endif
114645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  }
115645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez}
116645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
117645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector ChavezChannel::Message::~Message() {
118645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  base::AlignedFree(data_);
119645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez}
120645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
121645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// static
122645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector ChavezChannel::MessagePtr Channel::Message::Deserialize(const void* data,
123645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez                                                  size_t data_num_bytes) {
124645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  if (data_num_bytes < sizeof(Header))
125645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    return nullptr;
126645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
127645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  const Header* header = reinterpret_cast<const Header*>(data);
128645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  if (header->num_bytes != data_num_bytes) {
129645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    DLOG(ERROR) << "Decoding invalid message: " << header->num_bytes
130645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez                << " != " << data_num_bytes;
131645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    return nullptr;
132645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  }
133645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
134645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#if defined(MOJO_EDK_LEGACY_PROTOCOL)
135645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  size_t payload_size = data_num_bytes - sizeof(Header);
136645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  const char* payload = static_cast<const char*>(data) + sizeof(Header);
137645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#else
138645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  if (header->num_bytes < header->num_header_bytes ||
139645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      header->num_header_bytes < sizeof(Header)) {
140645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    DLOG(ERROR) << "Decoding invalid message: " << header->num_bytes << " < "
141645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez                << header->num_header_bytes;
142645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    return nullptr;
143645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  }
144645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
145645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  uint32_t extra_header_size = header->num_header_bytes - sizeof(Header);
146645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  size_t payload_size = data_num_bytes - header->num_header_bytes;
147645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  const char* payload =
148645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      static_cast<const char*>(data) + header->num_header_bytes;
149645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#endif  // defined(MOJO_EDK_LEGACY_PROTOCOL)
150645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
151645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#if defined(OS_WIN)
152645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  uint32_t max_handles = extra_header_size / sizeof(HandleEntry);
153645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#elif defined(OS_MACOSX) && !defined(OS_IOS)
154645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  if (extra_header_size < sizeof(MachPortsExtraHeader)) {
155645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    DLOG(ERROR) << "Decoding invalid message: " << extra_header_size << " < "
156645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez                << sizeof(MachPortsExtraHeader);
157645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    return nullptr;
158645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  }
159645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  uint32_t max_handles = (extra_header_size - sizeof(MachPortsExtraHeader)) /
160645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      sizeof(MachPortsEntry);
161645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#else
162645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  const uint32_t max_handles = 0;
163645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#endif  // defined(OS_WIN)
164645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
165645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  if (header->num_handles > max_handles || max_handles > kMaxAttachedHandles) {
166645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    DLOG(ERROR) << "Decoding invalid message:" << header->num_handles
167645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez                << " > " << max_handles;
168645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    return nullptr;
169645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  }
170645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
171645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  MessagePtr message(new Message(payload_size, max_handles));
172645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  DCHECK_EQ(message->data_num_bytes(), data_num_bytes);
173645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
174645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  // Copy all payload bytes.
175645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  if (payload_size)
176645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    memcpy(message->mutable_payload(), payload, payload_size);
177645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
178645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#if !defined(MOJO_EDK_LEGACY_PROTOCOL)
179645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  DCHECK_EQ(message->extra_header_size(), extra_header_size);
180645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  DCHECK_EQ(message->header_->num_header_bytes, header->num_header_bytes);
181645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
182645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  if (message->extra_header_size()) {
183645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    // Copy extra header bytes.
184645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    memcpy(message->mutable_extra_header(),
185645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez           static_cast<const char*>(data) + sizeof(Header),
186645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez           message->extra_header_size());
187645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  }
188645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#endif
189645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
190645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  message->header_->num_handles = header->num_handles;
191645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#if defined(OS_WIN)
192645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  ScopedPlatformHandleVectorPtr handles(
193645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      new PlatformHandleVector(header->num_handles));
194645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  for (size_t i = 0; i < header->num_handles; i++) {
195645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    (*handles)[i].handle = reinterpret_cast<HANDLE>(
196645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        static_cast<uintptr_t>(message->handles_[i].handle));
197645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  }
198645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  message->SetHandles(std::move(handles));
199645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#endif
200645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
201645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  return message;
202645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez}
203645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
204645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezsize_t Channel::Message::payload_size() const {
205645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#if defined(MOJO_EDK_LEGACY_PROTOCOL)
206645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  return header_->num_bytes - sizeof(Header);
207645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#else
208645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  return size_ - header_->num_header_bytes;
209645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#endif
210645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez}
211645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
212645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#if defined(OS_MACOSX) && !defined(OS_IOS)
213645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezbool Channel::Message::has_mach_ports() const {
214645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  if (!has_handles())
215645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    return false;
216645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
217645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  for (const auto& handle : (*handle_vector_)) {
218645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    if (handle.type == PlatformHandle::Type::MACH ||
219645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        handle.type == PlatformHandle::Type::MACH_NAME) {
220645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      return true;
221645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    }
222645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  }
223645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  return false;
224645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez}
225645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#endif
226645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
227645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezvoid Channel::Message::SetHandles(ScopedPlatformHandleVectorPtr new_handles) {
228645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#if defined(MOJO_EDK_LEGACY_PROTOCOL)
229645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  // Old semantics for ChromeOS and Android
230645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  if (header_->num_handles == 0) {
231645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    CHECK(!new_handles || new_handles->size() == 0);
232645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    return;
233645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  }
234645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  CHECK(new_handles && new_handles->size() == header_->num_handles);
235645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  std::swap(handle_vector_, new_handles);
236645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
237645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#else
238645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  if (max_handles_ == 0) {
239645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    CHECK(!new_handles || new_handles->size() == 0);
240645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    return;
241645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  }
242645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
243645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  CHECK(new_handles && new_handles->size() <= max_handles_);
244645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  header_->num_handles = static_cast<uint16_t>(new_handles->size());
245645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  std::swap(handle_vector_, new_handles);
246645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#if defined(OS_WIN)
247645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  memset(handles_, 0, extra_header_size());
248645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  for (size_t i = 0; i < handle_vector_->size(); i++)
249645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    handles_[i].handle = base::win::HandleToUint32((*handle_vector_)[i].handle);
250645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#endif  // defined(OS_WIN)
251645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#endif  // defined(MOJO_EDK_LEGACY_PROTOCOL)
252645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
253645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#if defined(OS_MACOSX) && !defined(OS_IOS)
254645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  size_t mach_port_index = 0;
255645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  if (mach_ports_header_) {
256645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    for (size_t i = 0; i < max_handles_; ++i) {
257645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      mach_ports_header_->entries[i] =
258645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez          {0, static_cast<uint32_t>(MACH_PORT_NULL)};
259645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    }
260645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    for (size_t i = 0; i < handle_vector_->size(); i++) {
261645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      if ((*handle_vector_)[i].type == PlatformHandle::Type::MACH ||
262645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez          (*handle_vector_)[i].type == PlatformHandle::Type::MACH_NAME) {
263645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        mach_port_t port = (*handle_vector_)[i].port;
264645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        mach_ports_header_->entries[mach_port_index].index = i;
265645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        mach_ports_header_->entries[mach_port_index].mach_port = port;
266645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        mach_port_index++;
267645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      }
268645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    }
269645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    mach_ports_header_->num_ports = static_cast<uint16_t>(mach_port_index);
270645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  }
271645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#endif
272645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez}
273645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
274645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector ChavezScopedPlatformHandleVectorPtr Channel::Message::TakeHandles() {
275645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#if defined(OS_MACOSX) && !defined(OS_IOS)
276645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  if (mach_ports_header_) {
277645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    for (size_t i = 0; i < max_handles_; ++i) {
278645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      mach_ports_header_->entries[i] =
279645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez          {0, static_cast<uint32_t>(MACH_PORT_NULL)};
280645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    }
281645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    mach_ports_header_->num_ports = 0;
282645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  }
283645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  header_->num_handles = 0;
284645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  return std::move(handle_vector_);
285645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#else
286645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  header_->num_handles = 0;
287645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  return std::move(handle_vector_);
288645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#endif
289645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez}
290645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
291645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector ChavezScopedPlatformHandleVectorPtr Channel::Message::TakeHandlesForTransport() {
292645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#if defined(OS_WIN)
293645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  // Not necessary on Windows.
294645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  NOTREACHED();
295645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  return nullptr;
296645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#elif defined(OS_MACOSX) && !defined(OS_IOS)
297645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  if (handle_vector_) {
298645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    for (auto it = handle_vector_->begin(); it != handle_vector_->end(); ) {
299645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      if (it->type == PlatformHandle::Type::MACH ||
300645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez          it->type == PlatformHandle::Type::MACH_NAME) {
301645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        // For Mach port names, we can can just leak them. They're not real
302645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        // ports anyways. For real ports, they're leaked because this is a child
303645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        // process and the remote process will take ownership.
304645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        it = handle_vector_->erase(it);
305645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      } else {
306645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        ++it;
307645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      }
308645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    }
309645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  }
310645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  return std::move(handle_vector_);
311645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#else
312645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  return std::move(handle_vector_);
313645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#endif
314645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez}
315645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
316645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#if defined(OS_WIN)
317645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// static
318645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezbool Channel::Message::RewriteHandles(base::ProcessHandle from_process,
319645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez                                      base::ProcessHandle to_process,
320645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez                                      PlatformHandleVector* handles) {
321645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  bool success = true;
322645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  for (size_t i = 0; i < handles->size(); ++i) {
323645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    if (!(*handles)[i].is_valid()) {
324645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      DLOG(ERROR) << "Refusing to duplicate invalid handle.";
325645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      continue;
326645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    }
327645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    DCHECK_EQ((*handles)[i].owning_process, from_process);
328645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    BOOL result = DuplicateHandle(
329645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        from_process, (*handles)[i].handle, to_process,
330645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        &(*handles)[i].handle, 0, FALSE,
331645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE);
332645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    if (result) {
333645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      (*handles)[i].owning_process = to_process;
334645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    } else {
335645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      success = false;
336645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
337645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      // If handle duplication fails, the source handle will already be closed
338645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      // due to DUPLICATE_CLOSE_SOURCE. Replace the handle in the message with
339645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      // an invalid handle.
340645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      (*handles)[i].handle = INVALID_HANDLE_VALUE;
341645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      (*handles)[i].owning_process = base::GetCurrentProcessHandle();
342645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    }
343645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  }
344645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  return success;
345645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez}
346645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#endif
347645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
348645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// Helper class for managing a Channel's read buffer allocations. This maintains
349645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// a single contiguous buffer with the layout:
350645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez//
351645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez//   [discarded bytes][occupied bytes][unoccupied bytes]
352645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez//
353645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// The Reserve() method ensures that a certain capacity of unoccupied bytes are
354645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// available. It does not claim that capacity and only allocates new capacity
355645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// when strictly necessary.
356645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez//
357645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// Claim() marks unoccupied bytes as occupied.
358645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez//
359645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// Discard() marks occupied bytes as discarded, signifying that their contents
360645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// can be forgotten or overwritten.
361645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez//
362645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// Realign() moves occupied bytes to the front of the buffer so that those
363645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// occupied bytes are properly aligned.
364645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez//
365645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// The most common Channel behavior in practice should result in very few
366645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// allocations and copies, as memory is claimed and discarded shortly after
367645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// being reserved, and future reservations will immediately reuse discarded
368645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// memory.
369645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezclass Channel::ReadBuffer {
370645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez public:
371645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  ReadBuffer() {
372645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    size_ = kReadBufferSize;
373645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    data_ = static_cast<char*>(base::AlignedAlloc(size_,
374645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez                                                  kChannelMessageAlignment));
375645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  }
376645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
377645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  ~ReadBuffer() {
378645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    DCHECK(data_);
379645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    base::AlignedFree(data_);
380645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  }
381645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
382645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  const char* occupied_bytes() const { return data_ + num_discarded_bytes_; }
383645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
384645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  size_t num_occupied_bytes() const {
385645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    return num_occupied_bytes_ - num_discarded_bytes_;
386645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  }
387645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
388645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  // Ensures the ReadBuffer has enough contiguous space allocated to hold
389645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  // |num_bytes| more bytes; returns the address of the first available byte.
390645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  char* Reserve(size_t num_bytes) {
391645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    if (num_occupied_bytes_ + num_bytes > size_) {
392645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      size_ = std::max(size_ * 2, num_occupied_bytes_ + num_bytes);
393645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      void* new_data = base::AlignedAlloc(size_, kChannelMessageAlignment);
394645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      memcpy(new_data, data_, num_occupied_bytes_);
395645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      base::AlignedFree(data_);
396645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      data_ = static_cast<char*>(new_data);
397645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    }
398645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
399645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    return data_ + num_occupied_bytes_;
400645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  }
401645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
402645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  // Marks the first |num_bytes| unoccupied bytes as occupied.
403645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  void Claim(size_t num_bytes) {
404645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    DCHECK_LE(num_occupied_bytes_ + num_bytes, size_);
405645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    num_occupied_bytes_ += num_bytes;
406645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  }
407645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
408645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  // Marks the first |num_bytes| occupied bytes as discarded. This may result in
409645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  // shrinkage of the internal buffer, and it is not safe to assume the result
410645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  // of a previous Reserve() call is still valid after this.
411645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  void Discard(size_t num_bytes) {
412645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    DCHECK_LE(num_discarded_bytes_ + num_bytes, num_occupied_bytes_);
413645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    num_discarded_bytes_ += num_bytes;
414645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
415645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    if (num_discarded_bytes_ == num_occupied_bytes_) {
416645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      // We can just reuse the buffer from the beginning in this common case.
417645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      num_discarded_bytes_ = 0;
418645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      num_occupied_bytes_ = 0;
419645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    }
420645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
421645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    if (num_discarded_bytes_ > kMaxUnusedReadBufferCapacity) {
422645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      // In the uncommon case that we have a lot of discarded data at the
423645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      // front of the buffer, simply move remaining data to a smaller buffer.
424645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      size_t num_preserved_bytes = num_occupied_bytes_ - num_discarded_bytes_;
425645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      size_ = std::max(num_preserved_bytes, kReadBufferSize);
426645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      char* new_data = static_cast<char*>(
427645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez          base::AlignedAlloc(size_, kChannelMessageAlignment));
428645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      memcpy(new_data, data_ + num_discarded_bytes_, num_preserved_bytes);
429645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      base::AlignedFree(data_);
430645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      data_ = new_data;
431645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      num_discarded_bytes_ = 0;
432645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      num_occupied_bytes_ = num_preserved_bytes;
433645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    }
434645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
435645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    if (num_occupied_bytes_ == 0 && size_ > kMaxUnusedReadBufferCapacity) {
436645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      // Opportunistically shrink the read buffer back down to a small size if
437645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      // it's grown very large. We only do this if there are no remaining
438645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      // unconsumed bytes in the buffer to avoid copies in most the common
439645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      // cases.
440645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      size_ = kMaxUnusedReadBufferCapacity;
441645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      base::AlignedFree(data_);
442645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      data_ = static_cast<char*>(
443645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez          base::AlignedAlloc(size_, kChannelMessageAlignment));
444645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    }
445645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  }
446645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
447645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  void Realign() {
448645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    size_t num_bytes = num_occupied_bytes();
449645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    memmove(data_, occupied_bytes(), num_bytes);
450645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    num_discarded_bytes_ = 0;
451645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    num_occupied_bytes_ = num_bytes;
452645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  }
453645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
454645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez private:
455645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  char* data_ = nullptr;
456645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
457645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  // The total size of the allocated buffer.
458645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  size_t size_ = 0;
459645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
460645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  // The number of discarded bytes at the beginning of the allocated buffer.
461645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  size_t num_discarded_bytes_ = 0;
462645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
463645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  // The total number of occupied bytes, including discarded bytes.
464645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  size_t num_occupied_bytes_ = 0;
465645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
466645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  DISALLOW_COPY_AND_ASSIGN(ReadBuffer);
467645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez};
468645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
469645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector ChavezChannel::Channel(Delegate* delegate)
470645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    : delegate_(delegate), read_buffer_(new ReadBuffer) {
471645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez}
472645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
473645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector ChavezChannel::~Channel() {
474645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez}
475645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
476645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezvoid Channel::ShutDown() {
477645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  delegate_ = nullptr;
478645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  ShutDownImpl();
479645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez}
480645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
481645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezchar* Channel::GetReadBuffer(size_t *buffer_capacity) {
482645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  DCHECK(read_buffer_);
483645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  size_t required_capacity = *buffer_capacity;
484645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  if (!required_capacity)
485645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    required_capacity = kReadBufferSize;
486645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
487645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  *buffer_capacity = required_capacity;
488645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  return read_buffer_->Reserve(required_capacity);
489645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez}
490645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
491645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezbool Channel::OnReadComplete(size_t bytes_read, size_t *next_read_size_hint) {
492645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  bool did_dispatch_message = false;
493645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  read_buffer_->Claim(bytes_read);
494645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  while (read_buffer_->num_occupied_bytes() >= sizeof(Message::Header)) {
495645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    // Ensure the occupied data is properly aligned. If it isn't, a SIGBUS could
496645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    // happen on architectures that don't allow misaligned words access (i.e.
497645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    // anything other than x86). Only re-align when necessary to avoid copies.
498645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    if (reinterpret_cast<uintptr_t>(read_buffer_->occupied_bytes()) %
499645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        kChannelMessageAlignment != 0)
500645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      read_buffer_->Realign();
501645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
502645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    // We have at least enough data available for a MessageHeader.
503645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    const Message::Header* header = reinterpret_cast<const Message::Header*>(
504645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        read_buffer_->occupied_bytes());
505645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    if (header->num_bytes < sizeof(Message::Header) ||
506645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        header->num_bytes > kMaxChannelMessageSize) {
507645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      LOG(ERROR) << "Invalid message size: " << header->num_bytes;
508645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      return false;
509645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    }
510645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
511645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    if (read_buffer_->num_occupied_bytes() < header->num_bytes) {
512645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      // Not enough data available to read the full message. Hint to the
513645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      // implementation that it should try reading the full size of the message.
514645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      *next_read_size_hint =
515645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez          header->num_bytes - read_buffer_->num_occupied_bytes();
516645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      return true;
517645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    }
518645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
519645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#if defined(MOJO_EDK_LEGACY_PROTOCOL)
520645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    size_t extra_header_size = 0;
521645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    const void* extra_header = nullptr;
522645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    size_t payload_size = header->num_bytes - sizeof(Message::Header);
523645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    void* payload = payload_size ? const_cast<Message::Header*>(&header[1])
524645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez                                 : nullptr;
525645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#else
526645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    if (header->num_header_bytes < sizeof(Message::Header) ||
527645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        header->num_header_bytes > header->num_bytes) {
528645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      LOG(ERROR) << "Invalid message header size: " << header->num_header_bytes;
529645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      return false;
530645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    }
531645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    size_t extra_header_size =
532645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        header->num_header_bytes - sizeof(Message::Header);
533645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    const void* extra_header = extra_header_size ? header + 1 : nullptr;
534645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    size_t payload_size = header->num_bytes - header->num_header_bytes;
535645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    void* payload =
536645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        payload_size ? reinterpret_cast<Message::Header*>(
537645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez                           const_cast<char*>(read_buffer_->occupied_bytes()) +
538645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez                           header->num_header_bytes)
539645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez                     : nullptr;
540645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#endif  // defined(MOJO_EDK_LEGACY_PROTOCOL)
541645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
542645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    ScopedPlatformHandleVectorPtr handles;
543645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    if (header->num_handles > 0) {
544645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      if (!GetReadPlatformHandles(header->num_handles, extra_header,
545645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez                                 extra_header_size, &handles)) {
546645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        return false;
547645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      }
548645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
549645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      if (!handles) {
550645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        // Not enough handles available for this message.
551645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        break;
552645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      }
553645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    }
554645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
555645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    // We've got a complete message! Dispatch it and try another.
556645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    if (header->message_type != Message::Header::MessageType::NORMAL) {
557645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      if (!OnControlMessage(header->message_type, payload, payload_size,
558645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez                            std::move(handles))) {
559645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        return false;
560645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      }
561645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      did_dispatch_message = true;
562645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    } else if (delegate_) {
563645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      delegate_->OnChannelMessage(payload, payload_size, std::move(handles));
564645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez      did_dispatch_message = true;
565645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    }
566645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
567645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    read_buffer_->Discard(header->num_bytes);
568645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  }
569645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
570645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  *next_read_size_hint = did_dispatch_message ? 0 : kReadBufferSize;
571645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  return true;
572645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez}
573645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
574645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezvoid Channel::OnError() {
575645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  if (delegate_)
576645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    delegate_->OnChannelError();
577645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez}
578645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
579645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezbool Channel::OnControlMessage(Message::Header::MessageType message_type,
580645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez                               const void* payload,
581645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez                               size_t payload_size,
582645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez                               ScopedPlatformHandleVectorPtr handles) {
583645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez  return false;
584645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez}
585645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
586645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez}  // namespace edk
587645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez}  // namespace mojo
588