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