raw_channel.cc revision 6e8cce623b6e4fe0c9e4af605d675dd9d0338c38
1a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved. 2a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 3a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// found in the LICENSE file. 4a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 5a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "mojo/system/raw_channel.h" 6a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 7a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include <string.h> 8a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 9a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include <algorithm> 10a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 11a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/bind.h" 12a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/location.h" 13a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/logging.h" 14a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/message_loop/message_loop.h" 15a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/stl_util.h" 16a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "mojo/system/message_in_transit.h" 17010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "mojo/system/transport_data.h" 18a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 19a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)namespace mojo { 20a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)namespace system { 21a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 22a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)const size_t kReadSize = 4096; 23a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 240de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)// RawChannel::ReadBuffer ------------------------------------------------------ 250de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) 265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)RawChannel::ReadBuffer::ReadBuffer() : buffer_(kReadSize), num_valid_bytes_(0) { 27a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 28a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 290de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)RawChannel::ReadBuffer::~ReadBuffer() { 300de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)} 31a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 32a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void RawChannel::ReadBuffer::GetBuffer(char** addr, size_t* size) { 336e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) DCHECK_GE(buffer_.size(), num_valid_bytes_ + kReadSize); 34a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) *addr = &buffer_[0] + num_valid_bytes_; 35a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) *size = kReadSize; 36a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 37a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 380de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)// RawChannel::WriteBuffer ----------------------------------------------------- 390de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) 400de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)RawChannel::WriteBuffer::WriteBuffer(size_t serialized_platform_handle_size) 410de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) : serialized_platform_handle_size_(serialized_platform_handle_size), 420de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) platform_handles_offset_(0), 430de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) data_offset_(0) { 440de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)} 45a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 46a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)RawChannel::WriteBuffer::~WriteBuffer() { 47a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) STLDeleteElements(&message_queue_); 48a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 49a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 500de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)bool RawChannel::WriteBuffer::HavePlatformHandlesToSend() const { 510de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) if (message_queue_.empty()) 520de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) return false; 530de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) 540de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) const TransportData* transport_data = 550de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) message_queue_.front()->transport_data(); 560de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) if (!transport_data) 570de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) return false; 580de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) 59cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const embedder::PlatformHandleVector* all_platform_handles = 600de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) transport_data->platform_handles(); 610de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) if (!all_platform_handles) { 626e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) DCHECK_EQ(platform_handles_offset_, 0u); 630de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) return false; 640de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) } 650de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) if (platform_handles_offset_ >= all_platform_handles->size()) { 666e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) DCHECK_EQ(platform_handles_offset_, all_platform_handles->size()); 670de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) return false; 680de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) } 690de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) 700de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) return true; 710de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)} 720de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) 730de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)void RawChannel::WriteBuffer::GetPlatformHandlesToSend( 740de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) size_t* num_platform_handles, 750de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) embedder::PlatformHandle** platform_handles, 760de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) void** serialization_data) { 776e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) DCHECK(HavePlatformHandlesToSend()); 780de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) 790de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) TransportData* transport_data = message_queue_.front()->transport_data(); 80cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) embedder::PlatformHandleVector* all_platform_handles = 810de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) transport_data->platform_handles(); 820de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) *num_platform_handles = 830de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) all_platform_handles->size() - platform_handles_offset_; 840de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) *platform_handles = &(*all_platform_handles)[platform_handles_offset_]; 850de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) size_t serialization_data_offset = 860de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) transport_data->platform_handle_table_offset(); 876e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) DCHECK_GT(serialization_data_offset, 0u); 880de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) serialization_data_offset += 890de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) platform_handles_offset_ * serialized_platform_handle_size_; 900de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) *serialization_data = 910de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) static_cast<char*>(transport_data->buffer()) + serialization_data_offset; 920de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)} 930de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) 94a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void RawChannel::WriteBuffer::GetBuffers(std::vector<Buffer>* buffers) const { 95a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) buffers->clear(); 96a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 97010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (message_queue_.empty()) 98a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return; 99a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 100a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) MessageInTransit* message = message_queue_.front(); 1016e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) DCHECK_LT(data_offset_, message->total_size()); 1020de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) size_t bytes_to_write = message->total_size() - data_offset_; 103010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 1045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) size_t transport_data_buffer_size = 1055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) message->transport_data() ? message->transport_data()->buffer_size() : 0; 106010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 107010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (!transport_data_buffer_size) { 108a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Only write from the main buffer. 1096e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) DCHECK_LT(data_offset_, message->main_buffer_size()); 1106e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) DCHECK_LE(bytes_to_write, message->main_buffer_size()); 111a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) Buffer buffer = { 1120de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) static_cast<const char*>(message->main_buffer()) + data_offset_, 113a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) bytes_to_write}; 114a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) buffers->push_back(buffer); 115a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return; 116a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 117a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 1180de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) if (data_offset_ >= message->main_buffer_size()) { 119010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // Only write from the transport data buffer. 1206e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) DCHECK_LT(data_offset_ - message->main_buffer_size(), 1216e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) transport_data_buffer_size); 1226e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) DCHECK_LE(bytes_to_write, transport_data_buffer_size); 123a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) Buffer buffer = { 124010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) static_cast<const char*>(message->transport_data()->buffer()) + 1250de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) (data_offset_ - message->main_buffer_size()), 126a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) bytes_to_write}; 127a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) buffers->push_back(buffer); 128a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return; 129a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 130a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 131cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // TODO(vtl): We could actually send out buffers from multiple messages, with 132cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // the "stopping" condition being reaching a message with platform handles 133cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // attached. 134cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 135a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Write from both buffers. 1366e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) DCHECK_EQ( 1375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) bytes_to_write, 1385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) message->main_buffer_size() - data_offset_ + transport_data_buffer_size); 139a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) Buffer buffer1 = { 1405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) static_cast<const char*>(message->main_buffer()) + data_offset_, 1415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) message->main_buffer_size() - data_offset_}; 142a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) buffers->push_back(buffer1); 143a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) Buffer buffer2 = { 1445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) static_cast<const char*>(message->transport_data()->buffer()), 1455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) transport_data_buffer_size}; 146a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) buffers->push_back(buffer2); 147a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 148a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 1490de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)// RawChannel ------------------------------------------------------------------ 1500de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) 151c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen MurdochRawChannel::RawChannel() 1525c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu : message_loop_for_io_(NULL), 1535c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu delegate_(NULL), 154a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) read_stopped_(false), 155a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) write_stopped_(false), 156a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) weak_ptr_factory_(this) { 157a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 158a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 159a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)RawChannel::~RawChannel() { 1606e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) DCHECK(!read_buffer_); 1616e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) DCHECK(!write_buffer_); 162a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 163a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // No need to take the |write_lock_| here -- if there are still weak pointers 164a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // outstanding, then we're hosed anyway (since we wouldn't be able to 165a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // invalidate them cleanly, since we might not be on the I/O thread). 1666e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) DCHECK(!weak_ptr_factory_.HasWeakPtrs()); 167a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 168a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 169c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochbool RawChannel::Init(Delegate* delegate) { 1706e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) DCHECK(delegate); 171c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 1726e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) DCHECK(!delegate_); 173c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch delegate_ = delegate; 174c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 175c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch CHECK_EQ(base::MessageLoop::current()->type(), base::MessageLoop::TYPE_IO); 1766e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) DCHECK(!message_loop_for_io_); 177c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch message_loop_for_io_ = 178c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch static_cast<base::MessageLoopForIO*>(base::MessageLoop::current()); 179a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 180a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // No need to take the lock. No one should be using us yet. 1816e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) DCHECK(!read_buffer_); 182a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) read_buffer_.reset(new ReadBuffer); 1836e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) DCHECK(!write_buffer_); 1840de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) write_buffer_.reset(new WriteBuffer(GetSerializedPlatformHandleSize())); 185a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 1865c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (!OnInit()) { 1875c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu delegate_ = NULL; 1885c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu message_loop_for_io_ = NULL; 1895c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu read_buffer_.reset(); 1905c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu write_buffer_.reset(); 191a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return false; 1925c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 193a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 1946e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) IOResult io_result = ScheduleRead(); 1956e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (io_result != IO_PENDING) { 196cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // This will notify the delegate about the read failure. Although we're on 197cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // the I/O thread, don't call it in the nested context. 1985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) message_loop_for_io_->PostTask(FROM_HERE, 1995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) base::Bind(&RawChannel::OnReadCompleted, 2005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) weak_ptr_factory_.GetWeakPtr(), 2016e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) io_result, 2025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 0)); 203cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 204cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 205cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // ScheduleRead() failure is treated as a read failure (by notifying the 206cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // delegate), not as an init failure. 207cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return true; 208a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 209a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 210a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void RawChannel::Shutdown() { 2116e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) DCHECK_EQ(base::MessageLoop::current(), message_loop_for_io_); 212a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 213a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::AutoLock locker(write_lock_); 214a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 215effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch LOG_IF(WARNING, !write_buffer_->message_queue_.empty()) 216effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch << "Shutting down RawChannel with write buffer nonempty"; 217effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 2185c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // Reset the delegate so that it won't receive further calls. 2195c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu delegate_ = NULL; 220a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) read_stopped_ = true; 221a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) write_stopped_ = true; 2225c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu weak_ptr_factory_.InvalidateWeakPtrs(); 223a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 224a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) OnShutdownNoLock(read_buffer_.Pass(), write_buffer_.Pass()); 225a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 226a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 227a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Reminder: This must be thread-safe. 228a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)bool RawChannel::WriteMessage(scoped_ptr<MessageInTransit> message) { 2296e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) DCHECK(message); 230c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 231a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::AutoLock locker(write_lock_); 232a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (write_stopped_) 233a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return false; 234a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 235a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (!write_buffer_->message_queue_.empty()) { 236cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) EnqueueMessageNoLock(message.Pass()); 237a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return true; 238a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 239a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 240cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) EnqueueMessageNoLock(message.Pass()); 2416e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) DCHECK_EQ(write_buffer_->data_offset_, 0u); 242a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 2430de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) size_t platform_handles_written = 0; 244a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) size_t bytes_written = 0; 2450de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) IOResult io_result = WriteNoLock(&platform_handles_written, &bytes_written); 246a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (io_result == IO_PENDING) 247a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return true; 248a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 2495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) bool result = OnWriteCompletedNoLock( 2506e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) io_result, platform_handles_written, bytes_written); 251a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (!result) { 2526e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // Even if we're on the I/O thread, don't call |OnError()| in the nested 2536e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // context. 2545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) message_loop_for_io_->PostTask(FROM_HERE, 2556e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) base::Bind(&RawChannel::CallOnError, 2565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) weak_ptr_factory_.GetWeakPtr(), 2576e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) Delegate::ERROR_WRITE)); 258a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 259a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 260a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return result; 261a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 262a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 263effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// Reminder: This must be thread-safe. 264effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochbool RawChannel::IsWriteBufferEmpty() { 265effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch base::AutoLock locker(write_lock_); 266effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch return write_buffer_->message_queue_.empty(); 267effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch} 268effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 2696e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)void RawChannel::OnReadCompleted(IOResult io_result, size_t bytes_read) { 2706e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) DCHECK_EQ(base::MessageLoop::current(), message_loop_for_io_); 271a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 272a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (read_stopped_) { 273a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) NOTREACHED(); 274a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return; 275a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 276a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 277a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Keep reading data in a loop, and dispatch messages if enough data is 278a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // received. Exit the loop if any of the following happens: 279a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // - one or more messages were dispatched; 280a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // - the last read failed, was a partial read or would block; 281a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // - |Shutdown()| was called. 282a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) do { 2836e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) switch (io_result) { 2846e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) case IO_SUCCEEDED: 2856e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) break; 2866e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) case IO_FAILED_SHUTDOWN: 2876e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) case IO_FAILED_BROKEN: 2886e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) case IO_FAILED_UNKNOWN: 2896e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) read_stopped_ = true; 2906e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) CallOnError(ReadIOResultToError(io_result)); 2916e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return; 2926e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) case IO_PENDING: 2936e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) NOTREACHED(); 2946e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return; 295a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 296a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 297a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) read_buffer_->num_valid_bytes_ += bytes_read; 298a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 299a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Dispatch all the messages that we can. 300a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) bool did_dispatch_message = false; 301a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Tracks the offset of the first undispatched message in |read_buffer_|. 302a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Currently, we copy data to ensure that this is zero at the beginning. 303a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) size_t read_buffer_start = 0; 304a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) size_t remaining_bytes = read_buffer_->num_valid_bytes_; 305a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) size_t message_size; 306a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Note that we rely on short-circuit evaluation here: 307a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // - |read_buffer_start| may be an invalid index into 308a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // |read_buffer_->buffer_| if |remaining_bytes| is zero. 309a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // - |message_size| is only valid if |GetNextMessageSize()| returns true. 310a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // TODO(vtl): Use |message_size| more intelligently (e.g., to request the 311a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // next read). 312a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // TODO(vtl): Validate that |message_size| is sane. 3135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) while (remaining_bytes > 0 && MessageInTransit::GetNextMessageSize( 3145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) &read_buffer_->buffer_[read_buffer_start], 3155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) remaining_bytes, 3165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) &message_size) && 317a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) remaining_bytes >= message_size) { 3185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) MessageInTransit::View message_view( 3195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) message_size, &read_buffer_->buffer_[read_buffer_start]); 3206e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) DCHECK_EQ(message_view.total_size(), message_size); 321a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 322cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const char* error_message = NULL; 323cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (!message_view.IsValid(GetSerializedPlatformHandleSize(), 324cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) &error_message)) { 3256e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) DCHECK(error_message); 3266e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) LOG(ERROR) << "Received invalid message: " << error_message; 327cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) read_stopped_ = true; 3286e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) CallOnError(Delegate::ERROR_READ_BAD_MESSAGE); 329a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return; 330a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 331cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 332cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (message_view.type() == MessageInTransit::kTypeRawChannel) { 333cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (!OnReadMessageForRawChannel(message_view)) { 334cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) read_stopped_ = true; 3356e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) CallOnError(Delegate::ERROR_READ_BAD_MESSAGE); 336cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return; 337cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 338cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } else { 339cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) embedder::ScopedPlatformHandleVectorPtr platform_handles; 340cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (message_view.transport_data_buffer()) { 341cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) size_t num_platform_handles; 342cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const void* platform_handle_table; 343cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) TransportData::GetPlatformHandleTable( 344cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) message_view.transport_data_buffer(), 345cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) &num_platform_handles, 346cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) &platform_handle_table); 347cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 348cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (num_platform_handles > 0) { 349cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) platform_handles = 350cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) GetReadPlatformHandles(num_platform_handles, 351cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) platform_handle_table).Pass(); 352cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (!platform_handles) { 3536e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) LOG(ERROR) << "Invalid number of platform handles received"; 354cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) read_stopped_ = true; 3556e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) CallOnError(Delegate::ERROR_READ_BAD_MESSAGE); 356cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return; 357cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 358cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 359cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 360cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 361cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // TODO(vtl): In the case that we aren't expecting any platform handles, 362cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // for the POSIX implementation, we should confirm that none are stored. 363cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 364cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Dispatch the message. 3656e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) DCHECK(delegate_); 366cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) delegate_->OnReadMessage(message_view, platform_handles.Pass()); 367cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (read_stopped_) { 368cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // |Shutdown()| was called in |OnReadMessage()|. 369cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // TODO(vtl): Add test for this case. 370cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return; 371cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 372cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 373cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 374a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) did_dispatch_message = true; 375a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 376a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Update our state. 377a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) read_buffer_start += message_size; 378a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) remaining_bytes -= message_size; 379a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 380a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 381a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (read_buffer_start > 0) { 382a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Move data back to start. 383a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) read_buffer_->num_valid_bytes_ = remaining_bytes; 384a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (read_buffer_->num_valid_bytes_ > 0) { 385a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) memmove(&read_buffer_->buffer_[0], 3865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) &read_buffer_->buffer_[read_buffer_start], 3875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) remaining_bytes); 388a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 389a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) read_buffer_start = 0; 390a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 391a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 392a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (read_buffer_->buffer_.size() - read_buffer_->num_valid_bytes_ < 3935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) kReadSize) { 394a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Use power-of-2 buffer sizes. 395a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // TODO(vtl): Make sure the buffer doesn't get too large (and enforce the 396a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // maximum message size to whatever extent necessary). 397a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // TODO(vtl): We may often be able to peek at the header and get the real 398a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // required extra space (which may be much bigger than |kReadSize|). 399a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) size_t new_size = std::max(read_buffer_->buffer_.size(), kReadSize); 400a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) while (new_size < read_buffer_->num_valid_bytes_ + kReadSize) 401a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) new_size *= 2; 402a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 403a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // TODO(vtl): It's suboptimal to zero out the fresh memory. 404a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) read_buffer_->buffer_.resize(new_size, 0); 405a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 406a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 407a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // (1) If we dispatched any messages, stop reading for now (and let the 408a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // message loop do its thing for another round). 409a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // TODO(vtl): Is this the behavior we want? (Alternatives: i. Dispatch only 410a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // a single message. Risks: slower, more complex if we want to avoid lots of 411a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // copying. ii. Keep reading until there's no more data and dispatch all the 412a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // messages we can. Risks: starvation of other users of the message loop.) 413a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // (2) If we didn't max out |kReadSize|, stop reading for now. 414a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) bool schedule_for_later = did_dispatch_message || bytes_read < kReadSize; 415a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) bytes_read = 0; 416a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) io_result = schedule_for_later ? ScheduleRead() : Read(&bytes_read); 417a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } while (io_result != IO_PENDING); 418a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 419a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 4206e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)void RawChannel::OnWriteCompleted(IOResult io_result, 4210de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) size_t platform_handles_written, 4220de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) size_t bytes_written) { 4236e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) DCHECK_EQ(base::MessageLoop::current(), message_loop_for_io_); 4246e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) DCHECK_NE(io_result, IO_PENDING); 425a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 426a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) bool did_fail = false; 427a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) { 428a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::AutoLock locker(write_lock_); 4296e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) DCHECK_EQ(write_stopped_, write_buffer_->message_queue_.empty()); 430a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 431a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (write_stopped_) { 432a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) NOTREACHED(); 433a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return; 434a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 435a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 4365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) did_fail = !OnWriteCompletedNoLock( 4376e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) io_result, platform_handles_written, bytes_written); 438a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 439a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 440a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (did_fail) 4416e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) CallOnError(Delegate::ERROR_WRITE); 442a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 443a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 444cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void RawChannel::EnqueueMessageNoLock(scoped_ptr<MessageInTransit> message) { 445cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) write_lock_.AssertAcquired(); 446cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) write_buffer_->message_queue_.push_back(message.release()); 447cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 448cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 449cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)bool RawChannel::OnReadMessageForRawChannel( 450cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const MessageInTransit::View& message_view) { 451cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // No non-implementation specific |RawChannel| control messages. 452cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) LOG(ERROR) << "Invalid control message (subtype " << message_view.subtype() 453cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) << ")"; 454cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return false; 455cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 456cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 4576e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// static 4586e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)RawChannel::Delegate::Error RawChannel::ReadIOResultToError( 4596e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) IOResult io_result) { 4606e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) switch (io_result) { 4616e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) case IO_FAILED_SHUTDOWN: 4626e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return Delegate::ERROR_READ_SHUTDOWN; 4636e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) case IO_FAILED_BROKEN: 4646e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return Delegate::ERROR_READ_BROKEN; 4656e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) case IO_FAILED_UNKNOWN: 4666e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return Delegate::ERROR_READ_UNKNOWN; 4676e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) case IO_SUCCEEDED: 4686e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) case IO_PENDING: 4696e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) NOTREACHED(); 4706e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) break; 4716e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 4726e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return Delegate::ERROR_READ_UNKNOWN; 4736e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)} 4746e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 4756e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)void RawChannel::CallOnError(Delegate::Error error) { 4766e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) DCHECK_EQ(base::MessageLoop::current(), message_loop_for_io_); 477a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // TODO(vtl): Add a "write_lock_.AssertNotAcquired()"? 4785c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (delegate_) 4796e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) delegate_->OnError(error); 480a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 481a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 4826e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)bool RawChannel::OnWriteCompletedNoLock(IOResult io_result, 4830de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) size_t platform_handles_written, 4840de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) size_t bytes_written) { 485a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) write_lock_.AssertAcquired(); 486a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 4876e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) DCHECK(!write_stopped_); 4886e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) DCHECK(!write_buffer_->message_queue_.empty()); 489a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 4906e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (io_result == IO_SUCCEEDED) { 4910de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) write_buffer_->platform_handles_offset_ += platform_handles_written; 4920de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) write_buffer_->data_offset_ += bytes_written; 493010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 494010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) MessageInTransit* message = write_buffer_->message_queue_.front(); 4950de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) if (write_buffer_->data_offset_ >= message->total_size()) { 496a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Complete write. 4975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) CHECK_EQ(write_buffer_->data_offset_, message->total_size()); 498a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) write_buffer_->message_queue_.pop_front(); 499010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) delete message; 5000de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) write_buffer_->platform_handles_offset_ = 0; 5010de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) write_buffer_->data_offset_ = 0; 502a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 503010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (write_buffer_->message_queue_.empty()) 504010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) return true; 505010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) } 506a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 507a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Schedule the next write. 5086e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) io_result = ScheduleWriteNoLock(); 509010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (io_result == IO_PENDING) 510a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return true; 5116e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) DCHECK_NE(io_result, IO_SUCCEEDED); 512a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 513a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 514a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) write_stopped_ = true; 515a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) STLDeleteElements(&write_buffer_->message_queue_); 5160de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) write_buffer_->platform_handles_offset_ = 0; 5170de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) write_buffer_->data_offset_ = 0; 518a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return false; 519a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 520a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 521a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} // namespace system 522a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} // namespace mojo 523