Home | History | Annotate | Download | only in ipc
      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