1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "ipc/ipc_channel_nacl.h"
9 #include <sys/nacl_imc_api.h>
10 #include <sys/nacl_syscalls.h>
11 #include <sys/types.h>
15 #include "base/bind.h"
16 #include "base/file_util.h"
17 #include "base/logging.h"
18 #include "base/message_loop_proxy.h"
19 #include "base/process_util.h"
20 #include "base/synchronization/lock.h"
21 #include "base/task_runner_util.h"
22 #include "base/threading/simple_thread.h"
23 #include "ipc/file_descriptor_set_posix.h"
24 #include "ipc/ipc_logging.h"
28 struct MessageContents
{
29 std::vector
<char> data
;
35 bool ReadDataOnReaderThread(int pipe
, MessageContents
* contents
) {
40 contents
->data
.resize(Channel::kReadBufferSize
);
41 contents
->fds
.resize(FileDescriptorSet::kMaxDescriptorsPerMessage
);
43 NaClImcMsgIoVec iov
= { &contents
->data
[0], contents
->data
.size() };
44 NaClImcMsgHdr msg
= { &iov
, 1, &contents
->fds
[0], contents
->fds
.size() };
46 int bytes_read
= imc_recvmsg(pipe
, &msg
, 0);
48 if (bytes_read
<= 0) {
49 // NaClIPCAdapter::BlockingReceive returns -1 when the pipe closes (either
50 // due to error or for regular shutdown).
51 contents
->data
.clear();
52 contents
->fds
.clear();
56 // Resize the buffers down to the number of bytes and fds we actually read.
57 contents
->data
.resize(bytes_read
);
58 contents
->fds
.resize(msg
.desc_length
);
64 class Channel::ChannelImpl::ReaderThreadRunner
65 : public base::DelegateSimpleThread::Delegate
{
67 // |pipe|: A file descriptor from which we will read using imc_recvmsg.
68 // |data_read_callback|: A callback we invoke (on the main thread) when we
70 // |failure_callback|: A callback we invoke when we have a failure reading
72 // |main_message_loop|: A proxy for the main thread, where we will invoke the
76 base::Callback
<void (scoped_ptr
<MessageContents
>)> data_read_callback
,
77 base::Callback
<void ()> failure_callback
,
78 scoped_refptr
<base::MessageLoopProxy
> main_message_loop
);
80 // DelegateSimpleThread implementation. Reads data from the pipe in a loop
81 // until either we are told to quit or a read fails.
82 virtual void Run() OVERRIDE
;
86 base::Callback
<void (scoped_ptr
<MessageContents
>)> data_read_callback_
;
87 base::Callback
<void ()> failure_callback_
;
88 scoped_refptr
<base::MessageLoopProxy
> main_message_loop_
;
90 DISALLOW_COPY_AND_ASSIGN(ReaderThreadRunner
);
93 Channel::ChannelImpl::ReaderThreadRunner::ReaderThreadRunner(
95 base::Callback
<void (scoped_ptr
<MessageContents
>)> data_read_callback
,
96 base::Callback
<void ()> failure_callback
,
97 scoped_refptr
<base::MessageLoopProxy
> main_message_loop
)
99 data_read_callback_(data_read_callback
),
100 failure_callback_(failure_callback
),
101 main_message_loop_(main_message_loop
) {
104 void Channel::ChannelImpl::ReaderThreadRunner::Run() {
106 scoped_ptr
<MessageContents
> msg_contents(new MessageContents
);
107 bool success
= ReadDataOnReaderThread(pipe_
, msg_contents
.get());
109 main_message_loop_
->PostTask(FROM_HERE
,
110 base::Bind(data_read_callback_
, base::Passed(&msg_contents
)));
112 main_message_loop_
->PostTask(FROM_HERE
, failure_callback_
);
113 // Because the read failed, we know we're going to quit. Don't bother
114 // trying to read again.
120 Channel::ChannelImpl::ChannelImpl(const IPC::ChannelHandle
& channel_handle
,
123 : ChannelReader(listener
),
125 waiting_connect_(true),
127 pipe_name_(channel_handle
.name
),
128 weak_ptr_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {
129 if (!CreatePipe(channel_handle
)) {
130 // The pipe may have been closed already.
131 const char *modestr
= (mode_
& MODE_SERVER_FLAG
) ? "server" : "client";
132 LOG(WARNING
) << "Unable to create pipe named \"" << channel_handle
.name
133 << "\" in " << modestr
<< " mode";
137 Channel::ChannelImpl::~ChannelImpl() {
141 bool Channel::ChannelImpl::Connect() {
143 DLOG(INFO
) << "Channel creation failed: " << pipe_name_
;
147 // Note that Connect is called on the "Channel" thread (i.e., the same thread
148 // where Channel::Send will be called, and the same thread that should receive
149 // messages). The constructor might be invoked on another thread (see
150 // ChannelProxy for an example of that). Therefore, we must wait until Connect
151 // is called to decide which MessageLoopProxy to pass to ReaderThreadRunner.
152 reader_thread_runner_
.reset(
153 new ReaderThreadRunner(
155 base::Bind(&Channel::ChannelImpl::DidRecvMsg
,
156 weak_ptr_factory_
.GetWeakPtr()),
157 base::Bind(&Channel::ChannelImpl::ReadDidFail
,
158 weak_ptr_factory_
.GetWeakPtr()),
159 base::MessageLoopProxy::current()));
160 reader_thread_
.reset(
161 new base::DelegateSimpleThread(reader_thread_runner_
.get(),
162 "ipc_channel_nacl reader thread"));
163 reader_thread_
->Start();
164 waiting_connect_
= false;
165 // If there were any messages queued before connection, send them.
166 ProcessOutgoingMessages();
170 void Channel::ChannelImpl::Close() {
171 // For now, we assume that at shutdown, the reader thread will be woken with
172 // a failure (see NaClIPCAdapter::BlockingRead and CloseChannel). Or... we
173 // might simply be killed with no chance to clean up anyway :-).
174 // If untrusted code tries to close the channel prior to shutdown, it's likely
176 // TODO(dmichael): Can we do anything smarter here to make sure the reader
177 // thread wakes up and quits?
178 reader_thread_
->Join();
181 reader_thread_runner_
.reset();
182 reader_thread_
.reset();
184 output_queue_
.clear();
187 bool Channel::ChannelImpl::Send(Message
* message
) {
188 DVLOG(2) << "sending message @" << message
<< " on channel @" << this
189 << " with type " << message
->type();
190 scoped_ptr
<Message
> message_ptr(message
);
192 #ifdef IPC_MESSAGE_LOG_ENABLED
193 Logging::GetInstance()->OnSendMessage(message_ptr
.get(), "");
194 #endif // IPC_MESSAGE_LOG_ENABLED
196 message
->TraceMessageBegin();
197 output_queue_
.push_back(linked_ptr
<Message
>(message_ptr
.release()));
198 if (!waiting_connect_
)
199 return ProcessOutgoingMessages();
204 void Channel::ChannelImpl::DidRecvMsg(scoped_ptr
<MessageContents
> contents
) {
205 // Close sets the pipe to -1. It's possible we'll get a buffer sent to us from
206 // the reader thread after Close is called. If so, we ignore it.
210 linked_ptr
<std::vector
<char> > data(new std::vector
<char>);
211 data
->swap(contents
->data
);
212 read_queue_
.push_back(data
);
214 input_fds_
.insert(input_fds_
.end(),
215 contents
->fds
.begin(), contents
->fds
.end());
216 contents
->fds
.clear();
218 // In POSIX, we would be told when there are bytes to read by implementing
219 // OnFileCanReadWithoutBlocking in MessageLoopForIO::Watcher. In NaCl, we
220 // instead know at this point because the reader thread posted some data to
222 ProcessIncomingMessages();
225 void Channel::ChannelImpl::ReadDidFail() {
229 bool Channel::ChannelImpl::CreatePipe(
230 const IPC::ChannelHandle
& channel_handle
) {
233 // There's one possible case in NaCl:
234 // 1) It's a channel wrapping a pipe that is given to us.
235 // We don't support these:
236 // 2) It's for a named channel.
237 // 3) It's for a client that we implement ourself.
238 // 4) It's the initial IPC channel.
240 if (channel_handle
.socket
.fd
== -1) {
244 pipe_
= channel_handle
.socket
.fd
;
248 bool Channel::ChannelImpl::ProcessOutgoingMessages() {
249 DCHECK(!waiting_connect_
); // Why are we trying to send messages if there's
251 if (output_queue_
.empty())
257 // Write out all the messages. The trusted implementation is guaranteed to not
258 // block. See NaClIPCAdapter::Send for the implementation of imc_sendmsg.
259 while (!output_queue_
.empty()) {
260 linked_ptr
<Message
> msg
= output_queue_
.front();
261 output_queue_
.pop_front();
263 int fds
[FileDescriptorSet::kMaxDescriptorsPerMessage
];
264 const size_t num_fds
= msg
->file_descriptor_set()->size();
265 DCHECK(num_fds
<= FileDescriptorSet::kMaxDescriptorsPerMessage
);
266 msg
->file_descriptor_set()->GetDescriptors(fds
);
268 NaClImcMsgIoVec iov
= { const_cast<void*>(msg
->data()), msg
->size() };
269 NaClImcMsgHdr msgh
= { &iov
, 1, fds
, num_fds
};
270 ssize_t bytes_written
= imc_sendmsg(pipe_
, &msgh
, 0);
272 DCHECK(bytes_written
); // The trusted side shouldn't return 0.
273 if (bytes_written
< 0) {
274 // The trusted side should only ever give us an error of EPIPE. We
275 // should never be interrupted, nor should we get EAGAIN.
276 DCHECK(errno
== EPIPE
);
278 PLOG(ERROR
) << "pipe_ error on "
280 << " Currently writing message of size: "
284 msg
->file_descriptor_set()->CommitAll();
288 DVLOG(2) << "sent message @" << msg
.get() << " with type " << msg
->type()
289 << " on fd " << pipe_
;
294 Channel::ChannelImpl::ReadState
Channel::ChannelImpl::ReadData(
301 if (read_queue_
.empty())
303 while (!read_queue_
.empty() && *bytes_read
< buffer_len
) {
304 linked_ptr
<std::vector
<char> > vec(read_queue_
.front());
305 size_t bytes_to_read
= buffer_len
- *bytes_read
;
306 if (vec
->size() <= bytes_to_read
) {
307 // We can read and discard the entire vector.
308 std::copy(vec
->begin(), vec
->end(), buffer
+ *bytes_read
);
309 *bytes_read
+= vec
->size();
310 read_queue_
.pop_front();
312 // Read all the bytes we can and discard them from the front of the
313 // vector. (This can be slowish, since erase has to move the back of the
314 // vector to the front, but it's hopefully a temporary hack and it keeps
316 std::copy(vec
->begin(), vec
->begin() + bytes_to_read
,
317 buffer
+ *bytes_read
);
318 vec
->erase(vec
->begin(), vec
->begin() + bytes_to_read
);
319 *bytes_read
+= bytes_to_read
;
322 return READ_SUCCEEDED
;
325 bool Channel::ChannelImpl::WillDispatchInputMessage(Message
* msg
) {
326 uint16 header_fds
= msg
->header()->num_fds
;
327 CHECK(header_fds
== input_fds_
.size());
329 return true; // Nothing to do.
331 // The shenaniganery below with &foo.front() requires input_fds_ to have
332 // contiguous underlying storage (such as a simple array or a std::vector).
333 // This is why the header warns not to make input_fds_ a deque<>.
334 msg
->file_descriptor_set()->SetDescriptors(&input_fds_
.front(),
340 bool Channel::ChannelImpl::DidEmptyInputBuffers() {
341 // When the input data buffer is empty, the fds should be too.
342 return input_fds_
.empty();
345 void Channel::ChannelImpl::HandleHelloMessage(const Message
& msg
) {
346 // The trusted side IPC::Channel should handle the "hello" handshake; we
347 // should not receive the "Hello" message.
351 //------------------------------------------------------------------------------
352 // Channel's methods simply call through to ChannelImpl.
354 Channel::Channel(const IPC::ChannelHandle
& channel_handle
,
357 : channel_impl_(new ChannelImpl(channel_handle
, mode
, listener
)) {
360 Channel::~Channel() {
361 delete channel_impl_
;
364 bool Channel::Connect() {
365 return channel_impl_
->Connect();
368 void Channel::Close() {
369 channel_impl_
->Close();
372 base::ProcessId
Channel::peer_pid() const {
373 // This shouldn't actually get used in the untrusted side of the proxy, and we
374 // don't have the real pid anyway.
378 bool Channel::Send(Message
* message
) {
379 return channel_impl_
->Send(message
);