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)#ifndef IPC_IPC_CHANNEL_NACL_H_
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define IPC_IPC_CHANNEL_NACL_H_
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <deque>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string>
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/linked_ptr.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/weak_ptr.h"
14a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch#include "base/process/process.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/simple_thread.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ipc/ipc_channel.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ipc/ipc_channel_reader.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace IPC {
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Contains the results from one call to imc_recvmsg (data and file
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// descriptors).
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct MessageContents;
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Similar to the Posix version of ChannelImpl but for Native Client code.
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This is somewhat different because sendmsg/recvmsg here do not follow POSIX
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// semantics. Instead, they are implemented by a custom embedding of
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// NaClDescCustom. See NaClIPCAdapter for the trusted-side implementation.
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// We don't need to worry about complicated set up and READWRITE mode for
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// sharing handles. We also currently do not support passing file descriptors or
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// named pipes, and we use background threads to emulate signaling when we can
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// read or write without blocking.
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class Channel::ChannelImpl : public internal::ChannelReader {
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Mirror methods of Channel, see ipc_channel.h for description.
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ChannelImpl(const IPC::ChannelHandle& channel_handle,
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              Mode mode,
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              Listener* listener);
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~ChannelImpl();
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Channel implementation.
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool Connect();
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void Close();
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool Send(Message* message);
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Posted to the main thread by ReaderThreadRunner.
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void DidRecvMsg(scoped_ptr<MessageContents> contents);
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void ReadDidFail();
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  class ReaderThreadRunner;
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool CreatePipe(const IPC::ChannelHandle& channel_handle);
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool ProcessOutgoingMessages();
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // ChannelReader implementation.
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ReadState ReadData(char* buffer,
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             int buffer_len,
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             int* bytes_read) OVERRIDE;
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool WillDispatchInputMessage(Message* msg) OVERRIDE;
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool DidEmptyInputBuffers() OVERRIDE;
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void HandleHelloMessage(const Message& msg) OVERRIDE;
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Mode mode_;
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool waiting_connect_;
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The pipe used for communication.
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int pipe_;
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The "name" of our pipe.  On Windows this is the global identifier for
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the pipe.  On POSIX it's used as a key in a local map of file descriptors.
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // For NaCl, we don't actually support looking up file descriptors by name,
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // and it's only used for debug information.
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string pipe_name_;
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We use a thread for reading, so that we can simply block on reading and
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // post the received data back to the main thread to be properly interleaved
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // with other tasks in the MessagePump.
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // imc_recvmsg supports non-blocking reads, but there's no easy way to be
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // informed when a write or read can be done without blocking (this is handled
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // by libevent in Posix).
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<ReaderThreadRunner> reader_thread_runner_;
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<base::DelegateSimpleThread> reader_thread_;
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // IPC::ChannelReader expects to be able to call ReadData on us to
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // synchronously read data waiting in the pipe's buffer without blocking.
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Since we can't do that (see 1 and 2 above), the reader thread does blocking
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // reads and posts the data over to the main thread in MessageContents. Each
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // MessageContents object is the result of one call to "imc_recvmsg".
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // DidRecvMsg breaks the MessageContents out in to the data and the file
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // descriptors, and puts them on these two queues.
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(dmichael): There's probably a more efficient way to emulate this with
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //                 a circular buffer or something, so we don't have to do so
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //                 many heap allocations. But it maybe isn't worth
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //                 the trouble given that we probably want to implement 1 and
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //                 2 above in NaCl eventually.
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // When ReadData is called, it pulls the bytes out of this queue in order.
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::deque<linked_ptr<std::vector<char> > > read_queue_;
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Queue of file descriptors extracted from imc_recvmsg messages.
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // NOTE: The implementation assumes underlying storage here is contiguous, so
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // don't change to something like std::deque<> without changing the
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // implementation!
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<int> input_fds_;
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This queue is used when a message is sent prior to Connect having been
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // called. Normally after we're connected, the queue is empty.
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::deque<linked_ptr<Message> > output_queue_;
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::WeakPtrFactory<ChannelImpl> weak_ptr_factory_;
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_IMPLICIT_CONSTRUCTORS(ChannelImpl);
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace IPC
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // IPC_IPC_CHANNEL_NACL_H_
119