OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "ipc/ipc_channel_reader.h" | 5 #include "ipc/ipc_channel_reader.h" |
6 | 6 |
7 #include <stddef.h> | 7 #include <stddef.h> |
8 | 8 |
9 #include <algorithm> | 9 #include <algorithm> |
10 | 10 |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
44 IPC_MESSAGE_ID_LINE((message).type())); | 44 IPC_MESSAGE_ID_LINE((message).type())); |
45 #endif // IPC_MESSAGE_LOG_ENABLED | 45 #endif // IPC_MESSAGE_LOG_ENABLED |
46 | 46 |
47 ChannelReader::ChannelReader(Listener* listener) | 47 ChannelReader::ChannelReader(Listener* listener) |
48 : listener_(listener), | 48 : listener_(listener), |
49 max_input_buffer_size_(Channel::kMaximumReadBufferSize) { | 49 max_input_buffer_size_(Channel::kMaximumReadBufferSize) { |
50 memset(input_buf_, 0, sizeof(input_buf_)); | 50 memset(input_buf_, 0, sizeof(input_buf_)); |
51 } | 51 } |
52 | 52 |
53 ChannelReader::~ChannelReader() { | 53 ChannelReader::~ChannelReader() { |
54 DCHECK(blocked_ids_.empty()); | |
55 } | 54 } |
56 | 55 |
57 ChannelReader::DispatchState ChannelReader::ProcessIncomingMessages() { | 56 ChannelReader::DispatchState ChannelReader::ProcessIncomingMessages() { |
58 while (true) { | 57 while (true) { |
59 int bytes_read = 0; | 58 int bytes_read = 0; |
60 ReadState read_state = ReadData(input_buf_, Channel::kReadBufferSize, | 59 ReadState read_state = ReadData(input_buf_, Channel::kReadBufferSize, |
61 &bytes_read); | 60 &bytes_read); |
62 if (read_state == READ_FAILED) | 61 if (read_state == READ_FAILED) |
63 return DISPATCH_ERROR; | 62 return DISPATCH_ERROR; |
64 if (read_state == READ_PENDING) | 63 if (read_state == READ_PENDING) |
65 return DISPATCH_FINISHED; | 64 return DISPATCH_FINISHED; |
66 | 65 |
67 DCHECK(bytes_read > 0); | 66 DCHECK(bytes_read > 0); |
68 if (!TranslateInputData(input_buf_, bytes_read)) | 67 if (!TranslateInputData(input_buf_, bytes_read)) |
69 return DISPATCH_ERROR; | 68 return DISPATCH_ERROR; |
70 | |
71 DispatchState state = DispatchMessages(); | |
72 if (state != DISPATCH_FINISHED) | |
73 return state; | |
74 } | 69 } |
75 } | 70 } |
76 | 71 |
77 ChannelReader::DispatchState ChannelReader::AsyncReadComplete(int bytes_read) { | 72 ChannelReader::DispatchState ChannelReader::AsyncReadComplete(int bytes_read) { |
78 if (!TranslateInputData(input_buf_, bytes_read)) | 73 if (!TranslateInputData(input_buf_, bytes_read)) |
79 return DISPATCH_ERROR; | 74 return DISPATCH_ERROR; |
80 | 75 |
81 return DispatchMessages(); | 76 return DISPATCH_FINISHED; |
82 } | 77 } |
83 | 78 |
84 bool ChannelReader::IsInternalMessage(const Message& m) { | 79 bool ChannelReader::IsInternalMessage(const Message& m) { |
85 return m.routing_id() == MSG_ROUTING_NONE && | 80 return m.routing_id() == MSG_ROUTING_NONE && |
86 m.type() >= Channel::CLOSE_FD_MESSAGE_TYPE && | 81 m.type() >= Channel::CLOSE_FD_MESSAGE_TYPE && |
87 m.type() <= Channel::HELLO_MESSAGE_TYPE; | 82 m.type() <= Channel::HELLO_MESSAGE_TYPE; |
88 } | 83 } |
89 | 84 |
90 bool ChannelReader::IsHelloMessage(const Message& m) { | 85 bool ChannelReader::IsHelloMessage(const Message& m) { |
91 return m.routing_id() == MSG_ROUTING_NONE && | 86 return m.routing_id() == MSG_ROUTING_NONE && |
92 m.type() == Channel::HELLO_MESSAGE_TYPE; | 87 m.type() == Channel::HELLO_MESSAGE_TYPE; |
93 } | 88 } |
94 | 89 |
95 void ChannelReader::CleanUp() { | 90 void ChannelReader::CleanUp() { |
96 if (!blocked_ids_.empty()) { | |
97 StopObservingAttachmentBroker(); | |
98 blocked_ids_.clear(); | |
99 } | |
100 } | 91 } |
101 | 92 |
102 void ChannelReader::DispatchMessage(Message* m) { | 93 void ChannelReader::DispatchMessage(Message* m) { |
103 EMIT_TRACE_EVENT(*m); | 94 EMIT_TRACE_EVENT(*m); |
104 listener_->OnMessageReceived(*m); | 95 listener_->OnMessageReceived(*m); |
105 HandleDispatchError(*m); | 96 HandleDispatchError(*m); |
106 } | 97 } |
107 | 98 |
108 bool ChannelReader::TranslateInputData(const char* input_data, | 99 bool ChannelReader::TranslateInputData(const char* input_data, |
109 int input_data_len) { | 100 int input_data_len) { |
(...skipping 15 matching lines...) Expand all Loading... |
125 size_t next_message_size = 0; | 116 size_t next_message_size = 0; |
126 | 117 |
127 // Dispatch all complete messages in the data buffer. | 118 // Dispatch all complete messages in the data buffer. |
128 while (p < end) { | 119 while (p < end) { |
129 Message::NextMessageInfo info; | 120 Message::NextMessageInfo info; |
130 Message::FindNext(p, end, &info); | 121 Message::FindNext(p, end, &info); |
131 if (info.message_found) { | 122 if (info.message_found) { |
132 int pickle_len = static_cast<int>(info.pickle_end - p); | 123 int pickle_len = static_cast<int>(info.pickle_end - p); |
133 Message translated_message(p, pickle_len); | 124 Message translated_message(p, pickle_len); |
134 | 125 |
135 if (!HandleTranslatedMessage(&translated_message, info.attachment_ids)) | 126 if (!HandleTranslatedMessage(&translated_message)) |
136 return false; | 127 return false; |
137 | 128 |
138 p = info.message_end; | 129 p = info.message_end; |
139 } else { | 130 } else { |
140 // Last message is partial. | 131 // Last message is partial. |
141 next_message_size = info.message_size; | 132 next_message_size = info.message_size; |
142 if (!CheckMessageSize(next_message_size)) | 133 if (!CheckMessageSize(next_message_size)) |
143 return false; | 134 return false; |
144 break; | 135 break; |
145 } | 136 } |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
181 trimmed_buf.assign(input_overflow_buf_.data(), | 172 trimmed_buf.assign(input_overflow_buf_.data(), |
182 input_overflow_buf_.size()); | 173 input_overflow_buf_.size()); |
183 input_overflow_buf_.swap(trimmed_buf); | 174 input_overflow_buf_.swap(trimmed_buf); |
184 } | 175 } |
185 | 176 |
186 if (input_overflow_buf_.empty() && !DidEmptyInputBuffers()) | 177 if (input_overflow_buf_.empty() && !DidEmptyInputBuffers()) |
187 return false; | 178 return false; |
188 return true; | 179 return true; |
189 } | 180 } |
190 | 181 |
191 bool ChannelReader::HandleTranslatedMessage( | 182 bool ChannelReader::HandleTranslatedMessage(Message* translated_message) { |
192 Message* translated_message, | |
193 const AttachmentIdVector& attachment_ids) { | |
194 // Immediately handle internal messages. | 183 // Immediately handle internal messages. |
195 if (IsInternalMessage(*translated_message)) { | 184 if (IsInternalMessage(*translated_message)) { |
196 EMIT_TRACE_EVENT(*translated_message); | 185 EMIT_TRACE_EVENT(*translated_message); |
197 HandleInternalMessage(*translated_message); | 186 HandleInternalMessage(*translated_message); |
198 HandleDispatchError(*translated_message); | 187 HandleDispatchError(*translated_message); |
199 return true; | 188 return true; |
200 } | 189 } |
201 | 190 |
202 translated_message->set_sender_pid(GetSenderPID()); | 191 translated_message->set_sender_pid(GetSenderPID()); |
203 | 192 |
204 // Immediately handle attachment broker messages. | 193 return HandleExternalMessage(translated_message); |
205 if (DispatchAttachmentBrokerMessage(*translated_message)) { | |
206 // Ideally, the log would have been emitted prior to dispatching the | |
207 // message, but that would require this class to know more about the | |
208 // internals of attachment brokering, which should be avoided. | |
209 EMIT_TRACE_EVENT(*translated_message); | |
210 HandleDispatchError(*translated_message); | |
211 return true; | |
212 } | |
213 | |
214 return HandleExternalMessage(translated_message, attachment_ids); | |
215 } | 194 } |
216 | 195 |
217 bool ChannelReader::HandleExternalMessage( | 196 bool ChannelReader::HandleExternalMessage(Message* external_message) { |
218 Message* external_message, | |
219 const AttachmentIdVector& attachment_ids) { | |
220 for (const auto& id : attachment_ids) | |
221 external_message->AddPlaceholderBrokerableAttachmentWithId(id); | |
222 | |
223 if (!GetNonBrokeredAttachments(external_message)) | 197 if (!GetNonBrokeredAttachments(external_message)) |
224 return false; | 198 return false; |
225 | 199 |
226 // If there are no queued messages, attempt to immediately dispatch the | 200 DispatchMessage(external_message); |
227 // newly translated message. | |
228 if (queued_messages_.empty()) { | |
229 DCHECK(blocked_ids_.empty()); | |
230 AttachmentIdSet blocked_ids = GetBrokeredAttachments(external_message); | |
231 | |
232 if (blocked_ids.empty()) { | |
233 DispatchMessage(external_message); | |
234 return true; | |
235 } | |
236 | |
237 blocked_ids_.swap(blocked_ids); | |
238 StartObservingAttachmentBroker(); | |
239 } | |
240 | |
241 // Make a deep copy of |external_message| to add to the queue. | |
242 std::unique_ptr<Message> m(new Message(*external_message)); | |
243 queued_messages_.push_back(m.release()); | |
244 return true; | 201 return true; |
245 } | 202 } |
246 | 203 |
247 void ChannelReader::HandleDispatchError(const Message& message) { | 204 void ChannelReader::HandleDispatchError(const Message& message) { |
248 if (message.dispatch_error()) | 205 if (message.dispatch_error()) |
249 listener_->OnBadMessageReceived(message); | 206 listener_->OnBadMessageReceived(message); |
250 } | 207 } |
251 | 208 |
252 bool ChannelReader::DispatchAttachmentBrokerMessage(const Message& message) { | |
253 #if USE_ATTACHMENT_BROKER | |
254 if (IsAttachmentBrokerEndpoint() && GetAttachmentBroker()) { | |
255 return GetAttachmentBroker()->OnMessageReceived(message); | |
256 } | |
257 #endif // USE_ATTACHMENT_BROKER | |
258 | |
259 return false; | |
260 } | |
261 | |
262 ChannelReader::DispatchState ChannelReader::DispatchMessages() { | |
263 while (!queued_messages_.empty()) { | |
264 if (!blocked_ids_.empty()) | |
265 return DISPATCH_WAITING_ON_BROKER; | |
266 | |
267 Message* m = queued_messages_.front(); | |
268 | |
269 AttachmentIdSet blocked_ids = GetBrokeredAttachments(m); | |
270 if (!blocked_ids.empty()) { | |
271 blocked_ids_.swap(blocked_ids); | |
272 StartObservingAttachmentBroker(); | |
273 return DISPATCH_WAITING_ON_BROKER; | |
274 } | |
275 | |
276 DispatchMessage(m); | |
277 queued_messages_.erase(queued_messages_.begin()); | |
278 } | |
279 return DISPATCH_FINISHED; | |
280 } | |
281 | |
282 ChannelReader::AttachmentIdSet ChannelReader::GetBrokeredAttachments( | |
283 Message* msg) { | |
284 std::set<BrokerableAttachment::AttachmentId> blocked_ids; | |
285 | |
286 #if USE_ATTACHMENT_BROKER | |
287 MessageAttachmentSet* set = msg->attachment_set(); | |
288 std::vector<scoped_refptr<IPC::BrokerableAttachment>> | |
289 brokerable_attachments_copy(set->GetBrokerableAttachments()); | |
290 for (const auto& attachment : brokerable_attachments_copy) { | |
291 if (attachment->NeedsBrokering()) { | |
292 AttachmentBroker* broker = GetAttachmentBroker(); | |
293 DCHECK(broker); | |
294 scoped_refptr<BrokerableAttachment> brokered_attachment; | |
295 bool result = broker->GetAttachmentWithId(attachment->GetIdentifier(), | |
296 &brokered_attachment); | |
297 if (!result) { | |
298 blocked_ids.insert(attachment->GetIdentifier()); | |
299 continue; | |
300 } | |
301 | |
302 set->ReplacePlaceholderWithAttachment(brokered_attachment); | |
303 } | |
304 } | |
305 #endif // USE_ATTACHMENT_BROKER | |
306 | |
307 return blocked_ids; | |
308 } | |
309 | |
310 void ChannelReader::ReceivedBrokerableAttachmentWithId( | |
311 const BrokerableAttachment::AttachmentId& id) { | |
312 if (blocked_ids_.empty()) | |
313 return; | |
314 | |
315 auto it = find(blocked_ids_.begin(), blocked_ids_.end(), id); | |
316 if (it != blocked_ids_.end()) | |
317 blocked_ids_.erase(it); | |
318 | |
319 if (blocked_ids_.empty()) { | |
320 StopObservingAttachmentBroker(); | |
321 DispatchMessages(); | |
322 } | |
323 } | |
324 | |
325 void ChannelReader::StartObservingAttachmentBroker() { | |
326 #if USE_ATTACHMENT_BROKER | |
327 DCHECK(base::MessageLoopForIO::IsCurrent()); | |
328 GetAttachmentBroker()->AddObserver(this, base::ThreadTaskRunnerHandle::Get()); | |
329 #endif // USE_ATTACHMENT_BROKER | |
330 } | |
331 | |
332 void ChannelReader::StopObservingAttachmentBroker() { | |
333 #if USE_ATTACHMENT_BROKER | |
334 GetAttachmentBroker()->RemoveObserver(this); | |
335 #endif // USE_ATTACHMENT_BROKER | |
336 } | |
337 | |
338 bool ChannelReader::CheckMessageSize(size_t size) { | 209 bool ChannelReader::CheckMessageSize(size_t size) { |
339 if (size <= Channel::kMaximumMessageSize) { | 210 if (size <= Channel::kMaximumMessageSize) { |
340 return true; | 211 return true; |
341 } | 212 } |
342 input_overflow_buf_.clear(); | 213 input_overflow_buf_.clear(); |
343 LOG(ERROR) << "IPC message is too big: " << size; | 214 LOG(ERROR) << "IPC message is too big: " << size; |
344 return false; | 215 return false; |
345 } | 216 } |
346 | 217 |
347 } // namespace internal | 218 } // namespace internal |
348 } // namespace IPC | 219 } // namespace IPC |
OLD | NEW |