OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "ipc/ipc_channel_nacl.h" | 5 #include "ipc/ipc_channel_nacl.h" |
6 | 6 |
7 #include <errno.h> | 7 #include <errno.h> |
8 #include <stddef.h> | 8 #include <stddef.h> |
9 #include <sys/nacl_imc_api.h> | 9 #include <sys/nacl_imc_api.h> |
10 #include <sys/nacl_syscalls.h> | 10 #include <sys/nacl_syscalls.h> |
11 #include <sys/types.h> | 11 #include <sys/types.h> |
12 | 12 |
13 #include <algorithm> | 13 #include <algorithm> |
14 | 14 |
15 #include "base/bind.h" | 15 #include "base/bind.h" |
16 #include "base/file_util.h" | 16 #include "base/file_util.h" |
17 #include "base/logging.h" | 17 #include "base/logging.h" |
18 #include "base/message_loop_proxy.h" | 18 #include "base/message_loop_proxy.h" |
19 #include "base/process_util.h" | 19 #include "base/process_util.h" |
20 #include "base/synchronization/lock.h" | 20 #include "base/synchronization/lock.h" |
21 #include "base/task_runner_util.h" | 21 #include "base/task_runner_util.h" |
22 #include "base/threading/simple_thread.h" | 22 #include "base/threading/simple_thread.h" |
23 #include "ipc/file_descriptor_set_posix.h" | 23 #include "ipc/file_descriptor_set_posix.h" |
24 #include "ipc/ipc_logging.h" | 24 #include "ipc/ipc_logging.h" |
25 | 25 |
26 namespace IPC { | 26 namespace IPC { |
| 27 |
| 28 struct MessageContents { |
| 29 std::vector<char> data; |
| 30 std::vector<int> fds; |
| 31 }; |
| 32 |
27 namespace { | 33 namespace { |
28 | 34 |
29 scoped_ptr<std::vector<char> > ReadDataOnReaderThread(int pipe) { | 35 bool ReadDataOnReaderThread(int pipe, MessageContents* contents) { |
30 DCHECK(pipe >= 0); | 36 DCHECK(pipe >= 0); |
| 37 if (pipe < 0) |
| 38 return false; |
31 | 39 |
32 if (pipe < 0) | 40 contents->data.resize(Channel::kReadBufferSize); |
33 return scoped_ptr<std::vector<char> >(); | 41 contents->fds.resize(FileDescriptorSet::kMaxDescriptorsPerMessage); |
34 | 42 |
35 scoped_ptr<std::vector<char> > buffer( | 43 NaClImcMsgIoVec iov = { &contents->data[0], contents->data.size() }; |
36 new std::vector<char>(Channel::kReadBufferSize)); | 44 NaClImcMsgHdr msg = { &iov, 1, &contents->fds[0], contents->fds.size() }; |
37 struct NaClImcMsgHdr msg = {0}; | |
38 struct NaClImcMsgIoVec iov = {&buffer->at(0), buffer->size()}; | |
39 msg.iov = &iov; | |
40 msg.iov_length = 1; | |
41 | 45 |
42 int bytes_read = imc_recvmsg(pipe, &msg, 0); | 46 int bytes_read = imc_recvmsg(pipe, &msg, 0); |
43 | 47 |
44 if (bytes_read <= 0) { | 48 if (bytes_read <= 0) { |
45 // NaClIPCAdapter::BlockingReceive returns -1 when the pipe closes (either | 49 // NaClIPCAdapter::BlockingReceive returns -1 when the pipe closes (either |
46 // due to error or for regular shutdown). | 50 // due to error or for regular shutdown). |
47 return scoped_ptr<std::vector<char> >(); | 51 contents->data.clear(); |
| 52 contents->fds.clear(); |
| 53 return false; |
48 } | 54 } |
49 DCHECK(bytes_read); | 55 DCHECK(bytes_read); |
50 buffer->resize(bytes_read); | 56 // Resize the buffers down to the number of bytes and fds we actually read. |
51 return buffer.Pass(); | 57 contents->data.resize(bytes_read); |
| 58 contents->fds.resize(msg.desc_length); |
| 59 return true; |
52 } | 60 } |
53 | 61 |
54 } // namespace | 62 } // namespace |
55 | 63 |
56 class Channel::ChannelImpl::ReaderThreadRunner | 64 class Channel::ChannelImpl::ReaderThreadRunner |
57 : public base::DelegateSimpleThread::Delegate { | 65 : public base::DelegateSimpleThread::Delegate { |
58 public: | 66 public: |
59 // |pipe|: A file descriptor from which we will read using imc_recvmsg. | 67 // |pipe|: A file descriptor from which we will read using imc_recvmsg. |
60 // |data_read_callback|: A callback we invoke (on the main thread) when we | 68 // |data_read_callback|: A callback we invoke (on the main thread) when we |
61 // have read data. The callback is passed a buffer of | 69 // have read data. |
62 // data that was read. | |
63 // |failure_callback|: A callback we invoke when we have a failure reading | 70 // |failure_callback|: A callback we invoke when we have a failure reading |
64 // from |pipe|. | 71 // from |pipe|. |
65 // |main_message_loop|: A proxy for the main thread, where we will invoke the | 72 // |main_message_loop|: A proxy for the main thread, where we will invoke the |
66 // above callbacks. | 73 // above callbacks. |
67 ReaderThreadRunner( | 74 ReaderThreadRunner( |
68 int pipe, | 75 int pipe, |
69 base::Callback<void (scoped_ptr<std::vector<char> >)> data_read_callback, | 76 base::Callback<void (scoped_ptr<MessageContents>)> data_read_callback, |
70 base::Callback<void ()> failure_callback, | 77 base::Callback<void ()> failure_callback, |
71 base::MessageLoopProxy* main_message_loop); | 78 scoped_refptr<base::MessageLoopProxy> main_message_loop); |
72 | 79 |
73 // DelegateSimpleThread implementation. Reads data from the pipe in a loop | 80 // DelegateSimpleThread implementation. Reads data from the pipe in a loop |
74 // until either we are told to quit or a read fails. | 81 // until either we are told to quit or a read fails. |
75 virtual void Run() OVERRIDE; | 82 virtual void Run() OVERRIDE; |
76 | 83 |
77 private: | 84 private: |
78 int pipe_; | 85 int pipe_; |
79 base::Callback<void (scoped_ptr<std::vector<char> >)> data_read_callback_; | 86 base::Callback<void (scoped_ptr<MessageContents>)> data_read_callback_; |
80 base::Callback<void ()> failure_callback_; | 87 base::Callback<void ()> failure_callback_; |
81 scoped_refptr<base::MessageLoopProxy> main_message_loop_; | 88 scoped_refptr<base::MessageLoopProxy> main_message_loop_; |
82 | 89 |
83 DISALLOW_COPY_AND_ASSIGN(ReaderThreadRunner); | 90 DISALLOW_COPY_AND_ASSIGN(ReaderThreadRunner); |
84 }; | 91 }; |
85 | 92 |
86 Channel::ChannelImpl::ReaderThreadRunner::ReaderThreadRunner( | 93 Channel::ChannelImpl::ReaderThreadRunner::ReaderThreadRunner( |
87 int pipe, | 94 int pipe, |
88 base::Callback<void (scoped_ptr<std::vector<char> >)> data_read_callback, | 95 base::Callback<void (scoped_ptr<MessageContents>)> data_read_callback, |
89 base::Callback<void ()> failure_callback, | 96 base::Callback<void ()> failure_callback, |
90 base::MessageLoopProxy* main_message_loop) | 97 scoped_refptr<base::MessageLoopProxy> main_message_loop) |
91 : pipe_(pipe), | 98 : pipe_(pipe), |
92 data_read_callback_(data_read_callback), | 99 data_read_callback_(data_read_callback), |
93 failure_callback_(failure_callback), | 100 failure_callback_(failure_callback), |
94 main_message_loop_(main_message_loop) { | 101 main_message_loop_(main_message_loop) { |
95 } | 102 } |
96 | 103 |
97 void Channel::ChannelImpl::ReaderThreadRunner::Run() { | 104 void Channel::ChannelImpl::ReaderThreadRunner::Run() { |
98 while (true) { | 105 while (true) { |
99 scoped_ptr<std::vector<char> > buffer(ReadDataOnReaderThread(pipe_)); | 106 scoped_ptr<MessageContents> msg_contents(new MessageContents); |
100 if (buffer.get()) { | 107 bool success = ReadDataOnReaderThread(pipe_, msg_contents.get()); |
| 108 if (success) { |
101 main_message_loop_->PostTask(FROM_HERE, | 109 main_message_loop_->PostTask(FROM_HERE, |
102 base::Bind(data_read_callback_, base::Passed(buffer.Pass()))); | 110 base::Bind(data_read_callback_, base::Passed(msg_contents.Pass()))); |
103 } else { | 111 } else { |
104 main_message_loop_->PostTask(FROM_HERE, failure_callback_); | 112 main_message_loop_->PostTask(FROM_HERE, failure_callback_); |
105 // Because the read failed, we know we're going to quit. Don't bother | 113 // Because the read failed, we know we're going to quit. Don't bother |
106 // trying to read again. | 114 // trying to read again. |
107 return; | 115 return; |
108 } | 116 } |
109 } | 117 } |
110 } | 118 } |
111 | 119 |
112 Channel::ChannelImpl::ChannelImpl(const IPC::ChannelHandle& channel_handle, | 120 Channel::ChannelImpl::ChannelImpl(const IPC::ChannelHandle& channel_handle, |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
180 Logging::GetInstance()->OnSendMessage(message_ptr.get(), ""); | 188 Logging::GetInstance()->OnSendMessage(message_ptr.get(), ""); |
181 #endif // IPC_MESSAGE_LOG_ENABLED | 189 #endif // IPC_MESSAGE_LOG_ENABLED |
182 | 190 |
183 output_queue_.push_back(linked_ptr<Message>(message_ptr.release())); | 191 output_queue_.push_back(linked_ptr<Message>(message_ptr.release())); |
184 if (!waiting_connect_) | 192 if (!waiting_connect_) |
185 return ProcessOutgoingMessages(); | 193 return ProcessOutgoingMessages(); |
186 | 194 |
187 return true; | 195 return true; |
188 } | 196 } |
189 | 197 |
190 void Channel::ChannelImpl::DidRecvMsg(scoped_ptr<std::vector<char> > buffer) { | 198 void Channel::ChannelImpl::DidRecvMsg(scoped_ptr<MessageContents> contents) { |
191 // Close sets the pipe to -1. It's possible we'll get a buffer sent to us from | 199 // Close sets the pipe to -1. It's possible we'll get a buffer sent to us from |
192 // the reader thread after Close is called. If so, we ignore it. | 200 // the reader thread after Close is called. If so, we ignore it. |
193 if (pipe_ == -1) | 201 if (pipe_ == -1) |
194 return; | 202 return; |
195 | 203 |
196 read_queue_.push_back(linked_ptr<std::vector<char> >(buffer.release())); | 204 linked_ptr<std::vector<char> > data(new std::vector<char>); |
| 205 data->swap(contents->data); |
| 206 read_queue_.push_back(data); |
| 207 |
| 208 input_fds_.insert(input_fds_.end(), |
| 209 contents->fds.begin(), contents->fds.end()); |
| 210 contents->fds.clear(); |
197 | 211 |
198 // In POSIX, we would be told when there are bytes to read by implementing | 212 // In POSIX, we would be told when there are bytes to read by implementing |
199 // OnFileCanReadWithoutBlocking in MessageLoopForIO::Watcher. In NaCl, we | 213 // OnFileCanReadWithoutBlocking in MessageLoopForIO::Watcher. In NaCl, we |
200 // instead know at this point because the reader thread posted some data to | 214 // instead know at this point because the reader thread posted some data to |
201 // us. | 215 // us. |
202 ProcessIncomingMessages(); | 216 ProcessIncomingMessages(); |
203 } | 217 } |
204 | 218 |
205 void Channel::ChannelImpl::ReadDidFail() { | 219 void Channel::ChannelImpl::ReadDidFail() { |
206 Close(); | 220 Close(); |
(...skipping 26 matching lines...) Expand all Loading... |
233 | 247 |
234 if (pipe_ == -1) | 248 if (pipe_ == -1) |
235 return false; | 249 return false; |
236 | 250 |
237 // Write out all the messages. The trusted implementation is guaranteed to not | 251 // Write out all the messages. The trusted implementation is guaranteed to not |
238 // block. See NaClIPCAdapter::Send for the implementation of imc_sendmsg. | 252 // block. See NaClIPCAdapter::Send for the implementation of imc_sendmsg. |
239 while (!output_queue_.empty()) { | 253 while (!output_queue_.empty()) { |
240 linked_ptr<Message> msg = output_queue_.front(); | 254 linked_ptr<Message> msg = output_queue_.front(); |
241 output_queue_.pop_front(); | 255 output_queue_.pop_front(); |
242 | 256 |
243 struct NaClImcMsgHdr msgh = {0}; | 257 int fds[FileDescriptorSet::kMaxDescriptorsPerMessage]; |
244 struct NaClImcMsgIoVec iov = {const_cast<void*>(msg->data()), msg->size()}; | 258 const int num_fds = msg->file_descriptor_set()->size(); |
245 msgh.iov = &iov; | 259 DCHECK(num_fds <= FileDescriptorSet::kMaxDescriptorsPerMessage); |
246 msgh.iov_length = 1; | 260 msg->file_descriptor_set()->GetDescriptors(fds); |
| 261 |
| 262 NaClImcMsgIoVec iov = { const_cast<void*>(msg->data()), msg->size() }; |
| 263 NaClImcMsgHdr msgh = { &iov, 1, fds, num_fds }; |
247 ssize_t bytes_written = imc_sendmsg(pipe_, &msgh, 0); | 264 ssize_t bytes_written = imc_sendmsg(pipe_, &msgh, 0); |
248 | 265 |
| 266 DCHECK(bytes_written); // The trusted side shouldn't return 0. |
249 if (bytes_written < 0) { | 267 if (bytes_written < 0) { |
250 // The trusted side should only ever give us an error of EPIPE. We | 268 // The trusted side should only ever give us an error of EPIPE. We |
251 // should never be interrupted, nor should we get EAGAIN. | 269 // should never be interrupted, nor should we get EAGAIN. |
252 DCHECK(errno == EPIPE); | 270 DCHECK(errno == EPIPE); |
253 Close(); | 271 Close(); |
254 PLOG(ERROR) << "pipe_ error on " | 272 PLOG(ERROR) << "pipe_ error on " |
255 << pipe_ | 273 << pipe_ |
256 << " Currently writing message of size: " | 274 << " Currently writing message of size: " |
257 << msg->size(); | 275 << msg->size(); |
258 return false; | 276 return false; |
| 277 } else { |
| 278 msg->file_descriptor_set()->CommitAll(); |
259 } | 279 } |
260 | 280 |
261 // Message sent OK! | 281 // Message sent OK! |
262 DVLOG(2) << "sent message @" << msg.get() << " with type " << msg->type() | 282 DVLOG(2) << "sent message @" << msg.get() << " with type " << msg->type() |
263 << " on fd " << pipe_; | 283 << " on fd " << pipe_; |
264 } | 284 } |
265 return true; | 285 return true; |
266 } | 286 } |
267 | 287 |
268 Channel::ChannelImpl::ReadState Channel::ChannelImpl::ReadData( | 288 Channel::ChannelImpl::ReadState Channel::ChannelImpl::ReadData( |
(...skipping 21 matching lines...) Expand all Loading... |
290 std::copy(vec->begin(), vec->begin() + bytes_to_read, | 310 std::copy(vec->begin(), vec->begin() + bytes_to_read, |
291 buffer + *bytes_read); | 311 buffer + *bytes_read); |
292 vec->erase(vec->begin(), vec->begin() + bytes_to_read); | 312 vec->erase(vec->begin(), vec->begin() + bytes_to_read); |
293 *bytes_read += bytes_to_read; | 313 *bytes_read += bytes_to_read; |
294 } | 314 } |
295 } | 315 } |
296 return READ_SUCCEEDED; | 316 return READ_SUCCEEDED; |
297 } | 317 } |
298 | 318 |
299 bool Channel::ChannelImpl::WillDispatchInputMessage(Message* msg) { | 319 bool Channel::ChannelImpl::WillDispatchInputMessage(Message* msg) { |
| 320 uint16 header_fds = msg->header()->num_fds; |
| 321 CHECK(header_fds == input_fds_.size()); |
| 322 if (header_fds == 0) |
| 323 return true; // Nothing to do. |
| 324 |
| 325 // The shenaniganery below with &foo.front() requires input_fds_ to have |
| 326 // contiguous underlying storage (such as a simple array or a std::vector). |
| 327 // This is why the header warns not to make input_fds_ a deque<>. |
| 328 msg->file_descriptor_set()->SetDescriptors(&input_fds_.front(), |
| 329 header_fds); |
| 330 input_fds_.clear(); |
300 return true; | 331 return true; |
301 } | 332 } |
302 | 333 |
303 bool Channel::ChannelImpl::DidEmptyInputBuffers() { | 334 bool Channel::ChannelImpl::DidEmptyInputBuffers() { |
304 return true; | 335 // When the input data buffer is empty, the fds should be too. |
| 336 return input_fds_.empty(); |
305 } | 337 } |
306 | 338 |
307 void Channel::ChannelImpl::HandleHelloMessage(const Message& msg) { | 339 void Channel::ChannelImpl::HandleHelloMessage(const Message& msg) { |
308 // The trusted side IPC::Channel should handle the "hello" handshake; we | 340 // The trusted side IPC::Channel should handle the "hello" handshake; we |
309 // should not receive the "Hello" message. | 341 // should not receive the "Hello" message. |
310 NOTREACHED(); | 342 NOTREACHED(); |
311 } | 343 } |
312 | 344 |
313 //------------------------------------------------------------------------------ | 345 //------------------------------------------------------------------------------ |
314 // Channel's methods simply call through to ChannelImpl. | 346 // Channel's methods simply call through to ChannelImpl. |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
350 // A random name is sufficient validation on posix systems, so we don't need | 382 // A random name is sufficient validation on posix systems, so we don't need |
351 // an additional shared secret. | 383 // an additional shared secret. |
352 std::string id = prefix; | 384 std::string id = prefix; |
353 if (!id.empty()) | 385 if (!id.empty()) |
354 id.append("."); | 386 id.append("."); |
355 | 387 |
356 return id.append(GenerateUniqueRandomChannelID()); | 388 return id.append(GenerateUniqueRandomChannelID()); |
357 } | 389 } |
358 | 390 |
359 } // namespace IPC | 391 } // namespace IPC |
OLD | NEW |