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()
1521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    : message_loop_for_io_(nullptr),
1531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      delegate_(nullptr),
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()) {
1871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    delegate_ = nullptr;
1881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    message_loop_for_io_ = nullptr;
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.
2191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  delegate_ = nullptr;
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)
3221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      const char* error_message = nullptr;
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