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