OLD | NEW |
---|---|
1 // Copyright (c) 2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2008 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_posix.h" | 5 #include "ipc/ipc_channel_posix.h" |
6 | 6 |
7 #include <errno.h> | 7 #include <errno.h> |
8 #include <fcntl.h> | 8 #include <fcntl.h> |
9 #include <stddef.h> | 9 #include <stddef.h> |
10 #include <sys/types.h> | 10 #include <sys/types.h> |
(...skipping 255 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
266 Channel::ChannelImpl::ChannelImpl(const std::string& channel_id, Mode mode, | 266 Channel::ChannelImpl::ChannelImpl(const std::string& channel_id, Mode mode, |
267 Listener* listener) | 267 Listener* listener) |
268 : mode_(mode), | 268 : mode_(mode), |
269 is_blocked_on_write_(false), | 269 is_blocked_on_write_(false), |
270 message_send_bytes_written_(0), | 270 message_send_bytes_written_(0), |
271 uses_fifo_(CommandLine::ForCurrentProcess()->HasSwitch( | 271 uses_fifo_(CommandLine::ForCurrentProcess()->HasSwitch( |
272 switches::kIPCUseFIFO)), | 272 switches::kIPCUseFIFO)), |
273 server_listen_pipe_(-1), | 273 server_listen_pipe_(-1), |
274 pipe_(-1), | 274 pipe_(-1), |
275 client_pipe_(-1), | 275 client_pipe_(-1), |
276 #if defined(OS_LINUX) | 276 #if !defined(OS_MACOSX) |
277 fd_pipe_(-1), | 277 fd_pipe_(-1), |
278 remote_fd_pipe_(-1), | 278 remote_fd_pipe_(-1), |
279 #endif | 279 #endif |
280 listener_(listener), | 280 listener_(listener), |
281 waiting_connect_(true), | 281 waiting_connect_(true), |
282 factory_(this) { | 282 factory_(this) { |
283 if (!CreatePipe(channel_id, mode)) { | 283 if (!CreatePipe(channel_id, mode)) { |
284 // The pipe may have been closed already. | 284 // The pipe may have been closed already. |
285 PLOG(WARNING) << "Unable to create pipe named \"" << channel_id | 285 PLOG(WARNING) << "Unable to create pipe named \"" << channel_id |
286 << "\" in " << (mode == MODE_SERVER ? "server" : "client") | 286 << "\" in " << (mode == MODE_SERVER ? "server" : "client") |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
377 } | 377 } |
378 } else { | 378 } else { |
379 waiting_connect_ = mode == MODE_SERVER; | 379 waiting_connect_ = mode == MODE_SERVER; |
380 } | 380 } |
381 } | 381 } |
382 | 382 |
383 // Create the Hello message to be sent when Connect is called | 383 // Create the Hello message to be sent when Connect is called |
384 scoped_ptr<Message> msg(new Message(MSG_ROUTING_NONE, | 384 scoped_ptr<Message> msg(new Message(MSG_ROUTING_NONE, |
385 HELLO_MESSAGE_TYPE, | 385 HELLO_MESSAGE_TYPE, |
386 IPC::Message::PRIORITY_NORMAL)); | 386 IPC::Message::PRIORITY_NORMAL)); |
387 #if defined(OS_LINUX) | 387 #if !defined(OS_MACOSX) |
388 if (!uses_fifo_) { | 388 if (!uses_fifo_) { |
389 // On Linux, the seccomp sandbox makes it very expensive to call | 389 // On Linux, the seccomp sandbox makes it very expensive to call |
390 // recvmsg() and sendmsg(). Often, we are perfectly OK with resorting to | 390 // recvmsg() and sendmsg(). Often, we are perfectly OK with resorting to |
391 // read() and write(), which are cheap. | 391 // read() and write(), which are cheap. |
392 // | 392 // |
393 // As we cannot anticipate, when the sender will provide us with file | 393 // As we cannot anticipate, when the sender will provide us with file |
394 // handles, we have to make the decision about whether we call read() or | 394 // handles, we have to make the decision about whether we call read() or |
395 // recvmsg() before we actually make the call. The easiest option is to | 395 // recvmsg() before we actually make the call. The easiest option is to |
396 // create a dedicated socketpair() for exchanging file handles. | 396 // create a dedicated socketpair() for exchanging file handles. |
397 if (mode == MODE_SERVER) { | 397 if (mode == MODE_SERVER) { |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
453 for (;;) { | 453 for (;;) { |
454 msg.msg_iov = &iov; | 454 msg.msg_iov = &iov; |
455 | 455 |
456 if (bytes_read == 0) { | 456 if (bytes_read == 0) { |
457 if (pipe_ == -1) | 457 if (pipe_ == -1) |
458 return false; | 458 return false; |
459 | 459 |
460 // Read from pipe. | 460 // Read from pipe. |
461 // recvmsg() returns 0 if the connection has closed or EAGAIN if no data | 461 // recvmsg() returns 0 if the connection has closed or EAGAIN if no data |
462 // is waiting on the pipe. | 462 // is waiting on the pipe. |
463 #if defined(OS_LINUX) | 463 #if !defined(OS_MACOSX) |
464 if (fd_pipe_ >= 0) { | 464 if (fd_pipe_ >= 0) { |
465 bytes_read = HANDLE_EINTR(read(pipe_, input_buf_, | 465 bytes_read = HANDLE_EINTR(read(pipe_, input_buf_, |
466 Channel::kReadBufferSize)); | 466 Channel::kReadBufferSize)); |
467 msg.msg_controllen = 0; | 467 msg.msg_controllen = 0; |
468 } else | 468 } else |
469 #endif | 469 #endif |
470 { | 470 { |
471 msg.msg_controllen = sizeof(input_cmsg_buf_); | 471 msg.msg_controllen = sizeof(input_cmsg_buf_); |
472 bytes_read = HANDLE_EINTR(recvmsg(pipe_, &msg, MSG_DONTWAIT)); | 472 bytes_read = HANDLE_EINTR(recvmsg(pipe_, &msg, MSG_DONTWAIT)); |
473 } | 473 } |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
585 if (message_tail) { | 585 if (message_tail) { |
586 int len = static_cast<int>(message_tail - p); | 586 int len = static_cast<int>(message_tail - p); |
587 Message m(p, len); | 587 Message m(p, len); |
588 | 588 |
589 if (m.header()->num_fds) { | 589 if (m.header()->num_fds) { |
590 // the message has file descriptors | 590 // the message has file descriptors |
591 const char* error = NULL; | 591 const char* error = NULL; |
592 if (m.header()->num_fds > num_fds - fds_i) { | 592 if (m.header()->num_fds > num_fds - fds_i) { |
593 // the message has been completely received, but we didn't get | 593 // the message has been completely received, but we didn't get |
594 // enough file descriptors. | 594 // enough file descriptors. |
595 #if defined(OS_LINUX) | 595 #if !defined(OS_MACOSX) |
596 if (!uses_fifo_) { | 596 if (!uses_fifo_) { |
597 char dummy; | 597 char dummy; |
598 struct iovec fd_pipe_iov = { &dummy, 1 }; | 598 struct iovec fd_pipe_iov = { &dummy, 1 }; |
599 msg.msg_iov = &fd_pipe_iov; | 599 msg.msg_iov = &fd_pipe_iov; |
600 msg.msg_controllen = sizeof(input_cmsg_buf_); | 600 msg.msg_controllen = sizeof(input_cmsg_buf_); |
601 ssize_t n = HANDLE_EINTR(recvmsg(fd_pipe_, &msg, MSG_DONTWAIT)); | 601 ssize_t n = HANDLE_EINTR(recvmsg(fd_pipe_, &msg, MSG_DONTWAIT)); |
602 if (n == 1 && msg.msg_controllen > 0) { | 602 if (n == 1 && msg.msg_controllen > 0) { |
603 for (struct cmsghdr* cmsg = CMSG_FIRSTHDR(&msg); cmsg; | 603 for (struct cmsghdr* cmsg = CMSG_FIRSTHDR(&msg); cmsg; |
604 cmsg = CMSG_NXTHDR(&msg, cmsg)) { | 604 cmsg = CMSG_NXTHDR(&msg, cmsg)) { |
605 if (cmsg->cmsg_level == SOL_SOCKET && | 605 if (cmsg->cmsg_level == SOL_SOCKET && |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
675 " with type " << m.type(); | 675 " with type " << m.type(); |
676 #endif | 676 #endif |
677 if (m.routing_id() == MSG_ROUTING_NONE && | 677 if (m.routing_id() == MSG_ROUTING_NONE && |
678 m.type() == HELLO_MESSAGE_TYPE) { | 678 m.type() == HELLO_MESSAGE_TYPE) { |
679 // The Hello message contains only the process id. | 679 // The Hello message contains only the process id. |
680 void *iter = NULL; | 680 void *iter = NULL; |
681 int pid; | 681 int pid; |
682 if (!m.ReadInt(&iter, &pid)) { | 682 if (!m.ReadInt(&iter, &pid)) { |
683 NOTREACHED(); | 683 NOTREACHED(); |
684 } | 684 } |
685 #if defined(OS_LINUX) | 685 #if !defined(OS_MACOSX) |
686 if (mode_ == MODE_SERVER && !uses_fifo_) { | 686 if (mode_ == MODE_SERVER && !uses_fifo_) { |
687 // On Linux, the Hello message from the client to the server | 687 // On Linux, the Hello message from the client to the server |
Evan Martin
2010/05/19 11:50:11
s/Linux/non-Mac/
| |
688 // also contains the fd_pipe_, which will be used for all | 688 // also contains the fd_pipe_, which will be used for all |
689 // subsequent file descriptor passing. | 689 // subsequent file descriptor passing. |
690 DCHECK_EQ(m.file_descriptor_set()->size(), 1); | 690 DCHECK_EQ(m.file_descriptor_set()->size(), 1); |
691 base::FileDescriptor descriptor; | 691 base::FileDescriptor descriptor; |
692 if (!m.ReadFileDescriptor(&iter, &descriptor)) { | 692 if (!m.ReadFileDescriptor(&iter, &descriptor)) { |
693 NOTREACHED(); | 693 NOTREACHED(); |
694 } | 694 } |
695 fd_pipe_ = descriptor.fd; | 695 fd_pipe_ = descriptor.fd; |
696 CHECK(descriptor.auto_close); | 696 CHECK(descriptor.auto_close); |
697 } | 697 } |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
738 | 738 |
739 if (pipe_ == -1) { | 739 if (pipe_ == -1) { |
740 return false; | 740 return false; |
741 } | 741 } |
742 | 742 |
743 // Write out all the messages we can till the write blocks or there are no | 743 // Write out all the messages we can till the write blocks or there are no |
744 // more outgoing messages. | 744 // more outgoing messages. |
745 while (!output_queue_.empty()) { | 745 while (!output_queue_.empty()) { |
746 Message* msg = output_queue_.front(); | 746 Message* msg = output_queue_.front(); |
747 | 747 |
748 #if defined(OS_LINUX) | 748 #if !defined(OS_MACOSX) |
749 scoped_ptr<Message> hello; | 749 scoped_ptr<Message> hello; |
750 if (remote_fd_pipe_ != -1 && | 750 if (remote_fd_pipe_ != -1 && |
751 msg->routing_id() == MSG_ROUTING_NONE && | 751 msg->routing_id() == MSG_ROUTING_NONE && |
752 msg->type() == HELLO_MESSAGE_TYPE) { | 752 msg->type() == HELLO_MESSAGE_TYPE) { |
753 hello.reset(new Message(MSG_ROUTING_NONE, | 753 hello.reset(new Message(MSG_ROUTING_NONE, |
754 HELLO_MESSAGE_TYPE, | 754 HELLO_MESSAGE_TYPE, |
755 IPC::Message::PRIORITY_NORMAL)); | 755 IPC::Message::PRIORITY_NORMAL)); |
756 void* iter = NULL; | 756 void* iter = NULL; |
757 int pid; | 757 int pid; |
758 if (!msg->ReadInt(&iter, &pid) || | 758 if (!msg->ReadInt(&iter, &pid) || |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
799 cmsg->cmsg_type = SCM_RIGHTS; | 799 cmsg->cmsg_type = SCM_RIGHTS; |
800 cmsg->cmsg_len = CMSG_LEN(sizeof(int) * num_fds); | 800 cmsg->cmsg_len = CMSG_LEN(sizeof(int) * num_fds); |
801 msg->file_descriptor_set()->GetDescriptors( | 801 msg->file_descriptor_set()->GetDescriptors( |
802 reinterpret_cast<int*>(CMSG_DATA(cmsg))); | 802 reinterpret_cast<int*>(CMSG_DATA(cmsg))); |
803 msgh.msg_controllen = cmsg->cmsg_len; | 803 msgh.msg_controllen = cmsg->cmsg_len; |
804 | 804 |
805 // DCHECK_LE above already checks that | 805 // DCHECK_LE above already checks that |
806 // num_fds < MAX_DESCRIPTORS_PER_MESSAGE so no danger of overflow. | 806 // num_fds < MAX_DESCRIPTORS_PER_MESSAGE so no danger of overflow. |
807 msg->header()->num_fds = static_cast<uint16>(num_fds); | 807 msg->header()->num_fds = static_cast<uint16>(num_fds); |
808 | 808 |
809 #if defined(OS_LINUX) | 809 #if !defined(OS_MACOSX) |
810 if (!uses_fifo_ && | 810 if (!uses_fifo_ && |
811 (msg->routing_id() != MSG_ROUTING_NONE || | 811 (msg->routing_id() != MSG_ROUTING_NONE || |
812 msg->type() != HELLO_MESSAGE_TYPE)) { | 812 msg->type() != HELLO_MESSAGE_TYPE)) { |
813 // Only the Hello message sends the file descriptor with the message. | 813 // Only the Hello message sends the file descriptor with the message. |
814 // Subsequently, we can send file descriptors on the dedicated | 814 // Subsequently, we can send file descriptors on the dedicated |
815 // fd_pipe_ which makes Seccomp sandbox operation more efficient. | 815 // fd_pipe_ which makes Seccomp sandbox operation more efficient. |
816 struct iovec fd_pipe_iov = { const_cast<char *>(""), 1 }; | 816 struct iovec fd_pipe_iov = { const_cast<char *>(""), 1 }; |
817 msgh.msg_iov = &fd_pipe_iov; | 817 msgh.msg_iov = &fd_pipe_iov; |
818 fd_written = fd_pipe_; | 818 fd_written = fd_pipe_; |
819 bytes_written = HANDLE_EINTR(sendmsg(fd_pipe_, &msgh, MSG_DONTWAIT)); | 819 bytes_written = HANDLE_EINTR(sendmsg(fd_pipe_, &msgh, MSG_DONTWAIT)); |
820 msgh.msg_iov = &iov; | 820 msgh.msg_iov = &iov; |
821 msgh.msg_controllen = 0; | 821 msgh.msg_controllen = 0; |
822 if (bytes_written > 0) { | 822 if (bytes_written > 0) { |
823 msg->file_descriptor_set()->CommitAll(); | 823 msg->file_descriptor_set()->CommitAll(); |
824 } | 824 } |
825 } | 825 } |
826 #endif | 826 #endif |
827 } | 827 } |
828 | 828 |
829 if (bytes_written == 1) { | 829 if (bytes_written == 1) { |
830 fd_written = pipe_; | 830 fd_written = pipe_; |
831 #if defined(OS_LINUX) | 831 #if !defined(OS_MACOSX) |
832 if (mode_ != MODE_SERVER && !uses_fifo_ && | 832 if (mode_ != MODE_SERVER && !uses_fifo_ && |
833 msg->routing_id() == MSG_ROUTING_NONE && | 833 msg->routing_id() == MSG_ROUTING_NONE && |
834 msg->type() == HELLO_MESSAGE_TYPE) { | 834 msg->type() == HELLO_MESSAGE_TYPE) { |
835 DCHECK_EQ(msg->file_descriptor_set()->size(), 1); | 835 DCHECK_EQ(msg->file_descriptor_set()->size(), 1); |
836 } | 836 } |
837 if (!uses_fifo_ && !msgh.msg_controllen) { | 837 if (!uses_fifo_ && !msgh.msg_controllen) { |
838 bytes_written = HANDLE_EINTR(write(pipe_, out_bytes, amt_to_write)); | 838 bytes_written = HANDLE_EINTR(write(pipe_, out_bytes, amt_to_write)); |
839 } else | 839 } else |
840 #endif | 840 #endif |
841 { | 841 { |
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
992 read_watcher_.StopWatchingFileDescriptor(); | 992 read_watcher_.StopWatchingFileDescriptor(); |
993 write_watcher_.StopWatchingFileDescriptor(); | 993 write_watcher_.StopWatchingFileDescriptor(); |
994 if (pipe_ != -1) { | 994 if (pipe_ != -1) { |
995 HANDLE_EINTR(close(pipe_)); | 995 HANDLE_EINTR(close(pipe_)); |
996 pipe_ = -1; | 996 pipe_ = -1; |
997 } | 997 } |
998 if (client_pipe_ != -1) { | 998 if (client_pipe_ != -1) { |
999 Singleton<PipeMap>()->RemoveAndClose(pipe_name_); | 999 Singleton<PipeMap>()->RemoveAndClose(pipe_name_); |
1000 client_pipe_ = -1; | 1000 client_pipe_ = -1; |
1001 } | 1001 } |
1002 #if defined(OS_LINUX) | 1002 #if !defined(OS_MACOSX) |
1003 if (fd_pipe_ != -1) { | 1003 if (fd_pipe_ != -1) { |
1004 HANDLE_EINTR(close(fd_pipe_)); | 1004 HANDLE_EINTR(close(fd_pipe_)); |
1005 fd_pipe_ = -1; | 1005 fd_pipe_ = -1; |
1006 } | 1006 } |
1007 if (remote_fd_pipe_ != -1) { | 1007 if (remote_fd_pipe_ != -1) { |
1008 HANDLE_EINTR(close(remote_fd_pipe_)); | 1008 HANDLE_EINTR(close(remote_fd_pipe_)); |
1009 remote_fd_pipe_ = -1; | 1009 remote_fd_pipe_ = -1; |
1010 } | 1010 } |
1011 #endif | 1011 #endif |
1012 | 1012 |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1054 | 1054 |
1055 bool Channel::Send(Message* message) { | 1055 bool Channel::Send(Message* message) { |
1056 return channel_impl_->Send(message); | 1056 return channel_impl_->Send(message); |
1057 } | 1057 } |
1058 | 1058 |
1059 int Channel::GetClientFileDescriptor() const { | 1059 int Channel::GetClientFileDescriptor() const { |
1060 return channel_impl_->GetClientFileDescriptor(); | 1060 return channel_impl_->GetClientFileDescriptor(); |
1061 } | 1061 } |
1062 | 1062 |
1063 } // namespace IPC | 1063 } // namespace IPC |
OLD | NEW |