Roll google-toolbax-for-mac a095262:17eee69 (svn 685:703).
[chromium-blink-merge.git] / ipc / ipc_channel_reader.cc
blobf41a0d7737e4656cd279db0de8ef83c2b9e9fbaa
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
3 // found in the LICENSE file.
5 #include "ipc/ipc_channel_reader.h"
7 #include "ipc/ipc_listener.h"
8 #include "ipc/ipc_logging.h"
9 #include "ipc/ipc_message_macros.h"
11 namespace IPC {
12 namespace internal {
14 ChannelReader::ChannelReader(Listener* listener) : listener_(listener) {
15 memset(input_buf_, 0, sizeof(input_buf_));
18 ChannelReader::~ChannelReader() {
21 bool ChannelReader::ProcessIncomingMessages() {
22 while (true) {
23 int bytes_read = 0;
24 ReadState read_state = ReadData(input_buf_, Channel::kReadBufferSize,
25 &bytes_read);
26 if (read_state == READ_FAILED)
27 return false;
28 if (read_state == READ_PENDING)
29 return true;
31 DCHECK(bytes_read > 0);
32 if (!DispatchInputData(input_buf_, bytes_read))
33 return false;
37 bool ChannelReader::AsyncReadComplete(int bytes_read) {
38 return DispatchInputData(input_buf_, bytes_read);
41 bool ChannelReader::IsInternalMessage(const Message& m) {
42 return m.routing_id() == MSG_ROUTING_NONE &&
43 m.type() >= Channel::CLOSE_FD_MESSAGE_TYPE &&
44 m.type() <= Channel::HELLO_MESSAGE_TYPE;
47 bool ChannelReader::IsHelloMessage(const Message& m) {
48 return m.routing_id() == MSG_ROUTING_NONE &&
49 m.type() == Channel::HELLO_MESSAGE_TYPE;
52 bool ChannelReader::DispatchInputData(const char* input_data,
53 int input_data_len) {
54 const char* p;
55 const char* end;
57 // Possibly combine with the overflow buffer to make a larger buffer.
58 if (input_overflow_buf_.empty()) {
59 p = input_data;
60 end = input_data + input_data_len;
61 } else {
62 if (input_overflow_buf_.size() + input_data_len >
63 Channel::kMaximumMessageSize) {
64 input_overflow_buf_.clear();
65 LOG(ERROR) << "IPC message is too big";
66 return false;
68 input_overflow_buf_.append(input_data, input_data_len);
69 p = input_overflow_buf_.data();
70 end = p + input_overflow_buf_.size();
73 // Dispatch all complete messages in the data buffer.
74 while (p < end) {
75 const char* message_tail = Message::FindNext(p, end);
76 if (message_tail) {
77 int len = static_cast<int>(message_tail - p);
78 Message m(p, len);
79 if (!WillDispatchInputMessage(&m))
80 return false;
82 #ifdef IPC_MESSAGE_LOG_ENABLED
83 std::string name;
84 Logging::GetInstance()->GetMessageText(m.type(), &name, &m, NULL);
85 TRACE_EVENT1("ipc,toplevel", "ChannelReader::DispatchInputData",
86 "name", name);
87 #else
88 TRACE_EVENT2("ipc,toplevel", "ChannelReader::DispatchInputData",
89 "class", IPC_MESSAGE_ID_CLASS(m.type()),
90 "line", IPC_MESSAGE_ID_LINE(m.type()));
91 #endif
92 m.TraceMessageEnd();
93 if (IsInternalMessage(m))
94 HandleInternalMessage(m);
95 else
96 listener_->OnMessageReceived(m);
97 if (m.dispatch_error())
98 listener_->OnBadMessageReceived(m);
99 p = message_tail;
100 } else {
101 // Last message is partial.
102 break;
106 // Save any partial data in the overflow buffer.
107 input_overflow_buf_.assign(p, end - p);
109 if (input_overflow_buf_.empty() && !DidEmptyInputBuffers())
110 return false;
111 return true;
115 } // namespace internal
116 } // namespace IPC