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

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') | no next file » | 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 461 matching lines...) Expand 10 before | Expand all | Expand 10 after
472 MessageLoopForIO::WATCH_READ, 472 MessageLoopForIO::WATCH_READ,
473 &server_listen_connection_watcher_, 473 &server_listen_connection_watcher_,
474 this); 474 this);
475 } else { 475 } else {
476 did_connect = AcceptConnection(); 476 did_connect = AcceptConnection();
477 } 477 }
478 return did_connect; 478 return did_connect;
479 } 479 }
480 480
481 bool Channel::ChannelImpl::ProcessIncomingMessages() { 481 bool Channel::ChannelImpl::ProcessIncomingMessages() {
482 for (;;) { 482 while (true) {
483 if (pipe_ == -1) 483 int bytes_read = 0;
brettw 2012/03/01 06:43:23 This check moved to ReadData
484 ReadState read_state = ReadData(input_buf_, Channel::kReadBufferSize,
485 &bytes_read);
486 if (read_state == READ_FAILED)
484 return false; 487 return false;
488 if (read_state == READ_PENDING)
489 return true;
485 490
486 const char* p = NULL; 491 DCHECK(bytes_read > 0);
487 const char* end = NULL; 492 if (!DispatchInputData(input_buf_, bytes_read))
488 if (!ReadDataFromPipe(&p, &end))
489 return false; // Pipe error.
490 if (!p)
491 return true; // No data waiting.
492
493 // Dispatch all complete messages in the data buffer.
494 while (p < end) {
brettw 2012/03/01 06:43:23 This block moved to DispatchInputData.
495 const char* message_tail = Message::FindNext(p, end);
496 if (message_tail) {
497 int len = static_cast<int>(message_tail - p);
498 Message m(p, len);
499 if (!PopulateMessageFileDescriptors(&m))
brettw 2012/03/01 06:43:23 This was renamed to WillDispatchInputMessage (sinc
500 return false;
501
502 DVLOG(2) << "received message on channel @" << this
503 << " with type " << m.type() << " on fd " << pipe_;
504 if (IsHelloMessage(&m))
505 HandleHelloMessage(m);
506 else
507 listener_->OnMessageReceived(m);
508 p = message_tail;
509 } else {
510 // Last message is partial.
511 break;
512 }
513 }
514 input_overflow_buf_.assign(p, end - p);
515
516 // When the input data buffer is empty, the fds should be too. If this is
517 // not the case, we probably have a rogue renderer which is trying to fill
518 // our descriptor table.
519 if (input_overflow_buf_.empty() && !input_fds_.empty()) {
brettw 2012/03/01 06:43:23 This check moved to DidEmptyInputBuffers.
520 // We close these descriptors in Close()
521 return false; 493 return false;
522 }
523 } 494 }
524 } 495 }
525 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
526 bool Channel::ChannelImpl::ProcessOutgoingMessages() { 546 bool Channel::ChannelImpl::ProcessOutgoingMessages() {
527 DCHECK(!waiting_connect_); // Why are we trying to send messages if there's 547 DCHECK(!waiting_connect_); // Why are we trying to send messages if there's
528 // no connection? 548 // no connection?
529 if (output_queue_.empty()) 549 if (output_queue_.empty())
530 return true; 550 return true;
531 551
532 if (pipe_ == -1) 552 if (pipe_ == -1)
533 return false; 553 return false;
534 554
535 // Write out all the messages we can till the write blocks or there are no 555 // Write out all the messages we can till the write blocks or there are no
(...skipping 394 matching lines...) Expand 10 before | Expand all | Expand 10 after
930 DCHECK_EQ(msg->file_descriptor_set()->size(), 1U); 950 DCHECK_EQ(msg->file_descriptor_set()->size(), 1U);
931 } 951 }
932 #endif // IPC_USES_READWRITE 952 #endif // IPC_USES_READWRITE
933 output_queue_.push(msg.release()); 953 output_queue_.push(msg.release());
934 } 954 }
935 955
936 bool Channel::ChannelImpl::IsHelloMessage(const Message* m) const { 956 bool Channel::ChannelImpl::IsHelloMessage(const Message* m) const {
937 return m->routing_id() == MSG_ROUTING_NONE && m->type() == HELLO_MESSAGE_TYPE; 957 return m->routing_id() == MSG_ROUTING_NONE && m->type() == HELLO_MESSAGE_TYPE;
938 } 958 }
939 959
940 bool Channel::ChannelImpl::ReadDataFromPipe(const char** buffer_begin, 960 Channel::ChannelImpl::ReadState Channel::ChannelImpl::ReadData(
941 const char** buffer_end) { 961 char* buffer,
962 int buffer_len,
963 int* bytes_read) {
964 if (pipe_ == -1)
965 return READ_FAILED;
966
942 struct msghdr msg = {0}; 967 struct msghdr msg = {0};
943 968
944 struct iovec iov = {input_buf_, Channel::kReadBufferSize}; 969 struct iovec iov = {buffer, buffer_len};
945 msg.msg_iov = &iov; 970 msg.msg_iov = &iov;
946 msg.msg_iovlen = 1; 971 msg.msg_iovlen = 1;
947 972
948 msg.msg_control = input_cmsg_buf_; 973 msg.msg_control = input_cmsg_buf_;
949 974
950 // recvmsg() returns 0 if the connection has closed or EAGAIN if no data 975 // recvmsg() returns 0 if the connection has closed or EAGAIN if no data
951 // is waiting on the pipe. 976 // is waiting on the pipe.
952 ssize_t bytes_read = 0;
953 #if defined(IPC_USES_READWRITE) 977 #if defined(IPC_USES_READWRITE)
954 if (fd_pipe_ >= 0) { 978 if (fd_pipe_ >= 0) {
955 bytes_read = HANDLE_EINTR(read(pipe_, input_buf_, 979 *bytes_read = HANDLE_EINTR(read(pipe_, buffer, buffer_len));
956 Channel::kReadBufferSize));
957 msg.msg_controllen = 0; 980 msg.msg_controllen = 0;
958 } else 981 } else
959 #endif // IPC_USES_READWRITE 982 #endif // IPC_USES_READWRITE
960 { 983 {
961 msg.msg_controllen = sizeof(input_cmsg_buf_); 984 msg.msg_controllen = sizeof(input_cmsg_buf_);
962 bytes_read = HANDLE_EINTR(recvmsg(pipe_, &msg, MSG_DONTWAIT)); 985 *bytes_read = HANDLE_EINTR(recvmsg(pipe_, &msg, MSG_DONTWAIT));
963 } 986 }
964 if (bytes_read < 0) { 987 if (*bytes_read < 0) {
965 if (errno == EAGAIN) { 988 if (errno == EAGAIN) {
966 *buffer_begin = *buffer_end = NULL; // Signal no data was read. 989 return READ_PENDING;
967 return true;
968 #if defined(OS_MACOSX) 990 #if defined(OS_MACOSX)
969 } else if (errno == EPERM) { 991 } else if (errno == EPERM) {
970 // On OSX, reading from a pipe with no listener returns EPERM 992 // On OSX, reading from a pipe with no listener returns EPERM
971 // treat this as a special case to prevent spurious error messages 993 // treat this as a special case to prevent spurious error messages
972 // to the console. 994 // to the console.
973 return false; 995 return READ_FAILED;
974 #endif // OS_MACOSX 996 #endif // OS_MACOSX
975 } else if (errno == ECONNRESET || errno == EPIPE) { 997 } else if (errno == ECONNRESET || errno == EPIPE) {
976 return false; 998 return READ_FAILED;
977 } else { 999 } else {
978 PLOG(ERROR) << "pipe error (" << pipe_ << ")"; 1000 PLOG(ERROR) << "pipe error (" << pipe_ << ")";
979 return false; 1001 return READ_FAILED;
980 } 1002 }
981 } else if (bytes_read == 0) { 1003 } else if (*bytes_read == 0) {
982 // The pipe has closed... 1004 // The pipe has closed...
983 return false; 1005 return READ_FAILED;
984 } 1006 }
985 DCHECK(bytes_read); 1007 DCHECK(*bytes_read);
986 1008
987 CloseClientFileDescriptor(); 1009 CloseClientFileDescriptor();
988 1010
989 // Read any file descriptors from the message. 1011 // Read any file descriptors from the message.
990 if (!ExtractFileDescriptorsFromMsghdr(&msg)) 1012 if (!ExtractFileDescriptorsFromMsghdr(&msg))
991 return false; 1013 return READ_FAILED;
992 1014 return READ_SUCCEEDED;
993 // Possibly combine with the overflow buffer to make a larger buffer.
brettw 2012/03/01 06:43:23 This moved to DispatchInputData.
994 if (input_overflow_buf_.empty()) {
995 *buffer_begin = input_buf_;
996 *buffer_end = *buffer_begin + bytes_read;
997 } else {
998 if (input_overflow_buf_.size() > (kMaximumMessageSize - bytes_read)) {
999 input_overflow_buf_.clear();
1000 LOG(ERROR) << "IPC message is too big";
1001 return false;
1002 }
1003 input_overflow_buf_.append(input_buf_, bytes_read);
1004 *buffer_begin = input_overflow_buf_.data();
1005 *buffer_end = *buffer_begin + input_overflow_buf_.size();
1006 }
1007 return true;
1008 } 1015 }
1009 1016
1010 #if defined(IPC_USES_READWRITE) 1017 #if defined(IPC_USES_READWRITE)
1011 bool Channel::ChannelImpl::ReadFileDescriptorsFromFDPipe() { 1018 bool Channel::ChannelImpl::ReadFileDescriptorsFromFDPipe() {
1012 char dummy; 1019 char dummy;
1013 struct iovec fd_pipe_iov = { &dummy, 1 }; 1020 struct iovec fd_pipe_iov = { &dummy, 1 };
1014 1021
1015 struct msghdr msg = { 0 }; 1022 struct msghdr msg = { 0 };
1016 msg.msg_iov = &fd_pipe_iov; 1023 msg.msg_iov = &fd_pipe_iov;
1017 msg.msg_iovlen = 1; 1024 msg.msg_iovlen = 1;
1018 msg.msg_control = input_cmsg_buf_; 1025 msg.msg_control = input_cmsg_buf_;
1019 msg.msg_controllen = sizeof(input_cmsg_buf_); 1026 msg.msg_controllen = sizeof(input_cmsg_buf_);
1020 ssize_t bytes_received = HANDLE_EINTR(recvmsg(fd_pipe_, &msg, MSG_DONTWAIT)); 1027 ssize_t bytes_received = HANDLE_EINTR(recvmsg(fd_pipe_, &msg, MSG_DONTWAIT));
1021 1028
1022 if (bytes_received != 1) 1029 if (bytes_received != 1)
1023 return true; // No message waiting. 1030 return true; // No message waiting.
1024 1031
1025 if (!ExtractFileDescriptorsFromMsghdr(&msg)) 1032 if (!ExtractFileDescriptorsFromMsghdr(&msg))
1026 return false; 1033 return false;
1027 return true; 1034 return true;
1028 } 1035 }
1029 #endif 1036 #endif
1030 1037
1031 bool Channel::ChannelImpl::PopulateMessageFileDescriptors(Message* msg) { 1038 bool Channel::ChannelImpl::WillDispatchInputMessage(Message* msg) {
1032 uint16 header_fds = msg->header()->num_fds; 1039 uint16 header_fds = msg->header()->num_fds;
1033 if (!header_fds) 1040 if (!header_fds)
1034 return true; // Nothing to do. 1041 return true; // Nothing to do.
1035 1042
1036 // The message has file descriptors. 1043 // The message has file descriptors.
1037 const char* error = NULL; 1044 const char* error = NULL;
1038 if (header_fds > input_fds_.size()) { 1045 if (header_fds > input_fds_.size()) {
1039 // The message has been completely received, but we didn't get 1046 // The message has been completely received, but we didn't get
1040 // enough file descriptors. 1047 // enough file descriptors.
1041 #if defined(IPC_USES_READWRITE) 1048 #if defined(IPC_USES_READWRITE)
(...skipping 21 matching lines...) Expand all
1063 ClearInputFDs(); 1070 ClearInputFDs();
1064 return false; 1071 return false;
1065 } 1072 }
1066 1073
1067 msg->file_descriptor_set()->SetDescriptors(&input_fds_.front(), 1074 msg->file_descriptor_set()->SetDescriptors(&input_fds_.front(),
1068 header_fds); 1075 header_fds);
1069 input_fds_.erase(input_fds_.begin(), input_fds_.begin() + header_fds); 1076 input_fds_.erase(input_fds_.begin(), input_fds_.begin() + header_fds);
1070 return true; 1077 return true;
1071 } 1078 }
1072 1079
1080 bool Channel::ChannelImpl::DidEmptyInputBuffers() {
1081 // When the input data buffer is empty, the fds should be too. If this is
1082 // not the case, we probably have a rogue renderer which is trying to fill
1083 // our descriptor table.
1084 return input_fds_.empty();
1085 }
1086
1073 bool Channel::ChannelImpl::ExtractFileDescriptorsFromMsghdr(msghdr* msg) { 1087 bool Channel::ChannelImpl::ExtractFileDescriptorsFromMsghdr(msghdr* msg) {
1074 // Check that there are any control messages. On OSX, CMSG_FIRSTHDR will 1088 // Check that there are any control messages. On OSX, CMSG_FIRSTHDR will
1075 // return an invalid non-NULL pointer in the case that controllen == 0. 1089 // return an invalid non-NULL pointer in the case that controllen == 0.
1076 if (msg->msg_controllen == 0) 1090 if (msg->msg_controllen == 0)
1077 return true; 1091 return true;
1078 1092
1079 for (cmsghdr* cmsg = CMSG_FIRSTHDR(msg); 1093 for (cmsghdr* cmsg = CMSG_FIRSTHDR(msg);
1080 cmsg; 1094 cmsg;
1081 cmsg = CMSG_NXTHDR(msg, cmsg)) { 1095 cmsg = CMSG_NXTHDR(msg, cmsg)) {
1082 if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) { 1096 if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) {
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after
1212 } 1226 }
1213 1227
1214 #if defined(OS_LINUX) 1228 #if defined(OS_LINUX)
1215 // static 1229 // static
1216 void Channel::SetGlobalPid(int pid) { 1230 void Channel::SetGlobalPid(int pid) {
1217 ChannelImpl::SetGlobalPid(pid); 1231 ChannelImpl::SetGlobalPid(pid);
1218 } 1232 }
1219 #endif // OS_LINUX 1233 #endif // OS_LINUX
1220 1234
1221 } // namespace IPC 1235 } // namespace IPC
OLDNEW
« no previous file with comments | « ipc/ipc_channel_posix.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698