Index: ipc/ipc_channel_reader.cc |
diff --git a/ipc/ipc_channel_reader.cc b/ipc/ipc_channel_reader.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..47d1e8d50ee8902d03963592c36d54aa1acc98b7 |
--- /dev/null |
+++ b/ipc/ipc_channel_reader.cc |
@@ -0,0 +1,93 @@ |
+// Copyright (c) 2012 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "ipc/ipc_channel_reader.h" |
+ |
+namespace IPC { |
+namespace internal { |
+ |
+ChannelReader::ChannelReader(Channel::Listener* listener) |
+ : listener_(listener) { |
+} |
+ |
+ChannelReader::~ChannelReader() { |
+} |
+ |
+bool ChannelReader::ProcessIncomingMessages() { |
+ 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; |
+ |
+ DCHECK(bytes_read > 0); |
+ if (!DispatchInputData(input_buf_, bytes_read)) |
+ return false; |
+ } |
+} |
+ |
+bool ChannelReader::AsyncReadComplete(int bytes_read) { |
+ return DispatchInputData(input_buf_, bytes_read); |
+} |
+ |
+bool ChannelReader::IsHelloMessage(const Message& m) const { |
+ return m.routing_id() == MSG_ROUTING_NONE && |
+ m.type() == Channel::HELLO_MESSAGE_TYPE; |
+} |
+ |
+bool ChannelReader::DispatchInputData(const char* input_data, |
+ int input_data_len) { |
+ const char* p; |
+ const char* end; |
+ |
+ // 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() > |
+ Channel::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; |
+} |
+ |
+ |
+} // namespace internal |
+} // namespace IPC |