1*635a8641SAndroid Build Coastguard Worker // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2*635a8641SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*635a8641SAndroid Build Coastguard Worker // found in the LICENSE file.
4*635a8641SAndroid Build Coastguard Worker
5*635a8641SAndroid Build Coastguard Worker #include "ipc/ipc_channel_reader.h"
6*635a8641SAndroid Build Coastguard Worker
7*635a8641SAndroid Build Coastguard Worker #include <stddef.h>
8*635a8641SAndroid Build Coastguard Worker
9*635a8641SAndroid Build Coastguard Worker #include <algorithm>
10*635a8641SAndroid Build Coastguard Worker
11*635a8641SAndroid Build Coastguard Worker #include "base/logging.h"
12*635a8641SAndroid Build Coastguard Worker #include "base/threading/thread_task_runner_handle.h"
13*635a8641SAndroid Build Coastguard Worker #include "ipc/ipc_listener.h"
14*635a8641SAndroid Build Coastguard Worker #include "ipc/ipc_logging.h"
15*635a8641SAndroid Build Coastguard Worker #include "ipc/ipc_message.h"
16*635a8641SAndroid Build Coastguard Worker #include "ipc/ipc_message_attachment_set.h"
17*635a8641SAndroid Build Coastguard Worker #include "ipc/ipc_message_macros.h"
18*635a8641SAndroid Build Coastguard Worker
19*635a8641SAndroid Build Coastguard Worker namespace IPC {
20*635a8641SAndroid Build Coastguard Worker namespace internal {
21*635a8641SAndroid Build Coastguard Worker
22*635a8641SAndroid Build Coastguard Worker #if BUILDFLAG(IPC_MESSAGE_LOG_ENABLED)
23*635a8641SAndroid Build Coastguard Worker
24*635a8641SAndroid Build Coastguard Worker namespace {
GetMessageText(const Message & message)25*635a8641SAndroid Build Coastguard Worker std::string GetMessageText(const Message& message) {
26*635a8641SAndroid Build Coastguard Worker std::string name;
27*635a8641SAndroid Build Coastguard Worker Logging::GetInstance()->GetMessageText(
28*635a8641SAndroid Build Coastguard Worker message.type(), &name, &message, nullptr);
29*635a8641SAndroid Build Coastguard Worker return name;
30*635a8641SAndroid Build Coastguard Worker }
31*635a8641SAndroid Build Coastguard Worker } // namespace
32*635a8641SAndroid Build Coastguard Worker
33*635a8641SAndroid Build Coastguard Worker #define EMIT_TRACE_EVENT(message) \
34*635a8641SAndroid Build Coastguard Worker TRACE_EVENT_WITH_FLOW1( \
35*635a8641SAndroid Build Coastguard Worker "ipc,toplevel", "ChannelReader::DispatchInputData", \
36*635a8641SAndroid Build Coastguard Worker (message).flags(), TRACE_EVENT_FLAG_FLOW_IN, "name", \
37*635a8641SAndroid Build Coastguard Worker GetMessageText(message));
38*635a8641SAndroid Build Coastguard Worker #else
39*635a8641SAndroid Build Coastguard Worker #define EMIT_TRACE_EVENT(message) \
40*635a8641SAndroid Build Coastguard Worker TRACE_EVENT_WITH_FLOW2("ipc,toplevel", "ChannelReader::DispatchInputData", \
41*635a8641SAndroid Build Coastguard Worker (message).flags(), TRACE_EVENT_FLAG_FLOW_IN, "class", \
42*635a8641SAndroid Build Coastguard Worker IPC_MESSAGE_ID_CLASS((message).type()), "line", \
43*635a8641SAndroid Build Coastguard Worker IPC_MESSAGE_ID_LINE((message).type()));
44*635a8641SAndroid Build Coastguard Worker #endif // BUILDFLAG(IPC_MESSAGE_LOG_ENABLED)
45*635a8641SAndroid Build Coastguard Worker
ChannelReader(Listener * listener)46*635a8641SAndroid Build Coastguard Worker ChannelReader::ChannelReader(Listener* listener)
47*635a8641SAndroid Build Coastguard Worker : listener_(listener),
48*635a8641SAndroid Build Coastguard Worker max_input_buffer_size_(Channel::kMaximumReadBufferSize) {
49*635a8641SAndroid Build Coastguard Worker memset(input_buf_, 0, sizeof(input_buf_));
50*635a8641SAndroid Build Coastguard Worker }
51*635a8641SAndroid Build Coastguard Worker
52*635a8641SAndroid Build Coastguard Worker ChannelReader::~ChannelReader() = default;
53*635a8641SAndroid Build Coastguard Worker
ProcessIncomingMessages()54*635a8641SAndroid Build Coastguard Worker ChannelReader::DispatchState ChannelReader::ProcessIncomingMessages() {
55*635a8641SAndroid Build Coastguard Worker while (true) {
56*635a8641SAndroid Build Coastguard Worker int bytes_read = 0;
57*635a8641SAndroid Build Coastguard Worker ReadState read_state = ReadData(input_buf_, Channel::kReadBufferSize,
58*635a8641SAndroid Build Coastguard Worker &bytes_read);
59*635a8641SAndroid Build Coastguard Worker if (read_state == READ_FAILED)
60*635a8641SAndroid Build Coastguard Worker return DISPATCH_ERROR;
61*635a8641SAndroid Build Coastguard Worker if (read_state == READ_PENDING)
62*635a8641SAndroid Build Coastguard Worker return DISPATCH_FINISHED;
63*635a8641SAndroid Build Coastguard Worker
64*635a8641SAndroid Build Coastguard Worker DCHECK(bytes_read > 0);
65*635a8641SAndroid Build Coastguard Worker if (!TranslateInputData(input_buf_, bytes_read))
66*635a8641SAndroid Build Coastguard Worker return DISPATCH_ERROR;
67*635a8641SAndroid Build Coastguard Worker }
68*635a8641SAndroid Build Coastguard Worker }
69*635a8641SAndroid Build Coastguard Worker
AsyncReadComplete(int bytes_read)70*635a8641SAndroid Build Coastguard Worker ChannelReader::DispatchState ChannelReader::AsyncReadComplete(int bytes_read) {
71*635a8641SAndroid Build Coastguard Worker if (!TranslateInputData(input_buf_, bytes_read))
72*635a8641SAndroid Build Coastguard Worker return DISPATCH_ERROR;
73*635a8641SAndroid Build Coastguard Worker
74*635a8641SAndroid Build Coastguard Worker return DISPATCH_FINISHED;
75*635a8641SAndroid Build Coastguard Worker }
76*635a8641SAndroid Build Coastguard Worker
IsInternalMessage(const Message & m)77*635a8641SAndroid Build Coastguard Worker bool ChannelReader::IsInternalMessage(const Message& m) {
78*635a8641SAndroid Build Coastguard Worker return m.routing_id() == MSG_ROUTING_NONE &&
79*635a8641SAndroid Build Coastguard Worker m.type() >= Channel::CLOSE_FD_MESSAGE_TYPE &&
80*635a8641SAndroid Build Coastguard Worker m.type() <= Channel::HELLO_MESSAGE_TYPE;
81*635a8641SAndroid Build Coastguard Worker }
82*635a8641SAndroid Build Coastguard Worker
IsHelloMessage(const Message & m)83*635a8641SAndroid Build Coastguard Worker bool ChannelReader::IsHelloMessage(const Message& m) {
84*635a8641SAndroid Build Coastguard Worker return m.routing_id() == MSG_ROUTING_NONE &&
85*635a8641SAndroid Build Coastguard Worker m.type() == Channel::HELLO_MESSAGE_TYPE;
86*635a8641SAndroid Build Coastguard Worker }
87*635a8641SAndroid Build Coastguard Worker
CleanUp()88*635a8641SAndroid Build Coastguard Worker void ChannelReader::CleanUp() {
89*635a8641SAndroid Build Coastguard Worker }
90*635a8641SAndroid Build Coastguard Worker
DispatchMessage(Message * m)91*635a8641SAndroid Build Coastguard Worker void ChannelReader::DispatchMessage(Message* m) {
92*635a8641SAndroid Build Coastguard Worker EMIT_TRACE_EVENT(*m);
93*635a8641SAndroid Build Coastguard Worker listener_->OnMessageReceived(*m);
94*635a8641SAndroid Build Coastguard Worker HandleDispatchError(*m);
95*635a8641SAndroid Build Coastguard Worker }
96*635a8641SAndroid Build Coastguard Worker
TranslateInputData(const char * input_data,int input_data_len)97*635a8641SAndroid Build Coastguard Worker bool ChannelReader::TranslateInputData(const char* input_data,
98*635a8641SAndroid Build Coastguard Worker int input_data_len) {
99*635a8641SAndroid Build Coastguard Worker const char* p;
100*635a8641SAndroid Build Coastguard Worker const char* end;
101*635a8641SAndroid Build Coastguard Worker
102*635a8641SAndroid Build Coastguard Worker // Possibly combine with the overflow buffer to make a larger buffer.
103*635a8641SAndroid Build Coastguard Worker if (input_overflow_buf_.empty()) {
104*635a8641SAndroid Build Coastguard Worker p = input_data;
105*635a8641SAndroid Build Coastguard Worker end = input_data + input_data_len;
106*635a8641SAndroid Build Coastguard Worker } else {
107*635a8641SAndroid Build Coastguard Worker if (!CheckMessageSize(input_overflow_buf_.size() + input_data_len))
108*635a8641SAndroid Build Coastguard Worker return false;
109*635a8641SAndroid Build Coastguard Worker input_overflow_buf_.append(input_data, input_data_len);
110*635a8641SAndroid Build Coastguard Worker p = input_overflow_buf_.data();
111*635a8641SAndroid Build Coastguard Worker end = p + input_overflow_buf_.size();
112*635a8641SAndroid Build Coastguard Worker }
113*635a8641SAndroid Build Coastguard Worker
114*635a8641SAndroid Build Coastguard Worker size_t next_message_size = 0;
115*635a8641SAndroid Build Coastguard Worker
116*635a8641SAndroid Build Coastguard Worker // Dispatch all complete messages in the data buffer.
117*635a8641SAndroid Build Coastguard Worker while (p < end) {
118*635a8641SAndroid Build Coastguard Worker Message::NextMessageInfo info;
119*635a8641SAndroid Build Coastguard Worker Message::FindNext(p, end, &info);
120*635a8641SAndroid Build Coastguard Worker if (info.message_found) {
121*635a8641SAndroid Build Coastguard Worker int pickle_len = static_cast<int>(info.pickle_end - p);
122*635a8641SAndroid Build Coastguard Worker Message translated_message(p, pickle_len);
123*635a8641SAndroid Build Coastguard Worker
124*635a8641SAndroid Build Coastguard Worker if (!HandleTranslatedMessage(&translated_message))
125*635a8641SAndroid Build Coastguard Worker return false;
126*635a8641SAndroid Build Coastguard Worker
127*635a8641SAndroid Build Coastguard Worker p = info.message_end;
128*635a8641SAndroid Build Coastguard Worker } else {
129*635a8641SAndroid Build Coastguard Worker // Last message is partial.
130*635a8641SAndroid Build Coastguard Worker next_message_size = info.message_size;
131*635a8641SAndroid Build Coastguard Worker if (!CheckMessageSize(next_message_size))
132*635a8641SAndroid Build Coastguard Worker return false;
133*635a8641SAndroid Build Coastguard Worker break;
134*635a8641SAndroid Build Coastguard Worker }
135*635a8641SAndroid Build Coastguard Worker }
136*635a8641SAndroid Build Coastguard Worker
137*635a8641SAndroid Build Coastguard Worker // Account for the case where last message's byte is in the next data chunk.
138*635a8641SAndroid Build Coastguard Worker size_t next_message_buffer_size = next_message_size ?
139*635a8641SAndroid Build Coastguard Worker next_message_size + Channel::kReadBufferSize - 1:
140*635a8641SAndroid Build Coastguard Worker 0;
141*635a8641SAndroid Build Coastguard Worker
142*635a8641SAndroid Build Coastguard Worker // Save any partial data in the overflow buffer.
143*635a8641SAndroid Build Coastguard Worker if (p != input_overflow_buf_.data())
144*635a8641SAndroid Build Coastguard Worker input_overflow_buf_.assign(p, end - p);
145*635a8641SAndroid Build Coastguard Worker
146*635a8641SAndroid Build Coastguard Worker if (!input_overflow_buf_.empty()) {
147*635a8641SAndroid Build Coastguard Worker // We have something in the overflow buffer, which means that we will
148*635a8641SAndroid Build Coastguard Worker // append the next data chunk (instead of parsing it directly). So we
149*635a8641SAndroid Build Coastguard Worker // resize the buffer to fit the next message, to avoid repeatedly
150*635a8641SAndroid Build Coastguard Worker // growing the buffer as we receive all message' data chunks.
151*635a8641SAndroid Build Coastguard Worker if (next_message_buffer_size > input_overflow_buf_.capacity()) {
152*635a8641SAndroid Build Coastguard Worker input_overflow_buf_.reserve(next_message_buffer_size);
153*635a8641SAndroid Build Coastguard Worker }
154*635a8641SAndroid Build Coastguard Worker }
155*635a8641SAndroid Build Coastguard Worker
156*635a8641SAndroid Build Coastguard Worker // Trim the buffer if we can
157*635a8641SAndroid Build Coastguard Worker if (next_message_buffer_size < max_input_buffer_size_ &&
158*635a8641SAndroid Build Coastguard Worker input_overflow_buf_.size() < max_input_buffer_size_ &&
159*635a8641SAndroid Build Coastguard Worker input_overflow_buf_.capacity() > max_input_buffer_size_) {
160*635a8641SAndroid Build Coastguard Worker // std::string doesn't really have a method to shrink capacity to
161*635a8641SAndroid Build Coastguard Worker // a specific value, so we have to swap with another string.
162*635a8641SAndroid Build Coastguard Worker std::string trimmed_buf;
163*635a8641SAndroid Build Coastguard Worker trimmed_buf.reserve(max_input_buffer_size_);
164*635a8641SAndroid Build Coastguard Worker if (trimmed_buf.capacity() > max_input_buffer_size_) {
165*635a8641SAndroid Build Coastguard Worker // Since we don't control how much space reserve() actually reserves,
166*635a8641SAndroid Build Coastguard Worker // we have to go other way around and change the max size to avoid
167*635a8641SAndroid Build Coastguard Worker // getting into the outer if() again.
168*635a8641SAndroid Build Coastguard Worker max_input_buffer_size_ = trimmed_buf.capacity();
169*635a8641SAndroid Build Coastguard Worker }
170*635a8641SAndroid Build Coastguard Worker trimmed_buf.assign(input_overflow_buf_.data(),
171*635a8641SAndroid Build Coastguard Worker input_overflow_buf_.size());
172*635a8641SAndroid Build Coastguard Worker input_overflow_buf_.swap(trimmed_buf);
173*635a8641SAndroid Build Coastguard Worker }
174*635a8641SAndroid Build Coastguard Worker
175*635a8641SAndroid Build Coastguard Worker if (input_overflow_buf_.empty() && !DidEmptyInputBuffers())
176*635a8641SAndroid Build Coastguard Worker return false;
177*635a8641SAndroid Build Coastguard Worker return true;
178*635a8641SAndroid Build Coastguard Worker }
179*635a8641SAndroid Build Coastguard Worker
HandleTranslatedMessage(Message * translated_message)180*635a8641SAndroid Build Coastguard Worker bool ChannelReader::HandleTranslatedMessage(Message* translated_message) {
181*635a8641SAndroid Build Coastguard Worker // Immediately handle internal messages.
182*635a8641SAndroid Build Coastguard Worker if (IsInternalMessage(*translated_message)) {
183*635a8641SAndroid Build Coastguard Worker EMIT_TRACE_EVENT(*translated_message);
184*635a8641SAndroid Build Coastguard Worker HandleInternalMessage(*translated_message);
185*635a8641SAndroid Build Coastguard Worker HandleDispatchError(*translated_message);
186*635a8641SAndroid Build Coastguard Worker return true;
187*635a8641SAndroid Build Coastguard Worker }
188*635a8641SAndroid Build Coastguard Worker
189*635a8641SAndroid Build Coastguard Worker return HandleExternalMessage(translated_message);
190*635a8641SAndroid Build Coastguard Worker }
191*635a8641SAndroid Build Coastguard Worker
HandleExternalMessage(Message * external_message)192*635a8641SAndroid Build Coastguard Worker bool ChannelReader::HandleExternalMessage(Message* external_message) {
193*635a8641SAndroid Build Coastguard Worker if (!GetAttachments(external_message))
194*635a8641SAndroid Build Coastguard Worker return false;
195*635a8641SAndroid Build Coastguard Worker
196*635a8641SAndroid Build Coastguard Worker DispatchMessage(external_message);
197*635a8641SAndroid Build Coastguard Worker return true;
198*635a8641SAndroid Build Coastguard Worker }
199*635a8641SAndroid Build Coastguard Worker
HandleDispatchError(const Message & message)200*635a8641SAndroid Build Coastguard Worker void ChannelReader::HandleDispatchError(const Message& message) {
201*635a8641SAndroid Build Coastguard Worker if (message.dispatch_error())
202*635a8641SAndroid Build Coastguard Worker listener_->OnBadMessageReceived(message);
203*635a8641SAndroid Build Coastguard Worker }
204*635a8641SAndroid Build Coastguard Worker
CheckMessageSize(size_t size)205*635a8641SAndroid Build Coastguard Worker bool ChannelReader::CheckMessageSize(size_t size) {
206*635a8641SAndroid Build Coastguard Worker if (size <= Channel::kMaximumMessageSize) {
207*635a8641SAndroid Build Coastguard Worker return true;
208*635a8641SAndroid Build Coastguard Worker }
209*635a8641SAndroid Build Coastguard Worker input_overflow_buf_.clear();
210*635a8641SAndroid Build Coastguard Worker LOG(ERROR) << "IPC message is too big: " << size;
211*635a8641SAndroid Build Coastguard Worker return false;
212*635a8641SAndroid Build Coastguard Worker }
213*635a8641SAndroid Build Coastguard Worker
214*635a8641SAndroid Build Coastguard Worker } // namespace internal
215*635a8641SAndroid Build Coastguard Worker } // namespace IPC
216