diff options
author | rch@chromium.org <rch@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-05-30 22:02:24 +0000 |
---|---|---|
committer | rch@chromium.org <rch@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-05-30 22:02:24 +0000 |
commit | 800c8d730fc85e7bf9b548947f5842828346c485 (patch) | |
tree | 3522f743ae1e8d474278af6ca28e4a0183de4175 /ipc/ipc_channel_nacl.cc | |
parent | 6c64593b006e833c6712c534acccbb2b79126135 (diff) | |
download | chromium_src-800c8d730fc85e7bf9b548947f5842828346c485.zip chromium_src-800c8d730fc85e7bf9b548947f5842828346c485.tar.gz chromium_src-800c8d730fc85e7bf9b548947f5842828346c485.tar.bz2 |
Revert 139635 - PPAPI/NaCl: Speculative implementation for ipc_channel_nacl.cc
BUG=116317
TEST=
Review URL: https://chromiumcodereview.appspot.com/10174048
TBR=dmichael@chromium.org
Review URL: https://chromiumcodereview.appspot.com/10456039
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@139646 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ipc/ipc_channel_nacl.cc')
-rw-r--r-- | ipc/ipc_channel_nacl.cc | 336 |
1 files changed, 73 insertions, 263 deletions
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 |