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/types.h> | 9 #include <sys/types.h> |
10 | 10 |
11 #include <algorithm> | 11 #include <algorithm> |
12 | 12 |
13 #include "base/bind.h" | 13 #include "base/bind.h" |
14 #include "base/logging.h" | 14 #include "base/logging.h" |
15 #include "base/message_loop/message_loop_proxy.h" | 15 #include "base/message_loop/message_loop_proxy.h" |
16 #include "base/synchronization/lock.h" | 16 #include "base/synchronization/lock.h" |
17 #include "base/task_runner_util.h" | 17 #include "base/task_runner_util.h" |
18 #include "base/threading/simple_thread.h" | 18 #include "base/threading/simple_thread.h" |
19 #include "ipc/file_descriptor_set_posix.h" | |
20 #include "ipc/ipc_listener.h" | 19 #include "ipc/ipc_listener.h" |
21 #include "ipc/ipc_logging.h" | 20 #include "ipc/ipc_logging.h" |
| 21 #include "ipc/ipc_message_attachment_set.h" |
22 #include "native_client/src/public/imc_syscalls.h" | 22 #include "native_client/src/public/imc_syscalls.h" |
23 #include "native_client/src/public/imc_types.h" | 23 #include "native_client/src/public/imc_types.h" |
24 | 24 |
25 namespace IPC { | 25 namespace IPC { |
26 | 26 |
27 struct MessageContents { | 27 struct MessageContents { |
28 std::vector<char> data; | 28 std::vector<char> data; |
29 std::vector<int> fds; | 29 std::vector<int> fds; |
30 }; | 30 }; |
31 | 31 |
32 namespace { | 32 namespace { |
33 | 33 |
34 bool ReadDataOnReaderThread(int pipe, MessageContents* contents) { | 34 bool ReadDataOnReaderThread(int pipe, MessageContents* contents) { |
35 DCHECK(pipe >= 0); | 35 DCHECK(pipe >= 0); |
36 if (pipe < 0) | 36 if (pipe < 0) |
37 return false; | 37 return false; |
38 | 38 |
39 contents->data.resize(Channel::kReadBufferSize); | 39 contents->data.resize(Channel::kReadBufferSize); |
40 contents->fds.resize(FileDescriptorSet::kMaxDescriptorsPerMessage); | 40 contents->fds.resize(MessageAttachmentSet::kMaxDescriptorsPerMessage); |
41 | 41 |
42 NaClAbiNaClImcMsgIoVec iov = { &contents->data[0], contents->data.size() }; | 42 NaClAbiNaClImcMsgIoVec iov = { &contents->data[0], contents->data.size() }; |
43 NaClAbiNaClImcMsgHdr msg = { | 43 NaClAbiNaClImcMsgHdr msg = { |
44 &iov, 1, &contents->fds[0], contents->fds.size() | 44 &iov, 1, &contents->fds[0], contents->fds.size() |
45 }; | 45 }; |
46 | 46 |
47 int bytes_read = imc_recvmsg(pipe, &msg, 0); | 47 int bytes_read = imc_recvmsg(pipe, &msg, 0); |
48 | 48 |
49 if (bytes_read <= 0) { | 49 if (bytes_read <= 0) { |
50 // NaClIPCAdapter::BlockingReceive returns -1 when the pipe closes (either | 50 // NaClIPCAdapter::BlockingReceive returns -1 when the pipe closes (either |
(...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
268 | 268 |
269 if (pipe_ == -1) | 269 if (pipe_ == -1) |
270 return false; | 270 return false; |
271 | 271 |
272 // Write out all the messages. The trusted implementation is guaranteed to not | 272 // Write out all the messages. The trusted implementation is guaranteed to not |
273 // block. See NaClIPCAdapter::Send for the implementation of imc_sendmsg. | 273 // block. See NaClIPCAdapter::Send for the implementation of imc_sendmsg. |
274 while (!output_queue_.empty()) { | 274 while (!output_queue_.empty()) { |
275 linked_ptr<Message> msg = output_queue_.front(); | 275 linked_ptr<Message> msg = output_queue_.front(); |
276 output_queue_.pop_front(); | 276 output_queue_.pop_front(); |
277 | 277 |
278 int fds[FileDescriptorSet::kMaxDescriptorsPerMessage]; | 278 int fds[MessageAttachmentSet::kMaxDescriptorsPerMessage]; |
279 const size_t num_fds = msg->file_descriptor_set()->size(); | 279 const size_t num_fds = msg->attachment_set()->size(); |
280 DCHECK(num_fds <= FileDescriptorSet::kMaxDescriptorsPerMessage); | 280 DCHECK(num_fds <= MessageAttachmentSet::kMaxDescriptorsPerMessage); |
281 msg->file_descriptor_set()->PeekDescriptors(fds); | 281 msg->attachment_set()->PeekDescriptors(fds); |
282 | 282 |
283 NaClAbiNaClImcMsgIoVec iov = { | 283 NaClAbiNaClImcMsgIoVec iov = { |
284 const_cast<void*>(msg->data()), msg->size() | 284 const_cast<void*>(msg->data()), msg->size() |
285 }; | 285 }; |
286 NaClAbiNaClImcMsgHdr msgh = { &iov, 1, fds, num_fds }; | 286 NaClAbiNaClImcMsgHdr msgh = { &iov, 1, fds, num_fds }; |
287 ssize_t bytes_written = imc_sendmsg(pipe_, &msgh, 0); | 287 ssize_t bytes_written = imc_sendmsg(pipe_, &msgh, 0); |
288 | 288 |
289 DCHECK(bytes_written); // The trusted side shouldn't return 0. | 289 DCHECK(bytes_written); // The trusted side shouldn't return 0. |
290 if (bytes_written < 0) { | 290 if (bytes_written < 0) { |
291 // The trusted side should only ever give us an error of EPIPE. We | 291 // The trusted side should only ever give us an error of EPIPE. We |
292 // should never be interrupted, nor should we get EAGAIN. | 292 // should never be interrupted, nor should we get EAGAIN. |
293 DCHECK(errno == EPIPE); | 293 DCHECK(errno == EPIPE); |
294 Close(); | 294 Close(); |
295 PLOG(ERROR) << "pipe_ error on " | 295 PLOG(ERROR) << "pipe_ error on " |
296 << pipe_ | 296 << pipe_ |
297 << " Currently writing message of size: " | 297 << " Currently writing message of size: " |
298 << msg->size(); | 298 << msg->size(); |
299 return false; | 299 return false; |
300 } else { | 300 } else { |
301 msg->file_descriptor_set()->CommitAll(); | 301 msg->attachment_set()->CommitAll(); |
302 } | 302 } |
303 | 303 |
304 // Message sent OK! | 304 // Message sent OK! |
305 DVLOG(2) << "sent message @" << msg.get() << " with type " << msg->type() | 305 DVLOG(2) << "sent message @" << msg.get() << " with type " << msg->type() |
306 << " on fd " << pipe_; | 306 << " on fd " << pipe_; |
307 } | 307 } |
308 return true; | 308 return true; |
309 } | 309 } |
310 | 310 |
311 void ChannelNacl::CallOnChannelConnected() { | 311 void ChannelNacl::CallOnChannelConnected() { |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
345 | 345 |
346 bool ChannelNacl::WillDispatchInputMessage(Message* msg) { | 346 bool ChannelNacl::WillDispatchInputMessage(Message* msg) { |
347 uint16 header_fds = msg->header()->num_fds; | 347 uint16 header_fds = msg->header()->num_fds; |
348 CHECK(header_fds == input_fds_.size()); | 348 CHECK(header_fds == input_fds_.size()); |
349 if (header_fds == 0) | 349 if (header_fds == 0) |
350 return true; // Nothing to do. | 350 return true; // Nothing to do. |
351 | 351 |
352 // The shenaniganery below with &foo.front() requires input_fds_ to have | 352 // The shenaniganery below with &foo.front() requires input_fds_ to have |
353 // contiguous underlying storage (such as a simple array or a std::vector). | 353 // contiguous underlying storage (such as a simple array or a std::vector). |
354 // This is why the header warns not to make input_fds_ a deque<>. | 354 // This is why the header warns not to make input_fds_ a deque<>. |
355 msg->file_descriptor_set()->AddDescriptorsToOwn(&input_fds_.front(), | 355 msg->attachment_set()->AddDescriptorsToOwn(&input_fds_.front(), header_fds); |
356 header_fds); | |
357 input_fds_.clear(); | 356 input_fds_.clear(); |
358 return true; | 357 return true; |
359 } | 358 } |
360 | 359 |
361 bool ChannelNacl::DidEmptyInputBuffers() { | 360 bool ChannelNacl::DidEmptyInputBuffers() { |
362 // When the input data buffer is empty, the fds should be too. | 361 // When the input data buffer is empty, the fds should be too. |
363 return input_fds_.empty(); | 362 return input_fds_.empty(); |
364 } | 363 } |
365 | 364 |
366 void ChannelNacl::HandleInternalMessage(const Message& msg) { | 365 void ChannelNacl::HandleInternalMessage(const Message& msg) { |
367 // The trusted side IPC::Channel should handle the "hello" handshake; we | 366 // The trusted side IPC::Channel should handle the "hello" handshake; we |
368 // should not receive the "Hello" message. | 367 // should not receive the "Hello" message. |
369 NOTREACHED(); | 368 NOTREACHED(); |
370 } | 369 } |
371 | 370 |
372 // Channel's methods | 371 // Channel's methods |
373 | 372 |
374 // static | 373 // static |
375 scoped_ptr<Channel> Channel::Create( | 374 scoped_ptr<Channel> Channel::Create( |
376 const IPC::ChannelHandle &channel_handle, Mode mode, Listener* listener) { | 375 const IPC::ChannelHandle &channel_handle, Mode mode, Listener* listener) { |
377 return scoped_ptr<Channel>( | 376 return scoped_ptr<Channel>( |
378 new ChannelNacl(channel_handle, mode, listener)); | 377 new ChannelNacl(channel_handle, mode, listener)); |
379 } | 378 } |
380 | 379 |
381 } // namespace IPC | 380 } // namespace IPC |
OLD | NEW |