summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--base/message_loop.cc8
-rw-r--r--ipc/ipc_channel_nacl.cc336
-rw-r--r--ipc/ipc_channel_nacl.h80
-rw-r--r--ipc/ipc_channel_proxy.cc2
-rw-r--r--ipc/ipc_channel_proxy.h2
-rw-r--r--ppapi/ppapi_proxy_untrusted.gypi1
-rw-r--r--ppapi/proxy/proxy_channel.cc2
-rw-r--r--ppapi/proxy/proxy_channel.h2
8 files changed, 91 insertions, 342 deletions
diff --git a/base/message_loop.cc b/base/message_loop.cc
index a207659..dd8ba3a 100644
--- a/base/message_loop.cc
+++ b/base/message_loop.cc
@@ -151,12 +151,10 @@ MessageLoop::MessageLoop(Type type)
#define MESSAGE_PUMP_UI base::MessagePumpMac::Create()
#define MESSAGE_PUMP_IO new base::MessagePumpLibevent()
#elif defined(OS_NACL)
-// Currently NaCl doesn't have a UI MessageLoop.
-// TODO(abarth): Figure out if we need this.
+// Currently NaCl doesn't have a UI or an IO MessageLoop.
+// TODO(abarth): Figure out if we need these.
#define MESSAGE_PUMP_UI NULL
-// ipc_channel_nacl.cc uses a worker thread to do socket reads currently, and
-// doesn't require extra support for watching file descriptors.
-#define MESSAGE_PUMP_IO new base::MessagePumpDefault();
+#define MESSAGE_PUMP_IO NULL
#elif defined(OS_POSIX) // POSIX but not MACOSX.
#define MESSAGE_PUMP_UI new base::MessagePumpForUI()
#define MESSAGE_PUMP_IO new base::MessagePumpLibevent()
diff --git a/ipc/ipc_channel_nacl.cc b/ipc/ipc_channel_nacl.cc
index 192b4a8b..683353e 100644
--- a/ipc/ipc_channel_nacl.cc
+++ b/ipc/ipc_channel_nacl.cc
@@ -4,137 +4,18 @@
#include "ipc/ipc_channel_nacl.h"
-#include <errno.h>
-#include <stddef.h>
-#include <sys/nacl_imc_api.h>
-#include <sys/nacl_syscalls.h>
-#include <sys/types.h>
-
-#include <algorithm>
-
-#include "base/bind.h"
#include "base/file_util.h"
#include "base/logging.h"
-#include "base/message_loop_proxy.h"
-#include "base/process_util.h"
-#include "base/synchronization/lock.h"
-#include "base/task_runner_util.h"
-#include "base/threading/simple_thread.h"
-#include "ipc/file_descriptor_set_posix.h"
-#include "ipc/ipc_logging.h"
-
-namespace IPC {
-namespace {
-
-scoped_ptr<std::vector<char> > ReadDataOnReaderThread(int pipe) {
- DCHECK(pipe >= 0);
-
- if (pipe < 0)
- return scoped_ptr<std::vector<char> >();
-
- scoped_ptr<std::vector<char> > buffer(
- new std::vector<char>(Channel::kReadBufferSize));
- struct NaClImcMsgHdr msg = {0};
- struct NaClImcMsgIoVec iov = {&buffer->at(0), buffer->size()};
- msg.iov = &iov;
- msg.iov_length = 1;
-
- int bytes_read = imc_recvmsg(pipe, &msg, 0);
-
- if (bytes_read <= 0) {
- // NaClIPCAdapter::BlockingReceive returns -1 when the pipe closes (either
- // due to error or for regular shutdown).
- return scoped_ptr<std::vector<char> >();
- }
- DCHECK(bytes_read);
- buffer->resize(bytes_read);
- return buffer.Pass();
-}
-} // namespace
-
-class Channel::ChannelImpl::ReaderThreadRunner
- : public base::DelegateSimpleThread::Delegate {
- public:
- // |pipe|: A file descriptor from which we will read using imc_recvmsg.
- // |data_read_callback|: A callback we invoke (on the main thread) when we
- // have read data. The callback is passed a buffer of
- // data that was read.
- // |failure_callback|: A callback we invoke when we have a failure reading
- // from |pipe|.
- // |main_message_loop|: A proxy for the main thread, where we will invoke the
- // above callbacks.
- ReaderThreadRunner(
- int pipe,
- base::Callback<void (scoped_ptr<std::vector<char> >)> data_read_callback,
- base::Callback<void ()> failure_callback,
- base::MessageLoopProxy* main_message_loop);
-
- // DelegateSimpleThread implementation. Reads data from the pipe in a loop
- // until either we are told to quit or a read fails.
- virtual void Run() OVERRIDE;
-
- private:
- int pipe_;
- base::Callback<void (scoped_ptr<std::vector<char> >)> data_read_callback_;
- base::Callback<void ()> failure_callback_;
- base::MessageLoopProxy* main_message_loop_;
-
- DISALLOW_COPY_AND_ASSIGN(ReaderThreadRunner);
-};
-
-Channel::ChannelImpl::ReaderThreadRunner::ReaderThreadRunner(
- int pipe,
- base::Callback<void (scoped_ptr<std::vector<char> >)> data_read_callback,
- base::Callback<void ()> failure_callback,
- base::MessageLoopProxy* main_message_loop)
- : pipe_(pipe),
- data_read_callback_(data_read_callback),
- failure_callback_(failure_callback),
- main_message_loop_(main_message_loop) {
-}
+// This file is currently a stub to get us linking.
+// TODO(brettw) implement this.
-void Channel::ChannelImpl::ReaderThreadRunner::Run() {
- while (true) {
- scoped_ptr<std::vector<char> > buffer(ReadDataOnReaderThread(pipe_));
- if (buffer.get()) {
- main_message_loop_->PostTask(FROM_HERE,
- base::Bind(data_read_callback_, base::Passed(buffer.Pass())));
- } else {
- main_message_loop_->PostTask(FROM_HERE, failure_callback_);
- // Because the read failed, we know we're going to quit. Don't bother
- // trying to read again.
- return;
- }
- }
-}
+namespace IPC {
Channel::ChannelImpl::ChannelImpl(const IPC::ChannelHandle& channel_handle,
- Mode mode,
- Listener* listener)
- : ChannelReader(listener),
- mode_(mode),
- waiting_connect_(true),
- pipe_(-1),
- pipe_name_(channel_handle.name),
- weak_ptr_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {
- if (!CreatePipe(channel_handle)) {
- // The pipe may have been closed already.
- const char *modestr = (mode_ & MODE_SERVER_FLAG) ? "server" : "client";
- LOG(WARNING) << "Unable to create pipe named \"" << channel_handle.name
- << "\" in " << modestr << " mode";
- }
- reader_thread_runner_.reset(
- new ReaderThreadRunner(
- pipe_,
- base::Bind(&Channel::ChannelImpl::DidRecvMsg,
- weak_ptr_factory_.GetWeakPtr()),
- base::Bind(&Channel::ChannelImpl::ReadDidFail,
- weak_ptr_factory_.GetWeakPtr()),
- base::MessageLoopProxy::current()));
- reader_thread_.reset(
- new base::DelegateSimpleThread(reader_thread_runner_.get(),
- "ipc_channel_nacl reader thread"));
+ Mode mode,
+ Listener* listener)
+ : ChannelReader(listener) {
}
Channel::ChannelImpl::~ChannelImpl() {
@@ -142,165 +23,69 @@ Channel::ChannelImpl::~ChannelImpl() {
}
bool Channel::ChannelImpl::Connect() {
- if (pipe_ == -1) {
- DLOG(INFO) << "Channel creation failed: " << pipe_name_;
- return false;
- }
-
- reader_thread_->Start();
- waiting_connect_ = false;
- // If there were any messages queued before connection, send them.
- ProcessOutgoingMessages();
+ NOTIMPLEMENTED();
+ return false;
}
void Channel::ChannelImpl::Close() {
- // For now, we assume that at shutdown, the reader thread will be woken with
- // a failure (see NaClIPCAdapter::BlockingRead and CloseChannel). Or... we
- // might simply be killed with no chance to clean up anyway :-).
- // If untrusted code tries to close the channel prior to shutdown, it's likely
- // to hang.
- // TODO(dmichael): Can we do anything smarter here to make sure the reader
- // thread wakes up and quits?
- reader_thread_->Join();
- close(pipe_);
- pipe_ = -1;
- reader_thread_runner_.reset();
- reader_thread_.reset();
- read_queue_.clear();
- output_queue_.clear();
+ NOTIMPLEMENTED();
}
bool Channel::ChannelImpl::Send(Message* message) {
- DVLOG(2) << "sending message @" << message << " on channel @" << this
- << " with type " << message->type();
- scoped_ptr<Message> message_ptr(message);
-
-#ifdef IPC_MESSAGE_LOG_ENABLED
- Logging::GetInstance()->OnSendMessage(message, "");
-#endif // IPC_MESSAGE_LOG_ENABLED
-
- output_queue_.push_back(linked_ptr<Message>(message));
- if (!waiting_connect_)
- return ProcessOutgoingMessages();
+ NOTIMPLEMENTED();
+}
- return true;
+int Channel::ChannelImpl::GetClientFileDescriptor() const {
+ NOTIMPLEMENTED();
+ return -1;
}
-void Channel::ChannelImpl::DidRecvMsg(scoped_ptr<std::vector<char> > buffer) {
- // Close sets the pipe to -1. It's possible we'll get a buffer sent to us from
- // the reader thread after Close is called. If so, we ignore it.
- if (pipe_ == -1)
- return;
+int Channel::ChannelImpl::TakeClientFileDescriptor() {
+ NOTIMPLEMENTED();
+ return -1;
+}
- read_queue_.push_back(linked_ptr<std::vector<char> >(buffer.release()));
+bool Channel::ChannelImpl::AcceptsConnections() const {
+ NOTIMPLEMENTED();
+ return false;
}
-void Channel::ChannelImpl::ReadDidFail() {
- Close();
+bool Channel::ChannelImpl::HasAcceptedConnection() const {
+ NOTIMPLEMENTED();
+ return false;
}
-bool Channel::ChannelImpl::CreatePipe(
- const IPC::ChannelHandle& channel_handle) {
- DCHECK(pipe_ == -1);
-
- // There's one possible case in NaCl:
- // 1) It's a channel wrapping a pipe that is given to us.
- // We don't support these:
- // 2) It's for a named channel.
- // 3) It's for a client that we implement ourself.
- // 4) It's the initial IPC channel.
-
- if (channel_handle.socket.fd == -1) {
- NOTIMPLEMENTED();
- return false;
- }
- pipe_ = channel_handle.socket.fd;
- return true;
+bool Channel::ChannelImpl::GetClientEuid(uid_t* client_euid) const {
+ NOTIMPLEMENTED();
+ return false;
}
-bool Channel::ChannelImpl::ProcessOutgoingMessages() {
- DCHECK(!waiting_connect_); // Why are we trying to send messages if there's
- // no connection?
- if (output_queue_.empty())
- return true;
-
- if (pipe_ == -1)
- return false;
-
- // Write out all the messages. The trusted implementation is guaranteed to not
- // block. See NaClIPCAdapter::Send for the implementation of imc_sendmsg.
- while (!output_queue_.empty()) {
- linked_ptr<Message> msg = output_queue_.front();
- output_queue_.pop_front();
-
- struct NaClImcMsgHdr msgh = {0};
- struct NaClImcMsgIoVec iov = {const_cast<void*>(msg->data()), msg->size()};
- msgh.iov = &iov;
- msgh.iov_length = 1;
- ssize_t bytes_written = imc_sendmsg(pipe_, &msgh, 0);
-
- if (bytes_written < 0) {
- // The trusted side should only ever give us an error of EPIPE. We
- // should never be interrupted, nor should we get EAGAIN.
- DCHECK(errno == EPIPE);
- Close();
- PLOG(ERROR) << "pipe_ error on "
- << pipe_
- << " Currently writing message of size: "
- << msg->size();
- return false;
- }
-
- // Message sent OK!
- DVLOG(2) << "sent message @" << msg.get() << " with type " << msg->type()
- << " on fd " << pipe_;
- }
- return true;
+void Channel::ChannelImpl::ResetToAcceptingConnectionState() {
+ NOTIMPLEMENTED();
}
-Channel::ChannelImpl::ReadState Channel::ChannelImpl::ReadData(
- char* buffer,
- int buffer_len,
- int* bytes_read) {
- *bytes_read = 0;
- if (pipe_ == -1)
- return READ_FAILED;
- if (read_queue_.empty())
- return READ_PENDING;
- while (!read_queue_.empty() && *bytes_read < buffer_len) {
- linked_ptr<std::vector<char> > vec(read_queue_.front());
- int bytes_to_read = buffer_len - *bytes_read;
- if (vec->size() <= bytes_to_read) {
- // We can read and discard the entire vector.
- std::copy(vec->begin(), vec->end(), buffer + *bytes_read);
- *bytes_read += vec->size();
- read_queue_.pop_front();
- } else {
- // Read all the bytes we can and discard them from the front of the
- // vector. (This can be slowish, since erase has to move the back of the
- // vector to the front, but it's hopefully a temporary hack and it keeps
- // the code simple).
- std::copy(vec->begin(), vec->begin() + bytes_to_read,
- buffer + *bytes_read);
- vec->erase(vec->begin(), vec->begin() + bytes_to_read);
- *bytes_read += bytes_to_read;
- }
- }
- return READ_SUCCEEDED;
+Channel::ChannelImpl::ReadState
+ Channel::ChannelImpl::ReadData(char* buffer,
+ int buffer_len,
+ int* bytes_read) {
+ return Channel::ChannelImpl::ReadState();
}
bool Channel::ChannelImpl::WillDispatchInputMessage(Message* msg) {
- return true;
+ return false;
}
bool Channel::ChannelImpl::DidEmptyInputBuffers() {
- return true;
+ return false;
}
void Channel::ChannelImpl::HandleHelloMessage(const Message& msg) {
- // The trusted side IPC::Channel should handle the "hello" handshake; we
- // should not receive the "Hello" message.
- NOTREACHED();
+}
+
+// static
+bool Channel::ChannelImpl::IsNamedServerInitialized(
+ const std::string& channel_id) {
+ return false; //file_util::PathExists(FilePath(channel_id));
}
//------------------------------------------------------------------------------
@@ -328,16 +113,41 @@ void Channel::set_listener(Listener* listener) {
channel_impl_->set_listener(listener);
}
-base::ProcessId Channel::peer_pid() const {
- // This shouldn't actually get used in the untrusted side of the proxy, and we
- // don't have the real pid anyway.
- return -1;
-}
-
bool Channel::Send(Message* message) {
return channel_impl_->Send(message);
}
+int Channel::GetClientFileDescriptor() const {
+ return channel_impl_->GetClientFileDescriptor();
+}
+
+int Channel::TakeClientFileDescriptor() {
+ return channel_impl_->TakeClientFileDescriptor();
+}
+
+bool Channel::AcceptsConnections() const {
+ return channel_impl_->AcceptsConnections();
+}
+
+bool Channel::HasAcceptedConnection() const {
+ return channel_impl_->HasAcceptedConnection();
+}
+
+bool Channel::GetClientEuid(uid_t* client_euid) const {
+ return channel_impl_->GetClientEuid(client_euid);
+}
+
+void Channel::ResetToAcceptingConnectionState() {
+ channel_impl_->ResetToAcceptingConnectionState();
+}
+
+base::ProcessId Channel::peer_pid() const { return 0; }
+
+// static
+bool Channel::IsNamedServerInitialized(const std::string& channel_id) {
+ return ChannelImpl::IsNamedServerInitialized(channel_id);
+}
+
// static
std::string Channel::GenerateVerifiedChannelID(const std::string& prefix) {
// A random name is sufficient validation on posix systems, so we don't need
diff --git a/ipc/ipc_channel_nacl.h b/ipc/ipc_channel_nacl.h
index 84f4ef7..2747263 100644
--- a/ipc/ipc_channel_nacl.h
+++ b/ipc/ipc_channel_nacl.h
@@ -6,31 +6,17 @@
#define IPC_IPC_CHANNEL_NACL_H_
#pragma once
-#include <deque>
-#include <string>
-
-#include "base/memory/linked_ptr.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/memory/weak_ptr.h"
-#include "base/process.h"
-#include "base/threading/simple_thread.h"
#include "ipc/ipc_channel.h"
#include "ipc/ipc_channel_reader.h"
namespace IPC {
// Similar to the Posix version of ChannelImpl but for Native Client code.
-// This is somewhat different because sendmsg/recvmsg here do not follow POSIX
-// semantics. Instead, they are implemented by a custom embedding of
-// NaClDescCustom. See NaClIPCAdapter for the trusted-side implementation.
-//
-// We don't need to worry about complicated set up and READWRITE mode for
-// sharing handles. We also currently do not support passing file descriptors or
-// named pipes, and we use background threads to emulate signaling when we can
-// read or write without blocking.
+// This is somewhat different because NaCl's send/recvmsg is slightly different
+// and we don't need to worry about complicated set up and READWRITE mode for
+// sharing handles.
class Channel::ChannelImpl : public internal::ChannelReader {
public:
- // Mirror methods of Channel, see ipc_channel.h for description.
ChannelImpl(const IPC::ChannelHandle& channel_handle,
Mode mode,
Listener* listener);
@@ -40,18 +26,14 @@ class Channel::ChannelImpl : public internal::ChannelReader {
bool Connect();
void Close();
bool Send(Message* message);
+ int GetClientFileDescriptor() const;
+ int TakeClientFileDescriptor();
+ bool AcceptsConnections() const;
+ bool HasAcceptedConnection() const;
+ bool GetClientEuid(uid_t* client_euid) const;
+ void ResetToAcceptingConnectionState();
+ static bool IsNamedServerInitialized(const std::string& channel_id);
- // Posted to the main thread by ReaderThreadRunner.
- void DidRecvMsg(scoped_ptr<std::vector<char> > buffer);
- void ReadDidFail();
-
- private:
- class ReaderThreadRunner;
-
- bool CreatePipe(const IPC::ChannelHandle& channel_handle);
- bool ProcessOutgoingMessages();
-
- // ChannelReader implementation.
virtual ReadState ReadData(char* buffer,
int buffer_len,
int* bytes_read) OVERRIDE;
@@ -59,47 +41,7 @@ class Channel::ChannelImpl : public internal::ChannelReader {
virtual bool DidEmptyInputBuffers() OVERRIDE;
virtual void HandleHelloMessage(const Message& msg) OVERRIDE;
- Mode mode_;
- bool waiting_connect_;
-
- // The pipe used for communication.
- int pipe_;
-
- // The "name" of our pipe. On Windows this is the global identifier for
- // the pipe. On POSIX it's used as a key in a local map of file descriptors.
- // For NaCl, we don't actually support looking up file descriptors by name,
- // and it's only used for debug information.
- std::string pipe_name_;
-
- // We use a thread for reading, so that we can simply block on reading and
- // post the received data back to the main thread to be properly interleaved
- // with other tasks in the MessagePump.
- //
- // imc_recvmsg supports non-blocking reads, but there's no easy way to be
- // informed when a write or read can be done without blocking (this is handled
- // by libevent in Posix).
- scoped_ptr<ReaderThreadRunner> reader_thread_runner_;
- scoped_ptr<base::DelegateSimpleThread> reader_thread_;
-
- // IPC::ChannelReader expects to be able to call ReadData on us to
- // synchronously read data waiting in the pipe's buffer without blocking.
- // Since we can't do that (see 1 and 2 above), the reader thread does blocking
- // reads and posts the data over to the main thread in byte vectors. Each byte
- // vector is the result of one call to "recvmsg". When ReadData is called, it
- // pulls the bytes out of these vectors in order.
- // TODO(dmichael): There's probably a more efficient way to emulate this with
- // a circular buffer or something, so we don't have to do so
- // many heap allocations. But it maybe isn't worth
- // the trouble given that we probably want to implement 1 and
- // 2 above in NaCl eventually.
- std::deque<linked_ptr<std::vector<char> > > read_queue_;
-
- // This queue is used when a message is sent prior to Connect having been
- // called. Normally after we're connected, the queue is empty.
- std::deque<linked_ptr<Message> > output_queue_;
-
- base::WeakPtrFactory<ChannelImpl> weak_ptr_factory_;
-
+ private:
DISALLOW_IMPLICIT_CONSTRUCTORS(ChannelImpl);
};
diff --git a/ipc/ipc_channel_proxy.cc b/ipc/ipc_channel_proxy.cc
index b9cc79c..3f0afa1 100644
--- a/ipc/ipc_channel_proxy.cc
+++ b/ipc/ipc_channel_proxy.cc
@@ -367,7 +367,7 @@ void ChannelProxy::ClearIPCMessageLoop() {
context()->ClearIPCMessageLoop();
}
-#if defined(OS_POSIX) && !defined(OS_NACL)
+#if defined(OS_POSIX)
// See the TODO regarding lazy initialization of the channel in
// ChannelProxy::Init().
int ChannelProxy::GetClientFileDescriptor() {
diff --git a/ipc/ipc_channel_proxy.h b/ipc/ipc_channel_proxy.h
index 6f5b96f..8c0031a 100644
--- a/ipc/ipc_channel_proxy.h
+++ b/ipc/ipc_channel_proxy.h
@@ -179,7 +179,7 @@ class IPC_EXPORT ChannelProxy : public Message::Sender {
// Returns base::kNullProcessId if the peer is not connected yet.
base::ProcessId peer_pid() const { return context_->peer_pid_; }
-#if defined(OS_POSIX) && !defined(OS_NACL)
+#if defined(OS_POSIX)
// Calls through to the underlying channel's methods.
int GetClientFileDescriptor();
int TakeClientFileDescriptor();
diff --git a/ppapi/ppapi_proxy_untrusted.gypi b/ppapi/ppapi_proxy_untrusted.gypi
index ac60926..c6d117a 100644
--- a/ppapi/ppapi_proxy_untrusted.gypi
+++ b/ppapi/ppapi_proxy_untrusted.gypi
@@ -193,7 +193,6 @@
'type': 'none',
'dependencies': [
'base_untrusted',
- '<(DEPTH)/native_client/src/untrusted/nacl/nacl.gyp:imc_syscalls_lib',
],
'variables': {
'nlib_target': 'libipc_untrusted.a',
diff --git a/ppapi/proxy/proxy_channel.cc b/ppapi/proxy/proxy_channel.cc
index f5743e8..c67d83c 100644
--- a/ppapi/proxy/proxy_channel.cc
+++ b/ppapi/proxy/proxy_channel.cc
@@ -40,7 +40,7 @@ void ProxyChannel::OnChannelError() {
channel_.reset();
}
-#if defined(OS_POSIX) && !defined(OS_NACL)
+#if defined(OS_POSIX)
int ProxyChannel::TakeRendererFD() {
DCHECK(channel());
return channel()->TakeClientFileDescriptor();
diff --git a/ppapi/proxy/proxy_channel.h b/ppapi/proxy/proxy_channel.h
index ffd3f2f..424da94 100644
--- a/ppapi/proxy/proxy_channel.h
+++ b/ppapi/proxy/proxy_channel.h
@@ -78,7 +78,7 @@ class PPAPI_PROXY_EXPORT ProxyChannel
return channel_.get();
}
-#if defined(OS_POSIX) && !defined(OS_NACL)
+#if defined(OS_POSIX)
int TakeRendererFD();
#endif