| 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 |