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

Unified 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, 10 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « ipc/ipc_channel_posix.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: ipc/ipc_channel_posix.cc
diff --git a/ipc/ipc_channel_posix.cc b/ipc/ipc_channel_posix.cc
index 573015378ad7fb1fa154a29fe58757a0f59ad419..1960cb037e0c4f927b10196b5f5373ee1bdfd77a 100644
--- a/ipc/ipc_channel_posix.cc
+++ b/ipc/ipc_channel_posix.cc
@@ -479,48 +479,68 @@ bool Channel::ChannelImpl::Connect() {
}
bool Channel::ChannelImpl::ProcessIncomingMessages() {
- for (;;) {
- if (pipe_ == -1)
brettw 2012/03/01 06:43:23 This check moved to ReadData
+ while (true) {
+ int bytes_read = 0;
+ ReadState read_state = ReadData(input_buf_, Channel::kReadBufferSize,
+ &bytes_read);
+ if (read_state == READ_FAILED)
return false;
+ if (read_state == READ_PENDING)
+ return true;
- const char* p = NULL;
- const char* end = NULL;
- if (!ReadDataFromPipe(&p, &end))
- return false; // Pipe error.
- if (!p)
- return true; // No data waiting.
-
- // Dispatch all complete messages in the data buffer.
- while (p < end) {
brettw 2012/03/01 06:43:23 This block moved to DispatchInputData.
- const char* message_tail = Message::FindNext(p, end);
- if (message_tail) {
- int len = static_cast<int>(message_tail - p);
- Message m(p, len);
- if (!PopulateMessageFileDescriptors(&m))
brettw 2012/03/01 06:43:23 This was renamed to WillDispatchInputMessage (sinc
- return false;
+ DCHECK(bytes_read > 0);
+ if (!DispatchInputData(input_buf_, bytes_read))
+ return false;
+ }
+}
- DVLOG(2) << "received message on channel @" << this
- << " with type " << m.type() << " on fd " << pipe_;
- if (IsHelloMessage(&m))
- HandleHelloMessage(m);
- else
- listener_->OnMessageReceived(m);
- p = message_tail;
- } else {
- // Last message is partial.
- break;
- }
- }
- input_overflow_buf_.assign(p, end - p);
+bool Channel::ChannelImpl::DispatchInputData(const char* input_data,
+ int input_data_len) {
+ const char* p;
+ const char* end;
- // When the input data buffer is empty, the fds should be too. If this is
- // not the case, we probably have a rogue renderer which is trying to fill
- // our descriptor table.
- if (input_overflow_buf_.empty() && !input_fds_.empty()) {
brettw 2012/03/01 06:43:23 This check moved to DidEmptyInputBuffers.
- // We close these descriptors in Close()
+ // Possibly combine with the overflow buffer to make a larger buffer.
+ if (input_overflow_buf_.empty()) {
+ p = input_data;
+ end = input_data + input_data_len;
+ } else {
+ if (input_overflow_buf_.size() >
+ kMaximumMessageSize - input_data_len) {
+ input_overflow_buf_.clear();
+ LOG(ERROR) << "IPC message is too big";
return false;
}
+ input_overflow_buf_.append(input_data, input_data_len);
+ p = input_overflow_buf_.data();
+ end = p + input_overflow_buf_.size();
}
+
+ // Dispatch all complete messages in the data buffer.
+ while (p < end) {
+ const char* message_tail = Message::FindNext(p, end);
+ if (message_tail) {
+ int len = static_cast<int>(message_tail - p);
+ Message m(p, len);
+ if (!WillDispatchInputMessage(&m))
+ return false;
+
+ if (IsHelloMessage(&m))
+ HandleHelloMessage(m);
+ else
+ listener_->OnMessageReceived(m);
+ p = message_tail;
+ } else {
+ // Last message is partial.
+ break;
+ }
+ }
+
+ // Save any partial data in the overflow buffer.
+ input_overflow_buf_.assign(p, end - p);
+
+ if (input_overflow_buf_.empty() && !DidEmptyInputBuffers())
+ return false;
+ return true;
}
bool Channel::ChannelImpl::ProcessOutgoingMessages() {
@@ -937,11 +957,16 @@ bool Channel::ChannelImpl::IsHelloMessage(const Message* m) const {
return m->routing_id() == MSG_ROUTING_NONE && m->type() == HELLO_MESSAGE_TYPE;
}
-bool Channel::ChannelImpl::ReadDataFromPipe(const char** buffer_begin,
- const char** buffer_end) {
+Channel::ChannelImpl::ReadState Channel::ChannelImpl::ReadData(
+ char* buffer,
+ int buffer_len,
+ int* bytes_read) {
+ if (pipe_ == -1)
+ return READ_FAILED;
+
struct msghdr msg = {0};
- struct iovec iov = {input_buf_, Channel::kReadBufferSize};
+ struct iovec iov = {buffer, buffer_len};
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
@@ -949,62 +974,44 @@ bool Channel::ChannelImpl::ReadDataFromPipe(const char** buffer_begin,
// recvmsg() returns 0 if the connection has closed or EAGAIN if no data
// is waiting on the pipe.
- ssize_t bytes_read = 0;
#if defined(IPC_USES_READWRITE)
if (fd_pipe_ >= 0) {
- bytes_read = HANDLE_EINTR(read(pipe_, input_buf_,
- Channel::kReadBufferSize));
+ *bytes_read = HANDLE_EINTR(read(pipe_, buffer, buffer_len));
msg.msg_controllen = 0;
} else
#endif // IPC_USES_READWRITE
{
msg.msg_controllen = sizeof(input_cmsg_buf_);
- bytes_read = HANDLE_EINTR(recvmsg(pipe_, &msg, MSG_DONTWAIT));
+ *bytes_read = HANDLE_EINTR(recvmsg(pipe_, &msg, MSG_DONTWAIT));
}
- if (bytes_read < 0) {
+ if (*bytes_read < 0) {
if (errno == EAGAIN) {
- *buffer_begin = *buffer_end = NULL; // Signal no data was read.
- return true;
+ return READ_PENDING;
#if defined(OS_MACOSX)
} else if (errno == EPERM) {
// On OSX, reading from a pipe with no listener returns EPERM
// treat this as a special case to prevent spurious error messages
// to the console.
- return false;
+ return READ_FAILED;
#endif // OS_MACOSX
} else if (errno == ECONNRESET || errno == EPIPE) {
- return false;
+ return READ_FAILED;
} else {
PLOG(ERROR) << "pipe error (" << pipe_ << ")";
- return false;
+ return READ_FAILED;
}
- } else if (bytes_read == 0) {
+ } else if (*bytes_read == 0) {
// The pipe has closed...
- return false;
+ return READ_FAILED;
}
- DCHECK(bytes_read);
+ DCHECK(*bytes_read);
CloseClientFileDescriptor();
// Read any file descriptors from the message.
if (!ExtractFileDescriptorsFromMsghdr(&msg))
- return false;
-
- // Possibly combine with the overflow buffer to make a larger buffer.
brettw 2012/03/01 06:43:23 This moved to DispatchInputData.
- if (input_overflow_buf_.empty()) {
- *buffer_begin = input_buf_;
- *buffer_end = *buffer_begin + bytes_read;
- } else {
- if (input_overflow_buf_.size() > (kMaximumMessageSize - bytes_read)) {
- input_overflow_buf_.clear();
- LOG(ERROR) << "IPC message is too big";
- return false;
- }
- input_overflow_buf_.append(input_buf_, bytes_read);
- *buffer_begin = input_overflow_buf_.data();
- *buffer_end = *buffer_begin + input_overflow_buf_.size();
- }
- return true;
+ return READ_FAILED;
+ return READ_SUCCEEDED;
}
#if defined(IPC_USES_READWRITE)
@@ -1028,7 +1035,7 @@ bool Channel::ChannelImpl::ReadFileDescriptorsFromFDPipe() {
}
#endif
-bool Channel::ChannelImpl::PopulateMessageFileDescriptors(Message* msg) {
+bool Channel::ChannelImpl::WillDispatchInputMessage(Message* msg) {
uint16 header_fds = msg->header()->num_fds;
if (!header_fds)
return true; // Nothing to do.
@@ -1070,6 +1077,13 @@ bool Channel::ChannelImpl::PopulateMessageFileDescriptors(Message* msg) {
return true;
}
+bool Channel::ChannelImpl::DidEmptyInputBuffers() {
+ // When the input data buffer is empty, the fds should be too. If this is
+ // not the case, we probably have a rogue renderer which is trying to fill
+ // our descriptor table.
+ return input_fds_.empty();
+}
+
bool Channel::ChannelImpl::ExtractFileDescriptorsFromMsghdr(msghdr* msg) {
// Check that there are any control messages. On OSX, CMSG_FIRSTHDR will
// return an invalid non-NULL pointer in the case that controllen == 0.
« 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