message_in_transit.cc revision 010d83a9304c5a91596085d917d248abff47903a
14e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved. 24e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 34e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// found in the LICENSE file. 44e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 54e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "mojo/system/message_in_transit.h" 64e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 74e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include <string.h> 84e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 9f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "base/compiler_specific.h" 104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "base/logging.h" 115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "mojo/system/constants.h" 12010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "mojo/system/transport_data.h" 134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)namespace mojo { 154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)namespace system { 164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 175c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuSTATIC_CONST_MEMBER_DEFINITION const MessageInTransit::Type 185c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu MessageInTransit::kTypeMessagePipeEndpoint; 195c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuSTATIC_CONST_MEMBER_DEFINITION const MessageInTransit::Type 205c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu MessageInTransit::kTypeMessagePipe; 215c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuSTATIC_CONST_MEMBER_DEFINITION const MessageInTransit::Type 225c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu MessageInTransit::kTypeChannel; 235c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuSTATIC_CONST_MEMBER_DEFINITION const MessageInTransit::Subtype 245c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu MessageInTransit::kSubtypeMessagePipeEndpointData; 255c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuSTATIC_CONST_MEMBER_DEFINITION const MessageInTransit::Subtype 265c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu MessageInTransit::kSubtypeChannelRunMessagePipeEndpoint; 275c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuSTATIC_CONST_MEMBER_DEFINITION const MessageInTransit::Subtype 285c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu MessageInTransit::kSubtypeChannelRemoveMessagePipeEndpoint; 295c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuSTATIC_CONST_MEMBER_DEFINITION const MessageInTransit::Subtype 305c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu MessageInTransit::kSubtypeChannelRemoveMessagePipeEndpointAck; 315c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuSTATIC_CONST_MEMBER_DEFINITION const MessageInTransit::EndpointId 325c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu MessageInTransit::kInvalidEndpointId; 335c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuSTATIC_CONST_MEMBER_DEFINITION const size_t MessageInTransit::kMessageAlignment; 345c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 35a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)struct MessageInTransit::PrivateStructForCompileAsserts { 36c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch // The size of |Header| must be a multiple of the alignment. 37a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) COMPILE_ASSERT(sizeof(Header) % kMessageAlignment == 0, 38a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) sizeof_MessageInTransit_Header_invalid); 39a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Avoid dangerous situations, but making sure that the size of the "header" + 40a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // the size of the data fits into a 31-bit number. 41a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) COMPILE_ASSERT(static_cast<uint64_t>(sizeof(Header)) + kMaxMessageNumBytes <= 42a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 0x7fffffffULL, 43a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) kMaxMessageNumBytes_too_big); 444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 45effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // We assume (to avoid extra rounding code) that the maximum message (data) 46effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // size is a multiple of the alignment. 47effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch COMPILE_ASSERT(kMaxMessageNumBytes % kMessageAlignment == 0, 48effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch kMessageAlignment_not_a_multiple_of_alignment); 49a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}; 504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 51a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)MessageInTransit::View::View(size_t message_size, const void* buffer) 52a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) : buffer_(buffer) { 53a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) size_t next_message_size = 0; 54a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DCHECK(MessageInTransit::GetNextMessageSize(buffer_, message_size, 55a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) &next_message_size)); 56a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DCHECK_EQ(message_size, next_message_size); 57a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // This should be equivalent. 58a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DCHECK_EQ(message_size, total_size()); 59a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 60a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 61effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochbool MessageInTransit::View::IsValid(const char** error_message) const { 62effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // Note: This also implies a check on the |main_buffer_size()|, which is just 63effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // |RoundUpMessageAlignment(sizeof(Header) + num_bytes())|. 64effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (num_bytes() > kMaxMessageNumBytes) { 65effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch *error_message = "Message data payload too large"; 66effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch return false; 67effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 68effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 69010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (transport_data_buffer_size() > 0) { 70010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) const char* e = TransportData::ValidateBuffer(transport_data_buffer(), 71010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) transport_data_buffer_size()); 72010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (e) { 73010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) *error_message = e; 74010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) return false; 75010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) } 76effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 77effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 78effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch return true; 79effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch} 80effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 81a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)MessageInTransit::MessageInTransit(Type type, 82a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) Subtype subtype, 83a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) uint32_t num_bytes, 84a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const void* bytes) 85a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) : main_buffer_size_(RoundUpMessageAlignment(sizeof(Header) + num_bytes)), 86010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) main_buffer_(static_cast<char*>(base::AlignedAlloc(main_buffer_size_, 87010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) kMessageAlignment))) { 885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK_LE(num_bytes, kMaxMessageNumBytes); 895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 90a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // |total_size| is updated below, from the other values. 91a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) header()->type = type; 92a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) header()->subtype = subtype; 93a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) header()->source_id = kInvalidEndpointId; 94a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) header()->destination_id = kInvalidEndpointId; 95a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) header()->num_bytes = num_bytes; 96010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) header()->unused = 0; 97010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // Note: If dispatchers are subsequently attached, then |total_size| will have 98010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // to be adjusted. 99a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) UpdateTotalSize(); 100a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 101a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (bytes) { 102a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) memcpy(MessageInTransit::bytes(), bytes, num_bytes); 103a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) memset(static_cast<char*>(MessageInTransit::bytes()) + num_bytes, 0, 104a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) main_buffer_size_ - sizeof(Header) - num_bytes); 105a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } else { 106a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) memset(MessageInTransit::bytes(), 0, main_buffer_size_ - sizeof(Header)); 107a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 1084e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 1094e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 110a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)MessageInTransit::MessageInTransit(const View& message_view) 111a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) : main_buffer_size_(message_view.main_buffer_size()), 112010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) main_buffer_(static_cast<char*>(base::AlignedAlloc(main_buffer_size_, 113010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) kMessageAlignment))) { 114a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DCHECK_GE(main_buffer_size_, sizeof(Header)); 115a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DCHECK_EQ(main_buffer_size_ % kMessageAlignment, 0u); 116a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 117010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) memcpy(main_buffer_.get(), message_view.main_buffer(), main_buffer_size_); 118a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DCHECK_EQ(main_buffer_size_, 119a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) RoundUpMessageAlignment(sizeof(Header) + num_bytes())); 1205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 1215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 122a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)MessageInTransit::~MessageInTransit() { 123c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch if (dispatchers_) { 124a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) for (size_t i = 0; i < dispatchers_->size(); i++) { 125a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (!(*dispatchers_)[i]) 126a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) continue; 127a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 128a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DCHECK((*dispatchers_)[i]->HasOneRef()); 129a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) (*dispatchers_)[i]->Close(); 130a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 131a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 132a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 133a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 134a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// static 135a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)bool MessageInTransit::GetNextMessageSize(const void* buffer, 136a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) size_t buffer_size, 137a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) size_t* next_message_size) { 138a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DCHECK(next_message_size); 139a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (!buffer_size) 140a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return false; 141a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DCHECK(buffer); 142a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DCHECK_EQ(reinterpret_cast<uintptr_t>(buffer) % 143a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) MessageInTransit::kMessageAlignment, 0u); 144a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 145a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (buffer_size < sizeof(Header)) 146a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return false; 147a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 148a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const Header* header = static_cast<const Header*>(buffer); 149a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) *next_message_size = header->total_size; 150a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DCHECK_EQ(*next_message_size % kMessageAlignment, 0u); 151a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return true; 152a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 153a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 154a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void MessageInTransit::SetDispatchers( 155010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) scoped_ptr<DispatcherVector> dispatchers) { 156c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch DCHECK(dispatchers); 157c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch DCHECK(!dispatchers_); 158a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 159a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) dispatchers_ = dispatchers.Pass(); 160a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#ifndef NDEBUG 161a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) for (size_t i = 0; i < dispatchers_->size(); i++) 162a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DCHECK(!(*dispatchers_)[i] || (*dispatchers_)[i]->HasOneRef()); 163a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#endif 164a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 165a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 166a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void MessageInTransit::SerializeAndCloseDispatchers(Channel* channel) { 167a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DCHECK(channel); 168010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) DCHECK(!transport_data_); 169a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 170010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (!dispatchers_ || !dispatchers_->size()) 171a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return; 172a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 173010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) transport_data_.reset(new TransportData(dispatchers_.Pass(), channel)); 174a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 175010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // Update the sizes in the message header. 176a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) UpdateTotalSize(); 177a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 178a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 179a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void MessageInTransit::UpdateTotalSize() { 180a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DCHECK_EQ(main_buffer_size_ % kMessageAlignment, 0u); 181010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) header()->total_size = static_cast<uint32_t>(main_buffer_size_); 182010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (transport_data_) { 183010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) header()->total_size += 184010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) static_cast<uint32_t>(transport_data_->buffer_size()); 185010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) } 1865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 1875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1884e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} // namespace system 1894e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} // namespace mojo 190