blob: 28a889a41c55291bcb65faceb99bd0212778838b [file] [log] [blame]
brettw@chromium.org0e9d0a12012-03-08 21:30:28 +09001// 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.
4
5#include "ipc/ipc_channel_reader.h"
6
tfarina@chromium.orgb6d81202012-11-16 07:22:17 +09007#include "ipc/ipc_listener.h"
jbates@chromium.org7cc80332012-09-18 12:41:29 +09008#include "ipc/ipc_logging.h"
9#include "ipc/ipc_message_macros.h"
10
brettw@chromium.org0e9d0a12012-03-08 21:30:28 +090011namespace IPC {
12namespace internal {
13
brettw@chromium.orgf947ed02012-06-12 07:35:26 +090014ChannelReader::ChannelReader(Listener* listener) : listener_(listener) {
jhawkins@chromium.org4448a872012-03-13 05:45:03 +090015 memset(input_buf_, 0, sizeof(input_buf_));
brettw@chromium.org0e9d0a12012-03-08 21:30:28 +090016}
17
18ChannelReader::~ChannelReader() {
19}
20
21bool 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;
30
31 DCHECK(bytes_read > 0);
32 if (!DispatchInputData(input_buf_, bytes_read))
33 return false;
34 }
35}
36
37bool ChannelReader::AsyncReadComplete(int bytes_read) {
38 return DispatchInputData(input_buf_, bytes_read);
39}
40
morrita@chromium.org15996aa2014-08-05 08:44:17 +090041bool ChannelReader::IsInternalMessage(const Message& m) {
hubbe@chromium.org683920d2013-10-15 09:07:00 +090042 return m.routing_id() == MSG_ROUTING_NONE &&
43 m.type() >= Channel::CLOSE_FD_MESSAGE_TYPE &&
44 m.type() <= Channel::HELLO_MESSAGE_TYPE;
45}
46
morrita@chromium.org15996aa2014-08-05 08:44:17 +090047bool ChannelReader::IsHelloMessage(const Message& m) {
brettw@chromium.org0e9d0a12012-03-08 21:30:28 +090048 return m.routing_id() == MSG_ROUTING_NONE &&
hubbe@chromium.org683920d2013-10-15 09:07:00 +090049 m.type() == Channel::HELLO_MESSAGE_TYPE;
brettw@chromium.org0e9d0a12012-03-08 21:30:28 +090050}
51
52bool ChannelReader::DispatchInputData(const char* input_data,
53 int input_data_len) {
54 const char* p;
55 const char* end;
56
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 {
rkc@chromium.org3b17d8f2012-11-29 07:26:12 +090062 if (input_overflow_buf_.size() + input_data_len >
63 Channel::kMaximumMessageSize) {
brettw@chromium.org0e9d0a12012-03-08 21:30:28 +090064 input_overflow_buf_.clear();
65 LOG(ERROR) << "IPC message is too big";
66 return false;
67 }
68 input_overflow_buf_.append(input_data, input_data_len);
69 p = input_overflow_buf_.data();
70 end = p + input_overflow_buf_.size();
71 }
72
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;
81
jbates@chromium.org7cc80332012-09-18 12:41:29 +090082#ifdef IPC_MESSAGE_LOG_ENABLED
83 Logging* logger = Logging::GetInstance();
84 std::string name;
85 logger->GetMessageText(m.type(), &name, &m, NULL);
epenner@chromium.org24f2bea2014-05-03 06:29:24 +090086 TRACE_EVENT1("ipc,toplevel", "ChannelReader::DispatchInputData",
fmeawad@chromium.org4529a9d2014-02-07 03:28:53 +090087 "name", name);
jbates@chromium.org7cc80332012-09-18 12:41:29 +090088#else
epenner@chromium.org24f2bea2014-05-03 06:29:24 +090089 TRACE_EVENT2("ipc,toplevel", "ChannelReader::DispatchInputData",
jbates@chromium.org7cc80332012-09-18 12:41:29 +090090 "class", IPC_MESSAGE_ID_CLASS(m.type()),
91 "line", IPC_MESSAGE_ID_LINE(m.type()));
92#endif
93 m.TraceMessageEnd();
hubbe@chromium.org683920d2013-10-15 09:07:00 +090094 if (IsInternalMessage(m))
95 HandleInternalMessage(m);
brettw@chromium.org0e9d0a12012-03-08 21:30:28 +090096 else
97 listener_->OnMessageReceived(m);
jam@chromium.org822f1fb2014-05-16 08:06:07 +090098 if (m.dispatch_error())
99 listener_->OnBadMessageReceived(m);
brettw@chromium.org0e9d0a12012-03-08 21:30:28 +0900100 p = message_tail;
101 } else {
102 // Last message is partial.
103 break;
104 }
105 }
106
107 // Save any partial data in the overflow buffer.
108 input_overflow_buf_.assign(p, end - p);
109
110 if (input_overflow_buf_.empty() && !DidEmptyInputBuffers())
111 return false;
112 return true;
113}
114
115
116} // namespace internal
117} // namespace IPC