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 7cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli#include <stddef.h> 8645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#include <string.h> 9645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 10645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#include <algorithm> 11645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#include <limits> 12645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#include <utility> 13645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 14645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#include "base/macros.h" 15645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#include "base/memory/aligned_memory.h" 16645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#include "base/process/process_handle.h" 17645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#include "mojo/edk/embedder/platform_handle.h" 18645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 19645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#if defined(OS_MACOSX) && !defined(OS_IOS) 20645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#include "base/mac/mach_logging.h" 21645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#elif defined(OS_WIN) 22645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#include "base/win/win_util.h" 23645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#endif 24645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 25645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chaveznamespace mojo { 26645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chaveznamespace edk { 27645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 28645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chaveznamespace { 29645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 30cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civellistatic_assert( 31cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli IsAlignedForChannelMessage(sizeof(Channel::Message::LegacyHeader)), 32cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli "Invalid LegacyHeader size."); 33645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 34cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civellistatic_assert(IsAlignedForChannelMessage(sizeof(Channel::Message::Header)), 35cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli "Invalid Header size."); 36cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli 37cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civellistatic_assert(sizeof(Channel::Message::LegacyHeader) == 8, 38cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli "LegacyHeader must be 8 bytes on ChromeOS and Android"); 39cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli 40cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civellistatic_assert(offsetof(Channel::Message::LegacyHeader, num_bytes) == 41cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli offsetof(Channel::Message::Header, num_bytes), 42cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli "num_bytes should be at the same offset in both Header structs."); 43cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civellistatic_assert(offsetof(Channel::Message::LegacyHeader, message_type) == 44cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli offsetof(Channel::Message::Header, message_type), 45cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli "message_type should be at the same offset in both Header " 46cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli "structs."); 47645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 48645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} // namespace 49645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 50645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezconst size_t kReadBufferSize = 4096; 51cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelliconst size_t kMaxUnusedReadBufferCapacity = 4096; 52645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezconst size_t kMaxChannelMessageSize = 256 * 1024 * 1024; 53645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezconst size_t kMaxAttachedHandles = 128; 54645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 55cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay CivelliChannel::Message::Message(size_t payload_size, size_t max_handles) 56cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli#if defined(MOJO_EDK_LEGACY_PROTOCOL) 57cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli : Message(payload_size, max_handles, MessageType::NORMAL_LEGACY) { 58cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli} 59cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli#else 60cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli : Message(payload_size, max_handles, MessageType::NORMAL) { 61cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli} 62cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli#endif 63cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli 64645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector ChavezChannel::Message::Message(size_t payload_size, 65645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez size_t max_handles, 66cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli MessageType message_type) 67645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez : max_handles_(max_handles) { 68645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez DCHECK_LE(max_handles_, kMaxAttachedHandles); 69645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 70cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli const bool is_legacy_message = (message_type == MessageType::NORMAL_LEGACY); 71645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez size_t extra_header_size = 0; 72645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#if defined(OS_WIN) 73645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // On Windows we serialize HANDLEs into the extra header space. 74645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez extra_header_size = max_handles_ * sizeof(HandleEntry); 75645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#elif defined(OS_MACOSX) && !defined(OS_IOS) 76645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // On OSX, some of the platform handles may be mach ports, which are 77645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // serialised into the message buffer. Since there could be a mix of fds and 78645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // mach ports, we store the mach ports as an <index, port> pair (of uint32_t), 79645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // so that the original ordering of handles can be re-created. 80645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (max_handles) { 81645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez extra_header_size = 82645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez sizeof(MachPortsExtraHeader) + (max_handles * sizeof(MachPortsEntry)); 83645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 84645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#endif 85645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // Pad extra header data to be aliged to |kChannelMessageAlignment| bytes. 86cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli if (!IsAlignedForChannelMessage(extra_header_size)) { 87645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez extra_header_size += kChannelMessageAlignment - 88645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez (extra_header_size % kChannelMessageAlignment); 89645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 90cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli DCHECK(IsAlignedForChannelMessage(extra_header_size)); 91cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli const size_t header_size = 92cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli is_legacy_message ? sizeof(LegacyHeader) : sizeof(Header); 93cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli DCHECK(extra_header_size == 0 || !is_legacy_message); 94645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 95cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli size_ = header_size + extra_header_size + payload_size; 96645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez data_ = static_cast<char*>(base::AlignedAlloc(size_, 97645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez kChannelMessageAlignment)); 98645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // Only zero out the header and not the payload. Since the payload is going to 99645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // be memcpy'd, zeroing the payload is unnecessary work and a significant 100645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // performance issue when dealing with large messages. Any sanitizer errors 101645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // complaining about an uninitialized read in the payload area should be 102645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // treated as an error and fixed. 103cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli memset(data_, 0, header_size + extra_header_size); 104645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 105645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez DCHECK_LE(size_, std::numeric_limits<uint32_t>::max()); 106cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli legacy_header()->num_bytes = static_cast<uint32_t>(size_); 107645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 108cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli DCHECK_LE(header_size + extra_header_size, 109645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez std::numeric_limits<uint16_t>::max()); 110cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli legacy_header()->message_type = message_type; 111cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli 112cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli if (is_legacy_message) { 113cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli legacy_header()->num_handles = static_cast<uint16_t>(max_handles); 114cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli } else { 115cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli header()->num_header_bytes = 116cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli static_cast<uint16_t>(header_size + extra_header_size); 117cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli } 118645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 119645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (max_handles_ > 0) { 120645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#if defined(OS_WIN) 121645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez handles_ = reinterpret_cast<HandleEntry*>(mutable_extra_header()); 122645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // Initialize all handles to invalid values. 123645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez for (size_t i = 0; i < max_handles_; ++i) 124645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez handles_[i].handle = base::win::HandleToUint32(INVALID_HANDLE_VALUE); 125645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#elif defined(OS_MACOSX) && !defined(OS_IOS) 126645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez mach_ports_header_ = 127645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez reinterpret_cast<MachPortsExtraHeader*>(mutable_extra_header()); 128645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez mach_ports_header_->num_ports = 0; 129645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // Initialize all handles to invalid values. 130645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez for (size_t i = 0; i < max_handles_; ++i) { 131645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez mach_ports_header_->entries[i] = 132645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez {0, static_cast<uint32_t>(MACH_PORT_NULL)}; 133645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 134645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#endif 135645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 136645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} 137645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 138645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector ChavezChannel::Message::~Message() { 139645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez base::AlignedFree(data_); 140645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} 141645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 142645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// static 143645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector ChavezChannel::MessagePtr Channel::Message::Deserialize(const void* data, 144645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez size_t data_num_bytes) { 145cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli if (data_num_bytes < sizeof(LegacyHeader)) 146645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return nullptr; 147645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 148cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli const LegacyHeader* legacy_header = 149cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli reinterpret_cast<const LegacyHeader*>(data); 150cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli if (legacy_header->num_bytes != data_num_bytes) { 151cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli DLOG(ERROR) << "Decoding invalid message: " << legacy_header->num_bytes 152645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez << " != " << data_num_bytes; 153645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return nullptr; 154645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 155645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 156cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli const Header* header = nullptr; 157cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli if (legacy_header->message_type == MessageType::NORMAL) 158cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli header = reinterpret_cast<const Header*>(data); 159cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli 160cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli uint32_t extra_header_size = 0; 161cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli size_t payload_size = 0; 162cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli const char* payload = nullptr; 163cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli if (!header) { 164cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli payload_size = data_num_bytes - sizeof(LegacyHeader); 165cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli payload = static_cast<const char*>(data) + sizeof(LegacyHeader); 166cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli } else { 167cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli if (header->num_bytes < header->num_header_bytes || 168cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli header->num_header_bytes < sizeof(Header)) { 169cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli DLOG(ERROR) << "Decoding invalid message: " << header->num_bytes << " < " 170cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli << header->num_header_bytes; 171cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli return nullptr; 172cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli } 173cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli extra_header_size = header->num_header_bytes - sizeof(Header); 174cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli payload_size = data_num_bytes - header->num_header_bytes; 175cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli payload = static_cast<const char*>(data) + header->num_header_bytes; 176645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 177645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 178645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#if defined(OS_WIN) 179645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez uint32_t max_handles = extra_header_size / sizeof(HandleEntry); 180645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#elif defined(OS_MACOSX) && !defined(OS_IOS) 181cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli if (extra_header_size > 0 && 182cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli extra_header_size < sizeof(MachPortsExtraHeader)) { 183645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez DLOG(ERROR) << "Decoding invalid message: " << extra_header_size << " < " 184645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez << sizeof(MachPortsExtraHeader); 185645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return nullptr; 186645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 187cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli uint32_t max_handles = 188cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli extra_header_size == 0 189cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli ? 0 190cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli : (extra_header_size - sizeof(MachPortsExtraHeader)) / 191cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli sizeof(MachPortsEntry); 192645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#else 193645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez const uint32_t max_handles = 0; 194645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#endif // defined(OS_WIN) 195645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 196cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli const uint16_t num_handles = 197cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli header ? header->num_handles : legacy_header->num_handles; 198cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli if (num_handles > max_handles || max_handles > kMaxAttachedHandles) { 199cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli DLOG(ERROR) << "Decoding invalid message: " << num_handles << " > " 200cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli << max_handles; 201645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return nullptr; 202645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 203645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 204cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli MessagePtr message( 205cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli new Message(payload_size, max_handles, legacy_header->message_type)); 206645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez DCHECK_EQ(message->data_num_bytes(), data_num_bytes); 207645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 208645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // Copy all payload bytes. 209645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (payload_size) 210645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez memcpy(message->mutable_payload(), payload, payload_size); 211645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 212cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli if (header) { 213cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli DCHECK_EQ(message->extra_header_size(), extra_header_size); 214cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli DCHECK_EQ(message->header()->num_header_bytes, header->num_header_bytes); 215645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 216cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli if (message->extra_header_size()) { 217cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli // Copy extra header bytes. 218cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli memcpy(message->mutable_extra_header(), 219cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli static_cast<const char*>(data) + sizeof(Header), 220cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli message->extra_header_size()); 221cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli } 222cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli message->header()->num_handles = header->num_handles; 223cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli } else { 224cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli message->legacy_header()->num_handles = legacy_header->num_handles; 225645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 226645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 227645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#if defined(OS_WIN) 228cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli ScopedPlatformHandleVectorPtr handles(new PlatformHandleVector(num_handles)); 229cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli for (size_t i = 0; i < num_handles; i++) { 230cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli (*handles)[i].handle = 231cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli base::win::Uint32ToHandle(message->handles_[i].handle); 232645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 233645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez message->SetHandles(std::move(handles)); 234645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#endif 235645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 236645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return message; 237645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} 238645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 239cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelliconst void* Channel::Message::extra_header() const { 240cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli DCHECK(!is_legacy_message()); 241cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli return data_ + sizeof(Header); 242cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli} 243cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli 244cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civellivoid* Channel::Message::mutable_extra_header() { 245cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli DCHECK(!is_legacy_message()); 246cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli return data_ + sizeof(Header); 247cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli} 248cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli 249cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civellisize_t Channel::Message::extra_header_size() const { 250cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli return header()->num_header_bytes - sizeof(Header); 251cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli} 252cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli 253cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civellivoid* Channel::Message::mutable_payload() { 254cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli if (is_legacy_message()) 255cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli return static_cast<void*>(legacy_header() + 1); 256cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli return data_ + header()->num_header_bytes; 257cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli} 258cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli 259cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelliconst void* Channel::Message::payload() const { 260cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli if (is_legacy_message()) 261cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli return static_cast<const void*>(legacy_header() + 1); 262cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli return data_ + header()->num_header_bytes; 263cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli} 264cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli 265645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezsize_t Channel::Message::payload_size() const { 266cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli if (is_legacy_message()) 267cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli return legacy_header()->num_bytes - sizeof(LegacyHeader); 268cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli return size_ - header()->num_header_bytes; 269cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli} 270cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli 271cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civellisize_t Channel::Message::num_handles() const { 272cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli return is_legacy_message() ? legacy_header()->num_handles 273cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli : header()->num_handles; 274cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli} 275cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli 276cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civellibool Channel::Message::has_handles() const { 277cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli return (is_legacy_message() ? legacy_header()->num_handles 278cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli : header()->num_handles) > 0; 279645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} 280645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 281645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#if defined(OS_MACOSX) && !defined(OS_IOS) 282645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezbool Channel::Message::has_mach_ports() const { 283645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (!has_handles()) 284645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return false; 285645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 286645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez for (const auto& handle : (*handle_vector_)) { 287645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (handle.type == PlatformHandle::Type::MACH || 288645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez handle.type == PlatformHandle::Type::MACH_NAME) { 289645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return true; 290645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 291645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 292645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return false; 293645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} 294645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#endif 295645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 296cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civellibool Channel::Message::is_legacy_message() const { 297cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli return legacy_header()->message_type == MessageType::NORMAL_LEGACY; 298cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli} 299cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli 300cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay CivelliChannel::Message::LegacyHeader* Channel::Message::legacy_header() const { 301cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli return reinterpret_cast<LegacyHeader*>(data_); 302cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli} 303cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli 304cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay CivelliChannel::Message::Header* Channel::Message::header() const { 305cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli DCHECK(!is_legacy_message()); 306cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli return reinterpret_cast<Header*>(data_); 307cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli} 308cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli 309645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezvoid Channel::Message::SetHandles(ScopedPlatformHandleVectorPtr new_handles) { 310cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli if (is_legacy_message()) { 311cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli // Old semantics for ChromeOS and Android 312cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli if (legacy_header()->num_handles == 0) { 313cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli CHECK(!new_handles || new_handles->size() == 0); 314cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli return; 315cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli } 316cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli CHECK(new_handles && new_handles->size() == legacy_header()->num_handles); 317cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli std::swap(handle_vector_, new_handles); 318645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return; 319645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 320645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 321645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (max_handles_ == 0) { 322645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez CHECK(!new_handles || new_handles->size() == 0); 323645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return; 324645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 325645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 326645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez CHECK(new_handles && new_handles->size() <= max_handles_); 327cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli header()->num_handles = static_cast<uint16_t>(new_handles->size()); 328645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez std::swap(handle_vector_, new_handles); 329645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#if defined(OS_WIN) 330645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez memset(handles_, 0, extra_header_size()); 331645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez for (size_t i = 0; i < handle_vector_->size(); i++) 332645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez handles_[i].handle = base::win::HandleToUint32((*handle_vector_)[i].handle); 333645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#endif // defined(OS_WIN) 334645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 335645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#if defined(OS_MACOSX) && !defined(OS_IOS) 336645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez size_t mach_port_index = 0; 337645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (mach_ports_header_) { 338645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez for (size_t i = 0; i < max_handles_; ++i) { 339645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez mach_ports_header_->entries[i] = 340645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez {0, static_cast<uint32_t>(MACH_PORT_NULL)}; 341645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 342645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez for (size_t i = 0; i < handle_vector_->size(); i++) { 343645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if ((*handle_vector_)[i].type == PlatformHandle::Type::MACH || 344645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez (*handle_vector_)[i].type == PlatformHandle::Type::MACH_NAME) { 345645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez mach_port_t port = (*handle_vector_)[i].port; 346645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez mach_ports_header_->entries[mach_port_index].index = i; 347645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez mach_ports_header_->entries[mach_port_index].mach_port = port; 348645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez mach_port_index++; 349645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 350645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 351645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez mach_ports_header_->num_ports = static_cast<uint16_t>(mach_port_index); 352645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 353645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#endif 354645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} 355645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 356645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector ChavezScopedPlatformHandleVectorPtr Channel::Message::TakeHandles() { 357645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#if defined(OS_MACOSX) && !defined(OS_IOS) 358645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (mach_ports_header_) { 359645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez for (size_t i = 0; i < max_handles_; ++i) { 360645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez mach_ports_header_->entries[i] = 361645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez {0, static_cast<uint32_t>(MACH_PORT_NULL)}; 362645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 363645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez mach_ports_header_->num_ports = 0; 364645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 36521a249e4d9cb0b2ec6f0ff84ed5f7939ea67ac52Luis Hector Chavez#endif 366cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli if (is_legacy_message()) 367cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli legacy_header()->num_handles = 0; 368cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli else 369cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli header()->num_handles = 0; 370cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli return std::move(handle_vector_); 371645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} 372645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 373645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector ChavezScopedPlatformHandleVectorPtr Channel::Message::TakeHandlesForTransport() { 374645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#if defined(OS_WIN) 375645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // Not necessary on Windows. 376645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez NOTREACHED(); 377645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return nullptr; 378645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#elif defined(OS_MACOSX) && !defined(OS_IOS) 379645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (handle_vector_) { 380645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez for (auto it = handle_vector_->begin(); it != handle_vector_->end(); ) { 381645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (it->type == PlatformHandle::Type::MACH || 382645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez it->type == PlatformHandle::Type::MACH_NAME) { 383645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // For Mach port names, we can can just leak them. They're not real 384645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // ports anyways. For real ports, they're leaked because this is a child 385645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // process and the remote process will take ownership. 386645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez it = handle_vector_->erase(it); 387645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } else { 388645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez ++it; 389645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 390645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 391645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 392645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return std::move(handle_vector_); 393645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#else 394645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return std::move(handle_vector_); 395645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#endif 396645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} 397645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 398645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#if defined(OS_WIN) 399645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// static 400645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezbool Channel::Message::RewriteHandles(base::ProcessHandle from_process, 401645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez base::ProcessHandle to_process, 402645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez PlatformHandleVector* handles) { 403645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez bool success = true; 404645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez for (size_t i = 0; i < handles->size(); ++i) { 405645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (!(*handles)[i].is_valid()) { 406645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez DLOG(ERROR) << "Refusing to duplicate invalid handle."; 407645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez continue; 408645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 409645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez DCHECK_EQ((*handles)[i].owning_process, from_process); 410645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez BOOL result = DuplicateHandle( 411645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez from_process, (*handles)[i].handle, to_process, 412645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez &(*handles)[i].handle, 0, FALSE, 413645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE); 414645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (result) { 415645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez (*handles)[i].owning_process = to_process; 416645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } else { 417645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez success = false; 418645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 419645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // If handle duplication fails, the source handle will already be closed 420645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // due to DUPLICATE_CLOSE_SOURCE. Replace the handle in the message with 421645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // an invalid handle. 422645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez (*handles)[i].handle = INVALID_HANDLE_VALUE; 423645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez (*handles)[i].owning_process = base::GetCurrentProcessHandle(); 424645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 425645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 426645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return success; 427645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} 428645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#endif 429645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 430645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// Helper class for managing a Channel's read buffer allocations. This maintains 431645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// a single contiguous buffer with the layout: 432645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// 433645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// [discarded bytes][occupied bytes][unoccupied bytes] 434645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// 435645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// The Reserve() method ensures that a certain capacity of unoccupied bytes are 436645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// available. It does not claim that capacity and only allocates new capacity 437645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// when strictly necessary. 438645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// 439645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// Claim() marks unoccupied bytes as occupied. 440645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// 441645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// Discard() marks occupied bytes as discarded, signifying that their contents 442645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// can be forgotten or overwritten. 443645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// 444645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// Realign() moves occupied bytes to the front of the buffer so that those 445645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// occupied bytes are properly aligned. 446645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// 447645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// The most common Channel behavior in practice should result in very few 448645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// allocations and copies, as memory is claimed and discarded shortly after 449645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// being reserved, and future reservations will immediately reuse discarded 450645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez// memory. 451645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezclass Channel::ReadBuffer { 452645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez public: 453645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez ReadBuffer() { 454645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez size_ = kReadBufferSize; 455645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez data_ = static_cast<char*>(base::AlignedAlloc(size_, 456645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez kChannelMessageAlignment)); 457645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 458645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 459645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez ~ReadBuffer() { 460645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez DCHECK(data_); 461645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez base::AlignedFree(data_); 462645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 463645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 464645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez const char* occupied_bytes() const { return data_ + num_discarded_bytes_; } 465645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 466645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez size_t num_occupied_bytes() const { 467645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return num_occupied_bytes_ - num_discarded_bytes_; 468645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 469645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 470645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // Ensures the ReadBuffer has enough contiguous space allocated to hold 471645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // |num_bytes| more bytes; returns the address of the first available byte. 472645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez char* Reserve(size_t num_bytes) { 473645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (num_occupied_bytes_ + num_bytes > size_) { 474645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez size_ = std::max(size_ * 2, num_occupied_bytes_ + num_bytes); 475645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez void* new_data = base::AlignedAlloc(size_, kChannelMessageAlignment); 476645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez memcpy(new_data, data_, num_occupied_bytes_); 477645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez base::AlignedFree(data_); 478645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez data_ = static_cast<char*>(new_data); 479645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 480645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 481645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return data_ + num_occupied_bytes_; 482645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 483645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 484645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // Marks the first |num_bytes| unoccupied bytes as occupied. 485645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez void Claim(size_t num_bytes) { 486645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez DCHECK_LE(num_occupied_bytes_ + num_bytes, size_); 487645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez num_occupied_bytes_ += num_bytes; 488645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 489645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 490645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // Marks the first |num_bytes| occupied bytes as discarded. This may result in 491645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // shrinkage of the internal buffer, and it is not safe to assume the result 492645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // of a previous Reserve() call is still valid after this. 493645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez void Discard(size_t num_bytes) { 494645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez DCHECK_LE(num_discarded_bytes_ + num_bytes, num_occupied_bytes_); 495645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez num_discarded_bytes_ += num_bytes; 496645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 497645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (num_discarded_bytes_ == num_occupied_bytes_) { 498645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // We can just reuse the buffer from the beginning in this common case. 499645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez num_discarded_bytes_ = 0; 500645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez num_occupied_bytes_ = 0; 501645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 502645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 503645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (num_discarded_bytes_ > kMaxUnusedReadBufferCapacity) { 504645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // In the uncommon case that we have a lot of discarded data at the 505645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // front of the buffer, simply move remaining data to a smaller buffer. 506645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez size_t num_preserved_bytes = num_occupied_bytes_ - num_discarded_bytes_; 507645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez size_ = std::max(num_preserved_bytes, kReadBufferSize); 508645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez char* new_data = static_cast<char*>( 509645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez base::AlignedAlloc(size_, kChannelMessageAlignment)); 510645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez memcpy(new_data, data_ + num_discarded_bytes_, num_preserved_bytes); 511645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez base::AlignedFree(data_); 512645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez data_ = new_data; 513645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez num_discarded_bytes_ = 0; 514645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez num_occupied_bytes_ = num_preserved_bytes; 515645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 516645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 517645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (num_occupied_bytes_ == 0 && size_ > kMaxUnusedReadBufferCapacity) { 518645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // Opportunistically shrink the read buffer back down to a small size if 519645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // it's grown very large. We only do this if there are no remaining 520645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // unconsumed bytes in the buffer to avoid copies in most the common 521645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // cases. 522645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez size_ = kMaxUnusedReadBufferCapacity; 523645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez base::AlignedFree(data_); 524645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez data_ = static_cast<char*>( 525645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez base::AlignedAlloc(size_, kChannelMessageAlignment)); 526645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 527645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 528645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 529645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez void Realign() { 530645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez size_t num_bytes = num_occupied_bytes(); 531645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez memmove(data_, occupied_bytes(), num_bytes); 532645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez num_discarded_bytes_ = 0; 533645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez num_occupied_bytes_ = num_bytes; 534645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 535645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 536645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez private: 537645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez char* data_ = nullptr; 538645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 539645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // The total size of the allocated buffer. 540645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez size_t size_ = 0; 541645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 542645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // The number of discarded bytes at the beginning of the allocated buffer. 543645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez size_t num_discarded_bytes_ = 0; 544645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 545645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // The total number of occupied bytes, including discarded bytes. 546645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez size_t num_occupied_bytes_ = 0; 547645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 548645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez DISALLOW_COPY_AND_ASSIGN(ReadBuffer); 549645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez}; 550645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 551645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector ChavezChannel::Channel(Delegate* delegate) 552645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez : delegate_(delegate), read_buffer_(new ReadBuffer) { 553645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} 554645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 555645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector ChavezChannel::~Channel() { 556645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} 557645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 558645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezvoid Channel::ShutDown() { 559645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez delegate_ = nullptr; 560645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez ShutDownImpl(); 561645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} 562645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 563645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezchar* Channel::GetReadBuffer(size_t *buffer_capacity) { 564645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez DCHECK(read_buffer_); 565645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez size_t required_capacity = *buffer_capacity; 566645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (!required_capacity) 567645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez required_capacity = kReadBufferSize; 568645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 569645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez *buffer_capacity = required_capacity; 570645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return read_buffer_->Reserve(required_capacity); 571645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} 572645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 573645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezbool Channel::OnReadComplete(size_t bytes_read, size_t *next_read_size_hint) { 574645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez bool did_dispatch_message = false; 575645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez read_buffer_->Claim(bytes_read); 576cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli while (read_buffer_->num_occupied_bytes() >= sizeof(Message::LegacyHeader)) { 577645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // Ensure the occupied data is properly aligned. If it isn't, a SIGBUS could 578645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // happen on architectures that don't allow misaligned words access (i.e. 579645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // anything other than x86). Only re-align when necessary to avoid copies. 580cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli if (!IsAlignedForChannelMessage( 581cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli reinterpret_cast<uintptr_t>(read_buffer_->occupied_bytes()))) { 582645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez read_buffer_->Realign(); 583cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli } 584cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli 585cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli // We have at least enough data available for a LegacyHeader. 586cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli const Message::LegacyHeader* legacy_header = 587cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli reinterpret_cast<const Message::LegacyHeader*>( 588cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli read_buffer_->occupied_bytes()); 589645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 590cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli if (legacy_header->num_bytes < sizeof(Message::LegacyHeader) || 591cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli legacy_header->num_bytes > kMaxChannelMessageSize) { 592cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli LOG(ERROR) << "Invalid message size: " << legacy_header->num_bytes; 593645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return false; 594645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 595645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 596cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli if (read_buffer_->num_occupied_bytes() < legacy_header->num_bytes) { 597645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // Not enough data available to read the full message. Hint to the 598645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // implementation that it should try reading the full size of the message. 599645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez *next_read_size_hint = 600cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli legacy_header->num_bytes - read_buffer_->num_occupied_bytes(); 601645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return true; 602645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 603645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 604cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli const Message::Header* header = nullptr; 605cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli if (legacy_header->message_type != Message::MessageType::NORMAL_LEGACY) { 606cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli header = reinterpret_cast<const Message::Header*>(legacy_header); 607cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli } 608cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli 609645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez size_t extra_header_size = 0; 610645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez const void* extra_header = nullptr; 611cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli size_t payload_size = 0; 612cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli void* payload = nullptr; 613cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli if (header) { 614cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli if (header->num_header_bytes < sizeof(Message::Header) || 615cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli header->num_header_bytes > header->num_bytes) { 616cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli LOG(ERROR) << "Invalid message header size: " 617cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli << header->num_header_bytes; 618cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli return false; 619cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli } 620cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli extra_header_size = header->num_header_bytes - sizeof(Message::Header); 621cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli extra_header = extra_header_size ? header + 1 : nullptr; 622cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli payload_size = header->num_bytes - header->num_header_bytes; 623cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli payload = payload_size 624cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli ? reinterpret_cast<Message::Header*>( 625cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli const_cast<char*>(read_buffer_->occupied_bytes()) + 626cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli header->num_header_bytes) 627cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli : nullptr; 628cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli } else { 629cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli payload_size = legacy_header->num_bytes - sizeof(Message::LegacyHeader); 630cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli payload = payload_size 631cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli ? const_cast<Message::LegacyHeader*>(&legacy_header[1]) 632cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli : nullptr; 633645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 634645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 635cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli const uint16_t num_handles = 636cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli header ? header->num_handles : legacy_header->num_handles; 637645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez ScopedPlatformHandleVectorPtr handles; 638cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli if (num_handles > 0) { 639cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli if (!GetReadPlatformHandles(num_handles, extra_header, extra_header_size, 640cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli &handles)) { 641645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return false; 642645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 643645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 644645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (!handles) { 645645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // Not enough handles available for this message. 646645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez break; 647645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 648645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 649645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 650645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez // We've got a complete message! Dispatch it and try another. 651cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli if (legacy_header->message_type != Message::MessageType::NORMAL_LEGACY && 652cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli legacy_header->message_type != Message::MessageType::NORMAL) { 653cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli if (!OnControlMessage(legacy_header->message_type, payload, payload_size, 654645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez std::move(handles))) { 655645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return false; 656645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 657645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez did_dispatch_message = true; 658645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } else if (delegate_) { 659645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez delegate_->OnChannelMessage(payload, payload_size, std::move(handles)); 660645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez did_dispatch_message = true; 661645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 662645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 663cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civelli read_buffer_->Discard(legacy_header->num_bytes); 664645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 665645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 666645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez *next_read_size_hint = did_dispatch_message ? 0 : kReadBufferSize; 667645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return true; 668645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} 669645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 670645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezvoid Channel::OnError() { 671645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if (delegate_) 672645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez delegate_->OnChannelError(); 673645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} 674645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 675cfc1eaa913db3974e56c87b5489bda0a2bf36d93Jay Civellibool Channel::OnControlMessage(Message::MessageType message_type, 676645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez const void* payload, 677645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez size_t payload_size, 678645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez ScopedPlatformHandleVectorPtr handles) { 679645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return false; 680645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} 681645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 682645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} // namespace edk 683645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez} // namespace mojo 684