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