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 "ipc/ipc_listener.h" 8 #include "ipc/ipc_logging.h" 9 #include "ipc/ipc_message_macros.h" 10 11 namespace IPC { 12 namespace internal { 13 14 ChannelReader::ChannelReader(Listener* listener) : listener_(listener) { 15 memset(input_buf_, 0, sizeof(input_buf_)); 16 } 17 18 ChannelReader::~ChannelReader() { 19 } 20 21 bool ChannelReader::ProcessIncomingMessages() { 22 while (true) { 23 int bytes_read = 0; 24 ReadState read_state = ReadData(input_buf_, Channel::kReadBufferSize, 25 &bytes_read); 26 if (read_state == READ_FAILED) 27 return false; 28 if (read_state == READ_PENDING) 29 return true; 30 31 DCHECK(bytes_read > 0); 32 if (!DispatchInputData(input_buf_, bytes_read)) 33 return false; 34 } 35 } 36 37 bool ChannelReader::AsyncReadComplete(int bytes_read) { 38 return DispatchInputData(input_buf_, bytes_read); 39 } 40 41 bool ChannelReader::IsHelloMessage(const Message& m) const { 42 return m.routing_id() == MSG_ROUTING_NONE && 43 m.type() == Channel::HELLO_MESSAGE_TYPE; 44 } 45 46 bool ChannelReader::DispatchInputData(const char* input_data, 47 int input_data_len) { 48 const char* p; 49 const char* end; 50 51 // Possibly combine with the overflow buffer to make a larger buffer. 52 if (input_overflow_buf_.empty()) { 53 p = input_data; 54 end = input_data + input_data_len; 55 } else { 56 if (input_overflow_buf_.size() + input_data_len > 57 Channel::kMaximumMessageSize) { 58 input_overflow_buf_.clear(); 59 LOG(ERROR) << "IPC message is too big"; 60 return false; 61 } 62 input_overflow_buf_.append(input_data, input_data_len); 63 p = input_overflow_buf_.data(); 64 end = p + input_overflow_buf_.size(); 65 } 66 67 // Dispatch all complete messages in the data buffer. 68 while (p < end) { 69 const char* message_tail = Message::FindNext(p, end); 70 if (message_tail) { 71 int len = static_cast<int>(message_tail - p); 72 Message m(p, len); 73 if (!WillDispatchInputMessage(&m)) 74 return false; 75 76 #ifdef IPC_MESSAGE_LOG_ENABLED 77 Logging* logger = Logging::GetInstance(); 78 std::string name; 79 logger->GetMessageText(m.type(), &name, &m, NULL); 80 TRACE_EVENT1("ipc", "ChannelReader::DispatchInputData", "name", name); 81 #else 82 TRACE_EVENT2("ipc", "ChannelReader::DispatchInputData", 83 "class", IPC_MESSAGE_ID_CLASS(m.type()), 84 "line", IPC_MESSAGE_ID_LINE(m.type())); 85 #endif 86 m.TraceMessageEnd(); 87 if (IsHelloMessage(m)) 88 HandleHelloMessage(m); 89 else 90 listener_->OnMessageReceived(m); 91 p = message_tail; 92 } else { 93 // Last message is partial. 94 break; 95 } 96 } 97 98 // Save any partial data in the overflow buffer. 99 input_overflow_buf_.assign(p, end - p); 100 101 if (input_overflow_buf_.empty() && !DidEmptyInputBuffers()) 102 return false; 103 return true; 104 } 105 106 107 } // namespace internal 108 } // namespace IPC 109