ipc_channel_nacl.cc revision 46d4c2bc3267f3f028f39e7e311b0f89aba2e4fd
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ipc/ipc_channel_nacl.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <errno.h> 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stddef.h> 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/types.h> 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <algorithm> 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 15868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/message_loop/message_loop_proxy.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/synchronization/lock.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/task_runner_util.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/simple_thread.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ipc/file_descriptor_set_posix.h" 2023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include "ipc/ipc_listener.h" 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ipc/ipc_logging.h" 22868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "native_client/src/public/imc_syscalls.h" 23868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "native_client/src/public/imc_types.h" 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace IPC { 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct MessageContents { 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<char> data; 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<int> fds; 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ReadDataOnReaderThread(int pipe, MessageContents* contents) { 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(pipe >= 0); 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (pipe < 0) 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) contents->data.resize(Channel::kReadBufferSize); 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) contents->fds.resize(FileDescriptorSet::kMaxDescriptorsPerMessage); 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 42868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) NaClAbiNaClImcMsgIoVec iov = { &contents->data[0], contents->data.size() }; 43868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) NaClAbiNaClImcMsgHdr msg = { 44868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) &iov, 1, &contents->fds[0], contents->fds.size() 45868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) }; 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int bytes_read = imc_recvmsg(pipe, &msg, 0); 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (bytes_read <= 0) { 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // NaClIPCAdapter::BlockingReceive returns -1 when the pipe closes (either 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // due to error or for regular shutdown). 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) contents->data.clear(); 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) contents->fds.clear(); 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(bytes_read); 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Resize the buffers down to the number of bytes and fds we actually read. 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) contents->data.resize(bytes_read); 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) contents->fds.resize(msg.desc_length); 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)class ChannelNacl::ReaderThreadRunner 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : public base::DelegateSimpleThread::Delegate { 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |pipe|: A file descriptor from which we will read using imc_recvmsg. 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |data_read_callback|: A callback we invoke (on the main thread) when we 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // have read data. 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |failure_callback|: A callback we invoke when we have a failure reading 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // from |pipe|. 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |main_message_loop|: A proxy for the main thread, where we will invoke the 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // above callbacks. 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReaderThreadRunner( 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int pipe, 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Callback<void (scoped_ptr<MessageContents>)> data_read_callback, 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Callback<void ()> failure_callback, 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<base::MessageLoopProxy> main_message_loop); 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // DelegateSimpleThread implementation. Reads data from the pipe in a loop 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // until either we are told to quit or a read fails. 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void Run() OVERRIDE; 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int pipe_; 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Callback<void (scoped_ptr<MessageContents>)> data_read_callback_; 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Callback<void ()> failure_callback_; 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<base::MessageLoopProxy> main_message_loop_; 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(ReaderThreadRunner); 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)ChannelNacl::ReaderThreadRunner::ReaderThreadRunner( 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int pipe, 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Callback<void (scoped_ptr<MessageContents>)> data_read_callback, 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Callback<void ()> failure_callback, 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<base::MessageLoopProxy> main_message_loop) 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : pipe_(pipe), 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data_read_callback_(data_read_callback), 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) failure_callback_(failure_callback), 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) main_message_loop_(main_message_loop) { 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void ChannelNacl::ReaderThreadRunner::Run() { 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (true) { 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<MessageContents> msg_contents(new MessageContents); 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool success = ReadDataOnReaderThread(pipe_, msg_contents.get()); 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (success) { 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) main_message_loop_->PostTask(FROM_HERE, 1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(data_read_callback_, base::Passed(&msg_contents))); 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) main_message_loop_->PostTask(FROM_HERE, failure_callback_); 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Because the read failed, we know we're going to quit. Don't bother 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // trying to read again. 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)ChannelNacl::ChannelNacl(const IPC::ChannelHandle& channel_handle, 12246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) Mode mode, 12346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) Listener* listener) 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : ChannelReader(listener), 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mode_(mode), 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) waiting_connect_(true), 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pipe_(-1), 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pipe_name_(channel_handle.name), 129c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) weak_ptr_factory_(this) { 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!CreatePipe(channel_handle)) { 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The pipe may have been closed already. 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char *modestr = (mode_ & MODE_SERVER_FLAG) ? "server" : "client"; 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(WARNING) << "Unable to create pipe named \"" << channel_handle.name 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "\" in " << modestr << " mode"; 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)ChannelNacl::~ChannelNacl() { 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Close(); 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)base::ProcessId ChannelNacl::GetPeerPID() const { 14323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) // This shouldn't actually get used in the untrusted side of the proxy, and we 14423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) // don't have the real pid anyway. 14523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) return -1; 14623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)} 14723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) 14846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)bool ChannelNacl::Connect() { 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (pipe_ == -1) { 15023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) DLOG(WARNING) << "Channel creation failed: " << pipe_name_; 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Note that Connect is called on the "Channel" thread (i.e., the same thread 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // where Channel::Send will be called, and the same thread that should receive 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // messages). The constructor might be invoked on another thread (see 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // ChannelProxy for an example of that). Therefore, we must wait until Connect 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // is called to decide which MessageLoopProxy to pass to ReaderThreadRunner. 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reader_thread_runner_.reset( 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new ReaderThreadRunner( 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pipe_, 16246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) base::Bind(&ChannelNacl::DidRecvMsg, 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) weak_ptr_factory_.GetWeakPtr()), 16446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) base::Bind(&ChannelNacl::ReadDidFail, 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) weak_ptr_factory_.GetWeakPtr()), 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::MessageLoopProxy::current())); 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reader_thread_.reset( 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new base::DelegateSimpleThread(reader_thread_runner_.get(), 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "ipc_channel_nacl reader thread")); 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reader_thread_->Start(); 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) waiting_connect_ = false; 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If there were any messages queued before connection, send them. 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ProcessOutgoingMessages(); 17423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) base::MessageLoopProxy::current()->PostTask(FROM_HERE, 17546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) base::Bind(&ChannelNacl::CallOnChannelConnected, 17623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) weak_ptr_factory_.GetWeakPtr())); 17723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void ChannelNacl::Close() { 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // For now, we assume that at shutdown, the reader thread will be woken with 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // a failure (see NaClIPCAdapter::BlockingRead and CloseChannel). Or... we 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // might simply be killed with no chance to clean up anyway :-). 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If untrusted code tries to close the channel prior to shutdown, it's likely 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // to hang. 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(dmichael): Can we do anything smarter here to make sure the reader 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // thread wakes up and quits? 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reader_thread_->Join(); 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) close(pipe_); 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pipe_ = -1; 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reader_thread_runner_.reset(); 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reader_thread_.reset(); 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) read_queue_.clear(); 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) output_queue_.clear(); 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)bool ChannelNacl::Send(Message* message) { 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DVLOG(2) << "sending message @" << message << " on channel @" << this 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << " with type " << message->type(); 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<Message> message_ptr(message); 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef IPC_MESSAGE_LOG_ENABLED 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Logging::GetInstance()->OnSendMessage(message_ptr.get(), ""); 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif // IPC_MESSAGE_LOG_ENABLED 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) message->TraceMessageBegin(); 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) output_queue_.push_back(linked_ptr<Message>(message_ptr.release())); 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!waiting_connect_) 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ProcessOutgoingMessages(); 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void ChannelNacl::DidRecvMsg(scoped_ptr<MessageContents> contents) { 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Close sets the pipe to -1. It's possible we'll get a buffer sent to us from 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the reader thread after Close is called. If so, we ignore it. 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (pipe_ == -1) 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) linked_ptr<std::vector<char> > data(new std::vector<char>); 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data->swap(contents->data); 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) read_queue_.push_back(data); 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) input_fds_.insert(input_fds_.end(), 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) contents->fds.begin(), contents->fds.end()); 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) contents->fds.clear(); 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // In POSIX, we would be told when there are bytes to read by implementing 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // OnFileCanReadWithoutBlocking in MessageLoopForIO::Watcher. In NaCl, we 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // instead know at this point because the reader thread posted some data to 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // us. 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ProcessIncomingMessages(); 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void ChannelNacl::ReadDidFail() { 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Close(); 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)bool ChannelNacl::CreatePipe( 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const IPC::ChannelHandle& channel_handle) { 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(pipe_ == -1); 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // There's one possible case in NaCl: 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 1) It's a channel wrapping a pipe that is given to us. 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We don't support these: 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 2) It's for a named channel. 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 3) It's for a client that we implement ourself. 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 4) It's the initial IPC channel. 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (channel_handle.socket.fd == -1) { 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTIMPLEMENTED(); 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pipe_ = channel_handle.socket.fd; 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 25946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)bool ChannelNacl::ProcessOutgoingMessages() { 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!waiting_connect_); // Why are we trying to send messages if there's 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // no connection? 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (output_queue_.empty()) 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (pipe_ == -1) 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Write out all the messages. The trusted implementation is guaranteed to not 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // block. See NaClIPCAdapter::Send for the implementation of imc_sendmsg. 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (!output_queue_.empty()) { 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) linked_ptr<Message> msg = output_queue_.front(); 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) output_queue_.pop_front(); 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int fds[FileDescriptorSet::kMaxDescriptorsPerMessage]; 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const size_t num_fds = msg->file_descriptor_set()->size(); 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(num_fds <= FileDescriptorSet::kMaxDescriptorsPerMessage); 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) msg->file_descriptor_set()->GetDescriptors(fds); 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 279868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) NaClAbiNaClImcMsgIoVec iov = { 280868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const_cast<void*>(msg->data()), msg->size() 281868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) }; 282868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) NaClAbiNaClImcMsgHdr msgh = { &iov, 1, fds, num_fds }; 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ssize_t bytes_written = imc_sendmsg(pipe_, &msgh, 0); 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(bytes_written); // The trusted side shouldn't return 0. 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (bytes_written < 0) { 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The trusted side should only ever give us an error of EPIPE. We 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // should never be interrupted, nor should we get EAGAIN. 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(errno == EPIPE); 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Close(); 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PLOG(ERROR) << "pipe_ error on " 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << pipe_ 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << " Currently writing message of size: " 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << msg->size(); 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) msg->file_descriptor_set()->CommitAll(); 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Message sent OK! 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DVLOG(2) << "sent message @" << msg.get() << " with type " << msg->type() 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << " on fd " << pipe_; 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 30746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void ChannelNacl::CallOnChannelConnected() { 30846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) listener()->OnChannelConnected(GetPeerPID()); 30923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)} 31023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) 31146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)ChannelNacl::ReadState ChannelNacl::ReadData( 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char* buffer, 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int buffer_len, 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int* bytes_read) { 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *bytes_read = 0; 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (pipe_ == -1) 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return READ_FAILED; 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (read_queue_.empty()) 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return READ_PENDING; 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (!read_queue_.empty() && *bytes_read < buffer_len) { 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) linked_ptr<std::vector<char> > vec(read_queue_.front()); 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t bytes_to_read = buffer_len - *bytes_read; 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (vec->size() <= bytes_to_read) { 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We can read and discard the entire vector. 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::copy(vec->begin(), vec->end(), buffer + *bytes_read); 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *bytes_read += vec->size(); 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) read_queue_.pop_front(); 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Read all the bytes we can and discard them from the front of the 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // vector. (This can be slowish, since erase has to move the back of the 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // vector to the front, but it's hopefully a temporary hack and it keeps 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the code simple). 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::copy(vec->begin(), vec->begin() + bytes_to_read, 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buffer + *bytes_read); 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) vec->erase(vec->begin(), vec->begin() + bytes_to_read); 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *bytes_read += bytes_to_read; 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return READ_SUCCEEDED; 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 34246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)bool ChannelNacl::WillDispatchInputMessage(Message* msg) { 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint16 header_fds = msg->header()->num_fds; 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK(header_fds == input_fds_.size()); 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (header_fds == 0) 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; // Nothing to do. 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The shenaniganery below with &foo.front() requires input_fds_ to have 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // contiguous underlying storage (such as a simple array or a std::vector). 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This is why the header warns not to make input_fds_ a deque<>. 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) msg->file_descriptor_set()->SetDescriptors(&input_fds_.front(), 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) header_fds); 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) input_fds_.clear(); 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 35746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)bool ChannelNacl::DidEmptyInputBuffers() { 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // When the input data buffer is empty, the fds should be too. 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return input_fds_.empty(); 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 36246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void ChannelNacl::HandleInternalMessage(const Message& msg) { 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The trusted side IPC::Channel should handle the "hello" handshake; we 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // should not receive the "Hello" message. 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 36846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// Channel's methods 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 37046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// static 37146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)scoped_ptr<Channel> Channel::Create( 37246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) const IPC::ChannelHandle &channel_handle, Mode mode, Listener* listener) { 37346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return scoped_ptr<Channel>( 37446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) new ChannelNacl(channel_handle, mode, listener)); 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace IPC 378