Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(870)

Side by Side Diff: ipc/ipc_channel_posix.cc

Issue 9570001: Separate out the platform-independent parts of Channel reading. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « ipc/ipc_channel_posix.h ('k') | ipc/ipc_channel_reader.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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_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 282 matching lines...) Expand 10 before | Expand all | Expand 10 after
293 293
294 } // namespace 294 } // namespace
295 //------------------------------------------------------------------------------ 295 //------------------------------------------------------------------------------
296 296
297 #if defined(OS_LINUX) 297 #if defined(OS_LINUX)
298 int Channel::ChannelImpl::global_pid_ = 0; 298 int Channel::ChannelImpl::global_pid_ = 0;
299 #endif // OS_LINUX 299 #endif // OS_LINUX
300 300
301 Channel::ChannelImpl::ChannelImpl(const IPC::ChannelHandle& channel_handle, 301 Channel::ChannelImpl::ChannelImpl(const IPC::ChannelHandle& channel_handle,
302 Mode mode, Listener* listener) 302 Mode mode, Listener* listener)
303 : mode_(mode), 303 : ChannelReader(listener),
304 mode_(mode),
304 is_blocked_on_write_(false), 305 is_blocked_on_write_(false),
305 waiting_connect_(true), 306 waiting_connect_(true),
306 message_send_bytes_written_(0), 307 message_send_bytes_written_(0),
307 server_listen_pipe_(-1), 308 server_listen_pipe_(-1),
308 pipe_(-1), 309 pipe_(-1),
309 client_pipe_(-1), 310 client_pipe_(-1),
310 #if defined(IPC_USES_READWRITE) 311 #if defined(IPC_USES_READWRITE)
311 fd_pipe_(-1), 312 fd_pipe_(-1),
312 remote_fd_pipe_(-1), 313 remote_fd_pipe_(-1),
313 #endif // IPC_USES_READWRITE 314 #endif // IPC_USES_READWRITE
314 pipe_name_(channel_handle.name), 315 pipe_name_(channel_handle.name),
315 listener_(listener),
316 must_unlink_(false) { 316 must_unlink_(false) {
317 memset(input_buf_, 0, sizeof(input_buf_));
318 memset(input_cmsg_buf_, 0, sizeof(input_cmsg_buf_)); 317 memset(input_cmsg_buf_, 0, sizeof(input_cmsg_buf_));
319 if (!CreatePipe(channel_handle)) { 318 if (!CreatePipe(channel_handle)) {
320 // The pipe may have been closed already. 319 // The pipe may have been closed already.
321 const char *modestr = (mode_ & MODE_SERVER_FLAG) ? "server" : "client"; 320 const char *modestr = (mode_ & MODE_SERVER_FLAG) ? "server" : "client";
322 LOG(WARNING) << "Unable to create pipe named \"" << channel_handle.name 321 LOG(WARNING) << "Unable to create pipe named \"" << channel_handle.name
323 << "\" in " << modestr << " mode"; 322 << "\" in " << modestr << " mode";
324 } 323 }
325 } 324 }
326 325
327 Channel::ChannelImpl::~ChannelImpl() { 326 Channel::ChannelImpl::~ChannelImpl() {
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after
471 true, 470 true,
472 MessageLoopForIO::WATCH_READ, 471 MessageLoopForIO::WATCH_READ,
473 &server_listen_connection_watcher_, 472 &server_listen_connection_watcher_,
474 this); 473 this);
475 } else { 474 } else {
476 did_connect = AcceptConnection(); 475 did_connect = AcceptConnection();
477 } 476 }
478 return did_connect; 477 return did_connect;
479 } 478 }
480 479
481 bool Channel::ChannelImpl::ProcessIncomingMessages() {
482 while (true) {
483 int bytes_read = 0;
484 ReadState read_state = ReadData(input_buf_, Channel::kReadBufferSize,
485 &bytes_read);
486 if (read_state == READ_FAILED)
487 return false;
488 if (read_state == READ_PENDING)
489 return true;
490
491 DCHECK(bytes_read > 0);
492 if (!DispatchInputData(input_buf_, bytes_read))
493 return false;
494 }
495 }
496
497 bool Channel::ChannelImpl::DispatchInputData(const char* input_data,
498 int input_data_len) {
499 const char* p;
500 const char* end;
501
502 // Possibly combine with the overflow buffer to make a larger buffer.
503 if (input_overflow_buf_.empty()) {
504 p = input_data;
505 end = input_data + input_data_len;
506 } else {
507 if (input_overflow_buf_.size() >
508 kMaximumMessageSize - input_data_len) {
509 input_overflow_buf_.clear();
510 LOG(ERROR) << "IPC message is too big";
511 return false;
512 }
513 input_overflow_buf_.append(input_data, input_data_len);
514 p = input_overflow_buf_.data();
515 end = p + input_overflow_buf_.size();
516 }
517
518 // Dispatch all complete messages in the data buffer.
519 while (p < end) {
520 const char* message_tail = Message::FindNext(p, end);
521 if (message_tail) {
522 int len = static_cast<int>(message_tail - p);
523 Message m(p, len);
524 if (!WillDispatchInputMessage(&m))
525 return false;
526
527 if (IsHelloMessage(&m))
528 HandleHelloMessage(m);
529 else
530 listener_->OnMessageReceived(m);
531 p = message_tail;
532 } else {
533 // Last message is partial.
534 break;
535 }
536 }
537
538 // Save any partial data in the overflow buffer.
539 input_overflow_buf_.assign(p, end - p);
540
541 if (input_overflow_buf_.empty() && !DidEmptyInputBuffers())
542 return false;
543 return true;
544 }
545
546 bool Channel::ChannelImpl::ProcessOutgoingMessages() { 480 bool Channel::ChannelImpl::ProcessOutgoingMessages() {
547 DCHECK(!waiting_connect_); // Why are we trying to send messages if there's 481 DCHECK(!waiting_connect_); // Why are we trying to send messages if there's
548 // no connection? 482 // no connection?
549 if (output_queue_.empty()) 483 if (output_queue_.empty())
550 return true; 484 return true;
551 485
552 if (pipe_ == -1) 486 if (pipe_ == -1)
553 return false; 487 return false;
554 488
555 // Write out all the messages we can till the write blocks or there are no 489 // Write out all the messages we can till the write blocks or there are no
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
597 cmsg->cmsg_len = CMSG_LEN(sizeof(int) * num_fds); 531 cmsg->cmsg_len = CMSG_LEN(sizeof(int) * num_fds);
598 msg->file_descriptor_set()->GetDescriptors( 532 msg->file_descriptor_set()->GetDescriptors(
599 reinterpret_cast<int*>(CMSG_DATA(cmsg))); 533 reinterpret_cast<int*>(CMSG_DATA(cmsg)));
600 msgh.msg_controllen = cmsg->cmsg_len; 534 msgh.msg_controllen = cmsg->cmsg_len;
601 535
602 // DCHECK_LE above already checks that 536 // DCHECK_LE above already checks that
603 // num_fds < kMaxDescriptorsPerMessage so no danger of overflow. 537 // num_fds < kMaxDescriptorsPerMessage so no danger of overflow.
604 msg->header()->num_fds = static_cast<uint16>(num_fds); 538 msg->header()->num_fds = static_cast<uint16>(num_fds);
605 539
606 #if defined(IPC_USES_READWRITE) 540 #if defined(IPC_USES_READWRITE)
607 if (!IsHelloMessage(msg)) { 541 if (!IsHelloMessage(*msg)) {
608 // Only the Hello message sends the file descriptor with the message. 542 // Only the Hello message sends the file descriptor with the message.
609 // Subsequently, we can send file descriptors on the dedicated 543 // Subsequently, we can send file descriptors on the dedicated
610 // fd_pipe_ which makes Seccomp sandbox operation more efficient. 544 // fd_pipe_ which makes Seccomp sandbox operation more efficient.
611 struct iovec fd_pipe_iov = { const_cast<char *>(""), 1 }; 545 struct iovec fd_pipe_iov = { const_cast<char *>(""), 1 };
612 msgh.msg_iov = &fd_pipe_iov; 546 msgh.msg_iov = &fd_pipe_iov;
613 fd_written = fd_pipe_; 547 fd_written = fd_pipe_;
614 bytes_written = HANDLE_EINTR(sendmsg(fd_pipe_, &msgh, MSG_DONTWAIT)); 548 bytes_written = HANDLE_EINTR(sendmsg(fd_pipe_, &msgh, MSG_DONTWAIT));
615 msgh.msg_iov = &iov; 549 msgh.msg_iov = &iov;
616 msgh.msg_controllen = 0; 550 msgh.msg_controllen = 0;
617 if (bytes_written > 0) { 551 if (bytes_written > 0) {
618 msg->file_descriptor_set()->CommitAll(); 552 msg->file_descriptor_set()->CommitAll();
619 } 553 }
620 } 554 }
621 #endif // IPC_USES_READWRITE 555 #endif // IPC_USES_READWRITE
622 } 556 }
623 557
624 if (bytes_written == 1) { 558 if (bytes_written == 1) {
625 fd_written = pipe_; 559 fd_written = pipe_;
626 #if defined(IPC_USES_READWRITE) 560 #if defined(IPC_USES_READWRITE)
627 if ((mode_ & MODE_CLIENT_FLAG) && IsHelloMessage(msg)) { 561 if ((mode_ & MODE_CLIENT_FLAG) && IsHelloMessage(*msg)) {
628 DCHECK_EQ(msg->file_descriptor_set()->size(), 1U); 562 DCHECK_EQ(msg->file_descriptor_set()->size(), 1U);
629 } 563 }
630 if (!msgh.msg_controllen) { 564 if (!msgh.msg_controllen) {
631 bytes_written = HANDLE_EINTR(write(pipe_, out_bytes, amt_to_write)); 565 bytes_written = HANDLE_EINTR(write(pipe_, out_bytes, amt_to_write));
632 } else 566 } else
633 #endif // IPC_USES_READWRITE 567 #endif // IPC_USES_READWRITE
634 { 568 {
635 bytes_written = HANDLE_EINTR(sendmsg(pipe_, &msgh, MSG_DONTWAIT)); 569 bytes_written = HANDLE_EINTR(sendmsg(pipe_, &msgh, MSG_DONTWAIT));
636 } 570 }
637 } 571 }
(...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after
809 } 743 }
810 #endif // OS_LINUX 744 #endif // OS_LINUX
811 745
812 // Called by libevent when we can read from the pipe without blocking. 746 // Called by libevent when we can read from the pipe without blocking.
813 void Channel::ChannelImpl::OnFileCanReadWithoutBlocking(int fd) { 747 void Channel::ChannelImpl::OnFileCanReadWithoutBlocking(int fd) {
814 bool send_server_hello_msg = false; 748 bool send_server_hello_msg = false;
815 if (fd == server_listen_pipe_) { 749 if (fd == server_listen_pipe_) {
816 int new_pipe = 0; 750 int new_pipe = 0;
817 if (!ServerAcceptConnection(server_listen_pipe_, &new_pipe)) { 751 if (!ServerAcceptConnection(server_listen_pipe_, &new_pipe)) {
818 Close(); 752 Close();
819 listener_->OnChannelListenError(); 753 listener()->OnChannelListenError();
820 } 754 }
821 755
822 if (pipe_ != -1) { 756 if (pipe_ != -1) {
823 // We already have a connection. We only handle one at a time. 757 // We already have a connection. We only handle one at a time.
824 // close our new descriptor. 758 // close our new descriptor.
825 if (HANDLE_EINTR(shutdown(new_pipe, SHUT_RDWR)) < 0) 759 if (HANDLE_EINTR(shutdown(new_pipe, SHUT_RDWR)) < 0)
826 DPLOG(ERROR) << "shutdown " << pipe_name_; 760 DPLOG(ERROR) << "shutdown " << pipe_name_;
827 if (HANDLE_EINTR(close(new_pipe)) < 0) 761 if (HANDLE_EINTR(close(new_pipe)) < 0)
828 DPLOG(ERROR) << "close " << pipe_name_; 762 DPLOG(ERROR) << "close " << pipe_name_;
829 listener_->OnChannelDenied(); 763 listener()->OnChannelDenied();
830 return; 764 return;
831 } 765 }
832 pipe_ = new_pipe; 766 pipe_ = new_pipe;
833 767
834 if ((mode_ & MODE_OPEN_ACCESS_FLAG) == 0) { 768 if ((mode_ & MODE_OPEN_ACCESS_FLAG) == 0) {
835 // Verify that the IPC channel peer is running as the same user. 769 // Verify that the IPC channel peer is running as the same user.
836 uid_t client_euid; 770 uid_t client_euid;
837 if (!GetClientEuid(&client_euid)) { 771 if (!GetClientEuid(&client_euid)) {
838 DLOG(ERROR) << "Unable to query client euid"; 772 DLOG(ERROR) << "Unable to query client euid";
839 ResetToAcceptingConnectionState(); 773 ResetToAcceptingConnectionState();
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
903 return true; 837 return true;
904 } else { 838 } else {
905 NOTREACHED(); 839 NOTREACHED();
906 return false; 840 return false;
907 } 841 }
908 } 842 }
909 843
910 void Channel::ChannelImpl::ClosePipeOnError() { 844 void Channel::ChannelImpl::ClosePipeOnError() {
911 if (HasAcceptedConnection()) { 845 if (HasAcceptedConnection()) {
912 ResetToAcceptingConnectionState(); 846 ResetToAcceptingConnectionState();
913 listener_->OnChannelError(); 847 listener()->OnChannelError();
914 } else { 848 } else {
915 Close(); 849 Close();
916 if (AcceptsConnections()) { 850 if (AcceptsConnections()) {
917 listener_->OnChannelListenError(); 851 listener()->OnChannelListenError();
918 } else { 852 } else {
919 listener_->OnChannelError(); 853 listener()->OnChannelError();
920 } 854 }
921 } 855 }
922 } 856 }
923 857
924 int Channel::ChannelImpl::GetHelloMessageProcId() { 858 int Channel::ChannelImpl::GetHelloMessageProcId() {
925 int pid = base::GetCurrentProcId(); 859 int pid = base::GetCurrentProcId();
926 #if defined(OS_LINUX) 860 #if defined(OS_LINUX)
927 // Our process may be in a sandbox with a separate PID namespace. 861 // Our process may be in a sandbox with a separate PID namespace.
928 if (global_pid_) { 862 if (global_pid_) {
929 pid = global_pid_; 863 pid = global_pid_;
(...skipping 16 matching lines...) Expand all
946 if (!msg->WriteFileDescriptor(base::FileDescriptor(remote_fd_pipe_, 880 if (!msg->WriteFileDescriptor(base::FileDescriptor(remote_fd_pipe_,
947 false))) { 881 false))) {
948 NOTREACHED() << "Unable to pickle hello message file descriptors"; 882 NOTREACHED() << "Unable to pickle hello message file descriptors";
949 } 883 }
950 DCHECK_EQ(msg->file_descriptor_set()->size(), 1U); 884 DCHECK_EQ(msg->file_descriptor_set()->size(), 1U);
951 } 885 }
952 #endif // IPC_USES_READWRITE 886 #endif // IPC_USES_READWRITE
953 output_queue_.push(msg.release()); 887 output_queue_.push(msg.release());
954 } 888 }
955 889
956 bool Channel::ChannelImpl::IsHelloMessage(const Message* m) const {
957 return m->routing_id() == MSG_ROUTING_NONE && m->type() == HELLO_MESSAGE_TYPE;
958 }
959
960 Channel::ChannelImpl::ReadState Channel::ChannelImpl::ReadData( 890 Channel::ChannelImpl::ReadState Channel::ChannelImpl::ReadData(
961 char* buffer, 891 char* buffer,
962 int buffer_len, 892 int buffer_len,
963 int* bytes_read) { 893 int* bytes_read) {
964 if (pipe_ == -1) 894 if (pipe_ == -1)
965 return READ_FAILED; 895 return READ_FAILED;
966 896
967 struct msghdr msg = {0}; 897 struct msghdr msg = {0};
968 898
969 struct iovec iov = {buffer, buffer_len}; 899 struct iovec iov = {buffer, buffer_len};
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
1028 958
1029 if (bytes_received != 1) 959 if (bytes_received != 1)
1030 return true; // No message waiting. 960 return true; // No message waiting.
1031 961
1032 if (!ExtractFileDescriptorsFromMsghdr(&msg)) 962 if (!ExtractFileDescriptorsFromMsghdr(&msg))
1033 return false; 963 return false;
1034 return true; 964 return true;
1035 } 965 }
1036 #endif 966 #endif
1037 967
968 // On Posix, we need to fix up the file descriptors before the input message
969 // is dispatched.
970 //
971 // This will read from the input_fds_ (READWRITE mode only) and read more
972 // handles from the FD pipe if necessary.
1038 bool Channel::ChannelImpl::WillDispatchInputMessage(Message* msg) { 973 bool Channel::ChannelImpl::WillDispatchInputMessage(Message* msg) {
1039 uint16 header_fds = msg->header()->num_fds; 974 uint16 header_fds = msg->header()->num_fds;
1040 if (!header_fds) 975 if (!header_fds)
1041 return true; // Nothing to do. 976 return true; // Nothing to do.
1042 977
1043 // The message has file descriptors. 978 // The message has file descriptors.
1044 const char* error = NULL; 979 const char* error = NULL;
1045 if (header_fds > input_fds_.size()) { 980 if (header_fds > input_fds_.size()) {
1046 // The message has been completely received, but we didn't get 981 // The message has been completely received, but we didn't get
1047 // enough file descriptors. 982 // enough file descriptors.
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
1138 // subsequent file descriptor passing. 1073 // subsequent file descriptor passing.
1139 DCHECK_EQ(msg.file_descriptor_set()->size(), 1U); 1074 DCHECK_EQ(msg.file_descriptor_set()->size(), 1U);
1140 base::FileDescriptor descriptor; 1075 base::FileDescriptor descriptor;
1141 if (!msg.ReadFileDescriptor(&iter, &descriptor)) { 1076 if (!msg.ReadFileDescriptor(&iter, &descriptor)) {
1142 NOTREACHED(); 1077 NOTREACHED();
1143 } 1078 }
1144 fd_pipe_ = descriptor.fd; 1079 fd_pipe_ = descriptor.fd;
1145 CHECK(descriptor.auto_close); 1080 CHECK(descriptor.auto_close);
1146 } 1081 }
1147 #endif // IPC_USES_READWRITE 1082 #endif // IPC_USES_READWRITE
1148 listener_->OnChannelConnected(pid); 1083 listener()->OnChannelConnected(pid);
1149 } 1084 }
1150 1085
1151 void Channel::ChannelImpl::Close() { 1086 void Channel::ChannelImpl::Close() {
1152 // Close can be called multiple time, so we need to make sure we're 1087 // Close can be called multiple time, so we need to make sure we're
1153 // idempotent. 1088 // idempotent.
1154 1089
1155 ResetToAcceptingConnectionState(); 1090 ResetToAcceptingConnectionState();
1156 1091
1157 if (must_unlink_) { 1092 if (must_unlink_) {
1158 unlink(pipe_name_.c_str()); 1093 unlink(pipe_name_.c_str());
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
1226 } 1161 }
1227 1162
1228 #if defined(OS_LINUX) 1163 #if defined(OS_LINUX)
1229 // static 1164 // static
1230 void Channel::SetGlobalPid(int pid) { 1165 void Channel::SetGlobalPid(int pid) {
1231 ChannelImpl::SetGlobalPid(pid); 1166 ChannelImpl::SetGlobalPid(pid);
1232 } 1167 }
1233 #endif // OS_LINUX 1168 #endif // OS_LINUX
1234 1169
1235 } // namespace IPC 1170 } // namespace IPC
OLDNEW
« no previous file with comments | « ipc/ipc_channel_posix.h ('k') | ipc/ipc_channel_reader.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698