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::IsInternalMessage(const Message& m) const { 42 return m.routing_id() == MSG_ROUTING_NONE && 43 m.type() >= Channel::CLOSE_FD_MESSAGE_TYPE && 44 m.type() <= Channel::HELLO_MESSAGE_TYPE; 45 } 46 47 bool ChannelReader::IsHelloMessage(const Message& m) const { 48 return m.routing_id() == MSG_ROUTING_NONE && 49 m.type() == Channel::HELLO_MESSAGE_TYPE; 50 } 51 52 bool ChannelReader::DispatchInputData(const char* input_data, 53 int input_data_len) { 54 const char* p; 55 const char* end; 56 57 // Possibly combine with the overflow buffer to make a larger buffer. 58 if (input_overflow_buf_.empty()) { 59 p = input_data; 60 end = input_data + input_data_len; 61 } else { 62 if (input_overflow_buf_.size() + input_data_len > 63 Channel::kMaximumMessageSize) { 64 input_overflow_buf_.clear(); 65 LOG(ERROR) << "IPC message is too big"; 66 return false; 67 } 68 input_overflow_buf_.append(input_data, input_data_len); 69 p = input_overflow_buf_.data(); 70 end = p + input_overflow_buf_.size(); 71 } 72 73 // Dispatch all complete messages in the data buffer. 74 while (p < end) { 75 const char* message_tail = Message::FindNext(p, end); 76 if (message_tail) { 77 int len = static_cast<int>(message_tail - p); 78 Message m(p, len); 79 if (!WillDispatchInputMessage(&m)) 80 return false; 81 82 #ifdef IPC_MESSAGE_LOG_ENABLED 83 Logging* logger = Logging::GetInstance(); 84 std::string name; 85 logger->GetMessageText(m.type(), &name, &m, NULL); 86 TRACE_EVENT1("ipc", "ChannelReader::DispatchInputData", "name", name); 87 #else 88 TRACE_EVENT2("ipc", "ChannelReader::DispatchInputData", 89 "class", IPC_MESSAGE_ID_CLASS(m.type()), 90 "line", IPC_MESSAGE_ID_LINE(m.type())); 91 #endif 92 m.TraceMessageEnd(); 93 if (IsInternalMessage(m)) 94 HandleInternalMessage(m); 95 else 96 listener_->OnMessageReceived(m); 97 p = message_tail; 98 } else { 99 // Last message is partial. 100 break; 101 } 102 } 103 104 // Save any partial data in the overflow buffer. 105 input_overflow_buf_.assign(p, end - p); 106 107 if (input_overflow_buf_.empty() && !DidEmptyInputBuffers()) 108 return false; 109 return true; 110 } 111 112 113 } // namespace internal 114 } // namespace IPC 115