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