Fix SplitRange() logic in SourceBufferRange to transfer next buffer position appropri...
[chromium-blink-merge.git] / ipc / ipc_channel_nacl.cc
blob628b8a163d02617d459d9411e4d0b0655c656fef
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"
7 #include <errno.h>
8 #include <stddef.h>
9 #include <sys/nacl_imc_api.h>
10 #include <sys/nacl_syscalls.h>
11 #include <sys/types.h>
13 #include <algorithm>
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"
26 namespace IPC {
28 struct MessageContents {
29 std::vector<char> data;
30 std::vector<int> fds;
33 namespace {
35 bool ReadDataOnReaderThread(int pipe, MessageContents* contents) {
36 DCHECK(pipe >= 0);
37 if (pipe < 0)
38 return false;
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();
53 return false;
55 DCHECK(bytes_read);
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);
59 return true;
62 } // namespace
64 class Channel::ChannelImpl::ReaderThreadRunner
65 : public base::DelegateSimpleThread::Delegate {
66 public:
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
69 // have read data.
70 // |failure_callback|: A callback we invoke when we have a failure reading
71 // from |pipe|.
72 // |main_message_loop|: A proxy for the main thread, where we will invoke the
73 // above callbacks.
74 ReaderThreadRunner(
75 int pipe,
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;
84 private:
85 int pipe_;
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(
94 int pipe,
95 base::Callback<void (scoped_ptr<MessageContents>)> data_read_callback,
96 base::Callback<void ()> failure_callback,
97 scoped_refptr<base::MessageLoopProxy> main_message_loop)
98 : pipe_(pipe),
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() {
105 while (true) {
106 scoped_ptr<MessageContents> msg_contents(new MessageContents);
107 bool success = ReadDataOnReaderThread(pipe_, msg_contents.get());
108 if (success) {
109 main_message_loop_->PostTask(FROM_HERE,
110 base::Bind(data_read_callback_, base::Passed(msg_contents.Pass())));
111 } else {
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.
115 return;
120 Channel::ChannelImpl::ChannelImpl(const IPC::ChannelHandle& channel_handle,
121 Mode mode,
122 Listener* listener)
123 : ChannelReader(listener),
124 mode_(mode),
125 waiting_connect_(true),
126 pipe_(-1),
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() {
138 Close();
141 bool Channel::ChannelImpl::Connect() {
142 if (pipe_ == -1) {
143 DLOG(INFO) << "Channel creation failed: " << pipe_name_;
144 return false;
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(
154 pipe_,
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();
167 return true;
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
175 // to hang.
176 // TODO(dmichael): Can we do anything smarter here to make sure the reader
177 // thread wakes up and quits?
178 reader_thread_->Join();
179 close(pipe_);
180 pipe_ = -1;
181 reader_thread_runner_.reset();
182 reader_thread_.reset();
183 read_queue_.clear();
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 output_queue_.push_back(linked_ptr<Message>(message_ptr.release()));
197 if (!waiting_connect_)
198 return ProcessOutgoingMessages();
200 return true;
203 void Channel::ChannelImpl::DidRecvMsg(scoped_ptr<MessageContents> contents) {
204 // Close sets the pipe to -1. It's possible we'll get a buffer sent to us from
205 // the reader thread after Close is called. If so, we ignore it.
206 if (pipe_ == -1)
207 return;
209 linked_ptr<std::vector<char> > data(new std::vector<char>);
210 data->swap(contents->data);
211 read_queue_.push_back(data);
213 input_fds_.insert(input_fds_.end(),
214 contents->fds.begin(), contents->fds.end());
215 contents->fds.clear();
217 // In POSIX, we would be told when there are bytes to read by implementing
218 // OnFileCanReadWithoutBlocking in MessageLoopForIO::Watcher. In NaCl, we
219 // instead know at this point because the reader thread posted some data to
220 // us.
221 ProcessIncomingMessages();
224 void Channel::ChannelImpl::ReadDidFail() {
225 Close();
228 bool Channel::ChannelImpl::CreatePipe(
229 const IPC::ChannelHandle& channel_handle) {
230 DCHECK(pipe_ == -1);
232 // There's one possible case in NaCl:
233 // 1) It's a channel wrapping a pipe that is given to us.
234 // We don't support these:
235 // 2) It's for a named channel.
236 // 3) It's for a client that we implement ourself.
237 // 4) It's the initial IPC channel.
239 if (channel_handle.socket.fd == -1) {
240 NOTIMPLEMENTED();
241 return false;
243 pipe_ = channel_handle.socket.fd;
244 return true;
247 bool Channel::ChannelImpl::ProcessOutgoingMessages() {
248 DCHECK(!waiting_connect_); // Why are we trying to send messages if there's
249 // no connection?
250 if (output_queue_.empty())
251 return true;
253 if (pipe_ == -1)
254 return false;
256 // Write out all the messages. The trusted implementation is guaranteed to not
257 // block. See NaClIPCAdapter::Send for the implementation of imc_sendmsg.
258 while (!output_queue_.empty()) {
259 linked_ptr<Message> msg = output_queue_.front();
260 output_queue_.pop_front();
262 int fds[FileDescriptorSet::kMaxDescriptorsPerMessage];
263 const int num_fds = msg->file_descriptor_set()->size();
264 DCHECK(num_fds <= FileDescriptorSet::kMaxDescriptorsPerMessage);
265 msg->file_descriptor_set()->GetDescriptors(fds);
267 NaClImcMsgIoVec iov = { const_cast<void*>(msg->data()), msg->size() };
268 NaClImcMsgHdr msgh = { &iov, 1, fds, num_fds };
269 ssize_t bytes_written = imc_sendmsg(pipe_, &msgh, 0);
271 DCHECK(bytes_written); // The trusted side shouldn't return 0.
272 if (bytes_written < 0) {
273 // The trusted side should only ever give us an error of EPIPE. We
274 // should never be interrupted, nor should we get EAGAIN.
275 DCHECK(errno == EPIPE);
276 Close();
277 PLOG(ERROR) << "pipe_ error on "
278 << pipe_
279 << " Currently writing message of size: "
280 << msg->size();
281 return false;
282 } else {
283 msg->file_descriptor_set()->CommitAll();
286 // Message sent OK!
287 DVLOG(2) << "sent message @" << msg.get() << " with type " << msg->type()
288 << " on fd " << pipe_;
290 return true;
293 Channel::ChannelImpl::ReadState Channel::ChannelImpl::ReadData(
294 char* buffer,
295 int buffer_len,
296 int* bytes_read) {
297 *bytes_read = 0;
298 if (pipe_ == -1)
299 return READ_FAILED;
300 if (read_queue_.empty())
301 return READ_PENDING;
302 while (!read_queue_.empty() && *bytes_read < buffer_len) {
303 linked_ptr<std::vector<char> > vec(read_queue_.front());
304 int bytes_to_read = buffer_len - *bytes_read;
305 if (vec->size() <= bytes_to_read) {
306 // We can read and discard the entire vector.
307 std::copy(vec->begin(), vec->end(), buffer + *bytes_read);
308 *bytes_read += vec->size();
309 read_queue_.pop_front();
310 } else {
311 // Read all the bytes we can and discard them from the front of the
312 // vector. (This can be slowish, since erase has to move the back of the
313 // vector to the front, but it's hopefully a temporary hack and it keeps
314 // the code simple).
315 std::copy(vec->begin(), vec->begin() + bytes_to_read,
316 buffer + *bytes_read);
317 vec->erase(vec->begin(), vec->begin() + bytes_to_read);
318 *bytes_read += bytes_to_read;
321 return READ_SUCCEEDED;
324 bool Channel::ChannelImpl::WillDispatchInputMessage(Message* msg) {
325 uint16 header_fds = msg->header()->num_fds;
326 CHECK(header_fds == input_fds_.size());
327 if (header_fds == 0)
328 return true; // Nothing to do.
330 // The shenaniganery below with &foo.front() requires input_fds_ to have
331 // contiguous underlying storage (such as a simple array or a std::vector).
332 // This is why the header warns not to make input_fds_ a deque<>.
333 msg->file_descriptor_set()->SetDescriptors(&input_fds_.front(),
334 header_fds);
335 input_fds_.clear();
336 return true;
339 bool Channel::ChannelImpl::DidEmptyInputBuffers() {
340 // When the input data buffer is empty, the fds should be too.
341 return input_fds_.empty();
344 void Channel::ChannelImpl::HandleHelloMessage(const Message& msg) {
345 // The trusted side IPC::Channel should handle the "hello" handshake; we
346 // should not receive the "Hello" message.
347 NOTREACHED();
350 //------------------------------------------------------------------------------
351 // Channel's methods simply call through to ChannelImpl.
353 Channel::Channel(const IPC::ChannelHandle& channel_handle,
354 Mode mode,
355 Listener* listener)
356 : channel_impl_(new ChannelImpl(channel_handle, mode, listener)) {
359 Channel::~Channel() {
360 delete channel_impl_;
363 bool Channel::Connect() {
364 return channel_impl_->Connect();
367 void Channel::Close() {
368 channel_impl_->Close();
371 void Channel::set_listener(Listener* listener) {
372 channel_impl_->set_listener(listener);
375 base::ProcessId Channel::peer_pid() const {
376 // This shouldn't actually get used in the untrusted side of the proxy, and we
377 // don't have the real pid anyway.
378 return -1;
381 bool Channel::Send(Message* message) {
382 return channel_impl_->Send(message);
385 // static
386 std::string Channel::GenerateVerifiedChannelID(const std::string& prefix) {
387 // A random name is sufficient validation on posix systems, so we don't need
388 // an additional shared secret.
389 std::string id = prefix;
390 if (!id.empty())
391 id.append(".");
393 return id.append(GenerateUniqueRandomChannelID());
396 } // namespace IPC