Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / ipc / ipc_channel_reader.cc
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("toplevel", "ChannelReader::DispatchInputData",
87                    "name", name);
88 #else
89       TRACE_EVENT2("toplevel", "ChannelReader::DispatchInputData",
90                    "class", IPC_MESSAGE_ID_CLASS(m.type()),
91                    "line", IPC_MESSAGE_ID_LINE(m.type()));
92 #endif
93       m.TraceMessageEnd();
94       if (IsInternalMessage(m))
95         HandleInternalMessage(m);
96       else
97         listener_->OnMessageReceived(m);
98       p = message_tail;
99     } else {
100       // Last message is partial.
101       break;
102     }
103   }
104
105   // Save any partial data in the overflow buffer.
106   input_overflow_buf_.assign(p, end - p);
107
108   if (input_overflow_buf_.empty() && !DidEmptyInputBuffers())
109     return false;
110   return true;
111 }
112
113
114 }  // namespace internal
115 }  // namespace IPC